Merge branch 'for-upstream/mali-dp' of git://linux-arm.org/linux-ld into drm-next
authorDave Airlie <airlied@redhat.com>
Thu, 31 Jan 2019 23:51:23 +0000 (09:51 +1000)
committerDave Airlie <airlied@redhat.com>
Fri, 1 Feb 2019 00:01:50 +0000 (10:01 +1000)
This pull includes the new Arm "komeda" DRM driver. It is currently hosted
in the same repo as the other "mali-dp" driver because it is the next
iteration of the IP.

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Liviu Dudau <Liviu.Dudau@arm.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190131173600.GN25147@e110455-lin.cambridge.arm.com
662 files changed:
Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
Documentation/devicetree/bindings/display/bridge/thine,thc63lvdm83d.txt
Documentation/devicetree/bindings/display/bridge/ti,ds90c185.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/auo,g101evn010.txt [moved from Documentation/devicetree/bindings/display/panel/auo,g101evn010 with 100% similarity]
Documentation/devicetree/bindings/display/renesas,du.txt
Documentation/devicetree/bindings/display/rockchip/rockchip-vop.txt
Documentation/gpu/dp-mst/topology-figure-1.dot [new file with mode: 0644]
Documentation/gpu/dp-mst/topology-figure-2.dot [new file with mode: 0644]
Documentation/gpu/dp-mst/topology-figure-3.dot [new file with mode: 0644]
Documentation/gpu/drm-internals.rst
Documentation/gpu/drm-kms-helpers.rst
Documentation/gpu/todo.rst
MAINTAINERS
drivers/acpi/pmic/intel_pmic.c
drivers/acpi/pmic/intel_pmic.h
drivers/acpi/pmic/intel_pmic_chtwc.c
drivers/acpi/pmic/intel_pmic_xpower.c
drivers/dma-buf/dma-buf.c
drivers/dma-buf/dma-fence.c
drivers/dma-buf/sw_sync.c
drivers/dma-buf/sync_debug.c
drivers/dma-buf/sync_file.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/amd/amdgpu/Makefile
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_fence.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell.h
drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
drivers/gpu/drm/amd/amdgpu/atom.c
drivers/gpu/drm/amd/amdgpu/ci_dpm.c [deleted file]
drivers/gpu/drm/amd/amdgpu/ci_dpm.h [deleted file]
drivers/gpu/drm/amd/amdgpu/ci_smc.c [deleted file]
drivers/gpu/drm/amd/amdgpu/cik.c
drivers/gpu/drm/amd/amdgpu/cik_dpm.h
drivers/gpu/drm/amd/amdgpu/cik_ih.c
drivers/gpu/drm/amd/amdgpu/cik_sdma.c
drivers/gpu/drm/amd/amdgpu/cz_ih.c
drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
drivers/gpu/drm/amd/amdgpu/dce_virtual.c
drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
drivers/gpu/drm/amd/amdgpu/iceland_ih.c
drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c
drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c
drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c
drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h
drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
drivers/gpu/drm/amd/amdgpu/si.c
drivers/gpu/drm/amd/amdgpu/si_dma.c
drivers/gpu/drm/amd/amdgpu/si_ih.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/amdgpu/tonga_ih.c
drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
drivers/gpu/drm/amd/amdgpu/vce_v4_0.c
drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
drivers/gpu/drm/amd/amdgpu/vega10_ih.c
drivers/gpu/drm/amd/amdgpu/vega10_reg_init.c
drivers/gpu/drm/amd/amdgpu/vega20_reg_init.c
drivers/gpu/drm/amd/amdgpu/vi.c
drivers/gpu/drm/amd/amdkfd/Kconfig
drivers/gpu/drm/amd/amdkfd/kfd_crat.c
drivers/gpu/drm/amd/amdkfd/kfd_module.c
drivers/gpu/drm/amd/amdkfd/kfd_priv.h
drivers/gpu/drm/amd/amdkfd/kfd_topology.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
drivers/gpu/drm/amd/display/dc/Makefile
drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c
drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h
drivers/gpu/drm/amd/display/dc/bios/command_table.c
drivers/gpu/drm/amd/display/dc/bios/command_table.h
drivers/gpu/drm/amd/display/dc/bios/command_table2.c
drivers/gpu/drm/amd/display/dc/bios/command_table2.h
drivers/gpu/drm/amd/display/dc/calcs/Makefile
drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c
drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c
drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/display/dc/core/dc_stream.c
drivers/gpu/drm/amd/display/dc/core/dc_surface.c
drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dc_bios_types.h
drivers/gpu/drm/amd/display/dc/dc_dp_types.h
drivers/gpu/drm/amd/display/dc/dc_helper.c
drivers/gpu/drm/amd/display/dc/dc_hw_types.h
drivers/gpu/drm/amd/display/dc/dc_link.h
drivers/gpu/drm/amd/display/dc/dc_stream.h
drivers/gpu/drm/amd/display/dc/dc_types.h
drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
drivers/gpu/drm/amd/display/dc/dce/dce_aux.h
drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c
drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.h
drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h
drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h
drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h
drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c
drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_clk_mgr.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h
drivers/gpu/drm/amd/display/dc/dm_pp_smu.h
drivers/gpu/drm/amd/display/dc/dm_services_types.h
drivers/gpu/drm/amd/display/dc/dml/Makefile
drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h
drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c
drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h
drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h
drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
drivers/gpu/drm/amd/display/dc/i2caux/Makefile [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.h [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/engine.h [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c [deleted file]
drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h [deleted file]
drivers/gpu/drm/amd/display/dc/inc/clock_source.h
drivers/gpu/drm/amd/display/dc/inc/core_status.h
drivers/gpu/drm/amd/display/dc/inc/core_types.h
drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h
drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h
drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
drivers/gpu/drm/amd/display/dc/inc/hw/vmid.h [moved from drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c with 63% similarity]
drivers/gpu/drm/amd/display/dc/inc/vm_helper.h [moved from drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.h with 65% similarity]
drivers/gpu/drm/amd/display/include/bios_parser_types.h
drivers/gpu/drm/amd/display/include/i2caux_interface.h
drivers/gpu/drm/amd/display/modules/color/color_gamma.c
drivers/gpu/drm/amd/display/modules/freesync/freesync.c
drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
drivers/gpu/drm/amd/display/modules/inc/mod_shared.h
drivers/gpu/drm/amd/display/modules/power/power_helpers.c
drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_6_1_offset.h
drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_6_1_sh_mask.h
drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_6_1_smn.h [new file with mode: 0644]
drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_0_smn.h [new file with mode: 0644]
drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_4_0_smn.h [new file with mode: 0644]
drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_4_offset.h
drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_4_sh_mask.h
drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_offset.h
drivers/gpu/drm/amd/include/atombios.h
drivers/gpu/drm/amd/include/kgd_kfd_interface.h
drivers/gpu/drm/amd/include/kgd_pp_interface.h
drivers/gpu/drm/amd/powerplay/amd_powerplay.c
drivers/gpu/drm/amd/powerplay/hwmgr/Makefile
drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.c [new file with mode: 0644]
drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.h [moved from drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.h with 65% similarity]
drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c
drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c
drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.h
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.c [new file with mode: 0644]
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.h [moved from drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h with 74% similarity]
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_pptable.h
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h
drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.c [new file with mode: 0644]
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.h [moved from drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.h with 73% similarity]
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_inc.h
drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h
drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
drivers/gpu/drm/arc/arcpgu_crtc.c
drivers/gpu/drm/arc/arcpgu_drv.c
drivers/gpu/drm/arc/arcpgu_sim.c
drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c
drivers/gpu/drm/armada/armada_crtc.c
drivers/gpu/drm/ast/ast_fb.c
drivers/gpu/drm/ati_pcigart.c
drivers/gpu/drm/bochs/Makefile
drivers/gpu/drm/bochs/bochs.h
drivers/gpu/drm/bochs/bochs_drv.c
drivers/gpu/drm/bochs/bochs_fbdev.c [deleted file]
drivers/gpu/drm/bochs/bochs_hw.c
drivers/gpu/drm/bochs/bochs_kms.c
drivers/gpu/drm/bochs/bochs_mm.c
drivers/gpu/drm/bridge/adv7511/adv7511.h
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
drivers/gpu/drm/bridge/adv7511/adv7533.c
drivers/gpu/drm/bridge/analogix-anx78xx.c
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
drivers/gpu/drm/bridge/lvds-encoder.c
drivers/gpu/drm/bridge/panel.c
drivers/gpu/drm/bridge/sii902x.c
drivers/gpu/drm/bridge/sil-sii8620.c
drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
drivers/gpu/drm/bridge/tc358767.c
drivers/gpu/drm/cirrus/cirrus_fbdev.c
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_bridge.c
drivers/gpu/drm/drm_bufs.c
drivers/gpu/drm/drm_color_mgmt.c
drivers/gpu/drm/drm_connector.c
drivers/gpu/drm/drm_context.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_crtc_internal.h
drivers/gpu/drm/drm_damage_helper.c
drivers/gpu/drm/drm_dp_helper.c
drivers/gpu/drm/drm_dp_mst_topology.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_fb_cma_helper.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_flip_work.c
drivers/gpu/drm/drm_framebuffer.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_gem_framebuffer_helper.c
drivers/gpu/drm/drm_internal.h
drivers/gpu/drm/drm_lease.c
drivers/gpu/drm/drm_mode_config.c
drivers/gpu/drm/drm_mode_object.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/drm_modeset_lock.c
drivers/gpu/drm/drm_of.c
drivers/gpu/drm/drm_panel.c
drivers/gpu/drm/drm_plane.c
drivers/gpu/drm/drm_syncobj.c
drivers/gpu/drm/drm_vblank.c
drivers/gpu/drm/etnaviv/etnaviv_gem.c
drivers/gpu/drm/etnaviv/etnaviv_sched.c
drivers/gpu/drm/exynos/exynos_drm_mic.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h
drivers/gpu/drm/i2c/ch7006_drv.c
drivers/gpu/drm/i2c/tda998x_drv.c
drivers/gpu/drm/i915/Kconfig.debug
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/dvo.h
drivers/gpu/drm/i915/gvt/Makefile
drivers/gpu/drm/i915/gvt/aperture_gm.c
drivers/gpu/drm/i915/gvt/cmd_parser.c
drivers/gpu/drm/i915/gvt/display.c
drivers/gpu/drm/i915/gvt/dmabuf.c
drivers/gpu/drm/i915/gvt/edid.c
drivers/gpu/drm/i915/gvt/fb_decoder.c
drivers/gpu/drm/i915/gvt/gvt.c
drivers/gpu/drm/i915/gvt/gvt.h
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/hypercall.h
drivers/gpu/drm/i915/gvt/interrupt.c
drivers/gpu/drm/i915/gvt/kvmgt.c
drivers/gpu/drm/i915/gvt/mmio.c
drivers/gpu/drm/i915/gvt/mmio.h
drivers/gpu/drm/i915/gvt/mmio_context.c
drivers/gpu/drm/i915/gvt/mpt.h
drivers/gpu/drm/i915/gvt/sched_policy.c
drivers/gpu/drm/i915/gvt/scheduler.c
drivers/gpu/drm/i915/gvt/scheduler.h
drivers/gpu/drm/i915/gvt/trace.h
drivers/gpu/drm/i915/gvt/vgpu.c
drivers/gpu/drm/i915/i915_cmd_parser.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_context.c
drivers/gpu/drm/i915/i915_gem_context.h
drivers/gpu/drm/i915/i915_gem_dmabuf.c
drivers/gpu/drm/i915/i915_gem_evict.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gem_fence_reg.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_gtt.h
drivers/gpu/drm/i915/i915_gem_internal.c
drivers/gpu/drm/i915/i915_gem_object.h
drivers/gpu/drm/i915/i915_gem_shrinker.c
drivers/gpu/drm/i915/i915_gem_stolen.c
drivers/gpu/drm/i915/i915_gem_tiling.c
drivers/gpu/drm/i915/i915_gem_userptr.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_gpu_error.h
drivers/gpu/drm/i915/i915_ioc32.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_params.c
drivers/gpu/drm/i915/i915_params.h
drivers/gpu/drm/i915/i915_pci.c
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/i915/i915_pmu.c
drivers/gpu/drm/i915/i915_query.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_request.c
drivers/gpu/drm/i915/i915_request.h
drivers/gpu/drm/i915/i915_reset.c [new file with mode: 0644]
drivers/gpu/drm/i915/i915_reset.h [new file with mode: 0644]
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/i915_sw_fence.c
drivers/gpu/drm/i915/i915_sysfs.c
drivers/gpu/drm/i915/i915_timeline.h
drivers/gpu/drm/i915/i915_trace.h
drivers/gpu/drm/i915/icl_dsi.c
drivers/gpu/drm/i915/intel_acpi.c
drivers/gpu/drm/i915/intel_atomic.c
drivers/gpu/drm/i915/intel_atomic_plane.c
drivers/gpu/drm/i915/intel_audio.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_breadcrumbs.c
drivers/gpu/drm/i915/intel_cdclk.c
drivers/gpu/drm/i915/intel_color.c
drivers/gpu/drm/i915/intel_connector.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_csr.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_device_info.c
drivers/gpu/drm/i915/intel_device_info.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_display.h
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_dp_link_training.c
drivers/gpu/drm/i915/intel_dp_mst.c
drivers/gpu/drm/i915/intel_dpio_phy.c
drivers/gpu/drm/i915/intel_dpll_mgr.c
drivers/gpu/drm/i915/intel_dpll_mgr.h
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dsi.h
drivers/gpu/drm/i915/intel_dsi_vbt.c
drivers/gpu/drm/i915/intel_dvo.c
drivers/gpu/drm/i915/intel_engine_cs.c
drivers/gpu/drm/i915/intel_fbc.c
drivers/gpu/drm/i915/intel_fbdev.c
drivers/gpu/drm/i915/intel_fifo_underrun.c
drivers/gpu/drm/i915/intel_frontbuffer.c
drivers/gpu/drm/i915/intel_guc.h
drivers/gpu/drm/i915/intel_guc_fw.c
drivers/gpu/drm/i915/intel_guc_log.c
drivers/gpu/drm/i915/intel_guc_submission.c
drivers/gpu/drm/i915/intel_gvt.c
drivers/gpu/drm/i915/intel_hangcheck.c
drivers/gpu/drm/i915/intel_hdcp.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_hotplug.c
drivers/gpu/drm/i915/intel_huc.c
drivers/gpu/drm/i915/intel_huc_fw.c
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_lrc.h
drivers/gpu/drm/i915/intel_lspcon.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_mocs.c
drivers/gpu/drm/i915/intel_mocs.h
drivers/gpu/drm/i915/intel_opregion.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pipe_crc.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_psr.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/i915/intel_runtime_pm.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/i915/intel_tv.c
drivers/gpu/drm/i915/intel_uc.c
drivers/gpu/drm/i915/intel_uc.h
drivers/gpu/drm/i915/intel_uc_fw.c
drivers/gpu/drm/i915/intel_uncore.c
drivers/gpu/drm/i915/intel_vdsc.c
drivers/gpu/drm/i915/intel_wopcm.c
drivers/gpu/drm/i915/intel_workarounds.c
drivers/gpu/drm/i915/selftests/huge_pages.c
drivers/gpu/drm/i915/selftests/i915_gem.c
drivers/gpu/drm/i915/selftests/i915_gem_coherency.c
drivers/gpu/drm/i915/selftests/i915_gem_context.c
drivers/gpu/drm/i915/selftests/i915_gem_evict.c
drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
drivers/gpu/drm/i915/selftests/i915_gem_object.c
drivers/gpu/drm/i915/selftests/i915_request.c
drivers/gpu/drm/i915/selftests/i915_vma.c
drivers/gpu/drm/i915/selftests/igt_live_test.c [new file with mode: 0644]
drivers/gpu/drm/i915/selftests/igt_live_test.h [new file with mode: 0644]
drivers/gpu/drm/i915/selftests/igt_spinner.c
drivers/gpu/drm/i915/selftests/intel_guc.c
drivers/gpu/drm/i915/selftests/intel_hangcheck.c
drivers/gpu/drm/i915/selftests/intel_lrc.c
drivers/gpu/drm/i915/selftests/intel_workarounds.c
drivers/gpu/drm/i915/selftests/mock_context.c
drivers/gpu/drm/i915/selftests/mock_engine.c
drivers/gpu/drm/i915/selftests/mock_gem_device.c
drivers/gpu/drm/i915/selftests/mock_gtt.c
drivers/gpu/drm/i915/selftests/mock_gtt.h
drivers/gpu/drm/i915/vlv_dsi.c
drivers/gpu/drm/i915/vlv_dsi_pll.c
drivers/gpu/drm/mediatek/mtk_hdmi.c
drivers/gpu/drm/meson/meson_drv.c
drivers/gpu/drm/meson/meson_dw_hdmi.c
drivers/gpu/drm/mgag200/mgag200_fb.c
drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c
drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c
drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c
drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c
drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
drivers/gpu/drm/msm/dsi/dsi.h
drivers/gpu/drm/msm/dsi/dsi_host.c
drivers/gpu/drm/msm/dsi/dsi_manager.c
drivers/gpu/drm/msm/edp/edp_bridge.c
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/mxsfb/mxsfb_drv.c
drivers/gpu/drm/mxsfb/mxsfb_drv.h
drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/omapdrm/omap_connector.c
drivers/gpu/drm/omapdrm/omap_crtc.c
drivers/gpu/drm/omapdrm/omap_encoder.c
drivers/gpu/drm/omapdrm/omap_fbdev.c
drivers/gpu/drm/panel/Kconfig
drivers/gpu/drm/panel/Makefile
drivers/gpu/drm/panel/panel-innolux-p079zca.c
drivers/gpu/drm/panel/panel-tpo-tpg110.c [new file with mode: 0644]
drivers/gpu/drm/qxl/qxl_cmd.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/r128/r128_cce.c
drivers/gpu/drm/radeon/atom.c
drivers/gpu/drm/radeon/ci_dpm.c
drivers/gpu/drm/radeon/radeon_audio.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_dp_mst.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/rcar-du/rcar_du_crtc.c
drivers/gpu/drm/rcar-du/rcar_du_crtc.h
drivers/gpu/drm/rcar-du/rcar_du_drv.c
drivers/gpu/drm/rcar-du/rcar_du_drv.h
drivers/gpu/drm/rcar-du/rcar_du_encoder.c
drivers/gpu/drm/rcar-du/rcar_du_encoder.h
drivers/gpu/drm/rcar-du/rcar_du_group.c
drivers/gpu/drm/rcar-du/rcar_du_kms.c
drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts
drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts
drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts
drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts
drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts
drivers/gpu/drm/rcar-du/rcar_du_plane.c
drivers/gpu/drm/rcar-du/rcar_du_plane.h
drivers/gpu/drm/rcar-du/rcar_du_vsp.c
drivers/gpu/drm/rcar-du/rcar_du_vsp.h
drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c
drivers/gpu/drm/rcar-du/rcar_lvds.c
drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
drivers/gpu/drm/rockchip/inno_hdmi.c
drivers/gpu/drm/rockchip/rockchip_drm_fb.c
drivers/gpu/drm/rockchip/rockchip_drm_psr.c
drivers/gpu/drm/rockchip/rockchip_drm_psr.h
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.h
drivers/gpu/drm/rockchip/rockchip_vop_reg.c
drivers/gpu/drm/rockchip/rockchip_vop_reg.h
drivers/gpu/drm/scheduler/sched_main.c
drivers/gpu/drm/shmobile/shmob_drm_drv.c
drivers/gpu/drm/sti/sti_crtc.c
drivers/gpu/drm/sti/sti_dvo.c
drivers/gpu/drm/sti/sti_hda.c
drivers/gpu/drm/sti/sti_hdmi.c
drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
drivers/gpu/drm/stm/ltdc.c
drivers/gpu/drm/sun4i/sun4i_backend.c
drivers/gpu/drm/sun4i/sun4i_drv.c
drivers/gpu/drm/sun4i/sun4i_frontend.c
drivers/gpu/drm/sun4i/sun4i_frontend.h
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
drivers/gpu/drm/sun4i/sun4i_layer.c
drivers/gpu/drm/tegra/hdmi.c
drivers/gpu/drm/tegra/hub.c
drivers/gpu/drm/tegra/sor.c
drivers/gpu/drm/tilcdc/tilcdc_drv.c
drivers/gpu/drm/tinydrm/core/tinydrm-core.c
drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c
drivers/gpu/drm/tinydrm/hx8357d.c
drivers/gpu/drm/tinydrm/ili9225.c
drivers/gpu/drm/tinydrm/ili9341.c
drivers/gpu/drm/tinydrm/mi0283qt.c
drivers/gpu/drm/tinydrm/mipi-dbi.c
drivers/gpu/drm/tinydrm/repaper.c
drivers/gpu/drm/tinydrm/st7586.c
drivers/gpu/drm/tinydrm/st7735r.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_bo_vm.c
drivers/gpu/drm/v3d/v3d_drv.h
drivers/gpu/drm/v3d/v3d_gem.c
drivers/gpu/drm/v3d/v3d_sched.c
drivers/gpu/drm/vc4/vc4_crtc.c
drivers/gpu/drm/vc4/vc4_drv.h
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/gpu/drm/vc4/vc4_kms.c
drivers/gpu/drm/vc4/vc4_plane.c
drivers/gpu/drm/vgem/vgem_fence.c
drivers/gpu/drm/virtio/Makefile
drivers/gpu/drm/virtio/virtgpu_display.c
drivers/gpu/drm/virtio/virtgpu_drm_bus.c [deleted file]
drivers/gpu/drm/virtio/virtgpu_drv.c
drivers/gpu/drm/virtio/virtgpu_drv.h
drivers/gpu/drm/virtio/virtgpu_fb.c
drivers/gpu/drm/virtio/virtgpu_fence.c
drivers/gpu/drm/virtio/virtgpu_ioctl.c
drivers/gpu/drm/virtio/virtgpu_kms.c
drivers/gpu/drm/virtio/virtgpu_plane.c
drivers/gpu/drm/virtio/virtgpu_vq.c
drivers/gpu/drm/vkms/vkms_drv.c
drivers/gpu/drm/xen/xen_drm_front_conn.c
drivers/gpu/drm/zte/zx_hdmi.c
drivers/staging/vboxvideo/vbox_fb.c
include/drm/bridge/dw_hdmi.h
include/drm/bridge/dw_mipi_dsi.h
include/drm/drmP.h
include/drm/drm_atomic.h
include/drm/drm_bridge.h
include/drm/drm_color_mgmt.h
include/drm/drm_connector.h
include/drm/drm_crtc.h
include/drm/drm_crtc_helper.h
include/drm/drm_damage_helper.h
include/drm/drm_device.h
include/drm/drm_dp_helper.h
include/drm/drm_dp_mst_helper.h
include/drm/drm_edid.h
include/drm/drm_encoder_slave.h
include/drm/drm_fb_cma_helper.h
include/drm/drm_file.h
include/drm/drm_fourcc.h
include/drm/drm_framebuffer.h
include/drm/drm_gem_cma_helper.h
include/drm/drm_gem_framebuffer_helper.h
include/drm/drm_hdcp.h
include/drm/drm_legacy.h
include/drm/drm_mode_config.h
include/drm/drm_modes.h
include/drm/drm_syncobj.h
include/drm/drm_util.h
include/drm/drm_vblank.h
include/drm/gpu_scheduler.h
include/drm/i915_pciids.h
include/drm/intel-gtt.h
include/drm/tinydrm/mipi-dbi.h
include/drm/tinydrm/tinydrm-helpers.h
include/drm/tinydrm/tinydrm.h
include/drm/ttm/ttm_bo_driver.h
include/linux/dma-fence-array.h
include/linux/dma-fence.h
include/linux/mfd/intel_soc_pmic.h
include/uapi/drm/drm_fourcc.h
include/uapi/drm/v3d_drm.h

index 50220190c20330a47a1425e2e2798e59c8f1652b..60091db5dfa5218958ff35133df0e3c02b4fdc5c 100644 (file)
@@ -22,13 +22,11 @@ among others.
 
 Required properties:
 
-- compatible: Must be one or more of the following
-  - "ti,ds90c185" for the TI DS90C185 FPD-Link Serializer
-  - "lvds-encoder" for a generic LVDS encoder device
+- compatible: Must be "lvds-encoder"
 
-  When compatible with the generic version, nodes must list the
-  device-specific version corresponding to the device first
-  followed by the generic version.
+  Any encoder compatible with this generic binding, but with additional
+  properties not listed here, must list a device specific compatible first
+  followed by this generic compatible.
 
 Required nodes:
 
@@ -44,8 +42,6 @@ Example
 
 lvds-encoder {
        compatible = "lvds-encoder";
-       #address-cells = <1>;
-       #size-cells = <0>;
 
        ports {
                #address-cells = <1>;
index ba5469dd09f35393e339af8000d6ca776d1c2f31..27a054e1bb5fb82ccd4bbc2d3120ac56a9b98e49 100644 (file)
@@ -8,6 +8,7 @@ Required properties:
 
 - compatible : Shall contain one of
   - "renesas,r8a7743-lvds" for R8A7743 (RZ/G1M) compatible LVDS encoders
+  - "renesas,r8a774c0-lvds" for R8A774C0 (RZ/G2E) compatible LVDS encoders
   - "renesas,r8a7790-lvds" for R8A7790 (R-Car H2) compatible LVDS encoders
   - "renesas,r8a7791-lvds" for R8A7791 (R-Car M2-W) compatible LVDS encoders
   - "renesas,r8a7793-lvds" for R8A7793 (R-Car M2-N) compatible LVDS encoders
@@ -25,7 +26,7 @@ Required properties:
 - clock-names: Name of the clocks. This property is model-dependent.
   - The functional clock, which mandatory for all models, shall be listed
     first, and shall be named "fck".
-  - On R8A77990 and R8A77995, the LVDS encoder can use the EXTAL or
+  - On R8A77990, R8A77995 and R8A774C0, the LVDS encoder can use the EXTAL or
     DU_DOTCLKINx clocks. Those clocks are optional. When supplied they must be
     named "extal" and "dclkin.x" respectively, with "x" being the DU_DOTCLKIN
     numerical index.
index 527e236e9a2a126dcdd814e3b50c972a7145fe44..fee3c88e1a176e6388a49806ed65dca4471e7d42 100644 (file)
@@ -10,7 +10,7 @@ Required properties:
 
 Optional properties:
 
-- pwdn-gpios: Power down control GPIO
+- powerdown-gpios: Power down control GPIO (the /PWDN pin, active low).
 
 Required nodes:
 
diff --git a/Documentation/devicetree/bindings/display/bridge/ti,ds90c185.txt b/Documentation/devicetree/bindings/display/bridge/ti,ds90c185.txt
new file mode 100644 (file)
index 0000000..e575f99
--- /dev/null
@@ -0,0 +1,55 @@
+Texas Instruments FPD-Link (LVDS) Serializer
+--------------------------------------------
+
+The DS90C185 and DS90C187 are low-power serializers for portable
+battery-powered applications that reduces the size of the RGB
+interface between the host GPU and the display.
+
+Required properties:
+
+- compatible: Should be
+  "ti,ds90c185", "lvds-encoder"  for the TI DS90C185 FPD-Link Serializer
+  "ti,ds90c187", "lvds-encoder"  for the TI DS90C187 FPD-Link Serializer
+
+Optional properties:
+
+- powerdown-gpios: Power down control GPIO (the PDB pin, active-low)
+
+Required nodes:
+
+The devices have two video ports. Their connections are modeled using the OF
+graph bindings specified in Documentation/devicetree/bindings/graph.txt.
+
+- Video port 0 for parallel input
+- Video port 1 for LVDS output
+
+
+Example
+-------
+
+lvds-encoder {
+       compatible = "ti,ds90c185", "lvds-encoder";
+
+       powerdown-gpios = <&gpio 17 GPIO_ACTIVE_LOW>;
+
+       ports {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               port@0 {
+                       reg = <0>;
+
+                       lvds_enc_in: endpoint {
+                               remote-endpoint = <&lcdc_out_rgb>;
+                       };
+               };
+
+               port@1 {
+                       reg = <1>;
+
+                       lvds_enc_out: endpoint {
+                               remote-endpoint = <&lvds_panel_in>;
+                       };
+               };
+       };
+};
index 3c855d9f27193bcb03f365cc8c4a3a78a5d478a0..aedb22b4d1613d1ff69b833a5babd227892538e0 100644 (file)
@@ -7,6 +7,7 @@ Required Properties:
     - "renesas,du-r8a7744" for R8A7744 (RZ/G1N) compatible DU
     - "renesas,du-r8a7745" for R8A7745 (RZ/G1E) compatible DU
     - "renesas,du-r8a77470" for R8A77470 (RZ/G1C) compatible DU
+    - "renesas,du-r8a774c0" for R8A774C0 (RZ/G2E) compatible DU
     - "renesas,du-r8a7779" for R8A7779 (R-Car H1) compatible DU
     - "renesas,du-r8a7790" for R8A7790 (R-Car H2) compatible DU
     - "renesas,du-r8a7791" for R8A7791 (R-Car M2-W) compatible DU
@@ -57,6 +58,7 @@ corresponding to each DU output.
  R8A7744 (RZ/G1N)       DPAD 0         LVDS 0         -              -
  R8A7745 (RZ/G1E)       DPAD 0         DPAD 1         -              -
  R8A77470 (RZ/G1C)      DPAD 0         DPAD 1         LVDS 0         -
+ R8A774C0 (RZ/G2E)      DPAD 0         LVDS 0         LVDS 1         -
  R8A7779 (R-Car H1)     DPAD 0         DPAD 1         -              -
  R8A7790 (R-Car H2)     DPAD 0         LVDS 0         LVDS 1         -
  R8A7791 (R-Car M2-W)   DPAD 0         LVDS 0         -              -
index b79e5769f0ae7d1b28835d73f9886d83d42fb389..4f58c5a2d19501c92b4388dbb9acaacac8001759 100644 (file)
@@ -10,6 +10,7 @@ Required properties:
                "rockchip,rk3126-vop";
                "rockchip,px30-vop-lit";
                "rockchip,px30-vop-big";
+               "rockchip,rk3066-vop";
                "rockchip,rk3188-vop";
                "rockchip,rk3288-vop";
                "rockchip,rk3368-vop";
diff --git a/Documentation/gpu/dp-mst/topology-figure-1.dot b/Documentation/gpu/dp-mst/topology-figure-1.dot
new file mode 100644 (file)
index 0000000..157e17c
--- /dev/null
@@ -0,0 +1,52 @@
+digraph T {
+    /* Make sure our payloads are always drawn below the driver node */
+    subgraph cluster_driver {
+        fillcolor = grey;
+        style = filled;
+        driver -> {payload1, payload2} [dir=none];
+    }
+
+    /* Driver malloc references */
+    edge [style=dashed];
+    driver -> port1;
+    driver -> port2;
+    driver -> port3:e;
+    driver -> port4;
+
+    payload1:s -> port1:e;
+    payload2:s -> port3:e;
+    edge [style=""];
+
+    subgraph cluster_topology {
+        label="Topology Manager";
+        labelloc=bottom;
+
+        /* Topology references */
+        mstb1 -> {port1, port2};
+        port1 -> mstb2;
+        port2 -> mstb3 -> {port3, port4};
+        port3 -> mstb4;
+
+        /* Malloc references */
+        edge [style=dashed;dir=back];
+        mstb1 -> {port1, port2};
+        port1 -> mstb2;
+        port2 -> mstb3 -> {port3, port4};
+        port3 -> mstb4;
+    }
+
+    driver [label="DRM driver";style=filled;shape=box;fillcolor=lightblue];
+
+    payload1 [label="Payload #1";style=filled;shape=box;fillcolor=lightblue];
+    payload2 [label="Payload #2";style=filled;shape=box;fillcolor=lightblue];
+
+    mstb1 [label="MSTB #1";style=filled;fillcolor=palegreen;shape=oval];
+    mstb2 [label="MSTB #2";style=filled;fillcolor=palegreen;shape=oval];
+    mstb3 [label="MSTB #3";style=filled;fillcolor=palegreen;shape=oval];
+    mstb4 [label="MSTB #4";style=filled;fillcolor=palegreen;shape=oval];
+
+    port1 [label="Port #1";shape=oval];
+    port2 [label="Port #2";shape=oval];
+    port3 [label="Port #3";shape=oval];
+    port4 [label="Port #4";shape=oval];
+}
diff --git a/Documentation/gpu/dp-mst/topology-figure-2.dot b/Documentation/gpu/dp-mst/topology-figure-2.dot
new file mode 100644 (file)
index 0000000..4243dd1
--- /dev/null
@@ -0,0 +1,56 @@
+digraph T {
+    /* Make sure our payloads are always drawn below the driver node */
+    subgraph cluster_driver {
+        fillcolor = grey;
+        style = filled;
+        driver -> {payload1, payload2} [dir=none];
+    }
+
+    /* Driver malloc references */
+    edge [style=dashed];
+    driver -> port1;
+    driver -> port2;
+    driver -> port3:e;
+    driver -> port4 [color=red];
+
+    payload1:s -> port1:e;
+    payload2:s -> port3:e;
+    edge [style=""];
+
+    subgraph cluster_topology {
+        label="Topology Manager";
+        labelloc=bottom;
+
+        /* Topology references */
+        mstb1 -> {port1, port2};
+        port1 -> mstb2;
+        edge [color=red];
+        port2 -> mstb3 -> {port3, port4};
+        port3 -> mstb4;
+        edge [color=""];
+
+        /* Malloc references */
+        edge [style=dashed;dir=back];
+        mstb1 -> {port1, port2};
+        port1 -> mstb2;
+        port2 -> mstb3 -> port3;
+        edge [color=red];
+        mstb3 -> port4;
+        port3 -> mstb4;
+    }
+
+    mstb1 [label="MSTB #1";style=filled;fillcolor=palegreen];
+    mstb2 [label="MSTB #2";style=filled;fillcolor=palegreen];
+    mstb3 [label="MSTB #3";style=filled;fillcolor=palegreen];
+    mstb4 [label="MSTB #4";style=filled;fillcolor=grey];
+
+    port1 [label="Port #1"];
+    port2 [label="Port #2"];
+    port3 [label="Port #3"];
+    port4 [label="Port #4";style=filled;fillcolor=grey];
+
+    driver [label="DRM driver";style=filled;shape=box;fillcolor=lightblue];
+
+    payload1 [label="Payload #1";style=filled;shape=box;fillcolor=lightblue];
+    payload2 [label="Payload #2";style=filled;shape=box;fillcolor=lightblue];
+}
diff --git a/Documentation/gpu/dp-mst/topology-figure-3.dot b/Documentation/gpu/dp-mst/topology-figure-3.dot
new file mode 100644 (file)
index 0000000..6cd78d0
--- /dev/null
@@ -0,0 +1,59 @@
+digraph T {
+    /* Make sure our payloads are always drawn below the driver node */
+    subgraph cluster_driver {
+        fillcolor = grey;
+        style = filled;
+        edge [dir=none];
+        driver -> payload1;
+        driver -> payload2 [penwidth=3];
+        edge [dir=""];
+    }
+
+    /* Driver malloc references */
+    edge [style=dashed];
+    driver -> port1;
+    driver -> port2;
+    driver -> port3:e;
+    driver -> port4 [color=grey];
+    payload1:s -> port1:e;
+    payload2:s -> port3:e [penwidth=3];
+    edge [style=""];
+
+    subgraph cluster_topology {
+        label="Topology Manager";
+        labelloc=bottom;
+
+        /* Topology references */
+        mstb1 -> {port1, port2};
+        port1 -> mstb2;
+        edge [color=grey];
+        port2 -> mstb3 -> {port3, port4};
+        port3 -> mstb4;
+        edge [color=""];
+
+        /* Malloc references */
+        edge [style=dashed;dir=back];
+        mstb1 -> {port1, port2};
+        port1 -> mstb2;
+        port2 -> mstb3 [penwidth=3];
+        mstb3 -> port3 [penwidth=3];
+        edge [color=grey];
+        mstb3 -> port4;
+        port3 -> mstb4;
+    }
+
+    mstb1 [label="MSTB #1";style=filled;fillcolor=palegreen];
+    mstb2 [label="MSTB #2";style=filled;fillcolor=palegreen];
+    mstb3 [label="MSTB #3";style=filled;fillcolor=palegreen;penwidth=3];
+    mstb4 [label="MSTB #4";style=filled;fillcolor=grey];
+
+    port1 [label="Port #1"];
+    port2 [label="Port #2";penwidth=5];
+    port3 [label="Port #3";penwidth=3];
+    port4 [label="Port #4";style=filled;fillcolor=grey];
+
+    driver [label="DRM driver";style=filled;shape=box;fillcolor=lightblue];
+
+    payload1 [label="Payload #1";style=filled;shape=box;fillcolor=lightblue];
+    payload2 [label="Payload #2";style=filled;shape=box;fillcolor=lightblue;penwidth=3];
+}
index 5ee9674fb9e981db2c17c0b6f1a08402b5ab5290..2caf21effd281d28805a64a27f921235e489ba66 100644 (file)
@@ -143,6 +143,9 @@ Device Instance and Driver Handling
 .. kernel-doc:: drivers/gpu/drm/drm_drv.c
    :doc: driver instance overview
 
+.. kernel-doc:: include/drm/drm_device.h
+   :internal:
+
 .. kernel-doc:: include/drm/drm_drv.h
    :internal:
 
@@ -230,6 +233,15 @@ Printer
 .. kernel-doc:: drivers/gpu/drm/drm_print.c
    :export:
 
+Utilities
+---------
+
+.. kernel-doc:: include/drm/drm_util.h
+   :doc: drm utils
+
+.. kernel-doc:: include/drm/drm_util.h
+   :internal:
+
 
 Legacy Support Code
 ===================
index b422eb8edf1627baba10a231560eca754e31e846..fbd11b2fe5b5729eab7f3ee0ed112ced354d1f19 100644 (file)
@@ -116,8 +116,6 @@ Framebuffer CMA Helper Functions Reference
 .. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c
    :export:
 
-.. _drm_bridges:
-
 Framebuffer GEM Helper Reference
 ================================
 
@@ -127,6 +125,8 @@ Framebuffer GEM Helper Reference
 .. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c
    :export:
 
+.. _drm_bridges:
+
 Bridges
 =======
 
@@ -208,18 +208,40 @@ Display Port Dual Mode Adaptor Helper Functions Reference
 .. kernel-doc:: drivers/gpu/drm/drm_dp_dual_mode_helper.c
    :export:
 
-Display Port MST Helper Functions Reference
-===========================================
+Display Port MST Helpers
+========================
+
+Overview
+--------
 
 .. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c
    :doc: dp mst helper
 
+.. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c
+   :doc: Branch device and port refcounting
+
+Functions Reference
+-------------------
+
 .. kernel-doc:: include/drm/drm_dp_mst_helper.h
    :internal:
 
 .. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c
    :export:
 
+Topology Lifetime Internals
+---------------------------
+
+These functions aren't exported to drivers, but are documented here to help make
+the MST topology helpers easier to understand
+
+.. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c
+   :functions: drm_dp_mst_topology_try_get_mstb drm_dp_mst_topology_get_mstb
+               drm_dp_mst_topology_put_mstb
+               drm_dp_mst_topology_try_get_port drm_dp_mst_topology_get_port
+               drm_dp_mst_topology_put_port
+               drm_dp_mst_get_mstb_malloc drm_dp_mst_put_mstb_malloc
+
 MIPI DSI Helper Functions Reference
 ===================================
 
index 14191b64446df0eadae3215f690e07ec4a09885b..38360ede12215e6fa0d012d5498436966b38c8c9 100644 (file)
@@ -82,30 +82,6 @@ events for atomic commits correctly. But fixing these bugs is good anyway.
 
 Contact: Daniel Vetter, respective driver maintainers
 
-Better manual-upload support for atomic
----------------------------------------
-
-This would be especially useful for tinydrm:
-
-- Add a struct drm_rect dirty_clip to drm_crtc_state. When duplicating the
-  crtc state, clear that to the max values, x/y = 0 and w/h = MAX_INT, in
-  __drm_atomic_helper_crtc_duplicate_state().
-
-- Move tinydrm_merge_clips into drm_framebuffer.c, dropping the tinydrm\_
-  prefix ofc and using drm_fb\_. drm_framebuffer.c makes sense since this
-  is a function useful to implement the fb->dirty function.
-
-- Create a new drm_fb_dirty function which does essentially what e.g.
-  mipi_dbi_fb_dirty does. You can use e.g. drm_atomic_helper_update_plane as the
-  template. But instead of doing a simple full-screen plane update, this new
-  helper also sets crtc_state->dirty_clip to the right coordinates. And of
-  course it needs to check whether the fb is actually active (and maybe where),
-  so there's some book-keeping involved. There's also some good fun involved in
-  scaling things appropriately. For that case we might simply give up and
-  declare the entire area covered by the plane as dirty.
-
-Contact: Noralf Trønnes, Daniel Vetter
-
 Fallout from atomic KMS
 -----------------------
 
@@ -209,6 +185,36 @@ Would be great to refactor this all into a set of small common helpers.
 
 Contact: Daniel Vetter
 
+Generic fbdev defio support
+---------------------------
+
+The defio support code in the fbdev core has some very specific requirements,
+which means drivers need to have a special framebuffer for fbdev. Which prevents
+us from using the generic fbdev emulation code everywhere. The main issue is
+that it uses some fields in struct page itself, which breaks shmem gem objects
+(and other things).
+
+Possible solution would be to write our own defio mmap code in the drm fbdev
+emulation. It would need to fully wrap the existing mmap ops, forwarding
+everything after it has done the write-protect/mkwrite trickery:
+
+- In the drm_fbdev_fb_mmap helper, if we need defio, change the
+  default page prots to write-protected with something like this::
+
+      vma->vm_page_prot = pgprot_wrprotect(vma->vm_page_prot);
+
+- Set the mkwrite and fsync callbacks with similar implementions to the core
+  fbdev defio stuff. These should all work on plain ptes, they don't actually
+  require a struct page.  uff. These should all work on plain ptes, they don't
+  actually require a struct page.
+
+- Track the dirty pages in a separate structure (bitfield with one bit per page
+  should work) to avoid clobbering struct page.
+
+Might be good to also have some igt testcases for this.
+
+Contact: Daniel Vetter, Noralf Tronnes
+
 Put a reservation_object into drm_gem_object
 --------------------------------------------
 
@@ -354,9 +360,6 @@ KMS cleanups
 
 Some of these date from the very introduction of KMS in 2008 ...
 
-- drm_mode_config.crtc_idr is misnamed, since it contains all KMS object. Should
-  be renamed to drm_mode_config.object_idr.
-
 - drm_display_mode doesn't need to be derived from drm_mode_object. That's
   leftovers from older (never merged into upstream) KMS designs where modes
   where set using their ID, including support to add/remove modes.
@@ -432,21 +435,10 @@ those drivers as simple as possible, so lots of room for refactoring:
   one of the ideas for having a shared dsi/dbi helper, abstracting away the
   transport details more.
 
-- tinydrm_gem_cma_prime_import_sg_table should probably go into the cma
-  helpers, as a _vmapped variant (since not every driver needs the vmap).
-  And tinydrm_gem_cma_free_object could the be merged into
-  drm_gem_cma_free_object().
-
-- tinydrm_fb_create we could move into drm_simple_pipe, only need to add
-  the fb_create hook to drm_simple_pipe_funcs, which would again simplify a
-  bunch of things (since it gives you a one-stop vfunc for simple drivers).
-
 - Quick aside: The unregister devm stuff is kinda getting the lifetimes of
   a drm_device wrong. Doesn't matter, since everyone else gets it wrong
   too :-)
 
-- also rework the drm_framebuffer_funcs->dirty hook wire-up, see above.
-
 Contact: Noralf Trønnes, Daniel Vetter
 
 AMD DC Display Driver
index e5e741714462e15099595697355a18cd4ce36c97..4b752571fe03b7e7aa94bf19281f304cfd4316b7 100644 (file)
@@ -4886,6 +4886,7 @@ DRM DRIVER FOR QXL VIRTUAL GPU
 M:     Dave Airlie <airlied@redhat.com>
 M:     Gerd Hoffmann <kraxel@redhat.com>
 L:     virtualization@lists.linux-foundation.org
+L:     spice-devel@lists.freedesktop.org
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 S:     Maintained
 F:     drivers/gpu/drm/qxl/
@@ -4922,6 +4923,13 @@ DRM DRIVER FOR TDFX VIDEO CARDS
 S:     Orphan / Obsolete
 F:     drivers/gpu/drm/tdfx/
 
+DRM DRIVER FOR TPO TPG110 PANELS
+M:     Linus Walleij <linus.walleij@linaro.org>
+T:     git git://anongit.freedesktop.org/drm/drm-misc
+S:     Maintained
+F:     drivers/gpu/drm/panel/panel-tpo-tpg110.c
+F:     Documentation/devicetree/bindings/display/panel/tpo,tpg110.txt
+
 DRM DRIVER FOR USB DISPLAYLINK VIDEO ADAPTERS
 M:     Dave Airlie <airlied@redhat.com>
 R:     Sean Paul <sean@poorly.run>
@@ -4930,6 +4938,16 @@ S:       Odd Fixes
 F:     drivers/gpu/drm/udl/
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 
+DRM DRIVER FOR VIRTUAL KERNEL MODESETTING (VKMS)
+M:     Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com>
+R:     Haneen Mohammed <hamohammed.sa@gmail.com>
+R:     Daniel Vetter <daniel@ffwll.ch>
+T:     git git://anongit.freedesktop.org/drm/drm-misc
+S:     Maintained
+L:     dri-devel@lists.freedesktop.org
+F:     drivers/gpu/drm/vkms/
+F:     Documentation/gpu/vkms.rst
+
 DRM DRIVER FOR VMWARE VIRTUAL GPU
 M:     "VMware Graphics" <linux-graphics-maintainer@vmware.com>
 M:     Thomas Hellstrom <thellstrom@vmware.com>
@@ -4999,7 +5017,6 @@ F:        Documentation/devicetree/bindings/display/atmel/
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 
 DRM DRIVERS FOR BRIDGE CHIPS
-M:     Archit Taneja <architt@codeaurora.org>
 M:     Andrzej Hajda <a.hajda@samsung.com>
 R:     Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
 S:     Maintained
index ca18e0d23df9775e0a9c342d5a22ac9257d6ee3a..c14cfaea92e25683e26970c24576a47ad3f8b927 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/export.h>
 #include <linux/acpi.h>
+#include <linux/mfd/intel_soc_pmic.h>
 #include <linux/regmap.h>
 #include <acpi/acpi_lpat.h>
 #include "intel_pmic.h"
@@ -36,6 +37,8 @@ struct intel_pmic_opregion {
        struct intel_pmic_regs_handler_ctx ctx;
 };
 
+static struct intel_pmic_opregion *intel_pmic_opregion;
+
 static int pmic_get_reg_bit(int address, struct pmic_table *table,
                            int count, int *reg, int *bit)
 {
@@ -304,6 +307,7 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
        }
 
        opregion->data = d;
+       intel_pmic_opregion = opregion;
        return 0;
 
 out_remove_thermal_handler:
@@ -319,3 +323,60 @@ out_error:
        return ret;
 }
 EXPORT_SYMBOL_GPL(intel_pmic_install_opregion_handler);
+
+/**
+ * intel_soc_pmic_exec_mipi_pmic_seq_element - Execute PMIC MIPI sequence
+ * @i2c_address:  I2C client address for the PMIC
+ * @reg_address:  PMIC register address
+ * @value:        New value for the register bits to change
+ * @mask:         Mask indicating which register bits to change
+ *
+ * DSI LCD panels describe an initialization sequence in the i915 VBT (Video
+ * BIOS Tables) using so called MIPI sequences. One possible element in these
+ * sequences is a PMIC specific element of 15 bytes.
+ *
+ * This function executes these PMIC specific elements sending the embedded
+ * commands to the PMIC.
+ *
+ * Return 0 on success, < 0 on failure.
+ */
+int intel_soc_pmic_exec_mipi_pmic_seq_element(u16 i2c_address, u32 reg_address,
+                                             u32 value, u32 mask)
+{
+       struct intel_pmic_opregion_data *d;
+       int ret;
+
+       if (!intel_pmic_opregion) {
+               pr_warn("%s: No PMIC registered\n", __func__);
+               return -ENXIO;
+       }
+
+       d = intel_pmic_opregion->data;
+
+       mutex_lock(&intel_pmic_opregion->lock);
+
+       if (d->exec_mipi_pmic_seq_element) {
+               ret = d->exec_mipi_pmic_seq_element(intel_pmic_opregion->regmap,
+                                                   i2c_address, reg_address,
+                                                   value, mask);
+       } else if (d->pmic_i2c_address) {
+               if (i2c_address == d->pmic_i2c_address) {
+                       ret = regmap_update_bits(intel_pmic_opregion->regmap,
+                                                reg_address, mask, value);
+               } else {
+                       pr_err("%s: Unexpected i2c-addr: 0x%02x (reg-addr 0x%x value 0x%x mask 0x%x)\n",
+                              __func__, i2c_address, reg_address, value, mask);
+                       ret = -ENXIO;
+               }
+       } else {
+               pr_warn("%s: Not implemented\n", __func__);
+               pr_warn("%s: i2c-addr: 0x%x reg-addr 0x%x value 0x%x mask 0x%x\n",
+                       __func__, i2c_address, reg_address, value, mask);
+               ret = -EOPNOTSUPP;
+       }
+
+       mutex_unlock(&intel_pmic_opregion->lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(intel_soc_pmic_exec_mipi_pmic_seq_element);
index 095afc96952ee5acf03b19df763343f121e91ff7..89379476a1df61f255a03195f5663f3d07df5241 100644 (file)
@@ -15,10 +15,14 @@ struct intel_pmic_opregion_data {
        int (*update_aux)(struct regmap *r, int reg, int raw_temp);
        int (*get_policy)(struct regmap *r, int reg, int bit, u64 *value);
        int (*update_policy)(struct regmap *r, int reg, int bit, int enable);
+       int (*exec_mipi_pmic_seq_element)(struct regmap *r, u16 i2c_address,
+                                         u32 reg_address, u32 value, u32 mask);
        struct pmic_table *power_table;
        int power_table_count;
        struct pmic_table *thermal_table;
        int thermal_table_count;
+       /* For generic exec_mipi_pmic_seq_element handling */
+       int pmic_i2c_address;
 };
 
 int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle, struct regmap *regmap, struct intel_pmic_opregion_data *d);
index 078b0448f30a001f90dbc62deb63eafebb78a1ec..7ffd5624b8e15f9734aa3f301e4a3136a8633887 100644 (file)
@@ -231,6 +231,24 @@ static int intel_cht_wc_pmic_update_power(struct regmap *regmap, int reg,
        return regmap_update_bits(regmap, reg, bitmask, on ? 1 : 0);
 }
 
+static int intel_cht_wc_exec_mipi_pmic_seq_element(struct regmap *regmap,
+                                                  u16 i2c_client_address,
+                                                  u32 reg_address,
+                                                  u32 value, u32 mask)
+{
+       u32 address;
+
+       if (i2c_client_address > 0xff || reg_address > 0xff) {
+               pr_warn("%s warning addresses too big client 0x%x reg 0x%x\n",
+                       __func__, i2c_client_address, reg_address);
+               return -ERANGE;
+       }
+
+       address = (i2c_client_address << 8) | reg_address;
+
+       return regmap_update_bits(regmap, address, mask, value);
+}
+
 /*
  * The thermal table and ops are empty, we do not support the Thermal opregion
  * (DPTF) due to lacking documentation.
@@ -238,6 +256,7 @@ static int intel_cht_wc_pmic_update_power(struct regmap *regmap, int reg,
 static struct intel_pmic_opregion_data intel_cht_wc_pmic_opregion_data = {
        .get_power              = intel_cht_wc_pmic_get_power,
        .update_power           = intel_cht_wc_pmic_update_power,
+       .exec_mipi_pmic_seq_element = intel_cht_wc_exec_mipi_pmic_seq_element,
        .power_table            = power_table,
        .power_table_count      = ARRAY_SIZE(power_table),
 };
index 2579675b7082b76e593a095771f50e9c8e07bca9..1b49cbb1e21e85377e7474b7b2f00231e5ed2dce 100644 (file)
@@ -240,6 +240,7 @@ static struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = {
        .power_table_count = ARRAY_SIZE(power_table),
        .thermal_table = thermal_table,
        .thermal_table_count = ARRAY_SIZE(thermal_table),
+       .pmic_i2c_address = 0x34,
 };
 
 static acpi_status intel_xpower_pmic_gpio_handler(u32 function,
index 02f7f9a899797467968ee7894ccd94797a971366..7c858020d14b8e91a1af439193873f3bd5434f88 100644 (file)
@@ -1093,17 +1093,7 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
        return 0;
 }
 
-static int dma_buf_debug_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, dma_buf_debug_show, NULL);
-}
-
-static const struct file_operations dma_buf_debug_fops = {
-       .open           = dma_buf_debug_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(dma_buf_debug);
 
 static struct dentry *dma_buf_debugfs_dir;
 
index 136ec04d683f1c5b80598301f8fab897cd99b5e4..3aa8733f832af9596f664b0f525de3620babf8fc 100644 (file)
@@ -649,7 +649,7 @@ EXPORT_SYMBOL(dma_fence_wait_any_timeout);
  */
 void
 dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops,
-              spinlock_t *lock, u64 context, unsigned seqno)
+              spinlock_t *lock, u64 context, u64 seqno)
 {
        BUG_ON(!lock);
        BUG_ON(!ops || !ops->get_driver_name || !ops->get_timeline_name);
index 53c1d6d36a642f04ec49aa0e3cfeabeb84205609..32dcf7b4c9356833ceb23e33af61a7725493e664 100644 (file)
@@ -172,7 +172,7 @@ static bool timeline_fence_enable_signaling(struct dma_fence *fence)
 static void timeline_fence_value_str(struct dma_fence *fence,
                                    char *str, int size)
 {
-       snprintf(str, size, "%d", fence->seqno);
+       snprintf(str, size, "%lld", fence->seqno);
 }
 
 static void timeline_fence_timeline_value_str(struct dma_fence *fence,
index c4c8ecb24aa9b4e9eb233847dd9a7bbfa1cb7fe4..c0abf37df88bbe25d2331249e902fa47a5c0c7a3 100644 (file)
@@ -147,7 +147,7 @@ static void sync_print_sync_file(struct seq_file *s,
        }
 }
 
-static int sync_debugfs_show(struct seq_file *s, void *unused)
+static int sync_info_debugfs_show(struct seq_file *s, void *unused)
 {
        struct list_head *pos;
 
@@ -178,17 +178,7 @@ static int sync_debugfs_show(struct seq_file *s, void *unused)
        return 0;
 }
 
-static int sync_info_debugfs_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, sync_debugfs_show, inode->i_private);
-}
-
-static const struct file_operations sync_info_debugfs_fops = {
-       .open           = sync_info_debugfs_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(sync_info_debugfs);
 
 static __init int sync_debugfs_init(void)
 {
@@ -218,7 +208,7 @@ void sync_dump(void)
        };
        int i;
 
-       sync_debugfs_show(&s, NULL);
+       sync_info_debugfs_show(&s, NULL);
 
        for (i = 0; i < s.count; i += DUMP_CHUNK) {
                if ((s.count - i) > DUMP_CHUNK) {
index 35dd06479867fad9636db14fc58747ee60dbf198..4f6305ca52c8e96c006b29516486a4e0ba7d12f4 100644 (file)
@@ -144,7 +144,7 @@ char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len)
        } else {
                struct dma_fence *fence = sync_file->fence;
 
-               snprintf(buf, len, "%s-%s%llu-%d",
+               snprintf(buf, len, "%s-%s%llu-%lld",
                         fence->ops->get_driver_name(fence),
                         fence->ops->get_timeline_name(fence),
                         fence->context,
@@ -258,7 +258,7 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
 
                        i_b++;
                } else {
-                       if (pt_a->seqno - pt_b->seqno <= INT_MAX)
+                       if (__dma_fence_is_later(pt_a->seqno, pt_b->seqno))
                                add_fence(fences, &i, pt_a);
                        else
                                add_fence(fences, &i, pt_b);
index 4385f00e1d055583df06ae4b7be0e6a6a68adc51..bd943a71756ca81bb8fe38836ef07980a26dd324 100644 (file)
@@ -170,10 +170,6 @@ config DRM_KMS_CMA_HELPER
        bool
        depends on DRM
        select DRM_GEM_CMA_HELPER
-       select DRM_KMS_FB_HELPER
-       select FB_SYS_FILLRECT
-       select FB_SYS_COPYAREA
-       select FB_SYS_IMAGEBLIT
        help
          Choose this if you need the KMS CMA helper functions
 
index f76bcb9c45e488a07d1f17dc7125d831563c76fc..466da5954a682de002582e2759ef07a33a775ecd 100644 (file)
@@ -57,7 +57,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
 
 # add asic specific block
 amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \
-       ci_smc.o ci_dpm.o dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o
+       dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o
 
 amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce_v6_0.o si_dpm.o si_smc.o
 
index bcef6ea4bcf9f83d49f6c3739406b52eb8a196b0..9efa681d08781162b3e51c52564adc176f30081d 100644 (file)
@@ -542,6 +542,11 @@ struct amdgpu_asic_funcs {
        bool (*need_full_reset)(struct amdgpu_device *adev);
        /* initialize doorbell layout for specific asic*/
        void (*init_doorbell_index)(struct amdgpu_device *adev);
+       /* PCIe bandwidth usage */
+       void (*get_pcie_usage)(struct amdgpu_device *adev, uint64_t *count0,
+                              uint64_t *count1);
+       /* do we need to reset the asic at init time (e.g., kexec) */
+       bool (*need_reset_on_init)(struct amdgpu_device *adev);
 };
 
 /*
@@ -634,7 +639,7 @@ struct amdgpu_nbio_funcs {
        void (*hdp_flush)(struct amdgpu_device *adev, struct amdgpu_ring *ring);
        u32 (*get_memsize)(struct amdgpu_device *adev);
        void (*sdma_doorbell_range)(struct amdgpu_device *adev, int instance,
-                                   bool use_doorbell, int doorbell_index);
+                       bool use_doorbell, int doorbell_index, int doorbell_size);
        void (*enable_doorbell_aperture)(struct amdgpu_device *adev,
                                         bool enable);
        void (*enable_doorbell_selfring_aperture)(struct amdgpu_device *adev,
@@ -1042,6 +1047,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
 #define amdgpu_asic_invalidate_hdp(adev, r) (adev)->asic_funcs->invalidate_hdp((adev), (r))
 #define amdgpu_asic_need_full_reset(adev) (adev)->asic_funcs->need_full_reset((adev))
 #define amdgpu_asic_init_doorbell_index(adev) (adev)->asic_funcs->init_doorbell_index((adev))
+#define amdgpu_asic_get_pcie_usage(adev, cnt0, cnt1) ((adev)->asic_funcs->get_pcie_usage((adev), (cnt0), (cnt1)))
+#define amdgpu_asic_need_reset_on_init(adev) (adev)->asic_funcs->need_reset_on_init((adev))
 
 /* Common functions */
 bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev);
index 2dfaf158ef073340e778c9f51a9e6bc905f3f48d..e957e42c539a8e7d73d6e26c3a35f145d8da4e7f 100644 (file)
@@ -28,8 +28,6 @@
 #include <linux/module.h>
 #include <linux/dma-buf.h>
 
-const struct kgd2kfd_calls *kgd2kfd;
-
 static const unsigned int compute_vmid_bitmap = 0xFF00;
 
 /* Total memory size in system memory and all GPU VRAM. Used to
@@ -47,12 +45,9 @@ int amdgpu_amdkfd_init(void)
        amdgpu_amdkfd_total_mem_size *= si.mem_unit;
 
 #ifdef CONFIG_HSA_AMD
-       ret = kgd2kfd_init(KFD_INTERFACE_VERSION, &kgd2kfd);
-       if (ret)
-               kgd2kfd = NULL;
+       ret = kgd2kfd_init();
        amdgpu_amdkfd_gpuvm_init_mem_limits();
 #else
-       kgd2kfd = NULL;
        ret = -ENOENT;
 #endif
 
@@ -61,17 +56,13 @@ int amdgpu_amdkfd_init(void)
 
 void amdgpu_amdkfd_fini(void)
 {
-       if (kgd2kfd)
-               kgd2kfd->exit();
+       kgd2kfd_exit();
 }
 
 void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev)
 {
        const struct kfd2kgd_calls *kfd2kgd;
 
-       if (!kgd2kfd)
-               return;
-
        switch (adev->asic_type) {
 #ifdef CONFIG_DRM_AMDGPU_CIK
        case CHIP_KAVERI:
@@ -98,8 +89,8 @@ void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev)
                return;
        }
 
-       adev->kfd.dev = kgd2kfd->probe((struct kgd_dev *)adev,
-                                      adev->pdev, kfd2kgd);
+       adev->kfd.dev = kgd2kfd_probe((struct kgd_dev *)adev,
+                                     adev->pdev, kfd2kgd);
 
        if (adev->kfd.dev)
                amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size;
@@ -182,7 +173,7 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
                                &gpu_resources.doorbell_start_offset);
 
                if (adev->asic_type < CHIP_VEGA10) {
-                       kgd2kfd->device_init(adev->kfd.dev, &gpu_resources);
+                       kgd2kfd_device_init(adev->kfd.dev, &gpu_resources);
                        return;
                }
 
@@ -197,13 +188,13 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
                         * can use each doorbell assignment twice.
                         */
                        gpu_resources.sdma_doorbell[0][i] =
-                               adev->doorbell_index.sdma_engine0 + (i >> 1);
+                               adev->doorbell_index.sdma_engine[0] + (i >> 1);
                        gpu_resources.sdma_doorbell[0][i+1] =
-                               adev->doorbell_index.sdma_engine0 + 0x200 + (i >> 1);
+                               adev->doorbell_index.sdma_engine[0] + 0x200 + (i >> 1);
                        gpu_resources.sdma_doorbell[1][i] =
-                               adev->doorbell_index.sdma_engine1 + (i >> 1);
+                               adev->doorbell_index.sdma_engine[1] + (i >> 1);
                        gpu_resources.sdma_doorbell[1][i+1] =
-                               adev->doorbell_index.sdma_engine1 + 0x200 + (i >> 1);
+                               adev->doorbell_index.sdma_engine[1] + 0x200 + (i >> 1);
                }
                /* Doorbells 0x0e0-0ff and 0x2e0-2ff are reserved for
                 * SDMA, IH and VCN. So don't use them for the CP.
@@ -211,14 +202,14 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
                gpu_resources.reserved_doorbell_mask = 0x1e0;
                gpu_resources.reserved_doorbell_val  = 0x0e0;
 
-               kgd2kfd->device_init(adev->kfd.dev, &gpu_resources);
+               kgd2kfd_device_init(adev->kfd.dev, &gpu_resources);
        }
 }
 
 void amdgpu_amdkfd_device_fini(struct amdgpu_device *adev)
 {
        if (adev->kfd.dev) {
-               kgd2kfd->device_exit(adev->kfd.dev);
+               kgd2kfd_device_exit(adev->kfd.dev);
                adev->kfd.dev = NULL;
        }
 }
@@ -227,13 +218,13 @@ void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev,
                const void *ih_ring_entry)
 {
        if (adev->kfd.dev)
-               kgd2kfd->interrupt(adev->kfd.dev, ih_ring_entry);
+               kgd2kfd_interrupt(adev->kfd.dev, ih_ring_entry);
 }
 
 void amdgpu_amdkfd_suspend(struct amdgpu_device *adev)
 {
        if (adev->kfd.dev)
-               kgd2kfd->suspend(adev->kfd.dev);
+               kgd2kfd_suspend(adev->kfd.dev);
 }
 
 int amdgpu_amdkfd_resume(struct amdgpu_device *adev)
@@ -241,7 +232,7 @@ int amdgpu_amdkfd_resume(struct amdgpu_device *adev)
        int r = 0;
 
        if (adev->kfd.dev)
-               r = kgd2kfd->resume(adev->kfd.dev);
+               r = kgd2kfd_resume(adev->kfd.dev);
 
        return r;
 }
@@ -251,7 +242,7 @@ int amdgpu_amdkfd_pre_reset(struct amdgpu_device *adev)
        int r = 0;
 
        if (adev->kfd.dev)
-               r = kgd2kfd->pre_reset(adev->kfd.dev);
+               r = kgd2kfd_pre_reset(adev->kfd.dev);
 
        return r;
 }
@@ -261,7 +252,7 @@ int amdgpu_amdkfd_post_reset(struct amdgpu_device *adev)
        int r = 0;
 
        if (adev->kfd.dev)
-               r = kgd2kfd->post_reset(adev->kfd.dev);
+               r = kgd2kfd_post_reset(adev->kfd.dev);
 
        return r;
 }
@@ -619,4 +610,47 @@ struct kfd2kgd_calls *amdgpu_amdkfd_gfx_9_0_get_functions(void)
 {
        return NULL;
 }
+
+struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev,
+                             const struct kfd2kgd_calls *f2g)
+{
+       return NULL;
+}
+
+bool kgd2kfd_device_init(struct kfd_dev *kfd,
+                        const struct kgd2kfd_shared_resources *gpu_resources)
+{
+       return false;
+}
+
+void kgd2kfd_device_exit(struct kfd_dev *kfd)
+{
+}
+
+void kgd2kfd_exit(void)
+{
+}
+
+void kgd2kfd_suspend(struct kfd_dev *kfd)
+{
+}
+
+int kgd2kfd_resume(struct kfd_dev *kfd)
+{
+       return 0;
+}
+
+int kgd2kfd_pre_reset(struct kfd_dev *kfd)
+{
+       return 0;
+}
+
+int kgd2kfd_post_reset(struct kfd_dev *kfd)
+{
+       return 0;
+}
+
+void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry)
+{
+}
 #endif
index 70429f7aa9a84c0189ce3e3748a55f4b3549b08b..0b31a1859023c76403081277c6f3aa5941bee0ce 100644 (file)
@@ -33,7 +33,6 @@
 #include "amdgpu_sync.h"
 #include "amdgpu_vm.h"
 
-extern const struct kgd2kfd_calls *kgd2kfd;
 extern uint64_t amdgpu_amdkfd_total_mem_size;
 
 struct amdgpu_device;
@@ -214,4 +213,22 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd,
 void amdgpu_amdkfd_gpuvm_init_mem_limits(void);
 void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo);
 
+/* KGD2KFD callbacks */
+int kgd2kfd_init(void);
+void kgd2kfd_exit(void);
+struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev,
+                             const struct kfd2kgd_calls *f2g);
+bool kgd2kfd_device_init(struct kfd_dev *kfd,
+                        const struct kgd2kfd_shared_resources *gpu_resources);
+void kgd2kfd_device_exit(struct kfd_dev *kfd);
+void kgd2kfd_suspend(struct kfd_dev *kfd);
+int kgd2kfd_resume(struct kfd_dev *kfd);
+int kgd2kfd_pre_reset(struct kfd_dev *kfd);
+int kgd2kfd_post_reset(struct kfd_dev *kfd);
+void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry);
+int kgd2kfd_quiesce_mm(struct mm_struct *mm);
+int kgd2kfd_resume_mm(struct mm_struct *mm);
+int kgd2kfd_schedule_evict_and_restore_process(struct mm_struct *mm,
+                                              struct dma_fence *fence);
+
 #endif /* AMDGPU_AMDKFD_H_INCLUDED */
index 574c1181ae9a22c1e63f37a5919c47a3b2d9c476..3107b9575929184bbf624d579bdcf3589116efdc 100644 (file)
@@ -122,7 +122,7 @@ static bool amdkfd_fence_enable_signaling(struct dma_fence *f)
        if (dma_fence_is_signaled(f))
                return true;
 
-       if (!kgd2kfd->schedule_evict_and_restore_process(fence->mm, f))
+       if (!kgd2kfd_schedule_evict_and_restore_process(fence->mm, f))
                return true;
 
        return false;
index be1ab43473c6c727bd1832efa3d5b7c09edffed2..d7b10d79f1debdcb5e8f254dd69c7d0b7119e730 100644 (file)
@@ -1790,7 +1790,7 @@ int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem,
        evicted_bos = atomic_inc_return(&process_info->evicted_bos);
        if (evicted_bos == 1) {
                /* First eviction, stop the queues */
-               r = kgd2kfd->quiesce_mm(mm);
+               r = kgd2kfd_quiesce_mm(mm);
                if (r)
                        pr_err("Failed to quiesce KFD\n");
                schedule_delayed_work(&process_info->restore_userptr_work,
@@ -2082,7 +2082,7 @@ static void amdgpu_amdkfd_restore_userptr_worker(struct work_struct *work)
            evicted_bos)
                goto unlock_out;
        evicted_bos = 0;
-       if (kgd2kfd->resume_mm(mm)) {
+       if (kgd2kfd_resume_mm(mm)) {
                pr_err("%s: Failed to resume KFD\n", __func__);
                /* No recovery from this failure. Probably the CP is
                 * hanging. No point trying again.
index a028661d9e2013dd2a6e5611448438c7590fec82..92b11de1958132c28e4ffd68e1fd782a8e2e5771 100644 (file)
@@ -576,6 +576,7 @@ static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = {
        { 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0x1002, 0x6900, 0x1025, 0x125A, AMDGPU_PX_QUIRK_FORCE_ATPX },
+       { 0x1002, 0x6900, 0x17AA, 0x3806, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0, 0, 0, 0, 0 },
 };
 
index 8a078f4ae73dd17cc43384e605d28e4c613e7c37..c898b19f335a3549fe5ed0331b3a511b93b1d7a2 100644 (file)
@@ -1645,7 +1645,7 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
                if (r) {
                        DRM_ERROR("sw_init of IP block <%s> failed %d\n",
                                  adev->ip_blocks[i].version->funcs->name, r);
-                       return r;
+                       goto init_failed;
                }
                adev->ip_blocks[i].status.sw = true;
 
@@ -1654,17 +1654,17 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
                        r = amdgpu_device_vram_scratch_init(adev);
                        if (r) {
                                DRM_ERROR("amdgpu_vram_scratch_init failed %d\n", r);
-                               return r;
+                               goto init_failed;
                        }
                        r = adev->ip_blocks[i].version->funcs->hw_init((void *)adev);
                        if (r) {
                                DRM_ERROR("hw_init %d failed %d\n", i, r);
-                               return r;
+                               goto init_failed;
                        }
                        r = amdgpu_device_wb_init(adev);
                        if (r) {
                                DRM_ERROR("amdgpu_device_wb_init failed %d\n", r);
-                               return r;
+                               goto init_failed;
                        }
                        adev->ip_blocks[i].status.hw = true;
 
@@ -1675,7 +1675,7 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
                                                                AMDGPU_CSA_SIZE);
                                if (r) {
                                        DRM_ERROR("allocate CSA failed %d\n", r);
-                                       return r;
+                                       goto init_failed;
                                }
                        }
                }
@@ -1683,28 +1683,32 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
 
        r = amdgpu_ucode_create_bo(adev); /* create ucode bo when sw_init complete*/
        if (r)
-               return r;
+               goto init_failed;
 
        r = amdgpu_device_ip_hw_init_phase1(adev);
        if (r)
-               return r;
+               goto init_failed;
 
        r = amdgpu_device_fw_loading(adev);
        if (r)
-               return r;
+               goto init_failed;
 
        r = amdgpu_device_ip_hw_init_phase2(adev);
        if (r)
-               return r;
+               goto init_failed;
 
        if (adev->gmc.xgmi.num_physical_nodes > 1)
                amdgpu_xgmi_add_device(adev);
        amdgpu_amdkfd_device_init(adev);
 
-       if (amdgpu_sriov_vf(adev))
+init_failed:
+       if (amdgpu_sriov_vf(adev)) {
+               if (!r)
+                       amdgpu_virt_init_data_exchange(adev);
                amdgpu_virt_release_full_gpu(adev, true);
+       }
 
-       return 0;
+       return r;
 }
 
 /**
@@ -2131,7 +2135,7 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev)
                                continue;
 
                        r = block->version->funcs->hw_init(adev);
-                       DRM_INFO("RE-INIT: %s %s\n", block->version->funcs->name, r?"failed":"succeeded");
+                       DRM_INFO("RE-INIT-early: %s %s\n", block->version->funcs->name, r?"failed":"succeeded");
                        if (r)
                                return r;
                }
@@ -2165,7 +2169,7 @@ static int amdgpu_device_ip_reinit_late_sriov(struct amdgpu_device *adev)
                                continue;
 
                        r = block->version->funcs->hw_init(adev);
-                       DRM_INFO("RE-INIT: %s %s\n", block->version->funcs->name, r?"failed":"succeeded");
+                       DRM_INFO("RE-INIT-late: %s %s\n", block->version->funcs->name, r?"failed":"succeeded");
                        if (r)
                                return r;
                }
@@ -2546,6 +2550,17 @@ int amdgpu_device_init(struct amdgpu_device *adev,
        /* detect if we are with an SRIOV vbios */
        amdgpu_device_detect_sriov_bios(adev);
 
+       /* check if we need to reset the asic
+        *  E.g., driver was not cleanly unloaded previously, etc.
+        */
+       if (!amdgpu_sriov_vf(adev) && amdgpu_asic_need_reset_on_init(adev)) {
+               r = amdgpu_asic_reset(adev);
+               if (r) {
+                       dev_err(adev->dev, "asic reset on init failed\n");
+                       goto failed;
+               }
+       }
+
        /* Post card if necessary */
        if (amdgpu_device_need_post(adev)) {
                if (!adev->bios) {
@@ -2610,6 +2625,8 @@ fence_driver_init:
                }
                dev_err(adev->dev, "amdgpu_device_ip_init failed\n");
                amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_AMDGPU_INIT_FAIL, 0, 0);
+               if (amdgpu_virt_request_full_gpu(adev, false))
+                       amdgpu_virt_release_full_gpu(adev, false);
                goto failed;
        }
 
@@ -2632,9 +2649,6 @@ fence_driver_init:
                goto failed;
        }
 
-       if (amdgpu_sriov_vf(adev))
-               amdgpu_virt_init_data_exchange(adev);
-
        amdgpu_fbdev_init(adev);
 
        r = amdgpu_pm_sysfs_init(adev);
@@ -2708,7 +2722,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
        amdgpu_irq_disable_all(adev);
        if (adev->mode_info.mode_config_initialized){
                if (!amdgpu_device_has_dc_support(adev))
-                       drm_crtc_force_disable_all(adev->ddev);
+                       drm_helper_force_disable_all(adev->ddev);
                else
                        drm_atomic_helper_shutdown(adev->ddev);
        }
@@ -2798,7 +2812,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
                        struct drm_framebuffer *fb = crtc->primary->fb;
                        struct amdgpu_bo *robj;
 
-                       if (amdgpu_crtc->cursor_bo) {
+                       if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {
                                struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
                                r = amdgpu_bo_reserve(aobj, true);
                                if (r == 0) {
@@ -2906,7 +2920,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
                list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                        struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 
-                       if (amdgpu_crtc->cursor_bo) {
+                       if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {
                                struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
                                r = amdgpu_bo_reserve(aobj, true);
                                if (r == 0) {
@@ -3226,6 +3240,7 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
        r = amdgpu_ib_ring_tests(adev);
 
 error:
+       amdgpu_virt_init_data_exchange(adev);
        amdgpu_virt_release_full_gpu(adev, true);
        if (!r && adev->virt.gim_feature & AMDGIM_FEATURE_GIM_FLR_VRAMLOST) {
                atomic_inc(&adev->vram_lost_counter);
@@ -3298,17 +3313,15 @@ static int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
                if (!ring || !ring->sched.thread)
                        continue;
 
-               kthread_park(ring->sched.thread);
-
-               if (job && job->base.sched != &ring->sched)
-                       continue;
-
-               drm_sched_hw_job_reset(&ring->sched, job ? &job->base : NULL);
+               drm_sched_stop(&ring->sched);
 
                /* after all hw jobs are reset, hw fence is meaningless, so force_completion */
                amdgpu_fence_driver_force_completion(ring);
        }
 
+       if(job)
+               drm_sched_increase_karma(&job->base);
+
 
 
        if (!amdgpu_sriov_vf(adev)) {
@@ -3454,14 +3467,10 @@ static void amdgpu_device_post_asic_reset(struct amdgpu_device *adev,
                if (!ring || !ring->sched.thread)
                        continue;
 
-               /* only need recovery sched of the given job's ring
-                * or all rings (in the case @job is NULL)
-                * after above amdgpu_reset accomplished
-                */
-               if ((!job || job->base.sched == &ring->sched) && !adev->asic_reset_res)
-                       drm_sched_job_recovery(&ring->sched);
+               if (!adev->asic_reset_res)
+                       drm_sched_resubmit_jobs(&ring->sched);
 
-               kthread_unpark(ring->sched.thread);
+               drm_sched_start(&ring->sched, !adev->asic_reset_res);
        }
 
        if (!amdgpu_device_has_dc_support(adev)) {
@@ -3521,9 +3530,9 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
         * by different nodes. No point also since the one node already executing
         * reset will also reset all the other nodes in the hive.
         */
-       hive = amdgpu_get_xgmi_hive(adev);
+       hive = amdgpu_get_xgmi_hive(adev, 0);
        if (hive && adev->gmc.xgmi.num_physical_nodes > 1 &&
-           !mutex_trylock(&hive->hive_lock))
+           !mutex_trylock(&hive->reset_lock))
                return 0;
 
        /* Start with adev pre asic reset first for soft reset check.*/
@@ -3602,7 +3611,7 @@ retry:    /* Rest of adevs pre asic reset from XGMI hive. */
        }
 
        if (hive && adev->gmc.xgmi.num_physical_nodes > 1)
-               mutex_unlock(&hive->hive_lock);
+               mutex_unlock(&hive->reset_lock);
 
        if (r)
                dev_info(adev->dev, "GPU reset end with ret = %d\n", r);
index 15ce7e681d67c1776be90449a6d61bc0dfd02aa5..b083b219b1a966e9e38c318cb30c91e478f650c7 100644 (file)
@@ -188,10 +188,12 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
                goto cleanup;
        }
 
-       r = amdgpu_bo_pin(new_abo, amdgpu_display_supported_domains(adev));
-       if (unlikely(r != 0)) {
-               DRM_ERROR("failed to pin new abo buffer before flip\n");
-               goto unreserve;
+       if (!adev->enable_virtual_display) {
+               r = amdgpu_bo_pin(new_abo, amdgpu_display_supported_domains(adev));
+               if (unlikely(r != 0)) {
+                       DRM_ERROR("failed to pin new abo buffer before flip\n");
+                       goto unreserve;
+               }
        }
 
        r = amdgpu_ttm_alloc_gart(&new_abo->tbo);
@@ -211,7 +213,8 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
        amdgpu_bo_get_tiling_flags(new_abo, &tiling_flags);
        amdgpu_bo_unreserve(new_abo);
 
-       work->base = amdgpu_bo_gpu_offset(new_abo);
+       if (!adev->enable_virtual_display)
+               work->base = amdgpu_bo_gpu_offset(new_abo);
        work->target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) +
                amdgpu_get_vblank_counter_kms(dev, work->crtc_id);
 
@@ -242,9 +245,10 @@ pflip_cleanup:
                goto cleanup;
        }
 unpin:
-       if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) {
-               DRM_ERROR("failed to unpin new abo in error path\n");
-       }
+       if (!adev->enable_virtual_display)
+               if (unlikely(amdgpu_bo_unpin(new_abo) != 0))
+                       DRM_ERROR("failed to unpin new abo in error path\n");
+
 unreserve:
        amdgpu_bo_unreserve(new_abo);
 
index be620b29f4aaa6b96e378955cf2831c75fbb223e..1cfec06f81d4049a35534f73f90defa303bcad2e 100644 (file)
@@ -51,14 +51,7 @@ struct amdgpu_doorbell_index {
        uint32_t userqueue_start;
        uint32_t userqueue_end;
        uint32_t gfx_ring0;
-       uint32_t sdma_engine0;
-       uint32_t sdma_engine1;
-       uint32_t sdma_engine2;
-       uint32_t sdma_engine3;
-       uint32_t sdma_engine4;
-       uint32_t sdma_engine5;
-       uint32_t sdma_engine6;
-       uint32_t sdma_engine7;
+       uint32_t sdma_engine[8];
        uint32_t ih;
        union {
                struct {
@@ -79,6 +72,8 @@ struct amdgpu_doorbell_index {
                } uvd_vce;
        };
        uint32_t max_assignment;
+       /* Per engine SDMA doorbell size in dword */
+       uint32_t sdma_doorbell_range;
 };
 
 typedef enum _AMDGPU_DOORBELL_ASSIGNMENT
index f972cd156795ab60ed786ee198b8d0048b90fc95..2f61e9edb1c1a10f69322807bb3f75d76a5ae97b 100644 (file)
@@ -364,6 +364,14 @@ enum amdgpu_pcie_gen {
                ((adev)->powerplay.pp_funcs->enable_mgpu_fan_boost(\
                        (adev)->powerplay.pp_handle))
 
+#define amdgpu_dpm_get_ppfeature_status(adev, buf) \
+               ((adev)->powerplay.pp_funcs->get_ppfeature_status(\
+                       (adev)->powerplay.pp_handle, (buf)))
+
+#define amdgpu_dpm_set_ppfeature_status(adev, ppfeatures) \
+               ((adev)->powerplay.pp_funcs->set_ppfeature_status(\
+                       (adev)->powerplay.pp_handle, (ppfeatures)))
+
 struct amdgpu_dpm {
        struct amdgpu_ps        *ps;
        /* number of valid power states */
index c48207b377bc5f5c64549eca69662896285971e5..0b8ef2d27d6b2b8e60e0959f0cb8e742e4de3c7f 100644 (file)
@@ -202,12 +202,12 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
                        amdgpu_asic_flush_hdp(adev, ring);
        }
 
+       if (need_ctx_switch)
+               status |= AMDGPU_HAVE_CTX_SWITCH;
+
        skip_preamble = ring->current_ctx == fence_ctx;
        if (job && ring->funcs->emit_cntxcntl) {
-               if (need_ctx_switch)
-                       status |= AMDGPU_HAVE_CTX_SWITCH;
                status |= job->preamble_status;
-
                amdgpu_ring_emit_cntxcntl(ring, status);
        }
 
@@ -221,8 +221,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
                        !amdgpu_sriov_vf(adev)) /* for SRIOV preemption, Preamble CE ib must be inserted anyway */
                        continue;
 
-               amdgpu_ring_emit_ib(ring, job, ib, need_ctx_switch);
-               need_ctx_switch = false;
+               amdgpu_ring_emit_ib(ring, job, ib, status);
+               status &= ~AMDGPU_HAVE_CTX_SWITCH;
        }
 
        if (ring->funcs->emit_tmz)
index 8af67f6496608e04ed69de5e69930877c6029fea..d0a5db777b6d24c0b505a3ea827877ee91728ccf 100644 (file)
@@ -52,6 +52,8 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
        ih->use_bus_addr = use_bus_addr;
 
        if (use_bus_addr) {
+               dma_addr_t dma_addr;
+
                if (ih->ring)
                        return 0;
 
@@ -59,21 +61,26 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
                 * add them to the end of the ring allocation.
                 */
                ih->ring = dma_alloc_coherent(adev->dev, ih->ring_size + 8,
-                                             &ih->rb_dma_addr, GFP_KERNEL);
+                                             &dma_addr, GFP_KERNEL);
                if (ih->ring == NULL)
                        return -ENOMEM;
 
                memset((void *)ih->ring, 0, ih->ring_size + 8);
-               ih->wptr_offs = (ih->ring_size / 4) + 0;
-               ih->rptr_offs = (ih->ring_size / 4) + 1;
+               ih->gpu_addr = dma_addr;
+               ih->wptr_addr = dma_addr + ih->ring_size;
+               ih->wptr_cpu = &ih->ring[ih->ring_size / 4];
+               ih->rptr_addr = dma_addr + ih->ring_size + 4;
+               ih->rptr_cpu = &ih->ring[(ih->ring_size / 4) + 1];
        } else {
-               r = amdgpu_device_wb_get(adev, &ih->wptr_offs);
+               unsigned wptr_offs, rptr_offs;
+
+               r = amdgpu_device_wb_get(adev, &wptr_offs);
                if (r)
                        return r;
 
-               r = amdgpu_device_wb_get(adev, &ih->rptr_offs);
+               r = amdgpu_device_wb_get(adev, &rptr_offs);
                if (r) {
-                       amdgpu_device_wb_free(adev, ih->wptr_offs);
+                       amdgpu_device_wb_free(adev, wptr_offs);
                        return r;
                }
 
@@ -82,10 +89,15 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
                                            &ih->ring_obj, &ih->gpu_addr,
                                            (void **)&ih->ring);
                if (r) {
-                       amdgpu_device_wb_free(adev, ih->rptr_offs);
-                       amdgpu_device_wb_free(adev, ih->wptr_offs);
+                       amdgpu_device_wb_free(adev, rptr_offs);
+                       amdgpu_device_wb_free(adev, wptr_offs);
                        return r;
                }
+
+               ih->wptr_addr = adev->wb.gpu_addr + wptr_offs * 4;
+               ih->wptr_cpu = &adev->wb.wb[wptr_offs];
+               ih->rptr_addr = adev->wb.gpu_addr + rptr_offs * 4;
+               ih->rptr_cpu = &adev->wb.wb[rptr_offs];
        }
        return 0;
 }
@@ -109,13 +121,13 @@ void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
                 * add them to the end of the ring allocation.
                 */
                dma_free_coherent(adev->dev, ih->ring_size + 8,
-                                 (void *)ih->ring, ih->rb_dma_addr);
+                                 (void *)ih->ring, ih->gpu_addr);
                ih->ring = NULL;
        } else {
                amdgpu_bo_free_kernel(&ih->ring_obj, &ih->gpu_addr,
                                      (void **)&ih->ring);
-               amdgpu_device_wb_free(adev, ih->wptr_offs);
-               amdgpu_device_wb_free(adev, ih->rptr_offs);
+               amdgpu_device_wb_free(adev, (ih->wptr_addr - ih->gpu_addr) / 4);
+               amdgpu_device_wb_free(adev, (ih->rptr_addr - ih->gpu_addr) / 4);
        }
 }
 
@@ -137,7 +149,7 @@ int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
        if (!ih->enabled || adev->shutdown)
                return IRQ_NONE;
 
-       wptr = amdgpu_ih_get_wptr(adev);
+       wptr = amdgpu_ih_get_wptr(adev, ih);
 
 restart_ih:
        /* is somebody else already processing irqs? */
@@ -154,11 +166,11 @@ restart_ih:
                ih->rptr &= ih->ptr_mask;
        }
 
-       amdgpu_ih_set_rptr(adev);
+       amdgpu_ih_set_rptr(adev, ih);
        atomic_set(&ih->lock, 0);
 
        /* make sure wptr hasn't changed while processing */
-       wptr = amdgpu_ih_get_wptr(adev);
+       wptr = amdgpu_ih_get_wptr(adev, ih);
        if (wptr != ih->rptr)
                goto restart_ih;
 
index f877bb78d10a31b11ebb9d8563d7b86055390966..1ccb1831382a2699a91d69a8a441f0e4fc60bfbb 100644 (file)
@@ -31,34 +31,40 @@ struct amdgpu_iv_entry;
  * R6xx+ IH ring
  */
 struct amdgpu_ih_ring {
-       struct amdgpu_bo        *ring_obj;
-       volatile uint32_t       *ring;
-       unsigned                rptr;
        unsigned                ring_size;
-       uint64_t                gpu_addr;
        uint32_t                ptr_mask;
-       atomic_t                lock;
-       bool                    enabled;
-       unsigned                wptr_offs;
-       unsigned                rptr_offs;
        u32                     doorbell_index;
        bool                    use_doorbell;
        bool                    use_bus_addr;
-       dma_addr_t              rb_dma_addr; /* only used when use_bus_addr = true */
+
+       struct amdgpu_bo        *ring_obj;
+       volatile uint32_t       *ring;
+       uint64_t                gpu_addr;
+
+       uint64_t                wptr_addr;
+       volatile uint32_t       *wptr_cpu;
+
+       uint64_t                rptr_addr;
+       volatile uint32_t       *rptr_cpu;
+
+       bool                    enabled;
+       unsigned                rptr;
+       atomic_t                lock;
 };
 
 /* provided by the ih block */
 struct amdgpu_ih_funcs {
        /* ring read/write ptr handling, called from interrupt context */
-       u32 (*get_wptr)(struct amdgpu_device *adev);
-       void (*decode_iv)(struct amdgpu_device *adev,
+       u32 (*get_wptr)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
+       void (*decode_iv)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
                          struct amdgpu_iv_entry *entry);
-       void (*set_rptr)(struct amdgpu_device *adev);
+       void (*set_rptr)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
 };
 
-#define amdgpu_ih_get_wptr(adev) (adev)->irq.ih_funcs->get_wptr((adev))
-#define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv))
-#define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev))
+#define amdgpu_ih_get_wptr(adev, ih) (adev)->irq.ih_funcs->get_wptr((adev), (ih))
+#define amdgpu_ih_decode_iv(adev, iv) \
+       (adev)->irq.ih_funcs->decode_iv((adev), (ih), (iv))
+#define amdgpu_ih_set_rptr(adev, ih) (adev)->irq.ih_funcs->set_rptr((adev), (ih))
 
 int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
                        unsigned ring_size, bool use_bus_addr);
index b7968f4268625e99f7dc62fdddf3b44a896edae5..8bfb3dab46f711029018729db41bbf808c34261e 100644 (file)
@@ -148,6 +148,8 @@ static void amdgpu_irq_callback(struct amdgpu_device *adev,
        entry.iv_entry = (const uint32_t *)&ih->ring[ring_index];
        amdgpu_ih_decode_iv(adev, &entry);
 
+       trace_amdgpu_iv(ih - &adev->irq.ih, &entry);
+
        amdgpu_irq_dispatch(adev, &entry);
 }
 
@@ -174,6 +176,36 @@ irqreturn_t amdgpu_irq_handler(int irq, void *arg)
        return ret;
 }
 
+/**
+ * amdgpu_irq_handle_ih1 - kick of processing for IH1
+ *
+ * @work: work structure in struct amdgpu_irq
+ *
+ * Kick of processing IH ring 1.
+ */
+static void amdgpu_irq_handle_ih1(struct work_struct *work)
+{
+       struct amdgpu_device *adev = container_of(work, struct amdgpu_device,
+                                                 irq.ih1_work);
+
+       amdgpu_ih_process(adev, &adev->irq.ih1, amdgpu_irq_callback);
+}
+
+/**
+ * amdgpu_irq_handle_ih2 - kick of processing for IH2
+ *
+ * @work: work structure in struct amdgpu_irq
+ *
+ * Kick of processing IH ring 2.
+ */
+static void amdgpu_irq_handle_ih2(struct work_struct *work)
+{
+       struct amdgpu_device *adev = container_of(work, struct amdgpu_device,
+                                                 irq.ih2_work);
+
+       amdgpu_ih_process(adev, &adev->irq.ih2, amdgpu_irq_callback);
+}
+
 /**
  * amdgpu_msi_ok - check whether MSI functionality is enabled
  *
@@ -238,6 +270,9 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
                                amdgpu_hotplug_work_func);
        }
 
+       INIT_WORK(&adev->irq.ih1_work, amdgpu_irq_handle_ih1);
+       INIT_WORK(&adev->irq.ih2_work, amdgpu_irq_handle_ih2);
+
        adev->irq.installed = true;
        r = drm_irq_install(adev->ddev, adev->ddev->pdev->irq);
        if (r) {
@@ -367,8 +402,6 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev,
        bool handled = false;
        int r;
 
-       trace_amdgpu_iv(entry);
-
        if (client_id >= AMDGPU_IRQ_CLIENTID_MAX) {
                DRM_DEBUG("Invalid client_id in IV: %d\n", client_id);
 
index f6ce171cb8aa76a3ba38ba396ee0ad2d7b5b153d..c27decfda494d7f6caaa430225ec584f74b30240 100644 (file)
@@ -87,9 +87,11 @@ struct amdgpu_irq {
        /* status, etc. */
        bool                            msi_enabled; /* msi enabled */
 
-       /* interrupt ring */
-       struct amdgpu_ih_ring           ih;
-       const struct amdgpu_ih_funcs    *ih_funcs;
+       /* interrupt rings */
+       struct amdgpu_ih_ring           ih, ih1, ih2;
+       const struct amdgpu_ih_funcs    *ih_funcs;
+       struct work_struct              ih1_work, ih2_work;
+       struct amdgpu_irq_src           self_irq;
 
        /* gen irq stuff */
        struct irq_domain               *domain; /* GPU irq controller domain */
index 1f61ed95727ce3083faa9036c0d05f2d16641a5c..a7adb7b6bd98ab7b615a1d8c103551f2ffa46d1c 100644 (file)
@@ -626,11 +626,71 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev,
 }
 
 /**
- * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_pcie
+ * DOC: ppfeatures
+ *
+ * The amdgpu driver provides a sysfs API for adjusting what powerplay
+ * features to be enabled. The file ppfeatures is used for this. And
+ * this is only available for Vega10 and later dGPUs.
+ *
+ * Reading back the file will show you the followings:
+ * - Current ppfeature masks
+ * - List of the all supported powerplay features with their naming,
+ *   bitmasks and enablement status('Y'/'N' means "enabled"/"disabled").
+ *
+ * To manually enable or disable a specific feature, just set or clear
+ * the corresponding bit from original ppfeature masks and input the
+ * new ppfeature masks.
+ */
+static ssize_t amdgpu_set_ppfeature_status(struct device *dev,
+               struct device_attribute *attr,
+               const char *buf,
+               size_t count)
+{
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       struct amdgpu_device *adev = ddev->dev_private;
+       uint64_t featuremask;
+       int ret;
+
+       ret = kstrtou64(buf, 0, &featuremask);
+       if (ret)
+               return -EINVAL;
+
+       pr_debug("featuremask = 0x%llx\n", featuremask);
+
+       if (adev->powerplay.pp_funcs->set_ppfeature_status) {
+               ret = amdgpu_dpm_set_ppfeature_status(adev, featuremask);
+               if (ret)
+                       return -EINVAL;
+       }
+
+       return count;
+}
+
+static ssize_t amdgpu_get_ppfeature_status(struct device *dev,
+               struct device_attribute *attr,
+               char *buf)
+{
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       struct amdgpu_device *adev = ddev->dev_private;
+
+       if (adev->powerplay.pp_funcs->get_ppfeature_status)
+               return amdgpu_dpm_get_ppfeature_status(adev, buf);
+
+       return snprintf(buf, PAGE_SIZE, "\n");
+}
+
+/**
+ * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_dcefclk
+ * pp_dpm_pcie
  *
  * The amdgpu driver provides a sysfs API for adjusting what power levels
  * are enabled for a given power state.  The files pp_dpm_sclk, pp_dpm_mclk,
- * and pp_dpm_pcie are used for this.
+ * pp_dpm_socclk, pp_dpm_fclk, pp_dpm_dcefclk and pp_dpm_pcie are used for
+ * this.
+ *
+ * pp_dpm_socclk and pp_dpm_dcefclk interfaces are only available for
+ * Vega10 and later ASICs.
+ * pp_dpm_fclk interface is only available for Vega20 and later ASICs.
  *
  * Reading back the files will show you the available power levels within
  * the power state and the clock information for those levels.
@@ -640,6 +700,8 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev,
  * Secondly,Enter a new value for each level by inputing a string that
  * contains " echo xx xx xx > pp_dpm_sclk/mclk/pcie"
  * E.g., echo 4 5 6 to > pp_dpm_sclk will enable sclk levels 4, 5, and 6.
+ *
+ * NOTE: change to the dcefclk max dpm level is not supported now
  */
 
 static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev,
@@ -750,6 +812,114 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev,
        return count;
 }
 
+static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev,
+               struct device_attribute *attr,
+               char *buf)
+{
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       struct amdgpu_device *adev = ddev->dev_private;
+
+       if (adev->powerplay.pp_funcs->print_clock_levels)
+               return amdgpu_dpm_print_clock_levels(adev, PP_SOCCLK, buf);
+       else
+               return snprintf(buf, PAGE_SIZE, "\n");
+}
+
+static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev,
+               struct device_attribute *attr,
+               const char *buf,
+               size_t count)
+{
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       struct amdgpu_device *adev = ddev->dev_private;
+       int ret;
+       uint32_t mask = 0;
+
+       ret = amdgpu_read_mask(buf, count, &mask);
+       if (ret)
+               return ret;
+
+       if (adev->powerplay.pp_funcs->force_clock_level)
+               ret = amdgpu_dpm_force_clock_level(adev, PP_SOCCLK, mask);
+
+       if (ret)
+               return -EINVAL;
+
+       return count;
+}
+
+static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev,
+               struct device_attribute *attr,
+               char *buf)
+{
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       struct amdgpu_device *adev = ddev->dev_private;
+
+       if (adev->powerplay.pp_funcs->print_clock_levels)
+               return amdgpu_dpm_print_clock_levels(adev, PP_FCLK, buf);
+       else
+               return snprintf(buf, PAGE_SIZE, "\n");
+}
+
+static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev,
+               struct device_attribute *attr,
+               const char *buf,
+               size_t count)
+{
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       struct amdgpu_device *adev = ddev->dev_private;
+       int ret;
+       uint32_t mask = 0;
+
+       ret = amdgpu_read_mask(buf, count, &mask);
+       if (ret)
+               return ret;
+
+       if (adev->powerplay.pp_funcs->force_clock_level)
+               ret = amdgpu_dpm_force_clock_level(adev, PP_FCLK, mask);
+
+       if (ret)
+               return -EINVAL;
+
+       return count;
+}
+
+static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev,
+               struct device_attribute *attr,
+               char *buf)
+{
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       struct amdgpu_device *adev = ddev->dev_private;
+
+       if (adev->powerplay.pp_funcs->print_clock_levels)
+               return amdgpu_dpm_print_clock_levels(adev, PP_DCEFCLK, buf);
+       else
+               return snprintf(buf, PAGE_SIZE, "\n");
+}
+
+static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev,
+               struct device_attribute *attr,
+               const char *buf,
+               size_t count)
+{
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       struct amdgpu_device *adev = ddev->dev_private;
+       int ret;
+       uint32_t mask = 0;
+
+       ret = amdgpu_read_mask(buf, count, &mask);
+       if (ret)
+               return ret;
+
+       if (adev->powerplay.pp_funcs->force_clock_level)
+               ret = amdgpu_dpm_force_clock_level(adev, PP_DCEFCLK, mask);
+
+       if (ret)
+               return -EINVAL;
+
+       return count;
+}
+
 static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev,
                struct device_attribute *attr,
                char *buf)
@@ -990,6 +1160,31 @@ static ssize_t amdgpu_get_busy_percent(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%d\n", value);
 }
 
+/**
+ * DOC: pcie_bw
+ *
+ * The amdgpu driver provides a sysfs API for estimating how much data
+ * has been received and sent by the GPU in the last second through PCIe.
+ * The file pcie_bw is used for this.
+ * The Perf counters count the number of received and sent messages and return
+ * those values, as well as the maximum payload size of a PCIe packet (mps).
+ * Note that it is not possible to easily and quickly obtain the size of each
+ * packet transmitted, so we output the max payload size (mps) to allow for
+ * quick estimation of the PCIe bandwidth usage
+ */
+static ssize_t amdgpu_get_pcie_bw(struct device *dev,
+               struct device_attribute *attr,
+               char *buf)
+{
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       struct amdgpu_device *adev = ddev->dev_private;
+       uint64_t count0, count1;
+
+       amdgpu_asic_get_pcie_usage(adev, &count0, &count1);
+       return snprintf(buf, PAGE_SIZE, "%llu %llu %i\n",
+                       count0, count1, pcie_get_mps(adev->pdev));
+}
+
 static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state);
 static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR,
                   amdgpu_get_dpm_forced_performance_level,
@@ -1008,6 +1203,15 @@ static DEVICE_ATTR(pp_dpm_sclk, S_IRUGO | S_IWUSR,
 static DEVICE_ATTR(pp_dpm_mclk, S_IRUGO | S_IWUSR,
                amdgpu_get_pp_dpm_mclk,
                amdgpu_set_pp_dpm_mclk);
+static DEVICE_ATTR(pp_dpm_socclk, S_IRUGO | S_IWUSR,
+               amdgpu_get_pp_dpm_socclk,
+               amdgpu_set_pp_dpm_socclk);
+static DEVICE_ATTR(pp_dpm_fclk, S_IRUGO | S_IWUSR,
+               amdgpu_get_pp_dpm_fclk,
+               amdgpu_set_pp_dpm_fclk);
+static DEVICE_ATTR(pp_dpm_dcefclk, S_IRUGO | S_IWUSR,
+               amdgpu_get_pp_dpm_dcefclk,
+               amdgpu_set_pp_dpm_dcefclk);
 static DEVICE_ATTR(pp_dpm_pcie, S_IRUGO | S_IWUSR,
                amdgpu_get_pp_dpm_pcie,
                amdgpu_set_pp_dpm_pcie);
@@ -1025,6 +1229,10 @@ static DEVICE_ATTR(pp_od_clk_voltage, S_IRUGO | S_IWUSR,
                amdgpu_set_pp_od_clk_voltage);
 static DEVICE_ATTR(gpu_busy_percent, S_IRUGO,
                amdgpu_get_busy_percent, NULL);
+static DEVICE_ATTR(pcie_bw, S_IRUGO, amdgpu_get_pcie_bw, NULL);
+static DEVICE_ATTR(ppfeatures, S_IRUGO | S_IWUSR,
+               amdgpu_get_ppfeature_status,
+               amdgpu_set_ppfeature_status);
 
 static ssize_t amdgpu_hwmon_show_temp(struct device *dev,
                                      struct device_attribute *attr,
@@ -1516,6 +1724,75 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev,
        return count;
 }
 
+static ssize_t amdgpu_hwmon_show_sclk(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       struct amdgpu_device *adev = dev_get_drvdata(dev);
+       struct drm_device *ddev = adev->ddev;
+       uint32_t sclk;
+       int r, size = sizeof(sclk);
+
+       /* Can't get voltage when the card is off */
+       if  ((adev->flags & AMD_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+               return -EINVAL;
+
+       /* sanity check PP is enabled */
+       if (!(adev->powerplay.pp_funcs &&
+             adev->powerplay.pp_funcs->read_sensor))
+             return -EINVAL;
+
+       /* get the sclk */
+       r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK,
+                                  (void *)&sclk, &size);
+       if (r)
+               return r;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", sclk * 10 * 1000);
+}
+
+static ssize_t amdgpu_hwmon_show_sclk_label(struct device *dev,
+                                           struct device_attribute *attr,
+                                           char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "sclk\n");
+}
+
+static ssize_t amdgpu_hwmon_show_mclk(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       struct amdgpu_device *adev = dev_get_drvdata(dev);
+       struct drm_device *ddev = adev->ddev;
+       uint32_t mclk;
+       int r, size = sizeof(mclk);
+
+       /* Can't get voltage when the card is off */
+       if  ((adev->flags & AMD_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+               return -EINVAL;
+
+       /* sanity check PP is enabled */
+       if (!(adev->powerplay.pp_funcs &&
+             adev->powerplay.pp_funcs->read_sensor))
+             return -EINVAL;
+
+       /* get the sclk */
+       r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK,
+                                  (void *)&mclk, &size);
+       if (r)
+               return r;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", mclk * 10 * 1000);
+}
+
+static ssize_t amdgpu_hwmon_show_mclk_label(struct device *dev,
+                                           struct device_attribute *attr,
+                                           char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "mclk\n");
+}
 
 /**
  * DOC: hwmon
@@ -1532,6 +1809,10 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev,
  *
  * - GPU fan
  *
+ * - GPU gfx/compute engine clock
+ *
+ * - GPU memory clock (dGPU only)
+ *
  * hwmon interfaces for GPU temperature:
  *
  * - temp1_input: the on die GPU temperature in millidegrees Celsius
@@ -1576,6 +1857,12 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev,
  *
  * - fan[1-*]_enable: Enable or disable the sensors.1: Enable 0: Disable
  *
+ * hwmon interfaces for GPU clocks:
+ *
+ * - freq1_input: the gfx/compute clock in hertz
+ *
+ * - freq2_input: the memory clock in hertz
+ *
  * You can use hwmon tools like sensors to view this information on your system.
  *
  */
@@ -1600,6 +1887,10 @@ static SENSOR_DEVICE_ATTR(power1_average, S_IRUGO, amdgpu_hwmon_show_power_avg,
 static SENSOR_DEVICE_ATTR(power1_cap_max, S_IRUGO, amdgpu_hwmon_show_power_cap_max, NULL, 0);
 static SENSOR_DEVICE_ATTR(power1_cap_min, S_IRUGO, amdgpu_hwmon_show_power_cap_min, NULL, 0);
 static SENSOR_DEVICE_ATTR(power1_cap, S_IRUGO | S_IWUSR, amdgpu_hwmon_show_power_cap, amdgpu_hwmon_set_power_cap, 0);
+static SENSOR_DEVICE_ATTR(freq1_input, S_IRUGO, amdgpu_hwmon_show_sclk, NULL, 0);
+static SENSOR_DEVICE_ATTR(freq1_label, S_IRUGO, amdgpu_hwmon_show_sclk_label, NULL, 0);
+static SENSOR_DEVICE_ATTR(freq2_input, S_IRUGO, amdgpu_hwmon_show_mclk, NULL, 0);
+static SENSOR_DEVICE_ATTR(freq2_label, S_IRUGO, amdgpu_hwmon_show_mclk_label, NULL, 0);
 
 static struct attribute *hwmon_attributes[] = {
        &sensor_dev_attr_temp1_input.dev_attr.attr,
@@ -1622,6 +1913,10 @@ static struct attribute *hwmon_attributes[] = {
        &sensor_dev_attr_power1_cap_max.dev_attr.attr,
        &sensor_dev_attr_power1_cap_min.dev_attr.attr,
        &sensor_dev_attr_power1_cap.dev_attr.attr,
+       &sensor_dev_attr_freq1_input.dev_attr.attr,
+       &sensor_dev_attr_freq1_label.dev_attr.attr,
+       &sensor_dev_attr_freq2_input.dev_attr.attr,
+       &sensor_dev_attr_freq2_label.dev_attr.attr,
        NULL
 };
 
@@ -1686,7 +1981,8 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
                effective_mode &= ~S_IWUSR;
 
        if ((adev->flags & AMD_IS_APU) &&
-           (attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr ||
+           (attr == &sensor_dev_attr_power1_average.dev_attr.attr ||
+            attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr ||
             attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr||
             attr == &sensor_dev_attr_power1_cap.dev_attr.attr))
                return 0;
@@ -1712,6 +2008,12 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
             attr == &sensor_dev_attr_in1_label.dev_attr.attr))
                return 0;
 
+       /* no mclk on APUs */
+       if ((adev->flags & AMD_IS_APU) &&
+           (attr == &sensor_dev_attr_freq2_input.dev_attr.attr ||
+            attr == &sensor_dev_attr_freq2_label.dev_attr.attr))
+               return 0;
+
        return effective_mode;
 }
 
@@ -2008,6 +2310,7 @@ void amdgpu_pm_print_power_states(struct amdgpu_device *adev)
 
 int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
 {
+       struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
        int ret;
 
        if (adev->pm.sysfs_initialized)
@@ -2069,6 +2372,25 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
                DRM_ERROR("failed to create device file pp_dpm_mclk\n");
                return ret;
        }
+       if (adev->asic_type >= CHIP_VEGA10) {
+               ret = device_create_file(adev->dev, &dev_attr_pp_dpm_socclk);
+               if (ret) {
+                       DRM_ERROR("failed to create device file pp_dpm_socclk\n");
+                       return ret;
+               }
+               ret = device_create_file(adev->dev, &dev_attr_pp_dpm_dcefclk);
+               if (ret) {
+                       DRM_ERROR("failed to create device file pp_dpm_dcefclk\n");
+                       return ret;
+               }
+       }
+       if (adev->asic_type >= CHIP_VEGA20) {
+               ret = device_create_file(adev->dev, &dev_attr_pp_dpm_fclk);
+               if (ret) {
+                       DRM_ERROR("failed to create device file pp_dpm_fclk\n");
+                       return ret;
+               }
+       }
        ret = device_create_file(adev->dev, &dev_attr_pp_dpm_pcie);
        if (ret) {
                DRM_ERROR("failed to create device file pp_dpm_pcie\n");
@@ -2091,12 +2413,14 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
                                "pp_power_profile_mode\n");
                return ret;
        }
-       ret = device_create_file(adev->dev,
-                       &dev_attr_pp_od_clk_voltage);
-       if (ret) {
-               DRM_ERROR("failed to create device file "
-                               "pp_od_clk_voltage\n");
-               return ret;
+       if (hwmgr->od_enabled) {
+               ret = device_create_file(adev->dev,
+                               &dev_attr_pp_od_clk_voltage);
+               if (ret) {
+                       DRM_ERROR("failed to create device file "
+                                       "pp_od_clk_voltage\n");
+                       return ret;
+               }
        }
        ret = device_create_file(adev->dev,
                        &dev_attr_gpu_busy_percent);
@@ -2105,12 +2429,31 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
                                "gpu_busy_level\n");
                return ret;
        }
+       /* PCIe Perf counters won't work on APU nodes */
+       if (!(adev->flags & AMD_IS_APU)) {
+               ret = device_create_file(adev->dev, &dev_attr_pcie_bw);
+               if (ret) {
+                       DRM_ERROR("failed to create device file pcie_bw\n");
+                       return ret;
+               }
+       }
        ret = amdgpu_debugfs_pm_init(adev);
        if (ret) {
                DRM_ERROR("Failed to register debugfs file for dpm!\n");
                return ret;
        }
 
+       if ((adev->asic_type >= CHIP_VEGA10) &&
+           !(adev->flags & AMD_IS_APU)) {
+               ret = device_create_file(adev->dev,
+                               &dev_attr_ppfeatures);
+               if (ret) {
+                       DRM_ERROR("failed to create device file "
+                                       "ppfeatures\n");
+                       return ret;
+               }
+       }
+
        adev->pm.sysfs_initialized = true;
 
        return 0;
@@ -2118,6 +2461,8 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
 
 void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
 {
+       struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
+
        if (adev->pm.dpm_enabled == 0)
                return;
 
@@ -2133,14 +2478,26 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
 
        device_remove_file(adev->dev, &dev_attr_pp_dpm_sclk);
        device_remove_file(adev->dev, &dev_attr_pp_dpm_mclk);
+       if (adev->asic_type >= CHIP_VEGA10) {
+               device_remove_file(adev->dev, &dev_attr_pp_dpm_socclk);
+               device_remove_file(adev->dev, &dev_attr_pp_dpm_dcefclk);
+       }
        device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie);
+       if (adev->asic_type >= CHIP_VEGA20)
+               device_remove_file(adev->dev, &dev_attr_pp_dpm_fclk);
        device_remove_file(adev->dev, &dev_attr_pp_sclk_od);
        device_remove_file(adev->dev, &dev_attr_pp_mclk_od);
        device_remove_file(adev->dev,
                        &dev_attr_pp_power_profile_mode);
-       device_remove_file(adev->dev,
-                       &dev_attr_pp_od_clk_voltage);
+       if (hwmgr->od_enabled)
+               device_remove_file(adev->dev,
+                               &dev_attr_pp_od_clk_voltage);
        device_remove_file(adev->dev, &dev_attr_gpu_busy_percent);
+       if (!(adev->flags & AMD_IS_APU))
+               device_remove_file(adev->dev, &dev_attr_pcie_bw);
+       if ((adev->asic_type >= CHIP_VEGA10) &&
+           !(adev->flags & AMD_IS_APU))
+               device_remove_file(adev->dev, &dev_attr_ppfeatures);
 }
 
 void amdgpu_pm_compute_clocks(struct amdgpu_device *adev)
index 8fab0d637ee51f96fa31cb5d81178d60f52db458..d87f165e3a23dd2de261c4489d229134962e756d 100644 (file)
@@ -67,9 +67,6 @@ static int psp_sw_init(void *handle)
 
        psp->adev = adev;
 
-       if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
-               return 0;
-
        ret = psp_init_microcode(psp);
        if (ret) {
                DRM_ERROR("Failed to load psp firmware!\n");
@@ -83,9 +80,6 @@ static int psp_sw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
-               return 0;
-
        release_firmware(adev->psp.sos_fw);
        adev->psp.sos_fw = NULL;
        release_firmware(adev->psp.asd_fw);
@@ -140,13 +134,24 @@ psp_cmd_submit_buf(struct psp_context *psp,
        while (*((unsigned int *)psp->fence_buf) != index)
                msleep(1);
 
-       /* the status field must be 0 after FW is loaded */
-       if (ucode && psp->cmd_buf_mem->resp.status) {
-               DRM_ERROR("failed loading with status (%d) and ucode id (%d)\n",
-                         psp->cmd_buf_mem->resp.status, ucode->ucode_id);
-               return -EINVAL;
+       /* In some cases, psp response status is not 0 even there is no
+        * problem while the command is submitted. Some version of PSP FW
+        * doesn't write 0 to that field.
+        * So here we would like to only print a warning instead of an error
+        * during psp initialization to avoid breaking hw_init and it doesn't
+        * return -EINVAL.
+        */
+       if (psp->cmd_buf_mem->resp.status) {
+               if (ucode)
+                       DRM_WARN("failed to load ucode id (%d) ",
+                                 ucode->ucode_id);
+               DRM_WARN("psp command failed and response status is (%d)\n",
+                         psp->cmd_buf_mem->resp.status);
        }
 
+       /* get xGMI session id from response buffer */
+       cmd->resp.session_id = psp->cmd_buf_mem->resp.session_id;
+
        if (ucode) {
                ucode->tmr_mc_addr_lo = psp->cmd_buf_mem->resp.fw_addr_lo;
                ucode->tmr_mc_addr_hi = psp->cmd_buf_mem->resp.fw_addr_hi;
@@ -495,6 +500,98 @@ static int psp_hw_start(struct psp_context *psp)
        return 0;
 }
 
+static int psp_get_fw_type(struct amdgpu_firmware_info *ucode,
+                          enum psp_gfx_fw_type *type)
+{
+       switch (ucode->ucode_id) {
+       case AMDGPU_UCODE_ID_SDMA0:
+               *type = GFX_FW_TYPE_SDMA0;
+               break;
+       case AMDGPU_UCODE_ID_SDMA1:
+               *type = GFX_FW_TYPE_SDMA1;
+               break;
+       case AMDGPU_UCODE_ID_CP_CE:
+               *type = GFX_FW_TYPE_CP_CE;
+               break;
+       case AMDGPU_UCODE_ID_CP_PFP:
+               *type = GFX_FW_TYPE_CP_PFP;
+               break;
+       case AMDGPU_UCODE_ID_CP_ME:
+               *type = GFX_FW_TYPE_CP_ME;
+               break;
+       case AMDGPU_UCODE_ID_CP_MEC1:
+               *type = GFX_FW_TYPE_CP_MEC;
+               break;
+       case AMDGPU_UCODE_ID_CP_MEC1_JT:
+               *type = GFX_FW_TYPE_CP_MEC_ME1;
+               break;
+       case AMDGPU_UCODE_ID_CP_MEC2:
+               *type = GFX_FW_TYPE_CP_MEC;
+               break;
+       case AMDGPU_UCODE_ID_CP_MEC2_JT:
+               *type = GFX_FW_TYPE_CP_MEC_ME2;
+               break;
+       case AMDGPU_UCODE_ID_RLC_G:
+               *type = GFX_FW_TYPE_RLC_G;
+               break;
+       case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL:
+               *type = GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_CNTL;
+               break;
+       case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM:
+               *type = GFX_FW_TYPE_RLC_RESTORE_LIST_GPM_MEM;
+               break;
+       case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM:
+               *type = GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_MEM;
+               break;
+       case AMDGPU_UCODE_ID_SMC:
+               *type = GFX_FW_TYPE_SMU;
+               break;
+       case AMDGPU_UCODE_ID_UVD:
+               *type = GFX_FW_TYPE_UVD;
+               break;
+       case AMDGPU_UCODE_ID_UVD1:
+               *type = GFX_FW_TYPE_UVD1;
+               break;
+       case AMDGPU_UCODE_ID_VCE:
+               *type = GFX_FW_TYPE_VCE;
+               break;
+       case AMDGPU_UCODE_ID_VCN:
+               *type = GFX_FW_TYPE_VCN;
+               break;
+       case AMDGPU_UCODE_ID_DMCU_ERAM:
+               *type = GFX_FW_TYPE_DMCU_ERAM;
+               break;
+       case AMDGPU_UCODE_ID_DMCU_INTV:
+               *type = GFX_FW_TYPE_DMCU_ISR;
+               break;
+       case AMDGPU_UCODE_ID_MAXIMUM:
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int psp_prep_load_ip_fw_cmd_buf(struct amdgpu_firmware_info *ucode,
+                                      struct psp_gfx_cmd_resp *cmd)
+{
+       int ret;
+       uint64_t fw_mem_mc_addr = ucode->mc_addr;
+
+       memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
+
+       cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW;
+       cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr);
+       cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr);
+       cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size;
+
+       ret = psp_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type);
+       if (ret)
+               DRM_ERROR("Unknown firmware type\n");
+
+       return ret;
+}
+
 static int psp_np_fw_load(struct psp_context *psp)
 {
        int i, ret;
@@ -516,7 +613,7 @@ static int psp_np_fw_load(struct psp_context *psp)
                        /*skip ucode loading in SRIOV VF */
                        continue;
 
-               ret = psp_prep_cmd_buf(ucode, psp->cmd);
+               ret = psp_prep_load_ip_fw_cmd_buf(ucode, psp->cmd);
                if (ret)
                        return ret;
 
@@ -541,7 +638,7 @@ static int psp_load_fw(struct amdgpu_device *adev)
        struct psp_context *psp = &adev->psp;
 
        if (amdgpu_sriov_vf(adev) && adev->in_gpu_reset) {
-               psp_ring_destroy(psp, PSP_RING_TYPE__KM);
+               psp_ring_stop(psp, PSP_RING_TYPE__KM); /* should not destroy ring, only stop */
                goto skip_memalloc;
        }
 
@@ -618,10 +715,6 @@ static int psp_hw_init(void *handle)
        int ret;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-
-       if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
-               return 0;
-
        mutex_lock(&adev->firmware.mutex);
        /*
         * This sequence is just used on hw_init only once, no need on
@@ -651,9 +744,6 @@ static int psp_hw_fini(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        struct psp_context *psp = &adev->psp;
 
-       if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
-               return 0;
-
        if (adev->gmc.xgmi.num_physical_nodes > 1 &&
            psp->xgmi_context.initialized == 1)
                 psp_xgmi_terminate(psp);
@@ -682,9 +772,6 @@ static int psp_suspend(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        struct psp_context *psp = &adev->psp;
 
-       if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
-               return 0;
-
        if (adev->gmc.xgmi.num_physical_nodes > 1 &&
            psp->xgmi_context.initialized == 1) {
                ret = psp_xgmi_terminate(psp);
@@ -709,9 +796,6 @@ static int psp_resume(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        struct psp_context *psp = &adev->psp;
 
-       if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
-               return 0;
-
        DRM_INFO("PSP is resuming...\n");
 
        mutex_lock(&adev->firmware.mutex);
@@ -747,11 +831,6 @@ static bool psp_check_fw_loading_status(struct amdgpu_device *adev,
 {
        struct amdgpu_firmware_info *ucode = NULL;
 
-       if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
-               DRM_INFO("firmware is not loaded by PSP\n");
-               return true;
-       }
-
        if (!adev->firmware.fw_size)
                return false;
 
index 3ee573b4016e2118b208ec0fb466a63ed9722eb1..2ef98cc755d6e0438c551803a14f28570b827333 100644 (file)
@@ -65,8 +65,6 @@ struct psp_funcs
        int (*init_microcode)(struct psp_context *psp);
        int (*bootloader_load_sysdrv)(struct psp_context *psp);
        int (*bootloader_load_sos)(struct psp_context *psp);
-       int (*prep_cmd_buf)(struct amdgpu_firmware_info *ucode,
-                           struct psp_gfx_cmd_resp *cmd);
        int (*ring_init)(struct psp_context *psp, enum psp_ring_type ring_type);
        int (*ring_create)(struct psp_context *psp,
                           enum psp_ring_type ring_type);
@@ -176,7 +174,6 @@ struct psp_xgmi_topology_info {
        struct psp_xgmi_node_info       nodes[AMDGPU_XGMI_MAX_CONNECTED_NODES];
 };
 
-#define psp_prep_cmd_buf(ucode, type) (psp)->funcs->prep_cmd_buf((ucode), (type))
 #define psp_ring_init(psp, type) (psp)->funcs->ring_init((psp), (type))
 #define psp_ring_create(psp, type) (psp)->funcs->ring_create((psp), (type))
 #define psp_ring_stop(psp, type) (psp)->funcs->ring_stop((psp), (type))
index d87e828a084b959ee6651ad080c698eb7f2b3bca..d7fae2676269478b66fb0fd45dfd450ed37de86f 100644 (file)
@@ -131,7 +131,7 @@ struct amdgpu_ring_funcs {
        void (*emit_ib)(struct amdgpu_ring *ring,
                        struct amdgpu_job *job,
                        struct amdgpu_ib *ib,
-                       bool ctx_switch);
+                       uint32_t flags);
        void (*emit_fence)(struct amdgpu_ring *ring, uint64_t addr,
                           uint64_t seq, unsigned flags);
        void (*emit_pipeline_sync)(struct amdgpu_ring *ring);
@@ -229,7 +229,7 @@ struct amdgpu_ring {
 #define amdgpu_ring_get_rptr(r) (r)->funcs->get_rptr((r))
 #define amdgpu_ring_get_wptr(r) (r)->funcs->get_wptr((r))
 #define amdgpu_ring_set_wptr(r) (r)->funcs->set_wptr((r))
-#define amdgpu_ring_emit_ib(r, job, ib, c) ((r)->funcs->emit_ib((r), (job), (ib), (c)))
+#define amdgpu_ring_emit_ib(r, job, ib, flags) ((r)->funcs->emit_ib((r), (job), (ib), (flags)))
 #define amdgpu_ring_emit_pipeline_sync(r) (r)->funcs->emit_pipeline_sync((r))
 #define amdgpu_ring_emit_vm_flush(r, vmid, addr) (r)->funcs->emit_vm_flush((r), (vmid), (addr))
 #define amdgpu_ring_emit_fence(r, addr, seq, flags) (r)->funcs->emit_fence((r), (addr), (seq), (flags))
index 12f2bf97611fb9c6dec30f8569c3f11caebffc7a..bfaf5c6323becc187c4b174207bbeb07abad6e8e 100644 (file)
@@ -388,7 +388,7 @@ void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager,
                           soffset, eoffset, eoffset - soffset);
 
                if (i->fence)
-                       seq_printf(m, " protected by 0x%08x on context %llu",
+                       seq_printf(m, " protected by 0x%016llx on context %llu",
                                   i->fence->seqno, i->fence->context);
 
                seq_printf(m, "\n");
index 626abca770a0367b853000358b580fdc7c82ff22..d3ca2424b5fe9a153a67eb6d77d1f59bcb7ba729 100644 (file)
@@ -76,9 +76,10 @@ TRACE_EVENT(amdgpu_mm_wreg,
 );
 
 TRACE_EVENT(amdgpu_iv,
-           TP_PROTO(struct amdgpu_iv_entry *iv),
-           TP_ARGS(iv),
+           TP_PROTO(unsigned ih, struct amdgpu_iv_entry *iv),
+           TP_ARGS(ih, iv),
            TP_STRUCT__entry(
+                            __field(unsigned, ih)
                             __field(unsigned, client_id)
                             __field(unsigned, src_id)
                             __field(unsigned, ring_id)
@@ -90,6 +91,7 @@ TRACE_EVENT(amdgpu_iv,
                             __array(unsigned, src_data, 4)
                            ),
            TP_fast_assign(
+                          __entry->ih = ih;
                           __entry->client_id = iv->client_id;
                           __entry->src_id = iv->src_id;
                           __entry->ring_id = iv->ring_id;
@@ -103,8 +105,9 @@ TRACE_EVENT(amdgpu_iv,
                           __entry->src_data[2] = iv->src_data[2];
                           __entry->src_data[3] = iv->src_data[3];
                           ),
-           TP_printk("client_id:%u src_id:%u ring:%u vmid:%u timestamp: %llu pasid:%u src_data: %08x %08x %08x %08x",
-                     __entry->client_id, __entry->src_id,
+           TP_printk("ih:%u client_id:%u src_id:%u ring:%u vmid:%u "
+                     "timestamp: %llu pasid:%u src_data: %08x %08x %08x %08x",
+                     __entry->ih, __entry->client_id, __entry->src_id,
                      __entry->ring_id, __entry->vmid,
                      __entry->timestamp, __entry->pasid,
                      __entry->src_data[0], __entry->src_data[1],
index c91ec3101d00b5d06e48db30c71b3cf938d95b63..b852abb9db0f21b3e56400eb4facbf7eb85e9653 100644 (file)
@@ -1546,7 +1546,8 @@ static struct ttm_bo_driver amdgpu_bo_driver = {
        .io_mem_reserve = &amdgpu_ttm_io_mem_reserve,
        .io_mem_free = &amdgpu_ttm_io_mem_free,
        .io_mem_pfn = amdgpu_ttm_io_mem_pfn,
-       .access_memory = &amdgpu_ttm_access_memory
+       .access_memory = &amdgpu_ttm_access_memory,
+       .del_from_lru_notify = &amdgpu_vm_del_from_lru_notify
 };
 
 /*
index 98a1b2ce2b9d38cec778dc2c9a8097661eca27b0..c021b114c8a44ec04c6ca3bccc4479c141218232 100644 (file)
@@ -1035,7 +1035,7 @@ out:
 void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring,
                                struct amdgpu_job *job,
                                struct amdgpu_ib *ib,
-                               bool ctx_switch)
+                               uint32_t flags)
 {
        amdgpu_ring_write(ring, VCE_CMD_IB);
        amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
index 50293652af148cc3c8fa2d04d8b7723e8b744e32..30ea54dd91173b57dbf48e9a9d12915f752d0e13 100644 (file)
@@ -66,7 +66,7 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp);
 int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx);
 int amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser *p, uint32_t ib_idx);
 void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_job *job,
-                               struct amdgpu_ib *ib, bool ctx_switch);
+                               struct amdgpu_ib *ib, uint32_t flags);
 void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
                                unsigned flags);
 int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring);
index e73d152659a2f236f83b38996290facc7981581c..0bc6f553dc081700e58076685aa3314d95948680 100644 (file)
@@ -623,6 +623,28 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
        list_add(&entry->tv.head, validated);
 }
 
+void amdgpu_vm_del_from_lru_notify(struct ttm_buffer_object *bo)
+{
+       struct amdgpu_bo *abo;
+       struct amdgpu_vm_bo_base *bo_base;
+
+       if (!amdgpu_bo_is_amdgpu_bo(bo))
+               return;
+
+       if (bo->mem.placement & TTM_PL_FLAG_NO_EVICT)
+               return;
+
+       abo = ttm_to_amdgpu_bo(bo);
+       if (!abo->parent)
+               return;
+       for (bo_base = abo->vm_bo; bo_base; bo_base = bo_base->next) {
+               struct amdgpu_vm *vm = bo_base->vm;
+
+               if (abo->tbo.resv == vm->root.base.bo->tbo.resv)
+                       vm->bulk_moveable = false;
+       }
+
+}
 /**
  * amdgpu_vm_move_to_lru_tail - move all BOs to the end of LRU
  *
@@ -799,9 +821,16 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
                addr += ats_entries * 8;
        }
 
-       if (entries)
+       if (entries) {
+               uint64_t value = 0;
+
+               /* Workaround for fault priority problem on GMC9 */
+               if (level == AMDGPU_VM_PTB && adev->asic_type >= CHIP_VEGA10)
+                       value = AMDGPU_PTE_EXECUTABLE;
+
                amdgpu_vm_set_pte_pde(adev, &job->ibs[0], addr, 0,
-                                     entries, 0, 0);
+                                     entries, 0, value);
+       }
 
        amdgpu_ring_pad_ib(ring, &job->ibs[0]);
 
@@ -847,9 +876,6 @@ static void amdgpu_vm_bo_param(struct amdgpu_device *adev, struct amdgpu_vm *vm,
        bp->size = amdgpu_vm_bo_size(adev, level);
        bp->byte_align = AMDGPU_GPU_PAGE_SIZE;
        bp->domain = AMDGPU_GEM_DOMAIN_VRAM;
-       if (bp->size <= PAGE_SIZE && adev->asic_type >= CHIP_VEGA10 &&
-           adev->flags & AMD_IS_APU)
-               bp->domain |= AMDGPU_GEM_DOMAIN_GTT;
        bp->domain = amdgpu_bo_get_preferred_pin_domain(adev, bp->domain);
        bp->flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
                AMDGPU_GEM_CREATE_CPU_GTT_USWC;
@@ -1506,20 +1532,27 @@ error:
 }
 
 /**
- * amdgpu_vm_update_huge - figure out parameters for PTE updates
+ * amdgpu_vm_update_flags - figure out flags for PTE updates
  *
  * Make sure to set the right flags for the PTEs at the desired level.
  */
-static void amdgpu_vm_update_huge(struct amdgpu_pte_update_params *params,
-                                 struct amdgpu_bo *bo, unsigned level,
-                                 uint64_t pe, uint64_t addr,
-                                 unsigned count, uint32_t incr,
-                                 uint64_t flags)
+static void amdgpu_vm_update_flags(struct amdgpu_pte_update_params *params,
+                                  struct amdgpu_bo *bo, unsigned level,
+                                  uint64_t pe, uint64_t addr,
+                                  unsigned count, uint32_t incr,
+                                  uint64_t flags)
 
 {
        if (level != AMDGPU_VM_PTB) {
                flags |= AMDGPU_PDE_PTE;
                amdgpu_gmc_get_vm_pde(params->adev, level, &addr, &flags);
+
+       } else if (params->adev->asic_type >= CHIP_VEGA10 &&
+                  !(flags & AMDGPU_PTE_VALID) &&
+                  !(flags & AMDGPU_PTE_PRT)) {
+
+               /* Workaround for fault priority problem on GMC9 */
+               flags |= AMDGPU_PTE_EXECUTABLE;
        }
 
        amdgpu_vm_update_func(params, bo, pe, addr, count, incr, flags);
@@ -1676,9 +1709,9 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
                        uint64_t upd_end = min(entry_end, frag_end);
                        unsigned nptes = (upd_end - frag_start) >> shift;
 
-                       amdgpu_vm_update_huge(params, pt, cursor.level,
-                                             pe_start, dst, nptes, incr,
-                                             flags | AMDGPU_PTE_FRAG(frag));
+                       amdgpu_vm_update_flags(params, pt, cursor.level,
+                                              pe_start, dst, nptes, incr,
+                                              flags | AMDGPU_PTE_FRAG(frag));
 
                        pe_start += nptes * 8;
                        dst += (uint64_t)nptes * AMDGPU_GPU_PAGE_SIZE << shift;
@@ -3006,7 +3039,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
        }
        DRM_DEBUG_DRIVER("VM update mode is %s\n",
                         vm->use_cpu_for_update ? "CPU" : "SDMA");
-       WARN_ONCE((vm->use_cpu_for_update & !amdgpu_gmc_vram_full_visible(&adev->gmc)),
+       WARN_ONCE((vm->use_cpu_for_update && !amdgpu_gmc_vram_full_visible(&adev->gmc)),
                  "CPU update of VM recommended only for large BAR system\n");
        vm->last_update = NULL;
 
@@ -3136,7 +3169,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, uns
        vm->pte_support_ats = pte_support_ats;
        DRM_DEBUG_DRIVER("VM update mode is %s\n",
                         vm->use_cpu_for_update ? "CPU" : "SDMA");
-       WARN_ONCE((vm->use_cpu_for_update & !amdgpu_gmc_vram_full_visible(&adev->gmc)),
+       WARN_ONCE((vm->use_cpu_for_update && !amdgpu_gmc_vram_full_visible(&adev->gmc)),
                  "CPU update of VM recommended only for large BAR system\n");
 
        if (vm->pasid) {
index e8dcfd59fc93353468aaada4c42e6ab4ca6d85a5..81ff8177f09208183c96818bfaff38d81b0af67b 100644 (file)
@@ -363,4 +363,6 @@ int amdgpu_vm_add_fault(struct amdgpu_retryfault_hashtable *fault_hash, u64 key)
 
 void amdgpu_vm_clear_fault(struct amdgpu_retryfault_hashtable *fault_hash, u64 key);
 
+void amdgpu_vm_del_from_lru_notify(struct ttm_buffer_object *bo);
+
 #endif
index 8a8bc60cb6b4d482e216a0a32522cf0c1f47d881..dac187454b3359cd38508f88319b25ebe8f21d45 100644 (file)
@@ -40,26 +40,40 @@ void *amdgpu_xgmi_hive_try_lock(struct amdgpu_hive_info *hive)
        return &hive->device_list;
 }
 
-struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev)
+struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev, int lock)
 {
        int i;
        struct amdgpu_hive_info *tmp;
 
        if (!adev->gmc.xgmi.hive_id)
                return NULL;
+
+       mutex_lock(&xgmi_mutex);
+
        for (i = 0 ; i < hive_count; ++i) {
                tmp = &xgmi_hives[i];
-               if (tmp->hive_id == adev->gmc.xgmi.hive_id)
+               if (tmp->hive_id == adev->gmc.xgmi.hive_id) {
+                       if (lock)
+                               mutex_lock(&tmp->hive_lock);
+                       mutex_unlock(&xgmi_mutex);
                        return tmp;
+               }
        }
-       if (i >= AMDGPU_MAX_XGMI_HIVE)
+       if (i >= AMDGPU_MAX_XGMI_HIVE) {
+               mutex_unlock(&xgmi_mutex);
                return NULL;
+       }
 
        /* initialize new hive if not exist */
        tmp = &xgmi_hives[hive_count++];
        tmp->hive_id = adev->gmc.xgmi.hive_id;
        INIT_LIST_HEAD(&tmp->device_list);
        mutex_init(&tmp->hive_lock);
+       mutex_init(&tmp->reset_lock);
+       if (lock)
+               mutex_lock(&tmp->hive_lock);
+
+       mutex_unlock(&xgmi_mutex);
 
        return tmp;
 }
@@ -111,10 +125,14 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev)
                return ret;
        }
 
-       mutex_lock(&xgmi_mutex);
-       hive = amdgpu_get_xgmi_hive(adev);
-       if (!hive)
+       hive = amdgpu_get_xgmi_hive(adev, 1);
+       if (!hive) {
+               ret = -EINVAL;
+               dev_err(adev->dev,
+                       "XGMI: node 0x%llx, can not matech hive 0x%llx in the hive list.\n",
+                       adev->gmc.xgmi.node_id, adev->gmc.xgmi.hive_id);
                goto exit;
+       }
 
        hive_topology = &hive->topology_info;
 
@@ -142,8 +160,8 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev)
                        break;
        }
 
+       mutex_unlock(&hive->hive_lock);
 exit:
-       mutex_unlock(&xgmi_mutex);
        return ret;
 }
 
@@ -154,15 +172,14 @@ void amdgpu_xgmi_remove_device(struct amdgpu_device *adev)
        if (!adev->gmc.xgmi.supported)
                return;
 
-       mutex_lock(&xgmi_mutex);
-
-       hive = amdgpu_get_xgmi_hive(adev);
+       hive = amdgpu_get_xgmi_hive(adev, 1);
        if (!hive)
-               goto exit;
+               return;
 
-       if (!(hive->number_devices--))
+       if (!(hive->number_devices--)) {
                mutex_destroy(&hive->hive_lock);
-
-exit:
-       mutex_unlock(&xgmi_mutex);
+               mutex_destroy(&hive->reset_lock);
+       } else {
+               mutex_unlock(&hive->hive_lock);
+       }
 }
index 6151eb9c8ad30bbcaf54eacbcd67b649a7b4fa5a..14bc606641590d5845f4dec5c4dcc453b658862b 100644 (file)
@@ -29,10 +29,11 @@ struct amdgpu_hive_info {
        struct list_head        device_list;
        struct psp_xgmi_topology_info   topology_info;
        int number_devices;
-       struct mutex hive_lock;
+       struct mutex hive_lock,
+                    reset_lock;
 };
 
-struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev);
+struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev, int lock);
 int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_device *adev);
 int amdgpu_xgmi_add_device(struct amdgpu_device *adev);
 void amdgpu_xgmi_remove_device(struct amdgpu_device *adev);
index e9934de1b9cf8127eb2b770e4301d6ee90c98223..dd30f4e61a8cd97c73c06dc756177dbc33a79d52 100644 (file)
@@ -27,6 +27,8 @@
 #include <linux/slab.h>
 #include <asm/unaligned.h>
 
+#include <drm/drm_util.h>
+
 #define ATOM_DEBUG
 
 #include "atom.h"
diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
deleted file mode 100644 (file)
index 86e14c7..0000000
+++ /dev/null
@@ -1,6844 +0,0 @@
-/*
- * Copyright 2013 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 <linux/firmware.h>
-#include <drm/drmP.h>
-#include "amdgpu.h"
-#include "amdgpu_pm.h"
-#include "amdgpu_ucode.h"
-#include "cikd.h"
-#include "amdgpu_dpm.h"
-#include "ci_dpm.h"
-#include "gfx_v7_0.h"
-#include "atom.h"
-#include "amd_pcie.h"
-#include <linux/seq_file.h>
-
-#include "smu/smu_7_0_1_d.h"
-#include "smu/smu_7_0_1_sh_mask.h"
-
-#include "dce/dce_8_0_d.h"
-#include "dce/dce_8_0_sh_mask.h"
-
-#include "bif/bif_4_1_d.h"
-#include "bif/bif_4_1_sh_mask.h"
-
-#include "gca/gfx_7_2_d.h"
-#include "gca/gfx_7_2_sh_mask.h"
-
-#include "gmc/gmc_7_1_d.h"
-#include "gmc/gmc_7_1_sh_mask.h"
-
-MODULE_FIRMWARE("amdgpu/bonaire_smc.bin");
-MODULE_FIRMWARE("amdgpu/bonaire_k_smc.bin");
-MODULE_FIRMWARE("amdgpu/hawaii_smc.bin");
-MODULE_FIRMWARE("amdgpu/hawaii_k_smc.bin");
-
-#define MC_CG_ARB_FREQ_F0           0x0a
-#define MC_CG_ARB_FREQ_F1           0x0b
-#define MC_CG_ARB_FREQ_F2           0x0c
-#define MC_CG_ARB_FREQ_F3           0x0d
-
-#define SMC_RAM_END 0x40000
-
-#define VOLTAGE_SCALE               4
-#define VOLTAGE_VID_OFFSET_SCALE1    625
-#define VOLTAGE_VID_OFFSET_SCALE2    100
-
-static const struct amd_pm_funcs ci_dpm_funcs;
-
-static const struct ci_pt_defaults defaults_hawaii_xt =
-{
-       1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0xB0000,
-       { 0x2E,  0x00,  0x00,  0x88,  0x00,  0x00,  0x72,  0x60,  0x51,  0xA7,  0x79,  0x6B,  0x90,  0xBD,  0x79  },
-       { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 }
-};
-
-static const struct ci_pt_defaults defaults_hawaii_pro =
-{
-       1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0x65062,
-       { 0x2E,  0x00,  0x00,  0x88,  0x00,  0x00,  0x72,  0x60,  0x51,  0xA7,  0x79,  0x6B,  0x90,  0xBD,  0x79  },
-       { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 }
-};
-
-static const struct ci_pt_defaults defaults_bonaire_xt =
-{
-       1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000,
-       { 0x79,  0x253, 0x25D, 0xAE,  0x72,  0x80,  0x83,  0x86,  0x6F,  0xC8,  0xC9,  0xC9,  0x2F,  0x4D,  0x61  },
-       { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 }
-};
-
-#if 0
-static const struct ci_pt_defaults defaults_bonaire_pro =
-{
-       1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x65062,
-       { 0x8C,  0x23F, 0x244, 0xA6,  0x83,  0x85,  0x86,  0x86,  0x83,  0xDB,  0xDB,  0xDA,  0x67,  0x60,  0x5F  },
-       { 0x187, 0x193, 0x193, 0x1C7, 0x1D1, 0x1D1, 0x210, 0x219, 0x219, 0x266, 0x26C, 0x26C, 0x2C9, 0x2CB, 0x2CB }
-};
-#endif
-
-static const struct ci_pt_defaults defaults_saturn_xt =
-{
-       1, 0xF, 0xFD, 0x19, 5, 55, 0, 0x70000,
-       { 0x8C,  0x247, 0x249, 0xA6,  0x80,  0x81,  0x8B,  0x89,  0x86,  0xC9,  0xCA,  0xC9,  0x4D,  0x4D,  0x4D  },
-       { 0x187, 0x187, 0x187, 0x1C7, 0x1C7, 0x1C7, 0x210, 0x210, 0x210, 0x266, 0x266, 0x266, 0x2C9, 0x2C9, 0x2C9 }
-};
-
-#if 0
-static const struct ci_pt_defaults defaults_saturn_pro =
-{
-       1, 0xF, 0xFD, 0x19, 5, 55, 0, 0x30000,
-       { 0x96,  0x21D, 0x23B, 0xA1,  0x85,  0x87,  0x83,  0x84,  0x81,  0xE6,  0xE6,  0xE6,  0x71,  0x6A,  0x6A  },
-       { 0x193, 0x19E, 0x19E, 0x1D2, 0x1DC, 0x1DC, 0x21A, 0x223, 0x223, 0x26E, 0x27E, 0x274, 0x2CF, 0x2D2, 0x2D2 }
-};
-#endif
-
-static const struct ci_pt_config_reg didt_config_ci[] =
-{
-       { 0x10, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x10, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x10, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x10, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x11, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x11, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x11, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x11, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x12, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x12, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x12, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x12, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x2, 0x00003fff, 0, 0x4, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x2, 0x03ff0000, 16, 0x80, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x2, 0x78000000, 27, 0x3, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x1, 0x0000ffff, 0, 0x3FFF, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x1, 0xffff0000, 16, 0x3FFF, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x0, 0x00000001, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x30, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x30, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x30, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x30, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x31, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x31, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x31, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x31, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x32, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x32, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x32, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x32, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x22, 0x00003fff, 0, 0x4, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x22, 0x03ff0000, 16, 0x80, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x22, 0x78000000, 27, 0x3, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x21, 0x0000ffff, 0, 0x3FFF, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x21, 0xffff0000, 16, 0x3FFF, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x20, 0x00000001, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x50, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x50, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x50, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x50, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x51, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x51, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x51, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x51, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x52, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x52, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x52, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x52, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x42, 0x00003fff, 0, 0x4, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x42, 0x03ff0000, 16, 0x80, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x42, 0x78000000, 27, 0x3, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x41, 0x0000ffff, 0, 0x3FFF, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x41, 0xffff0000, 16, 0x3FFF, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x40, 0x00000001, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x70, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x70, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x70, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x70, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x71, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x71, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x71, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x71, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x72, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x72, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x72, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x72, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x62, 0x00003fff, 0, 0x4, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x62, 0x03ff0000, 16, 0x80, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x62, 0x78000000, 27, 0x3, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x61, 0x0000ffff, 0, 0x3FFF, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x61, 0xffff0000, 16, 0x3FFF, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0x60, 0x00000001, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND },
-       { 0xFFFFFFFF }
-};
-
-static u8 ci_get_memory_module_index(struct amdgpu_device *adev)
-{
-       return (u8) ((RREG32(mmBIOS_SCRATCH_4) >> 16) & 0xff);
-}
-
-#define MC_CG_ARB_FREQ_F0           0x0a
-#define MC_CG_ARB_FREQ_F1           0x0b
-#define MC_CG_ARB_FREQ_F2           0x0c
-#define MC_CG_ARB_FREQ_F3           0x0d
-
-static int ci_copy_and_switch_arb_sets(struct amdgpu_device *adev,
-                                      u32 arb_freq_src, u32 arb_freq_dest)
-{
-       u32 mc_arb_dram_timing;
-       u32 mc_arb_dram_timing2;
-       u32 burst_time;
-       u32 mc_cg_config;
-
-       switch (arb_freq_src) {
-       case MC_CG_ARB_FREQ_F0:
-               mc_arb_dram_timing  = RREG32(mmMC_ARB_DRAM_TIMING);
-               mc_arb_dram_timing2 = RREG32(mmMC_ARB_DRAM_TIMING2);
-               burst_time = (RREG32(mmMC_ARB_BURST_TIME) & MC_ARB_BURST_TIME__STATE0_MASK) >>
-                        MC_ARB_BURST_TIME__STATE0__SHIFT;
-               break;
-       case MC_CG_ARB_FREQ_F1:
-               mc_arb_dram_timing  = RREG32(mmMC_ARB_DRAM_TIMING_1);
-               mc_arb_dram_timing2 = RREG32(mmMC_ARB_DRAM_TIMING2_1);
-               burst_time = (RREG32(mmMC_ARB_BURST_TIME) & MC_ARB_BURST_TIME__STATE1_MASK) >>
-                        MC_ARB_BURST_TIME__STATE1__SHIFT;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       switch (arb_freq_dest) {
-       case MC_CG_ARB_FREQ_F0:
-               WREG32(mmMC_ARB_DRAM_TIMING, mc_arb_dram_timing);
-               WREG32(mmMC_ARB_DRAM_TIMING2, mc_arb_dram_timing2);
-               WREG32_P(mmMC_ARB_BURST_TIME, (burst_time << MC_ARB_BURST_TIME__STATE0__SHIFT),
-                       ~MC_ARB_BURST_TIME__STATE0_MASK);
-               break;
-       case MC_CG_ARB_FREQ_F1:
-               WREG32(mmMC_ARB_DRAM_TIMING_1, mc_arb_dram_timing);
-               WREG32(mmMC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2);
-               WREG32_P(mmMC_ARB_BURST_TIME, (burst_time << MC_ARB_BURST_TIME__STATE1__SHIFT),
-                       ~MC_ARB_BURST_TIME__STATE1_MASK);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       mc_cg_config = RREG32(mmMC_CG_CONFIG) | 0x0000000F;
-       WREG32(mmMC_CG_CONFIG, mc_cg_config);
-       WREG32_P(mmMC_ARB_CG, (arb_freq_dest) << MC_ARB_CG__CG_ARB_REQ__SHIFT,
-               ~MC_ARB_CG__CG_ARB_REQ_MASK);
-
-       return 0;
-}
-
-static u8 ci_get_ddr3_mclk_frequency_ratio(u32 memory_clock)
-{
-       u8 mc_para_index;
-
-       if (memory_clock < 10000)
-               mc_para_index = 0;
-       else if (memory_clock >= 80000)
-               mc_para_index = 0x0f;
-       else
-               mc_para_index = (u8)((memory_clock - 10000) / 5000 + 1);
-       return mc_para_index;
-}
-
-static u8 ci_get_mclk_frequency_ratio(u32 memory_clock, bool strobe_mode)
-{
-       u8 mc_para_index;
-
-       if (strobe_mode) {
-               if (memory_clock < 12500)
-                       mc_para_index = 0x00;
-               else if (memory_clock > 47500)
-                       mc_para_index = 0x0f;
-               else
-                       mc_para_index = (u8)((memory_clock - 10000) / 2500);
-       } else {
-               if (memory_clock < 65000)
-                       mc_para_index = 0x00;
-               else if (memory_clock > 135000)
-                       mc_para_index = 0x0f;
-               else
-                       mc_para_index = (u8)((memory_clock - 60000) / 5000);
-       }
-       return mc_para_index;
-}
-
-static void ci_trim_voltage_table_to_fit_state_table(struct amdgpu_device *adev,
-                                                    u32 max_voltage_steps,
-                                                    struct atom_voltage_table *voltage_table)
-{
-       unsigned int i, diff;
-
-       if (voltage_table->count <= max_voltage_steps)
-               return;
-
-       diff = voltage_table->count - max_voltage_steps;
-
-       for (i = 0; i < max_voltage_steps; i++)
-               voltage_table->entries[i] = voltage_table->entries[i + diff];
-
-       voltage_table->count = max_voltage_steps;
-}
-
-static int ci_get_std_voltage_value_sidd(struct amdgpu_device *adev,
-                                        struct atom_voltage_table_entry *voltage_table,
-                                        u16 *std_voltage_hi_sidd, u16 *std_voltage_lo_sidd);
-static int ci_set_power_limit(struct amdgpu_device *adev, u32 n);
-static int ci_set_overdrive_target_tdp(struct amdgpu_device *adev,
-                                      u32 target_tdp);
-static int ci_update_uvd_dpm(struct amdgpu_device *adev, bool gate);
-static void ci_dpm_set_irq_funcs(struct amdgpu_device *adev);
-
-static PPSMC_Result amdgpu_ci_send_msg_to_smc_with_parameter(struct amdgpu_device *adev,
-                                                            PPSMC_Msg msg, u32 parameter);
-static void ci_thermal_start_smc_fan_control(struct amdgpu_device *adev);
-static void ci_fan_ctrl_set_default_mode(struct amdgpu_device *adev);
-
-static struct ci_power_info *ci_get_pi(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = adev->pm.dpm.priv;
-
-       return pi;
-}
-
-static struct ci_ps *ci_get_ps(struct amdgpu_ps *rps)
-{
-       struct ci_ps *ps = rps->ps_priv;
-
-       return ps;
-}
-
-static void ci_initialize_powertune_defaults(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       switch (adev->pdev->device) {
-       case 0x6649:
-       case 0x6650:
-       case 0x6651:
-       case 0x6658:
-       case 0x665C:
-       case 0x665D:
-       default:
-               pi->powertune_defaults = &defaults_bonaire_xt;
-               break;
-       case 0x6640:
-       case 0x6641:
-       case 0x6646:
-       case 0x6647:
-               pi->powertune_defaults = &defaults_saturn_xt;
-               break;
-       case 0x67B8:
-       case 0x67B0:
-               pi->powertune_defaults = &defaults_hawaii_xt;
-               break;
-       case 0x67BA:
-       case 0x67B1:
-               pi->powertune_defaults = &defaults_hawaii_pro;
-               break;
-       case 0x67A0:
-       case 0x67A1:
-       case 0x67A2:
-       case 0x67A8:
-       case 0x67A9:
-       case 0x67AA:
-       case 0x67B9:
-       case 0x67BE:
-               pi->powertune_defaults = &defaults_bonaire_xt;
-               break;
-       }
-
-       pi->dte_tj_offset = 0;
-
-       pi->caps_power_containment = true;
-       pi->caps_cac = false;
-       pi->caps_sq_ramping = false;
-       pi->caps_db_ramping = false;
-       pi->caps_td_ramping = false;
-       pi->caps_tcp_ramping = false;
-
-       if (pi->caps_power_containment) {
-               pi->caps_cac = true;
-               if (adev->asic_type == CHIP_HAWAII)
-                       pi->enable_bapm_feature = false;
-               else
-                       pi->enable_bapm_feature = true;
-               pi->enable_tdc_limit_feature = true;
-               pi->enable_pkg_pwr_tracking_feature = true;
-       }
-}
-
-static u8 ci_convert_to_vid(u16 vddc)
-{
-       return (6200 - (vddc * VOLTAGE_SCALE)) / 25;
-}
-
-static int ci_populate_bapm_vddc_vid_sidd(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u8 *hi_vid = pi->smc_powertune_table.BapmVddCVidHiSidd;
-       u8 *lo_vid = pi->smc_powertune_table.BapmVddCVidLoSidd;
-       u8 *hi2_vid = pi->smc_powertune_table.BapmVddCVidHiSidd2;
-       u32 i;
-
-       if (adev->pm.dpm.dyn_state.cac_leakage_table.entries == NULL)
-               return -EINVAL;
-       if (adev->pm.dpm.dyn_state.cac_leakage_table.count > 8)
-               return -EINVAL;
-       if (adev->pm.dpm.dyn_state.cac_leakage_table.count !=
-           adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count)
-               return -EINVAL;
-
-       for (i = 0; i < adev->pm.dpm.dyn_state.cac_leakage_table.count; i++) {
-               if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) {
-                       lo_vid[i] = ci_convert_to_vid(adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1);
-                       hi_vid[i] = ci_convert_to_vid(adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2);
-                       hi2_vid[i] = ci_convert_to_vid(adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3);
-               } else {
-                       lo_vid[i] = ci_convert_to_vid(adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc);
-                       hi_vid[i] = ci_convert_to_vid((u16)adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage);
-               }
-       }
-       return 0;
-}
-
-static int ci_populate_vddc_vid(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u8 *vid = pi->smc_powertune_table.VddCVid;
-       u32 i;
-
-       if (pi->vddc_voltage_table.count > 8)
-               return -EINVAL;
-
-       for (i = 0; i < pi->vddc_voltage_table.count; i++)
-               vid[i] = ci_convert_to_vid(pi->vddc_voltage_table.entries[i].value);
-
-       return 0;
-}
-
-static int ci_populate_svi_load_line(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       const struct ci_pt_defaults *pt_defaults = pi->powertune_defaults;
-
-       pi->smc_powertune_table.SviLoadLineEn = pt_defaults->svi_load_line_en;
-       pi->smc_powertune_table.SviLoadLineVddC = pt_defaults->svi_load_line_vddc;
-       pi->smc_powertune_table.SviLoadLineTrimVddC = 3;
-       pi->smc_powertune_table.SviLoadLineOffsetVddC = 0;
-
-       return 0;
-}
-
-static int ci_populate_tdc_limit(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       const struct ci_pt_defaults *pt_defaults = pi->powertune_defaults;
-       u16 tdc_limit;
-
-       tdc_limit = adev->pm.dpm.dyn_state.cac_tdp_table->tdc * 256;
-       pi->smc_powertune_table.TDC_VDDC_PkgLimit = cpu_to_be16(tdc_limit);
-       pi->smc_powertune_table.TDC_VDDC_ThrottleReleaseLimitPerc =
-               pt_defaults->tdc_vddc_throttle_release_limit_perc;
-       pi->smc_powertune_table.TDC_MAWt = pt_defaults->tdc_mawt;
-
-       return 0;
-}
-
-static int ci_populate_dw8(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       const struct ci_pt_defaults *pt_defaults = pi->powertune_defaults;
-       int ret;
-
-       ret = amdgpu_ci_read_smc_sram_dword(adev,
-                                    SMU7_FIRMWARE_HEADER_LOCATION +
-                                    offsetof(SMU7_Firmware_Header, PmFuseTable) +
-                                    offsetof(SMU7_Discrete_PmFuses, TdcWaterfallCtl),
-                                    (u32 *)&pi->smc_powertune_table.TdcWaterfallCtl,
-                                    pi->sram_end);
-       if (ret)
-               return -EINVAL;
-       else
-               pi->smc_powertune_table.TdcWaterfallCtl = pt_defaults->tdc_waterfall_ctl;
-
-       return 0;
-}
-
-static int ci_populate_fuzzy_fan(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       if ((adev->pm.dpm.fan.fan_output_sensitivity & (1 << 15)) ||
-           (adev->pm.dpm.fan.fan_output_sensitivity == 0))
-               adev->pm.dpm.fan.fan_output_sensitivity =
-                       adev->pm.dpm.fan.default_fan_output_sensitivity;
-
-       pi->smc_powertune_table.FuzzyFan_PwmSetDelta =
-               cpu_to_be16(adev->pm.dpm.fan.fan_output_sensitivity);
-
-       return 0;
-}
-
-static int ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u8 *hi_vid = pi->smc_powertune_table.BapmVddCVidHiSidd;
-       u8 *lo_vid = pi->smc_powertune_table.BapmVddCVidLoSidd;
-       int i, min, max;
-
-       min = max = hi_vid[0];
-       for (i = 0; i < 8; i++) {
-               if (0 != hi_vid[i]) {
-                       if (min > hi_vid[i])
-                               min = hi_vid[i];
-                       if (max < hi_vid[i])
-                               max = hi_vid[i];
-               }
-
-               if (0 != lo_vid[i]) {
-                       if (min > lo_vid[i])
-                               min = lo_vid[i];
-                       if (max < lo_vid[i])
-                               max = lo_vid[i];
-               }
-       }
-
-       if ((min == 0) || (max == 0))
-               return -EINVAL;
-       pi->smc_powertune_table.GnbLPMLMaxVid = (u8)max;
-       pi->smc_powertune_table.GnbLPMLMinVid = (u8)min;
-
-       return 0;
-}
-
-static int ci_populate_bapm_vddc_base_leakage_sidd(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u16 hi_sidd = pi->smc_powertune_table.BapmVddCBaseLeakageHiSidd;
-       u16 lo_sidd = pi->smc_powertune_table.BapmVddCBaseLeakageLoSidd;
-       struct amdgpu_cac_tdp_table *cac_tdp_table =
-               adev->pm.dpm.dyn_state.cac_tdp_table;
-
-       hi_sidd = cac_tdp_table->high_cac_leakage / 100 * 256;
-       lo_sidd = cac_tdp_table->low_cac_leakage / 100 * 256;
-
-       pi->smc_powertune_table.BapmVddCBaseLeakageHiSidd = cpu_to_be16(hi_sidd);
-       pi->smc_powertune_table.BapmVddCBaseLeakageLoSidd = cpu_to_be16(lo_sidd);
-
-       return 0;
-}
-
-static int ci_populate_bapm_parameters_in_dpm_table(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       const struct ci_pt_defaults *pt_defaults = pi->powertune_defaults;
-       SMU7_Discrete_DpmTable  *dpm_table = &pi->smc_state_table;
-       struct amdgpu_cac_tdp_table *cac_tdp_table =
-               adev->pm.dpm.dyn_state.cac_tdp_table;
-       struct amdgpu_ppm_table *ppm = adev->pm.dpm.dyn_state.ppm_table;
-       int i, j, k;
-       const u16 *def1;
-       const u16 *def2;
-
-       dpm_table->DefaultTdp = cac_tdp_table->tdp * 256;
-       dpm_table->TargetTdp = cac_tdp_table->configurable_tdp * 256;
-
-       dpm_table->DTETjOffset = (u8)pi->dte_tj_offset;
-       dpm_table->GpuTjMax =
-               (u8)(pi->thermal_temp_setting.temperature_high / 1000);
-       dpm_table->GpuTjHyst = 8;
-
-       dpm_table->DTEAmbientTempBase = pt_defaults->dte_ambient_temp_base;
-
-       if (ppm) {
-               dpm_table->PPM_PkgPwrLimit = cpu_to_be16((u16)ppm->dgpu_tdp * 256 / 1000);
-               dpm_table->PPM_TemperatureLimit = cpu_to_be16((u16)ppm->tj_max * 256);
-       } else {
-               dpm_table->PPM_PkgPwrLimit = cpu_to_be16(0);
-               dpm_table->PPM_TemperatureLimit = cpu_to_be16(0);
-       }
-
-       dpm_table->BAPM_TEMP_GRADIENT = cpu_to_be32(pt_defaults->bapm_temp_gradient);
-       def1 = pt_defaults->bapmti_r;
-       def2 = pt_defaults->bapmti_rc;
-
-       for (i = 0; i < SMU7_DTE_ITERATIONS; i++) {
-               for (j = 0; j < SMU7_DTE_SOURCES; j++) {
-                       for (k = 0; k < SMU7_DTE_SINKS; k++) {
-                               dpm_table->BAPMTI_R[i][j][k] = cpu_to_be16(*def1);
-                               dpm_table->BAPMTI_RC[i][j][k] = cpu_to_be16(*def2);
-                               def1++;
-                               def2++;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static int ci_populate_pm_base(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u32 pm_fuse_table_offset;
-       int ret;
-
-       if (pi->caps_power_containment) {
-               ret = amdgpu_ci_read_smc_sram_dword(adev,
-                                            SMU7_FIRMWARE_HEADER_LOCATION +
-                                            offsetof(SMU7_Firmware_Header, PmFuseTable),
-                                            &pm_fuse_table_offset, pi->sram_end);
-               if (ret)
-                       return ret;
-               ret = ci_populate_bapm_vddc_vid_sidd(adev);
-               if (ret)
-                       return ret;
-               ret = ci_populate_vddc_vid(adev);
-               if (ret)
-                       return ret;
-               ret = ci_populate_svi_load_line(adev);
-               if (ret)
-                       return ret;
-               ret = ci_populate_tdc_limit(adev);
-               if (ret)
-                       return ret;
-               ret = ci_populate_dw8(adev);
-               if (ret)
-                       return ret;
-               ret = ci_populate_fuzzy_fan(adev);
-               if (ret)
-                       return ret;
-               ret = ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(adev);
-               if (ret)
-                       return ret;
-               ret = ci_populate_bapm_vddc_base_leakage_sidd(adev);
-               if (ret)
-                       return ret;
-               ret = amdgpu_ci_copy_bytes_to_smc(adev, pm_fuse_table_offset,
-                                          (u8 *)&pi->smc_powertune_table,
-                                          sizeof(SMU7_Discrete_PmFuses), pi->sram_end);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static void ci_do_enable_didt(struct amdgpu_device *adev, const bool enable)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u32 data;
-
-       if (pi->caps_sq_ramping) {
-               data = RREG32_DIDT(ixDIDT_SQ_CTRL0);
-               if (enable)
-                       data |= DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK;
-               else
-                       data &= ~DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK;
-               WREG32_DIDT(ixDIDT_SQ_CTRL0, data);
-       }
-
-       if (pi->caps_db_ramping) {
-               data = RREG32_DIDT(ixDIDT_DB_CTRL0);
-               if (enable)
-                       data |= DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK;
-               else
-                       data &= ~DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK;
-               WREG32_DIDT(ixDIDT_DB_CTRL0, data);
-       }
-
-       if (pi->caps_td_ramping) {
-               data = RREG32_DIDT(ixDIDT_TD_CTRL0);
-               if (enable)
-                       data |= DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK;
-               else
-                       data &= ~DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK;
-               WREG32_DIDT(ixDIDT_TD_CTRL0, data);
-       }
-
-       if (pi->caps_tcp_ramping) {
-               data = RREG32_DIDT(ixDIDT_TCP_CTRL0);
-               if (enable)
-                       data |= DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK;
-               else
-                       data &= ~DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK;
-               WREG32_DIDT(ixDIDT_TCP_CTRL0, data);
-       }
-}
-
-static int ci_program_pt_config_registers(struct amdgpu_device *adev,
-                                         const struct ci_pt_config_reg *cac_config_regs)
-{
-       const struct ci_pt_config_reg *config_regs = cac_config_regs;
-       u32 data;
-       u32 cache = 0;
-
-       if (config_regs == NULL)
-               return -EINVAL;
-
-       while (config_regs->offset != 0xFFFFFFFF) {
-               if (config_regs->type == CISLANDS_CONFIGREG_CACHE) {
-                       cache |= ((config_regs->value << config_regs->shift) & config_regs->mask);
-               } else {
-                       switch (config_regs->type) {
-                       case CISLANDS_CONFIGREG_SMC_IND:
-                               data = RREG32_SMC(config_regs->offset);
-                               break;
-                       case CISLANDS_CONFIGREG_DIDT_IND:
-                               data = RREG32_DIDT(config_regs->offset);
-                               break;
-                       default:
-                               data = RREG32(config_regs->offset);
-                               break;
-                       }
-
-                       data &= ~config_regs->mask;
-                       data |= ((config_regs->value << config_regs->shift) & config_regs->mask);
-                       data |= cache;
-
-                       switch (config_regs->type) {
-                       case CISLANDS_CONFIGREG_SMC_IND:
-                               WREG32_SMC(config_regs->offset, data);
-                               break;
-                       case CISLANDS_CONFIGREG_DIDT_IND:
-                               WREG32_DIDT(config_regs->offset, data);
-                               break;
-                       default:
-                               WREG32(config_regs->offset, data);
-                               break;
-                       }
-                       cache = 0;
-               }
-               config_regs++;
-       }
-       return 0;
-}
-
-static int ci_enable_didt(struct amdgpu_device *adev, bool enable)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       int ret;
-
-       if (pi->caps_sq_ramping || pi->caps_db_ramping ||
-           pi->caps_td_ramping || pi->caps_tcp_ramping) {
-               amdgpu_gfx_rlc_enter_safe_mode(adev);
-
-               if (enable) {
-                       ret = ci_program_pt_config_registers(adev, didt_config_ci);
-                       if (ret) {
-                               amdgpu_gfx_rlc_exit_safe_mode(adev);
-                               return ret;
-                       }
-               }
-
-               ci_do_enable_didt(adev, enable);
-
-               amdgpu_gfx_rlc_exit_safe_mode(adev);
-       }
-
-       return 0;
-}
-
-static int ci_enable_power_containment(struct amdgpu_device *adev, bool enable)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       PPSMC_Result smc_result;
-       int ret = 0;
-
-       if (enable) {
-               pi->power_containment_features = 0;
-               if (pi->caps_power_containment) {
-                       if (pi->enable_bapm_feature) {
-                               smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_EnableDTE);
-                               if (smc_result != PPSMC_Result_OK)
-                                       ret = -EINVAL;
-                               else
-                                       pi->power_containment_features |= POWERCONTAINMENT_FEATURE_BAPM;
-                       }
-
-                       if (pi->enable_tdc_limit_feature) {
-                               smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_TDCLimitEnable);
-                               if (smc_result != PPSMC_Result_OK)
-                                       ret = -EINVAL;
-                               else
-                                       pi->power_containment_features |= POWERCONTAINMENT_FEATURE_TDCLimit;
-                       }
-
-                       if (pi->enable_pkg_pwr_tracking_feature) {
-                               smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_PkgPwrLimitEnable);
-                               if (smc_result != PPSMC_Result_OK) {
-                                       ret = -EINVAL;
-                               } else {
-                                       struct amdgpu_cac_tdp_table *cac_tdp_table =
-                                               adev->pm.dpm.dyn_state.cac_tdp_table;
-                                       u32 default_pwr_limit =
-                                               (u32)(cac_tdp_table->maximum_power_delivery_limit * 256);
-
-                                       pi->power_containment_features |= POWERCONTAINMENT_FEATURE_PkgPwrLimit;
-
-                                       ci_set_power_limit(adev, default_pwr_limit);
-                               }
-                       }
-               }
-       } else {
-               if (pi->caps_power_containment && pi->power_containment_features) {
-                       if (pi->power_containment_features & POWERCONTAINMENT_FEATURE_TDCLimit)
-                               amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_TDCLimitDisable);
-
-                       if (pi->power_containment_features & POWERCONTAINMENT_FEATURE_BAPM)
-                               amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_DisableDTE);
-
-                       if (pi->power_containment_features & POWERCONTAINMENT_FEATURE_PkgPwrLimit)
-                               amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_PkgPwrLimitDisable);
-                       pi->power_containment_features = 0;
-               }
-       }
-
-       return ret;
-}
-
-static int ci_enable_smc_cac(struct amdgpu_device *adev, bool enable)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       PPSMC_Result smc_result;
-       int ret = 0;
-
-       if (pi->caps_cac) {
-               if (enable) {
-                       smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_EnableCac);
-                       if (smc_result != PPSMC_Result_OK) {
-                               ret = -EINVAL;
-                               pi->cac_enabled = false;
-                       } else {
-                               pi->cac_enabled = true;
-                       }
-               } else if (pi->cac_enabled) {
-                       amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_DisableCac);
-                       pi->cac_enabled = false;
-               }
-       }
-
-       return ret;
-}
-
-static int ci_enable_thermal_based_sclk_dpm(struct amdgpu_device *adev,
-                                           bool enable)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       PPSMC_Result smc_result = PPSMC_Result_OK;
-
-       if (pi->thermal_sclk_dpm_enabled) {
-               if (enable)
-                       smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_ENABLE_THERMAL_DPM);
-               else
-                       smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_DISABLE_THERMAL_DPM);
-       }
-
-       if (smc_result == PPSMC_Result_OK)
-               return 0;
-       else
-               return -EINVAL;
-}
-
-static int ci_power_control_set_level(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct amdgpu_cac_tdp_table *cac_tdp_table =
-               adev->pm.dpm.dyn_state.cac_tdp_table;
-       s32 adjust_percent;
-       s32 target_tdp;
-       int ret = 0;
-       bool adjust_polarity = false; /* ??? */
-
-       if (pi->caps_power_containment) {
-               adjust_percent = adjust_polarity ?
-                       adev->pm.dpm.tdp_adjustment : (-1 * adev->pm.dpm.tdp_adjustment);
-               target_tdp = ((100 + adjust_percent) *
-                             (s32)cac_tdp_table->configurable_tdp) / 100;
-
-               ret = ci_set_overdrive_target_tdp(adev, (u32)target_tdp);
-       }
-
-       return ret;
-}
-
-static void ci_dpm_powergate_uvd(void *handle, bool gate)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       pi->uvd_power_gated = gate;
-
-       if (gate) {
-               /* stop the UVD block */
-               amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
-                                                      AMD_PG_STATE_GATE);
-               ci_update_uvd_dpm(adev, gate);
-       } else {
-               amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
-                                                      AMD_PG_STATE_UNGATE);
-               ci_update_uvd_dpm(adev, gate);
-       }
-}
-
-static bool ci_dpm_vblank_too_short(void *handle)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       u32 vblank_time = amdgpu_dpm_get_vblank_time(adev);
-       u32 switch_limit = adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 300;
-
-       /* disable mclk switching if the refresh is >120Hz, even if the
-        * blanking period would allow it
-        */
-       if (amdgpu_dpm_get_vrefresh(adev) > 120)
-               return true;
-
-       if (vblank_time < switch_limit)
-               return true;
-       else
-               return false;
-
-}
-
-static void ci_apply_state_adjust_rules(struct amdgpu_device *adev,
-                                       struct amdgpu_ps *rps)
-{
-       struct ci_ps *ps = ci_get_ps(rps);
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct amdgpu_clock_and_voltage_limits *max_limits;
-       bool disable_mclk_switching;
-       u32 sclk, mclk;
-       int i;
-
-       if (rps->vce_active) {
-               rps->evclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].evclk;
-               rps->ecclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].ecclk;
-       } else {
-               rps->evclk = 0;
-               rps->ecclk = 0;
-       }
-
-       if ((adev->pm.dpm.new_active_crtc_count > 1) ||
-           ci_dpm_vblank_too_short(adev))
-               disable_mclk_switching = true;
-       else
-               disable_mclk_switching = false;
-
-       if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)
-               pi->battery_state = true;
-       else
-               pi->battery_state = false;
-
-       if (adev->pm.ac_power)
-               max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
-       else
-               max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_dc;
-
-       if (adev->pm.ac_power == false) {
-               for (i = 0; i < ps->performance_level_count; i++) {
-                       if (ps->performance_levels[i].mclk > max_limits->mclk)
-                               ps->performance_levels[i].mclk = max_limits->mclk;
-                       if (ps->performance_levels[i].sclk > max_limits->sclk)
-                               ps->performance_levels[i].sclk = max_limits->sclk;
-               }
-       }
-
-       /* XXX validate the min clocks required for display */
-
-       if (disable_mclk_switching) {
-               mclk  = ps->performance_levels[ps->performance_level_count - 1].mclk;
-               sclk = ps->performance_levels[0].sclk;
-       } else {
-               mclk = ps->performance_levels[0].mclk;
-               sclk = ps->performance_levels[0].sclk;
-       }
-
-       if (adev->pm.pm_display_cfg.min_core_set_clock > sclk)
-               sclk = adev->pm.pm_display_cfg.min_core_set_clock;
-
-       if (adev->pm.pm_display_cfg.min_mem_set_clock > mclk)
-               mclk = adev->pm.pm_display_cfg.min_mem_set_clock;
-
-       if (rps->vce_active) {
-               if (sclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk)
-                       sclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk;
-               if (mclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].mclk)
-                       mclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].mclk;
-       }
-
-       ps->performance_levels[0].sclk = sclk;
-       ps->performance_levels[0].mclk = mclk;
-
-       if (ps->performance_levels[1].sclk < ps->performance_levels[0].sclk)
-               ps->performance_levels[1].sclk = ps->performance_levels[0].sclk;
-
-       if (disable_mclk_switching) {
-               if (ps->performance_levels[0].mclk < ps->performance_levels[1].mclk)
-                       ps->performance_levels[0].mclk = ps->performance_levels[1].mclk;
-       } else {
-               if (ps->performance_levels[1].mclk < ps->performance_levels[0].mclk)
-                       ps->performance_levels[1].mclk = ps->performance_levels[0].mclk;
-       }
-}
-
-static int ci_thermal_set_temperature_range(struct amdgpu_device *adev,
-                                           int min_temp, int max_temp)
-{
-       int low_temp = 0 * 1000;
-       int high_temp = 255 * 1000;
-       u32 tmp;
-
-       if (low_temp < min_temp)
-               low_temp = min_temp;
-       if (high_temp > max_temp)
-               high_temp = max_temp;
-       if (high_temp < low_temp) {
-               DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp);
-               return -EINVAL;
-       }
-
-       tmp = RREG32_SMC(ixCG_THERMAL_INT);
-       tmp &= ~(CG_THERMAL_INT__DIG_THERM_INTH_MASK | CG_THERMAL_INT__DIG_THERM_INTL_MASK);
-       tmp |= ((high_temp / 1000) << CG_THERMAL_INT__DIG_THERM_INTH__SHIFT) |
-               ((low_temp / 1000)) << CG_THERMAL_INT__DIG_THERM_INTL__SHIFT;
-       WREG32_SMC(ixCG_THERMAL_INT, tmp);
-
-#if 0
-       /* XXX: need to figure out how to handle this properly */
-       tmp = RREG32_SMC(ixCG_THERMAL_CTRL);
-       tmp &= DIG_THERM_DPM_MASK;
-       tmp |= DIG_THERM_DPM(high_temp / 1000);
-       WREG32_SMC(ixCG_THERMAL_CTRL, tmp);
-#endif
-
-       adev->pm.dpm.thermal.min_temp = low_temp;
-       adev->pm.dpm.thermal.max_temp = high_temp;
-       return 0;
-}
-
-static int ci_thermal_enable_alert(struct amdgpu_device *adev,
-                                  bool enable)
-{
-       u32 thermal_int = RREG32_SMC(ixCG_THERMAL_INT);
-       PPSMC_Result result;
-
-       if (enable) {
-               thermal_int &= ~(CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK |
-                                CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK);
-               WREG32_SMC(ixCG_THERMAL_INT, thermal_int);
-               result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_Thermal_Cntl_Enable);
-               if (result != PPSMC_Result_OK) {
-                       DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
-                       return -EINVAL;
-               }
-       } else {
-               thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK |
-                       CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
-               WREG32_SMC(ixCG_THERMAL_INT, thermal_int);
-               result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_Thermal_Cntl_Disable);
-               if (result != PPSMC_Result_OK) {
-                       DRM_DEBUG_KMS("Could not disable thermal interrupts.\n");
-                       return -EINVAL;
-               }
-       }
-
-       return 0;
-}
-
-static void ci_fan_ctrl_set_static_mode(struct amdgpu_device *adev, u32 mode)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u32 tmp;
-
-       if (pi->fan_ctrl_is_in_default_mode) {
-               tmp = (RREG32_SMC(ixCG_FDO_CTRL2) & CG_FDO_CTRL2__FDO_PWM_MODE_MASK)
-                       >> CG_FDO_CTRL2__FDO_PWM_MODE__SHIFT;
-               pi->fan_ctrl_default_mode = tmp;
-               tmp = (RREG32_SMC(ixCG_FDO_CTRL2) & CG_FDO_CTRL2__TMIN_MASK)
-                       >> CG_FDO_CTRL2__TMIN__SHIFT;
-               pi->t_min = tmp;
-               pi->fan_ctrl_is_in_default_mode = false;
-       }
-
-       tmp = RREG32_SMC(ixCG_FDO_CTRL2) & ~CG_FDO_CTRL2__TMIN_MASK;
-       tmp |= 0 << CG_FDO_CTRL2__TMIN__SHIFT;
-       WREG32_SMC(ixCG_FDO_CTRL2, tmp);
-
-       tmp = RREG32_SMC(ixCG_FDO_CTRL2) & ~CG_FDO_CTRL2__FDO_PWM_MODE_MASK;
-       tmp |= mode << CG_FDO_CTRL2__FDO_PWM_MODE__SHIFT;
-       WREG32_SMC(ixCG_FDO_CTRL2, tmp);
-}
-
-static int ci_thermal_setup_fan_table(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       SMU7_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE };
-       u32 duty100;
-       u32 t_diff1, t_diff2, pwm_diff1, pwm_diff2;
-       u16 fdo_min, slope1, slope2;
-       u32 reference_clock, tmp;
-       int ret;
-       u64 tmp64;
-
-       if (!pi->fan_table_start) {
-               adev->pm.dpm.fan.ucode_fan_control = false;
-               return 0;
-       }
-
-       duty100 = (RREG32_SMC(ixCG_FDO_CTRL1) & CG_FDO_CTRL1__FMAX_DUTY100_MASK)
-               >> CG_FDO_CTRL1__FMAX_DUTY100__SHIFT;
-
-       if (duty100 == 0) {
-               adev->pm.dpm.fan.ucode_fan_control = false;
-               return 0;
-       }
-
-       tmp64 = (u64)adev->pm.dpm.fan.pwm_min * duty100;
-       do_div(tmp64, 10000);
-       fdo_min = (u16)tmp64;
-
-       t_diff1 = adev->pm.dpm.fan.t_med - adev->pm.dpm.fan.t_min;
-       t_diff2 = adev->pm.dpm.fan.t_high - adev->pm.dpm.fan.t_med;
-
-       pwm_diff1 = adev->pm.dpm.fan.pwm_med - adev->pm.dpm.fan.pwm_min;
-       pwm_diff2 = adev->pm.dpm.fan.pwm_high - adev->pm.dpm.fan.pwm_med;
-
-       slope1 = (u16)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
-       slope2 = (u16)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);
-
-       fan_table.TempMin = cpu_to_be16((50 + adev->pm.dpm.fan.t_min) / 100);
-       fan_table.TempMed = cpu_to_be16((50 + adev->pm.dpm.fan.t_med) / 100);
-       fan_table.TempMax = cpu_to_be16((50 + adev->pm.dpm.fan.t_max) / 100);
-
-       fan_table.Slope1 = cpu_to_be16(slope1);
-       fan_table.Slope2 = cpu_to_be16(slope2);
-
-       fan_table.FdoMin = cpu_to_be16(fdo_min);
-
-       fan_table.HystDown = cpu_to_be16(adev->pm.dpm.fan.t_hyst);
-
-       fan_table.HystUp = cpu_to_be16(1);
-
-       fan_table.HystSlope = cpu_to_be16(1);
-
-       fan_table.TempRespLim = cpu_to_be16(5);
-
-       reference_clock = amdgpu_asic_get_xclk(adev);
-
-       fan_table.RefreshPeriod = cpu_to_be32((adev->pm.dpm.fan.cycle_delay *
-                                              reference_clock) / 1600);
-
-       fan_table.FdoMax = cpu_to_be16((u16)duty100);
-
-       tmp = (RREG32_SMC(ixCG_MULT_THERMAL_CTRL) & CG_MULT_THERMAL_CTRL__TEMP_SEL_MASK)
-               >> CG_MULT_THERMAL_CTRL__TEMP_SEL__SHIFT;
-       fan_table.TempSrc = (uint8_t)tmp;
-
-       ret = amdgpu_ci_copy_bytes_to_smc(adev,
-                                         pi->fan_table_start,
-                                         (u8 *)(&fan_table),
-                                         sizeof(fan_table),
-                                         pi->sram_end);
-
-       if (ret) {
-               DRM_ERROR("Failed to load fan table to the SMC.");
-               adev->pm.dpm.fan.ucode_fan_control = false;
-       }
-
-       return 0;
-}
-
-static int ci_fan_ctrl_start_smc_fan_control(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       PPSMC_Result ret;
-
-       if (pi->caps_od_fuzzy_fan_control_support) {
-               ret = amdgpu_ci_send_msg_to_smc_with_parameter(adev,
-                                                              PPSMC_StartFanControl,
-                                                              FAN_CONTROL_FUZZY);
-               if (ret != PPSMC_Result_OK)
-                       return -EINVAL;
-               ret = amdgpu_ci_send_msg_to_smc_with_parameter(adev,
-                                                              PPSMC_MSG_SetFanPwmMax,
-                                                              adev->pm.dpm.fan.default_max_fan_pwm);
-               if (ret != PPSMC_Result_OK)
-                       return -EINVAL;
-       } else {
-               ret = amdgpu_ci_send_msg_to_smc_with_parameter(adev,
-                                                              PPSMC_StartFanControl,
-                                                              FAN_CONTROL_TABLE);
-               if (ret != PPSMC_Result_OK)
-                       return -EINVAL;
-       }
-
-       pi->fan_is_controlled_by_smc = true;
-       return 0;
-}
-
-
-static int ci_fan_ctrl_stop_smc_fan_control(struct amdgpu_device *adev)
-{
-       PPSMC_Result ret;
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       ret = amdgpu_ci_send_msg_to_smc(adev, PPSMC_StopFanControl);
-       if (ret == PPSMC_Result_OK) {
-               pi->fan_is_controlled_by_smc = false;
-               return 0;
-       } else {
-               return -EINVAL;
-       }
-}
-
-static int ci_dpm_get_fan_speed_percent(void *handle,
-                                       u32 *speed)
-{
-       u32 duty, duty100;
-       u64 tmp64;
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       if (adev->pm.no_fan)
-               return -ENOENT;
-
-       duty100 = (RREG32_SMC(ixCG_FDO_CTRL1) & CG_FDO_CTRL1__FMAX_DUTY100_MASK)
-               >> CG_FDO_CTRL1__FMAX_DUTY100__SHIFT;
-       duty = (RREG32_SMC(ixCG_THERMAL_STATUS) & CG_THERMAL_STATUS__FDO_PWM_DUTY_MASK)
-               >> CG_THERMAL_STATUS__FDO_PWM_DUTY__SHIFT;
-
-       if (duty100 == 0)
-               return -EINVAL;
-
-       tmp64 = (u64)duty * 100;
-       do_div(tmp64, duty100);
-       *speed = (u32)tmp64;
-
-       if (*speed > 100)
-               *speed = 100;
-
-       return 0;
-}
-
-static int ci_dpm_set_fan_speed_percent(void *handle,
-                                       u32 speed)
-{
-       u32 tmp;
-       u32 duty, duty100;
-       u64 tmp64;
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       if (adev->pm.no_fan)
-               return -ENOENT;
-
-       if (pi->fan_is_controlled_by_smc)
-               return -EINVAL;
-
-       if (speed > 100)
-               return -EINVAL;
-
-       duty100 = (RREG32_SMC(ixCG_FDO_CTRL1) & CG_FDO_CTRL1__FMAX_DUTY100_MASK)
-               >> CG_FDO_CTRL1__FMAX_DUTY100__SHIFT;
-
-       if (duty100 == 0)
-               return -EINVAL;
-
-       tmp64 = (u64)speed * duty100;
-       do_div(tmp64, 100);
-       duty = (u32)tmp64;
-
-       tmp = RREG32_SMC(ixCG_FDO_CTRL0) & ~CG_FDO_CTRL0__FDO_STATIC_DUTY_MASK;
-       tmp |= duty << CG_FDO_CTRL0__FDO_STATIC_DUTY__SHIFT;
-       WREG32_SMC(ixCG_FDO_CTRL0, tmp);
-
-       return 0;
-}
-
-static void ci_dpm_set_fan_control_mode(void *handle, u32 mode)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       switch (mode) {
-       case AMD_FAN_CTRL_NONE:
-               if (adev->pm.dpm.fan.ucode_fan_control)
-                       ci_fan_ctrl_stop_smc_fan_control(adev);
-               ci_dpm_set_fan_speed_percent(adev, 100);
-               break;
-       case AMD_FAN_CTRL_MANUAL:
-               if (adev->pm.dpm.fan.ucode_fan_control)
-                       ci_fan_ctrl_stop_smc_fan_control(adev);
-               break;
-       case AMD_FAN_CTRL_AUTO:
-               if (adev->pm.dpm.fan.ucode_fan_control)
-                       ci_thermal_start_smc_fan_control(adev);
-               break;
-       default:
-               break;
-       }
-}
-
-static u32 ci_dpm_get_fan_control_mode(void *handle)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       if (pi->fan_is_controlled_by_smc)
-               return AMD_FAN_CTRL_AUTO;
-       else
-               return AMD_FAN_CTRL_MANUAL;
-}
-
-#if 0
-static int ci_fan_ctrl_get_fan_speed_rpm(struct amdgpu_device *adev,
-                                        u32 *speed)
-{
-       u32 tach_period;
-       u32 xclk = amdgpu_asic_get_xclk(adev);
-
-       if (adev->pm.no_fan)
-               return -ENOENT;
-
-       if (adev->pm.fan_pulses_per_revolution == 0)
-               return -ENOENT;
-
-       tach_period = (RREG32_SMC(ixCG_TACH_STATUS) & CG_TACH_STATUS__TACH_PERIOD_MASK)
-               >> CG_TACH_STATUS__TACH_PERIOD__SHIFT;
-       if (tach_period == 0)
-               return -ENOENT;
-
-       *speed = 60 * xclk * 10000 / tach_period;
-
-       return 0;
-}
-
-static int ci_fan_ctrl_set_fan_speed_rpm(struct amdgpu_device *adev,
-                                        u32 speed)
-{
-       u32 tach_period, tmp;
-       u32 xclk = amdgpu_asic_get_xclk(adev);
-
-       if (adev->pm.no_fan)
-               return -ENOENT;
-
-       if (adev->pm.fan_pulses_per_revolution == 0)
-               return -ENOENT;
-
-       if ((speed < adev->pm.fan_min_rpm) ||
-           (speed > adev->pm.fan_max_rpm))
-               return -EINVAL;
-
-       if (adev->pm.dpm.fan.ucode_fan_control)
-               ci_fan_ctrl_stop_smc_fan_control(adev);
-
-       tach_period = 60 * xclk * 10000 / (8 * speed);
-       tmp = RREG32_SMC(ixCG_TACH_CTRL) & ~CG_TACH_CTRL__TARGET_PERIOD_MASK;
-       tmp |= tach_period << CG_TACH_CTRL__TARGET_PERIOD__SHIFT;
-       WREG32_SMC(CG_TACH_CTRL, tmp);
-
-       ci_fan_ctrl_set_static_mode(adev, FDO_PWM_MODE_STATIC_RPM);
-
-       return 0;
-}
-#endif
-
-static void ci_fan_ctrl_set_default_mode(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u32 tmp;
-
-       if (!pi->fan_ctrl_is_in_default_mode) {
-               tmp = RREG32_SMC(ixCG_FDO_CTRL2) & ~CG_FDO_CTRL2__FDO_PWM_MODE_MASK;
-               tmp |= pi->fan_ctrl_default_mode << CG_FDO_CTRL2__FDO_PWM_MODE__SHIFT;
-               WREG32_SMC(ixCG_FDO_CTRL2, tmp);
-
-               tmp = RREG32_SMC(ixCG_FDO_CTRL2) & ~CG_FDO_CTRL2__TMIN_MASK;
-               tmp |= pi->t_min << CG_FDO_CTRL2__TMIN__SHIFT;
-               WREG32_SMC(ixCG_FDO_CTRL2, tmp);
-               pi->fan_ctrl_is_in_default_mode = true;
-       }
-}
-
-static void ci_thermal_start_smc_fan_control(struct amdgpu_device *adev)
-{
-       if (adev->pm.dpm.fan.ucode_fan_control) {
-               ci_fan_ctrl_start_smc_fan_control(adev);
-               ci_fan_ctrl_set_static_mode(adev, FDO_PWM_MODE_STATIC);
-       }
-}
-
-static void ci_thermal_initialize(struct amdgpu_device *adev)
-{
-       u32 tmp;
-
-       if (adev->pm.fan_pulses_per_revolution) {
-               tmp = RREG32_SMC(ixCG_TACH_CTRL) & ~CG_TACH_CTRL__EDGE_PER_REV_MASK;
-               tmp |= (adev->pm.fan_pulses_per_revolution - 1)
-                       << CG_TACH_CTRL__EDGE_PER_REV__SHIFT;
-               WREG32_SMC(ixCG_TACH_CTRL, tmp);
-       }
-
-       tmp = RREG32_SMC(ixCG_FDO_CTRL2) & ~CG_FDO_CTRL2__TACH_PWM_RESP_RATE_MASK;
-       tmp |= 0x28 << CG_FDO_CTRL2__TACH_PWM_RESP_RATE__SHIFT;
-       WREG32_SMC(ixCG_FDO_CTRL2, tmp);
-}
-
-static int ci_thermal_start_thermal_controller(struct amdgpu_device *adev)
-{
-       int ret;
-
-       ci_thermal_initialize(adev);
-       ret = ci_thermal_set_temperature_range(adev, CISLANDS_TEMP_RANGE_MIN, CISLANDS_TEMP_RANGE_MAX);
-       if (ret)
-               return ret;
-       ret = ci_thermal_enable_alert(adev, true);
-       if (ret)
-               return ret;
-       if (adev->pm.dpm.fan.ucode_fan_control) {
-               ret = ci_thermal_setup_fan_table(adev);
-               if (ret)
-                       return ret;
-               ci_thermal_start_smc_fan_control(adev);
-       }
-
-       return 0;
-}
-
-static void ci_thermal_stop_thermal_controller(struct amdgpu_device *adev)
-{
-       if (!adev->pm.no_fan)
-               ci_fan_ctrl_set_default_mode(adev);
-}
-
-static int ci_read_smc_soft_register(struct amdgpu_device *adev,
-                                    u16 reg_offset, u32 *value)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       return amdgpu_ci_read_smc_sram_dword(adev,
-                                     pi->soft_regs_start + reg_offset,
-                                     value, pi->sram_end);
-}
-
-static int ci_write_smc_soft_register(struct amdgpu_device *adev,
-                                     u16 reg_offset, u32 value)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       return amdgpu_ci_write_smc_sram_dword(adev,
-                                      pi->soft_regs_start + reg_offset,
-                                      value, pi->sram_end);
-}
-
-static void ci_init_fps_limits(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       SMU7_Discrete_DpmTable *table = &pi->smc_state_table;
-
-       if (pi->caps_fps) {
-               u16 tmp;
-
-               tmp = 45;
-               table->FpsHighT = cpu_to_be16(tmp);
-
-               tmp = 30;
-               table->FpsLowT = cpu_to_be16(tmp);
-       }
-}
-
-static int ci_update_sclk_t(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       int ret = 0;
-       u32 low_sclk_interrupt_t = 0;
-
-       if (pi->caps_sclk_throttle_low_notification) {
-               low_sclk_interrupt_t = cpu_to_be32(pi->low_sclk_interrupt_t);
-
-               ret = amdgpu_ci_copy_bytes_to_smc(adev,
-                                          pi->dpm_table_start +
-                                          offsetof(SMU7_Discrete_DpmTable, LowSclkInterruptT),
-                                          (u8 *)&low_sclk_interrupt_t,
-                                          sizeof(u32), pi->sram_end);
-
-       }
-
-       return ret;
-}
-
-static void ci_get_leakage_voltages(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u16 leakage_id, virtual_voltage_id;
-       u16 vddc, vddci;
-       int i;
-
-       pi->vddc_leakage.count = 0;
-       pi->vddci_leakage.count = 0;
-
-       if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) {
-               for (i = 0; i < CISLANDS_MAX_LEAKAGE_COUNT; i++) {
-                       virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
-                       if (amdgpu_atombios_get_voltage_evv(adev, virtual_voltage_id, &vddc) != 0)
-                               continue;
-                       if (vddc != 0 && vddc != virtual_voltage_id) {
-                               pi->vddc_leakage.actual_voltage[pi->vddc_leakage.count] = vddc;
-                               pi->vddc_leakage.leakage_id[pi->vddc_leakage.count] = virtual_voltage_id;
-                               pi->vddc_leakage.count++;
-                       }
-               }
-       } else if (amdgpu_atombios_get_leakage_id_from_vbios(adev, &leakage_id) == 0) {
-               for (i = 0; i < CISLANDS_MAX_LEAKAGE_COUNT; i++) {
-                       virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
-                       if (amdgpu_atombios_get_leakage_vddc_based_on_leakage_params(adev, &vddc, &vddci,
-                                                                                    virtual_voltage_id,
-                                                                                    leakage_id) == 0) {
-                               if (vddc != 0 && vddc != virtual_voltage_id) {
-                                       pi->vddc_leakage.actual_voltage[pi->vddc_leakage.count] = vddc;
-                                       pi->vddc_leakage.leakage_id[pi->vddc_leakage.count] = virtual_voltage_id;
-                                       pi->vddc_leakage.count++;
-                               }
-                               if (vddci != 0 && vddci != virtual_voltage_id) {
-                                       pi->vddci_leakage.actual_voltage[pi->vddci_leakage.count] = vddci;
-                                       pi->vddci_leakage.leakage_id[pi->vddci_leakage.count] = virtual_voltage_id;
-                                       pi->vddci_leakage.count++;
-                               }
-                       }
-               }
-       }
-}
-
-static void ci_set_dpm_event_sources(struct amdgpu_device *adev, u32 sources)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       bool want_thermal_protection;
-       enum amdgpu_dpm_event_src dpm_event_src;
-       u32 tmp;
-
-       switch (sources) {
-       case 0:
-       default:
-               want_thermal_protection = false;
-               break;
-       case (1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL):
-               want_thermal_protection = true;
-               dpm_event_src = AMDGPU_DPM_EVENT_SRC_DIGITAL;
-               break;
-       case (1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL):
-               want_thermal_protection = true;
-               dpm_event_src = AMDGPU_DPM_EVENT_SRC_EXTERNAL;
-               break;
-       case ((1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL) |
-             (1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL)):
-               want_thermal_protection = true;
-               dpm_event_src = AMDGPU_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL;
-               break;
-       }
-
-       if (want_thermal_protection) {
-#if 0
-               /* XXX: need to figure out how to handle this properly */
-               tmp = RREG32_SMC(ixCG_THERMAL_CTRL);
-               tmp &= DPM_EVENT_SRC_MASK;
-               tmp |= DPM_EVENT_SRC(dpm_event_src);
-               WREG32_SMC(ixCG_THERMAL_CTRL, tmp);
-#endif
-
-               tmp = RREG32_SMC(ixGENERAL_PWRMGT);
-               if (pi->thermal_protection)
-                       tmp &= ~GENERAL_PWRMGT__THERMAL_PROTECTION_DIS_MASK;
-               else
-                       tmp |= GENERAL_PWRMGT__THERMAL_PROTECTION_DIS_MASK;
-               WREG32_SMC(ixGENERAL_PWRMGT, tmp);
-       } else {
-               tmp = RREG32_SMC(ixGENERAL_PWRMGT);
-               tmp |= GENERAL_PWRMGT__THERMAL_PROTECTION_DIS_MASK;
-               WREG32_SMC(ixGENERAL_PWRMGT, tmp);
-       }
-}
-
-static void ci_enable_auto_throttle_source(struct amdgpu_device *adev,
-                                          enum amdgpu_dpm_auto_throttle_src source,
-                                          bool enable)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       if (enable) {
-               if (!(pi->active_auto_throttle_sources & (1 << source))) {
-                       pi->active_auto_throttle_sources |= 1 << source;
-                       ci_set_dpm_event_sources(adev, pi->active_auto_throttle_sources);
-               }
-       } else {
-               if (pi->active_auto_throttle_sources & (1 << source)) {
-                       pi->active_auto_throttle_sources &= ~(1 << source);
-                       ci_set_dpm_event_sources(adev, pi->active_auto_throttle_sources);
-               }
-       }
-}
-
-static void ci_enable_vr_hot_gpio_interrupt(struct amdgpu_device *adev)
-{
-       if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT)
-               amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_EnableVRHotGPIOInterrupt);
-}
-
-static int ci_unfreeze_sclk_mclk_dpm(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       PPSMC_Result smc_result;
-
-       if (!pi->need_update_smu7_dpm_table)
-               return 0;
-
-       if ((!pi->sclk_dpm_key_disabled) &&
-           (pi->need_update_smu7_dpm_table & (DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_UPDATE_SCLK))) {
-               smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_SCLKDPM_UnfreezeLevel);
-               if (smc_result != PPSMC_Result_OK)
-                       return -EINVAL;
-       }
-
-       if ((!pi->mclk_dpm_key_disabled) &&
-           (pi->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) {
-               smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_MCLKDPM_UnfreezeLevel);
-               if (smc_result != PPSMC_Result_OK)
-                       return -EINVAL;
-       }
-
-       pi->need_update_smu7_dpm_table = 0;
-       return 0;
-}
-
-static int ci_enable_sclk_mclk_dpm(struct amdgpu_device *adev, bool enable)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       PPSMC_Result smc_result;
-
-       if (enable) {
-               if (!pi->sclk_dpm_key_disabled) {
-                       smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_DPM_Enable);
-                       if (smc_result != PPSMC_Result_OK)
-                               return -EINVAL;
-               }
-
-               if (!pi->mclk_dpm_key_disabled) {
-                       smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_MCLKDPM_Enable);
-                       if (smc_result != PPSMC_Result_OK)
-                               return -EINVAL;
-
-                       WREG32_P(mmMC_SEQ_CNTL_3, MC_SEQ_CNTL_3__CAC_EN_MASK,
-                                       ~MC_SEQ_CNTL_3__CAC_EN_MASK);
-
-                       WREG32_SMC(ixLCAC_MC0_CNTL, 0x05);
-                       WREG32_SMC(ixLCAC_MC1_CNTL, 0x05);
-                       WREG32_SMC(ixLCAC_CPL_CNTL, 0x100005);
-
-                       udelay(10);
-
-                       WREG32_SMC(ixLCAC_MC0_CNTL, 0x400005);
-                       WREG32_SMC(ixLCAC_MC1_CNTL, 0x400005);
-                       WREG32_SMC(ixLCAC_CPL_CNTL, 0x500005);
-               }
-       } else {
-               if (!pi->sclk_dpm_key_disabled) {
-                       smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_DPM_Disable);
-                       if (smc_result != PPSMC_Result_OK)
-                               return -EINVAL;
-               }
-
-               if (!pi->mclk_dpm_key_disabled) {
-                       smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_MCLKDPM_Disable);
-                       if (smc_result != PPSMC_Result_OK)
-                               return -EINVAL;
-               }
-       }
-
-       return 0;
-}
-
-static int ci_start_dpm(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       PPSMC_Result smc_result;
-       int ret;
-       u32 tmp;
-
-       tmp = RREG32_SMC(ixGENERAL_PWRMGT);
-       tmp |= GENERAL_PWRMGT__GLOBAL_PWRMGT_EN_MASK;
-       WREG32_SMC(ixGENERAL_PWRMGT, tmp);
-
-       tmp = RREG32_SMC(ixSCLK_PWRMGT_CNTL);
-       tmp |= SCLK_PWRMGT_CNTL__DYNAMIC_PM_EN_MASK;
-       WREG32_SMC(ixSCLK_PWRMGT_CNTL, tmp);
-
-       ci_write_smc_soft_register(adev, offsetof(SMU7_SoftRegisters, VoltageChangeTimeout), 0x1000);
-
-       WREG32_P(mmBIF_LNCNT_RESET, 0, ~BIF_LNCNT_RESET__RESET_LNCNT_EN_MASK);
-
-       smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_Voltage_Cntl_Enable);
-       if (smc_result != PPSMC_Result_OK)
-               return -EINVAL;
-
-       ret = ci_enable_sclk_mclk_dpm(adev, true);
-       if (ret)
-               return ret;
-
-       if (!pi->pcie_dpm_key_disabled) {
-               smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_PCIeDPM_Enable);
-               if (smc_result != PPSMC_Result_OK)
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int ci_freeze_sclk_mclk_dpm(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       PPSMC_Result smc_result;
-
-       if (!pi->need_update_smu7_dpm_table)
-               return 0;
-
-       if ((!pi->sclk_dpm_key_disabled) &&
-           (pi->need_update_smu7_dpm_table & (DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_UPDATE_SCLK))) {
-               smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_SCLKDPM_FreezeLevel);
-               if (smc_result != PPSMC_Result_OK)
-                       return -EINVAL;
-       }
-
-       if ((!pi->mclk_dpm_key_disabled) &&
-           (pi->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) {
-               smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_MCLKDPM_FreezeLevel);
-               if (smc_result != PPSMC_Result_OK)
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int ci_stop_dpm(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       PPSMC_Result smc_result;
-       int ret;
-       u32 tmp;
-
-       tmp = RREG32_SMC(ixGENERAL_PWRMGT);
-       tmp &= ~GENERAL_PWRMGT__GLOBAL_PWRMGT_EN_MASK;
-       WREG32_SMC(ixGENERAL_PWRMGT, tmp);
-
-       tmp = RREG32_SMC(ixSCLK_PWRMGT_CNTL);
-       tmp &= ~SCLK_PWRMGT_CNTL__DYNAMIC_PM_EN_MASK;
-       WREG32_SMC(ixSCLK_PWRMGT_CNTL, tmp);
-
-       if (!pi->pcie_dpm_key_disabled) {
-               smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_PCIeDPM_Disable);
-               if (smc_result != PPSMC_Result_OK)
-                       return -EINVAL;
-       }
-
-       ret = ci_enable_sclk_mclk_dpm(adev, false);
-       if (ret)
-               return ret;
-
-       smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_Voltage_Cntl_Disable);
-       if (smc_result != PPSMC_Result_OK)
-               return -EINVAL;
-
-       return 0;
-}
-
-static void ci_enable_sclk_control(struct amdgpu_device *adev, bool enable)
-{
-       u32 tmp = RREG32_SMC(ixSCLK_PWRMGT_CNTL);
-
-       if (enable)
-               tmp &= ~SCLK_PWRMGT_CNTL__SCLK_PWRMGT_OFF_MASK;
-       else
-               tmp |= SCLK_PWRMGT_CNTL__SCLK_PWRMGT_OFF_MASK;
-       WREG32_SMC(ixSCLK_PWRMGT_CNTL, tmp);
-}
-
-#if 0
-static int ci_notify_hw_of_power_source(struct amdgpu_device *adev,
-                                       bool ac_power)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct amdgpu_cac_tdp_table *cac_tdp_table =
-               adev->pm.dpm.dyn_state.cac_tdp_table;
-       u32 power_limit;
-
-       if (ac_power)
-               power_limit = (u32)(cac_tdp_table->maximum_power_delivery_limit * 256);
-       else
-               power_limit = (u32)(cac_tdp_table->battery_power_limit * 256);
-
-       ci_set_power_limit(adev, power_limit);
-
-       if (pi->caps_automatic_dc_transition) {
-               if (ac_power)
-                       amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_RunningOnAC);
-               else
-                       amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_Remove_DC_Clamp);
-       }
-
-       return 0;
-}
-#endif
-
-static PPSMC_Result amdgpu_ci_send_msg_to_smc_with_parameter(struct amdgpu_device *adev,
-                                                     PPSMC_Msg msg, u32 parameter)
-{
-       WREG32(mmSMC_MSG_ARG_0, parameter);
-       return amdgpu_ci_send_msg_to_smc(adev, msg);
-}
-
-static PPSMC_Result amdgpu_ci_send_msg_to_smc_return_parameter(struct amdgpu_device *adev,
-                                                       PPSMC_Msg msg, u32 *parameter)
-{
-       PPSMC_Result smc_result;
-
-       smc_result = amdgpu_ci_send_msg_to_smc(adev, msg);
-
-       if ((smc_result == PPSMC_Result_OK) && parameter)
-               *parameter = RREG32(mmSMC_MSG_ARG_0);
-
-       return smc_result;
-}
-
-static int ci_dpm_force_state_sclk(struct amdgpu_device *adev, u32 n)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       if (!pi->sclk_dpm_key_disabled) {
-               PPSMC_Result smc_result =
-                       amdgpu_ci_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SCLKDPM_SetEnabledMask, 1 << n);
-               if (smc_result != PPSMC_Result_OK)
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int ci_dpm_force_state_mclk(struct amdgpu_device *adev, u32 n)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       if (!pi->mclk_dpm_key_disabled) {
-               PPSMC_Result smc_result =
-                       amdgpu_ci_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_MCLKDPM_SetEnabledMask, 1 << n);
-               if (smc_result != PPSMC_Result_OK)
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int ci_dpm_force_state_pcie(struct amdgpu_device *adev, u32 n)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       if (!pi->pcie_dpm_key_disabled) {
-               PPSMC_Result smc_result =
-                       amdgpu_ci_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_PCIeDPM_ForceLevel, n);
-               if (smc_result != PPSMC_Result_OK)
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int ci_set_power_limit(struct amdgpu_device *adev, u32 n)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       if (pi->power_containment_features & POWERCONTAINMENT_FEATURE_PkgPwrLimit) {
-               PPSMC_Result smc_result =
-                       amdgpu_ci_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_PkgPwrSetLimit, n);
-               if (smc_result != PPSMC_Result_OK)
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int ci_set_overdrive_target_tdp(struct amdgpu_device *adev,
-                                      u32 target_tdp)
-{
-       PPSMC_Result smc_result =
-               amdgpu_ci_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_OverDriveSetTargetTdp, target_tdp);
-       if (smc_result != PPSMC_Result_OK)
-               return -EINVAL;
-       return 0;
-}
-
-#if 0
-static int ci_set_boot_state(struct amdgpu_device *adev)
-{
-       return ci_enable_sclk_mclk_dpm(adev, false);
-}
-#endif
-
-static u32 ci_get_average_sclk_freq(struct amdgpu_device *adev)
-{
-       u32 sclk_freq;
-       PPSMC_Result smc_result =
-               amdgpu_ci_send_msg_to_smc_return_parameter(adev,
-                                                   PPSMC_MSG_API_GetSclkFrequency,
-                                                   &sclk_freq);
-       if (smc_result != PPSMC_Result_OK)
-               sclk_freq = 0;
-
-       return sclk_freq;
-}
-
-static u32 ci_get_average_mclk_freq(struct amdgpu_device *adev)
-{
-       u32 mclk_freq;
-       PPSMC_Result smc_result =
-               amdgpu_ci_send_msg_to_smc_return_parameter(adev,
-                                                   PPSMC_MSG_API_GetMclkFrequency,
-                                                   &mclk_freq);
-       if (smc_result != PPSMC_Result_OK)
-               mclk_freq = 0;
-
-       return mclk_freq;
-}
-
-static void ci_dpm_start_smc(struct amdgpu_device *adev)
-{
-       int i;
-
-       amdgpu_ci_program_jump_on_start(adev);
-       amdgpu_ci_start_smc_clock(adev);
-       amdgpu_ci_start_smc(adev);
-       for (i = 0; i < adev->usec_timeout; i++) {
-               if (RREG32_SMC(ixFIRMWARE_FLAGS) & FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK)
-                       break;
-       }
-}
-
-static void ci_dpm_stop_smc(struct amdgpu_device *adev)
-{
-       amdgpu_ci_reset_smc(adev);
-       amdgpu_ci_stop_smc_clock(adev);
-}
-
-static int ci_process_firmware_header(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u32 tmp;
-       int ret;
-
-       ret = amdgpu_ci_read_smc_sram_dword(adev,
-                                    SMU7_FIRMWARE_HEADER_LOCATION +
-                                    offsetof(SMU7_Firmware_Header, DpmTable),
-                                    &tmp, pi->sram_end);
-       if (ret)
-               return ret;
-
-       pi->dpm_table_start = tmp;
-
-       ret = amdgpu_ci_read_smc_sram_dword(adev,
-                                    SMU7_FIRMWARE_HEADER_LOCATION +
-                                    offsetof(SMU7_Firmware_Header, SoftRegisters),
-                                    &tmp, pi->sram_end);
-       if (ret)
-               return ret;
-
-       pi->soft_regs_start = tmp;
-
-       ret = amdgpu_ci_read_smc_sram_dword(adev,
-                                    SMU7_FIRMWARE_HEADER_LOCATION +
-                                    offsetof(SMU7_Firmware_Header, mcRegisterTable),
-                                    &tmp, pi->sram_end);
-       if (ret)
-               return ret;
-
-       pi->mc_reg_table_start = tmp;
-
-       ret = amdgpu_ci_read_smc_sram_dword(adev,
-                                    SMU7_FIRMWARE_HEADER_LOCATION +
-                                    offsetof(SMU7_Firmware_Header, FanTable),
-                                    &tmp, pi->sram_end);
-       if (ret)
-               return ret;
-
-       pi->fan_table_start = tmp;
-
-       ret = amdgpu_ci_read_smc_sram_dword(adev,
-                                    SMU7_FIRMWARE_HEADER_LOCATION +
-                                    offsetof(SMU7_Firmware_Header, mcArbDramTimingTable),
-                                    &tmp, pi->sram_end);
-       if (ret)
-               return ret;
-
-       pi->arb_table_start = tmp;
-
-       return 0;
-}
-
-static void ci_read_clock_registers(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       pi->clock_registers.cg_spll_func_cntl =
-               RREG32_SMC(ixCG_SPLL_FUNC_CNTL);
-       pi->clock_registers.cg_spll_func_cntl_2 =
-               RREG32_SMC(ixCG_SPLL_FUNC_CNTL_2);
-       pi->clock_registers.cg_spll_func_cntl_3 =
-               RREG32_SMC(ixCG_SPLL_FUNC_CNTL_3);
-       pi->clock_registers.cg_spll_func_cntl_4 =
-               RREG32_SMC(ixCG_SPLL_FUNC_CNTL_4);
-       pi->clock_registers.cg_spll_spread_spectrum =
-               RREG32_SMC(ixCG_SPLL_SPREAD_SPECTRUM);
-       pi->clock_registers.cg_spll_spread_spectrum_2 =
-               RREG32_SMC(ixCG_SPLL_SPREAD_SPECTRUM_2);
-       pi->clock_registers.dll_cntl = RREG32(mmDLL_CNTL);
-       pi->clock_registers.mclk_pwrmgt_cntl = RREG32(mmMCLK_PWRMGT_CNTL);
-       pi->clock_registers.mpll_ad_func_cntl = RREG32(mmMPLL_AD_FUNC_CNTL);
-       pi->clock_registers.mpll_dq_func_cntl = RREG32(mmMPLL_DQ_FUNC_CNTL);
-       pi->clock_registers.mpll_func_cntl = RREG32(mmMPLL_FUNC_CNTL);
-       pi->clock_registers.mpll_func_cntl_1 = RREG32(mmMPLL_FUNC_CNTL_1);
-       pi->clock_registers.mpll_func_cntl_2 = RREG32(mmMPLL_FUNC_CNTL_2);
-       pi->clock_registers.mpll_ss1 = RREG32(mmMPLL_SS1);
-       pi->clock_registers.mpll_ss2 = RREG32(mmMPLL_SS2);
-}
-
-static void ci_init_sclk_t(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       pi->low_sclk_interrupt_t = 0;
-}
-
-static void ci_enable_thermal_protection(struct amdgpu_device *adev,
-                                        bool enable)
-{
-       u32 tmp = RREG32_SMC(ixGENERAL_PWRMGT);
-
-       if (enable)
-               tmp &= ~GENERAL_PWRMGT__THERMAL_PROTECTION_DIS_MASK;
-       else
-               tmp |= GENERAL_PWRMGT__THERMAL_PROTECTION_DIS_MASK;
-       WREG32_SMC(ixGENERAL_PWRMGT, tmp);
-}
-
-static void ci_enable_acpi_power_management(struct amdgpu_device *adev)
-{
-       u32 tmp = RREG32_SMC(ixGENERAL_PWRMGT);
-
-       tmp |= GENERAL_PWRMGT__STATIC_PM_EN_MASK;
-
-       WREG32_SMC(ixGENERAL_PWRMGT, tmp);
-}
-
-#if 0
-static int ci_enter_ulp_state(struct amdgpu_device *adev)
-{
-
-       WREG32(mmSMC_MESSAGE_0, PPSMC_MSG_SwitchToMinimumPower);
-
-       udelay(25000);
-
-       return 0;
-}
-
-static int ci_exit_ulp_state(struct amdgpu_device *adev)
-{
-       int i;
-
-       WREG32(mmSMC_MESSAGE_0, PPSMC_MSG_ResumeFromMinimumPower);
-
-       udelay(7000);
-
-       for (i = 0; i < adev->usec_timeout; i++) {
-               if (RREG32(mmSMC_RESP_0) == 1)
-                       break;
-               udelay(1000);
-       }
-
-       return 0;
-}
-#endif
-
-static int ci_notify_smc_display_change(struct amdgpu_device *adev,
-                                       bool has_display)
-{
-       PPSMC_Msg msg = has_display ? PPSMC_MSG_HasDisplay : PPSMC_MSG_NoDisplay;
-
-       return (amdgpu_ci_send_msg_to_smc(adev, msg) == PPSMC_Result_OK) ?  0 : -EINVAL;
-}
-
-static int ci_enable_ds_master_switch(struct amdgpu_device *adev,
-                                     bool enable)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       if (enable) {
-               if (pi->caps_sclk_ds) {
-                       if (amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_MASTER_DeepSleep_ON) != PPSMC_Result_OK)
-                               return -EINVAL;
-               } else {
-                       if (amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_MASTER_DeepSleep_OFF) != PPSMC_Result_OK)
-                               return -EINVAL;
-               }
-       } else {
-               if (pi->caps_sclk_ds) {
-                       if (amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_MASTER_DeepSleep_OFF) != PPSMC_Result_OK)
-                               return -EINVAL;
-               }
-       }
-
-       return 0;
-}
-
-static void ci_program_display_gap(struct amdgpu_device *adev)
-{
-       u32 tmp = RREG32_SMC(ixCG_DISPLAY_GAP_CNTL);
-       u32 pre_vbi_time_in_us;
-       u32 frame_time_in_us;
-       u32 ref_clock = adev->clock.spll.reference_freq;
-       u32 refresh_rate = amdgpu_dpm_get_vrefresh(adev);
-       u32 vblank_time = amdgpu_dpm_get_vblank_time(adev);
-
-       tmp &= ~CG_DISPLAY_GAP_CNTL__DISP_GAP_MASK;
-       if (adev->pm.dpm.new_active_crtc_count > 0)
-               tmp |= (AMDGPU_PM_DISPLAY_GAP_VBLANK_OR_WM << CG_DISPLAY_GAP_CNTL__DISP_GAP__SHIFT);
-       else
-               tmp |= (AMDGPU_PM_DISPLAY_GAP_IGNORE << CG_DISPLAY_GAP_CNTL__DISP_GAP__SHIFT);
-       WREG32_SMC(ixCG_DISPLAY_GAP_CNTL, tmp);
-
-       if (refresh_rate == 0)
-               refresh_rate = 60;
-       if (vblank_time == 0xffffffff)
-               vblank_time = 500;
-       frame_time_in_us = 1000000 / refresh_rate;
-       pre_vbi_time_in_us =
-               frame_time_in_us - 200 - vblank_time;
-       tmp = pre_vbi_time_in_us * (ref_clock / 100);
-
-       WREG32_SMC(ixCG_DISPLAY_GAP_CNTL2, tmp);
-       ci_write_smc_soft_register(adev, offsetof(SMU7_SoftRegisters, PreVBlankGap), 0x64);
-       ci_write_smc_soft_register(adev, offsetof(SMU7_SoftRegisters, VBlankTimeout), (frame_time_in_us - pre_vbi_time_in_us));
-
-
-       ci_notify_smc_display_change(adev, (adev->pm.dpm.new_active_crtc_count == 1));
-
-}
-
-static void ci_enable_spread_spectrum(struct amdgpu_device *adev, bool enable)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u32 tmp;
-
-       if (enable) {
-               if (pi->caps_sclk_ss_support) {
-                       tmp = RREG32_SMC(ixGENERAL_PWRMGT);
-                       tmp |= GENERAL_PWRMGT__DYN_SPREAD_SPECTRUM_EN_MASK;
-                       WREG32_SMC(ixGENERAL_PWRMGT, tmp);
-               }
-       } else {
-               tmp = RREG32_SMC(ixCG_SPLL_SPREAD_SPECTRUM);
-               tmp &= ~CG_SPLL_SPREAD_SPECTRUM__SSEN_MASK;
-               WREG32_SMC(ixCG_SPLL_SPREAD_SPECTRUM, tmp);
-
-               tmp = RREG32_SMC(ixGENERAL_PWRMGT);
-               tmp &= ~GENERAL_PWRMGT__DYN_SPREAD_SPECTRUM_EN_MASK;
-               WREG32_SMC(ixGENERAL_PWRMGT, tmp);
-       }
-}
-
-static void ci_program_sstp(struct amdgpu_device *adev)
-{
-       WREG32_SMC(ixCG_STATIC_SCREEN_PARAMETER,
-       ((CISLANDS_SSTU_DFLT << CG_STATIC_SCREEN_PARAMETER__STATIC_SCREEN_THRESHOLD_UNIT__SHIFT) |
-        (CISLANDS_SST_DFLT << CG_STATIC_SCREEN_PARAMETER__STATIC_SCREEN_THRESHOLD__SHIFT)));
-}
-
-static void ci_enable_display_gap(struct amdgpu_device *adev)
-{
-       u32 tmp = RREG32_SMC(ixCG_DISPLAY_GAP_CNTL);
-
-       tmp &= ~(CG_DISPLAY_GAP_CNTL__DISP_GAP_MASK |
-                       CG_DISPLAY_GAP_CNTL__DISP_GAP_MCHG_MASK);
-       tmp |= ((AMDGPU_PM_DISPLAY_GAP_IGNORE << CG_DISPLAY_GAP_CNTL__DISP_GAP__SHIFT) |
-               (AMDGPU_PM_DISPLAY_GAP_VBLANK << CG_DISPLAY_GAP_CNTL__DISP_GAP_MCHG__SHIFT));
-
-       WREG32_SMC(ixCG_DISPLAY_GAP_CNTL, tmp);
-}
-
-static void ci_program_vc(struct amdgpu_device *adev)
-{
-       u32 tmp;
-
-       tmp = RREG32_SMC(ixSCLK_PWRMGT_CNTL);
-       tmp &= ~(SCLK_PWRMGT_CNTL__RESET_SCLK_CNT_MASK | SCLK_PWRMGT_CNTL__RESET_BUSY_CNT_MASK);
-       WREG32_SMC(ixSCLK_PWRMGT_CNTL, tmp);
-
-       WREG32_SMC(ixCG_FREQ_TRAN_VOTING_0, CISLANDS_VRC_DFLT0);
-       WREG32_SMC(ixCG_FREQ_TRAN_VOTING_1, CISLANDS_VRC_DFLT1);
-       WREG32_SMC(ixCG_FREQ_TRAN_VOTING_2, CISLANDS_VRC_DFLT2);
-       WREG32_SMC(ixCG_FREQ_TRAN_VOTING_3, CISLANDS_VRC_DFLT3);
-       WREG32_SMC(ixCG_FREQ_TRAN_VOTING_4, CISLANDS_VRC_DFLT4);
-       WREG32_SMC(ixCG_FREQ_TRAN_VOTING_5, CISLANDS_VRC_DFLT5);
-       WREG32_SMC(ixCG_FREQ_TRAN_VOTING_6, CISLANDS_VRC_DFLT6);
-       WREG32_SMC(ixCG_FREQ_TRAN_VOTING_7, CISLANDS_VRC_DFLT7);
-}
-
-static void ci_clear_vc(struct amdgpu_device *adev)
-{
-       u32 tmp;
-
-       tmp = RREG32_SMC(ixSCLK_PWRMGT_CNTL);
-       tmp |= (SCLK_PWRMGT_CNTL__RESET_SCLK_CNT_MASK | SCLK_PWRMGT_CNTL__RESET_BUSY_CNT_MASK);
-       WREG32_SMC(ixSCLK_PWRMGT_CNTL, tmp);
-
-       WREG32_SMC(ixCG_FREQ_TRAN_VOTING_0, 0);
-       WREG32_SMC(ixCG_FREQ_TRAN_VOTING_1, 0);
-       WREG32_SMC(ixCG_FREQ_TRAN_VOTING_2, 0);
-       WREG32_SMC(ixCG_FREQ_TRAN_VOTING_3, 0);
-       WREG32_SMC(ixCG_FREQ_TRAN_VOTING_4, 0);
-       WREG32_SMC(ixCG_FREQ_TRAN_VOTING_5, 0);
-       WREG32_SMC(ixCG_FREQ_TRAN_VOTING_6, 0);
-       WREG32_SMC(ixCG_FREQ_TRAN_VOTING_7, 0);
-}
-
-static int ci_upload_firmware(struct amdgpu_device *adev)
-{
-       int i, ret;
-
-       if (amdgpu_ci_is_smc_running(adev)) {
-               DRM_INFO("smc is running, no need to load smc firmware\n");
-               return 0;
-       }
-
-       for (i = 0; i < adev->usec_timeout; i++) {
-               if (RREG32_SMC(ixRCU_UC_EVENTS) & RCU_UC_EVENTS__boot_seq_done_MASK)
-                       break;
-       }
-       WREG32_SMC(ixSMC_SYSCON_MISC_CNTL, 1);
-
-       amdgpu_ci_stop_smc_clock(adev);
-       amdgpu_ci_reset_smc(adev);
-
-       ret = amdgpu_ci_load_smc_ucode(adev, SMC_RAM_END);
-
-       return ret;
-
-}
-
-static int ci_get_svi2_voltage_table(struct amdgpu_device *adev,
-                                    struct amdgpu_clock_voltage_dependency_table *voltage_dependency_table,
-                                    struct atom_voltage_table *voltage_table)
-{
-       u32 i;
-
-       if (voltage_dependency_table == NULL)
-               return -EINVAL;
-
-       voltage_table->mask_low = 0;
-       voltage_table->phase_delay = 0;
-
-       voltage_table->count = voltage_dependency_table->count;
-       for (i = 0; i < voltage_table->count; i++) {
-               voltage_table->entries[i].value = voltage_dependency_table->entries[i].v;
-               voltage_table->entries[i].smio_low = 0;
-       }
-
-       return 0;
-}
-
-static int ci_construct_voltage_tables(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       int ret;
-
-       if (pi->voltage_control == CISLANDS_VOLTAGE_CONTROL_BY_GPIO) {
-               ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_VDDC,
-                                                       VOLTAGE_OBJ_GPIO_LUT,
-                                                       &pi->vddc_voltage_table);
-               if (ret)
-                       return ret;
-       } else if (pi->voltage_control == CISLANDS_VOLTAGE_CONTROL_BY_SVID2) {
-               ret = ci_get_svi2_voltage_table(adev,
-                                               &adev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
-                                               &pi->vddc_voltage_table);
-               if (ret)
-                       return ret;
-       }
-
-       if (pi->vddc_voltage_table.count > SMU7_MAX_LEVELS_VDDC)
-               ci_trim_voltage_table_to_fit_state_table(adev, SMU7_MAX_LEVELS_VDDC,
-                                                        &pi->vddc_voltage_table);
-
-       if (pi->vddci_control == CISLANDS_VOLTAGE_CONTROL_BY_GPIO) {
-               ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_VDDCI,
-                                                       VOLTAGE_OBJ_GPIO_LUT,
-                                                       &pi->vddci_voltage_table);
-               if (ret)
-                       return ret;
-       } else if (pi->vddci_control == CISLANDS_VOLTAGE_CONTROL_BY_SVID2) {
-               ret = ci_get_svi2_voltage_table(adev,
-                                               &adev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
-                                               &pi->vddci_voltage_table);
-               if (ret)
-                       return ret;
-       }
-
-       if (pi->vddci_voltage_table.count > SMU7_MAX_LEVELS_VDDCI)
-               ci_trim_voltage_table_to_fit_state_table(adev, SMU7_MAX_LEVELS_VDDCI,
-                                                        &pi->vddci_voltage_table);
-
-       if (pi->mvdd_control == CISLANDS_VOLTAGE_CONTROL_BY_GPIO) {
-               ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_MVDDC,
-                                                       VOLTAGE_OBJ_GPIO_LUT,
-                                                       &pi->mvdd_voltage_table);
-               if (ret)
-                       return ret;
-       } else if (pi->mvdd_control == CISLANDS_VOLTAGE_CONTROL_BY_SVID2) {
-               ret = ci_get_svi2_voltage_table(adev,
-                                               &adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk,
-                                               &pi->mvdd_voltage_table);
-               if (ret)
-                       return ret;
-       }
-
-       if (pi->mvdd_voltage_table.count > SMU7_MAX_LEVELS_MVDD)
-               ci_trim_voltage_table_to_fit_state_table(adev, SMU7_MAX_LEVELS_MVDD,
-                                                        &pi->mvdd_voltage_table);
-
-       return 0;
-}
-
-static void ci_populate_smc_voltage_table(struct amdgpu_device *adev,
-                                         struct atom_voltage_table_entry *voltage_table,
-                                         SMU7_Discrete_VoltageLevel *smc_voltage_table)
-{
-       int ret;
-
-       ret = ci_get_std_voltage_value_sidd(adev, voltage_table,
-                                           &smc_voltage_table->StdVoltageHiSidd,
-                                           &smc_voltage_table->StdVoltageLoSidd);
-
-       if (ret) {
-               smc_voltage_table->StdVoltageHiSidd = voltage_table->value * VOLTAGE_SCALE;
-               smc_voltage_table->StdVoltageLoSidd = voltage_table->value * VOLTAGE_SCALE;
-       }
-
-       smc_voltage_table->Voltage = cpu_to_be16(voltage_table->value * VOLTAGE_SCALE);
-       smc_voltage_table->StdVoltageHiSidd =
-               cpu_to_be16(smc_voltage_table->StdVoltageHiSidd);
-       smc_voltage_table->StdVoltageLoSidd =
-               cpu_to_be16(smc_voltage_table->StdVoltageLoSidd);
-}
-
-static int ci_populate_smc_vddc_table(struct amdgpu_device *adev,
-                                     SMU7_Discrete_DpmTable *table)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       unsigned int count;
-
-       table->VddcLevelCount = pi->vddc_voltage_table.count;
-       for (count = 0; count < table->VddcLevelCount; count++) {
-               ci_populate_smc_voltage_table(adev,
-                                             &pi->vddc_voltage_table.entries[count],
-                                             &table->VddcLevel[count]);
-
-               if (pi->voltage_control == CISLANDS_VOLTAGE_CONTROL_BY_GPIO)
-                       table->VddcLevel[count].Smio |=
-                               pi->vddc_voltage_table.entries[count].smio_low;
-               else
-                       table->VddcLevel[count].Smio = 0;
-       }
-       table->VddcLevelCount = cpu_to_be32(table->VddcLevelCount);
-
-       return 0;
-}
-
-static int ci_populate_smc_vddci_table(struct amdgpu_device *adev,
-                                      SMU7_Discrete_DpmTable *table)
-{
-       unsigned int count;
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       table->VddciLevelCount = pi->vddci_voltage_table.count;
-       for (count = 0; count < table->VddciLevelCount; count++) {
-               ci_populate_smc_voltage_table(adev,
-                                             &pi->vddci_voltage_table.entries[count],
-                                             &table->VddciLevel[count]);
-
-               if (pi->vddci_control == CISLANDS_VOLTAGE_CONTROL_BY_GPIO)
-                       table->VddciLevel[count].Smio |=
-                               pi->vddci_voltage_table.entries[count].smio_low;
-               else
-                       table->VddciLevel[count].Smio = 0;
-       }
-       table->VddciLevelCount = cpu_to_be32(table->VddciLevelCount);
-
-       return 0;
-}
-
-static int ci_populate_smc_mvdd_table(struct amdgpu_device *adev,
-                                     SMU7_Discrete_DpmTable *table)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       unsigned int count;
-
-       table->MvddLevelCount = pi->mvdd_voltage_table.count;
-       for (count = 0; count < table->MvddLevelCount; count++) {
-               ci_populate_smc_voltage_table(adev,
-                                             &pi->mvdd_voltage_table.entries[count],
-                                             &table->MvddLevel[count]);
-
-               if (pi->mvdd_control == CISLANDS_VOLTAGE_CONTROL_BY_GPIO)
-                       table->MvddLevel[count].Smio |=
-                               pi->mvdd_voltage_table.entries[count].smio_low;
-               else
-                       table->MvddLevel[count].Smio = 0;
-       }
-       table->MvddLevelCount = cpu_to_be32(table->MvddLevelCount);
-
-       return 0;
-}
-
-static int ci_populate_smc_voltage_tables(struct amdgpu_device *adev,
-                                         SMU7_Discrete_DpmTable *table)
-{
-       int ret;
-
-       ret = ci_populate_smc_vddc_table(adev, table);
-       if (ret)
-               return ret;
-
-       ret = ci_populate_smc_vddci_table(adev, table);
-       if (ret)
-               return ret;
-
-       ret = ci_populate_smc_mvdd_table(adev, table);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
-static int ci_populate_mvdd_value(struct amdgpu_device *adev, u32 mclk,
-                                 SMU7_Discrete_VoltageLevel *voltage)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u32 i = 0;
-
-       if (pi->mvdd_control != CISLANDS_VOLTAGE_CONTROL_NONE) {
-               for (i = 0; i < adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.count; i++) {
-                       if (mclk <= adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries[i].clk) {
-                               voltage->Voltage = pi->mvdd_voltage_table.entries[i].value;
-                               break;
-                       }
-               }
-
-               if (i >= adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.count)
-                       return -EINVAL;
-       }
-
-       return -EINVAL;
-}
-
-static int ci_get_std_voltage_value_sidd(struct amdgpu_device *adev,
-                                        struct atom_voltage_table_entry *voltage_table,
-                                        u16 *std_voltage_hi_sidd, u16 *std_voltage_lo_sidd)
-{
-       u16 v_index, idx;
-       bool voltage_found = false;
-       *std_voltage_hi_sidd = voltage_table->value * VOLTAGE_SCALE;
-       *std_voltage_lo_sidd = voltage_table->value * VOLTAGE_SCALE;
-
-       if (adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries == NULL)
-               return -EINVAL;
-
-       if (adev->pm.dpm.dyn_state.cac_leakage_table.entries) {
-               for (v_index = 0; (u32)v_index < adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count; v_index++) {
-                       if (voltage_table->value ==
-                           adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[v_index].v) {
-                               voltage_found = true;
-                               if ((u32)v_index < adev->pm.dpm.dyn_state.cac_leakage_table.count)
-                                       idx = v_index;
-                               else
-                                       idx = adev->pm.dpm.dyn_state.cac_leakage_table.count - 1;
-                               *std_voltage_lo_sidd =
-                                       adev->pm.dpm.dyn_state.cac_leakage_table.entries[idx].vddc * VOLTAGE_SCALE;
-                               *std_voltage_hi_sidd =
-                                       adev->pm.dpm.dyn_state.cac_leakage_table.entries[idx].leakage * VOLTAGE_SCALE;
-                               break;
-                       }
-               }
-
-               if (!voltage_found) {
-                       for (v_index = 0; (u32)v_index < adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count; v_index++) {
-                               if (voltage_table->value <=
-                                   adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[v_index].v) {
-                                       voltage_found = true;
-                                       if ((u32)v_index < adev->pm.dpm.dyn_state.cac_leakage_table.count)
-                                               idx = v_index;
-                                       else
-                                               idx = adev->pm.dpm.dyn_state.cac_leakage_table.count - 1;
-                                       *std_voltage_lo_sidd =
-                                               adev->pm.dpm.dyn_state.cac_leakage_table.entries[idx].vddc * VOLTAGE_SCALE;
-                                       *std_voltage_hi_sidd =
-                                               adev->pm.dpm.dyn_state.cac_leakage_table.entries[idx].leakage * VOLTAGE_SCALE;
-                                       break;
-                               }
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static void ci_populate_phase_value_based_on_sclk(struct amdgpu_device *adev,
-                                                 const struct amdgpu_phase_shedding_limits_table *limits,
-                                                 u32 sclk,
-                                                 u32 *phase_shedding)
-{
-       unsigned int i;
-
-       *phase_shedding = 1;
-
-       for (i = 0; i < limits->count; i++) {
-               if (sclk < limits->entries[i].sclk) {
-                       *phase_shedding = i;
-                       break;
-               }
-       }
-}
-
-static void ci_populate_phase_value_based_on_mclk(struct amdgpu_device *adev,
-                                                 const struct amdgpu_phase_shedding_limits_table *limits,
-                                                 u32 mclk,
-                                                 u32 *phase_shedding)
-{
-       unsigned int i;
-
-       *phase_shedding = 1;
-
-       for (i = 0; i < limits->count; i++) {
-               if (mclk < limits->entries[i].mclk) {
-                       *phase_shedding = i;
-                       break;
-               }
-       }
-}
-
-static int ci_init_arb_table_index(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u32 tmp;
-       int ret;
-
-       ret = amdgpu_ci_read_smc_sram_dword(adev, pi->arb_table_start,
-                                    &tmp, pi->sram_end);
-       if (ret)
-               return ret;
-
-       tmp &= 0x00FFFFFF;
-       tmp |= MC_CG_ARB_FREQ_F1 << 24;
-
-       return amdgpu_ci_write_smc_sram_dword(adev, pi->arb_table_start,
-                                      tmp, pi->sram_end);
-}
-
-static int ci_get_dependency_volt_by_clk(struct amdgpu_device *adev,
-                                        struct amdgpu_clock_voltage_dependency_table *allowed_clock_voltage_table,
-                                        u32 clock, u32 *voltage)
-{
-       u32 i = 0;
-
-       if (allowed_clock_voltage_table->count == 0)
-               return -EINVAL;
-
-       for (i = 0; i < allowed_clock_voltage_table->count; i++) {
-               if (allowed_clock_voltage_table->entries[i].clk >= clock) {
-                       *voltage = allowed_clock_voltage_table->entries[i].v;
-                       return 0;
-               }
-       }
-
-       *voltage = allowed_clock_voltage_table->entries[i-1].v;
-
-       return 0;
-}
-
-static u8 ci_get_sleep_divider_id_from_clock(u32 sclk, u32 min_sclk_in_sr)
-{
-       u32 i;
-       u32 tmp;
-       u32 min = max(min_sclk_in_sr, (u32)CISLAND_MINIMUM_ENGINE_CLOCK);
-
-       if (sclk < min)
-               return 0;
-
-       for (i = CISLAND_MAX_DEEPSLEEP_DIVIDER_ID;  ; i--) {
-               tmp = sclk >> i;
-               if (tmp >= min || i == 0)
-                       break;
-       }
-
-       return (u8)i;
-}
-
-static int ci_initial_switch_from_arb_f0_to_f1(struct amdgpu_device *adev)
-{
-       return ci_copy_and_switch_arb_sets(adev, MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1);
-}
-
-static int ci_reset_to_default(struct amdgpu_device *adev)
-{
-       return (amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_ResetToDefaults) == PPSMC_Result_OK) ?
-               0 : -EINVAL;
-}
-
-static int ci_force_switch_to_arb_f0(struct amdgpu_device *adev)
-{
-       u32 tmp;
-
-       tmp = (RREG32_SMC(ixSMC_SCRATCH9) & 0x0000ff00) >> 8;
-
-       if (tmp == MC_CG_ARB_FREQ_F0)
-               return 0;
-
-       return ci_copy_and_switch_arb_sets(adev, tmp, MC_CG_ARB_FREQ_F0);
-}
-
-static void ci_register_patching_mc_arb(struct amdgpu_device *adev,
-                                       const u32 engine_clock,
-                                       const u32 memory_clock,
-                                       u32 *dram_timimg2)
-{
-       bool patch;
-       u32 tmp, tmp2;
-
-       tmp = RREG32(mmMC_SEQ_MISC0);
-       patch = ((tmp & 0x0000f00) == 0x300) ? true : false;
-
-       if (patch &&
-           ((adev->pdev->device == 0x67B0) ||
-            (adev->pdev->device == 0x67B1))) {
-               if ((memory_clock > 100000) && (memory_clock <= 125000)) {
-                       tmp2 = (((0x31 * engine_clock) / 125000) - 1) & 0xff;
-                       *dram_timimg2 &= ~0x00ff0000;
-                       *dram_timimg2 |= tmp2 << 16;
-               } else if ((memory_clock > 125000) && (memory_clock <= 137500)) {
-                       tmp2 = (((0x36 * engine_clock) / 137500) - 1) & 0xff;
-                       *dram_timimg2 &= ~0x00ff0000;
-                       *dram_timimg2 |= tmp2 << 16;
-               }
-       }
-}
-
-static int ci_populate_memory_timing_parameters(struct amdgpu_device *adev,
-                                               u32 sclk,
-                                               u32 mclk,
-                                               SMU7_Discrete_MCArbDramTimingTableEntry *arb_regs)
-{
-       u32 dram_timing;
-       u32 dram_timing2;
-       u32 burst_time;
-
-       amdgpu_atombios_set_engine_dram_timings(adev, sclk, mclk);
-
-       dram_timing  = RREG32(mmMC_ARB_DRAM_TIMING);
-       dram_timing2 = RREG32(mmMC_ARB_DRAM_TIMING2);
-       burst_time = RREG32(mmMC_ARB_BURST_TIME) & MC_ARB_BURST_TIME__STATE0_MASK;
-
-       ci_register_patching_mc_arb(adev, sclk, mclk, &dram_timing2);
-
-       arb_regs->McArbDramTiming  = cpu_to_be32(dram_timing);
-       arb_regs->McArbDramTiming2 = cpu_to_be32(dram_timing2);
-       arb_regs->McArbBurstTime = (u8)burst_time;
-
-       return 0;
-}
-
-static int ci_do_program_memory_timing_parameters(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       SMU7_Discrete_MCArbDramTimingTable arb_regs;
-       u32 i, j;
-       int ret =  0;
-
-       memset(&arb_regs, 0, sizeof(SMU7_Discrete_MCArbDramTimingTable));
-
-       for (i = 0; i < pi->dpm_table.sclk_table.count; i++) {
-               for (j = 0; j < pi->dpm_table.mclk_table.count; j++) {
-                       ret = ci_populate_memory_timing_parameters(adev,
-                                                                  pi->dpm_table.sclk_table.dpm_levels[i].value,
-                                                                  pi->dpm_table.mclk_table.dpm_levels[j].value,
-                                                                  &arb_regs.entries[i][j]);
-                       if (ret)
-                               break;
-               }
-       }
-
-       if (ret == 0)
-               ret = amdgpu_ci_copy_bytes_to_smc(adev,
-                                          pi->arb_table_start,
-                                          (u8 *)&arb_regs,
-                                          sizeof(SMU7_Discrete_MCArbDramTimingTable),
-                                          pi->sram_end);
-
-       return ret;
-}
-
-static int ci_program_memory_timing_parameters(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       if (pi->need_update_smu7_dpm_table == 0)
-               return 0;
-
-       return ci_do_program_memory_timing_parameters(adev);
-}
-
-static void ci_populate_smc_initial_state(struct amdgpu_device *adev,
-                                         struct amdgpu_ps *amdgpu_boot_state)
-{
-       struct ci_ps *boot_state = ci_get_ps(amdgpu_boot_state);
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u32 level = 0;
-
-       for (level = 0; level < adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count; level++) {
-               if (adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[level].clk >=
-                   boot_state->performance_levels[0].sclk) {
-                       pi->smc_state_table.GraphicsBootLevel = level;
-                       break;
-               }
-       }
-
-       for (level = 0; level < adev->pm.dpm.dyn_state.vddc_dependency_on_mclk.count; level++) {
-               if (adev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries[level].clk >=
-                   boot_state->performance_levels[0].mclk) {
-                       pi->smc_state_table.MemoryBootLevel = level;
-                       break;
-               }
-       }
-}
-
-static u32 ci_get_dpm_level_enable_mask_value(struct ci_single_dpm_table *dpm_table)
-{
-       u32 i;
-       u32 mask_value = 0;
-
-       for (i = dpm_table->count; i > 0; i--) {
-               mask_value = mask_value << 1;
-               if (dpm_table->dpm_levels[i-1].enabled)
-                       mask_value |= 0x1;
-               else
-                       mask_value &= 0xFFFFFFFE;
-       }
-
-       return mask_value;
-}
-
-static void ci_populate_smc_link_level(struct amdgpu_device *adev,
-                                      SMU7_Discrete_DpmTable *table)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_dpm_table *dpm_table = &pi->dpm_table;
-       u32 i;
-
-       for (i = 0; i < dpm_table->pcie_speed_table.count; i++) {
-               table->LinkLevel[i].PcieGenSpeed =
-                       (u8)dpm_table->pcie_speed_table.dpm_levels[i].value;
-               table->LinkLevel[i].PcieLaneCount =
-                       amdgpu_encode_pci_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1);
-               table->LinkLevel[i].EnabledForActivity = 1;
-               table->LinkLevel[i].DownT = cpu_to_be32(5);
-               table->LinkLevel[i].UpT = cpu_to_be32(30);
-       }
-
-       pi->smc_state_table.LinkLevelCount = (u8)dpm_table->pcie_speed_table.count;
-       pi->dpm_level_enable_mask.pcie_dpm_enable_mask =
-               ci_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table);
-}
-
-static int ci_populate_smc_uvd_level(struct amdgpu_device *adev,
-                                    SMU7_Discrete_DpmTable *table)
-{
-       u32 count;
-       struct atom_clock_dividers dividers;
-       int ret = -EINVAL;
-
-       table->UvdLevelCount =
-               adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count;
-
-       for (count = 0; count < table->UvdLevelCount; count++) {
-               table->UvdLevel[count].VclkFrequency =
-                       adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[count].vclk;
-               table->UvdLevel[count].DclkFrequency =
-                       adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[count].dclk;
-               table->UvdLevel[count].MinVddc =
-                       adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[count].v * VOLTAGE_SCALE;
-               table->UvdLevel[count].MinVddcPhases = 1;
-
-               ret = amdgpu_atombios_get_clock_dividers(adev,
-                                                        COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
-                                                        table->UvdLevel[count].VclkFrequency, false, &dividers);
-               if (ret)
-                       return ret;
-
-               table->UvdLevel[count].VclkDivider = (u8)dividers.post_divider;
-
-               ret = amdgpu_atombios_get_clock_dividers(adev,
-                                                        COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
-                                                        table->UvdLevel[count].DclkFrequency, false, &dividers);
-               if (ret)
-                       return ret;
-
-               table->UvdLevel[count].DclkDivider = (u8)dividers.post_divider;
-
-               table->UvdLevel[count].VclkFrequency = cpu_to_be32(table->UvdLevel[count].VclkFrequency);
-               table->UvdLevel[count].DclkFrequency = cpu_to_be32(table->UvdLevel[count].DclkFrequency);
-               table->UvdLevel[count].MinVddc = cpu_to_be16(table->UvdLevel[count].MinVddc);
-       }
-
-       return ret;
-}
-
-static int ci_populate_smc_vce_level(struct amdgpu_device *adev,
-                                    SMU7_Discrete_DpmTable *table)
-{
-       u32 count;
-       struct atom_clock_dividers dividers;
-       int ret = -EINVAL;
-
-       table->VceLevelCount =
-               adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count;
-
-       for (count = 0; count < table->VceLevelCount; count++) {
-               table->VceLevel[count].Frequency =
-                       adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[count].evclk;
-               table->VceLevel[count].MinVoltage =
-                       (u16)adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[count].v * VOLTAGE_SCALE;
-               table->VceLevel[count].MinPhases = 1;
-
-               ret = amdgpu_atombios_get_clock_dividers(adev,
-                                                        COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
-                                                        table->VceLevel[count].Frequency, false, &dividers);
-               if (ret)
-                       return ret;
-
-               table->VceLevel[count].Divider = (u8)dividers.post_divider;
-
-               table->VceLevel[count].Frequency = cpu_to_be32(table->VceLevel[count].Frequency);
-               table->VceLevel[count].MinVoltage = cpu_to_be16(table->VceLevel[count].MinVoltage);
-       }
-
-       return ret;
-
-}
-
-static int ci_populate_smc_acp_level(struct amdgpu_device *adev,
-                                    SMU7_Discrete_DpmTable *table)
-{
-       u32 count;
-       struct atom_clock_dividers dividers;
-       int ret = -EINVAL;
-
-       table->AcpLevelCount = (u8)
-               (adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count);
-
-       for (count = 0; count < table->AcpLevelCount; count++) {
-               table->AcpLevel[count].Frequency =
-                       adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[count].clk;
-               table->AcpLevel[count].MinVoltage =
-                       adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[count].v;
-               table->AcpLevel[count].MinPhases = 1;
-
-               ret = amdgpu_atombios_get_clock_dividers(adev,
-                                                        COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
-                                                        table->AcpLevel[count].Frequency, false, &dividers);
-               if (ret)
-                       return ret;
-
-               table->AcpLevel[count].Divider = (u8)dividers.post_divider;
-
-               table->AcpLevel[count].Frequency = cpu_to_be32(table->AcpLevel[count].Frequency);
-               table->AcpLevel[count].MinVoltage = cpu_to_be16(table->AcpLevel[count].MinVoltage);
-       }
-
-       return ret;
-}
-
-static int ci_populate_smc_samu_level(struct amdgpu_device *adev,
-                                     SMU7_Discrete_DpmTable *table)
-{
-       u32 count;
-       struct atom_clock_dividers dividers;
-       int ret = -EINVAL;
-
-       table->SamuLevelCount =
-               adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count;
-
-       for (count = 0; count < table->SamuLevelCount; count++) {
-               table->SamuLevel[count].Frequency =
-                       adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[count].clk;
-               table->SamuLevel[count].MinVoltage =
-                       adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[count].v * VOLTAGE_SCALE;
-               table->SamuLevel[count].MinPhases = 1;
-
-               ret = amdgpu_atombios_get_clock_dividers(adev,
-                                                        COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
-                                                        table->SamuLevel[count].Frequency, false, &dividers);
-               if (ret)
-                       return ret;
-
-               table->SamuLevel[count].Divider = (u8)dividers.post_divider;
-
-               table->SamuLevel[count].Frequency = cpu_to_be32(table->SamuLevel[count].Frequency);
-               table->SamuLevel[count].MinVoltage = cpu_to_be16(table->SamuLevel[count].MinVoltage);
-       }
-
-       return ret;
-}
-
-static int ci_calculate_mclk_params(struct amdgpu_device *adev,
-                                   u32 memory_clock,
-                                   SMU7_Discrete_MemoryLevel *mclk,
-                                   bool strobe_mode,
-                                   bool dll_state_on)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u32  dll_cntl = pi->clock_registers.dll_cntl;
-       u32  mclk_pwrmgt_cntl = pi->clock_registers.mclk_pwrmgt_cntl;
-       u32  mpll_ad_func_cntl = pi->clock_registers.mpll_ad_func_cntl;
-       u32  mpll_dq_func_cntl = pi->clock_registers.mpll_dq_func_cntl;
-       u32  mpll_func_cntl = pi->clock_registers.mpll_func_cntl;
-       u32  mpll_func_cntl_1 = pi->clock_registers.mpll_func_cntl_1;
-       u32  mpll_func_cntl_2 = pi->clock_registers.mpll_func_cntl_2;
-       u32  mpll_ss1 = pi->clock_registers.mpll_ss1;
-       u32  mpll_ss2 = pi->clock_registers.mpll_ss2;
-       struct atom_mpll_param mpll_param;
-       int ret;
-
-       ret = amdgpu_atombios_get_memory_pll_dividers(adev, memory_clock, strobe_mode, &mpll_param);
-       if (ret)
-               return ret;
-
-       mpll_func_cntl &= ~MPLL_FUNC_CNTL__BWCTRL_MASK;
-       mpll_func_cntl |= (mpll_param.bwcntl << MPLL_FUNC_CNTL__BWCTRL__SHIFT);
-
-       mpll_func_cntl_1 &= ~(MPLL_FUNC_CNTL_1__CLKF_MASK | MPLL_FUNC_CNTL_1__CLKFRAC_MASK |
-                       MPLL_FUNC_CNTL_1__VCO_MODE_MASK);
-       mpll_func_cntl_1 |= (mpll_param.clkf) << MPLL_FUNC_CNTL_1__CLKF__SHIFT |
-               (mpll_param.clkfrac << MPLL_FUNC_CNTL_1__CLKFRAC__SHIFT) |
-               (mpll_param.vco_mode << MPLL_FUNC_CNTL_1__VCO_MODE__SHIFT);
-
-       mpll_ad_func_cntl &= ~MPLL_AD_FUNC_CNTL__YCLK_POST_DIV_MASK;
-       mpll_ad_func_cntl |= (mpll_param.post_div << MPLL_AD_FUNC_CNTL__YCLK_POST_DIV__SHIFT);
-
-       if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) {
-               mpll_dq_func_cntl &= ~(MPLL_DQ_FUNC_CNTL__YCLK_SEL_MASK |
-                               MPLL_AD_FUNC_CNTL__YCLK_POST_DIV_MASK);
-               mpll_dq_func_cntl |= (mpll_param.yclk_sel << MPLL_DQ_FUNC_CNTL__YCLK_SEL__SHIFT) |
-                               (mpll_param.post_div << MPLL_AD_FUNC_CNTL__YCLK_POST_DIV__SHIFT);
-       }
-
-       if (pi->caps_mclk_ss_support) {
-               struct amdgpu_atom_ss ss;
-               u32 freq_nom;
-               u32 tmp;
-               u32 reference_clock = adev->clock.mpll.reference_freq;
-
-               if (mpll_param.qdr == 1)
-                       freq_nom = memory_clock * 4 * (1 << mpll_param.post_div);
-               else
-                       freq_nom = memory_clock * 2 * (1 << mpll_param.post_div);
-
-               tmp = (freq_nom / reference_clock);
-               tmp = tmp * tmp;
-               if (amdgpu_atombios_get_asic_ss_info(adev, &ss,
-                                                    ASIC_INTERNAL_MEMORY_SS, freq_nom)) {
-                       u32 clks = reference_clock * 5 / ss.rate;
-                       u32 clkv = (u32)((((131 * ss.percentage * ss.rate) / 100) * tmp) / freq_nom);
-
-                       mpll_ss1 &= ~MPLL_SS1__CLKV_MASK;
-                       mpll_ss1 |= (clkv << MPLL_SS1__CLKV__SHIFT);
-
-                       mpll_ss2 &= ~MPLL_SS2__CLKS_MASK;
-                       mpll_ss2 |= (clks << MPLL_SS2__CLKS__SHIFT);
-               }
-       }
-
-       mclk_pwrmgt_cntl &= ~MCLK_PWRMGT_CNTL__DLL_SPEED_MASK;
-       mclk_pwrmgt_cntl |= (mpll_param.dll_speed << MCLK_PWRMGT_CNTL__DLL_SPEED__SHIFT);
-
-       if (dll_state_on)
-               mclk_pwrmgt_cntl |= MCLK_PWRMGT_CNTL__MRDCK0_PDNB_MASK |
-                       MCLK_PWRMGT_CNTL__MRDCK1_PDNB_MASK;
-       else
-               mclk_pwrmgt_cntl &= ~(MCLK_PWRMGT_CNTL__MRDCK0_PDNB_MASK |
-                       MCLK_PWRMGT_CNTL__MRDCK1_PDNB_MASK);
-
-       mclk->MclkFrequency = memory_clock;
-       mclk->MpllFuncCntl = mpll_func_cntl;
-       mclk->MpllFuncCntl_1 = mpll_func_cntl_1;
-       mclk->MpllFuncCntl_2 = mpll_func_cntl_2;
-       mclk->MpllAdFuncCntl = mpll_ad_func_cntl;
-       mclk->MpllDqFuncCntl = mpll_dq_func_cntl;
-       mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl;
-       mclk->DllCntl = dll_cntl;
-       mclk->MpllSs1 = mpll_ss1;
-       mclk->MpllSs2 = mpll_ss2;
-
-       return 0;
-}
-
-static int ci_populate_single_memory_level(struct amdgpu_device *adev,
-                                          u32 memory_clock,
-                                          SMU7_Discrete_MemoryLevel *memory_level)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       int ret;
-       bool dll_state_on;
-
-       if (adev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries) {
-               ret = ci_get_dependency_volt_by_clk(adev,
-                                                   &adev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
-                                                   memory_clock, &memory_level->MinVddc);
-               if (ret)
-                       return ret;
-       }
-
-       if (adev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries) {
-               ret = ci_get_dependency_volt_by_clk(adev,
-                                                   &adev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
-                                                   memory_clock, &memory_level->MinVddci);
-               if (ret)
-                       return ret;
-       }
-
-       if (adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries) {
-               ret = ci_get_dependency_volt_by_clk(adev,
-                                                   &adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk,
-                                                   memory_clock, &memory_level->MinMvdd);
-               if (ret)
-                       return ret;
-       }
-
-       memory_level->MinVddcPhases = 1;
-
-       if (pi->vddc_phase_shed_control)
-               ci_populate_phase_value_based_on_mclk(adev,
-                                                     &adev->pm.dpm.dyn_state.phase_shedding_limits_table,
-                                                     memory_clock,
-                                                     &memory_level->MinVddcPhases);
-
-       memory_level->EnabledForActivity = 1;
-       memory_level->EnabledForThrottle = 1;
-       memory_level->UpH = 0;
-       memory_level->DownH = 100;
-       memory_level->VoltageDownH = 0;
-       memory_level->ActivityLevel = (u16)pi->mclk_activity_target;
-
-       memory_level->StutterEnable = false;
-       memory_level->StrobeEnable = false;
-       memory_level->EdcReadEnable = false;
-       memory_level->EdcWriteEnable = false;
-       memory_level->RttEnable = false;
-
-       memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
-
-       if (pi->mclk_stutter_mode_threshold &&
-           (memory_clock <= pi->mclk_stutter_mode_threshold) &&
-           (!pi->uvd_enabled) &&
-           (RREG32(mmDPG_PIPE_STUTTER_CONTROL) & DPG_PIPE_STUTTER_CONTROL__STUTTER_ENABLE_MASK) &&
-           (adev->pm.dpm.new_active_crtc_count <= 2))
-               memory_level->StutterEnable = true;
-
-       if (pi->mclk_strobe_mode_threshold &&
-           (memory_clock <= pi->mclk_strobe_mode_threshold))
-               memory_level->StrobeEnable = 1;
-
-       if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) {
-               memory_level->StrobeRatio =
-                       ci_get_mclk_frequency_ratio(memory_clock, memory_level->StrobeEnable);
-               if (pi->mclk_edc_enable_threshold &&
-                   (memory_clock > pi->mclk_edc_enable_threshold))
-                       memory_level->EdcReadEnable = true;
-
-               if (pi->mclk_edc_wr_enable_threshold &&
-                   (memory_clock > pi->mclk_edc_wr_enable_threshold))
-                       memory_level->EdcWriteEnable = true;
-
-               if (memory_level->StrobeEnable) {
-                       if (ci_get_mclk_frequency_ratio(memory_clock, true) >=
-                           ((RREG32(mmMC_SEQ_MISC7) >> 16) & 0xf))
-                               dll_state_on = ((RREG32(mmMC_SEQ_MISC5) >> 1) & 0x1) ? true : false;
-                       else
-                               dll_state_on = ((RREG32(mmMC_SEQ_MISC6) >> 1) & 0x1) ? true : false;
-               } else {
-                       dll_state_on = pi->dll_default_on;
-               }
-       } else {
-               memory_level->StrobeRatio = ci_get_ddr3_mclk_frequency_ratio(memory_clock);
-               dll_state_on = ((RREG32(mmMC_SEQ_MISC5) >> 1) & 0x1) ? true : false;
-       }
-
-       ret = ci_calculate_mclk_params(adev, memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on);
-       if (ret)
-               return ret;
-
-       memory_level->MinVddc = cpu_to_be32(memory_level->MinVddc * VOLTAGE_SCALE);
-       memory_level->MinVddcPhases = cpu_to_be32(memory_level->MinVddcPhases);
-       memory_level->MinVddci = cpu_to_be32(memory_level->MinVddci * VOLTAGE_SCALE);
-       memory_level->MinMvdd = cpu_to_be32(memory_level->MinMvdd * VOLTAGE_SCALE);
-
-       memory_level->MclkFrequency = cpu_to_be32(memory_level->MclkFrequency);
-       memory_level->ActivityLevel = cpu_to_be16(memory_level->ActivityLevel);
-       memory_level->MpllFuncCntl = cpu_to_be32(memory_level->MpllFuncCntl);
-       memory_level->MpllFuncCntl_1 = cpu_to_be32(memory_level->MpllFuncCntl_1);
-       memory_level->MpllFuncCntl_2 = cpu_to_be32(memory_level->MpllFuncCntl_2);
-       memory_level->MpllAdFuncCntl = cpu_to_be32(memory_level->MpllAdFuncCntl);
-       memory_level->MpllDqFuncCntl = cpu_to_be32(memory_level->MpllDqFuncCntl);
-       memory_level->MclkPwrmgtCntl = cpu_to_be32(memory_level->MclkPwrmgtCntl);
-       memory_level->DllCntl = cpu_to_be32(memory_level->DllCntl);
-       memory_level->MpllSs1 = cpu_to_be32(memory_level->MpllSs1);
-       memory_level->MpllSs2 = cpu_to_be32(memory_level->MpllSs2);
-
-       return 0;
-}
-
-static int ci_populate_smc_acpi_level(struct amdgpu_device *adev,
-                                     SMU7_Discrete_DpmTable *table)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct atom_clock_dividers dividers;
-       SMU7_Discrete_VoltageLevel voltage_level;
-       u32 spll_func_cntl = pi->clock_registers.cg_spll_func_cntl;
-       u32 spll_func_cntl_2 = pi->clock_registers.cg_spll_func_cntl_2;
-       u32 dll_cntl = pi->clock_registers.dll_cntl;
-       u32 mclk_pwrmgt_cntl = pi->clock_registers.mclk_pwrmgt_cntl;
-       int ret;
-
-       table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC;
-
-       if (pi->acpi_vddc)
-               table->ACPILevel.MinVddc = cpu_to_be32(pi->acpi_vddc * VOLTAGE_SCALE);
-       else
-               table->ACPILevel.MinVddc = cpu_to_be32(pi->min_vddc_in_pp_table * VOLTAGE_SCALE);
-
-       table->ACPILevel.MinVddcPhases = pi->vddc_phase_shed_control ? 0 : 1;
-
-       table->ACPILevel.SclkFrequency = adev->clock.spll.reference_freq;
-
-       ret = amdgpu_atombios_get_clock_dividers(adev,
-                                                COMPUTE_GPUCLK_INPUT_FLAG_SCLK,
-                                                table->ACPILevel.SclkFrequency, false, &dividers);
-       if (ret)
-               return ret;
-
-       table->ACPILevel.SclkDid = (u8)dividers.post_divider;
-       table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
-       table->ACPILevel.DeepSleepDivId = 0;
-
-       spll_func_cntl &= ~CG_SPLL_FUNC_CNTL__SPLL_PWRON_MASK;
-       spll_func_cntl |= CG_SPLL_FUNC_CNTL__SPLL_RESET_MASK;
-
-       spll_func_cntl_2 &= ~CG_SPLL_FUNC_CNTL_2__SCLK_MUX_SEL_MASK;
-       spll_func_cntl_2 |= (4 << CG_SPLL_FUNC_CNTL_2__SCLK_MUX_SEL__SHIFT);
-
-       table->ACPILevel.CgSpllFuncCntl = spll_func_cntl;
-       table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2;
-       table->ACPILevel.CgSpllFuncCntl3 = pi->clock_registers.cg_spll_func_cntl_3;
-       table->ACPILevel.CgSpllFuncCntl4 = pi->clock_registers.cg_spll_func_cntl_4;
-       table->ACPILevel.SpllSpreadSpectrum = pi->clock_registers.cg_spll_spread_spectrum;
-       table->ACPILevel.SpllSpreadSpectrum2 = pi->clock_registers.cg_spll_spread_spectrum_2;
-       table->ACPILevel.CcPwrDynRm = 0;
-       table->ACPILevel.CcPwrDynRm1 = 0;
-
-       table->ACPILevel.Flags = cpu_to_be32(table->ACPILevel.Flags);
-       table->ACPILevel.MinVddcPhases = cpu_to_be32(table->ACPILevel.MinVddcPhases);
-       table->ACPILevel.SclkFrequency = cpu_to_be32(table->ACPILevel.SclkFrequency);
-       table->ACPILevel.CgSpllFuncCntl = cpu_to_be32(table->ACPILevel.CgSpllFuncCntl);
-       table->ACPILevel.CgSpllFuncCntl2 = cpu_to_be32(table->ACPILevel.CgSpllFuncCntl2);
-       table->ACPILevel.CgSpllFuncCntl3 = cpu_to_be32(table->ACPILevel.CgSpllFuncCntl3);
-       table->ACPILevel.CgSpllFuncCntl4 = cpu_to_be32(table->ACPILevel.CgSpllFuncCntl4);
-       table->ACPILevel.SpllSpreadSpectrum = cpu_to_be32(table->ACPILevel.SpllSpreadSpectrum);
-       table->ACPILevel.SpllSpreadSpectrum2 = cpu_to_be32(table->ACPILevel.SpllSpreadSpectrum2);
-       table->ACPILevel.CcPwrDynRm = cpu_to_be32(table->ACPILevel.CcPwrDynRm);
-       table->ACPILevel.CcPwrDynRm1 = cpu_to_be32(table->ACPILevel.CcPwrDynRm1);
-
-       table->MemoryACPILevel.MinVddc = table->ACPILevel.MinVddc;
-       table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;
-
-       if (pi->vddci_control != CISLANDS_VOLTAGE_CONTROL_NONE) {
-               if (pi->acpi_vddci)
-                       table->MemoryACPILevel.MinVddci =
-                               cpu_to_be32(pi->acpi_vddci * VOLTAGE_SCALE);
-               else
-                       table->MemoryACPILevel.MinVddci =
-                               cpu_to_be32(pi->min_vddci_in_pp_table * VOLTAGE_SCALE);
-       }
-
-       if (ci_populate_mvdd_value(adev, 0, &voltage_level))
-               table->MemoryACPILevel.MinMvdd = 0;
-       else
-               table->MemoryACPILevel.MinMvdd =
-                       cpu_to_be32(voltage_level.Voltage * VOLTAGE_SCALE);
-
-       mclk_pwrmgt_cntl |= MCLK_PWRMGT_CNTL__MRDCK0_RESET_MASK |
-               MCLK_PWRMGT_CNTL__MRDCK1_RESET_MASK;
-       mclk_pwrmgt_cntl &= ~(MCLK_PWRMGT_CNTL__MRDCK0_PDNB_MASK |
-                       MCLK_PWRMGT_CNTL__MRDCK1_PDNB_MASK);
-
-       dll_cntl &= ~(DLL_CNTL__MRDCK0_BYPASS_MASK | DLL_CNTL__MRDCK1_BYPASS_MASK);
-
-       table->MemoryACPILevel.DllCntl = cpu_to_be32(dll_cntl);
-       table->MemoryACPILevel.MclkPwrmgtCntl = cpu_to_be32(mclk_pwrmgt_cntl);
-       table->MemoryACPILevel.MpllAdFuncCntl =
-               cpu_to_be32(pi->clock_registers.mpll_ad_func_cntl);
-       table->MemoryACPILevel.MpllDqFuncCntl =
-               cpu_to_be32(pi->clock_registers.mpll_dq_func_cntl);
-       table->MemoryACPILevel.MpllFuncCntl =
-               cpu_to_be32(pi->clock_registers.mpll_func_cntl);
-       table->MemoryACPILevel.MpllFuncCntl_1 =
-               cpu_to_be32(pi->clock_registers.mpll_func_cntl_1);
-       table->MemoryACPILevel.MpllFuncCntl_2 =
-               cpu_to_be32(pi->clock_registers.mpll_func_cntl_2);
-       table->MemoryACPILevel.MpllSs1 = cpu_to_be32(pi->clock_registers.mpll_ss1);
-       table->MemoryACPILevel.MpllSs2 = cpu_to_be32(pi->clock_registers.mpll_ss2);
-
-       table->MemoryACPILevel.EnabledForThrottle = 0;
-       table->MemoryACPILevel.EnabledForActivity = 0;
-       table->MemoryACPILevel.UpH = 0;
-       table->MemoryACPILevel.DownH = 100;
-       table->MemoryACPILevel.VoltageDownH = 0;
-       table->MemoryACPILevel.ActivityLevel =
-               cpu_to_be16((u16)pi->mclk_activity_target);
-
-       table->MemoryACPILevel.StutterEnable = false;
-       table->MemoryACPILevel.StrobeEnable = false;
-       table->MemoryACPILevel.EdcReadEnable = false;
-       table->MemoryACPILevel.EdcWriteEnable = false;
-       table->MemoryACPILevel.RttEnable = false;
-
-       return 0;
-}
-
-
-static int ci_enable_ulv(struct amdgpu_device *adev, bool enable)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_ulv_parm *ulv = &pi->ulv;
-
-       if (ulv->supported) {
-               if (enable)
-                       return (amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_EnableULV) == PPSMC_Result_OK) ?
-                               0 : -EINVAL;
-               else
-                       return (amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_DisableULV) == PPSMC_Result_OK) ?
-                               0 : -EINVAL;
-       }
-
-       return 0;
-}
-
-static int ci_populate_ulv_level(struct amdgpu_device *adev,
-                                SMU7_Discrete_Ulv *state)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u16 ulv_voltage = adev->pm.dpm.backbias_response_time;
-
-       state->CcPwrDynRm = 0;
-       state->CcPwrDynRm1 = 0;
-
-       if (ulv_voltage == 0) {
-               pi->ulv.supported = false;
-               return 0;
-       }
-
-       if (pi->voltage_control != CISLANDS_VOLTAGE_CONTROL_BY_SVID2) {
-               if (ulv_voltage > adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[0].v)
-                       state->VddcOffset = 0;
-               else
-                       state->VddcOffset =
-                               adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[0].v - ulv_voltage;
-       } else {
-               if (ulv_voltage > adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[0].v)
-                       state->VddcOffsetVid = 0;
-               else
-                       state->VddcOffsetVid = (u8)
-                               ((adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[0].v - ulv_voltage) *
-                                VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1);
-       }
-       state->VddcPhase = pi->vddc_phase_shed_control ? 0 : 1;
-
-       state->CcPwrDynRm = cpu_to_be32(state->CcPwrDynRm);
-       state->CcPwrDynRm1 = cpu_to_be32(state->CcPwrDynRm1);
-       state->VddcOffset = cpu_to_be16(state->VddcOffset);
-
-       return 0;
-}
-
-static int ci_calculate_sclk_params(struct amdgpu_device *adev,
-                                   u32 engine_clock,
-                                   SMU7_Discrete_GraphicsLevel *sclk)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct atom_clock_dividers dividers;
-       u32 spll_func_cntl_3 = pi->clock_registers.cg_spll_func_cntl_3;
-       u32 spll_func_cntl_4 = pi->clock_registers.cg_spll_func_cntl_4;
-       u32 cg_spll_spread_spectrum = pi->clock_registers.cg_spll_spread_spectrum;
-       u32 cg_spll_spread_spectrum_2 = pi->clock_registers.cg_spll_spread_spectrum_2;
-       u32 reference_clock = adev->clock.spll.reference_freq;
-       u32 reference_divider;
-       u32 fbdiv;
-       int ret;
-
-       ret = amdgpu_atombios_get_clock_dividers(adev,
-                                                COMPUTE_GPUCLK_INPUT_FLAG_SCLK,
-                                                engine_clock, false, &dividers);
-       if (ret)
-               return ret;
-
-       reference_divider = 1 + dividers.ref_div;
-       fbdiv = dividers.fb_div & 0x3FFFFFF;
-
-       spll_func_cntl_3 &= ~CG_SPLL_FUNC_CNTL_3__SPLL_FB_DIV_MASK;
-       spll_func_cntl_3 |= (fbdiv << CG_SPLL_FUNC_CNTL_3__SPLL_FB_DIV__SHIFT);
-       spll_func_cntl_3 |= CG_SPLL_FUNC_CNTL_3__SPLL_DITHEN_MASK;
-
-       if (pi->caps_sclk_ss_support) {
-               struct amdgpu_atom_ss ss;
-               u32 vco_freq = engine_clock * dividers.post_div;
-
-               if (amdgpu_atombios_get_asic_ss_info(adev, &ss,
-                                                    ASIC_INTERNAL_ENGINE_SS, vco_freq)) {
-                       u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate);
-                       u32 clk_v = 4 * ss.percentage * fbdiv / (clk_s * 10000);
-
-                       cg_spll_spread_spectrum &= ~(CG_SPLL_SPREAD_SPECTRUM__CLKS_MASK | CG_SPLL_SPREAD_SPECTRUM__SSEN_MASK);
-                       cg_spll_spread_spectrum |= (clk_s << CG_SPLL_SPREAD_SPECTRUM__CLKS__SHIFT);
-                       cg_spll_spread_spectrum |= (1 << CG_SPLL_SPREAD_SPECTRUM__SSEN__SHIFT);
-
-                       cg_spll_spread_spectrum_2 &= ~CG_SPLL_SPREAD_SPECTRUM_2__CLKV_MASK;
-                       cg_spll_spread_spectrum_2 |= (clk_v << CG_SPLL_SPREAD_SPECTRUM_2__CLKV__SHIFT);
-               }
-       }
-
-       sclk->SclkFrequency = engine_clock;
-       sclk->CgSpllFuncCntl3 = spll_func_cntl_3;
-       sclk->CgSpllFuncCntl4 = spll_func_cntl_4;
-       sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum;
-       sclk->SpllSpreadSpectrum2  = cg_spll_spread_spectrum_2;
-       sclk->SclkDid = (u8)dividers.post_divider;
-
-       return 0;
-}
-
-static int ci_populate_single_graphic_level(struct amdgpu_device *adev,
-                                           u32 engine_clock,
-                                           u16 sclk_activity_level_t,
-                                           SMU7_Discrete_GraphicsLevel *graphic_level)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       int ret;
-
-       ret = ci_calculate_sclk_params(adev, engine_clock, graphic_level);
-       if (ret)
-               return ret;
-
-       ret = ci_get_dependency_volt_by_clk(adev,
-                                           &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
-                                           engine_clock, &graphic_level->MinVddc);
-       if (ret)
-               return ret;
-
-       graphic_level->SclkFrequency = engine_clock;
-
-       graphic_level->Flags =  0;
-       graphic_level->MinVddcPhases = 1;
-
-       if (pi->vddc_phase_shed_control)
-               ci_populate_phase_value_based_on_sclk(adev,
-                                                     &adev->pm.dpm.dyn_state.phase_shedding_limits_table,
-                                                     engine_clock,
-                                                     &graphic_level->MinVddcPhases);
-
-       graphic_level->ActivityLevel = sclk_activity_level_t;
-
-       graphic_level->CcPwrDynRm = 0;
-       graphic_level->CcPwrDynRm1 = 0;
-       graphic_level->EnabledForThrottle = 1;
-       graphic_level->UpH = 0;
-       graphic_level->DownH = 0;
-       graphic_level->VoltageDownH = 0;
-       graphic_level->PowerThrottle = 0;
-
-       if (pi->caps_sclk_ds)
-               graphic_level->DeepSleepDivId = ci_get_sleep_divider_id_from_clock(engine_clock,
-                                                                                  CISLAND_MINIMUM_ENGINE_CLOCK);
-
-       graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
-
-       graphic_level->Flags = cpu_to_be32(graphic_level->Flags);
-       graphic_level->MinVddc = cpu_to_be32(graphic_level->MinVddc * VOLTAGE_SCALE);
-       graphic_level->MinVddcPhases = cpu_to_be32(graphic_level->MinVddcPhases);
-       graphic_level->SclkFrequency = cpu_to_be32(graphic_level->SclkFrequency);
-       graphic_level->ActivityLevel = cpu_to_be16(graphic_level->ActivityLevel);
-       graphic_level->CgSpllFuncCntl3 = cpu_to_be32(graphic_level->CgSpllFuncCntl3);
-       graphic_level->CgSpllFuncCntl4 = cpu_to_be32(graphic_level->CgSpllFuncCntl4);
-       graphic_level->SpllSpreadSpectrum = cpu_to_be32(graphic_level->SpllSpreadSpectrum);
-       graphic_level->SpllSpreadSpectrum2 = cpu_to_be32(graphic_level->SpllSpreadSpectrum2);
-       graphic_level->CcPwrDynRm = cpu_to_be32(graphic_level->CcPwrDynRm);
-       graphic_level->CcPwrDynRm1 = cpu_to_be32(graphic_level->CcPwrDynRm1);
-
-       return 0;
-}
-
-static int ci_populate_all_graphic_levels(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_dpm_table *dpm_table = &pi->dpm_table;
-       u32 level_array_address = pi->dpm_table_start +
-               offsetof(SMU7_Discrete_DpmTable, GraphicsLevel);
-       u32 level_array_size = sizeof(SMU7_Discrete_GraphicsLevel) *
-               SMU7_MAX_LEVELS_GRAPHICS;
-       SMU7_Discrete_GraphicsLevel *levels = pi->smc_state_table.GraphicsLevel;
-       u32 i, ret;
-
-       memset(levels, 0, level_array_size);
-
-       for (i = 0; i < dpm_table->sclk_table.count; i++) {
-               ret = ci_populate_single_graphic_level(adev,
-                                                      dpm_table->sclk_table.dpm_levels[i].value,
-                                                      (u16)pi->activity_target[i],
-                                                      &pi->smc_state_table.GraphicsLevel[i]);
-               if (ret)
-                       return ret;
-               if (i > 1)
-                       pi->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0;
-               if (i == (dpm_table->sclk_table.count - 1))
-                       pi->smc_state_table.GraphicsLevel[i].DisplayWatermark =
-                               PPSMC_DISPLAY_WATERMARK_HIGH;
-       }
-       pi->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1;
-
-       pi->smc_state_table.GraphicsDpmLevelCount = (u8)dpm_table->sclk_table.count;
-       pi->dpm_level_enable_mask.sclk_dpm_enable_mask =
-               ci_get_dpm_level_enable_mask_value(&dpm_table->sclk_table);
-
-       ret = amdgpu_ci_copy_bytes_to_smc(adev, level_array_address,
-                                  (u8 *)levels, level_array_size,
-                                  pi->sram_end);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
-static int ci_populate_ulv_state(struct amdgpu_device *adev,
-                                SMU7_Discrete_Ulv *ulv_level)
-{
-       return ci_populate_ulv_level(adev, ulv_level);
-}
-
-static int ci_populate_all_memory_levels(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_dpm_table *dpm_table = &pi->dpm_table;
-       u32 level_array_address = pi->dpm_table_start +
-               offsetof(SMU7_Discrete_DpmTable, MemoryLevel);
-       u32 level_array_size = sizeof(SMU7_Discrete_MemoryLevel) *
-               SMU7_MAX_LEVELS_MEMORY;
-       SMU7_Discrete_MemoryLevel *levels = pi->smc_state_table.MemoryLevel;
-       u32 i, ret;
-
-       memset(levels, 0, level_array_size);
-
-       for (i = 0; i < dpm_table->mclk_table.count; i++) {
-               if (dpm_table->mclk_table.dpm_levels[i].value == 0)
-                       return -EINVAL;
-               ret = ci_populate_single_memory_level(adev,
-                                                     dpm_table->mclk_table.dpm_levels[i].value,
-                                                     &pi->smc_state_table.MemoryLevel[i]);
-               if (ret)
-                       return ret;
-       }
-
-       if ((dpm_table->mclk_table.count >= 2) &&
-           ((adev->pdev->device == 0x67B0) || (adev->pdev->device == 0x67B1))) {
-               pi->smc_state_table.MemoryLevel[1].MinVddc =
-                       pi->smc_state_table.MemoryLevel[0].MinVddc;
-               pi->smc_state_table.MemoryLevel[1].MinVddcPhases =
-                       pi->smc_state_table.MemoryLevel[0].MinVddcPhases;
-       }
-
-       pi->smc_state_table.MemoryLevel[0].ActivityLevel = cpu_to_be16(0x1F);
-
-       pi->smc_state_table.MemoryDpmLevelCount = (u8)dpm_table->mclk_table.count;
-       pi->dpm_level_enable_mask.mclk_dpm_enable_mask =
-               ci_get_dpm_level_enable_mask_value(&dpm_table->mclk_table);
-
-       pi->smc_state_table.MemoryLevel[dpm_table->mclk_table.count - 1].DisplayWatermark =
-               PPSMC_DISPLAY_WATERMARK_HIGH;
-
-       ret = amdgpu_ci_copy_bytes_to_smc(adev, level_array_address,
-                                  (u8 *)levels, level_array_size,
-                                  pi->sram_end);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
-static void ci_reset_single_dpm_table(struct amdgpu_device *adev,
-                                     struct ci_single_dpm_table* dpm_table,
-                                     u32 count)
-{
-       u32 i;
-
-       dpm_table->count = count;
-       for (i = 0; i < MAX_REGULAR_DPM_NUMBER; i++)
-               dpm_table->dpm_levels[i].enabled = false;
-}
-
-static void ci_setup_pcie_table_entry(struct ci_single_dpm_table* dpm_table,
-                                     u32 index, u32 pcie_gen, u32 pcie_lanes)
-{
-       dpm_table->dpm_levels[index].value = pcie_gen;
-       dpm_table->dpm_levels[index].param1 = pcie_lanes;
-       dpm_table->dpm_levels[index].enabled = true;
-}
-
-static int ci_setup_default_pcie_tables(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       if (!pi->use_pcie_performance_levels && !pi->use_pcie_powersaving_levels)
-               return -EINVAL;
-
-       if (pi->use_pcie_performance_levels && !pi->use_pcie_powersaving_levels) {
-               pi->pcie_gen_powersaving = pi->pcie_gen_performance;
-               pi->pcie_lane_powersaving = pi->pcie_lane_performance;
-       } else if (!pi->use_pcie_performance_levels && pi->use_pcie_powersaving_levels) {
-               pi->pcie_gen_performance = pi->pcie_gen_powersaving;
-               pi->pcie_lane_performance = pi->pcie_lane_powersaving;
-       }
-
-       ci_reset_single_dpm_table(adev,
-                                 &pi->dpm_table.pcie_speed_table,
-                                 SMU7_MAX_LEVELS_LINK);
-
-       if (adev->asic_type == CHIP_BONAIRE)
-               ci_setup_pcie_table_entry(&pi->dpm_table.pcie_speed_table, 0,
-                                         pi->pcie_gen_powersaving.min,
-                                         pi->pcie_lane_powersaving.max);
-       else
-               ci_setup_pcie_table_entry(&pi->dpm_table.pcie_speed_table, 0,
-                                         pi->pcie_gen_powersaving.min,
-                                         pi->pcie_lane_powersaving.min);
-       ci_setup_pcie_table_entry(&pi->dpm_table.pcie_speed_table, 1,
-                                 pi->pcie_gen_performance.min,
-                                 pi->pcie_lane_performance.min);
-       ci_setup_pcie_table_entry(&pi->dpm_table.pcie_speed_table, 2,
-                                 pi->pcie_gen_powersaving.min,
-                                 pi->pcie_lane_powersaving.max);
-       ci_setup_pcie_table_entry(&pi->dpm_table.pcie_speed_table, 3,
-                                 pi->pcie_gen_performance.min,
-                                 pi->pcie_lane_performance.max);
-       ci_setup_pcie_table_entry(&pi->dpm_table.pcie_speed_table, 4,
-                                 pi->pcie_gen_powersaving.max,
-                                 pi->pcie_lane_powersaving.max);
-       ci_setup_pcie_table_entry(&pi->dpm_table.pcie_speed_table, 5,
-                                 pi->pcie_gen_performance.max,
-                                 pi->pcie_lane_performance.max);
-
-       pi->dpm_table.pcie_speed_table.count = 6;
-
-       return 0;
-}
-
-static int ci_setup_default_dpm_tables(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct amdgpu_clock_voltage_dependency_table *allowed_sclk_vddc_table =
-               &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk;
-       struct amdgpu_clock_voltage_dependency_table *allowed_mclk_table =
-               &adev->pm.dpm.dyn_state.vddc_dependency_on_mclk;
-       struct amdgpu_cac_leakage_table *std_voltage_table =
-               &adev->pm.dpm.dyn_state.cac_leakage_table;
-       u32 i;
-
-       if (allowed_sclk_vddc_table == NULL)
-               return -EINVAL;
-       if (allowed_sclk_vddc_table->count < 1)
-               return -EINVAL;
-       if (allowed_mclk_table == NULL)
-               return -EINVAL;
-       if (allowed_mclk_table->count < 1)
-               return -EINVAL;
-
-       memset(&pi->dpm_table, 0, sizeof(struct ci_dpm_table));
-
-       ci_reset_single_dpm_table(adev,
-                                 &pi->dpm_table.sclk_table,
-                                 SMU7_MAX_LEVELS_GRAPHICS);
-       ci_reset_single_dpm_table(adev,
-                                 &pi->dpm_table.mclk_table,
-                                 SMU7_MAX_LEVELS_MEMORY);
-       ci_reset_single_dpm_table(adev,
-                                 &pi->dpm_table.vddc_table,
-                                 SMU7_MAX_LEVELS_VDDC);
-       ci_reset_single_dpm_table(adev,
-                                 &pi->dpm_table.vddci_table,
-                                 SMU7_MAX_LEVELS_VDDCI);
-       ci_reset_single_dpm_table(adev,
-                                 &pi->dpm_table.mvdd_table,
-                                 SMU7_MAX_LEVELS_MVDD);
-
-       pi->dpm_table.sclk_table.count = 0;
-       for (i = 0; i < allowed_sclk_vddc_table->count; i++) {
-               if ((i == 0) ||
-                   (pi->dpm_table.sclk_table.dpm_levels[pi->dpm_table.sclk_table.count-1].value !=
-                    allowed_sclk_vddc_table->entries[i].clk)) {
-                       pi->dpm_table.sclk_table.dpm_levels[pi->dpm_table.sclk_table.count].value =
-                               allowed_sclk_vddc_table->entries[i].clk;
-                       pi->dpm_table.sclk_table.dpm_levels[pi->dpm_table.sclk_table.count].enabled =
-                               (i == 0) ? true : false;
-                       pi->dpm_table.sclk_table.count++;
-               }
-       }
-
-       pi->dpm_table.mclk_table.count = 0;
-       for (i = 0; i < allowed_mclk_table->count; i++) {
-               if ((i == 0) ||
-                   (pi->dpm_table.mclk_table.dpm_levels[pi->dpm_table.mclk_table.count-1].value !=
-                    allowed_mclk_table->entries[i].clk)) {
-                       pi->dpm_table.mclk_table.dpm_levels[pi->dpm_table.mclk_table.count].value =
-                               allowed_mclk_table->entries[i].clk;
-                       pi->dpm_table.mclk_table.dpm_levels[pi->dpm_table.mclk_table.count].enabled =
-                               (i == 0) ? true : false;
-                       pi->dpm_table.mclk_table.count++;
-               }
-       }
-
-       for (i = 0; i < allowed_sclk_vddc_table->count; i++) {
-               pi->dpm_table.vddc_table.dpm_levels[i].value =
-                       allowed_sclk_vddc_table->entries[i].v;
-               pi->dpm_table.vddc_table.dpm_levels[i].param1 =
-                       std_voltage_table->entries[i].leakage;
-               pi->dpm_table.vddc_table.dpm_levels[i].enabled = true;
-       }
-       pi->dpm_table.vddc_table.count = allowed_sclk_vddc_table->count;
-
-       allowed_mclk_table = &adev->pm.dpm.dyn_state.vddci_dependency_on_mclk;
-       if (allowed_mclk_table) {
-               for (i = 0; i < allowed_mclk_table->count; i++) {
-                       pi->dpm_table.vddci_table.dpm_levels[i].value =
-                               allowed_mclk_table->entries[i].v;
-                       pi->dpm_table.vddci_table.dpm_levels[i].enabled = true;
-               }
-               pi->dpm_table.vddci_table.count = allowed_mclk_table->count;
-       }
-
-       allowed_mclk_table = &adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk;
-       if (allowed_mclk_table) {
-               for (i = 0; i < allowed_mclk_table->count; i++) {
-                       pi->dpm_table.mvdd_table.dpm_levels[i].value =
-                               allowed_mclk_table->entries[i].v;
-                       pi->dpm_table.mvdd_table.dpm_levels[i].enabled = true;
-               }
-               pi->dpm_table.mvdd_table.count = allowed_mclk_table->count;
-       }
-
-       ci_setup_default_pcie_tables(adev);
-
-       /* save a copy of the default DPM table */
-       memcpy(&(pi->golden_dpm_table), &(pi->dpm_table),
-                       sizeof(struct ci_dpm_table));
-
-       return 0;
-}
-
-static int ci_find_boot_level(struct ci_single_dpm_table *table,
-                             u32 value, u32 *boot_level)
-{
-       u32 i;
-       int ret = -EINVAL;
-
-       for(i = 0; i < table->count; i++) {
-               if (value == table->dpm_levels[i].value) {
-                       *boot_level = i;
-                       ret = 0;
-               }
-       }
-
-       return ret;
-}
-
-static int ci_init_smc_table(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_ulv_parm *ulv = &pi->ulv;
-       struct amdgpu_ps *amdgpu_boot_state = adev->pm.dpm.boot_ps;
-       SMU7_Discrete_DpmTable *table = &pi->smc_state_table;
-       int ret;
-
-       ret = ci_setup_default_dpm_tables(adev);
-       if (ret)
-               return ret;
-
-       if (pi->voltage_control != CISLANDS_VOLTAGE_CONTROL_NONE)
-               ci_populate_smc_voltage_tables(adev, table);
-
-       ci_init_fps_limits(adev);
-
-       if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC)
-               table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
-
-       if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC)
-               table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
-
-       if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5)
-               table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
-
-       if (ulv->supported) {
-               ret = ci_populate_ulv_state(adev, &pi->smc_state_table.Ulv);
-               if (ret)
-                       return ret;
-               WREG32_SMC(ixCG_ULV_PARAMETER, ulv->cg_ulv_parameter);
-       }
-
-       ret = ci_populate_all_graphic_levels(adev);
-       if (ret)
-               return ret;
-
-       ret = ci_populate_all_memory_levels(adev);
-       if (ret)
-               return ret;
-
-       ci_populate_smc_link_level(adev, table);
-
-       ret = ci_populate_smc_acpi_level(adev, table);
-       if (ret)
-               return ret;
-
-       ret = ci_populate_smc_vce_level(adev, table);
-       if (ret)
-               return ret;
-
-       ret = ci_populate_smc_acp_level(adev, table);
-       if (ret)
-               return ret;
-
-       ret = ci_populate_smc_samu_level(adev, table);
-       if (ret)
-               return ret;
-
-       ret = ci_do_program_memory_timing_parameters(adev);
-       if (ret)
-               return ret;
-
-       ret = ci_populate_smc_uvd_level(adev, table);
-       if (ret)
-               return ret;
-
-       table->UvdBootLevel  = 0;
-       table->VceBootLevel  = 0;
-       table->AcpBootLevel  = 0;
-       table->SamuBootLevel  = 0;
-       table->GraphicsBootLevel  = 0;
-       table->MemoryBootLevel  = 0;
-
-       ret = ci_find_boot_level(&pi->dpm_table.sclk_table,
-                                pi->vbios_boot_state.sclk_bootup_value,
-                                (u32 *)&pi->smc_state_table.GraphicsBootLevel);
-
-       ret = ci_find_boot_level(&pi->dpm_table.mclk_table,
-                                pi->vbios_boot_state.mclk_bootup_value,
-                                (u32 *)&pi->smc_state_table.MemoryBootLevel);
-
-       table->BootVddc = pi->vbios_boot_state.vddc_bootup_value;
-       table->BootVddci = pi->vbios_boot_state.vddci_bootup_value;
-       table->BootMVdd = pi->vbios_boot_state.mvdd_bootup_value;
-
-       ci_populate_smc_initial_state(adev, amdgpu_boot_state);
-
-       ret = ci_populate_bapm_parameters_in_dpm_table(adev);
-       if (ret)
-               return ret;
-
-       table->UVDInterval = 1;
-       table->VCEInterval = 1;
-       table->ACPInterval = 1;
-       table->SAMUInterval = 1;
-       table->GraphicsVoltageChangeEnable = 1;
-       table->GraphicsThermThrottleEnable = 1;
-       table->GraphicsInterval = 1;
-       table->VoltageInterval = 1;
-       table->ThermalInterval = 1;
-       table->TemperatureLimitHigh = (u16)((pi->thermal_temp_setting.temperature_high *
-                                            CISLANDS_Q88_FORMAT_CONVERSION_UNIT) / 1000);
-       table->TemperatureLimitLow = (u16)((pi->thermal_temp_setting.temperature_low *
-                                           CISLANDS_Q88_FORMAT_CONVERSION_UNIT) / 1000);
-       table->MemoryVoltageChangeEnable = 1;
-       table->MemoryInterval = 1;
-       table->VoltageResponseTime = 0;
-       table->VddcVddciDelta = 4000;
-       table->PhaseResponseTime = 0;
-       table->MemoryThermThrottleEnable = 1;
-       table->PCIeBootLinkLevel = pi->dpm_table.pcie_speed_table.count - 1;
-       table->PCIeGenInterval = 1;
-       if (pi->voltage_control == CISLANDS_VOLTAGE_CONTROL_BY_SVID2)
-               table->SVI2Enable  = 1;
-       else
-               table->SVI2Enable  = 0;
-
-       table->ThermGpio = 17;
-       table->SclkStepSize = 0x4000;
-
-       table->SystemFlags = cpu_to_be32(table->SystemFlags);
-       table->SmioMaskVddcVid = cpu_to_be32(table->SmioMaskVddcVid);
-       table->SmioMaskVddcPhase = cpu_to_be32(table->SmioMaskVddcPhase);
-       table->SmioMaskVddciVid = cpu_to_be32(table->SmioMaskVddciVid);
-       table->SmioMaskMvddVid = cpu_to_be32(table->SmioMaskMvddVid);
-       table->SclkStepSize = cpu_to_be32(table->SclkStepSize);
-       table->TemperatureLimitHigh = cpu_to_be16(table->TemperatureLimitHigh);
-       table->TemperatureLimitLow = cpu_to_be16(table->TemperatureLimitLow);
-       table->VddcVddciDelta = cpu_to_be16(table->VddcVddciDelta);
-       table->VoltageResponseTime = cpu_to_be16(table->VoltageResponseTime);
-       table->PhaseResponseTime = cpu_to_be16(table->PhaseResponseTime);
-       table->BootVddc = cpu_to_be16(table->BootVddc * VOLTAGE_SCALE);
-       table->BootVddci = cpu_to_be16(table->BootVddci * VOLTAGE_SCALE);
-       table->BootMVdd = cpu_to_be16(table->BootMVdd * VOLTAGE_SCALE);
-
-       ret = amdgpu_ci_copy_bytes_to_smc(adev,
-                                  pi->dpm_table_start +
-                                  offsetof(SMU7_Discrete_DpmTable, SystemFlags),
-                                  (u8 *)&table->SystemFlags,
-                                  sizeof(SMU7_Discrete_DpmTable) - 3 * sizeof(SMU7_PIDController),
-                                  pi->sram_end);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
-static void ci_trim_single_dpm_states(struct amdgpu_device *adev,
-                                     struct ci_single_dpm_table *dpm_table,
-                                     u32 low_limit, u32 high_limit)
-{
-       u32 i;
-
-       for (i = 0; i < dpm_table->count; i++) {
-               if ((dpm_table->dpm_levels[i].value < low_limit) ||
-                   (dpm_table->dpm_levels[i].value > high_limit))
-                       dpm_table->dpm_levels[i].enabled = false;
-               else
-                       dpm_table->dpm_levels[i].enabled = true;
-       }
-}
-
-static void ci_trim_pcie_dpm_states(struct amdgpu_device *adev,
-                                   u32 speed_low, u32 lanes_low,
-                                   u32 speed_high, u32 lanes_high)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_single_dpm_table *pcie_table = &pi->dpm_table.pcie_speed_table;
-       u32 i, j;
-
-       for (i = 0; i < pcie_table->count; i++) {
-               if ((pcie_table->dpm_levels[i].value < speed_low) ||
-                   (pcie_table->dpm_levels[i].param1 < lanes_low) ||
-                   (pcie_table->dpm_levels[i].value > speed_high) ||
-                   (pcie_table->dpm_levels[i].param1 > lanes_high))
-                       pcie_table->dpm_levels[i].enabled = false;
-               else
-                       pcie_table->dpm_levels[i].enabled = true;
-       }
-
-       for (i = 0; i < pcie_table->count; i++) {
-               if (pcie_table->dpm_levels[i].enabled) {
-                       for (j = i + 1; j < pcie_table->count; j++) {
-                               if (pcie_table->dpm_levels[j].enabled) {
-                                       if ((pcie_table->dpm_levels[i].value == pcie_table->dpm_levels[j].value) &&
-                                           (pcie_table->dpm_levels[i].param1 == pcie_table->dpm_levels[j].param1))
-                                               pcie_table->dpm_levels[j].enabled = false;
-                               }
-                       }
-               }
-       }
-}
-
-static int ci_trim_dpm_states(struct amdgpu_device *adev,
-                             struct amdgpu_ps *amdgpu_state)
-{
-       struct ci_ps *state = ci_get_ps(amdgpu_state);
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u32 high_limit_count;
-
-       if (state->performance_level_count < 1)
-               return -EINVAL;
-
-       if (state->performance_level_count == 1)
-               high_limit_count = 0;
-       else
-               high_limit_count = 1;
-
-       ci_trim_single_dpm_states(adev,
-                                 &pi->dpm_table.sclk_table,
-                                 state->performance_levels[0].sclk,
-                                 state->performance_levels[high_limit_count].sclk);
-
-       ci_trim_single_dpm_states(adev,
-                                 &pi->dpm_table.mclk_table,
-                                 state->performance_levels[0].mclk,
-                                 state->performance_levels[high_limit_count].mclk);
-
-       ci_trim_pcie_dpm_states(adev,
-                               state->performance_levels[0].pcie_gen,
-                               state->performance_levels[0].pcie_lane,
-                               state->performance_levels[high_limit_count].pcie_gen,
-                               state->performance_levels[high_limit_count].pcie_lane);
-
-       return 0;
-}
-
-static int ci_apply_disp_minimum_voltage_request(struct amdgpu_device *adev)
-{
-       struct amdgpu_clock_voltage_dependency_table *disp_voltage_table =
-               &adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk;
-       struct amdgpu_clock_voltage_dependency_table *vddc_table =
-               &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk;
-       u32 requested_voltage = 0;
-       u32 i;
-
-       if (disp_voltage_table == NULL)
-               return -EINVAL;
-       if (!disp_voltage_table->count)
-               return -EINVAL;
-
-       for (i = 0; i < disp_voltage_table->count; i++) {
-               if (adev->clock.current_dispclk == disp_voltage_table->entries[i].clk)
-                       requested_voltage = disp_voltage_table->entries[i].v;
-       }
-
-       for (i = 0; i < vddc_table->count; i++) {
-               if (requested_voltage <= vddc_table->entries[i].v) {
-                       requested_voltage = vddc_table->entries[i].v;
-                       return (amdgpu_ci_send_msg_to_smc_with_parameter(adev,
-                                                                 PPSMC_MSG_VddC_Request,
-                                                                 requested_voltage * VOLTAGE_SCALE) == PPSMC_Result_OK) ?
-                               0 : -EINVAL;
-               }
-       }
-
-       return -EINVAL;
-}
-
-static int ci_upload_dpm_level_enable_mask(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       PPSMC_Result result;
-
-       ci_apply_disp_minimum_voltage_request(adev);
-
-       if (!pi->sclk_dpm_key_disabled) {
-               if (pi->dpm_level_enable_mask.sclk_dpm_enable_mask) {
-                       result = amdgpu_ci_send_msg_to_smc_with_parameter(adev,
-                                                                  PPSMC_MSG_SCLKDPM_SetEnabledMask,
-                                                                  pi->dpm_level_enable_mask.sclk_dpm_enable_mask);
-                       if (result != PPSMC_Result_OK)
-                               return -EINVAL;
-               }
-       }
-
-       if (!pi->mclk_dpm_key_disabled) {
-               if (pi->dpm_level_enable_mask.mclk_dpm_enable_mask) {
-                       result = amdgpu_ci_send_msg_to_smc_with_parameter(adev,
-                                                                  PPSMC_MSG_MCLKDPM_SetEnabledMask,
-                                                                  pi->dpm_level_enable_mask.mclk_dpm_enable_mask);
-                       if (result != PPSMC_Result_OK)
-                               return -EINVAL;
-               }
-       }
-
-#if 0
-       if (!pi->pcie_dpm_key_disabled) {
-               if (pi->dpm_level_enable_mask.pcie_dpm_enable_mask) {
-                       result = amdgpu_ci_send_msg_to_smc_with_parameter(adev,
-                                                                  PPSMC_MSG_PCIeDPM_SetEnabledMask,
-                                                                  pi->dpm_level_enable_mask.pcie_dpm_enable_mask);
-                       if (result != PPSMC_Result_OK)
-                               return -EINVAL;
-               }
-       }
-#endif
-
-       return 0;
-}
-
-static void ci_find_dpm_states_clocks_in_dpm_table(struct amdgpu_device *adev,
-                                                  struct amdgpu_ps *amdgpu_state)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_ps *state = ci_get_ps(amdgpu_state);
-       struct ci_single_dpm_table *sclk_table = &pi->dpm_table.sclk_table;
-       u32 sclk = state->performance_levels[state->performance_level_count-1].sclk;
-       struct ci_single_dpm_table *mclk_table = &pi->dpm_table.mclk_table;
-       u32 mclk = state->performance_levels[state->performance_level_count-1].mclk;
-       u32 i;
-
-       pi->need_update_smu7_dpm_table = 0;
-
-       for (i = 0; i < sclk_table->count; i++) {
-               if (sclk == sclk_table->dpm_levels[i].value)
-                       break;
-       }
-
-       if (i >= sclk_table->count) {
-               pi->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
-       } else {
-               /* XXX check display min clock requirements */
-               if (CISLAND_MINIMUM_ENGINE_CLOCK != CISLAND_MINIMUM_ENGINE_CLOCK)
-                       pi->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_SCLK;
-       }
-
-       for (i = 0; i < mclk_table->count; i++) {
-               if (mclk == mclk_table->dpm_levels[i].value)
-                       break;
-       }
-
-       if (i >= mclk_table->count)
-               pi->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
-
-       if (adev->pm.dpm.current_active_crtc_count !=
-           adev->pm.dpm.new_active_crtc_count)
-               pi->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_MCLK;
-}
-
-static int ci_populate_and_upload_sclk_mclk_dpm_levels(struct amdgpu_device *adev,
-                                                      struct amdgpu_ps *amdgpu_state)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_ps *state = ci_get_ps(amdgpu_state);
-       u32 sclk = state->performance_levels[state->performance_level_count-1].sclk;
-       u32 mclk = state->performance_levels[state->performance_level_count-1].mclk;
-       struct ci_dpm_table *dpm_table = &pi->dpm_table;
-       int ret;
-
-       if (!pi->need_update_smu7_dpm_table)
-               return 0;
-
-       if (pi->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK)
-               dpm_table->sclk_table.dpm_levels[dpm_table->sclk_table.count-1].value = sclk;
-
-       if (pi->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)
-               dpm_table->mclk_table.dpm_levels[dpm_table->mclk_table.count-1].value = mclk;
-
-       if (pi->need_update_smu7_dpm_table & (DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_UPDATE_SCLK)) {
-               ret = ci_populate_all_graphic_levels(adev);
-               if (ret)
-                       return ret;
-       }
-
-       if (pi->need_update_smu7_dpm_table & (DPMTABLE_OD_UPDATE_MCLK | DPMTABLE_UPDATE_MCLK)) {
-               ret = ci_populate_all_memory_levels(adev);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static int ci_enable_uvd_dpm(struct amdgpu_device *adev, bool enable)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       const struct amdgpu_clock_and_voltage_limits *max_limits;
-       int i;
-
-       if (adev->pm.ac_power)
-               max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
-       else
-               max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_dc;
-
-       if (enable) {
-               pi->dpm_level_enable_mask.uvd_dpm_enable_mask = 0;
-
-               for (i = adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count - 1; i >= 0; i--) {
-                       if (adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v <= max_limits->vddc) {
-                               pi->dpm_level_enable_mask.uvd_dpm_enable_mask |= 1 << i;
-
-                               if (!pi->caps_uvd_dpm)
-                                       break;
-                       }
-               }
-
-               amdgpu_ci_send_msg_to_smc_with_parameter(adev,
-                                                 PPSMC_MSG_UVDDPM_SetEnabledMask,
-                                                 pi->dpm_level_enable_mask.uvd_dpm_enable_mask);
-
-               if (pi->last_mclk_dpm_enable_mask & 0x1) {
-                       pi->uvd_enabled = true;
-                       pi->dpm_level_enable_mask.mclk_dpm_enable_mask &= 0xFFFFFFFE;
-                       amdgpu_ci_send_msg_to_smc_with_parameter(adev,
-                                                         PPSMC_MSG_MCLKDPM_SetEnabledMask,
-                                                         pi->dpm_level_enable_mask.mclk_dpm_enable_mask);
-               }
-       } else {
-               if (pi->uvd_enabled) {
-                       pi->uvd_enabled = false;
-                       pi->dpm_level_enable_mask.mclk_dpm_enable_mask |= 1;
-                       amdgpu_ci_send_msg_to_smc_with_parameter(adev,
-                                                         PPSMC_MSG_MCLKDPM_SetEnabledMask,
-                                                         pi->dpm_level_enable_mask.mclk_dpm_enable_mask);
-               }
-       }
-
-       return (amdgpu_ci_send_msg_to_smc(adev, enable ?
-                                  PPSMC_MSG_UVDDPM_Enable : PPSMC_MSG_UVDDPM_Disable) == PPSMC_Result_OK) ?
-               0 : -EINVAL;
-}
-
-static int ci_enable_vce_dpm(struct amdgpu_device *adev, bool enable)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       const struct amdgpu_clock_and_voltage_limits *max_limits;
-       int i;
-
-       if (adev->pm.ac_power)
-               max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
-       else
-               max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_dc;
-
-       if (enable) {
-               pi->dpm_level_enable_mask.vce_dpm_enable_mask = 0;
-               for (i = adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count - 1; i >= 0; i--) {
-                       if (adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v <= max_limits->vddc) {
-                               pi->dpm_level_enable_mask.vce_dpm_enable_mask |= 1 << i;
-
-                               if (!pi->caps_vce_dpm)
-                                       break;
-                       }
-               }
-
-               amdgpu_ci_send_msg_to_smc_with_parameter(adev,
-                                                 PPSMC_MSG_VCEDPM_SetEnabledMask,
-                                                 pi->dpm_level_enable_mask.vce_dpm_enable_mask);
-       }
-
-       return (amdgpu_ci_send_msg_to_smc(adev, enable ?
-                                  PPSMC_MSG_VCEDPM_Enable : PPSMC_MSG_VCEDPM_Disable) == PPSMC_Result_OK) ?
-               0 : -EINVAL;
-}
-
-#if 0
-static int ci_enable_samu_dpm(struct amdgpu_device *adev, bool enable)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       const struct amdgpu_clock_and_voltage_limits *max_limits;
-       int i;
-
-       if (adev->pm.ac_power)
-               max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
-       else
-               max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_dc;
-
-       if (enable) {
-               pi->dpm_level_enable_mask.samu_dpm_enable_mask = 0;
-               for (i = adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count - 1; i >= 0; i--) {
-                       if (adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v <= max_limits->vddc) {
-                               pi->dpm_level_enable_mask.samu_dpm_enable_mask |= 1 << i;
-
-                               if (!pi->caps_samu_dpm)
-                                       break;
-                       }
-               }
-
-               amdgpu_ci_send_msg_to_smc_with_parameter(adev,
-                                                 PPSMC_MSG_SAMUDPM_SetEnabledMask,
-                                                 pi->dpm_level_enable_mask.samu_dpm_enable_mask);
-       }
-       return (amdgpu_ci_send_msg_to_smc(adev, enable ?
-                                  PPSMC_MSG_SAMUDPM_Enable : PPSMC_MSG_SAMUDPM_Disable) == PPSMC_Result_OK) ?
-               0 : -EINVAL;
-}
-
-static int ci_enable_acp_dpm(struct amdgpu_device *adev, bool enable)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       const struct amdgpu_clock_and_voltage_limits *max_limits;
-       int i;
-
-       if (adev->pm.ac_power)
-               max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
-       else
-               max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_dc;
-
-       if (enable) {
-               pi->dpm_level_enable_mask.acp_dpm_enable_mask = 0;
-               for (i = adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count - 1; i >= 0; i--) {
-                       if (adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v <= max_limits->vddc) {
-                               pi->dpm_level_enable_mask.acp_dpm_enable_mask |= 1 << i;
-
-                               if (!pi->caps_acp_dpm)
-                                       break;
-                       }
-               }
-
-               amdgpu_ci_send_msg_to_smc_with_parameter(adev,
-                                                 PPSMC_MSG_ACPDPM_SetEnabledMask,
-                                                 pi->dpm_level_enable_mask.acp_dpm_enable_mask);
-       }
-
-       return (amdgpu_ci_send_msg_to_smc(adev, enable ?
-                                  PPSMC_MSG_ACPDPM_Enable : PPSMC_MSG_ACPDPM_Disable) == PPSMC_Result_OK) ?
-               0 : -EINVAL;
-}
-#endif
-
-static int ci_update_uvd_dpm(struct amdgpu_device *adev, bool gate)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u32 tmp;
-       int ret = 0;
-
-       if (!gate) {
-               /* turn the clocks on when decoding */
-               if (pi->caps_uvd_dpm ||
-                   (adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count <= 0))
-                       pi->smc_state_table.UvdBootLevel = 0;
-               else
-                       pi->smc_state_table.UvdBootLevel =
-                               adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count - 1;
-
-               tmp = RREG32_SMC(ixDPM_TABLE_475);
-               tmp &= ~DPM_TABLE_475__UvdBootLevel_MASK;
-               tmp |= (pi->smc_state_table.UvdBootLevel << DPM_TABLE_475__UvdBootLevel__SHIFT);
-               WREG32_SMC(ixDPM_TABLE_475, tmp);
-               ret = ci_enable_uvd_dpm(adev, true);
-       } else {
-               ret = ci_enable_uvd_dpm(adev, false);
-               if (ret)
-                       return ret;
-       }
-
-       return ret;
-}
-
-static u8 ci_get_vce_boot_level(struct amdgpu_device *adev)
-{
-       u8 i;
-       u32 min_evclk = 30000; /* ??? */
-       struct amdgpu_vce_clock_voltage_dependency_table *table =
-               &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
-
-       for (i = 0; i < table->count; i++) {
-               if (table->entries[i].evclk >= min_evclk)
-                       return i;
-       }
-
-       return table->count - 1;
-}
-
-static int ci_update_vce_dpm(struct amdgpu_device *adev,
-                            struct amdgpu_ps *amdgpu_new_state,
-                            struct amdgpu_ps *amdgpu_current_state)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       int ret = 0;
-       u32 tmp;
-
-       if (amdgpu_current_state->evclk != amdgpu_new_state->evclk) {
-               if (amdgpu_new_state->evclk) {
-                       pi->smc_state_table.VceBootLevel = ci_get_vce_boot_level(adev);
-                       tmp = RREG32_SMC(ixDPM_TABLE_475);
-                       tmp &= ~DPM_TABLE_475__VceBootLevel_MASK;
-                       tmp |= (pi->smc_state_table.VceBootLevel << DPM_TABLE_475__VceBootLevel__SHIFT);
-                       WREG32_SMC(ixDPM_TABLE_475, tmp);
-
-                       ret = ci_enable_vce_dpm(adev, true);
-               } else {
-                       ret = ci_enable_vce_dpm(adev, false);
-                       if (ret)
-                               return ret;
-               }
-       }
-       return ret;
-}
-
-#if 0
-static int ci_update_samu_dpm(struct amdgpu_device *adev, bool gate)
-{
-       return ci_enable_samu_dpm(adev, gate);
-}
-
-static int ci_update_acp_dpm(struct amdgpu_device *adev, bool gate)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u32 tmp;
-
-       if (!gate) {
-               pi->smc_state_table.AcpBootLevel = 0;
-
-               tmp = RREG32_SMC(ixDPM_TABLE_475);
-               tmp &= ~AcpBootLevel_MASK;
-               tmp |= AcpBootLevel(pi->smc_state_table.AcpBootLevel);
-               WREG32_SMC(ixDPM_TABLE_475, tmp);
-       }
-
-       return ci_enable_acp_dpm(adev, !gate);
-}
-#endif
-
-static int ci_generate_dpm_level_enable_mask(struct amdgpu_device *adev,
-                                            struct amdgpu_ps *amdgpu_state)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       int ret;
-
-       ret = ci_trim_dpm_states(adev, amdgpu_state);
-       if (ret)
-               return ret;
-
-       pi->dpm_level_enable_mask.sclk_dpm_enable_mask =
-               ci_get_dpm_level_enable_mask_value(&pi->dpm_table.sclk_table);
-       pi->dpm_level_enable_mask.mclk_dpm_enable_mask =
-               ci_get_dpm_level_enable_mask_value(&pi->dpm_table.mclk_table);
-       pi->last_mclk_dpm_enable_mask =
-               pi->dpm_level_enable_mask.mclk_dpm_enable_mask;
-       if (pi->uvd_enabled) {
-               if (pi->dpm_level_enable_mask.mclk_dpm_enable_mask & 1)
-                       pi->dpm_level_enable_mask.mclk_dpm_enable_mask &= 0xFFFFFFFE;
-       }
-       pi->dpm_level_enable_mask.pcie_dpm_enable_mask =
-               ci_get_dpm_level_enable_mask_value(&pi->dpm_table.pcie_speed_table);
-
-       return 0;
-}
-
-static u32 ci_get_lowest_enabled_level(struct amdgpu_device *adev,
-                                      u32 level_mask)
-{
-       u32 level = 0;
-
-       while ((level_mask & (1 << level)) == 0)
-               level++;
-
-       return level;
-}
-
-
-static int ci_dpm_force_performance_level(void *handle,
-                                         enum amd_dpm_forced_level level)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u32 tmp, levels, i;
-       int ret;
-
-       if (level == AMD_DPM_FORCED_LEVEL_HIGH) {
-               if ((!pi->pcie_dpm_key_disabled) &&
-                   pi->dpm_level_enable_mask.pcie_dpm_enable_mask) {
-                       levels = 0;
-                       tmp = pi->dpm_level_enable_mask.pcie_dpm_enable_mask;
-                       while (tmp >>= 1)
-                               levels++;
-                       if (levels) {
-                               ret = ci_dpm_force_state_pcie(adev, level);
-                               if (ret)
-                                       return ret;
-                               for (i = 0; i < adev->usec_timeout; i++) {
-                                       tmp = (RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX_1) &
-                                       TARGET_AND_CURRENT_PROFILE_INDEX_1__CURR_PCIE_INDEX_MASK) >>
-                                       TARGET_AND_CURRENT_PROFILE_INDEX_1__CURR_PCIE_INDEX__SHIFT;
-                                       if (tmp == levels)
-                                               break;
-                                       udelay(1);
-                               }
-                       }
-               }
-               if ((!pi->sclk_dpm_key_disabled) &&
-                   pi->dpm_level_enable_mask.sclk_dpm_enable_mask) {
-                       levels = 0;
-                       tmp = pi->dpm_level_enable_mask.sclk_dpm_enable_mask;
-                       while (tmp >>= 1)
-                               levels++;
-                       if (levels) {
-                               ret = ci_dpm_force_state_sclk(adev, levels);
-                               if (ret)
-                                       return ret;
-                               for (i = 0; i < adev->usec_timeout; i++) {
-                                       tmp = (RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX) &
-                                       TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX_MASK) >>
-                                       TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX__SHIFT;
-                                       if (tmp == levels)
-                                               break;
-                                       udelay(1);
-                               }
-                       }
-               }
-               if ((!pi->mclk_dpm_key_disabled) &&
-                   pi->dpm_level_enable_mask.mclk_dpm_enable_mask) {
-                       levels = 0;
-                       tmp = pi->dpm_level_enable_mask.mclk_dpm_enable_mask;
-                       while (tmp >>= 1)
-                               levels++;
-                       if (levels) {
-                               ret = ci_dpm_force_state_mclk(adev, levels);
-                               if (ret)
-                                       return ret;
-                               for (i = 0; i < adev->usec_timeout; i++) {
-                                       tmp = (RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX) &
-                                       TARGET_AND_CURRENT_PROFILE_INDEX__CURR_MCLK_INDEX_MASK) >>
-                                       TARGET_AND_CURRENT_PROFILE_INDEX__CURR_MCLK_INDEX__SHIFT;
-                                       if (tmp == levels)
-                                               break;
-                                       udelay(1);
-                               }
-                       }
-               }
-       } else if (level == AMD_DPM_FORCED_LEVEL_LOW) {
-               if ((!pi->sclk_dpm_key_disabled) &&
-                   pi->dpm_level_enable_mask.sclk_dpm_enable_mask) {
-                       levels = ci_get_lowest_enabled_level(adev,
-                                                            pi->dpm_level_enable_mask.sclk_dpm_enable_mask);
-                       ret = ci_dpm_force_state_sclk(adev, levels);
-                       if (ret)
-                               return ret;
-                       for (i = 0; i < adev->usec_timeout; i++) {
-                               tmp = (RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX) &
-                               TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX_MASK) >>
-                               TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX__SHIFT;
-                               if (tmp == levels)
-                                       break;
-                               udelay(1);
-                       }
-               }
-               if ((!pi->mclk_dpm_key_disabled) &&
-                   pi->dpm_level_enable_mask.mclk_dpm_enable_mask) {
-                       levels = ci_get_lowest_enabled_level(adev,
-                                                            pi->dpm_level_enable_mask.mclk_dpm_enable_mask);
-                       ret = ci_dpm_force_state_mclk(adev, levels);
-                       if (ret)
-                               return ret;
-                       for (i = 0; i < adev->usec_timeout; i++) {
-                               tmp = (RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX) &
-                               TARGET_AND_CURRENT_PROFILE_INDEX__CURR_MCLK_INDEX_MASK) >>
-                               TARGET_AND_CURRENT_PROFILE_INDEX__CURR_MCLK_INDEX__SHIFT;
-                               if (tmp == levels)
-                                       break;
-                               udelay(1);
-                       }
-               }
-               if ((!pi->pcie_dpm_key_disabled) &&
-                   pi->dpm_level_enable_mask.pcie_dpm_enable_mask) {
-                       levels = ci_get_lowest_enabled_level(adev,
-                                                            pi->dpm_level_enable_mask.pcie_dpm_enable_mask);
-                       ret = ci_dpm_force_state_pcie(adev, levels);
-                       if (ret)
-                               return ret;
-                       for (i = 0; i < adev->usec_timeout; i++) {
-                               tmp = (RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX_1) &
-                               TARGET_AND_CURRENT_PROFILE_INDEX_1__CURR_PCIE_INDEX_MASK) >>
-                               TARGET_AND_CURRENT_PROFILE_INDEX_1__CURR_PCIE_INDEX__SHIFT;
-                               if (tmp == levels)
-                                       break;
-                               udelay(1);
-                       }
-               }
-       } else if (level == AMD_DPM_FORCED_LEVEL_AUTO) {
-               if (!pi->pcie_dpm_key_disabled) {
-                       PPSMC_Result smc_result;
-
-                       smc_result = amdgpu_ci_send_msg_to_smc(adev,
-                                                              PPSMC_MSG_PCIeDPM_UnForceLevel);
-                       if (smc_result != PPSMC_Result_OK)
-                               return -EINVAL;
-               }
-               ret = ci_upload_dpm_level_enable_mask(adev);
-               if (ret)
-                       return ret;
-       }
-
-       adev->pm.dpm.forced_level = level;
-
-       return 0;
-}
-
-static int ci_set_mc_special_registers(struct amdgpu_device *adev,
-                                      struct ci_mc_reg_table *table)
-{
-       u8 i, j, k;
-       u32 temp_reg;
-
-       for (i = 0, j = table->last; i < table->last; i++) {
-               if (j >= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE)
-                       return -EINVAL;
-               switch(table->mc_reg_address[i].s1) {
-               case mmMC_SEQ_MISC1:
-                       temp_reg = RREG32(mmMC_PMG_CMD_EMRS);
-                       table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS;
-                       table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP;
-                       for (k = 0; k < table->num_entries; k++) {
-                               table->mc_reg_table_entry[k].mc_data[j] =
-                                       ((temp_reg & 0xffff0000)) | ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16);
-                       }
-                       j++;
-
-                       if (j >= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE)
-                               return -EINVAL;
-                       temp_reg = RREG32(mmMC_PMG_CMD_MRS);
-                       table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS;
-                       table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP;
-                       for (k = 0; k < table->num_entries; k++) {
-                               table->mc_reg_table_entry[k].mc_data[j] =
-                                       (temp_reg & 0xffff0000) | (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
-                               if (adev->gmc.vram_type != AMDGPU_VRAM_TYPE_GDDR5)
-                                       table->mc_reg_table_entry[k].mc_data[j] |= 0x100;
-                       }
-                       j++;
-
-                       if (adev->gmc.vram_type != AMDGPU_VRAM_TYPE_GDDR5) {
-                               if (j >= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE)
-                                       return -EINVAL;
-                               table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD;
-                               table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD;
-                               for (k = 0; k < table->num_entries; k++) {
-                                       table->mc_reg_table_entry[k].mc_data[j] =
-                                               (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16;
-                               }
-                               j++;
-                       }
-                       break;
-               case mmMC_SEQ_RESERVE_M:
-                       temp_reg = RREG32(mmMC_PMG_CMD_MRS1);
-                       table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1;
-                       table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP;
-                       for (k = 0; k < table->num_entries; k++) {
-                               table->mc_reg_table_entry[k].mc_data[j] =
-                                       (temp_reg & 0xffff0000) | (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
-                       }
-                       j++;
-                       break;
-               default:
-                       break;
-               }
-
-       }
-
-       table->last = j;
-
-       return 0;
-}
-
-static bool ci_check_s0_mc_reg_index(u16 in_reg, u16 *out_reg)
-{
-       bool result = true;
-
-       switch(in_reg) {
-       case mmMC_SEQ_RAS_TIMING:
-               *out_reg = mmMC_SEQ_RAS_TIMING_LP;
-               break;
-       case mmMC_SEQ_DLL_STBY:
-               *out_reg = mmMC_SEQ_DLL_STBY_LP;
-               break;
-       case mmMC_SEQ_G5PDX_CMD0:
-               *out_reg = mmMC_SEQ_G5PDX_CMD0_LP;
-               break;
-       case mmMC_SEQ_G5PDX_CMD1:
-               *out_reg = mmMC_SEQ_G5PDX_CMD1_LP;
-               break;
-       case mmMC_SEQ_G5PDX_CTRL:
-               *out_reg = mmMC_SEQ_G5PDX_CTRL_LP;
-               break;
-       case mmMC_SEQ_CAS_TIMING:
-               *out_reg = mmMC_SEQ_CAS_TIMING_LP;
-           break;
-       case mmMC_SEQ_MISC_TIMING:
-               *out_reg = mmMC_SEQ_MISC_TIMING_LP;
-               break;
-       case mmMC_SEQ_MISC_TIMING2:
-               *out_reg = mmMC_SEQ_MISC_TIMING2_LP;
-               break;
-       case mmMC_SEQ_PMG_DVS_CMD:
-               *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP;
-               break;
-       case mmMC_SEQ_PMG_DVS_CTL:
-               *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP;
-               break;
-       case mmMC_SEQ_RD_CTL_D0:
-               *out_reg = mmMC_SEQ_RD_CTL_D0_LP;
-               break;
-       case mmMC_SEQ_RD_CTL_D1:
-               *out_reg = mmMC_SEQ_RD_CTL_D1_LP;
-               break;
-       case mmMC_SEQ_WR_CTL_D0:
-               *out_reg = mmMC_SEQ_WR_CTL_D0_LP;
-               break;
-       case mmMC_SEQ_WR_CTL_D1:
-               *out_reg = mmMC_SEQ_WR_CTL_D1_LP;
-               break;
-       case mmMC_PMG_CMD_EMRS:
-               *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP;
-               break;
-       case mmMC_PMG_CMD_MRS:
-               *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP;
-               break;
-       case mmMC_PMG_CMD_MRS1:
-               *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP;
-               break;
-       case mmMC_SEQ_PMG_TIMING:
-               *out_reg = mmMC_SEQ_PMG_TIMING_LP;
-               break;
-       case mmMC_PMG_CMD_MRS2:
-               *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP;
-               break;
-       case mmMC_SEQ_WR_CTL_2:
-               *out_reg = mmMC_SEQ_WR_CTL_2_LP;
-               break;
-       default:
-               result = false;
-               break;
-       }
-
-       return result;
-}
-
-static void ci_set_valid_flag(struct ci_mc_reg_table *table)
-{
-       u8 i, j;
-
-       for (i = 0; i < table->last; i++) {
-               for (j = 1; j < table->num_entries; j++) {
-                       if (table->mc_reg_table_entry[j-1].mc_data[i] !=
-                           table->mc_reg_table_entry[j].mc_data[i]) {
-                               table->valid_flag |= 1 << i;
-                               break;
-                       }
-               }
-       }
-}
-
-static void ci_set_s0_mc_reg_index(struct ci_mc_reg_table *table)
-{
-       u32 i;
-       u16 address;
-
-       for (i = 0; i < table->last; i++) {
-               table->mc_reg_address[i].s0 =
-                       ci_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) ?
-                       address : table->mc_reg_address[i].s1;
-       }
-}
-
-static int ci_copy_vbios_mc_reg_table(const struct atom_mc_reg_table *table,
-                                     struct ci_mc_reg_table *ci_table)
-{
-       u8 i, j;
-
-       if (table->last > SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE)
-               return -EINVAL;
-       if (table->num_entries > MAX_AC_TIMING_ENTRIES)
-               return -EINVAL;
-
-       for (i = 0; i < table->last; i++)
-               ci_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1;
-
-       ci_table->last = table->last;
-
-       for (i = 0; i < table->num_entries; i++) {
-               ci_table->mc_reg_table_entry[i].mclk_max =
-                       table->mc_reg_table_entry[i].mclk_max;
-               for (j = 0; j < table->last; j++)
-                       ci_table->mc_reg_table_entry[i].mc_data[j] =
-                               table->mc_reg_table_entry[i].mc_data[j];
-       }
-       ci_table->num_entries = table->num_entries;
-
-       return 0;
-}
-
-static int ci_register_patching_mc_seq(struct amdgpu_device *adev,
-                                      struct ci_mc_reg_table *table)
-{
-       u8 i, k;
-       u32 tmp;
-       bool patch;
-
-       tmp = RREG32(mmMC_SEQ_MISC0);
-       patch = ((tmp & 0x0000f00) == 0x300) ? true : false;
-
-       if (patch &&
-           ((adev->pdev->device == 0x67B0) ||
-            (adev->pdev->device == 0x67B1))) {
-               for (i = 0; i < table->last; i++) {
-                       if (table->last >= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE)
-                               return -EINVAL;
-                       switch (table->mc_reg_address[i].s1) {
-                       case mmMC_SEQ_MISC1:
-                               for (k = 0; k < table->num_entries; k++) {
-                                       if ((table->mc_reg_table_entry[k].mclk_max == 125000) ||
-                                           (table->mc_reg_table_entry[k].mclk_max == 137500))
-                                               table->mc_reg_table_entry[k].mc_data[i] =
-                                                       (table->mc_reg_table_entry[k].mc_data[i] & 0xFFFFFFF8) |
-                                                       0x00000007;
-                               }
-                               break;
-                       case mmMC_SEQ_WR_CTL_D0:
-                               for (k = 0; k < table->num_entries; k++) {
-                                       if ((table->mc_reg_table_entry[k].mclk_max == 125000) ||
-                                           (table->mc_reg_table_entry[k].mclk_max == 137500))
-                                               table->mc_reg_table_entry[k].mc_data[i] =
-                                                       (table->mc_reg_table_entry[k].mc_data[i] & 0xFFFF0F00) |
-                                                       0x0000D0DD;
-                               }
-                               break;
-                       case mmMC_SEQ_WR_CTL_D1:
-                               for (k = 0; k < table->num_entries; k++) {
-                                       if ((table->mc_reg_table_entry[k].mclk_max == 125000) ||
-                                           (table->mc_reg_table_entry[k].mclk_max == 137500))
-                                               table->mc_reg_table_entry[k].mc_data[i] =
-                                                       (table->mc_reg_table_entry[k].mc_data[i] & 0xFFFF0F00) |
-                                                       0x0000D0DD;
-                               }
-                               break;
-                       case mmMC_SEQ_WR_CTL_2:
-                               for (k = 0; k < table->num_entries; k++) {
-                                       if ((table->mc_reg_table_entry[k].mclk_max == 125000) ||
-                                           (table->mc_reg_table_entry[k].mclk_max == 137500))
-                                               table->mc_reg_table_entry[k].mc_data[i] = 0;
-                               }
-                               break;
-                       case mmMC_SEQ_CAS_TIMING:
-                               for (k = 0; k < table->num_entries; k++) {
-                                       if (table->mc_reg_table_entry[k].mclk_max == 125000)
-                                               table->mc_reg_table_entry[k].mc_data[i] =
-                                                       (table->mc_reg_table_entry[k].mc_data[i] & 0xFFE0FE0F) |
-                                                       0x000C0140;
-                                       else if (table->mc_reg_table_entry[k].mclk_max == 137500)
-                                               table->mc_reg_table_entry[k].mc_data[i] =
-                                                       (table->mc_reg_table_entry[k].mc_data[i] & 0xFFE0FE0F) |
-                                                       0x000C0150;
-                               }
-                               break;
-                       case mmMC_SEQ_MISC_TIMING:
-                               for (k = 0; k < table->num_entries; k++) {
-                                       if (table->mc_reg_table_entry[k].mclk_max == 125000)
-                                               table->mc_reg_table_entry[k].mc_data[i] =
-                                                       (table->mc_reg_table_entry[k].mc_data[i] & 0xFFFFFFE0) |
-                                                       0x00000030;
-                                       else if (table->mc_reg_table_entry[k].mclk_max == 137500)
-                                               table->mc_reg_table_entry[k].mc_data[i] =
-                                                       (table->mc_reg_table_entry[k].mc_data[i] & 0xFFFFFFE0) |
-                                                       0x00000035;
-                               }
-                               break;
-                       default:
-                               break;
-                       }
-               }
-
-               WREG32(mmMC_SEQ_IO_DEBUG_INDEX, 3);
-               tmp = RREG32(mmMC_SEQ_IO_DEBUG_DATA);
-               tmp = (tmp & 0xFFF8FFFF) | (1 << 16);
-               WREG32(mmMC_SEQ_IO_DEBUG_INDEX, 3);
-               WREG32(mmMC_SEQ_IO_DEBUG_DATA, tmp);
-       }
-
-       return 0;
-}
-
-static int ci_initialize_mc_reg_table(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct atom_mc_reg_table *table;
-       struct ci_mc_reg_table *ci_table = &pi->mc_reg_table;
-       u8 module_index = ci_get_memory_module_index(adev);
-       int ret;
-
-       table = kzalloc(sizeof(struct atom_mc_reg_table), GFP_KERNEL);
-       if (!table)
-               return -ENOMEM;
-
-       WREG32(mmMC_SEQ_RAS_TIMING_LP, RREG32(mmMC_SEQ_RAS_TIMING));
-       WREG32(mmMC_SEQ_CAS_TIMING_LP, RREG32(mmMC_SEQ_CAS_TIMING));
-       WREG32(mmMC_SEQ_DLL_STBY_LP, RREG32(mmMC_SEQ_DLL_STBY));
-       WREG32(mmMC_SEQ_G5PDX_CMD0_LP, RREG32(mmMC_SEQ_G5PDX_CMD0));
-       WREG32(mmMC_SEQ_G5PDX_CMD1_LP, RREG32(mmMC_SEQ_G5PDX_CMD1));
-       WREG32(mmMC_SEQ_G5PDX_CTRL_LP, RREG32(mmMC_SEQ_G5PDX_CTRL));
-       WREG32(mmMC_SEQ_PMG_DVS_CMD_LP, RREG32(mmMC_SEQ_PMG_DVS_CMD));
-       WREG32(mmMC_SEQ_PMG_DVS_CTL_LP, RREG32(mmMC_SEQ_PMG_DVS_CTL));
-       WREG32(mmMC_SEQ_MISC_TIMING_LP, RREG32(mmMC_SEQ_MISC_TIMING));
-       WREG32(mmMC_SEQ_MISC_TIMING2_LP, RREG32(mmMC_SEQ_MISC_TIMING2));
-       WREG32(mmMC_SEQ_PMG_CMD_EMRS_LP, RREG32(mmMC_PMG_CMD_EMRS));
-       WREG32(mmMC_SEQ_PMG_CMD_MRS_LP, RREG32(mmMC_PMG_CMD_MRS));
-       WREG32(mmMC_SEQ_PMG_CMD_MRS1_LP, RREG32(mmMC_PMG_CMD_MRS1));
-       WREG32(mmMC_SEQ_WR_CTL_D0_LP, RREG32(mmMC_SEQ_WR_CTL_D0));
-       WREG32(mmMC_SEQ_WR_CTL_D1_LP, RREG32(mmMC_SEQ_WR_CTL_D1));
-       WREG32(mmMC_SEQ_RD_CTL_D0_LP, RREG32(mmMC_SEQ_RD_CTL_D0));
-       WREG32(mmMC_SEQ_RD_CTL_D1_LP, RREG32(mmMC_SEQ_RD_CTL_D1));
-       WREG32(mmMC_SEQ_PMG_TIMING_LP, RREG32(mmMC_SEQ_PMG_TIMING));
-       WREG32(mmMC_SEQ_PMG_CMD_MRS2_LP, RREG32(mmMC_PMG_CMD_MRS2));
-       WREG32(mmMC_SEQ_WR_CTL_2_LP, RREG32(mmMC_SEQ_WR_CTL_2));
-
-       ret = amdgpu_atombios_init_mc_reg_table(adev, module_index, table);
-       if (ret)
-               goto init_mc_done;
-
-       ret = ci_copy_vbios_mc_reg_table(table, ci_table);
-       if (ret)
-               goto init_mc_done;
-
-       ci_set_s0_mc_reg_index(ci_table);
-
-       ret = ci_register_patching_mc_seq(adev, ci_table);
-       if (ret)
-               goto init_mc_done;
-
-       ret = ci_set_mc_special_registers(adev, ci_table);
-       if (ret)
-               goto init_mc_done;
-
-       ci_set_valid_flag(ci_table);
-
-init_mc_done:
-       kfree(table);
-
-       return ret;
-}
-
-static int ci_populate_mc_reg_addresses(struct amdgpu_device *adev,
-                                       SMU7_Discrete_MCRegisters *mc_reg_table)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u32 i, j;
-
-       for (i = 0, j = 0; j < pi->mc_reg_table.last; j++) {
-               if (pi->mc_reg_table.valid_flag & (1 << j)) {
-                       if (i >= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE)
-                               return -EINVAL;
-                       mc_reg_table->address[i].s0 = cpu_to_be16(pi->mc_reg_table.mc_reg_address[j].s0);
-                       mc_reg_table->address[i].s1 = cpu_to_be16(pi->mc_reg_table.mc_reg_address[j].s1);
-                       i++;
-               }
-       }
-
-       mc_reg_table->last = (u8)i;
-
-       return 0;
-}
-
-static void ci_convert_mc_registers(const struct ci_mc_reg_entry *entry,
-                                   SMU7_Discrete_MCRegisterSet *data,
-                                   u32 num_entries, u32 valid_flag)
-{
-       u32 i, j;
-
-       for (i = 0, j = 0; j < num_entries; j++) {
-               if (valid_flag & (1 << j)) {
-                       data->value[i] = cpu_to_be32(entry->mc_data[j]);
-                       i++;
-               }
-       }
-}
-
-static void ci_convert_mc_reg_table_entry_to_smc(struct amdgpu_device *adev,
-                                                const u32 memory_clock,
-                                                SMU7_Discrete_MCRegisterSet *mc_reg_table_data)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u32 i = 0;
-
-       for(i = 0; i < pi->mc_reg_table.num_entries; i++) {
-               if (memory_clock <= pi->mc_reg_table.mc_reg_table_entry[i].mclk_max)
-                       break;
-       }
-
-       if ((i == pi->mc_reg_table.num_entries) && (i > 0))
-               --i;
-
-       ci_convert_mc_registers(&pi->mc_reg_table.mc_reg_table_entry[i],
-                               mc_reg_table_data, pi->mc_reg_table.last,
-                               pi->mc_reg_table.valid_flag);
-}
-
-static void ci_convert_mc_reg_table_to_smc(struct amdgpu_device *adev,
-                                          SMU7_Discrete_MCRegisters *mc_reg_table)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       u32 i;
-
-       for (i = 0; i < pi->dpm_table.mclk_table.count; i++)
-               ci_convert_mc_reg_table_entry_to_smc(adev,
-                                                    pi->dpm_table.mclk_table.dpm_levels[i].value,
-                                                    &mc_reg_table->data[i]);
-}
-
-static int ci_populate_initial_mc_reg_table(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       int ret;
-
-       memset(&pi->smc_mc_reg_table, 0, sizeof(SMU7_Discrete_MCRegisters));
-
-       ret = ci_populate_mc_reg_addresses(adev, &pi->smc_mc_reg_table);
-       if (ret)
-               return ret;
-       ci_convert_mc_reg_table_to_smc(adev, &pi->smc_mc_reg_table);
-
-       return amdgpu_ci_copy_bytes_to_smc(adev,
-                                   pi->mc_reg_table_start,
-                                   (u8 *)&pi->smc_mc_reg_table,
-                                   sizeof(SMU7_Discrete_MCRegisters),
-                                   pi->sram_end);
-}
-
-static int ci_update_and_upload_mc_reg_table(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       if (!(pi->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK))
-               return 0;
-
-       memset(&pi->smc_mc_reg_table, 0, sizeof(SMU7_Discrete_MCRegisters));
-
-       ci_convert_mc_reg_table_to_smc(adev, &pi->smc_mc_reg_table);
-
-       return amdgpu_ci_copy_bytes_to_smc(adev,
-                                   pi->mc_reg_table_start +
-                                   offsetof(SMU7_Discrete_MCRegisters, data[0]),
-                                   (u8 *)&pi->smc_mc_reg_table.data[0],
-                                   sizeof(SMU7_Discrete_MCRegisterSet) *
-                                   pi->dpm_table.mclk_table.count,
-                                   pi->sram_end);
-}
-
-static void ci_enable_voltage_control(struct amdgpu_device *adev)
-{
-       u32 tmp = RREG32_SMC(ixGENERAL_PWRMGT);
-
-       tmp |= GENERAL_PWRMGT__VOLT_PWRMGT_EN_MASK;
-       WREG32_SMC(ixGENERAL_PWRMGT, tmp);
-}
-
-static enum amdgpu_pcie_gen ci_get_maximum_link_speed(struct amdgpu_device *adev,
-                                                     struct amdgpu_ps *amdgpu_state)
-{
-       struct ci_ps *state = ci_get_ps(amdgpu_state);
-       int i;
-       u16 pcie_speed, max_speed = 0;
-
-       for (i = 0; i < state->performance_level_count; i++) {
-               pcie_speed = state->performance_levels[i].pcie_gen;
-               if (max_speed < pcie_speed)
-                       max_speed = pcie_speed;
-       }
-
-       return max_speed;
-}
-
-static u16 ci_get_current_pcie_speed(struct amdgpu_device *adev)
-{
-       u32 speed_cntl = 0;
-
-       speed_cntl = RREG32_PCIE(ixPCIE_LC_SPEED_CNTL) &
-               PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK;
-       speed_cntl >>= PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
-
-       return (u16)speed_cntl;
-}
-
-static int ci_get_current_pcie_lane_number(struct amdgpu_device *adev)
-{
-       u32 link_width = 0;
-
-       link_width = RREG32_PCIE(ixPCIE_LC_LINK_WIDTH_CNTL) &
-               PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK;
-       link_width >>= PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
-
-       switch (link_width) {
-       case 1:
-               return 1;
-       case 2:
-               return 2;
-       case 3:
-               return 4;
-       case 4:
-               return 8;
-       case 0:
-       case 6:
-       default:
-               return 16;
-       }
-}
-
-static void ci_request_link_speed_change_before_state_change(struct amdgpu_device *adev,
-                                                            struct amdgpu_ps *amdgpu_new_state,
-                                                            struct amdgpu_ps *amdgpu_current_state)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       enum amdgpu_pcie_gen target_link_speed =
-               ci_get_maximum_link_speed(adev, amdgpu_new_state);
-       enum amdgpu_pcie_gen current_link_speed;
-
-       if (pi->force_pcie_gen == AMDGPU_PCIE_GEN_INVALID)
-               current_link_speed = ci_get_maximum_link_speed(adev, amdgpu_current_state);
-       else
-               current_link_speed = pi->force_pcie_gen;
-
-       pi->force_pcie_gen = AMDGPU_PCIE_GEN_INVALID;
-       pi->pspp_notify_required = false;
-       if (target_link_speed > current_link_speed) {
-               switch (target_link_speed) {
-#ifdef CONFIG_ACPI
-               case AMDGPU_PCIE_GEN3:
-                       if (amdgpu_acpi_pcie_performance_request(adev, PCIE_PERF_REQ_PECI_GEN3, false) == 0)
-                               break;
-                       pi->force_pcie_gen = AMDGPU_PCIE_GEN2;
-                       if (current_link_speed == AMDGPU_PCIE_GEN2)
-                               break;
-               case AMDGPU_PCIE_GEN2:
-                       if (amdgpu_acpi_pcie_performance_request(adev, PCIE_PERF_REQ_PECI_GEN2, false) == 0)
-                               break;
-#endif
-               default:
-                       pi->force_pcie_gen = ci_get_current_pcie_speed(adev);
-                       break;
-               }
-       } else {
-               if (target_link_speed < current_link_speed)
-                       pi->pspp_notify_required = true;
-       }
-}
-
-static void ci_notify_link_speed_change_after_state_change(struct amdgpu_device *adev,
-                                                          struct amdgpu_ps *amdgpu_new_state,
-                                                          struct amdgpu_ps *amdgpu_current_state)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       enum amdgpu_pcie_gen target_link_speed =
-               ci_get_maximum_link_speed(adev, amdgpu_new_state);
-       u8 request;
-
-       if (pi->pspp_notify_required) {
-               if (target_link_speed == AMDGPU_PCIE_GEN3)
-                       request = PCIE_PERF_REQ_PECI_GEN3;
-               else if (target_link_speed == AMDGPU_PCIE_GEN2)
-                       request = PCIE_PERF_REQ_PECI_GEN2;
-               else
-                       request = PCIE_PERF_REQ_PECI_GEN1;
-
-               if ((request == PCIE_PERF_REQ_PECI_GEN1) &&
-                   (ci_get_current_pcie_speed(adev) > 0))
-                       return;
-
-#ifdef CONFIG_ACPI
-               amdgpu_acpi_pcie_performance_request(adev, request, false);
-#endif
-       }
-}
-
-static int ci_set_private_data_variables_based_on_pptable(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct amdgpu_clock_voltage_dependency_table *allowed_sclk_vddc_table =
-               &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk;
-       struct amdgpu_clock_voltage_dependency_table *allowed_mclk_vddc_table =
-               &adev->pm.dpm.dyn_state.vddc_dependency_on_mclk;
-       struct amdgpu_clock_voltage_dependency_table *allowed_mclk_vddci_table =
-               &adev->pm.dpm.dyn_state.vddci_dependency_on_mclk;
-
-       if (allowed_sclk_vddc_table == NULL)
-               return -EINVAL;
-       if (allowed_sclk_vddc_table->count < 1)
-               return -EINVAL;
-       if (allowed_mclk_vddc_table == NULL)
-               return -EINVAL;
-       if (allowed_mclk_vddc_table->count < 1)
-               return -EINVAL;
-       if (allowed_mclk_vddci_table == NULL)
-               return -EINVAL;
-       if (allowed_mclk_vddci_table->count < 1)
-               return -EINVAL;
-
-       pi->min_vddc_in_pp_table = allowed_sclk_vddc_table->entries[0].v;
-       pi->max_vddc_in_pp_table =
-               allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].v;
-
-       pi->min_vddci_in_pp_table = allowed_mclk_vddci_table->entries[0].v;
-       pi->max_vddci_in_pp_table =
-               allowed_mclk_vddci_table->entries[allowed_mclk_vddci_table->count - 1].v;
-
-       adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk =
-               allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].clk;
-       adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk =
-               allowed_mclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].clk;
-       adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc =
-               allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].v;
-       adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci =
-               allowed_mclk_vddci_table->entries[allowed_mclk_vddci_table->count - 1].v;
-
-       return 0;
-}
-
-static void ci_patch_with_vddc_leakage(struct amdgpu_device *adev, u16 *vddc)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_leakage_voltage *leakage_table = &pi->vddc_leakage;
-       u32 leakage_index;
-
-       for (leakage_index = 0; leakage_index < leakage_table->count; leakage_index++) {
-               if (leakage_table->leakage_id[leakage_index] == *vddc) {
-                       *vddc = leakage_table->actual_voltage[leakage_index];
-                       break;
-               }
-       }
-}
-
-static void ci_patch_with_vddci_leakage(struct amdgpu_device *adev, u16 *vddci)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_leakage_voltage *leakage_table = &pi->vddci_leakage;
-       u32 leakage_index;
-
-       for (leakage_index = 0; leakage_index < leakage_table->count; leakage_index++) {
-               if (leakage_table->leakage_id[leakage_index] == *vddci) {
-                       *vddci = leakage_table->actual_voltage[leakage_index];
-                       break;
-               }
-       }
-}
-
-static void ci_patch_clock_voltage_dependency_table_with_vddc_leakage(struct amdgpu_device *adev,
-                                                                     struct amdgpu_clock_voltage_dependency_table *table)
-{
-       u32 i;
-
-       if (table) {
-               for (i = 0; i < table->count; i++)
-                       ci_patch_with_vddc_leakage(adev, &table->entries[i].v);
-       }
-}
-
-static void ci_patch_clock_voltage_dependency_table_with_vddci_leakage(struct amdgpu_device *adev,
-                                                                      struct amdgpu_clock_voltage_dependency_table *table)
-{
-       u32 i;
-
-       if (table) {
-               for (i = 0; i < table->count; i++)
-                       ci_patch_with_vddci_leakage(adev, &table->entries[i].v);
-       }
-}
-
-static void ci_patch_vce_clock_voltage_dependency_table_with_vddc_leakage(struct amdgpu_device *adev,
-                                                                         struct amdgpu_vce_clock_voltage_dependency_table *table)
-{
-       u32 i;
-
-       if (table) {
-               for (i = 0; i < table->count; i++)
-                       ci_patch_with_vddc_leakage(adev, &table->entries[i].v);
-       }
-}
-
-static void ci_patch_uvd_clock_voltage_dependency_table_with_vddc_leakage(struct amdgpu_device *adev,
-                                                                         struct amdgpu_uvd_clock_voltage_dependency_table *table)
-{
-       u32 i;
-
-       if (table) {
-               for (i = 0; i < table->count; i++)
-                       ci_patch_with_vddc_leakage(adev, &table->entries[i].v);
-       }
-}
-
-static void ci_patch_vddc_phase_shed_limit_table_with_vddc_leakage(struct amdgpu_device *adev,
-                                                                  struct amdgpu_phase_shedding_limits_table *table)
-{
-       u32 i;
-
-       if (table) {
-               for (i = 0; i < table->count; i++)
-                       ci_patch_with_vddc_leakage(adev, &table->entries[i].voltage);
-       }
-}
-
-static void ci_patch_clock_voltage_limits_with_vddc_leakage(struct amdgpu_device *adev,
-                                                           struct amdgpu_clock_and_voltage_limits *table)
-{
-       if (table) {
-               ci_patch_with_vddc_leakage(adev, (u16 *)&table->vddc);
-               ci_patch_with_vddci_leakage(adev, (u16 *)&table->vddci);
-       }
-}
-
-static void ci_patch_cac_leakage_table_with_vddc_leakage(struct amdgpu_device *adev,
-                                                        struct amdgpu_cac_leakage_table *table)
-{
-       u32 i;
-
-       if (table) {
-               for (i = 0; i < table->count; i++)
-                       ci_patch_with_vddc_leakage(adev, &table->entries[i].vddc);
-       }
-}
-
-static void ci_patch_dependency_tables_with_leakage(struct amdgpu_device *adev)
-{
-
-       ci_patch_clock_voltage_dependency_table_with_vddc_leakage(adev,
-                                                                 &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk);
-       ci_patch_clock_voltage_dependency_table_with_vddc_leakage(adev,
-                                                                 &adev->pm.dpm.dyn_state.vddc_dependency_on_mclk);
-       ci_patch_clock_voltage_dependency_table_with_vddc_leakage(adev,
-                                                                 &adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk);
-       ci_patch_clock_voltage_dependency_table_with_vddci_leakage(adev,
-                                                                  &adev->pm.dpm.dyn_state.vddci_dependency_on_mclk);
-       ci_patch_vce_clock_voltage_dependency_table_with_vddc_leakage(adev,
-                                                                     &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table);
-       ci_patch_uvd_clock_voltage_dependency_table_with_vddc_leakage(adev,
-                                                                     &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table);
-       ci_patch_clock_voltage_dependency_table_with_vddc_leakage(adev,
-                                                                 &adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table);
-       ci_patch_clock_voltage_dependency_table_with_vddc_leakage(adev,
-                                                                 &adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table);
-       ci_patch_vddc_phase_shed_limit_table_with_vddc_leakage(adev,
-                                                              &adev->pm.dpm.dyn_state.phase_shedding_limits_table);
-       ci_patch_clock_voltage_limits_with_vddc_leakage(adev,
-                                                       &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac);
-       ci_patch_clock_voltage_limits_with_vddc_leakage(adev,
-                                                       &adev->pm.dpm.dyn_state.max_clock_voltage_on_dc);
-       ci_patch_cac_leakage_table_with_vddc_leakage(adev,
-                                                    &adev->pm.dpm.dyn_state.cac_leakage_table);
-
-}
-
-static void ci_update_current_ps(struct amdgpu_device *adev,
-                                struct amdgpu_ps *rps)
-{
-       struct ci_ps *new_ps = ci_get_ps(rps);
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       pi->current_rps = *rps;
-       pi->current_ps = *new_ps;
-       pi->current_rps.ps_priv = &pi->current_ps;
-       adev->pm.dpm.current_ps = &pi->current_rps;
-}
-
-static void ci_update_requested_ps(struct amdgpu_device *adev,
-                                  struct amdgpu_ps *rps)
-{
-       struct ci_ps *new_ps = ci_get_ps(rps);
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       pi->requested_rps = *rps;
-       pi->requested_ps = *new_ps;
-       pi->requested_rps.ps_priv = &pi->requested_ps;
-       adev->pm.dpm.requested_ps = &pi->requested_rps;
-}
-
-static int ci_dpm_pre_set_power_state(void *handle)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct amdgpu_ps requested_ps = *adev->pm.dpm.requested_ps;
-       struct amdgpu_ps *new_ps = &requested_ps;
-
-       ci_update_requested_ps(adev, new_ps);
-
-       ci_apply_state_adjust_rules(adev, &pi->requested_rps);
-
-       return 0;
-}
-
-static void ci_dpm_post_set_power_state(void *handle)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct amdgpu_ps *new_ps = &pi->requested_rps;
-
-       ci_update_current_ps(adev, new_ps);
-}
-
-
-static void ci_dpm_setup_asic(struct amdgpu_device *adev)
-{
-       ci_read_clock_registers(adev);
-       ci_enable_acpi_power_management(adev);
-       ci_init_sclk_t(adev);
-}
-
-static int ci_dpm_enable(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct amdgpu_ps *boot_ps = adev->pm.dpm.boot_ps;
-       int ret;
-
-       if (pi->voltage_control != CISLANDS_VOLTAGE_CONTROL_NONE) {
-               ci_enable_voltage_control(adev);
-               ret = ci_construct_voltage_tables(adev);
-               if (ret) {
-                       DRM_ERROR("ci_construct_voltage_tables failed\n");
-                       return ret;
-               }
-       }
-       if (pi->caps_dynamic_ac_timing) {
-               ret = ci_initialize_mc_reg_table(adev);
-               if (ret)
-                       pi->caps_dynamic_ac_timing = false;
-       }
-       if (pi->dynamic_ss)
-               ci_enable_spread_spectrum(adev, true);
-       if (pi->thermal_protection)
-               ci_enable_thermal_protection(adev, true);
-       ci_program_sstp(adev);
-       ci_enable_display_gap(adev);
-       ci_program_vc(adev);
-       ret = ci_upload_firmware(adev);
-       if (ret) {
-               DRM_ERROR("ci_upload_firmware failed\n");
-               return ret;
-       }
-       ret = ci_process_firmware_header(adev);
-       if (ret) {
-               DRM_ERROR("ci_process_firmware_header failed\n");
-               return ret;
-       }
-       ret = ci_initial_switch_from_arb_f0_to_f1(adev);
-       if (ret) {
-               DRM_ERROR("ci_initial_switch_from_arb_f0_to_f1 failed\n");
-               return ret;
-       }
-       ret = ci_init_smc_table(adev);
-       if (ret) {
-               DRM_ERROR("ci_init_smc_table failed\n");
-               return ret;
-       }
-       ret = ci_init_arb_table_index(adev);
-       if (ret) {
-               DRM_ERROR("ci_init_arb_table_index failed\n");
-               return ret;
-       }
-       if (pi->caps_dynamic_ac_timing) {
-               ret = ci_populate_initial_mc_reg_table(adev);
-               if (ret) {
-                       DRM_ERROR("ci_populate_initial_mc_reg_table failed\n");
-                       return ret;
-               }
-       }
-       ret = ci_populate_pm_base(adev);
-       if (ret) {
-               DRM_ERROR("ci_populate_pm_base failed\n");
-               return ret;
-       }
-       ci_dpm_start_smc(adev);
-       ci_enable_vr_hot_gpio_interrupt(adev);
-       ret = ci_notify_smc_display_change(adev, false);
-       if (ret) {
-               DRM_ERROR("ci_notify_smc_display_change failed\n");
-               return ret;
-       }
-       ci_enable_sclk_control(adev, true);
-       ret = ci_enable_ulv(adev, true);
-       if (ret) {
-               DRM_ERROR("ci_enable_ulv failed\n");
-               return ret;
-       }
-       ret = ci_enable_ds_master_switch(adev, true);
-       if (ret) {
-               DRM_ERROR("ci_enable_ds_master_switch failed\n");
-               return ret;
-       }
-       ret = ci_start_dpm(adev);
-       if (ret) {
-               DRM_ERROR("ci_start_dpm failed\n");
-               return ret;
-       }
-       ret = ci_enable_didt(adev, true);
-       if (ret) {
-               DRM_ERROR("ci_enable_didt failed\n");
-               return ret;
-       }
-       ret = ci_enable_smc_cac(adev, true);
-       if (ret) {
-               DRM_ERROR("ci_enable_smc_cac failed\n");
-               return ret;
-       }
-       ret = ci_enable_power_containment(adev, true);
-       if (ret) {
-               DRM_ERROR("ci_enable_power_containment failed\n");
-               return ret;
-       }
-
-       ret = ci_power_control_set_level(adev);
-       if (ret) {
-               DRM_ERROR("ci_power_control_set_level failed\n");
-               return ret;
-       }
-
-       ci_enable_auto_throttle_source(adev, AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
-
-       ret = ci_enable_thermal_based_sclk_dpm(adev, true);
-       if (ret) {
-               DRM_ERROR("ci_enable_thermal_based_sclk_dpm failed\n");
-               return ret;
-       }
-
-       ci_thermal_start_thermal_controller(adev);
-
-       ci_update_current_ps(adev, boot_ps);
-
-       return 0;
-}
-
-static void ci_dpm_disable(struct amdgpu_device *adev)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct amdgpu_ps *boot_ps = adev->pm.dpm.boot_ps;
-
-       amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq,
-                      AMDGPU_THERMAL_IRQ_LOW_TO_HIGH);
-       amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq,
-                      AMDGPU_THERMAL_IRQ_HIGH_TO_LOW);
-
-       ci_dpm_powergate_uvd(adev, true);
-
-       if (!amdgpu_ci_is_smc_running(adev))
-               return;
-
-       ci_thermal_stop_thermal_controller(adev);
-
-       if (pi->thermal_protection)
-               ci_enable_thermal_protection(adev, false);
-       ci_enable_power_containment(adev, false);
-       ci_enable_smc_cac(adev, false);
-       ci_enable_didt(adev, false);
-       ci_enable_spread_spectrum(adev, false);
-       ci_enable_auto_throttle_source(adev, AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, false);
-       ci_stop_dpm(adev);
-       ci_enable_ds_master_switch(adev, false);
-       ci_enable_ulv(adev, false);
-       ci_clear_vc(adev);
-       ci_reset_to_default(adev);
-       ci_dpm_stop_smc(adev);
-       ci_force_switch_to_arb_f0(adev);
-       ci_enable_thermal_based_sclk_dpm(adev, false);
-
-       ci_update_current_ps(adev, boot_ps);
-}
-
-static int ci_dpm_set_power_state(void *handle)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct amdgpu_ps *new_ps = &pi->requested_rps;
-       struct amdgpu_ps *old_ps = &pi->current_rps;
-       int ret;
-
-       ci_find_dpm_states_clocks_in_dpm_table(adev, new_ps);
-       if (pi->pcie_performance_request)
-               ci_request_link_speed_change_before_state_change(adev, new_ps, old_ps);
-       ret = ci_freeze_sclk_mclk_dpm(adev);
-       if (ret) {
-               DRM_ERROR("ci_freeze_sclk_mclk_dpm failed\n");
-               return ret;
-       }
-       ret = ci_populate_and_upload_sclk_mclk_dpm_levels(adev, new_ps);
-       if (ret) {
-               DRM_ERROR("ci_populate_and_upload_sclk_mclk_dpm_levels failed\n");
-               return ret;
-       }
-       ret = ci_generate_dpm_level_enable_mask(adev, new_ps);
-       if (ret) {
-               DRM_ERROR("ci_generate_dpm_level_enable_mask failed\n");
-               return ret;
-       }
-
-       ret = ci_update_vce_dpm(adev, new_ps, old_ps);
-       if (ret) {
-               DRM_ERROR("ci_update_vce_dpm failed\n");
-               return ret;
-       }
-
-       ret = ci_update_sclk_t(adev);
-       if (ret) {
-               DRM_ERROR("ci_update_sclk_t failed\n");
-               return ret;
-       }
-       if (pi->caps_dynamic_ac_timing) {
-               ret = ci_update_and_upload_mc_reg_table(adev);
-               if (ret) {
-                       DRM_ERROR("ci_update_and_upload_mc_reg_table failed\n");
-                       return ret;
-               }
-       }
-       ret = ci_program_memory_timing_parameters(adev);
-       if (ret) {
-               DRM_ERROR("ci_program_memory_timing_parameters failed\n");
-               return ret;
-       }
-       ret = ci_unfreeze_sclk_mclk_dpm(adev);
-       if (ret) {
-               DRM_ERROR("ci_unfreeze_sclk_mclk_dpm failed\n");
-               return ret;
-       }
-       ret = ci_upload_dpm_level_enable_mask(adev);
-       if (ret) {
-               DRM_ERROR("ci_upload_dpm_level_enable_mask failed\n");
-               return ret;
-       }
-       if (pi->pcie_performance_request)
-               ci_notify_link_speed_change_after_state_change(adev, new_ps, old_ps);
-
-       return 0;
-}
-
-#if 0
-static void ci_dpm_reset_asic(struct amdgpu_device *adev)
-{
-       ci_set_boot_state(adev);
-}
-#endif
-
-static void ci_dpm_display_configuration_changed(void *handle)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       ci_program_display_gap(adev);
-}
-
-union power_info {
-       struct _ATOM_POWERPLAY_INFO info;
-       struct _ATOM_POWERPLAY_INFO_V2 info_2;
-       struct _ATOM_POWERPLAY_INFO_V3 info_3;
-       struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
-       struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
-       struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
-};
-
-union pplib_clock_info {
-       struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
-       struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
-       struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
-       struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
-       struct _ATOM_PPLIB_SI_CLOCK_INFO si;
-       struct _ATOM_PPLIB_CI_CLOCK_INFO ci;
-};
-
-union pplib_power_state {
-       struct _ATOM_PPLIB_STATE v1;
-       struct _ATOM_PPLIB_STATE_V2 v2;
-};
-
-static void ci_parse_pplib_non_clock_info(struct amdgpu_device *adev,
-                                         struct amdgpu_ps *rps,
-                                         struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
-                                         u8 table_rev)
-{
-       rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
-       rps->class = le16_to_cpu(non_clock_info->usClassification);
-       rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
-
-       if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
-               rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
-               rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
-       } else {
-               rps->vclk = 0;
-               rps->dclk = 0;
-       }
-
-       if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT)
-               adev->pm.dpm.boot_ps = rps;
-       if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
-               adev->pm.dpm.uvd_ps = rps;
-}
-
-static void ci_parse_pplib_clock_info(struct amdgpu_device *adev,
-                                     struct amdgpu_ps *rps, int index,
-                                     union pplib_clock_info *clock_info)
-{
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_ps *ps = ci_get_ps(rps);
-       struct ci_pl *pl = &ps->performance_levels[index];
-
-       ps->performance_level_count = index + 1;
-
-       pl->sclk = le16_to_cpu(clock_info->ci.usEngineClockLow);
-       pl->sclk |= clock_info->ci.ucEngineClockHigh << 16;
-       pl->mclk = le16_to_cpu(clock_info->ci.usMemoryClockLow);
-       pl->mclk |= clock_info->ci.ucMemoryClockHigh << 16;
-
-       pl->pcie_gen = amdgpu_get_pcie_gen_support(adev,
-                                                  pi->sys_pcie_mask,
-                                                  pi->vbios_boot_state.pcie_gen_bootup_value,
-                                                  clock_info->ci.ucPCIEGen);
-       pl->pcie_lane = amdgpu_get_pcie_lane_support(adev,
-                                                    pi->vbios_boot_state.pcie_lane_bootup_value,
-                                                    le16_to_cpu(clock_info->ci.usPCIELane));
-
-       if (rps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) {
-               pi->acpi_pcie_gen = pl->pcie_gen;
-       }
-
-       if (rps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) {
-               pi->ulv.supported = true;
-               pi->ulv.pl = *pl;
-               pi->ulv.cg_ulv_parameter = CISLANDS_CGULVPARAMETER_DFLT;
-       }
-
-       /* patch up boot state */
-       if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
-               pl->mclk = pi->vbios_boot_state.mclk_bootup_value;
-               pl->sclk = pi->vbios_boot_state.sclk_bootup_value;
-               pl->pcie_gen = pi->vbios_boot_state.pcie_gen_bootup_value;
-               pl->pcie_lane = pi->vbios_boot_state.pcie_lane_bootup_value;
-       }
-
-       switch (rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {
-       case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY:
-               pi->use_pcie_powersaving_levels = true;
-               if (pi->pcie_gen_powersaving.max < pl->pcie_gen)
-                       pi->pcie_gen_powersaving.max = pl->pcie_gen;
-               if (pi->pcie_gen_powersaving.min > pl->pcie_gen)
-                       pi->pcie_gen_powersaving.min = pl->pcie_gen;
-               if (pi->pcie_lane_powersaving.max < pl->pcie_lane)
-                       pi->pcie_lane_powersaving.max = pl->pcie_lane;
-               if (pi->pcie_lane_powersaving.min > pl->pcie_lane)
-                       pi->pcie_lane_powersaving.min = pl->pcie_lane;
-               break;
-       case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE:
-               pi->use_pcie_performance_levels = true;
-               if (pi->pcie_gen_performance.max < pl->pcie_gen)
-                       pi->pcie_gen_performance.max = pl->pcie_gen;
-               if (pi->pcie_gen_performance.min > pl->pcie_gen)
-                       pi->pcie_gen_performance.min = pl->pcie_gen;
-               if (pi->pcie_lane_performance.max < pl->pcie_lane)
-                       pi->pcie_lane_performance.max = pl->pcie_lane;
-               if (pi->pcie_lane_performance.min > pl->pcie_lane)
-                       pi->pcie_lane_performance.min = pl->pcie_lane;
-               break;
-       default:
-               break;
-       }
-}
-
-static int ci_parse_power_table(struct amdgpu_device *adev)
-{
-       struct amdgpu_mode_info *mode_info = &adev->mode_info;
-       struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
-       union pplib_power_state *power_state;
-       int i, j, k, non_clock_array_index, clock_array_index;
-       union pplib_clock_info *clock_info;
-       struct _StateArray *state_array;
-       struct _ClockInfoArray *clock_info_array;
-       struct _NonClockInfoArray *non_clock_info_array;
-       union power_info *power_info;
-       int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
-       u16 data_offset;
-       u8 frev, crev;
-       u8 *power_state_offset;
-       struct ci_ps *ps;
-
-       if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
-                                  &frev, &crev, &data_offset))
-               return -EINVAL;
-       power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
-
-       amdgpu_add_thermal_controller(adev);
-
-       state_array = (struct _StateArray *)
-               (mode_info->atom_context->bios + data_offset +
-                le16_to_cpu(power_info->pplib.usStateArrayOffset));
-       clock_info_array = (struct _ClockInfoArray *)
-               (mode_info->atom_context->bios + data_offset +
-                le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
-       non_clock_info_array = (struct _NonClockInfoArray *)
-               (mode_info->atom_context->bios + data_offset +
-                le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
-
-       adev->pm.dpm.ps = kcalloc(state_array->ucNumEntries,
-                                 sizeof(struct amdgpu_ps),
-                                 GFP_KERNEL);
-       if (!adev->pm.dpm.ps)
-               return -ENOMEM;
-       power_state_offset = (u8 *)state_array->states;
-       for (i = 0; i < state_array->ucNumEntries; i++) {
-               u8 *idx;
-               power_state = (union pplib_power_state *)power_state_offset;
-               non_clock_array_index = power_state->v2.nonClockInfoIndex;
-               non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
-                       &non_clock_info_array->nonClockInfo[non_clock_array_index];
-               ps = kzalloc(sizeof(struct ci_ps), GFP_KERNEL);
-               if (ps == NULL) {
-                       kfree(adev->pm.dpm.ps);
-                       return -ENOMEM;
-               }
-               adev->pm.dpm.ps[i].ps_priv = ps;
-               ci_parse_pplib_non_clock_info(adev, &adev->pm.dpm.ps[i],
-                                             non_clock_info,
-                                             non_clock_info_array->ucEntrySize);
-               k = 0;
-               idx = (u8 *)&power_state->v2.clockInfoIndex[0];
-               for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
-                       clock_array_index = idx[j];
-                       if (clock_array_index >= clock_info_array->ucNumEntries)
-                               continue;
-                       if (k >= CISLANDS_MAX_HARDWARE_POWERLEVELS)
-                               break;
-                       clock_info = (union pplib_clock_info *)
-                               ((u8 *)&clock_info_array->clockInfo[0] +
-                                (clock_array_index * clock_info_array->ucEntrySize));
-                       ci_parse_pplib_clock_info(adev,
-                                                 &adev->pm.dpm.ps[i], k,
-                                                 clock_info);
-                       k++;
-               }
-               power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
-       }
-       adev->pm.dpm.num_ps = state_array->ucNumEntries;
-
-       /* fill in the vce power states */
-       for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {
-               u32 sclk, mclk;
-               clock_array_index = adev->pm.dpm.vce_states[i].clk_idx;
-               clock_info = (union pplib_clock_info *)
-                       &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
-               sclk = le16_to_cpu(clock_info->ci.usEngineClockLow);
-               sclk |= clock_info->ci.ucEngineClockHigh << 16;
-               mclk = le16_to_cpu(clock_info->ci.usMemoryClockLow);
-               mclk |= clock_info->ci.ucMemoryClockHigh << 16;
-               adev->pm.dpm.vce_states[i].sclk = sclk;
-               adev->pm.dpm.vce_states[i].mclk = mclk;
-       }
-
-       return 0;
-}
-
-static int ci_get_vbios_boot_values(struct amdgpu_device *adev,
-                                   struct ci_vbios_boot_state *boot_state)
-{
-       struct amdgpu_mode_info *mode_info = &adev->mode_info;
-       int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
-       ATOM_FIRMWARE_INFO_V2_2 *firmware_info;
-       u8 frev, crev;
-       u16 data_offset;
-
-       if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
-                                  &frev, &crev, &data_offset)) {
-               firmware_info =
-                       (ATOM_FIRMWARE_INFO_V2_2 *)(mode_info->atom_context->bios +
-                                                   data_offset);
-               boot_state->mvdd_bootup_value = le16_to_cpu(firmware_info->usBootUpMVDDCVoltage);
-               boot_state->vddc_bootup_value = le16_to_cpu(firmware_info->usBootUpVDDCVoltage);
-               boot_state->vddci_bootup_value = le16_to_cpu(firmware_info->usBootUpVDDCIVoltage);
-               boot_state->pcie_gen_bootup_value = ci_get_current_pcie_speed(adev);
-               boot_state->pcie_lane_bootup_value = ci_get_current_pcie_lane_number(adev);
-               boot_state->sclk_bootup_value = le32_to_cpu(firmware_info->ulDefaultEngineClock);
-               boot_state->mclk_bootup_value = le32_to_cpu(firmware_info->ulDefaultMemoryClock);
-
-               return 0;
-       }
-       return -EINVAL;
-}
-
-static void ci_dpm_fini(struct amdgpu_device *adev)
-{
-       int i;
-
-       for (i = 0; i < adev->pm.dpm.num_ps; i++) {
-               kfree(adev->pm.dpm.ps[i].ps_priv);
-       }
-       kfree(adev->pm.dpm.ps);
-       kfree(adev->pm.dpm.priv);
-       kfree(adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries);
-       amdgpu_free_extended_power_table(adev);
-}
-
-/**
- * ci_dpm_init_microcode - load ucode images from disk
- *
- * @adev: amdgpu_device pointer
- *
- * Use the firmware interface to load the ucode images into
- * the driver (not loaded into hw).
- * Returns 0 on success, error on failure.
- */
-static int ci_dpm_init_microcode(struct amdgpu_device *adev)
-{
-       const char *chip_name;
-       char fw_name[30];
-       int err;
-
-       DRM_DEBUG("\n");
-
-       switch (adev->asic_type) {
-       case CHIP_BONAIRE:
-               if ((adev->pdev->revision == 0x80) ||
-                   (adev->pdev->revision == 0x81) ||
-                   (adev->pdev->device == 0x665f))
-                       chip_name = "bonaire_k";
-               else
-                       chip_name = "bonaire";
-               break;
-       case CHIP_HAWAII:
-               if (adev->pdev->revision == 0x80)
-                       chip_name = "hawaii_k";
-               else
-                       chip_name = "hawaii";
-               break;
-       case CHIP_KAVERI:
-       case CHIP_KABINI:
-       case CHIP_MULLINS:
-       default: BUG();
-       }
-
-       snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_smc.bin", chip_name);
-       err = request_firmware(&adev->pm.fw, fw_name, adev->dev);
-       if (err)
-               goto out;
-       err = amdgpu_ucode_validate(adev->pm.fw);
-
-out:
-       if (err) {
-               pr_err("cik_smc: Failed to load firmware \"%s\"\n", fw_name);
-               release_firmware(adev->pm.fw);
-               adev->pm.fw = NULL;
-       }
-       return err;
-}
-
-static int ci_dpm_init(struct amdgpu_device *adev)
-{
-       int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info);
-       SMU7_Discrete_DpmTable *dpm_table;
-       struct amdgpu_gpio_rec gpio;
-       u16 data_offset, size;
-       u8 frev, crev;
-       struct ci_power_info *pi;
-       int ret;
-
-       pi = kzalloc(sizeof(struct ci_power_info), GFP_KERNEL);
-       if (pi == NULL)
-               return -ENOMEM;
-       adev->pm.dpm.priv = pi;
-
-       pi->sys_pcie_mask =
-               adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_MASK;
-
-       pi->force_pcie_gen = AMDGPU_PCIE_GEN_INVALID;
-
-       pi->pcie_gen_performance.max = AMDGPU_PCIE_GEN1;
-       pi->pcie_gen_performance.min = AMDGPU_PCIE_GEN3;
-       pi->pcie_gen_powersaving.max = AMDGPU_PCIE_GEN1;
-       pi->pcie_gen_powersaving.min = AMDGPU_PCIE_GEN3;
-
-       pi->pcie_lane_performance.max = 0;
-       pi->pcie_lane_performance.min = 16;
-       pi->pcie_lane_powersaving.max = 0;
-       pi->pcie_lane_powersaving.min = 16;
-
-       ret = ci_get_vbios_boot_values(adev, &pi->vbios_boot_state);
-       if (ret) {
-               ci_dpm_fini(adev);
-               return ret;
-       }
-
-       ret = amdgpu_get_platform_caps(adev);
-       if (ret) {
-               ci_dpm_fini(adev);
-               return ret;
-       }
-
-       ret = amdgpu_parse_extended_power_table(adev);
-       if (ret) {
-               ci_dpm_fini(adev);
-               return ret;
-       }
-
-       ret = ci_parse_power_table(adev);
-       if (ret) {
-               ci_dpm_fini(adev);
-               return ret;
-       }
-
-       pi->dll_default_on = false;
-       pi->sram_end = SMC_RAM_END;
-
-       pi->activity_target[0] = CISLAND_TARGETACTIVITY_DFLT;
-       pi->activity_target[1] = CISLAND_TARGETACTIVITY_DFLT;
-       pi->activity_target[2] = CISLAND_TARGETACTIVITY_DFLT;
-       pi->activity_target[3] = CISLAND_TARGETACTIVITY_DFLT;
-       pi->activity_target[4] = CISLAND_TARGETACTIVITY_DFLT;
-       pi->activity_target[5] = CISLAND_TARGETACTIVITY_DFLT;
-       pi->activity_target[6] = CISLAND_TARGETACTIVITY_DFLT;
-       pi->activity_target[7] = CISLAND_TARGETACTIVITY_DFLT;
-
-       pi->mclk_activity_target = CISLAND_MCLK_TARGETACTIVITY_DFLT;
-
-       pi->sclk_dpm_key_disabled = 0;
-       pi->mclk_dpm_key_disabled = 0;
-       pi->pcie_dpm_key_disabled = 0;
-       pi->thermal_sclk_dpm_enabled = 0;
-
-       if (adev->powerplay.pp_feature & PP_SCLK_DEEP_SLEEP_MASK)
-               pi->caps_sclk_ds = true;
-       else
-               pi->caps_sclk_ds = false;
-
-       pi->mclk_strobe_mode_threshold = 40000;
-       pi->mclk_stutter_mode_threshold = 40000;
-       pi->mclk_edc_enable_threshold = 40000;
-       pi->mclk_edc_wr_enable_threshold = 40000;
-
-       ci_initialize_powertune_defaults(adev);
-
-       pi->caps_fps = false;
-
-       pi->caps_sclk_throttle_low_notification = false;
-
-       pi->caps_uvd_dpm = true;
-       pi->caps_vce_dpm = true;
-
-       ci_get_leakage_voltages(adev);
-       ci_patch_dependency_tables_with_leakage(adev);
-       ci_set_private_data_variables_based_on_pptable(adev);
-
-       adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries =
-               kcalloc(4,
-                       sizeof(struct amdgpu_clock_voltage_dependency_entry),
-                       GFP_KERNEL);
-       if (!adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) {
-               ci_dpm_fini(adev);
-               return -ENOMEM;
-       }
-       adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count = 4;
-       adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].clk = 0;
-       adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].v = 0;
-       adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].clk = 36000;
-       adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].v = 720;
-       adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].clk = 54000;
-       adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].v = 810;
-       adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].clk = 72000;
-       adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].v = 900;
-
-       adev->pm.dpm.dyn_state.mclk_sclk_ratio = 4;
-       adev->pm.dpm.dyn_state.sclk_mclk_delta = 15000;
-       adev->pm.dpm.dyn_state.vddc_vddci_delta = 200;
-
-       adev->pm.dpm.dyn_state.valid_sclk_values.count = 0;
-       adev->pm.dpm.dyn_state.valid_sclk_values.values = NULL;
-       adev->pm.dpm.dyn_state.valid_mclk_values.count = 0;
-       adev->pm.dpm.dyn_state.valid_mclk_values.values = NULL;
-
-       if (adev->asic_type == CHIP_HAWAII) {
-               pi->thermal_temp_setting.temperature_low = 94500;
-               pi->thermal_temp_setting.temperature_high = 95000;
-               pi->thermal_temp_setting.temperature_shutdown = 104000;
-       } else {
-               pi->thermal_temp_setting.temperature_low = 99500;
-               pi->thermal_temp_setting.temperature_high = 100000;
-               pi->thermal_temp_setting.temperature_shutdown = 104000;
-       }
-
-       pi->uvd_enabled = false;
-
-       dpm_table = &pi->smc_state_table;
-
-       gpio = amdgpu_atombios_lookup_gpio(adev, VDDC_VRHOT_GPIO_PINID);
-       if (gpio.valid) {
-               dpm_table->VRHotGpio = gpio.shift;
-               adev->pm.dpm.platform_caps |= ATOM_PP_PLATFORM_CAP_REGULATOR_HOT;
-       } else {
-               dpm_table->VRHotGpio = CISLANDS_UNUSED_GPIO_PIN;
-               adev->pm.dpm.platform_caps &= ~ATOM_PP_PLATFORM_CAP_REGULATOR_HOT;
-       }
-
-       gpio = amdgpu_atombios_lookup_gpio(adev, PP_AC_DC_SWITCH_GPIO_PINID);
-       if (gpio.valid) {
-               dpm_table->AcDcGpio = gpio.shift;
-               adev->pm.dpm.platform_caps |= ATOM_PP_PLATFORM_CAP_HARDWAREDC;
-       } else {
-               dpm_table->AcDcGpio = CISLANDS_UNUSED_GPIO_PIN;
-               adev->pm.dpm.platform_caps &= ~ATOM_PP_PLATFORM_CAP_HARDWAREDC;
-       }
-
-       gpio = amdgpu_atombios_lookup_gpio(adev, VDDC_PCC_GPIO_PINID);
-       if (gpio.valid) {
-               u32 tmp = RREG32_SMC(ixCNB_PWRMGT_CNTL);
-
-               switch (gpio.shift) {
-               case 0:
-                       tmp &= ~CNB_PWRMGT_CNTL__GNB_SLOW_MODE_MASK;
-                       tmp |= 1 << CNB_PWRMGT_CNTL__GNB_SLOW_MODE__SHIFT;
-                       break;
-               case 1:
-                       tmp &= ~CNB_PWRMGT_CNTL__GNB_SLOW_MODE_MASK;
-                       tmp |= 2 << CNB_PWRMGT_CNTL__GNB_SLOW_MODE__SHIFT;
-                       break;
-               case 2:
-                       tmp |= CNB_PWRMGT_CNTL__GNB_SLOW_MASK;
-                       break;
-               case 3:
-                       tmp |= CNB_PWRMGT_CNTL__FORCE_NB_PS1_MASK;
-                       break;
-               case 4:
-                       tmp |= CNB_PWRMGT_CNTL__DPM_ENABLED_MASK;
-                       break;
-               default:
-                       DRM_INFO("Invalid PCC GPIO: %u!\n", gpio.shift);
-                       break;
-               }
-               WREG32_SMC(ixCNB_PWRMGT_CNTL, tmp);
-       }
-
-       pi->voltage_control = CISLANDS_VOLTAGE_CONTROL_NONE;
-       pi->vddci_control = CISLANDS_VOLTAGE_CONTROL_NONE;
-       pi->mvdd_control = CISLANDS_VOLTAGE_CONTROL_NONE;
-       if (amdgpu_atombios_is_voltage_gpio(adev, VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_GPIO_LUT))
-               pi->voltage_control = CISLANDS_VOLTAGE_CONTROL_BY_GPIO;
-       else if (amdgpu_atombios_is_voltage_gpio(adev, VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2))
-               pi->voltage_control = CISLANDS_VOLTAGE_CONTROL_BY_SVID2;
-
-       if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL) {
-               if (amdgpu_atombios_is_voltage_gpio(adev, VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT))
-                       pi->vddci_control = CISLANDS_VOLTAGE_CONTROL_BY_GPIO;
-               else if (amdgpu_atombios_is_voltage_gpio(adev, VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_SVID2))
-                       pi->vddci_control = CISLANDS_VOLTAGE_CONTROL_BY_SVID2;
-               else
-                       adev->pm.dpm.platform_caps &= ~ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL;
-       }
-
-       if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_MVDDCONTROL) {
-               if (amdgpu_atombios_is_voltage_gpio(adev, VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT))
-                       pi->mvdd_control = CISLANDS_VOLTAGE_CONTROL_BY_GPIO;
-               else if (amdgpu_atombios_is_voltage_gpio(adev, VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2))
-                       pi->mvdd_control = CISLANDS_VOLTAGE_CONTROL_BY_SVID2;
-               else
-                       adev->pm.dpm.platform_caps &= ~ATOM_PP_PLATFORM_CAP_MVDDCONTROL;
-       }
-
-       pi->vddc_phase_shed_control = true;
-
-#if defined(CONFIG_ACPI)
-       pi->pcie_performance_request =
-               amdgpu_acpi_is_pcie_performance_request_supported(adev);
-#else
-       pi->pcie_performance_request = false;
-#endif
-
-       if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, &size,
-                                  &frev, &crev, &data_offset)) {
-               pi->caps_sclk_ss_support = true;
-               pi->caps_mclk_ss_support = true;
-               pi->dynamic_ss = true;
-       } else {
-               pi->caps_sclk_ss_support = false;
-               pi->caps_mclk_ss_support = false;
-               pi->dynamic_ss = true;
-       }
-
-       if (adev->pm.int_thermal_type != THERMAL_TYPE_NONE)
-               pi->thermal_protection = true;
-       else
-               pi->thermal_protection = false;
-
-       pi->caps_dynamic_ac_timing = true;
-
-       pi->uvd_power_gated = true;
-
-       /* make sure dc limits are valid */
-       if ((adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk == 0) ||
-           (adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk == 0))
-               adev->pm.dpm.dyn_state.max_clock_voltage_on_dc =
-                       adev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
-
-       pi->fan_ctrl_is_in_default_mode = true;
-
-       return 0;
-}
-
-static void
-ci_dpm_debugfs_print_current_performance_level(void *handle,
-                                              struct seq_file *m)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct amdgpu_ps *rps = &pi->current_rps;
-       u32 sclk = ci_get_average_sclk_freq(adev);
-       u32 mclk = ci_get_average_mclk_freq(adev);
-       u32 activity_percent = 50;
-       int ret;
-
-       ret = ci_read_smc_soft_register(adev, offsetof(SMU7_SoftRegisters, AverageGraphicsA),
-                                       &activity_percent);
-
-       if (ret == 0) {
-               activity_percent += 0x80;
-               activity_percent >>= 8;
-               activity_percent = activity_percent > 100 ? 100 : activity_percent;
-       }
-
-       seq_printf(m, "uvd %sabled\n", pi->uvd_power_gated ? "dis" : "en");
-       seq_printf(m, "vce %sabled\n", rps->vce_active ? "en" : "dis");
-       seq_printf(m, "power level avg    sclk: %u mclk: %u\n",
-                  sclk, mclk);
-       seq_printf(m, "GPU load: %u %%\n", activity_percent);
-}
-
-static void ci_dpm_print_power_state(void *handle, void *current_ps)
-{
-       struct amdgpu_ps *rps = (struct amdgpu_ps *)current_ps;
-       struct ci_ps *ps = ci_get_ps(rps);
-       struct ci_pl *pl;
-       int i;
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       amdgpu_dpm_print_class_info(rps->class, rps->class2);
-       amdgpu_dpm_print_cap_info(rps->caps);
-       printk("\tuvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
-       for (i = 0; i < ps->performance_level_count; i++) {
-               pl = &ps->performance_levels[i];
-               printk("\t\tpower level %d    sclk: %u mclk: %u pcie gen: %u pcie lanes: %u\n",
-                      i, pl->sclk, pl->mclk, pl->pcie_gen + 1, pl->pcie_lane);
-       }
-       amdgpu_dpm_print_ps_status(adev, rps);
-}
-
-static inline bool ci_are_power_levels_equal(const struct ci_pl *ci_cpl1,
-                                               const struct ci_pl *ci_cpl2)
-{
-       return ((ci_cpl1->mclk == ci_cpl2->mclk) &&
-                 (ci_cpl1->sclk == ci_cpl2->sclk) &&
-                 (ci_cpl1->pcie_gen == ci_cpl2->pcie_gen) &&
-                 (ci_cpl1->pcie_lane == ci_cpl2->pcie_lane));
-}
-
-static int ci_check_state_equal(void *handle,
-                               void *current_ps,
-                               void *request_ps,
-                               bool *equal)
-{
-       struct ci_ps *ci_cps;
-       struct ci_ps *ci_rps;
-       int i;
-       struct amdgpu_ps *cps = (struct amdgpu_ps *)current_ps;
-       struct amdgpu_ps *rps = (struct amdgpu_ps *)request_ps;
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       if (adev == NULL || cps == NULL || rps == NULL || equal == NULL)
-               return -EINVAL;
-
-       ci_cps = ci_get_ps((struct amdgpu_ps *)cps);
-       ci_rps = ci_get_ps((struct amdgpu_ps *)rps);
-
-       if (ci_cps == NULL) {
-               *equal = false;
-               return 0;
-       }
-
-       if (ci_cps->performance_level_count != ci_rps->performance_level_count) {
-
-               *equal = false;
-               return 0;
-       }
-
-       for (i = 0; i < ci_cps->performance_level_count; i++) {
-               if (!ci_are_power_levels_equal(&(ci_cps->performance_levels[i]),
-                                       &(ci_rps->performance_levels[i]))) {
-                       *equal = false;
-                       return 0;
-               }
-       }
-
-       /* If all performance levels are the same try to use the UVD clocks to break the tie.*/
-       *equal = ((cps->vclk == rps->vclk) && (cps->dclk == rps->dclk));
-       *equal &= ((cps->evclk == rps->evclk) && (cps->ecclk == rps->ecclk));
-
-       return 0;
-}
-
-static u32 ci_dpm_get_sclk(void *handle, bool low)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_ps *requested_state = ci_get_ps(&pi->requested_rps);
-
-       if (low)
-               return requested_state->performance_levels[0].sclk;
-       else
-               return requested_state->performance_levels[requested_state->performance_level_count - 1].sclk;
-}
-
-static u32 ci_dpm_get_mclk(void *handle, bool low)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_ps *requested_state = ci_get_ps(&pi->requested_rps);
-
-       if (low)
-               return requested_state->performance_levels[0].mclk;
-       else
-               return requested_state->performance_levels[requested_state->performance_level_count - 1].mclk;
-}
-
-/* get temperature in millidegrees */
-static int ci_dpm_get_temp(void *handle)
-{
-       u32 temp;
-       int actual_temp = 0;
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       temp = (RREG32_SMC(ixCG_MULT_THERMAL_STATUS) & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
-               CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
-
-       if (temp & 0x200)
-               actual_temp = 255;
-       else
-               actual_temp = temp & 0x1ff;
-
-       actual_temp = actual_temp * 1000;
-
-       return actual_temp;
-}
-
-static int ci_set_temperature_range(struct amdgpu_device *adev)
-{
-       int ret;
-
-       ret = ci_thermal_enable_alert(adev, false);
-       if (ret)
-               return ret;
-       ret = ci_thermal_set_temperature_range(adev, CISLANDS_TEMP_RANGE_MIN,
-                                              CISLANDS_TEMP_RANGE_MAX);
-       if (ret)
-               return ret;
-       ret = ci_thermal_enable_alert(adev, true);
-       if (ret)
-               return ret;
-       return ret;
-}
-
-static int ci_dpm_early_init(void *handle)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       adev->powerplay.pp_funcs = &ci_dpm_funcs;
-       adev->powerplay.pp_handle = adev;
-       ci_dpm_set_irq_funcs(adev);
-
-       return 0;
-}
-
-static int ci_dpm_late_init(void *handle)
-{
-       int ret;
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       if (!adev->pm.dpm_enabled)
-               return 0;
-
-       /* init the sysfs and debugfs files late */
-       ret = amdgpu_pm_sysfs_init(adev);
-       if (ret)
-               return ret;
-
-       ret = ci_set_temperature_range(adev);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
-static int ci_dpm_sw_init(void *handle)
-{
-       int ret;
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       ret = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 230,
-                               &adev->pm.dpm.thermal.irq);
-       if (ret)
-               return ret;
-
-       ret = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 231,
-                               &adev->pm.dpm.thermal.irq);
-       if (ret)
-               return ret;
-
-       /* default to balanced state */
-       adev->pm.dpm.state = POWER_STATE_TYPE_BALANCED;
-       adev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED;
-       adev->pm.dpm.forced_level = AMD_DPM_FORCED_LEVEL_AUTO;
-       adev->pm.default_sclk = adev->clock.default_sclk;
-       adev->pm.default_mclk = adev->clock.default_mclk;
-       adev->pm.current_sclk = adev->clock.default_sclk;
-       adev->pm.current_mclk = adev->clock.default_mclk;
-       adev->pm.int_thermal_type = THERMAL_TYPE_NONE;
-
-       ret = ci_dpm_init_microcode(adev);
-       if (ret)
-               return ret;
-
-       if (amdgpu_dpm == 0)
-               return 0;
-
-       INIT_WORK(&adev->pm.dpm.thermal.work, amdgpu_dpm_thermal_work_handler);
-       mutex_lock(&adev->pm.mutex);
-       ret = ci_dpm_init(adev);
-       if (ret)
-               goto dpm_failed;
-       adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
-       if (amdgpu_dpm == 1)
-               amdgpu_pm_print_power_states(adev);
-       mutex_unlock(&adev->pm.mutex);
-       DRM_INFO("amdgpu: dpm initialized\n");
-
-       return 0;
-
-dpm_failed:
-       ci_dpm_fini(adev);
-       mutex_unlock(&adev->pm.mutex);
-       DRM_ERROR("amdgpu: dpm initialization failed\n");
-       return ret;
-}
-
-static int ci_dpm_sw_fini(void *handle)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       flush_work(&adev->pm.dpm.thermal.work);
-
-       mutex_lock(&adev->pm.mutex);
-       ci_dpm_fini(adev);
-       mutex_unlock(&adev->pm.mutex);
-
-       release_firmware(adev->pm.fw);
-       adev->pm.fw = NULL;
-
-       return 0;
-}
-
-static int ci_dpm_hw_init(void *handle)
-{
-       int ret;
-
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       if (!amdgpu_dpm) {
-               ret = ci_upload_firmware(adev);
-               if (ret) {
-                       DRM_ERROR("ci_upload_firmware failed\n");
-                       return ret;
-               }
-               ci_dpm_start_smc(adev);
-               return 0;
-       }
-
-       mutex_lock(&adev->pm.mutex);
-       ci_dpm_setup_asic(adev);
-       ret = ci_dpm_enable(adev);
-       if (ret)
-               adev->pm.dpm_enabled = false;
-       else
-               adev->pm.dpm_enabled = true;
-       mutex_unlock(&adev->pm.mutex);
-
-       return ret;
-}
-
-static int ci_dpm_hw_fini(void *handle)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       if (adev->pm.dpm_enabled) {
-               mutex_lock(&adev->pm.mutex);
-               ci_dpm_disable(adev);
-               mutex_unlock(&adev->pm.mutex);
-       } else {
-               ci_dpm_stop_smc(adev);
-       }
-
-       return 0;
-}
-
-static int ci_dpm_suspend(void *handle)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       if (adev->pm.dpm_enabled) {
-               mutex_lock(&adev->pm.mutex);
-               amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq,
-                              AMDGPU_THERMAL_IRQ_LOW_TO_HIGH);
-               amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq,
-                              AMDGPU_THERMAL_IRQ_HIGH_TO_LOW);
-               adev->pm.dpm.last_user_state = adev->pm.dpm.user_state;
-               adev->pm.dpm.last_state = adev->pm.dpm.state;
-               adev->pm.dpm.user_state = POWER_STATE_TYPE_INTERNAL_BOOT;
-               adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_BOOT;
-               mutex_unlock(&adev->pm.mutex);
-               amdgpu_pm_compute_clocks(adev);
-
-       }
-
-       return 0;
-}
-
-static int ci_dpm_resume(void *handle)
-{
-       int ret;
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       if (adev->pm.dpm_enabled) {
-               /* asic init will reset to the boot state */
-               mutex_lock(&adev->pm.mutex);
-               ci_dpm_setup_asic(adev);
-               ret = ci_dpm_enable(adev);
-               if (ret)
-                       adev->pm.dpm_enabled = false;
-               else
-                       adev->pm.dpm_enabled = true;
-               adev->pm.dpm.user_state = adev->pm.dpm.last_user_state;
-               adev->pm.dpm.state = adev->pm.dpm.last_state;
-               mutex_unlock(&adev->pm.mutex);
-               if (adev->pm.dpm_enabled)
-                       amdgpu_pm_compute_clocks(adev);
-       }
-       return 0;
-}
-
-static bool ci_dpm_is_idle(void *handle)
-{
-       /* XXX */
-       return true;
-}
-
-static int ci_dpm_wait_for_idle(void *handle)
-{
-       /* XXX */
-       return 0;
-}
-
-static int ci_dpm_soft_reset(void *handle)
-{
-       return 0;
-}
-
-static int ci_dpm_set_interrupt_state(struct amdgpu_device *adev,
-                                     struct amdgpu_irq_src *source,
-                                     unsigned type,
-                                     enum amdgpu_interrupt_state state)
-{
-       u32 cg_thermal_int;
-
-       switch (type) {
-       case AMDGPU_THERMAL_IRQ_LOW_TO_HIGH:
-               switch (state) {
-               case AMDGPU_IRQ_STATE_DISABLE:
-                       cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT);
-                       cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
-                       WREG32_SMC(ixCG_THERMAL_INT, cg_thermal_int);
-                       break;
-               case AMDGPU_IRQ_STATE_ENABLE:
-                       cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT);
-                       cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
-                       WREG32_SMC(ixCG_THERMAL_INT, cg_thermal_int);
-                       break;
-               default:
-                       break;
-               }
-               break;
-
-       case AMDGPU_THERMAL_IRQ_HIGH_TO_LOW:
-               switch (state) {
-               case AMDGPU_IRQ_STATE_DISABLE:
-                       cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT);
-                       cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
-                       WREG32_SMC(ixCG_THERMAL_INT, cg_thermal_int);
-                       break;
-               case AMDGPU_IRQ_STATE_ENABLE:
-                       cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT);
-                       cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
-                       WREG32_SMC(ixCG_THERMAL_INT, cg_thermal_int);
-                       break;
-               default:
-                       break;
-               }
-               break;
-
-       default:
-               break;
-       }
-       return 0;
-}
-
-static int ci_dpm_process_interrupt(struct amdgpu_device *adev,
-                                   struct amdgpu_irq_src *source,
-                                   struct amdgpu_iv_entry *entry)
-{
-       bool queue_thermal = false;
-
-       if (entry == NULL)
-               return -EINVAL;
-
-       switch (entry->src_id) {
-       case 230: /* thermal low to high */
-               DRM_DEBUG("IH: thermal low to high\n");
-               adev->pm.dpm.thermal.high_to_low = false;
-               queue_thermal = true;
-               break;
-       case 231: /* thermal high to low */
-               DRM_DEBUG("IH: thermal high to low\n");
-               adev->pm.dpm.thermal.high_to_low = true;
-               queue_thermal = true;
-               break;
-       default:
-               break;
-       }
-
-       if (queue_thermal)
-               schedule_work(&adev->pm.dpm.thermal.work);
-
-       return 0;
-}
-
-static int ci_dpm_set_clockgating_state(void *handle,
-                                         enum amd_clockgating_state state)
-{
-       return 0;
-}
-
-static int ci_dpm_set_powergating_state(void *handle,
-                                         enum amd_powergating_state state)
-{
-       return 0;
-}
-
-static int ci_dpm_print_clock_levels(void *handle,
-               enum pp_clock_type type, char *buf)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_single_dpm_table *sclk_table = &pi->dpm_table.sclk_table;
-       struct ci_single_dpm_table *mclk_table = &pi->dpm_table.mclk_table;
-       struct ci_single_dpm_table *pcie_table = &pi->dpm_table.pcie_speed_table;
-
-       int i, now, size = 0;
-       uint32_t clock, pcie_speed;
-
-       switch (type) {
-       case PP_SCLK:
-               amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_API_GetSclkFrequency);
-               clock = RREG32(mmSMC_MSG_ARG_0);
-
-               for (i = 0; i < sclk_table->count; i++) {
-                       if (clock > sclk_table->dpm_levels[i].value)
-                               continue;
-                       break;
-               }
-               now = i;
-
-               for (i = 0; i < sclk_table->count; i++)
-                       size += sprintf(buf + size, "%d: %uMhz %s\n",
-                                       i, sclk_table->dpm_levels[i].value / 100,
-                                       (i == now) ? "*" : "");
-               break;
-       case PP_MCLK:
-               amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_API_GetMclkFrequency);
-               clock = RREG32(mmSMC_MSG_ARG_0);
-
-               for (i = 0; i < mclk_table->count; i++) {
-                       if (clock > mclk_table->dpm_levels[i].value)
-                               continue;
-                       break;
-               }
-               now = i;
-
-               for (i = 0; i < mclk_table->count; i++)
-                       size += sprintf(buf + size, "%d: %uMhz %s\n",
-                                       i, mclk_table->dpm_levels[i].value / 100,
-                                       (i == now) ? "*" : "");
-               break;
-       case PP_PCIE:
-               pcie_speed = ci_get_current_pcie_speed(adev);
-               for (i = 0; i < pcie_table->count; i++) {
-                       if (pcie_speed != pcie_table->dpm_levels[i].value)
-                               continue;
-                       break;
-               }
-               now = i;
-
-               for (i = 0; i < pcie_table->count; i++)
-                       size += sprintf(buf + size, "%d: %s %s\n", i,
-                                       (pcie_table->dpm_levels[i].value == 0) ? "2.5GT/s, x1" :
-                                       (pcie_table->dpm_levels[i].value == 1) ? "5.0GT/s, x16" :
-                                       (pcie_table->dpm_levels[i].value == 2) ? "8.0GT/s, x16" : "",
-                                       (i == now) ? "*" : "");
-               break;
-       default:
-               break;
-       }
-
-       return size;
-}
-
-static int ci_dpm_force_clock_level(void *handle,
-               enum pp_clock_type type, uint32_t mask)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ci_power_info *pi = ci_get_pi(adev);
-
-       if (adev->pm.dpm.forced_level != AMD_DPM_FORCED_LEVEL_MANUAL)
-               return -EINVAL;
-
-       if (mask == 0)
-               return -EINVAL;
-
-       switch (type) {
-       case PP_SCLK:
-               if (!pi->sclk_dpm_key_disabled)
-                       amdgpu_ci_send_msg_to_smc_with_parameter(adev,
-                                       PPSMC_MSG_SCLKDPM_SetEnabledMask,
-                                       pi->dpm_level_enable_mask.sclk_dpm_enable_mask & mask);
-               break;
-
-       case PP_MCLK:
-               if (!pi->mclk_dpm_key_disabled)
-                       amdgpu_ci_send_msg_to_smc_with_parameter(adev,
-                                       PPSMC_MSG_MCLKDPM_SetEnabledMask,
-                                       pi->dpm_level_enable_mask.mclk_dpm_enable_mask & mask);
-               break;
-
-       case PP_PCIE:
-       {
-               uint32_t tmp = mask & pi->dpm_level_enable_mask.pcie_dpm_enable_mask;
-
-               if (!pi->pcie_dpm_key_disabled) {
-                       if (fls(tmp) != ffs(tmp))
-                               amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_PCIeDPM_UnForceLevel);
-                       else
-                               amdgpu_ci_send_msg_to_smc_with_parameter(adev,
-                                       PPSMC_MSG_PCIeDPM_ForceLevel,
-                                       fls(tmp) - 1);
-               }
-               break;
-       }
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-static int ci_dpm_get_sclk_od(void *handle)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_single_dpm_table *sclk_table = &(pi->dpm_table.sclk_table);
-       struct ci_single_dpm_table *golden_sclk_table =
-                       &(pi->golden_dpm_table.sclk_table);
-       int value;
-
-       value = (sclk_table->dpm_levels[sclk_table->count - 1].value -
-                       golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) *
-                       100 /
-                       golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
-
-       return value;
-}
-
-static int ci_dpm_set_sclk_od(void *handle, uint32_t value)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_ps *ps = ci_get_ps(adev->pm.dpm.requested_ps);
-       struct ci_single_dpm_table *golden_sclk_table =
-                       &(pi->golden_dpm_table.sclk_table);
-
-       if (value > 20)
-               value = 20;
-
-       ps->performance_levels[ps->performance_level_count - 1].sclk =
-                       golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value *
-                       value / 100 +
-                       golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
-
-       return 0;
-}
-
-static int ci_dpm_get_mclk_od(void *handle)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_single_dpm_table *mclk_table = &(pi->dpm_table.mclk_table);
-       struct ci_single_dpm_table *golden_mclk_table =
-                       &(pi->golden_dpm_table.mclk_table);
-       int value;
-
-       value = (mclk_table->dpm_levels[mclk_table->count - 1].value -
-                       golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value) *
-                       100 /
-                       golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value;
-
-       return value;
-}
-
-static int ci_dpm_set_mclk_od(void *handle, uint32_t value)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ci_power_info *pi = ci_get_pi(adev);
-       struct ci_ps *ps = ci_get_ps(adev->pm.dpm.requested_ps);
-       struct ci_single_dpm_table *golden_mclk_table =
-                       &(pi->golden_dpm_table.mclk_table);
-
-       if (value > 20)
-               value = 20;
-
-       ps->performance_levels[ps->performance_level_count - 1].mclk =
-                       golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value *
-                       value / 100 +
-                       golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value;
-
-       return 0;
-}
-
-static int ci_dpm_read_sensor(void *handle, int idx,
-                             void *value, int *size)
-{
-       u32 activity_percent = 50;
-       int ret;
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       /* size must be at least 4 bytes for all sensors */
-       if (*size < 4)
-               return -EINVAL;
-
-       switch (idx) {
-       case AMDGPU_PP_SENSOR_GFX_SCLK:
-               *((uint32_t *)value) = ci_get_average_sclk_freq(adev);
-               *size = 4;
-               return 0;
-       case AMDGPU_PP_SENSOR_GFX_MCLK:
-               *((uint32_t *)value) = ci_get_average_mclk_freq(adev);
-               *size = 4;
-               return 0;
-       case AMDGPU_PP_SENSOR_GPU_TEMP:
-               *((uint32_t *)value) = ci_dpm_get_temp(adev);
-               *size = 4;
-               return 0;
-       case AMDGPU_PP_SENSOR_GPU_LOAD:
-               ret = ci_read_smc_soft_register(adev,
-                                               offsetof(SMU7_SoftRegisters,
-                                                        AverageGraphicsA),
-                                               &activity_percent);
-               if (ret == 0) {
-                       activity_percent += 0x80;
-                       activity_percent >>= 8;
-                       activity_percent =
-                               activity_percent > 100 ? 100 : activity_percent;
-               }
-               *((uint32_t *)value) = activity_percent;
-               *size = 4;
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
-static int ci_set_powergating_by_smu(void *handle,
-                               uint32_t block_type, bool gate)
-{
-       switch (block_type) {
-       case AMD_IP_BLOCK_TYPE_UVD:
-               ci_dpm_powergate_uvd(handle, gate);
-               break;
-       default:
-               break;
-       }
-       return 0;
-}
-
-static const struct amd_ip_funcs ci_dpm_ip_funcs = {
-       .name = "ci_dpm",
-       .early_init = ci_dpm_early_init,
-       .late_init = ci_dpm_late_init,
-       .sw_init = ci_dpm_sw_init,
-       .sw_fini = ci_dpm_sw_fini,
-       .hw_init = ci_dpm_hw_init,
-       .hw_fini = ci_dpm_hw_fini,
-       .suspend = ci_dpm_suspend,
-       .resume = ci_dpm_resume,
-       .is_idle = ci_dpm_is_idle,
-       .wait_for_idle = ci_dpm_wait_for_idle,
-       .soft_reset = ci_dpm_soft_reset,
-       .set_clockgating_state = ci_dpm_set_clockgating_state,
-       .set_powergating_state = ci_dpm_set_powergating_state,
-};
-
-const struct amdgpu_ip_block_version ci_smu_ip_block =
-{
-       .type = AMD_IP_BLOCK_TYPE_SMC,
-       .major = 7,
-       .minor = 0,
-       .rev = 0,
-       .funcs = &ci_dpm_ip_funcs,
-};
-
-static const struct amd_pm_funcs ci_dpm_funcs = {
-       .pre_set_power_state = &ci_dpm_pre_set_power_state,
-       .set_power_state = &ci_dpm_set_power_state,
-       .post_set_power_state = &ci_dpm_post_set_power_state,
-       .display_configuration_changed = &ci_dpm_display_configuration_changed,
-       .get_sclk = &ci_dpm_get_sclk,
-       .get_mclk = &ci_dpm_get_mclk,
-       .print_power_state = &ci_dpm_print_power_state,
-       .debugfs_print_current_performance_level = &ci_dpm_debugfs_print_current_performance_level,
-       .force_performance_level = &ci_dpm_force_performance_level,
-       .vblank_too_short = &ci_dpm_vblank_too_short,
-       .set_powergating_by_smu = &ci_set_powergating_by_smu,
-       .set_fan_control_mode = &ci_dpm_set_fan_control_mode,
-       .get_fan_control_mode = &ci_dpm_get_fan_control_mode,
-       .set_fan_speed_percent = &ci_dpm_set_fan_speed_percent,
-       .get_fan_speed_percent = &ci_dpm_get_fan_speed_percent,
-       .print_clock_levels = ci_dpm_print_clock_levels,
-       .force_clock_level = ci_dpm_force_clock_level,
-       .get_sclk_od = ci_dpm_get_sclk_od,
-       .set_sclk_od = ci_dpm_set_sclk_od,
-       .get_mclk_od = ci_dpm_get_mclk_od,
-       .set_mclk_od = ci_dpm_set_mclk_od,
-       .check_state_equal = ci_check_state_equal,
-       .get_vce_clock_state = amdgpu_get_vce_clock_state,
-       .read_sensor = ci_dpm_read_sensor,
-};
-
-static const struct amdgpu_irq_src_funcs ci_dpm_irq_funcs = {
-       .set = ci_dpm_set_interrupt_state,
-       .process = ci_dpm_process_interrupt,
-};
-
-static void ci_dpm_set_irq_funcs(struct amdgpu_device *adev)
-{
-       adev->pm.dpm.thermal.irq.num_types = AMDGPU_THERMAL_IRQ_LAST;
-       adev->pm.dpm.thermal.irq.funcs = &ci_dpm_irq_funcs;
-}
diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.h b/drivers/gpu/drm/amd/amdgpu/ci_dpm.h
deleted file mode 100644 (file)
index 91be299..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * Copyright 2013 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 __CI_DPM_H__
-#define __CI_DPM_H__
-
-#include "amdgpu_atombios.h"
-#include "ppsmc.h"
-
-#define SMU__NUM_SCLK_DPM_STATE  8
-#define SMU__NUM_MCLK_DPM_LEVELS 6
-#define SMU__NUM_LCLK_DPM_LEVELS 8
-#define SMU__NUM_PCIE_DPM_LEVELS 8
-#include "smu7_discrete.h"
-
-#define CISLANDS_MAX_HARDWARE_POWERLEVELS 2
-
-#define CISLANDS_UNUSED_GPIO_PIN 0x7F
-
-struct ci_pl {
-       u32 mclk;
-       u32 sclk;
-       enum amdgpu_pcie_gen pcie_gen;
-       u16 pcie_lane;
-};
-
-struct ci_ps {
-       u16 performance_level_count;
-       bool dc_compatible;
-       u32 sclk_t;
-       struct ci_pl performance_levels[CISLANDS_MAX_HARDWARE_POWERLEVELS];
-};
-
-struct ci_dpm_level {
-       bool enabled;
-       u32 value;
-       u32 param1;
-};
-
-#define CISLAND_MAX_DEEPSLEEP_DIVIDER_ID 5
-#define MAX_REGULAR_DPM_NUMBER 8
-#define CISLAND_MINIMUM_ENGINE_CLOCK 800
-
-struct ci_single_dpm_table {
-       u32 count;
-       struct ci_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER];
-};
-
-struct ci_dpm_table {
-       struct ci_single_dpm_table sclk_table;
-       struct ci_single_dpm_table mclk_table;
-       struct ci_single_dpm_table pcie_speed_table;
-       struct ci_single_dpm_table vddc_table;
-       struct ci_single_dpm_table vddci_table;
-       struct ci_single_dpm_table mvdd_table;
-};
-
-struct ci_mc_reg_entry {
-       u32 mclk_max;
-       u32 mc_data[SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE];
-};
-
-struct ci_mc_reg_table {
-       u8 last;
-       u8 num_entries;
-       u16 valid_flag;
-       struct ci_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES];
-       SMU7_Discrete_MCRegisterAddress mc_reg_address[SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE];
-};
-
-struct ci_ulv_parm
-{
-       bool supported;
-       u32 cg_ulv_parameter;
-       u32 volt_change_delay;
-       struct ci_pl pl;
-};
-
-#define CISLANDS_MAX_LEAKAGE_COUNT  8
-
-struct ci_leakage_voltage {
-       u16 count;
-       u16 leakage_id[CISLANDS_MAX_LEAKAGE_COUNT];
-       u16 actual_voltage[CISLANDS_MAX_LEAKAGE_COUNT];
-};
-
-struct ci_dpm_level_enable_mask {
-       u32 uvd_dpm_enable_mask;
-       u32 vce_dpm_enable_mask;
-       u32 acp_dpm_enable_mask;
-       u32 samu_dpm_enable_mask;
-       u32 sclk_dpm_enable_mask;
-       u32 mclk_dpm_enable_mask;
-       u32 pcie_dpm_enable_mask;
-};
-
-struct ci_vbios_boot_state
-{
-       u16 mvdd_bootup_value;
-       u16 vddc_bootup_value;
-       u16 vddci_bootup_value;
-       u32 sclk_bootup_value;
-       u32 mclk_bootup_value;
-       u16 pcie_gen_bootup_value;
-       u16 pcie_lane_bootup_value;
-};
-
-struct ci_clock_registers {
-       u32 cg_spll_func_cntl;
-       u32 cg_spll_func_cntl_2;
-       u32 cg_spll_func_cntl_3;
-       u32 cg_spll_func_cntl_4;
-       u32 cg_spll_spread_spectrum;
-       u32 cg_spll_spread_spectrum_2;
-       u32 dll_cntl;
-       u32 mclk_pwrmgt_cntl;
-       u32 mpll_ad_func_cntl;
-       u32 mpll_dq_func_cntl;
-       u32 mpll_func_cntl;
-       u32 mpll_func_cntl_1;
-       u32 mpll_func_cntl_2;
-       u32 mpll_ss1;
-       u32 mpll_ss2;
-};
-
-struct ci_thermal_temperature_setting {
-       s32 temperature_low;
-       s32 temperature_high;
-       s32 temperature_shutdown;
-};
-
-struct ci_pcie_perf_range {
-       u16 max;
-       u16 min;
-};
-
-enum ci_pt_config_reg_type {
-       CISLANDS_CONFIGREG_MMR = 0,
-       CISLANDS_CONFIGREG_SMC_IND,
-       CISLANDS_CONFIGREG_DIDT_IND,
-       CISLANDS_CONFIGREG_CACHE,
-       CISLANDS_CONFIGREG_MAX
-};
-
-#define POWERCONTAINMENT_FEATURE_BAPM            0x00000001
-#define POWERCONTAINMENT_FEATURE_TDCLimit        0x00000002
-#define POWERCONTAINMENT_FEATURE_PkgPwrLimit     0x00000004
-
-struct ci_pt_config_reg {
-       u32 offset;
-       u32 mask;
-       u32 shift;
-       u32 value;
-       enum ci_pt_config_reg_type type;
-};
-
-struct ci_pt_defaults {
-       u8 svi_load_line_en;
-       u8 svi_load_line_vddc;
-       u8 tdc_vddc_throttle_release_limit_perc;
-       u8 tdc_mawt;
-       u8 tdc_waterfall_ctl;
-       u8 dte_ambient_temp_base;
-       u32 display_cac;
-       u32 bapm_temp_gradient;
-       u16 bapmti_r[SMU7_DTE_ITERATIONS * SMU7_DTE_SOURCES * SMU7_DTE_SINKS];
-       u16 bapmti_rc[SMU7_DTE_ITERATIONS * SMU7_DTE_SOURCES * SMU7_DTE_SINKS];
-};
-
-#define DPMTABLE_OD_UPDATE_SCLK     0x00000001
-#define DPMTABLE_OD_UPDATE_MCLK     0x00000002
-#define DPMTABLE_UPDATE_SCLK        0x00000004
-#define DPMTABLE_UPDATE_MCLK        0x00000008
-
-struct ci_power_info {
-       struct ci_dpm_table dpm_table;
-       struct ci_dpm_table golden_dpm_table;
-       u32 voltage_control;
-       u32 mvdd_control;
-       u32 vddci_control;
-       u32 active_auto_throttle_sources;
-       struct ci_clock_registers clock_registers;
-       u16 acpi_vddc;
-       u16 acpi_vddci;
-       enum amdgpu_pcie_gen force_pcie_gen;
-       enum amdgpu_pcie_gen acpi_pcie_gen;
-       struct ci_leakage_voltage vddc_leakage;
-       struct ci_leakage_voltage vddci_leakage;
-       u16 max_vddc_in_pp_table;
-       u16 min_vddc_in_pp_table;
-       u16 max_vddci_in_pp_table;
-       u16 min_vddci_in_pp_table;
-       u32 mclk_strobe_mode_threshold;
-       u32 mclk_stutter_mode_threshold;
-       u32 mclk_edc_enable_threshold;
-       u32 mclk_edc_wr_enable_threshold;
-       struct ci_vbios_boot_state vbios_boot_state;
-       /* smc offsets */
-       u32 sram_end;
-       u32 dpm_table_start;
-       u32 soft_regs_start;
-       u32 mc_reg_table_start;
-       u32 fan_table_start;
-       u32 arb_table_start;
-       /* smc tables */
-       SMU7_Discrete_DpmTable smc_state_table;
-       SMU7_Discrete_MCRegisters smc_mc_reg_table;
-       SMU7_Discrete_PmFuses smc_powertune_table;
-       /* other stuff */
-       struct ci_mc_reg_table mc_reg_table;
-       struct atom_voltage_table vddc_voltage_table;
-       struct atom_voltage_table vddci_voltage_table;
-       struct atom_voltage_table mvdd_voltage_table;
-       struct ci_ulv_parm ulv;
-       u32 power_containment_features;
-       const struct ci_pt_defaults *powertune_defaults;
-       u32 dte_tj_offset;
-       bool vddc_phase_shed_control;
-       struct ci_thermal_temperature_setting thermal_temp_setting;
-       struct ci_dpm_level_enable_mask dpm_level_enable_mask;
-       u32 need_update_smu7_dpm_table;
-       u32 sclk_dpm_key_disabled;
-       u32 mclk_dpm_key_disabled;
-       u32 pcie_dpm_key_disabled;
-       u32 thermal_sclk_dpm_enabled;
-       struct ci_pcie_perf_range pcie_gen_performance;
-       struct ci_pcie_perf_range pcie_lane_performance;
-       struct ci_pcie_perf_range pcie_gen_powersaving;
-       struct ci_pcie_perf_range pcie_lane_powersaving;
-       u32 activity_target[SMU7_MAX_LEVELS_GRAPHICS];
-       u32 mclk_activity_target;
-       u32 low_sclk_interrupt_t;
-       u32 last_mclk_dpm_enable_mask;
-       u32 sys_pcie_mask;
-       /* caps */
-       bool caps_power_containment;
-       bool caps_cac;
-       bool caps_sq_ramping;
-       bool caps_db_ramping;
-       bool caps_td_ramping;
-       bool caps_tcp_ramping;
-       bool caps_fps;
-       bool caps_sclk_ds;
-       bool caps_sclk_ss_support;
-       bool caps_mclk_ss_support;
-       bool caps_uvd_dpm;
-       bool caps_vce_dpm;
-       bool caps_samu_dpm;
-       bool caps_acp_dpm;
-       bool caps_automatic_dc_transition;
-       bool caps_sclk_throttle_low_notification;
-       bool caps_dynamic_ac_timing;
-       bool caps_od_fuzzy_fan_control_support;
-       /* flags */
-       bool thermal_protection;
-       bool pcie_performance_request;
-       bool dynamic_ss;
-       bool dll_default_on;
-       bool cac_enabled;
-       bool uvd_enabled;
-       bool battery_state;
-       bool pspp_notify_required;
-       bool enable_bapm_feature;
-       bool enable_tdc_limit_feature;
-       bool enable_pkg_pwr_tracking_feature;
-       bool use_pcie_performance_levels;
-       bool use_pcie_powersaving_levels;
-       bool uvd_power_gated;
-       /* driver states */
-       struct amdgpu_ps current_rps;
-       struct ci_ps current_ps;
-       struct amdgpu_ps requested_rps;
-       struct ci_ps requested_ps;
-       /* fan control */
-       bool fan_ctrl_is_in_default_mode;
-       bool fan_is_controlled_by_smc;
-       u32 t_min;
-       u32 fan_ctrl_default_mode;
-};
-
-#define CISLANDS_VOLTAGE_CONTROL_NONE                   0x0
-#define CISLANDS_VOLTAGE_CONTROL_BY_GPIO                0x1
-#define CISLANDS_VOLTAGE_CONTROL_BY_SVID2               0x2
-
-#define CISLANDS_Q88_FORMAT_CONVERSION_UNIT             256
-
-#define CISLANDS_VRC_DFLT0                              0x3FFFC000
-#define CISLANDS_VRC_DFLT1                              0x000400
-#define CISLANDS_VRC_DFLT2                              0xC00080
-#define CISLANDS_VRC_DFLT3                              0xC00200
-#define CISLANDS_VRC_DFLT4                              0xC01680
-#define CISLANDS_VRC_DFLT5                              0xC00033
-#define CISLANDS_VRC_DFLT6                              0xC00033
-#define CISLANDS_VRC_DFLT7                              0x3FFFC000
-
-#define CISLANDS_CGULVPARAMETER_DFLT                    0x00040035
-#define CISLAND_TARGETACTIVITY_DFLT                     30
-#define CISLAND_MCLK_TARGETACTIVITY_DFLT                10
-
-#define PCIE_PERF_REQ_REMOVE_REGISTRY   0
-#define PCIE_PERF_REQ_FORCE_LOWPOWER    1
-#define PCIE_PERF_REQ_PECI_GEN1         2
-#define PCIE_PERF_REQ_PECI_GEN2         3
-#define PCIE_PERF_REQ_PECI_GEN3         4
-
-#define CISLANDS_SSTU_DFLT                               0
-#define CISLANDS_SST_DFLT                                0x00C8
-
-/* XXX are these ok? */
-#define CISLANDS_TEMP_RANGE_MIN (90 * 1000)
-#define CISLANDS_TEMP_RANGE_MAX (120 * 1000)
-
-int amdgpu_ci_copy_bytes_to_smc(struct amdgpu_device *adev,
-                        u32 smc_start_address,
-                        const u8 *src, u32 byte_count, u32 limit);
-void amdgpu_ci_start_smc(struct amdgpu_device *adev);
-void amdgpu_ci_reset_smc(struct amdgpu_device *adev);
-int amdgpu_ci_program_jump_on_start(struct amdgpu_device *adev);
-void amdgpu_ci_stop_smc_clock(struct amdgpu_device *adev);
-void amdgpu_ci_start_smc_clock(struct amdgpu_device *adev);
-bool amdgpu_ci_is_smc_running(struct amdgpu_device *adev);
-PPSMC_Result amdgpu_ci_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg);
-PPSMC_Result amdgpu_ci_wait_for_smc_inactive(struct amdgpu_device *adev);
-int amdgpu_ci_load_smc_ucode(struct amdgpu_device *adev, u32 limit);
-int amdgpu_ci_read_smc_sram_dword(struct amdgpu_device *adev,
-                          u32 smc_address, u32 *value, u32 limit);
-int amdgpu_ci_write_smc_sram_dword(struct amdgpu_device *adev,
-                           u32 smc_address, u32 value, u32 limit);
-
-#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/ci_smc.c b/drivers/gpu/drm/amd/amdgpu/ci_smc.c
deleted file mode 100644 (file)
index b8ba51e..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright 2011 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: Alex Deucher
- */
-
-#include <linux/firmware.h>
-#include <drm/drmP.h>
-#include "amdgpu.h"
-#include "cikd.h"
-#include "ppsmc.h"
-#include "amdgpu_ucode.h"
-#include "ci_dpm.h"
-
-#include "smu/smu_7_0_1_d.h"
-#include "smu/smu_7_0_1_sh_mask.h"
-
-static int ci_set_smc_sram_address(struct amdgpu_device *adev,
-                                  u32 smc_address, u32 limit)
-{
-       if (smc_address & 3)
-               return -EINVAL;
-       if ((smc_address + 3) > limit)
-               return -EINVAL;
-
-       WREG32(mmSMC_IND_INDEX_0, smc_address);
-       WREG32_P(mmSMC_IND_ACCESS_CNTL, 0, ~SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_0_MASK);
-
-       return 0;
-}
-
-int amdgpu_ci_copy_bytes_to_smc(struct amdgpu_device *adev,
-                        u32 smc_start_address,
-                        const u8 *src, u32 byte_count, u32 limit)
-{
-       unsigned long flags;
-       u32 data, original_data;
-       u32 addr;
-       u32 extra_shift;
-       int ret = 0;
-
-       if (smc_start_address & 3)
-               return -EINVAL;
-       if ((smc_start_address + byte_count) > limit)
-               return -EINVAL;
-
-       addr = smc_start_address;
-
-       spin_lock_irqsave(&adev->smc_idx_lock, flags);
-       while (byte_count >= 4) {
-               /* SMC address space is BE */
-               data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
-
-               ret = ci_set_smc_sram_address(adev, addr, limit);
-               if (ret)
-                       goto done;
-
-               WREG32(mmSMC_IND_DATA_0, data);
-
-               src += 4;
-               byte_count -= 4;
-               addr += 4;
-       }
-
-       /* RMW for the final bytes */
-       if (byte_count > 0) {
-               data = 0;
-
-               ret = ci_set_smc_sram_address(adev, addr, limit);
-               if (ret)
-                       goto done;
-
-               original_data = RREG32(mmSMC_IND_DATA_0);
-
-               extra_shift = 8 * (4 - byte_count);
-
-               while (byte_count > 0) {
-                       data = (data << 8) + *src++;
-                       byte_count--;
-               }
-
-               data <<= extra_shift;
-
-               data |= (original_data & ~((~0UL) << extra_shift));
-
-               ret = ci_set_smc_sram_address(adev, addr, limit);
-               if (ret)
-                       goto done;
-
-               WREG32(mmSMC_IND_DATA_0, data);
-       }
-
-done:
-       spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
-
-       return ret;
-}
-
-void amdgpu_ci_start_smc(struct amdgpu_device *adev)
-{
-       u32 tmp = RREG32_SMC(ixSMC_SYSCON_RESET_CNTL);
-
-       tmp &= ~SMC_SYSCON_RESET_CNTL__rst_reg_MASK;
-       WREG32_SMC(ixSMC_SYSCON_RESET_CNTL, tmp);
-}
-
-void amdgpu_ci_reset_smc(struct amdgpu_device *adev)
-{
-       u32 tmp = RREG32_SMC(ixSMC_SYSCON_RESET_CNTL);
-
-       tmp |= SMC_SYSCON_RESET_CNTL__rst_reg_MASK;
-       WREG32_SMC(ixSMC_SYSCON_RESET_CNTL, tmp);
-}
-
-int amdgpu_ci_program_jump_on_start(struct amdgpu_device *adev)
-{
-       static u8 data[] = { 0xE0, 0x00, 0x80, 0x40 };
-
-       return amdgpu_ci_copy_bytes_to_smc(adev, 0x0, data, 4, sizeof(data)+1);
-}
-
-void amdgpu_ci_stop_smc_clock(struct amdgpu_device *adev)
-{
-       u32 tmp = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0);
-
-       tmp |= SMC_SYSCON_CLOCK_CNTL_0__ck_disable_MASK;
-
-       WREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0, tmp);
-}
-
-void amdgpu_ci_start_smc_clock(struct amdgpu_device *adev)
-{
-       u32 tmp = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0);
-
-       tmp &= ~SMC_SYSCON_CLOCK_CNTL_0__ck_disable_MASK;
-
-       WREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0, tmp);
-}
-
-bool amdgpu_ci_is_smc_running(struct amdgpu_device *adev)
-{
-       u32 clk = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0);
-       u32 pc_c = RREG32_SMC(ixSMC_PC_C);
-
-       if (!(clk & SMC_SYSCON_CLOCK_CNTL_0__ck_disable_MASK) && (0x20100 <= pc_c))
-               return true;
-
-       return false;
-}
-
-PPSMC_Result amdgpu_ci_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg)
-{
-       u32 tmp;
-       int i;
-
-       if (!amdgpu_ci_is_smc_running(adev))
-               return PPSMC_Result_Failed;
-
-       WREG32(mmSMC_MESSAGE_0, msg);
-
-       for (i = 0; i < adev->usec_timeout; i++) {
-               tmp = RREG32(mmSMC_RESP_0);
-               if (tmp != 0)
-                       break;
-               udelay(1);
-       }
-       tmp = RREG32(mmSMC_RESP_0);
-
-       return (PPSMC_Result)tmp;
-}
-
-PPSMC_Result amdgpu_ci_wait_for_smc_inactive(struct amdgpu_device *adev)
-{
-       u32 tmp;
-       int i;
-
-       if (!amdgpu_ci_is_smc_running(adev))
-               return PPSMC_Result_OK;
-
-       for (i = 0; i < adev->usec_timeout; i++) {
-               tmp = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0);
-               if ((tmp & SMC_SYSCON_CLOCK_CNTL_0__cken_MASK) == 0)
-                       break;
-               udelay(1);
-       }
-
-       return PPSMC_Result_OK;
-}
-
-int amdgpu_ci_load_smc_ucode(struct amdgpu_device *adev, u32 limit)
-{
-       const struct smc_firmware_header_v1_0 *hdr;
-       unsigned long flags;
-       u32 ucode_start_address;
-       u32 ucode_size;
-       const u8 *src;
-       u32 data;
-
-       if (!adev->pm.fw)
-               return -EINVAL;
-
-       hdr = (const struct smc_firmware_header_v1_0 *)adev->pm.fw->data;
-       amdgpu_ucode_print_smc_hdr(&hdr->header);
-
-       adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version);
-       ucode_start_address = le32_to_cpu(hdr->ucode_start_addr);
-       ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
-       src = (const u8 *)
-               (adev->pm.fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
-
-       if (ucode_size & 3)
-               return -EINVAL;
-
-       spin_lock_irqsave(&adev->smc_idx_lock, flags);
-       WREG32(mmSMC_IND_INDEX_0, ucode_start_address);
-       WREG32_P(mmSMC_IND_ACCESS_CNTL, SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_0_MASK,
-               ~SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_0_MASK);
-       while (ucode_size >= 4) {
-               /* SMC address space is BE */
-               data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
-
-               WREG32(mmSMC_IND_DATA_0, data);
-
-               src += 4;
-               ucode_size -= 4;
-       }
-       WREG32_P(mmSMC_IND_ACCESS_CNTL, 0, ~SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_0_MASK);
-       spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
-
-       return 0;
-}
-
-int amdgpu_ci_read_smc_sram_dword(struct amdgpu_device *adev,
-                          u32 smc_address, u32 *value, u32 limit)
-{
-       unsigned long flags;
-       int ret;
-
-       spin_lock_irqsave(&adev->smc_idx_lock, flags);
-       ret = ci_set_smc_sram_address(adev, smc_address, limit);
-       if (ret == 0)
-               *value = RREG32(mmSMC_IND_DATA_0);
-       spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
-
-       return ret;
-}
-
-int amdgpu_ci_write_smc_sram_dword(struct amdgpu_device *adev,
-                           u32 smc_address, u32 value, u32 limit)
-{
-       unsigned long flags;
-       int ret;
-
-       spin_lock_irqsave(&adev->smc_idx_lock, flags);
-       ret = ci_set_smc_sram_address(adev, smc_address, limit);
-       if (ret == 0)
-               WREG32(mmSMC_IND_DATA_0, value);
-       spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
-
-       return ret;
-}
index 71c50d8900e39137f7749c6a94f41426da32e711..07c1f239e9c344c83ef22414000fb92b8225e87f 100644 (file)
@@ -1741,6 +1741,69 @@ static bool cik_need_full_reset(struct amdgpu_device *adev)
        return true;
 }
 
+static void cik_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0,
+                              uint64_t *count1)
+{
+       uint32_t perfctr = 0;
+       uint64_t cnt0_of, cnt1_of;
+       int tmp;
+
+       /* This reports 0 on APUs, so return to avoid writing/reading registers
+        * that may or may not be different from their GPU counterparts
+        */
+       if (adev->flags & AMD_IS_APU)
+               return;
+
+       /* Set the 2 events that we wish to watch, defined above */
+       /* Reg 40 is # received msgs, Reg 104 is # of posted requests sent */
+       perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT0_SEL, 40);
+       perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT1_SEL, 104);
+
+       /* Write to enable desired perf counters */
+       WREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK, perfctr);
+       /* Zero out and enable the perf counters
+        * Write 0x5:
+        * Bit 0 = Start all counters(1)
+        * Bit 2 = Global counter reset enable(1)
+        */
+       WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000005);
+
+       msleep(1000);
+
+       /* Load the shadow and disable the perf counters
+        * Write 0x2:
+        * Bit 0 = Stop counters(0)
+        * Bit 1 = Load the shadow counters(1)
+        */
+       WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000002);
+
+       /* Read register values to get any >32bit overflow */
+       tmp = RREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK);
+       cnt0_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER0_UPPER);
+       cnt1_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER1_UPPER);
+
+       /* Get the values and add the overflow */
+       *count0 = RREG32_PCIE(ixPCIE_PERF_COUNT0_TXCLK) | (cnt0_of << 32);
+       *count1 = RREG32_PCIE(ixPCIE_PERF_COUNT1_TXCLK) | (cnt1_of << 32);
+}
+
+static bool cik_need_reset_on_init(struct amdgpu_device *adev)
+{
+       u32 clock_cntl, pc;
+
+       if (adev->flags & AMD_IS_APU)
+               return false;
+
+       /* check if the SMC is already running */
+       clock_cntl = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0);
+       pc = RREG32_SMC(ixSMC_PC_C);
+       if ((0 == REG_GET_FIELD(clock_cntl, SMC_SYSCON_CLOCK_CNTL_0, ck_disable)) &&
+           (0x20100 <= pc))
+               return true;
+
+       return false;
+}
+
 static const struct amdgpu_asic_funcs cik_asic_funcs =
 {
        .read_disabled_bios = &cik_read_disabled_bios,
@@ -1756,6 +1819,8 @@ static const struct amdgpu_asic_funcs cik_asic_funcs =
        .invalidate_hdp = &cik_invalidate_hdp,
        .need_full_reset = &cik_need_full_reset,
        .init_doorbell_index = &legacy_doorbell_index_init,
+       .get_pcie_usage = &cik_get_pcie_usage,
+       .need_reset_on_init = &cik_need_reset_on_init,
 };
 
 static int cik_common_early_init(void *handle)
@@ -2005,10 +2070,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
                amdgpu_device_ip_block_add(adev, &cik_ih_ip_block);
                amdgpu_device_ip_block_add(adev, &gfx_v7_2_ip_block);
                amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
-               if (amdgpu_dpm == -1)
-                       amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
-               else
-                       amdgpu_device_ip_block_add(adev, &ci_smu_ip_block);
+               amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
                if (adev->enable_virtual_display)
                        amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
@@ -2026,10 +2088,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
                amdgpu_device_ip_block_add(adev, &cik_ih_ip_block);
                amdgpu_device_ip_block_add(adev, &gfx_v7_3_ip_block);
                amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
-               if (amdgpu_dpm == -1)
-                       amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
-               else
-                       amdgpu_device_ip_block_add(adev, &ci_smu_ip_block);
+               amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
                if (adev->enable_virtual_display)
                        amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
index 2a086610f74d4d0c5d4351505b4d71eb33ca6ce7..2fcc4b60153cf7d712f24dfb68f1feb272c310ed 100644 (file)
@@ -24,7 +24,6 @@
 #ifndef __CIK_DPM_H__
 #define __CIK_DPM_H__
 
-extern const struct amdgpu_ip_block_version ci_smu_ip_block;
 extern const struct amdgpu_ip_block_version kv_smu_ip_block;
 
 #endif
index 8a8b4967a101fca3b8daca0908ce39fc2247ae4b..721c757156e871809290149ac1a4b43706419b5b 100644 (file)
@@ -103,9 +103,9 @@ static void cik_ih_disable_interrupts(struct amdgpu_device *adev)
  */
 static int cik_ih_irq_init(struct amdgpu_device *adev)
 {
+       struct amdgpu_ih_ring *ih = &adev->irq.ih;
        int rb_bufsz;
        u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
-       u64 wptr_off;
 
        /* disable irqs */
        cik_ih_disable_interrupts(adev);
@@ -131,9 +131,8 @@ static int cik_ih_irq_init(struct amdgpu_device *adev)
        ih_rb_cntl |= IH_RB_CNTL__WPTR_WRITEBACK_ENABLE_MASK;
 
        /* set the writeback address whether it's enabled or not */
-       wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4);
-       WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off));
-       WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF);
+       WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr));
+       WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF);
 
        WREG32(mmIH_RB_CNTL, ih_rb_cntl);
 
@@ -183,11 +182,12 @@ static void cik_ih_irq_disable(struct amdgpu_device *adev)
  * Used by cik_irq_process().
  * Returns the value of the wptr.
  */
-static u32 cik_ih_get_wptr(struct amdgpu_device *adev)
+static u32 cik_ih_get_wptr(struct amdgpu_device *adev,
+                          struct amdgpu_ih_ring *ih)
 {
        u32 wptr, tmp;
 
-       wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]);
+       wptr = le32_to_cpu(*ih->wptr_cpu);
 
        if (wptr & IH_RB_WPTR__RB_OVERFLOW_MASK) {
                wptr &= ~IH_RB_WPTR__RB_OVERFLOW_MASK;
@@ -196,13 +196,13 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev)
                 * this should allow us to catchup.
                 */
                dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
-                       wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask);
-               adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask;
+                        wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
+               ih->rptr = (wptr + 16) & ih->ptr_mask;
                tmp = RREG32(mmIH_RB_CNTL);
                tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK;
                WREG32(mmIH_RB_CNTL, tmp);
        }
-       return (wptr & adev->irq.ih.ptr_mask);
+       return (wptr & ih->ptr_mask);
 }
 
 /*        CIK IV Ring
@@ -237,16 +237,17 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev)
  * position and also advance the position.
  */
 static void cik_ih_decode_iv(struct amdgpu_device *adev,
+                            struct amdgpu_ih_ring *ih,
                             struct amdgpu_iv_entry *entry)
 {
        /* wptr/rptr are in bytes! */
-       u32 ring_index = adev->irq.ih.rptr >> 2;
+       u32 ring_index = ih->rptr >> 2;
        uint32_t dw[4];
 
-       dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
-       dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]);
-       dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]);
-       dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]);
+       dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
+       dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
+       dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
+       dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
 
        entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
        entry->src_id = dw[0] & 0xff;
@@ -256,7 +257,7 @@ static void cik_ih_decode_iv(struct amdgpu_device *adev,
        entry->pasid = (dw[2] >> 16) & 0xffff;
 
        /* wptr/rptr are in bytes! */
-       adev->irq.ih.rptr += 16;
+       ih->rptr += 16;
 }
 
 /**
@@ -266,9 +267,10 @@ static void cik_ih_decode_iv(struct amdgpu_device *adev,
  *
  * Set the IH ring buffer rptr.
  */
-static void cik_ih_set_rptr(struct amdgpu_device *adev)
+static void cik_ih_set_rptr(struct amdgpu_device *adev,
+                           struct amdgpu_ih_ring *ih)
 {
-       WREG32(mmIH_RB_RPTR, adev->irq.ih.rptr);
+       WREG32(mmIH_RB_RPTR, ih->rptr);
 }
 
 static int cik_ih_early_init(void *handle)
index 45795191de1ff9865153ba04f926aef38500cc22..189599b694e8a88ec523d439462564c99970d3a1 100644 (file)
@@ -220,7 +220,7 @@ static void cik_sdma_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
 static void cik_sdma_ring_emit_ib(struct amdgpu_ring *ring,
                                  struct amdgpu_job *job,
                                  struct amdgpu_ib *ib,
-                                 bool ctx_switch)
+                                 uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
        u32 extra_bits = vmid & 0xf;
index 9d3ea298e116de7a0fa14e5858b50444ddd7dd46..61024b9c7a4b2662b7ee56e805f8112d403ab241 100644 (file)
@@ -103,9 +103,9 @@ static void cz_ih_disable_interrupts(struct amdgpu_device *adev)
  */
 static int cz_ih_irq_init(struct amdgpu_device *adev)
 {
-       int rb_bufsz;
+       struct amdgpu_ih_ring *ih = &adev->irq.ih;
        u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
-       u64 wptr_off;
+       int rb_bufsz;
 
        /* disable irqs */
        cz_ih_disable_interrupts(adev);
@@ -133,9 +133,8 @@ static int cz_ih_irq_init(struct amdgpu_device *adev)
        ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_WRITEBACK_ENABLE, 1);
 
        /* set the writeback address whether it's enabled or not */
-       wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4);
-       WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off));
-       WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF);
+       WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr));
+       WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF);
 
        WREG32(mmIH_RB_CNTL, ih_rb_cntl);
 
@@ -185,11 +184,12 @@ static void cz_ih_irq_disable(struct amdgpu_device *adev)
  * Used by cz_irq_process(VI).
  * Returns the value of the wptr.
  */
-static u32 cz_ih_get_wptr(struct amdgpu_device *adev)
+static u32 cz_ih_get_wptr(struct amdgpu_device *adev,
+                         struct amdgpu_ih_ring *ih)
 {
        u32 wptr, tmp;
 
-       wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]);
+       wptr = le32_to_cpu(*ih->wptr_cpu);
 
        if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
                wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
@@ -198,13 +198,13 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev)
                 * this should allow us to catchup.
                 */
                dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
-                       wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask);
-               adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask;
+                       wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
+               ih->rptr = (wptr + 16) & ih->ptr_mask;
                tmp = RREG32(mmIH_RB_CNTL);
                tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
                WREG32(mmIH_RB_CNTL, tmp);
        }
-       return (wptr & adev->irq.ih.ptr_mask);
+       return (wptr & ih->ptr_mask);
 }
 
 /**
@@ -216,16 +216,17 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev)
  * position and also advance the position.
  */
 static void cz_ih_decode_iv(struct amdgpu_device *adev,
-                                struct amdgpu_iv_entry *entry)
+                           struct amdgpu_ih_ring *ih,
+                           struct amdgpu_iv_entry *entry)
 {
        /* wptr/rptr are in bytes! */
-       u32 ring_index = adev->irq.ih.rptr >> 2;
+       u32 ring_index = ih->rptr >> 2;
        uint32_t dw[4];
 
-       dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
-       dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]);
-       dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]);
-       dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]);
+       dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
+       dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
+       dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
+       dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
 
        entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
        entry->src_id = dw[0] & 0xff;
@@ -235,7 +236,7 @@ static void cz_ih_decode_iv(struct amdgpu_device *adev,
        entry->pasid = (dw[2] >> 16) & 0xffff;
 
        /* wptr/rptr are in bytes! */
-       adev->irq.ih.rptr += 16;
+       ih->rptr += 16;
 }
 
 /**
@@ -245,9 +246,10 @@ static void cz_ih_decode_iv(struct amdgpu_device *adev,
  *
  * Set the IH ring buffer rptr.
  */
-static void cz_ih_set_rptr(struct amdgpu_device *adev)
+static void cz_ih_set_rptr(struct amdgpu_device *adev,
+                          struct amdgpu_ih_ring *ih)
 {
-       WREG32(mmIH_RB_RPTR, adev->irq.ih.rptr);
+       WREG32(mmIH_RB_RPTR, ih->rptr);
 }
 
 static int cz_ih_early_init(void *handle)
index 4cfecdce29a3c86dc30e509007ecec3a22eda338..1f0426d2fc2a0149529e19dea0fa8cbbb21fd350 100644 (file)
@@ -1682,7 +1682,7 @@ static void dce_v10_0_afmt_setmode(struct drm_encoder *encoder,
        dce_v10_0_audio_write_sad_regs(encoder);
        dce_v10_0_audio_write_latency_fields(encoder, mode);
 
-       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
+       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, connector, mode);
        if (err < 0) {
                DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
                return;
index 7c868916d90f83a4493ffb27db4e6286430c75f5..2280b971d758457d7a07214687e6d3d6ecc70f78 100644 (file)
@@ -1724,7 +1724,7 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder,
        dce_v11_0_audio_write_sad_regs(encoder);
        dce_v11_0_audio_write_latency_fields(encoder, mode);
 
-       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
+       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, connector, mode);
        if (err < 0) {
                DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
                return;
index 17eaaba3601706ce4f8ed9010c9460a5b074e619..db443ec53d3aeb5db36c09fdbf45f9287658f4d2 100644 (file)
@@ -1423,6 +1423,7 @@ static void dce_v6_0_audio_set_avi_infoframe(struct drm_encoder *encoder,
        struct amdgpu_device *adev = dev->dev_private;
        struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
        struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
+       struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder);
        struct hdmi_avi_infoframe frame;
        u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
        uint8_t *payload = buffer + 3;
@@ -1430,7 +1431,7 @@ static void dce_v6_0_audio_set_avi_infoframe(struct drm_encoder *encoder,
        ssize_t err;
        u32 tmp;
 
-       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
+       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, connector, mode);
        if (err < 0) {
                DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
                return;
index 8c0576978d36220d305e1b0231764d8b78b2b8ea..13da915991dd4b8bfa0a08236fdc6e485ed0f646 100644 (file)
@@ -1616,7 +1616,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder,
        dce_v8_0_audio_write_sad_regs(encoder);
        dce_v8_0_audio_write_latency_fields(encoder, mode);
 
-       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
+       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, connector, mode);
        if (err < 0) {
                DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
                return;
index fdace004544d4ff814f43d2c5e894f8cd0dca51a..e4cc1d48eaabbcdffb76ce278e7d60bb44c4ddcb 100644 (file)
@@ -167,19 +167,6 @@ static void dce_virtual_crtc_disable(struct drm_crtc *crtc)
        struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 
        dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
-       if (crtc->primary->fb) {
-               int r;
-               struct amdgpu_bo *abo;
-
-               abo = gem_to_amdgpu_bo(crtc->primary->fb->obj[0]);
-               r = amdgpu_bo_reserve(abo, true);
-               if (unlikely(r))
-                       DRM_ERROR("failed to reserve abo before unpin\n");
-               else {
-                       amdgpu_bo_unpin(abo);
-                       amdgpu_bo_unreserve(abo);
-               }
-       }
 
        amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
        amdgpu_crtc->encoder = NULL;
@@ -692,7 +679,9 @@ static int dce_virtual_pageflip(struct amdgpu_device *adev,
        spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
 
        drm_crtc_vblank_put(&amdgpu_crtc->base);
-       schedule_work(&works->unpin_work);
+       amdgpu_bo_unref(&works->old_abo);
+       kfree(works->shared);
+       kfree(works);
 
        return 0;
 }
index 1dc3013ea1d5401120bb9f87393ca7875903d676..305276c7e4bf849602159f7ef202bb9cb5a3a7e2 100644 (file)
@@ -1842,13 +1842,13 @@ static void gfx_v6_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
 static void gfx_v6_0_ring_emit_ib(struct amdgpu_ring *ring,
                                  struct amdgpu_job *job,
                                  struct amdgpu_ib *ib,
-                                 bool ctx_switch)
+                                 uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
        u32 header, control = 0;
 
        /* insert SWITCH_BUFFER packet before first IB in the ring frame */
-       if (ctx_switch) {
+       if (flags & AMDGPU_HAVE_CTX_SWITCH) {
                amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
                amdgpu_ring_write(ring, 0);
        }
index 3a9fb6018c1611e99bf5e07eb35a21c44dda27f7..7984292f9282352c83adadfb9a52af1f254245f7 100644 (file)
@@ -2228,13 +2228,13 @@ static void gfx_v7_0_ring_emit_fence_compute(struct amdgpu_ring *ring,
 static void gfx_v7_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
                                        struct amdgpu_job *job,
                                        struct amdgpu_ib *ib,
-                                       bool ctx_switch)
+                                       uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
        u32 header, control = 0;
 
        /* insert SWITCH_BUFFER packet before first IB in the ring frame */
-       if (ctx_switch) {
+       if (flags & AMDGPU_HAVE_CTX_SWITCH) {
                amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
                amdgpu_ring_write(ring, 0);
        }
@@ -2259,7 +2259,7 @@ static void gfx_v7_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
 static void gfx_v7_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
                                          struct amdgpu_job *job,
                                          struct amdgpu_ib *ib,
-                                         bool ctx_switch)
+                                         uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
        u32 control = INDIRECT_BUFFER_VALID | ib->length_dw | (vmid << 24);
index 381f593b0cda83bdda6f67f2d2b41cd8488583c4..a26747681ed6be2fc9d11192ae0a946236247c4f 100644 (file)
@@ -4233,7 +4233,6 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev)
        u32 tmp;
        u32 rb_bufsz;
        u64 rb_addr, rptr_addr, wptr_gpu_addr;
-       int r;
 
        /* Set the write pointer delay */
        WREG32(mmCP_RB_WPTR_DELAY, 0);
@@ -4278,9 +4277,8 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev)
        amdgpu_ring_clear_ring(ring);
        gfx_v8_0_cp_gfx_start(adev);
        ring->sched.ready = true;
-       r = amdgpu_ring_test_helper(ring);
 
-       return r;
+       return 0;
 }
 
 static void gfx_v8_0_cp_compute_enable(struct amdgpu_device *adev, bool enable)
@@ -4369,10 +4367,9 @@ static int gfx_v8_0_kiq_kcq_enable(struct amdgpu_device *adev)
                amdgpu_ring_write(kiq_ring, upper_32_bits(wptr_addr));
        }
 
-       r = amdgpu_ring_test_helper(kiq_ring);
-       if (r)
-               DRM_ERROR("KCQ enable failed\n");
-       return r;
+       amdgpu_ring_commit(kiq_ring);
+
+       return 0;
 }
 
 static int gfx_v8_0_deactivate_hqd(struct amdgpu_device *adev, u32 req)
@@ -4709,16 +4706,32 @@ static int gfx_v8_0_kcq_resume(struct amdgpu_device *adev)
        if (r)
                goto done;
 
-       /* Test KCQs - reversing the order of rings seems to fix ring test failure
-        * after GPU reset
-        */
-       for (i = adev->gfx.num_compute_rings - 1; i >= 0; i--) {
+done:
+       return r;
+}
+
+static int gfx_v8_0_cp_test_all_rings(struct amdgpu_device *adev)
+{
+       int r, i;
+       struct amdgpu_ring *ring;
+
+       /* collect all the ring_tests here, gfx, kiq, compute */
+       ring = &adev->gfx.gfx_ring[0];
+       r = amdgpu_ring_test_helper(ring);
+       if (r)
+               return r;
+
+       ring = &adev->gfx.kiq.ring;
+       r = amdgpu_ring_test_helper(ring);
+       if (r)
+               return r;
+
+       for (i = 0; i < adev->gfx.num_compute_rings; i++) {
                ring = &adev->gfx.compute_ring[i];
-               r = amdgpu_ring_test_helper(ring);
+               amdgpu_ring_test_helper(ring);
        }
 
-done:
-       return r;
+       return 0;
 }
 
 static int gfx_v8_0_cp_resume(struct amdgpu_device *adev)
@@ -4739,6 +4752,11 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev)
        r = gfx_v8_0_kcq_resume(adev);
        if (r)
                return r;
+
+       r = gfx_v8_0_cp_test_all_rings(adev);
+       if (r)
+               return r;
+
        gfx_v8_0_enable_gui_idle_interrupt(adev, true);
 
        return 0;
@@ -5086,6 +5104,8 @@ static int gfx_v8_0_post_soft_reset(void *handle)
            REG_GET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_GFX))
                gfx_v8_0_cp_gfx_resume(adev);
 
+       gfx_v8_0_cp_test_all_rings(adev);
+
        adev->gfx.rlc.funcs->start(adev);
 
        return 0;
@@ -6027,7 +6047,7 @@ static void gfx_v8_0_ring_emit_vgt_flush(struct amdgpu_ring *ring)
 static void gfx_v8_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
                                        struct amdgpu_job *job,
                                        struct amdgpu_ib *ib,
-                                       bool ctx_switch)
+                                       uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
        u32 header, control = 0;
@@ -6059,7 +6079,7 @@ static void gfx_v8_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
 static void gfx_v8_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
                                          struct amdgpu_job *job,
                                          struct amdgpu_ib *ib,
-                                         bool ctx_switch)
+                                         uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
        u32 control = INDIRECT_BUFFER_VALID | ib->length_dw | (vmid << 24);
index 7556716038d376b6e7dff5fcd27af537dc5346e3..262ee3cf6f1c438dbbee1cb9ce7a8951afd7c6d3 100644 (file)
@@ -113,7 +113,10 @@ static const struct soc15_reg_golden golden_settings_gc_9_0[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_HI, 0xffffffff, 0x4a2c0e68),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_LO, 0xffffffff, 0xb5d3f197),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_CACHE_INVALIDATION, 0x3fff3af3, 0x19200000),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000003ff)
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000003ff),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x00000000, 0x00000800),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000000, 0x00000800),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00000000, 0x00008000)
 };
 
 static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] =
@@ -135,10 +138,7 @@ static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_UTCL1_CNTL2, 0x00030000, 0x00020000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL_1, 0x0000000f, 0x01000107),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTD_CNTL, 0x00001800, 0x00000800),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x00000000, 0x00000800),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000000, 0x00000800),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00000000, 0x00008000)
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080)
 };
 
 static const struct soc15_reg_golden golden_settings_gc_9_0_vg20[] =
@@ -3587,6 +3587,8 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
 {
        uint32_t data, def;
 
+       amdgpu_gfx_rlc_enter_safe_mode(adev);
+
        /* It is disabled by HW by default */
        if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
                /* 1 - RLC_CGTT_MGCG_OVERRIDE */
@@ -3651,6 +3653,8 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
                        WREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL, data);
                }
        }
+
+       amdgpu_gfx_rlc_exit_safe_mode(adev);
 }
 
 static void gfx_v9_0_update_3d_clock_gating(struct amdgpu_device *adev,
@@ -3968,7 +3972,7 @@ static void gfx_v9_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
 static void gfx_v9_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
                                        struct amdgpu_job *job,
                                        struct amdgpu_ib *ib,
-                                       bool ctx_switch)
+                                       uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
        u32 header, control = 0;
@@ -4001,7 +4005,7 @@ static void gfx_v9_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
 static void gfx_v9_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
                                          struct amdgpu_job *job,
                                          struct amdgpu_ib *ib,
-                                         bool ctx_switch)
+                                         uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
        u32 control = INDIRECT_BUFFER_VALID | ib->length_dw | (vmid << 24);
index 1ad7e6b8ed1dcf3f8795eab178f672938e82d050..34440672f938455a473e9dc4c9c5716236568aa3 100644 (file)
@@ -1471,8 +1471,9 @@ static int gmc_v8_0_process_interrupt(struct amdgpu_device *adev,
                gmc_v8_0_set_fault_enable_default(adev, false);
 
        if (printk_ratelimit()) {
-               struct amdgpu_task_info task_info = { 0 };
+               struct amdgpu_task_info task_info;
 
+               memset(&task_info, 0, sizeof(struct amdgpu_task_info));
                amdgpu_vm_get_task_info(adev, entry->pasid, &task_info);
 
                dev_err(adev->dev, "GPU fault detected: %d 0x%08x for process %s pid %d thread %s pid %d\n",
index bacdaef77b6c1ad0d3e12943e2bf53fefcea74b9..9c082f9aea1a13ed0bb0d44bac73437feb287f59 100644 (file)
@@ -305,6 +305,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
                                struct amdgpu_iv_entry *entry)
 {
        struct amdgpu_vmhub *hub = &adev->vmhub[entry->vmid_src];
+       bool retry_fault = !!(entry->src_data[1] & 0x80);
        uint32_t status = 0;
        u64 addr;
 
@@ -320,13 +321,16 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
        }
 
        if (printk_ratelimit()) {
-               struct amdgpu_task_info task_info = { 0 };
+               struct amdgpu_task_info task_info;
 
+               memset(&task_info, 0, sizeof(struct amdgpu_task_info));
                amdgpu_vm_get_task_info(adev, entry->pasid, &task_info);
 
                dev_err(adev->dev,
-                       "[%s] VMC page fault (src_id:%u ring:%u vmid:%u pasid:%u, for process %s pid %d thread %s pid %d)\n",
+                       "[%s] %s page fault (src_id:%u ring:%u vmid:%u "
+                       "pasid:%u, for process %s pid %d thread %s pid %d)\n",
                        entry->vmid_src ? "mmhub" : "gfxhub",
+                       retry_fault ? "retry" : "no-retry",
                        entry->src_id, entry->ring_id, entry->vmid,
                        entry->pasid, task_info.process_name, task_info.tgid,
                        task_info.task_name, task_info.pid);
index a3984d10b604e1a4127009bf63f57cf3a964da7e..b1626e1d2f5d62289f12c8bf2892151b0c470ad1 100644 (file)
@@ -103,9 +103,9 @@ static void iceland_ih_disable_interrupts(struct amdgpu_device *adev)
  */
 static int iceland_ih_irq_init(struct amdgpu_device *adev)
 {
+       struct amdgpu_ih_ring *ih = &adev->irq.ih;
        int rb_bufsz;
        u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
-       u64 wptr_off;
 
        /* disable irqs */
        iceland_ih_disable_interrupts(adev);
@@ -133,9 +133,8 @@ static int iceland_ih_irq_init(struct amdgpu_device *adev)
        ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_WRITEBACK_ENABLE, 1);
 
        /* set the writeback address whether it's enabled or not */
-       wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4);
-       WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off));
-       WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF);
+       WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr));
+       WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF);
 
        WREG32(mmIH_RB_CNTL, ih_rb_cntl);
 
@@ -185,11 +184,12 @@ static void iceland_ih_irq_disable(struct amdgpu_device *adev)
  * Used by cz_irq_process(VI).
  * Returns the value of the wptr.
  */
-static u32 iceland_ih_get_wptr(struct amdgpu_device *adev)
+static u32 iceland_ih_get_wptr(struct amdgpu_device *adev,
+                              struct amdgpu_ih_ring *ih)
 {
        u32 wptr, tmp;
 
-       wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]);
+       wptr = le32_to_cpu(*ih->wptr_cpu);
 
        if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
                wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
@@ -198,13 +198,13 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev)
                 * this should allow us to catchup.
                 */
                dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
-                       wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask);
-               adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask;
+                        wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
+               ih->rptr = (wptr + 16) & ih->ptr_mask;
                tmp = RREG32(mmIH_RB_CNTL);
                tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
                WREG32(mmIH_RB_CNTL, tmp);
        }
-       return (wptr & adev->irq.ih.ptr_mask);
+       return (wptr & ih->ptr_mask);
 }
 
 /**
@@ -216,16 +216,17 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev)
  * position and also advance the position.
  */
 static void iceland_ih_decode_iv(struct amdgpu_device *adev,
+                                struct amdgpu_ih_ring *ih,
                                 struct amdgpu_iv_entry *entry)
 {
        /* wptr/rptr are in bytes! */
-       u32 ring_index = adev->irq.ih.rptr >> 2;
+       u32 ring_index = ih->rptr >> 2;
        uint32_t dw[4];
 
-       dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
-       dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]);
-       dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]);
-       dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]);
+       dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
+       dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
+       dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
+       dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
 
        entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
        entry->src_id = dw[0] & 0xff;
@@ -235,7 +236,7 @@ static void iceland_ih_decode_iv(struct amdgpu_device *adev,
        entry->pasid = (dw[2] >> 16) & 0xffff;
 
        /* wptr/rptr are in bytes! */
-       adev->irq.ih.rptr += 16;
+       ih->rptr += 16;
 }
 
 /**
@@ -245,9 +246,10 @@ static void iceland_ih_decode_iv(struct amdgpu_device *adev,
  *
  * Set the IH ring buffer rptr.
  */
-static void iceland_ih_set_rptr(struct amdgpu_device *adev)
+static void iceland_ih_set_rptr(struct amdgpu_device *adev,
+                               struct amdgpu_ih_ring *ih)
 {
-       WREG32(mmIH_RB_RPTR, adev->irq.ih.rptr);
+       WREG32(mmIH_RB_RPTR, ih->rptr);
 }
 
 static int iceland_ih_early_init(void *handle)
index 8cbb4655896a3318471c909f9cac0116d74ac055..b11a1c17a7f27e76cdfd4036a1a3331e3a93476a 100644 (file)
@@ -174,7 +174,7 @@ static int xgpu_ai_send_access_requests(struct amdgpu_device *adev,
                        return r;
                }
                /* Retrieve checksum from mailbox2 */
-               if (req == IDH_REQ_GPU_INIT_ACCESS) {
+               if (req == IDH_REQ_GPU_INIT_ACCESS || req == IDH_REQ_GPU_RESET_ACCESS) {
                        adev->virt.fw_reserve.checksum_key =
                                RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0,
                                        mmBIF_BX_PF0_MAILBOX_MSGBUF_RCV_DW2));
index accdedd63c98199191972ca378a4bf5becc1c182..cc967dbfd631d352eea1bca20713903667ebebac 100644 (file)
 #include "nbio/nbio_6_1_default.h"
 #include "nbio/nbio_6_1_offset.h"
 #include "nbio/nbio_6_1_sh_mask.h"
+#include "nbio/nbio_6_1_smn.h"
 #include "vega10_enum.h"
 
-#define smnCPM_CONTROL                                                                                  0x11180460
-#define smnPCIE_CNTL2                                                                                   0x11180070
-#define smnPCIE_CONFIG_CNTL                                                                             0x11180044
-#define smnPCIE_CI_CNTL                                                                                 0x11180080
-
 static u32 nbio_v6_1_get_rev_id(struct amdgpu_device *adev)
 {
         u32 tmp = RREG32_SOC15(NBIO, 0, mmRCC_DEV0_EPF0_STRAP0);
@@ -72,7 +68,7 @@ static u32 nbio_v6_1_get_memsize(struct amdgpu_device *adev)
 }
 
 static void nbio_v6_1_sdma_doorbell_range(struct amdgpu_device *adev, int instance,
-                                 bool use_doorbell, int doorbell_index)
+                       bool use_doorbell, int doorbell_index, int doorbell_size)
 {
        u32 reg = instance == 0 ? SOC15_REG_OFFSET(NBIO, 0, mmBIF_SDMA0_DOORBELL_RANGE) :
                        SOC15_REG_OFFSET(NBIO, 0, mmBIF_SDMA1_DOORBELL_RANGE);
@@ -81,7 +77,7 @@ static void nbio_v6_1_sdma_doorbell_range(struct amdgpu_device *adev, int instan
 
        if (use_doorbell) {
                doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, OFFSET, doorbell_index);
-               doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, 2);
+               doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, doorbell_size);
        } else
                doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, 0);
 
index df34dc79d444f718cc80b5fd3f956005c5fd6ec4..1cdb98ad2db3c3e29039765743c03162c2b33d79 100644 (file)
 #include "nbio/nbio_7_0_default.h"
 #include "nbio/nbio_7_0_offset.h"
 #include "nbio/nbio_7_0_sh_mask.h"
+#include "nbio/nbio_7_0_smn.h"
 #include "vega10_enum.h"
 
 #define smnNBIF_MGCG_CTRL_LCLK 0x1013a05c
 
-#define smnCPM_CONTROL                                                                                  0x11180460
-#define smnPCIE_CNTL2                                                                                   0x11180070
-
 static u32 nbio_v7_0_get_rev_id(struct amdgpu_device *adev)
 {
         u32 tmp = RREG32_SOC15(NBIO, 0, mmRCC_DEV0_EPF0_STRAP0);
@@ -69,7 +67,7 @@ static u32 nbio_v7_0_get_memsize(struct amdgpu_device *adev)
 }
 
 static void nbio_v7_0_sdma_doorbell_range(struct amdgpu_device *adev, int instance,
-                                         bool use_doorbell, int doorbell_index)
+                       bool use_doorbell, int doorbell_index, int doorbell_size)
 {
        u32 reg = instance == 0 ? SOC15_REG_OFFSET(NBIO, 0, mmBIF_SDMA0_DOORBELL_RANGE) :
                        SOC15_REG_OFFSET(NBIO, 0, mmBIF_SDMA1_DOORBELL_RANGE);
@@ -78,7 +76,7 @@ static void nbio_v7_0_sdma_doorbell_range(struct amdgpu_device *adev, int instan
 
        if (use_doorbell) {
                doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, OFFSET, doorbell_index);
-               doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, 2);
+               doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, doorbell_size);
        } else
                doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, 0);
 
index 4cd31a276dcd29a29cc2187d54ffff4ce083d170..e347b407bd03948d4ee214474ed6728970ba1ee1 100644 (file)
 
 #include "nbio/nbio_7_4_offset.h"
 #include "nbio/nbio_7_4_sh_mask.h"
+#include "nbio/nbio_7_4_0_smn.h"
 
 #define smnNBIF_MGCG_CTRL_LCLK 0x1013a21c
 
-#define smnCPM_CONTROL                                                                                  0x11180460
-#define smnPCIE_CNTL2                                                                                   0x11180070
-#define smnPCIE_CI_CNTL                                                                                 0x11180080
-
 static u32 nbio_v7_4_get_rev_id(struct amdgpu_device *adev)
 {
     u32 tmp = RREG32_SOC15(NBIO, 0, mmRCC_DEV0_EPF0_STRAP0);
@@ -68,7 +65,7 @@ static u32 nbio_v7_4_get_memsize(struct amdgpu_device *adev)
 }
 
 static void nbio_v7_4_sdma_doorbell_range(struct amdgpu_device *adev, int instance,
-                                         bool use_doorbell, int doorbell_index)
+                       bool use_doorbell, int doorbell_index, int doorbell_size)
 {
        u32 reg = instance == 0 ? SOC15_REG_OFFSET(NBIO, 0, mmBIF_SDMA0_DOORBELL_RANGE) :
                        SOC15_REG_OFFSET(NBIO, 0, mmBIF_SDMA1_DOORBELL_RANGE);
@@ -77,7 +74,7 @@ static void nbio_v7_4_sdma_doorbell_range(struct amdgpu_device *adev, int instan
 
        if (use_doorbell) {
                doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, OFFSET, doorbell_index);
-               doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, 2);
+               doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, doorbell_size);
        } else
                doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, 0);
 
index 0de00fbe9233843cedf3549e4f5cc8bb875094d5..f3a7d207af07b88f80343ff8fd8eb553c9dd1791 100644 (file)
@@ -191,7 +191,7 @@ enum psp_gfx_fw_type
     GFX_FW_TYPE_MMSCH       = 19,
     GFX_FW_TYPE_RLC_RESTORE_LIST_GPM_MEM        = 20,
     GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_MEM        = 21,
-    GFX_FW_TYPE_RLC_RESTORE_LIST_CNTL           = 22,
+    GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_CNTL       = 22,
     GFX_FW_TYPE_UVD1        = 23,
     GFX_FW_TYPE_MAX         = 24
 };
index d78b4306a36f33411dd95b12245eedfd2ba9f847..77c2bc344dfc5f5271527c8424732d3ef7f95b88 100644 (file)
@@ -38,75 +38,6 @@ MODULE_FIRMWARE("amdgpu/raven_asd.bin");
 MODULE_FIRMWARE("amdgpu/picasso_asd.bin");
 MODULE_FIRMWARE("amdgpu/raven2_asd.bin");
 
-static int
-psp_v10_0_get_fw_type(struct amdgpu_firmware_info *ucode, enum psp_gfx_fw_type *type)
-{
-       switch(ucode->ucode_id) {
-       case AMDGPU_UCODE_ID_SDMA0:
-               *type = GFX_FW_TYPE_SDMA0;
-               break;
-       case AMDGPU_UCODE_ID_SDMA1:
-               *type = GFX_FW_TYPE_SDMA1;
-               break;
-       case AMDGPU_UCODE_ID_CP_CE:
-               *type = GFX_FW_TYPE_CP_CE;
-               break;
-       case AMDGPU_UCODE_ID_CP_PFP:
-               *type = GFX_FW_TYPE_CP_PFP;
-               break;
-       case AMDGPU_UCODE_ID_CP_ME:
-               *type = GFX_FW_TYPE_CP_ME;
-               break;
-       case AMDGPU_UCODE_ID_CP_MEC1:
-               *type = GFX_FW_TYPE_CP_MEC;
-               break;
-       case AMDGPU_UCODE_ID_CP_MEC1_JT:
-               *type = GFX_FW_TYPE_CP_MEC_ME1;
-               break;
-       case AMDGPU_UCODE_ID_CP_MEC2:
-               *type = GFX_FW_TYPE_CP_MEC;
-               break;
-       case AMDGPU_UCODE_ID_CP_MEC2_JT:
-               *type = GFX_FW_TYPE_CP_MEC_ME2;
-               break;
-       case AMDGPU_UCODE_ID_RLC_G:
-               *type = GFX_FW_TYPE_RLC_G;
-               break;
-       case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL:
-               *type = GFX_FW_TYPE_RLC_RESTORE_LIST_CNTL;
-               break;
-       case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM:
-               *type = GFX_FW_TYPE_RLC_RESTORE_LIST_GPM_MEM;
-               break;
-       case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM:
-               *type = GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_MEM;
-               break;
-       case AMDGPU_UCODE_ID_SMC:
-               *type = GFX_FW_TYPE_SMU;
-               break;
-       case AMDGPU_UCODE_ID_UVD:
-               *type = GFX_FW_TYPE_UVD;
-               break;
-       case AMDGPU_UCODE_ID_VCE:
-               *type = GFX_FW_TYPE_VCE;
-               break;
-       case AMDGPU_UCODE_ID_VCN:
-               *type = GFX_FW_TYPE_VCN;
-               break;
-       case AMDGPU_UCODE_ID_DMCU_ERAM:
-               *type = GFX_FW_TYPE_DMCU_ERAM;
-               break;
-       case AMDGPU_UCODE_ID_DMCU_INTV:
-               *type = GFX_FW_TYPE_DMCU_ISR;
-               break;
-       case AMDGPU_UCODE_ID_MAXIMUM:
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 static int psp_v10_0_init_microcode(struct psp_context *psp)
 {
        struct amdgpu_device *adev = psp->adev;
@@ -158,26 +89,6 @@ out:
        return err;
 }
 
-static int psp_v10_0_prep_cmd_buf(struct amdgpu_firmware_info *ucode,
-                                 struct psp_gfx_cmd_resp *cmd)
-{
-       int ret;
-       uint64_t fw_mem_mc_addr = ucode->mc_addr;
-
-       memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
-
-       cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW;
-       cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr);
-       cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr);
-       cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size;
-
-       ret = psp_v10_0_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type);
-       if (ret)
-               DRM_ERROR("Unknown firmware type\n");
-
-       return ret;
-}
-
 static int psp_v10_0_ring_init(struct psp_context *psp,
                               enum psp_ring_type ring_type)
 {
@@ -454,7 +365,6 @@ static int psp_v10_0_mode1_reset(struct psp_context *psp)
 
 static const struct psp_funcs psp_v10_0_funcs = {
        .init_microcode = psp_v10_0_init_microcode,
-       .prep_cmd_buf = psp_v10_0_prep_cmd_buf,
        .ring_init = psp_v10_0_ring_init,
        .ring_create = psp_v10_0_ring_create,
        .ring_stop = psp_v10_0_ring_stop,
index 0c6e7f9b143fa692f50996aeb93de86ed19d6d13..f71384be1f97486eea3aa6996a9cfa814748e440 100644 (file)
@@ -40,60 +40,6 @@ MODULE_FIRMWARE("amdgpu/vega20_ta.bin");
 /* address block */
 #define smnMP1_FIRMWARE_FLAGS          0x3010024
 
-static int
-psp_v11_0_get_fw_type(struct amdgpu_firmware_info *ucode, enum psp_gfx_fw_type *type)
-{
-       switch (ucode->ucode_id) {
-       case AMDGPU_UCODE_ID_SDMA0:
-               *type = GFX_FW_TYPE_SDMA0;
-               break;
-       case AMDGPU_UCODE_ID_SDMA1:
-               *type = GFX_FW_TYPE_SDMA1;
-               break;
-       case AMDGPU_UCODE_ID_CP_CE:
-               *type = GFX_FW_TYPE_CP_CE;
-               break;
-       case AMDGPU_UCODE_ID_CP_PFP:
-               *type = GFX_FW_TYPE_CP_PFP;
-               break;
-       case AMDGPU_UCODE_ID_CP_ME:
-               *type = GFX_FW_TYPE_CP_ME;
-               break;
-       case AMDGPU_UCODE_ID_CP_MEC1:
-               *type = GFX_FW_TYPE_CP_MEC;
-               break;
-       case AMDGPU_UCODE_ID_CP_MEC1_JT:
-               *type = GFX_FW_TYPE_CP_MEC_ME1;
-               break;
-       case AMDGPU_UCODE_ID_CP_MEC2:
-               *type = GFX_FW_TYPE_CP_MEC;
-               break;
-       case AMDGPU_UCODE_ID_CP_MEC2_JT:
-               *type = GFX_FW_TYPE_CP_MEC_ME2;
-               break;
-       case AMDGPU_UCODE_ID_RLC_G:
-               *type = GFX_FW_TYPE_RLC_G;
-               break;
-       case AMDGPU_UCODE_ID_SMC:
-               *type = GFX_FW_TYPE_SMU;
-               break;
-       case AMDGPU_UCODE_ID_UVD:
-               *type = GFX_FW_TYPE_UVD;
-               break;
-       case AMDGPU_UCODE_ID_VCE:
-               *type = GFX_FW_TYPE_VCE;
-               break;
-       case AMDGPU_UCODE_ID_UVD1:
-               *type = GFX_FW_TYPE_UVD1;
-               break;
-       case AMDGPU_UCODE_ID_MAXIMUM:
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 static int psp_v11_0_init_microcode(struct psp_context *psp)
 {
        struct amdgpu_device *adev = psp->adev;
@@ -267,26 +213,6 @@ static int psp_v11_0_bootloader_load_sos(struct psp_context *psp)
        return ret;
 }
 
-static int psp_v11_0_prep_cmd_buf(struct amdgpu_firmware_info *ucode,
-                                struct psp_gfx_cmd_resp *cmd)
-{
-       int ret;
-       uint64_t fw_mem_mc_addr = ucode->mc_addr;
-
-       memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
-
-       cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW;
-       cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr);
-       cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr);
-       cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size;
-
-       ret = psp_v11_0_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type);
-       if (ret)
-               DRM_ERROR("Unknown firmware type\n");
-
-       return ret;
-}
-
 static int psp_v11_0_ring_init(struct psp_context *psp,
                              enum psp_ring_type ring_type)
 {
@@ -753,7 +679,6 @@ static const struct psp_funcs psp_v11_0_funcs = {
        .init_microcode = psp_v11_0_init_microcode,
        .bootloader_load_sysdrv = psp_v11_0_bootloader_load_sysdrv,
        .bootloader_load_sos = psp_v11_0_bootloader_load_sos,
-       .prep_cmd_buf = psp_v11_0_prep_cmd_buf,
        .ring_init = psp_v11_0_ring_init,
        .ring_create = psp_v11_0_ring_create,
        .ring_stop = psp_v11_0_ring_stop,
index 79694ff1696966ff4ac17d7c1d03e49ff42ecec6..c63de945c0214d6321da38c7a70a60f52561c5b1 100644 (file)
@@ -47,57 +47,6 @@ MODULE_FIRMWARE("amdgpu/vega12_asd.bin");
 
 static uint32_t sos_old_versions[] = {1517616, 1510592, 1448594, 1446554};
 
-static int
-psp_v3_1_get_fw_type(struct amdgpu_firmware_info *ucode, enum psp_gfx_fw_type *type)
-{
-       switch(ucode->ucode_id) {
-       case AMDGPU_UCODE_ID_SDMA0:
-               *type = GFX_FW_TYPE_SDMA0;
-               break;
-       case AMDGPU_UCODE_ID_SDMA1:
-               *type = GFX_FW_TYPE_SDMA1;
-               break;
-       case AMDGPU_UCODE_ID_CP_CE:
-               *type = GFX_FW_TYPE_CP_CE;
-               break;
-       case AMDGPU_UCODE_ID_CP_PFP:
-               *type = GFX_FW_TYPE_CP_PFP;
-               break;
-       case AMDGPU_UCODE_ID_CP_ME:
-               *type = GFX_FW_TYPE_CP_ME;
-               break;
-       case AMDGPU_UCODE_ID_CP_MEC1:
-               *type = GFX_FW_TYPE_CP_MEC;
-               break;
-       case AMDGPU_UCODE_ID_CP_MEC1_JT:
-               *type = GFX_FW_TYPE_CP_MEC_ME1;
-               break;
-       case AMDGPU_UCODE_ID_CP_MEC2:
-               *type = GFX_FW_TYPE_CP_MEC;
-               break;
-       case AMDGPU_UCODE_ID_CP_MEC2_JT:
-               *type = GFX_FW_TYPE_CP_MEC_ME2;
-               break;
-       case AMDGPU_UCODE_ID_RLC_G:
-               *type = GFX_FW_TYPE_RLC_G;
-               break;
-       case AMDGPU_UCODE_ID_SMC:
-               *type = GFX_FW_TYPE_SMU;
-               break;
-       case AMDGPU_UCODE_ID_UVD:
-               *type = GFX_FW_TYPE_UVD;
-               break;
-       case AMDGPU_UCODE_ID_VCE:
-               *type = GFX_FW_TYPE_VCE;
-               break;
-       case AMDGPU_UCODE_ID_MAXIMUM:
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 static int psp_v3_1_init_microcode(struct psp_context *psp)
 {
        struct amdgpu_device *adev = psp->adev;
@@ -277,26 +226,6 @@ static int psp_v3_1_bootloader_load_sos(struct psp_context *psp)
        return ret;
 }
 
-static int psp_v3_1_prep_cmd_buf(struct amdgpu_firmware_info *ucode,
-                                struct psp_gfx_cmd_resp *cmd)
-{
-       int ret;
-       uint64_t fw_mem_mc_addr = ucode->mc_addr;
-
-       memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
-
-       cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW;
-       cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr);
-       cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr);
-       cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size;
-
-       ret = psp_v3_1_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type);
-       if (ret)
-               DRM_ERROR("Unknown firmware type\n");
-
-       return ret;
-}
-
 static int psp_v3_1_ring_init(struct psp_context *psp,
                              enum psp_ring_type ring_type)
 {
@@ -615,7 +544,6 @@ static const struct psp_funcs psp_v3_1_funcs = {
        .init_microcode = psp_v3_1_init_microcode,
        .bootloader_load_sysdrv = psp_v3_1_bootloader_load_sysdrv,
        .bootloader_load_sos = psp_v3_1_bootloader_load_sos,
-       .prep_cmd_buf = psp_v3_1_prep_cmd_buf,
        .ring_init = psp_v3_1_ring_init,
        .ring_create = psp_v3_1_ring_create,
        .ring_stop = psp_v3_1_ring_stop,
index 9f3cb2aec7c2842beb64864188de3e9fe47ebc7a..cca3552b36eda31c23ff064d04c37ae4f8f13fa2 100644 (file)
@@ -247,7 +247,7 @@ static void sdma_v2_4_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
 static void sdma_v2_4_ring_emit_ib(struct amdgpu_ring *ring,
                                   struct amdgpu_job *job,
                                   struct amdgpu_ib *ib,
-                                  bool ctx_switch)
+                                  uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
 
index 1bccc5fe2d9d97865677a25e7c967ec0b3cbe46b..0ce8331baeb2438b372d78290008611fa379271c 100644 (file)
@@ -421,7 +421,7 @@ static void sdma_v3_0_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
 static void sdma_v3_0_ring_emit_ib(struct amdgpu_ring *ring,
                                   struct amdgpu_job *job,
                                   struct amdgpu_ib *ib,
-                                  bool ctx_switch)
+                                  uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
 
@@ -1145,8 +1145,7 @@ static int sdma_v3_0_sw_init(void *handle)
                ring->ring_obj = NULL;
                if (!amdgpu_sriov_vf(adev)) {
                        ring->use_doorbell = true;
-                       ring->doorbell_index = (i == 0) ?
-                               adev->doorbell_index.sdma_engine0 : adev->doorbell_index.sdma_engine1;
+                       ring->doorbell_index = adev->doorbell_index.sdma_engine[i];
                } else {
                        ring->use_pollmem = true;
                }
index fd0bfe140ee01e6e26c12db9fc54ec48184d08dd..127b85983e8fbdaa3fd888c0fb75387db0cfdf43 100644 (file)
@@ -78,7 +78,6 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = {
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0),
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000),
-       SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CLK_CTRL, 0xffffffff, 0x3f000100),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_IB_CNTL, 0x800f0100, 0x00000100),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
@@ -96,6 +95,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = {
 static const struct soc15_reg_golden golden_settings_sdma_vg10[] = {
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002),
+       SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002)
 };
@@ -103,6 +103,7 @@ static const struct soc15_reg_golden golden_settings_sdma_vg10[] = {
 static const struct soc15_reg_golden golden_settings_sdma_vg12[] = {
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104001),
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001),
+       SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104001),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001)
 };
@@ -499,7 +500,7 @@ static void sdma_v4_0_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
 static void sdma_v4_0_ring_emit_ib(struct amdgpu_ring *ring,
                                   struct amdgpu_job *job,
                                   struct amdgpu_ib *ib,
-                                  bool ctx_switch)
+                                  uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
 
@@ -833,8 +834,6 @@ static void sdma_v4_0_gfx_resume(struct amdgpu_device *adev, unsigned int i)
                                        OFFSET, ring->doorbell_index);
        WREG32_SDMA(i, mmSDMA0_GFX_DOORBELL, doorbell);
        WREG32_SDMA(i, mmSDMA0_GFX_DOORBELL_OFFSET, doorbell_offset);
-       adev->nbio_funcs->sdma_doorbell_range(adev, i, ring->use_doorbell,
-                                             ring->doorbell_index);
 
        sdma_v4_0_ring_set_wptr(ring);
 
@@ -1521,9 +1520,7 @@ static int sdma_v4_0_sw_init(void *handle)
                                ring->use_doorbell?"true":"false");
 
                /* doorbell size is 2 dwords, get DWORD offset */
-               ring->doorbell_index = (i == 0) ?
-                       (adev->doorbell_index.sdma_engine0 << 1)
-                       : (adev->doorbell_index.sdma_engine1 << 1);
+               ring->doorbell_index = adev->doorbell_index.sdma_engine[i] << 1;
 
                sprintf(ring->name, "sdma%d", i);
                r = amdgpu_ring_init(adev, ring, 1024,
@@ -1542,9 +1539,7 @@ static int sdma_v4_0_sw_init(void *handle)
                        /* paging queue use same doorbell index/routing as gfx queue
                         * with 0x400 (4096 dwords) offset on second doorbell page
                         */
-                       ring->doorbell_index = (i == 0) ?
-                               (adev->doorbell_index.sdma_engine0 << 1)
-                               : (adev->doorbell_index.sdma_engine1 << 1);
+                       ring->doorbell_index = adev->doorbell_index.sdma_engine[i] << 1;
                        ring->doorbell_index += 0x400;
 
                        sprintf(ring->name, "page%d", i);
index f8408f88cd3740c898ccb609bf19682778222182..79c1a9bbcc215e450e4c1c439f0258a82608ca74 100644 (file)
@@ -47,6 +47,7 @@
 #include "dce/dce_6_0_d.h"
 #include "uvd/uvd_4_0_d.h"
 #include "bif/bif_3_0_d.h"
+#include "bif/bif_3_0_sh_mask.h"
 
 static const u32 tahiti_golden_registers[] =
 {
@@ -1258,6 +1259,11 @@ static bool si_need_full_reset(struct amdgpu_device *adev)
        return true;
 }
 
+static bool si_need_reset_on_init(struct amdgpu_device *adev)
+{
+       return false;
+}
+
 static int si_get_pcie_lanes(struct amdgpu_device *adev)
 {
        u32 link_width_cntl;
@@ -1323,6 +1329,52 @@ static void si_set_pcie_lanes(struct amdgpu_device *adev, int lanes)
        WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
 }
 
+static void si_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0,
+                             uint64_t *count1)
+{
+       uint32_t perfctr = 0;
+       uint64_t cnt0_of, cnt1_of;
+       int tmp;
+
+       /* This reports 0 on APUs, so return to avoid writing/reading registers
+        * that may or may not be different from their GPU counterparts
+        */
+        if (adev->flags & AMD_IS_APU)
+                return;
+
+       /* Set the 2 events that we wish to watch, defined above */
+       /* Reg 40 is # received msgs, Reg 104 is # of posted requests sent */
+       perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT0_SEL, 40);
+       perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT1_SEL, 104);
+
+       /* Write to enable desired perf counters */
+       WREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK, perfctr);
+       /* Zero out and enable the perf counters
+        * Write 0x5:
+        * Bit 0 = Start all counters(1)
+        * Bit 2 = Global counter reset enable(1)
+        */
+       WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000005);
+
+       msleep(1000);
+
+       /* Load the shadow and disable the perf counters
+        * Write 0x2:
+        * Bit 0 = Stop counters(0)
+        * Bit 1 = Load the shadow counters(1)
+        */
+       WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000002);
+
+       /* Read register values to get any >32bit overflow */
+       tmp = RREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK);
+       cnt0_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER0_UPPER);
+       cnt1_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER1_UPPER);
+
+       /* Get the values and add the overflow */
+       *count0 = RREG32_PCIE(ixPCIE_PERF_COUNT0_TXCLK) | (cnt0_of << 32);
+       *count1 = RREG32_PCIE(ixPCIE_PERF_COUNT1_TXCLK) | (cnt1_of << 32);
+}
+
 static const struct amdgpu_asic_funcs si_asic_funcs =
 {
        .read_disabled_bios = &si_read_disabled_bios,
@@ -1339,6 +1391,8 @@ static const struct amdgpu_asic_funcs si_asic_funcs =
        .flush_hdp = &si_flush_hdp,
        .invalidate_hdp = &si_invalidate_hdp,
        .need_full_reset = &si_need_full_reset,
+       .get_pcie_usage = &si_get_pcie_usage,
+       .need_reset_on_init = &si_need_reset_on_init,
 };
 
 static uint32_t si_get_rev_id(struct amdgpu_device *adev)
index b6e473134e19fae3bb107fa9160676616ecd44fc..f15f196684ba32fe66a31b9113eb8ebc2ee02d3b 100644 (file)
@@ -63,7 +63,7 @@ static void si_dma_ring_set_wptr(struct amdgpu_ring *ring)
 static void si_dma_ring_emit_ib(struct amdgpu_ring *ring,
                                struct amdgpu_job *job,
                                struct amdgpu_ib *ib,
-                               bool ctx_switch)
+                               uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
        /* The indirect buffer packet must end on an 8 DW boundary in the DMA ring.
index 2938fb9f17cc75c071ee0468434366fa68b39a4c..8c50c9cab455f9bdeb15d12898c8579c15bf3350 100644 (file)
@@ -57,9 +57,9 @@ static void si_ih_disable_interrupts(struct amdgpu_device *adev)
 
 static int si_ih_irq_init(struct amdgpu_device *adev)
 {
+       struct amdgpu_ih_ring *ih = &adev->irq.ih;
        int rb_bufsz;
        u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
-       u64 wptr_off;
 
        si_ih_disable_interrupts(adev);
        WREG32(INTERRUPT_CNTL2, adev->irq.ih.gpu_addr >> 8);
@@ -76,9 +76,8 @@ static int si_ih_irq_init(struct amdgpu_device *adev)
                     (rb_bufsz << 1) |
                     IH_WPTR_WRITEBACK_ENABLE;
 
-       wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4);
-       WREG32(IH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off));
-       WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF);
+       WREG32(IH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr));
+       WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF);
        WREG32(IH_RB_CNTL, ih_rb_cntl);
        WREG32(IH_RB_RPTR, 0);
        WREG32(IH_RB_WPTR, 0);
@@ -100,34 +99,36 @@ static void si_ih_irq_disable(struct amdgpu_device *adev)
        mdelay(1);
 }
 
-static u32 si_ih_get_wptr(struct amdgpu_device *adev)
+static u32 si_ih_get_wptr(struct amdgpu_device *adev,
+                         struct amdgpu_ih_ring *ih)
 {
        u32 wptr, tmp;
 
-       wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]);
+       wptr = le32_to_cpu(*ih->wptr_cpu);
 
        if (wptr & IH_RB_WPTR__RB_OVERFLOW_MASK) {
                wptr &= ~IH_RB_WPTR__RB_OVERFLOW_MASK;
                dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
-                       wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask);
-               adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask;
+                       wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
+               ih->rptr = (wptr + 16) & ih->ptr_mask;
                tmp = RREG32(IH_RB_CNTL);
                tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK;
                WREG32(IH_RB_CNTL, tmp);
        }
-       return (wptr & adev->irq.ih.ptr_mask);
+       return (wptr & ih->ptr_mask);
 }
 
 static void si_ih_decode_iv(struct amdgpu_device *adev,
-                            struct amdgpu_iv_entry *entry)
+                           struct amdgpu_ih_ring *ih,
+                           struct amdgpu_iv_entry *entry)
 {
-       u32 ring_index = adev->irq.ih.rptr >> 2;
+       u32 ring_index = ih->rptr >> 2;
        uint32_t dw[4];
 
-       dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
-       dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]);
-       dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]);
-       dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]);
+       dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
+       dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
+       dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
+       dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
 
        entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
        entry->src_id = dw[0] & 0xff;
@@ -135,12 +136,13 @@ static void si_ih_decode_iv(struct amdgpu_device *adev,
        entry->ring_id = dw[2] & 0xff;
        entry->vmid = (dw[2] >> 8) & 0xff;
 
-       adev->irq.ih.rptr += 16;
+       ih->rptr += 16;
 }
 
-static void si_ih_set_rptr(struct amdgpu_device *adev)
+static void si_ih_set_rptr(struct amdgpu_device *adev,
+                          struct amdgpu_ih_ring *ih)
 {
-       WREG32(IH_RB_RPTR, adev->irq.ih.rptr);
+       WREG32(IH_RB_RPTR, ih->rptr);
 }
 
 static int si_ih_early_init(void *handle)
index 8849b74078d6e5373d82fba3f82980cf1bc4c8a7..62d272b4be198392eeed4b593fe356d321651c01 100644 (file)
 #include "hdp/hdp_4_0_sh_mask.h"
 #include "smuio/smuio_9_0_offset.h"
 #include "smuio/smuio_9_0_sh_mask.h"
+#include "nbio/nbio_7_0_default.h"
+#include "nbio/nbio_7_0_sh_mask.h"
+#include "nbio/nbio_7_0_smn.h"
+#include "mp/mp_9_0_offset.h"
 
 #include "soc15.h"
 #include "soc15_common.h"
@@ -385,14 +389,13 @@ void soc15_program_register_sequence(struct amdgpu_device *adev,
 
 }
 
-
-static int soc15_asic_reset(struct amdgpu_device *adev)
+static int soc15_asic_mode1_reset(struct amdgpu_device *adev)
 {
        u32 i;
 
        amdgpu_atombios_scratch_regs_engine_hung(adev, true);
 
-       dev_info(adev->dev, "GPU reset\n");
+       dev_info(adev->dev, "GPU mode1 reset\n");
 
        /* disable BM */
        pci_clear_master(adev->pdev);
@@ -417,6 +420,63 @@ static int soc15_asic_reset(struct amdgpu_device *adev)
        return 0;
 }
 
+static int soc15_asic_get_baco_capability(struct amdgpu_device *adev, bool *cap)
+{
+       void *pp_handle = adev->powerplay.pp_handle;
+       const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+
+       if (!pp_funcs || !pp_funcs->get_asic_baco_capability) {
+               *cap = false;
+               return -ENOENT;
+       }
+
+       return pp_funcs->get_asic_baco_capability(pp_handle, cap);
+}
+
+static int soc15_asic_baco_reset(struct amdgpu_device *adev)
+{
+       void *pp_handle = adev->powerplay.pp_handle;
+       const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+
+       if (!pp_funcs ||!pp_funcs->get_asic_baco_state ||!pp_funcs->set_asic_baco_state)
+               return -ENOENT;
+
+       /* enter BACO state */
+       if (pp_funcs->set_asic_baco_state(pp_handle, 1))
+               return -EIO;
+
+       /* exit BACO state */
+       if (pp_funcs->set_asic_baco_state(pp_handle, 0))
+               return -EIO;
+
+       dev_info(adev->dev, "GPU BACO reset\n");
+
+       return 0;
+}
+
+static int soc15_asic_reset(struct amdgpu_device *adev)
+{
+       int ret;
+       bool baco_reset;
+
+       switch (adev->asic_type) {
+       case CHIP_VEGA10:
+       case CHIP_VEGA20:
+               soc15_asic_get_baco_capability(adev, &baco_reset);
+               break;
+       default:
+               baco_reset = false;
+               break;
+       }
+
+       if (baco_reset)
+               ret = soc15_asic_baco_reset(adev);
+       else
+               ret = soc15_asic_mode1_reset(adev);
+
+       return ret;
+}
+
 /*static int soc15_set_uvd_clock(struct amdgpu_device *adev, u32 clock,
                        u32 cntl_reg, u32 status_reg)
 {
@@ -535,10 +595,12 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
                amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
                amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block);
                amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
-               if (adev->asic_type == CHIP_VEGA20)
-                       amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
-               else
-                       amdgpu_device_ip_block_add(adev, &psp_v3_1_ip_block);
+               if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)) {
+                       if (adev->asic_type == CHIP_VEGA20)
+                               amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
+                       else
+                               amdgpu_device_ip_block_add(adev, &psp_v3_1_ip_block);
+               }
                amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
                amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
                if (!amdgpu_sriov_vf(adev))
@@ -560,7 +622,8 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
                amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
                amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block);
                amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
-               amdgpu_device_ip_block_add(adev, &psp_v10_0_ip_block);
+               if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
+                       amdgpu_device_ip_block_add(adev, &psp_v10_0_ip_block);
                amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
                amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
                amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
@@ -601,6 +664,68 @@ static bool soc15_need_full_reset(struct amdgpu_device *adev)
        /* change this when we implement soft reset */
        return true;
 }
+static void soc15_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0,
+                                uint64_t *count1)
+{
+       uint32_t perfctr = 0;
+       uint64_t cnt0_of, cnt1_of;
+       int tmp;
+
+       /* This reports 0 on APUs, so return to avoid writing/reading registers
+        * that may or may not be different from their GPU counterparts
+        */
+        if (adev->flags & AMD_IS_APU)
+                return;
+
+       /* Set the 2 events that we wish to watch, defined above */
+       /* Reg 40 is # received msgs, Reg 104 is # of posted requests sent */
+       perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT0_SEL, 40);
+       perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT1_SEL, 104);
+
+       /* Write to enable desired perf counters */
+       WREG32_PCIE(smnPCIE_PERF_CNTL_TXCLK, perfctr);
+       /* Zero out and enable the perf counters
+        * Write 0x5:
+        * Bit 0 = Start all counters(1)
+        * Bit 2 = Global counter reset enable(1)
+        */
+       WREG32_PCIE(smnPCIE_PERF_COUNT_CNTL, 0x00000005);
+
+       msleep(1000);
+
+       /* Load the shadow and disable the perf counters
+        * Write 0x2:
+        * Bit 0 = Stop counters(0)
+        * Bit 1 = Load the shadow counters(1)
+        */
+       WREG32_PCIE(smnPCIE_PERF_COUNT_CNTL, 0x00000002);
+
+       /* Read register values to get any >32bit overflow */
+       tmp = RREG32_PCIE(smnPCIE_PERF_CNTL_TXCLK);
+       cnt0_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER0_UPPER);
+       cnt1_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER1_UPPER);
+
+       /* Get the values and add the overflow */
+       *count0 = RREG32_PCIE(smnPCIE_PERF_COUNT0_TXCLK) | (cnt0_of << 32);
+       *count1 = RREG32_PCIE(smnPCIE_PERF_COUNT1_TXCLK) | (cnt1_of << 32);
+}
+
+static bool soc15_need_reset_on_init(struct amdgpu_device *adev)
+{
+       u32 sol_reg;
+
+       if (adev->flags & AMD_IS_APU)
+               return false;
+
+       /* Check sOS sign of life register to confirm sys driver and sOS
+        * are already been loaded.
+        */
+       sol_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81);
+       if (sol_reg)
+               return true;
+
+       return false;
+}
 
 static const struct amdgpu_asic_funcs soc15_asic_funcs =
 {
@@ -617,6 +742,8 @@ static const struct amdgpu_asic_funcs soc15_asic_funcs =
        .invalidate_hdp = &soc15_invalidate_hdp,
        .need_full_reset = &soc15_need_full_reset,
        .init_doorbell_index = &vega10_doorbell_index_init,
+       .get_pcie_usage = &soc15_get_pcie_usage,
+       .need_reset_on_init = &soc15_need_reset_on_init,
 };
 
 static const struct amdgpu_asic_funcs vega20_asic_funcs =
@@ -634,6 +761,8 @@ static const struct amdgpu_asic_funcs vega20_asic_funcs =
        .invalidate_hdp = &soc15_invalidate_hdp,
        .need_full_reset = &soc15_need_full_reset,
        .init_doorbell_index = &vega20_doorbell_index_init,
+       .get_pcie_usage = &soc15_get_pcie_usage,
+       .need_reset_on_init = &soc15_need_reset_on_init,
 };
 
 static int soc15_common_early_init(void *handle)
@@ -840,6 +969,22 @@ static int soc15_common_sw_fini(void *handle)
        return 0;
 }
 
+static void soc15_doorbell_range_init(struct amdgpu_device *adev)
+{
+       int i;
+       struct amdgpu_ring *ring;
+
+       for (i = 0; i < adev->sdma.num_instances; i++) {
+               ring = &adev->sdma.instance[i].ring;
+               adev->nbio_funcs->sdma_doorbell_range(adev, i,
+                       ring->use_doorbell, ring->doorbell_index,
+                       adev->doorbell_index.sdma_doorbell_range);
+       }
+
+       adev->nbio_funcs->ih_doorbell_range(adev, adev->irq.ih.use_doorbell,
+                                               adev->irq.ih.doorbell_index);
+}
+
 static int soc15_common_hw_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -852,6 +997,12 @@ static int soc15_common_hw_init(void *handle)
        adev->nbio_funcs->init_registers(adev);
        /* enable the doorbell aperture */
        soc15_enable_doorbell_aperture(adev, true);
+       /* HW doorbell routing policy: doorbell writing not
+        * in SDMA/IH/MM/ACV range will be routed to CP. So
+        * we need to init SDMA/IH/MM/ACV doorbell range prior
+        * to CP ip block init and ring test.
+        */
+       soc15_doorbell_range_init(adev);
 
        return 0;
 }
index 15da06ddeb751d9f20e1a461d5a0e4276186a3dc..a20b711a67568d1a78290095301c82f7bc041190 100644 (file)
@@ -99,9 +99,9 @@ static void tonga_ih_disable_interrupts(struct amdgpu_device *adev)
  */
 static int tonga_ih_irq_init(struct amdgpu_device *adev)
 {
-       int rb_bufsz;
        u32 interrupt_cntl, ih_rb_cntl, ih_doorbell_rtpr;
-       u64 wptr_off;
+       struct amdgpu_ih_ring *ih = &adev->irq.ih;
+       int rb_bufsz;
 
        /* disable irqs */
        tonga_ih_disable_interrupts(adev);
@@ -118,10 +118,7 @@ static int tonga_ih_irq_init(struct amdgpu_device *adev)
        WREG32(mmINTERRUPT_CNTL, interrupt_cntl);
 
        /* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/
-       if (adev->irq.ih.use_bus_addr)
-               WREG32(mmIH_RB_BASE, adev->irq.ih.rb_dma_addr >> 8);
-       else
-               WREG32(mmIH_RB_BASE, adev->irq.ih.gpu_addr >> 8);
+       WREG32(mmIH_RB_BASE, ih->gpu_addr >> 8);
 
        rb_bufsz = order_base_2(adev->irq.ih.ring_size / 4);
        ih_rb_cntl = REG_SET_FIELD(0, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
@@ -136,12 +133,8 @@ static int tonga_ih_irq_init(struct amdgpu_device *adev)
        WREG32(mmIH_RB_CNTL, ih_rb_cntl);
 
        /* set the writeback address whether it's enabled or not */
-       if (adev->irq.ih.use_bus_addr)
-               wptr_off = adev->irq.ih.rb_dma_addr + (adev->irq.ih.wptr_offs * 4);
-       else
-               wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4);
-       WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off));
-       WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF);
+       WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr));
+       WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF);
 
        /* set rptr, wptr to 0 */
        WREG32(mmIH_RB_RPTR, 0);
@@ -193,14 +186,12 @@ static void tonga_ih_irq_disable(struct amdgpu_device *adev)
  * Used by cz_irq_process(VI).
  * Returns the value of the wptr.
  */
-static u32 tonga_ih_get_wptr(struct amdgpu_device *adev)
+static u32 tonga_ih_get_wptr(struct amdgpu_device *adev,
+                            struct amdgpu_ih_ring *ih)
 {
        u32 wptr, tmp;
 
-       if (adev->irq.ih.use_bus_addr)
-               wptr = le32_to_cpu(adev->irq.ih.ring[adev->irq.ih.wptr_offs]);
-       else
-               wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]);
+       wptr = le32_to_cpu(*ih->wptr_cpu);
 
        if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
                wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
@@ -209,13 +200,13 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev)
                 * this should allow us to catchup.
                 */
                dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
-                       wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask);
-               adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask;
+                        wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
+               ih->rptr = (wptr + 16) & ih->ptr_mask;
                tmp = RREG32(mmIH_RB_CNTL);
                tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
                WREG32(mmIH_RB_CNTL, tmp);
        }
-       return (wptr & adev->irq.ih.ptr_mask);
+       return (wptr & ih->ptr_mask);
 }
 
 /**
@@ -227,16 +218,17 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev)
  * position and also advance the position.
  */
 static void tonga_ih_decode_iv(struct amdgpu_device *adev,
-                                struct amdgpu_iv_entry *entry)
+                              struct amdgpu_ih_ring *ih,
+                              struct amdgpu_iv_entry *entry)
 {
        /* wptr/rptr are in bytes! */
-       u32 ring_index = adev->irq.ih.rptr >> 2;
+       u32 ring_index = ih->rptr >> 2;
        uint32_t dw[4];
 
-       dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
-       dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]);
-       dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]);
-       dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]);
+       dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
+       dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
+       dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
+       dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
 
        entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
        entry->src_id = dw[0] & 0xff;
@@ -246,7 +238,7 @@ static void tonga_ih_decode_iv(struct amdgpu_device *adev,
        entry->pasid = (dw[2] >> 16) & 0xffff;
 
        /* wptr/rptr are in bytes! */
-       adev->irq.ih.rptr += 16;
+       ih->rptr += 16;
 }
 
 /**
@@ -256,17 +248,15 @@ static void tonga_ih_decode_iv(struct amdgpu_device *adev,
  *
  * Set the IH ring buffer rptr.
  */
-static void tonga_ih_set_rptr(struct amdgpu_device *adev)
+static void tonga_ih_set_rptr(struct amdgpu_device *adev,
+                             struct amdgpu_ih_ring *ih)
 {
-       if (adev->irq.ih.use_doorbell) {
+       if (ih->use_doorbell) {
                /* XXX check if swapping is necessary on BE */
-               if (adev->irq.ih.use_bus_addr)
-                       adev->irq.ih.ring[adev->irq.ih.rptr_offs] = adev->irq.ih.rptr;
-               else
-                       adev->wb.wb[adev->irq.ih.rptr_offs] = adev->irq.ih.rptr;
-               WDOORBELL32(adev->irq.ih.doorbell_index, adev->irq.ih.rptr);
+               *ih->rptr_cpu = ih->rptr;
+               WDOORBELL32(ih->doorbell_index, ih->rptr);
        } else {
-               WREG32(mmIH_RB_RPTR, adev->irq.ih.rptr);
+               WREG32(mmIH_RB_RPTR, ih->rptr);
        }
 }
 
index d69c8f6daaf80a0b062287cc7c4cf4ec3de2a356..c4fb58667fd451c8157398022735a1c35a568a3d 100644 (file)
@@ -511,7 +511,7 @@ static int uvd_v4_2_ring_test_ring(struct amdgpu_ring *ring)
 static void uvd_v4_2_ring_emit_ib(struct amdgpu_ring *ring,
                                  struct amdgpu_job *job,
                                  struct amdgpu_ib *ib,
-                                 bool ctx_switch)
+                                 uint32_t flags)
 {
        amdgpu_ring_write(ring, PACKET0(mmUVD_RBC_IB_BASE, 0));
        amdgpu_ring_write(ring, ib->gpu_addr);
index ee8cd06ddc385f08deb8271b3751696ecd1200b3..52bd8a6547347e287e18c916ae6e07517f2039a3 100644 (file)
@@ -526,7 +526,7 @@ static int uvd_v5_0_ring_test_ring(struct amdgpu_ring *ring)
 static void uvd_v5_0_ring_emit_ib(struct amdgpu_ring *ring,
                                  struct amdgpu_job *job,
                                  struct amdgpu_ib *ib,
-                                 bool ctx_switch)
+                                 uint32_t flags)
 {
        amdgpu_ring_write(ring, PACKET0(mmUVD_LMI_RBC_IB_64BIT_BAR_LOW, 0));
        amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
index d4f4a66f8324131f1e8d925026ee9ad39471d25e..c9edddf9f88a8c67ce9742632120287504838b68 100644 (file)
@@ -977,7 +977,7 @@ static int uvd_v6_0_ring_test_ring(struct amdgpu_ring *ring)
 static void uvd_v6_0_ring_emit_ib(struct amdgpu_ring *ring,
                                  struct amdgpu_job *job,
                                  struct amdgpu_ib *ib,
-                                 bool ctx_switch)
+                                 uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
 
@@ -1003,7 +1003,7 @@ static void uvd_v6_0_ring_emit_ib(struct amdgpu_ring *ring,
 static void uvd_v6_0_enc_ring_emit_ib(struct amdgpu_ring *ring,
                                        struct amdgpu_job *job,
                                        struct amdgpu_ib *ib,
-                                       bool ctx_switch)
+                                       uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
 
index aef924026a28c620373763aeb5d0c1274c1c44d2..dc461df48da09c22020f48bd8c3bd387d276099f 100644 (file)
@@ -1272,7 +1272,7 @@ static int uvd_v7_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
 static void uvd_v7_0_ring_emit_ib(struct amdgpu_ring *ring,
                                  struct amdgpu_job *job,
                                  struct amdgpu_ib *ib,
-                                 bool ctx_switch)
+                                 uint32_t flags)
 {
        struct amdgpu_device *adev = ring->adev;
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
@@ -1303,7 +1303,7 @@ static void uvd_v7_0_ring_emit_ib(struct amdgpu_ring *ring,
 static void uvd_v7_0_enc_ring_emit_ib(struct amdgpu_ring *ring,
                                        struct amdgpu_job *job,
                                        struct amdgpu_ib *ib,
-                                       bool ctx_switch)
+                                       uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
 
index 2668effadd271a3cfc1d6cd35d631975716b5689..6ec65cf111124e1f5659d3d46d05a152ab64d5c6 100644 (file)
@@ -834,7 +834,7 @@ out:
 static void vce_v3_0_ring_emit_ib(struct amdgpu_ring *ring,
                                  struct amdgpu_job *job,
                                  struct amdgpu_ib *ib,
-                                 bool ctx_switch)
+                                 uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
 
index 9fb34b7d8e03e88f411dcf369a79d4853aaef897..aadc3e66ebd7c1164c359f8e13afb12deec4c46d 100644 (file)
@@ -947,7 +947,7 @@ static int vce_v4_0_set_powergating_state(void *handle,
 #endif
 
 static void vce_v4_0_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_job *job,
-                                       struct amdgpu_ib *ib, bool ctx_switch)
+                                       struct amdgpu_ib *ib, uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
 
index 89bb2fef90eb725d5793c32b3c3c90aa0f23edf7..3dbc51f9d3b92ecde0bb04b9983ffb0d30036310 100644 (file)
@@ -1371,7 +1371,7 @@ static void vcn_v1_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64
 static void vcn_v1_0_dec_ring_emit_ib(struct amdgpu_ring *ring,
                                        struct amdgpu_job *job,
                                        struct amdgpu_ib *ib,
-                                       bool ctx_switch)
+                                       uint32_t flags)
 {
        struct amdgpu_device *adev = ring->adev;
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
@@ -1531,7 +1531,7 @@ static void vcn_v1_0_enc_ring_insert_end(struct amdgpu_ring *ring)
 static void vcn_v1_0_enc_ring_emit_ib(struct amdgpu_ring *ring,
                                        struct amdgpu_job *job,
                                        struct amdgpu_ib *ib,
-                                       bool ctx_switch)
+                                       uint32_t flags)
 {
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
 
@@ -1736,7 +1736,7 @@ static void vcn_v1_0_jpeg_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u6
 static void vcn_v1_0_jpeg_ring_emit_ib(struct amdgpu_ring *ring,
                                        struct amdgpu_job *job,
                                        struct amdgpu_ib *ib,
-                                       bool ctx_switch)
+                                       uint32_t flags)
 {
        struct amdgpu_device *adev = ring->adev;
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
index 2c250b01a903eb62e6724384c4816a701f0eabe4..6d1f804277f84b224b4999e82e0a12913e70014b 100644 (file)
@@ -50,6 +50,22 @@ static void vega10_ih_enable_interrupts(struct amdgpu_device *adev)
        ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 1);
        WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
        adev->irq.ih.enabled = true;
+
+       if (adev->irq.ih1.ring_size) {
+               ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
+               ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
+                                          RB_ENABLE, 1);
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
+               adev->irq.ih1.enabled = true;
+       }
+
+       if (adev->irq.ih2.ring_size) {
+               ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
+               ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
+                                          RB_ENABLE, 1);
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
+               adev->irq.ih2.enabled = true;
+       }
 }
 
 /**
@@ -71,6 +87,53 @@ static void vega10_ih_disable_interrupts(struct amdgpu_device *adev)
        WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR, 0);
        adev->irq.ih.enabled = false;
        adev->irq.ih.rptr = 0;
+
+       if (adev->irq.ih1.ring_size) {
+               ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
+               ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
+                                          RB_ENABLE, 0);
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
+               /* set rptr, wptr to 0 */
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
+               adev->irq.ih1.enabled = false;
+               adev->irq.ih1.rptr = 0;
+       }
+
+       if (adev->irq.ih2.ring_size) {
+               ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
+               ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
+                                          RB_ENABLE, 0);
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
+               /* set rptr, wptr to 0 */
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
+               adev->irq.ih2.enabled = false;
+               adev->irq.ih2.rptr = 0;
+       }
+}
+
+static uint32_t vega10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
+{
+       int rb_bufsz = order_base_2(ih->ring_size / 4);
+
+       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
+                                  MC_SPACE, ih->use_bus_addr ? 1 : 4);
+       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
+                                  WPTR_OVERFLOW_CLEAR, 1);
+       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
+                                  WPTR_OVERFLOW_ENABLE, 1);
+       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
+       /* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register
+        * value is written to memory
+        */
+       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
+                                  WPTR_WRITEBACK_ENABLE, 1);
+       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
+       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
+       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
+
+       return ih_rb_cntl;
 }
 
 /**
@@ -86,50 +149,32 @@ static void vega10_ih_disable_interrupts(struct amdgpu_device *adev)
  */
 static int vega10_ih_irq_init(struct amdgpu_device *adev)
 {
+       struct amdgpu_ih_ring *ih;
        int ret = 0;
-       int rb_bufsz;
        u32 ih_rb_cntl, ih_doorbell_rtpr;
        u32 tmp;
-       u64 wptr_off;
 
        /* disable irqs */
        vega10_ih_disable_interrupts(adev);
 
        adev->nbio_funcs->ih_control(adev);
 
-       ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
+       ih = &adev->irq.ih;
        /* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/
-       if (adev->irq.ih.use_bus_addr) {
-               WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, adev->irq.ih.rb_dma_addr >> 8);
-               WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI, ((u64)adev->irq.ih.rb_dma_addr >> 40) & 0xff);
-               ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SPACE, 1);
-       } else {
-               WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, adev->irq.ih.gpu_addr >> 8);
-               WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI, (adev->irq.ih.gpu_addr >> 40) & 0xff);
-               ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SPACE, 4);
-       }
-       rb_bufsz = order_base_2(adev->irq.ih.ring_size / 4);
-       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
-       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_OVERFLOW_ENABLE, 1);
-       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
-       /* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register value is written to memory */
-       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_WRITEBACK_ENABLE, 1);
-       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
-       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
-       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
-
-       if (adev->irq.msi_enabled)
-               ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RPTR_REARM, 1);
+       WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, ih->gpu_addr >> 8);
+       WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI, (ih->gpu_addr >> 40) & 0xff);
 
+       ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
+       ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
+       ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RPTR_REARM,
+                                  !!adev->irq.msi_enabled);
        WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
 
        /* set the writeback address whether it's enabled or not */
-       if (adev->irq.ih.use_bus_addr)
-               wptr_off = adev->irq.ih.rb_dma_addr + (adev->irq.ih.wptr_offs * 4);
-       else
-               wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4);
-       WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off));
-       WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFFFF);
+       WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_LO,
+                    lower_32_bits(ih->wptr_addr));
+       WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_HI,
+                    upper_32_bits(ih->wptr_addr) & 0xFFFF);
 
        /* set rptr, wptr to 0 */
        WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, 0);
@@ -137,17 +182,48 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
 
        ih_doorbell_rtpr = RREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR);
        if (adev->irq.ih.use_doorbell) {
-               ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
-                                                OFFSET, adev->irq.ih.doorbell_index);
-               ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
+               ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
+                                                IH_DOORBELL_RPTR, OFFSET,
+                                                adev->irq.ih.doorbell_index);
+               ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
+                                                IH_DOORBELL_RPTR,
                                                 ENABLE, 1);
        } else {
-               ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
+               ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
+                                                IH_DOORBELL_RPTR,
                                                 ENABLE, 0);
        }
        WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR, ih_doorbell_rtpr);
-       adev->nbio_funcs->ih_doorbell_range(adev, adev->irq.ih.use_doorbell,
-                                           adev->irq.ih.doorbell_index);
+
+       ih = &adev->irq.ih1;
+       if (ih->ring_size) {
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING1, ih->gpu_addr >> 8);
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING1,
+                            (ih->gpu_addr >> 40) & 0xff);
+
+               ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
+               ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
+
+               /* set rptr, wptr to 0 */
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
+       }
+
+       ih = &adev->irq.ih2;
+       if (ih->ring_size) {
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING2, ih->gpu_addr >> 8);
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING2,
+                            (ih->gpu_addr >> 40) & 0xff);
+
+               ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
+               ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
+
+               /* set rptr, wptr to 0 */
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
+       }
 
        tmp = RREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL);
        tmp = REG_SET_FIELD(tmp, IH_STORM_CLIENT_LIST_CNTL,
@@ -191,32 +267,58 @@ static void vega10_ih_irq_disable(struct amdgpu_device *adev)
  * ring buffer overflow and deal with it.
  * Returns the value of the wptr.
  */
-static u32 vega10_ih_get_wptr(struct amdgpu_device *adev)
+static u32 vega10_ih_get_wptr(struct amdgpu_device *adev,
+                             struct amdgpu_ih_ring *ih)
 {
-       u32 wptr, tmp;
+       u32 wptr, reg, tmp;
 
-       if (adev->irq.ih.use_bus_addr)
-               wptr = le32_to_cpu(adev->irq.ih.ring[adev->irq.ih.wptr_offs]);
+       wptr = le32_to_cpu(*ih->wptr_cpu);
+
+       if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
+               goto out;
+
+       /* Double check that the overflow wasn't already cleared. */
+
+       if (ih == &adev->irq.ih)
+               reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR);
+       else if (ih == &adev->irq.ih1)
+               reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING1);
+       else if (ih == &adev->irq.ih2)
+               reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING2);
        else
-               wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]);
-
-       if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
-               wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
-
-               /* When a ring buffer overflow happen start parsing interrupt
-                * from the last not overwritten vector (wptr + 32). Hopefully
-                * this should allow us to catchup.
-                */
-               tmp = (wptr + 32) & adev->irq.ih.ptr_mask;
-               dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
-                       wptr, adev->irq.ih.rptr, tmp);
-               adev->irq.ih.rptr = tmp;
-
-               tmp = RREG32_NO_KIQ(SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL));
-               tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
-               WREG32_NO_KIQ(SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL), tmp);
-       }
-       return (wptr & adev->irq.ih.ptr_mask);
+               BUG();
+
+       wptr = RREG32_NO_KIQ(reg);
+       if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
+               goto out;
+
+       wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
+
+       /* When a ring buffer overflow happen start parsing interrupt
+        * from the last not overwritten vector (wptr + 32). Hopefully
+        * this should allow us to catchup.
+        */
+       tmp = (wptr + 32) & ih->ptr_mask;
+       dev_warn(adev->dev, "IH ring buffer overflow "
+                "(0x%08X, 0x%08X, 0x%08X)\n",
+                wptr, ih->rptr, tmp);
+       ih->rptr = tmp;
+
+       if (ih == &adev->irq.ih)
+               reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL);
+       else if (ih == &adev->irq.ih1)
+               reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING1);
+       else if (ih == &adev->irq.ih2)
+               reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING2);
+       else
+               BUG();
+
+       tmp = RREG32_NO_KIQ(reg);
+       tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
+       WREG32_NO_KIQ(reg, tmp);
+
+out:
+       return (wptr & ih->ptr_mask);
 }
 
 /**
@@ -228,20 +330,21 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev)
  * position and also advance the position.
  */
 static void vega10_ih_decode_iv(struct amdgpu_device *adev,
-                                struct amdgpu_iv_entry *entry)
+                               struct amdgpu_ih_ring *ih,
+                               struct amdgpu_iv_entry *entry)
 {
        /* wptr/rptr are in bytes! */
-       u32 ring_index = adev->irq.ih.rptr >> 2;
+       u32 ring_index = ih->rptr >> 2;
        uint32_t dw[8];
 
-       dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
-       dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]);
-       dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]);
-       dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]);
-       dw[4] = le32_to_cpu(adev->irq.ih.ring[ring_index + 4]);
-       dw[5] = le32_to_cpu(adev->irq.ih.ring[ring_index + 5]);
-       dw[6] = le32_to_cpu(adev->irq.ih.ring[ring_index + 6]);
-       dw[7] = le32_to_cpu(adev->irq.ih.ring[ring_index + 7]);
+       dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
+       dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
+       dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
+       dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
+       dw[4] = le32_to_cpu(ih->ring[ring_index + 4]);
+       dw[5] = le32_to_cpu(ih->ring[ring_index + 5]);
+       dw[6] = le32_to_cpu(ih->ring[ring_index + 6]);
+       dw[7] = le32_to_cpu(ih->ring[ring_index + 7]);
 
        entry->client_id = dw[0] & 0xff;
        entry->src_id = (dw[0] >> 8) & 0xff;
@@ -257,9 +360,8 @@ static void vega10_ih_decode_iv(struct amdgpu_device *adev,
        entry->src_data[2] = dw[6];
        entry->src_data[3] = dw[7];
 
-
        /* wptr/rptr are in bytes! */
-       adev->irq.ih.rptr += 32;
+       ih->rptr += 32;
 }
 
 /**
@@ -269,37 +371,95 @@ static void vega10_ih_decode_iv(struct amdgpu_device *adev,
  *
  * Set the IH ring buffer rptr.
  */
-static void vega10_ih_set_rptr(struct amdgpu_device *adev)
+static void vega10_ih_set_rptr(struct amdgpu_device *adev,
+                              struct amdgpu_ih_ring *ih)
 {
-       if (adev->irq.ih.use_doorbell) {
+       if (ih->use_doorbell) {
                /* XXX check if swapping is necessary on BE */
-               if (adev->irq.ih.use_bus_addr)
-                       adev->irq.ih.ring[adev->irq.ih.rptr_offs] = adev->irq.ih.rptr;
-               else
-                       adev->wb.wb[adev->irq.ih.rptr_offs] = adev->irq.ih.rptr;
-               WDOORBELL32(adev->irq.ih.doorbell_index, adev->irq.ih.rptr);
-       } else {
-               WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, adev->irq.ih.rptr);
+               *ih->rptr_cpu = ih->rptr;
+               WDOORBELL32(ih->doorbell_index, ih->rptr);
+       } else if (ih == &adev->irq.ih) {
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, ih->rptr);
+       } else if (ih == &adev->irq.ih1) {
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, ih->rptr);
+       } else if (ih == &adev->irq.ih2) {
+               WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, ih->rptr);
        }
 }
 
+/**
+ * vega10_ih_self_irq - dispatch work for ring 1 and 2
+ *
+ * @adev: amdgpu_device pointer
+ * @source: irq source
+ * @entry: IV with WPTR update
+ *
+ * Update the WPTR from the IV and schedule work to handle the entries.
+ */
+static int vega10_ih_self_irq(struct amdgpu_device *adev,
+                             struct amdgpu_irq_src *source,
+                             struct amdgpu_iv_entry *entry)
+{
+       uint32_t wptr = cpu_to_le32(entry->src_data[0]);
+
+       switch (entry->ring_id) {
+       case 1:
+               *adev->irq.ih1.wptr_cpu = wptr;
+               schedule_work(&adev->irq.ih1_work);
+               break;
+       case 2:
+               *adev->irq.ih2.wptr_cpu = wptr;
+               schedule_work(&adev->irq.ih2_work);
+               break;
+       default: break;
+       }
+       return 0;
+}
+
+static const struct amdgpu_irq_src_funcs vega10_ih_self_irq_funcs = {
+       .process = vega10_ih_self_irq,
+};
+
+static void vega10_ih_set_self_irq_funcs(struct amdgpu_device *adev)
+{
+       adev->irq.self_irq.num_types = 0;
+       adev->irq.self_irq.funcs = &vega10_ih_self_irq_funcs;
+}
+
 static int vega10_ih_early_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
        vega10_ih_set_interrupt_funcs(adev);
+       vega10_ih_set_self_irq_funcs(adev);
        return 0;
 }
 
 static int vega10_ih_sw_init(void *handle)
 {
-       int r;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       int r;
+
+       r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_IH, 0,
+                             &adev->irq.self_irq);
+       if (r)
+               return r;
 
        r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 256 * 1024, true);
        if (r)
                return r;
 
+       if (adev->asic_type == CHIP_VEGA10) {
+               r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true);
+               if (r)
+                       return r;
+
+               r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true);
+               if (r)
+                       return r;
+       }
+
+       /* TODO add doorbell for IH1 & IH2 as well */
        adev->irq.ih.use_doorbell = true;
        adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1;
 
@@ -313,6 +473,8 @@ static int vega10_ih_sw_fini(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
        amdgpu_irq_fini(adev);
+       amdgpu_ih_ring_fini(adev, &adev->irq.ih2);
+       amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
        amdgpu_ih_ring_fini(adev, &adev->irq.ih);
 
        return 0;
index 422674bb3cdfdd8d2864003177b8704280feb0ad..4b5d60ea3e789fc5cf8393b129afe4071a7d76e0 100644 (file)
@@ -70,8 +70,8 @@ void vega10_doorbell_index_init(struct amdgpu_device *adev)
        adev->doorbell_index.userqueue_start = AMDGPU_DOORBELL64_USERQUEUE_START;
        adev->doorbell_index.userqueue_end = AMDGPU_DOORBELL64_USERQUEUE_END;
        adev->doorbell_index.gfx_ring0 = AMDGPU_DOORBELL64_GFX_RING0;
-       adev->doorbell_index.sdma_engine0 = AMDGPU_DOORBELL64_sDMA_ENGINE0;
-       adev->doorbell_index.sdma_engine1 = AMDGPU_DOORBELL64_sDMA_ENGINE1;
+       adev->doorbell_index.sdma_engine[0] = AMDGPU_DOORBELL64_sDMA_ENGINE0;
+       adev->doorbell_index.sdma_engine[1] = AMDGPU_DOORBELL64_sDMA_ENGINE1;
        adev->doorbell_index.ih = AMDGPU_DOORBELL64_IH;
        adev->doorbell_index.uvd_vce.uvd_ring0_1 = AMDGPU_DOORBELL64_UVD_RING0_1;
        adev->doorbell_index.uvd_vce.uvd_ring2_3 = AMDGPU_DOORBELL64_UVD_RING2_3;
@@ -83,5 +83,6 @@ void vega10_doorbell_index_init(struct amdgpu_device *adev)
        adev->doorbell_index.uvd_vce.vce_ring6_7 = AMDGPU_DOORBELL64_VCE_RING6_7;
        /* In unit of dword doorbell */
        adev->doorbell_index.max_assignment = AMDGPU_DOORBELL64_MAX_ASSIGNMENT << 1;
+       adev->doorbell_index.sdma_doorbell_range = 4;
 }
 
index edce413fda9a0256d8efa29f9f3c8e48b3c404c8..53716c593b2b808816f55aa3650eaaebf7b60125 100644 (file)
@@ -68,14 +68,14 @@ void vega20_doorbell_index_init(struct amdgpu_device *adev)
        adev->doorbell_index.userqueue_start = AMDGPU_VEGA20_DOORBELL_USERQUEUE_START;
        adev->doorbell_index.userqueue_end = AMDGPU_VEGA20_DOORBELL_USERQUEUE_END;
        adev->doorbell_index.gfx_ring0 = AMDGPU_VEGA20_DOORBELL_GFX_RING0;
-       adev->doorbell_index.sdma_engine0 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE0;
-       adev->doorbell_index.sdma_engine1 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE1;
-       adev->doorbell_index.sdma_engine2 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE2;
-       adev->doorbell_index.sdma_engine3 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE3;
-       adev->doorbell_index.sdma_engine4 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE4;
-       adev->doorbell_index.sdma_engine5 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE5;
-       adev->doorbell_index.sdma_engine6 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE6;
-       adev->doorbell_index.sdma_engine7 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE7;
+       adev->doorbell_index.sdma_engine[0] = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE0;
+       adev->doorbell_index.sdma_engine[1] = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE1;
+       adev->doorbell_index.sdma_engine[2] = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE2;
+       adev->doorbell_index.sdma_engine[3] = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE3;
+       adev->doorbell_index.sdma_engine[4] = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE4;
+       adev->doorbell_index.sdma_engine[5] = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE5;
+       adev->doorbell_index.sdma_engine[6] = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE6;
+       adev->doorbell_index.sdma_engine[7] = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE7;
        adev->doorbell_index.ih = AMDGPU_VEGA20_DOORBELL_IH;
        adev->doorbell_index.uvd_vce.uvd_ring0_1 = AMDGPU_VEGA20_DOORBELL64_UVD_RING0_1;
        adev->doorbell_index.uvd_vce.uvd_ring2_3 = AMDGPU_VEGA20_DOORBELL64_UVD_RING2_3;
@@ -86,5 +86,6 @@ void vega20_doorbell_index_init(struct amdgpu_device *adev)
        adev->doorbell_index.uvd_vce.vce_ring4_5 = AMDGPU_VEGA20_DOORBELL64_VCE_RING4_5;
        adev->doorbell_index.uvd_vce.vce_ring6_7 = AMDGPU_VEGA20_DOORBELL64_VCE_RING6_7;
        adev->doorbell_index.max_assignment = AMDGPU_VEGA20_DOORBELL_MAX_ASSIGNMENT << 1;
+       adev->doorbell_index.sdma_doorbell_range = 20;
 }
 
index 77e3674591013167eefaf617a6d116eec626e291..5e5b42a0744ac761b2e318991b4e3c5711723baa 100644 (file)
@@ -941,6 +941,69 @@ static bool vi_need_full_reset(struct amdgpu_device *adev)
        }
 }
 
+static void vi_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0,
+                             uint64_t *count1)
+{
+       uint32_t perfctr = 0;
+       uint64_t cnt0_of, cnt1_of;
+       int tmp;
+
+       /* This reports 0 on APUs, so return to avoid writing/reading registers
+        * that may or may not be different from their GPU counterparts
+        */
+       if (adev->flags & AMD_IS_APU)
+               return;
+
+       /* Set the 2 events that we wish to watch, defined above */
+       /* Reg 40 is # received msgs, Reg 104 is # of posted requests sent */
+       perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT0_SEL, 40);
+       perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT1_SEL, 104);
+
+       /* Write to enable desired perf counters */
+       WREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK, perfctr);
+       /* Zero out and enable the perf counters
+        * Write 0x5:
+        * Bit 0 = Start all counters(1)
+        * Bit 2 = Global counter reset enable(1)
+        */
+       WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000005);
+
+       msleep(1000);
+
+       /* Load the shadow and disable the perf counters
+        * Write 0x2:
+        * Bit 0 = Stop counters(0)
+        * Bit 1 = Load the shadow counters(1)
+        */
+       WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000002);
+
+       /* Read register values to get any >32bit overflow */
+       tmp = RREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK);
+       cnt0_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER0_UPPER);
+       cnt1_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER1_UPPER);
+
+       /* Get the values and add the overflow */
+       *count0 = RREG32_PCIE(ixPCIE_PERF_COUNT0_TXCLK) | (cnt0_of << 32);
+       *count1 = RREG32_PCIE(ixPCIE_PERF_COUNT1_TXCLK) | (cnt1_of << 32);
+}
+
+static bool vi_need_reset_on_init(struct amdgpu_device *adev)
+{
+       u32 clock_cntl, pc;
+
+       if (adev->flags & AMD_IS_APU)
+               return false;
+
+       /* check if the SMC is already running */
+       clock_cntl = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0);
+       pc = RREG32_SMC(ixSMC_PC_C);
+       if ((0 == REG_GET_FIELD(clock_cntl, SMC_SYSCON_CLOCK_CNTL_0, ck_disable)) &&
+           (0x20100 <= pc))
+               return true;
+
+       return false;
+}
+
 static const struct amdgpu_asic_funcs vi_asic_funcs =
 {
        .read_disabled_bios = &vi_read_disabled_bios,
@@ -956,6 +1019,8 @@ static const struct amdgpu_asic_funcs vi_asic_funcs =
        .invalidate_hdp = &vi_invalidate_hdp,
        .need_full_reset = &vi_need_full_reset,
        .init_doorbell_index = &legacy_doorbell_index_init,
+       .get_pcie_usage = &vi_get_pcie_usage,
+       .need_reset_on_init = &vi_need_reset_on_init,
 };
 
 #define CZ_REV_BRISTOL(rev)     \
@@ -1726,8 +1791,8 @@ void legacy_doorbell_index_init(struct amdgpu_device *adev)
        adev->doorbell_index.mec_ring6 = AMDGPU_DOORBELL_MEC_RING6;
        adev->doorbell_index.mec_ring7 = AMDGPU_DOORBELL_MEC_RING7;
        adev->doorbell_index.gfx_ring0 = AMDGPU_DOORBELL_GFX_RING0;
-       adev->doorbell_index.sdma_engine0 = AMDGPU_DOORBELL_sDMA_ENGINE0;
-       adev->doorbell_index.sdma_engine1 = AMDGPU_DOORBELL_sDMA_ENGINE1;
+       adev->doorbell_index.sdma_engine[0] = AMDGPU_DOORBELL_sDMA_ENGINE0;
+       adev->doorbell_index.sdma_engine[1] = AMDGPU_DOORBELL_sDMA_ENGINE1;
        adev->doorbell_index.ih = AMDGPU_DOORBELL_IH;
        adev->doorbell_index.max_assignment = AMDGPU_DOORBELL_MAX_ASSIGNMENT;
 }
index fbf0ee5201c370b1a09f51d6b2dfd6557b89b496..c3613604a4f8bc2d8d6bd60b4fc5dd31aa4dee55 100644 (file)
@@ -4,8 +4,8 @@
 
 config HSA_AMD
        bool "HSA kernel driver for AMD GPU devices"
-       depends on DRM_AMDGPU && X86_64
-       imply AMD_IOMMU_V2
+       depends on DRM_AMDGPU && (X86_64 || ARM64)
+       imply AMD_IOMMU_V2 if X86_64
        select MMU_NOTIFIER
        help
          Enable this if you want to use HSA features on AMD GPU devices.
index b7bc7d7d048f679cb11d58184578859868bd9bd4..5d85ff341385069cc349a83fe607d2e7511345a2 100644 (file)
@@ -863,6 +863,7 @@ static int kfd_fill_mem_info_for_cpu(int numa_node_id, int *avail_size,
        return 0;
 }
 
+#if CONFIG_X86_64
 static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size,
                                uint32_t *num_entries,
                                struct crat_subtype_iolink *sub_type_hdr)
@@ -905,6 +906,7 @@ static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size,
 
        return 0;
 }
+#endif
 
 /* kfd_create_vcrat_image_cpu - Create Virtual CRAT for CPU
  *
@@ -920,7 +922,9 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
        struct crat_subtype_generic *sub_type_hdr;
        int avail_size = *size;
        int numa_node_id;
+#ifdef CONFIG_X86_64
        uint32_t entries = 0;
+#endif
        int ret = 0;
 
        if (!pcrat_image || avail_size < VCRAT_SIZE_FOR_CPU)
@@ -982,6 +986,7 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
                        sub_type_hdr->length);
 
                /* Fill in Subtype: IO Link */
+#ifdef CONFIG_X86_64
                ret = kfd_fill_iolink_info_for_cpu(numa_node_id, &avail_size,
                                &entries,
                                (struct crat_subtype_iolink *)sub_type_hdr);
@@ -992,6 +997,9 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
 
                sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +
                                sub_type_hdr->length * entries);
+#else
+               pr_info("IO link not available for non x86 platforms\n");
+#endif
 
                crat_table->num_domains++;
        }
index 8018163414ffa6fef4838cefddb765e8b58336d0..932007eb9168e73322b56cc3c4d42227e64d2082 100644 (file)
 #include <linux/sched.h>
 #include <linux/device.h>
 #include "kfd_priv.h"
-
-static const struct kgd2kfd_calls kgd2kfd = {
-       .exit           = kgd2kfd_exit,
-       .probe          = kgd2kfd_probe,
-       .device_init    = kgd2kfd_device_init,
-       .device_exit    = kgd2kfd_device_exit,
-       .interrupt      = kgd2kfd_interrupt,
-       .suspend        = kgd2kfd_suspend,
-       .resume         = kgd2kfd_resume,
-       .quiesce_mm     = kgd2kfd_quiesce_mm,
-       .resume_mm      = kgd2kfd_resume_mm,
-       .schedule_evict_and_restore_process =
-                         kgd2kfd_schedule_evict_and_restore_process,
-       .pre_reset      = kgd2kfd_pre_reset,
-       .post_reset     = kgd2kfd_post_reset,
-};
+#include "amdgpu_amdkfd.h"
 
 static int kfd_init(void)
 {
@@ -91,20 +76,10 @@ static void kfd_exit(void)
        kfd_chardev_exit();
 }
 
-int kgd2kfd_init(unsigned int interface_version,
-               const struct kgd2kfd_calls **g2f)
+int kgd2kfd_init()
 {
-       int err;
-
-       err = kfd_init();
-       if (err)
-               return err;
-
-       *g2f = &kgd2kfd;
-
-       return 0;
+       return kfd_init();
 }
-EXPORT_SYMBOL(kgd2kfd_init);
 
 void kgd2kfd_exit(void)
 {
index 0689d4ccbbc0f6fd59164f5ebab76246fca396e6..12b66330fc6d3cefaa0d1cbbfc1b270f6c380cce 100644 (file)
@@ -266,14 +266,6 @@ struct kfd_dev {
        bool pci_atomic_requested;
 };
 
-/* KGD2KFD callbacks */
-void kgd2kfd_exit(void);
-struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd,
-                       struct pci_dev *pdev, const struct kfd2kgd_calls *f2g);
-bool kgd2kfd_device_init(struct kfd_dev *kfd,
-                       const struct kgd2kfd_shared_resources *gpu_resources);
-void kgd2kfd_device_exit(struct kfd_dev *kfd);
-
 enum kfd_mempool {
        KFD_MEMPOOL_SYSTEM_CACHEABLE = 1,
        KFD_MEMPOOL_SYSTEM_WRITECOMBINE = 2,
@@ -541,11 +533,6 @@ struct qcm_process_device {
 /* Approx. time before evicting the process again */
 #define PROCESS_ACTIVE_TIME_MS 10
 
-int kgd2kfd_quiesce_mm(struct mm_struct *mm);
-int kgd2kfd_resume_mm(struct mm_struct *mm);
-int kgd2kfd_schedule_evict_and_restore_process(struct mm_struct *mm,
-                                              struct dma_fence *fence);
-
 /* 8 byte handle containing GPU ID in the most significant 4 bytes and
  * idr_handle in the least significant 4 bytes
  */
@@ -800,20 +787,11 @@ int kfd_numa_node_to_apic_id(int numa_node_id);
 /* Interrupts */
 int kfd_interrupt_init(struct kfd_dev *dev);
 void kfd_interrupt_exit(struct kfd_dev *dev);
-void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry);
 bool enqueue_ih_ring_entry(struct kfd_dev *kfd,        const void *ih_ring_entry);
 bool interrupt_is_wanted(struct kfd_dev *dev,
                                const uint32_t *ih_ring_entry,
                                uint32_t *patched_ihre, bool *flag);
 
-/* Power Management */
-void kgd2kfd_suspend(struct kfd_dev *kfd);
-int kgd2kfd_resume(struct kfd_dev *kfd);
-
-/* GPU reset */
-int kgd2kfd_pre_reset(struct kfd_dev *kfd);
-int kgd2kfd_post_reset(struct kfd_dev *kfd);
-
 /* amdkfd Apertures */
 int kfd_init_apertures(struct kfd_process *process);
 
index 5f5b2acedbac3bf0e15d8727d5327af37e3f7a79..09da91644f9fc6e15d29c628d6e16f1a2ddd0f69 100644 (file)
@@ -1093,8 +1093,6 @@ static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu)
  *             the GPU device is not already present in the topology device
  *             list then return NULL. This means a new topology device has to
  *             be created for this GPU.
- * TODO: Rather than assiging @gpu to first topology device withtout
- *             gpu attached, it will better to have more stringent check.
  */
 static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
 {
@@ -1102,12 +1100,20 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
        struct kfd_topology_device *out_dev = NULL;
 
        down_write(&topology_lock);
-       list_for_each_entry(dev, &topology_device_list, list)
+       list_for_each_entry(dev, &topology_device_list, list) {
+               /* Discrete GPUs need their own topology device list
+                * entries. Don't assign them to CPU/APU nodes.
+                */
+               if (!gpu->device_info->needs_iommu_device &&
+                   dev->node_props.cpu_cores_count)
+                       continue;
+
                if (!dev->gpu && (dev->node_props.simd_count > 0)) {
                        dev->gpu = gpu;
                        out_dev = dev;
                        break;
                }
+       }
        up_write(&topology_lock);
        return out_dev;
 }
@@ -1392,7 +1398,6 @@ int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev)
 
 static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask)
 {
-       const struct cpuinfo_x86 *cpuinfo;
        int first_cpu_of_numa_node;
 
        if (!cpumask || cpumask == cpu_none_mask)
@@ -1400,9 +1405,11 @@ static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask)
        first_cpu_of_numa_node = cpumask_first(cpumask);
        if (first_cpu_of_numa_node >= nr_cpu_ids)
                return -1;
-       cpuinfo = &cpu_data(first_cpu_of_numa_node);
-
-       return cpuinfo->apicid;
+#ifdef CONFIG_X86_64
+       return cpu_data(first_cpu_of_numa_node).apicid;
+#else
+       return first_cpu_of_numa_node;
+#endif
 }
 
 /* kfd_numa_node_to_apic_id - Returns the APIC ID of the first logical processor
index a9a28dbc3e2421e36468554a554d1987b7c4f46e..407f733a47ea114df0596c7493a8886ae06fcb13 100644 (file)
@@ -1692,7 +1692,8 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
 
        dc_resource_state_copy_construct_current(adev->dm.dc, state->context);
 
-       drm_atomic_private_obj_init(&adev->dm.atomic_obj,
+       drm_atomic_private_obj_init(adev->ddev,
+                                   &adev->dm.atomic_obj,
                                    &state->base,
                                    &dm_atomic_state_funcs);
 
@@ -1759,7 +1760,7 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
                + caps.min_input_signal * 0x101;
 
        if (dc_link_set_backlight_level(dm->backlight_link,
-                       brightness, 0, 0))
+                       brightness, 0))
                return 0;
        else
                return 1;
@@ -2283,6 +2284,68 @@ static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb,
        return r;
 }
 
+static inline uint64_t get_dcc_address(uint64_t address, uint64_t tiling_flags)
+{
+       uint32_t offset = AMDGPU_TILING_GET(tiling_flags, DCC_OFFSET_256B);
+
+       return offset ? (address + offset * 256) : 0;
+}
+
+static bool fill_plane_dcc_attributes(struct amdgpu_device *adev,
+                                     const struct amdgpu_framebuffer *afb,
+                                     struct dc_plane_state *plane_state,
+                                     uint64_t info)
+{
+       struct dc *dc = adev->dm.dc;
+       struct dc_dcc_surface_param input = {0};
+       struct dc_surface_dcc_cap output = {0};
+       uint32_t offset = AMDGPU_TILING_GET(info, DCC_OFFSET_256B);
+       uint32_t i64b = AMDGPU_TILING_GET(info, DCC_INDEPENDENT_64B) != 0;
+       uint64_t dcc_address;
+
+       if (!offset)
+               return false;
+
+       if (!dc->cap_funcs.get_dcc_compression_cap)
+               return false;
+
+       input.format = plane_state->format;
+       input.surface_size.width =
+               plane_state->plane_size.grph.surface_size.width;
+       input.surface_size.height =
+               plane_state->plane_size.grph.surface_size.height;
+       input.swizzle_mode = plane_state->tiling_info.gfx9.swizzle;
+
+       if (plane_state->rotation == ROTATION_ANGLE_0 ||
+           plane_state->rotation == ROTATION_ANGLE_180)
+               input.scan = SCAN_DIRECTION_HORIZONTAL;
+       else if (plane_state->rotation == ROTATION_ANGLE_90 ||
+                plane_state->rotation == ROTATION_ANGLE_270)
+               input.scan = SCAN_DIRECTION_VERTICAL;
+
+       if (!dc->cap_funcs.get_dcc_compression_cap(dc, &input, &output))
+               return false;
+
+       if (!output.capable)
+               return false;
+
+       if (i64b == 0 && output.grph.rgb.independent_64b_blks != 0)
+               return false;
+
+       plane_state->dcc.enable = 1;
+       plane_state->dcc.grph.meta_pitch =
+               AMDGPU_TILING_GET(info, DCC_PITCH_MAX) + 1;
+       plane_state->dcc.grph.independent_64b_blks = i64b;
+
+       dcc_address = get_dcc_address(afb->address, info);
+       plane_state->address.grph.meta_addr.low_part =
+               lower_32_bits(dcc_address);
+       plane_state->address.grph.meta_addr.high_part =
+               upper_32_bits(dcc_address);
+
+       return true;
+}
+
 static int fill_plane_attributes_from_fb(struct amdgpu_device *adev,
                                         struct dc_plane_state *plane_state,
                                         const struct amdgpu_framebuffer *amdgpu_fb)
@@ -2335,6 +2398,10 @@ static int fill_plane_attributes_from_fb(struct amdgpu_device *adev,
                return -EINVAL;
        }
 
+       memset(&plane_state->address, 0, sizeof(plane_state->address));
+       memset(&plane_state->tiling_info, 0, sizeof(plane_state->tiling_info));
+       memset(&plane_state->dcc, 0, sizeof(plane_state->dcc));
+
        if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
                plane_state->address.type = PLN_ADDR_TYPE_GRAPHICS;
                plane_state->plane_size.grph.surface_size.x = 0;
@@ -2366,8 +2433,6 @@ static int fill_plane_attributes_from_fb(struct amdgpu_device *adev,
                plane_state->color_space = COLOR_SPACE_YCBCR709;
        }
 
-       memset(&plane_state->tiling_info, 0, sizeof(plane_state->tiling_info));
-
        /* Fill GFX8 params */
        if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) {
                unsigned int bankw, bankh, mtaspect, tile_split, num_banks;
@@ -2416,6 +2481,9 @@ static int fill_plane_attributes_from_fb(struct amdgpu_device *adev,
                plane_state->tiling_info.gfx9.swizzle =
                        AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE);
                plane_state->tiling_info.gfx9.shaderEnable = 1;
+
+               fill_plane_dcc_attributes(adev, amdgpu_fb, plane_state,
+                                         tiling_flags);
        }
 
        plane_state->visible = true;
@@ -2579,7 +2647,7 @@ get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing)
                 * according to HDMI spec, we use YCbCr709 and YCbCr601
                 * respectively
                 */
-               if (dc_crtc_timing->pix_clk_khz > 27030) {
+               if (dc_crtc_timing->pix_clk_100hz > 270300) {
                        if (dc_crtc_timing->flags.Y_ONLY)
                                color_space =
                                        COLOR_SPACE_YCBCR709_LIMITED;
@@ -2622,7 +2690,7 @@ static void adjust_colour_depth_from_display_info(struct dc_crtc_timing *timing_
        if (timing_out->display_color_depth <= COLOR_DEPTH_888)
                return;
        do {
-               normalized_clk = timing_out->pix_clk_khz;
+               normalized_clk = timing_out->pix_clk_100hz / 10;
                /* YCbCr 4:2:0 requires additional adjustment of 1/2 */
                if (timing_out->pixel_encoding == PIXEL_ENCODING_YCBCR420)
                        normalized_clk /= 2;
@@ -2665,10 +2733,10 @@ fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream,
        timing_out->v_border_bottom = 0;
        /* TODO: un-hardcode */
        if (drm_mode_is_420_only(info, mode_in)
-                       && stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A)
+                       && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
                timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
        else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444)
-                       && stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A)
+                       && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
                timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;
        else
                timing_out->pixel_encoding = PIXEL_ENCODING_RGB;
@@ -2703,14 +2771,14 @@ fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream,
                mode_in->crtc_vsync_start - mode_in->crtc_vdisplay;
        timing_out->v_sync_width =
                mode_in->crtc_vsync_end - mode_in->crtc_vsync_start;
-       timing_out->pix_clk_khz = mode_in->crtc_clock;
+       timing_out->pix_clk_100hz = mode_in->crtc_clock * 10;
        timing_out->aspect_ratio = get_aspect_ratio(mode_in);
 
        stream->output_color_space = get_output_color_space(timing_out);
 
        stream->out_transfer_func->type = TF_TYPE_PREDEFINED;
        stream->out_transfer_func->tf = TRANSFER_FUNCTION_SRGB;
-       if (stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A)
+       if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
                adjust_colour_depth_from_display_info(timing_out, info);
 }
 
@@ -2831,7 +2899,7 @@ static void set_master_stream(struct dc_stream_state *stream_set[],
                if (stream_set[j] && stream_set[j]->triggered_crtc_reset.enabled) {
                        int refresh_rate = 0;
 
-                       refresh_rate = (stream_set[j]->timing.pix_clk_khz*1000)/
+                       refresh_rate = (stream_set[j]->timing.pix_clk_100hz*100)/
                                (stream_set[j]->timing.h_total*stream_set[j]->timing.v_total);
                        if (refresh_rate > highest_rfr) {
                                highest_rfr = refresh_rate;
@@ -2904,6 +2972,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
                goto finish;
        }
 
+       stream->dm_stream_context = aconnector;
+
        list_for_each_entry(preferred_mode, &aconnector->base.modes, head) {
                /* Search for preferred mode */
                if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) {
@@ -2955,7 +3025,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
                drm_connector,
                sink);
 
-       update_stream_signal(stream);
+       update_stream_signal(stream, sink);
 
        if (dm_state && dm_state->freesync_capable)
                stream->ignore_msa_timing_param = true;
@@ -3531,6 +3601,7 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
        struct amdgpu_bo *rbo;
        uint64_t chroma_addr = 0;
        struct dm_plane_state *dm_plane_state_new, *dm_plane_state_old;
+       uint64_t tiling_flags, dcc_address;
        unsigned int awidth;
        uint32_t domain;
        int r;
@@ -3571,6 +3642,9 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
                DRM_ERROR("%p bind failed\n", rbo);
                return r;
        }
+
+       amdgpu_bo_get_tiling_flags(rbo, &tiling_flags);
+
        amdgpu_bo_unreserve(rbo);
 
        afb->address = amdgpu_bo_gpu_offset(rbo);
@@ -3584,6 +3658,13 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
                if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
                        plane_state->address.grph.addr.low_part = lower_32_bits(afb->address);
                        plane_state->address.grph.addr.high_part = upper_32_bits(afb->address);
+
+                       dcc_address =
+                               get_dcc_address(afb->address, tiling_flags);
+                       plane_state->address.grph.meta_addr.low_part =
+                               lower_32_bits(dcc_address);
+                       plane_state->address.grph.meta_addr.high_part =
+                               upper_32_bits(dcc_address);
                } else {
                        awidth = ALIGN(new_state->fb->width, 64);
                        plane_state->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE;
@@ -4455,20 +4536,6 @@ static void prepare_flip_isr(struct amdgpu_crtc *acrtc)
                                                 acrtc->crtc_id);
 }
 
-struct dc_stream_status *dc_state_get_stream_status(
-       struct dc_state *state,
-       struct dc_stream_state *stream)
-{
-       uint8_t i;
-
-       for (i = 0; i < state->stream_count; i++) {
-               if (stream == state->streams[i])
-                       return &state->stream_status[i];
-       }
-
-       return NULL;
-}
-
 static void update_freesync_state_on_stream(
        struct amdgpu_display_manager *dm,
        struct dm_crtc_state *new_crtc_state,
@@ -4522,12 +4589,12 @@ static void update_freesync_state_on_stream(
                TRANSFER_FUNC_UNKNOWN,
                &vrr_infopacket);
 
-       new_crtc_state->freesync_timing_changed =
+       new_crtc_state->freesync_timing_changed |=
                (memcmp(&new_crtc_state->vrr_params.adjust,
                        &vrr_params.adjust,
                        sizeof(vrr_params.adjust)) != 0);
 
-       new_crtc_state->freesync_vrr_info_changed =
+       new_crtc_state->freesync_vrr_info_changed |=
                (memcmp(&new_crtc_state->vrr_infopacket,
                        &vrr_infopacket,
                        sizeof(vrr_infopacket)) != 0);
@@ -4551,248 +4618,6 @@ static void update_freesync_state_on_stream(
                                  vrr_params.adjust.v_total_max);
 }
 
-/*
- * Executes flip
- *
- * Waits on all BO's fences and for proper vblank count
- */
-static void amdgpu_dm_do_flip(struct drm_crtc *crtc,
-                             struct drm_framebuffer *fb,
-                             uint32_t target,
-                             struct dc_state *state)
-{
-       unsigned long flags;
-       uint64_t timestamp_ns;
-       uint32_t target_vblank;
-       int r, vpos, hpos;
-       struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
-       struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(fb);
-       struct amdgpu_bo *abo = gem_to_amdgpu_bo(fb->obj[0]);
-       struct amdgpu_device *adev = crtc->dev->dev_private;
-       bool async_flip = (crtc->state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0;
-       struct dc_flip_addrs addr = { {0} };
-       /* TODO eliminate or rename surface_update */
-       struct dc_surface_update surface_updates[1] = { {0} };
-       struct dc_stream_update stream_update = {0};
-       struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
-       struct dc_stream_status *stream_status;
-       struct dc_plane_state *surface;
-
-
-       /* Prepare wait for target vblank early - before the fence-waits */
-       target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) +
-                       amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id);
-
-       /*
-        * TODO This might fail and hence better not used, wait
-        * explicitly on fences instead
-        * and in general should be called for
-        * blocking commit to as per framework helpers
-        */
-       r = amdgpu_bo_reserve(abo, true);
-       if (unlikely(r != 0)) {
-               DRM_ERROR("failed to reserve buffer before flip\n");
-               WARN_ON(1);
-       }
-
-       /* Wait for all fences on this FB */
-       WARN_ON(reservation_object_wait_timeout_rcu(abo->tbo.resv, true, false,
-                                                                   MAX_SCHEDULE_TIMEOUT) < 0);
-
-       amdgpu_bo_unreserve(abo);
-
-       /*
-        * Wait until we're out of the vertical blank period before the one
-        * targeted by the flip
-        */
-       while ((acrtc->enabled &&
-               (amdgpu_display_get_crtc_scanoutpos(adev->ddev, acrtc->crtc_id,
-                                                   0, &vpos, &hpos, NULL,
-                                                   NULL, &crtc->hwmode)
-                & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) ==
-               (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) &&
-               (int)(target_vblank -
-                 amdgpu_get_vblank_counter_kms(adev->ddev, acrtc->crtc_id)) > 0)) {
-               usleep_range(1000, 1100);
-       }
-
-       /* Flip */
-       spin_lock_irqsave(&crtc->dev->event_lock, flags);
-
-       WARN_ON(acrtc->pflip_status != AMDGPU_FLIP_NONE);
-       WARN_ON(!acrtc_state->stream);
-
-       addr.address.grph.addr.low_part = lower_32_bits(afb->address);
-       addr.address.grph.addr.high_part = upper_32_bits(afb->address);
-       addr.flip_immediate = async_flip;
-
-       timestamp_ns = ktime_get_ns();
-       addr.flip_timestamp_in_us = div_u64(timestamp_ns, 1000);
-
-
-       if (acrtc->base.state->event)
-               prepare_flip_isr(acrtc);
-
-       spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
-
-       stream_status = dc_stream_get_status(acrtc_state->stream);
-       if (!stream_status) {
-               DRM_ERROR("No stream status for CRTC: id=%d\n",
-                       acrtc->crtc_id);
-               return;
-       }
-
-       surface = stream_status->plane_states[0];
-       surface_updates->surface = surface;
-
-       if (!surface) {
-               DRM_ERROR("No surface for CRTC: id=%d\n",
-                       acrtc->crtc_id);
-               return;
-       }
-       surface_updates->flip_addr = &addr;
-
-       if (acrtc_state->stream) {
-               update_freesync_state_on_stream(
-                       &adev->dm,
-                       acrtc_state,
-                       acrtc_state->stream,
-                       surface,
-                       addr.flip_timestamp_in_us);
-
-               if (acrtc_state->freesync_timing_changed)
-                       stream_update.adjust =
-                               &acrtc_state->stream->adjust;
-
-               if (acrtc_state->freesync_vrr_info_changed)
-                       stream_update.vrr_infopacket =
-                               &acrtc_state->stream->vrr_infopacket;
-       }
-
-       /* Update surface timing information. */
-       surface->time.time_elapsed_in_us[surface->time.index] =
-               addr.flip_timestamp_in_us - surface->time.prev_update_time_in_us;
-       surface->time.prev_update_time_in_us = addr.flip_timestamp_in_us;
-       surface->time.index++;
-       if (surface->time.index >= DC_PLANE_UPDATE_TIMES_MAX)
-               surface->time.index = 0;
-
-       mutex_lock(&adev->dm.dc_lock);
-
-       dc_commit_updates_for_stream(adev->dm.dc,
-                                            surface_updates,
-                                            1,
-                                            acrtc_state->stream,
-                                            &stream_update,
-                                            &surface_updates->surface,
-                                            state);
-       mutex_unlock(&adev->dm.dc_lock);
-
-       DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n",
-                        __func__,
-                        addr.address.grph.addr.high_part,
-                        addr.address.grph.addr.low_part);
-}
-
-/*
- * TODO this whole function needs to go
- *
- * dc_surface_update is needlessly complex. See if we can just replace this
- * with a dc_plane_state and follow the atomic model a bit more closely here.
- */
-static bool commit_planes_to_stream(
-               struct amdgpu_display_manager *dm,
-               struct dc *dc,
-               struct dc_plane_state **plane_states,
-               uint8_t new_plane_count,
-               struct dm_crtc_state *dm_new_crtc_state,
-               struct dm_crtc_state *dm_old_crtc_state,
-               struct dc_state *state)
-{
-       /* no need to dynamically allocate this. it's pretty small */
-       struct dc_surface_update updates[MAX_SURFACES];
-       struct dc_flip_addrs *flip_addr;
-       struct dc_plane_info *plane_info;
-       struct dc_scaling_info *scaling_info;
-       int i;
-       struct dc_stream_state *dc_stream = dm_new_crtc_state->stream;
-       struct dc_stream_update *stream_update =
-                       kzalloc(sizeof(struct dc_stream_update), GFP_KERNEL);
-       unsigned int abm_level;
-
-       if (!stream_update) {
-               BREAK_TO_DEBUGGER();
-               return false;
-       }
-
-       flip_addr = kcalloc(MAX_SURFACES, sizeof(struct dc_flip_addrs),
-                           GFP_KERNEL);
-       plane_info = kcalloc(MAX_SURFACES, sizeof(struct dc_plane_info),
-                            GFP_KERNEL);
-       scaling_info = kcalloc(MAX_SURFACES, sizeof(struct dc_scaling_info),
-                              GFP_KERNEL);
-
-       if (!flip_addr || !plane_info || !scaling_info) {
-               kfree(flip_addr);
-               kfree(plane_info);
-               kfree(scaling_info);
-               kfree(stream_update);
-               return false;
-       }
-
-       memset(updates, 0, sizeof(updates));
-
-       stream_update->src = dc_stream->src;
-       stream_update->dst = dc_stream->dst;
-       stream_update->out_transfer_func = dc_stream->out_transfer_func;
-
-       if (dm_new_crtc_state->abm_level != dm_old_crtc_state->abm_level) {
-               abm_level = dm_new_crtc_state->abm_level;
-               stream_update->abm_level = &abm_level;
-       }
-
-       for (i = 0; i < new_plane_count; i++) {
-               updates[i].surface = plane_states[i];
-               updates[i].gamma =
-                       (struct dc_gamma *)plane_states[i]->gamma_correction;
-               updates[i].in_transfer_func = plane_states[i]->in_transfer_func;
-               flip_addr[i].address = plane_states[i]->address;
-               flip_addr[i].flip_immediate = plane_states[i]->flip_immediate;
-               plane_info[i].color_space = plane_states[i]->color_space;
-               plane_info[i].format = plane_states[i]->format;
-               plane_info[i].plane_size = plane_states[i]->plane_size;
-               plane_info[i].rotation = plane_states[i]->rotation;
-               plane_info[i].horizontal_mirror = plane_states[i]->horizontal_mirror;
-               plane_info[i].stereo_format = plane_states[i]->stereo_format;
-               plane_info[i].tiling_info = plane_states[i]->tiling_info;
-               plane_info[i].visible = plane_states[i]->visible;
-               plane_info[i].per_pixel_alpha = plane_states[i]->per_pixel_alpha;
-               plane_info[i].dcc = plane_states[i]->dcc;
-               scaling_info[i].scaling_quality = plane_states[i]->scaling_quality;
-               scaling_info[i].src_rect = plane_states[i]->src_rect;
-               scaling_info[i].dst_rect = plane_states[i]->dst_rect;
-               scaling_info[i].clip_rect = plane_states[i]->clip_rect;
-
-               updates[i].flip_addr = &flip_addr[i];
-               updates[i].plane_info = &plane_info[i];
-               updates[i].scaling_info = &scaling_info[i];
-       }
-
-       mutex_lock(&dm->dc_lock);
-       dc_commit_updates_for_stream(
-                       dc,
-                       updates,
-                       new_plane_count,
-                       dc_stream, stream_update, plane_states, state);
-       mutex_unlock(&dm->dc_lock);
-
-       kfree(flip_addr);
-       kfree(plane_info);
-       kfree(scaling_info);
-       kfree(stream_update);
-       return true;
-}
-
 static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                                    struct dc_state *dc_state,
                                    struct drm_device *dev,
@@ -4800,26 +4625,50 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                                    struct drm_crtc *pcrtc,
                                    bool *wait_for_vblank)
 {
-       uint32_t i;
+       uint32_t i, r;
+       uint64_t timestamp_ns;
        struct drm_plane *plane;
        struct drm_plane_state *old_plane_state, *new_plane_state;
-       struct dc_stream_state *dc_stream_attach;
-       struct dc_plane_state *plane_states_constructed[MAX_SURFACES];
        struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc);
        struct drm_crtc_state *new_pcrtc_state =
                        drm_atomic_get_new_crtc_state(state, pcrtc);
        struct dm_crtc_state *acrtc_state = to_dm_crtc_state(new_pcrtc_state);
        struct dm_crtc_state *dm_old_crtc_state =
                        to_dm_crtc_state(drm_atomic_get_old_crtc_state(state, pcrtc));
-       int planes_count = 0;
+       int flip_count = 0, planes_count = 0, vpos, hpos;
        unsigned long flags;
+       struct amdgpu_bo *abo;
+       uint64_t tiling_flags, dcc_address;
+       struct dc_stream_status *stream_status;
+       uint32_t target, target_vblank;
+
+       struct {
+               struct dc_surface_update surface_updates[MAX_SURFACES];
+               struct dc_flip_addrs flip_addrs[MAX_SURFACES];
+               struct dc_stream_update stream_update;
+       } *flip;
+
+       struct {
+               struct dc_surface_update surface_updates[MAX_SURFACES];
+               struct dc_plane_info plane_infos[MAX_SURFACES];
+               struct dc_scaling_info scaling_infos[MAX_SURFACES];
+               struct dc_stream_update stream_update;
+       } *full;
+
+       flip = kzalloc(sizeof(*flip), GFP_KERNEL);
+       full = kzalloc(sizeof(*full), GFP_KERNEL);
+
+       if (!flip || !full)
+               dm_error("Failed to allocate update bundles\n");
 
        /* update planes when needed */
        for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
                struct drm_crtc *crtc = new_plane_state->crtc;
                struct drm_crtc_state *new_crtc_state;
                struct drm_framebuffer *fb = new_plane_state->fb;
+               struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(fb);
                bool pflip_needed;
+               struct dc_plane_state *surface, *dc_plane;
                struct dm_plane_state *dm_new_plane_state = to_dm_plane_state(new_plane_state);
 
                if (plane->type == DRM_PLANE_TYPE_CURSOR) {
@@ -4834,72 +4683,205 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                if (!new_crtc_state->active)
                        continue;
 
-               pflip_needed = !state->allow_modeset;
+               pflip_needed = old_plane_state->fb &&
+                       old_plane_state->fb != new_plane_state->fb;
 
-               spin_lock_irqsave(&crtc->dev->event_lock, flags);
-               if (acrtc_attach->pflip_status != AMDGPU_FLIP_NONE) {
-                       DRM_ERROR("%s: acrtc %d, already busy\n",
-                                 __func__,
-                                 acrtc_attach->crtc_id);
-                       /* In commit tail framework this cannot happen */
-                       WARN_ON(1);
-               }
-               spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
-
-               if (!pflip_needed || plane->type == DRM_PLANE_TYPE_OVERLAY) {
-                       WARN_ON(!dm_new_plane_state->dc_state);
-
-                       plane_states_constructed[planes_count] = dm_new_plane_state->dc_state;
+               dc_plane = dm_new_plane_state->dc_state;
 
-                       dc_stream_attach = acrtc_state->stream;
-                       planes_count++;
-
-               } else if (new_crtc_state->planes_changed) {
-                       /* Assume even ONE crtc with immediate flip means
+               if (pflip_needed) {
+                       /*
+                        * Assume even ONE crtc with immediate flip means
                         * entire can't wait for VBLANK
                         * TODO Check if it's correct
                         */
-                       *wait_for_vblank =
-                                       new_pcrtc_state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC ?
-                               false : true;
-
-                       /* TODO: Needs rework for multiplane flip */
-                       if (plane->type == DRM_PLANE_TYPE_PRIMARY)
-                               drm_crtc_vblank_get(crtc);
-
-                       amdgpu_dm_do_flip(
-                               crtc,
-                               fb,
-                               (uint32_t)drm_crtc_vblank_count(crtc) + *wait_for_vblank,
-                               dc_state);
+                       if (new_pcrtc_state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC)
+                               *wait_for_vblank = false;
+
+                       /*
+                        * TODO This might fail and hence better not used, wait
+                        * explicitly on fences instead
+                        * and in general should be called for
+                        * blocking commit to as per framework helpers
+                        */
+                       abo = gem_to_amdgpu_bo(fb->obj[0]);
+                       r = amdgpu_bo_reserve(abo, true);
+                       if (unlikely(r != 0)) {
+                               DRM_ERROR("failed to reserve buffer before flip\n");
+                               WARN_ON(1);
+                       }
+
+                       /* Wait for all fences on this FB */
+                       WARN_ON(reservation_object_wait_timeout_rcu(abo->tbo.resv, true, false,
+                                                                                   MAX_SCHEDULE_TIMEOUT) < 0);
+
+                       amdgpu_bo_get_tiling_flags(abo, &tiling_flags);
+
+                       amdgpu_bo_unreserve(abo);
+
+                       flip->flip_addrs[flip_count].address.grph.addr.low_part = lower_32_bits(afb->address);
+                       flip->flip_addrs[flip_count].address.grph.addr.high_part = upper_32_bits(afb->address);
+
+                       dcc_address = get_dcc_address(afb->address, tiling_flags);
+                       flip->flip_addrs[flip_count].address.grph.meta_addr.low_part = lower_32_bits(dcc_address);
+                       flip->flip_addrs[flip_count].address.grph.meta_addr.high_part = upper_32_bits(dcc_address);
+
+                       flip->flip_addrs[flip_count].flip_immediate =
+                                       (crtc->state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0;
+
+                       timestamp_ns = ktime_get_ns();
+                       flip->flip_addrs[flip_count].flip_timestamp_in_us = div_u64(timestamp_ns, 1000);
+                       flip->surface_updates[flip_count].flip_addr = &flip->flip_addrs[flip_count];
+
+                       stream_status = dc_stream_get_status(acrtc_state->stream);
+                       if (!stream_status) {
+                               DRM_ERROR("No stream status for CRTC: id=%d\n",
+                                               acrtc_attach->crtc_id);
+                               continue;
+                       }
+
+                       surface = stream_status->plane_states[0];
+                       flip->surface_updates[flip_count].surface = surface;
+                       if (!flip->surface_updates[flip_count].surface) {
+                               DRM_ERROR("No surface for CRTC: id=%d\n",
+                                               acrtc_attach->crtc_id);
+                               continue;
+                       }
+
+                       if (acrtc_state->stream)
+                               update_freesync_state_on_stream(
+                                       dm,
+                                       acrtc_state,
+                                       acrtc_state->stream,
+                                       surface,
+                                       flip->flip_addrs[flip_count].flip_timestamp_in_us);
+
+                       /* Update surface timing information. */
+                       surface->time.time_elapsed_in_us[surface->time.index] =
+                               flip->flip_addrs[flip_count].flip_timestamp_in_us -
+                               surface->time.prev_update_time_in_us;
+                       surface->time.prev_update_time_in_us = flip->flip_addrs[flip_count].flip_timestamp_in_us;
+                       surface->time.index++;
+                       if (surface->time.index >= DC_PLANE_UPDATE_TIMES_MAX)
+                               surface->time.index = 0;
+
+                       DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x\n",
+                                        __func__,
+                                        flip->flip_addrs[flip_count].address.grph.addr.high_part,
+                                        flip->flip_addrs[flip_count].address.grph.addr.low_part);
+
+                       flip_count += 1;
                }
 
+               full->surface_updates[planes_count].surface = dc_plane;
+               if (new_pcrtc_state->color_mgmt_changed) {
+                       full->surface_updates[planes_count].gamma = dc_plane->gamma_correction;
+                       full->surface_updates[planes_count].in_transfer_func = dc_plane->in_transfer_func;
+               }
+
+
+               full->scaling_infos[planes_count].scaling_quality = dc_plane->scaling_quality;
+               full->scaling_infos[planes_count].src_rect = dc_plane->src_rect;
+               full->scaling_infos[planes_count].dst_rect = dc_plane->dst_rect;
+               full->scaling_infos[planes_count].clip_rect = dc_plane->clip_rect;
+               full->surface_updates[planes_count].scaling_info = &full->scaling_infos[planes_count];
+
+
+               full->plane_infos[planes_count].color_space = dc_plane->color_space;
+               full->plane_infos[planes_count].format = dc_plane->format;
+               full->plane_infos[planes_count].plane_size = dc_plane->plane_size;
+               full->plane_infos[planes_count].rotation = dc_plane->rotation;
+               full->plane_infos[planes_count].horizontal_mirror = dc_plane->horizontal_mirror;
+               full->plane_infos[planes_count].stereo_format = dc_plane->stereo_format;
+               full->plane_infos[planes_count].tiling_info = dc_plane->tiling_info;
+               full->plane_infos[planes_count].visible = dc_plane->visible;
+               full->plane_infos[planes_count].per_pixel_alpha = dc_plane->per_pixel_alpha;
+               full->plane_infos[planes_count].dcc = dc_plane->dcc;
+               full->surface_updates[planes_count].plane_info = &full->plane_infos[planes_count];
+
+               planes_count += 1;
+
        }
 
-       if (planes_count) {
-               unsigned long flags;
+       /*
+        * TODO: For proper atomic behaviour, we should be calling into DC once with
+        * all the changes.  However, DC refuses to do pageflips and non-pageflip
+        * changes in the same call.  Change DC to respect atomic behaviour,
+        * hopefully eliminating dc_*_update structs in their entirety.
+        */
+       if (flip_count) {
+               target = (uint32_t)drm_crtc_vblank_count(pcrtc) + *wait_for_vblank;
+               /* Prepare wait for target vblank early - before the fence-waits */
+               target_vblank = target - (uint32_t)drm_crtc_vblank_count(pcrtc) +
+                               amdgpu_get_vblank_counter_kms(pcrtc->dev, acrtc_attach->crtc_id);
 
-               if (new_pcrtc_state->event) {
+               /*
+                * Wait until we're out of the vertical blank period before the one
+                * targeted by the flip
+                */
+               while ((acrtc_attach->enabled &&
+                       (amdgpu_display_get_crtc_scanoutpos(dm->ddev, acrtc_attach->crtc_id,
+                                                           0, &vpos, &hpos, NULL,
+                                                           NULL, &pcrtc->hwmode)
+                        & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) ==
+                       (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) &&
+                       (int)(target_vblank -
+                         amdgpu_get_vblank_counter_kms(dm->ddev, acrtc_attach->crtc_id)) > 0)) {
+                       usleep_range(1000, 1100);
+               }
 
+               if (acrtc_attach->base.state->event) {
                        drm_crtc_vblank_get(pcrtc);
 
                        spin_lock_irqsave(&pcrtc->dev->event_lock, flags);
+
+                       WARN_ON(acrtc_attach->pflip_status != AMDGPU_FLIP_NONE);
                        prepare_flip_isr(acrtc_attach);
+
                        spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags);
                }
 
-               dc_stream_attach->abm_level = acrtc_state->abm_level;
+               if (acrtc_state->stream) {
 
-               if (false == commit_planes_to_stream(dm,
-                                                       dm->dc,
-                                                       plane_states_constructed,
-                                                       planes_count,
-                                                       acrtc_state,
-                                                       dm_old_crtc_state,
-                                                       dc_state))
-                       dm_error("%s: Failed to attach plane!\n", __func__);
-       } else {
-               /*TODO BUG Here should go disable planes on CRTC. */
+                       if (acrtc_state->freesync_timing_changed)
+                               flip->stream_update.adjust =
+                                       &acrtc_state->stream->adjust;
+
+                       if (acrtc_state->freesync_vrr_info_changed)
+                               flip->stream_update.vrr_infopacket =
+                                       &acrtc_state->stream->vrr_infopacket;
+               }
+
+               mutex_lock(&dm->dc_lock);
+               dc_commit_updates_for_stream(dm->dc,
+                                                    flip->surface_updates,
+                                                    flip_count,
+                                                    acrtc_state->stream,
+                                                    &flip->stream_update,
+                                                    dc_state);
+               mutex_unlock(&dm->dc_lock);
+       }
+
+       if (planes_count) {
+               if (new_pcrtc_state->mode_changed) {
+                       full->stream_update.src = acrtc_state->stream->src;
+                       full->stream_update.dst = acrtc_state->stream->dst;
+               }
+
+               if (new_pcrtc_state->color_mgmt_changed)
+                       full->stream_update.out_transfer_func = acrtc_state->stream->out_transfer_func;
+
+               acrtc_state->stream->abm_level = acrtc_state->abm_level;
+               if (acrtc_state->abm_level != dm_old_crtc_state->abm_level)
+                       full->stream_update.abm_level = &acrtc_state->abm_level;
+
+               mutex_lock(&dm->dc_lock);
+               dc_commit_updates_for_stream(dm->dc,
+                                                    full->surface_updates,
+                                                    planes_count,
+                                                    acrtc_state->stream,
+                                                    &full->stream_update,
+                                                    dc_state);
+               mutex_unlock(&dm->dc_lock);
        }
 }
 
@@ -5076,8 +5058,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                                        dc_stream_get_status(dm_new_crtc_state->stream);
 
                        if (!status)
-                               status = dc_state_get_stream_status(dc_state,
-                                                                   dm_new_crtc_state->stream);
+                               status = dc_stream_get_status_from_state(dc_state,
+                                                                        dm_new_crtc_state->stream);
 
                        if (!status)
                                DC_ERR("got no status for stream %p on acrtc%p\n", dm_new_crtc_state->stream, acrtc);
@@ -5086,11 +5068,13 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                }
        }
 
-       /* Handle scaling, underscan, and abm changes*/
+       /* Handle connector state changes */
        for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) {
                struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state);
                struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state);
                struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc);
+               struct dc_surface_update dummy_updates[MAX_SURFACES] = { 0 };
+               struct dc_stream_update stream_update = { 0 };
                struct dc_stream_status *status = NULL;
 
                if (acrtc) {
@@ -5102,37 +5086,48 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                if (!acrtc || drm_atomic_crtc_needs_modeset(new_crtc_state))
                        continue;
 
-
                dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
                dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
 
-               /* Skip anything that is not scaling or underscan changes */
                if (!is_scaling_state_different(dm_new_con_state, dm_old_con_state) &&
                                (dm_new_crtc_state->abm_level == dm_old_crtc_state->abm_level))
                        continue;
 
-               update_stream_scaling_settings(&dm_new_con_state->base.crtc->mode,
-                               dm_new_con_state, (struct dc_stream_state *)dm_new_crtc_state->stream);
+               if (is_scaling_state_different(dm_new_con_state, dm_old_con_state)) {
+                       update_stream_scaling_settings(&dm_new_con_state->base.crtc->mode,
+                                       dm_new_con_state, (struct dc_stream_state *)dm_new_crtc_state->stream);
 
-               if (!dm_new_crtc_state->stream)
-                       continue;
+                       stream_update.src = dm_new_crtc_state->stream->src;
+                       stream_update.dst = dm_new_crtc_state->stream->dst;
+               }
+
+               if (dm_new_crtc_state->abm_level != dm_old_crtc_state->abm_level) {
+                       dm_new_crtc_state->stream->abm_level = dm_new_crtc_state->abm_level;
+
+                       stream_update.abm_level = &dm_new_crtc_state->abm_level;
+               }
 
                status = dc_stream_get_status(dm_new_crtc_state->stream);
                WARN_ON(!status);
                WARN_ON(!status->plane_count);
 
-               dm_new_crtc_state->stream->abm_level = dm_new_crtc_state->abm_level;
+               /*
+                * TODO: DC refuses to perform stream updates without a dc_surface_update.
+                * Here we create an empty update on each plane.
+                * To fix this, DC should permit updating only stream properties.
+                */
+               for (j = 0; j < status->plane_count; j++)
+                       dummy_updates[j].surface = status->plane_states[0];
+
 
-               /*TODO How it works with MPO ?*/
-               if (!commit_planes_to_stream(
-                               dm,
-                               dm->dc,
-                               status->plane_states,
-                               status->plane_count,
-                               dm_new_crtc_state,
-                               to_dm_crtc_state(old_crtc_state),
-                               dc_state))
-                       dm_error("%s: Failed to update stream scaling!\n", __func__);
+               mutex_lock(&dm->dc_lock);
+               dc_commit_updates_for_stream(dm->dc,
+                                                    dummy_updates,
+                                                    status->plane_count,
+                                                    dm_new_crtc_state->stream,
+                                                    &stream_update,
+                                                    dc_state);
+               mutex_unlock(&dm->dc_lock);
        }
 
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
@@ -5183,18 +5178,12 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
        }
        spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
 
+       /* Signal HW programming completion */
+       drm_atomic_helper_commit_hw_done(state);
 
        if (wait_for_vblank)
                drm_atomic_helper_wait_for_flip_done(dev, state);
 
-       /*
-        * FIXME:
-        * Delay hw_done() until flip_done() is signaled. This is to block
-        * another commit from freeing the CRTC state while we're still
-        * waiting on flip_done.
-        */
-       drm_atomic_helper_commit_hw_done(state);
-
        drm_atomic_helper_cleanup_planes(dev, state);
 
        /*
@@ -5387,15 +5376,15 @@ static void reset_freesync_config_for_crtc(
               sizeof(new_crtc_state->vrr_infopacket));
 }
 
-static int dm_update_crtcs_state(struct amdgpu_display_manager *dm,
-                                struct drm_atomic_state *state,
-                                bool enable,
-                                bool *lock_and_validation_needed)
+static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
+                               struct drm_atomic_state *state,
+                               struct drm_crtc *crtc,
+                               struct drm_crtc_state *old_crtc_state,
+                               struct drm_crtc_state *new_crtc_state,
+                               bool enable,
+                               bool *lock_and_validation_needed)
 {
        struct dm_atomic_state *dm_state = NULL;
-       struct drm_crtc *crtc;
-       struct drm_crtc_state *old_crtc_state, *new_crtc_state;
-       int i;
        struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state;
        struct dc_stream_state *new_stream;
        int ret = 0;
@@ -5404,200 +5393,203 @@ static int dm_update_crtcs_state(struct amdgpu_display_manager *dm,
         * TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set
         * update changed items
         */
-       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
-               struct amdgpu_crtc *acrtc = NULL;
-               struct amdgpu_dm_connector *aconnector = NULL;
-               struct drm_connector_state *drm_new_conn_state = NULL, *drm_old_conn_state = NULL;
-               struct dm_connector_state *dm_new_conn_state = NULL, *dm_old_conn_state = NULL;
-               struct drm_plane_state *new_plane_state = NULL;
-
-               new_stream = NULL;
+       struct amdgpu_crtc *acrtc = NULL;
+       struct amdgpu_dm_connector *aconnector = NULL;
+       struct drm_connector_state *drm_new_conn_state = NULL, *drm_old_conn_state = NULL;
+       struct dm_connector_state *dm_new_conn_state = NULL, *dm_old_conn_state = NULL;
+       struct drm_plane_state *new_plane_state = NULL;
 
-               dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
-               dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
-               acrtc = to_amdgpu_crtc(crtc);
+       new_stream = NULL;
 
-               new_plane_state = drm_atomic_get_new_plane_state(state, new_crtc_state->crtc->primary);
+       dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
+       dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
+       acrtc = to_amdgpu_crtc(crtc);
 
-               if (new_crtc_state->enable && new_plane_state && !new_plane_state->fb) {
-                       ret = -EINVAL;
-                       goto fail;
-               }
+       new_plane_state = drm_atomic_get_new_plane_state(state, new_crtc_state->crtc->primary);
 
-               aconnector = amdgpu_dm_find_first_crtc_matching_connector(state, crtc);
+       if (new_crtc_state->enable && new_plane_state && !new_plane_state->fb) {
+               ret = -EINVAL;
+               goto fail;
+       }
 
-               /* TODO This hack should go away */
-               if (aconnector && enable) {
-                       /* Make sure fake sink is created in plug-in scenario */
-                       drm_new_conn_state = drm_atomic_get_new_connector_state(state,
-                                                                   &aconnector->base);
-                       drm_old_conn_state = drm_atomic_get_old_connector_state(state,
-                                                                   &aconnector->base);
+       aconnector = amdgpu_dm_find_first_crtc_matching_connector(state, crtc);
 
-                       if (IS_ERR(drm_new_conn_state)) {
-                               ret = PTR_ERR_OR_ZERO(drm_new_conn_state);
-                               break;
-                       }
+       /* TODO This hack should go away */
+       if (aconnector && enable) {
+               /* Make sure fake sink is created in plug-in scenario */
+               drm_new_conn_state = drm_atomic_get_new_connector_state(state,
+                                                           &aconnector->base);
+               drm_old_conn_state = drm_atomic_get_old_connector_state(state,
+                                                           &aconnector->base);
 
-                       dm_new_conn_state = to_dm_connector_state(drm_new_conn_state);
-                       dm_old_conn_state = to_dm_connector_state(drm_old_conn_state);
+               if (IS_ERR(drm_new_conn_state)) {
+                       ret = PTR_ERR_OR_ZERO(drm_new_conn_state);
+                       goto fail;
+               }
 
-                       new_stream = create_stream_for_sink(aconnector,
-                                                            &new_crtc_state->mode,
-                                                           dm_new_conn_state,
-                                                           dm_old_crtc_state->stream);
+               dm_new_conn_state = to_dm_connector_state(drm_new_conn_state);
+               dm_old_conn_state = to_dm_connector_state(drm_old_conn_state);
 
-                       /*
-                        * we can have no stream on ACTION_SET if a display
-                        * was disconnected during S3, in this case it is not an
-                        * error, the OS will be updated after detection, and
-                        * will do the right thing on next atomic commit
-                        */
+               if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
+                       goto skip_modeset;
 
-                       if (!new_stream) {
-                               DRM_DEBUG_DRIVER("%s: Failed to create new stream for crtc %d\n",
-                                               __func__, acrtc->base.base.id);
-                               break;
-                       }
+               new_stream = create_stream_for_sink(aconnector,
+                                                    &new_crtc_state->mode,
+                                                   dm_new_conn_state,
+                                                   dm_old_crtc_state->stream);
 
-                       dm_new_crtc_state->abm_level = dm_new_conn_state->abm_level;
+               /*
+                * we can have no stream on ACTION_SET if a display
+                * was disconnected during S3, in this case it is not an
+                * error, the OS will be updated after detection, and
+                * will do the right thing on next atomic commit
+                */
 
-                       if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) &&
-                           dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream)) {
-                               new_crtc_state->mode_changed = false;
-                               DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d",
-                                                new_crtc_state->mode_changed);
-                       }
+               if (!new_stream) {
+                       DRM_DEBUG_DRIVER("%s: Failed to create new stream for crtc %d\n",
+                                       __func__, acrtc->base.base.id);
+                       ret = -ENOMEM;
+                       goto fail;
                }
 
-               if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
-                       goto next_crtc;
+               dm_new_crtc_state->abm_level = dm_new_conn_state->abm_level;
 
-               DRM_DEBUG_DRIVER(
-                       "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
-                       "planes_changed:%d, mode_changed:%d,active_changed:%d,"
-                       "connectors_changed:%d\n",
-                       acrtc->crtc_id,
-                       new_crtc_state->enable,
-                       new_crtc_state->active,
-                       new_crtc_state->planes_changed,
-                       new_crtc_state->mode_changed,
-                       new_crtc_state->active_changed,
-                       new_crtc_state->connectors_changed);
+               if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) &&
+                   dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream)) {
+                       new_crtc_state->mode_changed = false;
+                       DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d",
+                                        new_crtc_state->mode_changed);
+               }
+       }
 
-               /* Remove stream for any changed/disabled CRTC */
-               if (!enable) {
+       /* mode_changed flag may get updated above, need to check again */
+       if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
+               goto skip_modeset;
 
-                       if (!dm_old_crtc_state->stream)
-                               goto next_crtc;
+       DRM_DEBUG_DRIVER(
+               "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
+               "planes_changed:%d, mode_changed:%d,active_changed:%d,"
+               "connectors_changed:%d\n",
+               acrtc->crtc_id,
+               new_crtc_state->enable,
+               new_crtc_state->active,
+               new_crtc_state->planes_changed,
+               new_crtc_state->mode_changed,
+               new_crtc_state->active_changed,
+               new_crtc_state->connectors_changed);
 
-                       ret = dm_atomic_get_state(state, &dm_state);
-                       if (ret)
-                               goto fail;
+       /* Remove stream for any changed/disabled CRTC */
+       if (!enable) {
 
-                       DRM_DEBUG_DRIVER("Disabling DRM crtc: %d\n",
-                                       crtc->base.id);
+               if (!dm_old_crtc_state->stream)
+                       goto skip_modeset;
 
-                       /* i.e. reset mode */
-                       if (dc_remove_stream_from_ctx(
-                                       dm->dc,
-                                       dm_state->context,
-                                       dm_old_crtc_state->stream) != DC_OK) {
-                               ret = -EINVAL;
-                               goto fail;
-                       }
+               ret = dm_atomic_get_state(state, &dm_state);
+               if (ret)
+                       goto fail;
 
-                       dc_stream_release(dm_old_crtc_state->stream);
-                       dm_new_crtc_state->stream = NULL;
+               DRM_DEBUG_DRIVER("Disabling DRM crtc: %d\n",
+                               crtc->base.id);
 
-                       reset_freesync_config_for_crtc(dm_new_crtc_state);
+               /* i.e. reset mode */
+               if (dc_remove_stream_from_ctx(
+                               dm->dc,
+                               dm_state->context,
+                               dm_old_crtc_state->stream) != DC_OK) {
+                       ret = -EINVAL;
+                       goto fail;
+               }
 
-                       *lock_and_validation_needed = true;
+               dc_stream_release(dm_old_crtc_state->stream);
+               dm_new_crtc_state->stream = NULL;
 
-               } else {/* Add stream for any updated/enabled CRTC */
-                       /*
-                        * Quick fix to prevent NULL pointer on new_stream when
-                        * added MST connectors not found in existing crtc_state in the chained mode
-                        * TODO: need to dig out the root cause of that
-                        */
-                       if (!aconnector || (!aconnector->dc_sink && aconnector->mst_port))
-                               goto next_crtc;
+               reset_freesync_config_for_crtc(dm_new_crtc_state);
 
-                       if (modereset_required(new_crtc_state))
-                               goto next_crtc;
+               *lock_and_validation_needed = true;
 
-                       if (modeset_required(new_crtc_state, new_stream,
-                                            dm_old_crtc_state->stream)) {
+       } else {/* Add stream for any updated/enabled CRTC */
+               /*
+                * Quick fix to prevent NULL pointer on new_stream when
+                * added MST connectors not found in existing crtc_state in the chained mode
+                * TODO: need to dig out the root cause of that
+                */
+               if (!aconnector || (!aconnector->dc_sink && aconnector->mst_port))
+                       goto skip_modeset;
 
-                               WARN_ON(dm_new_crtc_state->stream);
+               if (modereset_required(new_crtc_state))
+                       goto skip_modeset;
 
-                               ret = dm_atomic_get_state(state, &dm_state);
-                               if (ret)
-                                       goto fail;
+               if (modeset_required(new_crtc_state, new_stream,
+                                    dm_old_crtc_state->stream)) {
 
-                               dm_new_crtc_state->stream = new_stream;
+                       WARN_ON(dm_new_crtc_state->stream);
 
-                               dc_stream_retain(new_stream);
+                       ret = dm_atomic_get_state(state, &dm_state);
+                       if (ret)
+                               goto fail;
 
-                               DRM_DEBUG_DRIVER("Enabling DRM crtc: %d\n",
-                                                       crtc->base.id);
+                       dm_new_crtc_state->stream = new_stream;
 
-                               if (dc_add_stream_to_ctx(
-                                               dm->dc,
-                                               dm_state->context,
-                                               dm_new_crtc_state->stream) != DC_OK) {
-                                       ret = -EINVAL;
-                                       goto fail;
-                               }
+                       dc_stream_retain(new_stream);
 
-                               *lock_and_validation_needed = true;
+                       DRM_DEBUG_DRIVER("Enabling DRM crtc: %d\n",
+                                               crtc->base.id);
+
+                       if (dc_add_stream_to_ctx(
+                                       dm->dc,
+                                       dm_state->context,
+                                       dm_new_crtc_state->stream) != DC_OK) {
+                               ret = -EINVAL;
+                               goto fail;
                        }
+
+                       *lock_and_validation_needed = true;
                }
+       }
 
-next_crtc:
-               /* Release extra reference */
-               if (new_stream)
-                        dc_stream_release(new_stream);
+skip_modeset:
+       /* Release extra reference */
+       if (new_stream)
+                dc_stream_release(new_stream);
 
-               /*
-                * We want to do dc stream updates that do not require a
-                * full modeset below.
-                */
-               if (!(enable && aconnector && new_crtc_state->enable &&
-                     new_crtc_state->active))
-                       continue;
-               /*
-                * Given above conditions, the dc state cannot be NULL because:
-                * 1. We're in the process of enabling CRTCs (just been added
-                *    to the dc context, or already is on the context)
-                * 2. Has a valid connector attached, and
-                * 3. Is currently active and enabled.
-                * => The dc stream state currently exists.
-                */
-               BUG_ON(dm_new_crtc_state->stream == NULL);
+       /*
+        * We want to do dc stream updates that do not require a
+        * full modeset below.
+        */
+       if (!(enable && aconnector && new_crtc_state->enable &&
+             new_crtc_state->active))
+               return 0;
+       /*
+        * Given above conditions, the dc state cannot be NULL because:
+        * 1. We're in the process of enabling CRTCs (just been added
+        *    to the dc context, or already is on the context)
+        * 2. Has a valid connector attached, and
+        * 3. Is currently active and enabled.
+        * => The dc stream state currently exists.
+        */
+       BUG_ON(dm_new_crtc_state->stream == NULL);
 
-               /* Scaling or underscan settings */
-               if (is_scaling_state_different(dm_old_conn_state, dm_new_conn_state))
-                       update_stream_scaling_settings(
-                               &new_crtc_state->mode, dm_new_conn_state, dm_new_crtc_state->stream);
+       /* Scaling or underscan settings */
+       if (is_scaling_state_different(dm_old_conn_state, dm_new_conn_state))
+               update_stream_scaling_settings(
+                       &new_crtc_state->mode, dm_new_conn_state, dm_new_crtc_state->stream);
 
-               /*
-                * Color management settings. We also update color properties
-                * when a modeset is needed, to ensure it gets reprogrammed.
-                */
-               if (dm_new_crtc_state->base.color_mgmt_changed ||
-                   drm_atomic_crtc_needs_modeset(new_crtc_state)) {
-                       ret = amdgpu_dm_set_regamma_lut(dm_new_crtc_state);
-                       if (ret)
-                               goto fail;
-                       amdgpu_dm_set_ctm(dm_new_crtc_state);
-               }
-
-               /* Update Freesync settings. */
-               get_freesync_config_for_crtc(dm_new_crtc_state,
-                                            dm_new_conn_state);
+       /*
+        * Color management settings. We also update color properties
+        * when a modeset is needed, to ensure it gets reprogrammed.
+        */
+       if (dm_new_crtc_state->base.color_mgmt_changed ||
+           drm_atomic_crtc_needs_modeset(new_crtc_state)) {
+               ret = amdgpu_dm_set_regamma_lut(dm_new_crtc_state);
+               if (ret)
+                       goto fail;
+               amdgpu_dm_set_ctm(dm_new_crtc_state);
        }
 
+       /* Update Freesync settings. */
+       get_freesync_config_for_crtc(dm_new_crtc_state,
+                                    dm_new_conn_state);
+
        return ret;
 
 fail:
@@ -5606,145 +5598,141 @@ fail:
        return ret;
 }
 
-static int dm_update_planes_state(struct dc *dc,
-                                 struct drm_atomic_state *state,
-                                 bool enable,
-                                 bool *lock_and_validation_needed)
+static int dm_update_plane_state(struct dc *dc,
+                                struct drm_atomic_state *state,
+                                struct drm_plane *plane,
+                                struct drm_plane_state *old_plane_state,
+                                struct drm_plane_state *new_plane_state,
+                                bool enable,
+                                bool *lock_and_validation_needed)
 {
 
        struct dm_atomic_state *dm_state = NULL;
        struct drm_crtc *new_plane_crtc, *old_plane_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 dm_crtc_state *dm_new_crtc_state, *dm_old_crtc_state;
        struct dm_plane_state *dm_new_plane_state, *dm_old_plane_state;
-       int i ;
        /* TODO return page_flip_needed() function */
        bool pflip_needed  = !state->allow_modeset;
        int ret = 0;
 
 
-       /* Add new planes, in reverse order as DC expectation */
-       for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) {
-               new_plane_crtc = new_plane_state->crtc;
-               old_plane_crtc = old_plane_state->crtc;
-               dm_new_plane_state = to_dm_plane_state(new_plane_state);
-               dm_old_plane_state = to_dm_plane_state(old_plane_state);
+       new_plane_crtc = new_plane_state->crtc;
+       old_plane_crtc = old_plane_state->crtc;
+       dm_new_plane_state = to_dm_plane_state(new_plane_state);
+       dm_old_plane_state = to_dm_plane_state(old_plane_state);
 
-               /*TODO Implement atomic check for cursor plane */
-               if (plane->type == DRM_PLANE_TYPE_CURSOR)
-                       continue;
+       /*TODO Implement atomic check for cursor plane */
+       if (plane->type == DRM_PLANE_TYPE_CURSOR)
+               return 0;
 
-               /* Remove any changed/removed planes */
-               if (!enable) {
-                       if (pflip_needed &&
-                           plane->type != DRM_PLANE_TYPE_OVERLAY)
-                               continue;
+       /* Remove any changed/removed planes */
+       if (!enable) {
+               if (pflip_needed &&
+                   plane->type != DRM_PLANE_TYPE_OVERLAY)
+                       return 0;
 
-                       if (!old_plane_crtc)
-                               continue;
+               if (!old_plane_crtc)
+                       return 0;
 
-                       old_crtc_state = drm_atomic_get_old_crtc_state(
-                                       state, old_plane_crtc);
-                       dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
+               old_crtc_state = drm_atomic_get_old_crtc_state(
+                               state, old_plane_crtc);
+               dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
 
-                       if (!dm_old_crtc_state->stream)
-                               continue;
+               if (!dm_old_crtc_state->stream)
+                       return 0;
 
-                       DRM_DEBUG_ATOMIC("Disabling DRM plane: %d on DRM crtc %d\n",
-                                       plane->base.id, old_plane_crtc->base.id);
+               DRM_DEBUG_ATOMIC("Disabling DRM plane: %d on DRM crtc %d\n",
+                               plane->base.id, old_plane_crtc->base.id);
 
-                       ret = dm_atomic_get_state(state, &dm_state);
-                       if (ret)
-                               return ret;
+               ret = dm_atomic_get_state(state, &dm_state);
+               if (ret)
+                       return ret;
 
-                       if (!dc_remove_plane_from_context(
-                                       dc,
-                                       dm_old_crtc_state->stream,
-                                       dm_old_plane_state->dc_state,
-                                       dm_state->context)) {
+               if (!dc_remove_plane_from_context(
+                               dc,
+                               dm_old_crtc_state->stream,
+                               dm_old_plane_state->dc_state,
+                               dm_state->context)) {
 
-                               ret = EINVAL;
-                               return ret;
-                       }
+                       ret = EINVAL;
+                       return ret;
+               }
 
 
-                       dc_plane_state_release(dm_old_plane_state->dc_state);
-                       dm_new_plane_state->dc_state = NULL;
+               dc_plane_state_release(dm_old_plane_state->dc_state);
+               dm_new_plane_state->dc_state = NULL;
 
-                       *lock_and_validation_needed = true;
+               *lock_and_validation_needed = true;
 
-               } else { /* Add new planes */
-                       struct dc_plane_state *dc_new_plane_state;
+       } else { /* Add new planes */
+               struct dc_plane_state *dc_new_plane_state;
 
-                       if (drm_atomic_plane_disabling(plane->state, new_plane_state))
-                               continue;
+               if (drm_atomic_plane_disabling(plane->state, new_plane_state))
+                       return 0;
 
-                       if (!new_plane_crtc)
-                               continue;
+               if (!new_plane_crtc)
+                       return 0;
 
-                       new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_crtc);
-                       dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
+               new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_crtc);
+               dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
 
-                       if (!dm_new_crtc_state->stream)
-                               continue;
+               if (!dm_new_crtc_state->stream)
+                       return 0;
 
-                       if (pflip_needed &&
-                           plane->type != DRM_PLANE_TYPE_OVERLAY)
-                               continue;
+               if (pflip_needed && plane->type != DRM_PLANE_TYPE_OVERLAY)
+                       return 0;
 
-                       WARN_ON(dm_new_plane_state->dc_state);
+               WARN_ON(dm_new_plane_state->dc_state);
 
-                       dc_new_plane_state = dc_create_plane_state(dc);
-                       if (!dc_new_plane_state)
-                               return -ENOMEM;
+               dc_new_plane_state = dc_create_plane_state(dc);
+               if (!dc_new_plane_state)
+                       return -ENOMEM;
 
-                       DRM_DEBUG_DRIVER("Enabling DRM plane: %d on DRM crtc %d\n",
-                                       plane->base.id, new_plane_crtc->base.id);
+               DRM_DEBUG_DRIVER("Enabling DRM plane: %d on DRM crtc %d\n",
+                               plane->base.id, new_plane_crtc->base.id);
 
-                       ret = fill_plane_attributes(
-                               new_plane_crtc->dev->dev_private,
-                               dc_new_plane_state,
-                               new_plane_state,
-                               new_crtc_state);
-                       if (ret) {
-                               dc_plane_state_release(dc_new_plane_state);
-                               return ret;
-                       }
+               ret = fill_plane_attributes(
+                       new_plane_crtc->dev->dev_private,
+                       dc_new_plane_state,
+                       new_plane_state,
+                       new_crtc_state);
+               if (ret) {
+                       dc_plane_state_release(dc_new_plane_state);
+                       return ret;
+               }
 
-                       ret = dm_atomic_get_state(state, &dm_state);
-                       if (ret) {
-                               dc_plane_state_release(dc_new_plane_state);
-                               return ret;
-                       }
+               ret = dm_atomic_get_state(state, &dm_state);
+               if (ret) {
+                       dc_plane_state_release(dc_new_plane_state);
+                       return ret;
+               }
 
-                       /*
-                        * Any atomic check errors that occur after this will
-                        * not need a release. The plane state will be attached
-                        * to the stream, and therefore part of the atomic
-                        * state. It'll be released when the atomic state is
-                        * cleaned.
-                        */
-                       if (!dc_add_plane_to_context(
-                                       dc,
-                                       dm_new_crtc_state->stream,
-                                       dc_new_plane_state,
-                                       dm_state->context)) {
-
-                               dc_plane_state_release(dc_new_plane_state);
-                               return -EINVAL;
-                       }
+               /*
+                * Any atomic check errors that occur after this will
+                * not need a release. The plane state will be attached
+                * to the stream, and therefore part of the atomic
+                * state. It'll be released when the atomic state is
+                * cleaned.
+                */
+               if (!dc_add_plane_to_context(
+                               dc,
+                               dm_new_crtc_state->stream,
+                               dc_new_plane_state,
+                               dm_state->context)) {
 
-                       dm_new_plane_state->dc_state = dc_new_plane_state;
+                       dc_plane_state_release(dc_new_plane_state);
+                       return -EINVAL;
+               }
 
-                       /* Tell DC to do a full surface update every time there
-                        * is a plane change. Inefficient, but works for now.
-                        */
-                       dm_new_plane_state->dc_state->update_flags.bits.full_update = 1;
+               dm_new_plane_state->dc_state = dc_new_plane_state;
 
-                       *lock_and_validation_needed = true;
-               }
+               /* Tell DC to do a full surface update every time there
+                * is a plane change. Inefficient, but works for now.
+                */
+               dm_new_plane_state->dc_state->update_flags.bits.full_update = 1;
+
+               *lock_and_validation_needed = true;
        }
 
 
@@ -5768,11 +5756,14 @@ dm_determine_update_type_for_commit(struct dc *dc,
        struct dm_crtc_state *new_dm_crtc_state, *old_dm_crtc_state;
        struct dc_stream_status *status = NULL;
 
-       struct dc_surface_update *updates = kzalloc(MAX_SURFACES * sizeof(struct dc_surface_update), GFP_KERNEL);
-       struct dc_plane_state *surface = kzalloc(MAX_SURFACES * sizeof(struct dc_plane_state), GFP_KERNEL);
+       struct dc_surface_update *updates;
+       struct dc_plane_state *surface;
        struct dc_stream_update stream_update;
        enum surface_update_type update_type = UPDATE_TYPE_FAST;
 
+       updates = kcalloc(MAX_SURFACES, sizeof(*updates), GFP_KERNEL);
+       surface = kcalloc(MAX_SURFACES, sizeof(*surface), GFP_KERNEL);
+
        if (!updates || !surface) {
                DRM_ERROR("Plane or surface update failed to allocate");
                /* Set type to FULL to avoid crashing in DC*/
@@ -5841,8 +5832,8 @@ dm_determine_update_type_for_commit(struct dc *dc,
                                        goto cleanup;
                                }
 
-                               status = dc_state_get_stream_status(old_dm_state->context,
-                                                                   new_dm_crtc_state->stream);
+                               status = dc_stream_get_status_from_state(old_dm_state->context,
+                                                                        new_dm_crtc_state->stream);
 
                                update_type = dc_check_update_surfaces_for_stream(dc, updates, num_plane,
                                                                                  &stream_update, status);
@@ -5902,6 +5893,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
        struct drm_connector_state *old_con_state, *new_con_state;
        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;
        enum surface_update_type update_type = UPDATE_TYPE_FAST;
        enum surface_update_type overall_update_type = UPDATE_TYPE_FAST;
 
@@ -5920,7 +5913,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
                if (!drm_atomic_crtc_needs_modeset(new_crtc_state) &&
                    !new_crtc_state->color_mgmt_changed &&
-                   !new_crtc_state->vrr_enabled)
+                   old_crtc_state->vrr_enabled == new_crtc_state->vrr_enabled)
                        continue;
 
                if (!new_crtc_state->enable)
@@ -5936,27 +5929,47 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
        }
 
        /* Remove exiting planes if they are modified */
-       ret = dm_update_planes_state(dc, state, false, &lock_and_validation_needed);
-       if (ret) {
-               goto fail;
+       for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) {
+               ret = dm_update_plane_state(dc, state, plane,
+                                           old_plane_state,
+                                           new_plane_state,
+                                           false,
+                                           &lock_and_validation_needed);
+               if (ret)
+                       goto fail;
        }
 
        /* Disable all crtcs which require disable */
-       ret = dm_update_crtcs_state(&adev->dm, state, false, &lock_and_validation_needed);
-       if (ret) {
-               goto fail;
+       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+               ret = dm_update_crtc_state(&adev->dm, state, crtc,
+                                          old_crtc_state,
+                                          new_crtc_state,
+                                          false,
+                                          &lock_and_validation_needed);
+               if (ret)
+                       goto fail;
        }
 
        /* Enable all crtcs which require enable */
-       ret = dm_update_crtcs_state(&adev->dm, state, true, &lock_and_validation_needed);
-       if (ret) {
-               goto fail;
+       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+               ret = dm_update_crtc_state(&adev->dm, state, crtc,
+                                          old_crtc_state,
+                                          new_crtc_state,
+                                          true,
+                                          &lock_and_validation_needed);
+               if (ret)
+                       goto fail;
        }
 
        /* Add new/modified planes */
-       ret = dm_update_planes_state(dc, state, true, &lock_and_validation_needed);
-       if (ret) {
-               goto fail;
+       for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) {
+               ret = dm_update_plane_state(dc, state, plane,
+                                           old_plane_state,
+                                           new_plane_state,
+                                           true,
+                                           &lock_and_validation_needed);
+               if (ret)
+                       goto fail;
        }
 
        /* Run this here since we want to validate the streams we created */
index 9a7ac58eb18ea702383df1548e7013484b1edf62..cca3e16cda4f1a3c7aa160ad91b8a545a765e285 100644 (file)
@@ -783,6 +783,45 @@ static ssize_t dtn_log_write(
        return size;
 }
 
+/*
+ * Backlight at this moment.  Read only.
+ * As written to display, taking ABM and backlight lut into account.
+ * Ranges from 0x0 to 0x10000 (= 100% PWM)
+ */
+static int current_backlight_read(struct seq_file *m, void *data)
+{
+       struct drm_info_node *node = (struct drm_info_node *)m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct amdgpu_device *adev = dev->dev_private;
+       struct dc *dc = adev->dm.dc;
+       unsigned int backlight = dc_get_current_backlight_pwm(dc);
+
+       seq_printf(m, "0x%x\n", backlight);
+       return 0;
+}
+
+/*
+ * Backlight value that is being approached.  Read only.
+ * As written to display, taking ABM and backlight lut into account.
+ * Ranges from 0x0 to 0x10000 (= 100% PWM)
+ */
+static int target_backlight_read(struct seq_file *m, void *data)
+{
+       struct drm_info_node *node = (struct drm_info_node *)m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct amdgpu_device *adev = dev->dev_private;
+       struct dc *dc = adev->dm.dc;
+       unsigned int backlight = dc_get_target_backlight_pwm(dc);
+
+       seq_printf(m, "0x%x\n", backlight);
+       return 0;
+}
+
+static const struct drm_info_list amdgpu_dm_debugfs_list[] = {
+       {"amdgpu_current_backlight_pwm", &current_backlight_read},
+       {"amdgpu_target_backlight_pwm", &target_backlight_read},
+};
+
 int dtn_debugfs_init(struct amdgpu_device *adev)
 {
        static const struct file_operations dtn_log_fops = {
@@ -793,9 +832,15 @@ int dtn_debugfs_init(struct amdgpu_device *adev)
        };
 
        struct drm_minor *minor = adev->ddev->primary;
-       struct dentry *root = minor->debugfs_root;
+       struct dentry *ent, *root = minor->debugfs_root;
+       int ret;
+
+       ret = amdgpu_debugfs_add_files(adev, amdgpu_dm_debugfs_list,
+                               ARRAY_SIZE(amdgpu_dm_debugfs_list));
+       if (ret)
+               return ret;
 
-       struct dentry *ent = debugfs_create_file(
+       ent = debugfs_create_file(
                "amdgpu_dm_dtn_log",
                0644,
                root,
index 39997d977efb949e06aecb180212b9b15f553c60..e6ab0186955c85af17c1df678996201e48d102af 100644 (file)
@@ -192,7 +192,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
        int bpp = 0;
        int pbn = 0;
 
-       aconnector = stream->sink->priv;
+       aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
        if (!aconnector || !aconnector->mst_port)
                return false;
@@ -205,7 +205,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
        mst_port = aconnector->port;
 
        if (enable) {
-               clock = stream->timing.pix_clk_khz;
+               clock = stream->timing.pix_clk_100hz / 10;
 
                switch (stream->timing.display_color_depth) {
 
@@ -284,7 +284,7 @@ bool dm_helpers_dp_mst_poll_for_allocation_change_trigger(
        struct drm_dp_mst_topology_mgr *mst_mgr;
        int ret;
 
-       aconnector = stream->sink->priv;
+       aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
        if (!aconnector || !aconnector->mst_port)
                return false;
@@ -312,7 +312,7 @@ bool dm_helpers_dp_mst_send_payload_allocation(
        struct drm_dp_mst_port *mst_port;
        int ret;
 
-       aconnector = stream->sink->priv;
+       aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
        if (!aconnector || !aconnector->mst_port)
                return false;
index 1b0d209d836764ee16c4b9159100a52a6753f7b2..748d6ff3e4f3baefacfef45af36f37d6df08c771 100644 (file)
@@ -35,6 +35,8 @@
 
 #include "dc_link_ddc.h"
 
+#include "i2caux_interface.h"
+
 /* #define TRACE_DPCD */
 
 #ifdef TRACE_DPCD
@@ -81,80 +83,24 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
                                  struct drm_dp_aux_msg *msg)
 {
        ssize_t result = 0;
-       enum i2caux_transaction_action action;
-       enum aux_transaction_type type;
+       struct aux_payload payload;
 
        if (WARN_ON(msg->size > 16))
                return -E2BIG;
 
-       switch (msg->request & ~DP_AUX_I2C_MOT) {
-       case DP_AUX_NATIVE_READ:
-               type = AUX_TRANSACTION_TYPE_DP;
-               action = I2CAUX_TRANSACTION_ACTION_DP_READ;
-
-               result = dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service,
-                                             msg->address,
-                                             &msg->reply,
-                                             msg->buffer,
-                                             msg->size,
-                                             type,
-                                             action);
-               break;
-       case DP_AUX_NATIVE_WRITE:
-               type = AUX_TRANSACTION_TYPE_DP;
-               action = I2CAUX_TRANSACTION_ACTION_DP_WRITE;
-
-               dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service,
-                                    msg->address,
-                                    &msg->reply,
-                                    msg->buffer,
-                                    msg->size,
-                                    type,
-                                    action);
-               result = msg->size;
-               break;
-       case DP_AUX_I2C_READ:
-               type = AUX_TRANSACTION_TYPE_I2C;
-               if (msg->request & DP_AUX_I2C_MOT)
-                       action = I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT;
-               else
-                       action = I2CAUX_TRANSACTION_ACTION_I2C_READ;
-
-               result = dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service,
-                                             msg->address,
-                                             &msg->reply,
-                                             msg->buffer,
-                                             msg->size,
-                                             type,
-                                             action);
-               break;
-       case DP_AUX_I2C_WRITE:
-               type = AUX_TRANSACTION_TYPE_I2C;
-               if (msg->request & DP_AUX_I2C_MOT)
-                       action = I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT;
-               else
-                       action = I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
-
-               dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service,
-                                    msg->address,
-                                    &msg->reply,
-                                    msg->buffer,
-                                    msg->size,
-                                    type,
-                                    action);
-               result = msg->size;
-               break;
-       default:
-               return -EINVAL;
-       }
+       payload.address = msg->address;
+       payload.data = msg->buffer;
+       payload.length = msg->size;
+       payload.reply = &msg->reply;
+       payload.i2c_over_aux = (msg->request & DP_AUX_NATIVE_WRITE) == 0;
+       payload.write = (msg->request & DP_AUX_I2C_READ) == 0;
+       payload.mot = (msg->request & DP_AUX_I2C_MOT) != 0;
+       payload.defer_delay = 0;
 
-#ifdef TRACE_DPCD
-       log_dpcd(msg->request,
-                msg->address,
-                msg->buffer,
-                msg->size,
-                r == DDC_RESULT_SUCESSFULL);
-#endif
+       result = dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service, &payload);
+
+       if (payload.write)
+               result = msg->size;
 
        if (result < 0) /* DC doesn't know about kernel error codes */
                result = -EIO;
@@ -191,6 +137,7 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector)
        drm_encoder_cleanup(&amdgpu_encoder->base);
        kfree(amdgpu_encoder);
        drm_connector_cleanup(connector);
+       drm_dp_mst_put_port_malloc(amdgpu_dm_connector->port);
        kfree(amdgpu_dm_connector);
 }
 
@@ -363,7 +310,9 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
        amdgpu_dm_connector_funcs_reset(connector);
 
        DRM_INFO("DM_MST: added connector: %p [id: %d] [master: %p]\n",
-                       aconnector, connector->base.id, aconnector->mst_port);
+                aconnector, connector->base.id, aconnector->mst_port);
+
+       drm_dp_mst_get_port_malloc(port);
 
        DRM_DEBUG_KMS(":%d\n", connector->base.id);
 
@@ -379,12 +328,12 @@ static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
        struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
 
        DRM_INFO("DM_MST: Disabling connector: %p [id: %d] [master: %p]\n",
-                               aconnector, connector->base.id, aconnector->mst_port);
+                aconnector, connector->base.id, aconnector->mst_port);
 
-       aconnector->port = NULL;
        if (aconnector->dc_sink) {
                amdgpu_dm_update_freesync_caps(connector, NULL);
-               dc_link_remove_remote_sink(aconnector->dc_link, aconnector->dc_sink);
+               dc_link_remove_remote_sink(aconnector->dc_link,
+                                          aconnector->dc_sink);
                dc_sink_release(aconnector->dc_sink);
                aconnector->dc_sink = NULL;
        }
@@ -395,14 +344,6 @@ static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
        drm_connector_put(connector);
 }
 
-static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
-{
-       struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr);
-       struct drm_device *dev = master->base.dev;
-
-       drm_kms_helper_hotplug_event(dev);
-}
-
 static void dm_dp_mst_register_connector(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
@@ -419,7 +360,6 @@ static void dm_dp_mst_register_connector(struct drm_connector *connector)
 static const struct drm_dp_mst_topology_cbs dm_mst_cbs = {
        .add_connector = dm_dp_add_mst_connector,
        .destroy_connector = dm_dp_destroy_mst_connector,
-       .hotplug = dm_dp_mst_hotplug,
        .register_connector = dm_dp_mst_register_connector
 };
 
index 9d2d6986b98394be67d038f0d0abdff2ef1cef83..e8e9eebbae3f0d66b7cef395b17c186c19978247 100644 (file)
@@ -559,6 +559,58 @@ void pp_rv_set_pme_wa_enable(struct pp_smu *pp)
        pp_funcs->notify_smu_enable_pwe(pp_handle);
 }
 
+void pp_rv_set_active_display_count(struct pp_smu *pp, int count)
+{
+       const struct dc_context *ctx = pp->dm;
+       struct amdgpu_device *adev = ctx->driver_context;
+       void *pp_handle = adev->powerplay.pp_handle;
+       const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+
+       if (!pp_funcs || !pp_funcs->set_active_display_count)
+               return;
+
+       pp_funcs->set_active_display_count(pp_handle, count);
+}
+
+void pp_rv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int clock)
+{
+       const struct dc_context *ctx = pp->dm;
+       struct amdgpu_device *adev = ctx->driver_context;
+       void *pp_handle = adev->powerplay.pp_handle;
+       const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+
+       if (!pp_funcs || !pp_funcs->set_min_deep_sleep_dcefclk)
+               return;
+
+       pp_funcs->set_min_deep_sleep_dcefclk(pp_handle, clock);
+}
+
+void pp_rv_set_hard_min_dcefclk_by_freq(struct pp_smu *pp, int clock)
+{
+       const struct dc_context *ctx = pp->dm;
+       struct amdgpu_device *adev = ctx->driver_context;
+       void *pp_handle = adev->powerplay.pp_handle;
+       const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+
+       if (!pp_funcs || !pp_funcs->set_hard_min_dcefclk_by_freq)
+               return;
+
+       pp_funcs->set_hard_min_dcefclk_by_freq(pp_handle, clock);
+}
+
+void pp_rv_set_hard_min_fclk_by_freq(struct pp_smu *pp, int mhz)
+{
+       const struct dc_context *ctx = pp->dm;
+       struct amdgpu_device *adev = ctx->driver_context;
+       void *pp_handle = adev->powerplay.pp_handle;
+       const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+
+       if (!pp_funcs || !pp_funcs->set_hard_min_fclk_by_freq)
+               return;
+
+       pp_funcs->set_hard_min_fclk_by_freq(pp_handle, mhz);
+}
+
 void dm_pp_get_funcs_rv(
                struct dc_context *ctx,
                struct pp_smu_funcs_rv *funcs)
@@ -567,4 +619,9 @@ void dm_pp_get_funcs_rv(
        funcs->set_display_requirement = pp_rv_set_display_requirement;
        funcs->set_wm_ranges = pp_rv_set_wm_ranges;
        funcs->set_pme_wa_enable = pp_rv_set_pme_wa_enable;
+       funcs->set_display_count = pp_rv_set_active_display_count;
+       funcs->set_min_deep_sleep_dcfclk = pp_rv_set_min_deep_sleep_dcfclk;
+       funcs->set_hard_min_dcfclk_by_freq = pp_rv_set_hard_min_dcefclk_by_freq;
+       funcs->set_hard_min_fclk_by_freq = pp_rv_set_hard_min_fclk_by_freq;
 }
+
index aed538a4d1bace016fb37526d099656227b81348..b8ddb4acccdb438ea41cb2533000b283c6945b93 100644 (file)
@@ -23,7 +23,7 @@
 # Makefile for Display Core (dc) component.
 #
 
-DC_LIBS = basics bios calcs dce gpio i2caux irq virtual
+DC_LIBS = basics bios calcs dce gpio irq virtual
 
 ifdef CONFIG_DRM_AMD_DC_DCN1_0
 DC_LIBS += dcn10 dml
@@ -41,7 +41,8 @@ AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LI
 include $(AMD_DC)
 
 DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_sink.o \
-dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o
+dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o \
+dc_vm_helper.o
 
 AMD_DISPLAY_CORE = $(addprefix $(AMDDALPATH)/dc/core/,$(DISPLAY_CORE))
 
index c2ab026aee91f31d22970d29c169f61ef0eff8a0..a4c97d32e7512baee5da78f452d4178bec702615 100644 (file)
@@ -835,18 +835,6 @@ static enum bp_result bios_parser_enable_crtc(
        return bp->cmd_tbl.enable_crtc(bp, id, enable);
 }
 
-static enum bp_result bios_parser_crtc_source_select(
-       struct dc_bios *dcb,
-       struct bp_crtc_source_select *bp_params)
-{
-       struct bios_parser *bp = BP_FROM_DCB(dcb);
-
-       if (!bp->cmd_tbl.select_crtc_source)
-               return BP_RESULT_FAILURE;
-
-       return bp->cmd_tbl.select_crtc_source(bp, bp_params);
-}
-
 static enum bp_result bios_parser_enable_disp_power_gating(
        struct dc_bios *dcb,
        enum controller_id controller_id,
@@ -2842,8 +2830,6 @@ static const struct dc_vbios_funcs vbios_funcs = {
 
        .program_crtc_timing = bios_parser_program_crtc_timing, /* still use.  should probably retire and program directly */
 
-       .crtc_source_select = bios_parser_crtc_source_select,  /* still use.  should probably retire and program directly */
-
        .program_display_engine_pll = bios_parser_program_display_engine_pll,
 
        .enable_disp_power_gating = bios_parser_enable_disp_power_gating,
index c513ab6f38435b9281ec0f1799b044d3ed541115..a1c56f29cfeb2fe745fe97550288e77b1dfccc6b 100644 (file)
@@ -1083,18 +1083,6 @@ static enum bp_result bios_parser_enable_crtc(
        return bp->cmd_tbl.enable_crtc(bp, id, enable);
 }
 
-static enum bp_result bios_parser_crtc_source_select(
-       struct dc_bios *dcb,
-       struct bp_crtc_source_select *bp_params)
-{
-       struct bios_parser *bp = BP_FROM_DCB(dcb);
-
-       if (!bp->cmd_tbl.select_crtc_source)
-               return BP_RESULT_FAILURE;
-
-       return bp->cmd_tbl.select_crtc_source(bp, bp_params);
-}
-
 static enum bp_result bios_parser_enable_disp_power_gating(
        struct dc_bios *dcb,
        enum controller_id controller_id,
@@ -1899,8 +1887,6 @@ static const struct dc_vbios_funcs vbios_funcs = {
 
        .is_accelerated_mode = bios_parser_is_accelerated_mode,
 
-       .is_active_display = bios_is_active_display,
-
        .set_scratch_critical_state = bios_parser_set_scratch_critical_state,
 
 
@@ -1917,8 +1903,6 @@ static const struct dc_vbios_funcs vbios_funcs = {
 
        .program_crtc_timing = bios_parser_program_crtc_timing,
 
-       .crtc_source_select = bios_parser_crtc_source_select,
-
        .enable_disp_power_gating = bios_parser_enable_disp_power_gating,
 
        .bios_parser_destroy = firmware_parser_destroy,
index fdda8aa8e3031f7f667da7e931d34de8f849f847..fce46ab54c5436e92bd8175835e9edca199f256b 100644 (file)
@@ -83,101 +83,7 @@ uint32_t bios_get_vga_enabled_displays(
 {
        uint32_t active_disp = 1;
 
-       if (bios->regs->BIOS_SCRATCH_3) /*follow up with other asic, todo*/
-               active_disp = REG_READ(BIOS_SCRATCH_3) & 0XFFFF;
+       active_disp = REG_READ(BIOS_SCRATCH_3) & 0XFFFF;
        return active_disp;
 }
 
-bool bios_is_active_display(
-               struct dc_bios *bios,
-               enum signal_type signal,
-               const struct connector_device_tag_info *device_tag)
-{
-       uint32_t active = 0;
-       uint32_t connected = 0;
-       uint32_t bios_scratch_0 = 0;
-       uint32_t bios_scratch_3 = 0;
-
-       switch (signal) {
-       case SIGNAL_TYPE_DVI_SINGLE_LINK:
-       case SIGNAL_TYPE_DVI_DUAL_LINK:
-       case SIGNAL_TYPE_HDMI_TYPE_A:
-       case SIGNAL_TYPE_DISPLAY_PORT:
-       case SIGNAL_TYPE_DISPLAY_PORT_MST:
-               {
-                       if (device_tag->dev_id.device_type == DEVICE_TYPE_DFP) {
-                               switch (device_tag->dev_id.enum_id)     {
-                               case 1:
-                                       {
-                                               active    = ATOM_S3_DFP1_ACTIVE;
-                                               connected = 0x0008;     //ATOM_DISPLAY_DFP1_CONNECT
-                                       }
-                                       break;
-
-                               case 2:
-                                       {
-                                               active    = ATOM_S3_DFP2_ACTIVE;
-                                               connected = 0x0080; //ATOM_DISPLAY_DFP2_CONNECT
-                                       }
-                                       break;
-
-                               case 3:
-                                       {
-                                               active    = ATOM_S3_DFP3_ACTIVE;
-                                               connected = 0x0200; //ATOM_DISPLAY_DFP3_CONNECT
-                                       }
-                                       break;
-
-                               case 4:
-                                       {
-                                               active    = ATOM_S3_DFP4_ACTIVE;
-                                               connected = 0x0400;     //ATOM_DISPLAY_DFP4_CONNECT
-                                       }
-                                       break;
-
-                               case 5:
-                                       {
-                                               active    = ATOM_S3_DFP5_ACTIVE;
-                                               connected = 0x0800; //ATOM_DISPLAY_DFP5_CONNECT
-                                       }
-                                       break;
-
-                               case 6:
-                                       {
-                                               active    = ATOM_S3_DFP6_ACTIVE;
-                                               connected = 0x0040; //ATOM_DISPLAY_DFP6_CONNECT
-                                       }
-                                       break;
-
-                               default:
-                                       break;
-                               }
-                               }
-                       }
-                       break;
-
-       case SIGNAL_TYPE_LVDS:
-       case SIGNAL_TYPE_EDP:
-               {
-                       active    = ATOM_S3_LCD1_ACTIVE;
-                       connected = 0x0002;     //ATOM_DISPLAY_LCD1_CONNECT
-               }
-               break;
-
-       default:
-               break;
-       }
-
-
-       if (bios->regs->BIOS_SCRATCH_0) /*follow up with other asic, todo*/
-               bios_scratch_0 = REG_READ(BIOS_SCRATCH_0);
-       if (bios->regs->BIOS_SCRATCH_3) /*follow up with other asic, todo*/
-               bios_scratch_3 = REG_READ(BIOS_SCRATCH_3);
-
-       bios_scratch_3 &= ATOM_S3_DEVICE_ACTIVE_MASK;
-       if ((active & bios_scratch_3) && (connected & bios_scratch_0))
-               return true;
-
-       return false;
-}
-
index f33cac2147e32cc182d33aefabc09422be1af28b..75a29e68fb2782ad667f858b4f235aeccdcc8ace 100644 (file)
@@ -35,10 +35,6 @@ bool bios_is_accelerated_mode(struct dc_bios *bios);
 void bios_set_scratch_acc_mode_change(struct dc_bios *bios);
 void bios_set_scratch_critical_state(struct dc_bios *bios, bool state);
 uint32_t bios_get_vga_enabled_displays(struct dc_bios *bios);
-bool bios_is_active_display(
-       struct dc_bios *bios,
-       enum signal_type signal,
-       const struct connector_device_tag_info *device_tag);
 
 #define GET_IMAGE(type, offset) ((type *) bios_get_image(&bp->base, offset, sizeof(type)))
 
index 2bd7cd97e00dc55a64f81a3681dcf2e058cde501..5815983caaf80b01e3cbd595969f41e5dda077ee 100644 (file)
@@ -55,7 +55,6 @@ static void init_adjust_display_pll(struct bios_parser *bp);
 static void init_dac_encoder_control(struct bios_parser *bp);
 static void init_dac_output_control(struct bios_parser *bp);
 static void init_set_crtc_timing(struct bios_parser *bp);
-static void init_select_crtc_source(struct bios_parser *bp);
 static void init_enable_crtc(struct bios_parser *bp);
 static void init_enable_crtc_mem_req(struct bios_parser *bp);
 static void init_external_encoder_control(struct bios_parser *bp);
@@ -73,7 +72,6 @@ void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp)
        init_dac_encoder_control(bp);
        init_dac_output_control(bp);
        init_set_crtc_timing(bp);
-       init_select_crtc_source(bp);
        init_enable_crtc(bp);
        init_enable_crtc_mem_req(bp);
        init_program_clock(bp);
@@ -964,9 +962,9 @@ static enum bp_result set_pixel_clock_v3(
        allocation.sPCLKInput.ucPostDiv =
                        (uint8_t)bp_params->pixel_clock_post_divider;
 
-       /* We need to convert from KHz units into 10KHz units */
+       /* We need to convert from 100Hz units into 10KHz units */
        allocation.sPCLKInput.usPixelClock =
-                       cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10));
+                       cpu_to_le16((uint16_t)(bp_params->target_pixel_clock_100hz / 100));
 
        params = (PIXEL_CLOCK_PARAMETERS_V3 *)&allocation.sPCLKInput;
        params->ucTransmitterId =
@@ -1042,9 +1040,9 @@ static enum bp_result set_pixel_clock_v5(
                                (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
                                                bp_params->signal_type, false);
 
-               /* We need to convert from KHz units into 10KHz units */
+               /* We need to convert from 100Hz units into 10KHz units */
                clk.sPCLKInput.usPixelClock =
-                               cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10));
+                               cpu_to_le16((uint16_t)(bp_params->target_pixel_clock_100hz / 100));
 
                if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
                        clk.sPCLKInput.ucMiscInfo |=
@@ -1118,9 +1116,9 @@ static enum bp_result set_pixel_clock_v6(
                                (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(
                                                bp_params->signal_type, false);
 
-               /* We need to convert from KHz units into 10KHz units */
+               /* We need to convert from 100 Hz units into 10KHz units */
                clk.sPCLKInput.ulCrtcPclkFreq.ulPixelClock =
-                               cpu_to_le32(bp_params->target_pixel_clock / 10);
+                               cpu_to_le32(bp_params->target_pixel_clock_100hz / 100);
 
                if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) {
                        clk.sPCLKInput.ucMiscInfo |=
@@ -1182,8 +1180,7 @@ static enum bp_result set_pixel_clock_v7(
                clk.ucTransmitterID = bp->cmd_helper->encoder_id_to_atom(dal_graphics_object_id_get_encoder_id(bp_params->encoder_object_id));
                clk.ucEncoderMode = (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(bp_params->signal_type, false);
 
-               /* We need to convert from KHz units into 10KHz units */
-               clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock * 10);
+               clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock_100hz);
 
                clk.ucDeepColorRatio = (uint8_t) bp->cmd_helper->transmitter_color_depth_to_atom(bp_params->color_depth);
 
@@ -1896,120 +1893,6 @@ static enum bp_result set_crtc_using_dtd_timing_v3(
        return result;
 }
 
-/*******************************************************************************
- ********************************************************************************
- **
- **                  SELECT CRTC SOURCE
- **
- ********************************************************************************
- *******************************************************************************/
-
-static enum bp_result select_crtc_source_v2(
-       struct bios_parser *bp,
-       struct bp_crtc_source_select *bp_params);
-static enum bp_result select_crtc_source_v3(
-       struct bios_parser *bp,
-       struct bp_crtc_source_select *bp_params);
-
-static void init_select_crtc_source(struct bios_parser *bp)
-{
-       switch (BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source)) {
-       case 2:
-               bp->cmd_tbl.select_crtc_source = select_crtc_source_v2;
-               break;
-       case 3:
-               bp->cmd_tbl.select_crtc_source = select_crtc_source_v3;
-               break;
-       default:
-               dm_output_to_console("Don't select_crtc_source enable_crtc for v%d\n",
-                        BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source));
-               bp->cmd_tbl.select_crtc_source = NULL;
-               break;
-       }
-}
-
-static enum bp_result select_crtc_source_v2(
-       struct bios_parser *bp,
-       struct bp_crtc_source_select *bp_params)
-{
-       enum bp_result result = BP_RESULT_FAILURE;
-       SELECT_CRTC_SOURCE_PARAMETERS_V2 params;
-       uint8_t atom_controller_id;
-       uint32_t atom_engine_id;
-       enum signal_type s = bp_params->signal;
-
-       memset(&params, 0, sizeof(params));
-
-       /* set controller id */
-       if (bp->cmd_helper->controller_id_to_atom(
-                       bp_params->controller_id, &atom_controller_id))
-               params.ucCRTC = atom_controller_id;
-       else
-               return BP_RESULT_FAILURE;
-
-       /* set encoder id */
-       if (bp->cmd_helper->engine_bp_to_atom(
-                       bp_params->engine_id, &atom_engine_id))
-               params.ucEncoderID = (uint8_t)atom_engine_id;
-       else
-               return BP_RESULT_FAILURE;
-
-       if (SIGNAL_TYPE_EDP == s ||
-                       (SIGNAL_TYPE_DISPLAY_PORT == s &&
-                                       SIGNAL_TYPE_LVDS == bp_params->sink_signal))
-               s = SIGNAL_TYPE_LVDS;
-
-       params.ucEncodeMode =
-                       (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
-                                       s, bp_params->enable_dp_audio);
-
-       if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
-               result = BP_RESULT_OK;
-
-       return result;
-}
-
-static enum bp_result select_crtc_source_v3(
-       struct bios_parser *bp,
-       struct bp_crtc_source_select *bp_params)
-{
-       bool result = BP_RESULT_FAILURE;
-       SELECT_CRTC_SOURCE_PARAMETERS_V3 params;
-       uint8_t atom_controller_id;
-       uint32_t atom_engine_id;
-       enum signal_type s = bp_params->signal;
-
-       memset(&params, 0, sizeof(params));
-
-       if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id,
-                       &atom_controller_id))
-               params.ucCRTC = atom_controller_id;
-       else
-               return result;
-
-       if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id,
-                       &atom_engine_id))
-               params.ucEncoderID = (uint8_t)atom_engine_id;
-       else
-               return result;
-
-       if (SIGNAL_TYPE_EDP == s ||
-                       (SIGNAL_TYPE_DISPLAY_PORT == s &&
-                                       SIGNAL_TYPE_LVDS == bp_params->sink_signal))
-               s = SIGNAL_TYPE_LVDS;
-
-       params.ucEncodeMode =
-                       bp->cmd_helper->encoder_mode_bp_to_atom(
-                                       s, bp_params->enable_dp_audio);
-       /* Needed for VBIOS Random Spatial Dithering feature */
-       params.ucDstBpc = (uint8_t)(bp_params->display_output_bit_depth);
-
-       if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
-               result = BP_RESULT_OK;
-
-       return result;
-}
-
 /*******************************************************************************
  ********************************************************************************
  **
@@ -2164,7 +2047,7 @@ static enum bp_result program_clock_v5(
        /* We need to convert from KHz units into 10KHz units */
        params.sPCLKInput.ucPpll = (uint8_t) atom_pll_id;
        params.sPCLKInput.usPixelClock =
-                       cpu_to_le16((uint16_t) (bp_params->target_pixel_clock / 10));
+                       cpu_to_le16((uint16_t) (bp_params->target_pixel_clock_100hz / 100));
        params.sPCLKInput.ucCRTC = (uint8_t) ATOM_CRTC_INVALID;
 
        if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
@@ -2196,7 +2079,7 @@ static enum bp_result program_clock_v6(
        /* We need to convert from KHz units into 10KHz units */
        params.sPCLKInput.ucPpll = (uint8_t)atom_pll_id;
        params.sPCLKInput.ulDispEngClkFreq =
-                       cpu_to_le32(bp_params->target_pixel_clock / 10);
+                       cpu_to_le32(bp_params->target_pixel_clock_100hz / 100);
 
        if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
                params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
index 94f3d43a7471797d1af0a0402a7f29124ca03bd6..ad533775e72428c2ff1c3c97756823d4d037de12 100644 (file)
@@ -71,9 +71,6 @@ struct cmd_tbl {
        enum bp_result (*set_crtc_timing)(
                struct bios_parser *bp,
                struct bp_hw_crtc_timing_parameters *bp_params);
-       enum bp_result (*select_crtc_source)(
-               struct bios_parser *bp,
-               struct bp_crtc_source_select *bp_params);
        enum bp_result (*enable_crtc)(
                struct bios_parser *bp,
                enum controller_id controller_id,
index 2b5dc499a35edafd6cc4f37b37d9d16ed69ff6c6..bb2e8105e6aba12229a87e51cbafeafc2d15b42b 100644 (file)
@@ -301,17 +301,17 @@ static enum bp_result set_pixel_clock_v7(
                        cmd_helper->encoder_mode_bp_to_atom(
                                bp_params->signal_type, false);
 
-               /* We need to convert from KHz units into 10KHz units */
-               clk.pixclk_100hz = cpu_to_le32(bp_params->target_pixel_clock *
-                               10);
+               clk.pixclk_100hz = cpu_to_le32(bp_params->target_pixel_clock_100hz);
 
                clk.deep_color_ratio =
                        (uint8_t) bp->cmd_helper->
                                transmitter_color_depth_to_atom(
                                        bp_params->color_depth);
-               DC_LOG_BIOS("%s:program display clock = %d"\
-                               "colorDepth = %d\n", __func__,\
-                               bp_params->target_pixel_clock, bp_params->color_depth);
+
+               DC_LOG_BIOS("%s:program display clock = %d, tg = %d, pll = %d, "\
+                               "colorDepth = %d\n", __func__,
+                               bp_params->target_pixel_clock_100hz, (int)controller_id,
+                               pll_id, bp_params->color_depth);
 
                if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
                        clk.miscinfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL;
@@ -460,75 +460,6 @@ static enum bp_result set_crtc_using_dtd_timing_v3(
        return result;
 }
 
-/******************************************************************************
- ******************************************************************************
- **
- **                  SELECT CRTC SOURCE
- **
- ******************************************************************************
- *****************************************************************************/
-
-
-static enum bp_result select_crtc_source_v3(
-       struct bios_parser *bp,
-       struct bp_crtc_source_select *bp_params);
-
-static void init_select_crtc_source(struct bios_parser *bp)
-{
-       switch (BIOS_CMD_TABLE_PARA_REVISION(selectcrtc_source)) {
-       case 3:
-               bp->cmd_tbl.select_crtc_source = select_crtc_source_v3;
-               break;
-       default:
-               dm_output_to_console("Don't select_crtc_source enable_crtc for v%d\n",
-                        BIOS_CMD_TABLE_PARA_REVISION(selectcrtc_source));
-               bp->cmd_tbl.select_crtc_source = NULL;
-               break;
-       }
-}
-
-
-static enum bp_result select_crtc_source_v3(
-       struct bios_parser *bp,
-       struct bp_crtc_source_select *bp_params)
-{
-       bool result = BP_RESULT_FAILURE;
-       struct select_crtc_source_parameters_v2_3 params;
-       uint8_t atom_controller_id;
-       uint32_t atom_engine_id;
-       enum signal_type s = bp_params->signal;
-
-       memset(&params, 0, sizeof(params));
-
-       if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id,
-                       &atom_controller_id))
-               params.crtc_id = atom_controller_id;
-       else
-               return result;
-
-       if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id,
-                       &atom_engine_id))
-               params.encoder_id = (uint8_t)atom_engine_id;
-       else
-               return result;
-
-       if (s == SIGNAL_TYPE_EDP ||
-               (s == SIGNAL_TYPE_DISPLAY_PORT && bp_params->sink_signal ==
-                                                       SIGNAL_TYPE_LVDS))
-               s = SIGNAL_TYPE_LVDS;
-
-       params.encode_mode =
-                       bp->cmd_helper->encoder_mode_bp_to_atom(
-                                       s, bp_params->enable_dp_audio);
-       /* Needed for VBIOS Random Spatial Dithering feature */
-       params.dst_bpc = (uint8_t)(bp_params->display_output_bit_depth);
-
-       if (EXEC_BIOS_CMD_TABLE(selectcrtc_source, params))
-               result = BP_RESULT_OK;
-
-       return result;
-}
-
 /******************************************************************************
  ******************************************************************************
  **
@@ -808,7 +739,6 @@ void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp)
 
        init_set_crtc_timing(bp);
 
-       init_select_crtc_source(bp);
        init_enable_crtc(bp);
 
        init_external_encoder_control(bp);
index ec1c0c9f3f1d006e409e90a75f49900253df1d88..7a2af24dfe605cd752b0139f652d3061ee825d55 100644 (file)
@@ -71,9 +71,6 @@ struct cmd_tbl {
        enum bp_result (*set_crtc_timing)(
                struct bios_parser *bp,
                struct bp_hw_crtc_timing_parameters *bp_params);
-       enum bp_result (*select_crtc_source)(
-               struct bios_parser *bp,
-               struct bp_crtc_source_select *bp_params);
        enum bp_result (*enable_crtc)(
                struct bios_parser *bp,
                enum controller_id controller_id,
index 95f332ee3e7e6e3858294d485c03c23c1c25f613..dc85a3c088afd5624b121f63d673da1cd012d0dc 100644 (file)
@@ -30,7 +30,7 @@ else ifneq ($(call cc-option, -mstack-alignment=16),)
        cc_stack_align := -mstack-alignment=16
 endif
 
-calcs_ccflags := -mhard-float -msse $(cc_stack_align)
+calcs_ccflags := -mhard-float -msse -msse2 $(cc_stack_align)
 
 CFLAGS_dcn_calcs.o := $(calcs_ccflags)
 CFLAGS_dcn_calc_auto.o := $(calcs_ccflags)
index 9ebe30ba4dabfdf9b2559e7677983bb373d66adb..f3aa7b53d2aa81b857eaeede8496d91af5b2e228 100644 (file)
@@ -2792,7 +2792,7 @@ static void populate_initial_data(
                data->lpt_en[num_displays + 4] = false;
                data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.h_total);
                data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_total);
-               data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->timing.pix_clk_khz, 1000);
+               data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->timing.pix_clk_100hz, 10000);
                data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.viewport.width);
                data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4];
                data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.viewport.height);
@@ -2881,7 +2881,7 @@ static void populate_initial_data(
 
        /* Pipes without underlay after */
        for (i = 0; i < pipe_count; i++) {
-               unsigned int pixel_clock_khz;
+               unsigned int pixel_clock_100hz;
                if (!pipe[i].stream || pipe[i].bottom_pipe)
                        continue;
 
@@ -2890,10 +2890,10 @@ static void populate_initial_data(
                data->lpt_en[num_displays + 4] = false;
                data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.h_total);
                data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_total);
-               pixel_clock_khz = pipe[i].stream->timing.pix_clk_khz;
+               pixel_clock_100hz = pipe[i].stream->timing.pix_clk_100hz;
                if (pipe[i].stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
-                       pixel_clock_khz *= 2;
-               data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pixel_clock_khz, 1000);
+                       pixel_clock_100hz *= 2;
+               data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pixel_clock_100hz, 10000);
                if (pipe[i].plane_state) {
                        data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.viewport.width);
                        data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4];
index d0fc54f8fb1c22d87967f7bc02d4d4f923f899b0..7d102ac0d61bf71489c463b60bc7720a55142ccd 100644 (file)
@@ -797,9 +797,40 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v)
                                else {
                                        v->maximum_vstartup = v->v_sync_plus_back_porch[k] - 1.0;
                                }
-                               v->line_times_for_prefetch[k] = v->maximum_vstartup - v->urgent_latency / (v->htotal[k] / v->pixel_clock[k]) - (v->time_calc + v->time_setup) / (v->htotal[k] / v->pixel_clock[k]) - (v->dst_y_after_scaler + v->dst_x_after_scaler / v->htotal[k]);
-                               v->line_times_for_prefetch[k] =dcn_bw_floor2(4.0 * (v->line_times_for_prefetch[k] + 0.125), 1.0) / 4;
-                               v->prefetch_bw[k] = (v->meta_pte_bytes_per_frame[k] + 2.0 * v->meta_row_bytes[k] + 2.0 * v->dpte_bytes_per_row[k] + v->prefetch_lines_y[k] * v->swath_width_yper_state[i][j][k] *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + v->prefetch_lines_c[k] * v->swath_width_yper_state[i][j][k] / 2.0 *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0)) / (v->line_times_for_prefetch[k] * v->htotal[k] / v->pixel_clock[k]);
+
+                               do {
+                                       v->line_times_for_prefetch[k] = v->maximum_vstartup - v->urgent_latency / (v->htotal[k] / v->pixel_clock[k]) - (v->time_calc + v->time_setup) / (v->htotal[k] / v->pixel_clock[k]) - (v->dst_y_after_scaler + v->dst_x_after_scaler / v->htotal[k]);
+                                       v->line_times_for_prefetch[k] =dcn_bw_floor2(4.0 * (v->line_times_for_prefetch[k] + 0.125), 1.0) / 4;
+                                       v->prefetch_bw[k] = (v->meta_pte_bytes_per_frame[k] + 2.0 * v->meta_row_bytes[k] + 2.0 * v->dpte_bytes_per_row[k] + v->prefetch_lines_y[k] * v->swath_width_yper_state[i][j][k] *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + v->prefetch_lines_c[k] * v->swath_width_yper_state[i][j][k] / 2.0 *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0)) / (v->line_times_for_prefetch[k] * v->htotal[k] / v->pixel_clock[k]);
+
+                                       if (v->pte_enable == dcn_bw_yes && v->dcc_enable[k] == dcn_bw_yes) {
+                                               v->time_for_meta_pte_without_immediate_flip = dcn_bw_max3(
+                                                               v->meta_pte_bytes_frame[k] / v->prefetch_bandwidth[k],
+                                                               v->extra_latency,
+                                                               v->htotal[k] / v->pixel_clock[k] / 4.0);
+                                       } else {
+                                               v->time_for_meta_pte_without_immediate_flip = v->htotal[k] / v->pixel_clock[k] / 4.0;
+                                       }
+
+                                       if (v->pte_enable == dcn_bw_yes || v->dcc_enable[k] == dcn_bw_yes) {
+                                               v->time_for_meta_and_dpte_row_without_immediate_flip = dcn_bw_max3((
+                                                               v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) / v->prefetch_bandwidth[k],
+                                                               v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_without_immediate_flip,
+                                                               v->extra_latency);
+                                       } else {
+                                               v->time_for_meta_and_dpte_row_without_immediate_flip = dcn_bw_max2(
+                                                               v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_without_immediate_flip,
+                                                               v->extra_latency - v->time_for_meta_pte_with_immediate_flip);
+                                       }
+
+                                       v->lines_for_meta_pte_without_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_pte_without_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4;
+                                       v->lines_for_meta_and_dpte_row_without_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_and_dpte_row_without_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4;
+                                       v->maximum_vstartup = v->maximum_vstartup - 1;
+
+                                       if (v->lines_for_meta_pte_without_immediate_flip[k] < 8.0 && v->lines_for_meta_and_dpte_row_without_immediate_flip[k] < 16.0)
+                                               break;
+
+                               } while(1);
                        }
                        v->bw_available_for_immediate_flip = v->return_bw_per_state[i];
                        for (k = 0; k <= v->number_of_active_planes - 1; k++) {
@@ -814,24 +845,18 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v)
                        for (k = 0; k <= v->number_of_active_planes - 1; k++) {
                                if (v->pte_enable == dcn_bw_yes && v->dcc_enable[k] == dcn_bw_yes) {
                                        v->time_for_meta_pte_with_immediate_flip =dcn_bw_max5(v->meta_pte_bytes_per_frame[k] / v->prefetch_bw[k], v->meta_pte_bytes_per_frame[k] * v->total_immediate_flip_bytes[k] / (v->bw_available_for_immediate_flip * (v->meta_pte_bytes_per_frame[k] + v->meta_row_bytes[k] + v->dpte_bytes_per_row[k])), v->extra_latency, v->urgent_latency, v->htotal[k] / v->pixel_clock[k] / 4.0);
-                                       v->time_for_meta_pte_without_immediate_flip =dcn_bw_max3(v->meta_pte_bytes_per_frame[k] / v->prefetch_bw[k], v->extra_latency, v->htotal[k] / v->pixel_clock[k] / 4.0);
                                }
                                else {
                                        v->time_for_meta_pte_with_immediate_flip = v->htotal[k] / v->pixel_clock[k] / 4.0;
-                                       v->time_for_meta_pte_without_immediate_flip = v->htotal[k] / v->pixel_clock[k] / 4.0;
                                }
                                if (v->pte_enable == dcn_bw_yes || v->dcc_enable[k] == dcn_bw_yes) {
                                        v->time_for_meta_and_dpte_row_with_immediate_flip =dcn_bw_max5((v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) / v->prefetch_bw[k], (v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) * v->total_immediate_flip_bytes[k] / (v->bw_available_for_immediate_flip * (v->meta_pte_bytes_per_frame[k] + v->meta_row_bytes[k] + v->dpte_bytes_per_row[k])), v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_with_immediate_flip, v->extra_latency, 2.0 * v->urgent_latency);
-                                       v->time_for_meta_and_dpte_row_without_immediate_flip =dcn_bw_max3((v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) / v->prefetch_bw[k], v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_without_immediate_flip, v->extra_latency);
                                }
                                else {
                                        v->time_for_meta_and_dpte_row_with_immediate_flip =dcn_bw_max2(v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_with_immediate_flip, v->extra_latency - v->time_for_meta_pte_with_immediate_flip);
-                                       v->time_for_meta_and_dpte_row_without_immediate_flip =dcn_bw_max2(v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_without_immediate_flip, v->extra_latency - v->time_for_meta_pte_without_immediate_flip);
                                }
                                v->lines_for_meta_pte_with_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_pte_with_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4;
-                               v->lines_for_meta_pte_without_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_pte_without_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4;
                                v->lines_for_meta_and_dpte_row_with_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_and_dpte_row_with_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4;
-                               v->lines_for_meta_and_dpte_row_without_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_and_dpte_row_without_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4;
                                v->line_times_to_request_prefetch_pixel_data_with_immediate_flip = v->line_times_for_prefetch[k] - v->lines_for_meta_pte_with_immediate_flip[k] - v->lines_for_meta_and_dpte_row_with_immediate_flip[k];
                                v->line_times_to_request_prefetch_pixel_data_without_immediate_flip = v->line_times_for_prefetch[k] - v->lines_for_meta_pte_without_immediate_flip[k] - v->lines_for_meta_and_dpte_row_without_immediate_flip[k];
                                if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip > 0.0) {
index 43e4a2be0fa677f9630799826c3fcb2b6adae477..12d1842079ae5e3902d2fe7ea9719a7f35ebd2ef 100644 (file)
@@ -290,41 +290,34 @@ static void pipe_ctx_to_e2e_pipe_params (
        switch (pipe->plane_state->tiling_info.gfx9.swizzle) {
        /* for 4/8/16 high tiles */
        case DC_SW_LINEAR:
-               input->src.is_display_sw = 1;
                input->src.macro_tile_size = dm_4k_tile;
                break;
        case DC_SW_4KB_S:
        case DC_SW_4KB_S_X:
-               input->src.is_display_sw = 0;
                input->src.macro_tile_size = dm_4k_tile;
                break;
        case DC_SW_64KB_S:
        case DC_SW_64KB_S_X:
        case DC_SW_64KB_S_T:
-               input->src.is_display_sw = 0;
                input->src.macro_tile_size = dm_64k_tile;
                break;
        case DC_SW_VAR_S:
        case DC_SW_VAR_S_X:
-               input->src.is_display_sw = 0;
                input->src.macro_tile_size = dm_256k_tile;
                break;
 
        /* For 64bpp 2 high tiles */
        case DC_SW_4KB_D:
        case DC_SW_4KB_D_X:
-               input->src.is_display_sw = 1;
                input->src.macro_tile_size = dm_4k_tile;
                break;
        case DC_SW_64KB_D:
        case DC_SW_64KB_D_X:
        case DC_SW_64KB_D_T:
-               input->src.is_display_sw = 1;
                input->src.macro_tile_size = dm_64k_tile;
                break;
        case DC_SW_VAR_D:
        case DC_SW_VAR_D_X:
-               input->src.is_display_sw = 1;
                input->src.macro_tile_size = dm_256k_tile;
                break;
 
@@ -423,7 +416,7 @@ static void pipe_ctx_to_e2e_pipe_params (
                        - pipe->stream->timing.v_addressable
                        - pipe->stream->timing.v_border_bottom
                        - pipe->stream->timing.v_border_top;
-       input->dest.pixel_rate_mhz = pipe->stream->timing.pix_clk_khz/1000.0;
+       input->dest.pixel_rate_mhz = pipe->stream->timing.pix_clk_100hz/10000.0;
        input->dest.vstartup_start = pipe->pipe_dlg_param.vstartup_start;
        input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset;
        input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset;
@@ -670,9 +663,9 @@ 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_khz)
+               unsigned int pixel_rate_100hz)
 {
-       float pixel_rate_mhz = pixel_rate_khz / 1000;
+       float pixel_rate_mhz = pixel_rate_100hz / 10000;
 
        /*
         * force enabling pipe split by lower dpp clock for DPM0 to just
@@ -695,7 +688,7 @@ static void hack_bounding_box(struct dcn_bw_internal_vars *v,
 
        if (context->stream_count == 1 &&
                        dbg->force_single_disp_pipe_split)
-               hack_force_pipe_split(v, context->streams[0]->timing.pix_clk_khz);
+               hack_force_pipe_split(v, context->streams[0]->timing.pix_clk_100hz);
 }
 
 bool dcn_validate_bandwidth(
@@ -852,7 +845,7 @@ bool dcn_validate_bandwidth(
                v->v_sync_plus_back_porch[input_idx] = pipe->stream->timing.v_total
                                - v->vactive[input_idx]
                                - pipe->stream->timing.v_front_porch;
-               v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_khz/1000.0;
+               v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_100hz/10000.0;
                if (pipe->stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
                        v->pixel_clock[input_idx] *= 2;
                if (!pipe->plane_state) {
@@ -961,7 +954,7 @@ bool dcn_validate_bandwidth(
                v->dcc_rate[input_idx] = 1; /*TODO: Worst case? does this change?*/
                v->output_format[input_idx] = pipe->stream->timing.pixel_encoding ==
                                PIXEL_ENCODING_YCBCR420 ? dcn_bw_420 : dcn_bw_444;
-               v->output[input_idx] = pipe->stream->sink->sink_signal ==
+               v->output[input_idx] = pipe->stream->signal ==
                                SIGNAL_TYPE_HDMI_TYPE_A ? dcn_bw_hdmi : dcn_bw_dp;
                v->output_deep_color[input_idx] = dcn_bw_encoder_8bpc;
                if (v->output[input_idx] == dcn_bw_hdmi) {
index 5fd52094d459efb3cbf97f12c068ff9d2d5d0b35..1dabafc12cfe2d9f11bdca52f11fe629bc1d5ac9 100644 (file)
@@ -384,7 +384,7 @@ void dc_stream_set_dither_option(struct dc_stream_state *stream,
                enum dc_dither_option option)
 {
        struct bit_depth_reduction_params params;
-       struct dc_link *link = stream->sink->link;
+       struct dc_link *link = stream->link;
        struct pipe_ctx *pipes = NULL;
        int i;
 
@@ -451,7 +451,7 @@ bool dc_stream_program_csc_matrix(struct dc *dc, struct dc_stream_state *stream)
                                        pipes,
                                        stream->output_color_space,
                                        stream->csc_color_matrix.matrix,
-                                       pipes->plane_res.hubp->opp_id);
+                                       pipes->plane_res.hubp ? pipes->plane_res.hubp->opp_id : 0);
                        ret = true;
                }
        }
@@ -526,9 +526,8 @@ void dc_link_set_preferred_link_settings(struct dc *dc,
 
        for (i = 0; i < MAX_PIPES; i++) {
                pipe = &dc->current_state->res_ctx.pipe_ctx[i];
-               if (pipe->stream && pipe->stream->sink
-                       && pipe->stream->sink->link) {
-                       if (pipe->stream->sink->link == link)
+               if (pipe->stream && pipe->stream->link) {
+                       if (pipe->stream->link == link)
                                break;
                }
        }
@@ -586,9 +585,6 @@ static void destruct(struct dc *dc)
        if (dc->ctx->gpio_service)
                dal_gpio_service_destroy(&dc->ctx->gpio_service);
 
-       if (dc->ctx->i2caux)
-               dal_i2caux_destroy(&dc->ctx->i2caux);
-
        if (dc->ctx->created_bios)
                dal_bios_parser_destroy(&dc->ctx->dc_bios);
 
@@ -670,6 +666,7 @@ static bool construct(struct dc *dc,
        dc_ctx->dc = dc;
        dc_ctx->asic_id = init_params->asic_id;
        dc_ctx->dc_sink_id_count = 0;
+       dc_ctx->dc_stream_id_count = 0;
        dc->ctx = dc_ctx;
 
        dc->current_state = dc_create_state();
@@ -709,14 +706,6 @@ static bool construct(struct dc *dc,
                dc_ctx->created_bios = true;
                }
 
-       /* Create I2C AUX */
-       dc_ctx->i2caux = dal_i2caux_create(dc_ctx);
-
-       if (!dc_ctx->i2caux) {
-               ASSERT_CRITICAL(false);
-               goto fail;
-       }
-
        dc_ctx->perf_trace = dc_perf_trace_create();
        if (!dc_ctx->perf_trace) {
                ASSERT_CRITICAL(false);
@@ -840,6 +829,11 @@ alloc_fail:
        return NULL;
 }
 
+void dc_init_callbacks(struct dc *dc,
+               const struct dc_callback_init *init_params)
+{
+}
+
 void dc_destroy(struct dc **dc)
 {
        destruct(*dc);
@@ -1040,7 +1034,8 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
 
        /* Program all planes within new context*/
        for (i = 0; i < context->stream_count; i++) {
-               const struct dc_sink *sink = context->streams[i]->sink;
+               const struct dc_link *link = context->streams[i]->link;
+               struct dc_stream_status *status;
 
                if (!context->streams[i]->mode_changed)
                        continue;
@@ -1065,12 +1060,15 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
                        }
                }
 
-               CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}",
+               status = dc_stream_get_status_from_state(context, context->streams[i]);
+               context->streams[i]->out.otg_offset = status->primary_otg_inst;
+
+               CONN_MSG_MODE(link, "{%dx%d, %dx%d@%dKhz}",
                                context->streams[i]->timing.h_addressable,
                                context->streams[i]->timing.v_addressable,
                                context->streams[i]->timing.h_total,
                                context->streams[i]->timing.v_total,
-                               context->streams[i]->timing.pix_clk_khz);
+                               context->streams[i]->timing.pix_clk_100hz / 10);
        }
 
        dc_enable_stereo(dc, context, dc_streams, context->stream_count);
@@ -1215,6 +1213,12 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa
                 */
                update_flags->bits.bpp_change = 1;
 
+       if (u->plane_info->plane_size.grph.surface_pitch != u->surface->plane_size.grph.surface_pitch
+                       || u->plane_info->plane_size.video.luma_pitch != u->surface->plane_size.video.luma_pitch
+                       || u->plane_info->plane_size.video.chroma_pitch != u->surface->plane_size.video.chroma_pitch)
+               update_flags->bits.plane_size_change = 1;
+
+
        if (memcmp(&u->plane_info->tiling_info, &u->surface->tiling_info,
                        sizeof(union dc_tiling_info)) != 0) {
                update_flags->bits.swizzle_change = 1;
@@ -1236,7 +1240,7 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa
                        || update_flags->bits.output_tf_change)
                return UPDATE_TYPE_FULL;
 
-       return UPDATE_TYPE_MED;
+       return update_flags->raw ? UPDATE_TYPE_MED : UPDATE_TYPE_FAST;
 }
 
 static enum surface_update_type get_scaling_info_update_type(
@@ -1605,7 +1609,6 @@ void dc_commit_updates_for_stream(struct dc *dc,
                int surface_count,
                struct dc_stream_state *stream,
                struct dc_stream_update *stream_update,
-               struct dc_plane_state **plane_states,
                struct dc_state *state)
 {
        const struct dc_stream_status *stream_status;
@@ -1764,6 +1767,26 @@ void dc_resume(struct dc *dc)
                core_link_resume(dc->links[i]);
 }
 
+unsigned int dc_get_current_backlight_pwm(struct dc *dc)
+{
+       struct abm *abm = dc->res_pool->abm;
+
+       if (abm)
+               return abm->funcs->get_current_backlight(abm);
+
+       return 0;
+}
+
+unsigned int dc_get_target_backlight_pwm(struct dc *dc)
+{
+       struct abm *abm = dc->res_pool->abm;
+
+       if (abm)
+               return abm->funcs->get_target_backlight(abm);
+
+       return 0;
+}
+
 bool dc_is_dmcu_initialized(struct dc *dc)
 {
        struct dmcu *dmcu = dc->res_pool->dmcu;
index 52deacf398411378c1f63f02d62dc117ff0b522a..3dd5f2717b53375a5f666165b61441870e26b99c 100644 (file)
 #include "dpcd_defs.h"
 #include "dmcu.h"
 
-#include "dce/dce_11_0_d.h"
-#include "dce/dce_11_0_enum.h"
-#include "dce/dce_11_0_sh_mask.h"
-
 #define DC_LOGGER_INIT(logger)
 
 
@@ -789,7 +785,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
                        return false;
                }
 
-               sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock;
+               sink->link->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock;
                sink->converter_disable_audio = converter_disable_audio;
 
                link->local_sink = sink;
@@ -1372,7 +1368,7 @@ static void dpcd_configure_panel_mode(
 static void enable_stream_features(struct pipe_ctx *pipe_ctx)
 {
        struct dc_stream_state *stream = pipe_ctx->stream;
-       struct dc_link *link = stream->sink->link;
+       struct dc_link *link = stream->link;
        union down_spread_ctrl old_downspread;
        union down_spread_ctrl new_downspread;
 
@@ -1397,7 +1393,7 @@ static enum dc_status enable_link_dp(
        struct dc_stream_state *stream = pipe_ctx->stream;
        enum dc_status status;
        bool skip_video_pattern;
-       struct dc_link *link = stream->sink->link;
+       struct dc_link *link = stream->link;
        struct dc_link_settings link_settings = {0};
        enum dp_panel_mode panel_mode;
 
@@ -1414,8 +1410,8 @@ static enum dc_status enable_link_dp(
                pipe_ctx->clock_source->id,
                &link_settings);
 
-       if (stream->sink->edid_caps.panel_patch.dppowerup_delay > 0) {
-               int delay_dp_power_up_in_ms = stream->sink->edid_caps.panel_patch.dppowerup_delay;
+       if (stream->sink_patches.dppowerup_delay > 0) {
+               int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay;
 
                msleep(delay_dp_power_up_in_ms);
        }
@@ -1448,7 +1444,7 @@ static enum dc_status enable_link_edp(
 {
        enum dc_status status;
        struct dc_stream_state *stream = pipe_ctx->stream;
-       struct dc_link *link = stream->sink->link;
+       struct dc_link *link = stream->link;
        /*in case it is not on*/
        link->dc->hwss.edp_power_control(link, true);
        link->dc->hwss.edp_wait_for_hpd_ready(link, true);
@@ -1463,7 +1459,7 @@ static enum dc_status enable_link_dp_mst(
                struct dc_state *state,
                struct pipe_ctx *pipe_ctx)
 {
-       struct dc_link *link = pipe_ctx->stream->sink->link;
+       struct dc_link *link = pipe_ctx->stream->link;
 
        /* sink signal type after MST branch is MST. Multiple MST sinks
         * share one link. Link DP PHY is enable or training only once.
@@ -1597,7 +1593,7 @@ static bool i2c_write(struct pipe_ctx *pipe_ctx,
        cmd.payloads = &payload;
 
        if (dm_helpers_submit_i2c(pipe_ctx->stream->ctx,
-                       pipe_ctx->stream->sink->link, &cmd))
+                       pipe_ctx->stream->link, &cmd))
                return true;
 
        return false;
@@ -1651,7 +1647,7 @@ static void write_i2c_retimer_setting(
                                else {
                                        i2c_success =
                                                dal_ddc_service_query_ddc_data(
-                                               pipe_ctx->stream->sink->link->ddc,
+                                               pipe_ctx->stream->link->ddc,
                                                slave_address, &offset, 1, &value, 1);
                                        if (!i2c_success)
                                                /* Write failure */
@@ -1704,7 +1700,7 @@ static void write_i2c_retimer_setting(
                                        else {
                                                i2c_success =
                                                                dal_ddc_service_query_ddc_data(
-                                                               pipe_ctx->stream->sink->link->ddc,
+                                                               pipe_ctx->stream->link->ddc,
                                                                slave_address, &offset, 1, &value, 1);
                                                if (!i2c_success)
                                                        /* Write failure */
@@ -1929,7 +1925,7 @@ static void write_i2c_redriver_setting(
 static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
 {
        struct dc_stream_state *stream = pipe_ctx->stream;
-       struct dc_link *link = stream->sink->link;
+       struct dc_link *link = stream->link;
        enum dc_color_depth display_color_depth;
        enum engine_id eng_id;
        struct ext_hdmi_settings settings = {0};
@@ -1938,12 +1934,12 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
                        && (stream->timing.v_addressable == 480);
 
        if (stream->phy_pix_clk == 0)
-               stream->phy_pix_clk = stream->timing.pix_clk_khz;
+               stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10;
        if (stream->phy_pix_clk > 340000)
                is_over_340mhz = true;
 
        if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {
-               unsigned short masked_chip_caps = pipe_ctx->stream->sink->link->chip_caps &
+               unsigned short masked_chip_caps = pipe_ctx->stream->link->chip_caps &
                                EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK;
                if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) {
                        /* DP159, Retimer settings */
@@ -1964,11 +1960,11 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
 
        if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
                dal_ddc_service_write_scdc_data(
-                       stream->sink->link->ddc,
+                       stream->link->ddc,
                        stream->phy_pix_clk,
                        stream->timing.flags.LTE_340MCSC_SCRAMBLE);
 
-       memset(&stream->sink->link->cur_link_settings, 0,
+       memset(&stream->link->cur_link_settings, 0,
                        sizeof(struct dc_link_settings));
 
        display_color_depth = stream->timing.display_color_depth;
@@ -1989,12 +1985,12 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
 static void enable_link_lvds(struct pipe_ctx *pipe_ctx)
 {
        struct dc_stream_state *stream = pipe_ctx->stream;
-       struct dc_link *link = stream->sink->link;
+       struct dc_link *link = stream->link;
 
        if (stream->phy_pix_clk == 0)
-               stream->phy_pix_clk = stream->timing.pix_clk_khz;
+               stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10;
 
-       memset(&stream->sink->link->cur_link_settings, 0,
+       memset(&stream->link->cur_link_settings, 0,
                        sizeof(struct dc_link_settings));
 
        link->link_enc->funcs->enable_lvds_output(
@@ -2067,7 +2063,7 @@ static bool dp_active_dongle_validate_timing(
                const struct dc_crtc_timing *timing,
                const struct dpcd_caps *dpcd_caps)
 {
-       unsigned int required_pix_clk = timing->pix_clk_khz;
+       unsigned int required_pix_clk_100hz = timing->pix_clk_100hz;
        const struct dc_dongle_caps *dongle_caps = &dpcd_caps->dongle_caps;
 
        switch (dpcd_caps->dongle_type) {
@@ -2107,9 +2103,9 @@ static bool dp_active_dongle_validate_timing(
 
        /* Check Color Depth and Pixel Clock */
        if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
-               required_pix_clk /= 2;
+               required_pix_clk_100hz /= 2;
        else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
-               required_pix_clk = required_pix_clk * 2 / 3;
+               required_pix_clk_100hz = required_pix_clk_100hz * 2 / 3;
 
        switch (timing->display_color_depth) {
        case COLOR_DEPTH_666:
@@ -2119,12 +2115,12 @@ static bool dp_active_dongle_validate_timing(
        case COLOR_DEPTH_101010:
                if (dongle_caps->dp_hdmi_max_bpc < 10)
                        return false;
-               required_pix_clk = required_pix_clk * 10 / 8;
+               required_pix_clk_100hz = required_pix_clk_100hz * 10 / 8;
                break;
        case COLOR_DEPTH_121212:
                if (dongle_caps->dp_hdmi_max_bpc < 12)
                        return false;
-               required_pix_clk = required_pix_clk * 12 / 8;
+               required_pix_clk_100hz = required_pix_clk_100hz * 12 / 8;
                break;
 
        case COLOR_DEPTH_141414:
@@ -2134,7 +2130,7 @@ static bool dp_active_dongle_validate_timing(
                return false;
        }
 
-       if (required_pix_clk > dongle_caps->dp_hdmi_max_pixel_clk)
+       if (required_pix_clk_100hz > (dongle_caps->dp_hdmi_max_pixel_clk * 10))
                return false;
 
        return true;
@@ -2145,7 +2141,7 @@ enum dc_status dc_link_validate_mode_timing(
                struct dc_link *link,
                const struct dc_crtc_timing *timing)
 {
-       uint32_t max_pix_clk = stream->sink->dongle_max_pix_clk;
+       uint32_t max_pix_clk = stream->link->dongle_max_pix_clk * 10;
        struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
 
        /* A hack to avoid failing any modes for EDID override feature on
@@ -2155,7 +2151,7 @@ enum dc_status dc_link_validate_mode_timing(
                return DC_OK;
 
        /* Passive Dongle */
-       if (0 != max_pix_clk && timing->pix_clk_khz > max_pix_clk)
+       if (0 != max_pix_clk && timing->pix_clk_100hz > max_pix_clk)
                return DC_EXCEED_DONGLE_CAP;
 
        /* Active Dongle*/
@@ -2190,8 +2186,7 @@ int dc_link_get_backlight_level(const struct dc_link *link)
 
 bool dc_link_set_backlight_level(const struct dc_link *link,
                uint32_t backlight_pwm_u16_16,
-               uint32_t frame_ramp,
-               const struct dc_stream_state *stream)
+               uint32_t frame_ramp)
 {
        struct dc  *core_dc = link->ctx->dc;
        struct abm *abm = core_dc->res_pool->abm;
@@ -2206,10 +2201,6 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
                (abm->funcs->set_backlight_level_pwm == NULL))
                return false;
 
-       if (stream)
-               ((struct dc_stream_state *)stream)->bl_pwm_level =
-                               backlight_pwm_u16_16;
-
        use_smooth_brightness = dmcu->funcs->is_dmcu_initialized(dmcu);
 
        DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n",
@@ -2219,7 +2210,7 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
                for (i = 0; i < MAX_PIPES; i++) {
                        if (core_dc->current_state->res_ctx.pipe_ctx[i].stream) {
                                if (core_dc->current_state->res_ctx.
-                                               pipe_ctx[i].stream->sink->link
+                                               pipe_ctx[i].stream->link
                                                == link)
                                        /* DMCU -1 for all controller id values,
                                         * therefore +1 here
@@ -2279,7 +2270,7 @@ void core_link_resume(struct dc_link *link)
 static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream)
 {
        struct dc_link_settings *link_settings =
-                       &stream->sink->link->cur_link_settings;
+                       &stream->link->cur_link_settings;
        uint32_t link_rate_in_mbps =
                        link_settings->link_rate * LINK_RATE_REF_FREQ_IN_MHZ;
        struct fixed31_32 mbps = dc_fixpt_from_int(
@@ -2310,7 +2301,7 @@ static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx)
        uint32_t denominator;
 
        bpc = get_color_depth(pipe_ctx->stream_res.pix_clk_params.color_depth);
-       kbps = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk * bpc * 3;
+       kbps = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10 * bpc * 3;
 
        /*
         * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
@@ -2386,7 +2377,7 @@ static void update_mst_stream_alloc_table(
 static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
 {
        struct dc_stream_state *stream = pipe_ctx->stream;
-       struct dc_link *link = stream->sink->link;
+       struct dc_link *link = stream->link;
        struct link_encoder *link_encoder = link->link_enc;
        struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
        struct dp_mst_stream_allocation_table proposed_table = {0};
@@ -2466,7 +2457,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
 static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
 {
        struct dc_stream_state *stream = pipe_ctx->stream;
-       struct dc_link *link = stream->sink->link;
+       struct dc_link *link = stream->link;
        struct link_encoder *link_encoder = link->link_enc;
        struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
        struct dp_mst_stream_allocation_table proposed_table = {0};
@@ -2551,8 +2542,8 @@ void core_link_enable_stream(
        DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
 
        if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) {
-               stream->sink->link->link_enc->funcs->setup(
-                       stream->sink->link->link_enc,
+               stream->link->link_enc->funcs->setup(
+                       stream->link->link_enc,
                        pipe_ctx->stream->signal);
                pipe_ctx->stream_res.stream_enc->funcs->setup_stereo_sync(
                        pipe_ctx->stream_res.stream_enc,
@@ -2604,7 +2595,7 @@ void core_link_enable_stream(
 
                if (status != DC_OK) {
                        DC_LOG_WARNING("enabling link %u failed: %d\n",
-                       pipe_ctx->stream->sink->link->link_index,
+                       pipe_ctx->stream->link->link_index,
                        status);
 
                        /* Abort stream enable *unless* the failure was due to
@@ -2633,15 +2624,10 @@ void core_link_enable_stream(
                        allocate_mst_payload(pipe_ctx);
 
                core_dc->hwss.unblank_stream(pipe_ctx,
-                       &pipe_ctx->stream->sink->link->cur_link_settings);
+                       &pipe_ctx->stream->link->cur_link_settings);
 
                if (dc_is_dp_signal(pipe_ctx->stream->signal))
                        enable_stream_features(pipe_ctx);
-
-               dc_link_set_backlight_level(pipe_ctx->stream->sink->link,
-                               pipe_ctx->stream->bl_pwm_level,
-                               0,
-                               pipe_ctx->stream);
        }
 
 }
@@ -2657,7 +2643,7 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option)
 
        core_dc->hwss.disable_stream(pipe_ctx, option);
 
-       disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal);
+       disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal);
 }
 
 void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
index 506a97e1695621e18a4273c1eb3921a38b665ec3..b7ee63cd8dc7df4296b98d98c4f5dbbfd255a14a 100644 (file)
@@ -33,7 +33,7 @@
 #include "include/vector.h"
 #include "core_types.h"
 #include "dc_link_ddc.h"
-#include "aux_engine.h"
+#include "dce/dce_aux.h"
 
 #define AUX_POWER_UP_WA_DELAY 500
 #define I2C_OVER_AUX_DEFER_WA_DELAY 70
@@ -42,7 +42,6 @@
 #define CV_SMART_DONGLE_ADDRESS 0x20
 /* DVI-HDMI dongle slave address for retrieving dongle signature*/
 #define DVI_HDMI_DONGLE_ADDRESS 0x68
-static const int8_t dvi_hdmi_dongle_signature_str[] = "6140063500G";
 struct dvi_hdmi_dongle_signature_data {
        int8_t vendor[3];/* "AMD" */
        uint8_t version[2];
@@ -165,43 +164,6 @@ static void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p)
 
 }
 
-static struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count)
-{
-       struct aux_payloads *payloads;
-
-       payloads = kzalloc(sizeof(struct aux_payloads), GFP_KERNEL);
-
-       if (!payloads)
-               return NULL;
-
-       if (dal_vector_construct(
-               &payloads->payloads, ctx, count, sizeof(struct aux_payload)))
-               return payloads;
-
-       kfree(payloads);
-       return NULL;
-}
-
-static struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p)
-{
-       return (struct aux_payload *)p->payloads.container;
-}
-
-static uint32_t  dal_ddc_aux_payloads_get_count(struct aux_payloads *p)
-{
-       return p->payloads.count;
-}
-
-static void dal_ddc_aux_payloads_destroy(struct aux_payloads **p)
-{
-       if (!p || !*p)
-               return;
-
-       dal_vector_destruct(&(*p)->payloads);
-       kfree(*p);
-       *p = NULL;
-}
-
 #define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b))
 
 void dal_ddc_i2c_payloads_add(
@@ -225,27 +187,6 @@ void dal_ddc_i2c_payloads_add(
 
 }
 
-void dal_ddc_aux_payloads_add(
-       struct aux_payloads *payloads,
-       uint32_t address,
-       uint32_t len,
-       uint8_t *data,
-       bool write)
-{
-       uint32_t payload_size = DEFAULT_AUX_MAX_DATA_SIZE;
-       uint32_t pos;
-
-       for (pos = 0; pos < len; pos += payload_size) {
-               struct aux_payload payload = {
-                       .i2c_over_aux = true,
-                       .write = write,
-                       .address = address,
-                       .length = DDC_MIN(payload_size, len - pos),
-                       .data = data + pos };
-               dal_vector_append(&payloads->payloads, &payload);
-       }
-}
-
 static void construct(
        struct ddc_service *ddc_service,
        struct ddc_service_init_data *init_data)
@@ -574,32 +515,34 @@ bool dal_ddc_service_query_ddc_data(
        /*TODO: len of payload data for i2c and aux is uint8!!!!,
         *  but we want to read 256 over i2c!!!!*/
        if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) {
-
-               struct aux_payloads *payloads =
-                       dal_ddc_aux_payloads_create(ddc->ctx, payloads_num);
-
-               struct aux_command command = {
-                       .payloads = dal_ddc_aux_payloads_get(payloads),
-                       .number_of_payloads = 0,
+               struct aux_payload write_payload = {
+                       .i2c_over_aux = true,
+                       .write = true,
+                       .mot = true,
+                       .address = address,
+                       .length = write_size,
+                       .data = write_buf,
+                       .reply = NULL,
                        .defer_delay = get_defer_delay(ddc),
-                       .max_defer_write_retry = 0 };
+               };
 
-               dal_ddc_aux_payloads_add(
-                       payloads, address, write_size, write_buf, true);
-
-               dal_ddc_aux_payloads_add(
-                       payloads, address, read_size, read_buf, false);
-
-               command.number_of_payloads =
-                       dal_ddc_aux_payloads_get_count(payloads);
+               struct aux_payload read_payload = {
+                       .i2c_over_aux = true,
+                       .write = false,
+                       .mot = false,
+                       .address = address,
+                       .length = read_size,
+                       .data = read_buf,
+                       .reply = NULL,
+                       .defer_delay = get_defer_delay(ddc),
+               };
 
-               ret = dal_i2caux_submit_aux_command(
-                               ddc->ctx->i2caux,
-                               ddc->ddc_pin,
-                               &command);
+               ret = dc_link_aux_transfer_with_retries(ddc, &write_payload);
 
-               dal_ddc_aux_payloads_destroy(&payloads);
+               if (!ret)
+                       return false;
 
+               ret = dc_link_aux_transfer_with_retries(ddc, &read_payload);
        } else {
                struct i2c_payloads *payloads =
                        dal_ddc_i2c_payloads_create(ddc->ctx, payloads_num);
@@ -631,56 +574,15 @@ bool dal_ddc_service_query_ddc_data(
 }
 
 int dc_link_aux_transfer(struct ddc_service *ddc,
-                            unsigned int address,
-                            uint8_t *reply,
-                            void *buffer,
-                            unsigned int size,
-                            enum aux_transaction_type type,
-                            enum i2caux_transaction_action action)
+               struct aux_payload *payload)
 {
-       struct ddc *ddc_pin = ddc->ddc_pin;
-       struct aux_engine *aux_engine;
-       enum aux_channel_operation_result operation_result;
-       struct aux_request_transaction_data aux_req;
-       struct aux_reply_transaction_data aux_rep;
-       uint8_t returned_bytes = 0;
-       int res = -1;
-       uint32_t status;
-
-       memset(&aux_req, 0, sizeof(aux_req));
-       memset(&aux_rep, 0, sizeof(aux_rep));
-
-       aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
-       aux_engine->funcs->acquire(aux_engine, ddc_pin);
-
-       aux_req.type = type;
-       aux_req.action = action;
-
-       aux_req.address = address;
-       aux_req.delay = 0;
-       aux_req.length = size;
-       aux_req.data = buffer;
-
-       aux_engine->funcs->submit_channel_request(aux_engine, &aux_req);
-       operation_result = aux_engine->funcs->get_channel_status(aux_engine, &returned_bytes);
-
-       switch (operation_result) {
-       case AUX_CHANNEL_OPERATION_SUCCEEDED:
-               res = aux_engine->funcs->read_channel_reply(aux_engine, size,
-                                                       buffer, reply,
-                                                       &status);
-               break;
-       case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
-               res = 0;
-               break;
-       case AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN:
-       case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
-       case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
-               res = -1;
-               break;
-       }
-       aux_engine->funcs->release_engine(aux_engine);
-       return res;
+       return dce_aux_transfer(ddc, payload);
+}
+
+bool dc_link_aux_transfer_with_retries(struct ddc_service *ddc,
+               struct aux_payload *payload)
+{
+       return dce_aux_transfer_with_retries(ddc, payload);
 }
 
 /*test only function*/
index 0caacb60b02fe0df215f046c9ea460a7a5cc4625..92f565ca12609f753102d6da7868ad11e0daca1f 100644 (file)
@@ -47,7 +47,7 @@ static void wait_for_training_aux_rd_interval(
        struct dc_link *link,
        uint32_t default_wait_in_micro_secs)
 {
-       union training_aux_rd_interval training_rd_interval;
+       union training_aux_rd_interval training_rd_interval = {0};
 
        /* overwrite the delay if rev > 1.1*/
        if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
@@ -117,6 +117,13 @@ static void dpcd_set_link_settings(
        core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
        &downspread.raw, sizeof(downspread));
 
+       if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 &&
+               (link->dpcd_caps.link_rate_set >= 1 &&
+               link->dpcd_caps.link_rate_set <= 8)) {
+               core_link_write_dpcd(link, DP_LINK_RATE_SET,
+               &link->dpcd_caps.link_rate_set, 1);
+       }
+
        DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n",
                __func__,
                DP_LINK_BW_SET,
@@ -1542,7 +1549,7 @@ static uint32_t bandwidth_in_kbps_from_timing(
 
        ASSERT(bits_per_channel != 0);
 
-       kbps = timing->pix_clk_khz;
+       kbps = timing->pix_clk_100hz / 10;
        kbps *= bits_per_channel;
 
        if (timing->flags.Y_ONLY != 1) {
@@ -1584,7 +1591,7 @@ bool dp_validate_mode_timing(
        const struct dc_link_settings *link_setting;
 
        /*always DP fail safe mode*/
-       if (timing->pix_clk_khz == (uint32_t) 25175 &&
+       if ((timing->pix_clk_100hz / 10) == (uint32_t) 25175 &&
                timing->h_addressable == (uint32_t) 640 &&
                timing->v_addressable == (uint32_t) 480)
                return true;
@@ -1634,7 +1641,7 @@ void decide_link_settings(struct dc_stream_state *stream,
 
        req_bw = bandwidth_in_kbps_from_timing(&stream->timing);
 
-       link = stream->sink->link;
+       link = stream->link;
 
        /* if preferred is specified through AMDDP, use it, if it's enough
         * to drive the mode
@@ -1656,7 +1663,7 @@ void decide_link_settings(struct dc_stream_state *stream,
        }
 
        /* EDP use the link cap setting */
-       if (stream->sink->sink_signal == SIGNAL_TYPE_EDP) {
+       if (link->connector_signal == SIGNAL_TYPE_EDP) {
                *link_setting = link->verified_link_cap;
                return;
        }
@@ -2002,11 +2009,7 @@ static void handle_automated_test(struct dc_link *link)
                dp_test_send_phy_test_pattern(link);
                test_response.bits.ACK = 1;
        }
-       if (!test_request.raw)
-               /* no requests, revert all test signals
-                * TODO: revert all test signals
-                */
-               test_response.bits.ACK = 1;
+
        /* send request acknowledgment */
        if (test_response.bits.ACK)
                core_link_write_dpcd(
@@ -2493,13 +2496,105 @@ bool detect_dp_sink_caps(struct dc_link *link)
        /* TODO save sink caps in link->sink */
 }
 
+enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in_khz)
+{
+       enum dc_link_rate link_rate;
+       // LinkRate is normally stored as a multiplier of 0.27 Gbps per lane. Do the translation.
+       switch (link_rate_in_khz) {
+       case 1620000:
+               link_rate = LINK_RATE_LOW;              // Rate_1 (RBR)         - 1.62 Gbps/Lane
+               break;
+       case 2160000:
+               link_rate = LINK_RATE_RATE_2;   // Rate_2                       - 2.16 Gbps/Lane
+               break;
+       case 2430000:
+               link_rate = LINK_RATE_RATE_3;   // Rate_3                       - 2.43 Gbps/Lane
+               break;
+       case 2700000:
+               link_rate = LINK_RATE_HIGH;             // Rate_4 (HBR)         - 2.70 Gbps/Lane
+               break;
+       case 3240000:
+               link_rate = LINK_RATE_RBR2;             // Rate_5 (RBR2)        - 3.24 Gbps/Lane
+               break;
+       case 4320000:
+               link_rate = LINK_RATE_RATE_6;   // Rate_6                       - 4.32 Gbps/Lane
+               break;
+       case 5400000:
+               link_rate = LINK_RATE_HIGH2;    // Rate_7 (HBR2)        - 5.40 Gbps/Lane
+               break;
+       case 8100000:
+               link_rate = LINK_RATE_HIGH3;    // Rate_8 (HBR3)        - 8.10 Gbps/Lane
+               break;
+       default:
+               link_rate = LINK_RATE_UNKNOWN;
+               break;
+       }
+       return link_rate;
+}
+
 void detect_edp_sink_caps(struct dc_link *link)
 {
-       retrieve_link_cap(link);
+       uint8_t supported_link_rates[16] = {0};
+       uint32_t entry;
+       uint32_t link_rate_in_khz;
+       enum dc_link_rate link_rate = LINK_RATE_UNKNOWN;
+       uint8_t link_rate_set = 0;
 
-       if (link->reported_link_cap.link_rate == LINK_RATE_UNKNOWN)
-               link->reported_link_cap.link_rate = LINK_RATE_HIGH2;
+       retrieve_link_cap(link);
 
+       if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14) {
+               // Read DPCD 00010h - 0001Fh 16 bytes at one shot
+               core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
+                                                       supported_link_rates, sizeof(supported_link_rates));
+
+               link->dpcd_caps.link_rate_set = 0;
+               for (entry = 0; entry < 16; entry += 2) {
+                       // DPCD register reports per-lane link rate = 16-bit link rate capability
+                       // value X 200 kHz. Need multipler to find link rate in kHz.
+                       link_rate_in_khz = (supported_link_rates[entry+1] * 0x100 +
+                                                                               supported_link_rates[entry]) * 200;
+
+                       if (link_rate_in_khz != 0) {
+                               link_rate = linkRateInKHzToLinkRateMultiplier(link_rate_in_khz);
+                               if (link->reported_link_cap.link_rate < link_rate) {
+                                       link->reported_link_cap.link_rate = link_rate;
+
+                                       switch (link_rate) {
+                                       case LINK_RATE_LOW:
+                                               link_rate_set = 1;
+                                               break;
+                                       case LINK_RATE_RATE_2:
+                                               link_rate_set = 2;
+                                               break;
+                                       case LINK_RATE_RATE_3:
+                                               link_rate_set = 3;
+                                               break;
+                                       case LINK_RATE_HIGH:
+                                               link_rate_set = 4;
+                                               break;
+                                       case LINK_RATE_RBR2:
+                                               link_rate_set = 5;
+                                               break;
+                                       case LINK_RATE_RATE_6:
+                                               link_rate_set = 6;
+                                               break;
+                                       case LINK_RATE_HIGH2:
+                                               link_rate_set = 7;
+                                               break;
+                                       case LINK_RATE_HIGH3:
+                                               link_rate_set = 8;
+                                               break;
+                                       default:
+                                               link_rate_set = 0;
+                                               break;
+                                       }
+
+                                       if (link->dpcd_caps.link_rate_set < link_rate_set)
+                                               link->dpcd_caps.link_rate_set = link_rate_set;
+                               }
+                       }
+               }
+       }
        link->verified_link_cap = link->reported_link_cap;
 }
 
@@ -2621,7 +2716,7 @@ bool dc_link_dp_set_test_pattern(
        memset(&training_pattern, 0, sizeof(training_pattern));
 
        for (i = 0; i < MAX_PIPES; i++) {
-               if (pipes[i].stream->sink->link == link) {
+               if (pipes[i].stream->link == link) {
                        pipe_ctx = &pipes[i];
                        break;
                }
index 0065ec7d5330d9eaa03f8d5772e1c0f855373464..16d441d3af8a614dd38e92e6e544ac9276ae9aed 100644 (file)
@@ -70,13 +70,12 @@ void dp_enable_link_phy(
         */
        for (i = 0; i < MAX_PIPES; i++) {
                if (pipes[i].stream != NULL &&
-                       pipes[i].stream->sink != NULL &&
-                       pipes[i].stream->sink->link == link) {
+                       pipes[i].stream->link == link) {
                        if (pipes[i].clock_source != NULL &&
                                        pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) {
                                pipes[i].clock_source = dp_cs;
-                               pipes[i].stream_res.pix_clk_params.requested_pix_clk =
-                                               pipes[i].stream->timing.pix_clk_khz;
+                               pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz =
+                                               pipes[i].stream->timing.pix_clk_100hz;
                                pipes[i].clock_source->funcs->program_pix_clk(
                                                        pipes[i].clock_source,
                                                        &pipes[i].stream_res.pix_clk_params,
@@ -279,10 +278,8 @@ void dp_retrain_link_dp_test(struct dc_link *link,
        for (i = 0; i < MAX_PIPES; i++) {
                if (pipes[i].stream != NULL &&
                        !pipes[i].top_pipe &&
-                       pipes[i].stream->sink != NULL &&
-                       pipes[i].stream->sink->link != NULL &&
-                       pipes[i].stream_res.stream_enc != NULL &&
-                       pipes[i].stream->sink->link == link) {
+                       pipes[i].stream->link != NULL &&
+                       pipes[i].stream_res.stream_enc != NULL) {
                        udelay(100);
 
                        pipes[i].stream_res.stream_enc->funcs->dp_blank(
index 76137df74a535b6d8c1609e2bb265787538ee87d..9888bc7659f32f1456fa538cd569887dfb872c36 100644 (file)
@@ -355,8 +355,8 @@ bool resource_are_streams_timing_synchronizable(
                                != stream2->timing.v_addressable)
                return false;
 
-       if (stream1->timing.pix_clk_khz
-                               != stream2->timing.pix_clk_khz)
+       if (stream1->timing.pix_clk_100hz
+                               != stream2->timing.pix_clk_100hz)
                return false;
 
        if (stream1->clamping.c_depth != stream2->clamping.c_depth)
@@ -1559,7 +1559,7 @@ static struct stream_encoder *find_first_free_match_stream_enc_for_link(
 {
        int i;
        int j = -1;
-       struct dc_link *link = stream->sink->link;
+       struct dc_link *link = stream->link;
 
        for (i = 0; i < pool->stream_enc_count; i++) {
                if (!res_ctx->is_stream_enc_acquired[i] &&
@@ -1748,7 +1748,7 @@ static struct dc_stream_state *find_pll_sharable_stream(
                if (resource_are_streams_timing_synchronizable(
                        stream_needs_pll, stream_has_pll)
                        && !dc_is_dp_signal(stream_has_pll->signal)
-                       && stream_has_pll->sink->link->connector_signal
+                       && stream_has_pll->link->connector_signal
                        != SIGNAL_TYPE_VIRTUAL)
                        return stream_has_pll;
 
@@ -1759,7 +1759,7 @@ static struct dc_stream_state *find_pll_sharable_stream(
 
 static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
 {
-       uint32_t pix_clk = timing->pix_clk_khz;
+       uint32_t pix_clk = timing->pix_clk_100hz;
        uint32_t normalized_pix_clk = pix_clk;
 
        if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
@@ -1791,10 +1791,10 @@ static void calculate_phy_pix_clks(struct dc_stream_state *stream)
        /* update actual pixel clock on all streams */
        if (dc_is_hdmi_signal(stream->signal))
                stream->phy_pix_clk = get_norm_pix_clk(
-                       &stream->timing);
+                       &stream->timing) / 10;
        else
                stream->phy_pix_clk =
-                       stream->timing.pix_clk_khz;
+                       stream->timing.pix_clk_100hz / 10;
 
        if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
                stream->phy_pix_clk *= 2;
@@ -1842,7 +1842,7 @@ enum dc_status resource_map_pool_resources(
                        &context->res_ctx, pool, stream);
 
        if (!pipe_ctx->stream_res.stream_enc)
-               return DC_NO_STREAM_ENG_RESOURCE;
+               return DC_NO_STREAM_ENC_RESOURCE;
 
        update_stream_engine_usage(
                &context->res_ctx, pool,
@@ -1850,7 +1850,7 @@ enum dc_status resource_map_pool_resources(
                true);
 
        /* TODO: Add check if ASIC support and EDID audio */
-       if (!stream->sink->converter_disable_audio &&
+       if (!stream->converter_disable_audio &&
            dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
            stream->audio_info.mode_count) {
                pipe_ctx->stream_res.audio = find_first_free_audio(
@@ -2112,7 +2112,7 @@ static void set_avi_info_frame(
        itc = true;
        itc_value = 1;
 
-       support = stream->sink->edid_caps.content_support;
+       support = stream->content_support;
 
        if (itc) {
                if (!support.bits.valid_content_type) {
@@ -2151,8 +2151,8 @@ static void set_avi_info_frame(
 
        /* TODO : We should handle YCC quantization */
        /* but we do not have matrix calculation */
-       if (stream->sink->edid_caps.qs_bit == 1 &&
-                       stream->sink->edid_caps.qy_bit == 1) {
+       if (stream->qs_bit == 1 &&
+                       stream->qy_bit == 1) {
                if (color_space == COLOR_SPACE_SRGB ||
                        color_space == COLOR_SPACE_2020_RGB_FULLRANGE) {
                        hdmi_info.bits.Q0_Q1   = RGB_QUANTIZATION_FULL_RANGE;
@@ -2596,7 +2596,7 @@ 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)
 {
        struct dc  *core_dc = dc;
-       struct dc_link *link = stream->sink->link;
+       struct dc_link *link = stream->link;
        struct timing_generator *tg = core_dc->res_pool->timing_generators[0];
        enum dc_status res = DC_OK;
 
index 66e5c4623a49f8be5210ca782b6724728d3a7da4..996298c35f423cba54c8c1f913c2b0d16b339c49 100644 (file)
 /*******************************************************************************
  * Private functions
  ******************************************************************************/
-void update_stream_signal(struct dc_stream_state *stream)
+void update_stream_signal(struct dc_stream_state *stream, struct dc_sink *sink)
 {
-
-       struct dc_sink *dc_sink = stream->sink;
-
-       if (dc_sink->sink_signal == SIGNAL_TYPE_NONE)
-               stream->signal = stream->sink->link->connector_signal;
+       if (sink->sink_signal == SIGNAL_TYPE_NONE)
+               stream->signal = stream->link->connector_signal;
        else
-               stream->signal = dc_sink->sink_signal;
+               stream->signal = sink->sink_signal;
 
        if (dc_is_dvi_signal(stream->signal)) {
                if (stream->ctx->dc->caps.dual_link_dvi &&
-                   stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK &&
-                   stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK)
+                   (stream->timing.pix_clk_100hz / 10) > TMDS_MAX_PIXEL_CLOCK &&
+                   sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK)
                        stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK;
                else
                        stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
@@ -61,10 +58,15 @@ static void construct(struct dc_stream_state *stream,
        uint32_t i = 0;
 
        stream->sink = dc_sink_data;
-       stream->ctx = stream->sink->ctx;
-
        dc_sink_retain(dc_sink_data);
 
+       stream->ctx = dc_sink_data->ctx;
+       stream->link = dc_sink_data->link;
+       stream->sink_patches = dc_sink_data->edid_caps.panel_patch;
+       stream->converter_disable_audio = dc_sink_data->converter_disable_audio;
+       stream->qs_bit = dc_sink_data->edid_caps.qs_bit;
+       stream->qy_bit = dc_sink_data->edid_caps.qy_bit;
+
        /* Copy audio modes */
        /* TODO - Remove this translation */
        for (i = 0; i < (dc_sink_data->edid_caps.audio_mode_count); i++)
@@ -100,11 +102,14 @@ static void construct(struct dc_stream_state *stream,
        /* EDID CAP translation for HDMI 2.0 */
        stream->timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble;
 
-       update_stream_signal(stream);
+       update_stream_signal(stream, dc_sink_data);
 
        stream->out_transfer_func = dc_create_transfer_func();
        stream->out_transfer_func->type = TF_TYPE_BYPASS;
        stream->out_transfer_func->ctx = stream->ctx;
+
+       stream->stream_id = stream->ctx->dc_stream_id_count;
+       stream->ctx->dc_stream_id_count++;
 }
 
 static void destruct(struct dc_stream_state *stream)
@@ -155,20 +160,42 @@ struct dc_stream_state *dc_create_stream_for_sink(
        return stream;
 }
 
-struct dc_stream_status *dc_stream_get_status(
+/**
+ * dc_stream_get_status_from_state - Get stream status from given dc state
+ * @state: DC state to find the stream status in
+ * @stream: The stream to get the stream status for
+ *
+ * The given stream is expected to exist in the given dc state. Otherwise, NULL
+ * will be returned.
+ */
+struct dc_stream_status *dc_stream_get_status_from_state(
+       struct dc_state *state,
        struct dc_stream_state *stream)
 {
        uint8_t i;
-       struct dc  *dc = stream->ctx->dc;
 
-       for (i = 0; i < dc->current_state->stream_count; i++) {
-               if (stream == dc->current_state->streams[i])
-                       return &dc->current_state->stream_status[i];
+       for (i = 0; i < state->stream_count; i++) {
+               if (stream == state->streams[i])
+                       return &state->stream_status[i];
        }
 
        return NULL;
 }
 
+/**
+ * dc_stream_get_status() - Get current stream status of the given stream state
+ * @stream: The stream to get the stream status for.
+ *
+ * The given stream is expected to exist in dc->current_state. Otherwise, NULL
+ * will be returned.
+ */
+struct dc_stream_status *dc_stream_get_status(
+       struct dc_stream_state *stream)
+{
+       struct dc *dc = stream->ctx->dc;
+       return dc_stream_get_status_from_state(dc->current_state, stream);
+}
+
 /**
  * dc_stream_set_cursor_attributes() - Update cursor attributes and set cursor surface address
  */
@@ -334,16 +361,12 @@ void dc_stream_log(const struct dc *dc, const struct dc_stream_state *stream)
                        stream->output_color_space);
        DC_LOG_DC(
                        "\tpix_clk_khz: %d, h_total: %d, v_total: %d, pixelencoder:%d, displaycolorDepth:%d\n",
-                       stream->timing.pix_clk_khz,
+                       stream->timing.pix_clk_100hz / 10,
                        stream->timing.h_total,
                        stream->timing.v_total,
                        stream->timing.pixel_encoding,
                        stream->timing.display_color_depth);
-       DC_LOG_DC(
-                       "\tsink name: %s, serial: %d\n",
-                       stream->sink->edid_caps.display_name,
-                       stream->sink->edid_caps.serial_number);
        DC_LOG_DC(
                        "\tlink: %d\n",
-                       stream->sink->link->link_index);
+                       stream->link->link_index);
 }
index c60c9b4c307531e118ecd4f986985dfa4388ad00..ee6bd50f60b8dcd59406556b2eeae51ab3be94de 100644 (file)
@@ -40,11 +40,14 @@ static void construct(struct dc_context *ctx, struct dc_plane_state *plane_state
        plane_state->ctx = ctx;
 
        plane_state->gamma_correction = dc_create_gamma();
-       plane_state->gamma_correction->is_identity = true;
+       if (plane_state->gamma_correction != NULL)
+               plane_state->gamma_correction->is_identity = true;
 
        plane_state->in_transfer_func = dc_create_transfer_func();
-       plane_state->in_transfer_func->type = TF_TYPE_BYPASS;
-       plane_state->in_transfer_func->ctx = ctx;
+       if (plane_state->in_transfer_func != NULL) {
+               plane_state->in_transfer_func->type = TF_TYPE_BYPASS;
+               plane_state->in_transfer_func->ctx = ctx;
+       }
 }
 
 static void destruct(struct dc_plane_state *plane_state)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c b/drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c
new file mode 100644 (file)
index 0000000..e54b8ac
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2018 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "vm_helper.h"
+
+static void mark_vmid_used(struct vm_helper *vm_helper, unsigned int pos, uint8_t hubp_idx)
+{
+       struct vmid_usage vmids = vm_helper->hubp_vmid_usage[hubp_idx];
+
+       vmids.vmid_usage[0] = vmids.vmid_usage[1];
+       vmids.vmid_usage[1] = 1 << pos;
+}
+
+static void add_ptb_to_table(struct vm_helper *vm_helper, unsigned int vmid, uint64_t ptb)
+{
+       vm_helper->ptb_assigned_to_vmid[vmid] = ptb;
+       vm_helper->num_vmids_available--;
+}
+
+static void clear_entry_from_vmid_table(struct vm_helper *vm_helper, unsigned int vmid)
+{
+       vm_helper->ptb_assigned_to_vmid[vmid] = 0;
+       vm_helper->num_vmids_available++;
+}
+
+static void evict_vmids(struct vm_helper *vm_helper)
+{
+       int i;
+       uint16_t ord = 0;
+
+       for (i = 0; i < vm_helper->num_vmid; i++)
+               ord |= vm_helper->hubp_vmid_usage[i].vmid_usage[0] | vm_helper->hubp_vmid_usage[i].vmid_usage[1];
+
+       // At this point any positions with value 0 are unused vmids, evict them
+       for (i = 1; i < vm_helper->num_vmid; i++) {
+               if (ord & (1u << i))
+                       clear_entry_from_vmid_table(vm_helper, i);
+       }
+}
+
+// Return value of -1 indicates vmid table unitialized or ptb dne in the table
+static int get_existing_vmid_for_ptb(struct vm_helper *vm_helper, uint64_t ptb)
+{
+       int i;
+
+       for (i = 0; i < vm_helper->num_vmid; i++) {
+               if (vm_helper->ptb_assigned_to_vmid[i] == ptb)
+                       return i;
+       }
+
+       return -1;
+}
+
+// Expected to be called only when there's an available vmid
+static int get_next_available_vmid(struct vm_helper *vm_helper)
+{
+       int i;
+
+       for (i = 1; i < vm_helper->num_vmid; i++) {
+               if (vm_helper->ptb_assigned_to_vmid[i] == 0)
+                       return i;
+       }
+
+       return -1;
+}
+
+uint8_t get_vmid_for_ptb(struct vm_helper *vm_helper, int64_t ptb, uint8_t hubp_idx)
+{
+       unsigned int vmid = 0;
+       int vmid_exists = -1;
+
+       // Physical address gets vmid 0
+       if (ptb == 0)
+               return 0;
+
+       vmid_exists = get_existing_vmid_for_ptb(vm_helper, ptb);
+
+       if (vmid_exists != -1) {
+               mark_vmid_used(vm_helper, vmid_exists, hubp_idx);
+               vmid = vmid_exists;
+       } else {
+               if (vm_helper->num_vmids_available == 0)
+                       evict_vmids(vm_helper);
+
+               vmid = get_next_available_vmid(vm_helper);
+               mark_vmid_used(vm_helper, vmid, hubp_idx);
+               add_ptb_to_table(vm_helper, vmid, ptb);
+       }
+
+       return vmid;
+}
+
+struct vm_helper init_vm_helper(unsigned int num_vmid, unsigned int num_hubp)
+{
+       static uint64_t ptb_assigned_to_vmid[MAX_VMID];
+       static struct vmid_usage hubp_vmid_usage[MAX_HUBP];
+
+       return (struct vm_helper){
+               .num_vmid = num_vmid,
+               .num_hubp = num_hubp,
+               .num_vmids_available = num_vmid - 1,
+               .ptb_assigned_to_vmid = ptb_assigned_to_vmid,
+               .hubp_vmid_usage = hubp_vmid_usage
+       };
+}
index 4b5bbb13ce7fedcbd8d1d9d1b1be39c2478a9634..8391bc39b7a9d7a9958c019c3fdc7c804eae32f8 100644 (file)
@@ -39,7 +39,7 @@
 #include "inc/hw/dmcu.h"
 #include "dml/display_mode_lib.h"
 
-#define DC_VER "3.2.08"
+#define DC_VER "3.2.15"
 
 #define MAX_SURFACES 3
 #define MAX_STREAMS 6
@@ -255,6 +255,7 @@ struct dc_debug_options {
        bool scl_reset_length10;
        bool hdmi20_disable;
        bool skip_detection_link_training;
+       unsigned int force_fclk_khz;
 };
 
 struct dc_debug_data {
@@ -339,8 +340,13 @@ struct dc_init_data {
        uint32_t log_mask;
 };
 
-struct dc *dc_create(const struct dc_init_data *init_params);
+struct dc_callback_init {
+       uint8_t reserved;
+};
 
+struct dc *dc_create(const struct dc_init_data *init_params);
+void dc_init_callbacks(struct dc *dc,
+               const struct dc_callback_init *init_params);
 void dc_destroy(struct dc **dc);
 
 /*******************************************************************************
@@ -440,6 +446,7 @@ union surface_update_flags {
                uint32_t coeff_reduction_change:1;
                uint32_t output_tf_change:1;
                uint32_t pixel_format_change:1;
+               uint32_t plane_size_change:1;
 
                /* Full updates */
                uint32_t new_plane:1;
@@ -652,6 +659,7 @@ struct dpcd_caps {
        int8_t branch_dev_name[6];
        int8_t branch_hw_revision;
        int8_t branch_fw_revision[2];
+       uint8_t link_rate_set;
 
        bool allow_invalid_MSA_timing_param;
        bool panel_mode_edp;
@@ -742,6 +750,9 @@ void dc_set_power_state(
                struct dc *dc,
                enum dc_acpi_cm_power_state power_state);
 void dc_resume(struct dc *dc);
+unsigned int dc_get_current_backlight_pwm(struct dc *dc);
+unsigned int dc_get_target_backlight_pwm(struct dc *dc);
+
 bool dc_is_dmcu_initialized(struct dc *dc);
 
 #endif /* DC_INTERFACE_H_ */
index a8b3cedf943171fbcdfbb9848f07e9edd5fa1875..78c3b300ec45cd8648c76b39415ccd095b110513 100644 (file)
@@ -86,10 +86,6 @@ struct dc_vbios_funcs {
 
        bool (*is_accelerated_mode)(
                struct dc_bios *bios);
-       bool (*is_active_display)(
-               struct dc_bios *bios,
-               enum signal_type signal,
-               const struct connector_device_tag_info *device_tag);
        void (*set_scratch_critical_state)(
                struct dc_bios *bios,
                bool state);
@@ -125,10 +121,6 @@ struct dc_vbios_funcs {
        enum bp_result (*program_crtc_timing)(
                struct dc_bios *bios,
                struct bp_hw_crtc_timing_parameters *bp_params);
-
-       enum bp_result (*crtc_source_select)(
-               struct dc_bios *bios,
-               struct bp_crtc_source_select *bp_params);
        enum bp_result (*program_display_engine_pll)(
                struct dc_bios *bios,
                struct bp_pixel_clock_parameters *bp_params);
@@ -145,7 +137,6 @@ struct dc_vbios_funcs {
 };
 
 struct bios_registers {
-       uint32_t BIOS_SCRATCH_0;
        uint32_t BIOS_SCRATCH_3;
        uint32_t BIOS_SCRATCH_6;
 };
index da93ab43f2d8a8c2c7910309fcd7bbf2300f13cd..d4eab33c453b99071df316f2202f3ab469799733 100644 (file)
@@ -46,11 +46,14 @@ enum dc_lane_count {
  */
 enum dc_link_rate {
        LINK_RATE_UNKNOWN = 0,
-       LINK_RATE_LOW = 0x06,
-       LINK_RATE_HIGH = 0x0A,
-       LINK_RATE_RBR2 = 0x0C,
-       LINK_RATE_HIGH2 = 0x14,
-       LINK_RATE_HIGH3 = 0x1E
+       LINK_RATE_LOW = 0x06,           // Rate_1 (RBR) - 1.62 Gbps/Lane
+       LINK_RATE_RATE_2 = 0x08,        // Rate_2               - 2.16 Gbps/Lane
+       LINK_RATE_RATE_3 = 0x09,        // Rate_3               - 2.43 Gbps/Lane
+       LINK_RATE_HIGH = 0x0A,          // Rate_4 (HBR) - 2.70 Gbps/Lane
+       LINK_RATE_RBR2 = 0x0C,          // Rate_5 (RBR2)- 3.24 Gbps/Lane
+       LINK_RATE_RATE_6 = 0x10,        // Rate_6               - 4.32 Gbps/Lane
+       LINK_RATE_HIGH2 = 0x14,         // Rate_7 (HBR2)- 5.40 Gbps/Lane
+       LINK_RATE_HIGH3 = 0x1E          // Rate_8 (HBR3)- 8.10 Gbps/Lane
 };
 
 enum dc_link_spread {
index 4842d2378bbf5b28884708926dd05ccae45130db..597d38393379d7891b4310a2344d66390fa166cb 100644 (file)
 #include "dm_services.h"
 #include <stdarg.h>
 
+struct dc_reg_value_masks {
+       uint32_t value;
+       uint32_t mask;
+};
+
+struct dc_reg_sequence {
+       uint32_t addr;
+       struct dc_reg_value_masks value_masks;
+};
+
+static inline void set_reg_field_value_masks(
+       struct dc_reg_value_masks *field_value_mask,
+       uint32_t value,
+       uint32_t mask,
+       uint8_t shift)
+{
+       ASSERT(mask != 0);
+
+       field_value_mask->value = (field_value_mask->value & ~mask) | (mask & (value << shift));
+       field_value_mask->mask = field_value_mask->mask | mask;
+}
+
 uint32_t generic_reg_update_ex(const struct dc_context *ctx,
                uint32_t addr, uint32_t reg_val, int n,
                uint8_t shift1, uint32_t mask1, uint32_t field_value1,
                ...)
 {
+       struct dc_reg_value_masks field_value_mask = {0};
        uint32_t shift, mask, field_value;
        int i = 1;
 
        va_list ap;
        va_start(ap, field_value1);
 
-       reg_val = set_reg_field_value_ex(reg_val, field_value1, mask1, shift1);
+       /* gather all bits value/mask getting updated in this register */
+       set_reg_field_value_masks(&field_value_mask,
+                       field_value1, mask1, shift1);
 
        while (i < n) {
                shift = va_arg(ap, uint32_t);
                mask = va_arg(ap, uint32_t);
                field_value = va_arg(ap, uint32_t);
 
-               reg_val = set_reg_field_value_ex(reg_val, field_value, mask, shift);
+               set_reg_field_value_masks(&field_value_mask,
+                               field_value, mask, shift);
                i++;
        }
-
-       dm_write_reg(ctx, addr, reg_val);
        va_end(ap);
 
+
+       /* mmio write directly */
+       reg_val = (reg_val & ~field_value_mask.mask) | field_value_mask.value;
+       dm_write_reg(ctx, addr, reg_val);
        return reg_val;
 }
 
index e72fce4eca65c9cbca3acb1e0fd38f3819b245b4..da55d623647a1c5559510115a0477c6a4792e941 100644 (file)
@@ -97,6 +97,8 @@ struct dc_plane_address {
                        union large_integer chroma_dcc_const_color;
                } video_progressive;
        };
+
+       union large_integer page_table_base;
 };
 
 struct dc_size {
@@ -730,7 +732,7 @@ struct dc_crtc_timing {
        uint32_t v_front_porch;
        uint32_t v_sync_width;
 
-       uint32_t pix_clk_khz;
+       uint32_t pix_clk_100hz;
 
        uint32_t vic;
        uint32_t hdmi_vic;
index 29f19d57ff7abd1e132ba89e65caa5d4f6bb2161..f249ff9be2a7a0254dbdac8625a320e5e14563bc 100644 (file)
@@ -110,6 +110,7 @@ struct dc_link {
        union ddi_channel_mapping ddi_channel_mapping;
        struct connector_device_tag_info device_tag;
        struct dpcd_caps dpcd_caps;
+       uint32_t dongle_max_pix_clk;
        unsigned short chip_caps;
        unsigned int dpcd_sink_count;
        enum edp_revision edp_revision;
@@ -146,8 +147,7 @@ static inline struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_
  */
 bool dc_link_set_backlight_level(const struct dc_link *dc_link,
                uint32_t backlight_pwm_u16_16,
-               uint32_t frame_ramp,
-               const struct dc_stream_state *stream);
+               uint32_t frame_ramp);
 
 int dc_link_get_backlight_level(const struct dc_link *dc_link);
 
index be34d638e15dfee01416e82e38d209d102403fde..7bb1da18c1bacce408a44b7c9859f292d2ff7b00 100644 (file)
@@ -38,11 +38,6 @@ struct dc_stream_status {
        int stream_enc_inst;
        int plane_count;
        struct dc_plane_state *plane_states[MAX_SURFACE_NUM];
-
-       /*
-        * link this stream passes through
-        */
-       struct dc_link *link;
 };
 
 // TODO: References to this needs to be removed..
@@ -51,7 +46,13 @@ struct freesync_context {
 };
 
 struct dc_stream_state {
+       // sink is deprecated, new code should not reference
+       // this pointer
        struct dc_sink *sink;
+
+       struct dc_link *link;
+       struct dc_panel_patch sink_patches;
+       union display_content_support content_support;
        struct dc_crtc_timing timing;
        struct dc_crtc_timing_adjust adjust;
        struct dc_info_packet vrr_infopacket;
@@ -80,6 +81,9 @@ struct dc_stream_state {
        enum view_3d_format view_format;
 
        bool ignore_msa_timing_param;
+       bool converter_disable_audio;
+       uint8_t qs_bit;
+       uint8_t qy_bit;
 
        unsigned long long periodic_fn_vsync_delta;
 
@@ -91,7 +95,6 @@ struct dc_stream_state {
 
        /* DMCU info */
        unsigned int abm_level;
-       unsigned int bl_pwm_level;
 
        /* from core_stream struct */
        struct dc_context *ctx;
@@ -105,6 +108,8 @@ struct dc_stream_state {
        bool dpms_off;
        bool apply_edp_fast_boot_optimization;
 
+       void *dm_stream_context;
+
        struct dc_cursor_attributes cursor_attributes;
        struct dc_cursor_position cursor_position;
        uint32_t sdr_white_level; // for boosting (SDR) cursor in HDR mode
@@ -117,6 +122,18 @@ struct dc_stream_state {
        /* Computed state bits */
        bool mode_changed : 1;
 
+       /* Output from DC when stream state is committed or altered
+        * DC may only access these values during:
+        * dc_commit_state, dc_commit_state_no_check, dc_commit_streams
+        * values may not change outside of those calls
+        */
+       struct {
+               // For interrupt management, some hardware instance
+               // offsets need to be exposed to DM
+               uint8_t otg_offset;
+       } out;
+
+       uint32_t stream_id;
 };
 
 struct dc_stream_update {
@@ -163,7 +180,6 @@ void dc_commit_updates_for_stream(struct dc *dc,
                int surface_count,
                struct dc_stream_state *stream,
                struct dc_stream_update *stream_update,
-               struct dc_plane_state **plane_states,
                struct dc_state *state);
 /*
  * Log the current stream state.
@@ -256,11 +272,14 @@ enum surface_update_type dc_check_update_surfaces_for_stream(
  */
 struct dc_stream_state *dc_create_stream_for_sink(struct dc_sink *dc_sink);
 
-void update_stream_signal(struct dc_stream_state *stream);
+void update_stream_signal(struct dc_stream_state *stream, struct dc_sink *sink);
 
 void dc_stream_retain(struct dc_stream_state *dc_stream);
 void dc_stream_release(struct dc_stream_state *dc_stream);
 
+struct dc_stream_status *dc_stream_get_status_from_state(
+       struct dc_state *state,
+       struct dc_stream_state *stream);
 struct dc_stream_status *dc_stream_get_status(
        struct dc_stream_state *dc_stream);
 
index 0b20ae23f169241aae3368470a339ad32a5d7255..56e7f3dab15a659940add6ca1d0f1c1eb5c22d54 100644 (file)
@@ -97,8 +97,8 @@ struct dc_context {
        struct dc_bios *dc_bios;
        bool created_bios;
        struct gpio_service *gpio_service;
-       struct i2caux *i2caux;
        uint32_t dc_sink_id_count;
+       uint32_t dc_stream_id_count;
        uint64_t fbc_gpu_addr;
 };
 
index aaeb7faac0c431a6b28812b5b83c63a48229fa54..adbb22224e1afb7c56da56c95f1af6c131621cc2 100644 (file)
@@ -24,6 +24,7 @@
  */
 
 #include "dm_services.h"
+#include "core_types.h"
 #include "dce_aux.h"
 #include "dce/dce_11_0_sh_mask.h"
 
        container_of((ptr), struct aux_engine_dce110, base)
 
 #define FROM_ENGINE(ptr) \
-       FROM_AUX_ENGINE(container_of((ptr), struct aux_engine, base))
+       FROM_AUX_ENGINE(container_of((ptr), struct dce_aux, base))
 
 #define FROM_AUX_ENGINE_ENGINE(ptr) \
-       container_of((ptr), struct aux_engine, base)
+       container_of((ptr), struct dce_aux, base)
 enum {
        AUX_INVALID_REPLY_RETRY_COUNTER = 1,
        AUX_TIMED_OUT_RETRY_COUNTER = 2,
        AUX_DEFER_RETRY_COUNTER = 6
 };
 static void release_engine(
-       struct aux_engine *engine)
+       struct dce_aux *engine)
 {
        struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
 
@@ -66,7 +67,7 @@ static void release_engine(
 #define DMCU_CAN_ACCESS_AUX 2
 
 static bool is_engine_available(
-       struct aux_engine *engine)
+       struct dce_aux *engine)
 {
        struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
 
@@ -79,7 +80,7 @@ static bool is_engine_available(
        return (field != DMCU_CAN_ACCESS_AUX);
 }
 static bool acquire_engine(
-       struct aux_engine *engine)
+       struct dce_aux *engine)
 {
        struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
 
@@ -155,7 +156,7 @@ static bool acquire_engine(
        (0xFF & (address))
 
 static void submit_channel_request(
-       struct aux_engine *engine,
+       struct dce_aux *engine,
        struct aux_request_transaction_data *request)
 {
        struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
@@ -247,7 +248,7 @@ static void submit_channel_request(
        REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1);
 }
 
-static int read_channel_reply(struct aux_engine *engine, uint32_t size,
+static int read_channel_reply(struct dce_aux *engine, uint32_t size,
                              uint8_t *buffer, uint8_t *reply_result,
                              uint32_t *sw_status)
 {
@@ -273,7 +274,8 @@ static int read_channel_reply(struct aux_engine *engine, uint32_t size,
 
        REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32);
        reply_result_32 = reply_result_32 >> 4;
-       *reply_result = (uint8_t)reply_result_32;
+       if (reply_result != NULL)
+               *reply_result = (uint8_t)reply_result_32;
 
        if (reply_result_32 == 0) { /* ACK */
                uint32_t i = 0;
@@ -299,61 +301,8 @@ static int read_channel_reply(struct aux_engine *engine, uint32_t size,
        return 0;
 }
 
-static void process_channel_reply(
-       struct aux_engine *engine,
-       struct aux_reply_transaction_data *reply)
-{
-       int bytes_replied;
-       uint8_t reply_result;
-       uint32_t sw_status;
-
-       bytes_replied = read_channel_reply(engine, reply->length, reply->data,
-                                          &reply_result, &sw_status);
-
-       /* in case HPD is LOW, exit AUX transaction */
-       if ((sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) {
-               reply->status = AUX_TRANSACTION_REPLY_HPD_DISCON;
-               return;
-       }
-
-       if (bytes_replied < 0) {
-               /* Need to handle an error case...
-                * Hopefully, upper layer function won't call this function if
-                * the number of bytes in the reply was 0, because there was
-                * surely an error that was asserted that should have been
-                * handled for hot plug case, this could happens
-                */
-               if (!(sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) {
-                       reply->status = AUX_TRANSACTION_REPLY_INVALID;
-                       ASSERT_CRITICAL(false);
-                       return;
-               }
-       } else {
-
-               switch (reply_result) {
-               case 0: /* ACK */
-                       reply->status = AUX_TRANSACTION_REPLY_AUX_ACK;
-               break;
-               case 1: /* NACK */
-                       reply->status = AUX_TRANSACTION_REPLY_AUX_NACK;
-               break;
-               case 2: /* DEFER */
-                       reply->status = AUX_TRANSACTION_REPLY_AUX_DEFER;
-               break;
-               case 4: /* AUX ACK / I2C NACK */
-                       reply->status = AUX_TRANSACTION_REPLY_I2C_NACK;
-               break;
-               case 8: /* AUX ACK / I2C DEFER */
-                       reply->status = AUX_TRANSACTION_REPLY_I2C_DEFER;
-               break;
-               default:
-                       reply->status = AUX_TRANSACTION_REPLY_INVALID;
-               }
-       }
-}
-
 static enum aux_channel_operation_result get_channel_status(
-       struct aux_engine *engine,
+       struct dce_aux *engine,
        uint8_t *returned_bytes)
 {
        struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
@@ -414,469 +363,22 @@ static enum aux_channel_operation_result get_channel_status(
                return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
        }
 }
-static void process_read_reply(
-       struct aux_engine *engine,
-       struct read_command_context *ctx)
-{
-       engine->funcs->process_channel_reply(engine, &ctx->reply);
-
-       switch (ctx->reply.status) {
-       case AUX_TRANSACTION_REPLY_AUX_ACK:
-               ctx->defer_retry_aux = 0;
-               if (ctx->returned_byte > ctx->current_read_length) {
-                       ctx->status =
-                               I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
-                       ctx->operation_succeeded = false;
-               } else if (ctx->returned_byte < ctx->current_read_length) {
-                       ctx->current_read_length -= ctx->returned_byte;
-
-                       ctx->offset += ctx->returned_byte;
-
-                       ++ctx->invalid_reply_retry_aux_on_ack;
-
-                       if (ctx->invalid_reply_retry_aux_on_ack >
-                               AUX_INVALID_REPLY_RETRY_COUNTER) {
-                               ctx->status =
-                               I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
-                               ctx->operation_succeeded = false;
-                       }
-               } else {
-                       ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
-                       ctx->transaction_complete = true;
-                       ctx->operation_succeeded = true;
-               }
-       break;
-       case AUX_TRANSACTION_REPLY_AUX_NACK:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
-               ctx->operation_succeeded = false;
-       break;
-       case AUX_TRANSACTION_REPLY_AUX_DEFER:
-               ++ctx->defer_retry_aux;
-
-               if (ctx->defer_retry_aux > AUX_DEFER_RETRY_COUNTER) {
-                       ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
-                       ctx->operation_succeeded = false;
-               }
-       break;
-       case AUX_TRANSACTION_REPLY_I2C_DEFER:
-               ctx->defer_retry_aux = 0;
-
-               ++ctx->defer_retry_i2c;
-
-               if (ctx->defer_retry_i2c > AUX_DEFER_RETRY_COUNTER) {
-                       ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
-                       ctx->operation_succeeded = false;
-               }
-       break;
-       case AUX_TRANSACTION_REPLY_HPD_DISCON:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
-               ctx->operation_succeeded = false;
-       break;
-       default:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
-               ctx->operation_succeeded = false;
-       }
-}
-static void process_read_request(
-       struct aux_engine *engine,
-       struct read_command_context *ctx)
-{
-       enum aux_channel_operation_result operation_result;
 
-       engine->funcs->submit_channel_request(engine, &ctx->request);
-
-       operation_result = engine->funcs->get_channel_status(
-               engine, &ctx->returned_byte);
-
-       switch (operation_result) {
-       case AUX_CHANNEL_OPERATION_SUCCEEDED:
-               if (ctx->returned_byte > ctx->current_read_length) {
-                       ctx->status =
-                               I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
-                       ctx->operation_succeeded = false;
-               } else {
-                       ctx->timed_out_retry_aux = 0;
-                       ctx->invalid_reply_retry_aux = 0;
-
-                       ctx->reply.length = ctx->returned_byte;
-                       ctx->reply.data = ctx->buffer;
-
-                       process_read_reply(engine, ctx);
-               }
-       break;
-       case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
-               ++ctx->invalid_reply_retry_aux;
-
-               if (ctx->invalid_reply_retry_aux >
-                       AUX_INVALID_REPLY_RETRY_COUNTER) {
-                       ctx->status =
-                               I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
-                       ctx->operation_succeeded = false;
-               } else
-                       udelay(400);
-       break;
-       case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
-               ++ctx->timed_out_retry_aux;
-
-               if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) {
-                       ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
-                       ctx->operation_succeeded = false;
-               } else {
-                       /* DP 1.2a, table 2-58:
-                        * "S3: AUX Request CMD PENDING:
-                        * retry 3 times, with 400usec wait on each"
-                        * The HW timeout is set to 550usec,
-                        * so we should not wait here
-                        */
-               }
-       break;
-       case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
-               ctx->operation_succeeded = false;
-       break;
-       default:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
-               ctx->operation_succeeded = false;
-       }
-}
-static bool read_command(
-       struct aux_engine *engine,
-       struct i2caux_transaction_request *request,
-       bool middle_of_transaction)
-{
-       struct read_command_context ctx;
-
-       ctx.buffer = request->payload.data;
-       ctx.current_read_length = request->payload.length;
-       ctx.offset = 0;
-       ctx.timed_out_retry_aux = 0;
-       ctx.invalid_reply_retry_aux = 0;
-       ctx.defer_retry_aux = 0;
-       ctx.defer_retry_i2c = 0;
-       ctx.invalid_reply_retry_aux_on_ack = 0;
-       ctx.transaction_complete = false;
-       ctx.operation_succeeded = true;
-
-       if (request->payload.address_space ==
-               I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
-               ctx.request.type = AUX_TRANSACTION_TYPE_DP;
-               ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_READ;
-               ctx.request.address = request->payload.address;
-       } else if (request->payload.address_space ==
-               I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) {
-               ctx.request.type = AUX_TRANSACTION_TYPE_I2C;
-               ctx.request.action = middle_of_transaction ?
-                       I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
-                       I2CAUX_TRANSACTION_ACTION_I2C_READ;
-               ctx.request.address = request->payload.address >> 1;
-       } else {
-               /* in DAL2, there was no return in such case */
-               BREAK_TO_DEBUGGER();
-               return false;
-       }
-
-       ctx.request.delay = 0;
-
-       do {
-               memset(ctx.buffer + ctx.offset, 0, ctx.current_read_length);
-
-               ctx.request.data = ctx.buffer + ctx.offset;
-               ctx.request.length = ctx.current_read_length;
-
-               process_read_request(engine, &ctx);
-
-               request->status = ctx.status;
-
-               if (ctx.operation_succeeded && !ctx.transaction_complete)
-                       if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C)
-                               msleep(engine->delay);
-       } while (ctx.operation_succeeded && !ctx.transaction_complete);
-
-       if (request->payload.address_space ==
-               I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
-               DC_LOG_I2C_AUX("READ: addr:0x%x  value:0x%x Result:%d",
-                               request->payload.address,
-                               request->payload.data[0],
-                               ctx.operation_succeeded);
-       }
-
-       return ctx.operation_succeeded;
-}
-
-static void process_write_reply(
-       struct aux_engine *engine,
-       struct write_command_context *ctx)
-{
-       engine->funcs->process_channel_reply(engine, &ctx->reply);
-
-       switch (ctx->reply.status) {
-       case AUX_TRANSACTION_REPLY_AUX_ACK:
-               ctx->operation_succeeded = true;
-
-               if (ctx->returned_byte) {
-                       ctx->request.action = ctx->mot ?
-                       I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT :
-                       I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
-
-                       ctx->current_write_length = 0;
-
-                       ++ctx->ack_m_retry;
-
-                       if (ctx->ack_m_retry > AUX_DEFER_RETRY_COUNTER) {
-                               ctx->status =
-                               I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
-                               ctx->operation_succeeded = false;
-                       } else
-                               udelay(300);
-               } else {
-                       ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
-                       ctx->defer_retry_aux = 0;
-                       ctx->ack_m_retry = 0;
-                       ctx->transaction_complete = true;
-               }
-       break;
-       case AUX_TRANSACTION_REPLY_AUX_NACK:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
-               ctx->operation_succeeded = false;
-       break;
-       case AUX_TRANSACTION_REPLY_AUX_DEFER:
-               ++ctx->defer_retry_aux;
-
-               if (ctx->defer_retry_aux > ctx->max_defer_retry) {
-                       ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
-                       ctx->operation_succeeded = false;
-               }
-       break;
-       case AUX_TRANSACTION_REPLY_I2C_DEFER:
-               ctx->defer_retry_aux = 0;
-               ctx->current_write_length = 0;
-
-               ctx->request.action = ctx->mot ?
-                       I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT :
-                       I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
-
-               ++ctx->defer_retry_i2c;
-
-               if (ctx->defer_retry_i2c > ctx->max_defer_retry) {
-                       ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
-                       ctx->operation_succeeded = false;
-               }
-       break;
-       case AUX_TRANSACTION_REPLY_HPD_DISCON:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
-               ctx->operation_succeeded = false;
-       break;
-       default:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
-               ctx->operation_succeeded = false;
-       }
-}
-static void process_write_request(
-       struct aux_engine *engine,
-       struct write_command_context *ctx)
-{
-       enum aux_channel_operation_result operation_result;
-
-       engine->funcs->submit_channel_request(engine, &ctx->request);
-
-       operation_result = engine->funcs->get_channel_status(
-               engine, &ctx->returned_byte);
-
-       switch (operation_result) {
-       case AUX_CHANNEL_OPERATION_SUCCEEDED:
-               ctx->timed_out_retry_aux = 0;
-               ctx->invalid_reply_retry_aux = 0;
-
-               ctx->reply.length = ctx->returned_byte;
-               ctx->reply.data = ctx->reply_data;
-
-               process_write_reply(engine, ctx);
-       break;
-       case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
-               ++ctx->invalid_reply_retry_aux;
-
-               if (ctx->invalid_reply_retry_aux >
-                       AUX_INVALID_REPLY_RETRY_COUNTER) {
-                       ctx->status =
-                               I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
-                       ctx->operation_succeeded = false;
-               } else
-                       udelay(400);
-       break;
-       case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
-               ++ctx->timed_out_retry_aux;
-
-               if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) {
-                       ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
-                       ctx->operation_succeeded = false;
-               } else {
-                       /* DP 1.2a, table 2-58:
-                        * "S3: AUX Request CMD PENDING:
-                        * retry 3 times, with 400usec wait on each"
-                        * The HW timeout is set to 550usec,
-                        * so we should not wait here
-                        */
-               }
-       break;
-       case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
-               ctx->operation_succeeded = false;
-       break;
-       default:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
-               ctx->operation_succeeded = false;
-       }
-}
-static bool write_command(
-       struct aux_engine *engine,
-       struct i2caux_transaction_request *request,
-       bool middle_of_transaction)
-{
-       struct write_command_context ctx;
-
-       ctx.mot = middle_of_transaction;
-       ctx.buffer = request->payload.data;
-       ctx.current_write_length = request->payload.length;
-       ctx.timed_out_retry_aux = 0;
-       ctx.invalid_reply_retry_aux = 0;
-       ctx.defer_retry_aux = 0;
-       ctx.defer_retry_i2c = 0;
-       ctx.ack_m_retry = 0;
-       ctx.transaction_complete = false;
-       ctx.operation_succeeded = true;
-
-       if (request->payload.address_space ==
-               I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
-               ctx.request.type = AUX_TRANSACTION_TYPE_DP;
-               ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_WRITE;
-               ctx.request.address = request->payload.address;
-       } else if (request->payload.address_space ==
-               I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) {
-               ctx.request.type = AUX_TRANSACTION_TYPE_I2C;
-               ctx.request.action = middle_of_transaction ?
-                       I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
-                       I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
-               ctx.request.address = request->payload.address >> 1;
-       } else {
-               /* in DAL2, there was no return in such case */
-               BREAK_TO_DEBUGGER();
-               return false;
-       }
-
-       ctx.request.delay = 0;
-
-       ctx.max_defer_retry =
-               (engine->max_defer_write_retry > AUX_DEFER_RETRY_COUNTER) ?
-                       engine->max_defer_write_retry : AUX_DEFER_RETRY_COUNTER;
-
-       do {
-               ctx.request.data = ctx.buffer;
-               ctx.request.length = ctx.current_write_length;
-
-               process_write_request(engine, &ctx);
-
-               request->status = ctx.status;
-
-               if (ctx.operation_succeeded && !ctx.transaction_complete)
-                       if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C)
-                               msleep(engine->delay);
-       } while (ctx.operation_succeeded && !ctx.transaction_complete);
-
-       if (request->payload.address_space ==
-               I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
-               DC_LOG_I2C_AUX("WRITE: addr:0x%x  value:0x%x Result:%d",
-                               request->payload.address,
-                               request->payload.data[0],
-                               ctx.operation_succeeded);
-       }
-
-       return ctx.operation_succeeded;
-}
-static bool end_of_transaction_command(
-       struct aux_engine *engine,
-       struct i2caux_transaction_request *request)
-{
-       struct i2caux_transaction_request dummy_request;
-       uint8_t dummy_data;
-
-       /* [tcheng] We only need to send the stop (read with MOT = 0)
-        * for I2C-over-Aux, not native AUX
-        */
-
-       if (request->payload.address_space !=
-               I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C)
-               return false;
-
-       dummy_request.operation = request->operation;
-       dummy_request.payload.address_space = request->payload.address_space;
-       dummy_request.payload.address = request->payload.address;
-
-       /*
-        * Add a dummy byte due to some receiver quirk
-        * where one byte is sent along with MOT = 0.
-        * Ideally this should be 0.
-        */
-
-       dummy_request.payload.length = 0;
-       dummy_request.payload.data = &dummy_data;
-
-       if (request->operation == I2CAUX_TRANSACTION_READ)
-               return read_command(engine, &dummy_request, false);
-       else
-               return write_command(engine, &dummy_request, false);
-
-       /* according Syed, it does not need now DoDummyMOT */
-}
-static bool submit_request(
-       struct aux_engine *engine,
-       struct i2caux_transaction_request *request,
-       bool middle_of_transaction)
-{
-
-       bool result;
-       bool mot_used = true;
-
-       switch (request->operation) {
-       case I2CAUX_TRANSACTION_READ:
-               result = read_command(engine, request, mot_used);
-       break;
-       case I2CAUX_TRANSACTION_WRITE:
-               result = write_command(engine, request, mot_used);
-       break;
-       default:
-               result = false;
-       }
-
-       /* [tcheng]
-        * need to send stop for the last transaction to free up the AUX
-        * if the above command fails, this would be the last transaction
-        */
-
-       if (!middle_of_transaction || !result)
-               end_of_transaction_command(engine, request);
-
-       /* mask AUX interrupt */
-
-       return result;
-}
 enum i2caux_engine_type get_engine_type(
-               const struct aux_engine *engine)
+               const struct dce_aux *engine)
 {
        return I2CAUX_ENGINE_TYPE_AUX;
 }
 
 static bool acquire(
-       struct aux_engine *engine,
+       struct dce_aux *engine,
        struct ddc *ddc)
 {
 
        enum gpio_result result;
 
-       if (engine->funcs->is_engine_available) {
-               /*check whether SW could use the engine*/
-               if (!engine->funcs->is_engine_available(engine))
-                       return false;
-       }
+       if (!is_engine_available(engine))
+               return false;
 
        result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
                GPIO_DDC_CONFIG_TYPE_MODE_AUX);
@@ -884,7 +386,7 @@ static bool acquire(
        if (result != GPIO_RESULT_OK)
                return false;
 
-       if (!engine->funcs->acquire_engine(engine)) {
+       if (!acquire_engine(engine)) {
                dal_ddc_close(ddc);
                return false;
        }
@@ -894,21 +396,7 @@ static bool acquire(
        return true;
 }
 
-static const struct aux_engine_funcs aux_engine_funcs = {
-       .acquire_engine = acquire_engine,
-       .submit_channel_request = submit_channel_request,
-       .process_channel_reply = process_channel_reply,
-       .read_channel_reply = read_channel_reply,
-       .get_channel_status = get_channel_status,
-       .is_engine_available = is_engine_available,
-       .release_engine = release_engine,
-       .destroy_engine = dce110_engine_destroy,
-       .submit_request = submit_request,
-       .get_engine_type = get_engine_type,
-       .acquire = acquire,
-};
-
-void dce110_engine_destroy(struct aux_engine **engine)
+void dce110_engine_destroy(struct dce_aux **engine)
 {
 
        struct aux_engine_dce110 *engine110 = FROM_AUX_ENGINE(*engine);
@@ -917,7 +405,7 @@ void dce110_engine_destroy(struct aux_engine **engine)
        *engine = NULL;
 
 }
-struct aux_engine *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110,
+struct dce_aux *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110,
                struct dc_context *ctx,
                uint32_t inst,
                uint32_t timeout_period,
@@ -927,7 +415,6 @@ struct aux_engine *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_eng
        aux_engine110->base.ctx = ctx;
        aux_engine110->base.delay = 0;
        aux_engine110->base.max_defer_write_retry = 0;
-       aux_engine110->base.funcs = &aux_engine_funcs;
        aux_engine110->base.inst = inst;
        aux_engine110->timeout_period = timeout_period;
        aux_engine110->regs = regs;
@@ -935,3 +422,101 @@ struct aux_engine *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_eng
        return &aux_engine110->base;
 }
 
+static enum i2caux_transaction_action i2caux_action_from_payload(struct aux_payload *payload)
+{
+       if (payload->i2c_over_aux) {
+               if (payload->write) {
+                       if (payload->mot)
+                               return I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT;
+                       return I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
+               }
+               if (payload->mot)
+                       return I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT;
+               return I2CAUX_TRANSACTION_ACTION_I2C_READ;
+       }
+       if (payload->write)
+               return I2CAUX_TRANSACTION_ACTION_DP_WRITE;
+       return I2CAUX_TRANSACTION_ACTION_DP_READ;
+}
+
+int dce_aux_transfer(struct ddc_service *ddc,
+               struct aux_payload *payload)
+{
+       struct ddc *ddc_pin = ddc->ddc_pin;
+       struct dce_aux *aux_engine;
+       enum aux_channel_operation_result operation_result;
+       struct aux_request_transaction_data aux_req;
+       struct aux_reply_transaction_data aux_rep;
+       uint8_t returned_bytes = 0;
+       int res = -1;
+       uint32_t status;
+
+       memset(&aux_req, 0, sizeof(aux_req));
+       memset(&aux_rep, 0, sizeof(aux_rep));
+
+       aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
+       acquire(aux_engine, ddc_pin);
+
+       if (payload->i2c_over_aux)
+               aux_req.type = AUX_TRANSACTION_TYPE_I2C;
+       else
+               aux_req.type = AUX_TRANSACTION_TYPE_DP;
+
+       aux_req.action = i2caux_action_from_payload(payload);
+
+       aux_req.address = payload->address;
+       aux_req.delay = payload->defer_delay * 10;
+       aux_req.length = payload->length;
+       aux_req.data = payload->data;
+
+       submit_channel_request(aux_engine, &aux_req);
+       operation_result = get_channel_status(aux_engine, &returned_bytes);
+
+       switch (operation_result) {
+       case AUX_CHANNEL_OPERATION_SUCCEEDED:
+               res = read_channel_reply(aux_engine, payload->length,
+                                                       payload->data, payload->reply,
+                                                       &status);
+               break;
+       case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
+               res = 0;
+               break;
+       case AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN:
+       case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
+       case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
+               res = -1;
+               break;
+       }
+       release_engine(aux_engine);
+       return res;
+}
+
+#define AUX_RETRY_MAX 7
+
+bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
+               struct aux_payload *payload)
+{
+       int i, ret = 0;
+       uint8_t reply;
+       bool payload_reply = true;
+
+       if (!payload->reply) {
+               payload_reply = false;
+               payload->reply = &reply;
+       }
+
+       for (i = 0; i < AUX_RETRY_MAX; i++) {
+               ret = dce_aux_transfer(ddc, payload);
+
+               if (ret >= 0) {
+                       if (*payload->reply == 0) {
+                               if (!payload_reply)
+                                       payload->reply = NULL;
+                               return true;
+                       }
+               }
+
+               msleep(1);
+       }
+       return false;
+}
index f7caab85dc801d75d260cf5d31aa2d65cc04718a..d27f22c05e4b5abd0085fb7252fccba5296f6831 100644 (file)
@@ -25,7 +25,9 @@
 
 #ifndef __DAL_AUX_ENGINE_DCE110_H__
 #define __DAL_AUX_ENGINE_DCE110_H__
-#include "aux_engine.h"
+
+#include "i2caux_interface.h"
+#include "inc/hw/aux_engine.h"
 
 #define AUX_COMMON_REG_LIST(id)\
        SRI(AUX_CONTROL, DP_AUX, id), \
@@ -75,8 +77,20 @@ enum {       /* This is the timeout as defined in DP 1.2a,
         */
        SW_AUX_TIMEOUT_PERIOD_MULTIPLIER = 4
 };
+
+struct dce_aux {
+       uint32_t inst;
+       struct ddc *ddc;
+       struct dc_context *ctx;
+       /* following values are expressed in milliseconds */
+       uint32_t delay;
+       uint32_t max_defer_write_retry;
+
+       bool acquire_reset;
+};
+
 struct aux_engine_dce110 {
-       struct aux_engine base;
+       struct dce_aux base;
        const struct dce110_aux_registers *regs;
        struct {
                uint32_t aux_control;
@@ -96,16 +110,22 @@ struct aux_engine_dce110_init_data {
        const struct dce110_aux_registers *regs;
 };
 
-struct aux_engine *dce110_aux_engine_construct(
+struct dce_aux *dce110_aux_engine_construct(
                struct aux_engine_dce110 *aux_engine110,
                struct dc_context *ctx,
                uint32_t inst,
                uint32_t timeout_period,
                const struct dce110_aux_registers *regs);
 
-void dce110_engine_destroy(struct aux_engine **engine);
+void dce110_engine_destroy(struct dce_aux **engine);
 
 bool dce110_aux_engine_acquire(
-       struct aux_engine *aux_engine,
+       struct dce_aux *aux_engine,
        struct ddc *ddc);
+
+int dce_aux_transfer(struct ddc_service *ddc,
+               struct aux_payload *cmd);
+
+bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
+               struct aux_payload *cmd);
 #endif
index afd287f08bc9520840ce1593c23d2cd98ae06cb1..3c52a4fc921d3a66181b8b45287d91159ff5a691 100644 (file)
@@ -194,8 +194,8 @@ static uint32_t get_max_pixel_clock_for_all_paths(struct dc_state *context)
                if (pipe_ctx->top_pipe)
                        continue;
 
-               if (pipe_ctx->stream_res.pix_clk_params.requested_pix_clk > max_pix_clk)
-                       max_pix_clk = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk;
+               if (pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10 > max_pix_clk)
+                       max_pix_clk = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10;
 
                /* raise clock state for HBR3/2 if required. Confirmed with HW DCE/DPCS
                 * logic for HBR3 still needs Nominal (0.8V) on VDDC rail
@@ -257,7 +257,7 @@ static int dce_set_clock(
                                clk_mgr_dce->dentist_vco_freq_khz / 64);
 
        /* Prepare to program display clock*/
-       pxl_clk_params.target_pixel_clock = requested_clk_khz;
+       pxl_clk_params.target_pixel_clock_100hz = requested_clk_khz * 10;
        pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS;
 
        if (clk_mgr_dce->dfs_bypass_active)
@@ -450,6 +450,42 @@ void dce_clock_read_ss_info(struct dce_clk_mgr *clk_mgr_dce)
        }
 }
 
+/**
+ * dce121_clock_patch_xgmi_ss_info() - Save XGMI spread spectrum info
+ * @clk_mgr: clock manager base structure
+ *
+ * Reads from VBIOS the XGMI spread spectrum info and saves it within
+ * the dce clock manager. This operation will overwrite the existing dprefclk
+ * SS values if the vBIOS query succeeds. Otherwise, it does nothing. It also
+ * sets the ->xgmi_enabled flag.
+ */
+void dce121_clock_patch_xgmi_ss_info(struct clk_mgr *clk_mgr)
+{
+       struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr);
+       enum bp_result result;
+       struct spread_spectrum_info info = { { 0 } };
+       struct dc_bios *bp = clk_mgr_dce->base.ctx->dc_bios;
+
+       clk_mgr_dce->xgmi_enabled = false;
+
+       result = bp->funcs->get_spread_spectrum_info(bp, AS_SIGNAL_TYPE_XGMI,
+                                                    0, &info);
+       if (result == BP_RESULT_OK && info.spread_spectrum_percentage != 0) {
+               clk_mgr_dce->xgmi_enabled = true;
+               clk_mgr_dce->ss_on_dprefclk = true;
+               clk_mgr_dce->dprefclk_ss_divider =
+                               info.spread_percentage_divider;
+
+               if (info.type.CENTER_MODE == 0) {
+                       /* Currently for DP Reference clock we
+                        * need only SS percentage for
+                        * downspread */
+                       clk_mgr_dce->dprefclk_ss_percentage =
+                                       info.spread_spectrum_percentage;
+               }
+       }
+}
+
 void dce110_fill_display_configs(
        const struct dc_state *context,
        struct dm_pp_display_configuration *pp_display_cfg)
@@ -483,18 +519,18 @@ void dce110_fill_display_configs(
                cfg->src_height = stream->src.height;
                cfg->src_width = stream->src.width;
                cfg->ddi_channel_mapping =
-                       stream->sink->link->ddi_channel_mapping.raw;
+                       stream->link->ddi_channel_mapping.raw;
                cfg->transmitter =
-                       stream->sink->link->link_enc->transmitter;
+                       stream->link->link_enc->transmitter;
                cfg->link_settings.lane_count =
-                       stream->sink->link->cur_link_settings.lane_count;
+                       stream->link->cur_link_settings.lane_count;
                cfg->link_settings.link_rate =
-                       stream->sink->link->cur_link_settings.link_rate;
+                       stream->link->cur_link_settings.link_rate;
                cfg->link_settings.link_spread =
-                       stream->sink->link->cur_link_settings.link_spread;
+                       stream->link->cur_link_settings.link_spread;
                cfg->sym_clock = stream->phy_pix_clk;
                /* Round v_refresh*/
-               cfg->v_refresh = stream->timing.pix_clk_khz * 1000;
+               cfg->v_refresh = stream->timing.pix_clk_100hz * 100;
                cfg->v_refresh /= stream->timing.h_total;
                cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2)
                                                        / stream->timing.v_total;
@@ -518,7 +554,7 @@ static uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context)
                         - stream->timing.v_addressable);
 
                vertical_blank_time = vertical_blank_in_pixels
-                       * 1000 / stream->timing.pix_clk_khz;
+                       * 10000 / stream->timing.pix_clk_100hz;
 
                if (min_vertical_blank_time > vertical_blank_time)
                        min_vertical_blank_time = vertical_blank_time;
@@ -612,7 +648,7 @@ static void dce11_pplib_apply_display_requirements(
 
                pp_display_cfg->crtc_index =
                        pp_display_cfg->disp_configs[0].pipe_idx;
-               pp_display_cfg->line_time_in_us = timing->h_total * 1000 / timing->pix_clk_khz;
+               pp_display_cfg->line_time_in_us = timing->h_total * 10000 / timing->pix_clk_100hz;
        }
 
        if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) !=  0)
@@ -625,11 +661,11 @@ static void dce_update_clocks(struct clk_mgr *clk_mgr,
 {
        struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr);
        struct dm_pp_power_level_change_request level_change_req;
-       int unpatched_disp_clk = context->bw.dce.dispclk_khz;
+       int patched_disp_clk = context->bw.dce.dispclk_khz;
 
        /*TODO: W/A for dal3 linux, investigate why this works */
        if (!clk_mgr_dce->dfs_bypass_active)
-               context->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz * 115 / 100;
+               patched_disp_clk = patched_disp_clk * 115 / 100;
 
        level_change_req.power_level = dce_get_required_clocks_state(clk_mgr, context);
        /* get max clock state from PPLIB */
@@ -639,13 +675,11 @@ static void dce_update_clocks(struct clk_mgr *clk_mgr,
                        clk_mgr_dce->cur_min_clks_state = level_change_req.power_level;
        }
 
-       if (should_set_clock(safe_to_lower, context->bw.dce.dispclk_khz, clk_mgr->clks.dispclk_khz)) {
-               context->bw.dce.dispclk_khz = dce_set_clock(clk_mgr, context->bw.dce.dispclk_khz);
-               clk_mgr->clks.dispclk_khz = context->bw.dce.dispclk_khz; 
+       if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) {
+               patched_disp_clk = dce_set_clock(clk_mgr, patched_disp_clk);
+               clk_mgr->clks.dispclk_khz = patched_disp_clk;
        }
        dce_pplib_apply_display_requirements(clk_mgr->ctx->dc, context);
-
-       context->bw.dce.dispclk_khz = unpatched_disp_clk;
 }
 
 static void dce11_update_clocks(struct clk_mgr *clk_mgr,
@@ -676,11 +710,11 @@ static void dce112_update_clocks(struct clk_mgr *clk_mgr,
 {
        struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr);
        struct dm_pp_power_level_change_request level_change_req;
-       int unpatched_disp_clk = context->bw.dce.dispclk_khz;
+       int patched_disp_clk = context->bw.dce.dispclk_khz;
 
        /*TODO: W/A for dal3 linux, investigate why this works */
        if (!clk_mgr_dce->dfs_bypass_active)
-               context->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz * 115 / 100;
+               patched_disp_clk = patched_disp_clk * 115 / 100;
 
        level_change_req.power_level = dce_get_required_clocks_state(clk_mgr, context);
        /* get max clock state from PPLIB */
@@ -690,13 +724,11 @@ static void dce112_update_clocks(struct clk_mgr *clk_mgr,
                        clk_mgr_dce->cur_min_clks_state = level_change_req.power_level;
        }
 
-       if (should_set_clock(safe_to_lower, context->bw.dce.dispclk_khz, clk_mgr->clks.dispclk_khz)) {
-               context->bw.dce.dispclk_khz = dce112_set_clock(clk_mgr, context->bw.dce.dispclk_khz);
-               clk_mgr->clks.dispclk_khz = context->bw.dce.dispclk_khz;
+       if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) {
+               patched_disp_clk = dce112_set_clock(clk_mgr, patched_disp_clk);
+               clk_mgr->clks.dispclk_khz = patched_disp_clk;
        }
        dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context);
-
-       context->bw.dce.dispclk_khz = unpatched_disp_clk;
 }
 
 static void dce12_update_clocks(struct clk_mgr *clk_mgr,
@@ -706,17 +738,23 @@ static void dce12_update_clocks(struct clk_mgr *clk_mgr,
        struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr);
        struct dm_pp_clock_for_voltage_req clock_voltage_req = {0};
        int max_pix_clk = get_max_pixel_clock_for_all_paths(context);
-       int unpatched_disp_clk = context->bw.dce.dispclk_khz;
+       int patched_disp_clk = context->bw.dce.dispclk_khz;
 
        /*TODO: W/A for dal3 linux, investigate why this works */
        if (!clk_mgr_dce->dfs_bypass_active)
-               context->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz * 115 / 100;
+               patched_disp_clk = patched_disp_clk * 115 / 100;
 
-       if (should_set_clock(safe_to_lower, context->bw.dce.dispclk_khz, clk_mgr->clks.dispclk_khz)) {
+       if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) {
                clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DISPLAY_CLK;
-               clock_voltage_req.clocks_in_khz = context->bw.dce.dispclk_khz;
-               context->bw.dce.dispclk_khz = dce112_set_clock(clk_mgr, context->bw.dce.dispclk_khz);
-               clk_mgr->clks.dispclk_khz = context->bw.dce.dispclk_khz;
+               /*
+                * When xGMI is enabled, the display clk needs to be adjusted
+                * with the WAFL link's SS percentage.
+                */
+               if (clk_mgr_dce->xgmi_enabled)
+                       patched_disp_clk = clk_mgr_adjust_dp_ref_freq_for_ss(
+                                       clk_mgr_dce, patched_disp_clk);
+               clock_voltage_req.clocks_in_khz = patched_disp_clk;
+               clk_mgr->clks.dispclk_khz = dce112_set_clock(clk_mgr, patched_disp_clk);
 
                dm_pp_apply_clock_for_voltage_request(clk_mgr->ctx, &clock_voltage_req);
        }
@@ -729,8 +767,6 @@ static void dce12_update_clocks(struct clk_mgr *clk_mgr,
                dm_pp_apply_clock_for_voltage_request(clk_mgr->ctx, &clock_voltage_req);
        }
        dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context);
-
-       context->bw.dce.dispclk_khz = unpatched_disp_clk;
 }
 
 static const struct clk_mgr_funcs dce120_funcs = {
@@ -882,6 +918,27 @@ struct clk_mgr *dce120_clk_mgr_create(struct dc_context *ctx)
        return &clk_mgr_dce->base;
 }
 
+struct clk_mgr *dce121_clk_mgr_create(struct dc_context *ctx)
+{
+       struct dce_clk_mgr *clk_mgr_dce = kzalloc(sizeof(*clk_mgr_dce),
+                                                 GFP_KERNEL);
+
+       if (clk_mgr_dce == NULL) {
+               BREAK_TO_DEBUGGER();
+               return NULL;
+       }
+
+       memcpy(clk_mgr_dce->max_clks_by_state, dce120_max_clks_by_state,
+              sizeof(dce120_max_clks_by_state));
+
+       dce_clk_mgr_construct(clk_mgr_dce, ctx, NULL, NULL, NULL);
+
+       clk_mgr_dce->dprefclk_khz = 625000;
+       clk_mgr_dce->base.funcs = &dce120_funcs;
+
+       return &clk_mgr_dce->base;
+}
+
 void dce_clk_mgr_destroy(struct clk_mgr **clk_mgr)
 {
        struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(*clk_mgr);
index 3bceb31d910d108d2df5a3d51dfd8cc5100d8ab8..c8f8c442142a14535e1285bd0344d7467d0d2606 100644 (file)
@@ -94,11 +94,37 @@ struct dce_clk_mgr {
         * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */
        int dfs_bypass_disp_clk;
 
-       /* Flag for Enabled SS on DPREFCLK */
+       /**
+        * @ss_on_dprefclk:
+        *
+        * True if spread spectrum is enabled on the DP ref clock.
+        */
        bool ss_on_dprefclk;
-       /* DPREFCLK SS percentage (if down-spread enabled) */
+
+       /**
+        * @xgmi_enabled:
+        *
+        * True if xGMI is enabled. On VG20, both audio and display clocks need
+        * to be adjusted with the WAFL link's SS info if xGMI is enabled.
+        */
+       bool xgmi_enabled;
+
+       /**
+        * @dprefclk_ss_percentage:
+        *
+        * DPREFCLK SS percentage (if down-spread enabled).
+        *
+        * Note that if XGMI is enabled, the SS info (percentage and divider)
+        * from the WAFL link is used instead. This is decided during
+        * dce_clk_mgr initialization.
+        */
        int dprefclk_ss_percentage;
-       /* DPREFCLK SS percentage Divider (100 or 1000) */
+
+       /**
+        * @dprefclk_ss_divider:
+        *
+        * DPREFCLK SS percentage Divider (100 or 1000).
+        */
        int dprefclk_ss_divider;
        int dprefclk_khz;
 
@@ -163,6 +189,9 @@ struct clk_mgr *dce112_clk_mgr_create(
 
 struct clk_mgr *dce120_clk_mgr_create(struct dc_context *ctx);
 
+struct clk_mgr *dce121_clk_mgr_create(struct dc_context *ctx);
+void dce121_clock_patch_xgmi_ss_info(struct clk_mgr *clk_mgr);
+
 void dce_clk_mgr_destroy(struct clk_mgr **clk_mgr);
 
 int dentist_get_divider_from_did(int did);
index 723ce80ed89c4bea22c90a5d805d4407ea29d3d4..c67e90e5c339c5d0945c3fe847f33645f53158c2 100644 (file)
@@ -108,28 +108,28 @@ static const struct spread_spectrum_data *get_ss_data_entry(
 }
 
 /**
-* Function: calculate_fb_and_fractional_fb_divider
-*
-* * DESCRIPTION: Calculates feedback and fractional feedback dividers values
-*
-*PARAMETERS:
-* targetPixelClock             Desired frequency in 10 KHz
-* ref_divider                  Reference divider (already known)
-* postDivider                  Post Divider (already known)
-* feedback_divider_param       Pointer where to store
-                                     calculated feedback divider value
-* fract_feedback_divider_param Pointer where to store
-                                     calculated fract feedback divider value
-*
-*RETURNS:
-* It fills the locations pointed by feedback_divider_param
-                                     and fract_feedback_divider_param
-* It returns   - true if feedback divider not 0
-             - false should never happen)
-*/
+ * Function: calculate_fb_and_fractional_fb_divider
+ *
+ * * DESCRIPTION: Calculates feedback and fractional feedback dividers values
+ *
+ *PARAMETERS:
+ * targetPixelClock             Desired frequency in 100 Hz
+ * ref_divider                  Reference divider (already known)
+ * postDivider                  Post Divider (already known)
+ * feedback_divider_param       Pointer where to store
+ *                                     calculated feedback divider value
+ * fract_feedback_divider_param Pointer where to store
+ *                                     calculated fract feedback divider value
+ *
+ *RETURNS:
+ * It fills the locations pointed by feedback_divider_param
+ *                                     and fract_feedback_divider_param
+ * It returns  - true if feedback divider not 0
+ *             - false should never happen)
+ */
 static bool calculate_fb_and_fractional_fb_divider(
                struct calc_pll_clock_source *calc_pll_cs,
-               uint32_t target_pix_clk_khz,
+               uint32_t target_pix_clk_100hz,
                uint32_t ref_divider,
                uint32_t post_divider,
                uint32_t *feedback_divider_param,
@@ -138,11 +138,11 @@ static bool calculate_fb_and_fractional_fb_divider(
        uint64_t feedback_divider;
 
        feedback_divider =
-               (uint64_t)target_pix_clk_khz * ref_divider * post_divider;
+               (uint64_t)target_pix_clk_100hz * ref_divider * post_divider;
        feedback_divider *= 10;
        /* additional factor, since we divide by 10 afterwards */
        feedback_divider *= (uint64_t)(calc_pll_cs->fract_fb_divider_factor);
-       feedback_divider = div_u64(feedback_divider, calc_pll_cs->ref_freq_khz);
+       feedback_divider = div_u64(feedback_divider, calc_pll_cs->ref_freq_khz * 10ull);
 
 /*Round to the number of precision
  * The following code replace the old code (ullfeedbackDivider + 5)/10
@@ -195,36 +195,36 @@ static bool calc_fb_divider_checking_tolerance(
 {
        uint32_t feedback_divider;
        uint32_t fract_feedback_divider;
-       uint32_t actual_calculated_clock_khz;
+       uint32_t actual_calculated_clock_100hz;
        uint32_t abs_err;
-       uint64_t actual_calc_clk_khz;
+       uint64_t actual_calc_clk_100hz;
 
        calculate_fb_and_fractional_fb_divider(
                        calc_pll_cs,
-                       pll_settings->adjusted_pix_clk,
+                       pll_settings->adjusted_pix_clk_100hz,
                        ref_divider,
                        post_divider,
                        &feedback_divider,
                        &fract_feedback_divider);
 
        /*Actual calculated value*/
-       actual_calc_clk_khz = (uint64_t)feedback_divider *
+       actual_calc_clk_100hz = (uint64_t)feedback_divider *
                                        calc_pll_cs->fract_fb_divider_factor +
                                                        fract_feedback_divider;
-       actual_calc_clk_khz *= calc_pll_cs->ref_freq_khz;
-       actual_calc_clk_khz =
-               div_u64(actual_calc_clk_khz,
+       actual_calc_clk_100hz *= calc_pll_cs->ref_freq_khz * 10;
+       actual_calc_clk_100hz =
+               div_u64(actual_calc_clk_100hz,
                        ref_divider * post_divider *
                                calc_pll_cs->fract_fb_divider_factor);
 
-       actual_calculated_clock_khz = (uint32_t)(actual_calc_clk_khz);
+       actual_calculated_clock_100hz = (uint32_t)(actual_calc_clk_100hz);
 
-       abs_err = (actual_calculated_clock_khz >
-                                       pll_settings->adjusted_pix_clk)
-                       ? actual_calculated_clock_khz -
-                                       pll_settings->adjusted_pix_clk
-                       : pll_settings->adjusted_pix_clk -
-                                               actual_calculated_clock_khz;
+       abs_err = (actual_calculated_clock_100hz >
+                                       pll_settings->adjusted_pix_clk_100hz)
+                       ? actual_calculated_clock_100hz -
+                                       pll_settings->adjusted_pix_clk_100hz
+                       : pll_settings->adjusted_pix_clk_100hz -
+                                               actual_calculated_clock_100hz;
 
        if (abs_err <= tolerance) {
                /*found good values*/
@@ -233,10 +233,10 @@ static bool calc_fb_divider_checking_tolerance(
                pll_settings->feedback_divider = feedback_divider;
                pll_settings->fract_feedback_divider = fract_feedback_divider;
                pll_settings->pix_clk_post_divider = post_divider;
-               pll_settings->calculated_pix_clk =
-                       actual_calculated_clock_khz;
+               pll_settings->calculated_pix_clk_100hz =
+                       actual_calculated_clock_100hz;
                pll_settings->vco_freq =
-                       actual_calculated_clock_khz * post_divider;
+                       actual_calculated_clock_100hz * post_divider / 10;
                return true;
        }
        return false;
@@ -257,8 +257,8 @@ static bool calc_pll_dividers_in_range(
 
 /* This is err_tolerance / 10000 = 0.0025 - acceptable error of 0.25%
  * This is errorTolerance / 10000 = 0.0001 - acceptable error of 0.01%*/
-       tolerance = (pll_settings->adjusted_pix_clk * err_tolerance) /
-                                                                       10000;
+       tolerance = (pll_settings->adjusted_pix_clk_100hz * err_tolerance) /
+                                                                       100000;
        if (tolerance < CALC_PLL_CLK_SRC_ERR_TOLERANCE)
                tolerance = CALC_PLL_CLK_SRC_ERR_TOLERANCE;
 
@@ -294,7 +294,7 @@ static uint32_t calculate_pixel_clock_pll_dividers(
        uint32_t min_ref_divider;
        uint32_t max_ref_divider;
 
-       if (pll_settings->adjusted_pix_clk == 0) {
+       if (pll_settings->adjusted_pix_clk_100hz == 0) {
                DC_LOG_ERROR(
                        "%s Bad requested pixel clock", __func__);
                return MAX_PLL_CALC_ERROR;
@@ -306,21 +306,21 @@ static uint32_t calculate_pixel_clock_pll_dividers(
                max_post_divider = pll_settings->pix_clk_post_divider;
        } else {
                min_post_divider = calc_pll_cs->min_pix_clock_pll_post_divider;
-               if (min_post_divider * pll_settings->adjusted_pix_clk <
-                                               calc_pll_cs->min_vco_khz) {
-                       min_post_divider = calc_pll_cs->min_vco_khz /
-                                       pll_settings->adjusted_pix_clk;
+               if (min_post_divider * pll_settings->adjusted_pix_clk_100hz <
+                                               calc_pll_cs->min_vco_khz * 10) {
+                       min_post_divider = calc_pll_cs->min_vco_khz * 10 /
+                                       pll_settings->adjusted_pix_clk_100hz;
                        if ((min_post_divider *
-                                       pll_settings->adjusted_pix_clk) <
-                                               calc_pll_cs->min_vco_khz)
+                                       pll_settings->adjusted_pix_clk_100hz) <
+                                               calc_pll_cs->min_vco_khz * 10)
                                min_post_divider++;
                }
 
                max_post_divider = calc_pll_cs->max_pix_clock_pll_post_divider;
-               if (max_post_divider * pll_settings->adjusted_pix_clk
-                               > calc_pll_cs->max_vco_khz)
-                       max_post_divider = calc_pll_cs->max_vco_khz /
-                                       pll_settings->adjusted_pix_clk;
+               if (max_post_divider * pll_settings->adjusted_pix_clk_100hz
+                               > calc_pll_cs->max_vco_khz * 10)
+                       max_post_divider = calc_pll_cs->max_vco_khz * 10 /
+                                       pll_settings->adjusted_pix_clk_100hz;
        }
 
 /* 2) Find Reference divider ranges
@@ -392,47 +392,47 @@ static bool pll_adjust_pix_clk(
                struct pixel_clk_params *pix_clk_params,
                struct pll_settings *pll_settings)
 {
-       uint32_t actual_pix_clk_khz = 0;
-       uint32_t requested_clk_khz = 0;
+       uint32_t actual_pix_clk_100hz = 0;
+       uint32_t requested_clk_100hz = 0;
        struct bp_adjust_pixel_clock_parameters bp_adjust_pixel_clock_params = {
                                                        0 };
        enum bp_result bp_result;
        switch (pix_clk_params->signal_type) {
        case SIGNAL_TYPE_HDMI_TYPE_A: {
-               requested_clk_khz = pix_clk_params->requested_pix_clk;
+               requested_clk_100hz = pix_clk_params->requested_pix_clk_100hz;
                if (pix_clk_params->pixel_encoding != PIXEL_ENCODING_YCBCR422) {
                        switch (pix_clk_params->color_depth) {
                        case COLOR_DEPTH_101010:
-                               requested_clk_khz = (requested_clk_khz * 5) >> 2;
+                               requested_clk_100hz = (requested_clk_100hz * 5) >> 2;
                                break; /* x1.25*/
                        case COLOR_DEPTH_121212:
-                               requested_clk_khz = (requested_clk_khz * 6) >> 2;
+                               requested_clk_100hz = (requested_clk_100hz * 6) >> 2;
                                break; /* x1.5*/
                        case COLOR_DEPTH_161616:
-                               requested_clk_khz = requested_clk_khz * 2;
+                               requested_clk_100hz = requested_clk_100hz * 2;
                                break; /* x2.0*/
                        default:
                                break;
                        }
                }
-               actual_pix_clk_khz = requested_clk_khz;
+               actual_pix_clk_100hz = requested_clk_100hz;
        }
                break;
 
        case SIGNAL_TYPE_DISPLAY_PORT:
        case SIGNAL_TYPE_DISPLAY_PORT_MST:
        case SIGNAL_TYPE_EDP:
-               requested_clk_khz = pix_clk_params->requested_sym_clk;
-               actual_pix_clk_khz = pix_clk_params->requested_pix_clk;
+               requested_clk_100hz = pix_clk_params->requested_sym_clk * 10;
+               actual_pix_clk_100hz = pix_clk_params->requested_pix_clk_100hz;
                break;
 
        default:
-               requested_clk_khz = pix_clk_params->requested_pix_clk;
-               actual_pix_clk_khz = pix_clk_params->requested_pix_clk;
+               requested_clk_100hz = pix_clk_params->requested_pix_clk_100hz;
+               actual_pix_clk_100hz = pix_clk_params->requested_pix_clk_100hz;
                break;
        }
 
-       bp_adjust_pixel_clock_params.pixel_clock = requested_clk_khz;
+       bp_adjust_pixel_clock_params.pixel_clock = requested_clk_100hz / 10;
        bp_adjust_pixel_clock_params.
                encoder_object_id = pix_clk_params->encoder_object_id;
        bp_adjust_pixel_clock_params.signal_type = pix_clk_params->signal_type;
@@ -441,9 +441,9 @@ static bool pll_adjust_pix_clk(
        bp_result = clk_src->bios->funcs->adjust_pixel_clock(
                        clk_src->bios, &bp_adjust_pixel_clock_params);
        if (bp_result == BP_RESULT_OK) {
-               pll_settings->actual_pix_clk = actual_pix_clk_khz;
-               pll_settings->adjusted_pix_clk =
-                       bp_adjust_pixel_clock_params.adjusted_pixel_clock;
+               pll_settings->actual_pix_clk_100hz = actual_pix_clk_100hz;
+               pll_settings->adjusted_pix_clk_100hz =
+                       bp_adjust_pixel_clock_params.adjusted_pixel_clock * 10;
                pll_settings->reference_divider =
                        bp_adjust_pixel_clock_params.reference_divider;
                pll_settings->pix_clk_post_divider =
@@ -490,7 +490,7 @@ static uint32_t dce110_get_pix_clk_dividers_helper (
                const struct spread_spectrum_data *ss_data = get_ss_data_entry(
                                        clk_src,
                                        pix_clk_params->signal_type,
-                                       pll_settings->adjusted_pix_clk);
+                                       pll_settings->adjusted_pix_clk_100hz / 10);
 
                if (NULL != ss_data)
                        pll_settings->ss_percentage = ss_data->percentage;
@@ -502,13 +502,13 @@ static uint32_t dce110_get_pix_clk_dividers_helper (
                 * to continue. */
                DC_LOG_ERROR(
                        "%s: Failed to adjust pixel clock!!", __func__);
-               pll_settings->actual_pix_clk =
-                               pix_clk_params->requested_pix_clk;
-               pll_settings->adjusted_pix_clk =
-                               pix_clk_params->requested_pix_clk;
+               pll_settings->actual_pix_clk_100hz =
+                               pix_clk_params->requested_pix_clk_100hz;
+               pll_settings->adjusted_pix_clk_100hz =
+                               pix_clk_params->requested_pix_clk_100hz;
 
                if (dc_is_dp_signal(pix_clk_params->signal_type))
-                       pll_settings->adjusted_pix_clk = 100000;
+                       pll_settings->adjusted_pix_clk_100hz = 1000000;
        }
 
        /* Calculate Dividers */
@@ -533,28 +533,28 @@ static void dce112_get_pix_clk_dividers_helper (
                struct pll_settings *pll_settings,
                struct pixel_clk_params *pix_clk_params)
 {
-       uint32_t actualPixelClockInKHz;
+       uint32_t actual_pixel_clock_100hz;
 
-       actualPixelClockInKHz = pix_clk_params->requested_pix_clk;
+       actual_pixel_clock_100hz = pix_clk_params->requested_pix_clk_100hz;
        /* Calculate Dividers */
        if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) {
                switch (pix_clk_params->color_depth) {
                case COLOR_DEPTH_101010:
-                       actualPixelClockInKHz = (actualPixelClockInKHz * 5) >> 2;
+                       actual_pixel_clock_100hz = (actual_pixel_clock_100hz * 5) >> 2;
                        break;
                case COLOR_DEPTH_121212:
-                       actualPixelClockInKHz = (actualPixelClockInKHz * 6) >> 2;
+                       actual_pixel_clock_100hz = (actual_pixel_clock_100hz * 6) >> 2;
                        break;
                case COLOR_DEPTH_161616:
-                       actualPixelClockInKHz = actualPixelClockInKHz * 2;
+                       actual_pixel_clock_100hz = actual_pixel_clock_100hz * 2;
                        break;
                default:
                        break;
                }
        }
-       pll_settings->actual_pix_clk = actualPixelClockInKHz;
-       pll_settings->adjusted_pix_clk = actualPixelClockInKHz;
-       pll_settings->calculated_pix_clk = pix_clk_params->requested_pix_clk;
+       pll_settings->actual_pix_clk_100hz = actual_pixel_clock_100hz;
+       pll_settings->adjusted_pix_clk_100hz = actual_pixel_clock_100hz;
+       pll_settings->calculated_pix_clk_100hz = pix_clk_params->requested_pix_clk_100hz;
 }
 
 static uint32_t dce110_get_pix_clk_dividers(
@@ -567,7 +567,7 @@ static uint32_t dce110_get_pix_clk_dividers(
        DC_LOGGER_INIT();
 
        if (pix_clk_params == NULL || pll_settings == NULL
-                       || pix_clk_params->requested_pix_clk == 0) {
+                       || pix_clk_params->requested_pix_clk_100hz == 0) {
                DC_LOG_ERROR(
                        "%s: Invalid parameters!!\n", __func__);
                return pll_calc_error;
@@ -577,10 +577,10 @@ static uint32_t dce110_get_pix_clk_dividers(
 
        if (cs->id == CLOCK_SOURCE_ID_DP_DTO ||
                        cs->id == CLOCK_SOURCE_ID_EXTERNAL) {
-               pll_settings->adjusted_pix_clk = clk_src->ext_clk_khz;
-               pll_settings->calculated_pix_clk = clk_src->ext_clk_khz;
-               pll_settings->actual_pix_clk =
-                                       pix_clk_params->requested_pix_clk;
+               pll_settings->adjusted_pix_clk_100hz = clk_src->ext_clk_khz * 10;
+               pll_settings->calculated_pix_clk_100hz = clk_src->ext_clk_khz * 10;
+               pll_settings->actual_pix_clk_100hz =
+                                       pix_clk_params->requested_pix_clk_100hz;
                return 0;
        }
 
@@ -599,7 +599,7 @@ static uint32_t dce112_get_pix_clk_dividers(
        DC_LOGGER_INIT();
 
        if (pix_clk_params == NULL || pll_settings == NULL
-                       || pix_clk_params->requested_pix_clk == 0) {
+                       || pix_clk_params->requested_pix_clk_100hz == 0) {
                DC_LOG_ERROR(
                        "%s: Invalid parameters!!\n", __func__);
                return -1;
@@ -609,10 +609,10 @@ static uint32_t dce112_get_pix_clk_dividers(
 
        if (cs->id == CLOCK_SOURCE_ID_DP_DTO ||
                        cs->id == CLOCK_SOURCE_ID_EXTERNAL) {
-               pll_settings->adjusted_pix_clk = clk_src->ext_clk_khz;
-               pll_settings->calculated_pix_clk = clk_src->ext_clk_khz;
-               pll_settings->actual_pix_clk =
-                                       pix_clk_params->requested_pix_clk;
+               pll_settings->adjusted_pix_clk_100hz = clk_src->ext_clk_khz * 10;
+               pll_settings->calculated_pix_clk_100hz = clk_src->ext_clk_khz * 10;
+               pll_settings->actual_pix_clk_100hz =
+                                       pix_clk_params->requested_pix_clk_100hz;
                return -1;
        }
 
@@ -714,7 +714,7 @@ static bool enable_spread_spectrum(
        ss_data = get_ss_data_entry(
                        clk_src,
                        signal,
-                       pll_settings->calculated_pix_clk);
+                       pll_settings->calculated_pix_clk_100hz / 10);
 
 /* Pixel clock PLL has been programmed to generate desired pixel clock,
  * now enable SS on pixel clock */
@@ -853,7 +853,7 @@ static bool dce110_program_pix_clk(
        /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/
        bp_pc_params.controller_id = pix_clk_params->controller_id;
        bp_pc_params.pll_id = clock_source->id;
-       bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk;
+       bp_pc_params.target_pixel_clock_100hz = pll_settings->actual_pix_clk_100hz;
        bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id;
        bp_pc_params.signal_type = pix_clk_params->signal_type;
 
@@ -903,12 +903,12 @@ static bool dce112_program_pix_clk(
 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        if (IS_FPGA_MAXIMUS_DC(clock_source->ctx->dce_environment)) {
                unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;
-               unsigned dp_dto_ref_kHz = 700000;
-               unsigned clock_kHz = pll_settings->actual_pix_clk;
+               unsigned dp_dto_ref_100hz = 7000000;
+               unsigned clock_100hz = pll_settings->actual_pix_clk_100hz;
 
                /* Set DTO values: phase = target clock, modulo = reference clock */
-               REG_WRITE(PHASE[inst], clock_kHz);
-               REG_WRITE(MODULO[inst], dp_dto_ref_kHz);
+               REG_WRITE(PHASE[inst], clock_100hz);
+               REG_WRITE(MODULO[inst], dp_dto_ref_100hz);
 
                /* Enable DTO */
                REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 1);
@@ -927,7 +927,7 @@ static bool dce112_program_pix_clk(
        /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/
        bp_pc_params.controller_id = pix_clk_params->controller_id;
        bp_pc_params.pll_id = clock_source->id;
-       bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk;
+       bp_pc_params.target_pixel_clock_100hz = pll_settings->actual_pix_clk_100hz;
        bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id;
        bp_pc_params.signal_type = pix_clk_params->signal_type;
 
index dea40b3221918279795828d701aa336174dc9073..c2926cf19dee537a0e2d3193f622dd6adb5c46b6 100644 (file)
@@ -51,7 +51,6 @@
 #define PSR_SET_WAITLOOP 0x31
 #define MCP_INIT_DMCU 0x88
 #define MCP_INIT_IRAM 0x89
-#define MCP_DMCU_VERSION 0x90
 #define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK   0x00000001L
 
 static bool dce_dmcu_init(struct dmcu *dmcu)
@@ -317,38 +316,11 @@ static void dce_get_psr_wait_loop(
 }
 
 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
-static void dcn10_get_dmcu_state(struct dmcu *dmcu)
-{
-       struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
-       uint32_t dmcu_state_offset = 0xf6;
-
-       /* Enable write access to IRAM */
-       REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL,
-                       IRAM_HOST_ACCESS_EN, 1,
-                       IRAM_RD_ADDR_AUTO_INC, 1);
-
-       REG_WAIT(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, 0, 2, 10);
-
-       /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */
-       REG_WRITE(DMCU_IRAM_RD_CTRL, dmcu_state_offset);
-
-       /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/
-       dmcu->dmcu_state = REG_READ(DMCU_IRAM_RD_DATA);
-
-       /* Disable write access to IRAM to allow dynamic sleep state */
-       REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL,
-                       IRAM_HOST_ACCESS_EN, 0,
-                       IRAM_RD_ADDR_AUTO_INC, 0);
-}
-
 static void dcn10_get_dmcu_version(struct dmcu *dmcu)
 {
        struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
        uint32_t dmcu_version_offset = 0xf1;
 
-       /* Clear scratch */
-       REG_WRITE(DC_DMCU_SCRATCH, 0);
-
        /* Enable write access to IRAM */
        REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL,
                        IRAM_HOST_ACCESS_EN, 1,
@@ -359,85 +331,74 @@ static void dcn10_get_dmcu_version(struct dmcu *dmcu)
        /* Write address to IRAM_RD_ADDR and read from DATA register */
        REG_WRITE(DMCU_IRAM_RD_CTRL, dmcu_version_offset);
        dmcu->dmcu_version.interface_version = REG_READ(DMCU_IRAM_RD_DATA);
-       dmcu->dmcu_version.year = ((REG_READ(DMCU_IRAM_RD_DATA) << 8) |
+       dmcu->dmcu_version.abm_version = REG_READ(DMCU_IRAM_RD_DATA);
+       dmcu->dmcu_version.psr_version = REG_READ(DMCU_IRAM_RD_DATA);
+       dmcu->dmcu_version.build_version = ((REG_READ(DMCU_IRAM_RD_DATA) << 8) |
                                                REG_READ(DMCU_IRAM_RD_DATA));
-       dmcu->dmcu_version.month = REG_READ(DMCU_IRAM_RD_DATA);
-       dmcu->dmcu_version.date = REG_READ(DMCU_IRAM_RD_DATA);
 
        /* Disable write access to IRAM to allow dynamic sleep state */
        REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL,
                        IRAM_HOST_ACCESS_EN, 0,
                        IRAM_RD_ADDR_AUTO_INC, 0);
-
-       /* Send MCP command message to DMCU to get version reply from FW.
-        * We expect this version should match the one in IRAM, otherwise
-        * something is wrong with DMCU and we should fail and disable UC.
-        */
-       REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800);
-
-       /* Set command to get DMCU version from microcontroller */
-       REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0,
-                       MCP_DMCU_VERSION);
-
-       /* Notify microcontroller of new command */
-       REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
-
-       /* Ensure command has been executed before continuing */
-       REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800);
-
-       /* Somehow version does not match, so fail and return version 0 */
-       if (dmcu->dmcu_version.interface_version != REG_READ(DC_DMCU_SCRATCH))
-               dmcu->dmcu_version.interface_version = 0;
 }
 
 static bool dcn10_dmcu_init(struct dmcu *dmcu)
 {
        struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
+       bool status = false;
 
-       /* DMCU FW should populate the scratch register if running */
-       if (REG_READ(DC_DMCU_SCRATCH) == 0)
-               return false;
-
-       /* Check state is uninitialized */
-       dcn10_get_dmcu_state(dmcu);
-
-       /* If microcontroller is already initialized, do nothing */
-       if (dmcu->dmcu_state == DMCU_RUNNING)
-               return true;
-
-       /* Retrieve and cache the DMCU firmware version. */
-       dcn10_get_dmcu_version(dmcu);
-
-       /* Check interface version to confirm firmware is loaded and running */
-       if (dmcu->dmcu_version.interface_version == 0)
-               return false;
+       /*  Definition of DC_DMCU_SCRATCH
+        *  0 : firmare not loaded
+        *  1 : PSP load DMCU FW but not initialized
+        *  2 : Firmware already initialized
+        */
+       dmcu->dmcu_state = REG_READ(DC_DMCU_SCRATCH);
 
-       /* Wait until microcontroller is ready to process interrupt */
-       REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800);
+       switch (dmcu->dmcu_state) {
+       case DMCU_UNLOADED:
+               status = false;
+               break;
+       case DMCU_LOADED_UNINITIALIZED:
+               /* Wait until microcontroller is ready to process interrupt */
+               REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800);
 
-       /* Set initialized ramping boundary value */
-       REG_WRITE(MASTER_COMM_DATA_REG1, 0xFFFF);
+               /* Set initialized ramping boundary value */
+               REG_WRITE(MASTER_COMM_DATA_REG1, 0xFFFF);
 
-       /* Set command to initialize microcontroller */
-       REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0,
+               /* Set command to initialize microcontroller */
+               REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0,
                        MCP_INIT_DMCU);
 
-       /* Notify microcontroller of new command */
-       REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
+               /* Notify microcontroller of new command */
+               REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
 
-       /* Ensure command has been executed before continuing */
-       REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800);
+               /* Ensure command has been executed before continuing */
+               REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800);
 
-       // Check state is initialized
-       dcn10_get_dmcu_state(dmcu);
+               // Check state is initialized
+               dmcu->dmcu_state = REG_READ(DC_DMCU_SCRATCH);
 
-       // If microcontroller is not in running state, fail
-       if (dmcu->dmcu_state != DMCU_RUNNING)
-               return false;
+               // If microcontroller is not in running state, fail
+               if (dmcu->dmcu_state == DMCU_RUNNING) {
+                       /* Retrieve and cache the DMCU firmware version. */
+                       dcn10_get_dmcu_version(dmcu);
+                       status = true;
+               } else
+                       status = false;
 
-       return true;
+               break;
+       case DMCU_RUNNING:
+               status = true;
+               break;
+       default:
+               status = false;
+               break;
+       }
+
+       return status;
 }
 
+
 static bool dcn10_dmcu_load_iram(struct dmcu *dmcu,
                unsigned int start_offset,
                const char *src,
index c83a7f05f14c11090b90d081f0e338af9c95bc63..956bdf14503fd40f8bd31d281079326d77ebb7ba 100644 (file)
        SR(DCHUB_AGP_TOP), \
        BL_REG_LIST()
 
+#define HWSEQ_VG20_REG_LIST() \
+       HWSEQ_DCE120_REG_LIST(),\
+       MMHUB_SR(MC_VM_XGMI_LFB_CNTL)
+
 #define HWSEQ_DCE112_REG_LIST() \
        HWSEQ_DCE10_REG_LIST(), \
        HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \
@@ -298,6 +302,7 @@ struct dce_hwseq_registers {
        uint32_t MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB;
        uint32_t MC_VM_SYSTEM_APERTURE_LOW_ADDR;
        uint32_t MC_VM_SYSTEM_APERTURE_HIGH_ADDR;
+       uint32_t MC_VM_XGMI_LFB_CNTL;
        uint32_t AZALIA_AUDIO_DTO;
        uint32_t AZALIA_CONTROLLER_CLOCK_GATING;
 };
@@ -382,6 +387,11 @@ struct dce_hwseq_registers {
        HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \
        HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh)
 
+#define HWSEQ_VG20_MASK_SH_LIST(mask_sh)\
+       HWSEQ_DCE12_MASK_SH_LIST(mask_sh),\
+       HWS_SF(, MC_VM_XGMI_LFB_CNTL, PF_LFB_REGION, mask_sh),\
+       HWS_SF(, MC_VM_XGMI_LFB_CNTL, PF_MAX_REGION, mask_sh)
+
 #define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\
        HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\
        HWS_SF1(OTG0_, PHYPLL_PIXEL_RATE_CNTL, PHYPLL_PIXEL_RATE_SOURCE, mask_sh), \
@@ -470,6 +480,8 @@ struct dce_hwseq_registers {
        type PHYSICAL_PAGE_NUMBER_MSB;\
        type PHYSICAL_PAGE_NUMBER_LSB;\
        type LOGICAL_ADDR; \
+       type PF_LFB_REGION;\
+       type PF_MAX_REGION;\
        type ENABLE_L1_TLB;\
        type SYSTEM_ACCESS_MODE;\
        type LVTMA_BLON;\
index 3e18ea84b1f961ef7ddfd5b701e91e62f5e8852c..314c04a915d212b2bcf85f14da72fa5cf0e32cb5 100644 (file)
@@ -599,12 +599,12 @@ bool dce110_link_encoder_validate_dvi_output(
        if ((connector_signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
                connector_signal == SIGNAL_TYPE_HDMI_TYPE_A) &&
                signal != SIGNAL_TYPE_HDMI_TYPE_A &&
-               crtc_timing->pix_clk_khz > TMDS_MAX_PIXEL_CLOCK)
+               crtc_timing->pix_clk_100hz > (TMDS_MAX_PIXEL_CLOCK * 10))
                return false;
-       if (crtc_timing->pix_clk_khz < TMDS_MIN_PIXEL_CLOCK)
+       if (crtc_timing->pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10))
                return false;
 
-       if (crtc_timing->pix_clk_khz > max_pixel_clock)
+       if (crtc_timing->pix_clk_100hz > (max_pixel_clock * 10))
                return false;
 
        /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */
@@ -788,7 +788,7 @@ bool dce110_link_encoder_validate_output_with_stream(
        case SIGNAL_TYPE_DVI_DUAL_LINK:
                is_valid = dce110_link_encoder_validate_dvi_output(
                        enc110,
-                       stream->sink->link->connector_signal,
+                       stream->link->connector_signal,
                        stream->signal,
                        &stream->timing);
        break;
index cce0d18f91da66ea5a3c641eba20ee524d5798a7..1fa2d4fd7a352a2b7525dc4bfc324fd2145ed3d0 100644 (file)
@@ -288,9 +288,18 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
 #endif
 
        struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
-
+       struct dc_crtc_timing hw_crtc_timing = *crtc_timing;
+       if (hw_crtc_timing.flags.INTERLACE) {
+               /*the input timing is in VESA spec format with Interlace flag =1*/
+               hw_crtc_timing.v_total /= 2;
+               hw_crtc_timing.v_border_top /= 2;
+               hw_crtc_timing.v_addressable /= 2;
+               hw_crtc_timing.v_border_bottom /= 2;
+               hw_crtc_timing.v_front_porch /= 2;
+               hw_crtc_timing.v_sync_width /= 2;
+       }
        /* set pixel encoding */
-       switch (crtc_timing->pixel_encoding) {
+       switch (hw_crtc_timing.pixel_encoding) {
        case PIXEL_ENCODING_YCBCR422:
                REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING,
                                DP_PIXEL_ENCODING_TYPE_YCBCR422);
@@ -299,8 +308,8 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
                REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING,
                                DP_PIXEL_ENCODING_TYPE_YCBCR444);
 
-               if (crtc_timing->flags.Y_ONLY)
-                       if (crtc_timing->display_color_depth != COLOR_DEPTH_666)
+               if (hw_crtc_timing.flags.Y_ONLY)
+                       if (hw_crtc_timing.display_color_depth != COLOR_DEPTH_666)
                                /* HW testing only, no use case yet.
                                 * Color depth of Y-only could be
                                 * 8, 10, 12, 16 bits */
@@ -335,7 +344,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
 
        /* set color depth */
 
-       switch (crtc_timing->display_color_depth) {
+       switch (hw_crtc_timing.display_color_depth) {
        case COLOR_DEPTH_666:
                REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH,
                                0);
@@ -363,7 +372,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
 
 
 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
-       switch (crtc_timing->display_color_depth) {
+       switch (hw_crtc_timing.display_color_depth) {
        case COLOR_DEPTH_666:
                colorimetry_bpc = 0;
                break;
@@ -401,9 +410,9 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
                        misc0 = misc0 | 0x8; /* bit3=1, bit4=0 */
                        misc1 = misc1 & ~0x80; /* bit7 = 0*/
                        dynamic_range_ycbcr = 0; /*bt601*/
-                       if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
+                       if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)
                                misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */
-                       else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444)
+                       else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444)
                                misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */
                        break;
                case COLOR_SPACE_YCBCR709:
@@ -411,9 +420,9 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
                        misc0 = misc0 | 0x18; /* bit3=1, bit4=1 */
                        misc1 = misc1 & ~0x80; /* bit7 = 0*/
                        dynamic_range_ycbcr = 1; /*bt709*/
-                       if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
+                       if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)
                                misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */
-                       else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444)
+                       else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444)
                                misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */
                        break;
                case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
@@ -453,27 +462,27 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
         */
                if (REG(DP_MSA_TIMING_PARAM1))
                        REG_SET_2(DP_MSA_TIMING_PARAM1, 0,
-                                       DP_MSA_HTOTAL, crtc_timing->h_total,
-                                       DP_MSA_VTOTAL, crtc_timing->v_total);
+                                       DP_MSA_HTOTAL, hw_crtc_timing.h_total,
+                                       DP_MSA_VTOTAL, hw_crtc_timing.v_total);
 #endif
 
                /* calcuate from vesa timing parameters
                 * h_active_start related to leading edge of sync
                 */
 
-               h_blank = crtc_timing->h_total - crtc_timing->h_border_left -
-                               crtc_timing->h_addressable - crtc_timing->h_border_right;
+               h_blank = hw_crtc_timing.h_total - hw_crtc_timing.h_border_left -
+                               hw_crtc_timing.h_addressable - hw_crtc_timing.h_border_right;
 
-               h_back_porch = h_blank - crtc_timing->h_front_porch -
-                               crtc_timing->h_sync_width;
+               h_back_porch = h_blank - hw_crtc_timing.h_front_porch -
+                               hw_crtc_timing.h_sync_width;
 
                /* start at begining of left border */
-               h_active_start = crtc_timing->h_sync_width + h_back_porch;
+               h_active_start = hw_crtc_timing.h_sync_width + h_back_porch;
 
 
-               v_active_start = crtc_timing->v_total - crtc_timing->v_border_top -
-                               crtc_timing->v_addressable - crtc_timing->v_border_bottom -
-                               crtc_timing->v_front_porch;
+               v_active_start = hw_crtc_timing.v_total - hw_crtc_timing.v_border_top -
+                               hw_crtc_timing.v_addressable - hw_crtc_timing.v_border_bottom -
+                               hw_crtc_timing.v_front_porch;
 
 
 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
@@ -486,21 +495,21 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
                if (REG(DP_MSA_TIMING_PARAM3))
                        REG_SET_4(DP_MSA_TIMING_PARAM3, 0,
                                        DP_MSA_HSYNCWIDTH,
-                                       crtc_timing->h_sync_width,
+                                       hw_crtc_timing.h_sync_width,
                                        DP_MSA_HSYNCPOLARITY,
-                                       !crtc_timing->flags.HSYNC_POSITIVE_POLARITY,
+                                       !hw_crtc_timing.flags.HSYNC_POSITIVE_POLARITY,
                                        DP_MSA_VSYNCWIDTH,
-                                       crtc_timing->v_sync_width,
+                                       hw_crtc_timing.v_sync_width,
                                        DP_MSA_VSYNCPOLARITY,
-                                       !crtc_timing->flags.VSYNC_POSITIVE_POLARITY);
+                                       !hw_crtc_timing.flags.VSYNC_POSITIVE_POLARITY);
 
                /* HWDITH include border or overscan */
                if (REG(DP_MSA_TIMING_PARAM4))
                        REG_SET_2(DP_MSA_TIMING_PARAM4, 0,
-                               DP_MSA_HWIDTH, crtc_timing->h_border_left +
-                               crtc_timing->h_addressable + crtc_timing->h_border_right,
-                               DP_MSA_VHEIGHT, crtc_timing->v_border_top +
-                               crtc_timing->v_addressable + crtc_timing->v_border_bottom);
+                               DP_MSA_HWIDTH, hw_crtc_timing.h_border_left +
+                               hw_crtc_timing.h_addressable + hw_crtc_timing.h_border_right,
+                               DP_MSA_VHEIGHT, hw_crtc_timing.v_border_top +
+                               hw_crtc_timing.v_addressable + hw_crtc_timing.v_border_bottom);
 #endif
        }
 #endif
@@ -662,7 +671,7 @@ static void dce110_stream_encoder_dvi_set_stream_attribute(
        cntl.signal = is_dual_link ?
                        SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK;
        cntl.enable_dp_audio = false;
-       cntl.pixel_clock = crtc_timing->pix_clk_khz;
+       cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10;
        cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR;
 
        if (enc110->base.bp->funcs->encoder_control(
@@ -686,7 +695,7 @@ static void dce110_stream_encoder_lvds_set_stream_attribute(
        cntl.engine_id = enc110->base.id;
        cntl.signal = SIGNAL_TYPE_LVDS;
        cntl.enable_dp_audio = false;
-       cntl.pixel_clock = crtc_timing->pix_clk_khz;
+       cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10;
        cntl.lanes_number = LANE_COUNT_FOUR;
 
        if (enc110->base.bp->funcs->encoder_control(
@@ -1575,6 +1584,14 @@ static void setup_stereo_sync(
        REG_UPDATE(DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, !enable);
 }
 
+static void dig_connect_to_otg(
+       struct stream_encoder *enc,
+       int tg_inst)
+{
+       struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+
+       REG_UPDATE(DIG_FE_CNTL, DIG_SOURCE_SELECT, tg_inst);
+}
 
 static const struct stream_encoder_funcs dce110_str_enc_funcs = {
        .dp_set_stream_attribute =
@@ -1609,7 +1626,7 @@ static const struct stream_encoder_funcs dce110_str_enc_funcs = {
        .hdmi_audio_disable = dce110_se_hdmi_audio_disable,
        .setup_stereo_sync  = setup_stereo_sync,
        .set_avmute = dce110_stream_encoder_set_avmute,
-
+       .dig_connect_to_otg  = dig_connect_to_otg,
 };
 
 void dce110_stream_encoder_construct(
index 6c28229c76ebe32ef1a76b2a2f9a76866a1b8472..f9cdf2b5242c1334dee80fcb230871e0f9d6b5a0 100644 (file)
        SE_SF(DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\
        SE_SF(DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\
        SE_SF(DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\
-       SE_SF(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh)
+       SE_SF(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh),\
+       SE_SF(DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh)
 
 #define SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh)\
        SE_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)
        SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\
        SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\
        SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\
-       SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh)
+       SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\
+       SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh)
 
 #define SE_COMMON_MASK_SH_LIST_SOC(mask_sh)\
        SE_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh)
@@ -494,6 +496,7 @@ struct dce_stream_encoder_shift {
        uint8_t HDMI_DB_DISABLE;
        uint8_t DP_VID_N_MUL;
        uint8_t DP_VID_M_DOUBLE_VALUE_EN;
+       uint8_t DIG_SOURCE_SELECT;
 };
 
 struct dce_stream_encoder_mask {
@@ -624,6 +627,7 @@ struct dce_stream_encoder_mask {
        uint32_t HDMI_DB_DISABLE;
        uint32_t DP_VID_N_MUL;
        uint32_t DP_VID_M_DOUBLE_VALUE_EN;
+       uint32_t DIG_SOURCE_SELECT;
 };
 
 struct dce110_stream_enc_registers {
index 6ae51a5dfc049da69d8530879c54eab38225e9c8..23044e6723e88311c8059d2d18dc19c58821b834 100644 (file)
@@ -76,6 +76,7 @@
 
 #ifndef mmBIOS_SCRATCH_2
        #define mmBIOS_SCRATCH_2 0x05CB
+       #define mmBIOS_SCRATCH_3 0x05CC
        #define mmBIOS_SCRATCH_6 0x05CF
 #endif
 
@@ -365,6 +366,7 @@ static const struct dce_abm_mask abm_mask = {
 #define DCFE_MEM_PWR_CTRL_REG_BASE 0x1b03
 
 static const struct bios_registers bios_regs = {
+       .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3,
        .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6
 };
 
@@ -587,7 +589,7 @@ struct output_pixel_processor *dce100_opp_create(
        return &opp->base;
 }
 
-struct aux_engine *dce100_aux_engine_create(
+struct dce_aux *dce100_aux_engine_create(
        struct dc_context *ctx,
        uint32_t inst)
 {
index 52d50e24a99538ac04cafaf58b1446ab71cc5385..7b23239d33fedfb164e17b958b8d73255aeae361 100644 (file)
@@ -62,8 +62,6 @@ static const struct dce110_compressor_reg_offsets reg_offsets[] = {
 }
 };
 
-static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600;
-
 static uint32_t align_to_chunks_number_per_line(uint32_t pixels)
 {
        return 256 * ((pixels + 255) / 256);
index 4bf24758217fdf7ad6537a0f5ec2fde7b5ad1950..db0ef41eb91c5d46cb19bad9214002b8f191bbd9 100644 (file)
@@ -614,55 +614,6 @@ dce110_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
        return true;
 }
 
-static enum dc_status bios_parser_crtc_source_select(
-               struct pipe_ctx *pipe_ctx)
-{
-       struct dc_bios *dcb;
-       /* call VBIOS table to set CRTC source for the HW
-        * encoder block
-        * note: video bios clears all FMT setting here. */
-       struct bp_crtc_source_select crtc_source_select = {0};
-       const struct dc_sink *sink = pipe_ctx->stream->sink;
-
-       crtc_source_select.engine_id = pipe_ctx->stream_res.stream_enc->id;
-       crtc_source_select.controller_id = pipe_ctx->stream_res.tg->inst + 1;
-       /*TODO: Need to un-hardcode color depth, dp_audio and account for
-        * the case where signal and sink signal is different (translator
-        * encoder)*/
-       crtc_source_select.signal = pipe_ctx->stream->signal;
-       crtc_source_select.enable_dp_audio = false;
-       crtc_source_select.sink_signal = pipe_ctx->stream->signal;
-
-       switch (pipe_ctx->stream->timing.display_color_depth) {
-       case COLOR_DEPTH_666:
-               crtc_source_select.display_output_bit_depth = PANEL_6BIT_COLOR;
-               break;
-       case COLOR_DEPTH_888:
-               crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR;
-               break;
-       case COLOR_DEPTH_101010:
-               crtc_source_select.display_output_bit_depth = PANEL_10BIT_COLOR;
-               break;
-       case COLOR_DEPTH_121212:
-               crtc_source_select.display_output_bit_depth = PANEL_12BIT_COLOR;
-               break;
-       default:
-               BREAK_TO_DEBUGGER();
-               crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR;
-               break;
-       }
-
-       dcb = sink->ctx->dc_bios;
-
-       if (BP_RESULT_OK != dcb->funcs->crtc_source_select(
-               dcb,
-               &crtc_source_select)) {
-               return DC_ERROR_UNEXPECTED;
-       }
-
-       return DC_OK;
-}
-
 void dce110_update_info_frame(struct pipe_ctx *pipe_ctx)
 {
        bool is_hdmi;
@@ -692,10 +643,10 @@ void dce110_update_info_frame(struct pipe_ctx *pipe_ctx)
 void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
 {
        enum dc_lane_count lane_count =
-               pipe_ctx->stream->sink->link->cur_link_settings.lane_count;
+               pipe_ctx->stream->link->cur_link_settings.lane_count;
 
        struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
-       struct dc_link *link = pipe_ctx->stream->sink->link;
+       struct dc_link *link = pipe_ctx->stream->link;
 
 
        uint32_t active_total_with_borders;
@@ -1000,7 +951,7 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
 
                pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio);
 
-               if (num_audio == 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
+               if (num_audio >= 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
                        /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
                        pp_smu->set_pme_wa_enable(&pp_smu->pp_smu);
                /* un-mute audio */
@@ -1017,6 +968,8 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
        pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
                        pipe_ctx->stream_res.stream_enc, true);
        if (pipe_ctx->stream_res.audio) {
+               struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu;
+
                if (option != KEEP_ACQUIRED_RESOURCE ||
                                !dc->debug.az_endpoint_mute_only) {
                        /*only disalbe az_endpoint if power down or free*/
@@ -1036,6 +989,9 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
                        update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false);
                        pipe_ctx->stream_res.audio = NULL;
                }
+               if (pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
+                       /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
+                       pp_smu->set_pme_wa_enable(&pp_smu->pp_smu);
 
                /* TODO: notify audio driver for if audio modes list changed
                 * add audio mode list change flag */
@@ -1048,7 +1004,7 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
 void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option)
 {
        struct dc_stream_state *stream = pipe_ctx->stream;
-       struct dc_link *link = stream->sink->link;
+       struct dc_link *link = stream->link;
        struct dc *dc = pipe_ctx->stream->ctx->dc;
 
        if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
@@ -1073,11 +1029,11 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
 {
        struct encoder_unblank_param params = { { 0 } };
        struct dc_stream_state *stream = pipe_ctx->stream;
-       struct dc_link *link = stream->sink->link;
+       struct dc_link *link = stream->link;
 
        /* only 3 items below are used by unblank */
        params.pixel_clk_khz =
-               pipe_ctx->stream->timing.pix_clk_khz;
+               pipe_ctx->stream->timing.pix_clk_100hz / 10;
        params.link_settings.link_rate = link_settings->link_rate;
 
        if (dc_is_dp_signal(pipe_ctx->stream->signal))
@@ -1090,7 +1046,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
 void dce110_blank_stream(struct pipe_ctx *pipe_ctx)
 {
        struct dc_stream_state *stream = pipe_ctx->stream;
-       struct dc_link *link = stream->sink->link;
+       struct dc_link *link = stream->link;
 
        if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
                link->dc->hwss.edp_backlight_control(link, false);
@@ -1163,27 +1119,27 @@ static void build_audio_output(
                        stream->timing.flags.INTERLACE;
 
        audio_output->crtc_info.refresh_rate =
-               (stream->timing.pix_clk_khz*1000)/
+               (stream->timing.pix_clk_100hz*10000)/
                (stream->timing.h_total*stream->timing.v_total);
 
        audio_output->crtc_info.color_depth =
                stream->timing.display_color_depth;
 
        audio_output->crtc_info.requested_pixel_clock =
-                       pipe_ctx->stream_res.pix_clk_params.requested_pix_clk;
+                       pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10;
 
        audio_output->crtc_info.calculated_pixel_clock =
-                       pipe_ctx->stream_res.pix_clk_params.requested_pix_clk;
+                       pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10;
 
 /*for HDMI, audio ACR is with deep color ratio factor*/
        if (dc_is_hdmi_signal(pipe_ctx->stream->signal) &&
                audio_output->crtc_info.requested_pixel_clock ==
-                               stream->timing.pix_clk_khz) {
+                               (stream->timing.pix_clk_100hz / 10)) {
                if (pipe_ctx->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) {
                        audio_output->crtc_info.requested_pixel_clock =
                                        audio_output->crtc_info.requested_pixel_clock/2;
                        audio_output->crtc_info.calculated_pixel_clock =
-                                       pipe_ctx->stream_res.pix_clk_params.requested_pix_clk/2;
+                                       pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz/20;
 
                }
        }
@@ -1385,12 +1341,10 @@ static enum dc_status apply_single_controller_ctx_to_hw(
        /*  */
        dc->hwss.enable_stream_timing(pipe_ctx, context, dc);
 
-       /* TODO: move to stream encoder */
        if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
-               if (DC_OK != bios_parser_crtc_source_select(pipe_ctx)) {
-                       BREAK_TO_DEBUGGER();
-                       return DC_ERROR_UNEXPECTED;
-               }
+               pipe_ctx->stream_res.stream_enc->funcs->dig_connect_to_otg(
+                       pipe_ctx->stream_res.stream_enc,
+                       pipe_ctx->stream_res.tg->inst);
 
        pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
                        pipe_ctx->stream_res.opp,
@@ -1408,7 +1362,7 @@ static enum dc_status apply_single_controller_ctx_to_hw(
 
        pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
 
-       pipe_ctx->stream->sink->link->psr_enabled = false;
+       pipe_ctx->stream->link->psr_enabled = false;
 
        return DC_OK;
 }
@@ -1518,7 +1472,7 @@ static struct dc_link *get_link_for_edp(struct dc *dc)
        return NULL;
 }
 
-static struct dc_link *get_link_for_edp_not_in_use(
+static struct dc_link *get_link_for_edp_to_turn_off(
                struct dc *dc,
                struct dc_state *context)
 {
@@ -1527,8 +1481,12 @@ static struct dc_link *get_link_for_edp_not_in_use(
 
        /* check if eDP panel is suppose to be set mode, if yes, no need to disable */
        for (i = 0; i < context->stream_count; i++) {
-               if (context->streams[i]->signal == SIGNAL_TYPE_EDP)
-                       return NULL;
+               if (context->streams[i]->signal == SIGNAL_TYPE_EDP) {
+                       if (context->streams[i]->dpms_off == true)
+                               return context->streams[i]->sink->link;
+                       else
+                               return NULL;
+               }
        }
 
        /* check if there is an eDP panel not in use */
@@ -1555,7 +1513,6 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
        int i;
        struct dc_link *edp_link_to_turnoff = NULL;
        struct dc_link *edp_link = get_link_for_edp(dc);
-       struct dc_bios *bios = dc->ctx->dc_bios;
        bool can_edp_fast_boot_optimize = false;
        bool apply_edp_fast_boot_optimization = false;
 
@@ -1571,7 +1528,7 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
        }
 
        if (can_edp_fast_boot_optimize)
-               edp_link_to_turnoff = get_link_for_edp_not_in_use(dc, context);
+               edp_link_to_turnoff = get_link_for_edp_to_turn_off(dc, context);
 
        /* if OS doesn't light up eDP and eDP link is available, we want to disable
         * If resume from S4/S5, should optimization.
@@ -1582,20 +1539,6 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
                        if (context->streams[i]->signal == SIGNAL_TYPE_EDP) {
                                context->streams[i]->apply_edp_fast_boot_optimization = true;
                                apply_edp_fast_boot_optimization = true;
-
-                               /* When after S4 and S5, vbios may post edp and previous dpms_off
-                                * doesn't make sense.
-                                * Update dpms_off state to align hw and sw state via check
-                                * vBios scratch register.
-                                */
-                               if (bios->funcs->is_active_display)     {
-                                       const struct connector_device_tag_info *device_tag = &(edp_link->device_tag);
-
-                                       if (bios->funcs->is_active_display(bios,
-                                                       context->streams[i]->signal,
-                                                       device_tag))
-                                               context->streams[i]->dpms_off = false;
-                               }
                        }
                }
        }
@@ -1624,8 +1567,8 @@ static uint32_t compute_pstate_blackout_duration(
        pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24;
 
        total_dest_line_time_ns = 1000000UL *
-               stream->timing.h_total /
-               stream->timing.pix_clk_khz +
+               (stream->timing.h_total * 10) /
+               stream->timing.pix_clk_100hz +
                pstate_blackout_duration_ns;
 
        return total_dest_line_time_ns;
@@ -1813,18 +1756,15 @@ static bool should_enable_fbc(struct dc *dc,
        if (i == dc->res_pool->pipe_count)
                return false;
 
-       if (!pipe_ctx->stream->sink)
-               return false;
-
-       if (!pipe_ctx->stream->sink->link)
+       if (!pipe_ctx->stream->link)
                return false;
 
        /* Only supports eDP */
-       if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP)
+       if (pipe_ctx->stream->link->connector_signal != SIGNAL_TYPE_EDP)
                return false;
 
        /* PSR should not be enabled */
-       if (pipe_ctx->stream->sink->link->psr_enabled)
+       if (pipe_ctx->stream->link->psr_enabled)
                return false;
 
        /* Nothing to compress */
@@ -2573,7 +2513,7 @@ static void dce110_apply_ctx_for_surface(
                                pipe_ctx->plane_res.mi,
                                pipe_ctx->stream->timing.h_total,
                                pipe_ctx->stream->timing.v_total,
-                               pipe_ctx->stream->timing.pix_clk_khz,
+                               pipe_ctx->stream->timing.pix_clk_100hz / 10,
                                context->stream_count);
 
                dce110_program_front_end_for_pipe(dc, pipe_ctx);
@@ -2622,13 +2562,35 @@ static void dce110_wait_for_mpcc_disconnect(
        /* do nothing*/
 }
 
+static void program_output_csc(struct dc *dc,
+               struct pipe_ctx *pipe_ctx,
+               enum dc_color_space colorspace,
+               uint16_t *matrix,
+               int opp_id)
+{
+       int i;
+       struct out_csc_color_matrix tbl_entry;
+
+       if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
+               enum dc_color_space color_space = pipe_ctx->stream->output_color_space;
+
+               for (i = 0; i < 12; i++)
+                       tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i];
+
+               tbl_entry.color_space = color_space;
+
+               pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment(
+                               pipe_ctx->plane_res.xfm, &tbl_entry);
+       }
+}
+
 void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx)
 {
        struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
        struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
        struct mem_input *mi = pipe_ctx->plane_res.mi;
        struct dc_cursor_mi_param param = {
-               .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz,
+               .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10,
                .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clock_inKhz,
                .viewport = pipe_ctx->plane_res.scl_data.viewport,
                .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz,
@@ -2672,6 +2634,7 @@ void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
 
 static const struct hw_sequencer_funcs dce110_funcs = {
        .program_gamut_remap = program_gamut_remap,
+       .program_output_csc = program_output_csc,
        .init_hw = init_hw,
        .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
        .apply_ctx_for_surface = dce110_apply_ctx_for_surface,
index e33d11785b1fd11300c45579178887e95d223a6b..7549adaa1542beb28ce8087ed3dd73ff6ab6a33f 100644 (file)
@@ -84,6 +84,7 @@
 
 #ifndef mmBIOS_SCRATCH_2
        #define mmBIOS_SCRATCH_2 0x05CB
+       #define mmBIOS_SCRATCH_3 0x05CC
        #define mmBIOS_SCRATCH_6 0x05CF
 #endif
 
@@ -369,6 +370,7 @@ static const struct dce110_clk_src_mask cs_mask = {
 };
 
 static const struct bios_registers bios_regs = {
+       .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3,
        .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6
 };
 
@@ -606,7 +608,7 @@ static struct output_pixel_processor *dce110_opp_create(
        return &opp->base;
 }
 
-struct aux_engine *dce110_aux_engine_create(
+struct dce_aux *dce110_aux_engine_create(
        struct dc_context *ctx,
        uint32_t inst)
 {
@@ -779,8 +781,8 @@ static void get_pixel_clock_parameters(
         * the pixel clock normalization for hdmi up to here instead of doing it
         * in pll_adjust_pix_clk
         */
-       pixel_clk_params->requested_pix_clk = stream->timing.pix_clk_khz;
-       pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id;
+       pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz;
+       pixel_clk_params->encoder_object_id = stream->link->link_enc->id;
        pixel_clk_params->signal_type = pipe_ctx->stream->signal;
        pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1;
        /* TODO: un-hardcode*/
@@ -797,10 +799,10 @@ static void get_pixel_clock_parameters(
                pixel_clk_params->color_depth = COLOR_DEPTH_888;
        }
        if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) {
-               pixel_clk_params->requested_pix_clk  = pixel_clk_params->requested_pix_clk / 2;
+               pixel_clk_params->requested_pix_clk_100hz  = pixel_clk_params->requested_pix_clk_100hz / 2;
        }
        if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
-               pixel_clk_params->requested_pix_clk *= 2;
+               pixel_clk_params->requested_pix_clk_100hz *= 2;
 
 }
 
@@ -874,7 +876,7 @@ static bool dce110_validate_bandwidth(
                        __func__,
                        context->streams[0]->timing.h_addressable,
                        context->streams[0]->timing.v_addressable,
-                       context->streams[0]->timing.pix_clk_khz);
+                       context->streams[0]->timing.pix_clk_100hz / 10);
 
        if (memcmp(&dc->current_state->bw.dce,
                        &context->bw.dce, sizeof(context->bw.dce))) {
@@ -1055,7 +1057,7 @@ static struct pipe_ctx *dce110_acquire_underlay(
                pipe_ctx->plane_res.mi->funcs->allocate_mem_input(pipe_ctx->plane_res.mi,
                                stream->timing.h_total,
                                stream->timing.v_total,
-                               stream->timing.pix_clk_khz,
+                               stream->timing.pix_clk_100hz / 10,
                                context->stream_count);
 
                color_space_to_black_color(dc,
index 969d4e72dc94266a77b601f94d6ffba7035f4a50..ea3065d633722bf6b1f2199e5b44eba055646460 100644 (file)
@@ -76,6 +76,7 @@
 
 #ifndef mmBIOS_SCRATCH_2
        #define mmBIOS_SCRATCH_2 0x05CB
+       #define mmBIOS_SCRATCH_3 0x05CC
        #define mmBIOS_SCRATCH_6 0x05CF
 #endif
 
@@ -376,6 +377,7 @@ static const struct dce110_clk_src_mask cs_mask = {
 };
 
 static const struct bios_registers bios_regs = {
+       .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3,
        .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6
 };
 
@@ -607,7 +609,7 @@ struct output_pixel_processor *dce112_opp_create(
        return &opp->base;
 }
 
-struct aux_engine *dce112_aux_engine_create(
+struct dce_aux *dce112_aux_engine_create(
        struct dc_context *ctx,
        uint32_t inst)
 {
@@ -763,7 +765,7 @@ static struct clock_source *find_matching_pll(
                const struct resource_pool *pool,
                const struct dc_stream_state *const stream)
 {
-       switch (stream->sink->link->link_enc->transmitter) {
+       switch (stream->link->link_enc->transmitter) {
        case TRANSMITTER_UNIPHY_A:
                return pool->clock_sources[DCE112_CLK_SRC_PLL0];
        case TRANSMITTER_UNIPHY_B:
index eb0f5f9a973b9b2f79793023d8f1cdf21aae787c..1ca30928025ed9484736a5be70059ac1a28ad964 100644 (file)
@@ -244,6 +244,21 @@ static void dce120_update_dchub(
        dh_data->dchub_info_valid = false;
 }
 
+/**
+ * dce121_xgmi_enabled() - Check if xGMI is enabled
+ * @hws: DCE hardware sequencer object
+ *
+ * Return true if xGMI is enabled. False otherwise.
+ */
+bool dce121_xgmi_enabled(struct dce_hwseq *hws)
+{
+       uint32_t pf_max_region;
+
+       REG_GET(MC_VM_XGMI_LFB_CNTL, PF_MAX_REGION, &pf_max_region);
+       /* PF_MAX_REGION == 0 means xgmi is disabled */
+       return !!pf_max_region;
+}
+
 void dce120_hw_sequencer_construct(struct dc *dc)
 {
        /* All registers used by dce11.2 match those in dce11 in offset and
index 77a6b86d7606df0f5a650734f8c424d6853c708c..c51afbd0b0124fcee60efd5838487d2ced7c8df5 100644 (file)
@@ -30,6 +30,7 @@
 
 struct dc;
 
+bool dce121_xgmi_enabled(struct dce_hwseq *hws);
 void dce120_hw_sequencer_construct(struct dc *dc);
 
 #endif /* __DC_HWSS_DCE112_H__ */
index f12696674eb0cb779f481ad4569ecca85825b069..312a0aebf91fab31d8d4a6f6e076b5ed3aaf3c9a 100644 (file)
@@ -62,6 +62,8 @@
 #include "soc15_hw_ip.h"
 #include "vega10_ip_offset.h"
 #include "nbio/nbio_6_1_offset.h"
+#include "mmhub/mmhub_9_4_0_offset.h"
+#include "mmhub/mmhub_9_4_0_sh_mask.h"
 #include "reg_helper.h"
 
 #include "dce100/dce100_resource.h"
@@ -139,6 +141,17 @@ static const struct dce110_timing_generator_offsets dce120_tg_offsets[] = {
        .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
                                        mm ## block ## id ## _ ## reg_name
 
+/* MMHUB */
+#define MMHUB_BASE_INNER(seg) \
+       MMHUB_BASE__INST0_SEG ## seg
+
+#define MMHUB_BASE(seg) \
+       MMHUB_BASE_INNER(seg)
+
+#define MMHUB_SR(reg_name)\
+               .reg_name = MMHUB_BASE(mm ## reg_name ## _BASE_IDX) +  \
+                                       mm ## reg_name
+
 /* macros to expend register list macro defined in HW object header file
  * end *********************/
 
@@ -378,7 +391,7 @@ struct output_pixel_processor *dce120_opp_create(
                             ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask);
        return &opp->base;
 }
-struct aux_engine *dce120_aux_engine_create(
+struct dce_aux *dce120_aux_engine_create(
        struct dc_context *ctx,
        uint32_t inst)
 {
@@ -429,6 +442,7 @@ struct dce_i2c_hw *dce120_i2c_hw_create(
        return dce_i2c_hw;
 }
 static const struct bios_registers bios_regs = {
+       .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3 + NBIO_BASE(mmBIOS_SCRATCH_3_BASE_IDX),
        .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 + NBIO_BASE(mmBIOS_SCRATCH_6_BASE_IDX)
 };
 
@@ -681,6 +695,19 @@ static const struct dce_hwseq_mask hwseq_mask = {
                HWSEQ_DCE12_MASK_SH_LIST(_MASK)
 };
 
+/* HWSEQ regs for VG20 */
+static const struct dce_hwseq_registers dce121_hwseq_reg = {
+               HWSEQ_VG20_REG_LIST()
+};
+
+static const struct dce_hwseq_shift dce121_hwseq_shift = {
+               HWSEQ_VG20_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dce_hwseq_mask dce121_hwseq_mask = {
+               HWSEQ_VG20_MASK_SH_LIST(_MASK)
+};
+
 static struct dce_hwseq *dce120_hwseq_create(
        struct dc_context *ctx)
 {
@@ -695,6 +722,20 @@ static struct dce_hwseq *dce120_hwseq_create(
        return hws;
 }
 
+static struct dce_hwseq *dce121_hwseq_create(
+       struct dc_context *ctx)
+{
+       struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL);
+
+       if (hws) {
+               hws->ctx = ctx;
+               hws->regs = &dce121_hwseq_reg;
+               hws->shifts = &dce121_hwseq_shift;
+               hws->masks = &dce121_hwseq_mask;
+       }
+       return hws;
+}
+
 static const struct resource_create_funcs res_create_funcs = {
        .read_dce_straps = read_dce_straps,
        .create_audio = create_audio,
@@ -702,6 +743,14 @@ static const struct resource_create_funcs res_create_funcs = {
        .create_hwseq = dce120_hwseq_create,
 };
 
+static const struct resource_create_funcs dce121_res_create_funcs = {
+       .read_dce_straps = read_dce_straps,
+       .create_audio = create_audio,
+       .create_stream_encoder = dce120_stream_encoder_create,
+       .create_hwseq = dce121_hwseq_create,
+};
+
+
 #define mi_inst_regs(id) { MI_DCE12_REG_LIST(id) }
 static const struct dce_mem_input_registers mi_regs[] = {
                mi_inst_regs(0),
@@ -911,7 +960,8 @@ static bool construct(
        int j;
        struct dc_context *ctx = dc->ctx;
        struct irq_service_init_data irq_init_data;
-       bool harvest_enabled = ASICREV_IS_VEGA20_P(ctx->asic_id.hw_internal_rev);
+       static const struct resource_create_funcs *res_funcs;
+       bool is_vg20 = ASICREV_IS_VEGA20_P(ctx->asic_id.hw_internal_rev);
        uint32_t pipe_fuses;
 
        ctx->dc_bios->regs = &bios_regs;
@@ -975,7 +1025,11 @@ static bool construct(
                }
        }
 
-       pool->base.clk_mgr = dce120_clk_mgr_create(ctx);
+       if (is_vg20)
+               pool->base.clk_mgr = dce121_clk_mgr_create(ctx);
+       else
+               pool->base.clk_mgr = dce120_clk_mgr_create(ctx);
+
        if (pool->base.clk_mgr == NULL) {
                dm_error("DC: failed to create display clock!\n");
                BREAK_TO_DEBUGGER();
@@ -1008,14 +1062,14 @@ static bool construct(
        if (!pool->base.irqs)
                goto irqs_create_fail;
 
-       /* retrieve valid pipe fuses */
-       if (harvest_enabled)
+       /* VG20: Pipe harvesting enabled, retrieve valid pipe fuses */
+       if (is_vg20)
                pipe_fuses = read_pipe_fuses(ctx);
 
        /* index to valid pipe resource */
        j = 0;
        for (i = 0; i < pool->base.pipe_count; i++) {
-               if (harvest_enabled) {
+               if (is_vg20) {
                        if ((pipe_fuses & (1 << i)) != 0) {
                                dm_error("DC: skip invalid pipe %d!\n", i);
                                continue;
@@ -1093,10 +1147,24 @@ static bool construct(
        pool->base.pipe_count = j;
        pool->base.timing_generator_count = j;
 
-       if (!resource_construct(num_virtual_links, dc, &pool->base,
-                        &res_create_funcs))
+       if (is_vg20)
+               res_funcs = &dce121_res_create_funcs;
+       else
+               res_funcs = &res_create_funcs;
+
+       if (!resource_construct(num_virtual_links, dc, &pool->base, res_funcs))
                goto res_create_fail;
 
+       /*
+        * This is a bit of a hack. The xGMI enabled info is used to determine
+        * if audio and display clocks need to be adjusted with the WAFL link's
+        * SS info. This is a responsiblity of the clk_mgr. But since MMHUB is
+        * under hwseq, and the relevant register is in MMHUB, we have to do it
+        * here.
+        */
+       if (is_vg20 && dce121_xgmi_enabled(dc->hwseq))
+               dce121_clock_patch_xgmi_ss_info(pool->base.clk_mgr);
+
        /* Create hardware sequencer */
        if (!dce120_hw_sequencer_create(dc))
                goto controller_create_fail;
index cdd1d6b7b9f2eb18cc1491bfe4b8ff9e5f470936..2eca81b5cf2f770cc08bba6eecb27d9d2afdff90 100644 (file)
@@ -77,6 +77,7 @@
 
 #ifndef mmBIOS_SCRATCH_2
        #define mmBIOS_SCRATCH_2 0x05CB
+       #define mmBIOS_SCRATCH_3 0x05CC
        #define mmBIOS_SCRATCH_6 0x05CF
 #endif
 
@@ -358,6 +359,7 @@ static const struct dce110_clk_src_mask cs_mask = {
 };
 
 static const struct bios_registers bios_regs = {
+       .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3,
        .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6
 };
 
@@ -467,7 +469,7 @@ static struct output_pixel_processor *dce80_opp_create(
        return &opp->base;
 }
 
-struct aux_engine *dce80_aux_engine_create(
+struct dce_aux *dce80_aux_engine_create(
        struct dc_context *ctx,
        uint32_t inst)
 {
index 3ba4712a35abfe6e681fb749e2e5fecf00a208f2..8b5ce557ee7180a3c6878a5650f7ff64c8ca2781 100644 (file)
@@ -84,17 +84,17 @@ static const struct dce110_timing_generator_offsets reg_offsets[] = {
 #define DCP_REG(reg) (reg + tg110->offsets.dcp)
 #define DMIF_REG(reg) (reg + tg110->offsets.dmif)
 
-static void program_pix_dur(struct timing_generator *tg, uint32_t pix_clk_khz)
+static void program_pix_dur(struct timing_generator *tg, uint32_t pix_clk_100hz)
 {
        uint64_t pix_dur;
        uint32_t addr = mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL1
                                        + DCE110TG_FROM_TG(tg)->offsets.dmif;
        uint32_t value = dm_read_reg(tg->ctx, addr);
 
-       if (pix_clk_khz == 0)
+       if (pix_clk_100hz == 0)
                return;
 
-       pix_dur = 1000000000 / pix_clk_khz;
+       pix_dur = div_u64(10000000000ull, pix_clk_100hz);
 
        set_reg_field_value(
                value,
@@ -110,7 +110,7 @@ static void program_timing(struct timing_generator *tg,
        bool use_vbios)
 {
        if (!use_vbios)
-               program_pix_dur(tg, timing->pix_clk_khz);
+               program_pix_dur(tg, timing->pix_clk_100hz);
 
        dce110_tg_program_timing(tg, timing, use_vbios);
 }
index 54abedbf1b43f7f2946ec574970d0654b037d169..afe8c42211cd52683536e60dbb222bbc06f76e04 100644 (file)
@@ -161,69 +161,17 @@ static int get_active_display_cnt(
        return display_count;
 }
 
-static void notify_deep_sleep_dcfclk_to_smu(
-               struct pp_smu_funcs_rv *pp_smu, int min_dcef_deep_sleep_clk_khz)
-{
-       int min_dcef_deep_sleep_clk_mhz; //minimum required DCEF Deep Sleep clock in mhz
-       /*
-        * if function pointer not set up, this message is
-        * sent as part of pplib_apply_display_requirements.
-        * So just return.
-        */
-       if (!pp_smu || !pp_smu->set_min_deep_sleep_dcfclk)
-               return;
-
-       min_dcef_deep_sleep_clk_mhz = (min_dcef_deep_sleep_clk_khz + 999) / 1000; //Round up
-       pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, min_dcef_deep_sleep_clk_mhz);
-}
-
-static void notify_hard_min_dcfclk_to_smu(
-               struct pp_smu_funcs_rv *pp_smu, int min_dcf_clk_khz)
-{
-       int min_dcf_clk_mhz; //minimum required DCF clock in mhz
-
-       /*
-        * if function pointer not set up, this message is
-        * sent as part of pplib_apply_display_requirements.
-        * So just return.
-        */
-       if (!pp_smu || !pp_smu->set_hard_min_dcfclk_by_freq)
-               return;
-
-       min_dcf_clk_mhz = min_dcf_clk_khz / 1000;
-
-       pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, min_dcf_clk_mhz);
-}
-
-static void notify_hard_min_fclk_to_smu(
-               struct pp_smu_funcs_rv *pp_smu, int min_f_clk_khz)
-{
-       int min_f_clk_mhz; //minimum required F clock in mhz
-
-       /*
-        * if function pointer not set up, this message is
-        * sent as part of pplib_apply_display_requirements.
-        * So just return.
-        */
-       if (!pp_smu || !pp_smu->set_hard_min_fclk_by_freq)
-               return;
-
-       min_f_clk_mhz = min_f_clk_khz / 1000;
-
-       pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, min_f_clk_mhz);
-}
-
 static void dcn1_update_clocks(struct clk_mgr *clk_mgr,
                        struct dc_state *context,
                        bool safe_to_lower)
 {
        struct dc *dc = clk_mgr->ctx->dc;
+       struct dc_debug_options *debug = &dc->debug;
        struct dc_clocks *new_clocks = &context->bw.dcn.clk;
        struct pp_smu_display_requirement_rv *smu_req_cur =
                        &dc->res_pool->pp_smu_req;
        struct pp_smu_display_requirement_rv smu_req = *smu_req_cur;
        struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu;
-       uint32_t requested_dcf_clock_in_khz = 0;
        bool send_request_to_increase = false;
        bool send_request_to_lower = false;
        int display_count;
@@ -243,9 +191,8 @@ static void dcn1_update_clocks(struct clk_mgr *clk_mgr,
                 */
                if (pp_smu->set_display_count)
                        pp_smu->set_display_count(&pp_smu->pp_smu, display_count);
-               else
-                       smu_req.display_count = display_count;
 
+               smu_req.display_count = display_count;
        }
 
        if (new_clocks->dispclk_khz > clk_mgr->clks.dispclk_khz
@@ -261,12 +208,13 @@ static void dcn1_update_clocks(struct clk_mgr *clk_mgr,
        }
 
        // F Clock
+       if (debug->force_fclk_khz != 0)
+               new_clocks->fclk_khz = debug->force_fclk_khz;
+
        if (should_set_clock(safe_to_lower, new_clocks->fclk_khz, clk_mgr->clks.fclk_khz)) {
                clk_mgr->clks.fclk_khz = new_clocks->fclk_khz;
                smu_req.hard_min_fclk_mhz = new_clocks->fclk_khz / 1000;
 
-               notify_hard_min_fclk_to_smu(pp_smu, new_clocks->fclk_khz);
-
                send_request_to_lower = true;
        }
 
@@ -281,7 +229,7 @@ static void dcn1_update_clocks(struct clk_mgr *clk_mgr,
        if (should_set_clock(safe_to_lower,
                        new_clocks->dcfclk_deep_sleep_khz, clk_mgr->clks.dcfclk_deep_sleep_khz)) {
                clk_mgr->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz;
-               smu_req.min_deep_sleep_dcefclk_mhz = new_clocks->dcfclk_deep_sleep_khz / 1000;
+               smu_req.min_deep_sleep_dcefclk_mhz = (new_clocks->dcfclk_deep_sleep_khz + 999) / 1000;
 
                send_request_to_lower = true;
        }
@@ -291,15 +239,18 @@ static void dcn1_update_clocks(struct clk_mgr *clk_mgr,
         */
        if (send_request_to_increase) {
                /*use dcfclk to request voltage*/
-               requested_dcf_clock_in_khz = dcn_find_dcfclk_suits_all(dc, new_clocks);
-
-               notify_hard_min_dcfclk_to_smu(pp_smu, requested_dcf_clock_in_khz);
-
-               if (pp_smu->set_display_requirement)
-                       pp_smu->set_display_requirement(&pp_smu->pp_smu, &smu_req);
-
-               notify_deep_sleep_dcfclk_to_smu(pp_smu, clk_mgr->clks.dcfclk_deep_sleep_khz);
-               dcn1_pplib_apply_display_requirements(dc, context);
+               if (pp_smu->set_hard_min_fclk_by_freq &&
+                               pp_smu->set_hard_min_dcfclk_by_freq &&
+                               pp_smu->set_min_deep_sleep_dcfclk) {
+
+                       pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, smu_req.hard_min_fclk_mhz);
+                       pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, smu_req.hard_min_dcefclk_mhz);
+                       pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, smu_req.min_deep_sleep_dcefclk_mhz);
+               } else {
+                       if (pp_smu->set_display_requirement)
+                               pp_smu->set_display_requirement(&pp_smu->pp_smu, &smu_req);
+                       dcn1_pplib_apply_display_requirements(dc, context);
+               }
        }
 
        /* dcn1 dppclk is tied to dispclk */
@@ -314,18 +265,20 @@ static void dcn1_update_clocks(struct clk_mgr *clk_mgr,
 
        if (!send_request_to_increase && send_request_to_lower) {
                /*use dcfclk to request voltage*/
-               requested_dcf_clock_in_khz = dcn_find_dcfclk_suits_all(dc, new_clocks);
-
-               notify_hard_min_dcfclk_to_smu(pp_smu, requested_dcf_clock_in_khz);
-
-               if (pp_smu->set_display_requirement)
-                       pp_smu->set_display_requirement(&pp_smu->pp_smu, &smu_req);
-
-               notify_deep_sleep_dcfclk_to_smu(pp_smu, clk_mgr->clks.dcfclk_deep_sleep_khz);
-               dcn1_pplib_apply_display_requirements(dc, context);
+               if (pp_smu->set_hard_min_fclk_by_freq &&
+                               pp_smu->set_hard_min_dcfclk_by_freq &&
+                               pp_smu->set_min_deep_sleep_dcfclk) {
+
+                       pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, smu_req.hard_min_fclk_mhz);
+                       pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, smu_req.hard_min_dcefclk_mhz);
+                       pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, smu_req.min_deep_sleep_dcefclk_mhz);
+               } else {
+                       if (pp_smu->set_display_requirement)
+                               pp_smu->set_display_requirement(&pp_smu->pp_smu, &smu_req);
+                       dcn1_pplib_apply_display_requirements(dc, context);
+               }
        }
 
-
        *smu_req_cur = smu_req;
 }
 static const struct clk_mgr_funcs dcn1_funcs = {
index dcb3c55302365f84f06a07700f76509ee2016526..cd1ebe57ed594844a392ec2e1f2f0071c3dddbfe 100644 (file)
@@ -463,7 +463,7 @@ void dpp1_set_cursor_position(
        if (src_y_offset >= (int)param->viewport.height)
                cur_en = 0;  /* not visible beyond bottom edge*/
 
-       if (src_y_offset < 0)
+       if (src_y_offset + (int)height <= 0)
                cur_en = 0;  /* not visible beyond top edge*/
 
        REG_UPDATE(CURSOR0_CONTROL,
index 116977eb24e222b2abedaef47a57b9fb190bf006..41f0f4c912e7bd8b7b3719ae1f6762fbc7c64684 100644 (file)
 
 #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
 
-struct dcn10_input_csc_matrix {
-       enum dc_color_space color_space;
-       uint16_t regval[12];
-};
 
 enum dcn10_coef_filter_type_sel {
        SCL_COEF_LUMA_VERT_FILTER = 0,
@@ -99,7 +95,7 @@ enum gamut_remap_select {
        GAMUT_REMAP_COMB_COEFF
 };
 
-static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = {
+static const struct dpp_input_csc_matrix dpp_input_csc_matrix[] = {
        {COLOR_SPACE_SRGB,
                {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
        {COLOR_SPACE_SRGB_LIMITED,
@@ -454,7 +450,7 @@ void dpp1_program_input_csc(
 {
        struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
        int i;
-       int arr_size = sizeof(dcn10_input_csc_matrix)/sizeof(struct dcn10_input_csc_matrix);
+       int arr_size = sizeof(dpp_input_csc_matrix)/sizeof(struct dpp_input_csc_matrix);
        const uint16_t *regval = NULL;
        uint32_t cur_select = 0;
        enum dcn10_input_csc_select select;
@@ -467,8 +463,8 @@ void dpp1_program_input_csc(
 
        if (tbl_entry == NULL) {
                for (i = 0; i < arr_size; i++)
-                       if (dcn10_input_csc_matrix[i].color_space == color_space) {
-                               regval = dcn10_input_csc_matrix[i].regval;
+                       if (dpp_input_csc_matrix[i].color_space == color_space) {
+                               regval = dpp_input_csc_matrix[i].regval;
                                break;
                        }
 
index 4a863a5dab4178103698f574e1fa64b9dd85a625..c7642e74829704c46c53a66099cca542cc537b3e 100644 (file)
@@ -597,11 +597,13 @@ static void dpp1_dscl_set_manual_ratio_init(
                SCL_V_INIT_FRAC, init_frac,
                SCL_V_INIT_INT, init_int);
 
-       init_frac = dc_fixpt_u0d19(data->inits.v_bot) << 5;
-       init_int = dc_fixpt_floor(data->inits.v_bot);
-       REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0,
-               SCL_V_INIT_FRAC_BOT, init_frac,
-               SCL_V_INIT_INT_BOT, init_int);
+       if (REG(SCL_VERT_FILTER_INIT_BOT)) {
+               init_frac = dc_fixpt_u0d19(data->inits.v_bot) << 5;
+               init_int = dc_fixpt_floor(data->inits.v_bot);
+               REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0,
+                       SCL_V_INIT_FRAC_BOT, init_frac,
+                       SCL_V_INIT_INT_BOT, init_int);
+       }
 
        init_frac = dc_fixpt_u0d19(data->inits.v_c) << 5;
        init_int = dc_fixpt_floor(data->inits.v_c);
@@ -609,11 +611,13 @@ static void dpp1_dscl_set_manual_ratio_init(
                SCL_V_INIT_FRAC_C, init_frac,
                SCL_V_INIT_INT_C, init_int);
 
-       init_frac = dc_fixpt_u0d19(data->inits.v_c_bot) << 5;
-       init_int = dc_fixpt_floor(data->inits.v_c_bot);
-       REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0,
-               SCL_V_INIT_FRAC_BOT_C, init_frac,
-               SCL_V_INIT_INT_BOT_C, init_int);
+       if (REG(SCL_VERT_FILTER_INIT_BOT_C)) {
+               init_frac = dc_fixpt_u0d19(data->inits.v_c_bot) << 5;
+               init_int = dc_fixpt_floor(data->inits.v_c_bot);
+               REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0,
+                       SCL_V_INIT_FRAC_BOT_C, init_frac,
+                       SCL_V_INIT_INT_BOT_C, init_int);
+       }
 }
 
 
@@ -688,15 +692,17 @@ void dpp1_dscl_set_scaler_manual_scale(
                return;
 
        /* Black offsets */
-       if (ycbcr)
-               REG_SET_2(SCL_BLACK_OFFSET, 0,
-                               SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
-                               SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR);
-       else
+       if (REG(SCL_BLACK_OFFSET)) {
+               if (ycbcr)
+                       REG_SET_2(SCL_BLACK_OFFSET, 0,
+                                       SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
+                                       SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR);
+               else
 
-               REG_SET_2(SCL_BLACK_OFFSET, 0,
-                               SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
-                               SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y);
+                       REG_SET_2(SCL_BLACK_OFFSET, 0,
+                                       SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
+                                       SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y);
+       }
 
        /* Manually calculate scale ratio and init values */
        dpp1_dscl_set_manual_ratio_init(dpp, scl_data);
index c7d1e678ebf5b1a22d2fc35e8b83e05d2ea50159..5a4614c371bcb9bd1d7c6f2a40f8707e4712bd22 100644 (file)
 #include "reg_helper.h"
 
 #define CTX \
-       hubbub->ctx
+       hubbub1->base.ctx
 #define DC_LOGGER \
-       hubbub->ctx->logger
+       hubbub1->base.ctx->logger
 #define REG(reg)\
-       hubbub->regs->reg
+       hubbub1->regs->reg
 
 #undef FN
 #define FN(reg_name, field_name) \
-       hubbub->shifts->field_name, hubbub->masks->field_name
+       hubbub1->shifts->field_name, hubbub1->masks->field_name
 
 void hubbub1_wm_read_state(struct hubbub *hubbub,
                struct dcn_hubbub_wm *wm)
 {
+       struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
        struct dcn_hubbub_wm_set *s;
 
        memset(wm, 0, sizeof(struct dcn_hubbub_wm));
@@ -89,12 +90,14 @@ void hubbub1_wm_read_state(struct hubbub *hubbub,
 
 void hubbub1_disable_allow_self_refresh(struct hubbub *hubbub)
 {
+       struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
        REG_UPDATE(DCHUBBUB_ARB_DRAM_STATE_CNTL,
                        DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, 0);
 }
 
 bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubbub)
 {
+       struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
        uint32_t enable = 0;
 
        REG_GET(DCHUBBUB_ARB_DRAM_STATE_CNTL,
@@ -107,6 +110,8 @@ bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubbub)
 bool hubbub1_verify_allow_pstate_change_high(
        struct hubbub *hubbub)
 {
+       struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
+
        /* pstate latency is ~20us so if we wait over 40us and pstate allow
         * still not asserted, we are probably stuck and going to hang
         *
@@ -193,7 +198,7 @@ bool hubbub1_verify_allow_pstate_change_high(
         * 31:    SOC pstate change request
         */
 
-       REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, hubbub->debug_test_index_pstate);
+       REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, hubbub1->debug_test_index_pstate);
 
        for (i = 0; i < pstate_wait_timeout_us; i++) {
                debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA);
@@ -244,6 +249,8 @@ static uint32_t convert_and_clamp(
 
 void hubbub1_wm_change_req_wa(struct hubbub *hubbub)
 {
+       struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
+
        REG_UPDATE_SEQ(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
                        DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0, 1);
 }
@@ -254,7 +261,9 @@ void hubbub1_program_watermarks(
                unsigned int refclk_mhz,
                bool safe_to_lower)
 {
-       uint32_t force_en = hubbub->ctx->dc->debug.disable_stutter ? 1 : 0;
+       struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
+
+       uint32_t force_en = hubbub1->base.ctx->dc->debug.disable_stutter ? 1 : 0;
        /*
         * Need to clamp to max of the register values (i.e. no wrap)
         * for dcn1, all wm registers are 21-bit wide
@@ -264,8 +273,8 @@ void hubbub1_program_watermarks(
 
        /* Repeat for water mark set A, B, C and D. */
        /* clock state A */
-       if (safe_to_lower || watermarks->a.urgent_ns > hubbub->watermarks.a.urgent_ns) {
-               hubbub->watermarks.a.urgent_ns = watermarks->a.urgent_ns;
+       if (safe_to_lower || watermarks->a.urgent_ns > hubbub1->watermarks.a.urgent_ns) {
+               hubbub1->watermarks.a.urgent_ns = watermarks->a.urgent_ns;
                prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns,
                                refclk_mhz, 0x1fffff);
                REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value);
@@ -275,20 +284,22 @@ void hubbub1_program_watermarks(
                        watermarks->a.urgent_ns, prog_wm_value);
        }
 
-       if (safe_to_lower || watermarks->a.pte_meta_urgent_ns > hubbub->watermarks.a.pte_meta_urgent_ns) {
-               hubbub->watermarks.a.pte_meta_urgent_ns = watermarks->a.pte_meta_urgent_ns;
-               prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns,
-                               refclk_mhz, 0x1fffff);
-               REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value);
-               DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_A calculated =%d\n"
-                       "HW register value = 0x%x\n",
-                       watermarks->a.pte_meta_urgent_ns, prog_wm_value);
+       if (REG(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A)) {
+               if (safe_to_lower || watermarks->a.pte_meta_urgent_ns > hubbub1->watermarks.a.pte_meta_urgent_ns) {
+                       hubbub1->watermarks.a.pte_meta_urgent_ns = watermarks->a.pte_meta_urgent_ns;
+                       prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns,
+                                       refclk_mhz, 0x1fffff);
+                       REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value);
+                       DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_A calculated =%d\n"
+                               "HW register value = 0x%x\n",
+                               watermarks->a.pte_meta_urgent_ns, prog_wm_value);
+               }
        }
 
        if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A)) {
                if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
-                               > hubbub->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) {
-                       hubbub->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns =
+                               > hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) {
+                       hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns =
                                        watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns;
                        prog_wm_value = convert_and_clamp(
                                        watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns,
@@ -300,8 +311,8 @@ void hubbub1_program_watermarks(
                }
 
                if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns
-                               > hubbub->watermarks.a.cstate_pstate.cstate_exit_ns) {
-                       hubbub->watermarks.a.cstate_pstate.cstate_exit_ns =
+                               > hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns) {
+                       hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns =
                                        watermarks->a.cstate_pstate.cstate_exit_ns;
                        prog_wm_value = convert_and_clamp(
                                        watermarks->a.cstate_pstate.cstate_exit_ns,
@@ -314,8 +325,8 @@ void hubbub1_program_watermarks(
        }
 
        if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns
-                       > hubbub->watermarks.a.cstate_pstate.pstate_change_ns) {
-               hubbub->watermarks.a.cstate_pstate.pstate_change_ns =
+                       > hubbub1->watermarks.a.cstate_pstate.pstate_change_ns) {
+               hubbub1->watermarks.a.cstate_pstate.pstate_change_ns =
                                watermarks->a.cstate_pstate.pstate_change_ns;
                prog_wm_value = convert_and_clamp(
                                watermarks->a.cstate_pstate.pstate_change_ns,
@@ -327,8 +338,8 @@ void hubbub1_program_watermarks(
        }
 
        /* clock state B */
-       if (safe_to_lower || watermarks->b.urgent_ns > hubbub->watermarks.b.urgent_ns) {
-               hubbub->watermarks.b.urgent_ns = watermarks->b.urgent_ns;
+       if (safe_to_lower || watermarks->b.urgent_ns > hubbub1->watermarks.b.urgent_ns) {
+               hubbub1->watermarks.b.urgent_ns = watermarks->b.urgent_ns;
                prog_wm_value = convert_and_clamp(watermarks->b.urgent_ns,
                                refclk_mhz, 0x1fffff);
                REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value);
@@ -338,20 +349,22 @@ void hubbub1_program_watermarks(
                        watermarks->b.urgent_ns, prog_wm_value);
        }
 
-       if (safe_to_lower || watermarks->b.pte_meta_urgent_ns > hubbub->watermarks.b.pte_meta_urgent_ns) {
-               hubbub->watermarks.b.pte_meta_urgent_ns = watermarks->b.pte_meta_urgent_ns;
-               prog_wm_value = convert_and_clamp(watermarks->b.pte_meta_urgent_ns,
-                               refclk_mhz, 0x1fffff);
-               REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value);
-               DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_B calculated =%d\n"
-                       "HW register value = 0x%x\n",
-                       watermarks->b.pte_meta_urgent_ns, prog_wm_value);
+       if (REG(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B)) {
+               if (safe_to_lower || watermarks->b.pte_meta_urgent_ns > hubbub1->watermarks.b.pte_meta_urgent_ns) {
+                       hubbub1->watermarks.b.pte_meta_urgent_ns = watermarks->b.pte_meta_urgent_ns;
+                       prog_wm_value = convert_and_clamp(watermarks->b.pte_meta_urgent_ns,
+                                       refclk_mhz, 0x1fffff);
+                       REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value);
+                       DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_B calculated =%d\n"
+                               "HW register value = 0x%x\n",
+                               watermarks->b.pte_meta_urgent_ns, prog_wm_value);
+               }
        }
 
        if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B)) {
                if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
-                               > hubbub->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) {
-                       hubbub->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns =
+                               > hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) {
+                       hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns =
                                        watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns;
                        prog_wm_value = convert_and_clamp(
                                        watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns,
@@ -363,8 +376,8 @@ void hubbub1_program_watermarks(
                }
 
                if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns
-                               > hubbub->watermarks.b.cstate_pstate.cstate_exit_ns) {
-                       hubbub->watermarks.b.cstate_pstate.cstate_exit_ns =
+                               > hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns) {
+                       hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns =
                                        watermarks->b.cstate_pstate.cstate_exit_ns;
                        prog_wm_value = convert_and_clamp(
                                        watermarks->b.cstate_pstate.cstate_exit_ns,
@@ -377,8 +390,8 @@ void hubbub1_program_watermarks(
        }
 
        if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns
-                       > hubbub->watermarks.b.cstate_pstate.pstate_change_ns) {
-               hubbub->watermarks.b.cstate_pstate.pstate_change_ns =
+                       > hubbub1->watermarks.b.cstate_pstate.pstate_change_ns) {
+               hubbub1->watermarks.b.cstate_pstate.pstate_change_ns =
                                watermarks->b.cstate_pstate.pstate_change_ns;
                prog_wm_value = convert_and_clamp(
                                watermarks->b.cstate_pstate.pstate_change_ns,
@@ -390,8 +403,8 @@ void hubbub1_program_watermarks(
        }
 
        /* clock state C */
-       if (safe_to_lower || watermarks->c.urgent_ns > hubbub->watermarks.c.urgent_ns) {
-               hubbub->watermarks.c.urgent_ns = watermarks->c.urgent_ns;
+       if (safe_to_lower || watermarks->c.urgent_ns > hubbub1->watermarks.c.urgent_ns) {
+               hubbub1->watermarks.c.urgent_ns = watermarks->c.urgent_ns;
                prog_wm_value = convert_and_clamp(watermarks->c.urgent_ns,
                                refclk_mhz, 0x1fffff);
                REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value);
@@ -401,20 +414,22 @@ void hubbub1_program_watermarks(
                        watermarks->c.urgent_ns, prog_wm_value);
        }
 
-       if (safe_to_lower || watermarks->c.pte_meta_urgent_ns > hubbub->watermarks.c.pte_meta_urgent_ns) {
-               hubbub->watermarks.c.pte_meta_urgent_ns = watermarks->c.pte_meta_urgent_ns;
-               prog_wm_value = convert_and_clamp(watermarks->c.pte_meta_urgent_ns,
-                               refclk_mhz, 0x1fffff);
-               REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value);
-               DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_C calculated =%d\n"
-                       "HW register value = 0x%x\n",
-                       watermarks->c.pte_meta_urgent_ns, prog_wm_value);
+       if (REG(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C)) {
+               if (safe_to_lower || watermarks->c.pte_meta_urgent_ns > hubbub1->watermarks.c.pte_meta_urgent_ns) {
+                       hubbub1->watermarks.c.pte_meta_urgent_ns = watermarks->c.pte_meta_urgent_ns;
+                       prog_wm_value = convert_and_clamp(watermarks->c.pte_meta_urgent_ns,
+                                       refclk_mhz, 0x1fffff);
+                       REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value);
+                       DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_C calculated =%d\n"
+                               "HW register value = 0x%x\n",
+                               watermarks->c.pte_meta_urgent_ns, prog_wm_value);
+               }
        }
 
        if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C)) {
                if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
-                               > hubbub->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) {
-                       hubbub->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns =
+                               > hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) {
+                       hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns =
                                        watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns;
                        prog_wm_value = convert_and_clamp(
                                        watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns,
@@ -426,8 +441,8 @@ void hubbub1_program_watermarks(
                }
 
                if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns
-                               > hubbub->watermarks.c.cstate_pstate.cstate_exit_ns) {
-                       hubbub->watermarks.c.cstate_pstate.cstate_exit_ns =
+                               > hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns) {
+                       hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns =
                                        watermarks->c.cstate_pstate.cstate_exit_ns;
                        prog_wm_value = convert_and_clamp(
                                        watermarks->c.cstate_pstate.cstate_exit_ns,
@@ -440,8 +455,8 @@ void hubbub1_program_watermarks(
        }
 
        if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns
-                       > hubbub->watermarks.c.cstate_pstate.pstate_change_ns) {
-               hubbub->watermarks.c.cstate_pstate.pstate_change_ns =
+                       > hubbub1->watermarks.c.cstate_pstate.pstate_change_ns) {
+               hubbub1->watermarks.c.cstate_pstate.pstate_change_ns =
                                watermarks->c.cstate_pstate.pstate_change_ns;
                prog_wm_value = convert_and_clamp(
                                watermarks->c.cstate_pstate.pstate_change_ns,
@@ -453,8 +468,8 @@ void hubbub1_program_watermarks(
        }
 
        /* clock state D */
-       if (safe_to_lower || watermarks->d.urgent_ns > hubbub->watermarks.d.urgent_ns) {
-               hubbub->watermarks.d.urgent_ns = watermarks->d.urgent_ns;
+       if (safe_to_lower || watermarks->d.urgent_ns > hubbub1->watermarks.d.urgent_ns) {
+               hubbub1->watermarks.d.urgent_ns = watermarks->d.urgent_ns;
                prog_wm_value = convert_and_clamp(watermarks->d.urgent_ns,
                                refclk_mhz, 0x1fffff);
                REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value);
@@ -464,20 +479,22 @@ void hubbub1_program_watermarks(
                        watermarks->d.urgent_ns, prog_wm_value);
        }
 
-       if (safe_to_lower || watermarks->d.pte_meta_urgent_ns > hubbub->watermarks.d.pte_meta_urgent_ns) {
-               hubbub->watermarks.d.pte_meta_urgent_ns = watermarks->d.pte_meta_urgent_ns;
-               prog_wm_value = convert_and_clamp(watermarks->d.pte_meta_urgent_ns,
-                               refclk_mhz, 0x1fffff);
-               REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value);
-               DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_D calculated =%d\n"
-                       "HW register value = 0x%x\n",
-                       watermarks->d.pte_meta_urgent_ns, prog_wm_value);
+       if (REG(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D)) {
+               if (safe_to_lower || watermarks->d.pte_meta_urgent_ns > hubbub1->watermarks.d.pte_meta_urgent_ns) {
+                       hubbub1->watermarks.d.pte_meta_urgent_ns = watermarks->d.pte_meta_urgent_ns;
+                       prog_wm_value = convert_and_clamp(watermarks->d.pte_meta_urgent_ns,
+                                       refclk_mhz, 0x1fffff);
+                       REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value);
+                       DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_D calculated =%d\n"
+                               "HW register value = 0x%x\n",
+                               watermarks->d.pte_meta_urgent_ns, prog_wm_value);
+               }
        }
 
        if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D)) {
                if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
-                               > hubbub->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) {
-                       hubbub->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns =
+                               > hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) {
+                       hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns =
                                        watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns;
                        prog_wm_value = convert_and_clamp(
                                        watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns,
@@ -489,8 +506,8 @@ void hubbub1_program_watermarks(
                }
 
                if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns
-                               > hubbub->watermarks.d.cstate_pstate.cstate_exit_ns) {
-                       hubbub->watermarks.d.cstate_pstate.cstate_exit_ns =
+                               > hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns) {
+                       hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns =
                                        watermarks->d.cstate_pstate.cstate_exit_ns;
                        prog_wm_value = convert_and_clamp(
                                        watermarks->d.cstate_pstate.cstate_exit_ns,
@@ -503,8 +520,8 @@ void hubbub1_program_watermarks(
        }
 
        if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns
-                       > hubbub->watermarks.d.cstate_pstate.pstate_change_ns) {
-               hubbub->watermarks.d.cstate_pstate.pstate_change_ns =
+                       > hubbub1->watermarks.d.cstate_pstate.pstate_change_ns) {
+               hubbub1->watermarks.d.cstate_pstate.pstate_change_ns =
                                watermarks->d.cstate_pstate.pstate_change_ns;
                prog_wm_value = convert_and_clamp(
                                watermarks->d.cstate_pstate.pstate_change_ns,
@@ -535,6 +552,8 @@ void hubbub1_update_dchub(
        struct hubbub *hubbub,
        struct dchub_init_data *dh_data)
 {
+       struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
+
        if (REG(DCHUBBUB_SDPIF_FB_TOP) == 0) {
                ASSERT(false);
                /*should not come here*/
@@ -594,6 +613,8 @@ void hubbub1_update_dchub(
 
 void hubbub1_toggle_watermark_change_req(struct hubbub *hubbub)
 {
+       struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
+
        uint32_t watermark_change_req;
 
        REG_GET(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
@@ -610,6 +631,8 @@ void hubbub1_toggle_watermark_change_req(struct hubbub *hubbub)
 
 void hubbub1_soft_reset(struct hubbub *hubbub, bool reset)
 {
+       struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
+
        uint32_t reset_en = reset ? 1 : 0;
 
        REG_UPDATE(DCHUBBUB_SOFT_RESET,
@@ -752,7 +775,9 @@ static bool hubbub1_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;
+       struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
+       struct dc *dc = hubbub1->base.ctx->dc;
+
        /* implement section 1.6.2.1 of DCN1_Programming_Guide.docx */
        enum dcc_control dcc_control;
        unsigned int bpe;
@@ -764,10 +789,10 @@ static bool hubbub1_get_dcc_compression_cap(struct hubbub *hubbub,
        if (dc->debug.disable_dcc == DCC_DISABLE)
                return false;
 
-       if (!hubbub->funcs->dcc_support_pixel_format(input->format, &bpe))
+       if (!hubbub1->base.funcs->dcc_support_pixel_format(input->format, &bpe))
                return false;
 
-       if (!hubbub->funcs->dcc_support_swizzle(input->swizzle_mode, bpe,
+       if (!hubbub1->base.funcs->dcc_support_swizzle(input->swizzle_mode, bpe,
                        &segment_order_horz, &segment_order_vert))
                return false;
 
@@ -837,6 +862,7 @@ static const struct hubbub_funcs hubbub1_funcs = {
        .dcc_support_swizzle = hubbub1_dcc_support_swizzle,
        .dcc_support_pixel_format = hubbub1_dcc_support_pixel_format,
        .get_dcc_compression_cap = hubbub1_get_dcc_compression_cap,
+       .wm_read_state = hubbub1_wm_read_state,
 };
 
 void hubbub1_construct(struct hubbub *hubbub,
@@ -845,18 +871,20 @@ void hubbub1_construct(struct hubbub *hubbub,
        const struct dcn_hubbub_shift *hubbub_shift,
        const struct dcn_hubbub_mask *hubbub_mask)
 {
-       hubbub->ctx = ctx;
+       struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
+
+       hubbub1->base.ctx = ctx;
 
-       hubbub->funcs = &hubbub1_funcs;
+       hubbub1->base.funcs = &hubbub1_funcs;
 
-       hubbub->regs = hubbub_regs;
-       hubbub->shifts = hubbub_shift;
-       hubbub->masks = hubbub_mask;
+       hubbub1->regs = hubbub_regs;
+       hubbub1->shifts = hubbub_shift;
+       hubbub1->masks = hubbub_mask;
 
-       hubbub->debug_test_index_pstate = 0x7;
+       hubbub1->debug_test_index_pstate = 0x7;
 #if defined(CONFIG_DRM_AMD_DC_DCN1_01)
        if (ctx->dce_version == DCN_VERSION_1_01)
-               hubbub->debug_test_index_pstate = 0xB;
+               hubbub1->debug_test_index_pstate = 0xB;
 #endif
 }
 
index d0f03d15291325e091c570525333e9f7f75c33a8..c681e1cc92902777a5d3e53588e387f6624e4e45 100644 (file)
@@ -29,6 +29,9 @@
 #include "core_types.h"
 #include "dchubbub.h"
 
+#define TO_DCN10_HUBBUB(hubbub)\
+       container_of(hubbub, struct dcn10_hubbub, base)
+
 #define HUBHUB_REG_LIST_DCN()\
        SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\
        SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A),\
@@ -107,6 +110,12 @@ struct dcn_hubbub_registers {
        uint32_t DCHUBBUB_SDPIF_AGP_TOP;
        uint32_t DCHUBBUB_CRC_CTRL;
        uint32_t DCHUBBUB_SOFT_RESET;
+       uint32_t DCN_VM_FB_LOCATION_BASE;
+       uint32_t DCN_VM_FB_LOCATION_TOP;
+       uint32_t DCN_VM_FB_OFFSET;
+       uint32_t DCN_VM_AGP_BOT;
+       uint32_t DCN_VM_AGP_TOP;
+       uint32_t DCN_VM_AGP_BASE;
 };
 
 /* set field name */
@@ -152,7 +161,13 @@ struct dcn_hubbub_registers {
                type SDPIF_FB_OFFSET;\
                type SDPIF_AGP_BASE;\
                type SDPIF_AGP_BOT;\
-               type SDPIF_AGP_TOP
+               type SDPIF_AGP_TOP;\
+               type FB_BASE;\
+               type FB_TOP;\
+               type FB_OFFSET;\
+               type AGP_BOT;\
+               type AGP_TOP;\
+               type AGP_BASE
 
 
 struct dcn_hubbub_shift {
@@ -165,22 +180,8 @@ struct dcn_hubbub_mask {
 
 struct dc;
 
-struct dcn_hubbub_wm_set {
-       uint32_t wm_set;
-       uint32_t data_urgent;
-       uint32_t pte_meta_urgent;
-       uint32_t sr_enter;
-       uint32_t sr_exit;
-       uint32_t dram_clk_chanage;
-};
-
-struct dcn_hubbub_wm {
-       struct dcn_hubbub_wm_set sets[4];
-};
-
-struct hubbub {
-       const struct hubbub_funcs *funcs;
-       struct dc_context *ctx;
+struct dcn10_hubbub {
+       struct hubbub base;
        const struct dcn_hubbub_registers *regs;
        const struct dcn_hubbub_shift *shifts;
        const struct dcn_hubbub_mask *masks;
index 345af015d061f0850ccf64b633a9404293d7f381..0ba68d41b9c37b91064a5defbbcf62a3160df53f 100644 (file)
@@ -115,7 +115,7 @@ static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank)
        REG_UPDATE(DCHUBP_CNTL, HUBP_BLANK_EN, blank_en);
 }
 
-static void hubp1_vready_workaround(struct hubp *hubp,
+void hubp1_vready_workaround(struct hubp *hubp,
                struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest)
 {
        uint32_t value = 0;
@@ -317,7 +317,8 @@ void hubp1_program_pixel_format(
 bool hubp1_program_surface_flip_and_addr(
        struct hubp *hubp,
        const struct dc_plane_address *address,
-       bool flip_immediate)
+       bool flip_immediate,
+       uint8_t vmid)
 {
        struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
 
@@ -1140,7 +1141,7 @@ void hubp1_cursor_set_position(
        if (src_y_offset >= (int)param->viewport.height)
                cur_en = 0;  /* not visible beyond bottom edge*/
 
-       if (src_y_offset < 0) //+ (int)hubp->curs_attr.height
+       if (src_y_offset + (int)hubp->curs_attr.height <= 0)
                cur_en = 0;  /* not visible beyond top edge*/
 
        if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0)
index 62d4232e7796cfa2d2064f088083c4500e687510..a6d6dfe00617002eedb3c27e3e426b8979883cd0 100644 (file)
@@ -707,11 +707,6 @@ void hubp1_dcc_control(struct hubp *hubp,
                bool enable,
                bool independent_64b_blks);
 
-bool hubp1_program_surface_flip_and_addr(
-       struct hubp *hubp,
-       const struct dc_plane_address *address,
-       bool flip_immediate);
-
 bool hubp1_is_flip_pending(struct hubp *hubp);
 
 void hubp1_cursor_set_attributes(
@@ -745,5 +740,7 @@ void hubp1_clear_underflow(struct hubp *hubp);
 
 enum cursor_pitch hubp1_get_cursor_pitch(unsigned int pitch);
 
+void hubp1_vready_workaround(struct hubp *hubp,
+               struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest);
 
 #endif
index 91e015e143550d9a4b10d8a6249df35db72c6e62..9cde24dbdac8c7c5a5a2eb2372d0927f586c61f8 100644 (file)
@@ -40,7 +40,6 @@
 #include "ipp.h"
 #include "mpc.h"
 #include "reg_helper.h"
-#include "custom_float.h"
 #include "dcn10_hubp.h"
 #include "dcn10_hubbub.h"
 #include "dcn10_cm_common.h"
@@ -92,10 +91,11 @@ static void log_mpc_crc(struct dc *dc,
 void dcn10_log_hubbub_state(struct dc *dc, struct dc_log_buffer_ctx *log_ctx)
 {
        struct dc_context *dc_ctx = dc->ctx;
-       struct dcn_hubbub_wm wm = {0};
+       struct dcn_hubbub_wm wm;
        int i;
 
-       hubbub1_wm_read_state(dc->res_pool->hubbub, &wm);
+       memset(&wm, 0, sizeof(struct dcn_hubbub_wm));
+       dc->res_pool->hubbub->funcs->wm_read_state(dc->res_pool->hubbub, &wm);
 
        DTN_INFO("HUBBUB WM:      data_urgent  pte_meta_urgent"
                        "         sr_enter          sr_exit  dram_clk_change\n");
@@ -1202,7 +1202,8 @@ static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_c
        pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr(
                        pipe_ctx->plane_res.hubp,
                        &plane_state->address,
-                       plane_state->flip_immediate);
+                       plane_state->flip_immediate,
+                       0);
 
        plane_state->status.requested_address = plane_state->address;
 
@@ -2048,7 +2049,7 @@ void update_dchubp_dpp(
                        dc->res_pool->dccg->funcs->update_dpp_dto(
                                        dc->res_pool->dccg,
                                        dpp->inst,
-                                       pipe_ctx->plane_res.bw.calc.dppclk_khz);
+                                       pipe_ctx->plane_res.bw.dppclk_khz);
                else
                        dc->res_pool->clk_mgr->clks.dppclk_khz = should_divided_by_2 ?
                                                dc->res_pool->clk_mgr->clks.dispclk_khz / 2 :
@@ -2125,7 +2126,8 @@ void update_dchubp_dpp(
                plane_state->update_flags.bits.swizzle_change ||
                plane_state->update_flags.bits.dcc_change ||
                plane_state->update_flags.bits.bpp_change ||
-               plane_state->update_flags.bits.scaling_change) {
+               plane_state->update_flags.bits.scaling_change ||
+               plane_state->update_flags.bits.plane_size_change) {
                hubp->funcs->hubp_program_surface_config(
                        hubp,
                        plane_state->format,
@@ -2252,13 +2254,11 @@ static void program_all_pipe_in_tree(
 
        }
 
-       if (pipe_ctx->plane_state != NULL) {
+       if (pipe_ctx->plane_state != NULL)
                dcn10_program_pipe(dc, pipe_ctx, context);
-       }
 
-       if (pipe_ctx->bottom_pipe != NULL && pipe_ctx->bottom_pipe != pipe_ctx) {
+       if (pipe_ctx->bottom_pipe != NULL && pipe_ctx->bottom_pipe != pipe_ctx)
                program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context);
-       }
 }
 
 struct pipe_ctx *find_top_pipe_for_stream(
@@ -2355,29 +2355,22 @@ static void dcn10_apply_ctx_for_surface(
                        top_pipe_to_program->plane_state->update_flags.bits.full_update)
                for (i = 0; i < dc->res_pool->pipe_count; i++) {
                        struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-
+                       tg = pipe_ctx->stream_res.tg;
                        /* Skip inactive pipes and ones already updated */
                        if (!pipe_ctx->stream || pipe_ctx->stream == stream
-                                       || !pipe_ctx->plane_state)
+                                       || !pipe_ctx->plane_state
+                                       || !tg->funcs->is_tg_enabled(tg))
                                continue;
 
-                       pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
+                       tg->funcs->lock(tg);
 
                        pipe_ctx->plane_res.hubp->funcs->hubp_setup_interdependent(
                                pipe_ctx->plane_res.hubp,
                                &pipe_ctx->dlg_regs,
                                &pipe_ctx->ttu_regs);
-               }
 
-       for (i = 0; i < dc->res_pool->pipe_count; i++) {
-               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-
-               if (!pipe_ctx->stream || pipe_ctx->stream == stream
-                               || !pipe_ctx->plane_state)
-                       continue;
-
-               dcn10_pipe_control_lock(dc, pipe_ctx, false);
-       }
+                       tg->funcs->unlock(tg);
+               }
 
        if (num_planes == 0)
                false_optc_underflow_wa(dc, stream, tg);
@@ -2525,7 +2518,7 @@ static void dcn10_config_stereo_parameters(
                        timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA ||
                        timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) {
                        enum display_dongle_type dongle = \
-                                       stream->sink->link->ddc->dongle_type;
+                                       stream->link->ddc->dongle_type;
                        if (dongle == DISPLAY_DONGLE_DP_VGA_CONVERTER ||
                                dongle == DISPLAY_DONGLE_DP_DVI_CONVERTER ||
                                dongle == DISPLAY_DONGLE_DP_HDMI_CONVERTER)
@@ -2656,7 +2649,7 @@ static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
        struct hubp *hubp = pipe_ctx->plane_res.hubp;
        struct dpp *dpp = pipe_ctx->plane_res.dpp;
        struct dc_cursor_mi_param param = {
-               .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz,
+               .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10,
                .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clock_inKhz,
                .viewport = pipe_ctx->plane_res.scl_data.viewport,
                .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz,
index cd469014baa39f2ce505c7006f09a44e6e6ee9f5..98f41d2509787c512a58963b08cf4fe44afcbc3a 100644 (file)
@@ -40,7 +40,6 @@
 #include "ipp.h"
 #include "mpc.h"
 #include "reg_helper.h"
-#include "custom_float.h"
 #include "dcn10_hubp.h"
 #include "dcn10_hubbub.h"
 #include "dcn10_cm_common.h"
@@ -72,7 +71,7 @@ static unsigned int snprintf_count(char *pBuf, unsigned int bufSize, char *fmt,
 static unsigned int dcn10_get_hubbub_state(struct dc *dc, char *pBuf, unsigned int bufSize)
 {
        struct dc_context *dc_ctx = dc->ctx;
-       struct dcn_hubbub_wm wm = {0};
+       struct dcn_hubbub_wm wm;
        int i;
 
        unsigned int chars_printed = 0;
@@ -81,7 +80,8 @@ static unsigned int dcn10_get_hubbub_state(struct dc *dc, char *pBuf, unsigned i
        const uint32_t ref_clk_mhz = dc_ctx->dc->res_pool->ref_clock_inKhz / 1000;
        static const unsigned int frac = 1000;
 
-       hubbub1_wm_read_state(dc->res_pool->hubbub, &wm);
+       memset(&wm, 0, sizeof(struct dcn_hubbub_wm));
+       dc->res_pool->hubbub->funcs->wm_read_state(dc->res_pool->hubbub, &wm);
 
        chars_printed = snprintf_count(pBuf, remaining_buffer, "wm_set_index,data_urgent,pte_meta_urgent,sr_enter,sr_exit,dram_clk_chanage\n");
        remaining_buffer -= chars_printed;
@@ -419,20 +419,22 @@ static unsigned int dcn10_get_otg_states(struct dc *dc, char *pBuf, unsigned int
        unsigned int remaining_buffer = bufSize;
 
        chars_printed = snprintf_count(pBuf, remaining_buffer, "instance,v_bs,v_be,v_ss,v_se,vpol,vmax,vmin,vmax_sel,vmin_sel,"
-                       "h_bs,h_be,h_ss,h_se,hpol,htot,vtot,underflow\n");
+                       "h_bs,h_be,h_ss,h_se,hpol,htot,vtot,underflow,pixelclk[khz]\n");
        remaining_buffer -= chars_printed;
        pBuf += chars_printed;
 
        for (i = 0; i < pool->timing_generator_count; i++) {
                struct timing_generator *tg = pool->timing_generators[i];
                struct dcn_otg_state s = {0};
+               int pix_clk = 0;
 
                optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s);
+               pix_clk = dc->current_state->res_ctx.pipe_ctx[i].stream_res.pix_clk_params.requested_pix_clk_100hz / 10;
 
                //only print if OTG master is enabled
                if (s.otg_enabled & 1) {
                        chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%d,%d,%d,%d,%d,%d,%d,%d,%d,"
-                               "%d,%d,%d,%d,%d,%d,%d,%d"
+                               "%d,%d,%d,%d,%d,%d,%d,%d,%d"
                                "\n",
                                tg->inst,
                                s.v_blank_start,
@@ -451,7 +453,8 @@ static unsigned int dcn10_get_otg_states(struct dc *dc, char *pBuf, unsigned int
                                s.h_sync_a_pol,
                                s.h_total,
                                s.v_total,
-                               s.underflow_occurred_status);
+                               s.underflow_occurred_status,
+                               pix_clk);
 
                        remaining_buffer -= chars_printed;
                        pBuf += chars_printed;
index 477ab922221626dd47026d1874383418d0542cc9..771449f8984f87ab7d6b08f2305142f90ed59063 100644 (file)
@@ -440,7 +440,7 @@ static uint8_t get_frontend_source(
        }
 }
 
-void configure_encoder(
+void enc1_configure_encoder(
        struct dcn10_link_encoder *enc10,
        const struct dc_link_settings *link_settings)
 {
@@ -543,12 +543,12 @@ bool dcn10_link_encoder_validate_dvi_output(
        if ((connector_signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
                connector_signal == SIGNAL_TYPE_HDMI_TYPE_A) &&
                signal != SIGNAL_TYPE_HDMI_TYPE_A &&
-               crtc_timing->pix_clk_khz > TMDS_MAX_PIXEL_CLOCK)
+               crtc_timing->pix_clk_100hz > (TMDS_MAX_PIXEL_CLOCK * 10))
                return false;
-       if (crtc_timing->pix_clk_khz < TMDS_MIN_PIXEL_CLOCK)
+       if (crtc_timing->pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10))
                return false;
 
-       if (crtc_timing->pix_clk_khz > max_pixel_clock)
+       if (crtc_timing->pix_clk_100hz > (max_pixel_clock * 10))
                return false;
 
        /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */
@@ -571,7 +571,7 @@ bool dcn10_link_encoder_validate_dvi_output(
 static bool dcn10_link_encoder_validate_hdmi_output(
        const struct dcn10_link_encoder *enc10,
        const struct dc_crtc_timing *crtc_timing,
-       int adjusted_pix_clk_khz)
+       int adjusted_pix_clk_100hz)
 {
        enum dc_color_depth max_deep_color =
                        enc10->base.features.max_hdmi_deep_color;
@@ -581,11 +581,11 @@ static bool dcn10_link_encoder_validate_hdmi_output(
 
        if (crtc_timing->display_color_depth < COLOR_DEPTH_888)
                return false;
-       if (adjusted_pix_clk_khz < TMDS_MIN_PIXEL_CLOCK)
+       if (adjusted_pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10))
                return false;
 
-       if ((adjusted_pix_clk_khz == 0) ||
-               (adjusted_pix_clk_khz > enc10->base.features.max_hdmi_pixel_clock))
+       if ((adjusted_pix_clk_100hz == 0) ||
+               (adjusted_pix_clk_100hz > (enc10->base.features.max_hdmi_pixel_clock * 10)))
                return false;
 
        /* DCE11 HW does not support 420 */
@@ -594,7 +594,7 @@ static bool dcn10_link_encoder_validate_hdmi_output(
                return false;
 
        if (!enc10->base.features.flags.bits.HDMI_6GB_EN &&
-               adjusted_pix_clk_khz >= 300000)
+               adjusted_pix_clk_100hz >= 3000000)
                return false;
        if (enc10->base.ctx->dc->debug.hdmi20_disable &&
                crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
@@ -738,7 +738,7 @@ bool dcn10_link_encoder_validate_output_with_stream(
        case SIGNAL_TYPE_DVI_DUAL_LINK:
                is_valid = dcn10_link_encoder_validate_dvi_output(
                        enc10,
-                       stream->sink->link->connector_signal,
+                       stream->link->connector_signal,
                        stream->signal,
                        &stream->timing);
        break;
@@ -746,7 +746,7 @@ bool dcn10_link_encoder_validate_output_with_stream(
                is_valid = dcn10_link_encoder_validate_hdmi_output(
                                enc10,
                                &stream->timing,
-                               stream->phy_pix_clk);
+                               stream->phy_pix_clk * 10);
        break;
        case SIGNAL_TYPE_DISPLAY_PORT:
        case SIGNAL_TYPE_DISPLAY_PORT_MST:
@@ -910,7 +910,7 @@ void dcn10_link_encoder_enable_dp_output(
         * but it's not passed to asic_control.
         * We need to set number of lanes manually.
         */
-       configure_encoder(enc10, link_settings);
+       enc1_configure_encoder(enc10, link_settings);
 
        cntl.action = TRANSMITTER_CONTROL_ENABLE;
        cntl.engine_id = enc->preferred_engine;
@@ -949,7 +949,7 @@ void dcn10_link_encoder_enable_dp_mst_output(
         * but it's not passed to asic_control.
         * We need to set number of lanes manually.
         */
-       configure_encoder(enc10, link_settings);
+       enc1_configure_encoder(enc10, link_settings);
 
        cntl.action = TRANSMITTER_CONTROL_ENABLE;
        cntl.engine_id = ENGINE_ID_UNKNOWN;
index 49ead12b25329f497e6acf2c43411e1a8548ff11..670b46e887ed73ed832013de8511ef372343f8bd 100644 (file)
@@ -271,7 +271,7 @@ void dcn10_link_encoder_setup(
        struct link_encoder *enc,
        enum signal_type signal);
 
-void configure_encoder(
+void enc1_configure_encoder(
        struct dcn10_link_encoder *enc10,
        const struct dc_link_settings *link_settings);
 
index 7c138615f17d7020909a7b2b599c09d8ccee9aac..eb019d4049283eb7f359116cbc3a2ceba57b4c00 100644 (file)
@@ -102,14 +102,6 @@ static uint32_t get_start_vline(struct timing_generator *optc, const struct dc_c
        patched_crtc_timing = *dc_crtc_timing;
        optc1_apply_front_porch_workaround(optc, &patched_crtc_timing);
 
-       vesa_sync_start = patched_crtc_timing.h_addressable +
-                       patched_crtc_timing.h_border_right +
-                       patched_crtc_timing.h_front_porch;
-
-       asic_blank_end = patched_crtc_timing.h_total -
-                       vesa_sync_start -
-                       patched_crtc_timing.h_border_left;
-
        vesa_sync_start = patched_crtc_timing.v_addressable +
                        patched_crtc_timing.v_border_bottom +
                        patched_crtc_timing.v_front_porch;
@@ -119,10 +111,8 @@ static uint32_t get_start_vline(struct timing_generator *optc, const struct dc_c
                        patched_crtc_timing.v_border_top);
 
        vertical_line_start = asic_blank_end - optc->dlg_otg_param.vstartup_start + 1;
-       if (vertical_line_start < 0) {
-               ASSERT(0);
+       if (vertical_line_start < 0)
                vertical_line_start = 0;
-       }
 
        return vertical_line_start;
 }
@@ -136,14 +126,14 @@ void optc1_program_vline_interrupt(
        struct optc *optc1 = DCN10TG_FROM_TG(optc);
 
        unsigned long long req_delta_tens_of_usec = div64_u64((vsync_delta + 9999), 10000);
-       unsigned long long pix_clk_hundreds_khz = div64_u64((dc_crtc_timing->pix_clk_khz + 99), 100);
+       unsigned long long pix_clk_hundreds_khz = div64_u64((dc_crtc_timing->pix_clk_100hz + 999), 1000);
        uint32_t req_delta_lines = (uint32_t) div64_u64(
                        (req_delta_tens_of_usec * pix_clk_hundreds_khz + dc_crtc_timing->h_total - 1),
                                                                dc_crtc_timing->h_total);
 
        uint32_t vsync_line = get_start_vline(optc, dc_crtc_timing);
        uint32_t start_line = 0;
-       uint32_t endLine = 0;
+       uint32_t end_line = 0;
 
        if (req_delta_lines != 0)
                req_delta_lines--;
@@ -153,14 +143,17 @@ void optc1_program_vline_interrupt(
        else
                start_line = vsync_line - req_delta_lines;
 
-       endLine = start_line + 2;
+       end_line = start_line + 2;
 
-       if (endLine >= dc_crtc_timing->v_total)
-               endLine = 2;
+       if (start_line >= dc_crtc_timing->v_total)
+               start_line = start_line % dc_crtc_timing->v_total;
+
+       if (end_line >= dc_crtc_timing->v_total)
+               end_line = end_line % dc_crtc_timing->v_total;
 
        REG_SET_2(OTG_VERTICAL_INTERRUPT0_POSITION, 0,
                        OTG_VERTICAL_INTERRUPT0_LINE_START, start_line,
-                       OTG_VERTICAL_INTERRUPT0_LINE_END, endLine);
+                       OTG_VERTICAL_INTERRUPT0_LINE_END, end_line);
 }
 
 /**
@@ -299,16 +292,17 @@ void optc1_program_timing(
        }
 
        /* Interlace */
-       if (patched_crtc_timing.flags.INTERLACE == 1) {
-               REG_UPDATE(OTG_INTERLACE_CONTROL,
-                               OTG_INTERLACE_ENABLE, 1);
-               v_init = v_init / 2;
-               if ((optc->dlg_otg_param.vstartup_start/2)*2 > asic_blank_end)
-                       v_fp2 = v_fp2 / 2;
-       } else
-               REG_UPDATE(OTG_INTERLACE_CONTROL,
-                               OTG_INTERLACE_ENABLE, 0);
-
+       if (REG(OTG_INTERLACE_CONTROL)) {
+               if (patched_crtc_timing.flags.INTERLACE == 1) {
+                       REG_UPDATE(OTG_INTERLACE_CONTROL,
+                                       OTG_INTERLACE_ENABLE, 1);
+                       v_init = v_init / 2;
+                       if ((optc->dlg_otg_param.vstartup_start/2)*2 > asic_blank_end)
+                               v_fp2 = v_fp2 / 2;
+               } else
+                       REG_UPDATE(OTG_INTERLACE_CONTROL,
+                                       OTG_INTERLACE_ENABLE, 0);
+       }
 
        /* VTG enable set to 0 first VInit */
        REG_UPDATE(CONTROL,
index 5d4772dec0ba5454267b6fcfeae1b55d6b6cf049..09d74070a49b60e45ea3d5f2a9f1c2934026a0fa 100644 (file)
@@ -70,7 +70,7 @@
 const struct _vcs_dpi_ip_params_st dcn1_0_ip = {
        .rob_buffer_size_kbytes = 64,
        .det_buffer_size_kbytes = 164,
-       .dpte_buffer_size_in_pte_reqs = 42,
+       .dpte_buffer_size_in_pte_reqs_luma = 42,
        .dpp_output_buffer_pixels = 2560,
        .opp_output_buffer_lines = 1,
        .pixel_chunk_size_kbytes = 8,
@@ -436,7 +436,6 @@ static const struct dcn_optc_mask tg_mask = {
 };
 
 static const struct bios_registers bios_regs = {
-               NBIO_SR(BIOS_SCRATCH_0),
                NBIO_SR(BIOS_SCRATCH_3),
                NBIO_SR(BIOS_SCRATCH_6)
 };
@@ -609,7 +608,7 @@ static struct output_pixel_processor *dcn10_opp_create(
        return &opp->base;
 }
 
-struct aux_engine *dcn10_aux_engine_create(
+struct dce_aux *dcn10_aux_engine_create(
        struct dc_context *ctx,
        uint32_t inst)
 {
@@ -678,18 +677,18 @@ static struct mpc *dcn10_mpc_create(struct dc_context *ctx)
 
 static struct hubbub *dcn10_hubbub_create(struct dc_context *ctx)
 {
-       struct hubbub *hubbub = kzalloc(sizeof(struct hubbub),
+       struct dcn10_hubbub *dcn10_hubbub = kzalloc(sizeof(struct dcn10_hubbub),
                                          GFP_KERNEL);
 
-       if (!hubbub)
+       if (!dcn10_hubbub)
                return NULL;
 
-       hubbub1_construct(hubbub, ctx,
+       hubbub1_construct(&dcn10_hubbub->base, ctx,
                        &hubbub_reg,
                        &hubbub_shift,
                        &hubbub_mask);
 
-       return hubbub;
+       return &dcn10_hubbub->base;
 }
 
 static struct timing_generator *dcn10_timing_generator_create(
@@ -911,7 +910,7 @@ static void destruct(struct dcn10_resource_pool *pool)
 
        for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
                if (pool->base.engines[i] != NULL)
-                       pool->base.engines[i]->funcs->destroy_engine(&pool->base.engines[i]);
+                       dce110_engine_destroy(&pool->base.engines[i]);
                if (pool->base.hw_i2cs[i] != NULL) {
                        kfree(pool->base.hw_i2cs[i]);
                        pool->base.hw_i2cs[i] = NULL;
@@ -974,8 +973,8 @@ static void get_pixel_clock_parameters(
        struct pixel_clk_params *pixel_clk_params)
 {
        const struct dc_stream_state *stream = pipe_ctx->stream;
-       pixel_clk_params->requested_pix_clk = stream->timing.pix_clk_khz;
-       pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id;
+       pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz;
+       pixel_clk_params->encoder_object_id = stream->link->link_enc->id;
        pixel_clk_params->signal_type = pipe_ctx->stream->signal;
        pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1;
        /* TODO: un-hardcode*/
@@ -991,9 +990,9 @@ static void get_pixel_clock_parameters(
                pixel_clk_params->color_depth = COLOR_DEPTH_888;
 
        if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
-               pixel_clk_params->requested_pix_clk  /= 2;
+               pixel_clk_params->requested_pix_clk_100hz  /= 2;
        if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
-               pixel_clk_params->requested_pix_clk *= 2;
+               pixel_clk_params->requested_pix_clk_100hz *= 2;
 
 }
 
@@ -1131,6 +1130,56 @@ static enum dc_status dcn10_validate_plane(const struct dc_plane_state *plane_st
        return DC_OK;
 }
 
+static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *context)
+{
+       int i, j;
+       bool video_down_scaled = false;
+       bool video_large = false;
+       bool desktop_large = false;
+       bool dcc_disabled = false;
+
+       for (i = 0; i < context->stream_count; i++) {
+               if (context->stream_status[i].plane_count == 0)
+                       continue;
+
+               if (context->stream_status[i].plane_count > 2)
+                       return false;
+
+               for (j = 0; j < context->stream_status[i].plane_count; j++) {
+                       struct dc_plane_state *plane =
+                               context->stream_status[i].plane_states[j];
+
+
+                       if (plane->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
+
+                               if (plane->src_rect.width > plane->dst_rect.width ||
+                                               plane->src_rect.height > plane->dst_rect.height)
+                                       video_down_scaled = true;
+
+                               if (plane->src_rect.width >= 3840)
+                                       video_large = true;
+
+                       } else {
+                               if (plane->src_rect.width >= 3840)
+                                       desktop_large = true;
+                               if (!plane->dcc.enable)
+                                       dcc_disabled = true;
+                       }
+               }
+       }
+
+       /*
+        * Workaround: On DCN10 there is UMC issue that causes underflow when
+        * playing 4k video on 4k desktop with video downscaled and single channel
+        * memory
+        */
+       if (video_large && desktop_large && video_down_scaled && dcc_disabled &&
+                       dc->dcn_soc->number_of_channels == 1)
+               return DC_FAIL_SURFACE_VALIDATE;
+
+       return DC_OK;
+}
+
 static enum dc_status dcn10_get_default_swizzle_mode(struct dc_plane_state *plane_state)
 {
        enum dc_status result = DC_OK;
@@ -1159,6 +1208,7 @@ static const struct resource_funcs dcn10_res_pool_funcs = {
        .validate_bandwidth = dcn_validate_bandwidth,
        .acquire_idle_pipe_for_layer = dcn10_acquire_idle_pipe_for_layer,
        .validate_plane = dcn10_validate_plane,
+       .validate_global = dcn10_validate_global,
        .add_stream_to_ctx = dcn10_add_stream_to_ctx,
        .get_default_swizzle_mode = dcn10_get_default_swizzle_mode
 };
index b8b5525a389abf0926d94e9c20b5522b63ba06be..b08254121251238304313397a9a4f7b813605975 100644 (file)
@@ -261,17 +261,29 @@ void enc1_stream_encoder_dp_set_stream_attribute(
        uint8_t dp_component_depth = 0;
 
        struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+       struct dc_crtc_timing hw_crtc_timing = *crtc_timing;
+
+       if (hw_crtc_timing.flags.INTERLACE) {
+               /*the input timing is in VESA spec format with Interlace flag =1*/
+               hw_crtc_timing.v_total /= 2;
+               hw_crtc_timing.v_border_top /= 2;
+               hw_crtc_timing.v_addressable /= 2;
+               hw_crtc_timing.v_border_bottom /= 2;
+               hw_crtc_timing.v_front_porch /= 2;
+               hw_crtc_timing.v_sync_width /= 2;
+       }
+
 
        /* set pixel encoding */
-       switch (crtc_timing->pixel_encoding) {
+       switch (hw_crtc_timing.pixel_encoding) {
        case PIXEL_ENCODING_YCBCR422:
                dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR422;
                break;
        case PIXEL_ENCODING_YCBCR444:
                dp_pixel_encoding = DP_PIXEL_ENCODING_TYPE_YCBCR444;
 
-               if (crtc_timing->flags.Y_ONLY)
-                       if (crtc_timing->display_color_depth != COLOR_DEPTH_666)
+               if (hw_crtc_timing.flags.Y_ONLY)
+                       if (hw_crtc_timing.display_color_depth != COLOR_DEPTH_666)
                                /* HW testing only, no use case yet.
                                 * Color depth of Y-only could be
                                 * 8, 10, 12, 16 bits
@@ -299,7 +311,7 @@ void enc1_stream_encoder_dp_set_stream_attribute(
         * Pixel Encoding/Colorimetry Format and that a Sink device shall ignore MISC1, bit 7,
         * and MISC0, bits 7:1 (MISC1, bit 7, and MISC0, bits 7:1, become "don't care").
         */
-       if ((crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) ||
+       if ((hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) ||
                        (output_color_space == COLOR_SPACE_2020_YCBCR) ||
                        (output_color_space == COLOR_SPACE_2020_RGB_FULLRANGE) ||
                        (output_color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE))
@@ -308,7 +320,7 @@ void enc1_stream_encoder_dp_set_stream_attribute(
                misc1 = misc1 & ~0x40;
 
        /* set color depth */
-       switch (crtc_timing->display_color_depth) {
+       switch (hw_crtc_timing.display_color_depth) {
        case COLOR_DEPTH_666:
                dp_component_depth = DP_COMPONENT_PIXEL_DEPTH_6BPC;
                break;
@@ -336,7 +348,7 @@ void enc1_stream_encoder_dp_set_stream_attribute(
 
        /* set dynamic range and YCbCr range */
 
-       switch (crtc_timing->display_color_depth) {
+       switch (hw_crtc_timing.display_color_depth) {
        case COLOR_DEPTH_666:
                colorimetry_bpc = 0;
                break;
@@ -372,9 +384,9 @@ void enc1_stream_encoder_dp_set_stream_attribute(
                misc0 = misc0 | 0x8; /* bit3=1, bit4=0 */
                misc1 = misc1 & ~0x80; /* bit7 = 0*/
                dynamic_range_ycbcr = 0; /*bt601*/
-               if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
+               if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)
                        misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */
-               else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444)
+               else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444)
                        misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */
                break;
        case COLOR_SPACE_YCBCR709:
@@ -382,9 +394,9 @@ void enc1_stream_encoder_dp_set_stream_attribute(
                misc0 = misc0 | 0x18; /* bit3=1, bit4=1 */
                misc1 = misc1 & ~0x80; /* bit7 = 0*/
                dynamic_range_ycbcr = 1; /*bt709*/
-               if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
+               if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)
                        misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */
-               else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444)
+               else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444)
                        misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */
                break;
        case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
@@ -414,26 +426,26 @@ void enc1_stream_encoder_dp_set_stream_attribute(
         * dc_crtc_timing is vesa dmt struct. data from edid
         */
        REG_SET_2(DP_MSA_TIMING_PARAM1, 0,
-                       DP_MSA_HTOTAL, crtc_timing->h_total,
-                       DP_MSA_VTOTAL, crtc_timing->v_total);
+                       DP_MSA_HTOTAL, hw_crtc_timing.h_total,
+                       DP_MSA_VTOTAL, hw_crtc_timing.v_total);
 
        /* calculate from vesa timing parameters
         * h_active_start related to leading edge of sync
         */
 
-       h_blank = crtc_timing->h_total - crtc_timing->h_border_left -
-                       crtc_timing->h_addressable - crtc_timing->h_border_right;
+       h_blank = hw_crtc_timing.h_total - hw_crtc_timing.h_border_left -
+                       hw_crtc_timing.h_addressable - hw_crtc_timing.h_border_right;
 
-       h_back_porch = h_blank - crtc_timing->h_front_porch -
-                       crtc_timing->h_sync_width;
+       h_back_porch = h_blank - hw_crtc_timing.h_front_porch -
+                       hw_crtc_timing.h_sync_width;
 
        /* start at beginning of left border */
-       h_active_start = crtc_timing->h_sync_width + h_back_porch;
+       h_active_start = hw_crtc_timing.h_sync_width + h_back_porch;
 
 
-       v_active_start = crtc_timing->v_total - crtc_timing->v_border_top -
-                       crtc_timing->v_addressable - crtc_timing->v_border_bottom -
-                       crtc_timing->v_front_porch;
+       v_active_start = hw_crtc_timing.v_total - hw_crtc_timing.v_border_top -
+                       hw_crtc_timing.v_addressable - hw_crtc_timing.v_border_bottom -
+                       hw_crtc_timing.v_front_porch;
 
 
        /* start at beginning of left border */
@@ -443,20 +455,20 @@ void enc1_stream_encoder_dp_set_stream_attribute(
 
        REG_SET_4(DP_MSA_TIMING_PARAM3, 0,
                        DP_MSA_HSYNCWIDTH,
-                       crtc_timing->h_sync_width,
+                       hw_crtc_timing.h_sync_width,
                        DP_MSA_HSYNCPOLARITY,
-                       !crtc_timing->flags.HSYNC_POSITIVE_POLARITY,
+                       !hw_crtc_timing.flags.HSYNC_POSITIVE_POLARITY,
                        DP_MSA_VSYNCWIDTH,
-                       crtc_timing->v_sync_width,
+                       hw_crtc_timing.v_sync_width,
                        DP_MSA_VSYNCPOLARITY,
-                       !crtc_timing->flags.VSYNC_POSITIVE_POLARITY);
+                       !hw_crtc_timing.flags.VSYNC_POSITIVE_POLARITY);
 
        /* HWDITH include border or overscan */
        REG_SET_2(DP_MSA_TIMING_PARAM4, 0,
-               DP_MSA_HWIDTH, crtc_timing->h_border_left +
-               crtc_timing->h_addressable + crtc_timing->h_border_right,
-               DP_MSA_VHEIGHT, crtc_timing->v_border_top +
-               crtc_timing->v_addressable + crtc_timing->v_border_bottom);
+               DP_MSA_HWIDTH, hw_crtc_timing.h_border_left +
+               hw_crtc_timing.h_addressable + hw_crtc_timing.h_border_right,
+               DP_MSA_VHEIGHT, hw_crtc_timing.v_border_top +
+               hw_crtc_timing.v_addressable + hw_crtc_timing.v_border_bottom);
 }
 
 static void enc1_stream_encoder_set_stream_attribute_helper(
@@ -594,7 +606,7 @@ void enc1_stream_encoder_dvi_set_stream_attribute(
        cntl.signal = is_dual_link ?
                        SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK;
        cntl.enable_dp_audio = false;
-       cntl.pixel_clock = crtc_timing->pix_clk_khz;
+       cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10;
        cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR;
 
        if (enc1->base.bp->funcs->encoder_control(
@@ -1413,6 +1425,14 @@ void enc1_setup_stereo_sync(
        REG_UPDATE(DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, !enable);
 }
 
+void enc1_dig_connect_to_otg(
+       struct stream_encoder *enc,
+       int tg_inst)
+{
+       struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+       REG_UPDATE(DIG_FE_CNTL, DIG_SOURCE_SELECT, tg_inst);
+}
 
 static const struct stream_encoder_funcs dcn10_str_enc_funcs = {
        .dp_set_stream_attribute =
@@ -1445,6 +1465,7 @@ static const struct stream_encoder_funcs dcn10_str_enc_funcs = {
        .hdmi_audio_disable = enc1_se_hdmi_audio_disable,
        .setup_stereo_sync  = enc1_setup_stereo_sync,
        .set_avmute = enc1_stream_encoder_set_avmute,
+       .dig_connect_to_otg  = enc1_dig_connect_to_otg,
 };
 
 void dcn10_stream_encoder_construct(
index 67f3e4dd95c148b471c363f049bd6e0f4b56c1e8..b7c800e10a32fabc6aba11d34f3642a8f51b8cfc 100644 (file)
@@ -274,7 +274,8 @@ struct dcn10_stream_enc_registers {
        SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\
        SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\
        SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\
-       SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh)
+       SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh),\
+       SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh)
 
 #define SE_COMMON_MASK_SH_LIST_SOC(mask_sh)\
        SE_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh)
@@ -426,7 +427,8 @@ struct dcn10_stream_enc_registers {
        type DP_MSA_VHEIGHT;\
        type HDMI_DB_DISABLE;\
        type DP_VID_N_MUL;\
-       type DP_VID_M_DOUBLE_VALUE_EN
+       type DP_VID_M_DOUBLE_VALUE_EN;\
+       type DIG_SOURCE_SELECT
 
 struct dcn10_stream_encoder_shift {
        SE_REG_FIELD_LIST_DCN1_0(uint8_t);
@@ -523,4 +525,8 @@ void enc1_se_hdmi_audio_setup(
 void enc1_se_hdmi_audio_disable(
        struct stream_encoder *enc);
 
+void enc1_dig_connect_to_otg(
+       struct stream_encoder *enc,
+       int tg_inst);
+
 #endif /* __DC_STREAM_ENCODER_DCN10_H__ */
index 0029a39efb1cb5ffe09e6d775af18cfcdfbfd2be..14bed5b1fa97448c0ba944408c5d385d2d3c6e17 100644 (file)
@@ -38,7 +38,8 @@ enum pp_smu_ver {
         * of interface sharing between families of ASIcs.
         */
        PP_SMU_UNSUPPORTED,
-       PP_SMU_VER_RV
+       PP_SMU_VER_RV,
+       PP_SMU_VER_MAX
 };
 
 struct pp_smu {
index 1af8c777b3acbc15a3e7113af89a130bc9f8c134..77200711abbef6195f55b069d8a560579ccd36c6 100644 (file)
@@ -82,9 +82,17 @@ enum dm_pp_clock_type {
 #define DC_DECODE_PP_CLOCK_TYPE(clk_type) \
        (clk_type) == DM_PP_CLOCK_TYPE_DISPLAY_CLK ? "Display" : \
        (clk_type) == DM_PP_CLOCK_TYPE_ENGINE_CLK ? "Engine" : \
-       (clk_type) == DM_PP_CLOCK_TYPE_MEMORY_CLK ? "Memory" : "Invalid"
-
-#define DM_PP_MAX_CLOCK_LEVELS 8
+       (clk_type) == DM_PP_CLOCK_TYPE_MEMORY_CLK ? "Memory" : \
+       (clk_type) == DM_PP_CLOCK_TYPE_DCFCLK ? "DCF" : \
+       (clk_type) == DM_PP_CLOCK_TYPE_DCEFCLK ? "DCEF" : \
+       (clk_type) == DM_PP_CLOCK_TYPE_SOCCLK ? "SoC" : \
+       (clk_type) == DM_PP_CLOCK_TYPE_PIXELCLK ? "Pixel" : \
+       (clk_type) == DM_PP_CLOCK_TYPE_DISPLAYPHYCLK ? "Display PHY" : \
+       (clk_type) == DM_PP_CLOCK_TYPE_DPPCLK ? "DPP" : \
+       (clk_type) == DM_PP_CLOCK_TYPE_FCLK ? "F" : \
+       "Invalid"
+
+#define DM_PP_MAX_CLOCK_LEVELS 16
 
 struct dm_pp_clock_levels {
        uint32_t num_levels;
index d97ca6528f9d9d943f41bb416466277d2fcdf2bc..33c7d758871220c6fa4d4f32fdca4edf50e0f68c 100644 (file)
@@ -30,7 +30,7 @@ else ifneq ($(call cc-option, -mstack-alignment=16),)
        cc_stack_align := -mstack-alignment=16
 endif
 
-dml_ccflags := -mhard-float -msse $(cc_stack_align)
+dml_ccflags := -mhard-float -msse -msse2 $(cc_stack_align)
 
 CFLAGS_display_mode_lib.o := $(dml_ccflags)
 CFLAGS_display_pipe_clocks.o := $(dml_ccflags)
index bea4e61b94c7fe260d36a0c601cefb6290b1e007..c59e582c1f40264e2583874ca179819042571ca0 100644 (file)
@@ -121,4 +121,30 @@ enum self_refresh_affinity {
        dm_neither_self_refresh_nor_mclk_switch
 };
 
+enum dm_validation_status {
+       DML_VALIDATION_OK,
+       DML_FAIL_SCALE_RATIO_TAP,
+       DML_FAIL_SOURCE_PIXEL_FORMAT,
+       DML_FAIL_VIEWPORT_SIZE,
+       DML_FAIL_TOTAL_V_ACTIVE_BW,
+       DML_FAIL_DIO_SUPPORT,
+       DML_FAIL_NOT_ENOUGH_DSC,
+       DML_FAIL_DSC_CLK_REQUIRED,
+       DML_FAIL_URGENT_LATENCY,
+       DML_FAIL_REORDERING_BUFFER,
+       DML_FAIL_DISPCLK_DPPCLK,
+       DML_FAIL_TOTAL_AVAILABLE_PIPES,
+       DML_FAIL_NUM_OTG,
+       DML_FAIL_WRITEBACK_MODE,
+       DML_FAIL_WRITEBACK_LATENCY,
+       DML_FAIL_WRITEBACK_SCALE_RATIO_TAP,
+       DML_FAIL_CURSOR_SUPPORT,
+       DML_FAIL_PITCH_SUPPORT,
+       DML_FAIL_PTE_BUFFER_SIZE,
+       DML_FAIL_HOST_VM_IMMEDIATE_FLIP,
+       DML_FAIL_DSC_INPUT_BPC,
+       DML_FAIL_PREFETCH_SUPPORT,
+       DML_FAIL_V_RATIO_PREFETCH,
+};
+
 #endif
index dddeb0d4db8f337bfc4c7825ea47bba046e13935..d303b789adfec20fb4e4d02f66fb2e95dde26002 100644 (file)
@@ -62,3 +62,31 @@ void dml_init_instance(struct display_mode_lib *lib, enum dml_project project)
        }
 }
 
+const char *dml_get_status_message(enum dm_validation_status status)
+{
+       switch (status) {
+       case DML_VALIDATION_OK:                   return "Validation OK";
+       case DML_FAIL_SCALE_RATIO_TAP:            return "Scale ratio/tap";
+       case DML_FAIL_SOURCE_PIXEL_FORMAT:        return "Source pixel format";
+       case DML_FAIL_VIEWPORT_SIZE:              return "Viewport size";
+       case DML_FAIL_TOTAL_V_ACTIVE_BW:          return "Total vertical active bandwidth";
+       case DML_FAIL_DIO_SUPPORT:                return "DIO support";
+       case DML_FAIL_NOT_ENOUGH_DSC:             return "Not enough DSC Units";
+       case DML_FAIL_DSC_CLK_REQUIRED:           return "DSC clock required";
+       case DML_FAIL_URGENT_LATENCY:             return "Urgent latency";
+       case DML_FAIL_REORDERING_BUFFER:          return "Re-ordering buffer";
+       case DML_FAIL_DISPCLK_DPPCLK:             return "Dispclk and Dppclk";
+       case DML_FAIL_TOTAL_AVAILABLE_PIPES:      return "Total available pipes";
+       case DML_FAIL_NUM_OTG:                    return "Number of OTG";
+       case DML_FAIL_WRITEBACK_MODE:             return "Writeback mode";
+       case DML_FAIL_WRITEBACK_LATENCY:          return "Writeback latency";
+       case DML_FAIL_WRITEBACK_SCALE_RATIO_TAP:  return "Writeback scale ratio/tap";
+       case DML_FAIL_CURSOR_SUPPORT:             return "Cursor support";
+       case DML_FAIL_PITCH_SUPPORT:              return "Pitch support";
+       case DML_FAIL_PTE_BUFFER_SIZE:            return "PTE buffer size";
+       case DML_FAIL_DSC_INPUT_BPC:              return "DSC input bpc";
+       case DML_FAIL_PREFETCH_SUPPORT:           return "Prefetch support";
+       case DML_FAIL_V_RATIO_PREFETCH:           return "Vertical ratio prefetch";
+       default:                                  return "Unknown Status";
+       }
+}
index 6352062488898d4d445d94411635594d197df42d..a730e0209c056ef919fe15c7e0950c954bb117e8 100644 (file)
@@ -43,4 +43,6 @@ struct display_mode_lib {
 
 void dml_init_instance(struct display_mode_lib *lib, enum dml_project project);
 
+const char *dml_get_status_message(enum dm_validation_status status);
+
 #endif
index 5dd04520ceca5fa1ad0d52c74ee055087c660cb9..391183e3428faf4bbdaf24717d09087ec2faf28f 100644 (file)
@@ -30,22 +30,15 @@ typedef struct _vcs_dpi_soc_bounding_box_st soc_bounding_box_st;
 typedef struct _vcs_dpi_ip_params_st ip_params_st;
 typedef struct _vcs_dpi_display_pipe_source_params_st display_pipe_source_params_st;
 typedef struct _vcs_dpi_display_output_params_st display_output_params_st;
-typedef struct _vcs_dpi_display_bandwidth_st display_bandwidth_st;
 typedef struct _vcs_dpi_scaler_ratio_depth_st scaler_ratio_depth_st;
 typedef struct _vcs_dpi_scaler_taps_st scaler_taps_st;
 typedef struct _vcs_dpi_display_pipe_dest_params_st display_pipe_dest_params_st;
 typedef struct _vcs_dpi_display_pipe_params_st display_pipe_params_st;
 typedef struct _vcs_dpi_display_clocks_and_cfg_st display_clocks_and_cfg_st;
 typedef struct _vcs_dpi_display_e2e_pipe_params_st display_e2e_pipe_params_st;
-typedef struct _vcs_dpi_dchub_buffer_sizing_st dchub_buffer_sizing_st;
-typedef struct _vcs_dpi_watermarks_perf_st watermarks_perf_st;
-typedef struct _vcs_dpi_cstate_pstate_watermarks_st cstate_pstate_watermarks_st;
-typedef struct _vcs_dpi_wm_calc_pipe_params_st wm_calc_pipe_params_st;
-typedef struct _vcs_dpi_vratio_pre_st vratio_pre_st;
 typedef struct _vcs_dpi_display_data_rq_misc_params_st display_data_rq_misc_params_st;
 typedef struct _vcs_dpi_display_data_rq_sizing_params_st display_data_rq_sizing_params_st;
 typedef struct _vcs_dpi_display_data_rq_dlg_params_st display_data_rq_dlg_params_st;
-typedef struct _vcs_dpi_display_cur_rq_dlg_params_st display_cur_rq_dlg_params_st;
 typedef struct _vcs_dpi_display_rq_dlg_params_st display_rq_dlg_params_st;
 typedef struct _vcs_dpi_display_rq_sizing_params_st display_rq_sizing_params_st;
 typedef struct _vcs_dpi_display_rq_misc_params_st display_rq_misc_params_st;
@@ -55,8 +48,6 @@ typedef struct _vcs_dpi_display_ttu_regs_st display_ttu_regs_st;
 typedef struct _vcs_dpi_display_data_rq_regs_st display_data_rq_regs_st;
 typedef struct _vcs_dpi_display_rq_regs_st display_rq_regs_st;
 typedef struct _vcs_dpi_display_dlg_sys_params_st display_dlg_sys_params_st;
-typedef struct _vcs_dpi_display_dlg_prefetch_param_st display_dlg_prefetch_param_st;
-typedef struct _vcs_dpi_display_pipe_clock_st display_pipe_clock_st;
 typedef struct _vcs_dpi_display_arb_params_st display_arb_params_st;
 
 struct _vcs_dpi_voltage_scaling_st {
@@ -111,8 +102,6 @@ struct _vcs_dpi_soc_bounding_box_st {
        double xfc_bus_transport_time_us;
        double xfc_xbuf_latency_tolerance_us;
        int use_urgent_burst_bw;
-       double max_hscl_ratio;
-       double max_vscl_ratio;
        unsigned int num_states;
        struct _vcs_dpi_voltage_scaling_st clock_limits[8];
 };
@@ -129,7 +118,8 @@ struct _vcs_dpi_ip_params_st {
        unsigned int odm_capable;
        unsigned int rob_buffer_size_kbytes;
        unsigned int det_buffer_size_kbytes;
-       unsigned int dpte_buffer_size_in_pte_reqs;
+       unsigned int dpte_buffer_size_in_pte_reqs_luma;
+       unsigned int dpte_buffer_size_in_pte_reqs_chroma;
        unsigned int pde_proc_buffer_size_64k_reqs;
        unsigned int dpp_output_buffer_pixels;
        unsigned int opp_output_buffer_lines;
@@ -192,7 +182,6 @@ struct _vcs_dpi_display_xfc_params_st {
 struct _vcs_dpi_display_pipe_source_params_st {
        int source_format;
        unsigned char dcc;
-       unsigned int dcc_override;
        unsigned int dcc_rate;
        unsigned char dcc_use_global;
        unsigned char vm;
@@ -205,7 +194,6 @@ struct _vcs_dpi_display_pipe_source_params_st {
        int source_scan;
        int sw_mode;
        int macro_tile_size;
-       unsigned char is_display_sw;
        unsigned int viewport_width;
        unsigned int viewport_height;
        unsigned int viewport_y_y;
@@ -252,16 +240,10 @@ struct _vcs_dpi_display_output_params_st {
        int output_bpc;
        int output_type;
        int output_format;
-       int output_standard;
        int dsc_slices;
        struct writeback_st wb;
 };
 
-struct _vcs_dpi_display_bandwidth_st {
-       double total_bw_consumed_gbps;
-       double guaranteed_urgent_return_bw_gbps;
-};
-
 struct _vcs_dpi_scaler_ratio_depth_st {
        double hscl_ratio;
        double vscl_ratio;
@@ -300,11 +282,9 @@ struct _vcs_dpi_display_pipe_dest_params_st {
        unsigned int vupdate_width;
        unsigned int vready_offset;
        unsigned char interlaced;
-       unsigned char underscan;
        double pixel_rate_mhz;
        unsigned char synchronized_vblank_all_planes;
        unsigned char otg_inst;
-       unsigned char odm_split_cnt;
        unsigned char odm_combine;
        unsigned char use_maximum_vstartup;
 };
@@ -331,65 +311,6 @@ struct _vcs_dpi_display_e2e_pipe_params_st {
        display_clocks_and_cfg_st clks_cfg;
 };
 
-struct _vcs_dpi_dchub_buffer_sizing_st {
-       unsigned int swath_width_y;
-       unsigned int swath_height_y;
-       unsigned int swath_height_c;
-       unsigned int detail_buffer_size_y;
-};
-
-struct _vcs_dpi_watermarks_perf_st {
-       double stutter_eff_in_active_region_percent;
-       double urgent_latency_supported_us;
-       double non_urgent_latency_supported_us;
-       double dram_clock_change_margin_us;
-       double dram_access_eff_percent;
-};
-
-struct _vcs_dpi_cstate_pstate_watermarks_st {
-       double cstate_exit_us;
-       double cstate_enter_plus_exit_us;
-       double pstate_change_us;
-};
-
-struct _vcs_dpi_wm_calc_pipe_params_st {
-       unsigned int num_dpp;
-       int voltage;
-       int output_type;
-       double dcfclk_mhz;
-       double socclk_mhz;
-       double dppclk_mhz;
-       double pixclk_mhz;
-       unsigned char interlace_en;
-       unsigned char pte_enable;
-       unsigned char dcc_enable;
-       double dcc_rate;
-       double bytes_per_pixel_c;
-       double bytes_per_pixel_y;
-       unsigned int swath_width_y;
-       unsigned int swath_height_y;
-       unsigned int swath_height_c;
-       unsigned int det_buffer_size_y;
-       double h_ratio;
-       double v_ratio;
-       unsigned int h_taps;
-       unsigned int h_total;
-       unsigned int v_total;
-       unsigned int v_active;
-       unsigned int e2e_index;
-       double display_pipe_line_delivery_time;
-       double read_bw;
-       unsigned int lines_in_det_y;
-       unsigned int lines_in_det_y_rounded_down_to_swath;
-       double full_det_buffering_time;
-       double dcfclk_deepsleep_mhz_per_plane;
-};
-
-struct _vcs_dpi_vratio_pre_st {
-       double vratio_pre_l;
-       double vratio_pre_c;
-};
-
 struct _vcs_dpi_display_data_rq_misc_params_st {
        unsigned int full_swath_bytes;
        unsigned int stored_swath_bytes;
@@ -423,16 +344,9 @@ struct _vcs_dpi_display_data_rq_dlg_params_st {
        unsigned int meta_bytes_per_row_ub;
 };
 
-struct _vcs_dpi_display_cur_rq_dlg_params_st {
-       unsigned char enable;
-       unsigned int swath_height;
-       unsigned int req_per_line;
-};
-
 struct _vcs_dpi_display_rq_dlg_params_st {
        display_data_rq_dlg_params_st rq_l;
        display_data_rq_dlg_params_st rq_c;
-       display_cur_rq_dlg_params_st rq_cur0;
 };
 
 struct _vcs_dpi_display_rq_sizing_params_st {
@@ -498,6 +412,10 @@ struct _vcs_dpi_display_dlg_regs_st {
        unsigned int xfc_reg_remote_surface_flip_latency;
        unsigned int xfc_reg_prefetch_margin;
        unsigned int dst_y_delta_drq_limit;
+       unsigned int refcyc_per_vm_group_vblank;
+       unsigned int refcyc_per_vm_group_flip;
+       unsigned int refcyc_per_vm_req_vblank;
+       unsigned int refcyc_per_vm_req_flip;
 };
 
 struct _vcs_dpi_display_ttu_regs_st {
@@ -556,19 +474,6 @@ struct _vcs_dpi_display_dlg_sys_params_st {
        unsigned int total_flip_bytes;
 };
 
-struct _vcs_dpi_display_dlg_prefetch_param_st {
-       double prefetch_bw;
-       unsigned int flip_bytes;
-};
-
-struct _vcs_dpi_display_pipe_clock_st {
-       double dcfclk_mhz;
-       double dispclk_mhz;
-       double socclk_mhz;
-       double dscclk_mhz[6];
-       double dppclk_mhz[6];
-};
-
 struct _vcs_dpi_display_arb_params_st {
        int max_req_outstanding;
        int min_req_outstanding;
index c2037daa8e6666d7b2dd9b76477e03f7472e9220..ad8571f5a142fb3405d78dd165119f4a2a4a4d3e 100644 (file)
@@ -459,7 +459,7 @@ static void dml1_rq_dlg_get_row_heights(
        /* dpte   */
        /* ------ */
        log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes);
-       dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs;
+       dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs_luma;
 
        log2_vmpg_height = 0;
        log2_vmpg_width = 0;
@@ -776,7 +776,7 @@ static void get_surf_rq_param(
        /* dpte   */
        /* ------ */
        log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes);
-       dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs;
+       dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs_luma;
 
        log2_vmpg_height = 0;
        log2_vmpg_width = 0;
@@ -881,7 +881,7 @@ static void get_surf_rq_param(
        /* the dpte_group_bytes is reduced for the specific case of vertical
         * access of a tile surface that has dpte request of 8x1 ptes.
         */
-       if (!surf_linear & (log2_dpte_req_height_ptes == 0) & surf_vert) /*reduced, in this case, will have page fault within a group */
+       if (!surf_linear && (log2_dpte_req_height_ptes == 0) && surf_vert) /*reduced, in this case, will have page fault within a group */
                rq_sizing_param->dpte_group_bytes = 512;
        else
                /*full size */
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile
deleted file mode 100644 (file)
index 352885c..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-#
-# Copyright 2017 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.
-#
-#
-# Makefile for the 'i2c' sub-component of DAL.
-# It provides the control and status of HW i2c engine of the adapter.
-
-I2CAUX = aux_engine.o engine_base.o i2caux.o i2c_engine.o \
-        i2c_generic_hw_engine.o i2c_hw_engine.o i2c_sw_engine.o
-
-AMD_DAL_I2CAUX = $(addprefix $(AMDDALPATH)/dc/i2caux/,$(I2CAUX))
-
-AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX)
-
-###############################################################################
-# DCE 8x family
-###############################################################################
-I2CAUX_DCE80 = i2caux_dce80.o i2c_hw_engine_dce80.o \
-       i2c_sw_engine_dce80.o
-
-AMD_DAL_I2CAUX_DCE80 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce80/,$(I2CAUX_DCE80))
-
-AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE80)
-
-###############################################################################
-# DCE 100 family
-###############################################################################
-I2CAUX_DCE100 = i2caux_dce100.o
-
-AMD_DAL_I2CAUX_DCE100 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce100/,$(I2CAUX_DCE100))
-
-AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE100)
-
-###############################################################################
-# DCE 110 family
-###############################################################################
-I2CAUX_DCE110 = i2caux_dce110.o i2c_sw_engine_dce110.o i2c_hw_engine_dce110.o \
-       aux_engine_dce110.o
-
-AMD_DAL_I2CAUX_DCE110 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce110/,$(I2CAUX_DCE110))
-
-AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE110)
-
-###############################################################################
-# DCE 112 family
-###############################################################################
-I2CAUX_DCE112 = i2caux_dce112.o
-
-AMD_DAL_I2CAUX_DCE112 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce112/,$(I2CAUX_DCE112))
-
-AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE112)
-
-###############################################################################
-# DCN 1.0 family
-###############################################################################
-ifdef CONFIG_DRM_AMD_DC_DCN1_0
-I2CAUX_DCN1 = i2caux_dcn10.o
-
-AMD_DAL_I2CAUX_DCN1 = $(addprefix $(AMDDALPATH)/dc/i2caux/dcn10/,$(I2CAUX_DCN1))
-
-AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCN1)
-endif
-
-###############################################################################
-# DCE 120 family
-###############################################################################
-I2CAUX_DCE120 = i2caux_dce120.o
-
-AMD_DAL_I2CAUX_DCE120 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce120/,$(I2CAUX_DCE120))
-
-AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE120)
-
-###############################################################################
-# Diagnostics on FPGA
-###############################################################################
-I2CAUX_DIAG = i2caux_diag.o
-
-AMD_DAL_I2CAUX_DIAG = $(addprefix $(AMDDALPATH)/dc/i2caux/diagnostics/,$(I2CAUX_DIAG))
-
-AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DIAG)
-
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c
deleted file mode 100644 (file)
index 8cbf38b..0000000
+++ /dev/null
@@ -1,606 +0,0 @@
-/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-#include "dm_event_log.h"
-
-/*
- * Pre-requisites: headers required by header of this unit
- */
-#include "include/i2caux_interface.h"
-#include "engine.h"
-
-/*
- * Header of this unit
- */
-
-#include "aux_engine.h"
-
-/*
- * Post-requisites: headers required by this unit
- */
-
-#include "include/link_service_types.h"
-
-/*
- * This unit
- */
-
-enum {
-       AUX_INVALID_REPLY_RETRY_COUNTER = 1,
-       AUX_TIMED_OUT_RETRY_COUNTER = 2,
-       AUX_DEFER_RETRY_COUNTER = 6
-};
-
-#define FROM_ENGINE(ptr) \
-       container_of((ptr), struct aux_engine, base)
-#define DC_LOGGER \
-       engine->base.ctx->logger
-
-enum i2caux_engine_type dal_aux_engine_get_engine_type(
-       const struct engine *engine)
-{
-       return I2CAUX_ENGINE_TYPE_AUX;
-}
-
-bool dal_aux_engine_acquire(
-       struct engine *engine,
-       struct ddc *ddc)
-{
-       struct aux_engine *aux_engine = FROM_ENGINE(engine);
-
-       enum gpio_result result;
-       if (aux_engine->funcs->is_engine_available) {
-               /*check whether SW could use the engine*/
-               if (!aux_engine->funcs->is_engine_available(aux_engine)) {
-                       return false;
-               }
-       }
-
-       result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
-               GPIO_DDC_CONFIG_TYPE_MODE_AUX);
-
-       if (result != GPIO_RESULT_OK)
-               return false;
-
-       if (!aux_engine->funcs->acquire_engine(aux_engine)) {
-               dal_ddc_close(ddc);
-               return false;
-       }
-
-       engine->ddc = ddc;
-
-       return true;
-}
-
-struct read_command_context {
-       uint8_t *buffer;
-       uint32_t current_read_length;
-       uint32_t offset;
-       enum i2caux_transaction_status status;
-
-       struct aux_request_transaction_data request;
-       struct aux_reply_transaction_data reply;
-
-       uint8_t returned_byte;
-
-       uint32_t timed_out_retry_aux;
-       uint32_t invalid_reply_retry_aux;
-       uint32_t defer_retry_aux;
-       uint32_t defer_retry_i2c;
-       uint32_t invalid_reply_retry_aux_on_ack;
-
-       bool transaction_complete;
-       bool operation_succeeded;
-};
-
-static void process_read_reply(
-       struct aux_engine *engine,
-       struct read_command_context *ctx)
-{
-       engine->funcs->process_channel_reply(engine, &ctx->reply);
-
-       switch (ctx->reply.status) {
-       case AUX_TRANSACTION_REPLY_AUX_ACK:
-               ctx->defer_retry_aux = 0;
-               if (ctx->returned_byte > ctx->current_read_length) {
-                       ctx->status =
-                               I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
-                       ctx->operation_succeeded = false;
-               } else if (ctx->returned_byte < ctx->current_read_length) {
-                       ctx->current_read_length -= ctx->returned_byte;
-
-                       ctx->offset += ctx->returned_byte;
-
-                       ++ctx->invalid_reply_retry_aux_on_ack;
-
-                       if (ctx->invalid_reply_retry_aux_on_ack >
-                               AUX_INVALID_REPLY_RETRY_COUNTER) {
-                               ctx->status =
-                               I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
-                               ctx->operation_succeeded = false;
-                       }
-               } else {
-                       ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
-                       ctx->transaction_complete = true;
-                       ctx->operation_succeeded = true;
-               }
-       break;
-       case AUX_TRANSACTION_REPLY_AUX_NACK:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
-               ctx->operation_succeeded = false;
-       break;
-       case AUX_TRANSACTION_REPLY_AUX_DEFER:
-               ++ctx->defer_retry_aux;
-
-               if (ctx->defer_retry_aux > AUX_DEFER_RETRY_COUNTER) {
-                       ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
-                       ctx->operation_succeeded = false;
-               }
-       break;
-       case AUX_TRANSACTION_REPLY_I2C_DEFER:
-               ctx->defer_retry_aux = 0;
-
-               ++ctx->defer_retry_i2c;
-
-               if (ctx->defer_retry_i2c > AUX_DEFER_RETRY_COUNTER) {
-                       ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
-                       ctx->operation_succeeded = false;
-               }
-       break;
-       case AUX_TRANSACTION_REPLY_HPD_DISCON:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
-               ctx->operation_succeeded = false;
-       break;
-       default:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
-               ctx->operation_succeeded = false;
-       }
-}
-
-static void process_read_request(
-       struct aux_engine *engine,
-       struct read_command_context *ctx)
-{
-       enum aux_channel_operation_result operation_result;
-
-       engine->funcs->submit_channel_request(engine, &ctx->request);
-
-       operation_result = engine->funcs->get_channel_status(
-               engine, &ctx->returned_byte);
-
-       switch (operation_result) {
-       case AUX_CHANNEL_OPERATION_SUCCEEDED:
-               if (ctx->returned_byte > ctx->current_read_length) {
-                       ctx->status =
-                               I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
-                       ctx->operation_succeeded = false;
-               } else {
-                       ctx->timed_out_retry_aux = 0;
-                       ctx->invalid_reply_retry_aux = 0;
-
-                       ctx->reply.length = ctx->returned_byte;
-                       ctx->reply.data = ctx->buffer;
-
-                       process_read_reply(engine, ctx);
-               }
-       break;
-       case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
-               ++ctx->invalid_reply_retry_aux;
-
-               if (ctx->invalid_reply_retry_aux >
-                       AUX_INVALID_REPLY_RETRY_COUNTER) {
-                       ctx->status =
-                               I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
-                       ctx->operation_succeeded = false;
-               } else
-                       udelay(400);
-       break;
-       case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
-               ++ctx->timed_out_retry_aux;
-
-               if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) {
-                       ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
-                       ctx->operation_succeeded = false;
-               } else {
-                       /* DP 1.2a, table 2-58:
-                        * "S3: AUX Request CMD PENDING:
-                        * retry 3 times, with 400usec wait on each"
-                        * The HW timeout is set to 550usec,
-                        * so we should not wait here */
-               }
-       break;
-       case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
-               ctx->operation_succeeded = false;
-       break;
-       default:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
-               ctx->operation_succeeded = false;
-       }
-}
-
-static bool read_command(
-       struct aux_engine *engine,
-       struct i2caux_transaction_request *request,
-       bool middle_of_transaction)
-{
-       struct read_command_context ctx;
-
-       ctx.buffer = request->payload.data;
-       ctx.current_read_length = request->payload.length;
-       ctx.offset = 0;
-       ctx.timed_out_retry_aux = 0;
-       ctx.invalid_reply_retry_aux = 0;
-       ctx.defer_retry_aux = 0;
-       ctx.defer_retry_i2c = 0;
-       ctx.invalid_reply_retry_aux_on_ack = 0;
-       ctx.transaction_complete = false;
-       ctx.operation_succeeded = true;
-
-       if (request->payload.address_space ==
-               I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
-               ctx.request.type = AUX_TRANSACTION_TYPE_DP;
-               ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_READ;
-               ctx.request.address = request->payload.address;
-       } else if (request->payload.address_space ==
-               I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) {
-               ctx.request.type = AUX_TRANSACTION_TYPE_I2C;
-               ctx.request.action = middle_of_transaction ?
-                       I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
-                       I2CAUX_TRANSACTION_ACTION_I2C_READ;
-               ctx.request.address = request->payload.address >> 1;
-       } else {
-               /* in DAL2, there was no return in such case */
-               BREAK_TO_DEBUGGER();
-               return false;
-       }
-
-       ctx.request.delay = 0;
-
-       do {
-               memset(ctx.buffer + ctx.offset, 0, ctx.current_read_length);
-
-               ctx.request.data = ctx.buffer + ctx.offset;
-               ctx.request.length = ctx.current_read_length;
-
-               process_read_request(engine, &ctx);
-
-               request->status = ctx.status;
-
-               if (ctx.operation_succeeded && !ctx.transaction_complete)
-                       if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C)
-                               msleep(engine->delay);
-       } while (ctx.operation_succeeded && !ctx.transaction_complete);
-
-       if (request->payload.address_space ==
-               I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
-               DC_LOG_I2C_AUX("READ: addr:0x%x  value:0x%x Result:%d",
-                               request->payload.address,
-                               request->payload.data[0],
-                               ctx.operation_succeeded);
-       }
-
-       return ctx.operation_succeeded;
-}
-
-struct write_command_context {
-       bool mot;
-
-       uint8_t *buffer;
-       uint32_t current_write_length;
-       enum i2caux_transaction_status status;
-
-       struct aux_request_transaction_data request;
-       struct aux_reply_transaction_data reply;
-
-       uint8_t returned_byte;
-
-       uint32_t timed_out_retry_aux;
-       uint32_t invalid_reply_retry_aux;
-       uint32_t defer_retry_aux;
-       uint32_t defer_retry_i2c;
-       uint32_t max_defer_retry;
-       uint32_t ack_m_retry;
-
-       uint8_t reply_data[DEFAULT_AUX_MAX_DATA_SIZE];
-
-       bool transaction_complete;
-       bool operation_succeeded;
-};
-
-static void process_write_reply(
-       struct aux_engine *engine,
-       struct write_command_context *ctx)
-{
-       engine->funcs->process_channel_reply(engine, &ctx->reply);
-
-       switch (ctx->reply.status) {
-       case AUX_TRANSACTION_REPLY_AUX_ACK:
-               ctx->operation_succeeded = true;
-
-               if (ctx->returned_byte) {
-                       ctx->request.action = ctx->mot ?
-                       I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT :
-                       I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
-
-                       ctx->current_write_length = 0;
-
-                       ++ctx->ack_m_retry;
-
-                       if (ctx->ack_m_retry > AUX_DEFER_RETRY_COUNTER) {
-                               ctx->status =
-                               I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
-                               ctx->operation_succeeded = false;
-                       } else
-                               udelay(300);
-               } else {
-                       ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
-                       ctx->defer_retry_aux = 0;
-                       ctx->ack_m_retry = 0;
-                       ctx->transaction_complete = true;
-               }
-       break;
-       case AUX_TRANSACTION_REPLY_AUX_NACK:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
-               ctx->operation_succeeded = false;
-       break;
-       case AUX_TRANSACTION_REPLY_AUX_DEFER:
-               ++ctx->defer_retry_aux;
-
-               if (ctx->defer_retry_aux > ctx->max_defer_retry) {
-                       ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
-                       ctx->operation_succeeded = false;
-               }
-       break;
-       case AUX_TRANSACTION_REPLY_I2C_DEFER:
-               ctx->defer_retry_aux = 0;
-               ctx->current_write_length = 0;
-
-               ctx->request.action = ctx->mot ?
-                       I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT :
-                       I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
-
-               ++ctx->defer_retry_i2c;
-
-               if (ctx->defer_retry_i2c > ctx->max_defer_retry) {
-                       ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
-                       ctx->operation_succeeded = false;
-               }
-       break;
-       case AUX_TRANSACTION_REPLY_HPD_DISCON:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
-               ctx->operation_succeeded = false;
-       break;
-       default:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
-               ctx->operation_succeeded = false;
-       }
-}
-
-static void process_write_request(
-       struct aux_engine *engine,
-       struct write_command_context *ctx)
-{
-       enum aux_channel_operation_result operation_result;
-
-       engine->funcs->submit_channel_request(engine, &ctx->request);
-
-       operation_result = engine->funcs->get_channel_status(
-               engine, &ctx->returned_byte);
-
-       switch (operation_result) {
-       case AUX_CHANNEL_OPERATION_SUCCEEDED:
-               ctx->timed_out_retry_aux = 0;
-               ctx->invalid_reply_retry_aux = 0;
-
-               ctx->reply.length = ctx->returned_byte;
-               ctx->reply.data = ctx->reply_data;
-
-               process_write_reply(engine, ctx);
-       break;
-       case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
-               ++ctx->invalid_reply_retry_aux;
-
-               if (ctx->invalid_reply_retry_aux >
-                       AUX_INVALID_REPLY_RETRY_COUNTER) {
-                       ctx->status =
-                               I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
-                       ctx->operation_succeeded = false;
-               } else
-                       udelay(400);
-       break;
-       case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
-               ++ctx->timed_out_retry_aux;
-
-               if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) {
-                       ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
-                       ctx->operation_succeeded = false;
-               } else {
-                       /* DP 1.2a, table 2-58:
-                        * "S3: AUX Request CMD PENDING:
-                        * retry 3 times, with 400usec wait on each"
-                        * The HW timeout is set to 550usec,
-                        * so we should not wait here */
-               }
-       break;
-       case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON;
-               ctx->operation_succeeded = false;
-       break;
-       default:
-               ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
-               ctx->operation_succeeded = false;
-       }
-}
-
-static bool write_command(
-       struct aux_engine *engine,
-       struct i2caux_transaction_request *request,
-       bool middle_of_transaction)
-{
-       struct write_command_context ctx;
-
-       ctx.mot = middle_of_transaction;
-       ctx.buffer = request->payload.data;
-       ctx.current_write_length = request->payload.length;
-       ctx.timed_out_retry_aux = 0;
-       ctx.invalid_reply_retry_aux = 0;
-       ctx.defer_retry_aux = 0;
-       ctx.defer_retry_i2c = 0;
-       ctx.ack_m_retry = 0;
-       ctx.transaction_complete = false;
-       ctx.operation_succeeded = true;
-
-       if (request->payload.address_space ==
-               I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
-               ctx.request.type = AUX_TRANSACTION_TYPE_DP;
-               ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_WRITE;
-               ctx.request.address = request->payload.address;
-       } else if (request->payload.address_space ==
-               I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) {
-               ctx.request.type = AUX_TRANSACTION_TYPE_I2C;
-               ctx.request.action = middle_of_transaction ?
-                       I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
-                       I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
-               ctx.request.address = request->payload.address >> 1;
-       } else {
-               /* in DAL2, there was no return in such case */
-               BREAK_TO_DEBUGGER();
-               return false;
-       }
-
-       ctx.request.delay = 0;
-
-       ctx.max_defer_retry =
-               (engine->max_defer_write_retry > AUX_DEFER_RETRY_COUNTER) ?
-                       engine->max_defer_write_retry : AUX_DEFER_RETRY_COUNTER;
-
-       do {
-               ctx.request.data = ctx.buffer;
-               ctx.request.length = ctx.current_write_length;
-
-               process_write_request(engine, &ctx);
-
-               request->status = ctx.status;
-
-               if (ctx.operation_succeeded && !ctx.transaction_complete)
-                       if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C)
-                               msleep(engine->delay);
-       } while (ctx.operation_succeeded && !ctx.transaction_complete);
-
-       if (request->payload.address_space ==
-               I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
-               DC_LOG_I2C_AUX("WRITE: addr:0x%x  value:0x%x Result:%d",
-                               request->payload.address,
-                               request->payload.data[0],
-                               ctx.operation_succeeded);
-       }
-
-       return ctx.operation_succeeded;
-}
-
-static bool end_of_transaction_command(
-       struct aux_engine *engine,
-       struct i2caux_transaction_request *request)
-{
-       struct i2caux_transaction_request dummy_request;
-       uint8_t dummy_data;
-
-       /* [tcheng] We only need to send the stop (read with MOT = 0)
-        * for I2C-over-Aux, not native AUX */
-
-       if (request->payload.address_space !=
-               I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C)
-               return false;
-
-       dummy_request.operation = request->operation;
-       dummy_request.payload.address_space = request->payload.address_space;
-       dummy_request.payload.address = request->payload.address;
-
-       /*
-        * Add a dummy byte due to some receiver quirk
-        * where one byte is sent along with MOT = 0.
-        * Ideally this should be 0.
-        */
-
-       dummy_request.payload.length = 0;
-       dummy_request.payload.data = &dummy_data;
-
-       if (request->operation == I2CAUX_TRANSACTION_READ)
-               return read_command(engine, &dummy_request, false);
-       else
-               return write_command(engine, &dummy_request, false);
-
-       /* according Syed, it does not need now DoDummyMOT */
-}
-
-bool dal_aux_engine_submit_request(
-       struct engine *engine,
-       struct i2caux_transaction_request *request,
-       bool middle_of_transaction)
-{
-       struct aux_engine *aux_engine = FROM_ENGINE(engine);
-
-       bool result;
-       bool mot_used = true;
-
-       switch (request->operation) {
-       case I2CAUX_TRANSACTION_READ:
-               result = read_command(aux_engine, request, mot_used);
-       break;
-       case I2CAUX_TRANSACTION_WRITE:
-               result = write_command(aux_engine, request, mot_used);
-       break;
-       default:
-               result = false;
-       }
-
-       /* [tcheng]
-        * need to send stop for the last transaction to free up the AUX
-        * if the above command fails, this would be the last transaction */
-
-       if (!middle_of_transaction || !result)
-               end_of_transaction_command(aux_engine, request);
-
-       /* mask AUX interrupt */
-
-       return result;
-}
-
-void dal_aux_engine_construct(
-       struct aux_engine *engine,
-       struct dc_context *ctx)
-{
-       dal_i2caux_construct_engine(&engine->base, ctx);
-       engine->delay = 0;
-       engine->max_defer_write_retry = 0;
-}
-
-void dal_aux_engine_destruct(
-       struct aux_engine *engine)
-{
-       dal_i2caux_destruct_engine(&engine->base);
-}
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h
deleted file mode 100644 (file)
index c33a289..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2012-15 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 __DAL_AUX_ENGINE_H__
-#define __DAL_AUX_ENGINE_H__
-
-#include "dc_ddc_types.h"
-
-struct aux_engine;
-
-struct aux_engine_funcs {
-       void (*destroy)(
-               struct aux_engine **ptr);
-       bool (*acquire_engine)(
-               struct aux_engine *engine);
-       void (*configure)(
-               struct aux_engine *engine,
-               union aux_config cfg);
-       void (*submit_channel_request)(
-               struct aux_engine *engine,
-               struct aux_request_transaction_data *request);
-       void (*process_channel_reply)(
-               struct aux_engine *engine,
-               struct aux_reply_transaction_data *reply);
-       int (*read_channel_reply)(
-               struct aux_engine *engine,
-               uint32_t size,
-               uint8_t *buffer,
-               uint8_t *reply_result,
-               uint32_t *sw_status);
-       enum aux_channel_operation_result (*get_channel_status)(
-               struct aux_engine *engine,
-               uint8_t *returned_bytes);
-       bool (*is_engine_available) (
-               struct aux_engine *engine);
-};
-
-struct aux_engine {
-       struct engine base;
-       const struct aux_engine_funcs *funcs;
-       /* following values are expressed in milliseconds */
-       uint32_t delay;
-       uint32_t max_defer_write_retry;
-
-       bool acquire_reset;
-};
-
-void dal_aux_engine_construct(
-       struct aux_engine *engine,
-       struct dc_context *ctx);
-
-void dal_aux_engine_destruct(
-       struct aux_engine *engine);
-bool dal_aux_engine_submit_request(
-       struct engine *ptr,
-       struct i2caux_transaction_request *request,
-       bool middle_of_transaction);
-bool dal_aux_engine_acquire(
-       struct engine *ptr,
-       struct ddc *ddc);
-enum i2caux_engine_type dal_aux_engine_get_engine_type(
-       const struct engine *engine);
-
-#endif
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c
deleted file mode 100644 (file)
index 8b704ab..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-
-#include "include/i2caux_interface.h"
-#include "../i2caux.h"
-#include "../engine.h"
-#include "../i2c_engine.h"
-#include "../i2c_sw_engine.h"
-#include "../i2c_hw_engine.h"
-
-#include "../dce110/aux_engine_dce110.h"
-#include "../dce110/i2c_hw_engine_dce110.h"
-#include "../dce110/i2caux_dce110.h"
-
-#include "dce/dce_10_0_d.h"
-#include "dce/dce_10_0_sh_mask.h"
-
-/* set register offset */
-#define SR(reg_name)\
-       .reg_name = mm ## reg_name
-
-/* set register offset with instance */
-#define SRI(reg_name, block, id)\
-       .reg_name = mm ## block ## id ## _ ## reg_name
-
-#define aux_regs(id)\
-[id] = {\
-       AUX_COMMON_REG_LIST(id), \
-       .AUX_RESET_MASK = 0 \
-}
-
-#define hw_engine_regs(id)\
-{\
-               I2C_HW_ENGINE_COMMON_REG_LIST(id) \
-}
-
-static const struct dce110_aux_registers dce100_aux_regs[] = {
-               aux_regs(0),
-               aux_regs(1),
-               aux_regs(2),
-               aux_regs(3),
-               aux_regs(4),
-               aux_regs(5),
-};
-
-static const struct dce110_i2c_hw_engine_registers dce100_hw_engine_regs[] = {
-               hw_engine_regs(1),
-               hw_engine_regs(2),
-               hw_engine_regs(3),
-               hw_engine_regs(4),
-               hw_engine_regs(5),
-               hw_engine_regs(6)
-};
-
-static const struct dce110_i2c_hw_engine_shift i2c_shift = {
-               I2C_COMMON_MASK_SH_LIST_DCE100(__SHIFT)
-};
-
-static const struct dce110_i2c_hw_engine_mask i2c_mask = {
-               I2C_COMMON_MASK_SH_LIST_DCE100(_MASK)
-};
-
-struct i2caux *dal_i2caux_dce100_create(
-       struct dc_context *ctx)
-{
-       struct i2caux_dce110 *i2caux_dce110 =
-               kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL);
-
-       if (!i2caux_dce110) {
-               ASSERT_CRITICAL(false);
-               return NULL;
-       }
-
-       dal_i2caux_dce110_construct(i2caux_dce110,
-                                   ctx,
-                                   ARRAY_SIZE(dce100_aux_regs),
-                                   dce100_aux_regs,
-                                   dce100_hw_engine_regs,
-                                   &i2c_shift,
-                                   &i2c_mask);
-       return &i2caux_dce110->base;
-}
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h
deleted file mode 100644 (file)
index 2b508d3..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2012-15 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 __DAL_I2C_AUX_DCE100_H__
-#define __DAL_I2C_AUX_DCE100_H__
-
-struct i2caux *dal_i2caux_dce100_create(
-       struct dc_context *ctx);
-
-#endif /* __DAL_I2C_AUX_DCE100_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c
deleted file mode 100644 (file)
index 59c3ed4..0000000
+++ /dev/null
@@ -1,505 +0,0 @@
-/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-#include "dm_event_log.h"
-
-/*
- * Pre-requisites: headers required by header of this unit
- */
-#include "include/i2caux_interface.h"
-#include "../engine.h"
-#include "../aux_engine.h"
-
-/*
- * Header of this unit
- */
-
-#include "aux_engine_dce110.h"
-
-/*
- * Post-requisites: headers required by this unit
- */
-#include "dce/dce_11_0_sh_mask.h"
-
-#define CTX \
-       aux110->base.base.ctx
-#define REG(reg_name)\
-       (aux110->regs->reg_name)
-#include "reg_helper.h"
-
-/*
- * This unit
- */
-
-/*
- * @brief
- * Cast 'struct aux_engine *'
- * to 'struct aux_engine_dce110 *'
- */
-#define FROM_AUX_ENGINE(ptr) \
-       container_of((ptr), struct aux_engine_dce110, base)
-
-/*
- * @brief
- * Cast 'struct engine *'
- * to 'struct aux_engine_dce110 *'
- */
-#define FROM_ENGINE(ptr) \
-       FROM_AUX_ENGINE(container_of((ptr), struct aux_engine, base))
-
-static void release_engine(
-       struct engine *engine)
-{
-       struct aux_engine_dce110 *aux110 = FROM_ENGINE(engine);
-
-       REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1);
-}
-
-static void destruct(
-       struct aux_engine_dce110 *engine);
-
-static void destroy(
-       struct aux_engine **aux_engine)
-{
-       struct aux_engine_dce110 *engine = FROM_AUX_ENGINE(*aux_engine);
-
-       destruct(engine);
-
-       kfree(engine);
-
-       *aux_engine = NULL;
-}
-
-#define SW_CAN_ACCESS_AUX 1
-#define DMCU_CAN_ACCESS_AUX 2
-
-static bool is_engine_available(
-       struct aux_engine *engine)
-{
-       struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
-
-       uint32_t value = REG_READ(AUX_ARB_CONTROL);
-       uint32_t field = get_reg_field_value(
-                       value,
-                       AUX_ARB_CONTROL,
-                       AUX_REG_RW_CNTL_STATUS);
-
-       return (field != DMCU_CAN_ACCESS_AUX);
-}
-static bool acquire_engine(
-       struct aux_engine *engine)
-{
-       struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
-
-       uint32_t value = REG_READ(AUX_ARB_CONTROL);
-       uint32_t field = get_reg_field_value(
-                       value,
-                       AUX_ARB_CONTROL,
-                       AUX_REG_RW_CNTL_STATUS);
-       if (field == DMCU_CAN_ACCESS_AUX)
-        return false;
-       /* enable AUX before request SW to access AUX */
-       value = REG_READ(AUX_CONTROL);
-       field = get_reg_field_value(value,
-                               AUX_CONTROL,
-                               AUX_EN);
-
-       if (field == 0) {
-               set_reg_field_value(
-                               value,
-                               1,
-                               AUX_CONTROL,
-                               AUX_EN);
-
-               if (REG(AUX_RESET_MASK)) {
-                       /*DP_AUX block as part of the enable sequence*/
-                       set_reg_field_value(
-                               value,
-                               1,
-                               AUX_CONTROL,
-                               AUX_RESET);
-               }
-
-               REG_WRITE(AUX_CONTROL, value);
-
-               if (REG(AUX_RESET_MASK)) {
-                       /*poll HW to make sure reset it done*/
-
-                       REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1,
-                                       1, 11);
-
-                       set_reg_field_value(
-                               value,
-                               0,
-                               AUX_CONTROL,
-                               AUX_RESET);
-
-                       REG_WRITE(AUX_CONTROL, value);
-
-                       REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0,
-                                       1, 11);
-               }
-       } /*if (field)*/
-
-       /* request SW to access AUX */
-       REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1);
-
-       value = REG_READ(AUX_ARB_CONTROL);
-       field = get_reg_field_value(
-                       value,
-                       AUX_ARB_CONTROL,
-                       AUX_REG_RW_CNTL_STATUS);
-
-       return (field == SW_CAN_ACCESS_AUX);
-}
-
-#define COMPOSE_AUX_SW_DATA_16_20(command, address) \
-       ((command) | ((0xF0000 & (address)) >> 16))
-
-#define COMPOSE_AUX_SW_DATA_8_15(address) \
-       ((0xFF00 & (address)) >> 8)
-
-#define COMPOSE_AUX_SW_DATA_0_7(address) \
-       (0xFF & (address))
-
-static void submit_channel_request(
-       struct aux_engine *engine,
-       struct aux_request_transaction_data *request)
-{
-       struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
-       uint32_t value;
-       uint32_t length;
-
-       bool is_write =
-               ((request->type == AUX_TRANSACTION_TYPE_DP) &&
-                (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) ||
-               ((request->type == AUX_TRANSACTION_TYPE_I2C) &&
-               ((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
-                (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT)));
-       if (REG(AUXN_IMPCAL)) {
-               /* clear_aux_error */
-               REG_UPDATE_SEQ(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK,
-                               1,
-                               0);
-
-               REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK,
-                               1,
-                               0);
-
-               /* force_default_calibrate */
-               REG_UPDATE_1BY1_2(AUXN_IMPCAL,
-                               AUXN_IMPCAL_ENABLE, 1,
-                               AUXN_IMPCAL_OVERRIDE_ENABLE, 0);
-
-               /* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */
-
-               REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE,
-                               1,
-                               0);
-       }
-       /* set the delay and the number of bytes to write */
-
-       /* The length include
-        * the 4 bit header and the 20 bit address
-        * (that is 3 byte).
-        * If the requested length is non zero this means
-        * an addition byte specifying the length is required. */
-
-       length = request->length ? 4 : 3;
-       if (is_write)
-               length += request->length;
-
-       REG_UPDATE_2(AUX_SW_CONTROL,
-                       AUX_SW_START_DELAY, request->delay,
-                       AUX_SW_WR_BYTES, length);
-
-       /* program action and address and payload data (if 'is_write') */
-       value = REG_UPDATE_4(AUX_SW_DATA,
-                       AUX_SW_INDEX, 0,
-                       AUX_SW_DATA_RW, 0,
-                       AUX_SW_AUTOINCREMENT_DISABLE, 1,
-                       AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address));
-
-       value = REG_SET_2(AUX_SW_DATA, value,
-                       AUX_SW_AUTOINCREMENT_DISABLE, 0,
-                       AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address));
-
-       value = REG_SET(AUX_SW_DATA, value,
-                       AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address));
-
-       if (request->length) {
-               value = REG_SET(AUX_SW_DATA, value,
-                               AUX_SW_DATA, request->length - 1);
-       }
-
-       if (is_write) {
-               /* Load the HW buffer with the Data to be sent.
-                * This is relevant for write operation.
-                * For read, the data recived data will be
-                * processed in process_channel_reply(). */
-               uint32_t i = 0;
-
-               while (i < request->length) {
-                       value = REG_SET(AUX_SW_DATA, value,
-                                       AUX_SW_DATA, request->data[i]);
-
-                       ++i;
-               }
-       }
-
-       REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1);
-       REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0,
-                               10, aux110->timeout_period/10);
-       REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1);
-       EVENT_LOG_AUX_REQ(engine->base.ddc->pin_data->en, EVENT_LOG_AUX_ORIGIN_NATIVE,
-                                       request->action, request->address, request->length, request->data);
-}
-
-static int read_channel_reply(struct aux_engine *engine, uint32_t size,
-                             uint8_t *buffer, uint8_t *reply_result,
-                             uint32_t *sw_status)
-{
-       struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
-       uint32_t bytes_replied;
-       uint32_t reply_result_32;
-
-       *sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT,
-                            &bytes_replied);
-
-       /* In case HPD is LOW, exit AUX transaction */
-       if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
-               return -1;
-
-       /* Need at least the status byte */
-       if (!bytes_replied)
-               return -1;
-
-       REG_UPDATE_1BY1_3(AUX_SW_DATA,
-                         AUX_SW_INDEX, 0,
-                         AUX_SW_AUTOINCREMENT_DISABLE, 1,
-                         AUX_SW_DATA_RW, 1);
-
-       REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32);
-       reply_result_32 = reply_result_32 >> 4;
-       *reply_result = (uint8_t)reply_result_32;
-
-       if (reply_result_32 == 0) { /* ACK */
-               uint32_t i = 0;
-
-               /* First byte was already used to get the command status */
-               --bytes_replied;
-
-               /* Do not overflow buffer */
-               if (bytes_replied > size)
-                       return -1;
-
-               while (i < bytes_replied) {
-                       uint32_t aux_sw_data_val;
-
-                       REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val);
-                       buffer[i] = aux_sw_data_val;
-                       ++i;
-               }
-
-               return i;
-       }
-
-       return 0;
-}
-
-static void process_channel_reply(
-       struct aux_engine *engine,
-       struct aux_reply_transaction_data *reply)
-{
-       int bytes_replied;
-       uint8_t reply_result;
-       uint32_t sw_status;
-
-       bytes_replied = read_channel_reply(engine, reply->length, reply->data,
-                                               &reply_result, &sw_status);
-       EVENT_LOG_AUX_REP(engine->base.ddc->pin_data->en,
-                                       EVENT_LOG_AUX_ORIGIN_NATIVE, reply_result,
-                                       bytes_replied, reply->data);
-
-       /* in case HPD is LOW, exit AUX transaction */
-       if ((sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) {
-               reply->status = AUX_TRANSACTION_REPLY_HPD_DISCON;
-               return;
-       }
-
-       if (bytes_replied < 0) {
-               /* Need to handle an error case...
-                * Hopefully, upper layer function won't call this function if
-                * the number of bytes in the reply was 0, because there was
-                * surely an error that was asserted that should have been
-                * handled for hot plug case, this could happens
-                */
-               if (!(sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) {
-                       reply->status = AUX_TRANSACTION_REPLY_INVALID;
-                       ASSERT_CRITICAL(false);
-                       return;
-               }
-       } else {
-
-               switch (reply_result) {
-               case 0: /* ACK */
-                       reply->status = AUX_TRANSACTION_REPLY_AUX_ACK;
-               break;
-               case 1: /* NACK */
-                       reply->status = AUX_TRANSACTION_REPLY_AUX_NACK;
-               break;
-               case 2: /* DEFER */
-                       reply->status = AUX_TRANSACTION_REPLY_AUX_DEFER;
-               break;
-               case 4: /* AUX ACK / I2C NACK */
-                       reply->status = AUX_TRANSACTION_REPLY_I2C_NACK;
-               break;
-               case 8: /* AUX ACK / I2C DEFER */
-                       reply->status = AUX_TRANSACTION_REPLY_I2C_DEFER;
-               break;
-               default:
-                       reply->status = AUX_TRANSACTION_REPLY_INVALID;
-               }
-       }
-}
-
-static enum aux_channel_operation_result get_channel_status(
-       struct aux_engine *engine,
-       uint8_t *returned_bytes)
-{
-       struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
-
-       uint32_t value;
-
-       if (returned_bytes == NULL) {
-               /*caller pass NULL pointer*/
-               ASSERT_CRITICAL(false);
-               return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN;
-       }
-       *returned_bytes = 0;
-
-       /* poll to make sure that SW_DONE is asserted */
-       value = REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1,
-                               10, aux110->timeout_period/10);
-
-       /* in case HPD is LOW, exit AUX transaction */
-       if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
-               return AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON;
-
-       /* Note that the following bits are set in 'status.bits'
-        * during CTS 4.2.1.2 (FW 3.3.1):
-        * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP,
-        * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H.
-        *
-        * AUX_SW_RX_MIN_COUNT_VIOL is an internal,
-        * HW debugging bit and should be ignored. */
-       if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) {
-               if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) ||
-                       (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK))
-                       return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
-
-               else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) ||
-                       (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) ||
-                       (value &
-                               AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) ||
-                       (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK))
-                       return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
-
-               *returned_bytes = get_reg_field_value(value,
-                               AUX_SW_STATUS,
-                               AUX_SW_REPLY_BYTE_COUNT);
-
-               if (*returned_bytes == 0)
-                       return
-                       AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
-               else {
-                       *returned_bytes -= 1;
-                       return AUX_CHANNEL_OPERATION_SUCCEEDED;
-               }
-       } else {
-               /*time_elapsed >= aux_engine->timeout_period
-                *  AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point
-                */
-               ASSERT_CRITICAL(false);
-               return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
-       }
-}
-
-static const struct aux_engine_funcs aux_engine_funcs = {
-       .destroy = destroy,
-       .acquire_engine = acquire_engine,
-       .submit_channel_request = submit_channel_request,
-       .process_channel_reply = process_channel_reply,
-       .read_channel_reply = read_channel_reply,
-       .get_channel_status = get_channel_status,
-       .is_engine_available = is_engine_available,
-};
-
-static const struct engine_funcs engine_funcs = {
-       .release_engine = release_engine,
-       .submit_request = dal_aux_engine_submit_request,
-       .get_engine_type = dal_aux_engine_get_engine_type,
-       .acquire = dal_aux_engine_acquire,
-};
-
-static void construct(
-       struct aux_engine_dce110 *engine,
-       const struct aux_engine_dce110_init_data *aux_init_data)
-{
-       dal_aux_engine_construct(&engine->base, aux_init_data->ctx);
-       engine->base.base.funcs = &engine_funcs;
-       engine->base.funcs = &aux_engine_funcs;
-
-       engine->timeout_period = aux_init_data->timeout_period;
-       engine->regs = aux_init_data->regs;
-}
-
-static void destruct(
-       struct aux_engine_dce110 *engine)
-{
-       dal_aux_engine_destruct(&engine->base);
-}
-
-struct aux_engine *dal_aux_engine_dce110_create(
-       const struct aux_engine_dce110_init_data *aux_init_data)
-{
-       struct aux_engine_dce110 *engine;
-
-       if (!aux_init_data) {
-               ASSERT_CRITICAL(false);
-               return NULL;
-       }
-
-       engine = kzalloc(sizeof(*engine), GFP_KERNEL);
-
-       if (!engine) {
-               ASSERT_CRITICAL(false);
-               return NULL;
-       }
-
-       construct(engine, aux_init_data);
-       return &engine->base;
-}
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h
deleted file mode 100644 (file)
index 85ee821..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2012-15 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 __DAL_AUX_ENGINE_DCE110_H__
-#define __DAL_AUX_ENGINE_DCE110_H__
-
-#include "../aux_engine.h"
-
-#define AUX_COMMON_REG_LIST(id)\
-       SRI(AUX_CONTROL, DP_AUX, id), \
-       SRI(AUX_ARB_CONTROL, DP_AUX, id), \
-       SRI(AUX_SW_DATA, DP_AUX, id), \
-       SRI(AUX_SW_CONTROL, DP_AUX, id), \
-       SRI(AUX_INTERRUPT_CONTROL, DP_AUX, id), \
-       SRI(AUX_SW_STATUS, DP_AUX, id), \
-       SR(AUXN_IMPCAL), \
-       SR(AUXP_IMPCAL)
-
-struct dce110_aux_registers {
-       uint32_t AUX_CONTROL;
-       uint32_t AUX_ARB_CONTROL;
-       uint32_t AUX_SW_DATA;
-       uint32_t AUX_SW_CONTROL;
-       uint32_t AUX_INTERRUPT_CONTROL;
-       uint32_t AUX_SW_STATUS;
-       uint32_t AUXN_IMPCAL;
-       uint32_t AUXP_IMPCAL;
-
-       uint32_t AUX_RESET_MASK;
-};
-
-struct aux_engine_dce110 {
-       struct aux_engine base;
-       const struct dce110_aux_registers *regs;
-       struct {
-               uint32_t aux_control;
-               uint32_t aux_arb_control;
-               uint32_t aux_sw_data;
-               uint32_t aux_sw_control;
-               uint32_t aux_interrupt_control;
-               uint32_t aux_sw_status;
-       } addr;
-       uint32_t timeout_period;
-};
-
-struct aux_engine_dce110_init_data {
-       uint32_t engine_id;
-       uint32_t timeout_period;
-       struct dc_context *ctx;
-       const struct dce110_aux_registers *regs;
-};
-
-struct aux_engine *dal_aux_engine_dce110_create(
-       const struct aux_engine_dce110_init_data *aux_init_data);
-
-#endif
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c
deleted file mode 100644 (file)
index 9cbe1a7..0000000
+++ /dev/null
@@ -1,574 +0,0 @@
-/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-#include "include/logger_interface.h"
-/*
- * Pre-requisites: headers required by header of this unit
- */
-
-#include "include/i2caux_interface.h"
-#include "../engine.h"
-#include "../i2c_engine.h"
-#include "../i2c_hw_engine.h"
-#include "../i2c_generic_hw_engine.h"
-/*
- * Header of this unit
- */
-
-#include "i2c_hw_engine_dce110.h"
-
-/*
- * Post-requisites: headers required by this unit
- */
-#include "reg_helper.h"
-
-/*
- * This unit
- */
-#define DC_LOGGER \
-               hw_engine->base.base.base.ctx->logger
-
-enum dc_i2c_status {
-       DC_I2C_STATUS__DC_I2C_STATUS_IDLE,
-       DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW,
-       DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW
-};
-
-enum dc_i2c_arbitration {
-       DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL,
-       DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_HIGH
-};
-
-
-
-/*
- * @brief
- * Cast pointer to 'struct i2c_hw_engine *'
- * to pointer 'struct i2c_hw_engine_dce110 *'
- */
-#define FROM_I2C_HW_ENGINE(ptr) \
-       container_of((ptr), struct i2c_hw_engine_dce110, base)
-/*
- * @brief
- * Cast pointer to 'struct i2c_engine *'
- * to pointer to 'struct i2c_hw_engine_dce110 *'
- */
-#define FROM_I2C_ENGINE(ptr) \
-       FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base))
-
-/*
- * @brief
- * Cast pointer to 'struct engine *'
- * to 'pointer to struct i2c_hw_engine_dce110 *'
- */
-#define FROM_ENGINE(ptr) \
-       FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
-
-#define CTX \
-               hw_engine->base.base.base.ctx
-
-#define REG(reg_name)\
-       (hw_engine->regs->reg_name)
-
-#undef FN
-#define FN(reg_name, field_name) \
-       hw_engine->i2c_shift->field_name, hw_engine->i2c_mask->field_name
-
-#include "reg_helper.h"
-
-static void disable_i2c_hw_engine(
-       struct i2c_hw_engine_dce110 *hw_engine)
-{
-       REG_UPDATE_N(SETUP, 1, FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 0);
-}
-
-static void release_engine(
-       struct engine *engine)
-{
-       struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);
-
-       struct i2c_engine *base = NULL;
-       bool safe_to_reset;
-
-       base = &hw_engine->base.base;
-
-       /* Restore original HW engine speed */
-
-       base->funcs->set_speed(base, hw_engine->base.original_speed);
-
-       /* Release I2C */
-       REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, 1);
-
-       /* Reset HW engine */
-       {
-               uint32_t i2c_sw_status = 0;
-               REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
-               /* if used by SW, safe to reset */
-               safe_to_reset = (i2c_sw_status == 1);
-       }
-
-       if (safe_to_reset)
-               REG_UPDATE_2(
-                       DC_I2C_CONTROL,
-                       DC_I2C_SOFT_RESET, 1,
-                       DC_I2C_SW_STATUS_RESET, 1);
-       else
-               REG_UPDATE(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, 1);
-
-       /* HW I2c engine - clock gating feature */
-       if (!hw_engine->engine_keep_power_up_count)
-               disable_i2c_hw_engine(hw_engine);
-}
-
-static bool setup_engine(
-       struct i2c_engine *i2c_engine)
-{
-       struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine);
-       uint32_t i2c_setup_limit = I2C_SETUP_TIME_LIMIT_DCE;
-       uint32_t  reset_length = 0;
-
-       if (hw_engine->base.base.setup_limit != 0)
-               i2c_setup_limit = hw_engine->base.base.setup_limit;
-
-       /* Program pin select */
-       REG_UPDATE_6(
-                       DC_I2C_CONTROL,
-                       DC_I2C_GO, 0,
-                       DC_I2C_SOFT_RESET, 0,
-                       DC_I2C_SEND_RESET, 0,
-                       DC_I2C_SW_STATUS_RESET, 1,
-                       DC_I2C_TRANSACTION_COUNT, 0,
-                       DC_I2C_DDC_SELECT, hw_engine->engine_id);
-
-       /* Program time limit */
-       if (hw_engine->base.base.send_reset_length == 0) {
-               /*pre-dcn*/
-               REG_UPDATE_N(
-                               SETUP, 2,
-                               FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT), i2c_setup_limit,
-                               FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 1);
-       } else {
-               reset_length = hw_engine->base.base.send_reset_length;
-       }
-       /* Program HW priority
-        * set to High - interrupt software I2C at any time
-        * Enable restart of SW I2C that was interrupted by HW
-        * disable queuing of software while I2C is in use by HW */
-       REG_UPDATE_2(
-                       DC_I2C_ARBITRATION,
-                       DC_I2C_NO_QUEUED_SW_GO, 0,
-                       DC_I2C_SW_PRIORITY, DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL);
-
-       return true;
-}
-
-static uint32_t get_speed(
-       const struct i2c_engine *i2c_engine)
-{
-       const struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine);
-       uint32_t pre_scale = 0;
-
-       REG_GET(SPEED, DC_I2C_DDC1_PRESCALE, &pre_scale);
-
-       /* [anaumov] it seems following is unnecessary */
-       /*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/
-       return pre_scale ?
-               hw_engine->reference_frequency / pre_scale :
-               hw_engine->base.default_speed;
-}
-
-static void set_speed(
-       struct i2c_engine *i2c_engine,
-       uint32_t speed)
-{
-       struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine);
-
-       if (speed) {
-               if (hw_engine->i2c_mask->DC_I2C_DDC1_START_STOP_TIMING_CNTL)
-                       REG_UPDATE_N(
-                               SPEED, 3,
-                               FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), hw_engine->reference_frequency / speed,
-                               FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2,
-                               FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_START_STOP_TIMING_CNTL), speed > 50 ? 2:1);
-               else
-                       REG_UPDATE_N(
-                               SPEED, 2,
-                               FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), hw_engine->reference_frequency / speed,
-                               FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2);
-       }
-}
-
-static inline void reset_hw_engine(struct engine *engine)
-{
-       struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);
-
-       REG_UPDATE_2(
-                       DC_I2C_CONTROL,
-                       DC_I2C_SW_STATUS_RESET, 1,
-                       DC_I2C_SW_STATUS_RESET, 1);
-}
-
-static bool is_hw_busy(struct engine *engine)
-{
-       struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);
-       uint32_t i2c_sw_status = 0;
-
-       REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
-       if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
-               return false;
-
-       reset_hw_engine(engine);
-
-       REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
-       return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE;
-}
-
-
-#define STOP_TRANS_PREDICAT \
-               ((hw_engine->transaction_count == 3) || \
-                               (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||     \
-                               (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ))
-
-#define SET_I2C_TRANSACTION(id)        \
-               do {    \
-                       REG_UPDATE_N(DC_I2C_TRANSACTION##id, 5, \
-                               FN(DC_I2C_TRANSACTION0, DC_I2C_STOP_ON_NACK0), 1,       \
-                               FN(DC_I2C_TRANSACTION0, DC_I2C_START0), 1,      \
-                               FN(DC_I2C_TRANSACTION0, DC_I2C_STOP0), STOP_TRANS_PREDICAT ? 1:0,       \
-                               FN(DC_I2C_TRANSACTION0, DC_I2C_RW0), (0 != (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)),     \
-                               FN(DC_I2C_TRANSACTION0, DC_I2C_COUNT0), length);        \
-                               if (STOP_TRANS_PREDICAT)        \
-                                       last_transaction = true;        \
-               } while (false)
-
-
-static bool process_transaction(
-       struct i2c_hw_engine_dce110 *hw_engine,
-       struct i2c_request_transaction_data *request)
-{
-       uint32_t length = request->length;
-       uint8_t *buffer = request->data;
-       uint32_t value = 0;
-
-       bool last_transaction = false;
-
-       struct dc_context *ctx = NULL;
-
-       ctx = hw_engine->base.base.base.ctx;
-
-
-
-       switch (hw_engine->transaction_count) {
-       case 0:
-               SET_I2C_TRANSACTION(0);
-               break;
-       case 1:
-               SET_I2C_TRANSACTION(1);
-               break;
-       case 2:
-               SET_I2C_TRANSACTION(2);
-               break;
-       case 3:
-               SET_I2C_TRANSACTION(3);
-               break;
-       default:
-               /* TODO Warning ? */
-               break;
-       }
-
-
-       /* Write the I2C address and I2C data
-        * into the hardware circular buffer, one byte per entry.
-        * As an example, the 7-bit I2C slave address for CRT monitor
-        * for reading DDC/EDID information is 0b1010001.
-        * For an I2C send operation, the LSB must be programmed to 0;
-        * for I2C receive operation, the LSB must be programmed to 1. */
-       if (hw_engine->transaction_count == 0) {
-               value = REG_SET_4(DC_I2C_DATA, 0,
-                                 DC_I2C_DATA_RW, false,
-                                 DC_I2C_DATA, request->address,
-                                 DC_I2C_INDEX, 0,
-                                 DC_I2C_INDEX_WRITE, 1);
-               hw_engine->buffer_used_write = 0;
-       } else
-               value = REG_SET_2(DC_I2C_DATA, 0,
-                                 DC_I2C_DATA_RW, false,
-                                 DC_I2C_DATA, request->address);
-
-       hw_engine->buffer_used_write++;
-
-       if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
-               while (length) {
-                       REG_SET_2(DC_I2C_DATA, value,
-                                       DC_I2C_INDEX_WRITE, 0,
-                                       DC_I2C_DATA, *buffer++);
-                       hw_engine->buffer_used_write++;
-                       --length;
-               }
-       }
-
-       ++hw_engine->transaction_count;
-       hw_engine->buffer_used_bytes += length + 1;
-
-       return last_transaction;
-}
-
-static void execute_transaction(
-       struct i2c_hw_engine_dce110 *hw_engine)
-{
-       REG_UPDATE_N(SETUP, 5,
-               FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_EN), 0,
-               FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_DRIVE_EN), 0,
-               FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL), 0,
-               FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY), 0,
-               FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY), 0);
-
-
-       REG_UPDATE_5(DC_I2C_CONTROL,
-               DC_I2C_SOFT_RESET, 0,
-               DC_I2C_SW_STATUS_RESET, 0,
-               DC_I2C_SEND_RESET, 0,
-               DC_I2C_GO, 0,
-               DC_I2C_TRANSACTION_COUNT, hw_engine->transaction_count - 1);
-
-       /* start I2C transfer */
-       REG_UPDATE(DC_I2C_CONTROL, DC_I2C_GO, 1);
-
-       /* all transactions were executed and HW buffer became empty
-        * (even though it actually happens when status becomes DONE) */
-       hw_engine->transaction_count = 0;
-       hw_engine->buffer_used_bytes = 0;
-}
-
-static void submit_channel_request(
-       struct i2c_engine *engine,
-       struct i2c_request_transaction_data *request)
-{
-       request->status = I2C_CHANNEL_OPERATION_SUCCEEDED;
-
-       if (!process_transaction(FROM_I2C_ENGINE(engine), request))
-               return;
-
-       if (is_hw_busy(&engine->base)) {
-               request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
-               return;
-       }
-
-       execute_transaction(FROM_I2C_ENGINE(engine));
-}
-
-static void process_channel_reply(
-       struct i2c_engine *engine,
-       struct i2c_reply_transaction_data *reply)
-{
-       uint32_t length = reply->length;
-       uint8_t *buffer = reply->data;
-
-       struct i2c_hw_engine_dce110 *hw_engine =
-               FROM_I2C_ENGINE(engine);
-
-
-       REG_SET_3(DC_I2C_DATA, 0,
-                       DC_I2C_INDEX, hw_engine->buffer_used_write,
-                       DC_I2C_DATA_RW, 1,
-                       DC_I2C_INDEX_WRITE, 1);
-
-       while (length) {
-               /* after reading the status,
-                * if the I2C operation executed successfully
-                * (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller
-                * should read data bytes from I2C circular data buffer */
-
-               uint32_t i2c_data;
-
-               REG_GET(DC_I2C_DATA, DC_I2C_DATA, &i2c_data);
-               *buffer++ = i2c_data;
-
-               --length;
-       }
-}
-
-static enum i2c_channel_operation_result get_channel_status(
-       struct i2c_engine *i2c_engine,
-       uint8_t *returned_bytes)
-{
-       uint32_t i2c_sw_status = 0;
-       struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine);
-       uint32_t value =
-                       REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
-
-       if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW)
-               return I2C_CHANNEL_OPERATION_ENGINE_BUSY;
-       else if (value & hw_engine->i2c_mask->DC_I2C_SW_STOPPED_ON_NACK)
-               return I2C_CHANNEL_OPERATION_NO_RESPONSE;
-       else if (value & hw_engine->i2c_mask->DC_I2C_SW_TIMEOUT)
-               return I2C_CHANNEL_OPERATION_TIMEOUT;
-       else if (value & hw_engine->i2c_mask->DC_I2C_SW_ABORTED)
-               return I2C_CHANNEL_OPERATION_FAILED;
-       else if (value & hw_engine->i2c_mask->DC_I2C_SW_DONE)
-               return I2C_CHANNEL_OPERATION_SUCCEEDED;
-
-       /*
-        * this is the case when HW used for communication, I2C_SW_STATUS
-        * could be zero
-        */
-       return I2C_CHANNEL_OPERATION_SUCCEEDED;
-}
-
-static uint32_t get_hw_buffer_available_size(
-       const struct i2c_hw_engine *engine)
-{
-       return I2C_HW_BUFFER_SIZE -
-               FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes;
-}
-
-static uint32_t get_transaction_timeout(
-       const struct i2c_hw_engine *engine,
-       uint32_t length)
-{
-       uint32_t speed = engine->base.funcs->get_speed(&engine->base);
-
-       uint32_t period_timeout;
-       uint32_t num_of_clock_stretches;
-
-       if (!speed)
-               return 0;
-
-       period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed;
-
-       num_of_clock_stretches = 1 + (length << 3) + 1;
-       num_of_clock_stretches +=
-               (FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes << 3) +
-               (FROM_I2C_HW_ENGINE(engine)->transaction_count << 1);
-
-       return period_timeout * num_of_clock_stretches;
-}
-
-static void destroy(
-       struct i2c_engine **i2c_engine)
-{
-       struct i2c_hw_engine_dce110 *engine_dce110 =
-                       FROM_I2C_ENGINE(*i2c_engine);
-
-       dal_i2c_hw_engine_destruct(&engine_dce110->base);
-
-       kfree(engine_dce110);
-
-       *i2c_engine = NULL;
-}
-
-static const struct i2c_engine_funcs i2c_engine_funcs = {
-       .destroy = destroy,
-       .get_speed = get_speed,
-       .set_speed = set_speed,
-       .setup_engine = setup_engine,
-       .submit_channel_request = submit_channel_request,
-       .process_channel_reply = process_channel_reply,
-       .get_channel_status = get_channel_status,
-       .acquire_engine = dal_i2c_hw_engine_acquire_engine,
-};
-
-static const struct engine_funcs engine_funcs = {
-       .release_engine = release_engine,
-       .get_engine_type = dal_i2c_hw_engine_get_engine_type,
-       .acquire = dal_i2c_engine_acquire,
-       .submit_request = dal_i2c_hw_engine_submit_request,
-};
-
-static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = {
-       .get_hw_buffer_available_size = get_hw_buffer_available_size,
-       .get_transaction_timeout = get_transaction_timeout,
-       .wait_on_operation_result = dal_i2c_hw_engine_wait_on_operation_result,
-};
-
-static void construct(
-       struct i2c_hw_engine_dce110 *hw_engine,
-       const struct i2c_hw_engine_dce110_create_arg *arg)
-{
-       uint32_t xtal_ref_div = 0;
-
-       dal_i2c_hw_engine_construct(&hw_engine->base, arg->ctx);
-
-       hw_engine->base.base.base.funcs = &engine_funcs;
-       hw_engine->base.base.funcs = &i2c_engine_funcs;
-       hw_engine->base.funcs = &i2c_hw_engine_funcs;
-       hw_engine->base.default_speed = arg->default_speed;
-
-       hw_engine->regs = arg->regs;
-       hw_engine->i2c_shift = arg->i2c_shift;
-       hw_engine->i2c_mask = arg->i2c_mask;
-
-       hw_engine->engine_id = arg->engine_id;
-
-       hw_engine->buffer_used_bytes = 0;
-       hw_engine->transaction_count = 0;
-       hw_engine->engine_keep_power_up_count = 1;
-
-
-       REG_GET(MICROSECOND_TIME_BASE_DIV, XTAL_REF_DIV, &xtal_ref_div);
-
-       if (xtal_ref_div == 0) {
-               DC_LOG_WARNING("Invalid base timer divider [%s]\n",
-                               __func__);
-               xtal_ref_div = 2;
-       }
-
-       /*Calculating Reference Clock by divding original frequency by
-        * XTAL_REF_DIV.
-        * At upper level, uint32_t reference_frequency =
-        *  dal_i2caux_get_reference_clock(as) >> 1
-        *  which already divided by 2. So we need x2 to get original
-        *  reference clock from ppll_info
-        */
-       hw_engine->reference_frequency =
-               (arg->reference_frequency * 2) / xtal_ref_div;
-}
-
-struct i2c_engine *dal_i2c_hw_engine_dce110_create(
-       const struct i2c_hw_engine_dce110_create_arg *arg)
-{
-       struct i2c_hw_engine_dce110 *engine_dce10;
-
-       if (!arg) {
-               ASSERT_CRITICAL(false);
-               return NULL;
-       }
-       if (!arg->reference_frequency) {
-               ASSERT_CRITICAL(false);
-               return NULL;
-       }
-
-       engine_dce10 = kzalloc(sizeof(struct i2c_hw_engine_dce110),
-                              GFP_KERNEL);
-
-       if (!engine_dce10) {
-               ASSERT_CRITICAL(false);
-               return NULL;
-       }
-
-       construct(engine_dce10, arg);
-       return &engine_dce10->base.base;
-}
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h
deleted file mode 100644 (file)
index fea2946..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright 2012-15 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 __DAL_I2C_HW_ENGINE_DCE110_H__
-#define __DAL_I2C_HW_ENGINE_DCE110_H__
-
-#define I2C_HW_ENGINE_COMMON_REG_LIST(id)\
-       SRI(SETUP, DC_I2C_DDC, id),\
-       SRI(SPEED, DC_I2C_DDC, id),\
-       SR(DC_I2C_ARBITRATION),\
-       SR(DC_I2C_CONTROL),\
-       SR(DC_I2C_SW_STATUS),\
-       SR(DC_I2C_TRANSACTION0),\
-       SR(DC_I2C_TRANSACTION1),\
-       SR(DC_I2C_TRANSACTION2),\
-       SR(DC_I2C_TRANSACTION3),\
-       SR(DC_I2C_DATA),\
-       SR(MICROSECOND_TIME_BASE_DIV)
-
-#define I2C_SF(reg_name, field_name, post_fix)\
-       .field_name = reg_name ## __ ## field_name ## post_fix
-
-#define I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\
-       I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE, mask_sh),\
-       I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT, mask_sh),\
-       I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_EN, mask_sh),\
-       I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_DRIVE_EN, mask_sh),\
-       I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL, mask_sh),\
-       I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY, mask_sh),\
-       I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY, mask_sh),\
-       I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, mask_sh),\
-       I2C_SF(DC_I2C_ARBITRATION, DC_I2C_NO_QUEUED_SW_GO, mask_sh),\
-       I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_PRIORITY, mask_sh),\
-       I2C_SF(DC_I2C_CONTROL, DC_I2C_SOFT_RESET, mask_sh),\
-       I2C_SF(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, mask_sh),\
-       I2C_SF(DC_I2C_CONTROL, DC_I2C_GO, mask_sh),\
-       I2C_SF(DC_I2C_CONTROL, DC_I2C_SEND_RESET, mask_sh),\
-       I2C_SF(DC_I2C_CONTROL, DC_I2C_TRANSACTION_COUNT, mask_sh),\
-       I2C_SF(DC_I2C_CONTROL, DC_I2C_DDC_SELECT, mask_sh),\
-       I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE, mask_sh),\
-       I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD, mask_sh),\
-       I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_STOPPED_ON_NACK, mask_sh),\
-       I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_TIMEOUT, mask_sh),\
-       I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_ABORTED, mask_sh),\
-       I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_DONE, mask_sh),\
-       I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, mask_sh),\
-       I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_STOP_ON_NACK0, mask_sh),\
-       I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_START0, mask_sh),\
-       I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_RW0, mask_sh),\
-       I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_STOP0, mask_sh),\
-       I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_COUNT0, mask_sh),\
-       I2C_SF(DC_I2C_DATA, DC_I2C_DATA_RW, mask_sh),\
-       I2C_SF(DC_I2C_DATA, DC_I2C_DATA, mask_sh),\
-       I2C_SF(DC_I2C_DATA, DC_I2C_INDEX, mask_sh),\
-       I2C_SF(DC_I2C_DATA, DC_I2C_INDEX_WRITE, mask_sh),\
-       I2C_SF(MICROSECOND_TIME_BASE_DIV, XTAL_REF_DIV, mask_sh)
-
-#define I2C_COMMON_MASK_SH_LIST_DCE100(mask_sh)\
-       I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)
-
-#define I2C_COMMON_MASK_SH_LIST_DCE110(mask_sh)\
-       I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\
-       I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_START_STOP_TIMING_CNTL, mask_sh)
-
-struct dce110_i2c_hw_engine_shift {
-       uint8_t DC_I2C_DDC1_ENABLE;
-       uint8_t DC_I2C_DDC1_TIME_LIMIT;
-       uint8_t DC_I2C_DDC1_DATA_DRIVE_EN;
-       uint8_t DC_I2C_DDC1_CLK_DRIVE_EN;
-       uint8_t DC_I2C_DDC1_DATA_DRIVE_SEL;
-       uint8_t DC_I2C_DDC1_INTRA_TRANSACTION_DELAY;
-       uint8_t DC_I2C_DDC1_INTRA_BYTE_DELAY;
-       uint8_t DC_I2C_SW_DONE_USING_I2C_REG;
-       uint8_t DC_I2C_NO_QUEUED_SW_GO;
-       uint8_t DC_I2C_SW_PRIORITY;
-       uint8_t DC_I2C_SOFT_RESET;
-       uint8_t DC_I2C_SW_STATUS_RESET;
-       uint8_t DC_I2C_GO;
-       uint8_t DC_I2C_SEND_RESET;
-       uint8_t DC_I2C_TRANSACTION_COUNT;
-       uint8_t DC_I2C_DDC_SELECT;
-       uint8_t DC_I2C_DDC1_PRESCALE;
-       uint8_t DC_I2C_DDC1_THRESHOLD;
-       uint8_t DC_I2C_DDC1_START_STOP_TIMING_CNTL;
-       uint8_t DC_I2C_SW_STOPPED_ON_NACK;
-       uint8_t DC_I2C_SW_TIMEOUT;
-       uint8_t DC_I2C_SW_ABORTED;
-       uint8_t DC_I2C_SW_DONE;
-       uint8_t DC_I2C_SW_STATUS;
-       uint8_t DC_I2C_STOP_ON_NACK0;
-       uint8_t DC_I2C_START0;
-       uint8_t DC_I2C_RW0;
-       uint8_t DC_I2C_STOP0;
-       uint8_t DC_I2C_COUNT0;
-       uint8_t DC_I2C_DATA_RW;
-       uint8_t DC_I2C_DATA;
-       uint8_t DC_I2C_INDEX;
-       uint8_t DC_I2C_INDEX_WRITE;
-       uint8_t XTAL_REF_DIV;
-};
-
-struct dce110_i2c_hw_engine_mask {
-       uint32_t DC_I2C_DDC1_ENABLE;
-       uint32_t DC_I2C_DDC1_TIME_LIMIT;
-       uint32_t DC_I2C_DDC1_DATA_DRIVE_EN;
-       uint32_t DC_I2C_DDC1_CLK_DRIVE_EN;
-       uint32_t DC_I2C_DDC1_DATA_DRIVE_SEL;
-       uint32_t DC_I2C_DDC1_INTRA_TRANSACTION_DELAY;
-       uint32_t DC_I2C_DDC1_INTRA_BYTE_DELAY;
-       uint32_t DC_I2C_SW_DONE_USING_I2C_REG;
-       uint32_t DC_I2C_NO_QUEUED_SW_GO;
-       uint32_t DC_I2C_SW_PRIORITY;
-       uint32_t DC_I2C_SOFT_RESET;
-       uint32_t DC_I2C_SW_STATUS_RESET;
-       uint32_t DC_I2C_GO;
-       uint32_t DC_I2C_SEND_RESET;
-       uint32_t DC_I2C_TRANSACTION_COUNT;
-       uint32_t DC_I2C_DDC_SELECT;
-       uint32_t DC_I2C_DDC1_PRESCALE;
-       uint32_t DC_I2C_DDC1_THRESHOLD;
-       uint32_t DC_I2C_DDC1_START_STOP_TIMING_CNTL;
-       uint32_t DC_I2C_SW_STOPPED_ON_NACK;
-       uint32_t DC_I2C_SW_TIMEOUT;
-       uint32_t DC_I2C_SW_ABORTED;
-       uint32_t DC_I2C_SW_DONE;
-       uint32_t DC_I2C_SW_STATUS;
-       uint32_t DC_I2C_STOP_ON_NACK0;
-       uint32_t DC_I2C_START0;
-       uint32_t DC_I2C_RW0;
-       uint32_t DC_I2C_STOP0;
-       uint32_t DC_I2C_COUNT0;
-       uint32_t DC_I2C_DATA_RW;
-       uint32_t DC_I2C_DATA;
-       uint32_t DC_I2C_INDEX;
-       uint32_t DC_I2C_INDEX_WRITE;
-       uint32_t XTAL_REF_DIV;
-};
-
-struct dce110_i2c_hw_engine_registers {
-       uint32_t SETUP;
-       uint32_t SPEED;
-       uint32_t DC_I2C_ARBITRATION;
-       uint32_t DC_I2C_CONTROL;
-       uint32_t DC_I2C_SW_STATUS;
-       uint32_t DC_I2C_TRANSACTION0;
-       uint32_t DC_I2C_TRANSACTION1;
-       uint32_t DC_I2C_TRANSACTION2;
-       uint32_t DC_I2C_TRANSACTION3;
-       uint32_t DC_I2C_DATA;
-       uint32_t MICROSECOND_TIME_BASE_DIV;
-};
-
-struct i2c_hw_engine_dce110 {
-       struct i2c_hw_engine base;
-       const struct dce110_i2c_hw_engine_registers *regs;
-       const struct dce110_i2c_hw_engine_shift *i2c_shift;
-       const struct dce110_i2c_hw_engine_mask *i2c_mask;
-       struct {
-               uint32_t DC_I2C_DDCX_SETUP;
-               uint32_t DC_I2C_DDCX_SPEED;
-       } addr;
-       uint32_t engine_id;
-       /* expressed in kilohertz */
-       uint32_t reference_frequency;
-       /* number of bytes currently used in HW buffer */
-       uint32_t buffer_used_bytes;
-       /* number of bytes used for write transaction in HW buffer
-        * - this will be used as the index to read from*/
-       uint32_t buffer_used_write;
-       /* number of pending transactions (before GO) */
-       uint32_t transaction_count;
-       uint32_t engine_keep_power_up_count;
-       uint32_t i2_setup_time_limit;
-};
-
-struct i2c_hw_engine_dce110_create_arg {
-       uint32_t engine_id;
-       uint32_t reference_frequency;
-       uint32_t default_speed;
-       struct dc_context *ctx;
-       const struct dce110_i2c_hw_engine_registers *regs;
-       const struct dce110_i2c_hw_engine_shift *i2c_shift;
-       const struct dce110_i2c_hw_engine_mask *i2c_mask;
-};
-
-struct i2c_engine *dal_i2c_hw_engine_dce110_create(
-       const struct i2c_hw_engine_dce110_create_arg *arg);
-
-enum {
-       I2C_SETUP_TIME_LIMIT_DCE = 255,
-       I2C_SETUP_TIME_LIMIT_DCN = 3,
-       I2C_HW_BUFFER_SIZE = 538,
-       I2C_SEND_RESET_LENGTH_9 = 9,
-       I2C_SEND_RESET_LENGTH_10 = 10,
-};
-#endif
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c
deleted file mode 100644 (file)
index 3aa7f79..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-
-/*
- * Pre-requisites: headers required by header of this unit
- */
-#include "include/i2caux_interface.h"
-#include "../engine.h"
-#include "../i2c_engine.h"
-#include "../i2c_sw_engine.h"
-
-/*
- * Header of this unit
- */
-
-#include "i2c_sw_engine_dce110.h"
-
-/*
- * Post-requisites: headers required by this unit
- */
-
-/*
- * This unit
- */
-
-/*
- * @brief
- * Cast 'struct i2c_sw_engine *'
- * to 'struct i2c_sw_engine_dce110 *'
- */
-#define FROM_I2C_SW_ENGINE(ptr) \
-       container_of((ptr), struct i2c_sw_engine_dce110, base)
-/*
- * @brief
- * Cast 'struct i2c_engine *'
- * to 'struct i2c_sw_engine_dce80 *'
- */
-#define FROM_I2C_ENGINE(ptr) \
-       FROM_I2C_SW_ENGINE(container_of((ptr), struct i2c_sw_engine, base))
-
-/*
- * @brief
- * Cast 'struct engine *'
- * to 'struct i2c_sw_engine_dce80 *'
- */
-#define FROM_ENGINE(ptr) \
-       FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
-
-static void release_engine(
-       struct engine *engine)
-{
-}
-
-static void destruct(
-       struct i2c_sw_engine_dce110 *engine)
-{
-       dal_i2c_sw_engine_destruct(&engine->base);
-}
-
-static void destroy(
-       struct i2c_engine **engine)
-{
-       struct i2c_sw_engine_dce110 *sw_engine = FROM_I2C_ENGINE(*engine);
-
-       destruct(sw_engine);
-
-       kfree(sw_engine);
-
-       *engine = NULL;
-}
-
-static bool acquire_engine(
-       struct i2c_engine *engine,
-       struct ddc *ddc_handle)
-{
-       return dal_i2caux_i2c_sw_engine_acquire_engine(engine, ddc_handle);
-}
-
-static const struct i2c_engine_funcs i2c_engine_funcs = {
-       .acquire_engine = acquire_engine,
-       .destroy = destroy,
-       .get_speed = dal_i2c_sw_engine_get_speed,
-       .set_speed = dal_i2c_sw_engine_set_speed,
-       .setup_engine = dal_i2c_engine_setup_i2c_engine,
-       .submit_channel_request = dal_i2c_sw_engine_submit_channel_request,
-       .process_channel_reply = dal_i2c_engine_process_channel_reply,
-       .get_channel_status = dal_i2c_sw_engine_get_channel_status,
-};
-
-static const struct engine_funcs engine_funcs = {
-       .release_engine = release_engine,
-       .get_engine_type = dal_i2c_sw_engine_get_engine_type,
-       .acquire = dal_i2c_engine_acquire,
-       .submit_request = dal_i2c_sw_engine_submit_request,
-};
-
-static void construct(
-       struct i2c_sw_engine_dce110 *engine_dce110,
-       const struct i2c_sw_engine_dce110_create_arg *arg_dce110)
-{
-       struct i2c_sw_engine_create_arg arg_base;
-
-       arg_base.ctx = arg_dce110->ctx;
-       arg_base.default_speed = arg_dce110->default_speed;
-
-       dal_i2c_sw_engine_construct(&engine_dce110->base, &arg_base);
-
-       /*struct engine   struct engine_funcs*/
-       engine_dce110->base.base.base.funcs = &engine_funcs;
-       /*struct i2c_engine  struct i2c_engine_funcs*/
-       engine_dce110->base.base.funcs = &i2c_engine_funcs;
-       engine_dce110->base.default_speed = arg_dce110->default_speed;
-       engine_dce110->engine_id = arg_dce110->engine_id;
-}
-
-struct i2c_engine *dal_i2c_sw_engine_dce110_create(
-       const struct i2c_sw_engine_dce110_create_arg *arg)
-{
-       struct i2c_sw_engine_dce110 *engine_dce110;
-
-       if (!arg) {
-               ASSERT_CRITICAL(false);
-               return NULL;
-       }
-
-       engine_dce110 = kzalloc(sizeof(struct i2c_sw_engine_dce110),
-                               GFP_KERNEL);
-
-       if (!engine_dce110) {
-               ASSERT_CRITICAL(false);
-               return NULL;
-       }
-
-       construct(engine_dce110, arg);
-       return &engine_dce110->base.base;
-}
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c
deleted file mode 100644 (file)
index 1d748ac..0000000
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-
-/*
- * Pre-requisites: headers required by header of this unit
- */
-#include "include/i2caux_interface.h"
-#include "../i2caux.h"
-#include "../engine.h"
-#include "../i2c_engine.h"
-#include "../i2c_sw_engine.h"
-#include "../i2c_hw_engine.h"
-
-/*
- * Header of this unit
- */
-#include "i2caux_dce110.h"
-
-#include "i2c_sw_engine_dce110.h"
-#include "i2c_hw_engine_dce110.h"
-#include "aux_engine_dce110.h"
-#include "../../dc.h"
-#include "dc_types.h"
-
-
-/*
- * Post-requisites: headers required by this unit
- */
-
-/*
- * This unit
- */
-/*cast pointer to struct i2caux TO pointer to struct i2caux_dce110*/
-#define FROM_I2C_AUX(ptr) \
-       container_of((ptr), struct i2caux_dce110, base)
-
-static void destruct(
-       struct i2caux_dce110 *i2caux_dce110)
-{
-       dal_i2caux_destruct(&i2caux_dce110->base);
-}
-
-static void destroy(
-       struct i2caux **i2c_engine)
-{
-       struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(*i2c_engine);
-
-       destruct(i2caux_dce110);
-
-       kfree(i2caux_dce110);
-
-       *i2c_engine = NULL;
-}
-
-static struct i2c_engine *acquire_i2c_hw_engine(
-       struct i2caux *i2caux,
-       struct ddc *ddc)
-{
-       struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(i2caux);
-
-       struct i2c_engine *engine = NULL;
-       /* generic hw engine is not used for EDID read
-        * It may be needed for external i2c device, like thermal chip,
-        * TODO will be implemented when needed.
-        * check dce80 bool non_generic for generic hw engine;
-        */
-
-       if (!ddc)
-               return NULL;
-
-       if (ddc->hw_info.hw_supported) {
-               enum gpio_ddc_line line = dal_ddc_get_line(ddc);
-
-               if (line < GPIO_DDC_LINE_COUNT)
-                       engine = i2caux->i2c_hw_engines[line];
-       }
-
-       if (!engine)
-               return NULL;
-
-       if (!i2caux_dce110->i2c_hw_buffer_in_use &&
-               engine->base.funcs->acquire(&engine->base, ddc)) {
-               i2caux_dce110->i2c_hw_buffer_in_use = true;
-               return engine;
-       }
-
-       return NULL;
-}
-
-static void release_engine(
-       struct i2caux *i2caux,
-       struct engine *engine)
-{
-       struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(i2caux);
-
-       if (engine->funcs->get_engine_type(engine) ==
-               I2CAUX_ENGINE_TYPE_I2C_DDC_HW)
-               i2caux_dce110->i2c_hw_buffer_in_use = false;
-
-       dal_i2caux_release_engine(i2caux, engine);
-}
-
-static const enum gpio_ddc_line hw_ddc_lines[] = {
-       GPIO_DDC_LINE_DDC1,
-       GPIO_DDC_LINE_DDC2,
-       GPIO_DDC_LINE_DDC3,
-       GPIO_DDC_LINE_DDC4,
-       GPIO_DDC_LINE_DDC5,
-       GPIO_DDC_LINE_DDC6,
-};
-
-static const enum gpio_ddc_line hw_aux_lines[] = {
-       GPIO_DDC_LINE_DDC1,
-       GPIO_DDC_LINE_DDC2,
-       GPIO_DDC_LINE_DDC3,
-       GPIO_DDC_LINE_DDC4,
-       GPIO_DDC_LINE_DDC5,
-       GPIO_DDC_LINE_DDC6,
-};
-
-/* function table */
-static const struct i2caux_funcs i2caux_funcs = {
-       .destroy = destroy,
-       .acquire_i2c_hw_engine = acquire_i2c_hw_engine,
-       .release_engine = release_engine,
-       .acquire_i2c_sw_engine = dal_i2caux_acquire_i2c_sw_engine,
-       .acquire_aux_engine = dal_i2caux_acquire_aux_engine,
-};
-
-#include "dce/dce_11_0_d.h"
-#include "dce/dce_11_0_sh_mask.h"
-
-/* set register offset */
-#define SR(reg_name)\
-       .reg_name = mm ## reg_name
-
-/* set register offset with instance */
-#define SRI(reg_name, block, id)\
-       .reg_name = mm ## block ## id ## _ ## reg_name
-
-#define aux_regs(id)\
-[id] = {\
-       AUX_COMMON_REG_LIST(id), \
-       .AUX_RESET_MASK = AUX_CONTROL__AUX_RESET_MASK \
-}
-
-#define hw_engine_regs(id)\
-{\
-               I2C_HW_ENGINE_COMMON_REG_LIST(id) \
-}
-
-static const struct dce110_aux_registers dce110_aux_regs[] = {
-               aux_regs(0),
-               aux_regs(1),
-               aux_regs(2),
-               aux_regs(3),
-               aux_regs(4),
-               aux_regs(5)
-};
-
-static const struct dce110_i2c_hw_engine_registers i2c_hw_engine_regs[] = {
-               hw_engine_regs(1),
-               hw_engine_regs(2),
-               hw_engine_regs(3),
-               hw_engine_regs(4),
-               hw_engine_regs(5),
-               hw_engine_regs(6)
-};
-
-static const struct dce110_i2c_hw_engine_shift i2c_shift = {
-               I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT)
-};
-
-static const struct dce110_i2c_hw_engine_mask i2c_mask = {
-               I2C_COMMON_MASK_SH_LIST_DCE110(_MASK)
-};
-
-void dal_i2caux_dce110_construct(
-       struct i2caux_dce110 *i2caux_dce110,
-       struct dc_context *ctx,
-       unsigned int num_i2caux_inst,
-       const struct dce110_aux_registers aux_regs[],
-       const struct dce110_i2c_hw_engine_registers i2c_hw_engine_regs[],
-       const struct dce110_i2c_hw_engine_shift *i2c_shift,
-       const struct dce110_i2c_hw_engine_mask *i2c_mask)
-{
-       uint32_t i = 0;
-       uint32_t reference_frequency = 0;
-       bool use_i2c_sw_engine = false;
-       struct i2caux *base = NULL;
-       /*TODO: For CZ bring up, if dal_i2caux_get_reference_clock
-        * does not return 48KHz, we need hard coded for 48Khz.
-        * Some BIOS setting incorrect cause this
-        * For production, we always get value from BIOS*/
-       reference_frequency =
-               dal_i2caux_get_reference_clock(ctx->dc_bios) >> 1;
-
-       base = &i2caux_dce110->base;
-
-       dal_i2caux_construct(base, ctx);
-
-       i2caux_dce110->base.funcs = &i2caux_funcs;
-       i2caux_dce110->i2c_hw_buffer_in_use = false;
-       /* Create I2C engines (DDC lines per connector)
-        * different I2C/AUX usage cases, DDC, Generic GPIO, AUX.
-        */
-       do {
-               enum gpio_ddc_line line_id = hw_ddc_lines[i];
-
-               struct i2c_hw_engine_dce110_create_arg hw_arg_dce110;
-
-               if (use_i2c_sw_engine) {
-                       struct i2c_sw_engine_dce110_create_arg sw_arg;
-
-                       sw_arg.engine_id = i;
-                       sw_arg.default_speed = base->default_i2c_sw_speed;
-                       sw_arg.ctx = ctx;
-                       base->i2c_sw_engines[line_id] =
-                               dal_i2c_sw_engine_dce110_create(&sw_arg);
-               }
-
-               hw_arg_dce110.engine_id = i;
-               hw_arg_dce110.reference_frequency = reference_frequency;
-               hw_arg_dce110.default_speed = base->default_i2c_hw_speed;
-               hw_arg_dce110.ctx = ctx;
-               hw_arg_dce110.regs = &i2c_hw_engine_regs[i];
-               hw_arg_dce110.i2c_shift = i2c_shift;
-               hw_arg_dce110.i2c_mask = i2c_mask;
-
-               base->i2c_hw_engines[line_id] =
-                       dal_i2c_hw_engine_dce110_create(&hw_arg_dce110);
-               if (base->i2c_hw_engines[line_id] != NULL) {
-                       switch (ctx->dce_version) {
-                       case DCN_VERSION_1_0:
-                               base->i2c_hw_engines[line_id]->setup_limit =
-                                       I2C_SETUP_TIME_LIMIT_DCN;
-                               base->i2c_hw_engines[line_id]->send_reset_length  = 0;
-                       break;
-                       default:
-                               base->i2c_hw_engines[line_id]->setup_limit =
-                                       I2C_SETUP_TIME_LIMIT_DCE;
-                               base->i2c_hw_engines[line_id]->send_reset_length  = 0;
-                               break;
-                       }
-               }
-               ++i;
-       } while (i < num_i2caux_inst);
-
-       /* Create AUX engines for all lines which has assisted HW AUX
-        * 'i' (loop counter) used as DDC/AUX engine_id */
-
-       i = 0;
-
-       do {
-               enum gpio_ddc_line line_id = hw_aux_lines[i];
-
-               struct aux_engine_dce110_init_data aux_init_data;
-
-               aux_init_data.engine_id = i;
-               aux_init_data.timeout_period = base->aux_timeout_period;
-               aux_init_data.ctx = ctx;
-               aux_init_data.regs = &aux_regs[i];
-
-               base->aux_engines[line_id] =
-                       dal_aux_engine_dce110_create(&aux_init_data);
-
-               ++i;
-       } while (i < num_i2caux_inst);
-
-       /*TODO Generic I2C SW and HW*/
-}
-
-/*
- * dal_i2caux_dce110_create
- *
- * @brief
- * public interface to allocate memory for DCE11 I2CAUX
- *
- * @param
- * struct adapter_service *as - [in]
- * struct dc_context *ctx - [in]
- *
- * @return
- * pointer to the base struct of DCE11 I2CAUX
- */
-struct i2caux *dal_i2caux_dce110_create(
-       struct dc_context *ctx)
-{
-       struct i2caux_dce110 *i2caux_dce110 =
-               kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL);
-
-       if (!i2caux_dce110) {
-               ASSERT_CRITICAL(false);
-               return NULL;
-       }
-
-       dal_i2caux_dce110_construct(i2caux_dce110,
-                                   ctx,
-                                   ARRAY_SIZE(dce110_aux_regs),
-                                   dce110_aux_regs,
-                                   i2c_hw_engine_regs,
-                                   &i2c_shift,
-                                   &i2c_mask);
-       return &i2caux_dce110->base;
-}
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h
deleted file mode 100644 (file)
index d3d8cc5..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012-15 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 __DAL_I2C_AUX_DCE110_H__
-#define __DAL_I2C_AUX_DCE110_H__
-
-#include "../i2caux.h"
-
-struct i2caux_dce110 {
-       struct i2caux base;
-       /* indicate the I2C HW circular buffer is in use */
-       bool i2c_hw_buffer_in_use;
-};
-
-struct dce110_aux_registers;
-struct dce110_i2c_hw_engine_registers;
-struct dce110_i2c_hw_engine_shift;
-struct dce110_i2c_hw_engine_mask;
-
-struct i2caux *dal_i2caux_dce110_create(
-       struct dc_context *ctx);
-
-void dal_i2caux_dce110_construct(
-       struct i2caux_dce110 *i2caux_dce110,
-       struct dc_context *ctx,
-       unsigned int num_i2caux_inst,
-       const struct dce110_aux_registers *aux_regs,
-       const struct dce110_i2c_hw_engine_registers *i2c_hw_engine_regs,
-       const struct dce110_i2c_hw_engine_shift *i2c_shift,
-       const struct dce110_i2c_hw_engine_mask *i2c_mask);
-
-#endif /* __DAL_I2C_AUX_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c
deleted file mode 100644 (file)
index a9db047..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-
-#include "include/i2caux_interface.h"
-#include "../i2caux.h"
-#include "../engine.h"
-#include "../i2c_engine.h"
-#include "../i2c_sw_engine.h"
-#include "../i2c_hw_engine.h"
-
-#include "../dce110/i2caux_dce110.h"
-#include "i2caux_dce112.h"
-
-#include "../dce110/aux_engine_dce110.h"
-
-#include "../dce110/i2c_hw_engine_dce110.h"
-
-#include "dce/dce_11_2_d.h"
-#include "dce/dce_11_2_sh_mask.h"
-
-/* set register offset */
-#define SR(reg_name)\
-       .reg_name = mm ## reg_name
-
-/* set register offset with instance */
-#define SRI(reg_name, block, id)\
-       .reg_name = mm ## block ## id ## _ ## reg_name
-
-#define aux_regs(id)\
-[id] = {\
-       AUX_COMMON_REG_LIST(id), \
-       .AUX_RESET_MASK = AUX_CONTROL__AUX_RESET_MASK \
-}
-
-#define hw_engine_regs(id)\
-{\
-               I2C_HW_ENGINE_COMMON_REG_LIST(id) \
-}
-
-static const struct dce110_aux_registers dce112_aux_regs[] = {
-               aux_regs(0),
-               aux_regs(1),
-               aux_regs(2),
-               aux_regs(3),
-               aux_regs(4),
-               aux_regs(5),
-};
-
-static const struct dce110_i2c_hw_engine_registers dce112_hw_engine_regs[] = {
-               hw_engine_regs(1),
-               hw_engine_regs(2),
-               hw_engine_regs(3),
-               hw_engine_regs(4),
-               hw_engine_regs(5),
-               hw_engine_regs(6)
-};
-
-static const struct dce110_i2c_hw_engine_shift i2c_shift = {
-               I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT)
-};
-
-static const struct dce110_i2c_hw_engine_mask i2c_mask = {
-               I2C_COMMON_MASK_SH_LIST_DCE110(_MASK)
-};
-
-static void construct(
-       struct i2caux_dce110 *i2caux_dce110,
-       struct dc_context *ctx)
-{
-       dal_i2caux_dce110_construct(i2caux_dce110,
-                                   ctx,
-                                   ARRAY_SIZE(dce112_aux_regs),
-                                   dce112_aux_regs,
-                                   dce112_hw_engine_regs,
-                                   &i2c_shift,
-                                   &i2c_mask);
-}
-
-/*
- * dal_i2caux_dce110_create
- *
- * @brief
- * public interface to allocate memory for DCE11 I2CAUX
- *
- * @param
- * struct adapter_service *as - [in]
- * struct dc_context *ctx - [in]
- *
- * @return
- * pointer to the base struct of DCE11 I2CAUX
- */
-struct i2caux *dal_i2caux_dce112_create(
-       struct dc_context *ctx)
-{
-       struct i2caux_dce110 *i2caux_dce110 =
-               kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL);
-
-       if (!i2caux_dce110) {
-               ASSERT_CRITICAL(false);
-               return NULL;
-       }
-
-       construct(i2caux_dce110, ctx);
-       return &i2caux_dce110->base;
-}
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h
deleted file mode 100644 (file)
index 8d35453..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2012-15 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 __DAL_I2C_AUX_DCE112_H__
-#define __DAL_I2C_AUX_DCE112_H__
-
-struct i2caux *dal_i2caux_dce112_create(
-       struct dc_context *ctx);
-
-#endif /* __DAL_I2C_AUX_DCE112_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c
deleted file mode 100644 (file)
index 6a4f344..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright 2012-16 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-
-#include "include/i2caux_interface.h"
-#include "../i2caux.h"
-#include "../engine.h"
-#include "../i2c_engine.h"
-#include "../i2c_sw_engine.h"
-#include "../i2c_hw_engine.h"
-
-#include "../dce110/i2c_hw_engine_dce110.h"
-#include "../dce110/aux_engine_dce110.h"
-#include "../dce110/i2caux_dce110.h"
-
-#include "dce/dce_12_0_offset.h"
-#include "dce/dce_12_0_sh_mask.h"
-#include "soc15_hw_ip.h"
-#include "vega10_ip_offset.h"
-
-/* begin *********************
- * macros to expend register list macro defined in HW object header file */
-
-#define BASE_INNER(seg) \
-       DCE_BASE__INST0_SEG ## seg
-
-/* compile time expand base address. */
-#define BASE(seg) \
-       BASE_INNER(seg)
-
-#define SR(reg_name)\
-               .reg_name = BASE(mm ## reg_name ## _BASE_IDX) +  \
-                                       mm ## reg_name
-
-#define SRI(reg_name, block, id)\
-       .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
-                                       mm ## block ## id ## _ ## reg_name
-/* macros to expend register list macro defined in HW object header file
- * end *********************/
-
-#define aux_regs(id)\
-[id] = {\
-       AUX_COMMON_REG_LIST(id), \
-       .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK \
-}
-
-static const struct dce110_aux_registers dce120_aux_regs[] = {
-               aux_regs(0),
-               aux_regs(1),
-               aux_regs(2),
-               aux_regs(3),
-               aux_regs(4),
-               aux_regs(5),
-};
-
-#define hw_engine_regs(id)\
-{\
-               I2C_HW_ENGINE_COMMON_REG_LIST(id) \
-}
-
-static const struct dce110_i2c_hw_engine_registers dce120_hw_engine_regs[] = {
-               hw_engine_regs(1),
-               hw_engine_regs(2),
-               hw_engine_regs(3),
-               hw_engine_regs(4),
-               hw_engine_regs(5),
-               hw_engine_regs(6)
-};
-
-static const struct dce110_i2c_hw_engine_shift i2c_shift = {
-               I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT)
-};
-
-static const struct dce110_i2c_hw_engine_mask i2c_mask = {
-               I2C_COMMON_MASK_SH_LIST_DCE110(_MASK)
-};
-
-struct i2caux *dal_i2caux_dce120_create(
-       struct dc_context *ctx)
-{
-       struct i2caux_dce110 *i2caux_dce110 =
-               kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL);
-
-       if (!i2caux_dce110) {
-               ASSERT_CRITICAL(false);
-               return NULL;
-       }
-
-       dal_i2caux_dce110_construct(i2caux_dce110,
-                                   ctx,
-                                   ARRAY_SIZE(dce120_aux_regs),
-                                   dce120_aux_regs,
-                                   dce120_hw_engine_regs,
-                                   &i2c_shift,
-                                   &i2c_mask);
-       return &i2caux_dce110->base;
-}
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c
deleted file mode 100644 (file)
index fd0832d..0000000
+++ /dev/null
@@ -1,875 +0,0 @@
-/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-
-/*
- * Pre-requisites: headers required by header of this unit
- */
-#include "include/i2caux_interface.h"
-#include "../engine.h"
-#include "../i2c_engine.h"
-#include "../i2c_hw_engine.h"
-#include "../i2c_generic_hw_engine.h"
-/*
- * Header of this unit
- */
-
-#include "i2c_hw_engine_dce80.h"
-
-/*
- * Post-requisites: headers required by this unit
- */
-
-#include "dce/dce_8_0_d.h"
-#include "dce/dce_8_0_sh_mask.h"
-/*
- * This unit
- */
-
-enum dc_i2c_status {
-       DC_I2C_STATUS__DC_I2C_STATUS_IDLE,
-       DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW,
-       DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW
-};
-
-enum dc_i2c_arbitration {
-       DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL,
-       DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_HIGH
-};
-
-enum {
-       /* No timeout in HW
-        * (timeout implemented in SW by querying status) */
-       I2C_SETUP_TIME_LIMIT = 255,
-       I2C_HW_BUFFER_SIZE = 144
-};
-
-/*
- * @brief
- * Cast 'struct i2c_hw_engine *'
- * to 'struct i2c_hw_engine_dce80 *'
- */
-#define FROM_I2C_HW_ENGINE(ptr) \
-       container_of((ptr), struct i2c_hw_engine_dce80, base)
-
-/*
- * @brief
- * Cast pointer to 'struct i2c_engine *'
- * to pointer to 'struct i2c_hw_engine_dce80 *'
- */
-#define FROM_I2C_ENGINE(ptr) \
-       FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base))
-
-/*
- * @brief
- * Cast pointer to 'struct engine *'
- * to 'pointer to struct i2c_hw_engine_dce80 *'
- */
-#define FROM_ENGINE(ptr) \
-       FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
-
-static void disable_i2c_hw_engine(
-       struct i2c_hw_engine_dce80 *engine)
-{
-       const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
-       uint32_t value = 0;
-
-       struct dc_context *ctx = NULL;
-
-       ctx = engine->base.base.base.ctx;
-
-       value = dm_read_reg(ctx, addr);
-
-       set_reg_field_value(
-               value,
-               0,
-               DC_I2C_DDC1_SETUP,
-               DC_I2C_DDC1_ENABLE);
-
-       dm_write_reg(ctx, addr, value);
-}
-
-static void release_engine(
-       struct engine *engine)
-{
-       struct i2c_hw_engine_dce80 *hw_engine = FROM_ENGINE(engine);
-
-       struct i2c_engine *base = NULL;
-       bool safe_to_reset;
-       uint32_t value = 0;
-
-       base = &hw_engine->base.base;
-
-       /* Restore original HW engine speed */
-
-       base->funcs->set_speed(base, hw_engine->base.original_speed);
-
-       /* Release I2C */
-       {
-               value = dm_read_reg(engine->ctx, mmDC_I2C_ARBITRATION);
-
-               set_reg_field_value(
-                               value,
-                               1,
-                               DC_I2C_ARBITRATION,
-                               DC_I2C_SW_DONE_USING_I2C_REG);
-
-               dm_write_reg(engine->ctx, mmDC_I2C_ARBITRATION, value);
-       }
-
-       /* Reset HW engine */
-       {
-               uint32_t i2c_sw_status = 0;
-
-               value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
-
-               i2c_sw_status = get_reg_field_value(
-                               value,
-                               DC_I2C_SW_STATUS,
-                               DC_I2C_SW_STATUS);
-               /* if used by SW, safe to reset */
-               safe_to_reset = (i2c_sw_status == 1);
-       }
-       {
-               value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL);
-
-               if (safe_to_reset)
-                       set_reg_field_value(
-                               value,
-                               1,
-                               DC_I2C_CONTROL,
-                               DC_I2C_SOFT_RESET);
-
-               set_reg_field_value(
-                       value,
-                       1,
-                       DC_I2C_CONTROL,
-                       DC_I2C_SW_STATUS_RESET);
-
-               dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value);
-       }
-
-       /* HW I2c engine - clock gating feature */
-       if (!hw_engine->engine_keep_power_up_count)
-               disable_i2c_hw_engine(hw_engine);
-}
-
-static void destruct(
-       struct i2c_hw_engine_dce80 *engine)
-{
-       dal_i2c_hw_engine_destruct(&engine->base);
-}
-
-static void destroy(
-       struct i2c_engine **i2c_engine)
-{
-       struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(*i2c_engine);
-
-       destruct(engine);
-
-       kfree(engine);
-
-       *i2c_engine = NULL;
-}
-
-static bool setup_engine(
-       struct i2c_engine *i2c_engine)
-{
-       uint32_t value = 0;
-       struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine);
-
-       /* Program pin select */
-       {
-               const uint32_t addr = mmDC_I2C_CONTROL;
-
-               value = dm_read_reg(i2c_engine->base.ctx, addr);
-
-               set_reg_field_value(
-                       value,
-                       0,
-                       DC_I2C_CONTROL,
-                       DC_I2C_GO);
-
-               set_reg_field_value(
-                       value,
-                       0,
-                       DC_I2C_CONTROL,
-                       DC_I2C_SOFT_RESET);
-
-               set_reg_field_value(
-                       value,
-                       0,
-                       DC_I2C_CONTROL,
-                       DC_I2C_SEND_RESET);
-
-               set_reg_field_value(
-                       value,
-                       0,
-                       DC_I2C_CONTROL,
-                       DC_I2C_SW_STATUS_RESET);
-
-               set_reg_field_value(
-                       value,
-                       0,
-                       DC_I2C_CONTROL,
-                       DC_I2C_TRANSACTION_COUNT);
-
-               set_reg_field_value(
-                       value,
-                       engine->engine_id,
-                       DC_I2C_CONTROL,
-                       DC_I2C_DDC_SELECT);
-
-               dm_write_reg(i2c_engine->base.ctx, addr, value);
-       }
-
-       /* Program time limit */
-       {
-               const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
-
-               value = dm_read_reg(i2c_engine->base.ctx, addr);
-
-               set_reg_field_value(
-                       value,
-                       I2C_SETUP_TIME_LIMIT,
-                       DC_I2C_DDC1_SETUP,
-                       DC_I2C_DDC1_TIME_LIMIT);
-
-               set_reg_field_value(
-                       value,
-                       1,
-                       DC_I2C_DDC1_SETUP,
-                       DC_I2C_DDC1_ENABLE);
-
-               dm_write_reg(i2c_engine->base.ctx, addr, value);
-       }
-
-       /* Program HW priority
-        * set to High - interrupt software I2C at any time
-        * Enable restart of SW I2C that was interrupted by HW
-        * disable queuing of software while I2C is in use by HW */
-       {
-               value = dm_read_reg(i2c_engine->base.ctx,
-                               mmDC_I2C_ARBITRATION);
-
-               set_reg_field_value(
-                       value,
-                       0,
-                       DC_I2C_ARBITRATION,
-                       DC_I2C_NO_QUEUED_SW_GO);
-
-               set_reg_field_value(
-                       value,
-                       DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL,
-                       DC_I2C_ARBITRATION,
-                       DC_I2C_SW_PRIORITY);
-
-               dm_write_reg(i2c_engine->base.ctx,
-                               mmDC_I2C_ARBITRATION, value);
-       }
-
-       return true;
-}
-
-static uint32_t get_speed(
-       const struct i2c_engine *i2c_engine)
-{
-       const struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine);
-
-       const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED;
-
-       uint32_t pre_scale = 0;
-
-       uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr);
-
-       pre_scale = get_reg_field_value(
-                       value,
-                       DC_I2C_DDC1_SPEED,
-                       DC_I2C_DDC1_PRESCALE);
-
-       /* [anaumov] it seems following is unnecessary */
-       /*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/
-
-       return pre_scale ?
-               engine->reference_frequency / pre_scale :
-               engine->base.default_speed;
-}
-
-static void set_speed(
-       struct i2c_engine *i2c_engine,
-       uint32_t speed)
-{
-       struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine);
-
-       if (speed) {
-               const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED;
-
-               uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr);
-
-               set_reg_field_value(
-                       value,
-                       engine->reference_frequency / speed,
-                       DC_I2C_DDC1_SPEED,
-                       DC_I2C_DDC1_PRESCALE);
-
-               set_reg_field_value(
-                       value,
-                       2,
-                       DC_I2C_DDC1_SPEED,
-                       DC_I2C_DDC1_THRESHOLD);
-
-               dm_write_reg(i2c_engine->base.ctx, addr, value);
-       }
-}
-
-static inline void reset_hw_engine(struct engine *engine)
-{
-       uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL);
-
-       set_reg_field_value(
-               value,
-               1,
-               DC_I2C_CONTROL,
-               DC_I2C_SOFT_RESET);
-
-       set_reg_field_value(
-               value,
-               1,
-               DC_I2C_CONTROL,
-               DC_I2C_SW_STATUS_RESET);
-
-       dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value);
-}
-
-static bool is_hw_busy(struct engine *engine)
-{
-       uint32_t i2c_sw_status = 0;
-
-       uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
-
-       i2c_sw_status = get_reg_field_value(
-                       value,
-                       DC_I2C_SW_STATUS,
-                       DC_I2C_SW_STATUS);
-
-       if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
-               return false;
-
-       reset_hw_engine(engine);
-
-       value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
-
-       i2c_sw_status = get_reg_field_value(
-                       value,
-                       DC_I2C_SW_STATUS,
-                       DC_I2C_SW_STATUS);
-
-       return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE;
-}
-
-/*
- * @brief
- * DC_GPIO_DDC MM register offsets
- */
-static const uint32_t transaction_addr[] = {
-       mmDC_I2C_TRANSACTION0,
-       mmDC_I2C_TRANSACTION1,
-       mmDC_I2C_TRANSACTION2,
-       mmDC_I2C_TRANSACTION3
-};
-
-static bool process_transaction(
-       struct i2c_hw_engine_dce80 *engine,
-       struct i2c_request_transaction_data *request)
-{
-       uint32_t length = request->length;
-       uint8_t *buffer = request->data;
-
-       bool last_transaction = false;
-       uint32_t value = 0;
-
-       struct dc_context *ctx = NULL;
-
-       ctx = engine->base.base.base.ctx;
-
-       {
-               const uint32_t addr =
-                       transaction_addr[engine->transaction_count];
-
-               value = dm_read_reg(ctx, addr);
-
-               set_reg_field_value(
-                       value,
-                       1,
-                       DC_I2C_TRANSACTION0,
-                       DC_I2C_STOP_ON_NACK0);
-
-               set_reg_field_value(
-                       value,
-                       1,
-                       DC_I2C_TRANSACTION0,
-                       DC_I2C_START0);
-
-               if ((engine->transaction_count == 3) ||
-               (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
-               (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
-
-                       set_reg_field_value(
-                               value,
-                               1,
-                               DC_I2C_TRANSACTION0,
-                               DC_I2C_STOP0);
-
-                       last_transaction = true;
-               } else
-                       set_reg_field_value(
-                               value,
-                               0,
-                               DC_I2C_TRANSACTION0,
-                               DC_I2C_STOP0);
-
-               set_reg_field_value(
-                       value,
-                       (0 != (request->action &
-                                       I2CAUX_TRANSACTION_ACTION_I2C_READ)),
-                       DC_I2C_TRANSACTION0,
-                       DC_I2C_RW0);
-
-               set_reg_field_value(
-                       value,
-                       length,
-                       DC_I2C_TRANSACTION0,
-                       DC_I2C_COUNT0);
-
-               dm_write_reg(ctx, addr, value);
-       }
-
-       /* Write the I2C address and I2C data
-        * into the hardware circular buffer, one byte per entry.
-        * As an example, the 7-bit I2C slave address for CRT monitor
-        * for reading DDC/EDID information is 0b1010001.
-        * For an I2C send operation, the LSB must be programmed to 0;
-        * for I2C receive operation, the LSB must be programmed to 1. */
-
-       {
-               value = 0;
-
-               set_reg_field_value(
-                       value,
-                       false,
-                       DC_I2C_DATA,
-                       DC_I2C_DATA_RW);
-
-               set_reg_field_value(
-                       value,
-                       request->address,
-                       DC_I2C_DATA,
-                       DC_I2C_DATA);
-
-               if (engine->transaction_count == 0) {
-                       set_reg_field_value(
-                               value,
-                               0,
-                               DC_I2C_DATA,
-                               DC_I2C_INDEX);
-
-                       /*enable index write*/
-                       set_reg_field_value(
-                               value,
-                               1,
-                               DC_I2C_DATA,
-                               DC_I2C_INDEX_WRITE);
-               }
-
-               dm_write_reg(ctx, mmDC_I2C_DATA, value);
-
-               if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
-
-                       set_reg_field_value(
-                               value,
-                               0,
-                               DC_I2C_DATA,
-                               DC_I2C_INDEX_WRITE);
-
-                       while (length) {
-
-                               set_reg_field_value(
-                                       value,
-                                       *buffer++,
-                                       DC_I2C_DATA,
-                                       DC_I2C_DATA);
-
-                               dm_write_reg(ctx, mmDC_I2C_DATA, value);
-                               --length;
-                       }
-               }
-       }
-
-       ++engine->transaction_count;
-       engine->buffer_used_bytes += length + 1;
-
-       return last_transaction;
-}
-
-static void execute_transaction(
-       struct i2c_hw_engine_dce80 *engine)
-{
-       uint32_t value = 0;
-       struct dc_context *ctx = NULL;
-
-       ctx = engine->base.base.base.ctx;
-
-       {
-               const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
-
-               value = dm_read_reg(ctx, addr);
-
-               set_reg_field_value(
-                       value,
-                       0,
-                       DC_I2C_DDC1_SETUP,
-                       DC_I2C_DDC1_DATA_DRIVE_EN);
-
-               set_reg_field_value(
-                       value,
-                       0,
-                       DC_I2C_DDC1_SETUP,
-                       DC_I2C_DDC1_CLK_DRIVE_EN);
-
-               set_reg_field_value(
-                       value,
-                       0,
-                       DC_I2C_DDC1_SETUP,
-                       DC_I2C_DDC1_DATA_DRIVE_SEL);
-
-               set_reg_field_value(
-                       value,
-                       0,
-                       DC_I2C_DDC1_SETUP,
-                       DC_I2C_DDC1_INTRA_TRANSACTION_DELAY);
-
-               set_reg_field_value(
-                       value,
-                       0,
-                       DC_I2C_DDC1_SETUP,
-                       DC_I2C_DDC1_INTRA_BYTE_DELAY);
-
-               dm_write_reg(ctx, addr, value);
-       }
-
-       {
-               const uint32_t addr = mmDC_I2C_CONTROL;
-
-               value = dm_read_reg(ctx, addr);
-
-               set_reg_field_value(
-                       value,
-                       0,
-                       DC_I2C_CONTROL,
-                       DC_I2C_SOFT_RESET);
-
-               set_reg_field_value(
-                       value,
-                       0,
-                       DC_I2C_CONTROL,
-                       DC_I2C_SW_STATUS_RESET);
-
-               set_reg_field_value(
-                       value,
-                       0,
-                       DC_I2C_CONTROL,
-                       DC_I2C_SEND_RESET);
-
-               set_reg_field_value(
-                       value,
-                       0,
-                       DC_I2C_CONTROL,
-                       DC_I2C_GO);
-
-               set_reg_field_value(
-                       value,
-                       engine->transaction_count - 1,
-                       DC_I2C_CONTROL,
-                       DC_I2C_TRANSACTION_COUNT);
-
-               dm_write_reg(ctx, addr, value);
-       }
-
-       /* start I2C transfer */
-       {
-               const uint32_t addr = mmDC_I2C_CONTROL;
-
-               value   = dm_read_reg(ctx, addr);
-
-               set_reg_field_value(
-                       value,
-                       1,
-                       DC_I2C_CONTROL,
-                       DC_I2C_GO);
-
-               dm_write_reg(ctx, addr, value);
-       }
-
-       /* all transactions were executed and HW buffer became empty
-        * (even though it actually happens when status becomes DONE) */
-       engine->transaction_count = 0;
-       engine->buffer_used_bytes = 0;
-}
-
-static void submit_channel_request(
-       struct i2c_engine *engine,
-       struct i2c_request_transaction_data *request)
-{
-       request->status = I2C_CHANNEL_OPERATION_SUCCEEDED;
-
-       if (!process_transaction(FROM_I2C_ENGINE(engine), request))
-               return;
-
-       if (is_hw_busy(&engine->base)) {
-               request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
-               return;
-       }
-
-       execute_transaction(FROM_I2C_ENGINE(engine));
-}
-
-static void process_channel_reply(
-       struct i2c_engine *engine,
-       struct i2c_reply_transaction_data *reply)
-{
-       uint32_t length = reply->length;
-       uint8_t *buffer = reply->data;
-
-       uint32_t value = 0;
-
-       /*set index*/
-       set_reg_field_value(
-               value,
-               length - 1,
-               DC_I2C_DATA,
-               DC_I2C_INDEX);
-
-       set_reg_field_value(
-               value,
-               1,
-               DC_I2C_DATA,
-               DC_I2C_DATA_RW);
-
-       set_reg_field_value(
-               value,
-               1,
-               DC_I2C_DATA,
-               DC_I2C_INDEX_WRITE);
-
-       dm_write_reg(engine->base.ctx, mmDC_I2C_DATA, value);
-
-       while (length) {
-               /* after reading the status,
-                * if the I2C operation executed successfully
-                * (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller
-                * should read data bytes from I2C circular data buffer */
-
-               value = dm_read_reg(engine->base.ctx, mmDC_I2C_DATA);
-
-               *buffer++ = get_reg_field_value(
-                               value,
-                               DC_I2C_DATA,
-                               DC_I2C_DATA);
-
-               --length;
-       }
-}
-
-static enum i2c_channel_operation_result get_channel_status(
-       struct i2c_engine *engine,
-       uint8_t *returned_bytes)
-{
-       uint32_t i2c_sw_status = 0;
-       uint32_t value = dm_read_reg(engine->base.ctx, mmDC_I2C_SW_STATUS);
-
-       i2c_sw_status = get_reg_field_value(
-                       value,
-                       DC_I2C_SW_STATUS,
-                       DC_I2C_SW_STATUS);
-
-       if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW)
-               return I2C_CHANNEL_OPERATION_ENGINE_BUSY;
-       else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_STOPPED_ON_NACK_MASK)
-               return I2C_CHANNEL_OPERATION_NO_RESPONSE;
-       else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_TIMEOUT_MASK)
-               return I2C_CHANNEL_OPERATION_TIMEOUT;
-       else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_ABORTED_MASK)
-               return I2C_CHANNEL_OPERATION_FAILED;
-       else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_DONE_MASK)
-               return I2C_CHANNEL_OPERATION_SUCCEEDED;
-
-       /*
-        * this is the case when HW used for communication, I2C_SW_STATUS
-        * could be zero
-        */
-       return I2C_CHANNEL_OPERATION_SUCCEEDED;
-}
-
-static uint32_t get_hw_buffer_available_size(
-       const struct i2c_hw_engine *engine)
-{
-       return I2C_HW_BUFFER_SIZE -
-               FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes;
-}
-
-static uint32_t get_transaction_timeout(
-       const struct i2c_hw_engine *engine,
-       uint32_t length)
-{
-       uint32_t speed = engine->base.funcs->get_speed(&engine->base);
-
-       uint32_t period_timeout;
-       uint32_t num_of_clock_stretches;
-
-       if (!speed)
-               return 0;
-
-       period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed;
-
-       num_of_clock_stretches = 1 + (length << 3) + 1;
-       num_of_clock_stretches +=
-               (FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes << 3) +
-               (FROM_I2C_HW_ENGINE(engine)->transaction_count << 1);
-
-       return period_timeout * num_of_clock_stretches;
-}
-
-/*
- * @brief
- * DC_I2C_DDC1_SETUP MM register offsets
- *
- * @note
- * The indices of this offset array are DDC engine IDs
- */
-static const int32_t ddc_setup_offset[] = {
-
-       mmDC_I2C_DDC1_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 1 */
-       mmDC_I2C_DDC2_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 2 */
-       mmDC_I2C_DDC3_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 3 */
-       mmDC_I2C_DDC4_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 4 */
-       mmDC_I2C_DDC5_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 5 */
-       mmDC_I2C_DDC6_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 6 */
-       mmDC_I2C_DDCVGA_SETUP - mmDC_I2C_DDC1_SETUP /* DDC Engine 7 */
-};
-
-/*
- * @brief
- * DC_I2C_DDC1_SPEED MM register offsets
- *
- * @note
- * The indices of this offset array are DDC engine IDs
- */
-static const int32_t ddc_speed_offset[] = {
-       mmDC_I2C_DDC1_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 1 */
-       mmDC_I2C_DDC2_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 2 */
-       mmDC_I2C_DDC3_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 3 */
-       mmDC_I2C_DDC4_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 4 */
-       mmDC_I2C_DDC5_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 5 */
-       mmDC_I2C_DDC6_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 6 */
-       mmDC_I2C_DDCVGA_SPEED - mmDC_I2C_DDC1_SPEED /* DDC Engine 7 */
-};
-
-static const struct i2c_engine_funcs i2c_engine_funcs = {
-       .destroy = destroy,
-       .get_speed = get_speed,
-       .set_speed = set_speed,
-       .setup_engine = setup_engine,
-       .submit_channel_request = submit_channel_request,
-       .process_channel_reply = process_channel_reply,
-       .get_channel_status = get_channel_status,
-       .acquire_engine = dal_i2c_hw_engine_acquire_engine,
-};
-
-static const struct engine_funcs engine_funcs = {
-       .release_engine = release_engine,
-       .get_engine_type = dal_i2c_hw_engine_get_engine_type,
-       .acquire = dal_i2c_engine_acquire,
-       .submit_request = dal_i2c_hw_engine_submit_request,
-};
-
-static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = {
-       .get_hw_buffer_available_size =
-               get_hw_buffer_available_size,
-       .get_transaction_timeout =
-               get_transaction_timeout,
-       .wait_on_operation_result =
-               dal_i2c_hw_engine_wait_on_operation_result,
-};
-
-static void construct(
-       struct i2c_hw_engine_dce80 *engine,
-       const struct i2c_hw_engine_dce80_create_arg *arg)
-{
-       dal_i2c_hw_engine_construct(&engine->base, arg->ctx);
-
-       engine->base.base.base.funcs = &engine_funcs;
-       engine->base.base.funcs = &i2c_engine_funcs;
-       engine->base.funcs = &i2c_hw_engine_funcs;
-       engine->base.default_speed = arg->default_speed;
-       engine->addr.DC_I2C_DDCX_SETUP =
-               mmDC_I2C_DDC1_SETUP + ddc_setup_offset[arg->engine_id];
-       engine->addr.DC_I2C_DDCX_SPEED =
-               mmDC_I2C_DDC1_SPEED + ddc_speed_offset[arg->engine_id];
-
-       engine->engine_id = arg->engine_id;
-       engine->reference_frequency = arg->reference_frequency;
-       engine->buffer_used_bytes = 0;
-       engine->transaction_count = 0;
-       engine->engine_keep_power_up_count = 1;
-}
-
-struct i2c_engine *dal_i2c_hw_engine_dce80_create(
-       const struct i2c_hw_engine_dce80_create_arg *arg)
-{
-       struct i2c_hw_engine_dce80 *engine;
-
-       if (!arg) {
-               BREAK_TO_DEBUGGER();
-               return NULL;
-       }
-
-       if ((arg->engine_id >= sizeof(ddc_setup_offset) / sizeof(int32_t)) ||
-           (arg->engine_id >= sizeof(ddc_speed_offset) / sizeof(int32_t)) ||
-           !arg->reference_frequency) {
-               BREAK_TO_DEBUGGER();
-               return NULL;
-       }
-
-       engine = kzalloc(sizeof(struct i2c_hw_engine_dce80), GFP_KERNEL);
-
-       if (!engine) {
-               BREAK_TO_DEBUGGER();
-               return NULL;
-       }
-
-       construct(engine, arg);
-       return &engine->base.base;
-}
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h
deleted file mode 100644 (file)
index 5c6116f..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012-15 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 __DAL_I2C_HW_ENGINE_DCE80_H__
-#define __DAL_I2C_HW_ENGINE_DCE80_H__
-
-struct i2c_hw_engine_dce80 {
-       struct i2c_hw_engine base;
-       struct {
-               uint32_t DC_I2C_DDCX_SETUP;
-               uint32_t DC_I2C_DDCX_SPEED;
-       } addr;
-       uint32_t engine_id;
-       /* expressed in kilohertz */
-       uint32_t reference_frequency;
-       /* number of bytes currently used in HW buffer */
-       uint32_t buffer_used_bytes;
-       /* number of pending transactions (before GO) */
-       uint32_t transaction_count;
-       uint32_t engine_keep_power_up_count;
-};
-
-struct i2c_hw_engine_dce80_create_arg {
-       uint32_t engine_id;
-       uint32_t reference_frequency;
-       uint32_t default_speed;
-       struct dc_context *ctx;
-};
-
-struct i2c_engine *dal_i2c_hw_engine_dce80_create(
-       const struct i2c_hw_engine_dce80_create_arg *arg);
-#endif
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c
deleted file mode 100644 (file)
index 4853ee2..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-
-/*
- * Pre-requisites: headers required by header of this unit
- */
-#include "include/i2caux_interface.h"
-#include "../engine.h"
-#include "../i2c_engine.h"
-#include "../i2c_sw_engine.h"
-
-/*
- * Header of this unit
- */
-
-#include "i2c_sw_engine_dce80.h"
-
-/*
- * Post-requisites: headers required by this unit
- */
-
-#include "dce/dce_8_0_d.h"
-#include "dce/dce_8_0_sh_mask.h"
-
-/*
- * This unit
- */
-
-static const uint32_t ddc_hw_status_addr[] = {
-       mmDC_I2C_DDC1_HW_STATUS,
-       mmDC_I2C_DDC2_HW_STATUS,
-       mmDC_I2C_DDC3_HW_STATUS,
-       mmDC_I2C_DDC4_HW_STATUS,
-       mmDC_I2C_DDC5_HW_STATUS,
-       mmDC_I2C_DDC6_HW_STATUS,
-       mmDC_I2C_DDCVGA_HW_STATUS
-};
-
-/*
- * @brief
- * Cast 'struct i2c_sw_engine *'
- * to 'struct i2c_sw_engine_dce80 *'
- */
-#define FROM_I2C_SW_ENGINE(ptr) \
-       container_of((ptr), struct i2c_sw_engine_dce80, base)
-
-/*
- * @brief
- * Cast 'struct i2c_engine *'
- * to 'struct i2c_sw_engine_dce80 *'
- */
-#define FROM_I2C_ENGINE(ptr) \
-       FROM_I2C_SW_ENGINE(container_of((ptr), struct i2c_sw_engine, base))
-
-/*
- * @brief
- * Cast 'struct engine *'
- * to 'struct i2c_sw_engine_dce80 *'
- */
-#define FROM_ENGINE(ptr) \
-       FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
-
-static void release_engine(
-       struct engine *engine)
-{
-
-}
-
-static void destruct(
-       struct i2c_sw_engine_dce80 *engine)
-{
-       dal_i2c_sw_engine_destruct(&engine->base);
-}
-
-static void destroy(
-       struct i2c_engine **engine)
-{
-       struct i2c_sw_engine_dce80 *sw_engine = FROM_I2C_ENGINE(*engine);
-
-       destruct(sw_engine);
-
-       kfree(sw_engine);
-
-       *engine = NULL;
-}
-
-static bool acquire_engine(
-       struct i2c_engine *engine,
-       struct ddc *ddc_handle)
-{
-       return dal_i2caux_i2c_sw_engine_acquire_engine(engine, ddc_handle);
-}
-
-static const struct i2c_engine_funcs i2c_engine_funcs = {
-       .acquire_engine = acquire_engine,
-       .destroy = destroy,
-       .get_speed = dal_i2c_sw_engine_get_speed,
-       .set_speed = dal_i2c_sw_engine_set_speed,
-       .setup_engine = dal_i2c_engine_setup_i2c_engine,
-       .submit_channel_request = dal_i2c_sw_engine_submit_channel_request,
-       .process_channel_reply = dal_i2c_engine_process_channel_reply,
-       .get_channel_status = dal_i2c_sw_engine_get_channel_status,
-};
-
-static const struct engine_funcs engine_funcs = {
-       .release_engine = release_engine,
-       .get_engine_type = dal_i2c_sw_engine_get_engine_type,
-       .acquire = dal_i2c_engine_acquire,
-       .submit_request = dal_i2c_sw_engine_submit_request,
-};
-
-static void construct(
-       struct i2c_sw_engine_dce80 *engine,
-       const struct i2c_sw_engine_dce80_create_arg *arg)
-{
-       struct i2c_sw_engine_create_arg arg_base;
-
-       arg_base.ctx = arg->ctx;
-       arg_base.default_speed = arg->default_speed;
-
-       dal_i2c_sw_engine_construct(&engine->base, &arg_base);
-
-       engine->base.base.base.funcs = &engine_funcs;
-       engine->base.base.funcs = &i2c_engine_funcs;
-       engine->base.default_speed = arg->default_speed;
-       engine->engine_id = arg->engine_id;
-}
-
-struct i2c_engine *dal_i2c_sw_engine_dce80_create(
-       const struct i2c_sw_engine_dce80_create_arg *arg)
-{
-       struct i2c_sw_engine_dce80 *engine;
-
-       if (!arg) {
-               BREAK_TO_DEBUGGER();
-               return NULL;
-       }
-
-       engine = kzalloc(sizeof(struct i2c_sw_engine_dce80), GFP_KERNEL);
-
-       if (!engine) {
-               BREAK_TO_DEBUGGER();
-               return NULL;
-       }
-
-       construct(engine, arg);
-       return &engine->base.base;
-}
-
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c
deleted file mode 100644 (file)
index ed48596..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-
-/*
- * Pre-requisites: headers required by header of this unit
- */
-#include "include/i2caux_interface.h"
-#include "../i2caux.h"
-
-/*
- * Header of this unit
- */
-
-#include "i2caux_dce80.h"
-
-/*
- * Post-requisites: headers required by this unit
- */
-
-#include "../engine.h"
-#include "../i2c_engine.h"
-#include "../i2c_sw_engine.h"
-#include "i2c_sw_engine_dce80.h"
-#include "../i2c_hw_engine.h"
-#include "i2c_hw_engine_dce80.h"
-#include "../i2c_generic_hw_engine.h"
-#include "../aux_engine.h"
-
-
-#include "../dce110/aux_engine_dce110.h"
-#include "../dce110/i2caux_dce110.h"
-
-#include "dce/dce_8_0_d.h"
-#include "dce/dce_8_0_sh_mask.h"
-
-
-/* set register offset */
-#define SR(reg_name)\
-       .reg_name = mm ## reg_name
-
-/* set register offset with instance */
-#define SRI(reg_name, block, id)\
-       .reg_name = mm ## block ## id ## _ ## reg_name
-
-#define aux_regs(id)\
-[id] = {\
-       AUX_COMMON_REG_LIST(id), \
-       .AUX_RESET_MASK = 0 \
-}
-
-static const struct dce110_aux_registers dce80_aux_regs[] = {
-               aux_regs(0),
-               aux_regs(1),
-               aux_regs(2),
-               aux_regs(3),
-               aux_regs(4),
-               aux_regs(5)
-};
-
-/*
- * This unit
- */
-
-#define FROM_I2C_AUX(ptr) \
-       container_of((ptr), struct i2caux_dce80, base)
-
-static void destruct(
-       struct i2caux_dce80 *i2caux_dce80)
-{
-       dal_i2caux_destruct(&i2caux_dce80->base);
-}
-
-static void destroy(
-       struct i2caux **i2c_engine)
-{
-       struct i2caux_dce80 *i2caux_dce80 = FROM_I2C_AUX(*i2c_engine);
-
-       destruct(i2caux_dce80);
-
-       kfree(i2caux_dce80);
-
-       *i2c_engine = NULL;
-}
-
-static struct i2c_engine *acquire_i2c_hw_engine(
-       struct i2caux *i2caux,
-       struct ddc *ddc)
-{
-       struct i2caux_dce80 *i2caux_dce80 = FROM_I2C_AUX(i2caux);
-
-       struct i2c_engine *engine = NULL;
-       bool non_generic;
-
-       if (!ddc)
-               return NULL;
-
-       if (ddc->hw_info.hw_supported) {
-               enum gpio_ddc_line line = dal_ddc_get_line(ddc);
-
-               if (line < GPIO_DDC_LINE_COUNT) {
-                       non_generic = true;
-                       engine = i2caux->i2c_hw_engines[line];
-               }
-       }
-
-       if (!engine) {
-               non_generic = false;
-               engine = i2caux->i2c_generic_hw_engine;
-       }
-
-       if (!engine)
-               return NULL;
-
-       if (non_generic) {
-               if (!i2caux_dce80->i2c_hw_buffer_in_use &&
-                       engine->base.funcs->acquire(&engine->base, ddc)) {
-                       i2caux_dce80->i2c_hw_buffer_in_use = true;
-                       return engine;
-               }
-       } else {
-               if (engine->base.funcs->acquire(&engine->base, ddc))
-                       return engine;
-       }
-
-       return NULL;
-}
-
-static void release_engine(
-       struct i2caux *i2caux,
-       struct engine *engine)
-{
-       if (engine->funcs->get_engine_type(engine) ==
-               I2CAUX_ENGINE_TYPE_I2C_DDC_HW)
-               FROM_I2C_AUX(i2caux)->i2c_hw_buffer_in_use = false;
-
-       dal_i2caux_release_engine(i2caux, engine);
-}
-
-static const enum gpio_ddc_line hw_ddc_lines[] = {
-       GPIO_DDC_LINE_DDC1,
-       GPIO_DDC_LINE_DDC2,
-       GPIO_DDC_LINE_DDC3,
-       GPIO_DDC_LINE_DDC4,
-       GPIO_DDC_LINE_DDC5,
-       GPIO_DDC_LINE_DDC6,
-       GPIO_DDC_LINE_DDC_VGA
-};
-
-static const enum gpio_ddc_line hw_aux_lines[] = {
-       GPIO_DDC_LINE_DDC1,
-       GPIO_DDC_LINE_DDC2,
-       GPIO_DDC_LINE_DDC3,
-       GPIO_DDC_LINE_DDC4,
-       GPIO_DDC_LINE_DDC5,
-       GPIO_DDC_LINE_DDC6
-};
-
-static const struct i2caux_funcs i2caux_funcs = {
-       .destroy = destroy,
-       .acquire_i2c_hw_engine = acquire_i2c_hw_engine,
-       .release_engine = release_engine,
-       .acquire_i2c_sw_engine = dal_i2caux_acquire_i2c_sw_engine,
-       .acquire_aux_engine = dal_i2caux_acquire_aux_engine,
-};
-
-static void construct(
-       struct i2caux_dce80 *i2caux_dce80,
-       struct dc_context *ctx)
-{
-       /* Entire family have I2C engine reference clock frequency
-        * changed from XTALIN (27) to XTALIN/2 (13.5) */
-
-       struct i2caux *base = &i2caux_dce80->base;
-
-       uint32_t reference_frequency =
-               dal_i2caux_get_reference_clock(ctx->dc_bios) >> 1;
-
-       /*bool use_i2c_sw_engine = dal_adapter_service_is_feature_supported(as,
-               FEATURE_RESTORE_USAGE_I2C_SW_ENGINE);*/
-
-       /* Use SWI2C for dce8 currently, sicne we have bug with hwi2c */
-       bool use_i2c_sw_engine = true;
-
-       uint32_t i;
-
-       dal_i2caux_construct(base, ctx);
-
-       i2caux_dce80->base.funcs = &i2caux_funcs;
-       i2caux_dce80->i2c_hw_buffer_in_use = false;
-
-       /* Create I2C HW engines (HW + SW pairs)
-        * for all lines which has assisted HW DDC
-        * 'i' (loop counter) used as DDC/AUX engine_id */
-
-       i = 0;
-
-       do {
-               enum gpio_ddc_line line_id = hw_ddc_lines[i];
-
-               struct i2c_hw_engine_dce80_create_arg hw_arg;
-
-               if (use_i2c_sw_engine) {
-                       struct i2c_sw_engine_dce80_create_arg sw_arg;
-
-                       sw_arg.engine_id = i;
-                       sw_arg.default_speed = base->default_i2c_sw_speed;
-                       sw_arg.ctx = ctx;
-                       base->i2c_sw_engines[line_id] =
-                               dal_i2c_sw_engine_dce80_create(&sw_arg);
-               }
-
-               hw_arg.engine_id = i;
-               hw_arg.reference_frequency = reference_frequency;
-               hw_arg.default_speed = base->default_i2c_hw_speed;
-               hw_arg.ctx = ctx;
-
-               base->i2c_hw_engines[line_id] =
-                       dal_i2c_hw_engine_dce80_create(&hw_arg);
-
-               ++i;
-       } while (i < ARRAY_SIZE(hw_ddc_lines));
-
-       /* Create AUX engines for all lines which has assisted HW AUX
-        * 'i' (loop counter) used as DDC/AUX engine_id */
-
-       i = 0;
-
-       do {
-               enum gpio_ddc_line line_id = hw_aux_lines[i];
-
-               struct aux_engine_dce110_init_data arg;
-
-               arg.engine_id = i;
-               arg.timeout_period = base->aux_timeout_period;
-               arg.ctx = ctx;
-               arg.regs = &dce80_aux_regs[i];
-
-               base->aux_engines[line_id] =
-                       dal_aux_engine_dce110_create(&arg);
-
-               ++i;
-       } while (i < ARRAY_SIZE(hw_aux_lines));
-
-       /* TODO Generic I2C SW and HW */
-}
-
-struct i2caux *dal_i2caux_dce80_create(
-       struct dc_context *ctx)
-{
-       struct i2caux_dce80 *i2caux_dce80 =
-               kzalloc(sizeof(struct i2caux_dce80), GFP_KERNEL);
-
-       if (!i2caux_dce80) {
-               BREAK_TO_DEBUGGER();
-               return NULL;
-       }
-
-       construct(i2caux_dce80, ctx);
-       return &i2caux_dce80->base;
-}
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c
deleted file mode 100644 (file)
index a59c1f5..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-
-#include "include/i2caux_interface.h"
-#include "../i2caux.h"
-#include "../engine.h"
-#include "../i2c_engine.h"
-#include "../i2c_sw_engine.h"
-#include "../i2c_hw_engine.h"
-
-#include "../dce110/aux_engine_dce110.h"
-#include "../dce110/i2c_hw_engine_dce110.h"
-#include "../dce110/i2caux_dce110.h"
-
-#include "dcn/dcn_1_0_offset.h"
-#include "dcn/dcn_1_0_sh_mask.h"
-#include "soc15_hw_ip.h"
-#include "vega10_ip_offset.h"
-
-/* begin *********************
- * macros to expend register list macro defined in HW object header file */
-
-#define BASE_INNER(seg) \
-       DCE_BASE__INST0_SEG ## seg
-
-/* compile time expand base address. */
-#define BASE(seg) \
-       BASE_INNER(seg)
-
-#define SR(reg_name)\
-               .reg_name = BASE(mm ## reg_name ## _BASE_IDX) +  \
-                                       mm ## reg_name
-
-#define SRI(reg_name, block, id)\
-       .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
-                                       mm ## block ## id ## _ ## reg_name
-/* macros to expend register list macro defined in HW object header file
- * end *********************/
-
-#define aux_regs(id)\
-[id] = {\
-       AUX_COMMON_REG_LIST(id), \
-       .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK \
-}
-
-#define hw_engine_regs(id)\
-{\
-               I2C_HW_ENGINE_COMMON_REG_LIST(id) \
-}
-
-static const struct dce110_aux_registers dcn10_aux_regs[] = {
-               aux_regs(0),
-               aux_regs(1),
-               aux_regs(2),
-               aux_regs(3),
-               aux_regs(4),
-               aux_regs(5),
-};
-
-static const struct dce110_i2c_hw_engine_registers dcn10_hw_engine_regs[] = {
-               hw_engine_regs(1),
-               hw_engine_regs(2),
-               hw_engine_regs(3),
-               hw_engine_regs(4),
-               hw_engine_regs(5),
-               hw_engine_regs(6)
-};
-
-static const struct dce110_i2c_hw_engine_shift i2c_shift = {
-               I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT)
-};
-
-static const struct dce110_i2c_hw_engine_mask i2c_mask = {
-               I2C_COMMON_MASK_SH_LIST_DCE110(_MASK)
-};
-
-struct i2caux *dal_i2caux_dcn10_create(
-       struct dc_context *ctx)
-{
-       struct i2caux_dce110 *i2caux_dce110 =
-               kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL);
-
-       if (!i2caux_dce110) {
-               ASSERT_CRITICAL(false);
-               return NULL;
-       }
-
-       dal_i2caux_dce110_construct(i2caux_dce110,
-                                   ctx,
-                                   ARRAY_SIZE(dcn10_aux_regs),
-                                   dcn10_aux_regs,
-                                   dcn10_hw_engine_regs,
-                                   &i2c_shift,
-                                   &i2c_mask);
-       return &i2caux_dce110->base;
-}
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.h b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.h
deleted file mode 100644 (file)
index aeb4a86..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2012-15 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 __DAL_I2C_AUX_DCN10_H__
-#define __DAL_I2C_AUX_DCN10_H__
-
-struct i2caux *dal_i2caux_dcn10_create(
-       struct dc_context *ctx);
-
-#endif /* __DAL_I2C_AUX_DCN10_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c
deleted file mode 100644 (file)
index e6408f6..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2012-16 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-
-/*
- * Pre-requisites: headers required by header of this unit
- */
-#include "include/i2caux_interface.h"
-#include "../i2caux.h"
-#include "../engine.h"
-#include "../i2c_engine.h"
-#include "../i2c_sw_engine.h"
-#include "../i2c_hw_engine.h"
-
-/*
- * Header of this unit
- */
-#include "i2caux_diag.h"
-
-/*
- * Post-requisites: headers required by this unit
- */
-
-/*
- * This unit
- */
-
-static void destruct(
-       struct i2caux *i2caux)
-{
-       dal_i2caux_destruct(i2caux);
-}
-
-static void destroy(
-       struct i2caux **i2c_engine)
-{
-       destruct(*i2c_engine);
-
-       kfree(*i2c_engine);
-
-       *i2c_engine = NULL;
-}
-
-/* function table */
-static const struct i2caux_funcs i2caux_funcs = {
-       .destroy = destroy,
-       .acquire_i2c_hw_engine = NULL,
-       .release_engine = NULL,
-       .acquire_i2c_sw_engine = NULL,
-       .acquire_aux_engine = NULL,
-};
-
-static void construct(
-       struct i2caux *i2caux,
-       struct dc_context *ctx)
-{
-       dal_i2caux_construct(i2caux, ctx);
-       i2caux->funcs = &i2caux_funcs;
-}
-
-struct i2caux *dal_i2caux_diag_fpga_create(
-       struct dc_context *ctx)
-{
-       struct i2caux *i2caux = kzalloc(sizeof(struct i2caux),
-                                              GFP_KERNEL);
-
-       if (!i2caux) {
-               ASSERT_CRITICAL(false);
-               return NULL;
-       }
-
-       construct(i2caux, ctx);
-       return i2caux;
-}
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h
deleted file mode 100644 (file)
index a83eeb7..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2012-16 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 __DAL_I2C_AUX_DIAG_FPGA_H__
-#define __DAL_I2C_AUX_DIAG_FPGA_H__
-
-struct i2caux *dal_i2caux_diag_fpga_create(
-       struct dc_context *ctx);
-
-#endif /* __DAL_I2C_AUX_DIAG_FPGA_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/engine.h
deleted file mode 100644 (file)
index b16fb1f..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2012-15 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 __DAL_ENGINE_H__
-#define __DAL_ENGINE_H__
-
-#include "dc_ddc_types.h"
-
-enum i2caux_transaction_operation {
-       I2CAUX_TRANSACTION_READ,
-       I2CAUX_TRANSACTION_WRITE
-};
-
-enum i2caux_transaction_address_space {
-       I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C = 1,
-       I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD
-};
-
-struct i2caux_transaction_payload {
-       enum i2caux_transaction_address_space address_space;
-       uint32_t address;
-       uint32_t length;
-       uint8_t *data;
-};
-
-enum i2caux_transaction_status {
-       I2CAUX_TRANSACTION_STATUS_UNKNOWN = (-1L),
-       I2CAUX_TRANSACTION_STATUS_SUCCEEDED,
-       I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY,
-       I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT,
-       I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR,
-       I2CAUX_TRANSACTION_STATUS_FAILED_NACK,
-       I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE,
-       I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION,
-       I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION,
-       I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW,
-       I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON
-};
-
-struct i2caux_transaction_request {
-       enum i2caux_transaction_operation operation;
-       struct i2caux_transaction_payload payload;
-       enum i2caux_transaction_status status;
-};
-
-enum i2caux_engine_type {
-       I2CAUX_ENGINE_TYPE_UNKNOWN = (-1L),
-       I2CAUX_ENGINE_TYPE_AUX,
-       I2CAUX_ENGINE_TYPE_I2C_DDC_HW,
-       I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW,
-       I2CAUX_ENGINE_TYPE_I2C_SW
-};
-
-enum i2c_default_speed {
-       I2CAUX_DEFAULT_I2C_HW_SPEED = 50,
-       I2CAUX_DEFAULT_I2C_SW_SPEED = 50
-};
-
-struct engine;
-
-struct engine_funcs {
-       enum i2caux_engine_type (*get_engine_type)(
-               const struct engine *engine);
-       bool (*acquire)(
-               struct engine *engine,
-               struct ddc *ddc);
-       bool (*submit_request)(
-               struct engine *engine,
-               struct i2caux_transaction_request *request,
-               bool middle_of_transaction);
-       void (*release_engine)(
-               struct engine *engine);
-};
-
-struct engine {
-       const struct engine_funcs *funcs;
-       uint32_t inst;
-       struct ddc *ddc;
-       struct dc_context *ctx;
-};
-
-void dal_i2caux_construct_engine(
-       struct engine *engine,
-       struct dc_context *ctx);
-
-void dal_i2caux_destruct_engine(
-       struct engine *engine);
-
-#endif
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c
deleted file mode 100644 (file)
index 70e20bd..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-
-/*
- * Pre-requisites: headers required by header of this unit
- */
-#include "include/i2caux_interface.h"
-#include "engine.h"
-
-/*
- * Header of this unit
- */
-
-#include "i2c_engine.h"
-
-/*
- * Post-requisites: headers required by this unit
- */
-
-/*
- * This unit
- */
-
-#define FROM_ENGINE(ptr) \
-       container_of((ptr), struct i2c_engine, base)
-
-bool dal_i2c_engine_acquire(
-       struct engine *engine,
-       struct ddc *ddc_handle)
-{
-       struct i2c_engine *i2c_engine = FROM_ENGINE(engine);
-
-       uint32_t counter = 0;
-       bool result;
-
-       do {
-               result = i2c_engine->funcs->acquire_engine(
-                       i2c_engine, ddc_handle);
-
-               if (result)
-                       break;
-
-               /* i2c_engine is busy by VBios, lets wait and retry */
-
-               udelay(10);
-
-               ++counter;
-       } while (counter < 2);
-
-       if (result) {
-               if (!i2c_engine->funcs->setup_engine(i2c_engine)) {
-                       engine->funcs->release_engine(engine);
-                       result = false;
-               }
-       }
-
-       return result;
-}
-
-bool dal_i2c_engine_setup_i2c_engine(
-       struct i2c_engine *engine)
-{
-       /* Derivative classes do not have to override this */
-
-       return true;
-}
-
-void dal_i2c_engine_submit_channel_request(
-       struct i2c_engine *engine,
-       struct i2c_request_transaction_data *request)
-{
-
-}
-
-void dal_i2c_engine_process_channel_reply(
-       struct i2c_engine *engine,
-       struct i2c_reply_transaction_data *reply)
-{
-
-}
-
-void dal_i2c_engine_construct(
-       struct i2c_engine *engine,
-       struct dc_context *ctx)
-{
-       dal_i2caux_construct_engine(&engine->base, ctx);
-       engine->timeout_delay = 0;
-}
-
-void dal_i2c_engine_destruct(
-       struct i2c_engine *engine)
-{
-       dal_i2caux_destruct_engine(&engine->base);
-}
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h
deleted file mode 100644 (file)
index ded6ea3..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2012-15 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 __DAL_I2C_ENGINE_H__
-#define __DAL_I2C_ENGINE_H__
-
-enum i2c_channel_operation_result {
-       I2C_CHANNEL_OPERATION_SUCCEEDED,
-       I2C_CHANNEL_OPERATION_FAILED,
-       I2C_CHANNEL_OPERATION_NOT_GRANTED,
-       I2C_CHANNEL_OPERATION_IS_BUSY,
-       I2C_CHANNEL_OPERATION_NO_HANDLE_PROVIDED,
-       I2C_CHANNEL_OPERATION_CHANNEL_IN_USE,
-       I2C_CHANNEL_OPERATION_CHANNEL_CLIENT_MAX_ALLOWED,
-       I2C_CHANNEL_OPERATION_ENGINE_BUSY,
-       I2C_CHANNEL_OPERATION_TIMEOUT,
-       I2C_CHANNEL_OPERATION_NO_RESPONSE,
-       I2C_CHANNEL_OPERATION_HW_REQUEST_I2C_BUS,
-       I2C_CHANNEL_OPERATION_WRONG_PARAMETER,
-       I2C_CHANNEL_OPERATION_OUT_NB_OF_RETRIES,
-       I2C_CHANNEL_OPERATION_NOT_STARTED
-};
-
-struct i2c_request_transaction_data {
-       enum i2caux_transaction_action action;
-       enum i2c_channel_operation_result status;
-       uint8_t address;
-       uint32_t length;
-       uint8_t *data;
-};
-
-struct i2c_reply_transaction_data {
-       uint32_t length;
-       uint8_t *data;
-};
-
-struct i2c_engine;
-
-struct i2c_engine_funcs {
-       void (*destroy)(
-               struct i2c_engine **ptr);
-       uint32_t (*get_speed)(
-               const struct i2c_engine *engine);
-       void (*set_speed)(
-               struct i2c_engine *engine,
-               uint32_t speed);
-       bool (*acquire_engine)(
-               struct i2c_engine *engine,
-               struct ddc *ddc);
-       bool (*setup_engine)(
-               struct i2c_engine *engine);
-       void (*submit_channel_request)(
-               struct i2c_engine *engine,
-               struct i2c_request_transaction_data *request);
-       void (*process_channel_reply)(
-               struct i2c_engine *engine,
-               struct i2c_reply_transaction_data *reply);
-       enum i2c_channel_operation_result (*get_channel_status)(
-               struct i2c_engine *engine,
-               uint8_t *returned_bytes);
-};
-
-struct i2c_engine {
-       struct engine base;
-       const struct i2c_engine_funcs *funcs;
-       uint32_t timeout_delay;
-       uint32_t setup_limit;
-       uint32_t send_reset_length;
-};
-
-void dal_i2c_engine_construct(
-       struct i2c_engine *engine,
-       struct dc_context *ctx);
-
-void dal_i2c_engine_destruct(
-       struct i2c_engine *engine);
-
-bool dal_i2c_engine_setup_i2c_engine(
-       struct i2c_engine *engine);
-
-void dal_i2c_engine_submit_channel_request(
-       struct i2c_engine *engine,
-       struct i2c_request_transaction_data *request);
-
-void dal_i2c_engine_process_channel_reply(
-       struct i2c_engine *engine,
-       struct i2c_reply_transaction_data *reply);
-
-bool dal_i2c_engine_acquire(
-       struct engine *ptr,
-       struct ddc *ddc_handle);
-
-#endif
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c
deleted file mode 100644 (file)
index 5a4295e..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-
-/*
- * Pre-requisites: headers required by header of this unit
- */
-#include "include/i2caux_interface.h"
-#include "engine.h"
-#include "i2c_engine.h"
-#include "i2c_hw_engine.h"
-
-/*
- * Header of this unit
- */
-
-#include "i2c_generic_hw_engine.h"
-
-/*
- * Post-requisites: headers required by this unit
- */
-
-/*
- * This unit
- */
-
-/*
- * @brief
- * Cast 'struct i2c_hw_engine *'
- * to 'struct i2c_generic_hw_engine *'
- */
-#define FROM_I2C_HW_ENGINE(ptr) \
-       container_of((ptr), struct i2c_generic_hw_engine, base)
-
-/*
- * @brief
- * Cast 'struct i2c_engine *'
- * to 'struct i2c_generic_hw_engine *'
- */
-#define FROM_I2C_ENGINE(ptr) \
-       FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base))
-
-/*
- * @brief
- * Cast 'struct engine *'
- * to 'struct i2c_generic_hw_engine *'
- */
-#define FROM_ENGINE(ptr) \
-       FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
-
-enum i2caux_engine_type dal_i2c_generic_hw_engine_get_engine_type(
-       const struct engine *engine)
-{
-       return I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW;
-}
-
-/*
- * @brief
- * Single transaction handling.
- * Since transaction may be bigger than HW buffer size,
- * it divides transaction to sub-transactions
- * and uses batch transaction feature of the engine.
- */
-bool dal_i2c_generic_hw_engine_submit_request(
-       struct engine *engine,
-       struct i2caux_transaction_request *i2caux_request,
-       bool middle_of_transaction)
-{
-       struct i2c_generic_hw_engine *hw_engine = FROM_ENGINE(engine);
-
-       struct i2c_hw_engine *base = &hw_engine->base;
-
-       uint32_t max_payload_size =
-               base->funcs->get_hw_buffer_available_size(base);
-
-       bool initial_stop_bit = !middle_of_transaction;
-
-       struct i2c_generic_transaction_attributes attributes;
-
-       enum i2c_channel_operation_result operation_result =
-               I2C_CHANNEL_OPERATION_FAILED;
-
-       bool result = false;
-
-       /* setup transaction initial properties */
-
-       uint8_t address = i2caux_request->payload.address;
-       uint8_t *current_payload = i2caux_request->payload.data;
-       uint32_t remaining_payload_size = i2caux_request->payload.length;
-
-       bool first_iteration = true;
-
-       if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
-               attributes.action = I2CAUX_TRANSACTION_ACTION_I2C_READ;
-       else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
-               attributes.action = I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
-       else {
-               i2caux_request->status =
-                       I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION;
-               return false;
-       }
-
-       /* Do batch transaction.
-        * Divide read/write data into payloads which fit HW buffer size.
-        * 1. Single transaction:
-        *    start_bit = 1, stop_bit depends on session state, ack_on_read = 0;
-        * 2. Start of batch transaction:
-        *    start_bit = 1, stop_bit = 0, ack_on_read = 1;
-        * 3. Middle of batch transaction:
-        *    start_bit = 0, stop_bit = 0, ack_on_read = 1;
-        * 4. End of batch transaction:
-        *    start_bit = 0, stop_bit depends on session state, ack_on_read = 0.
-        * Session stop bit is set if 'middle_of_transaction' = 0. */
-
-       while (remaining_payload_size) {
-               uint32_t current_transaction_size;
-               uint32_t current_payload_size;
-
-               bool last_iteration;
-               bool stop_bit;
-
-               /* Calculate current transaction size and payload size.
-                * Transaction size = total number of bytes in transaction,
-                * including slave's address;
-                * Payload size = number of data bytes in transaction. */
-
-               if (first_iteration) {
-                       /* In the first sub-transaction we send slave's address
-                        * thus we need to reserve one byte for it */
-                       current_transaction_size =
-                       (remaining_payload_size > max_payload_size - 1) ?
-                               max_payload_size :
-                               remaining_payload_size + 1;
-
-                       current_payload_size = current_transaction_size - 1;
-               } else {
-                       /* Second and further sub-transactions will have
-                        * entire buffer reserved for data */
-                       current_transaction_size =
-                               (remaining_payload_size > max_payload_size) ?
-                               max_payload_size :
-                               remaining_payload_size;
-
-                       current_payload_size = current_transaction_size;
-               }
-
-               last_iteration =
-                       (remaining_payload_size == current_payload_size);
-
-               stop_bit = last_iteration ? initial_stop_bit : false;
-
-               /* write slave device address */
-
-               if (first_iteration)
-                       hw_engine->funcs->write_address(hw_engine, address);
-
-               /* write current portion of data, if requested */
-
-               if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
-                       hw_engine->funcs->write_data(
-                               hw_engine,
-                               current_payload,
-                               current_payload_size);
-
-               /* execute transaction */
-
-               attributes.start_bit = first_iteration;
-               attributes.stop_bit = stop_bit;
-               attributes.last_read = last_iteration;
-               attributes.transaction_size = current_transaction_size;
-
-               hw_engine->funcs->execute_transaction(hw_engine, &attributes);
-
-               /* wait until transaction is processed; if it fails - quit */
-
-               operation_result = base->funcs->wait_on_operation_result(
-                       base,
-                       base->funcs->get_transaction_timeout(
-                               base, current_transaction_size),
-                       I2C_CHANNEL_OPERATION_ENGINE_BUSY);
-
-               if (operation_result != I2C_CHANNEL_OPERATION_SUCCEEDED)
-                       break;
-
-               /* read current portion of data, if requested */
-
-               /* the read offset should be 1 for first sub-transaction,
-                * and 0 for any next one */
-
-               if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
-                       hw_engine->funcs->read_data(hw_engine, current_payload,
-                               current_payload_size, first_iteration ? 1 : 0);
-
-               /* update loop variables */
-
-               first_iteration = false;
-               current_payload += current_payload_size;
-               remaining_payload_size -= current_payload_size;
-       }
-
-       /* update transaction status */
-
-       switch (operation_result) {
-       case I2C_CHANNEL_OPERATION_SUCCEEDED:
-               i2caux_request->status =
-                       I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
-               result = true;
-       break;
-       case I2C_CHANNEL_OPERATION_NO_RESPONSE:
-               i2caux_request->status =
-                       I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
-       break;
-       case I2C_CHANNEL_OPERATION_TIMEOUT:
-               i2caux_request->status =
-                       I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
-       break;
-       case I2C_CHANNEL_OPERATION_FAILED:
-               i2caux_request->status =
-                       I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE;
-       break;
-       default:
-               i2caux_request->status =
-                       I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION;
-       }
-
-       return result;
-}
-
-/*
- * @brief
- * Returns number of microseconds to wait until timeout to be considered
- */
-uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout(
-       const struct i2c_hw_engine *engine,
-       uint32_t length)
-{
-       const struct i2c_engine *base = &engine->base;
-
-       uint32_t speed = base->funcs->get_speed(base);
-
-       if (!speed)
-               return 0;
-
-       /* total timeout = period_timeout * (start + data bits count + stop) */
-
-       return ((1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed) *
-               (1 + (length << 3) + 1);
-}
-
-void dal_i2c_generic_hw_engine_construct(
-       struct i2c_generic_hw_engine *engine,
-       struct dc_context *ctx)
-{
-       dal_i2c_hw_engine_construct(&engine->base, ctx);
-}
-
-void dal_i2c_generic_hw_engine_destruct(
-       struct i2c_generic_hw_engine *engine)
-{
-       dal_i2c_hw_engine_destruct(&engine->base);
-}
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h
deleted file mode 100644 (file)
index 1da0397..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2012-15 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 __DAL_I2C_GENERIC_HW_ENGINE_H__
-#define __DAL_I2C_GENERIC_HW_ENGINE_H__
-
-struct i2c_generic_transaction_attributes {
-       enum i2caux_transaction_action action;
-       uint32_t transaction_size;
-       bool start_bit;
-       bool stop_bit;
-       bool last_read;
-};
-
-struct i2c_generic_hw_engine;
-
-struct i2c_generic_hw_engine_funcs {
-       void (*write_address)(
-               struct i2c_generic_hw_engine *engine,
-               uint8_t address);
-       void (*write_data)(
-               struct i2c_generic_hw_engine *engine,
-               const uint8_t *buffer,
-               uint32_t length);
-       void (*read_data)(
-               struct i2c_generic_hw_engine *engine,
-               uint8_t *buffer,
-               uint32_t length,
-               uint32_t offset);
-       void (*execute_transaction)(
-               struct i2c_generic_hw_engine *engine,
-               struct i2c_generic_transaction_attributes *attributes);
-};
-
-struct i2c_generic_hw_engine {
-       struct i2c_hw_engine base;
-       const struct i2c_generic_hw_engine_funcs *funcs;
-};
-
-void dal_i2c_generic_hw_engine_construct(
-       struct i2c_generic_hw_engine *engine,
-       struct dc_context *ctx);
-
-void dal_i2c_generic_hw_engine_destruct(
-       struct i2c_generic_hw_engine *engine);
-enum i2caux_engine_type dal_i2c_generic_hw_engine_get_engine_type(
-       const struct engine *engine);
-bool dal_i2c_generic_hw_engine_submit_request(
-       struct engine *ptr,
-       struct i2caux_transaction_request *i2caux_request,
-       bool middle_of_transaction);
-uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout(
-       const struct i2c_hw_engine *engine,
-       uint32_t length);
-#endif
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c
deleted file mode 100644 (file)
index 1418985..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-#include "dm_event_log.h"
-
-/*
- * Pre-requisites: headers required by header of this unit
- */
-#include "include/i2caux_interface.h"
-#include "engine.h"
-#include "i2c_engine.h"
-
-/*
- * Header of this unit
- */
-
-#include "i2c_hw_engine.h"
-
-/*
- * Post-requisites: headers required by this unit
- */
-
-/*
- * This unit
- */
-
-/*
- * @brief
- * Cast 'struct i2c_engine *'
- * to 'struct i2c_hw_engine *'
- */
-#define FROM_I2C_ENGINE(ptr) \
-       container_of((ptr), struct i2c_hw_engine, base)
-
-/*
- * @brief
- * Cast 'struct engine *'
- * to 'struct i2c_hw_engine *'
- */
-#define FROM_ENGINE(ptr) \
-       FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
-
-enum i2caux_engine_type dal_i2c_hw_engine_get_engine_type(
-       const struct engine *engine)
-{
-       return I2CAUX_ENGINE_TYPE_I2C_DDC_HW;
-}
-
-bool dal_i2c_hw_engine_submit_request(
-       struct engine *engine,
-       struct i2caux_transaction_request *i2caux_request,
-       bool middle_of_transaction)
-{
-       struct i2c_hw_engine *hw_engine = FROM_ENGINE(engine);
-
-       struct i2c_request_transaction_data request;
-
-       uint32_t transaction_timeout;
-
-       enum i2c_channel_operation_result operation_result;
-
-       bool result = false;
-
-       /* We need following:
-        * transaction length will not exceed
-        * the number of free bytes in HW buffer (minus one for address)*/
-
-       if (i2caux_request->payload.length >=
-               hw_engine->funcs->get_hw_buffer_available_size(hw_engine)) {
-               i2caux_request->status =
-                       I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW;
-               return false;
-       }
-
-       if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
-               request.action = middle_of_transaction ?
-                       I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
-                       I2CAUX_TRANSACTION_ACTION_I2C_READ;
-       else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
-               request.action = middle_of_transaction ?
-                       I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
-                       I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
-       else {
-               i2caux_request->status =
-                       I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION;
-               /* [anaumov] in DAL2, there was no "return false" */
-               return false;
-       }
-
-       request.address = (uint8_t)i2caux_request->payload.address;
-       request.length = i2caux_request->payload.length;
-       request.data = i2caux_request->payload.data;
-
-       /* obtain timeout value before submitting request */
-
-       transaction_timeout = hw_engine->funcs->get_transaction_timeout(
-               hw_engine, i2caux_request->payload.length + 1);
-
-       hw_engine->base.funcs->submit_channel_request(
-               &hw_engine->base, &request);
-       /* EVENT_LOG_AUX_REQ(engine->ddc->pin_data->en, EVENT_LOG_AUX_ORIGIN_I2C, */
-       /* request.action, request.address, request.length, request.data); */
-
-       if ((request.status == I2C_CHANNEL_OPERATION_FAILED) ||
-               (request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY)) {
-               i2caux_request->status =
-                       I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY;
-               return false;
-       }
-
-       /* wait until transaction proceed */
-
-       operation_result = hw_engine->funcs->wait_on_operation_result(
-               hw_engine,
-               transaction_timeout,
-               I2C_CHANNEL_OPERATION_ENGINE_BUSY);
-
-       /* update transaction status */
-
-       switch (operation_result) {
-       case I2C_CHANNEL_OPERATION_SUCCEEDED:
-               i2caux_request->status =
-                       I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
-               result = true;
-       break;
-       case I2C_CHANNEL_OPERATION_NO_RESPONSE:
-               i2caux_request->status =
-                       I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
-       break;
-       case I2C_CHANNEL_OPERATION_TIMEOUT:
-               i2caux_request->status =
-                       I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
-       break;
-       case I2C_CHANNEL_OPERATION_FAILED:
-               i2caux_request->status =
-                       I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE;
-       break;
-       default:
-               i2caux_request->status =
-                       I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION;
-       }
-
-       if (result && (i2caux_request->operation == I2CAUX_TRANSACTION_READ)) {
-               struct i2c_reply_transaction_data reply;
-
-               reply.data = i2caux_request->payload.data;
-               reply.length = i2caux_request->payload.length;
-
-               hw_engine->base.funcs->
-                       process_channel_reply(&hw_engine->base, &reply);
-               /* EVENT_LOG_AUX_REP(engine->ddc->pin_data->en, EVENT_LOG_AUX_ORIGIN_I2C, */
-               /* AUX_TRANSACTION_REPLY_I2C_ACK, reply.length, reply.data); */
-       }
-
-
-
-       return result;
-}
-
-bool dal_i2c_hw_engine_acquire_engine(
-       struct i2c_engine *engine,
-       struct ddc *ddc)
-{
-       enum gpio_result result;
-       uint32_t current_speed;
-
-       result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
-               GPIO_DDC_CONFIG_TYPE_MODE_I2C);
-
-       if (result != GPIO_RESULT_OK)
-               return false;
-
-       engine->base.ddc = ddc;
-
-       current_speed = engine->funcs->get_speed(engine);
-
-       if (current_speed)
-               FROM_I2C_ENGINE(engine)->original_speed = current_speed;
-
-       return true;
-}
-/*
- * @brief
- * Queries in a loop for current engine status
- * until retrieved status matches 'expected_result', or timeout occurs.
- * Timeout given in microseconds
- * and the status query frequency is also one per microsecond.
- */
-enum i2c_channel_operation_result dal_i2c_hw_engine_wait_on_operation_result(
-       struct i2c_hw_engine *engine,
-       uint32_t timeout,
-       enum i2c_channel_operation_result expected_result)
-{
-       enum i2c_channel_operation_result result;
-       uint32_t i = 0;
-
-       if (!timeout)
-               return I2C_CHANNEL_OPERATION_SUCCEEDED;
-
-       do {
-               result = engine->base.funcs->get_channel_status(
-                       &engine->base, NULL);
-
-               if (result != expected_result)
-                       break;
-
-               udelay(1);
-
-               ++i;
-       } while (i < timeout);
-
-       return result;
-}
-
-void dal_i2c_hw_engine_construct(
-       struct i2c_hw_engine *engine,
-       struct dc_context *ctx)
-{
-       dal_i2c_engine_construct(&engine->base, ctx);
-       engine->original_speed = I2CAUX_DEFAULT_I2C_HW_SPEED;
-       engine->default_speed = I2CAUX_DEFAULT_I2C_HW_SPEED;
-}
-
-void dal_i2c_hw_engine_destruct(
-       struct i2c_hw_engine *engine)
-{
-       dal_i2c_engine_destruct(&engine->base);
-}
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h
deleted file mode 100644 (file)
index 8936a99..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2012-15 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 __DAL_I2C_HW_ENGINE_H__
-#define __DAL_I2C_HW_ENGINE_H__
-
-enum {
-       TRANSACTION_TIMEOUT_IN_I2C_CLOCKS = 32
-};
-
-struct i2c_hw_engine;
-
-struct i2c_hw_engine_funcs {
-       uint32_t (*get_hw_buffer_available_size)(
-               const struct i2c_hw_engine *engine);
-       enum i2c_channel_operation_result (*wait_on_operation_result)(
-               struct i2c_hw_engine *engine,
-               uint32_t timeout,
-               enum i2c_channel_operation_result expected_result);
-       uint32_t (*get_transaction_timeout)(
-               const struct i2c_hw_engine *engine,
-               uint32_t length);
-};
-
-struct i2c_hw_engine {
-       struct i2c_engine base;
-       const struct i2c_hw_engine_funcs *funcs;
-
-       /* Values below are in kilohertz */
-       uint32_t original_speed;
-       uint32_t default_speed;
-};
-
-void dal_i2c_hw_engine_construct(
-       struct i2c_hw_engine *engine,
-       struct dc_context *ctx);
-
-void dal_i2c_hw_engine_destruct(
-       struct i2c_hw_engine *engine);
-
-enum i2c_channel_operation_result dal_i2c_hw_engine_wait_on_operation_result(
-       struct i2c_hw_engine *engine,
-       uint32_t timeout,
-       enum i2c_channel_operation_result expected_result);
-
-bool dal_i2c_hw_engine_acquire_engine(
-       struct i2c_engine *engine,
-       struct ddc *ddc);
-
-bool dal_i2c_hw_engine_submit_request(
-       struct engine *ptr,
-       struct i2caux_transaction_request *i2caux_request,
-       bool middle_of_transaction);
-
-enum i2caux_engine_type dal_i2c_hw_engine_get_engine_type(
-       const struct engine *engine);
-
-#endif
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c
deleted file mode 100644 (file)
index 8e19bb6..0000000
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-
-/*
- * Pre-requisites: headers required by header of this unit
- */
-#include "include/i2caux_interface.h"
-#include "engine.h"
-#include "i2c_engine.h"
-
-/*
- * Header of this unit
- */
-
-#include "i2c_sw_engine.h"
-
-/*
- * Post-requisites: headers required by this unit
- */
-
-/*
- * This unit
- */
-
-#define SCL false
-#define SDA true
-
-static inline bool read_bit_from_ddc(
-       struct ddc *ddc,
-       bool data_nor_clock)
-{
-       uint32_t value = 0;
-
-       if (data_nor_clock)
-               dal_gpio_get_value(ddc->pin_data, &value);
-       else
-               dal_gpio_get_value(ddc->pin_clock, &value);
-
-       return (value != 0);
-}
-
-static inline void write_bit_to_ddc(
-       struct ddc *ddc,
-       bool data_nor_clock,
-       bool bit)
-{
-       uint32_t value = bit ? 1 : 0;
-
-       if (data_nor_clock)
-               dal_gpio_set_value(ddc->pin_data, value);
-       else
-               dal_gpio_set_value(ddc->pin_clock, value);
-}
-
-static bool wait_for_scl_high(
-       struct dc_context *ctx,
-       struct ddc *ddc,
-       uint16_t clock_delay_div_4)
-{
-       uint32_t scl_retry = 0;
-       uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4;
-
-       udelay(clock_delay_div_4);
-
-       /* 3 milliseconds delay
-        * to wake up some displays from "low power" state.
-        */
-
-       do {
-               if (read_bit_from_ddc(ddc, SCL))
-                       return true;
-
-               udelay(clock_delay_div_4);
-
-               ++scl_retry;
-       } while (scl_retry <= scl_retry_max);
-
-       return false;
-}
-
-static bool start_sync(
-       struct dc_context *ctx,
-       struct ddc *ddc_handle,
-       uint16_t clock_delay_div_4)
-{
-       uint32_t retry = 0;
-
-       /* The I2C communications start signal is:
-        * the SDA going low from high, while the SCL is high. */
-
-       write_bit_to_ddc(ddc_handle, SCL, true);
-
-       udelay(clock_delay_div_4);
-
-       do {
-               write_bit_to_ddc(ddc_handle, SDA, true);
-
-               if (!read_bit_from_ddc(ddc_handle, SDA)) {
-                       ++retry;
-                       continue;
-               }
-
-               udelay(clock_delay_div_4);
-
-               write_bit_to_ddc(ddc_handle, SCL, true);
-
-               if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
-                       break;
-
-               write_bit_to_ddc(ddc_handle, SDA, false);
-
-               udelay(clock_delay_div_4);
-
-               write_bit_to_ddc(ddc_handle, SCL, false);
-
-               udelay(clock_delay_div_4);
-
-               return true;
-       } while (retry <= I2C_SW_RETRIES);
-
-       return false;
-}
-
-static bool stop_sync(
-       struct dc_context *ctx,
-       struct ddc *ddc_handle,
-       uint16_t clock_delay_div_4)
-{
-       uint32_t retry = 0;
-
-       /* The I2C communications stop signal is:
-        * the SDA going high from low, while the SCL is high. */
-
-       write_bit_to_ddc(ddc_handle, SCL, false);
-
-       udelay(clock_delay_div_4);
-
-       write_bit_to_ddc(ddc_handle, SDA, false);
-
-       udelay(clock_delay_div_4);
-
-       write_bit_to_ddc(ddc_handle, SCL, true);
-
-       if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
-               return false;
-
-       write_bit_to_ddc(ddc_handle, SDA, true);
-
-       do {
-               udelay(clock_delay_div_4);
-
-               if (read_bit_from_ddc(ddc_handle, SDA))
-                       return true;
-
-               ++retry;
-       } while (retry <= 2);
-
-       return false;
-}
-
-static bool write_byte(
-       struct dc_context *ctx,
-       struct ddc *ddc_handle,
-       uint16_t clock_delay_div_4,
-       uint8_t byte)
-{
-       int32_t shift = 7;
-       bool ack;
-
-       /* bits are transmitted serially, starting from MSB */
-
-       do {
-               udelay(clock_delay_div_4);
-
-               write_bit_to_ddc(ddc_handle, SDA, (byte >> shift) & 1);
-
-               udelay(clock_delay_div_4);
-
-               write_bit_to_ddc(ddc_handle, SCL, true);
-
-               if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
-                       return false;
-
-               write_bit_to_ddc(ddc_handle, SCL, false);
-
-               --shift;
-       } while (shift >= 0);
-
-       /* The display sends ACK by preventing the SDA from going high
-        * after the SCL pulse we use to send our last data bit.
-        * If the SDA goes high after that bit, it's a NACK */
-
-       udelay(clock_delay_div_4);
-
-       write_bit_to_ddc(ddc_handle, SDA, true);
-
-       udelay(clock_delay_div_4);
-
-       write_bit_to_ddc(ddc_handle, SCL, true);
-
-       if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
-               return false;
-
-       /* read ACK bit */
-
-       ack = !read_bit_from_ddc(ddc_handle, SDA);
-
-       udelay(clock_delay_div_4 << 1);
-
-       write_bit_to_ddc(ddc_handle, SCL, false);
-
-       udelay(clock_delay_div_4 << 1);
-
-       return ack;
-}
-
-static bool read_byte(
-       struct dc_context *ctx,
-       struct ddc *ddc_handle,
-       uint16_t clock_delay_div_4,
-       uint8_t *byte,
-       bool more)
-{
-       int32_t shift = 7;
-
-       uint8_t data = 0;
-
-       /* The data bits are read from MSB to LSB;
-        * bit is read while SCL is high */
-
-       do {
-               write_bit_to_ddc(ddc_handle, SCL, true);
-
-               if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
-                       return false;
-
-               if (read_bit_from_ddc(ddc_handle, SDA))
-                       data |= (1 << shift);
-
-               write_bit_to_ddc(ddc_handle, SCL, false);
-
-               udelay(clock_delay_div_4 << 1);
-
-               --shift;
-       } while (shift >= 0);
-
-       /* read only whole byte */
-
-       *byte = data;
-
-       udelay(clock_delay_div_4);
-
-       /* send the acknowledge bit:
-        * SDA low means ACK, SDA high means NACK */
-
-       write_bit_to_ddc(ddc_handle, SDA, !more);
-
-       udelay(clock_delay_div_4);
-
-       write_bit_to_ddc(ddc_handle, SCL, true);
-
-       if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
-               return false;
-
-       write_bit_to_ddc(ddc_handle, SCL, false);
-
-       udelay(clock_delay_div_4);
-
-       write_bit_to_ddc(ddc_handle, SDA, true);
-
-       udelay(clock_delay_div_4);
-
-       return true;
-}
-
-static bool i2c_write(
-       struct dc_context *ctx,
-       struct ddc *ddc_handle,
-       uint16_t clock_delay_div_4,
-       uint8_t address,
-       uint32_t length,
-       const uint8_t *data)
-{
-       uint32_t i = 0;
-
-       if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address))
-               return false;
-
-       while (i < length) {
-               if (!write_byte(ctx, ddc_handle, clock_delay_div_4, data[i]))
-                       return false;
-               ++i;
-       }
-
-       return true;
-}
-
-static bool i2c_read(
-       struct dc_context *ctx,
-       struct ddc *ddc_handle,
-       uint16_t clock_delay_div_4,
-       uint8_t address,
-       uint32_t length,
-       uint8_t *data)
-{
-       uint32_t i = 0;
-
-       if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address))
-               return false;
-
-       while (i < length) {
-               if (!read_byte(ctx, ddc_handle, clock_delay_div_4, data + i,
-                       i < length - 1))
-                       return false;
-               ++i;
-       }
-
-       return true;
-}
-
-/*
- * @brief
- * Cast 'struct i2c_engine *'
- * to 'struct i2c_sw_engine *'
- */
-#define FROM_I2C_ENGINE(ptr) \
-       container_of((ptr), struct i2c_sw_engine, base)
-
-/*
- * @brief
- * Cast 'struct engine *'
- * to 'struct i2c_sw_engine *'
- */
-#define FROM_ENGINE(ptr) \
-       FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
-
-enum i2caux_engine_type dal_i2c_sw_engine_get_engine_type(
-       const struct engine *engine)
-{
-       return I2CAUX_ENGINE_TYPE_I2C_SW;
-}
-
-bool dal_i2c_sw_engine_submit_request(
-       struct engine *engine,
-       struct i2caux_transaction_request *i2caux_request,
-       bool middle_of_transaction)
-{
-       struct i2c_sw_engine *sw_engine = FROM_ENGINE(engine);
-
-       struct i2c_engine *base = &sw_engine->base;
-
-       struct i2c_request_transaction_data request;
-       bool operation_succeeded = false;
-
-       if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
-               request.action = middle_of_transaction ?
-                       I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
-                       I2CAUX_TRANSACTION_ACTION_I2C_READ;
-       else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
-               request.action = middle_of_transaction ?
-                       I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
-                       I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
-       else {
-               i2caux_request->status =
-                       I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION;
-               /* in DAL2, there was no "return false" */
-               return false;
-       }
-
-       request.address = (uint8_t)i2caux_request->payload.address;
-       request.length = i2caux_request->payload.length;
-       request.data = i2caux_request->payload.data;
-
-       base->funcs->submit_channel_request(base, &request);
-
-       if ((request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY) ||
-               (request.status == I2C_CHANNEL_OPERATION_FAILED))
-               i2caux_request->status =
-                       I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY;
-       else {
-               enum i2c_channel_operation_result operation_result;
-
-               do {
-                       operation_result =
-                               base->funcs->get_channel_status(base, NULL);
-
-                       switch (operation_result) {
-                       case I2C_CHANNEL_OPERATION_SUCCEEDED:
-                               i2caux_request->status =
-                                       I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
-                               operation_succeeded = true;
-                       break;
-                       case I2C_CHANNEL_OPERATION_NO_RESPONSE:
-                               i2caux_request->status =
-                                       I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
-                       break;
-                       case I2C_CHANNEL_OPERATION_TIMEOUT:
-                               i2caux_request->status =
-                               I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
-                       break;
-                       case I2C_CHANNEL_OPERATION_FAILED:
-                               i2caux_request->status =
-                               I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE;
-                       break;
-                       default:
-                               i2caux_request->status =
-                               I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION;
-                       break;
-                       }
-               } while (operation_result == I2C_CHANNEL_OPERATION_ENGINE_BUSY);
-       }
-
-       return operation_succeeded;
-}
-
-uint32_t dal_i2c_sw_engine_get_speed(
-       const struct i2c_engine *engine)
-{
-       return FROM_I2C_ENGINE(engine)->speed;
-}
-
-void dal_i2c_sw_engine_set_speed(
-       struct i2c_engine *engine,
-       uint32_t speed)
-{
-       struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine);
-
-       ASSERT(speed);
-
-       sw_engine->speed = speed ? speed : I2CAUX_DEFAULT_I2C_SW_SPEED;
-
-       sw_engine->clock_delay = 1000 / sw_engine->speed;
-
-       if (sw_engine->clock_delay < 12)
-               sw_engine->clock_delay = 12;
-}
-
-bool dal_i2caux_i2c_sw_engine_acquire_engine(
-       struct i2c_engine *engine,
-       struct ddc *ddc)
-{
-       enum gpio_result result;
-
-       result = dal_ddc_open(ddc, GPIO_MODE_FAST_OUTPUT,
-               GPIO_DDC_CONFIG_TYPE_MODE_I2C);
-
-       if (result != GPIO_RESULT_OK)
-               return false;
-
-       engine->base.ddc = ddc;
-
-       return true;
-}
-
-void dal_i2c_sw_engine_submit_channel_request(
-       struct i2c_engine *engine,
-       struct i2c_request_transaction_data *req)
-{
-       struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine);
-
-       struct ddc *ddc = engine->base.ddc;
-       uint16_t clock_delay_div_4 = sw_engine->clock_delay >> 2;
-
-       /* send sync (start / repeated start) */
-
-       bool result = start_sync(engine->base.ctx, ddc, clock_delay_div_4);
-
-       /* process payload */
-
-       if (result) {
-               switch (req->action) {
-               case I2CAUX_TRANSACTION_ACTION_I2C_WRITE:
-               case I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT:
-                       result = i2c_write(engine->base.ctx, ddc, clock_delay_div_4,
-                               req->address, req->length, req->data);
-               break;
-               case I2CAUX_TRANSACTION_ACTION_I2C_READ:
-               case I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT:
-                       result = i2c_read(engine->base.ctx, ddc, clock_delay_div_4,
-                               req->address, req->length, req->data);
-               break;
-               default:
-                       result = false;
-               break;
-               }
-       }
-
-       /* send stop if not 'mot' or operation failed */
-
-       if (!result ||
-               (req->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
-               (req->action == I2CAUX_TRANSACTION_ACTION_I2C_READ))
-               if (!stop_sync(engine->base.ctx, ddc, clock_delay_div_4))
-                       result = false;
-
-       req->status = result ?
-               I2C_CHANNEL_OPERATION_SUCCEEDED :
-               I2C_CHANNEL_OPERATION_FAILED;
-}
-
-enum i2c_channel_operation_result dal_i2c_sw_engine_get_channel_status(
-       struct i2c_engine *engine,
-       uint8_t *returned_bytes)
-{
-       /* No arbitration with VBIOS is performed since DCE 6.0 */
-       return I2C_CHANNEL_OPERATION_SUCCEEDED;
-}
-
-void dal_i2c_sw_engine_destruct(
-       struct i2c_sw_engine *engine)
-{
-       dal_i2c_engine_destruct(&engine->base);
-}
-
-static void destroy(
-       struct i2c_engine **ptr)
-{
-       dal_i2c_sw_engine_destruct(FROM_I2C_ENGINE(*ptr));
-
-       kfree(*ptr);
-       *ptr = NULL;
-}
-
-static const struct i2c_engine_funcs i2c_engine_funcs = {
-       .acquire_engine = dal_i2caux_i2c_sw_engine_acquire_engine,
-       .destroy = destroy,
-       .get_speed = dal_i2c_sw_engine_get_speed,
-       .set_speed = dal_i2c_sw_engine_set_speed,
-       .setup_engine = dal_i2c_engine_setup_i2c_engine,
-       .submit_channel_request = dal_i2c_sw_engine_submit_channel_request,
-       .process_channel_reply = dal_i2c_engine_process_channel_reply,
-       .get_channel_status = dal_i2c_sw_engine_get_channel_status,
-};
-
-static void release_engine(
-       struct engine *engine)
-{
-
-}
-
-static const struct engine_funcs engine_funcs = {
-       .release_engine = release_engine,
-       .get_engine_type = dal_i2c_sw_engine_get_engine_type,
-       .acquire = dal_i2c_engine_acquire,
-       .submit_request = dal_i2c_sw_engine_submit_request,
-};
-
-void dal_i2c_sw_engine_construct(
-       struct i2c_sw_engine *engine,
-       const struct i2c_sw_engine_create_arg *arg)
-{
-       dal_i2c_engine_construct(&engine->base, arg->ctx);
-       dal_i2c_sw_engine_set_speed(&engine->base, arg->default_speed);
-       engine->base.funcs = &i2c_engine_funcs;
-       engine->base.base.funcs = &engine_funcs;
-}
-
-struct i2c_engine *dal_i2c_sw_engine_create(
-       const struct i2c_sw_engine_create_arg *arg)
-{
-       struct i2c_sw_engine *engine;
-
-       if (!arg) {
-               BREAK_TO_DEBUGGER();
-               return NULL;
-       }
-
-       engine = kzalloc(sizeof(struct i2c_sw_engine), GFP_KERNEL);
-
-       if (!engine) {
-               BREAK_TO_DEBUGGER();
-               return NULL;
-       }
-
-       dal_i2c_sw_engine_construct(engine, arg);
-       return &engine->base;
-}
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h
deleted file mode 100644 (file)
index 546f15b..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2012-15 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 __DAL_I2C_SW_ENGINE_H__
-#define __DAL_I2C_SW_ENGINE_H__
-
-enum {
-       I2C_SW_RETRIES = 10,
-       I2C_SW_SCL_READ_RETRIES = 128,
-       /* following value is in microseconds */
-       I2C_SW_TIMEOUT_DELAY = 3000
-};
-
-struct i2c_sw_engine;
-
-struct i2c_sw_engine {
-       struct i2c_engine base;
-       uint32_t clock_delay;
-       /* Values below are in KHz */
-       uint32_t speed;
-       uint32_t default_speed;
-};
-
-struct i2c_sw_engine_create_arg {
-       uint32_t default_speed;
-       struct dc_context *ctx;
-};
-
-void dal_i2c_sw_engine_construct(
-       struct i2c_sw_engine *engine,
-       const struct i2c_sw_engine_create_arg *arg);
-
-bool dal_i2caux_i2c_sw_engine_acquire_engine(
-       struct i2c_engine *engine,
-       struct ddc *ddc_handle);
-
-void dal_i2c_sw_engine_destruct(
-       struct i2c_sw_engine *engine);
-
-struct i2c_engine *dal_i2c_sw_engine_create(
-       const struct i2c_sw_engine_create_arg *arg);
-enum i2caux_engine_type dal_i2c_sw_engine_get_engine_type(
-       const struct engine *engine);
-bool dal_i2c_sw_engine_submit_request(
-       struct engine *ptr,
-       struct i2caux_transaction_request *i2caux_request,
-       bool middle_of_transaction);
-uint32_t dal_i2c_sw_engine_get_speed(
-       const struct i2c_engine *engine);
-void dal_i2c_sw_engine_set_speed(
-       struct i2c_engine *ptr,
-       uint32_t speed);
-void dal_i2c_sw_engine_submit_channel_request(
-       struct i2c_engine *ptr,
-       struct i2c_request_transaction_data *req);
-enum i2c_channel_operation_result dal_i2c_sw_engine_get_channel_status(
-       struct i2c_engine *engine,
-       uint8_t *returned_bytes);
-#endif
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c
deleted file mode 100644 (file)
index 1ad6e49..0000000
+++ /dev/null
@@ -1,491 +0,0 @@
-/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include "dm_services.h"
-
-/*
- * Pre-requisites: headers required by header of this unit
- */
-#include "include/i2caux_interface.h"
-#include "dc_bios_types.h"
-
-/*
- * Header of this unit
- */
-
-#include "i2caux.h"
-
-/*
- * Post-requisites: headers required by this unit
- */
-
-#include "engine.h"
-#include "i2c_engine.h"
-#include "aux_engine.h"
-
-/*
- * This unit
- */
-
-#include "dce80/i2caux_dce80.h"
-
-#include "dce100/i2caux_dce100.h"
-
-#include "dce110/i2caux_dce110.h"
-
-#include "dce112/i2caux_dce112.h"
-
-#include "dce120/i2caux_dce120.h"
-
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
-#include "dcn10/i2caux_dcn10.h"
-#endif
-
-#include "diagnostics/i2caux_diag.h"
-
-/*
- * @brief
- * Plain API, available publicly
- */
-
-struct i2caux *dal_i2caux_create(
-       struct dc_context *ctx)
-{
-       if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) {
-               return dal_i2caux_diag_fpga_create(ctx);
-       }
-
-       switch (ctx->dce_version) {
-       case DCE_VERSION_8_0:
-       case DCE_VERSION_8_1:
-       case DCE_VERSION_8_3:
-               return dal_i2caux_dce80_create(ctx);
-       case DCE_VERSION_11_2:
-       case DCE_VERSION_11_22:
-               return dal_i2caux_dce112_create(ctx);
-       case DCE_VERSION_11_0:
-               return dal_i2caux_dce110_create(ctx);
-       case DCE_VERSION_10_0:
-               return dal_i2caux_dce100_create(ctx);
-       case DCE_VERSION_12_0:
-       case DCE_VERSION_12_1:
-               return dal_i2caux_dce120_create(ctx);
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
-       case DCN_VERSION_1_0:
-               return dal_i2caux_dcn10_create(ctx);
-#endif
-
-#if defined(CONFIG_DRM_AMD_DC_DCN1_01)
-       case DCN_VERSION_1_01:
-               return dal_i2caux_dcn10_create(ctx);
-#endif
-       default:
-               BREAK_TO_DEBUGGER();
-               return NULL;
-       }
-}
-
-bool dal_i2caux_submit_i2c_command(
-       struct i2caux *i2caux,
-       struct ddc *ddc,
-       struct i2c_command *cmd)
-{
-       struct i2c_engine *engine;
-       uint8_t index_of_payload = 0;
-       bool result;
-
-       if (!ddc) {
-               BREAK_TO_DEBUGGER();
-               return false;
-       }
-
-       if (!cmd) {
-               BREAK_TO_DEBUGGER();
-               return false;
-       }
-
-       /*
-        * default will be SW, however there is a feature flag in adapter
-        * service that determines whether SW i2c_engine will be available or
-        * not, if sw i2c is not available we will fallback to hw. This feature
-        * flag is set to not creating sw i2c engine for every dce except dce80
-        * currently
-        */
-       switch (cmd->engine) {
-       case I2C_COMMAND_ENGINE_DEFAULT:
-       case I2C_COMMAND_ENGINE_SW:
-               /* try to acquire SW engine first,
-                * acquire HW engine if SW engine not available */
-               engine = i2caux->funcs->acquire_i2c_sw_engine(i2caux, ddc);
-
-               if (!engine)
-                       engine = i2caux->funcs->acquire_i2c_hw_engine(
-                               i2caux, ddc);
-       break;
-       case I2C_COMMAND_ENGINE_HW:
-       default:
-               /* try to acquire HW engine first,
-                * acquire SW engine if HW engine not available */
-               engine = i2caux->funcs->acquire_i2c_hw_engine(i2caux, ddc);
-
-               if (!engine)
-                       engine = i2caux->funcs->acquire_i2c_sw_engine(
-                               i2caux, ddc);
-       }
-
-       if (!engine)
-               return false;
-
-       engine->funcs->set_speed(engine, cmd->speed);
-
-       result = true;
-
-       while (index_of_payload < cmd->number_of_payloads) {
-               bool mot = (index_of_payload != cmd->number_of_payloads - 1);
-
-               struct i2c_payload *payload = cmd->payloads + index_of_payload;
-
-               struct i2caux_transaction_request request = { 0 };
-
-               request.operation = payload->write ?
-                       I2CAUX_TRANSACTION_WRITE :
-                       I2CAUX_TRANSACTION_READ;
-
-               request.payload.address_space =
-                       I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C;
-               request.payload.address = (payload->address << 1) |
-                       !payload->write;
-               request.payload.length = payload->length;
-               request.payload.data = payload->data;
-
-               if (!engine->base.funcs->submit_request(
-                       &engine->base, &request, mot)) {
-                       result = false;
-                       break;
-               }
-
-               ++index_of_payload;
-       }
-
-       i2caux->funcs->release_engine(i2caux, &engine->base);
-
-       return result;
-}
-
-bool dal_i2caux_submit_aux_command(
-       struct i2caux *i2caux,
-       struct ddc *ddc,
-       struct aux_command *cmd)
-{
-       struct aux_engine *engine;
-       uint8_t index_of_payload = 0;
-       bool result;
-       bool mot;
-
-       if (!ddc) {
-               BREAK_TO_DEBUGGER();
-               return false;
-       }
-
-       if (!cmd) {
-               BREAK_TO_DEBUGGER();
-               return false;
-       }
-
-       engine = i2caux->funcs->acquire_aux_engine(i2caux, ddc);
-
-       if (!engine)
-               return false;
-
-       engine->delay = cmd->defer_delay;
-       engine->max_defer_write_retry = cmd->max_defer_write_retry;
-
-       result = true;
-
-       while (index_of_payload < cmd->number_of_payloads) {
-               struct aux_payload *payload = cmd->payloads + index_of_payload;
-               struct i2caux_transaction_request request = { 0 };
-
-               if (cmd->mot == I2C_MOT_UNDEF)
-                       mot = (index_of_payload != cmd->number_of_payloads - 1);
-               else
-                       mot = (cmd->mot == I2C_MOT_TRUE);
-
-               request.operation = payload->write ?
-                       I2CAUX_TRANSACTION_WRITE :
-                       I2CAUX_TRANSACTION_READ;
-
-               if (payload->i2c_over_aux) {
-                       request.payload.address_space =
-                               I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C;
-
-                       request.payload.address = (payload->address << 1) |
-                               !payload->write;
-               } else {
-                       request.payload.address_space =
-                               I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD;
-
-                       request.payload.address = payload->address;
-               }
-
-               request.payload.length = payload->length;
-               request.payload.data = payload->data;
-
-               if (!engine->base.funcs->submit_request(
-                       &engine->base, &request, mot)) {
-                       result = false;
-                       break;
-               }
-
-               ++index_of_payload;
-       }
-
-       i2caux->funcs->release_engine(i2caux, &engine->base);
-
-       return result;
-}
-
-static bool get_hw_supported_ddc_line(
-       struct ddc *ddc,
-       enum gpio_ddc_line *line)
-{
-       enum gpio_ddc_line line_found;
-
-       *line = GPIO_DDC_LINE_UNKNOWN;
-
-       if (!ddc) {
-               BREAK_TO_DEBUGGER();
-               return false;
-       }
-
-       if (!ddc->hw_info.hw_supported)
-               return false;
-
-       line_found = dal_ddc_get_line(ddc);
-
-       if (line_found >= GPIO_DDC_LINE_COUNT)
-               return false;
-
-       *line = line_found;
-
-       return true;
-}
-
-void dal_i2caux_configure_aux(
-       struct i2caux *i2caux,
-       struct ddc *ddc,
-       union aux_config cfg)
-{
-       struct aux_engine *engine =
-               i2caux->funcs->acquire_aux_engine(i2caux, ddc);
-
-       if (!engine)
-               return;
-
-       engine->funcs->configure(engine, cfg);
-
-       i2caux->funcs->release_engine(i2caux, &engine->base);
-}
-
-void dal_i2caux_destroy(
-       struct i2caux **i2caux)
-{
-       if (!i2caux || !*i2caux) {
-               BREAK_TO_DEBUGGER();
-               return;
-       }
-
-       (*i2caux)->funcs->destroy(i2caux);
-
-       *i2caux = NULL;
-}
-
-/*
- * @brief
- * An utility function used by 'struct i2caux' and its descendants
- */
-
-uint32_t dal_i2caux_get_reference_clock(
-               struct dc_bios *bios)
-{
-       struct dc_firmware_info info = { { 0 } };
-
-       if (bios->funcs->get_firmware_info(bios, &info) != BP_RESULT_OK)
-               return 0;
-
-       return info.pll_info.crystal_frequency;
-}
-
-/*
- * @brief
- * i2caux
- */
-
-enum {
-       /* following are expressed in KHz */
-       DEFAULT_I2C_SW_SPEED = 50,
-       DEFAULT_I2C_HW_SPEED = 50,
-
-       DEFAULT_I2C_SW_SPEED_100KHZ = 100,
-       DEFAULT_I2C_HW_SPEED_100KHZ = 100,
-
-       /* This is the timeout as defined in DP 1.2a,
-        * 2.3.4 "Detailed uPacket TX AUX CH State Description". */
-       AUX_TIMEOUT_PERIOD = 400,
-
-       /* Ideally, the SW timeout should be just above 550usec
-        * which is programmed in HW.
-        * But the SW timeout of 600usec is not reliable,
-        * because on some systems, delay_in_microseconds()
-        * returns faster than it should.
-        * EPR #379763: by trial-and-error on different systems,
-        * 700usec is the minimum reliable SW timeout for polling
-        * the AUX_SW_STATUS.AUX_SW_DONE bit.
-        * This timeout expires *only* when there is
-        * AUX Error or AUX Timeout conditions - not during normal operation.
-        * During normal operation, AUX_SW_STATUS.AUX_SW_DONE bit is set
-        * at most within ~240usec. That means,
-        * increasing this timeout will not affect normal operation,
-        * and we'll timeout after
-        * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD = 1600usec.
-        * This timeout is especially important for
-        * resume from S3 and CTS. */
-       SW_AUX_TIMEOUT_PERIOD_MULTIPLIER = 4
-};
-
-struct i2c_engine *dal_i2caux_acquire_i2c_sw_engine(
-       struct i2caux *i2caux,
-       struct ddc *ddc)
-{
-       enum gpio_ddc_line line;
-       struct i2c_engine *engine = NULL;
-
-       if (get_hw_supported_ddc_line(ddc, &line))
-               engine = i2caux->i2c_sw_engines[line];
-
-       if (!engine)
-               engine = i2caux->i2c_generic_sw_engine;
-
-       if (!engine)
-               return NULL;
-
-       if (!engine->base.funcs->acquire(&engine->base, ddc))
-               return NULL;
-
-       return engine;
-}
-
-struct aux_engine *dal_i2caux_acquire_aux_engine(
-       struct i2caux *i2caux,
-       struct ddc *ddc)
-{
-       enum gpio_ddc_line line;
-       struct aux_engine *engine;
-
-       if (!get_hw_supported_ddc_line(ddc, &line))
-               return NULL;
-
-       engine = i2caux->aux_engines[line];
-
-       if (!engine)
-               return NULL;
-
-       if (!engine->base.funcs->acquire(&engine->base, ddc))
-               return NULL;
-
-       return engine;
-}
-
-void dal_i2caux_release_engine(
-       struct i2caux *i2caux,
-       struct engine *engine)
-{
-       engine->funcs->release_engine(engine);
-
-       dal_ddc_close(engine->ddc);
-
-       engine->ddc = NULL;
-}
-
-void dal_i2caux_construct(
-       struct i2caux *i2caux,
-       struct dc_context *ctx)
-{
-       uint32_t i = 0;
-
-       i2caux->ctx = ctx;
-       do {
-               i2caux->i2c_sw_engines[i] = NULL;
-               i2caux->i2c_hw_engines[i] = NULL;
-               i2caux->aux_engines[i] = NULL;
-
-               ++i;
-       } while (i < GPIO_DDC_LINE_COUNT);
-
-       i2caux->i2c_generic_sw_engine = NULL;
-       i2caux->i2c_generic_hw_engine = NULL;
-
-       i2caux->aux_timeout_period =
-               SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD;
-
-       if (ctx->dce_version >= DCE_VERSION_11_2) {
-               i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED_100KHZ;
-               i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED_100KHZ;
-       } else {
-               i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED;
-               i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED;
-       }
-}
-
-void dal_i2caux_destruct(
-       struct i2caux *i2caux)
-{
-       uint32_t i = 0;
-
-       if (i2caux->i2c_generic_hw_engine)
-               i2caux->i2c_generic_hw_engine->funcs->destroy(
-                       &i2caux->i2c_generic_hw_engine);
-
-       if (i2caux->i2c_generic_sw_engine)
-               i2caux->i2c_generic_sw_engine->funcs->destroy(
-                       &i2caux->i2c_generic_sw_engine);
-
-       do {
-               if (i2caux->aux_engines[i])
-                       i2caux->aux_engines[i]->funcs->destroy(
-                               &i2caux->aux_engines[i]);
-
-               if (i2caux->i2c_hw_engines[i])
-                       i2caux->i2c_hw_engines[i]->funcs->destroy(
-                               &i2caux->i2c_hw_engines[i]);
-
-               if (i2caux->i2c_sw_engines[i])
-                       i2caux->i2c_sw_engines[i]->funcs->destroy(
-                               &i2caux->i2c_sw_engines[i]);
-
-               ++i;
-       } while (i < GPIO_DDC_LINE_COUNT);
-}
-
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h
deleted file mode 100644 (file)
index 64f51bb..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2012-15 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 __DAL_I2C_AUX_H__
-#define __DAL_I2C_AUX_H__
-
-uint32_t dal_i2caux_get_reference_clock(
-       struct dc_bios *bios);
-
-struct i2caux;
-
-struct engine;
-
-struct i2caux_funcs {
-       void (*destroy)(struct i2caux **ptr);
-       struct i2c_engine * (*acquire_i2c_sw_engine)(
-               struct i2caux *i2caux,
-               struct ddc *ddc);
-       struct i2c_engine * (*acquire_i2c_hw_engine)(
-               struct i2caux *i2caux,
-               struct ddc *ddc);
-       struct aux_engine * (*acquire_aux_engine)(
-               struct i2caux *i2caux,
-               struct ddc *ddc);
-       void (*release_engine)(
-               struct i2caux *i2caux,
-               struct engine *engine);
-};
-
-struct i2c_engine;
-struct aux_engine;
-
-struct i2caux {
-       struct dc_context *ctx;
-       const struct i2caux_funcs *funcs;
-       /* On ASIC we have certain amount of lines with HW DDC engine
-        * (4, 6, or maybe more in the future).
-        * For every such line, we create separate HW DDC engine
-        * (since we have these engines in HW) and separate SW DDC engine
-        * (to allow concurrent use of few lines).
-        * In similar way we have AUX engines. */
-
-       /* I2C SW engines, per DDC line.
-        * Only lines with HW DDC support will be initialized */
-       struct i2c_engine *i2c_sw_engines[GPIO_DDC_LINE_COUNT];
-
-       /* I2C HW engines, per DDC line.
-        * Only lines with HW DDC support will be initialized */
-       struct i2c_engine *i2c_hw_engines[GPIO_DDC_LINE_COUNT];
-
-       /* AUX engines, per DDC line.
-        * Only lines with HW AUX support will be initialized */
-       struct aux_engine *aux_engines[GPIO_DDC_LINE_COUNT];
-
-       /* For all other lines, we can use
-        * single instance of generic I2C HW engine
-        * (since in HW, there is single instance of it)
-        * or single instance of generic I2C SW engine.
-        * AUX is not supported for other lines. */
-
-       /* General-purpose I2C SW engine.
-        * Can be assigned dynamically to any line per transaction */
-       struct i2c_engine *i2c_generic_sw_engine;
-
-       /* General-purpose I2C generic HW engine.
-        * Can be assigned dynamically to almost any line per transaction */
-       struct i2c_engine *i2c_generic_hw_engine;
-
-       /* [anaumov] in DAL2, there is a Mutex */
-
-       uint32_t aux_timeout_period;
-
-       /* expressed in KHz */
-       uint32_t default_i2c_sw_speed;
-       uint32_t default_i2c_hw_speed;
-};
-
-void dal_i2caux_construct(
-       struct i2caux *i2caux,
-       struct dc_context *ctx);
-
-void dal_i2caux_release_engine(
-       struct i2caux *i2caux,
-       struct engine *engine);
-
-void dal_i2caux_destruct(
-       struct i2caux *i2caux);
-
-void dal_i2caux_destroy(
-       struct i2caux **ptr);
-
-struct i2c_engine *dal_i2caux_acquire_i2c_sw_engine(
-       struct i2caux *i2caux,
-       struct ddc *ddc);
-
-struct aux_engine *dal_i2caux_acquire_aux_engine(
-       struct i2caux *i2caux,
-       struct ddc *ddc);
-
-#endif
index 47ef90495376a44dd9736444372f1aea4e380b21..43d1fbd8ace57e01108eb339979f2d8eb222f7df 100644 (file)
@@ -78,7 +78,7 @@ struct csdp_ref_clk_ds_params {
 };
 
 struct pixel_clk_params {
-       uint32_t requested_pix_clk; /* in KHz */
+       uint32_t requested_pix_clk_100hz;
 /*> Requested Pixel Clock
  * (based on Video Timing standard used for requested mode)*/
        uint32_t requested_sym_clk; /* in KHz */
@@ -104,9 +104,9 @@ struct pixel_clk_params {
  *  with actually calculated Clock and reference Crystal frequency
  */
 struct pll_settings {
-       uint32_t actual_pix_clk;
-       uint32_t adjusted_pix_clk;
-       uint32_t calculated_pix_clk;
+       uint32_t actual_pix_clk_100hz;
+       uint32_t adjusted_pix_clk_100hz;
+       uint32_t calculated_pix_clk_100hz;
        uint32_t vco_freq;
        uint32_t reference_freq;
        uint32_t reference_divider;
index 94fc31080fdad1faa14fd4de8c13db8e6ccc2bcc..2e61a22ef4b258dd50c9832f43058bf3bab9b290 100644 (file)
@@ -30,7 +30,7 @@ enum dc_status {
        DC_OK = 1,
 
        DC_NO_CONTROLLER_RESOURCE = 2,
-       DC_NO_STREAM_ENG_RESOURCE = 3,
+       DC_NO_STREAM_ENC_RESOURCE = 3,
        DC_NO_CLOCK_SOURCE_RESOURCE = 4,
        DC_FAIL_CONTROLLER_VALIDATE = 5,
        DC_FAIL_ENC_VALIDATE = 6,
index b168a5e9dd9dcef7fa9c0ae2e95b05505300e938..986ed172864421f2d368b517380b3d75036de050 100644 (file)
@@ -146,7 +146,7 @@ struct resource_pool {
        struct mpc *mpc;
        struct pp_smu_funcs_rv *pp_smu;
        struct pp_smu_display_requirement_rv pp_smu_req;
-       struct aux_engine *engines[MAX_PIPES];
+       struct dce_aux *engines[MAX_PIPES];
        struct dce_i2c_hw *hw_i2cs[MAX_PIPES];
        struct dce_i2c_sw *sw_i2cs[MAX_PIPES];
        bool i2c_hw_buffer_in_use;
@@ -180,13 +180,8 @@ struct resource_pool {
        const struct resource_caps *res_cap;
 };
 
-struct dcn_fe_clocks {
-       int dppclk_khz;
-};
-
 struct dcn_fe_bandwidth {
-       struct dcn_fe_clocks calc;
-       struct dcn_fe_clocks cur;
+       int dppclk_khz;
 };
 
 struct stream_resource {
index 538b83303b866e8f5a58b9b47751a3b6ace2578d..16fd4dc6c4dd73377fbe0c239be135475919f726 100644 (file)
@@ -64,13 +64,6 @@ void dal_ddc_i2c_payloads_add(
                uint8_t *data,
                bool write);
 
-void dal_ddc_aux_payloads_add(
-               struct aux_payloads *payloads,
-               uint32_t address,
-               uint32_t len,
-               uint8_t *data,
-               bool write);
-
 struct ddc_service_init_data {
        struct graphics_object_id id;
        struct dc_context *ctx;
@@ -103,12 +96,10 @@ bool dal_ddc_service_query_ddc_data(
                uint32_t read_size);
 
 int dc_link_aux_transfer(struct ddc_service *ddc,
-                            unsigned int address,
-                            uint8_t *reply,
-                            void *buffer,
-                            unsigned int size,
-                            enum aux_transaction_type type,
-                            enum i2caux_transaction_action action);
+               struct aux_payload *payload);
+
+bool dc_link_aux_transfer_with_retries(struct ddc_service *ddc,
+               struct aux_payload *payload);
 
 void dal_ddc_service_write_scdc_data(
                struct ddc_service *ddc_service,
index 02f757dd70d44e55b0ee57c3970c72bf00f7d4cb..9d2d8e51306c7fccb24ea29cd3e4783c20ba705b 100644 (file)
@@ -39,6 +39,18 @@ enum segment_order {
        segment_order__non_contiguous,
 };
 
+struct dcn_hubbub_wm_set {
+       uint32_t wm_set;
+       uint32_t data_urgent;
+       uint32_t pte_meta_urgent;
+       uint32_t sr_enter;
+       uint32_t sr_exit;
+       uint32_t dram_clk_chanage;
+};
+
+struct dcn_hubbub_wm {
+       struct dcn_hubbub_wm_set sets[4];
+};
 
 struct hubbub_funcs {
        void (*update_dchub)(
@@ -58,7 +70,14 @@ struct hubbub_funcs {
        bool (*dcc_support_pixel_format)(
                        enum surface_pixel_format format,
                        unsigned int *bytes_per_element);
+
+       void (*wm_read_state)(struct hubbub *hubbub,
+                       struct dcn_hubbub_wm *wm);
 };
 
+struct hubbub {
+       const struct hubbub_funcs *funcs;
+       struct dc_context *ctx;
+};
 
 #endif
index cb85eaa9857f84e878115934dc00fb10f92b80ea..cbaa43853611e42d3dd5a011a80237c4a353756e 100644 (file)
 
 #include "dm_services_types.h"
 
+/* If HW itself ever powered down it will be 0.
+ * fwDmcuInit will write to 1.
+ * Driver will only call MCP init if current state is 1,
+ * and the MCP command will transition this to 2.
+ */
 enum dmcu_state {
-       DMCU_NOT_INITIALIZED = 0,
-       DMCU_RUNNING = 1
+       DMCU_UNLOADED = 0,
+       DMCU_LOADED_UNINITIALIZED = 1,
+       DMCU_RUNNING = 2,
 };
 
 struct dmcu_version {
-       unsigned int date;
-       unsigned int month;
-       unsigned int year;
        unsigned int interface_version;
+       unsigned int abm_version;
+       unsigned int psr_version;
+       unsigned int build_version;
 };
 
 struct dmcu {
index e894e649ce5af8880335cd94a828a27b5484a59e..fb7967b39edbf217d46dc8ceaa7234d01d40054c 100644 (file)
@@ -39,6 +39,11 @@ struct dpp {
 
 };
 
+struct dpp_input_csc_matrix {
+       enum dc_color_space color_space;
+       uint16_t regval[12];
+};
+
 struct dpp_grph_csc_adjustment {
        struct fixed31_32 temperature_matrix[CSC_TEMPERATURE_MATRIX_SIZE];
        enum graphics_gamut_adjust_type gamut_adjust_type;
index 04c6989aac58dd002288ef669d6e8f372a3f7c84..1cd07e94ee63184de3f1338887b456cb4cfab147 100644 (file)
@@ -78,7 +78,8 @@ struct hubp_funcs {
        bool (*hubp_program_surface_flip_and_addr)(
                struct hubp *hubp,
                const struct dc_plane_address *address,
-               bool flip_immediate);
+               bool flip_immediate,
+               uint8_t vmid);
 
        void (*hubp_program_pte_vm)(
                struct hubp *hubp,
index 06df02ddff6a045a9f201e78a504b57453f33717..da89c2edb07c758034d640045201465833dfa245 100644 (file)
@@ -31,7 +31,7 @@
 #include "dml/display_mode_structs.h"
 
 struct dchub_init_data;
-struct cstate_pstate_watermarks_st1 {
+struct cstate_pstate_watermarks_st {
        uint32_t cstate_exit_ns;
        uint32_t cstate_enter_plus_exit_ns;
        uint32_t pstate_change_ns;
@@ -40,7 +40,7 @@ struct cstate_pstate_watermarks_st1 {
 struct dcn_watermarks {
        uint32_t pte_meta_urgent_ns;
        uint32_t urgent_ns;
-       struct cstate_pstate_watermarks_st1 cstate_pstate;
+       struct cstate_pstate_watermarks_st cstate_pstate;
 };
 
 struct dcn_watermark_set {
index 53a9b64df11a7d2960e018efb3df4796e04723f4..4051493557bcccdef4715dafb58aa93e3a714f10 100644 (file)
@@ -161,6 +161,10 @@ struct stream_encoder_funcs {
        void (*set_avmute)(
                struct stream_encoder *enc, bool enable);
 
+       void (*dig_connect_to_otg)(
+               struct stream_encoder *enc,
+               int tg_inst);
+
 };
 
 #endif /* STREAM_ENCODER_H_ */
similarity index 63%
rename from drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c
rename to drivers/gpu/drm/amd/display/dc/inc/hw/vmid.h
index 5d155d36d353ebbab49bb5f83487eaab78d6b9ee..037beb0a2a270af171698b53911b03242bada608 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
+ * Copyright 2018 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"),
  *
  */
 
-#include "dm_services.h"
+#ifndef DAL_DC_INC_HW_VMID_H_
+#define DAL_DC_INC_HW_VMID_H_
 
-/*
- * Pre-requisites: headers required by header of this unit
- */
-#include "include/i2caux_interface.h"
-
-/*
- * Header of this unit
- */
-
-#include "engine.h"
+#include "core_types.h"
+#include "dchubbub.h"
 
-void dal_i2caux_construct_engine(
-       struct engine *engine,
-       struct dc_context *ctx)
-{
-       engine->ddc = NULL;
-       engine->ctx = ctx;
-}
+struct dcn_vmid_registers {
+       uint32_t CNTL;
+       uint32_t PAGE_TABLE_BASE_ADDR_HI32;
+       uint32_t PAGE_TABLE_BASE_ADDR_LO32;
+       uint32_t PAGE_TABLE_START_ADDR_HI32;
+       uint32_t PAGE_TABLE_START_ADDR_LO32;
+       uint32_t PAGE_TABLE_END_ADDR_HI32;
+       uint32_t PAGE_TABLE_END_ADDR_LO32;
+};
 
-void dal_i2caux_destruct_engine(
-       struct engine *engine)
-{
-       /* nothing to do */
-}
+struct dcn_vmid_page_table_config {
+       uint64_t        page_table_start_addr;
+       uint64_t        page_table_end_addr;
+       enum dcn_hubbub_page_table_depth        depth;
+       enum dcn_hubbub_page_table_block_size   block_size;
+};
 
+#endif /* DAL_DC_INC_HW_VMID_H_ */
similarity index 65%
rename from drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.h
rename to drivers/gpu/drm/amd/display/dc/inc/vm_helper.h
index c48c61f540a86fcf57e385428e582d49091dd934..a202206e22a3c8aea2b0f360f15fbaeacbb0428c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
+ * Copyright 2018 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"),
  *
  */
 
-#ifndef __DAL_I2C_SW_ENGINE_DCE110_H__
-#define __DAL_I2C_SW_ENGINE_DCE110_H__
+#ifndef DC_INC_VM_HELPER_H_
+#define DC_INC_VM_HELPER_H_
 
-struct i2c_sw_engine_dce110 {
-       struct i2c_sw_engine base;
-       uint32_t engine_id;
+#include "dc_types.h"
+
+#define MAX_VMID 16
+#define MAX_HUBP 6
+
+struct vmid_usage {
+       uint16_t vmid_usage[2];
 };
 
-struct i2c_sw_engine_dce110_create_arg {
-       uint32_t engine_id;
-       uint32_t default_speed;
-       struct dc_context *ctx;
+struct vm_helper {
+       unsigned int num_vmid;
+       unsigned int num_hubp;
+       unsigned int num_vmids_available;
+       uint64_t *ptb_assigned_to_vmid;
+       struct vmid_usage *hubp_vmid_usage;
 };
 
-struct i2c_engine *dal_i2c_sw_engine_dce110_create(
-       const struct i2c_sw_engine_dce110_create_arg *arg);
+uint8_t get_vmid_for_ptb(
+               struct vm_helper *vm_helper,
+               int64_t ptb,
+               uint8_t pipe_idx);
+
+struct vm_helper init_vm_helper(
+       unsigned int num_vmid,
+       unsigned int num_hubp);
 
-#endif
+#endif /* DC_INC_VM_HELPER_H_ */
index 7fd78a696800b50982c8744df5a47bc98240a022..01bf01a34a08c24699a6b3d6d338c1e2d4beef32 100644 (file)
@@ -211,8 +211,8 @@ struct bp_pixel_clock_parameters {
        /* signal_type -> Encoder Mode - needed by VBIOS Exec table */
        enum signal_type signal_type;
        /* Adjusted Pixel Clock (after VBIOS exec table)
-        * that becomes Target Pixel Clock (KHz) */
-       uint32_t target_pixel_clock;
+        * that becomes Target Pixel Clock (100 Hz units) */
+       uint32_t target_pixel_clock_100hz;
        /* Calculated Reference divider of Display PLL */
        uint32_t reference_divider;
        /* Calculated Feedback divider of Display PLL */
index 13a3c82d118f170963e752f415adcc7a73e439a8..bb012cb1a9f58bb515db94502a461a181c49d89f 100644 (file)
@@ -40,9 +40,19 @@ struct aux_payload {
        /* set following flag to write data,
         * reset it to read data */
        bool write;
+       bool mot;
        uint32_t address;
        uint8_t length;
        uint8_t *data;
+       /*
+        * used to return the reply type of the transaction
+        * ignored if NULL
+        */
+       uint8_t *reply;
+       /* expressed in milliseconds
+        * zero means "use default value"
+        */
+       uint32_t defer_delay;
 };
 
 struct aux_command {
@@ -66,27 +76,4 @@ union aux_config {
        uint32_t raw;
 };
 
-struct i2caux;
-
-struct i2caux *dal_i2caux_create(
-       struct dc_context *ctx);
-
-bool dal_i2caux_submit_i2c_command(
-       struct i2caux *i2caux,
-       struct ddc *ddc,
-       struct i2c_command *cmd);
-
-bool dal_i2caux_submit_aux_command(
-       struct i2caux *i2caux,
-       struct ddc *ddc,
-       struct aux_command *cmd);
-
-void dal_i2caux_configure_aux(
-       struct i2caux *i2caux,
-       struct ddc *ddc,
-       union aux_config cfg);
-
-void dal_i2caux_destroy(
-       struct i2caux **ptr);
-
 #endif
index 479b77c2e89e222467753209ebf40524a07bd7c1..eefb85928298b11aed866f5d9f677d5be3c49d56 100644 (file)
@@ -823,7 +823,7 @@ static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma,
        bool is_clipped = false;
        struct fixed31_32 sdr_white_level;
 
-       if (fs_params == NULL || fs_params->max_content == 0 ||
+       if (fs_params->max_content == 0 ||
                        fs_params->max_display == 0)
                return false;
 
@@ -1508,7 +1508,7 @@ static bool map_regamma_hw_to_x_user(
        struct hw_x_point *coords = coords_x;
        const struct pwl_float_data_ex *regamma = rgb_regamma;
 
-       if (mapUserRamp) {
+       if (ramp && mapUserRamp) {
                copy_rgb_regamma_to_coordinates_x(coords,
                                hw_points_num,
                                rgb_regamma);
@@ -1545,7 +1545,7 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf,
 
        struct pwl_float_data *rgb_user = NULL;
        struct pwl_float_data_ex *rgb_regamma = NULL;
-       struct gamma_pixel *axix_x = NULL;
+       struct gamma_pixel *axis_x = NULL;
        struct pixel_gamma_point *coeff = NULL;
        enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB;
        bool ret = false;
@@ -1555,47 +1555,54 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf,
 
        /* we can use hardcoded curve for plain SRGB TF */
        if (output_tf->type == TF_TYPE_PREDEFINED && canRomBeUsed == true &&
-                       output_tf->tf == TRANSFER_FUNCTION_SRGB &&
-                       (ramp->is_identity || (!mapUserRamp && ramp->type == GAMMA_RGB_256)))
-               return true;
+                       output_tf->tf == TRANSFER_FUNCTION_SRGB) {
+               if (ramp == NULL)
+                       return true;
+               if (ramp->is_identity || (!mapUserRamp && ramp->type == GAMMA_RGB_256))
+                       return true;
+       }
 
        output_tf->type = TF_TYPE_DISTRIBUTED_POINTS;
 
-       rgb_user = kvcalloc(ramp->num_entries + _EXTRA_POINTS,
+       if (ramp && (mapUserRamp || ramp->type != GAMMA_RGB_256)) {
+               rgb_user = kvcalloc(ramp->num_entries + _EXTRA_POINTS,
                            sizeof(*rgb_user),
                            GFP_KERNEL);
-       if (!rgb_user)
-               goto rgb_user_alloc_fail;
+               if (!rgb_user)
+                       goto rgb_user_alloc_fail;
+
+               axis_x = kvcalloc(ramp->num_entries + 3, sizeof(*axis_x),
+                               GFP_KERNEL);
+               if (!axis_x)
+                       goto axis_x_alloc_fail;
+
+               dividers.divider1 = dc_fixpt_from_fraction(3, 2);
+               dividers.divider2 = dc_fixpt_from_int(2);
+               dividers.divider3 = dc_fixpt_from_fraction(5, 2);
+
+               build_evenly_distributed_points(
+                               axis_x,
+                               ramp->num_entries,
+                               dividers);
+
+               if (ramp->type == GAMMA_RGB_256 && mapUserRamp)
+                       scale_gamma(rgb_user, ramp, dividers);
+               else if (ramp->type == GAMMA_RGB_FLOAT_1024)
+                       scale_gamma_dx(rgb_user, ramp, dividers);
+       }
+
        rgb_regamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
                               sizeof(*rgb_regamma),
                               GFP_KERNEL);
        if (!rgb_regamma)
                goto rgb_regamma_alloc_fail;
-       axix_x = kvcalloc(ramp->num_entries + 3, sizeof(*axix_x),
-                         GFP_KERNEL);
-       if (!axix_x)
-               goto axix_x_alloc_fail;
+
        coeff = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS, sizeof(*coeff),
                         GFP_KERNEL);
        if (!coeff)
                goto coeff_alloc_fail;
 
-       dividers.divider1 = dc_fixpt_from_fraction(3, 2);
-       dividers.divider2 = dc_fixpt_from_int(2);
-       dividers.divider3 = dc_fixpt_from_fraction(5, 2);
-
        tf = output_tf->tf;
-
-       build_evenly_distributed_points(
-                       axix_x,
-                       ramp->num_entries,
-                       dividers);
-
-       if (ramp->type == GAMMA_RGB_256 && mapUserRamp)
-               scale_gamma(rgb_user, ramp, dividers);
-       else if (ramp->type == GAMMA_RGB_FLOAT_1024)
-               scale_gamma_dx(rgb_user, ramp, dividers);
-
        if (tf == TRANSFER_FUNCTION_PQ) {
                tf_pts->end_exponent = 7;
                tf_pts->x_point_at_y1_red = 125;
@@ -1623,22 +1630,22 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf,
                                coordinates_x, tf == TRANSFER_FUNCTION_SRGB ? true:false);
        }
        map_regamma_hw_to_x_user(ramp, coeff, rgb_user,
-                       coordinates_x, axix_x, rgb_regamma,
+                       coordinates_x, axis_x, rgb_regamma,
                        MAX_HW_POINTS, tf_pts,
-                       (mapUserRamp || ramp->type != GAMMA_RGB_256) &&
-                       ramp->type != GAMMA_CS_TFM_1D);
+                       (mapUserRamp || (ramp && ramp->type != GAMMA_RGB_256)) &&
+                       (ramp && ramp->type != GAMMA_CS_TFM_1D));
 
-       if (ramp->type == GAMMA_CS_TFM_1D)
+       if (ramp && ramp->type == GAMMA_CS_TFM_1D)
                apply_lut_1d(ramp, MAX_HW_POINTS, tf_pts);
 
        ret = true;
 
        kvfree(coeff);
 coeff_alloc_fail:
-       kvfree(axix_x);
-axix_x_alloc_fail:
        kvfree(rgb_regamma);
 rgb_regamma_alloc_fail:
+       kvfree(axis_x);
+axis_x_alloc_fail:
        kvfree(rgb_user);
 rgb_user_alloc_fail:
        return ret;
@@ -1772,8 +1779,7 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf,
        /* we can use hardcoded curve for plain SRGB TF */
        if (input_tf->type == TF_TYPE_PREDEFINED &&
                        input_tf->tf == TRANSFER_FUNCTION_SRGB &&
-                       (!mapUserRamp &&
-                       (ramp->type == GAMMA_RGB_256 || ramp->num_entries == 0)))
+                       !mapUserRamp)
                return true;
 
        input_tf->type = TF_TYPE_DISTRIBUTED_POINTS;
index 1544ed3f17473cb80c0009c338bccd60f245a52c..94a84bc57c7a6a5db2604fbaf4d2ef9ae40e445d 100644 (file)
@@ -108,8 +108,8 @@ static unsigned int calc_duration_in_us_from_v_total(
 {
        unsigned int duration_in_us =
                        (unsigned int)(div64_u64(((unsigned long long)(v_total)
-                               * 1000) * stream->timing.h_total,
-                                       stream->timing.pix_clk_khz));
+                               * 10000) * stream->timing.h_total,
+                                       stream->timing.pix_clk_100hz));
 
        return duration_in_us;
 }
@@ -126,7 +126,7 @@ static unsigned int calc_v_total_from_refresh(
                                        refresh_in_uhz)));
 
        v_total = div64_u64(div64_u64(((unsigned long long)(
-                       frame_duration_in_ns) * stream->timing.pix_clk_khz),
+                       frame_duration_in_ns) * (stream->timing.pix_clk_100hz / 10)),
                        stream->timing.h_total), 1000000);
 
        /* v_total cannot be less than nominal */
@@ -152,7 +152,7 @@ static unsigned int calc_v_total_from_duration(
                duration_in_us = vrr->max_duration_in_us;
 
        v_total = div64_u64(div64_u64(((unsigned long long)(
-                               duration_in_us) * stream->timing.pix_clk_khz),
+                               duration_in_us) * (stream->timing.pix_clk_100hz / 10)),
                                stream->timing.h_total), 1000);
 
        /* v_total cannot be less than nominal */
@@ -227,7 +227,7 @@ static void update_v_total_for_static_ramp(
        }
 
        v_total = div64_u64(div64_u64(((unsigned long long)(
-                       current_duration_in_us) * stream->timing.pix_clk_khz),
+                       current_duration_in_us) * (stream->timing.pix_clk_100hz / 10)),
                                stream->timing.h_total), 1000);
 
        in_out_vrr->adjust.v_total_min = v_total;
@@ -461,6 +461,26 @@ bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync,
        return false;
 }
 
+static void build_vrr_infopacket_header_vtem(enum signal_type signal,
+               struct dc_info_packet *infopacket)
+{
+       // HEADER
+
+       // HB0, HB1, HB2 indicates PacketType VTEMPacket
+       infopacket->hb0 = 0x7F;
+       infopacket->hb1 = 0xC0;
+       infopacket->hb2 = 0x00;
+       /* HB3 Bit Fields
+        * Reserved :1 = 0
+        * Sync     :1 = 0
+        * VFR      :1 = 1
+        * Ds_Type  :2 = 0
+        * End      :1 = 0
+        * New      :1 = 0
+        */
+       infopacket->hb3 = 0x20;
+}
+
 static void build_vrr_infopacket_header_v1(enum signal_type signal,
                struct dc_info_packet *infopacket,
                unsigned int *payload_size)
@@ -559,6 +579,54 @@ static void build_vrr_infopacket_header_v2(enum signal_type signal,
        }
 }
 
+static void build_vrr_vtem_infopacket_data(const struct dc_stream_state *stream,
+               const struct mod_vrr_params *vrr,
+               struct dc_info_packet *infopacket)
+{
+       /* dc_info_packet to VtemPacket Translation of Bit-fields,
+        * SB[6]
+        * unsigned char VRR_EN        :1
+        * unsigned char M_CONST       :1
+        * unsigned char Reserved2     :2
+        * unsigned char FVA_Factor_M1 :4
+        * SB[7]
+        * unsigned char Base_Vfront   :8
+        * SB[8]
+        * unsigned char Base_Refresh_Rate_98 :2
+        * unsigned char RB                   :1
+        * unsigned char Reserved3            :5
+        * SB[9]
+        * unsigned char Base_RefreshRate_07  :8
+        */
+       unsigned int fieldRateInHz;
+
+       if (vrr->state == VRR_STATE_ACTIVE_VARIABLE ||
+                               vrr->state == VRR_STATE_ACTIVE_FIXED){
+               infopacket->sb[6] |= 0x80; //VRR_EN Bit = 1
+       } else {
+               infopacket->sb[6] &= 0x7F; //VRR_EN Bit = 0
+       }
+
+       if (!stream->timing.vic) {
+               infopacket->sb[7] = stream->timing.v_front_porch;
+
+               /* TODO: In dal2, we check mode flags for a reduced blanking timing.
+                * Need a way to relay that information to this function.
+                * if("ReducedBlanking")
+                * {
+                *   infopacket->sb[8] |= 0x20; //Set 3rd bit to 1
+                * }
+                */
+               fieldRateInHz = (stream->timing.pix_clk_100hz * 100)/
+                               (stream->timing.h_total * stream->timing.v_total);
+
+               infopacket->sb[8] |= ((fieldRateInHz & 0x300) >> 2);
+               infopacket->sb[9] |= fieldRateInHz & 0xFF;
+
+       }
+       infopacket->valid = true;
+}
+
 static void build_vrr_infopacket_data(const struct mod_vrr_params *vrr,
                struct dc_info_packet *infopacket)
 {
@@ -672,6 +740,19 @@ static void build_vrr_infopacket_v2(enum signal_type signal,
        infopacket->valid = true;
 }
 
+static void build_vrr_infopacket_vtem(const struct dc_stream_state *stream,
+               const struct mod_vrr_params *vrr,
+               struct dc_info_packet *infopacket)
+{
+       //VTEM info packet for HdmiVrr
+
+       //VTEM Packet is structured differently
+       build_vrr_infopacket_header_vtem(stream->signal, infopacket);
+       build_vrr_vtem_infopacket_data(stream, vrr, infopacket);
+
+       infopacket->valid = true;
+}
+
 void mod_freesync_build_vrr_infopacket(struct mod_freesync *mod_freesync,
                const struct dc_stream_state *stream,
                const struct mod_vrr_params *vrr,
@@ -679,18 +760,21 @@ void mod_freesync_build_vrr_infopacket(struct mod_freesync *mod_freesync,
                const enum color_transfer_func *app_tf,
                struct dc_info_packet *infopacket)
 {
-       /* SPD info packet for FreeSync */
-
-       /* Check if Freesync is supported. Return if false. If true,
+       /* SPD info packet for FreeSync
+        * VTEM info packet for HdmiVRR
+        * Check if Freesync is supported. Return if false. If true,
         * set the corresponding bit in the info packet
         */
-       if (!vrr->supported || !vrr->send_vsif)
+       if (!vrr->supported || (!vrr->send_info_frame && packet_type != PACKET_TYPE_VTEM))
                return;
 
        switch (packet_type) {
        case PACKET_TYPE_FS2:
                build_vrr_infopacket_v2(stream->signal, vrr, app_tf, infopacket);
                break;
+       case PACKET_TYPE_VTEM:
+               build_vrr_infopacket_vtem(stream, vrr, infopacket);
+               break;
        case PACKET_TYPE_VRR:
        case PACKET_TYPE_FS1:
        default:
@@ -739,7 +823,7 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
                return;
 
        in_out_vrr->state = in_config->state;
-       in_out_vrr->send_vsif = in_config->vsif_supported;
+       in_out_vrr->send_info_frame = in_config->vsif_supported;
 
        if (in_config->state == VRR_STATE_UNSUPPORTED) {
                in_out_vrr->state = VRR_STATE_UNSUPPORTED;
@@ -972,7 +1056,7 @@ unsigned long long mod_freesync_calc_nominal_field_rate(
        unsigned long long nominal_field_rate_in_uhz = 0;
 
        /* Calculate nominal field rate for stream */
-       nominal_field_rate_in_uhz = stream->timing.pix_clk_khz;
+       nominal_field_rate_in_uhz = stream->timing.pix_clk_100hz / 10;
        nominal_field_rate_in_uhz *= 1000ULL * 1000ULL * 1000ULL;
        nominal_field_rate_in_uhz = div_u64(nominal_field_rate_in_uhz,
                                                stream->timing.h_total);
index 949a8b62aa988292042dd27816cf875adcf0e4f9..4222e403b15150f43d50e75822844b47570107e4 100644 (file)
@@ -104,7 +104,7 @@ struct mod_vrr_params_fixed_refresh {
 
 struct mod_vrr_params {
        bool supported;
-       bool send_vsif;
+       bool send_info_frame;
        enum mod_vrr_state state;
 
        uint32_t min_refresh_in_uhz;
index 1bd02c0ac30c3f0bde291918146d60a7e7ecfcba..b711e7e6c2044ef39313a6b280cbf83fc5fa1539 100644 (file)
@@ -41,7 +41,8 @@ enum color_transfer_func {
 enum vrr_packet_type {
        PACKET_TYPE_VRR,
        PACKET_TYPE_FS1,
-       PACKET_TYPE_FS2
+       PACKET_TYPE_FS2,
+       PACKET_TYPE_VTEM
 };
 
 
index 00f63b7dd32f77828409d4b1b34008b3b316d9c2..baab6c4ae1918461e000dd5a1196871f492a3b63 100644 (file)
@@ -41,6 +41,17 @@ static const unsigned char min_reduction_table[13] = {
 static const unsigned char max_reduction_table[13] = {
 0xf5, 0xe5, 0xd9, 0xcd, 0xb1, 0xa5, 0xa5, 0x80, 0x65, 0x4d, 0x4d, 0x4d, 0x32};
 
+/* ABM 2.2 Min Reduction effectively disabled (100% for all configs)*/
+static const unsigned char min_reduction_table_v_2_2[13] = {
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+/* Possible ABM 2.2 Max Reduction configs from least aggressive to most aggressive
+ *  0    1     2     3     4     5     6     7     8     9     10    11   12
+ * 96.1 89.8 85.1  80.3  69.4  64.7  54.9  45.1  30.2  25.1  19.6  12.5  12.5 %
+ */
+static const unsigned char max_reduction_table_v_2_2[13] = {
+0xf5, 0xe5, 0xd9, 0xcd, 0xb1, 0xa5, 0x8c, 0x73, 0x4d, 0x40, 0x32, 0x20, 0x20};
+
 /* Predefined ABM configuration sets. We may have different configuration sets
  * in order to satisfy different power/quality requirements.
  */
@@ -56,7 +67,10 @@ static const unsigned char abm_config[abm_defines_max_config][abm_defines_max_le
 #define NUM_AGGR_LEVEL    4
 #define NUM_POWER_FN_SEGS 8
 #define NUM_BL_CURVE_SEGS 16
+#define IRAM_RESERVE_AREA_START 0xF0  // reserve 0xF0~0xFF are write by DMCU only
+#define IRAM_SIZE 256
 
+#pragma pack(push, 1)
 /* NOTE: iRAM is 256B in size */
 struct iram_table_v_2 {
        /* flags                      */
@@ -85,11 +99,10 @@ struct iram_table_v_2 {
 
        /* For reading PSR State directly from IRAM */
        uint8_t psr_state;                                              /* 0xf0       */
-       uint8_t dmcu_interface_version;                                 /* 0xf1       */
-       uint8_t dmcu_date_version_year_b0;                              /* 0xf2       */
-       uint8_t dmcu_date_version_year_b1;                              /* 0xf3       */
-       uint8_t dmcu_date_version_month;                                /* 0xf4       */
-       uint8_t dmcu_date_version_day;                                  /* 0xf5       */
+       uint8_t dmcu_mcp_interface_version;                                                     /* 0xf1       */
+       uint8_t dmcu_abm_feature_version;                                                       /* 0xf2       */
+       uint8_t dmcu_psr_feature_version;                                                       /* 0xf3       */
+       uint16_t dmcu_version;                                                                          /* 0xf4       */
        uint8_t dmcu_state;                                             /* 0xf6       */
 
        uint16_t blRampReduction;                                       /* 0xf7       */
@@ -101,6 +114,50 @@ struct iram_table_v_2 {
        uint8_t dummy9;                                                 /* 0xff       */
 };
 
+struct iram_table_v_2_2 {
+       /* flags                      */
+       uint16_t flags;                                                 /* 0x00 U16  */
+
+       /* parameters for ABM2.2 algorithm */
+       uint8_t min_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];          /* 0x02 U0.8 */
+       uint8_t max_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];          /* 0x16 U0.8 */
+       uint8_t bright_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];        /* 0x2a U2.6 */
+       uint8_t dark_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];          /* 0x3e U2.6 */
+       uint8_t hybridFactor[NUM_AGGR_LEVEL];                                           /* 0x52 U0.8 */
+       uint8_t contrastFactor[NUM_AGGR_LEVEL];                                         /* 0x56 U0.8 */
+       uint8_t deviation_gain[NUM_AGGR_LEVEL];                                         /* 0x5a U0.8 */
+       uint8_t iir_curve[NUM_AMBI_LEVEL];                                                      /* 0x5e U0.8 */
+       uint8_t pad[29];                                                                                        /* 0x63 U0.8 */
+
+       /* parameters for crgb conversion */
+       uint16_t crgb_thresh[NUM_POWER_FN_SEGS];                                        /* 0x80 U3.13 */
+       uint16_t crgb_offset[NUM_POWER_FN_SEGS];                                        /* 0x90 U1.15 */
+       uint16_t crgb_slope[NUM_POWER_FN_SEGS];                                         /* 0xa0 U4.12 */
+
+       /* parameters for custom curve */
+       /* thresholds for brightness --> backlight */
+       uint16_t backlight_thresholds[NUM_BL_CURVE_SEGS];                       /* 0xb0 U16.0 */
+       /* offsets for brightness --> backlight */
+       uint16_t backlight_offsets[NUM_BL_CURVE_SEGS];                          /* 0xd0 U16.0 */
+
+       /* For reading PSR State directly from IRAM */
+       uint8_t psr_state;                                                                                      /* 0xf0       */
+       uint8_t dmcu_mcp_interface_version;                                                     /* 0xf1       */
+       uint8_t dmcu_abm_feature_version;                                                       /* 0xf2       */
+       uint8_t dmcu_psr_feature_version;                                                       /* 0xf3       */
+       uint16_t dmcu_version;                                                                          /* 0xf4       */
+       uint8_t dmcu_state;                                                                                     /* 0xf6       */
+
+       uint16_t blRampReduction;                                                                       /* 0xf7       */
+       uint16_t blRampStart;                                                                           /* 0xf9       */
+       uint8_t dummy5;                                                                                         /* 0xfb       */
+       uint8_t dummy6;                                                                                         /* 0xfc       */
+       uint8_t dummy7;                                                                                         /* 0xfd       */
+       uint8_t dummy8;                                                                                         /* 0xfe       */
+       uint8_t dummy9;                                                                                         /* 0xff       */
+};
+#pragma pack(pop)
+
 static uint16_t backlight_8_to_16(unsigned int backlight_8bit)
 {
        return (uint16_t)(backlight_8bit * 0x101);
@@ -143,11 +200,367 @@ static void fill_backlight_transform_table(struct dmcu_iram_parameters params,
        }
 }
 
+static void fill_backlight_transform_table_v_2_2(struct dmcu_iram_parameters params,
+               struct iram_table_v_2_2 *table)
+{
+       unsigned int i;
+       unsigned int num_entries = NUM_BL_CURVE_SEGS;
+       unsigned int query_input_8bit;
+       unsigned int query_output_8bit;
+       unsigned int lut_index;
+
+       table->backlight_thresholds[0] = 0;
+       table->backlight_offsets[0] = params.backlight_lut_array[0];
+       table->backlight_thresholds[num_entries-1] = 0xFFFF;
+       table->backlight_offsets[num_entries-1] =
+               params.backlight_lut_array[params.backlight_lut_array_size - 1];
+
+       /* Setup all brightness levels between 0% and 100% exclusive
+        * Fills brightness-to-backlight transform table. Backlight custom curve
+        * describes transform from brightness to backlight. It will be defined
+        * as set of thresholds and set of offsets, together, implying
+        * extrapolation of custom curve into 16 uniformly spanned linear
+        * segments.  Each threshold/offset represented by 16 bit entry in
+        * format U4.10.
+        */
+       for (i = 1; i+1 < num_entries; i++) {
+               query_input_8bit = DIV_ROUNDUP((i * 256), num_entries);
+
+               lut_index = (params.backlight_lut_array_size - 1) * i / (num_entries - 1);
+               ASSERT(lut_index < params.backlight_lut_array_size);
+               query_output_8bit = params.backlight_lut_array[lut_index] >> 8;
+
+               table->backlight_thresholds[i] =
+                               backlight_8_to_16(query_input_8bit);
+               table->backlight_offsets[i] =
+                               backlight_8_to_16(query_output_8bit);
+       }
+}
+
+void fill_iram_v_2(struct iram_table_v_2 *ram_table, struct dmcu_iram_parameters params)
+{
+       unsigned int set = params.set;
+
+       ram_table->flags = 0x0;
+       ram_table->deviation_gain = 0xb3;
+
+       ram_table->blRampReduction =
+               cpu_to_be16(params.backlight_ramping_reduction);
+       ram_table->blRampStart =
+               cpu_to_be16(params.backlight_ramping_start);
+
+       ram_table->min_reduction[0][0] = min_reduction_table[abm_config[set][0]];
+       ram_table->min_reduction[1][0] = min_reduction_table[abm_config[set][0]];
+       ram_table->min_reduction[2][0] = min_reduction_table[abm_config[set][0]];
+       ram_table->min_reduction[3][0] = min_reduction_table[abm_config[set][0]];
+       ram_table->min_reduction[4][0] = min_reduction_table[abm_config[set][0]];
+       ram_table->max_reduction[0][0] = max_reduction_table[abm_config[set][0]];
+       ram_table->max_reduction[1][0] = max_reduction_table[abm_config[set][0]];
+       ram_table->max_reduction[2][0] = max_reduction_table[abm_config[set][0]];
+       ram_table->max_reduction[3][0] = max_reduction_table[abm_config[set][0]];
+       ram_table->max_reduction[4][0] = max_reduction_table[abm_config[set][0]];
+
+       ram_table->min_reduction[0][1] = min_reduction_table[abm_config[set][1]];
+       ram_table->min_reduction[1][1] = min_reduction_table[abm_config[set][1]];
+       ram_table->min_reduction[2][1] = min_reduction_table[abm_config[set][1]];
+       ram_table->min_reduction[3][1] = min_reduction_table[abm_config[set][1]];
+       ram_table->min_reduction[4][1] = min_reduction_table[abm_config[set][1]];
+       ram_table->max_reduction[0][1] = max_reduction_table[abm_config[set][1]];
+       ram_table->max_reduction[1][1] = max_reduction_table[abm_config[set][1]];
+       ram_table->max_reduction[2][1] = max_reduction_table[abm_config[set][1]];
+       ram_table->max_reduction[3][1] = max_reduction_table[abm_config[set][1]];
+       ram_table->max_reduction[4][1] = max_reduction_table[abm_config[set][1]];
+
+       ram_table->min_reduction[0][2] = min_reduction_table[abm_config[set][2]];
+       ram_table->min_reduction[1][2] = min_reduction_table[abm_config[set][2]];
+       ram_table->min_reduction[2][2] = min_reduction_table[abm_config[set][2]];
+       ram_table->min_reduction[3][2] = min_reduction_table[abm_config[set][2]];
+       ram_table->min_reduction[4][2] = min_reduction_table[abm_config[set][2]];
+       ram_table->max_reduction[0][2] = max_reduction_table[abm_config[set][2]];
+       ram_table->max_reduction[1][2] = max_reduction_table[abm_config[set][2]];
+       ram_table->max_reduction[2][2] = max_reduction_table[abm_config[set][2]];
+       ram_table->max_reduction[3][2] = max_reduction_table[abm_config[set][2]];
+       ram_table->max_reduction[4][2] = max_reduction_table[abm_config[set][2]];
+
+       ram_table->min_reduction[0][3] = min_reduction_table[abm_config[set][3]];
+       ram_table->min_reduction[1][3] = min_reduction_table[abm_config[set][3]];
+       ram_table->min_reduction[2][3] = min_reduction_table[abm_config[set][3]];
+       ram_table->min_reduction[3][3] = min_reduction_table[abm_config[set][3]];
+       ram_table->min_reduction[4][3] = min_reduction_table[abm_config[set][3]];
+       ram_table->max_reduction[0][3] = max_reduction_table[abm_config[set][3]];
+       ram_table->max_reduction[1][3] = max_reduction_table[abm_config[set][3]];
+       ram_table->max_reduction[2][3] = max_reduction_table[abm_config[set][3]];
+       ram_table->max_reduction[3][3] = max_reduction_table[abm_config[set][3]];
+       ram_table->max_reduction[4][3] = max_reduction_table[abm_config[set][3]];
+
+       ram_table->bright_pos_gain[0][0] = 0x20;
+       ram_table->bright_pos_gain[0][1] = 0x20;
+       ram_table->bright_pos_gain[0][2] = 0x20;
+       ram_table->bright_pos_gain[0][3] = 0x20;
+       ram_table->bright_pos_gain[1][0] = 0x20;
+       ram_table->bright_pos_gain[1][1] = 0x20;
+       ram_table->bright_pos_gain[1][2] = 0x20;
+       ram_table->bright_pos_gain[1][3] = 0x20;
+       ram_table->bright_pos_gain[2][0] = 0x20;
+       ram_table->bright_pos_gain[2][1] = 0x20;
+       ram_table->bright_pos_gain[2][2] = 0x20;
+       ram_table->bright_pos_gain[2][3] = 0x20;
+       ram_table->bright_pos_gain[3][0] = 0x20;
+       ram_table->bright_pos_gain[3][1] = 0x20;
+       ram_table->bright_pos_gain[3][2] = 0x20;
+       ram_table->bright_pos_gain[3][3] = 0x20;
+       ram_table->bright_pos_gain[4][0] = 0x20;
+       ram_table->bright_pos_gain[4][1] = 0x20;
+       ram_table->bright_pos_gain[4][2] = 0x20;
+       ram_table->bright_pos_gain[4][3] = 0x20;
+       ram_table->bright_neg_gain[0][1] = 0x00;
+       ram_table->bright_neg_gain[0][2] = 0x00;
+       ram_table->bright_neg_gain[0][3] = 0x00;
+       ram_table->bright_neg_gain[1][0] = 0x00;
+       ram_table->bright_neg_gain[1][1] = 0x00;
+       ram_table->bright_neg_gain[1][2] = 0x00;
+       ram_table->bright_neg_gain[1][3] = 0x00;
+       ram_table->bright_neg_gain[2][0] = 0x00;
+       ram_table->bright_neg_gain[2][1] = 0x00;
+       ram_table->bright_neg_gain[2][2] = 0x00;
+       ram_table->bright_neg_gain[2][3] = 0x00;
+       ram_table->bright_neg_gain[3][0] = 0x00;
+       ram_table->bright_neg_gain[3][1] = 0x00;
+       ram_table->bright_neg_gain[3][2] = 0x00;
+       ram_table->bright_neg_gain[3][3] = 0x00;
+       ram_table->bright_neg_gain[4][0] = 0x00;
+       ram_table->bright_neg_gain[4][1] = 0x00;
+       ram_table->bright_neg_gain[4][2] = 0x00;
+       ram_table->bright_neg_gain[4][3] = 0x00;
+       ram_table->dark_pos_gain[0][0] = 0x00;
+       ram_table->dark_pos_gain[0][1] = 0x00;
+       ram_table->dark_pos_gain[0][2] = 0x00;
+       ram_table->dark_pos_gain[0][3] = 0x00;
+       ram_table->dark_pos_gain[1][0] = 0x00;
+       ram_table->dark_pos_gain[1][1] = 0x00;
+       ram_table->dark_pos_gain[1][2] = 0x00;
+       ram_table->dark_pos_gain[1][3] = 0x00;
+       ram_table->dark_pos_gain[2][0] = 0x00;
+       ram_table->dark_pos_gain[2][1] = 0x00;
+       ram_table->dark_pos_gain[2][2] = 0x00;
+       ram_table->dark_pos_gain[2][3] = 0x00;
+       ram_table->dark_pos_gain[3][0] = 0x00;
+       ram_table->dark_pos_gain[3][1] = 0x00;
+       ram_table->dark_pos_gain[3][2] = 0x00;
+       ram_table->dark_pos_gain[3][3] = 0x00;
+       ram_table->dark_pos_gain[4][0] = 0x00;
+       ram_table->dark_pos_gain[4][1] = 0x00;
+       ram_table->dark_pos_gain[4][2] = 0x00;
+       ram_table->dark_pos_gain[4][3] = 0x00;
+       ram_table->dark_neg_gain[0][0] = 0x00;
+       ram_table->dark_neg_gain[0][1] = 0x00;
+       ram_table->dark_neg_gain[0][2] = 0x00;
+       ram_table->dark_neg_gain[0][3] = 0x00;
+       ram_table->dark_neg_gain[1][0] = 0x00;
+       ram_table->dark_neg_gain[1][1] = 0x00;
+       ram_table->dark_neg_gain[1][2] = 0x00;
+       ram_table->dark_neg_gain[1][3] = 0x00;
+       ram_table->dark_neg_gain[2][0] = 0x00;
+       ram_table->dark_neg_gain[2][1] = 0x00;
+       ram_table->dark_neg_gain[2][2] = 0x00;
+       ram_table->dark_neg_gain[2][3] = 0x00;
+       ram_table->dark_neg_gain[3][0] = 0x00;
+       ram_table->dark_neg_gain[3][1] = 0x00;
+       ram_table->dark_neg_gain[3][2] = 0x00;
+       ram_table->dark_neg_gain[3][3] = 0x00;
+       ram_table->dark_neg_gain[4][0] = 0x00;
+       ram_table->dark_neg_gain[4][1] = 0x00;
+       ram_table->dark_neg_gain[4][2] = 0x00;
+       ram_table->dark_neg_gain[4][3] = 0x00;
+
+       ram_table->iir_curve[0] = 0x65;
+       ram_table->iir_curve[1] = 0x65;
+       ram_table->iir_curve[2] = 0x65;
+       ram_table->iir_curve[3] = 0x65;
+       ram_table->iir_curve[4] = 0x65;
+
+       //Gamma 2.4
+       ram_table->crgb_thresh[0] = cpu_to_be16(0x13b6);
+       ram_table->crgb_thresh[1] = cpu_to_be16(0x1648);
+       ram_table->crgb_thresh[2] = cpu_to_be16(0x18e3);
+       ram_table->crgb_thresh[3] = cpu_to_be16(0x1b41);
+       ram_table->crgb_thresh[4] = cpu_to_be16(0x1d46);
+       ram_table->crgb_thresh[5] = cpu_to_be16(0x1f21);
+       ram_table->crgb_thresh[6] = cpu_to_be16(0x2167);
+       ram_table->crgb_thresh[7] = cpu_to_be16(0x2384);
+       ram_table->crgb_offset[0] = cpu_to_be16(0x2999);
+       ram_table->crgb_offset[1] = cpu_to_be16(0x3999);
+       ram_table->crgb_offset[2] = cpu_to_be16(0x4666);
+       ram_table->crgb_offset[3] = cpu_to_be16(0x5999);
+       ram_table->crgb_offset[4] = cpu_to_be16(0x6333);
+       ram_table->crgb_offset[5] = cpu_to_be16(0x7800);
+       ram_table->crgb_offset[6] = cpu_to_be16(0x8c00);
+       ram_table->crgb_offset[7] = cpu_to_be16(0xa000);
+       ram_table->crgb_slope[0]  = cpu_to_be16(0x3147);
+       ram_table->crgb_slope[1]  = cpu_to_be16(0x2978);
+       ram_table->crgb_slope[2]  = cpu_to_be16(0x23a2);
+       ram_table->crgb_slope[3]  = cpu_to_be16(0x1f55);
+       ram_table->crgb_slope[4]  = cpu_to_be16(0x1c63);
+       ram_table->crgb_slope[5]  = cpu_to_be16(0x1a0f);
+       ram_table->crgb_slope[6]  = cpu_to_be16(0x178d);
+       ram_table->crgb_slope[7]  = cpu_to_be16(0x15ab);
+
+       fill_backlight_transform_table(
+                       params, ram_table);
+}
+
+void fill_iram_v_2_2(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parameters params)
+{
+       unsigned int set = params.set;
+
+       ram_table->flags = 0x0;
+
+       ram_table->deviation_gain[0] = 0xb3;
+       ram_table->deviation_gain[1] = 0xb3;
+       ram_table->deviation_gain[2] = 0xb3;
+       ram_table->deviation_gain[3] = 0xb3;
+
+       ram_table->blRampReduction =
+               cpu_to_be16(params.backlight_ramping_reduction);
+       ram_table->blRampStart =
+               cpu_to_be16(params.backlight_ramping_start);
+
+       ram_table->min_reduction[0][0] = min_reduction_table_v_2_2[abm_config[set][0]];
+       ram_table->min_reduction[1][0] = min_reduction_table_v_2_2[abm_config[set][0]];
+       ram_table->min_reduction[2][0] = min_reduction_table_v_2_2[abm_config[set][0]];
+       ram_table->min_reduction[3][0] = min_reduction_table_v_2_2[abm_config[set][0]];
+       ram_table->min_reduction[4][0] = min_reduction_table_v_2_2[abm_config[set][0]];
+       ram_table->max_reduction[0][0] = max_reduction_table_v_2_2[abm_config[set][0]];
+       ram_table->max_reduction[1][0] = max_reduction_table_v_2_2[abm_config[set][0]];
+       ram_table->max_reduction[2][0] = max_reduction_table_v_2_2[abm_config[set][0]];
+       ram_table->max_reduction[3][0] = max_reduction_table_v_2_2[abm_config[set][0]];
+       ram_table->max_reduction[4][0] = max_reduction_table_v_2_2[abm_config[set][0]];
+
+       ram_table->min_reduction[0][1] = min_reduction_table_v_2_2[abm_config[set][1]];
+       ram_table->min_reduction[1][1] = min_reduction_table_v_2_2[abm_config[set][1]];
+       ram_table->min_reduction[2][1] = min_reduction_table_v_2_2[abm_config[set][1]];
+       ram_table->min_reduction[3][1] = min_reduction_table_v_2_2[abm_config[set][1]];
+       ram_table->min_reduction[4][1] = min_reduction_table_v_2_2[abm_config[set][1]];
+       ram_table->max_reduction[0][1] = max_reduction_table_v_2_2[abm_config[set][1]];
+       ram_table->max_reduction[1][1] = max_reduction_table_v_2_2[abm_config[set][1]];
+       ram_table->max_reduction[2][1] = max_reduction_table_v_2_2[abm_config[set][1]];
+       ram_table->max_reduction[3][1] = max_reduction_table_v_2_2[abm_config[set][1]];
+       ram_table->max_reduction[4][1] = max_reduction_table_v_2_2[abm_config[set][1]];
+
+       ram_table->min_reduction[0][2] = min_reduction_table_v_2_2[abm_config[set][2]];
+       ram_table->min_reduction[1][2] = min_reduction_table_v_2_2[abm_config[set][2]];
+       ram_table->min_reduction[2][2] = min_reduction_table_v_2_2[abm_config[set][2]];
+       ram_table->min_reduction[3][2] = min_reduction_table_v_2_2[abm_config[set][2]];
+       ram_table->min_reduction[4][2] = min_reduction_table_v_2_2[abm_config[set][2]];
+       ram_table->max_reduction[0][2] = max_reduction_table_v_2_2[abm_config[set][2]];
+       ram_table->max_reduction[1][2] = max_reduction_table_v_2_2[abm_config[set][2]];
+       ram_table->max_reduction[2][2] = max_reduction_table_v_2_2[abm_config[set][2]];
+       ram_table->max_reduction[3][2] = max_reduction_table_v_2_2[abm_config[set][2]];
+       ram_table->max_reduction[4][2] = max_reduction_table_v_2_2[abm_config[set][2]];
+
+       ram_table->min_reduction[0][3] = min_reduction_table_v_2_2[abm_config[set][3]];
+       ram_table->min_reduction[1][3] = min_reduction_table_v_2_2[abm_config[set][3]];
+       ram_table->min_reduction[2][3] = min_reduction_table_v_2_2[abm_config[set][3]];
+       ram_table->min_reduction[3][3] = min_reduction_table_v_2_2[abm_config[set][3]];
+       ram_table->min_reduction[4][3] = min_reduction_table_v_2_2[abm_config[set][3]];
+       ram_table->max_reduction[0][3] = max_reduction_table_v_2_2[abm_config[set][3]];
+       ram_table->max_reduction[1][3] = max_reduction_table_v_2_2[abm_config[set][3]];
+       ram_table->max_reduction[2][3] = max_reduction_table_v_2_2[abm_config[set][3]];
+       ram_table->max_reduction[3][3] = max_reduction_table_v_2_2[abm_config[set][3]];
+       ram_table->max_reduction[4][3] = max_reduction_table_v_2_2[abm_config[set][3]];
+
+       ram_table->bright_pos_gain[0][0] = 0x20;
+       ram_table->bright_pos_gain[0][1] = 0x20;
+       ram_table->bright_pos_gain[0][2] = 0x20;
+       ram_table->bright_pos_gain[0][3] = 0x20;
+       ram_table->bright_pos_gain[1][0] = 0x20;
+       ram_table->bright_pos_gain[1][1] = 0x20;
+       ram_table->bright_pos_gain[1][2] = 0x20;
+       ram_table->bright_pos_gain[1][3] = 0x20;
+       ram_table->bright_pos_gain[2][0] = 0x20;
+       ram_table->bright_pos_gain[2][1] = 0x20;
+       ram_table->bright_pos_gain[2][2] = 0x20;
+       ram_table->bright_pos_gain[2][3] = 0x20;
+       ram_table->bright_pos_gain[3][0] = 0x20;
+       ram_table->bright_pos_gain[3][1] = 0x20;
+       ram_table->bright_pos_gain[3][2] = 0x20;
+       ram_table->bright_pos_gain[3][3] = 0x20;
+       ram_table->bright_pos_gain[4][0] = 0x20;
+       ram_table->bright_pos_gain[4][1] = 0x20;
+       ram_table->bright_pos_gain[4][2] = 0x20;
+       ram_table->bright_pos_gain[4][3] = 0x20;
+
+       ram_table->dark_pos_gain[0][0] = 0x00;
+       ram_table->dark_pos_gain[0][1] = 0x00;
+       ram_table->dark_pos_gain[0][2] = 0x00;
+       ram_table->dark_pos_gain[0][3] = 0x00;
+       ram_table->dark_pos_gain[1][0] = 0x00;
+       ram_table->dark_pos_gain[1][1] = 0x00;
+       ram_table->dark_pos_gain[1][2] = 0x00;
+       ram_table->dark_pos_gain[1][3] = 0x00;
+       ram_table->dark_pos_gain[2][0] = 0x00;
+       ram_table->dark_pos_gain[2][1] = 0x00;
+       ram_table->dark_pos_gain[2][2] = 0x00;
+       ram_table->dark_pos_gain[2][3] = 0x00;
+       ram_table->dark_pos_gain[3][0] = 0x00;
+       ram_table->dark_pos_gain[3][1] = 0x00;
+       ram_table->dark_pos_gain[3][2] = 0x00;
+       ram_table->dark_pos_gain[3][3] = 0x00;
+       ram_table->dark_pos_gain[4][0] = 0x00;
+       ram_table->dark_pos_gain[4][1] = 0x00;
+       ram_table->dark_pos_gain[4][2] = 0x00;
+       ram_table->dark_pos_gain[4][3] = 0x00;
+
+       ram_table->hybridFactor[0] = 0xff;
+       ram_table->hybridFactor[1] = 0xff;
+       ram_table->hybridFactor[2] = 0xff;
+       ram_table->hybridFactor[3] = 0xc0;
+
+       ram_table->contrastFactor[0] = 0x99;
+       ram_table->contrastFactor[1] = 0x99;
+       ram_table->contrastFactor[2] = 0x99;
+       ram_table->contrastFactor[3] = 0x80;
+
+       ram_table->iir_curve[0] = 0x65;
+       ram_table->iir_curve[1] = 0x65;
+       ram_table->iir_curve[2] = 0x65;
+       ram_table->iir_curve[3] = 0x65;
+       ram_table->iir_curve[4] = 0x65;
+
+       //Gamma 2.2
+       ram_table->crgb_thresh[0] = cpu_to_be16(0x127c);
+       ram_table->crgb_thresh[1] = cpu_to_be16(0x151b);
+       ram_table->crgb_thresh[2] = cpu_to_be16(0x17d5);
+       ram_table->crgb_thresh[3] = cpu_to_be16(0x1a56);
+       ram_table->crgb_thresh[4] = cpu_to_be16(0x1c83);
+       ram_table->crgb_thresh[5] = cpu_to_be16(0x1e72);
+       ram_table->crgb_thresh[6] = cpu_to_be16(0x20f0);
+       ram_table->crgb_thresh[7] = cpu_to_be16(0x232b);
+       ram_table->crgb_offset[0] = cpu_to_be16(0x2999);
+       ram_table->crgb_offset[1] = cpu_to_be16(0x3999);
+       ram_table->crgb_offset[2] = cpu_to_be16(0x4666);
+       ram_table->crgb_offset[3] = cpu_to_be16(0x5999);
+       ram_table->crgb_offset[4] = cpu_to_be16(0x6333);
+       ram_table->crgb_offset[5] = cpu_to_be16(0x7800);
+       ram_table->crgb_offset[6] = cpu_to_be16(0x8c00);
+       ram_table->crgb_offset[7] = cpu_to_be16(0xa000);
+       ram_table->crgb_slope[0]  = cpu_to_be16(0x3609);
+       ram_table->crgb_slope[1]  = cpu_to_be16(0x2dfa);
+       ram_table->crgb_slope[2]  = cpu_to_be16(0x27ea);
+       ram_table->crgb_slope[3]  = cpu_to_be16(0x235d);
+       ram_table->crgb_slope[4]  = cpu_to_be16(0x2042);
+       ram_table->crgb_slope[5]  = cpu_to_be16(0x1dc3);
+       ram_table->crgb_slope[6]  = cpu_to_be16(0x1b1a);
+       ram_table->crgb_slope[7]  = cpu_to_be16(0x1910);
+
+       fill_backlight_transform_table_v_2_2(
+                       params, ram_table);
+}
+
 bool dmcu_load_iram(struct dmcu *dmcu,
        struct dmcu_iram_parameters params)
 {
-       struct iram_table_v_2 ram_table;
-       unsigned int set = params.set;
+       unsigned char ram_table[IRAM_SIZE];
 
        if (dmcu == NULL)
                return false;
@@ -157,170 +570,12 @@ bool dmcu_load_iram(struct dmcu *dmcu,
 
        memset(&ram_table, 0, sizeof(ram_table));
 
-       ram_table.flags = 0x0;
-       ram_table.deviation_gain = 0xb3;
-
-       ram_table.blRampReduction =
-               cpu_to_be16(params.backlight_ramping_reduction);
-       ram_table.blRampStart =
-               cpu_to_be16(params.backlight_ramping_start);
-
-       ram_table.min_reduction[0][0] = min_reduction_table[abm_config[set][0]];
-       ram_table.min_reduction[1][0] = min_reduction_table[abm_config[set][0]];
-       ram_table.min_reduction[2][0] = min_reduction_table[abm_config[set][0]];
-       ram_table.min_reduction[3][0] = min_reduction_table[abm_config[set][0]];
-       ram_table.min_reduction[4][0] = min_reduction_table[abm_config[set][0]];
-       ram_table.max_reduction[0][0] = max_reduction_table[abm_config[set][0]];
-       ram_table.max_reduction[1][0] = max_reduction_table[abm_config[set][0]];
-       ram_table.max_reduction[2][0] = max_reduction_table[abm_config[set][0]];
-       ram_table.max_reduction[3][0] = max_reduction_table[abm_config[set][0]];
-       ram_table.max_reduction[4][0] = max_reduction_table[abm_config[set][0]];
-
-       ram_table.min_reduction[0][1] = min_reduction_table[abm_config[set][1]];
-       ram_table.min_reduction[1][1] = min_reduction_table[abm_config[set][1]];
-       ram_table.min_reduction[2][1] = min_reduction_table[abm_config[set][1]];
-       ram_table.min_reduction[3][1] = min_reduction_table[abm_config[set][1]];
-       ram_table.min_reduction[4][1] = min_reduction_table[abm_config[set][1]];
-       ram_table.max_reduction[0][1] = max_reduction_table[abm_config[set][1]];
-       ram_table.max_reduction[1][1] = max_reduction_table[abm_config[set][1]];
-       ram_table.max_reduction[2][1] = max_reduction_table[abm_config[set][1]];
-       ram_table.max_reduction[3][1] = max_reduction_table[abm_config[set][1]];
-       ram_table.max_reduction[4][1] = max_reduction_table[abm_config[set][1]];
-
-       ram_table.min_reduction[0][2] = min_reduction_table[abm_config[set][2]];
-       ram_table.min_reduction[1][2] = min_reduction_table[abm_config[set][2]];
-       ram_table.min_reduction[2][2] = min_reduction_table[abm_config[set][2]];
-       ram_table.min_reduction[3][2] = min_reduction_table[abm_config[set][2]];
-       ram_table.min_reduction[4][2] = min_reduction_table[abm_config[set][2]];
-       ram_table.max_reduction[0][2] = max_reduction_table[abm_config[set][2]];
-       ram_table.max_reduction[1][2] = max_reduction_table[abm_config[set][2]];
-       ram_table.max_reduction[2][2] = max_reduction_table[abm_config[set][2]];
-       ram_table.max_reduction[3][2] = max_reduction_table[abm_config[set][2]];
-       ram_table.max_reduction[4][2] = max_reduction_table[abm_config[set][2]];
-
-       ram_table.min_reduction[0][3] = min_reduction_table[abm_config[set][3]];
-       ram_table.min_reduction[1][3] = min_reduction_table[abm_config[set][3]];
-       ram_table.min_reduction[2][3] = min_reduction_table[abm_config[set][3]];
-       ram_table.min_reduction[3][3] = min_reduction_table[abm_config[set][3]];
-       ram_table.min_reduction[4][3] = min_reduction_table[abm_config[set][3]];
-       ram_table.max_reduction[0][3] = max_reduction_table[abm_config[set][3]];
-       ram_table.max_reduction[1][3] = max_reduction_table[abm_config[set][3]];
-       ram_table.max_reduction[2][3] = max_reduction_table[abm_config[set][3]];
-       ram_table.max_reduction[3][3] = max_reduction_table[abm_config[set][3]];
-       ram_table.max_reduction[4][3] = max_reduction_table[abm_config[set][3]];
-
-       ram_table.bright_pos_gain[0][0] = 0x20;
-       ram_table.bright_pos_gain[0][1] = 0x20;
-       ram_table.bright_pos_gain[0][2] = 0x20;
-       ram_table.bright_pos_gain[0][3] = 0x20;
-       ram_table.bright_pos_gain[1][0] = 0x20;
-       ram_table.bright_pos_gain[1][1] = 0x20;
-       ram_table.bright_pos_gain[1][2] = 0x20;
-       ram_table.bright_pos_gain[1][3] = 0x20;
-       ram_table.bright_pos_gain[2][0] = 0x20;
-       ram_table.bright_pos_gain[2][1] = 0x20;
-       ram_table.bright_pos_gain[2][2] = 0x20;
-       ram_table.bright_pos_gain[2][3] = 0x20;
-       ram_table.bright_pos_gain[3][0] = 0x20;
-       ram_table.bright_pos_gain[3][1] = 0x20;
-       ram_table.bright_pos_gain[3][2] = 0x20;
-       ram_table.bright_pos_gain[3][3] = 0x20;
-       ram_table.bright_pos_gain[4][0] = 0x20;
-       ram_table.bright_pos_gain[4][1] = 0x20;
-       ram_table.bright_pos_gain[4][2] = 0x20;
-       ram_table.bright_pos_gain[4][3] = 0x20;
-       ram_table.bright_neg_gain[0][1] = 0x00;
-       ram_table.bright_neg_gain[0][2] = 0x00;
-       ram_table.bright_neg_gain[0][3] = 0x00;
-       ram_table.bright_neg_gain[1][0] = 0x00;
-       ram_table.bright_neg_gain[1][1] = 0x00;
-       ram_table.bright_neg_gain[1][2] = 0x00;
-       ram_table.bright_neg_gain[1][3] = 0x00;
-       ram_table.bright_neg_gain[2][0] = 0x00;
-       ram_table.bright_neg_gain[2][1] = 0x00;
-       ram_table.bright_neg_gain[2][2] = 0x00;
-       ram_table.bright_neg_gain[2][3] = 0x00;
-       ram_table.bright_neg_gain[3][0] = 0x00;
-       ram_table.bright_neg_gain[3][1] = 0x00;
-       ram_table.bright_neg_gain[3][2] = 0x00;
-       ram_table.bright_neg_gain[3][3] = 0x00;
-       ram_table.bright_neg_gain[4][0] = 0x00;
-       ram_table.bright_neg_gain[4][1] = 0x00;
-       ram_table.bright_neg_gain[4][2] = 0x00;
-       ram_table.bright_neg_gain[4][3] = 0x00;
-       ram_table.dark_pos_gain[0][0] = 0x00;
-       ram_table.dark_pos_gain[0][1] = 0x00;
-       ram_table.dark_pos_gain[0][2] = 0x00;
-       ram_table.dark_pos_gain[0][3] = 0x00;
-       ram_table.dark_pos_gain[1][0] = 0x00;
-       ram_table.dark_pos_gain[1][1] = 0x00;
-       ram_table.dark_pos_gain[1][2] = 0x00;
-       ram_table.dark_pos_gain[1][3] = 0x00;
-       ram_table.dark_pos_gain[2][0] = 0x00;
-       ram_table.dark_pos_gain[2][1] = 0x00;
-       ram_table.dark_pos_gain[2][2] = 0x00;
-       ram_table.dark_pos_gain[2][3] = 0x00;
-       ram_table.dark_pos_gain[3][0] = 0x00;
-       ram_table.dark_pos_gain[3][1] = 0x00;
-       ram_table.dark_pos_gain[3][2] = 0x00;
-       ram_table.dark_pos_gain[3][3] = 0x00;
-       ram_table.dark_pos_gain[4][0] = 0x00;
-       ram_table.dark_pos_gain[4][1] = 0x00;
-       ram_table.dark_pos_gain[4][2] = 0x00;
-       ram_table.dark_pos_gain[4][3] = 0x00;
-       ram_table.dark_neg_gain[0][0] = 0x00;
-       ram_table.dark_neg_gain[0][1] = 0x00;
-       ram_table.dark_neg_gain[0][2] = 0x00;
-       ram_table.dark_neg_gain[0][3] = 0x00;
-       ram_table.dark_neg_gain[1][0] = 0x00;
-       ram_table.dark_neg_gain[1][1] = 0x00;
-       ram_table.dark_neg_gain[1][2] = 0x00;
-       ram_table.dark_neg_gain[1][3] = 0x00;
-       ram_table.dark_neg_gain[2][0] = 0x00;
-       ram_table.dark_neg_gain[2][1] = 0x00;
-       ram_table.dark_neg_gain[2][2] = 0x00;
-       ram_table.dark_neg_gain[2][3] = 0x00;
-       ram_table.dark_neg_gain[3][0] = 0x00;
-       ram_table.dark_neg_gain[3][1] = 0x00;
-       ram_table.dark_neg_gain[3][2] = 0x00;
-       ram_table.dark_neg_gain[3][3] = 0x00;
-       ram_table.dark_neg_gain[4][0] = 0x00;
-       ram_table.dark_neg_gain[4][1] = 0x00;
-       ram_table.dark_neg_gain[4][2] = 0x00;
-       ram_table.dark_neg_gain[4][3] = 0x00;
-       ram_table.iir_curve[0] = 0x65;
-       ram_table.iir_curve[1] = 0x65;
-       ram_table.iir_curve[2] = 0x65;
-       ram_table.iir_curve[3] = 0x65;
-       ram_table.iir_curve[4] = 0x65;
-       ram_table.crgb_thresh[0] = cpu_to_be16(0x13b6);
-       ram_table.crgb_thresh[1] = cpu_to_be16(0x1648);
-       ram_table.crgb_thresh[2] = cpu_to_be16(0x18e3);
-       ram_table.crgb_thresh[3] = cpu_to_be16(0x1b41);
-       ram_table.crgb_thresh[4] = cpu_to_be16(0x1d46);
-       ram_table.crgb_thresh[5] = cpu_to_be16(0x1f21);
-       ram_table.crgb_thresh[6] = cpu_to_be16(0x2167);
-       ram_table.crgb_thresh[7] = cpu_to_be16(0x2384);
-       ram_table.crgb_offset[0] = cpu_to_be16(0x2999);
-       ram_table.crgb_offset[1] = cpu_to_be16(0x3999);
-       ram_table.crgb_offset[2] = cpu_to_be16(0x4666);
-       ram_table.crgb_offset[3] = cpu_to_be16(0x5999);
-       ram_table.crgb_offset[4] = cpu_to_be16(0x6333);
-       ram_table.crgb_offset[5] = cpu_to_be16(0x7800);
-       ram_table.crgb_offset[6] = cpu_to_be16(0x8c00);
-       ram_table.crgb_offset[7] = cpu_to_be16(0xa000);
-       ram_table.crgb_slope[0]  = cpu_to_be16(0x3147);
-       ram_table.crgb_slope[1]  = cpu_to_be16(0x2978);
-       ram_table.crgb_slope[2]  = cpu_to_be16(0x23a2);
-       ram_table.crgb_slope[3]  = cpu_to_be16(0x1f55);
-       ram_table.crgb_slope[4]  = cpu_to_be16(0x1c63);
-       ram_table.crgb_slope[5]  = cpu_to_be16(0x1a0f);
-       ram_table.crgb_slope[6]  = cpu_to_be16(0x178d);
-       ram_table.crgb_slope[7]  = cpu_to_be16(0x15ab);
-
-       fill_backlight_transform_table(
-                       params, &ram_table);
+       if (dmcu->dmcu_version.abm_version == 0x22) {
+               fill_iram_v_2_2((struct iram_table_v_2_2 *)ram_table, params);
+       } else {
+               fill_iram_v_2((struct iram_table_v_2 *)ram_table, params);
+       }
 
        return dmcu->funcs->load_iram(
-                       dmcu, 0, (char *)(&ram_table), sizeof(ram_table));
+                       dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START);
 }
index 13d4de645190fe8b54391e348a1f89cc6b990364..d8e0dd192fdd6a55b535b6b7fcd7a641880bc665 100644 (file)
 
 // addressBlock: nbio_nbif_rcc_strap_BIFDEC1[13440..14975]
 // base address: 0x3480
+#define mmRCC_BIF_STRAP0                                                                               0x0000
+#define mmRCC_BIF_STRAP0_BASE_IDX                                                                      2
 #define mmRCC_DEV0_EPF0_STRAP0                                                                         0x000f
 #define mmRCC_DEV0_EPF0_STRAP0_BASE_IDX                                                                2
 
index a02b6794337286bc12c907c33d5d75537c240bd0..29af5167cd0057fcfbfab150378322008d3d2667 100644 (file)
 
 
 // addressBlock: nbio_nbif_rcc_strap_BIFDEC1[13440..14975]
+//RCC_BIF_STRAP0
+#define RCC_BIF_STRAP0__STRAP_PX_CAPABLE__SHIFT                                                               0x7
+#define RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK                                                                 0x00000080L
+
 //RCC_DEV0_EPF0_STRAP0
 #define RCC_DEV0_EPF0_STRAP0__STRAP_DEVICE_ID_DEV0_F0__SHIFT                                                  0x0
 #define RCC_DEV0_EPF0_STRAP0__STRAP_MAJOR_REV_ID_DEV0_F0__SHIFT                                               0x10
diff --git a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_6_1_smn.h b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_6_1_smn.h
new file mode 100644 (file)
index 0000000..8c75669
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019  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 _nbio_6_1_SMN_HEADER
+#define _nbio_6_1_SMN_HEADER
+
+
+#define smnCPM_CONTROL                                 0x11180460
+#define smnPCIE_CNTL2                                  0x11180070
+#define smnPCIE_CONFIG_CNTL                            0x11180044
+#define smnPCIE_CI_CNTL                                        0x11180080
+
+
+#define smnPCIE_PERF_COUNT_CNTL                                0x11180200
+#define smnPCIE_PERF_CNTL_TXCLK                                0x11180204
+#define smnPCIE_PERF_COUNT0_TXCLK                      0x11180208
+#define smnPCIE_PERF_COUNT1_TXCLK                      0x1118020c
+#define smnPCIE_PERF_CNTL_MST_R_CLK                    0x11180210
+#define smnPCIE_PERF_COUNT0_MST_R_CLK                  0x11180214
+#define smnPCIE_PERF_COUNT1_MST_R_CLK                  0x11180218
+#define smnPCIE_PERF_CNTL_MST_C_CLK                    0x1118021c
+#define smnPCIE_PERF_COUNT0_MST_C_CLK                  0x11180220
+#define smnPCIE_PERF_COUNT1_MST_C_CLK                  0x11180224
+#define smnPCIE_PERF_CNTL_SLV_R_CLK                    0x11180228
+#define smnPCIE_PERF_COUNT0_SLV_R_CLK                  0x1118022c
+#define smnPCIE_PERF_COUNT1_SLV_R_CLK                  0x11180230
+#define smnPCIE_PERF_CNTL_SLV_S_C_CLK                  0x11180234
+#define smnPCIE_PERF_COUNT0_SLV_S_C_CLK                        0x11180238
+#define smnPCIE_PERF_COUNT1_SLV_S_C_CLK                        0x1118023c
+#define smnPCIE_PERF_CNTL_SLV_NS_C_CLK                 0x11180240
+#define smnPCIE_PERF_COUNT0_SLV_NS_C_CLK               0x11180244
+#define smnPCIE_PERF_COUNT1_SLV_NS_C_CLK               0x11180248
+#define smnPCIE_PERF_CNTL_EVENT0_PORT_SEL              0x1118024c
+#define smnPCIE_PERF_CNTL_EVENT1_PORT_SEL              0x11180250
+#define smnPCIE_PERF_CNTL_TXCLK2                       0x11180254
+#define smnPCIE_PERF_COUNT0_TXCLK2                     0x11180258
+#define smnPCIE_PERF_COUNT1_TXCLK2                     0x1118025c
+
+#endif // _nbio_6_1_SMN_HEADER
+
diff --git a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_0_smn.h b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_0_smn.h
new file mode 100644 (file)
index 0000000..5563f07
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2019  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 _nbio_7_0_SMN_HEADER
+#define _nbio_7_0_SMN_HEADER
+
+
+#define smnCPM_CONTROL                                 0x11180460
+#define smnPCIE_CNTL2                                  0x11180070
+
+#define smnPCIE_PERF_COUNT_CNTL                                0x11180200
+#define smnPCIE_PERF_CNTL_TXCLK                                0x11180204
+#define smnPCIE_PERF_COUNT0_TXCLK                      0x11180208
+#define smnPCIE_PERF_COUNT1_TXCLK                      0x1118020c
+#define smnPCIE_PERF_CNTL_MST_R_CLK                    0x11180210
+#define smnPCIE_PERF_COUNT0_MST_R_CLK                  0x11180214
+#define smnPCIE_PERF_COUNT1_MST_R_CLK                  0x11180218
+#define smnPCIE_PERF_CNTL_MST_C_CLK                    0x1118021c
+#define smnPCIE_PERF_COUNT0_MST_C_CLK                  0x11180220
+#define smnPCIE_PERF_COUNT1_MST_C_CLK                  0x11180224
+#define smnPCIE_PERF_CNTL_SLV_R_CLK                    0x11180228
+#define smnPCIE_PERF_COUNT0_SLV_R_CLK                  0x1118022c
+#define smnPCIE_PERF_COUNT1_SLV_R_CLK                  0x11180230
+#define smnPCIE_PERF_CNTL_SLV_S_C_CLK                  0x11180234
+#define smnPCIE_PERF_COUNT0_SLV_S_C_CLK                        0x11180238
+#define smnPCIE_PERF_COUNT1_SLV_S_C_CLK                        0x1118023c
+#define smnPCIE_PERF_CNTL_SLV_NS_C_CLK                 0x11180240
+#define smnPCIE_PERF_COUNT0_SLV_NS_C_CLK               0x11180244
+#define smnPCIE_PERF_COUNT1_SLV_NS_C_CLK               0x11180248
+#define smnPCIE_PERF_CNTL_EVENT0_PORT_SEL              0x1118024c
+#define smnPCIE_PERF_CNTL_EVENT1_PORT_SEL              0x11180250
+#define smnPCIE_PERF_CNTL_TXCLK2                       0x11180254
+#define smnPCIE_PERF_COUNT0_TXCLK2                     0x11180258
+#define smnPCIE_PERF_COUNT1_TXCLK2                     0x1118025c
+
+#endif // _nbio_7_0_SMN_HEADER
diff --git a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_4_0_smn.h b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_4_0_smn.h
new file mode 100644 (file)
index 0000000..c1457d8
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019  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 _nbio_7_4_0_SMN_HEADER
+#define _nbio_7_4_0_SMN_HEADER
+
+
+#define smnNBIF_MGCG_CTRL_LCLK                         0x1013a21c
+#define smnCPM_CONTROL                                 0x11180460
+#define smnPCIE_CNTL2                                  0x11180070
+#define smnPCIE_CI_CNTL                                        0x11180080
+
+#define smnPCIE_PERF_COUNT_CNTL                                0x11180200
+#define smnPCIE_PERF_CNTL_TXCLK1                       0x11180204
+#define smnPCIE_PERF_COUNT0_TXCLK1                     0x11180208
+#define smnPCIE_PERF_COUNT1_TXCLK1                     0x1118020c
+#define smnPCIE_PERF_CNTL_TXCLK2                       0x11180210
+#define smnPCIE_PERF_COUNT0_TXCLK2                     0x11180214
+#define smnPCIE_PERF_COUNT1_TXCLK2                     0x11180218
+#define smnPCIE_PERF_CNTL_TXCLK3                       0x1118021c
+#define smnPCIE_PERF_COUNT0_TXCLK3                     0x11180220
+#define smnPCIE_PERF_COUNT1_TXCLK3                     0x11180224
+#define smnPCIE_PERF_CNTL_TXCLK4                       0x11180228
+#define smnPCIE_PERF_COUNT0_TXCLK4                     0x1118022c
+#define smnPCIE_PERF_COUNT1_TXCLK4                     0x11180230
+#define smnPCIE_PERF_CNTL_SCLK1                                0x11180234
+#define smnPCIE_PERF_COUNT0_SCLK1                      0x11180238
+#define smnPCIE_PERF_COUNT1_SCLK1                      0x1118023c
+#define smnPCIE_PERF_CNTL_SCLK2                                0x11180240
+#define smnPCIE_PERF_COUNT0_SCLK2                      0x11180244
+#define smnPCIE_PERF_COUNT1_SCLK2                      0x11180248
+#define smnPCIE_PERF_CNTL_EVENT_LC_PORT_SEL            0x1118024c
+#define smnPCIE_PERF_CNTL_EVENT_CI_PORT_SEL            0x11180250
+
+#endif // _nbio_7_4_0_SMN_HEADER
index e932213f87f0d99951c2948937018e4556001387..994e796a28d78fa5a20ccc88c120ce651c867cae 100644 (file)
 
 // addressBlock: nbio_nbif0_rcc_strap_BIFDEC1
 // base address: 0x0
+#define mmRCC_BIF_STRAP0                                                                               0x0000
+#define mmRCC_BIF_STRAP0_BASE_IDX                                                                      2
 #define mmRCC_DEV0_EPF0_STRAP0                                                                         0x0011
 #define mmRCC_DEV0_EPF0_STRAP0_BASE_IDX                                                                2
 
index d3704b438f2dbd870fb8a33ea005539355d57c0f..d467b939c97133789a357a9841e5560ec9cd7e48 100644 (file)
 
 
 // addressBlock: nbio_nbif0_rcc_strap_BIFDEC1
+//RCC_BIF_STRAP0
+#define RCC_BIF_STRAP0__STRAP_PX_CAPABLE__SHIFT                                                               0x7
+#define RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK                                                                 0x00000080L
 //RCC_DEV0_EPF0_STRAP0
 #define RCC_DEV0_EPF0_STRAP0__STRAP_DEVICE_ID_DEV0_F0__SHIFT                                                  0x0
 #define RCC_DEV0_EPF0_STRAP0__STRAP_MAJOR_REV_ID_DEV0_F0__SHIFT                                               0x10
index a9eb57a53e5927d5e74a5a687aa7c47e0c489e85..a485526f3a511ca44a8c6beba409d271d18f164e 100644 (file)
@@ -46,4 +46,7 @@
 #define mmTHM_TCON_THERM_TRIP                                                                          0x0002
 #define mmTHM_TCON_THERM_TRIP_BASE_IDX                                                                 0
 
+#define mmTHM_BACO_CNTL                                                                                0x0081
+#define mmTHM_BACO_CNTL_BASE_IDX                                                                       0
+
 #endif
index 7931502fa54fae8766ba40c1fd7f1f82468d16d4..8ba21747b40a3f1f792bfbb93c9f5ca013f8cc39 100644 (file)
@@ -4106,7 +4106,7 @@ typedef struct  _ATOM_LCD_MODE_CONTROL_CAP
 typedef struct _ATOM_FAKE_EDID_PATCH_RECORD
 {
   UCHAR ucRecordType;
-  UCHAR ucFakeEDIDLength;       // = 128 means EDID lenght is 128 bytes, otherwise the EDID length = ucFakeEDIDLength*128
+  UCHAR ucFakeEDIDLength;       // = 128 means EDID length is 128 bytes, otherwise the EDID length = ucFakeEDIDLength*128
   UCHAR ucFakeEDIDString[1];    // This actually has ucFakeEdidLength elements.
 } ATOM_FAKE_EDID_PATCH_RECORD;
 
index 8154d67388ccef99185431ce8d04b7b16af59762..83d960110d23e0a369e8895859d4197442ac47d3 100644 (file)
@@ -34,7 +34,6 @@
 
 struct pci_dev;
 
-#define KFD_INTERFACE_VERSION 2
 #define KGD_MAX_QUEUES 128
 
 struct kfd_dev;
@@ -330,56 +329,4 @@ struct kfd2kgd_calls {
 
 };
 
-/**
- * struct kgd2kfd_calls
- *
- * @exit: Notifies amdkfd that kgd module is unloaded
- *
- * @probe: Notifies amdkfd about a probe done on a device in the kgd driver.
- *
- * @device_init: Initialize the newly probed device (if it is a device that
- * amdkfd supports)
- *
- * @device_exit: Notifies amdkfd about a removal of a kgd device
- *
- * @suspend: Notifies amdkfd about a suspend action done to a kgd device
- *
- * @resume: Notifies amdkfd about a resume action done to a kgd device
- *
- * @quiesce_mm: Quiesce all user queue access to specified MM address space
- *
- * @resume_mm: Resume user queue access to specified MM address space
- *
- * @schedule_evict_and_restore_process: Schedules work queue that will prepare
- * for safe eviction of KFD BOs that belong to the specified process.
- *
- * @pre_reset: Notifies amdkfd that amdgpu about to reset the gpu
- *
- * @post_reset: Notify amdkfd that amgpu successfully reseted the gpu
- *
- * This structure contains function callback pointers so the kgd driver
- * will notify to the amdkfd about certain status changes.
- *
- */
-struct kgd2kfd_calls {
-       void (*exit)(void);
-       struct kfd_dev* (*probe)(struct kgd_dev *kgd, struct pci_dev *pdev,
-               const struct kfd2kgd_calls *f2g);
-       bool (*device_init)(struct kfd_dev *kfd,
-                       const struct kgd2kfd_shared_resources *gpu_resources);
-       void (*device_exit)(struct kfd_dev *kfd);
-       void (*interrupt)(struct kfd_dev *kfd, const void *ih_ring_entry);
-       void (*suspend)(struct kfd_dev *kfd);
-       int (*resume)(struct kfd_dev *kfd);
-       int (*quiesce_mm)(struct mm_struct *mm);
-       int (*resume_mm)(struct mm_struct *mm);
-       int (*schedule_evict_and_restore_process)(struct mm_struct *mm,
-                       struct dma_fence *fence);
-       int  (*pre_reset)(struct kfd_dev *kfd);
-       int  (*post_reset)(struct kfd_dev *kfd);
-};
-
-int kgd2kfd_init(unsigned interface_version,
-               const struct kgd2kfd_calls **g2f);
-
 #endif /* KGD_KFD_INTERFACE_H_INCLUDED */
index 1479ea1dc3e7166fe96c7e759bf06c33aaba2683..2b579ba9b68552f81f7a2a3223e3563ae20bc9ee 100644 (file)
@@ -92,6 +92,9 @@ enum pp_clock_type {
        PP_SCLK,
        PP_MCLK,
        PP_PCIE,
+       PP_SOCCLK,
+       PP_FCLK,
+       PP_DCEFCLK,
        OD_SCLK,
        OD_MCLK,
        OD_VDDC_CURVE,
@@ -127,12 +130,13 @@ enum amd_pp_task {
 };
 
 enum PP_SMC_POWER_PROFILE {
-       PP_SMC_POWER_PROFILE_FULLSCREEN3D = 0x0,
-       PP_SMC_POWER_PROFILE_POWERSAVING  = 0x1,
-       PP_SMC_POWER_PROFILE_VIDEO        = 0x2,
-       PP_SMC_POWER_PROFILE_VR           = 0x3,
-       PP_SMC_POWER_PROFILE_COMPUTE      = 0x4,
-       PP_SMC_POWER_PROFILE_CUSTOM       = 0x5,
+       PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT = 0x0,
+       PP_SMC_POWER_PROFILE_FULLSCREEN3D = 0x1,
+       PP_SMC_POWER_PROFILE_POWERSAVING  = 0x2,
+       PP_SMC_POWER_PROFILE_VIDEO        = 0x3,
+       PP_SMC_POWER_PROFILE_VR           = 0x4,
+       PP_SMC_POWER_PROFILE_COMPUTE      = 0x5,
+       PP_SMC_POWER_PROFILE_CUSTOM       = 0x6,
 };
 
 enum {
@@ -280,6 +284,11 @@ struct amd_pm_funcs {
        int (*set_hard_min_dcefclk_by_freq)(void *handle, uint32_t clock);
        int (*set_hard_min_fclk_by_freq)(void *handle, uint32_t clock);
        int (*set_min_deep_sleep_dcefclk)(void *handle, uint32_t clock);
+       int (*get_asic_baco_capability)(void *handle, bool *cap);
+       int (*get_asic_baco_state)(void *handle, int *state);
+       int (*set_asic_baco_state)(void *handle, int state);
+       int (*get_ppfeature_status)(void *handle, char *buf);
+       int (*set_ppfeature_status)(void *handle, uint64_t ppfeature_masks);
 };
 
 #endif
index 9bc27f468d5be578fe4f014d1439698703eb4972..3f73f7cd18b97673e62bcfa0105e325f4f7ef4e6 100644 (file)
@@ -1404,6 +1404,97 @@ static int pp_set_active_display_count(void *handle, uint32_t count)
        return ret;
 }
 
+static int pp_get_asic_baco_capability(void *handle, bool *cap)
+{
+       struct pp_hwmgr *hwmgr = handle;
+
+       if (!hwmgr)
+               return -EINVAL;
+
+       if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_asic_baco_capability)
+               return 0;
+
+       mutex_lock(&hwmgr->smu_lock);
+       hwmgr->hwmgr_func->get_asic_baco_capability(hwmgr, cap);
+       mutex_unlock(&hwmgr->smu_lock);
+
+       return 0;
+}
+
+static int pp_get_asic_baco_state(void *handle, int *state)
+{
+       struct pp_hwmgr *hwmgr = handle;
+
+       if (!hwmgr)
+               return -EINVAL;
+
+       if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_asic_baco_state)
+               return 0;
+
+       mutex_lock(&hwmgr->smu_lock);
+       hwmgr->hwmgr_func->get_asic_baco_state(hwmgr, (enum BACO_STATE *)state);
+       mutex_unlock(&hwmgr->smu_lock);
+
+       return 0;
+}
+
+static int pp_set_asic_baco_state(void *handle, int state)
+{
+       struct pp_hwmgr *hwmgr = handle;
+
+       if (!hwmgr)
+               return -EINVAL;
+
+       if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_asic_baco_state)
+               return 0;
+
+       mutex_lock(&hwmgr->smu_lock);
+       hwmgr->hwmgr_func->set_asic_baco_state(hwmgr, (enum BACO_STATE)state);
+       mutex_unlock(&hwmgr->smu_lock);
+
+       return 0;
+}
+
+static int pp_get_ppfeature_status(void *handle, char *buf)
+{
+       struct pp_hwmgr *hwmgr = handle;
+       int ret = 0;
+
+       if (!hwmgr || !hwmgr->pm_en || !buf)
+               return -EINVAL;
+
+       if (hwmgr->hwmgr_func->get_ppfeature_status == NULL) {
+               pr_info_ratelimited("%s was not implemented.\n", __func__);
+               return -EINVAL;
+       }
+
+       mutex_lock(&hwmgr->smu_lock);
+       ret = hwmgr->hwmgr_func->get_ppfeature_status(hwmgr, buf);
+       mutex_unlock(&hwmgr->smu_lock);
+
+       return ret;
+}
+
+static int pp_set_ppfeature_status(void *handle, uint64_t ppfeature_masks)
+{
+       struct pp_hwmgr *hwmgr = handle;
+       int ret = 0;
+
+       if (!hwmgr || !hwmgr->pm_en)
+               return -EINVAL;
+
+       if (hwmgr->hwmgr_func->set_ppfeature_status == NULL) {
+               pr_info_ratelimited("%s was not implemented.\n", __func__);
+               return -EINVAL;
+       }
+
+       mutex_lock(&hwmgr->smu_lock);
+       ret = hwmgr->hwmgr_func->set_ppfeature_status(hwmgr, ppfeature_masks);
+       mutex_unlock(&hwmgr->smu_lock);
+
+       return ret;
+}
+
 static const struct amd_pm_funcs pp_dpm_funcs = {
        .load_firmware = pp_dpm_load_fw,
        .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
@@ -1454,4 +1545,9 @@ static const struct amd_pm_funcs pp_dpm_funcs = {
        .set_min_deep_sleep_dcefclk = pp_set_min_deep_sleep_dcefclk,
        .set_hard_min_dcefclk_by_freq = pp_set_hard_min_dcefclk_by_freq,
        .set_hard_min_fclk_by_freq = pp_set_hard_min_fclk_by_freq,
+       .get_asic_baco_capability = pp_get_asic_baco_capability,
+       .get_asic_baco_state = pp_get_asic_baco_state,
+       .set_asic_baco_state = pp_set_asic_baco_state,
+       .get_ppfeature_status = pp_get_ppfeature_status,
+       .set_ppfeature_status = pp_set_ppfeature_status,
 };
index ade8973b6f4d6307f0a3562f00224afd48ad4eb7..0b3c6d1d52e4a7d44ff0954d706e8d60bb809af1 100644 (file)
@@ -35,7 +35,7 @@ HARDWARE_MGR = hwmgr.o processpptables.o \
                vega12_thermal.o \
                pp_overdriver.o smu_helper.o \
                vega20_processpptables.o vega20_hwmgr.o vega20_powertune.o \
-               vega20_thermal.o
+               vega20_thermal.o common_baco.o vega10_baco.o  vega20_baco.o
 
 AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR))
 
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.c b/drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.c
new file mode 100644 (file)
index 0000000..9c57c1f
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2018 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 "common_baco.h"
+
+
+static bool baco_wait_register(struct pp_hwmgr *hwmgr, u32 reg, u32 mask, u32 value)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
+       u32 timeout = 5000, data;
+
+       do {
+               msleep(1);
+               data = RREG32(reg);
+               timeout--;
+       } while (value != (data & mask) && (timeout != 0));
+
+       if (timeout == 0)
+               return false;
+
+       return true;
+}
+
+static bool baco_cmd_handler(struct pp_hwmgr *hwmgr, u32 command, u32 reg, u32 mask,
+                               u32 shift, u32 value, u32 timeout)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
+       u32 data;
+       bool ret = true;
+
+       switch (command) {
+       case CMD_WRITE:
+               WREG32(reg, value << shift);
+               break;
+       case CMD_READMODIFYWRITE:
+               data = RREG32(reg);
+               data = (data & (~mask)) | (value << shift);
+               WREG32(reg, data);
+               break;
+       case CMD_WAITFOR:
+               ret = baco_wait_register(hwmgr, reg, mask, value);
+               break;
+       case CMD_DELAY_MS:
+               if (timeout)
+                       /* Delay in milli Seconds */
+                       msleep(timeout);
+               break;
+       case CMD_DELAY_US:
+               if (timeout)
+                       /* Delay in micro Seconds */
+                       udelay(timeout);
+               break;
+
+       default:
+               dev_warn(adev->dev, "Invalid BACO command.\n");
+               ret = false;
+       }
+
+       return ret;
+}
+
+bool soc15_baco_program_registers(struct pp_hwmgr *hwmgr,
+                                const struct soc15_baco_cmd_entry *entry,
+                                const u32 array_size)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
+       u32 i, reg = 0;
+
+       for (i = 0; i < array_size; i++) {
+               if ((entry[i].cmd == CMD_WRITE) ||
+                   (entry[i].cmd == CMD_READMODIFYWRITE) ||
+                   (entry[i].cmd == CMD_WAITFOR))
+                       reg = adev->reg_offset[entry[i].hwip][entry[i].inst][entry[i].seg]
+                               + entry[i].reg_offset;
+               if (!baco_cmd_handler(hwmgr, entry[i].cmd, reg, entry[i].mask,
+                                    entry[i].shift, entry[i].val, entry[i].timeout))
+                       return false;
+       }
+
+       return true;
+}
similarity index 65%
rename from drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.h
rename to drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.h
index 26355c0887460fddec0a08c322a4a383f33607b3..95296c916f4e9c1fd9bd86067a287424b0888e1a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
+ * Copyright 2018 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"),
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
  *
- * Authors: AMD
- *
  */
+#ifndef __COMMON_BOCO_H__
+#define __COMMON_BOCO_H__
+#include "hwmgr.h"
 
-#ifndef __DAL_I2C_SW_ENGINE_DCE80_H__
-#define __DAL_I2C_SW_ENGINE_DCE80_H__
 
-struct i2c_sw_engine_dce80 {
-       struct i2c_sw_engine base;
-       uint32_t engine_id;
+enum baco_cmd_type {
+       CMD_WRITE = 0,
+       CMD_READMODIFYWRITE,
+       CMD_WAITFOR,
+       CMD_DELAY_MS,
+       CMD_DELAY_US,
 };
 
-struct i2c_sw_engine_dce80_create_arg {
-       uint32_t engine_id;
-       uint32_t default_speed;
-       struct dc_context *ctx;
+struct soc15_baco_cmd_entry {
+       enum baco_cmd_type cmd;
+       uint32_t        hwip;
+       uint32_t        inst;
+       uint32_t        seg;
+       uint32_t        reg_offset;
+       uint32_t        mask;
+       uint32_t        shift;
+       uint32_t        timeout;
+       uint32_t        val;
 };
-
-struct i2c_engine *dal_i2c_sw_engine_dce80_create(
-       const struct i2c_sw_engine_dce80_create_arg *arg);
-
+extern bool soc15_baco_program_registers(struct pp_hwmgr *hwmgr,
+                                       const struct soc15_baco_cmd_entry *entry,
+                                       const u32 array_size);
 #endif
index 1f92a9f4c9e3414e756ed181947ac97f5a9f9611..c1c51c115e57a660c050bc53fb9b025e62212321 100644 (file)
@@ -154,15 +154,6 @@ int phm_powerdown_uvd(struct pp_hwmgr *hwmgr)
        return 0;
 }
 
-int phm_enable_clock_power_gatings(struct pp_hwmgr *hwmgr)
-{
-       PHM_FUNC_CHECK(hwmgr);
-
-       if (NULL != hwmgr->hwmgr_func->enable_clock_power_gating)
-               return hwmgr->hwmgr_func->enable_clock_power_gating(hwmgr);
-
-       return 0;
-}
 
 int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr)
 {
index 0173d04800245b44f88f1f80e8dc3cb50df3bd2c..6cd6497c6fc21d3e935c4274de9d31048de2ee9f 100644 (file)
@@ -64,17 +64,19 @@ static int ci_set_asic_special_caps(struct pp_hwmgr *hwmgr);
 
 static void hwmgr_init_workload_prority(struct pp_hwmgr *hwmgr)
 {
-       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 2;
-       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 0;
-       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 1;
-       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VR] = 3;
-       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 4;
-
-       hwmgr->workload_setting[0] = PP_SMC_POWER_PROFILE_POWERSAVING;
-       hwmgr->workload_setting[1] = PP_SMC_POWER_PROFILE_VIDEO;
-       hwmgr->workload_setting[2] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
-       hwmgr->workload_setting[3] = PP_SMC_POWER_PROFILE_VR;
-       hwmgr->workload_setting[4] = PP_SMC_POWER_PROFILE_COMPUTE;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VR] = 4;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
+
+       hwmgr->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+       hwmgr->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
+       hwmgr->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING;
+       hwmgr->workload_setting[3] = PP_SMC_POWER_PROFILE_VIDEO;
+       hwmgr->workload_setting[4] = PP_SMC_POWER_PROFILE_VR;
+       hwmgr->workload_setting[5] = PP_SMC_POWER_PROFILE_COMPUTE;
 }
 
 int hwmgr_early_init(struct pp_hwmgr *hwmgr)
@@ -271,7 +273,7 @@ int hwmgr_hw_fini(struct pp_hwmgr *hwmgr)
 
        phm_stop_thermal_controller(hwmgr);
        psm_set_boot_states(hwmgr);
-       psm_adjust_power_state_dynamic(hwmgr, false, NULL);
+       psm_adjust_power_state_dynamic(hwmgr, true, NULL);
        phm_disable_dynamic_state_management(hwmgr);
        phm_disable_clock_power_gatings(hwmgr);
 
@@ -293,7 +295,7 @@ int hwmgr_suspend(struct pp_hwmgr *hwmgr)
        ret = psm_set_boot_states(hwmgr);
        if (ret)
                return ret;
-       ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL);
+       ret = psm_adjust_power_state_dynamic(hwmgr, true, NULL);
        if (ret)
                return ret;
        ret = phm_power_down_asic(hwmgr);
@@ -323,7 +325,7 @@ int hwmgr_resume(struct pp_hwmgr *hwmgr)
        if (ret)
                return ret;
 
-       ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL);
+       ret = psm_adjust_power_state_dynamic(hwmgr, true, NULL);
 
        return ret;
 }
@@ -377,12 +379,12 @@ int hwmgr_handle_task(struct pp_hwmgr *hwmgr, enum amd_pp_task task_id,
                ret = psm_set_user_performance_state(hwmgr, requested_ui_label, &requested_ps);
                if (ret)
                        return ret;
-               ret = psm_adjust_power_state_dynamic(hwmgr, false, requested_ps);
+               ret = psm_adjust_power_state_dynamic(hwmgr, true, requested_ps);
                break;
        }
        case AMD_PP_TASK_COMPLETE_INIT:
        case AMD_PP_TASK_READJUST_POWER_STATE:
-               ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL);
+               ret = psm_adjust_power_state_dynamic(hwmgr, true, NULL);
                break;
        default:
                break;
index 56437866d1206c163f36593e2764bfb6bfd96170..ce177d7f04cbe9ad930d01650a5ede1995e9a135 100644 (file)
@@ -256,16 +256,14 @@ static void power_state_management(struct pp_hwmgr *hwmgr,
        }
 }
 
-int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip,
+int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip_display_settings,
                                                struct pp_power_state *new_ps)
 {
        uint32_t index;
        long workload;
 
-       if (skip)
-               return 0;
-
-       phm_display_configuration_changed(hwmgr);
+       if (!skip_display_settings)
+               phm_display_configuration_changed(hwmgr);
 
        if (hwmgr->ps)
                power_state_management(hwmgr, new_ps);
@@ -276,9 +274,11 @@ int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip,
                 */
                phm_apply_clock_adjust_rules(hwmgr);
 
-       phm_notify_smc_display_config_after_ps_adjustment(hwmgr);
+       if (!skip_display_settings)
+               phm_notify_smc_display_config_after_ps_adjustment(hwmgr);
 
-       if (!phm_force_dpm_levels(hwmgr, hwmgr->request_dpm_level))
+       if ((hwmgr->request_dpm_level != hwmgr->dpm_level) &&
+           !phm_force_dpm_levels(hwmgr, hwmgr->request_dpm_level))
                hwmgr->dpm_level = hwmgr->request_dpm_level;
 
        if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
index fa1b6825036a1c2ad45bfaa577ca40de46a0230f..b62d55f1f28959c0a87fb680f544c2e69db469b8 100644 (file)
@@ -34,7 +34,7 @@ int psm_set_user_performance_state(struct pp_hwmgr *hwmgr,
                                        enum PP_StateUILabel label_id,
                                        struct pp_power_state **state);
 int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr,
-                               bool skip,
+                               bool skip_display_settings,
                                struct pp_power_state *new_ps);
 
 #endif
index d913904593267439c78824149e40dc64d5d32eb4..c8f5c00dd1e775e40e2d986dcfc167b76e6927df 100644 (file)
@@ -77,8 +77,9 @@
 #define PCIE_BUS_CLK                10000
 #define TCLK                        (PCIE_BUS_CLK / 10)
 
-static const struct profile_mode_setting smu7_profiling[6] =
-                                       {{1, 0, 100, 30, 1, 0, 100, 10},
+static const struct profile_mode_setting smu7_profiling[7] =
+                                       {{0, 0, 0, 0, 0, 0, 0, 0},
+                                        {1, 0, 100, 30, 1, 0, 100, 10},
                                         {1, 10, 0, 30, 0, 0, 0, 0},
                                         {0, 0, 0, 0, 1, 10, 16, 31},
                                         {1, 0, 11, 50, 1, 0, 100, 10},
@@ -4889,7 +4890,8 @@ static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
        uint32_t i, size = 0;
        uint32_t len;
 
-       static const char *profile_name[6] = {"3D_FULL_SCREEN",
+       static const char *profile_name[7] = {"BOOTUP_DEFAULT",
+                                       "3D_FULL_SCREEN",
                                        "POWER_SAVING",
                                        "VIDEO",
                                        "VR",
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.c
new file mode 100644 (file)
index 0000000..f94dab2
--- /dev/null
@@ -0,0 +1,136 @@
+#include "amdgpu.h"
+#include "soc15.h"
+#include "soc15_hw_ip.h"
+#include "vega10_ip_offset.h"
+#include "soc15_common.h"
+#include "vega10_inc.h"
+#include "vega10_ppsmc.h"
+#include "vega10_baco.h"
+
+
+
+static const struct soc15_baco_cmd_entry  pre_baco_tbl[] =
+{
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIF_DOORBELL_CNTL), BIF_DOORBELL_CNTL__DOORBELL_MONITOR_EN_MASK, BIF_DOORBELL_CNTL__DOORBELL_MONITOR_EN__SHIFT, 0, 1},
+       {CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIF_FB_EN), 0, 0, 0, 0},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_DSTATE_BYPASS_MASK, BACO_CNTL__BACO_DSTATE_BYPASS__SHIFT, 0, 1},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_RST_INTR_MASK_MASK, BACO_CNTL__BACO_RST_INTR_MASK__SHIFT, 0, 1}
+};
+
+static const struct soc15_baco_cmd_entry enter_baco_tbl[] =
+{
+       {CMD_WAITFOR, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__SOC_DOMAIN_IDLE_MASK, THM_BACO_CNTL__SOC_DOMAIN_IDLE__SHIFT, 0xffffffff, 0x80000000},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 1},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_BIF_LCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_LCLK_SWITCH__SHIFT, 0, 1},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_DUMMY_EN_MASK, BACO_CNTL__BACO_DUMMY_EN__SHIFT, 0, 1},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SOC_VDCI_RESET_MASK, THM_BACO_CNTL__BACO_SOC_VDCI_RESET__SHIFT, 0, 1},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SMNCLK_MUX_MASK, THM_BACO_CNTL__BACO_SMNCLK_MUX__SHIFT,0, 1},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_ISO_EN_MASK, THM_BACO_CNTL__BACO_ISO_EN__SHIFT, 0, 1},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_AEB_ISO_EN_MASK, THM_BACO_CNTL__BACO_AEB_ISO_EN__SHIFT,0, 1},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_ANA_ISO_EN_MASK, THM_BACO_CNTL__BACO_ANA_ISO_EN__SHIFT, 0, 1},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SOC_REFCLK_OFF_MASK,     THM_BACO_CNTL__BACO_SOC_REFCLK_OFF__SHIFT, 0, 1},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 1},
+       {CMD_DELAY_MS, 0, 0, 0, 0, 0, 0, 5, 0},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_RESET_EN_MASK, THM_BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 1},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_PWROKRAW_CNTL_MASK, THM_BACO_CNTL__BACO_PWROKRAW_CNTL__SHIFT, 0, 0},
+       {CMD_WAITFOR, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_MODE_MASK, BACO_CNTL__BACO_MODE__SHIFT, 0xffffffff, 0x100}
+};
+
+static const struct soc15_baco_cmd_entry exit_baco_tbl[] =
+{
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0},
+       {CMD_DELAY_MS, 0, 0, 0, 0, 0, 0, 10,0},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SOC_REFCLK_OFF_MASK, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF__SHIFT, 0,0},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_ANA_ISO_EN_MASK, THM_BACO_CNTL__BACO_ANA_ISO_EN__SHIFT, 0, 0},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_AEB_ISO_EN_MASK, THM_BACO_CNTL__BACO_AEB_ISO_EN__SHIFT,0, 0},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_ISO_EN_MASK, THM_BACO_CNTL__BACO_ISO_EN__SHIFT, 0, 0},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_PWROKRAW_CNTL_MASK, THM_BACO_CNTL__BACO_PWROKRAW_CNTL__SHIFT, 0, 1},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SMNCLK_MUX_MASK, THM_BACO_CNTL__BACO_SMNCLK_MUX__SHIFT, 0, 0},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SOC_VDCI_RESET_MASK, THM_BACO_CNTL__BACO_SOC_VDCI_RESET__SHIFT, 0, 0},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_EXIT_MASK, THM_BACO_CNTL__BACO_EXIT__SHIFT, 0, 1},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_RESET_EN_MASK, THM_BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0},
+       {CMD_WAITFOR, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_EXIT_MASK, 0, 0xffffffff, 0},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SB_AXI_FENCE_MASK, THM_BACO_CNTL__BACO_SB_AXI_FENCE__SHIFT, 0, 0},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_DUMMY_EN_MASK, BACO_CNTL__BACO_DUMMY_EN__SHIFT,  0, 0},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_BIF_LCLK_SWITCH_MASK ,BACO_CNTL__BACO_BIF_LCLK_SWITCH__SHIFT, 0, 0},
+       {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_EN_MASK , BACO_CNTL__BACO_EN__SHIFT, 0,0},
+       {CMD_WAITFOR, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0}
+ };
+
+static const struct soc15_baco_cmd_entry clean_baco_tbl[] =
+{
+       {CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_6), 0, 0, 0, 0},
+       {CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_7), 0, 0, 0, 0},
+};
+
+int vega10_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
+       uint32_t reg, data;
+
+       *cap = false;
+       if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_BACO))
+               return 0;
+
+       WREG32(0x12074, 0xFFF0003B);
+       data = RREG32(0x12075);
+
+       if (data == 0x1) {
+               reg = RREG32_SOC15(NBIF, 0, mmRCC_BIF_STRAP0);
+
+               if (reg & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK)
+                       *cap = true;
+       }
+
+       return 0;
+}
+
+int vega10_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
+       uint32_t reg;
+
+       reg = RREG32_SOC15(NBIF, 0, mmBACO_CNTL);
+
+       if (reg & BACO_CNTL__BACO_MODE_MASK)
+               /* gfx has already entered BACO state */
+               *state = BACO_STATE_IN;
+       else
+               *state = BACO_STATE_OUT;
+       return 0;
+}
+
+int vega10_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state)
+{
+       enum BACO_STATE cur_state;
+
+       vega10_baco_get_state(hwmgr, &cur_state);
+
+       if (cur_state == state)
+               /* aisc already in the target state */
+               return 0;
+
+       if (state == BACO_STATE_IN) {
+               if (soc15_baco_program_registers(hwmgr, pre_baco_tbl,
+                                            ARRAY_SIZE(pre_baco_tbl))) {
+                       if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnterBaco))
+                               return -1;
+
+                       if (soc15_baco_program_registers(hwmgr, enter_baco_tbl,
+                                                  ARRAY_SIZE(enter_baco_tbl)))
+                               return 0;
+               }
+       } else if (state == BACO_STATE_OUT) {
+               /* HW requires at least 20ms between regulator off and on */
+               msleep(20);
+               /* Execute Hardware BACO exit sequence */
+               if (soc15_baco_program_registers(hwmgr, exit_baco_tbl,
+                                            ARRAY_SIZE(exit_baco_tbl))) {
+                       if (soc15_baco_program_registers(hwmgr, clean_baco_tbl,
+                                                    ARRAY_SIZE(clean_baco_tbl)))
+                               return 0;
+               }
+       }
+
+       return -1;
+}
similarity index 74%
rename from drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h
rename to drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.h
index 21908629e973a14bcc2e5740f707e5b7fa678111..a93b1e6d1c66061704a755a6666a6278cb718a66 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
+ * Copyright 2018 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"),
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
  *
- * Authors: AMD
- *
  */
+#ifndef __VEGA10_BOCO_H__
+#define __VEGA10_BOCO_H__
+#include "hwmgr.h"
+#include "common_baco.h"
 
-#ifndef __DAL_I2C_AUX_DCE80_H__
-#define __DAL_I2C_AUX_DCE80_H__
-
-struct i2caux_dce80 {
-       struct i2caux base;
-       /* indicate the I2C HW circular buffer is in use */
-       bool i2c_hw_buffer_in_use;
-};
-
-struct i2caux *dal_i2caux_dce80_create(
-       struct dc_context *ctx);
+extern int vega10_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap);
+extern int vega10_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state);
+extern int vega10_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
 
 #endif
index 79c86247d0ac0324f2282a3fc2ef46006cefc209..0d38ac2fdbf145d981a1563589172836b2a3a270 100644 (file)
@@ -48,6 +48,7 @@
 #include "ppinterrupt.h"
 #include "pp_overdriver.h"
 #include "pp_thermal.h"
+#include "vega10_baco.h"
 
 #include "smuio/smuio_9_0_offset.h"
 #include "smuio/smuio_9_0_sh_mask.h"
@@ -71,6 +72,21 @@ static const uint32_t channel_number[] = {1, 2, 0, 4, 0, 8, 0, 16, 2};
 #define DF_CS_AON0_DramBaseAddress0__IntLvAddrSel_MASK                                                        0x00000700L
 #define DF_CS_AON0_DramBaseAddress0__DramBaseAddr_MASK                                                        0xFFFFF000L
 
+typedef enum {
+       CLK_SMNCLK = 0,
+       CLK_SOCCLK,
+       CLK_MP0CLK,
+       CLK_MP1CLK,
+       CLK_LCLK,
+       CLK_DCEFCLK,
+       CLK_VCLK,
+       CLK_DCLK,
+       CLK_ECLK,
+       CLK_UCLK,
+       CLK_GFXCLK,
+       CLK_COUNT,
+} CLOCK_ID_e;
+
 static const ULONG PhwVega10_Magic = (ULONG)(PHM_VIslands_Magic);
 
 struct vega10_power_state *cast_phw_vega10_power_state(
@@ -804,9 +820,9 @@ static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
 
        hwmgr->backend = data;
 
-       hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO];
-       hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
-       hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
+       hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
+       hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+       hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
 
        vega10_set_default_registry_data(hwmgr);
        data->disable_dpm_mask = 0xff;
@@ -3485,6 +3501,17 @@ static int vega10_upload_dpm_bootup_level(struct pp_hwmgr *hwmgr)
                }
        }
 
+       if (!data->registry_data.socclk_dpm_key_disabled) {
+               if (data->smc_state_table.soc_boot_level !=
+                               data->dpm_table.soc_table.dpm_state.soft_min_level) {
+                       smum_send_msg_to_smc_with_parameter(hwmgr,
+                               PPSMC_MSG_SetSoftMinSocclkByIndex,
+                               data->smc_state_table.soc_boot_level);
+                       data->dpm_table.soc_table.dpm_state.soft_min_level =
+                                       data->smc_state_table.soc_boot_level;
+               }
+       }
+
        return 0;
 }
 
@@ -3516,6 +3543,17 @@ static int vega10_upload_dpm_max_level(struct pp_hwmgr *hwmgr)
                }
        }
 
+       if (!data->registry_data.socclk_dpm_key_disabled) {
+               if (data->smc_state_table.soc_max_level !=
+                       data->dpm_table.soc_table.dpm_state.soft_max_level) {
+                       smum_send_msg_to_smc_with_parameter(hwmgr,
+                               PPSMC_MSG_SetSoftMaxSocclkByIndex,
+                               data->smc_state_table.soc_max_level);
+                       data->dpm_table.soc_table.dpm_state.soft_max_level =
+                                       data->smc_state_table.soc_max_level;
+               }
+       }
+
        return 0;
 }
 
@@ -4028,6 +4066,24 @@ static int vega10_force_clock_level(struct pp_hwmgr *hwmgr,
 
                break;
 
+       case PP_SOCCLK:
+               data->smc_state_table.soc_boot_level = mask ? (ffs(mask) - 1) : 0;
+               data->smc_state_table.soc_max_level = mask ? (fls(mask) - 1) : 0;
+
+               PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
+                       "Failed to upload boot level to lowest!",
+                       return -EINVAL);
+
+               PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
+                       "Failed to upload dpm max level to highest!",
+                       return -EINVAL);
+
+               break;
+
+       case PP_DCEFCLK:
+               pr_info("Setting DCEFCLK min/max dpm level is not supported!\n");
+               break;
+
        case PP_PCIE:
        default:
                break;
@@ -4267,12 +4323,113 @@ static int vega10_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
        return result;
 }
 
+static int vega10_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf)
+{
+       static const char *ppfeature_name[] = {
+                               "DPM_PREFETCHER",
+                               "GFXCLK_DPM",
+                               "UCLK_DPM",
+                               "SOCCLK_DPM",
+                               "UVD_DPM",
+                               "VCE_DPM",
+                               "ULV",
+                               "MP0CLK_DPM",
+                               "LINK_DPM",
+                               "DCEFCLK_DPM",
+                               "AVFS",
+                               "GFXCLK_DS",
+                               "SOCCLK_DS",
+                               "LCLK_DS",
+                               "PPT",
+                               "TDC",
+                               "THERMAL",
+                               "GFX_PER_CU_CG",
+                               "RM",
+                               "DCEFCLK_DS",
+                               "ACDC",
+                               "VR0HOT",
+                               "VR1HOT",
+                               "FW_CTF",
+                               "LED_DISPLAY",
+                               "FAN_CONTROL",
+                               "FAST_PPT",
+                               "DIDT",
+                               "ACG",
+                               "PCC_LIMIT"};
+       static const char *output_title[] = {
+                               "FEATURES",
+                               "BITMASK",
+                               "ENABLEMENT"};
+       uint64_t features_enabled;
+       int i;
+       int ret = 0;
+       int size = 0;
+
+       ret = vega10_get_enabled_smc_features(hwmgr, &features_enabled);
+       PP_ASSERT_WITH_CODE(!ret,
+                       "[EnableAllSmuFeatures] Failed to get enabled smc features!",
+                       return ret);
+
+       size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled);
+       size += sprintf(buf + size, "%-19s %-22s %s\n",
+                               output_title[0],
+                               output_title[1],
+                               output_title[2]);
+       for (i = 0; i < GNLD_FEATURES_MAX; i++) {
+               size += sprintf(buf + size, "%-19s 0x%016llx %6s\n",
+                                       ppfeature_name[i],
+                                       1ULL << i,
+                                       (features_enabled & (1ULL << i)) ? "Y" : "N");
+       }
+
+       return size;
+}
+
+static int vega10_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks)
+{
+       uint64_t features_enabled;
+       uint64_t features_to_enable;
+       uint64_t features_to_disable;
+       int ret = 0;
+
+       if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX))
+               return -EINVAL;
+
+       ret = vega10_get_enabled_smc_features(hwmgr, &features_enabled);
+       if (ret)
+               return ret;
+
+       features_to_disable =
+               (features_enabled ^ new_ppfeature_masks) & features_enabled;
+       features_to_enable =
+               (features_enabled ^ new_ppfeature_masks) ^ features_to_disable;
+
+       pr_debug("features_to_disable 0x%llx\n", features_to_disable);
+       pr_debug("features_to_enable 0x%llx\n", features_to_enable);
+
+       if (features_to_disable) {
+               ret = vega10_enable_smc_features(hwmgr, false, features_to_disable);
+               if (ret)
+                       return ret;
+       }
+
+       if (features_to_enable) {
+               ret = vega10_enable_smc_features(hwmgr, true, features_to_enable);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
                enum pp_clock_type type, char *buf)
 {
        struct vega10_hwmgr *data = hwmgr->backend;
        struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
        struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
+       struct vega10_single_dpm_table *soc_table = &(data->dpm_table.soc_table);
+       struct vega10_single_dpm_table *dcef_table = &(data->dpm_table.dcef_table);
        struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table);
        struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep = NULL;
 
@@ -4303,6 +4460,32 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
                                        i, mclk_table->dpm_levels[i].value / 100,
                                        (i == now) ? "*" : "");
                break;
+       case PP_SOCCLK:
+               if (data->registry_data.socclk_dpm_key_disabled)
+                       break;
+
+               smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentSocclkIndex);
+               now = smum_get_argument(hwmgr);
+
+               for (i = 0; i < soc_table->count; i++)
+                       size += sprintf(buf + size, "%d: %uMhz %s\n",
+                                       i, soc_table->dpm_levels[i].value / 100,
+                                       (i == now) ? "*" : "");
+               break;
+       case PP_DCEFCLK:
+               if (data->registry_data.dcefclk_dpm_key_disabled)
+                       break;
+
+               smum_send_msg_to_smc_with_parameter(hwmgr,
+                               PPSMC_MSG_GetClockFreqMHz, CLK_DCEFCLK);
+               now = smum_get_argument(hwmgr);
+
+               for (i = 0; i < dcef_table->count; i++)
+                       size += sprintf(buf + size, "%d: %uMhz %s\n",
+                                       i, dcef_table->dpm_levels[i].value / 100,
+                                       (dcef_table->dpm_levels[i].value / 100 == now) ?
+                                       "*" : "");
+               break;
        case PP_PCIE:
                smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentLinkIndex);
                now = smum_get_argument(hwmgr);
@@ -4668,13 +4851,15 @@ static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
 {
        struct vega10_hwmgr *data = hwmgr->backend;
        uint32_t i, size = 0;
-       static const uint8_t profile_mode_setting[5][4] = {{70, 60, 1, 3,},
+       static const uint8_t profile_mode_setting[6][4] = {{70, 60, 0, 0,},
+                                               {70, 60, 1, 3,},
                                                {90, 60, 0, 0,},
                                                {70, 60, 0, 0,},
                                                {70, 90, 0, 0,},
                                                {30, 60, 0, 6,},
                                                };
-       static const char *profile_name[6] = {"3D_FULL_SCREEN",
+       static const char *profile_name[7] = {"BOOTUP_DEFAULT",
+                                       "3D_FULL_SCREEN",
                                        "POWER_SAVING",
                                        "VIDEO",
                                        "VR",
@@ -4978,6 +5163,12 @@ static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
        .set_power_limit = vega10_set_power_limit,
        .odn_edit_dpm_table = vega10_odn_edit_dpm_table,
        .get_performance_level = vega10_get_performance_level,
+       .get_asic_baco_capability = vega10_baco_get_capability,
+       .get_asic_baco_state = vega10_baco_get_state,
+       .set_asic_baco_state = vega10_baco_set_state,
+       .enable_mgpu_fan_boost = vega10_enable_mgpu_fan_boost,
+       .get_ppfeature_status = vega10_get_ppfeature_status,
+       .set_ppfeature_status = vega10_set_ppfeature_status,
 };
 
 int vega10_hwmgr_init(struct pp_hwmgr *hwmgr)
index 89870556de1b49fd057a4051484d6427f970cae9..f752b4ad0c8ae76700996411ed78322444591459 100644 (file)
@@ -199,6 +199,7 @@ struct vega10_smc_state_table {
        uint32_t        vce_boot_level;
        uint32_t        gfx_max_level;
        uint32_t        mem_max_level;
+       uint32_t        soc_max_level;
        uint8_t         vr_hot_gpio;
        uint8_t         ac_dc_gpio;
        uint8_t         therm_out_gpio;
index b3e63003a789c72262e73012a371492fb31350f9..c934e9612c1b56e6002c9724df88b116175a50d2 100644 (file)
@@ -282,6 +282,30 @@ typedef struct _ATOM_Vega10_Fan_Table_V2 {
        UCHAR   ucFanMaxRPM;
 } ATOM_Vega10_Fan_Table_V2;
 
+typedef struct _ATOM_Vega10_Fan_Table_V3 {
+       UCHAR   ucRevId;
+       USHORT  usFanOutputSensitivity;
+       USHORT  usFanAcousticLimitRpm;
+       USHORT  usThrottlingRPM;
+       USHORT  usTargetTemperature;
+       USHORT  usMinimumPWMLimit;
+       USHORT  usTargetGfxClk;
+       USHORT  usFanGainEdge;
+       USHORT  usFanGainHotspot;
+       USHORT  usFanGainLiquid;
+       USHORT  usFanGainVrVddc;
+       USHORT  usFanGainVrMvdd;
+       USHORT  usFanGainPlx;
+       USHORT  usFanGainHbm;
+       UCHAR   ucEnableZeroRPM;
+       USHORT  usFanStopTemperature;
+       USHORT  usFanStartTemperature;
+       UCHAR   ucFanParameters;
+       UCHAR   ucFanMinRPM;
+       UCHAR   ucFanMaxRPM;
+       USHORT  usMGpuThrottlingRPM;
+} ATOM_Vega10_Fan_Table_V3;
+
 typedef struct _ATOM_Vega10_Thermal_Controller {
        UCHAR ucRevId;
        UCHAR ucType;           /* one of ATOM_VEGA10_PP_THERMALCONTROLLER_*/
index b8747a5c9204d6341a92ab16e51091616f4715d6..b6767d74dc852aca70b10ab88052959f0a02c20c 100644 (file)
@@ -32,6 +32,7 @@
 #include "vega10_pptable.h"
 
 #define NUM_DSPCLK_LEVELS 8
+#define VEGA10_ENGINECLOCK_HARDMAX 198000
 
 static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
                enum phm_platform_caps cap)
@@ -122,6 +123,7 @@ static int init_thermal_controller(
        const Vega10_PPTable_Generic_SubTable_Header *header;
        const ATOM_Vega10_Fan_Table *fan_table_v1;
        const ATOM_Vega10_Fan_Table_V2 *fan_table_v2;
+       const ATOM_Vega10_Fan_Table_V3 *fan_table_v3;
 
        thermal_controller = (ATOM_Vega10_Thermal_Controller *)
                        (((unsigned long)powerplay_table) +
@@ -206,7 +208,7 @@ static int init_thermal_controller(
                                le16_to_cpu(fan_table_v1->usFanStopTemperature);
                hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStartTemperature =
                                le16_to_cpu(fan_table_v1->usFanStartTemperature);
-       } else if (header->ucRevId > 10) {
+       } else if (header->ucRevId == 0xb) {
                fan_table_v2 = (ATOM_Vega10_Fan_Table_V2 *)header;
 
                hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
@@ -250,7 +252,54 @@ static int init_thermal_controller(
                                le16_to_cpu(fan_table_v2->usFanStopTemperature);
                hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStartTemperature =
                                le16_to_cpu(fan_table_v2->usFanStartTemperature);
+       } else if (header->ucRevId > 0xb) {
+               fan_table_v3 = (ATOM_Vega10_Fan_Table_V3 *)header;
+
+               hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
+                               fan_table_v3->ucFanParameters & ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
+               hwmgr->thermal_controller.fanInfo.ulMinRPM = fan_table_v3->ucFanMinRPM * 100UL;
+               hwmgr->thermal_controller.fanInfo.ulMaxRPM = fan_table_v3->ucFanMaxRPM * 100UL;
+               phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+                               PHM_PlatformCaps_MicrocodeFanControl);
+               hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity =
+                               le16_to_cpu(fan_table_v3->usFanOutputSensitivity);
+               hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM =
+                               fan_table_v3->ucFanMaxRPM * 100UL;
+               hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit =
+                               le16_to_cpu(fan_table_v3->usThrottlingRPM);
+               hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit =
+                               le16_to_cpu(fan_table_v3->usFanAcousticLimitRpm);
+               hwmgr->thermal_controller.advanceFanControlParameters.usTMax =
+                               le16_to_cpu(fan_table_v3->usTargetTemperature);
+               hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin =
+                               le16_to_cpu(fan_table_v3->usMinimumPWMLimit);
+               hwmgr->thermal_controller.advanceFanControlParameters.ulTargetGfxClk =
+                               le16_to_cpu(fan_table_v3->usTargetGfxClk);
+               hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge =
+                               le16_to_cpu(fan_table_v3->usFanGainEdge);
+               hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot =
+                               le16_to_cpu(fan_table_v3->usFanGainHotspot);
+               hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid =
+                               le16_to_cpu(fan_table_v3->usFanGainLiquid);
+               hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc =
+                               le16_to_cpu(fan_table_v3->usFanGainVrVddc);
+               hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd =
+                               le16_to_cpu(fan_table_v3->usFanGainVrMvdd);
+               hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx =
+                               le16_to_cpu(fan_table_v3->usFanGainPlx);
+               hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm =
+                               le16_to_cpu(fan_table_v3->usFanGainHbm);
+
+               hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM =
+                               fan_table_v3->ucEnableZeroRPM;
+               hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStopTemperature =
+                               le16_to_cpu(fan_table_v3->usFanStopTemperature);
+               hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStartTemperature =
+                               le16_to_cpu(fan_table_v3->usFanStartTemperature);
+               hwmgr->thermal_controller.advanceFanControlParameters.usMGpuThrottlingRPMLimit =
+                               le16_to_cpu(fan_table_v3->usMGpuThrottlingRPM);
        }
+
        return 0;
 }
 
@@ -258,7 +307,26 @@ static int init_over_drive_limits(
                struct pp_hwmgr *hwmgr,
                const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
 {
-       hwmgr->platform_descriptor.overdriveLimit.engineClock =
+       const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table =
+                       (const ATOM_Vega10_GFXCLK_Dependency_Table *)
+                       (((unsigned long) powerplay_table) +
+                       le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset));
+       bool is_acg_enabled = false;
+       ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_v2;
+
+       if (gfxclk_dep_table->ucRevId == 1) {
+               patom_record_v2 =
+                       (ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)gfxclk_dep_table->entries;
+               is_acg_enabled =
+                       (bool)patom_record_v2[gfxclk_dep_table->ucNumEntries-1].ucACGEnable;
+       }
+
+       if (powerplay_table->ulMaxODEngineClock > VEGA10_ENGINECLOCK_HARDMAX &&
+               !is_acg_enabled)
+               hwmgr->platform_descriptor.overdriveLimit.engineClock =
+                       VEGA10_ENGINECLOCK_HARDMAX;
+       else
+               hwmgr->platform_descriptor.overdriveLimit.engineClock =
                        le32_to_cpu(powerplay_table->ulMaxODEngineClock);
        hwmgr->platform_descriptor.overdriveLimit.memoryClock =
                        le32_to_cpu(powerplay_table->ulMaxODMemoryClock);
index 3f807d6c95ce1764fdcdff2207556342ad37a199..ba8763daa3808b2a6fcd57f7ff6315d6bc8c3e5e 100644 (file)
@@ -556,6 +556,43 @@ int vega10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
        return ret;
 }
 
+int vega10_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr)
+{
+       struct vega10_hwmgr *data = hwmgr->backend;
+       PPTable_t *table = &(data->smc_state_table.pp_table);
+       int ret;
+
+       if (!data->smu_features[GNLD_FAN_CONTROL].supported)
+               return 0;
+
+       if (!hwmgr->thermal_controller.advanceFanControlParameters.
+                       usMGpuThrottlingRPMLimit)
+               return 0;
+
+       table->FanThrottlingRpm = hwmgr->thermal_controller.
+                       advanceFanControlParameters.usMGpuThrottlingRPMLimit;
+
+       ret = smum_smc_table_manager(hwmgr,
+                               (uint8_t *)(&(data->smc_state_table.pp_table)),
+                               PPTABLE, false);
+       if (ret) {
+               pr_info("Failed to update fan control table in pptable!");
+               return ret;
+       }
+
+       ret = vega10_disable_fan_control_feature(hwmgr);
+       if (ret) {
+               pr_info("Attempt to disable SMC fan control feature failed!");
+               return ret;
+       }
+
+       ret = vega10_enable_fan_control_feature(hwmgr);
+       if (ret)
+               pr_info("Attempt to enable SMC fan control feature failed!");
+
+       return ret;
+}
+
 /**
 * Start the fan control on the SMC.
 * @param    hwmgr  the address of the powerplay hardware manager.
index 21e7c4dfa2cac69c4cfa0f296e5d172945cefa68..4a0ede7c1f07b535900a65d1fc7460c4fcd2518c 100644 (file)
@@ -73,6 +73,7 @@ extern int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr);
 extern int vega10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr);
 extern int vega10_start_thermal_controller(struct pp_hwmgr *hwmgr,
                                struct PP_TemperatureRange *range);
+extern int vega10_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr);
 
 
 #endif
index 54364444ecd121dd611c30148f4e292a8ee18e1a..6c8e78611c033c20a381f492c7ad01cca764e150 100644 (file)
@@ -753,6 +753,22 @@ static int vega12_init_smc_table(struct pp_hwmgr *hwmgr)
        return 0;
 }
 
+static int vega12_run_acg_btc(struct pp_hwmgr *hwmgr)
+{
+       uint32_t result;
+
+       PP_ASSERT_WITH_CODE(
+               smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgBtc) == 0,
+               "[Run_ACG_BTC] Attempt to run ACG BTC failed!",
+               return -EINVAL);
+
+       result = smum_get_argument(hwmgr);
+       PP_ASSERT_WITH_CODE(result == 1,
+                       "Failed to run ACG BTC!", return -EINVAL);
+
+       return 0;
+}
+
 static int vega12_set_allowed_featuresmask(struct pp_hwmgr *hwmgr)
 {
        struct vega12_hwmgr *data =
@@ -931,6 +947,11 @@ static int vega12_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
                        "Failed to initialize SMC table!",
                        result = tmp_result);
 
+       tmp_result = vega12_run_acg_btc(hwmgr);
+       PP_ASSERT_WITH_CODE(!tmp_result,
+                       "Failed to run ACG BTC!",
+                       result = tmp_result);
+
        result = vega12_enable_all_smu_features(hwmgr);
        PP_ASSERT_WITH_CODE(!result,
                        "Failed to enable all smu features!",
@@ -1072,6 +1093,16 @@ static int vega12_upload_dpm_min_level(struct pp_hwmgr *hwmgr)
                                        return ret);
        }
 
+       if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
+               min_freq = data->dpm_table.dcef_table.dpm_state.hard_min_level;
+
+               PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
+                                       hwmgr, PPSMC_MSG_SetHardMinByFreq,
+                                       (PPCLK_DCEFCLK << 16) | (min_freq & 0xffff))),
+                                       "Failed to set hard min dcefclk!",
+                                       return ret);
+       }
+
        return ret;
 
 }
@@ -1797,7 +1828,7 @@ static int vega12_force_clock_level(struct pp_hwmgr *hwmgr,
                enum pp_clock_type type, uint32_t mask)
 {
        struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
-       uint32_t soft_min_level, soft_max_level;
+       uint32_t soft_min_level, soft_max_level, hard_min_level;
        int ret = 0;
 
        switch (type) {
@@ -1842,6 +1873,56 @@ static int vega12_force_clock_level(struct pp_hwmgr *hwmgr,
 
                break;
 
+       case PP_SOCCLK:
+               soft_min_level = mask ? (ffs(mask) - 1) : 0;
+               soft_max_level = mask ? (fls(mask) - 1) : 0;
+
+               if (soft_max_level >= data->dpm_table.soc_table.count) {
+                       pr_err("Clock level specified %d is over max allowed %d\n",
+                                       soft_max_level,
+                                       data->dpm_table.soc_table.count - 1);
+                       return -EINVAL;
+               }
+
+               data->dpm_table.soc_table.dpm_state.soft_min_level =
+                       data->dpm_table.soc_table.dpm_levels[soft_min_level].value;
+               data->dpm_table.soc_table.dpm_state.soft_max_level =
+                       data->dpm_table.soc_table.dpm_levels[soft_max_level].value;
+
+               ret = vega12_upload_dpm_min_level(hwmgr);
+               PP_ASSERT_WITH_CODE(!ret,
+                       "Failed to upload boot level to lowest!",
+                       return ret);
+
+               ret = vega12_upload_dpm_max_level(hwmgr);
+               PP_ASSERT_WITH_CODE(!ret,
+                       "Failed to upload dpm max level to highest!",
+                       return ret);
+
+               break;
+
+       case PP_DCEFCLK:
+               hard_min_level = mask ? (ffs(mask) - 1) : 0;
+
+               if (hard_min_level >= data->dpm_table.dcef_table.count) {
+                       pr_err("Clock level specified %d is over max allowed %d\n",
+                                       hard_min_level,
+                                       data->dpm_table.dcef_table.count - 1);
+                       return -EINVAL;
+               }
+
+               data->dpm_table.dcef_table.dpm_state.hard_min_level =
+                       data->dpm_table.dcef_table.dpm_levels[hard_min_level].value;
+
+               ret = vega12_upload_dpm_min_level(hwmgr);
+               PP_ASSERT_WITH_CODE(!ret,
+                       "Failed to upload boot level to lowest!",
+                       return ret);
+
+               //TODO: Setting DCEFCLK max dpm level is not supported
+
+               break;
+
        case PP_PCIE:
                break;
 
@@ -1852,6 +1933,104 @@ static int vega12_force_clock_level(struct pp_hwmgr *hwmgr,
        return 0;
 }
 
+static int vega12_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf)
+{
+       static const char *ppfeature_name[] = {
+                       "DPM_PREFETCHER",
+                       "GFXCLK_DPM",
+                       "UCLK_DPM",
+                       "SOCCLK_DPM",
+                       "UVD_DPM",
+                       "VCE_DPM",
+                       "ULV",
+                       "MP0CLK_DPM",
+                       "LINK_DPM",
+                       "DCEFCLK_DPM",
+                       "GFXCLK_DS",
+                       "SOCCLK_DS",
+                       "LCLK_DS",
+                       "PPT",
+                       "TDC",
+                       "THERMAL",
+                       "GFX_PER_CU_CG",
+                       "RM",
+                       "DCEFCLK_DS",
+                       "ACDC",
+                       "VR0HOT",
+                       "VR1HOT",
+                       "FW_CTF",
+                       "LED_DISPLAY",
+                       "FAN_CONTROL",
+                       "DIDT",
+                       "GFXOFF",
+                       "CG",
+                       "ACG"};
+       static const char *output_title[] = {
+                       "FEATURES",
+                       "BITMASK",
+                       "ENABLEMENT"};
+       uint64_t features_enabled;
+       int i;
+       int ret = 0;
+       int size = 0;
+
+       ret = vega12_get_enabled_smc_features(hwmgr, &features_enabled);
+       PP_ASSERT_WITH_CODE(!ret,
+               "[EnableAllSmuFeatures] Failed to get enabled smc features!",
+               return ret);
+
+       size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled);
+       size += sprintf(buf + size, "%-19s %-22s %s\n",
+                               output_title[0],
+                               output_title[1],
+                               output_title[2]);
+       for (i = 0; i < GNLD_FEATURES_MAX; i++) {
+               size += sprintf(buf + size, "%-19s 0x%016llx %6s\n",
+                               ppfeature_name[i],
+                               1ULL << i,
+                               (features_enabled & (1ULL << i)) ? "Y" : "N");
+       }
+
+       return size;
+}
+
+static int vega12_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks)
+{
+       uint64_t features_enabled;
+       uint64_t features_to_enable;
+       uint64_t features_to_disable;
+       int ret = 0;
+
+       if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX))
+               return -EINVAL;
+
+       ret = vega12_get_enabled_smc_features(hwmgr, &features_enabled);
+       if (ret)
+               return ret;
+
+       features_to_disable =
+               (features_enabled ^ new_ppfeature_masks) & features_enabled;
+       features_to_enable =
+               (features_enabled ^ new_ppfeature_masks) ^ features_to_disable;
+
+       pr_debug("features_to_disable 0x%llx\n", features_to_disable);
+       pr_debug("features_to_enable 0x%llx\n", features_to_enable);
+
+       if (features_to_disable) {
+               ret = vega12_enable_smc_features(hwmgr, false, features_to_disable);
+               if (ret)
+                       return ret;
+       }
+
+       if (features_to_enable) {
+               ret = vega12_enable_smc_features(hwmgr, true, features_to_enable);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr,
                enum pp_clock_type type, char *buf)
 {
@@ -1891,6 +2070,42 @@ static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr,
                                (clocks.data[i].clocks_in_khz / 1000 == now / 100) ? "*" : "");
                break;
 
+       case PP_SOCCLK:
+               PP_ASSERT_WITH_CODE(
+                               smum_send_msg_to_smc_with_parameter(hwmgr,
+                                       PPSMC_MSG_GetDpmClockFreq, (PPCLK_SOCCLK << 16)) == 0,
+                               "Attempt to get Current SOCCLK Frequency Failed!",
+                               return -EINVAL);
+               now = smum_get_argument(hwmgr);
+
+               PP_ASSERT_WITH_CODE(
+                               vega12_get_socclocks(hwmgr, &clocks) == 0,
+                               "Attempt to get soc clk levels Failed!",
+                               return -1);
+               for (i = 0; i < clocks.num_levels; i++)
+                       size += sprintf(buf + size, "%d: %uMhz %s\n",
+                               i, clocks.data[i].clocks_in_khz / 1000,
+                               (clocks.data[i].clocks_in_khz / 1000 == now) ? "*" : "");
+               break;
+
+       case PP_DCEFCLK:
+               PP_ASSERT_WITH_CODE(
+                               smum_send_msg_to_smc_with_parameter(hwmgr,
+                                       PPSMC_MSG_GetDpmClockFreq, (PPCLK_DCEFCLK << 16)) == 0,
+                               "Attempt to get Current DCEFCLK Frequency Failed!",
+                               return -EINVAL);
+               now = smum_get_argument(hwmgr);
+
+               PP_ASSERT_WITH_CODE(
+                               vega12_get_dcefclocks(hwmgr, &clocks) == 0,
+                               "Attempt to get dcef clk levels Failed!",
+                               return -1);
+               for (i = 0; i < clocks.num_levels; i++)
+                       size += sprintf(buf + size, "%d: %uMhz %s\n",
+                               i, clocks.data[i].clocks_in_khz / 1000,
+                               (clocks.data[i].clocks_in_khz / 1000 == now) ? "*" : "");
+               break;
+
        case PP_PCIE:
                break;
 
@@ -2411,6 +2626,8 @@ static const struct pp_hwmgr_func vega12_hwmgr_funcs = {
        .start_thermal_controller = vega12_start_thermal_controller,
        .powergate_gfx = vega12_gfx_off_control,
        .get_performance_level = vega12_get_performance_level,
+       .get_ppfeature_status = vega12_get_ppfeature_status,
+       .set_ppfeature_status = vega12_set_ppfeature_status,
 };
 
 int vega12_hwmgr_init(struct pp_hwmgr *hwmgr)
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.c
new file mode 100644 (file)
index 0000000..0d883b3
--- /dev/null
@@ -0,0 +1,81 @@
+#include "amdgpu.h"
+#include "soc15.h"
+#include "soc15_hw_ip.h"
+#include "soc15_common.h"
+#include "vega20_inc.h"
+#include "vega20_ppsmc.h"
+#include "vega20_baco.h"
+
+
+
+static const struct soc15_baco_cmd_entry clean_baco_tbl[] =
+{
+       {CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_6), 0, 0, 0, 0},
+       {CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_7), 0, 0, 0, 0},
+};
+
+int vega20_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
+       uint32_t reg;
+
+       *cap = false;
+       if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_BACO))
+               return 0;
+
+       if (((RREG32(0x17569) & 0x20000000) >> 29) == 0x1) {
+               reg = RREG32_SOC15(NBIF, 0, mmRCC_BIF_STRAP0);
+
+               if (reg & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK)
+                       *cap = true;
+       }
+
+       return 0;
+}
+
+int vega20_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
+       uint32_t reg;
+
+       reg = RREG32_SOC15(NBIF, 0, mmBACO_CNTL);
+
+       if (reg & BACO_CNTL__BACO_MODE_MASK)
+               /* gfx has already entered BACO state */
+               *state = BACO_STATE_IN;
+       else
+               *state = BACO_STATE_OUT;
+       return 0;
+}
+
+int vega20_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
+       enum BACO_STATE cur_state;
+       uint32_t data;
+
+       vega20_baco_get_state(hwmgr, &cur_state);
+
+       if (cur_state == state)
+               /* aisc already in the target state */
+               return 0;
+
+       if (state == BACO_STATE_IN) {
+               data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL);
+               data |= 0x80000000;
+               WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data);
+
+
+               if(smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_EnterBaco, 0))
+                       return -1;
+
+       } else if (state == BACO_STATE_OUT) {
+               if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ExitBaco))
+                       return -1;
+               if (!soc15_baco_program_registers(hwmgr, clean_baco_tbl,
+                                                    ARRAY_SIZE(clean_baco_tbl)))
+                       return -1;
+       }
+
+       return 0;
+}
similarity index 73%
rename from drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.h
rename to drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.h
index b6ac47617c701032f70340a658a14db120f25a5d..c51988a9ed774b5749d80b88a909cd6af7f1f607 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-16 Advanced Micro Devices, Inc.
+ * Copyright 2018 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"),
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
  *
- * Authors: AMD
- *
  */
+#ifndef __VEGA20_BOCO_H__
+#define __VEGA20_BOCO_H__
+#include "hwmgr.h"
+#include "common_baco.h"
 
-#ifndef __DAL_I2C_AUX_DCE120_H__
-#define __DAL_I2C_AUX_DCE120_H__
-
-struct i2caux *dal_i2caux_dce120_create(
-       struct dc_context *ctx);
+extern int vega20_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap);
+extern int vega20_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state);
+extern int vega20_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
 
-#endif /* __DAL_I2C_AUX_DCE120_H__ */
+#endif
index 26154f9b2178d86c3eb843ef189efdf7aff316e7..7b49a9a13a4ae8d778ed460d1f3bf1406fb6f337 100644 (file)
@@ -47,6 +47,7 @@
 #include "pp_overdriver.h"
 #include "pp_thermal.h"
 #include "soc15_common.h"
+#include "vega20_baco.h"
 #include "smuio/smuio_9_0_offset.h"
 #include "smuio/smuio_9_0_sh_mask.h"
 #include "nbio/nbio_7_4_sh_mask.h"
@@ -390,9 +391,9 @@ static int vega20_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
 
        hwmgr->backend = data;
 
-       hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO];
-       hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
-       hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
+       hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
+       hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+       hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
 
        vega20_set_default_registry_data(hwmgr);
 
@@ -803,6 +804,11 @@ static int vega20_set_allowed_featuresmask(struct pp_hwmgr *hwmgr)
        return 0;
 }
 
+static int vega20_run_btc(struct pp_hwmgr *hwmgr)
+{
+       return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunBtc);
+}
+
 static int vega20_run_btc_afll(struct pp_hwmgr *hwmgr)
 {
        return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAfllBtc);
@@ -980,6 +986,9 @@ static int vega20_od8_set_feature_capabilities(
            pp_table->FanZeroRpmEnable)
                od_settings->overdrive8_capabilities |= OD8_FAN_ZERO_RPM_CONTROL;
 
+       if (!od_settings->overdrive8_capabilities)
+               hwmgr->od_enabled = false;
+
        return 0;
 }
 
@@ -1561,6 +1570,11 @@ static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
                        "[EnableDPMTasks] Failed to initialize SMC table!",
                        return result);
 
+       result = vega20_run_btc(hwmgr);
+       PP_ASSERT_WITH_CODE(!result,
+                       "[EnableDPMTasks] Failed to run btc!",
+                       return result);
+
        result = vega20_run_btc_afll(hwmgr);
        PP_ASSERT_WITH_CODE(!result,
                        "[EnableDPMTasks] Failed to run btc afll!",
@@ -1689,13 +1703,6 @@ static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_
                                        (PPCLK_UCLK << 16) | (min_freq & 0xffff))),
                                        "Failed to set soft min memclk !",
                                        return ret);
-
-               min_freq = data->dpm_table.mem_table.dpm_state.hard_min_level;
-               PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
-                                       hwmgr, PPSMC_MSG_SetHardMinByFreq,
-                                       (PPCLK_UCLK << 16) | (min_freq & 0xffff))),
-                                       "Failed to set hard min memclk !",
-                                       return ret);
        }
 
        if (data->smu_features[GNLD_DPM_UVD].enabled &&
@@ -1739,6 +1746,28 @@ static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_
                                        return ret);
        }
 
+       if (data->smu_features[GNLD_DPM_FCLK].enabled &&
+          (feature_mask & FEATURE_DPM_FCLK_MASK)) {
+               min_freq = data->dpm_table.fclk_table.dpm_state.soft_min_level;
+
+               PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
+                                       hwmgr, PPSMC_MSG_SetSoftMinByFreq,
+                                       (PPCLK_FCLK << 16) | (min_freq & 0xffff))),
+                                       "Failed to set soft min fclk!",
+                                       return ret);
+       }
+
+       if (data->smu_features[GNLD_DPM_DCEFCLK].enabled &&
+          (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
+               min_freq = data->dpm_table.dcef_table.dpm_state.hard_min_level;
+
+               PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
+                                       hwmgr, PPSMC_MSG_SetHardMinByFreq,
+                                       (PPCLK_DCEFCLK << 16) | (min_freq & 0xffff))),
+                                       "Failed to set hard min dcefclk!",
+                                       return ret);
+       }
+
        return ret;
 }
 
@@ -1811,6 +1840,17 @@ static int vega20_upload_dpm_max_level(struct pp_hwmgr *hwmgr, uint32_t feature_
                                        return ret);
        }
 
+       if (data->smu_features[GNLD_DPM_FCLK].enabled &&
+          (feature_mask & FEATURE_DPM_FCLK_MASK)) {
+               max_freq = data->dpm_table.fclk_table.dpm_state.soft_max_level;
+
+               PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
+                                       hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
+                                       (PPCLK_FCLK << 16) | (max_freq & 0xffff))),
+                                       "Failed to set soft max fclk!",
+                                       return ret);
+       }
+
        return ret;
 }
 
@@ -1918,16 +1958,36 @@ static uint32_t vega20_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
        return (mem_clk * 100);
 }
 
+static int vega20_get_metrics_table(struct pp_hwmgr *hwmgr, SmuMetrics_t *metrics_table)
+{
+       struct vega20_hwmgr *data =
+                       (struct vega20_hwmgr *)(hwmgr->backend);
+       int ret = 0;
+
+       if (!data->metrics_time || time_after(jiffies, data->metrics_time + HZ / 2)) {
+               ret = smum_smc_table_manager(hwmgr, (uint8_t *)metrics_table,
+                               TABLE_SMU_METRICS, true);
+               if (ret) {
+                       pr_info("Failed to export SMU metrics table!\n");
+                       return ret;
+               }
+               memcpy(&data->metrics_table, metrics_table, sizeof(SmuMetrics_t));
+               data->metrics_time = jiffies;
+       } else
+               memcpy(metrics_table, &data->metrics_table, sizeof(SmuMetrics_t));
+
+       return ret;
+}
+
 static int vega20_get_gpu_power(struct pp_hwmgr *hwmgr,
                uint32_t *query)
 {
        int ret = 0;
        SmuMetrics_t metrics_table;
 
-       ret = smum_smc_table_manager(hwmgr, (uint8_t *)&metrics_table, TABLE_SMU_METRICS, true);
-       PP_ASSERT_WITH_CODE(!ret,
-                       "Failed to export SMU METRICS table!",
-                       return ret);
+       ret = vega20_get_metrics_table(hwmgr, &metrics_table);
+       if (ret)
+               return ret;
 
        *query = metrics_table.CurrSocketPower << 8;
 
@@ -1958,10 +2018,9 @@ static int vega20_get_current_activity_percent(struct pp_hwmgr *hwmgr,
        int ret = 0;
        SmuMetrics_t metrics_table;
 
-       ret = smum_smc_table_manager(hwmgr, (uint8_t *)&metrics_table, TABLE_SMU_METRICS, true);
-       PP_ASSERT_WITH_CODE(!ret,
-                       "Failed to export SMU METRICS table!",
-                       return ret);
+       ret = vega20_get_metrics_table(hwmgr, &metrics_table);
+       if (ret)
+               return ret;
 
        *activity_percent = metrics_table.AverageGfxActivity;
 
@@ -1973,16 +2032,18 @@ static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx,
 {
        struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
        struct amdgpu_device *adev = hwmgr->adev;
+       SmuMetrics_t metrics_table;
        uint32_t val_vid;
        int ret = 0;
 
        switch (idx) {
        case AMDGPU_PP_SENSOR_GFX_SCLK:
-               ret = vega20_get_current_clk_freq(hwmgr,
-                               PPCLK_GFXCLK,
-                               (uint32_t *)value);
-               if (!ret)
-                       *size = 4;
+               ret = vega20_get_metrics_table(hwmgr, &metrics_table);
+               if (ret)
+                       return ret;
+
+               *((uint32_t *)value) = metrics_table.AverageGfxclkFrequency * 100;
+               *size = 4;
                break;
        case AMDGPU_PP_SENSOR_GFX_MCLK:
                ret = vega20_get_current_clk_freq(hwmgr,
@@ -2140,6 +2201,12 @@ static int vega20_force_dpm_highest(struct pp_hwmgr *hwmgr)
                data->dpm_table.mem_table.dpm_state.soft_max_level =
                data->dpm_table.mem_table.dpm_levels[soft_level].value;
 
+       soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.soc_table));
+
+       data->dpm_table.soc_table.dpm_state.soft_min_level =
+               data->dpm_table.soc_table.dpm_state.soft_max_level =
+               data->dpm_table.soc_table.dpm_levels[soft_level].value;
+
        ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload boot level to highest!",
@@ -2172,6 +2239,12 @@ static int vega20_force_dpm_lowest(struct pp_hwmgr *hwmgr)
                data->dpm_table.mem_table.dpm_state.soft_max_level =
                data->dpm_table.mem_table.dpm_levels[soft_level].value;
 
+       soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table));
+
+       data->dpm_table.soc_table.dpm_state.soft_min_level =
+               data->dpm_table.soc_table.dpm_state.soft_max_level =
+               data->dpm_table.soc_table.dpm_levels[soft_level].value;
+
        ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload boot level to highest!",
@@ -2188,8 +2261,32 @@ static int vega20_force_dpm_lowest(struct pp_hwmgr *hwmgr)
 
 static int vega20_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
 {
+       struct vega20_hwmgr *data =
+                       (struct vega20_hwmgr *)(hwmgr->backend);
+       uint32_t soft_min_level, soft_max_level;
        int ret = 0;
 
+       soft_min_level = vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
+       soft_max_level = vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table));
+       data->dpm_table.gfx_table.dpm_state.soft_min_level =
+               data->dpm_table.gfx_table.dpm_levels[soft_min_level].value;
+       data->dpm_table.gfx_table.dpm_state.soft_max_level =
+               data->dpm_table.gfx_table.dpm_levels[soft_max_level].value;
+
+       soft_min_level = vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table));
+       soft_max_level = vega20_find_highest_dpm_level(&(data->dpm_table.mem_table));
+       data->dpm_table.mem_table.dpm_state.soft_min_level =
+               data->dpm_table.mem_table.dpm_levels[soft_min_level].value;
+       data->dpm_table.mem_table.dpm_state.soft_max_level =
+               data->dpm_table.mem_table.dpm_levels[soft_max_level].value;
+
+       soft_min_level = vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table));
+       soft_max_level = vega20_find_highest_dpm_level(&(data->dpm_table.soc_table));
+       data->dpm_table.soc_table.dpm_state.soft_min_level =
+               data->dpm_table.soc_table.dpm_levels[soft_min_level].value;
+       data->dpm_table.soc_table.dpm_state.soft_max_level =
+               data->dpm_table.soc_table.dpm_levels[soft_max_level].value;
+
        ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload DPM Bootup Levels!",
@@ -2240,7 +2337,7 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
                enum pp_clock_type type, uint32_t mask)
 {
        struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
-       uint32_t soft_min_level, soft_max_level;
+       uint32_t soft_min_level, soft_max_level, hard_min_level;
        int ret = 0;
 
        switch (type) {
@@ -2248,6 +2345,13 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
                soft_min_level = mask ? (ffs(mask) - 1) : 0;
                soft_max_level = mask ? (fls(mask) - 1) : 0;
 
+               if (soft_max_level >= data->dpm_table.gfx_table.count) {
+                       pr_err("Clock level specified %d is over max allowed %d\n",
+                                       soft_max_level,
+                                       data->dpm_table.gfx_table.count - 1);
+                       return -EINVAL;
+               }
+
                data->dpm_table.gfx_table.dpm_state.soft_min_level =
                        data->dpm_table.gfx_table.dpm_levels[soft_min_level].value;
                data->dpm_table.gfx_table.dpm_state.soft_max_level =
@@ -2268,6 +2372,13 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
                soft_min_level = mask ? (ffs(mask) - 1) : 0;
                soft_max_level = mask ? (fls(mask) - 1) : 0;
 
+               if (soft_max_level >= data->dpm_table.mem_table.count) {
+                       pr_err("Clock level specified %d is over max allowed %d\n",
+                                       soft_max_level,
+                                       data->dpm_table.mem_table.count - 1);
+                       return -EINVAL;
+               }
+
                data->dpm_table.mem_table.dpm_state.soft_min_level =
                        data->dpm_table.mem_table.dpm_levels[soft_min_level].value;
                data->dpm_table.mem_table.dpm_state.soft_max_level =
@@ -2285,6 +2396,84 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
 
                break;
 
+       case PP_SOCCLK:
+               soft_min_level = mask ? (ffs(mask) - 1) : 0;
+               soft_max_level = mask ? (fls(mask) - 1) : 0;
+
+               if (soft_max_level >= data->dpm_table.soc_table.count) {
+                       pr_err("Clock level specified %d is over max allowed %d\n",
+                                       soft_max_level,
+                                       data->dpm_table.soc_table.count - 1);
+                       return -EINVAL;
+               }
+
+               data->dpm_table.soc_table.dpm_state.soft_min_level =
+                       data->dpm_table.soc_table.dpm_levels[soft_min_level].value;
+               data->dpm_table.soc_table.dpm_state.soft_max_level =
+                       data->dpm_table.soc_table.dpm_levels[soft_max_level].value;
+
+               ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_SOCCLK_MASK);
+               PP_ASSERT_WITH_CODE(!ret,
+                       "Failed to upload boot level to lowest!",
+                       return ret);
+
+               ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_SOCCLK_MASK);
+               PP_ASSERT_WITH_CODE(!ret,
+                       "Failed to upload dpm max level to highest!",
+                       return ret);
+
+               break;
+
+       case PP_FCLK:
+               soft_min_level = mask ? (ffs(mask) - 1) : 0;
+               soft_max_level = mask ? (fls(mask) - 1) : 0;
+
+               if (soft_max_level >= data->dpm_table.fclk_table.count) {
+                       pr_err("Clock level specified %d is over max allowed %d\n",
+                                       soft_max_level,
+                                       data->dpm_table.fclk_table.count - 1);
+                       return -EINVAL;
+               }
+
+               data->dpm_table.fclk_table.dpm_state.soft_min_level =
+                       data->dpm_table.fclk_table.dpm_levels[soft_min_level].value;
+               data->dpm_table.fclk_table.dpm_state.soft_max_level =
+                       data->dpm_table.fclk_table.dpm_levels[soft_max_level].value;
+
+               ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_FCLK_MASK);
+               PP_ASSERT_WITH_CODE(!ret,
+                       "Failed to upload boot level to lowest!",
+                       return ret);
+
+               ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_FCLK_MASK);
+               PP_ASSERT_WITH_CODE(!ret,
+                       "Failed to upload dpm max level to highest!",
+                       return ret);
+
+               break;
+
+       case PP_DCEFCLK:
+               hard_min_level = mask ? (ffs(mask) - 1) : 0;
+
+               if (hard_min_level >= data->dpm_table.dcef_table.count) {
+                       pr_err("Clock level specified %d is over max allowed %d\n",
+                                       hard_min_level,
+                                       data->dpm_table.dcef_table.count - 1);
+                       return -EINVAL;
+               }
+
+               data->dpm_table.dcef_table.dpm_state.hard_min_level =
+                       data->dpm_table.dcef_table.dpm_levels[hard_min_level].value;
+
+               ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_DCEFCLK_MASK);
+               PP_ASSERT_WITH_CODE(!ret,
+                       "Failed to upload boot level to lowest!",
+                       return ret);
+
+               //TODO: Setting DCEFCLK max dpm level is not supported
+
+               break;
+
        case PP_PCIE:
                soft_min_level = mask ? (ffs(mask) - 1) : 0;
                soft_max_level = mask ? (fls(mask) - 1) : 0;
@@ -2335,6 +2524,7 @@ static int vega20_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
                        return ret;
                vega20_force_clock_level(hwmgr, PP_SCLK, 1 << sclk_mask);
                vega20_force_clock_level(hwmgr, PP_MCLK, 1 << mclk_mask);
+               vega20_force_clock_level(hwmgr, PP_SOCCLK, 1 << soc_mask);
                break;
 
        case AMD_DPM_FORCED_LEVEL_MANUAL:
@@ -2765,6 +2955,108 @@ static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
        return 0;
 }
 
+static int vega20_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf)
+{
+       static const char *ppfeature_name[] = {
+                               "DPM_PREFETCHER",
+                               "GFXCLK_DPM",
+                               "UCLK_DPM",
+                               "SOCCLK_DPM",
+                               "UVD_DPM",
+                               "VCE_DPM",
+                               "ULV",
+                               "MP0CLK_DPM",
+                               "LINK_DPM",
+                               "DCEFCLK_DPM",
+                               "GFXCLK_DS",
+                               "SOCCLK_DS",
+                               "LCLK_DS",
+                               "PPT",
+                               "TDC",
+                               "THERMAL",
+                               "GFX_PER_CU_CG",
+                               "RM",
+                               "DCEFCLK_DS",
+                               "ACDC",
+                               "VR0HOT",
+                               "VR1HOT",
+                               "FW_CTF",
+                               "LED_DISPLAY",
+                               "FAN_CONTROL",
+                               "GFX_EDC",
+                               "GFXOFF",
+                               "CG",
+                               "FCLK_DPM",
+                               "FCLK_DS",
+                               "MP1CLK_DS",
+                               "MP0CLK_DS",
+                               "XGMI"};
+       static const char *output_title[] = {
+                               "FEATURES",
+                               "BITMASK",
+                               "ENABLEMENT"};
+       uint64_t features_enabled;
+       int i;
+       int ret = 0;
+       int size = 0;
+
+       ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
+       PP_ASSERT_WITH_CODE(!ret,
+                       "[EnableAllSmuFeatures] Failed to get enabled smc features!",
+                       return ret);
+
+       size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled);
+       size += sprintf(buf + size, "%-19s %-22s %s\n",
+                               output_title[0],
+                               output_title[1],
+                               output_title[2]);
+       for (i = 0; i < GNLD_FEATURES_MAX; i++) {
+               size += sprintf(buf + size, "%-19s 0x%016llx %6s\n",
+                                       ppfeature_name[i],
+                                       1ULL << i,
+                                       (features_enabled & (1ULL << i)) ? "Y" : "N");
+       }
+
+       return size;
+}
+
+static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks)
+{
+       uint64_t features_enabled;
+       uint64_t features_to_enable;
+       uint64_t features_to_disable;
+       int ret = 0;
+
+       if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX))
+               return -EINVAL;
+
+       ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
+       if (ret)
+               return ret;
+
+       features_to_disable =
+               (features_enabled ^ new_ppfeature_masks) & features_enabled;
+       features_to_enable =
+               (features_enabled ^ new_ppfeature_masks) ^ features_to_disable;
+
+       pr_debug("features_to_disable 0x%llx\n", features_to_disable);
+       pr_debug("features_to_enable 0x%llx\n", features_to_enable);
+
+       if (features_to_disable) {
+               ret = vega20_enable_smc_features(hwmgr, false, features_to_disable);
+               if (ret)
+                       return ret;
+       }
+
+       if (features_to_enable) {
+               ret = vega20_enable_smc_features(hwmgr, true, features_to_enable);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
                enum pp_clock_type type, char *buf)
 {
@@ -2779,6 +3071,8 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
        PPTable_t *pptable = (PPTable_t *)pptable_information->smc_pptable;
        struct amdgpu_device *adev = hwmgr->adev;
        struct pp_clock_levels_with_latency clocks;
+       struct vega20_single_dpm_table *fclk_dpm_table =
+                       &(data->dpm_table.fclk_table);
        int i, now, size = 0;
        int ret = 0;
        uint32_t gen_speed, lane_width;
@@ -2818,6 +3112,52 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
                                (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
                break;
 
+       case PP_SOCCLK:
+               ret = vega20_get_current_clk_freq(hwmgr, PPCLK_SOCCLK, &now);
+               PP_ASSERT_WITH_CODE(!ret,
+                               "Attempt to get current socclk freq Failed!",
+                               return ret);
+
+               ret = vega20_get_socclocks(hwmgr, &clocks);
+               PP_ASSERT_WITH_CODE(!ret,
+                               "Attempt to get soc clk levels Failed!",
+                               return ret);
+
+               for (i = 0; i < clocks.num_levels; i++)
+                       size += sprintf(buf + size, "%d: %uMhz %s\n",
+                               i, clocks.data[i].clocks_in_khz / 1000,
+                               (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
+               break;
+
+       case PP_FCLK:
+               ret = vega20_get_current_clk_freq(hwmgr, PPCLK_FCLK, &now);
+               PP_ASSERT_WITH_CODE(!ret,
+                               "Attempt to get current fclk freq Failed!",
+                               return ret);
+
+               for (i = 0; i < fclk_dpm_table->count; i++)
+                       size += sprintf(buf + size, "%d: %uMhz %s\n",
+                               i, fclk_dpm_table->dpm_levels[i].value,
+                               fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" : "");
+               break;
+
+       case PP_DCEFCLK:
+               ret = vega20_get_current_clk_freq(hwmgr, PPCLK_DCEFCLK, &now);
+               PP_ASSERT_WITH_CODE(!ret,
+                               "Attempt to get current dcefclk freq Failed!",
+                               return ret);
+
+               ret = vega20_get_dcefclocks(hwmgr, &clocks);
+               PP_ASSERT_WITH_CODE(!ret,
+                               "Attempt to get dcefclk levels Failed!",
+                               return ret);
+
+               for (i = 0; i < clocks.num_levels; i++)
+                       size += sprintf(buf + size, "%d: %uMhz %s\n",
+                               i, clocks.data[i].clocks_in_khz / 1000,
+                               (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
+               break;
+
        case PP_PCIE:
                gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
                             PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
@@ -3261,6 +3601,9 @@ static int conv_power_profile_to_pplib_workload(int power_profile)
        int pplib_workload = 0;
 
        switch (power_profile) {
+       case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT:
+               pplib_workload = WORKLOAD_DEFAULT_BIT;
+               break;
        case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
                pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;
                break;
@@ -3290,6 +3633,7 @@ static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
        uint32_t i, size = 0;
        uint16_t workload_type = 0;
        static const char *profile_name[] = {
+                                       "BOOTUP_DEFAULT",
                                        "3D_FULL_SCREEN",
                                        "POWER_SAVING",
                                        "VIDEO",
@@ -3557,6 +3901,8 @@ static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
        .force_clock_level = vega20_force_clock_level,
        .print_clock_levels = vega20_print_clock_levels,
        .read_sensor = vega20_read_sensor,
+       .get_ppfeature_status = vega20_get_ppfeature_status,
+       .set_ppfeature_status = vega20_set_ppfeature_status,
        /* powergate related */
        .powergate_uvd = vega20_power_gate_uvd,
        .powergate_vce = vega20_power_gate_vce,
@@ -3577,6 +3923,10 @@ static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
        /* smu memory related */
        .notify_cac_buffer_info = vega20_notify_cac_buffer_info,
        .enable_mgpu_fan_boost = vega20_enable_mgpu_fan_boost,
+       /* BACO related */
+       .get_asic_baco_capability = vega20_baco_get_capability,
+       .get_asic_baco_state = vega20_baco_get_state,
+       .set_asic_baco_state = vega20_baco_set_state,
 };
 
 int vega20_hwmgr_init(struct pp_hwmgr *hwmgr)
index 25faaa5c5b10cbc5fcd720d7b15546a826641682..37f5f5e657da796a2610cc86d21e8170520405b7 100644 (file)
@@ -520,6 +520,9 @@ struct vega20_hwmgr {
        /* ---- Gfxoff ---- */
        bool                           gfxoff_allowed;
        uint32_t                       counter_gfxoff;
+
+       unsigned long                  metrics_time;
+       SmuMetrics_t                   metrics_table;
 };
 
 #define VEGA20_DPM2_NEAR_TDP_DEC                      10
index 6738bad536022b478f0aed98881b43c3ed4af9f9..613cb1989b3df49a7d56627468f265dfd1d3f1d9 100644 (file)
@@ -31,5 +31,6 @@
 #include "asic_reg/mp/mp_9_0_sh_mask.h"
 
 #include "asic_reg/nbio/nbio_7_4_offset.h"
+#include "asic_reg/nbio/nbio_7_4_sh_mask.h"
 
 #endif
index f4dab979a3a120dd87cea6a9e9e59a03b4e06f6e..6e0be602770579542e2db1fd3f11492287bee76a 100644 (file)
@@ -397,7 +397,6 @@ struct phm_odn_clock_levels {
 };
 
 extern int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr);
-extern int phm_enable_clock_power_gatings(struct pp_hwmgr *hwmgr);
 extern int phm_powerdown_uvd(struct pp_hwmgr *hwmgr);
 extern int phm_setup_asic(struct pp_hwmgr *hwmgr);
 extern int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr);
index 0d298a0409f578b6942a9594362890f381e6f8e2..bac3d85e3b82ce02a5ee91ab52c5064c04f8273a 100644 (file)
@@ -47,6 +47,11 @@ enum DISPLAY_GAP {
 };
 typedef enum DISPLAY_GAP DISPLAY_GAP;
 
+enum BACO_STATE {
+       BACO_STATE_OUT = 0,
+       BACO_STATE_IN,
+};
+
 struct vi_dpm_level {
        bool enabled;
        uint32_t value;
@@ -251,7 +256,6 @@ struct pp_hwmgr_func {
        uint32_t (*get_sclk)(struct pp_hwmgr *hwmgr, bool low);
        int (*power_state_set)(struct pp_hwmgr *hwmgr,
                                                const void *state);
-       int (*enable_clock_power_gating)(struct pp_hwmgr *hwmgr);
        int (*notify_smc_display_config_after_ps_adjustment)(struct pp_hwmgr *hwmgr);
        int (*pre_display_config_changed)(struct pp_hwmgr *hwmgr);
        int (*display_config_changed)(struct pp_hwmgr *hwmgr);
@@ -334,6 +338,11 @@ struct pp_hwmgr_func {
        int (*enable_mgpu_fan_boost)(struct pp_hwmgr *hwmgr);
        int (*set_hard_min_dcefclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock);
        int (*set_hard_min_fclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock);
+       int (*get_asic_baco_capability)(struct pp_hwmgr *hwmgr, bool *cap);
+       int (*get_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE *state);
+       int (*set_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
+       int (*get_ppfeature_status)(struct pp_hwmgr *hwmgr, char *buf);
+       int (*set_ppfeature_status)(struct pp_hwmgr *hwmgr, uint64_t ppfeature_masks);
 };
 
 struct pp_table_func {
@@ -678,6 +687,7 @@ struct pp_advance_fan_control_parameters {
        uint32_t  ulTargetGfxClk;
        uint16_t  usZeroRPMStartTemperature;
        uint16_t  usZeroRPMStopTemperature;
+       uint16_t  usMGpuThrottlingRPMLimit;
 };
 
 struct pp_thermal_controller_info {
@@ -705,7 +715,7 @@ enum PP_TABLE_VERSION {
 /**
  * The main hardware manager structure.
  */
-#define Workload_Policy_Max 5
+#define Workload_Policy_Max 6
 
 struct pp_hwmgr {
        void *adev;
index 62f51f70606d73060ea0d0430e305a0ff6b9860f..155ab177ce0b866166abaf666d8655e2b742772d 100644 (file)
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_device.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_vblank.h>
 #include <drm/drm_plane_helper.h>
 #include <linux/clk.h>
 #include <linux/platform_data/simplefb.h>
index 206a76abf77133f0e56ac668041ada8b9ea9859b..39a79f5718c44d58066ebd073c87ab0942562cf1 100644 (file)
 
 #include <linux/clk.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_device.h>
+#include <drm/drm_debugfs.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_atomic_helper.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
 #include <linux/of_reserved_mem.h>
+#include <linux/platform_device.h>
 
 #include "arcpgu.h"
 #include "arcpgu_regs.h"
index 68629e6149909fd08d52f22e314296971a3d4618..6530d88f72939f04fd51e5e7f6e7dc682aa45c08 100644 (file)
@@ -51,7 +51,6 @@ arcpgu_drm_connector_helper_funcs = {
 };
 
 static const struct drm_connector_funcs arcpgu_drm_connector_funcs = {
-       .dpms = drm_helper_connector_dpms,
        .reset = drm_atomic_helper_connector_reset,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .destroy = arcpgu_drm_connector_destroy,
index 9edfd6ab0c1281a6ed700fb6a86a5746e20ab16f..f1c9e3fefa86b4f8722d201475c1961603690836 100644 (file)
@@ -45,7 +45,7 @@ static int komeda_pipeline_obj_add(struct komeda_kms_dev *kms,
                return -ENOMEM;
 
        st->pipe = pipe;
-       drm_atomic_private_obj_init(&pipe->obj, &st->obj,
+       drm_atomic_private_obj_init(&kms->base, &pipe->obj, &st->obj,
                                    &komeda_pipeline_obj_funcs);
 
        return 0;
index da9360688b5546664deb1f41de3e75e12137fa85..20dfb29561c2fd8ea47237eac864aab2263469a9 100644 (file)
@@ -270,13 +270,7 @@ static void armada_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
        tm = adj->crtc_vtotal - adj->crtc_vsync_end;
 
        DRM_DEBUG_KMS("[CRTC:%d:%s] mode " DRM_MODE_FMT "\n",
-                     crtc->base.id, crtc->name,
-                     adj->base.id, adj->name, adj->vrefresh, adj->clock,
-                     adj->crtc_hdisplay, adj->crtc_hsync_start,
-                     adj->crtc_hsync_end, adj->crtc_htotal,
-                     adj->crtc_vdisplay, adj->crtc_vsync_start,
-                     adj->crtc_vsync_end, adj->crtc_vtotal,
-                     adj->type, adj->flags);
+                     crtc->base.id, crtc->name, DRM_MODE_ARG(adj));
        DRM_DEBUG_KMS("lm %d rm %d tm %d bm %d\n", lm, rm, tm, bm);
 
        /* Now compute the divider for real */
index de26df0c6044de127422999c669eeb5d68304a66..2c9f8dd9733a404354085db8d5347df2eefc300d 100644 (file)
@@ -39,7 +39,9 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_util.h>
 #include <drm/drm_crtc_helper.h>
+
 #include "ast_drv.h"
 
 static void ast_dirty_update(struct ast_fbdev *afbdev,
@@ -191,7 +193,6 @@ static int astfb_create(struct drm_fb_helper *helper,
        int size, ret;
        void *sysram;
        struct drm_gem_object *gobj = NULL;
-       struct ast_bo *bo = NULL;
        mode_cmd.width = sizes->surface_width;
        mode_cmd.height = sizes->surface_height;
        mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7)/8);
@@ -206,7 +207,6 @@ static int astfb_create(struct drm_fb_helper *helper,
                DRM_ERROR("failed to create fbcon backing object %d\n", ret);
                return ret;
        }
-       bo = gem_to_ast_bo(gobj);
 
        sysram = vmalloc(size);
        if (!sysram)
@@ -263,7 +263,7 @@ static void ast_fbdev_destroy(struct drm_device *dev,
 {
        struct ast_framebuffer *afb = &afbdev->afb;
 
-       drm_crtc_force_disable_all(dev);
+       drm_helper_force_disable_all(dev);
        drm_fb_helper_unregister_fbi(&afbdev->helper);
 
        if (afb->obj) {
index 6c4d4b6eba80a94e1cd4d42f746ae22c63aae80c..2362f07fe1fc03cb5c66b2f58d658a30e61de31c 100644 (file)
@@ -103,7 +103,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
        unsigned long pages;
        u32 *pci_gart = NULL, page_base, gart_idx;
        dma_addr_t bus_address = 0;
-       int i, j, ret = 0;
+       int i, j, ret = -ENOMEM;
        int max_ati_pages, max_real_pages;
 
        if (!entry) {
@@ -117,7 +117,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
                if (pci_set_dma_mask(dev->pdev, gart_info->table_mask)) {
                        DRM_ERROR("fail to set dma mask to 0x%Lx\n",
                                  (unsigned long long)gart_info->table_mask);
-                       ret = 1;
+                       ret = -EFAULT;
                        goto done;
                }
 
@@ -160,6 +160,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
                        drm_ati_pcigart_cleanup(dev, gart_info);
                        address = NULL;
                        bus_address = 0;
+                       ret = -ENOMEM;
                        goto done;
                }
                page_base = (u32) entry->busaddr[i];
@@ -188,7 +189,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
                        page_base += ATI_PCIGART_PAGE_SIZE;
                }
        }
-       ret = 1;
+       ret = 0;
 
 #if defined(__i386__) || defined(__x86_64__)
        wbinvd();
index 98ef60a19e8f06968cf34b05a224dd200ddc3945..e9e0f8f5eb5b6edde7784131bc685ea2fc2bd0dd 100644 (file)
@@ -1,3 +1,3 @@
-bochs-drm-y := bochs_drv.o bochs_mm.o bochs_kms.o bochs_fbdev.o bochs_hw.o
+bochs-drm-y := bochs_drv.o bochs_mm.o bochs_kms.o bochs_hw.o
 
 obj-$(CONFIG_DRM_BOCHS)        += bochs-drm.o
index fb38c8b857b5a26a7e40d2469d00fe3ce02546ed..03711394f1eda3315e1695b7dfa7e05e7b55effc 100644 (file)
@@ -80,12 +80,6 @@ struct bochs_device {
                struct ttm_bo_device bdev;
                bool initialized;
        } ttm;
-
-       /* fbdev */
-       struct {
-               struct drm_framebuffer *fb;
-               struct drm_fb_helper helper;
-       } fb;
 };
 
 struct bochs_bo {
@@ -121,8 +115,9 @@ int bochs_hw_init(struct drm_device *dev);
 void bochs_hw_fini(struct drm_device *dev);
 
 void bochs_hw_setmode(struct bochs_device *bochs,
-                     struct drm_display_mode *mode,
-                     const struct drm_format_info *format);
+                     struct drm_display_mode *mode);
+void bochs_hw_setformat(struct bochs_device *bochs,
+                       const struct drm_format_info *format);
 void bochs_hw_setbase(struct bochs_device *bochs,
                      int x, int y, u64 addr);
 int bochs_hw_load_edid(struct bochs_device *bochs);
@@ -141,15 +136,19 @@ int bochs_dumb_create(struct drm_file *file, struct drm_device *dev,
 int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
                           uint32_t handle, uint64_t *offset);
 
-int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag, u64 *gpu_addr);
+int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag);
 int bochs_bo_unpin(struct bochs_bo *bo);
 
+int bochs_gem_prime_pin(struct drm_gem_object *obj);
+void bochs_gem_prime_unpin(struct drm_gem_object *obj);
+void *bochs_gem_prime_vmap(struct drm_gem_object *obj);
+void bochs_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
+int bochs_gem_prime_mmap(struct drm_gem_object *obj,
+                        struct vm_area_struct *vma);
+
 /* bochs_kms.c */
 int bochs_kms_init(struct bochs_device *bochs);
 void bochs_kms_fini(struct bochs_device *bochs);
 
 /* bochs_fbdev.c */
-int bochs_fbdev_init(struct bochs_device *bochs);
-void bochs_fbdev_fini(struct bochs_device *bochs);
-
 extern const struct drm_mode_config_funcs bochs_mode_funcs;
index f3dd66ae990aebc8a9518127f74d63c1ee98b252..cea42ac64d7e952c413bf06bbdd5dc6a538e7c50 100644 (file)
@@ -16,10 +16,6 @@ static int bochs_modeset = -1;
 module_param_named(modeset, bochs_modeset, int, 0444);
 MODULE_PARM_DESC(modeset, "enable/disable kernel modesetting");
 
-static bool enable_fbdev = true;
-module_param_named(fbdev, enable_fbdev, bool, 0444);
-MODULE_PARM_DESC(fbdev, "register fbdev device");
-
 /* ---------------------------------------------------------------------- */
 /* drm interface                                                          */
 
@@ -27,7 +23,6 @@ static void bochs_unload(struct drm_device *dev)
 {
        struct bochs_device *bochs = dev->dev_private;
 
-       bochs_fbdev_fini(bochs);
        bochs_kms_fini(bochs);
        bochs_mm_fini(bochs);
        bochs_hw_fini(dev);
@@ -58,9 +53,6 @@ static int bochs_load(struct drm_device *dev)
        if (ret)
                goto err;
 
-       if (enable_fbdev)
-               bochs_fbdev_init(bochs);
-
        return 0;
 
 err:
@@ -81,7 +73,8 @@ static const struct file_operations bochs_fops = {
 };
 
 static struct drm_driver bochs_driver = {
-       .driver_features        = DRIVER_GEM | DRIVER_MODESET,
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC |
+                                 DRIVER_PRIME,
        .fops                   = &bochs_fops,
        .name                   = "bochs-drm",
        .desc                   = "bochs dispi vga interface (qemu stdvga)",
@@ -91,6 +84,14 @@ static struct drm_driver bochs_driver = {
        .gem_free_object_unlocked = bochs_gem_free_object,
        .dumb_create            = bochs_dumb_create,
        .dumb_map_offset        = bochs_dumb_mmap_offset,
+
+       .gem_prime_export = drm_gem_prime_export,
+       .gem_prime_import = drm_gem_prime_import,
+       .gem_prime_pin = bochs_gem_prime_pin,
+       .gem_prime_unpin = bochs_gem_prime_unpin,
+       .gem_prime_vmap = bochs_gem_prime_vmap,
+       .gem_prime_vunmap = bochs_gem_prime_vunmap,
+       .gem_prime_mmap = bochs_gem_prime_mmap,
 };
 
 /* ---------------------------------------------------------------------- */
@@ -101,27 +102,16 @@ static int bochs_pm_suspend(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct drm_device *drm_dev = pci_get_drvdata(pdev);
-       struct bochs_device *bochs = drm_dev->dev_private;
-
-       drm_kms_helper_poll_disable(drm_dev);
-
-       drm_fb_helper_set_suspend_unlocked(&bochs->fb.helper, 1);
 
-       return 0;
+       return drm_mode_config_helper_suspend(drm_dev);
 }
 
 static int bochs_pm_resume(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct drm_device *drm_dev = pci_get_drvdata(pdev);
-       struct bochs_device *bochs = drm_dev->dev_private;
-
-       drm_helper_resume_force_mode(drm_dev);
 
-       drm_fb_helper_set_suspend_unlocked(&bochs->fb.helper, 0);
-
-       drm_kms_helper_poll_enable(drm_dev);
-       return 0;
+       return drm_mode_config_helper_resume(drm_dev);
 }
 #endif
 
@@ -165,6 +155,7 @@ static int bochs_pci_probe(struct pci_dev *pdev,
        if (ret)
                goto err_unload;
 
+       drm_fbdev_generic_setup(dev, 32);
        return ret;
 
 err_unload:
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c
deleted file mode 100644 (file)
index dd3c7df..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "bochs.h"
-#include <drm/drm_gem_framebuffer_helper.h>
-
-/* ---------------------------------------------------------------------- */
-
-static int bochsfb_mmap(struct fb_info *info,
-                       struct vm_area_struct *vma)
-{
-       struct drm_fb_helper *fb_helper = info->par;
-       struct bochs_bo *bo = gem_to_bochs_bo(fb_helper->fb->obj[0]);
-
-       return ttm_fbdev_mmap(vma, &bo->bo);
-}
-
-static struct fb_ops bochsfb_ops = {
-       .owner = THIS_MODULE,
-       DRM_FB_HELPER_DEFAULT_OPS,
-       .fb_fillrect = drm_fb_helper_cfb_fillrect,
-       .fb_copyarea = drm_fb_helper_cfb_copyarea,
-       .fb_imageblit = drm_fb_helper_cfb_imageblit,
-       .fb_mmap = bochsfb_mmap,
-};
-
-static int bochsfb_create_object(struct bochs_device *bochs,
-                                const struct drm_mode_fb_cmd2 *mode_cmd,
-                                struct drm_gem_object **gobj_p)
-{
-       struct drm_device *dev = bochs->dev;
-       struct drm_gem_object *gobj;
-       u32 size;
-       int ret = 0;
-
-       size = mode_cmd->pitches[0] * mode_cmd->height;
-       ret = bochs_gem_create(dev, size, true, &gobj);
-       if (ret)
-               return ret;
-
-       *gobj_p = gobj;
-       return ret;
-}
-
-static int bochsfb_create(struct drm_fb_helper *helper,
-                         struct drm_fb_helper_surface_size *sizes)
-{
-       struct bochs_device *bochs =
-               container_of(helper, struct bochs_device, fb.helper);
-       struct fb_info *info;
-       struct drm_framebuffer *fb;
-       struct drm_mode_fb_cmd2 mode_cmd;
-       struct drm_gem_object *gobj = NULL;
-       struct bochs_bo *bo = NULL;
-       int size, ret;
-
-       if (sizes->surface_bpp != 32)
-               return -EINVAL;
-
-       mode_cmd.width = sizes->surface_width;
-       mode_cmd.height = sizes->surface_height;
-       mode_cmd.pitches[0] = sizes->surface_width * 4;
-       mode_cmd.pixel_format = DRM_FORMAT_HOST_XRGB8888;
-       size = mode_cmd.pitches[0] * mode_cmd.height;
-
-       /* alloc, pin & map bo */
-       ret = bochsfb_create_object(bochs, &mode_cmd, &gobj);
-       if (ret) {
-               DRM_ERROR("failed to create fbcon backing object %d\n", ret);
-               return ret;
-       }
-
-       bo = gem_to_bochs_bo(gobj);
-
-       ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
-       if (ret)
-               return ret;
-
-       ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL);
-       if (ret) {
-               DRM_ERROR("failed to pin fbcon\n");
-               ttm_bo_unreserve(&bo->bo);
-               return ret;
-       }
-
-       ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages,
-                         &bo->kmap);
-       if (ret) {
-               DRM_ERROR("failed to kmap fbcon\n");
-               ttm_bo_unreserve(&bo->bo);
-               return ret;
-       }
-
-       ttm_bo_unreserve(&bo->bo);
-
-       /* init fb device */
-       info = drm_fb_helper_alloc_fbi(helper);
-       if (IS_ERR(info)) {
-               DRM_ERROR("Failed to allocate fbi: %ld\n", PTR_ERR(info));
-               return PTR_ERR(info);
-       }
-
-       info->par = &bochs->fb.helper;
-
-       fb = drm_gem_fbdev_fb_create(bochs->dev, sizes, 0, gobj, NULL);
-       if (IS_ERR(fb)) {
-               DRM_ERROR("Failed to create framebuffer: %ld\n", PTR_ERR(fb));
-               return PTR_ERR(fb);
-       }
-
-       /* setup helper */
-       bochs->fb.helper.fb = fb;
-
-       strcpy(info->fix.id, "bochsdrmfb");
-
-       info->fbops = &bochsfb_ops;
-
-       drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
-       drm_fb_helper_fill_var(info, &bochs->fb.helper, sizes->fb_width,
-                              sizes->fb_height);
-
-       info->screen_base = bo->kmap.virtual;
-       info->screen_size = size;
-
-       drm_vma_offset_remove(&bo->bo.bdev->vma_manager, &bo->bo.vma_node);
-       info->fix.smem_start = 0;
-       info->fix.smem_len = size;
-       return 0;
-}
-
-static const struct drm_fb_helper_funcs bochs_fb_helper_funcs = {
-       .fb_probe = bochsfb_create,
-};
-
-static struct drm_framebuffer *
-bochs_gem_fb_create(struct drm_device *dev, struct drm_file *file,
-                   const struct drm_mode_fb_cmd2 *mode_cmd)
-{
-       if (mode_cmd->pixel_format != DRM_FORMAT_XRGB8888 &&
-           mode_cmd->pixel_format != DRM_FORMAT_BGRX8888)
-               return ERR_PTR(-EINVAL);
-
-       return drm_gem_fb_create(dev, file, mode_cmd);
-}
-
-const struct drm_mode_config_funcs bochs_mode_funcs = {
-       .fb_create = bochs_gem_fb_create,
-};
-
-int bochs_fbdev_init(struct bochs_device *bochs)
-{
-       return drm_fb_helper_fbdev_setup(bochs->dev, &bochs->fb.helper,
-                                        &bochs_fb_helper_funcs, 32, 1);
-}
-
-void bochs_fbdev_fini(struct bochs_device *bochs)
-{
-       drm_fb_helper_fbdev_teardown(bochs->dev);
-}
index c90a0d492fd5973fe53f0430919e0fa8f2883368..3e04b2f0ec08037db6a2b6ce4f1c0630bf2c4266 100644 (file)
@@ -86,9 +86,16 @@ static int bochs_get_edid_block(void *data, u8 *buf,
 
 int bochs_hw_load_edid(struct bochs_device *bochs)
 {
+       u8 header[8];
+
        if (!bochs->mmio)
                return -1;
 
+       /* check header to detect whenever edid support is enabled in qemu */
+       bochs_get_edid_block(bochs, header, 0, ARRAY_SIZE(header));
+       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);
@@ -197,8 +204,7 @@ void bochs_hw_fini(struct drm_device *dev)
 }
 
 void bochs_hw_setmode(struct bochs_device *bochs,
-                     struct drm_display_mode *mode,
-                     const struct drm_format_info *format)
+                     struct drm_display_mode *mode)
 {
        bochs->xres = mode->hdisplay;
        bochs->yres = mode->vdisplay;
@@ -206,12 +212,8 @@ void bochs_hw_setmode(struct bochs_device *bochs,
        bochs->stride = mode->hdisplay * (bochs->bpp / 8);
        bochs->yres_virtual = bochs->fb_size / bochs->stride;
 
-       DRM_DEBUG_DRIVER("%dx%d @ %d bpp, format %c%c%c%c, vy %d\n",
+       DRM_DEBUG_DRIVER("%dx%d @ %d bpp, vy %d\n",
                         bochs->xres, bochs->yres, bochs->bpp,
-                        (format->format >>  0) & 0xff,
-                        (format->format >>  8) & 0xff,
-                        (format->format >> 16) & 0xff,
-                        (format->format >> 24) & 0xff,
                         bochs->yres_virtual);
 
        bochs_vga_writeb(bochs, 0x3c0, 0x20); /* unblank */
@@ -229,6 +231,16 @@ void bochs_hw_setmode(struct bochs_device *bochs,
 
        bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE,
                          VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
+}
+
+void bochs_hw_setformat(struct bochs_device *bochs,
+                       const struct drm_format_info *format)
+{
+       DRM_DEBUG_DRIVER("format %c%c%c%c\n",
+                        (format->format >>  0) & 0xff,
+                        (format->format >>  8) & 0xff,
+                        (format->format >> 16) & 0xff,
+                        (format->format >> 24) & 0xff);
 
        switch (format->format) {
        case DRM_FORMAT_XRGB8888:
index f87c284dd93d896c720172e66bb9b8ada9c6e2a8..e9d5dbc34676af19b3d0bb0eb5bd6dd8445d5232 100644 (file)
@@ -6,7 +6,10 @@
  */
 
 #include "bochs.h"
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_atomic_uapi.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 
 static int defx = 1024;
 static int defy = 768;
@@ -18,115 +21,51 @@ MODULE_PARM_DESC(defy, "default y resolution");
 
 /* ---------------------------------------------------------------------- */
 
-static void bochs_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-       switch (mode) {
-       case DRM_MODE_DPMS_ON:
-       case DRM_MODE_DPMS_STANDBY:
-       case DRM_MODE_DPMS_SUSPEND:
-       case DRM_MODE_DPMS_OFF:
-       default:
-               return;
-       }
-}
-
-static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
-                                   struct drm_framebuffer *old_fb)
-{
-       struct bochs_device *bochs =
-               container_of(crtc, struct bochs_device, crtc);
-       struct bochs_bo *bo;
-       u64 gpu_addr = 0;
-       int ret;
-
-       if (old_fb) {
-               bo = gem_to_bochs_bo(old_fb->obj[0]);
-               ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
-               if (ret) {
-                       DRM_ERROR("failed to reserve old_fb bo\n");
-               } else {
-                       bochs_bo_unpin(bo);
-                       ttm_bo_unreserve(&bo->bo);
-               }
-       }
-
-       if (WARN_ON(crtc->primary->fb == NULL))
-               return -EINVAL;
-
-       bo = gem_to_bochs_bo(crtc->primary->fb->obj[0]);
-       ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
-       if (ret)
-               return ret;
-
-       ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
-       if (ret) {
-               ttm_bo_unreserve(&bo->bo);
-               return ret;
-       }
-
-       ttm_bo_unreserve(&bo->bo);
-       bochs_hw_setbase(bochs, x, y, gpu_addr);
-       return 0;
-}
-
-static int bochs_crtc_mode_set(struct drm_crtc *crtc,
-                              struct drm_display_mode *mode,
-                              struct drm_display_mode *adjusted_mode,
-                              int x, int y, struct drm_framebuffer *old_fb)
+static void bochs_crtc_mode_set_nofb(struct drm_crtc *crtc)
 {
        struct bochs_device *bochs =
                container_of(crtc, struct bochs_device, crtc);
 
-       if (WARN_ON(crtc->primary->fb == NULL))
-               return -EINVAL;
-
-       bochs_hw_setmode(bochs, mode, crtc->primary->fb->format);
-       bochs_crtc_mode_set_base(crtc, x, y, old_fb);
-       return 0;
+       bochs_hw_setmode(bochs, &crtc->mode);
 }
 
-static void bochs_crtc_prepare(struct drm_crtc *crtc)
+static void bochs_crtc_atomic_enable(struct drm_crtc *crtc,
+                                    struct drm_crtc_state *old_crtc_state)
 {
 }
 
-static void bochs_crtc_commit(struct drm_crtc *crtc)
+static void bochs_crtc_atomic_flush(struct drm_crtc *crtc,
+                                   struct drm_crtc_state *old_crtc_state)
 {
-}
+       struct drm_device *dev = crtc->dev;
+       struct drm_pending_vblank_event *event;
 
-static int bochs_crtc_page_flip(struct drm_crtc *crtc,
-                               struct drm_framebuffer *fb,
-                               struct drm_pending_vblank_event *event,
-                               uint32_t page_flip_flags,
-                               struct drm_modeset_acquire_ctx *ctx)
-{
-       struct bochs_device *bochs =
-               container_of(crtc, struct bochs_device, crtc);
-       struct drm_framebuffer *old_fb = crtc->primary->fb;
-       unsigned long irqflags;
+       if (crtc->state && crtc->state->event) {
+               unsigned long irqflags;
 
-       crtc->primary->fb = fb;
-       bochs_crtc_mode_set_base(crtc, 0, 0, old_fb);
-       if (event) {
-               spin_lock_irqsave(&bochs->dev->event_lock, irqflags);
+               spin_lock_irqsave(&dev->event_lock, irqflags);
+               event = crtc->state->event;
+               crtc->state->event = NULL;
                drm_crtc_send_vblank_event(crtc, event);
-               spin_unlock_irqrestore(&bochs->dev->event_lock, irqflags);
+               spin_unlock_irqrestore(&dev->event_lock, irqflags);
        }
-       return 0;
 }
 
+
 /* These provide the minimum set of functions required to handle a CRTC */
 static const struct drm_crtc_funcs bochs_crtc_funcs = {
-       .set_config = drm_crtc_helper_set_config,
+       .set_config = drm_atomic_helper_set_config,
        .destroy = drm_crtc_cleanup,
-       .page_flip = bochs_crtc_page_flip,
+       .page_flip = drm_atomic_helper_page_flip,
+       .reset = drm_atomic_helper_crtc_reset,
+       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 };
 
 static const struct drm_crtc_helper_funcs bochs_helper_funcs = {
-       .dpms = bochs_crtc_dpms,
-       .mode_set = bochs_crtc_mode_set,
-       .mode_set_base = bochs_crtc_mode_set_base,
-       .prepare = bochs_crtc_prepare,
-       .commit = bochs_crtc_commit,
+       .mode_set_nofb = bochs_crtc_mode_set_nofb,
+       .atomic_enable = bochs_crtc_atomic_enable,
+       .atomic_flush = bochs_crtc_atomic_flush,
 };
 
 static const uint32_t bochs_formats[] = {
@@ -134,6 +73,59 @@ static const uint32_t bochs_formats[] = {
        DRM_FORMAT_BGRX8888,
 };
 
+static void bochs_plane_atomic_update(struct drm_plane *plane,
+                                     struct drm_plane_state *old_state)
+{
+       struct bochs_device *bochs = plane->dev->dev_private;
+       struct bochs_bo *bo;
+
+       if (!plane->state->fb)
+               return;
+       bo = gem_to_bochs_bo(plane->state->fb->obj[0]);
+       bochs_hw_setbase(bochs,
+                        plane->state->crtc_x,
+                        plane->state->crtc_y,
+                        bo->bo.offset);
+       bochs_hw_setformat(bochs, plane->state->fb->format);
+}
+
+static int bochs_plane_prepare_fb(struct drm_plane *plane,
+                               struct drm_plane_state *new_state)
+{
+       struct bochs_bo *bo;
+
+       if (!new_state->fb)
+               return 0;
+       bo = gem_to_bochs_bo(new_state->fb->obj[0]);
+       return bochs_bo_pin(bo, TTM_PL_FLAG_VRAM);
+}
+
+static void bochs_plane_cleanup_fb(struct drm_plane *plane,
+                                  struct drm_plane_state *old_state)
+{
+       struct bochs_bo *bo;
+
+       if (!old_state->fb)
+               return;
+       bo = gem_to_bochs_bo(old_state->fb->obj[0]);
+       bochs_bo_unpin(bo);
+}
+
+static const struct drm_plane_helper_funcs bochs_plane_helper_funcs = {
+       .atomic_update = bochs_plane_atomic_update,
+       .prepare_fb = bochs_plane_prepare_fb,
+       .cleanup_fb = bochs_plane_cleanup_fb,
+};
+
+static const struct drm_plane_funcs bochs_plane_funcs = {
+       .update_plane   = drm_atomic_helper_update_plane,
+       .disable_plane  = drm_atomic_helper_disable_plane,
+       .destroy        = drm_primary_helper_destroy,
+       .reset          = drm_atomic_helper_plane_reset,
+       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
 static struct drm_plane *bochs_primary_plane(struct drm_device *dev)
 {
        struct drm_plane *primary;
@@ -146,16 +138,17 @@ static struct drm_plane *bochs_primary_plane(struct drm_device *dev)
        }
 
        ret = drm_universal_plane_init(dev, primary, 0,
-                                      &drm_primary_helper_funcs,
+                                      &bochs_plane_funcs,
                                       bochs_formats,
                                       ARRAY_SIZE(bochs_formats),
                                       NULL,
                                       DRM_PLANE_TYPE_PRIMARY, NULL);
        if (ret) {
                kfree(primary);
-               primary = NULL;
+               return NULL;
        }
 
+       drm_plane_helper_add(primary, &bochs_plane_helper_funcs);
        return primary;
 }
 
@@ -170,31 +163,6 @@ static void bochs_crtc_init(struct drm_device *dev)
        drm_crtc_helper_add(crtc, &bochs_helper_funcs);
 }
 
-static void bochs_encoder_mode_set(struct drm_encoder *encoder,
-                                  struct drm_display_mode *mode,
-                                  struct drm_display_mode *adjusted_mode)
-{
-}
-
-static void bochs_encoder_dpms(struct drm_encoder *encoder, int state)
-{
-}
-
-static void bochs_encoder_prepare(struct drm_encoder *encoder)
-{
-}
-
-static void bochs_encoder_commit(struct drm_encoder *encoder)
-{
-}
-
-static const struct drm_encoder_helper_funcs bochs_encoder_helper_funcs = {
-       .dpms = bochs_encoder_dpms,
-       .mode_set = bochs_encoder_mode_set,
-       .prepare = bochs_encoder_prepare,
-       .commit = bochs_encoder_commit,
-};
-
 static const struct drm_encoder_funcs bochs_encoder_encoder_funcs = {
        .destroy = drm_encoder_cleanup,
 };
@@ -207,7 +175,6 @@ static void bochs_encoder_init(struct drm_device *dev)
        encoder->possible_crtcs = 0x1;
        drm_encoder_init(dev, encoder, &bochs_encoder_encoder_funcs,
                         DRM_MODE_ENCODER_DAC, NULL);
-       drm_encoder_helper_add(encoder, &bochs_encoder_helper_funcs);
 }
 
 
@@ -266,6 +233,9 @@ static const struct drm_connector_funcs bochs_connector_connector_funcs = {
        .dpms = drm_helper_connector_dpms,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .destroy = drm_connector_cleanup,
+       .reset = drm_atomic_helper_connector_reset,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
 static void bochs_connector_init(struct drm_device *dev)
@@ -287,6 +257,22 @@ static void bochs_connector_init(struct drm_device *dev)
        }
 }
 
+static struct drm_framebuffer *
+bochs_gem_fb_create(struct drm_device *dev, struct drm_file *file,
+                   const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+       if (mode_cmd->pixel_format != DRM_FORMAT_XRGB8888 &&
+           mode_cmd->pixel_format != DRM_FORMAT_BGRX8888)
+               return ERR_PTR(-EINVAL);
+
+       return drm_gem_fb_create(dev, file, mode_cmd);
+}
+
+const struct drm_mode_config_funcs bochs_mode_funcs = {
+       .fb_create = bochs_gem_fb_create,
+       .atomic_check = drm_atomic_helper_check,
+       .atomic_commit = drm_atomic_helper_commit,
+};
 
 int bochs_kms_init(struct bochs_device *bochs)
 {
@@ -309,6 +295,8 @@ int bochs_kms_init(struct bochs_device *bochs)
        drm_connector_attach_encoder(&bochs->connector,
                                          &bochs->encoder);
 
+       drm_mode_config_reset(bochs->dev);
+
        return 0;
 }
 
index 0980411e41bf0d7d61fa173b4199253795aa2966..641a33f134eeb2f5ef85fee1bf54a8ab8219593a 100644 (file)
@@ -210,33 +210,28 @@ static void bochs_ttm_placement(struct bochs_bo *bo, int domain)
        bo->placement.num_busy_placement = c;
 }
 
-static inline u64 bochs_bo_gpu_offset(struct bochs_bo *bo)
-{
-       return bo->bo.offset;
-}
-
-int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag, u64 *gpu_addr)
+int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag)
 {
        struct ttm_operation_ctx ctx = { false, false };
        int i, ret;
 
        if (bo->pin_count) {
                bo->pin_count++;
-               if (gpu_addr)
-                       *gpu_addr = bochs_bo_gpu_offset(bo);
                return 0;
        }
 
        bochs_ttm_placement(bo, pl_flag);
        for (i = 0; i < bo->placement.num_placement; i++)
                bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
+       ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
+       if (ret)
+               return ret;
        ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
+       ttm_bo_unreserve(&bo->bo);
        if (ret)
                return ret;
 
        bo->pin_count = 1;
-       if (gpu_addr)
-               *gpu_addr = bochs_bo_gpu_offset(bo);
        return 0;
 }
 
@@ -256,7 +251,11 @@ int bochs_bo_unpin(struct bochs_bo *bo)
 
        for (i = 0; i < bo->placement.num_placement; i++)
                bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
+       ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
+       if (ret)
+               return ret;
        ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
+       ttm_bo_unreserve(&bo->bo);
        if (ret)
                return ret;
 
@@ -396,3 +395,52 @@ int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
        drm_gem_object_put_unlocked(obj);
        return 0;
 }
+
+/* ---------------------------------------------------------------------- */
+
+int bochs_gem_prime_pin(struct drm_gem_object *obj)
+{
+       struct bochs_bo *bo = gem_to_bochs_bo(obj);
+
+       return bochs_bo_pin(bo, TTM_PL_FLAG_VRAM);
+}
+
+void bochs_gem_prime_unpin(struct drm_gem_object *obj)
+{
+       struct bochs_bo *bo = gem_to_bochs_bo(obj);
+
+       bochs_bo_unpin(bo);
+}
+
+void *bochs_gem_prime_vmap(struct drm_gem_object *obj)
+{
+       struct bochs_bo *bo = gem_to_bochs_bo(obj);
+       bool is_iomem;
+       int ret;
+
+       ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM);
+       if (ret)
+               return NULL;
+       ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
+       if (ret) {
+               bochs_bo_unpin(bo);
+               return NULL;
+       }
+       return ttm_kmap_obj_virtual(&bo->kmap, &is_iomem);
+}
+
+void bochs_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
+{
+       struct bochs_bo *bo = gem_to_bochs_bo(obj);
+
+       ttm_bo_kunmap(&bo->kmap);
+       bochs_bo_unpin(bo);
+}
+
+int bochs_gem_prime_mmap(struct drm_gem_object *obj,
+                        struct vm_area_struct *vma)
+{
+       struct bochs_bo *bo = gem_to_bochs_bo(obj);
+
+       return ttm_fbdev_mmap(vma, &bo->bo);
+}
index 73d8ccb977427a5b995081db91de5126165565db..2b6e0832d1cfd50f165ad775efccad6c96879d67 100644 (file)
@@ -395,7 +395,7 @@ static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
 #ifdef CONFIG_DRM_I2C_ADV7533
 void adv7533_dsi_power_on(struct adv7511 *adv);
 void adv7533_dsi_power_off(struct adv7511 *adv);
-void adv7533_mode_set(struct adv7511 *adv, struct drm_display_mode *mode);
+void adv7533_mode_set(struct adv7511 *adv, const struct drm_display_mode *mode);
 int adv7533_patch_registers(struct adv7511 *adv);
 int adv7533_patch_cec_registers(struct adv7511 *adv);
 int adv7533_attach_dsi(struct adv7511 *adv);
@@ -411,7 +411,7 @@ static inline void adv7533_dsi_power_off(struct adv7511 *adv)
 }
 
 static inline void adv7533_mode_set(struct adv7511 *adv,
-                                   struct drm_display_mode *mode)
+                                   const struct drm_display_mode *mode)
 {
 }
 
index 85c2d407a52e1a5476b3269d13655606d10478fd..d0e98caa2e2a1d95f38dce89213cae84cde6490a 100644 (file)
@@ -676,8 +676,8 @@ static enum drm_mode_status adv7511_mode_valid(struct adv7511 *adv7511,
 }
 
 static void adv7511_mode_set(struct adv7511 *adv7511,
-                            struct drm_display_mode *mode,
-                            struct drm_display_mode *adj_mode)
+                            const struct drm_display_mode *mode,
+                            const struct drm_display_mode *adj_mode)
 {
        unsigned int low_refresh_rate;
        unsigned int hsync_polarity = 0;
@@ -839,8 +839,8 @@ static void adv7511_bridge_disable(struct drm_bridge *bridge)
 }
 
 static void adv7511_bridge_mode_set(struct drm_bridge *bridge,
-                                   struct drm_display_mode *mode,
-                                   struct drm_display_mode *adj_mode)
+                                   const struct drm_display_mode *mode,
+                                   const struct drm_display_mode *adj_mode)
 {
        struct adv7511 *adv = bridge_to_adv7511(bridge);
 
index 185b6d84216653003bdd0cd26df89bd6e598b3ad..5d5e7d9eded2f4bda06c8baf8ffd4070a5786207 100644 (file)
@@ -108,7 +108,7 @@ void adv7533_dsi_power_off(struct adv7511 *adv)
        regmap_write(adv->regmap_cec, 0x27, 0x0b);
 }
 
-void adv7533_mode_set(struct adv7511 *adv, struct drm_display_mode *mode)
+void adv7533_mode_set(struct adv7511 *adv, const struct drm_display_mode *mode)
 {
        struct mipi_dsi_device *dsi = adv->dsi;
        int lanes, ret;
index f8433c93f4634620c177c77ac67aea70337288ec..4cf7bc17ae149699c653936baebd41b1ee1fc5b4 100644 (file)
@@ -1082,8 +1082,8 @@ static void anx78xx_bridge_disable(struct drm_bridge *bridge)
 }
 
 static void anx78xx_bridge_mode_set(struct drm_bridge *bridge,
-                                   struct drm_display_mode *mode,
-                                   struct drm_display_mode *adjusted_mode)
+                               const struct drm_display_mode *mode,
+                               const struct drm_display_mode *adjusted_mode)
 {
        struct anx78xx *anx78xx = bridge_to_anx78xx(bridge);
        struct hdmi_avi_infoframe frame;
@@ -1094,8 +1094,9 @@ static void anx78xx_bridge_mode_set(struct drm_bridge *bridge,
 
        mutex_lock(&anx78xx->lock);
 
-       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode,
-                                                      false);
+       err = drm_hdmi_avi_infoframe_from_display_mode(&frame,
+                                                      &anx78xx->connector,
+                                                      adjusted_mode);
        if (err) {
                DRM_ERROR("Failed to setup AVI infoframe: %d\n", err);
                goto unlock;
index 753e96129ab7a63355d3d50e322780f563e76684..4d5b475858348f9aaf65e81493b241faca560991 100644 (file)
@@ -1361,8 +1361,8 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge)
 }
 
 static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge,
-                                       struct drm_display_mode *orig_mode,
-                                       struct drm_display_mode *mode)
+                               const struct drm_display_mode *orig_mode,
+                               const struct drm_display_mode *mode)
 {
        struct analogix_dp_device *dp = bridge->driver_private;
        struct drm_display_info *display_info = &dp->connector.display_info;
index f56c92f7af7c484b90fcbac98b9177e36177b949..ae8fc597eb381b2551e8beeebdf8eb32a5e2098d 100644 (file)
 #include <drm/drm_bridge.h>
 #include <drm/drm_panel.h>
 
+#include <linux/gpio/consumer.h>
 #include <linux/of_graph.h>
 
 struct lvds_encoder {
        struct drm_bridge bridge;
        struct drm_bridge *panel_bridge;
+       struct gpio_desc *powerdown_gpio;
 };
 
 static int lvds_encoder_attach(struct drm_bridge *bridge)
@@ -28,54 +30,85 @@ static int lvds_encoder_attach(struct drm_bridge *bridge)
                                 bridge);
 }
 
+static void lvds_encoder_enable(struct drm_bridge *bridge)
+{
+       struct lvds_encoder *lvds_encoder = container_of(bridge,
+                                                        struct lvds_encoder,
+                                                        bridge);
+
+       if (lvds_encoder->powerdown_gpio)
+               gpiod_set_value_cansleep(lvds_encoder->powerdown_gpio, 0);
+}
+
+static void lvds_encoder_disable(struct drm_bridge *bridge)
+{
+       struct lvds_encoder *lvds_encoder = container_of(bridge,
+                                                        struct lvds_encoder,
+                                                        bridge);
+
+       if (lvds_encoder->powerdown_gpio)
+               gpiod_set_value_cansleep(lvds_encoder->powerdown_gpio, 1);
+}
+
 static struct drm_bridge_funcs funcs = {
        .attach = lvds_encoder_attach,
+       .enable = lvds_encoder_enable,
+       .disable = lvds_encoder_disable,
 };
 
 static int lvds_encoder_probe(struct platform_device *pdev)
 {
+       struct device *dev = &pdev->dev;
        struct device_node *port;
        struct device_node *endpoint;
        struct device_node *panel_node;
        struct drm_panel *panel;
        struct lvds_encoder *lvds_encoder;
 
-       lvds_encoder = devm_kzalloc(&pdev->dev, sizeof(*lvds_encoder),
-                                   GFP_KERNEL);
+       lvds_encoder = devm_kzalloc(dev, sizeof(*lvds_encoder), GFP_KERNEL);
        if (!lvds_encoder)
                return -ENOMEM;
 
+       lvds_encoder->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown",
+                                                              GPIOD_OUT_HIGH);
+       if (IS_ERR(lvds_encoder->powerdown_gpio)) {
+               int err = PTR_ERR(lvds_encoder->powerdown_gpio);
+
+               if (err != -EPROBE_DEFER)
+                       dev_err(dev, "powerdown GPIO failure: %d\n", err);
+               return err;
+       }
+
        /* Locate the panel DT node. */
-       port = of_graph_get_port_by_id(pdev->dev.of_node, 1);
+       port = of_graph_get_port_by_id(dev->of_node, 1);
        if (!port) {
-               dev_dbg(&pdev->dev, "port 1 not found\n");
+               dev_dbg(dev, "port 1 not found\n");
                return -ENXIO;
        }
 
        endpoint = of_get_child_by_name(port, "endpoint");
        of_node_put(port);
        if (!endpoint) {
-               dev_dbg(&pdev->dev, "no endpoint for port 1\n");
+               dev_dbg(dev, "no endpoint for port 1\n");
                return -ENXIO;
        }
 
        panel_node = of_graph_get_remote_port_parent(endpoint);
        of_node_put(endpoint);
        if (!panel_node) {
-               dev_dbg(&pdev->dev, "no remote endpoint for port 1\n");
+               dev_dbg(dev, "no remote endpoint for port 1\n");
                return -ENXIO;
        }
 
        panel = of_drm_find_panel(panel_node);
        of_node_put(panel_node);
        if (IS_ERR(panel)) {
-               dev_dbg(&pdev->dev, "panel not found, deferring probe\n");
+               dev_dbg(dev, "panel not found, deferring probe\n");
                return PTR_ERR(panel);
        }
 
        lvds_encoder->panel_bridge =
-               devm_drm_panel_bridge_add(&pdev->dev,
-                                         panel, DRM_MODE_CONNECTOR_LVDS);
+               devm_drm_panel_bridge_add(dev, panel, DRM_MODE_CONNECTOR_LVDS);
        if (IS_ERR(lvds_encoder->panel_bridge))
                return PTR_ERR(lvds_encoder->panel_bridge);
 
@@ -83,7 +116,7 @@ static int lvds_encoder_probe(struct platform_device *pdev)
         * but we need a bridge attached to our of_node for our user
         * to look up.
         */
-       lvds_encoder->bridge.of_node = pdev->dev.of_node;
+       lvds_encoder->bridge.of_node = dev->of_node;
        lvds_encoder->bridge.funcs = &funcs;
        drm_bridge_add(&lvds_encoder->bridge);
 
index 7cbaba213ef693d11c430533df45c838a56c1229..37baa79e95c3e4da4dc13e91962581ee415cb5a9 100644 (file)
@@ -134,8 +134,8 @@ static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
 };
 
 /**
- * drm_panel_bridge_add - Creates a drm_bridge and drm_connector that
- * just calls the appropriate functions from drm_panel.
+ * drm_panel_bridge_add - Creates a &drm_bridge and &drm_connector that
+ * just calls the appropriate functions from &drm_panel.
  *
  * @panel: The drm_panel being wrapped.  Must be non-NULL.
  * @connector_type: The DRM_MODE_CONNECTOR_* for the connector to be
@@ -149,9 +149,12 @@ static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
  * passed to drm_bridge_attach().  The drm_panel_prepare() and related
  * functions can be dropped from the encoder driver (they're now
  * called by the KMS helpers before calling into the encoder), along
- * with connector creation.  When done with the bridge,
- * drm_bridge_detach() should be called as normal, then
+ * with connector creation.  When done with the bridge (after
+ * drm_mode_config_cleanup() if the bridge has already been attached), then
  * drm_panel_bridge_remove() to free it.
+ *
+ * See devm_drm_panel_bridge_add() for an automatically manged version of this
+ * function.
  */
 struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
                                        u32 connector_type)
@@ -210,6 +213,17 @@ static void devm_drm_panel_bridge_release(struct device *dev, void *res)
        drm_panel_bridge_remove(*bridge);
 }
 
+/**
+ * devm_drm_panel_bridge_add - Creates a managed &drm_bridge and &drm_connector
+ * that just calls the appropriate functions from &drm_panel.
+ * @dev: device to tie the bridge lifetime to
+ * @panel: The drm_panel being wrapped.  Must be non-NULL.
+ * @connector_type: The DRM_MODE_CONNECTOR_* for the connector to be
+ * created.
+ *
+ * This is the managed version of drm_panel_bridge_add() which automatically
+ * calls drm_panel_bridge_remove() when @dev is unbound.
+ */
 struct drm_bridge *devm_drm_panel_bridge_add(struct device *dev,
                                             struct drm_panel *panel,
                                             u32 connector_type)
index bfa902013aa42e06f3eff686d25ba593cd9b2b89..a5d58f7035c157cda4aeb27d7ecb32c0b2c2d9d3 100644 (file)
@@ -232,8 +232,8 @@ static void sii902x_bridge_enable(struct drm_bridge *bridge)
 }
 
 static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
-                                   struct drm_display_mode *mode,
-                                   struct drm_display_mode *adj)
+                                   const struct drm_display_mode *mode,
+                                   const struct drm_display_mode *adj)
 {
        struct sii902x *sii902x = bridge_to_sii902x(bridge);
        struct regmap *regmap = sii902x->regmap;
@@ -258,7 +258,8 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
        if (ret)
                return;
 
-       ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj, false);
+       ret = drm_hdmi_avi_infoframe_from_display_mode(&frame,
+                                                      &sii902x->connector, adj);
        if (ret < 0) {
                DRM_ERROR("couldn't fill AVI infoframe\n");
                return;
index a6e8f4591e636241c6f1e8515fea33dc9147a7f3..0cc293a6ac246b391e11d6366a157d4326c91668 100644 (file)
@@ -1104,8 +1104,7 @@ static void sii8620_set_infoframes(struct sii8620 *ctx,
        int ret;
 
        ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi,
-                                                      mode,
-                                                      true);
+                                                      NULL, mode);
        if (ctx->use_packed_pixel)
                frm.avi.colorspace = HDMI_COLORSPACE_YUV422;
 
index 8f9c8a6b46de58ce5f25575670ef102d4f879171..5cbb71a866d54bf7a10ce8943ff0b3c364f65d53 100644 (file)
@@ -1,13 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * dw-hdmi-i2s-audio.c
  *
  * Copyright (c) 2017 Renesas Solutions Corp.
  * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
+
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+
 #include <drm/bridge/dw_hdmi.h>
 
 #include <sound/hdmi-codec.h>
index 64c3cf0275182649d9a5572ce6f3d907165f822a..129f464cbeb19aaffe37d3be6831fd7801ef8f0f 100644 (file)
@@ -1344,7 +1344,8 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
        u8 val;
 
        /* Initialise info frame from DRM mode */
-       drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
+       drm_hdmi_avi_infoframe_from_display_mode(&frame,
+                                                &hdmi->connector, mode);
 
        if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
                frame.colorspace = HDMI_COLORSPACE_YUV444;
@@ -1998,8 +1999,8 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
 }
 
 static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
-                                   struct drm_display_mode *orig_mode,
-                                   struct drm_display_mode *mode)
+                                   const struct drm_display_mode *orig_mode,
+                                   const struct drm_display_mode *mode)
 {
        struct dw_hdmi *hdmi = bridge->driver_private;
 
index 2f4b145b73af23d7db14845a111c5fc9d4f27736..23a5977a3b0a01eec66cf2e8269ac58e137c9642 100644 (file)
@@ -248,7 +248,7 @@ static inline bool dw_mipi_is_dual_mode(struct dw_mipi_dsi *dsi)
  * The controller should generate 2 frames before
  * preparing the peripheral.
  */
-static void dw_mipi_dsi_wait_for_two_frames(struct drm_display_mode *mode)
+static void dw_mipi_dsi_wait_for_two_frames(const struct drm_display_mode *mode)
 {
        int refresh, two_frames;
 
@@ -564,7 +564,7 @@ static void dw_mipi_dsi_init(struct dw_mipi_dsi *dsi)
 }
 
 static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi,
-                                  struct drm_display_mode *mode)
+                                  const struct drm_display_mode *mode)
 {
        u32 val = 0, color = 0;
 
@@ -607,7 +607,7 @@ static void dw_mipi_dsi_packet_handler_config(struct dw_mipi_dsi *dsi)
 }
 
 static void dw_mipi_dsi_video_packet_config(struct dw_mipi_dsi *dsi,
-                                           struct drm_display_mode *mode)
+                                           const struct drm_display_mode *mode)
 {
        /*
         * TODO dw drv improvements
@@ -642,7 +642,7 @@ static void dw_mipi_dsi_command_mode_config(struct dw_mipi_dsi *dsi)
 
 /* Get lane byte clock cycles. */
 static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct dw_mipi_dsi *dsi,
-                                          struct drm_display_mode *mode,
+                                          const struct drm_display_mode *mode,
                                           u32 hcomponent)
 {
        u32 frac, lbcc;
@@ -658,7 +658,7 @@ static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct dw_mipi_dsi *dsi,
 }
 
 static void dw_mipi_dsi_line_timer_config(struct dw_mipi_dsi *dsi,
-                                         struct drm_display_mode *mode)
+                                         const struct drm_display_mode *mode)
 {
        u32 htotal, hsa, hbp, lbcc;
 
@@ -681,7 +681,7 @@ static void dw_mipi_dsi_line_timer_config(struct dw_mipi_dsi *dsi,
 }
 
 static void dw_mipi_dsi_vertical_timing_config(struct dw_mipi_dsi *dsi,
-                                              struct drm_display_mode *mode)
+                                       const struct drm_display_mode *mode)
 {
        u32 vactive, vsa, vfp, vbp;
 
@@ -818,7 +818,7 @@ static unsigned int dw_mipi_dsi_get_lanes(struct dw_mipi_dsi *dsi)
 }
 
 static void dw_mipi_dsi_mode_set(struct dw_mipi_dsi *dsi,
-                               struct drm_display_mode *adjusted_mode)
+                                const struct drm_display_mode *adjusted_mode)
 {
        const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
        void *priv_data = dsi->plat_data->priv_data;
@@ -861,8 +861,8 @@ static void dw_mipi_dsi_mode_set(struct dw_mipi_dsi *dsi,
 }
 
 static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge,
-                                       struct drm_display_mode *mode,
-                                       struct drm_display_mode *adjusted_mode)
+                                       const struct drm_display_mode *mode,
+                                       const struct drm_display_mode *adjusted_mode)
 {
        struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
 
index 8e28e738cb52dec6ee8ea7eda2d655fc7035be93..4df07f4cbff556a10931072aa3bcc88d7ae87973 100644 (file)
@@ -203,7 +203,7 @@ struct tc_data {
        /* display edid */
        struct edid             *edid;
        /* current mode */
-       struct drm_display_mode *mode;
+       const struct drm_display_mode   *mode;
 
        u32                     rev;
        u8                      assr;
@@ -648,7 +648,8 @@ err_dpcd_read:
        return ret;
 }
 
-static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
+static int tc_set_video_mode(struct tc_data *tc,
+                            const struct drm_display_mode *mode)
 {
        int ret;
        int vid_sync_dly;
@@ -1113,8 +1114,8 @@ static enum drm_mode_status tc_connector_mode_valid(struct drm_connector *connec
 }
 
 static void tc_bridge_mode_set(struct drm_bridge *bridge,
-                              struct drm_display_mode *mode,
-                              struct drm_display_mode *adj)
+                              const struct drm_display_mode *mode,
+                              const struct drm_display_mode *adj)
 {
        struct tc_data *tc = bridge_to_tc(bridge);
 
index 4dd499c7d1ba13fc2cb49e91fc011ece76b07f16..39df62acac69d3c200910fd973e9933cde3b4b8d 100644 (file)
@@ -10,6 +10,7 @@
  */
 #include <linux/module.h>
 #include <drm/drmP.h>
+#include <drm/drm_util.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
 
@@ -256,6 +257,8 @@ static int cirrus_fbdev_destroy(struct drm_device *dev,
 {
        struct drm_framebuffer *gfb = gfbdev->gfb;
 
+       drm_helper_force_disable_all(dev);
+
        drm_fb_helper_unregister_fbi(&gfbdev->helper);
 
        vfree(gfbdev->sysram);
index 48ec378fb27ec37804179a306979fb06c7b72bf5..5eb40130fafb0fa94721806d5f0351cf90fe1a32 100644 (file)
@@ -698,6 +698,7 @@ static void drm_atomic_plane_print_state(struct drm_printer *p,
 
 /**
  * drm_atomic_private_obj_init - initialize private object
+ * @dev: DRM device this object will be attached to
  * @obj: private object
  * @state: initial private object state
  * @funcs: pointer to the struct of function pointers that identify the object
@@ -707,14 +708,18 @@ static void drm_atomic_plane_print_state(struct drm_printer *p,
  * driver private object that needs its own atomic state.
  */
 void
-drm_atomic_private_obj_init(struct drm_private_obj *obj,
+drm_atomic_private_obj_init(struct drm_device *dev,
+                           struct drm_private_obj *obj,
                            struct drm_private_state *state,
                            const struct drm_private_state_funcs *funcs)
 {
        memset(obj, 0, sizeof(*obj));
 
+       drm_modeset_lock_init(&obj->lock);
+
        obj->state = state;
        obj->funcs = funcs;
+       list_add_tail(&obj->head, &dev->mode_config.privobj_list);
 }
 EXPORT_SYMBOL(drm_atomic_private_obj_init);
 
@@ -727,7 +732,9 @@ EXPORT_SYMBOL(drm_atomic_private_obj_init);
 void
 drm_atomic_private_obj_fini(struct drm_private_obj *obj)
 {
+       list_del(&obj->head);
        obj->funcs->atomic_destroy_state(obj, obj->state);
+       drm_modeset_lock_fini(&obj->lock);
 }
 EXPORT_SYMBOL(drm_atomic_private_obj_fini);
 
@@ -737,8 +744,8 @@ EXPORT_SYMBOL(drm_atomic_private_obj_fini);
  * @obj: private object to get the state for
  *
  * This function returns the private object state for the given private object,
- * allocating the state if needed. It does not grab any locks as the caller is
- * expected to care of any required locking.
+ * allocating the state if needed. It will also grab the relevant private
+ * object lock to make sure that the state is consistent.
  *
  * RETURNS:
  *
@@ -748,7 +755,7 @@ struct drm_private_state *
 drm_atomic_get_private_obj_state(struct drm_atomic_state *state,
                                 struct drm_private_obj *obj)
 {
-       int index, num_objs, i;
+       int index, num_objs, i, ret;
        size_t size;
        struct __drm_private_objs_state *arr;
        struct drm_private_state *obj_state;
@@ -757,6 +764,10 @@ drm_atomic_get_private_obj_state(struct drm_atomic_state *state,
                if (obj == state->private_objs[i].ptr)
                        return state->private_objs[i].state;
 
+       ret = drm_modeset_lock(&obj->lock, state->acquire_ctx);
+       if (ret)
+               return ERR_PTR(ret);
+
        num_objs = state->num_private_objs + 1;
        size = sizeof(*state->private_objs) * num_objs;
        arr = krealloc(state->private_objs, size, GFP_KERNEL);
index ba7025041e4641ea16858497fde02dee9dd3c8f4..138b2711d389ebc0b49f2a2a7aab1e012e722347 100644 (file)
@@ -294,8 +294,8 @@ EXPORT_SYMBOL(drm_bridge_post_disable);
  * Note: the bridge passed should be the one closest to the encoder
  */
 void drm_bridge_mode_set(struct drm_bridge *bridge,
-                       struct drm_display_mode *mode,
-                       struct drm_display_mode *adjusted_mode)
+                        const struct drm_display_mode *mode,
+                        const struct drm_display_mode *adjusted_mode)
 {
        if (!bridge)
                return;
index d7d10cabb9bbfd15540f8fe04edb0bdd9fc6558d..a39ab2193bfe10890bb8aa3e85614ee03cecef25 100644 (file)
@@ -377,6 +377,17 @@ int drm_legacy_addmap(struct drm_device *dev, resource_size_t offset,
 }
 EXPORT_SYMBOL(drm_legacy_addmap);
 
+struct drm_local_map *drm_legacy_findmap(struct drm_device *dev,
+                                        unsigned int token)
+{
+       struct drm_map_list *_entry;
+       list_for_each_entry(_entry, &dev->maplist, head)
+               if (_entry->user_token == token)
+                       return _entry->map;
+       return NULL;
+}
+EXPORT_SYMBOL(drm_legacy_findmap);
+
 /**
  * Ioctl to specify a range of memory that is available for mapping by a
  * non-root process.
index 07dcf47daafe2befc0be3652fbc0e484a69a549e..968ca7c91ad8489990d9d6e9502ae816680bc594 100644 (file)
@@ -462,3 +462,47 @@ int drm_plane_create_color_properties(struct drm_plane *plane,
        return 0;
 }
 EXPORT_SYMBOL(drm_plane_create_color_properties);
+
+/**
+ * drm_color_lut_check - check validity of lookup table
+ * @lut: property blob containing LUT to check
+ * @tests: bitmask of tests to run
+ *
+ * Helper to check whether a userspace-provided lookup table is valid and
+ * satisfies hardware requirements.  Drivers pass a bitmask indicating which of
+ * the tests in &drm_color_lut_tests should be performed.
+ *
+ * Returns 0 on success, -EINVAL on failure.
+ */
+int drm_color_lut_check(struct drm_property_blob *lut,
+                       uint32_t tests)
+{
+       struct drm_color_lut *entry;
+       int i;
+
+       if (!lut || !tests)
+               return 0;
+
+       entry = lut->data;
+       for (i = 0; i < drm_color_lut_size(lut); i++) {
+               if (tests & DRM_COLOR_LUT_EQUAL_CHANNELS) {
+                       if (entry[i].red != entry[i].blue ||
+                           entry[i].red != entry[i].green) {
+                               DRM_DEBUG_KMS("All LUT entries must have equal r/g/b\n");
+                               return -EINVAL;
+                       }
+               }
+
+               if (i > 0 && tests & DRM_COLOR_LUT_NON_DECREASING) {
+                       if (entry[i].red < entry[i - 1].red ||
+                           entry[i].green < entry[i - 1].green ||
+                           entry[i].blue < entry[i - 1].blue) {
+                               DRM_DEBUG_KMS("LUT entries must never decrease.\n");
+                               return -EINVAL;
+                       }
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_color_lut_check);
index da8ae80c27506d279fa7fd2419b34eb72a3b292f..847539645558c7a9fc752298ae38bda1cda43282 100644 (file)
@@ -1138,7 +1138,71 @@ void drm_hdmi_avi_infoframe_content_type(struct hdmi_avi_infoframe *frame,
 EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type);
 
 /**
- * drm_create_tv_properties - create TV specific connector properties
+ * drm_mode_attach_tv_margin_properties - attach TV connector margin properties
+ * @connector: DRM connector
+ *
+ * Called by a driver when it needs to attach TV margin props to a connector.
+ * Typically used on SDTV and HDMI connectors.
+ */
+void drm_connector_attach_tv_margin_properties(struct drm_connector *connector)
+{
+       struct drm_device *dev = connector->dev;
+
+       drm_object_attach_property(&connector->base,
+                                  dev->mode_config.tv_left_margin_property,
+                                  0);
+       drm_object_attach_property(&connector->base,
+                                  dev->mode_config.tv_right_margin_property,
+                                  0);
+       drm_object_attach_property(&connector->base,
+                                  dev->mode_config.tv_top_margin_property,
+                                  0);
+       drm_object_attach_property(&connector->base,
+                                  dev->mode_config.tv_bottom_margin_property,
+                                  0);
+}
+EXPORT_SYMBOL(drm_connector_attach_tv_margin_properties);
+
+/**
+ * drm_mode_create_tv_margin_properties - create TV connector margin properties
+ * @dev: DRM device
+ *
+ * Called by a driver's HDMI connector initialization routine, this function
+ * creates the TV margin properties for a given device. No need to call this
+ * function for an SDTV connector, it's already called from
+ * drm_mode_create_tv_properties().
+ */
+int drm_mode_create_tv_margin_properties(struct drm_device *dev)
+{
+       if (dev->mode_config.tv_left_margin_property)
+               return 0;
+
+       dev->mode_config.tv_left_margin_property =
+               drm_property_create_range(dev, 0, "left margin", 0, 100);
+       if (!dev->mode_config.tv_left_margin_property)
+               return -ENOMEM;
+
+       dev->mode_config.tv_right_margin_property =
+               drm_property_create_range(dev, 0, "right margin", 0, 100);
+       if (!dev->mode_config.tv_right_margin_property)
+               return -ENOMEM;
+
+       dev->mode_config.tv_top_margin_property =
+               drm_property_create_range(dev, 0, "top margin", 0, 100);
+       if (!dev->mode_config.tv_top_margin_property)
+               return -ENOMEM;
+
+       dev->mode_config.tv_bottom_margin_property =
+               drm_property_create_range(dev, 0, "bottom margin", 0, 100);
+       if (!dev->mode_config.tv_bottom_margin_property)
+               return -ENOMEM;
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
+
+/**
+ * drm_mode_create_tv_properties - create TV specific connector properties
  * @dev: DRM device
  * @num_modes: number of different TV formats (modes) supported
  * @modes: array of pointers to strings containing name of each format
@@ -1183,24 +1247,7 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
        /*
         * Other, TV specific properties: margins & TV modes.
         */
-       dev->mode_config.tv_left_margin_property =
-               drm_property_create_range(dev, 0, "left margin", 0, 100);
-       if (!dev->mode_config.tv_left_margin_property)
-               goto nomem;
-
-       dev->mode_config.tv_right_margin_property =
-               drm_property_create_range(dev, 0, "right margin", 0, 100);
-       if (!dev->mode_config.tv_right_margin_property)
-               goto nomem;
-
-       dev->mode_config.tv_top_margin_property =
-               drm_property_create_range(dev, 0, "top margin", 0, 100);
-       if (!dev->mode_config.tv_top_margin_property)
-               goto nomem;
-
-       dev->mode_config.tv_bottom_margin_property =
-               drm_property_create_range(dev, 0, "bottom margin", 0, 100);
-       if (!dev->mode_config.tv_bottom_margin_property)
+       if (drm_mode_create_tv_margin_properties(dev))
                goto nomem;
 
        dev->mode_config.tv_mode_property =
@@ -2077,7 +2124,7 @@ EXPORT_SYMBOL(drm_mode_get_tile_group);
  * identifier for the tile group.
  *
  * RETURNS:
- * new tile group or error.
+ * new tile group or NULL.
  */
 struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
                                                  char topology[8])
@@ -2087,7 +2134,7 @@ struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
 
        tg = kzalloc(sizeof(*tg), GFP_KERNEL);
        if (!tg)
-               return ERR_PTR(-ENOMEM);
+               return NULL;
 
        kref_init(&tg->refcount);
        memcpy(tg->group_data, topology, 8);
@@ -2099,7 +2146,7 @@ struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
                tg->id = ret;
        } else {
                kfree(tg);
-               tg = ERR_PTR(ret);
+               tg = NULL;
        }
 
        mutex_unlock(&dev->mode_config.idr_mutex);
index 506663c69b0a1e443a7dccb4a62dae117cc105de..6e8e1a9fcae301a2417316ac4331dcfc060daaf1 100644 (file)
@@ -361,23 +361,26 @@ int drm_legacy_addctx(struct drm_device *dev, void *data,
 {
        struct drm_ctx_list *ctx_entry;
        struct drm_ctx *ctx = data;
+       int tmp_handle;
 
        if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
            !drm_core_check_feature(dev, DRIVER_LEGACY))
                return -EOPNOTSUPP;
 
-       ctx->handle = drm_legacy_ctxbitmap_next(dev);
-       if (ctx->handle == DRM_KERNEL_CONTEXT) {
+       tmp_handle = drm_legacy_ctxbitmap_next(dev);
+       if (tmp_handle == DRM_KERNEL_CONTEXT) {
                /* Skip kernel's context and get a new one. */
-               ctx->handle = drm_legacy_ctxbitmap_next(dev);
+               tmp_handle = drm_legacy_ctxbitmap_next(dev);
        }
-       DRM_DEBUG("%d\n", ctx->handle);
-       if (ctx->handle < 0) {
+       DRM_DEBUG("%d\n", tmp_handle);
+       if (tmp_handle < 0) {
                DRM_DEBUG("Not enough free contexts.\n");
                /* Should this return -EBUSY instead? */
-               return -ENOMEM;
+               return tmp_handle;
        }
 
+       ctx->handle = tmp_handle;
+
        ctx_entry = kmalloc(sizeof(*ctx_entry), GFP_KERNEL);
        if (!ctx_entry) {
                DRM_DEBUG("out of memory\n");
index 1593dd6cdfb729c3bdfe19215947314df1f0a74d..7dabbaf033a16055671ccfdb9d164936a8b9a4da 100644 (file)
@@ -93,15 +93,6 @@ struct drm_crtc *drm_crtc_from_index(struct drm_device *dev, int idx)
 }
 EXPORT_SYMBOL(drm_crtc_from_index);
 
-/**
- * drm_crtc_force_disable - Forcibly turn off a CRTC
- * @crtc: CRTC to turn off
- *
- * Note: This should only be used by non-atomic legacy drivers.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
 int drm_crtc_force_disable(struct drm_crtc *crtc)
 {
        struct drm_mode_set set = {
@@ -112,38 +103,6 @@ int drm_crtc_force_disable(struct drm_crtc *crtc)
 
        return drm_mode_set_config_internal(&set);
 }
-EXPORT_SYMBOL(drm_crtc_force_disable);
-
-/**
- * drm_crtc_force_disable_all - Forcibly turn off all enabled CRTCs
- * @dev: DRM device whose CRTCs to turn off
- *
- * Drivers may want to call this on unload to ensure that all displays are
- * unlit and the GPU is in a consistent, low power state. Takes modeset locks.
- *
- * Note: This should only be used by non-atomic legacy drivers. For an atomic
- * version look at drm_atomic_helper_shutdown().
- *
- * Returns:
- * Zero on success, error code on failure.
- */
-int drm_crtc_force_disable_all(struct drm_device *dev)
-{
-       struct drm_crtc *crtc;
-       int ret = 0;
-
-       drm_modeset_lock_all(dev);
-       drm_for_each_crtc(crtc, dev)
-               if (crtc->enabled) {
-                       ret = drm_crtc_force_disable(crtc);
-                       if (ret)
-                               goto out;
-               }
-out:
-       drm_modeset_unlock_all(dev);
-       return ret;
-}
-EXPORT_SYMBOL(drm_crtc_force_disable_all);
 
 static unsigned int drm_num_crtcs(struct drm_device *dev)
 {
index a3c81850e755f6b8904b662744002d810f04c289..747661f63fbb4f65d35a5f9d1521ff01c5e56ed9 100644 (file)
@@ -93,6 +93,8 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
        struct drm_connector_list_iter conn_iter;
        struct drm_device *dev = encoder->dev;
 
+       WARN_ON(drm_drv_uses_atomic_modeset(dev));
+
        /*
         * We can expect this mutex to be locked if we are not panicking.
         * Locking is currently fubar in the panic handler.
@@ -131,6 +133,8 @@ bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
        struct drm_encoder *encoder;
        struct drm_device *dev = crtc->dev;
 
+       WARN_ON(drm_drv_uses_atomic_modeset(dev));
+
        /*
         * We can expect this mutex to be locked if we are not panicking.
         * Locking is currently fubar in the panic handler.
@@ -212,8 +216,7 @@ static void __drm_helper_disable_unused_functions(struct drm_device *dev)
  */
 void drm_helper_disable_unused_functions(struct drm_device *dev)
 {
-       if (drm_core_check_feature(dev, DRIVER_ATOMIC))
-               DRM_ERROR("Called for atomic driver, this is not what you want.\n");
+       WARN_ON(drm_drv_uses_atomic_modeset(dev));
 
        drm_modeset_lock_all(dev);
        __drm_helper_disable_unused_functions(dev);
@@ -281,6 +284,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
        struct drm_encoder *encoder;
        bool ret = true;
 
+       WARN_ON(drm_drv_uses_atomic_modeset(dev));
+
        drm_warn_on_modeset_not_all_locked(dev);
 
        saved_enabled = crtc->enabled;
@@ -386,9 +391,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
                if (!encoder_funcs)
                        continue;
 
-               DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
-                       encoder->base.id, encoder->name,
-                       mode->base.id, mode->name);
+               DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%s]\n",
+                       encoder->base.id, encoder->name, mode->name);
                if (encoder_funcs->mode_set)
                        encoder_funcs->mode_set(encoder, mode, adjusted_mode);
 
@@ -540,6 +544,9 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set,
 
        crtc_funcs = set->crtc->helper_private;
 
+       dev = set->crtc->dev;
+       WARN_ON(drm_drv_uses_atomic_modeset(dev));
+
        if (!set->mode)
                set->fb = NULL;
 
@@ -555,8 +562,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set,
                return 0;
        }
 
-       dev = set->crtc->dev;
-
        drm_warn_on_modeset_not_all_locked(dev);
 
        /*
@@ -875,6 +880,8 @@ int drm_helper_connector_dpms(struct drm_connector *connector, int mode)
        struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
        int old_dpms, encoder_dpms = DRM_MODE_DPMS_OFF;
 
+       WARN_ON(drm_drv_uses_atomic_modeset(connector->dev));
+
        if (mode == connector->dpms)
                return 0;
 
@@ -946,6 +953,8 @@ void drm_helper_resume_force_mode(struct drm_device *dev)
        int encoder_dpms;
        bool ret;
 
+       WARN_ON(drm_drv_uses_atomic_modeset(dev));
+
        drm_modeset_lock_all(dev);
        drm_for_each_crtc(crtc, dev) {
 
@@ -984,3 +993,38 @@ void drm_helper_resume_force_mode(struct drm_device *dev)
        drm_modeset_unlock_all(dev);
 }
 EXPORT_SYMBOL(drm_helper_resume_force_mode);
+
+/**
+ * drm_helper_force_disable_all - Forcibly turn off all enabled CRTCs
+ * @dev: DRM device whose CRTCs to turn off
+ *
+ * Drivers may want to call this on unload to ensure that all displays are
+ * unlit and the GPU is in a consistent, low power state. Takes modeset locks.
+ *
+ * Note: This should only be used by non-atomic legacy drivers. For an atomic
+ * version look at drm_atomic_helper_shutdown().
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_helper_force_disable_all(struct drm_device *dev)
+{
+       struct drm_crtc *crtc;
+       int ret = 0;
+
+       drm_modeset_lock_all(dev);
+       drm_for_each_crtc(crtc, dev)
+               if (crtc->enabled) {
+                       struct drm_mode_set set = {
+                               .crtc = crtc,
+                       };
+
+                       ret = drm_mode_set_config_internal(&set);
+                       if (ret)
+                               goto out;
+               }
+out:
+       drm_modeset_unlock_all(dev);
+       return ret;
+}
+EXPORT_SYMBOL(drm_helper_force_disable_all);
index 86893448f4868a876a49e174b64a29d7514a4108..216f2a9ee3d406e2fed7f21492d1590eef4025f9 100644 (file)
@@ -50,6 +50,7 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc,
                            const struct drm_framebuffer *fb);
 int drm_crtc_register_all(struct drm_device *dev);
 void drm_crtc_unregister_all(struct drm_device *dev);
+int drm_crtc_force_disable(struct drm_crtc *crtc);
 
 struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc);
 
index 31032407254d4dab631fb863f58ee5353dbfeb08..e16aa5ae00b48e0c490b7843871de6b0ee87651b 100644 (file)
@@ -333,3 +333,44 @@ drm_atomic_helper_damage_iter_next(struct drm_atomic_helper_damage_iter *iter,
        return ret;
 }
 EXPORT_SYMBOL(drm_atomic_helper_damage_iter_next);
+
+/**
+ * drm_atomic_helper_damage_merged - Merged plane damage
+ * @old_state: Old plane state for validation.
+ * @state: Plane state from which to iterate the damage clips.
+ * @rect: Returns the merged damage rectangle
+ *
+ * This function merges any valid plane damage clips into one rectangle and
+ * returns it in @rect.
+ *
+ * For details see: drm_atomic_helper_damage_iter_init() and
+ * drm_atomic_helper_damage_iter_next().
+ *
+ * Returns:
+ * True if there is valid plane damage otherwise false.
+ */
+bool drm_atomic_helper_damage_merged(const struct drm_plane_state *old_state,
+                                    struct drm_plane_state *state,
+                                    struct drm_rect *rect)
+{
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_rect clip;
+       bool valid = false;
+
+       rect->x1 = INT_MAX;
+       rect->y1 = INT_MAX;
+       rect->x2 = 0;
+       rect->y2 = 0;
+
+       drm_atomic_helper_damage_iter_init(&iter, old_state, state);
+       drm_atomic_for_each_plane_damage(&iter, &clip) {
+               rect->x1 = min(rect->x1, clip.x1);
+               rect->y1 = min(rect->y1, clip.y1);
+               rect->x2 = max(rect->x2, clip.x2);
+               rect->y2 = max(rect->y2, clip.y2);
+               valid = true;
+       }
+
+       return valid;
+}
+EXPORT_SYMBOL(drm_atomic_helper_damage_merged);
index 2d6c491a0542ef02655b8bee98a52644000703b3..54120b6319e7489e91c6c82565dd4946d7a64acd 100644 (file)
@@ -154,6 +154,7 @@ u8 drm_dp_link_rate_to_bw_code(int link_rate)
        default:
                WARN(1, "unknown DP link rate %d, using %x\n", link_rate,
                     DP_LINK_BW_1_62);
+               /* fall through */
        case 162000:
                return DP_LINK_BW_1_62;
        case 270000:
@@ -171,6 +172,7 @@ int drm_dp_bw_code_to_link_rate(u8 link_bw)
        switch (link_bw) {
        default:
                WARN(1, "unknown DP link BW code %x, using 162000\n", link_bw);
+               /* fall through */
        case DP_LINK_BW_1_62:
                return 162000;
        case DP_LINK_BW_2_7:
@@ -192,11 +194,11 @@ drm_dp_dump_access(const struct drm_dp_aux *aux,
        const char *arrow = request == DP_AUX_NATIVE_READ ? "->" : "<-";
 
        if (ret > 0)
-               drm_dbg(DRM_UT_DP, "%s: 0x%05x AUX %s (ret=%3d) %*ph\n",
-                       aux->name, offset, arrow, ret, min(ret, 20), buffer);
+               DRM_DEBUG_DP("%s: 0x%05x AUX %s (ret=%3d) %*ph\n",
+                            aux->name, offset, arrow, ret, min(ret, 20), buffer);
        else
-               drm_dbg(DRM_UT_DP, "%s: 0x%05x AUX %s (ret=%3d)\n",
-                       aux->name, offset, arrow, ret);
+               DRM_DEBUG_DP("%s: 0x%05x AUX %s (ret=%3d)\n",
+                            aux->name, offset, arrow, ret);
 }
 
 /**
@@ -552,6 +554,7 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
                case DP_DS_16BPC:
                        return 16;
                }
+               /* fall through */
        default:
                return 0;
        }
@@ -884,7 +887,8 @@ static void drm_dp_i2c_msg_set_request(struct drm_dp_aux_msg *msg,
 {
        msg->request = (i2c_msg->flags & I2C_M_RD) ?
                DP_AUX_I2C_READ : DP_AUX_I2C_WRITE;
-       msg->request |= DP_AUX_I2C_MOT;
+       if (!(i2c_msg->flags & I2C_M_STOP))
+               msg->request |= DP_AUX_I2C_MOT;
 }
 
 /*
@@ -1273,6 +1277,8 @@ static const struct dpcd_quirk dpcd_quirk_list[] = {
        { OUI(0x00, 0x22, 0xb9), DEVICE_ID_ANY, true, BIT(DP_DPCD_QUIRK_CONSTANT_N) },
        /* LG LP140WF6-SPM1 eDP panel */
        { OUI(0x00, 0x22, 0xb9), DEVICE_ID('s', 'i', 'v', 'a', 'r', 'T'), false, BIT(DP_DPCD_QUIRK_CONSTANT_N) },
+       /* Apple panels need some additional handling to support PSR */
+       { OUI(0x00, 0x10, 0xfa), DEVICE_ID_ANY, false, BIT(DP_DPCD_QUIRK_NO_PSR) }
 };
 
 #undef OUI
index 5294145569625df3e8d7fc05c5ccc5e405ef62b1..196ebba8af5f4f54b92c3079eff20934e7978412 100644 (file)
@@ -33,6 +33,7 @@
 #include <drm/drm_fixed.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
 
 /**
  * DOC: dp mst helper
@@ -45,7 +46,7 @@ static bool dump_dp_payload_table(struct drm_dp_mst_topology_mgr *mgr,
                                  char *buf);
 static int test_calc_pbn_mode(void);
 
-static void drm_dp_put_port(struct drm_dp_mst_port *port);
+static void drm_dp_mst_topology_put_port(struct drm_dp_mst_port *port);
 
 static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr,
                                     int id,
@@ -849,46 +850,212 @@ static struct drm_dp_mst_branch *drm_dp_add_mst_branch_device(u8 lct, u8 *rad)
        if (lct > 1)
                memcpy(mstb->rad, rad, lct / 2);
        INIT_LIST_HEAD(&mstb->ports);
-       kref_init(&mstb->kref);
+       kref_init(&mstb->topology_kref);
+       kref_init(&mstb->malloc_kref);
        return mstb;
 }
 
-static void drm_dp_free_mst_port(struct kref *kref);
-
 static void drm_dp_free_mst_branch_device(struct kref *kref)
 {
-       struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref);
-       if (mstb->port_parent) {
-               if (list_empty(&mstb->port_parent->next))
-                       kref_put(&mstb->port_parent->kref, drm_dp_free_mst_port);
-       }
+       struct drm_dp_mst_branch *mstb =
+               container_of(kref, struct drm_dp_mst_branch, malloc_kref);
+
+       if (mstb->port_parent)
+               drm_dp_mst_put_port_malloc(mstb->port_parent);
+
        kfree(mstb);
 }
 
+/**
+ * DOC: Branch device and port refcounting
+ *
+ * Topology refcount overview
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The refcounting schemes for &struct drm_dp_mst_branch and &struct
+ * drm_dp_mst_port are somewhat unusual. Both ports and branch devices have
+ * two different kinds of refcounts: topology refcounts, and malloc refcounts.
+ *
+ * Topology refcounts are not exposed to drivers, and are handled internally
+ * by the DP MST helpers. The helpers use them in order to prevent the
+ * in-memory topology state from being changed in the middle of critical
+ * operations like changing the internal state of payload allocations. This
+ * means each branch and port will be considered to be connected to the rest
+ * of the topology until it's topology refcount reaches zero. Additionally,
+ * for ports this means that their associated &struct drm_connector will stay
+ * registered with userspace until the port's refcount reaches 0.
+ *
+ * Malloc refcount overview
+ * ~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * Malloc references are used to keep a &struct drm_dp_mst_port or &struct
+ * drm_dp_mst_branch allocated even after all of its topology references have
+ * been dropped, so that the driver or MST helpers can safely access each
+ * branch's last known state before it was disconnected from the topology.
+ * When the malloc refcount of a port or branch reaches 0, the memory
+ * allocation containing the &struct drm_dp_mst_branch or &struct
+ * drm_dp_mst_port respectively will be freed.
+ *
+ * For &struct drm_dp_mst_branch, malloc refcounts are not currently exposed
+ * to drivers. As of writing this documentation, there are no drivers that
+ * have a usecase for accessing &struct drm_dp_mst_branch outside of the MST
+ * helpers. Exposing this API to drivers in a race-free manner would take more
+ * tweaking of the refcounting scheme, however patches are welcome provided
+ * there is a legitimate driver usecase for this.
+ *
+ * Refcount relationships in a topology
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * Let's take a look at why the relationship between topology and malloc
+ * refcounts is designed the way it is.
+ *
+ * .. kernel-figure:: dp-mst/topology-figure-1.dot
+ *
+ *    An example of topology and malloc refs in a DP MST topology with two
+ *    active payloads. Topology refcount increments are indicated by solid
+ *    lines, and malloc refcount increments are indicated by dashed lines.
+ *    Each starts from the branch which incremented the refcount, and ends at
+ *    the branch to which the refcount belongs to, i.e. the arrow points the
+ *    same way as the C pointers used to reference a structure.
+ *
+ * As you can see in the above figure, every branch increments the topology
+ * refcount of it's children, and increments the malloc refcount of it's
+ * parent. Additionally, every payload increments the malloc refcount of it's
+ * assigned port by 1.
+ *
+ * So, what would happen if MSTB #3 from the above figure was unplugged from
+ * the system, but the driver hadn't yet removed payload #2 from port #3? The
+ * topology would start to look like the figure below.
+ *
+ * .. kernel-figure:: dp-mst/topology-figure-2.dot
+ *
+ *    Ports and branch devices which have been released from memory are
+ *    colored grey, and references which have been removed are colored red.
+ *
+ * Whenever a port or branch device's topology refcount reaches zero, it will
+ * decrement the topology refcounts of all its children, the malloc refcount
+ * of its parent, and finally its own malloc refcount. For MSTB #4 and port
+ * #4, this means they both have been disconnected from the topology and freed
+ * from memory. But, because payload #2 is still holding a reference to port
+ * #3, port #3 is removed from the topology but it's &struct drm_dp_mst_port
+ * is still accessible from memory. This also means port #3 has not yet
+ * decremented the malloc refcount of MSTB #3, so it's &struct
+ * drm_dp_mst_branch will also stay allocated in memory until port #3's
+ * malloc refcount reaches 0.
+ *
+ * This relationship is necessary because in order to release payload #2, we
+ * need to be able to figure out the last relative of port #3 that's still
+ * connected to the topology. In this case, we would travel up the topology as
+ * shown below.
+ *
+ * .. kernel-figure:: dp-mst/topology-figure-3.dot
+ *
+ * And finally, remove payload #2 by communicating with port #2 through
+ * sideband transactions.
+ */
+
+/**
+ * drm_dp_mst_get_mstb_malloc() - Increment the malloc refcount of a branch
+ * device
+ * @mstb: The &struct drm_dp_mst_branch to increment the malloc refcount of
+ *
+ * Increments &drm_dp_mst_branch.malloc_kref. When
+ * &drm_dp_mst_branch.malloc_kref reaches 0, the memory allocation for @mstb
+ * will be released and @mstb may no longer be used.
+ *
+ * See also: drm_dp_mst_put_mstb_malloc()
+ */
+static void
+drm_dp_mst_get_mstb_malloc(struct drm_dp_mst_branch *mstb)
+{
+       kref_get(&mstb->malloc_kref);
+       DRM_DEBUG("mstb %p (%d)\n", mstb, kref_read(&mstb->malloc_kref));
+}
+
+/**
+ * drm_dp_mst_put_mstb_malloc() - Decrement the malloc refcount of a branch
+ * device
+ * @mstb: The &struct drm_dp_mst_branch to decrement the malloc refcount of
+ *
+ * Decrements &drm_dp_mst_branch.malloc_kref. When
+ * &drm_dp_mst_branch.malloc_kref reaches 0, the memory allocation for @mstb
+ * will be released and @mstb may no longer be used.
+ *
+ * See also: drm_dp_mst_get_mstb_malloc()
+ */
+static void
+drm_dp_mst_put_mstb_malloc(struct drm_dp_mst_branch *mstb)
+{
+       DRM_DEBUG("mstb %p (%d)\n", mstb, kref_read(&mstb->malloc_kref) - 1);
+       kref_put(&mstb->malloc_kref, drm_dp_free_mst_branch_device);
+}
+
+static void drm_dp_free_mst_port(struct kref *kref)
+{
+       struct drm_dp_mst_port *port =
+               container_of(kref, struct drm_dp_mst_port, malloc_kref);
+
+       drm_dp_mst_put_mstb_malloc(port->parent);
+       kfree(port);
+}
+
+/**
+ * drm_dp_mst_get_port_malloc() - Increment the malloc refcount of an MST port
+ * @port: The &struct drm_dp_mst_port to increment the malloc refcount of
+ *
+ * Increments &drm_dp_mst_port.malloc_kref. When &drm_dp_mst_port.malloc_kref
+ * reaches 0, the memory allocation for @port will be released and @port may
+ * no longer be used.
+ *
+ * Because @port could potentially be freed at any time by the DP MST helpers
+ * if &drm_dp_mst_port.malloc_kref reaches 0, including during a call to this
+ * function, drivers that which to make use of &struct drm_dp_mst_port should
+ * ensure that they grab at least one main malloc reference to their MST ports
+ * in &drm_dp_mst_topology_cbs.add_connector. This callback is called before
+ * there is any chance for &drm_dp_mst_port.malloc_kref to reach 0.
+ *
+ * See also: drm_dp_mst_put_port_malloc()
+ */
+void
+drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port)
+{
+       kref_get(&port->malloc_kref);
+       DRM_DEBUG("port %p (%d)\n", port, kref_read(&port->malloc_kref));
+}
+EXPORT_SYMBOL(drm_dp_mst_get_port_malloc);
+
+/**
+ * drm_dp_mst_put_port_malloc() - Decrement the malloc refcount of an MST port
+ * @port: The &struct drm_dp_mst_port to decrement the malloc refcount of
+ *
+ * Decrements &drm_dp_mst_port.malloc_kref. When &drm_dp_mst_port.malloc_kref
+ * reaches 0, the memory allocation for @port will be released and @port may
+ * no longer be used.
+ *
+ * See also: drm_dp_mst_get_port_malloc()
+ */
+void
+drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port)
+{
+       DRM_DEBUG("port %p (%d)\n", port, kref_read(&port->malloc_kref) - 1);
+       kref_put(&port->malloc_kref, drm_dp_free_mst_port);
+}
+EXPORT_SYMBOL(drm_dp_mst_put_port_malloc);
+
 static void drm_dp_destroy_mst_branch_device(struct kref *kref)
 {
-       struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref);
+       struct drm_dp_mst_branch *mstb =
+               container_of(kref, struct drm_dp_mst_branch, topology_kref);
+       struct drm_dp_mst_topology_mgr *mgr = mstb->mgr;
        struct drm_dp_mst_port *port, *tmp;
        bool wake_tx = false;
 
-       /*
-        * init kref again to be used by ports to remove mst branch when it is
-        * not needed anymore
-        */
-       kref_init(kref);
-
-       if (mstb->port_parent && list_empty(&mstb->port_parent->next))
-               kref_get(&mstb->port_parent->kref);
-
-       /*
-        * destroy all ports - don't need lock
-        * as there are no more references to the mst branch
-        * device at this point.
-        */
+       mutex_lock(&mgr->lock);
        list_for_each_entry_safe(port, tmp, &mstb->ports, next) {
                list_del(&port->next);
-               drm_dp_put_port(port);
+               drm_dp_mst_topology_put_port(port);
        }
+       mutex_unlock(&mgr->lock);
 
        /* drop any tx slots msg */
        mutex_lock(&mstb->mgr->qlock);
@@ -907,14 +1074,83 @@ static void drm_dp_destroy_mst_branch_device(struct kref *kref)
        if (wake_tx)
                wake_up_all(&mstb->mgr->tx_waitq);
 
-       kref_put(kref, drm_dp_free_mst_branch_device);
+       drm_dp_mst_put_mstb_malloc(mstb);
 }
 
-static void drm_dp_put_mst_branch_device(struct drm_dp_mst_branch *mstb)
+/**
+ * drm_dp_mst_topology_try_get_mstb() - Increment the topology refcount of a
+ * branch device unless its zero
+ * @mstb: &struct drm_dp_mst_branch to increment the topology refcount of
+ *
+ * Attempts to grab a topology reference to @mstb, if it hasn't yet been
+ * removed from the topology (e.g. &drm_dp_mst_branch.topology_kref has
+ * reached 0). Holding a topology reference implies that a malloc reference
+ * will be held to @mstb as long as the user holds the topology reference.
+ *
+ * Care should be taken to ensure that the user has at least one malloc
+ * reference to @mstb. If you already have a topology reference to @mstb, you
+ * should use drm_dp_mst_topology_get_mstb() instead.
+ *
+ * See also:
+ * drm_dp_mst_topology_get_mstb()
+ * drm_dp_mst_topology_put_mstb()
+ *
+ * Returns:
+ * * 1: A topology reference was grabbed successfully
+ * * 0: @port is no longer in the topology, no reference was grabbed
+ */
+static int __must_check
+drm_dp_mst_topology_try_get_mstb(struct drm_dp_mst_branch *mstb)
 {
-       kref_put(&mstb->kref, drm_dp_destroy_mst_branch_device);
+       int ret = kref_get_unless_zero(&mstb->topology_kref);
+
+       if (ret)
+               DRM_DEBUG("mstb %p (%d)\n", mstb,
+                         kref_read(&mstb->topology_kref));
+
+       return ret;
 }
 
+/**
+ * drm_dp_mst_topology_get_mstb() - Increment the topology refcount of a
+ * branch device
+ * @mstb: The &struct drm_dp_mst_branch to increment the topology refcount of
+ *
+ * Increments &drm_dp_mst_branch.topology_refcount without checking whether or
+ * not it's already reached 0. This is only valid to use in scenarios where
+ * you are already guaranteed to have at least one active topology reference
+ * to @mstb. Otherwise, drm_dp_mst_topology_try_get_mstb() must be used.
+ *
+ * See also:
+ * drm_dp_mst_topology_try_get_mstb()
+ * drm_dp_mst_topology_put_mstb()
+ */
+static void drm_dp_mst_topology_get_mstb(struct drm_dp_mst_branch *mstb)
+{
+       WARN_ON(kref_read(&mstb->topology_kref) == 0);
+       kref_get(&mstb->topology_kref);
+       DRM_DEBUG("mstb %p (%d)\n", mstb, kref_read(&mstb->topology_kref));
+}
+
+/**
+ * drm_dp_mst_topology_put_mstb() - release a topology reference to a branch
+ * device
+ * @mstb: The &struct drm_dp_mst_branch to release the topology reference from
+ *
+ * Releases a topology reference from @mstb by decrementing
+ * &drm_dp_mst_branch.topology_kref.
+ *
+ * See also:
+ * drm_dp_mst_topology_try_get_mstb()
+ * drm_dp_mst_topology_get_mstb()
+ */
+static void
+drm_dp_mst_topology_put_mstb(struct drm_dp_mst_branch *mstb)
+{
+       DRM_DEBUG("mstb %p (%d)\n",
+                 mstb, kref_read(&mstb->topology_kref) - 1);
+       kref_put(&mstb->topology_kref, drm_dp_destroy_mst_branch_device);
+}
 
 static void drm_dp_port_teardown_pdt(struct drm_dp_mst_port *port, int old_pdt)
 {
@@ -929,19 +1165,18 @@ static void drm_dp_port_teardown_pdt(struct drm_dp_mst_port *port, int old_pdt)
        case DP_PEER_DEVICE_MST_BRANCHING:
                mstb = port->mstb;
                port->mstb = NULL;
-               drm_dp_put_mst_branch_device(mstb);
+               drm_dp_mst_topology_put_mstb(mstb);
                break;
        }
 }
 
 static void drm_dp_destroy_port(struct kref *kref)
 {
-       struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref);
+       struct drm_dp_mst_port *port =
+               container_of(kref, struct drm_dp_mst_port, topology_kref);
        struct drm_dp_mst_topology_mgr *mgr = port->mgr;
 
        if (!port->input) {
-               port->vcpi.num_slots = 0;
-
                kfree(port->cached_edid);
 
                /*
@@ -955,7 +1190,6 @@ static void drm_dp_destroy_port(struct kref *kref)
                         * from an EDID retrieval */
 
                        mutex_lock(&mgr->destroy_connector_lock);
-                       kref_get(&port->parent->kref);
                        list_add(&port->next, &mgr->destroy_connector_list);
                        mutex_unlock(&mgr->destroy_connector_lock);
                        schedule_work(&mgr->destroy_connector_work);
@@ -966,25 +1200,95 @@ static void drm_dp_destroy_port(struct kref *kref)
                drm_dp_port_teardown_pdt(port, port->pdt);
                port->pdt = DP_PEER_DEVICE_NONE;
        }
-       kfree(port);
+       drm_dp_mst_put_port_malloc(port);
+}
+
+/**
+ * drm_dp_mst_topology_try_get_port() - Increment the topology refcount of a
+ * port unless its zero
+ * @port: &struct drm_dp_mst_port to increment the topology refcount of
+ *
+ * Attempts to grab a topology reference to @port, if it hasn't yet been
+ * removed from the topology (e.g. &drm_dp_mst_port.topology_kref has reached
+ * 0). Holding a topology reference implies that a malloc reference will be
+ * held to @port as long as the user holds the topology reference.
+ *
+ * Care should be taken to ensure that the user has at least one malloc
+ * reference to @port. If you already have a topology reference to @port, you
+ * should use drm_dp_mst_topology_get_port() instead.
+ *
+ * See also:
+ * drm_dp_mst_topology_get_port()
+ * drm_dp_mst_topology_put_port()
+ *
+ * Returns:
+ * * 1: A topology reference was grabbed successfully
+ * * 0: @port is no longer in the topology, no reference was grabbed
+ */
+static int __must_check
+drm_dp_mst_topology_try_get_port(struct drm_dp_mst_port *port)
+{
+       int ret = kref_get_unless_zero(&port->topology_kref);
+
+       if (ret)
+               DRM_DEBUG("port %p (%d)\n", port,
+                         kref_read(&port->topology_kref));
+
+       return ret;
+}
+
+/**
+ * drm_dp_mst_topology_get_port() - Increment the topology refcount of a port
+ * @port: The &struct drm_dp_mst_port to increment the topology refcount of
+ *
+ * Increments &drm_dp_mst_port.topology_refcount without checking whether or
+ * not it's already reached 0. This is only valid to use in scenarios where
+ * you are already guaranteed to have at least one active topology reference
+ * to @port. Otherwise, drm_dp_mst_topology_try_get_port() must be used.
+ *
+ * See also:
+ * drm_dp_mst_topology_try_get_port()
+ * drm_dp_mst_topology_put_port()
+ */
+static void drm_dp_mst_topology_get_port(struct drm_dp_mst_port *port)
+{
+       WARN_ON(kref_read(&port->topology_kref) == 0);
+       kref_get(&port->topology_kref);
+       DRM_DEBUG("port %p (%d)\n", port, kref_read(&port->topology_kref));
 }
 
-static void drm_dp_put_port(struct drm_dp_mst_port *port)
+/**
+ * drm_dp_mst_topology_put_port() - release a topology reference to a port
+ * @port: The &struct drm_dp_mst_port to release the topology reference from
+ *
+ * Releases a topology reference from @port by decrementing
+ * &drm_dp_mst_port.topology_kref.
+ *
+ * See also:
+ * drm_dp_mst_topology_try_get_port()
+ * drm_dp_mst_topology_get_port()
+ */
+static void drm_dp_mst_topology_put_port(struct drm_dp_mst_port *port)
 {
-       kref_put(&port->kref, drm_dp_destroy_port);
+       DRM_DEBUG("port %p (%d)\n",
+                 port, kref_read(&port->topology_kref) - 1);
+       kref_put(&port->topology_kref, drm_dp_destroy_port);
 }
 
-static struct drm_dp_mst_branch *drm_dp_mst_get_validated_mstb_ref_locked(struct drm_dp_mst_branch *mstb, struct drm_dp_mst_branch *to_find)
+static struct drm_dp_mst_branch *
+drm_dp_mst_topology_get_mstb_validated_locked(struct drm_dp_mst_branch *mstb,
+                                             struct drm_dp_mst_branch *to_find)
 {
        struct drm_dp_mst_port *port;
        struct drm_dp_mst_branch *rmstb;
-       if (to_find == mstb) {
-               kref_get(&mstb->kref);
+
+       if (to_find == mstb)
                return mstb;
-       }
+
        list_for_each_entry(port, &mstb->ports, next) {
                if (port->mstb) {
-                       rmstb = drm_dp_mst_get_validated_mstb_ref_locked(port->mstb, to_find);
+                       rmstb = drm_dp_mst_topology_get_mstb_validated_locked(
+                           port->mstb, to_find);
                        if (rmstb)
                                return rmstb;
                }
@@ -992,27 +1296,37 @@ static struct drm_dp_mst_branch *drm_dp_mst_get_validated_mstb_ref_locked(struct
        return NULL;
 }
 
-static struct drm_dp_mst_branch *drm_dp_get_validated_mstb_ref(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_branch *mstb)
+static struct drm_dp_mst_branch *
+drm_dp_mst_topology_get_mstb_validated(struct drm_dp_mst_topology_mgr *mgr,
+                                      struct drm_dp_mst_branch *mstb)
 {
        struct drm_dp_mst_branch *rmstb = NULL;
+
        mutex_lock(&mgr->lock);
-       if (mgr->mst_primary)
-               rmstb = drm_dp_mst_get_validated_mstb_ref_locked(mgr->mst_primary, mstb);
+       if (mgr->mst_primary) {
+               rmstb = drm_dp_mst_topology_get_mstb_validated_locked(
+                   mgr->mst_primary, mstb);
+
+               if (rmstb && !drm_dp_mst_topology_try_get_mstb(rmstb))
+                       rmstb = NULL;
+       }
        mutex_unlock(&mgr->lock);
        return rmstb;
 }
 
-static struct drm_dp_mst_port *drm_dp_mst_get_port_ref_locked(struct drm_dp_mst_branch *mstb, struct drm_dp_mst_port *to_find)
+static struct drm_dp_mst_port *
+drm_dp_mst_topology_get_port_validated_locked(struct drm_dp_mst_branch *mstb,
+                                             struct drm_dp_mst_port *to_find)
 {
        struct drm_dp_mst_port *port, *mport;
 
        list_for_each_entry(port, &mstb->ports, next) {
-               if (port == to_find) {
-                       kref_get(&port->kref);
+               if (port == to_find)
                        return port;
-               }
+
                if (port->mstb) {
-                       mport = drm_dp_mst_get_port_ref_locked(port->mstb, to_find);
+                       mport = drm_dp_mst_topology_get_port_validated_locked(
+                           port->mstb, to_find);
                        if (mport)
                                return mport;
                }
@@ -1020,12 +1334,20 @@ static struct drm_dp_mst_port *drm_dp_mst_get_port_ref_locked(struct drm_dp_mst_
        return NULL;
 }
 
-static struct drm_dp_mst_port *drm_dp_get_validated_port_ref(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+static struct drm_dp_mst_port *
+drm_dp_mst_topology_get_port_validated(struct drm_dp_mst_topology_mgr *mgr,
+                                      struct drm_dp_mst_port *port)
 {
        struct drm_dp_mst_port *rport = NULL;
+
        mutex_lock(&mgr->lock);
-       if (mgr->mst_primary)
-               rport = drm_dp_mst_get_port_ref_locked(mgr->mst_primary, port);
+       if (mgr->mst_primary) {
+               rport = drm_dp_mst_topology_get_port_validated_locked(
+                   mgr->mst_primary, port);
+
+               if (rport && !drm_dp_mst_topology_try_get_port(rport))
+                       rport = NULL;
+       }
        mutex_unlock(&mgr->lock);
        return rport;
 }
@@ -1033,11 +1355,12 @@ static struct drm_dp_mst_port *drm_dp_get_validated_port_ref(struct drm_dp_mst_t
 static struct drm_dp_mst_port *drm_dp_get_port(struct drm_dp_mst_branch *mstb, u8 port_num)
 {
        struct drm_dp_mst_port *port;
+       int ret;
 
        list_for_each_entry(port, &mstb->ports, next) {
                if (port->port_num == port_num) {
-                       kref_get(&port->kref);
-                       return port;
+                       ret = drm_dp_mst_topology_try_get_port(port);
+                       return ret ? port : NULL;
                }
        }
 
@@ -1086,6 +1409,11 @@ static bool drm_dp_port_setup_pdt(struct drm_dp_mst_port *port)
                if (port->mstb) {
                        port->mstb->mgr = port->mgr;
                        port->mstb->port_parent = port;
+                       /*
+                        * Make sure this port's memory allocation stays
+                        * around until it's child MSTB releases it
+                        */
+                       drm_dp_mst_get_port_malloc(port);
 
                        send_link = true;
                }
@@ -1146,17 +1474,26 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
        bool created = false;
        int old_pdt = 0;
        int old_ddps = 0;
+
        port = drm_dp_get_port(mstb, port_msg->port_number);
        if (!port) {
                port = kzalloc(sizeof(*port), GFP_KERNEL);
                if (!port)
                        return;
-               kref_init(&port->kref);
+               kref_init(&port->topology_kref);
+               kref_init(&port->malloc_kref);
                port->parent = mstb;
                port->port_num = port_msg->port_number;
                port->mgr = mstb->mgr;
                port->aux.name = "DPMST";
                port->aux.dev = dev->dev;
+
+               /*
+                * Make sure the memory allocation for our parent branch stays
+                * around until our own memory allocation is released
+                */
+               drm_dp_mst_get_mstb_malloc(mstb);
+
                created = true;
        } else {
                old_pdt = port->pdt;
@@ -1176,18 +1513,20 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
           for this list */
        if (created) {
                mutex_lock(&mstb->mgr->lock);
-               kref_get(&port->kref);
+               drm_dp_mst_topology_get_port(port);
                list_add(&port->next, &mstb->ports);
                mutex_unlock(&mstb->mgr->lock);
        }
 
        if (old_ddps != port->ddps) {
                if (port->ddps) {
-                       if (!port->input)
-                               drm_dp_send_enum_path_resources(mstb->mgr, mstb, port);
+                       if (!port->input) {
+                               drm_dp_send_enum_path_resources(mstb->mgr,
+                                                               mstb, port);
+                       }
                } else {
                        port->available_pbn = 0;
-                       }
+               }
        }
 
        if (old_pdt != port->pdt && !port->input) {
@@ -1201,21 +1540,25 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
        if (created && !port->input) {
                char proppath[255];
 
-               build_mst_prop_path(mstb, port->port_num, proppath, sizeof(proppath));
-               port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath);
+               build_mst_prop_path(mstb, port->port_num, proppath,
+                                   sizeof(proppath));
+               port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr,
+                                                                  port,
+                                                                  proppath);
                if (!port->connector) {
                        /* remove it from the port list */
                        mutex_lock(&mstb->mgr->lock);
                        list_del(&port->next);
                        mutex_unlock(&mstb->mgr->lock);
                        /* drop port list reference */
-                       drm_dp_put_port(port);
+                       drm_dp_mst_topology_put_port(port);
                        goto out;
                }
                if ((port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV ||
                     port->pdt == DP_PEER_DEVICE_SST_SINK) &&
                    port->port_num >= DP_MST_LOGICAL_PORT_0) {
-                       port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
+                       port->cached_edid = drm_get_edid(port->connector,
+                                                        &port->aux.ddc);
                        drm_connector_set_tile_property(port->connector);
                }
                (*mstb->mgr->cbs->register_connector)(port->connector);
@@ -1223,7 +1566,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
 
 out:
        /* put reference to this port */
-       drm_dp_put_port(port);
+       drm_dp_mst_topology_put_port(port);
 }
 
 static void drm_dp_update_port(struct drm_dp_mst_branch *mstb,
@@ -1258,7 +1601,7 @@ static void drm_dp_update_port(struct drm_dp_mst_branch *mstb,
                        dowork = true;
        }
 
-       drm_dp_put_port(port);
+       drm_dp_mst_topology_put_port(port);
        if (dowork)
                queue_work(system_long_wq, &mstb->mgr->work);
 
@@ -1269,7 +1612,7 @@ static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_
 {
        struct drm_dp_mst_branch *mstb;
        struct drm_dp_mst_port *port;
-       int i;
+       int i, ret;
        /* find the port by iterating down */
 
        mutex_lock(&mgr->lock);
@@ -1294,7 +1637,9 @@ static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_
                        }
                }
        }
-       kref_get(&mstb->kref);
+       ret = drm_dp_mst_topology_try_get_mstb(mstb);
+       if (!ret)
+               mstb = NULL;
 out:
        mutex_unlock(&mgr->lock);
        return mstb;
@@ -1324,19 +1669,22 @@ static struct drm_dp_mst_branch *get_mst_branch_device_by_guid_helper(
        return NULL;
 }
 
-static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device_by_guid(
-       struct drm_dp_mst_topology_mgr *mgr,
-       uint8_t *guid)
+static struct drm_dp_mst_branch *
+drm_dp_get_mst_branch_device_by_guid(struct drm_dp_mst_topology_mgr *mgr,
+                                    uint8_t *guid)
 {
        struct drm_dp_mst_branch *mstb;
+       int ret;
 
        /* find the port by iterating down */
        mutex_lock(&mgr->lock);
 
        mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid);
-
-       if (mstb)
-               kref_get(&mstb->kref);
+       if (mstb) {
+               ret = drm_dp_mst_topology_try_get_mstb(mstb);
+               if (!ret)
+                       mstb = NULL;
+       }
 
        mutex_unlock(&mgr->lock);
        return mstb;
@@ -1361,10 +1709,11 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m
                        drm_dp_send_enum_path_resources(mgr, mstb, port);
 
                if (port->mstb) {
-                       mstb_child = drm_dp_get_validated_mstb_ref(mgr, port->mstb);
+                       mstb_child = drm_dp_mst_topology_get_mstb_validated(
+                           mgr, port->mstb);
                        if (mstb_child) {
                                drm_dp_check_and_send_link_address(mgr, mstb_child);
-                               drm_dp_put_mst_branch_device(mstb_child);
+                               drm_dp_mst_topology_put_mstb(mstb_child);
                        }
                }
        }
@@ -1374,16 +1723,19 @@ static void drm_dp_mst_link_probe_work(struct work_struct *work)
 {
        struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, work);
        struct drm_dp_mst_branch *mstb;
+       int ret;
 
        mutex_lock(&mgr->lock);
        mstb = mgr->mst_primary;
        if (mstb) {
-               kref_get(&mstb->kref);
+               ret = drm_dp_mst_topology_try_get_mstb(mstb);
+               if (!ret)
+                       mstb = NULL;
        }
        mutex_unlock(&mgr->lock);
        if (mstb) {
                drm_dp_check_and_send_link_address(mgr, mstb);
-               drm_dp_put_mst_branch_device(mstb);
+               drm_dp_mst_topology_put_mstb(mstb);
        }
 }
 
@@ -1639,7 +1991,7 @@ static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
                        for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) {
                                drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]);
                        }
-                       (*mgr->cbs->hotplug)(mgr);
+                       drm_kms_helper_hotplug_event(mgr->dev);
                }
        } else {
                mstb->link_address_sent = false;
@@ -1694,22 +2046,40 @@ static struct drm_dp_mst_port *drm_dp_get_last_connected_port_to_mstb(struct drm
        return drm_dp_get_last_connected_port_to_mstb(mstb->port_parent->parent);
 }
 
-static struct drm_dp_mst_branch *drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr,
-                                                                        struct drm_dp_mst_branch *mstb,
-                                                                        int *port_num)
+/*
+ * Searches upwards in the topology starting from mstb to try to find the
+ * closest available parent of mstb that's still connected to the rest of the
+ * topology. This can be used in order to perform operations like releasing
+ * payloads, where the branch device which owned the payload may no longer be
+ * around and thus would require that the payload on the last living relative
+ * be freed instead.
+ */
+static struct drm_dp_mst_branch *
+drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr,
+                                       struct drm_dp_mst_branch *mstb,
+                                       int *port_num)
 {
        struct drm_dp_mst_branch *rmstb = NULL;
        struct drm_dp_mst_port *found_port;
+
        mutex_lock(&mgr->lock);
-       if (mgr->mst_primary) {
+       if (!mgr->mst_primary)
+               goto out;
+
+       do {
                found_port = drm_dp_get_last_connected_port_to_mstb(mstb);
+               if (!found_port)
+                       break;
 
-               if (found_port) {
+               if (drm_dp_mst_topology_try_get_mstb(found_port->parent)) {
                        rmstb = found_port->parent;
-                       kref_get(&rmstb->kref);
                        *port_num = found_port->port_num;
+               } else {
+                       /* Search again, starting from this parent */
+                       mstb = found_port->parent;
                }
-       }
+       } while (!rmstb);
+out:
        mutex_unlock(&mgr->lock);
        return rmstb;
 }
@@ -1725,19 +2095,15 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
        u8 sinks[DRM_DP_MAX_SDP_STREAMS];
        int i;
 
-       port = drm_dp_get_validated_port_ref(mgr, port);
-       if (!port)
-               return -EINVAL;
-
        port_num = port->port_num;
-       mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);
+       mstb = drm_dp_mst_topology_get_mstb_validated(mgr, port->parent);
        if (!mstb) {
-               mstb = drm_dp_get_last_connected_port_and_mstb(mgr, port->parent, &port_num);
+               mstb = drm_dp_get_last_connected_port_and_mstb(mgr,
+                                                              port->parent,
+                                                              &port_num);
 
-               if (!mstb) {
-                       drm_dp_put_port(port);
+               if (!mstb)
                        return -EINVAL;
-               }
        }
 
        txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
@@ -1756,17 +2122,24 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
 
        drm_dp_queue_down_tx(mgr, txmsg);
 
+       /*
+        * FIXME: there is a small chance that between getting the last
+        * connected mstb and sending the payload message, the last connected
+        * mstb could also be removed from the topology. In the future, this
+        * needs to be fixed by restarting the
+        * drm_dp_get_last_connected_port_and_mstb() search in the event of a
+        * timeout if the topology is still connected to the system.
+        */
        ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
        if (ret > 0) {
-               if (txmsg->reply.reply_type == 1) {
+               if (txmsg->reply.reply_type == 1)
                        ret = -EINVAL;
-               else
+               else
                        ret = 0;
        }
        kfree(txmsg);
 fail_put:
-       drm_dp_put_mst_branch_device(mstb);
-       drm_dp_put_port(port);
+       drm_dp_mst_topology_put_mstb(mstb);
        return ret;
 }
 
@@ -1776,13 +2149,13 @@ int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr,
        struct drm_dp_sideband_msg_tx *txmsg;
        int len, ret;
 
-       port = drm_dp_get_validated_port_ref(mgr, port);
+       port = drm_dp_mst_topology_get_port_validated(mgr, port);
        if (!port)
                return -EINVAL;
 
        txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
        if (!txmsg) {
-               drm_dp_put_port(port);
+               drm_dp_mst_topology_put_port(port);
                return -ENOMEM;
        }
 
@@ -1798,7 +2171,7 @@ int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr,
                        ret = 0;
        }
        kfree(txmsg);
-       drm_dp_put_port(port);
+       drm_dp_mst_topology_put_port(port);
 
        return ret;
 }
@@ -1871,72 +2244,93 @@ static int drm_dp_destroy_payload_step2(struct drm_dp_mst_topology_mgr *mgr,
  */
 int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr)
 {
-       int i, j;
-       int cur_slots = 1;
        struct drm_dp_payload req_payload;
        struct drm_dp_mst_port *port;
+       int i, j;
+       int cur_slots = 1;
 
        mutex_lock(&mgr->payload_lock);
        for (i = 0; i < mgr->max_payloads; i++) {
+               struct drm_dp_vcpi *vcpi = mgr->proposed_vcpis[i];
+               struct drm_dp_payload *payload = &mgr->payloads[i];
+               bool put_port = false;
+
                /* solve the current payloads - compare to the hw ones
                   - update the hw view */
                req_payload.start_slot = cur_slots;
-               if (mgr->proposed_vcpis[i]) {
-                       port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi);
-                       port = drm_dp_get_validated_port_ref(mgr, port);
-                       if (!port) {
-                               mutex_unlock(&mgr->payload_lock);
-                               return -EINVAL;
+               if (vcpi) {
+                       port = container_of(vcpi, struct drm_dp_mst_port,
+                                           vcpi);
+
+                       /* Validated ports don't matter if we're releasing
+                        * VCPI
+                        */
+                       if (vcpi->num_slots) {
+                               port = drm_dp_mst_topology_get_port_validated(
+                                   mgr, port);
+                               if (!port) {
+                                       mutex_unlock(&mgr->payload_lock);
+                                       return -EINVAL;
+                               }
+                               put_port = true;
                        }
-                       req_payload.num_slots = mgr->proposed_vcpis[i]->num_slots;
-                       req_payload.vcpi = mgr->proposed_vcpis[i]->vcpi;
+
+                       req_payload.num_slots = vcpi->num_slots;
+                       req_payload.vcpi = vcpi->vcpi;
                } else {
                        port = NULL;
                        req_payload.num_slots = 0;
                }
 
-               if (mgr->payloads[i].start_slot != req_payload.start_slot) {
-                       mgr->payloads[i].start_slot = req_payload.start_slot;
-               }
+               payload->start_slot = req_payload.start_slot;
                /* work out what is required to happen with this payload */
-               if (mgr->payloads[i].num_slots != req_payload.num_slots) {
+               if (payload->num_slots != req_payload.num_slots) {
 
                        /* need to push an update for this payload */
                        if (req_payload.num_slots) {
-                               drm_dp_create_payload_step1(mgr, mgr->proposed_vcpis[i]->vcpi, &req_payload);
-                               mgr->payloads[i].num_slots = req_payload.num_slots;
-                               mgr->payloads[i].vcpi = req_payload.vcpi;
-                       } else if (mgr->payloads[i].num_slots) {
-                               mgr->payloads[i].num_slots = 0;
-                               drm_dp_destroy_payload_step1(mgr, port, mgr->payloads[i].vcpi, &mgr->payloads[i]);
-                               req_payload.payload_state = mgr->payloads[i].payload_state;
-                               mgr->payloads[i].start_slot = 0;
+                               drm_dp_create_payload_step1(mgr, vcpi->vcpi,
+                                                           &req_payload);
+                               payload->num_slots = req_payload.num_slots;
+                               payload->vcpi = req_payload.vcpi;
+
+                       } else if (payload->num_slots) {
+                               payload->num_slots = 0;
+                               drm_dp_destroy_payload_step1(mgr, port,
+                                                            payload->vcpi,
+                                                            payload);
+                               req_payload.payload_state =
+                                       payload->payload_state;
+                               payload->start_slot = 0;
                        }
-                       mgr->payloads[i].payload_state = req_payload.payload_state;
+                       payload->payload_state = req_payload.payload_state;
                }
                cur_slots += req_payload.num_slots;
 
-               if (port)
-                       drm_dp_put_port(port);
+               if (put_port)
+                       drm_dp_mst_topology_put_port(port);
        }
 
        for (i = 0; i < mgr->max_payloads; i++) {
-               if (mgr->payloads[i].payload_state == DP_PAYLOAD_DELETE_LOCAL) {
-                       DRM_DEBUG_KMS("removing payload %d\n", i);
-                       for (j = i; j < mgr->max_payloads - 1; j++) {
-                               memcpy(&mgr->payloads[j], &mgr->payloads[j + 1], sizeof(struct drm_dp_payload));
-                               mgr->proposed_vcpis[j] = mgr->proposed_vcpis[j + 1];
-                               if (mgr->proposed_vcpis[j] && mgr->proposed_vcpis[j]->num_slots) {
-                                       set_bit(j + 1, &mgr->payload_mask);
-                               } else {
-                                       clear_bit(j + 1, &mgr->payload_mask);
-                               }
-                       }
-                       memset(&mgr->payloads[mgr->max_payloads - 1], 0, sizeof(struct drm_dp_payload));
-                       mgr->proposed_vcpis[mgr->max_payloads - 1] = NULL;
-                       clear_bit(mgr->max_payloads, &mgr->payload_mask);
+               if (mgr->payloads[i].payload_state != DP_PAYLOAD_DELETE_LOCAL)
+                       continue;
+
+               DRM_DEBUG_KMS("removing payload %d\n", i);
+               for (j = i; j < mgr->max_payloads - 1; j++) {
+                       mgr->payloads[j] = mgr->payloads[j + 1];
+                       mgr->proposed_vcpis[j] = mgr->proposed_vcpis[j + 1];
 
+                       if (mgr->proposed_vcpis[j] &&
+                           mgr->proposed_vcpis[j]->num_slots) {
+                               set_bit(j + 1, &mgr->payload_mask);
+                       } else {
+                               clear_bit(j + 1, &mgr->payload_mask);
+                       }
                }
+
+               memset(&mgr->payloads[mgr->max_payloads - 1], 0,
+                      sizeof(struct drm_dp_payload));
+               mgr->proposed_vcpis[mgr->max_payloads - 1] = NULL;
+               clear_bit(mgr->max_payloads, &mgr->payload_mask);
        }
        mutex_unlock(&mgr->payload_lock);
 
@@ -2012,7 +2406,7 @@ static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
        struct drm_dp_sideband_msg_tx *txmsg;
        struct drm_dp_mst_branch *mstb;
 
-       mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);
+       mstb = drm_dp_mst_topology_get_mstb_validated(mgr, port->parent);
        if (!mstb)
                return -EINVAL;
 
@@ -2036,7 +2430,7 @@ static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
        }
        kfree(txmsg);
 fail_put:
-       drm_dp_put_mst_branch_device(mstb);
+       drm_dp_mst_topology_put_mstb(mstb);
        return ret;
 }
 
@@ -2146,7 +2540,7 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
 
                /* give this the main reference */
                mgr->mst_primary = mstb;
-               kref_get(&mgr->mst_primary->kref);
+               drm_dp_mst_topology_get_mstb(mgr->mst_primary);
 
                ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
                                                         DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC);
@@ -2180,7 +2574,7 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
 out_unlock:
        mutex_unlock(&mgr->lock);
        if (mstb)
-               drm_dp_put_mst_branch_device(mstb);
+               drm_dp_mst_topology_put_mstb(mstb);
        return ret;
 
 }
@@ -2345,7 +2739,7 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
                               mgr->down_rep_recv.initial_hdr.lct,
                                      mgr->down_rep_recv.initial_hdr.rad[0],
                                      mgr->down_rep_recv.msg[0]);
-                       drm_dp_put_mst_branch_device(mstb);
+                       drm_dp_mst_topology_put_mstb(mstb);
                        memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
                        return 0;
                }
@@ -2356,7 +2750,7 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
                }
 
                memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
-               drm_dp_put_mst_branch_device(mstb);
+               drm_dp_mst_topology_put_mstb(mstb);
 
                mutex_lock(&mgr->qlock);
                txmsg->state = DRM_DP_SIDEBAND_TX_RX;
@@ -2412,7 +2806,7 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
                        drm_dp_update_port(mstb, &msg.u.conn_stat);
 
                        DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type);
-                       (*mgr->cbs->hotplug)(mgr);
+                       drm_kms_helper_hotplug_event(mgr->dev);
 
                } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
                        drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
@@ -2429,7 +2823,7 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
                }
 
                if (mstb)
-                       drm_dp_put_mst_branch_device(mstb);
+                       drm_dp_mst_topology_put_mstb(mstb);
 
                memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
        }
@@ -2489,7 +2883,7 @@ enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector
        enum drm_connector_status status = connector_status_disconnected;
 
        /* we need to search for the port in the mgr in case its gone */
-       port = drm_dp_get_validated_port_ref(mgr, port);
+       port = drm_dp_mst_topology_get_port_validated(mgr, port);
        if (!port)
                return connector_status_disconnected;
 
@@ -2514,7 +2908,7 @@ enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector
                break;
        }
 out:
-       drm_dp_put_port(port);
+       drm_dp_mst_topology_put_port(port);
        return status;
 }
 EXPORT_SYMBOL(drm_dp_mst_detect_port);
@@ -2531,11 +2925,11 @@ bool drm_dp_mst_port_has_audio(struct drm_dp_mst_topology_mgr *mgr,
 {
        bool ret = false;
 
-       port = drm_dp_get_validated_port_ref(mgr, port);
+       port = drm_dp_mst_topology_get_port_validated(mgr, port);
        if (!port)
                return ret;
        ret = port->has_audio;
-       drm_dp_put_port(port);
+       drm_dp_mst_topology_put_port(port);
        return ret;
 }
 EXPORT_SYMBOL(drm_dp_mst_port_has_audio);
@@ -2555,7 +2949,7 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
        struct edid *edid = NULL;
 
        /* we need to search for the port in the mgr in case its gone */
-       port = drm_dp_get_validated_port_ref(mgr, port);
+       port = drm_dp_mst_topology_get_port_validated(mgr, port);
        if (!port)
                return NULL;
 
@@ -2566,7 +2960,7 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
                drm_connector_set_tile_property(connector);
        }
        port->has_audio = drm_detect_monitor_audio(edid);
-       drm_dp_put_port(port);
+       drm_dp_mst_topology_put_port(port);
        return edid;
 }
 EXPORT_SYMBOL(drm_dp_mst_get_edid);
@@ -2617,43 +3011,98 @@ static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr,
 }
 
 /**
- * drm_dp_atomic_find_vcpi_slots() - Find and add vcpi slots to the state
+ * drm_dp_atomic_find_vcpi_slots() - Find and add VCPI slots to the state
  * @state: global atomic state
  * @mgr: MST topology manager for the port
  * @port: port to find vcpi slots for
  * @pbn: bandwidth required for the mode in PBN
  *
- * RETURNS:
- * Total slots in the atomic state assigned for this port or error
+ * Allocates VCPI slots to @port, replacing any previous VCPI allocations it
+ * may have had. Any atomic drivers which support MST must call this function
+ * in their &drm_encoder_helper_funcs.atomic_check() callback to change the
+ * current VCPI allocation for the new state, but only when
+ * &drm_crtc_state.mode_changed or &drm_crtc_state.connectors_changed is set
+ * to ensure compatibility with userspace applications that still use the
+ * legacy modesetting UAPI.
+ *
+ * Allocations set by this function are not checked against the bandwidth
+ * restraints of @mgr until the driver calls drm_dp_mst_atomic_check().
+ *
+ * Additionally, it is OK to call this function multiple times on the same
+ * @port as needed. It is not OK however, to call this function and
+ * drm_dp_atomic_release_vcpi_slots() in the same atomic check phase.
+ *
+ * See also:
+ * drm_dp_atomic_release_vcpi_slots()
+ * drm_dp_mst_atomic_check()
+ *
+ * Returns:
+ * Total slots in the atomic state assigned for this port, or a negative error
+ * code if the port no longer exists
  */
 int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
                                  struct drm_dp_mst_topology_mgr *mgr,
                                  struct drm_dp_mst_port *port, int pbn)
 {
        struct drm_dp_mst_topology_state *topology_state;
-       int req_slots;
+       struct drm_dp_vcpi_allocation *pos, *vcpi = NULL;
+       int prev_slots, req_slots, ret;
 
        topology_state = drm_atomic_get_mst_topology_state(state, mgr);
        if (IS_ERR(topology_state))
                return PTR_ERR(topology_state);
 
-       port = drm_dp_get_validated_port_ref(mgr, port);
+       port = drm_dp_mst_topology_get_port_validated(mgr, port);
        if (port == NULL)
                return -EINVAL;
-       req_slots = DIV_ROUND_UP(pbn, mgr->pbn_div);
-       DRM_DEBUG_KMS("vcpi slots req=%d, avail=%d\n",
-                       req_slots, topology_state->avail_slots);
 
-       if (req_slots > topology_state->avail_slots) {
-               drm_dp_put_port(port);
-               return -ENOSPC;
+       /* Find the current allocation for this port, if any */
+       list_for_each_entry(pos, &topology_state->vcpis, next) {
+               if (pos->port == port) {
+                       vcpi = pos;
+                       prev_slots = vcpi->vcpi;
+
+                       /*
+                        * This should never happen, unless the driver tries
+                        * releasing and allocating the same VCPI allocation,
+                        * which is an error
+                        */
+                       if (WARN_ON(!prev_slots)) {
+                               DRM_ERROR("cannot allocate and release VCPI on [MST PORT:%p] in the same state\n",
+                                         port);
+                               return -EINVAL;
+                       }
+
+                       break;
+               }
        }
+       if (!vcpi)
+               prev_slots = 0;
 
-       topology_state->avail_slots -= req_slots;
-       DRM_DEBUG_KMS("vcpi slots avail=%d", topology_state->avail_slots);
+       req_slots = DIV_ROUND_UP(pbn, mgr->pbn_div);
 
-       drm_dp_put_port(port);
-       return req_slots;
+       DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] [MST PORT:%p] VCPI %d -> %d\n",
+                        port->connector->base.id, port->connector->name,
+                        port, prev_slots, req_slots);
+
+       /* Add the new allocation to the state */
+       if (!vcpi) {
+               vcpi = kzalloc(sizeof(*vcpi), GFP_KERNEL);
+               if (!vcpi) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               drm_dp_mst_get_port_malloc(port);
+               vcpi->port = port;
+               list_add(&vcpi->next, &topology_state->vcpis);
+       }
+       vcpi->vcpi = req_slots;
+
+       ret = req_slots;
+out:
+       drm_dp_mst_topology_put_port(port);
+       return ret;
 }
 EXPORT_SYMBOL(drm_dp_atomic_find_vcpi_slots);
 
@@ -2661,31 +3110,57 @@ EXPORT_SYMBOL(drm_dp_atomic_find_vcpi_slots);
  * drm_dp_atomic_release_vcpi_slots() - Release allocated vcpi slots
  * @state: global atomic state
  * @mgr: MST topology manager for the port
- * @slots: number of vcpi slots to release
+ * @port: The port to release the VCPI slots from
  *
- * RETURNS:
- * 0 if @slots were added back to &drm_dp_mst_topology_state->avail_slots or
- * negative error code
+ * Releases any VCPI slots that have been allocated to a port in the atomic
+ * state. Any atomic drivers which support MST must call this function in
+ * their &drm_connector_helper_funcs.atomic_check() callback when the
+ * connector will no longer have VCPI allocated (e.g. because it's CRTC was
+ * removed) when it had VCPI allocated in the previous atomic state.
+ *
+ * It is OK to call this even if @port has been removed from the system.
+ * Additionally, it is OK to call this function multiple times on the same
+ * @port as needed. It is not OK however, to call this function and
+ * drm_dp_atomic_find_vcpi_slots() on the same @port in a single atomic check
+ * phase.
+ *
+ * See also:
+ * drm_dp_atomic_find_vcpi_slots()
+ * drm_dp_mst_atomic_check()
+ *
+ * Returns:
+ * 0 if all slots for this port were added back to
+ * &drm_dp_mst_topology_state.avail_slots or negative error code
  */
 int drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state,
                                     struct drm_dp_mst_topology_mgr *mgr,
-                                    int slots)
+                                    struct drm_dp_mst_port *port)
 {
        struct drm_dp_mst_topology_state *topology_state;
+       struct drm_dp_vcpi_allocation *pos;
+       bool found = false;
 
        topology_state = drm_atomic_get_mst_topology_state(state, mgr);
        if (IS_ERR(topology_state))
                return PTR_ERR(topology_state);
 
-       /* We cannot rely on port->vcpi.num_slots to update
-        * topology_state->avail_slots as the port may not exist if the parent
-        * branch device was unplugged. This should be fixed by tracking
-        * per-port slot allocation in drm_dp_mst_topology_state instead of
-        * depending on the caller to tell us how many slots to release.
-        */
-       topology_state->avail_slots += slots;
-       DRM_DEBUG_KMS("vcpi slots released=%d, avail=%d\n",
-                       slots, topology_state->avail_slots);
+       list_for_each_entry(pos, &topology_state->vcpis, next) {
+               if (pos->port == port) {
+                       found = true;
+                       break;
+               }
+       }
+       if (WARN_ON(!found)) {
+               DRM_ERROR("no VCPI for [MST PORT:%p] found in mst state %p\n",
+                         port, &topology_state->base);
+               return -EINVAL;
+       }
+
+       DRM_DEBUG_ATOMIC("[MST PORT:%p] VCPI %d -> 0\n", port, pos->vcpi);
+       if (pos->vcpi) {
+               drm_dp_mst_put_port_malloc(port);
+               pos->vcpi = 0;
+       }
 
        return 0;
 }
@@ -2703,7 +3178,7 @@ bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
 {
        int ret;
 
-       port = drm_dp_get_validated_port_ref(mgr, port);
+       port = drm_dp_mst_topology_get_port_validated(mgr, port);
        if (!port)
                return false;
 
@@ -2711,9 +3186,10 @@ bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
                return false;
 
        if (port->vcpi.vcpi > 0) {
-               DRM_DEBUG_KMS("payload: vcpi %d already allocated for pbn %d - requested pbn %d\n", port->vcpi.vcpi, port->vcpi.pbn, pbn);
+               DRM_DEBUG_KMS("payload: vcpi %d already allocated for pbn %d - requested pbn %d\n",
+                             port->vcpi.vcpi, port->vcpi.pbn, pbn);
                if (pbn == port->vcpi.pbn) {
-                       drm_dp_put_port(port);
+                       drm_dp_mst_topology_put_port(port);
                        return true;
                }
        }
@@ -2721,13 +3197,15 @@ bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
        ret = drm_dp_init_vcpi(mgr, &port->vcpi, pbn, slots);
        if (ret) {
                DRM_DEBUG_KMS("failed to init vcpi slots=%d max=63 ret=%d\n",
-                               DIV_ROUND_UP(pbn, mgr->pbn_div), ret);
+                             DIV_ROUND_UP(pbn, mgr->pbn_div), ret);
                goto out;
        }
        DRM_DEBUG_KMS("initing vcpi for pbn=%d slots=%d\n",
-                       pbn, port->vcpi.num_slots);
+                     pbn, port->vcpi.num_slots);
 
-       drm_dp_put_port(port);
+       /* Keep port allocated until it's payload has been removed */
+       drm_dp_mst_get_port_malloc(port);
+       drm_dp_mst_topology_put_port(port);
        return true;
 out:
        return false;
@@ -2737,12 +3215,12 @@ EXPORT_SYMBOL(drm_dp_mst_allocate_vcpi);
 int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
 {
        int slots = 0;
-       port = drm_dp_get_validated_port_ref(mgr, port);
+       port = drm_dp_mst_topology_get_port_validated(mgr, port);
        if (!port)
                return slots;
 
        slots = port->vcpi.num_slots;
-       drm_dp_put_port(port);
+       drm_dp_mst_topology_put_port(port);
        return slots;
 }
 EXPORT_SYMBOL(drm_dp_mst_get_vcpi_slots);
@@ -2756,11 +3234,12 @@ EXPORT_SYMBOL(drm_dp_mst_get_vcpi_slots);
  */
 void drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
 {
-       port = drm_dp_get_validated_port_ref(mgr, port);
-       if (!port)
-               return;
+       /*
+        * A port with VCPI will remain allocated until it's VCPI is
+        * released, no verified ref needed
+        */
+
        port->vcpi.num_slots = 0;
-       drm_dp_put_port(port);
 }
 EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots);
 
@@ -2769,18 +3248,20 @@ EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots);
  * @mgr: manager for this port
  * @port: unverified port to deallocate vcpi for
  */
-void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
+                               struct drm_dp_mst_port *port)
 {
-       port = drm_dp_get_validated_port_ref(mgr, port);
-       if (!port)
-               return;
+       /*
+        * A port with VCPI will remain allocated until it's VCPI is
+        * released, no verified ref needed
+        */
 
        drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
        port->vcpi.num_slots = 0;
        port->vcpi.pbn = 0;
        port->vcpi.aligned_pbn = 0;
        port->vcpi.vcpi = 0;
-       drm_dp_put_port(port);
+       drm_dp_mst_put_port_malloc(port);
 }
 EXPORT_SYMBOL(drm_dp_mst_deallocate_vcpi);
 
@@ -3064,13 +3545,6 @@ static void drm_dp_tx_work(struct work_struct *work)
        mutex_unlock(&mgr->qlock);
 }
 
-static void drm_dp_free_mst_port(struct kref *kref)
-{
-       struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref);
-       kref_put(&port->parent->kref, drm_dp_free_mst_branch_device);
-       kfree(port);
-}
-
 static void drm_dp_destroy_connector_work(struct work_struct *work)
 {
        struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work);
@@ -3091,7 +3565,6 @@ static void drm_dp_destroy_connector_work(struct work_struct *work)
                list_del(&port->next);
                mutex_unlock(&mgr->destroy_connector_lock);
 
-               kref_init(&port->kref);
                INIT_LIST_HEAD(&port->next);
 
                mgr->cbs->destroy_connector(mgr, port->connector);
@@ -3099,31 +3572,51 @@ static void drm_dp_destroy_connector_work(struct work_struct *work)
                drm_dp_port_teardown_pdt(port, port->pdt);
                port->pdt = DP_PEER_DEVICE_NONE;
 
-               if (!port->input && port->vcpi.vcpi > 0) {
-                       drm_dp_mst_reset_vcpi_slots(mgr, port);
-                       drm_dp_update_payload_part1(mgr);
-                       drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
-               }
-
-               kref_put(&port->kref, drm_dp_free_mst_port);
+               drm_dp_mst_put_port_malloc(port);
                send_hotplug = true;
        }
        if (send_hotplug)
-               (*mgr->cbs->hotplug)(mgr);
+               drm_kms_helper_hotplug_event(mgr->dev);
 }
 
 static struct drm_private_state *
 drm_dp_mst_duplicate_state(struct drm_private_obj *obj)
 {
-       struct drm_dp_mst_topology_state *state;
+       struct drm_dp_mst_topology_state *state, *old_state =
+               to_dp_mst_topology_state(obj->state);
+       struct drm_dp_vcpi_allocation *pos, *vcpi;
 
-       state = kmemdup(obj->state, sizeof(*state), GFP_KERNEL);
+       state = kmemdup(old_state, sizeof(*state), GFP_KERNEL);
        if (!state)
                return NULL;
 
        __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base);
 
+       INIT_LIST_HEAD(&state->vcpis);
+
+       list_for_each_entry(pos, &old_state->vcpis, next) {
+               /* Prune leftover freed VCPI allocations */
+               if (!pos->vcpi)
+                       continue;
+
+               vcpi = kmemdup(pos, sizeof(*vcpi), GFP_KERNEL);
+               if (!vcpi)
+                       goto fail;
+
+               drm_dp_mst_get_port_malloc(vcpi->port);
+               list_add(&vcpi->next, &state->vcpis);
+       }
+
        return &state->base;
+
+fail:
+       list_for_each_entry_safe(pos, vcpi, &state->vcpis, next) {
+               drm_dp_mst_put_port_malloc(pos->port);
+               kfree(pos);
+       }
+       kfree(state);
+
+       return NULL;
 }
 
 static void drm_dp_mst_destroy_state(struct drm_private_obj *obj,
@@ -3131,14 +3624,99 @@ static void drm_dp_mst_destroy_state(struct drm_private_obj *obj,
 {
        struct drm_dp_mst_topology_state *mst_state =
                to_dp_mst_topology_state(state);
+       struct drm_dp_vcpi_allocation *pos, *tmp;
+
+       list_for_each_entry_safe(pos, tmp, &mst_state->vcpis, next) {
+               /* We only keep references to ports with non-zero VCPIs */
+               if (pos->vcpi)
+                       drm_dp_mst_put_port_malloc(pos->port);
+               kfree(pos);
+       }
 
        kfree(mst_state);
 }
 
-static const struct drm_private_state_funcs mst_state_funcs = {
+static inline int
+drm_dp_mst_atomic_check_topology_state(struct drm_dp_mst_topology_mgr *mgr,
+                                      struct drm_dp_mst_topology_state *mst_state)
+{
+       struct drm_dp_vcpi_allocation *vcpi;
+       int avail_slots = 63, payload_count = 0;
+
+       list_for_each_entry(vcpi, &mst_state->vcpis, next) {
+               /* Releasing VCPI is always OK-even if the port is gone */
+               if (!vcpi->vcpi) {
+                       DRM_DEBUG_ATOMIC("[MST PORT:%p] releases all VCPI slots\n",
+                                        vcpi->port);
+                       continue;
+               }
+
+               DRM_DEBUG_ATOMIC("[MST PORT:%p] requires %d vcpi slots\n",
+                                vcpi->port, vcpi->vcpi);
+
+               avail_slots -= vcpi->vcpi;
+               if (avail_slots < 0) {
+                       DRM_DEBUG_ATOMIC("[MST PORT:%p] not enough VCPI slots in mst state %p (avail=%d)\n",
+                                        vcpi->port, mst_state,
+                                        avail_slots + vcpi->vcpi);
+                       return -ENOSPC;
+               }
+
+               if (++payload_count > mgr->max_payloads) {
+                       DRM_DEBUG_ATOMIC("[MST MGR:%p] state %p has too many payloads (max=%d)\n",
+                                        mgr, mst_state, mgr->max_payloads);
+                       return -EINVAL;
+               }
+       }
+       DRM_DEBUG_ATOMIC("[MST MGR:%p] mst state %p VCPI avail=%d used=%d\n",
+                        mgr, mst_state, avail_slots,
+                        63 - avail_slots);
+
+       return 0;
+}
+
+/**
+ * drm_dp_mst_atomic_check - Check that the new state of an MST topology in an
+ * atomic update is valid
+ * @state: Pointer to the new &struct drm_dp_mst_topology_state
+ *
+ * Checks the given topology state for an atomic update to ensure that it's
+ * valid. This includes checking whether there's enough bandwidth to support
+ * the new VCPI allocations in the atomic update.
+ *
+ * Any atomic drivers supporting DP MST must make sure to call this after
+ * checking the rest of their state in their
+ * &drm_mode_config_funcs.atomic_check() callback.
+ *
+ * See also:
+ * drm_dp_atomic_find_vcpi_slots()
+ * drm_dp_atomic_release_vcpi_slots()
+ *
+ * Returns:
+ *
+ * 0 if the new state is valid, negative error code otherwise.
+ */
+int drm_dp_mst_atomic_check(struct drm_atomic_state *state)
+{
+       struct drm_dp_mst_topology_mgr *mgr;
+       struct drm_dp_mst_topology_state *mst_state;
+       int i, ret = 0;
+
+       for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) {
+               ret = drm_dp_mst_atomic_check_topology_state(mgr, mst_state);
+               if (ret)
+                       break;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(drm_dp_mst_atomic_check);
+
+const struct drm_private_state_funcs drm_dp_mst_topology_state_funcs = {
        .atomic_duplicate_state = drm_dp_mst_duplicate_state,
        .atomic_destroy_state = drm_dp_mst_destroy_state,
 };
+EXPORT_SYMBOL(drm_dp_mst_topology_state_funcs);
 
 /**
  * drm_atomic_get_mst_topology_state: get MST topology state
@@ -3216,13 +3794,11 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
                return -ENOMEM;
 
        mst_state->mgr = mgr;
+       INIT_LIST_HEAD(&mst_state->vcpis);
 
-       /* max. time slots - one slot for MTP header */
-       mst_state->avail_slots = 63;
-
-       drm_atomic_private_obj_init(&mgr->base,
+       drm_atomic_private_obj_init(dev, &mgr->base,
                                    &mst_state->base,
-                                   &mst_state_funcs);
+                                   &drm_dp_mst_topology_state_funcs);
 
        return 0;
 }
@@ -3234,6 +3810,7 @@ EXPORT_SYMBOL(drm_dp_mst_topology_mgr_init);
  */
 void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr)
 {
+       drm_dp_mst_topology_mgr_set_mst(mgr, false);
        flush_work(&mgr->work);
        flush_work(&mgr->destroy_connector_work);
        mutex_lock(&mgr->payload_lock);
@@ -3249,6 +3826,23 @@ void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr)
 }
 EXPORT_SYMBOL(drm_dp_mst_topology_mgr_destroy);
 
+static bool remote_i2c_read_ok(const struct i2c_msg msgs[], int num)
+{
+       int i;
+
+       if (num - 1 > DP_REMOTE_I2C_READ_MAX_TRANSACTIONS)
+               return false;
+
+       for (i = 0; i < num - 1; i++) {
+               if (msgs[i].flags & I2C_M_RD ||
+                   msgs[i].len > 0xff)
+                       return false;
+       }
+
+       return msgs[num - 1].flags & I2C_M_RD &&
+               msgs[num - 1].len <= 0xff;
+}
+
 /* I2C device */
 static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
                               int num)
@@ -3258,21 +3852,15 @@ static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs
        struct drm_dp_mst_branch *mstb;
        struct drm_dp_mst_topology_mgr *mgr = port->mgr;
        unsigned int i;
-       bool reading = false;
        struct drm_dp_sideband_msg_req_body msg;
        struct drm_dp_sideband_msg_tx *txmsg = NULL;
        int ret;
 
-       mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);
+       mstb = drm_dp_mst_topology_get_mstb_validated(mgr, port->parent);
        if (!mstb)
                return -EREMOTEIO;
 
-       /* construct i2c msg */
-       /* see if last msg is a read */
-       if (msgs[num - 1].flags & I2C_M_RD)
-               reading = true;
-
-       if (!reading || (num - 1 > DP_REMOTE_I2C_READ_MAX_TRANSACTIONS)) {
+       if (!remote_i2c_read_ok(msgs, num)) {
                DRM_DEBUG_KMS("Unsupported I2C transaction for MST device\n");
                ret = -EIO;
                goto out;
@@ -3286,6 +3874,7 @@ static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs
                msg.u.i2c_read.transactions[i].i2c_dev_id = msgs[i].addr;
                msg.u.i2c_read.transactions[i].num_bytes = msgs[i].len;
                msg.u.i2c_read.transactions[i].bytes = msgs[i].buf;
+               msg.u.i2c_read.transactions[i].no_stop_bit = !(msgs[i].flags & I2C_M_STOP);
        }
        msg.u.i2c_read.read_i2c_device_id = msgs[num - 1].addr;
        msg.u.i2c_read.num_bytes_read = msgs[num - 1].len;
@@ -3317,7 +3906,7 @@ static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs
        }
 out:
        kfree(txmsg);
-       drm_dp_put_mst_branch_device(mstb);
+       drm_dp_mst_topology_put_mstb(mstb);
        return ret;
 }
 
index 12e5e2be7890e39952947f85594675093f4e8eb9..381581b01d485e581df8bcebcd6983b01bc8a488 100644 (file)
@@ -41,7 +41,6 @@
 #include "drm_crtc_internal.h"
 #include "drm_legacy.h"
 #include "drm_internal.h"
-#include "drm_crtc_internal.h"
 
 /*
  * drm_debug: Enable debug output.
@@ -265,14 +264,13 @@ void drm_minor_release(struct drm_minor *minor)
  * DOC: driver instance overview
  *
  * A device instance for a drm driver is represented by &struct drm_device. This
- * is allocated with drm_dev_alloc(), usually from bus-specific ->probe()
+ * is initialized with drm_dev_init(), usually from bus-specific ->probe()
  * callbacks implemented by the driver. The driver then needs to initialize all
  * the various subsystems for the drm device like memory management, vblank
  * handling, modesetting support and intial output configuration plus obviously
- * initialize all the corresponding hardware bits. An important part of this is
- * also calling drm_dev_set_unique() to set the userspace-visible unique name of
- * this device instance. Finally when everything is up and running and ready for
- * userspace the device instance can be published using drm_dev_register().
+ * initialize all the corresponding hardware bits. Finally when everything is up
+ * and running and ready for userspace the device instance can be published
+ * using drm_dev_register().
  *
  * There is also deprecated support for initalizing device instances using
  * bus-specific helpers and the &drm_driver.load callback. But due to
@@ -288,9 +286,6 @@ void drm_minor_release(struct drm_minor *minor)
  * Note that the lifetime rules for &drm_device instance has still a lot of
  * historical baggage. Hence use the reference counting provided by
  * drm_dev_get() and drm_dev_put() only carefully.
- *
- * It is recommended that drivers embed &struct drm_device into their own device
- * structure, which is supported through drm_dev_init().
  */
 
 /**
@@ -476,6 +471,9 @@ static void drm_fs_inode_free(struct inode *inode)
  * The initial ref-count of the object is 1. Use drm_dev_get() and
  * drm_dev_put() to take and drop further ref-counts.
  *
+ * It is recommended that drivers embed &struct drm_device into their own device
+ * structure.
+ *
  * Drivers that do not want to allocate their own device struct
  * embedding &struct drm_device can call drm_dev_alloc() instead. For drivers
  * that do embed &struct drm_device it must be placed first in the overall
@@ -766,7 +764,7 @@ static void remove_compat_control_link(struct drm_device *dev)
  * @flags: Flags passed to the driver's .load() function
  *
  * Register the DRM device @dev with the system, advertise device to user-space
- * and start normal device operation. @dev must be allocated via drm_dev_alloc()
+ * and start normal device operation. @dev must be initialized via drm_dev_init()
  * previously.
  *
  * Never call this twice on any device!
@@ -878,9 +876,9 @@ EXPORT_SYMBOL(drm_dev_unregister);
  * @dev: device of which to set the unique name
  * @name: unique name
  *
- * Sets the unique name of a DRM device using the specified string. Drivers
- * can use this at driver probe time if the unique name of the devices they
- * drive is static.
+ * Sets the unique name of a DRM device using the specified string. This is
+ * already done by drm_dev_init(), drivers should only override the default
+ * unique name for backwards compatibility reasons.
  *
  * Return: 0 on success or a negative error code on failure.
  */
index b506e3622b08f64d5e1bb6d9ece2c716580883a8..990b1909f9d721f276e2a257afe8efe9de8376e0 100644 (file)
@@ -3641,6 +3641,20 @@ static bool cea_db_is_hdmi_forum_vsdb(const u8 *db)
        return oui == HDMI_FORUM_IEEE_OUI;
 }
 
+static bool cea_db_is_vcdb(const u8 *db)
+{
+       if (cea_db_tag(db) != USE_EXTENDED_TAG)
+               return false;
+
+       if (cea_db_payload_len(db) != 2)
+               return false;
+
+       if (cea_db_extended_tag(db) != EXT_VIDEO_CAPABILITY_BLOCK)
+               return false;
+
+       return true;
+}
+
 static bool cea_db_is_y420cmdb(const u8 *db)
 {
        if (cea_db_tag(db) != USE_EXTENDED_TAG)
@@ -4223,41 +4237,6 @@ end:
 }
 EXPORT_SYMBOL(drm_detect_monitor_audio);
 
-/**
- * drm_rgb_quant_range_selectable - is RGB quantization range selectable?
- * @edid: EDID block to scan
- *
- * Check whether the monitor reports the RGB quantization range selection
- * as supported. The AVI infoframe can then be used to inform the monitor
- * which quantization range (full or limited) is used.
- *
- * Return: True if the RGB quantization range is selectable, false otherwise.
- */
-bool drm_rgb_quant_range_selectable(struct edid *edid)
-{
-       u8 *edid_ext;
-       int i, start, end;
-
-       edid_ext = drm_find_cea_extension(edid);
-       if (!edid_ext)
-               return false;
-
-       if (cea_db_offsets(edid_ext, &start, &end))
-               return false;
-
-       for_each_cea_db(edid_ext, i, start, end) {
-               if (cea_db_tag(&edid_ext[i]) == USE_EXTENDED_TAG &&
-                   cea_db_payload_len(&edid_ext[i]) == 2 &&
-                   cea_db_extended_tag(&edid_ext[i]) ==
-                       EXT_VIDEO_CAPABILITY_BLOCK) {
-                       DRM_DEBUG_KMS("CEA VCDB 0x%02x\n", edid_ext[i + 2]);
-                       return edid_ext[i + 2] & EDID_CEA_VCDB_QS;
-               }
-       }
-
-       return false;
-}
-EXPORT_SYMBOL(drm_rgb_quant_range_selectable);
 
 /**
  * drm_default_rgb_quant_range - default RGB quantization range
@@ -4278,6 +4257,16 @@ drm_default_rgb_quant_range(const struct drm_display_mode *mode)
 }
 EXPORT_SYMBOL(drm_default_rgb_quant_range);
 
+static void drm_parse_vcdb(struct drm_connector *connector, const u8 *db)
+{
+       struct drm_display_info *info = &connector->display_info;
+
+       DRM_DEBUG_KMS("CEA VCDB 0x%02x\n", db[2]);
+
+       if (db[2] & EDID_CEA_VCDB_QS)
+               info->rgb_quant_range_selectable = true;
+}
+
 static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector,
                                               const u8 *db)
 {
@@ -4452,6 +4441,8 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
                        drm_parse_hdmi_forum_vsdb(connector, db);
                if (cea_db_is_y420cmdb(db))
                        drm_parse_y420cmdb_bitmap(connector, db);
+               if (cea_db_is_vcdb(db))
+                       drm_parse_vcdb(connector, db);
        }
 }
 
@@ -4472,6 +4463,7 @@ drm_reset_display_info(struct drm_connector *connector)
        info->max_tmds_clock = 0;
        info->dvi_dual = false;
        info->has_hdmi_infoframe = false;
+       info->rgb_quant_range_selectable = false;
        memset(&info->hdmi, 0, sizeof(info->hdmi));
 
        info->non_desktop = 0;
@@ -4830,19 +4822,32 @@ void drm_set_preferred_mode(struct drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_set_preferred_mode);
 
+static bool is_hdmi2_sink(struct drm_connector *connector)
+{
+       /*
+        * FIXME: sil-sii8620 doesn't have a connector around when
+        * we need one, so we have to be prepared for a NULL connector.
+        */
+       if (!connector)
+               return true;
+
+       return connector->display_info.hdmi.scdc.supported ||
+               connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB420;
+}
+
 /**
  * drm_hdmi_avi_infoframe_from_display_mode() - fill an HDMI AVI infoframe with
  *                                              data from a DRM display mode
  * @frame: HDMI AVI infoframe
+ * @connector: the connector
  * @mode: DRM display mode
- * @is_hdmi2_sink: Sink is HDMI 2.0 compliant
  *
  * Return: 0 on success or a negative error code on failure.
  */
 int
 drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
-                                        const struct drm_display_mode *mode,
-                                        bool is_hdmi2_sink)
+                                        struct drm_connector *connector,
+                                        const struct drm_display_mode *mode)
 {
        enum hdmi_picture_aspect picture_aspect;
        int err;
@@ -4864,7 +4869,7 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
         * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
         * have to make sure we dont break HDMI 1.4 sinks.
         */
-       if (!is_hdmi2_sink && frame->video_code > 64)
+       if (!is_hdmi2_sink(connector) && frame->video_code > 64)
                frame->video_code = 0;
 
        /*
@@ -4923,22 +4928,18 @@ EXPORT_SYMBOL(drm_hdmi_avi_infoframe_from_display_mode);
  * drm_hdmi_avi_infoframe_quant_range() - fill the HDMI AVI infoframe
  *                                        quantization range information
  * @frame: HDMI AVI infoframe
+ * @connector: the connector
  * @mode: DRM display mode
  * @rgb_quant_range: RGB quantization range (Q)
- * @rgb_quant_range_selectable: Sink support selectable RGB quantization range (QS)
- * @is_hdmi2_sink: HDMI 2.0 sink, which has different default recommendations
- *
- * Note that @is_hdmi2_sink can be derived by looking at the
- * &drm_scdc.supported flag stored in &drm_hdmi_info.scdc,
- * &drm_display_info.hdmi, which can be found in &drm_connector.display_info.
  */
 void
 drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame,
+                                  struct drm_connector *connector,
                                   const struct drm_display_mode *mode,
-                                  enum hdmi_quantization_range rgb_quant_range,
-                                  bool rgb_quant_range_selectable,
-                                  bool is_hdmi2_sink)
+                                  enum hdmi_quantization_range rgb_quant_range)
 {
+       const struct drm_display_info *info = &connector->display_info;
+
        /*
         * CEA-861:
         * "A Source shall not send a non-zero Q value that does not correspond
@@ -4949,7 +4950,7 @@ drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame,
         * HDMI 2.0 recommends sending non-zero Q when it does match the
         * default RGB quantization range for the mode, even when QS=0.
         */
-       if (rgb_quant_range_selectable ||
+       if (info->rgb_quant_range_selectable ||
            rgb_quant_range == drm_default_rgb_quant_range(mode))
                frame->quantization_range = rgb_quant_range;
        else
@@ -4968,7 +4969,7 @@ drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame,
         * we limit non-zero YQ to HDMI 2.0 sinks only as HDMI 2.0 is based
         * on on CEA-861-F.
         */
-       if (!is_hdmi2_sink ||
+       if (!is_hdmi2_sink(connector) ||
            rgb_quant_range == HDMI_QUANTIZATION_RANGE_LIMITED)
                frame->ycc_quantization_range =
                        HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
index 5b516615881a0029c54a8fad9db2696f02406b80..5f8074ffe7d9d5fe7ec47c3a3dbc4847ddd0c44e 100644 (file)
  * GNU General Public License for more details.
  */
 
-#include <drm/drmP.h>
-#include <drm/drm_client.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_fb_cma_helper.h>
-#include <drm/drm_print.h>
+#include <drm/drm_plane.h>
 #include <linux/module.h>
 
-struct drm_fbdev_cma {
-       struct drm_fb_helper    fb_helper;
-};
-
 /**
  * DOC: framebuffer cma helper functions
  *
@@ -39,16 +32,8 @@ struct drm_fbdev_cma {
  *
  * drm_gem_fb_create() is used in the &drm_mode_config_funcs.fb_create
  * callback function to create a cma backed framebuffer.
- *
- * An fbdev framebuffer backed by cma is also available by calling
- * drm_fb_cma_fbdev_init(). drm_fb_cma_fbdev_fini() tears it down.
  */
 
-static inline struct drm_fbdev_cma *to_fbdev_cma(struct drm_fb_helper *helper)
-{
-       return container_of(helper, struct drm_fbdev_cma, fb_helper);
-}
-
 /**
  * drm_fb_cma_get_gem_obj() - Get CMA GEM object for framebuffer
  * @fb: The framebuffer
@@ -119,121 +104,3 @@ dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
        return paddr;
 }
 EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr);
-
-/**
- * drm_fb_cma_fbdev_init() - Allocate and initialize fbdev emulation
- * @dev: DRM device
- * @preferred_bpp: Preferred bits per pixel for the device.
- *                 @dev->mode_config.preferred_depth is used if this is zero.
- * @max_conn_count: Maximum number of connectors.
- *                  @dev->mode_config.num_connector is used if this is zero.
- *
- * Returns:
- * Zero on success or negative error code on failure.
- */
-int drm_fb_cma_fbdev_init(struct drm_device *dev, unsigned int preferred_bpp,
-                         unsigned int max_conn_count)
-{
-       struct drm_fbdev_cma *fbdev_cma;
-
-       /* dev->fb_helper will indirectly point to fbdev_cma after this call */
-       fbdev_cma = drm_fbdev_cma_init(dev, preferred_bpp, max_conn_count);
-       return PTR_ERR_OR_ZERO(fbdev_cma);
-}
-EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_init);
-
-/**
- * drm_fb_cma_fbdev_fini() - Teardown fbdev emulation
- * @dev: DRM device
- */
-void drm_fb_cma_fbdev_fini(struct drm_device *dev)
-{
-       if (dev->fb_helper)
-               drm_fbdev_cma_fini(to_fbdev_cma(dev->fb_helper));
-}
-EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_fini);
-
-static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
-       .fb_probe = drm_fb_helper_generic_probe,
-};
-
-/**
- * drm_fbdev_cma_init() - Allocate and initializes a drm_fbdev_cma struct
- * @dev: DRM device
- * @preferred_bpp: Preferred bits per pixel for the device
- * @max_conn_count: Maximum number of connectors
- *
- * Returns a newly allocated drm_fbdev_cma struct or a ERR_PTR.
- */
-struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
-       unsigned int preferred_bpp, unsigned int max_conn_count)
-{
-       struct drm_fbdev_cma *fbdev_cma;
-       struct drm_fb_helper *fb_helper;
-       int ret;
-
-       fbdev_cma = kzalloc(sizeof(*fbdev_cma), GFP_KERNEL);
-       if (!fbdev_cma)
-               return ERR_PTR(-ENOMEM);
-
-       fb_helper = &fbdev_cma->fb_helper;
-
-       ret = drm_client_init(dev, &fb_helper->client, "fbdev", NULL);
-       if (ret)
-               goto err_free;
-
-       ret = drm_fb_helper_fbdev_setup(dev, fb_helper, &drm_fb_cma_helper_funcs,
-                                       preferred_bpp, max_conn_count);
-       if (ret)
-               goto err_client_put;
-
-       drm_client_add(&fb_helper->client);
-
-       return fbdev_cma;
-
-err_client_put:
-       drm_client_release(&fb_helper->client);
-err_free:
-       kfree(fbdev_cma);
-
-       return ERR_PTR(ret);
-}
-EXPORT_SYMBOL_GPL(drm_fbdev_cma_init);
-
-/**
- * drm_fbdev_cma_fini() - Free drm_fbdev_cma struct
- * @fbdev_cma: The drm_fbdev_cma struct
- */
-void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma)
-{
-       drm_fb_helper_unregister_fbi(&fbdev_cma->fb_helper);
-       /* All resources have now been freed by drm_fbdev_fb_destroy() */
-}
-EXPORT_SYMBOL_GPL(drm_fbdev_cma_fini);
-
-/**
- * drm_fbdev_cma_restore_mode() - Restores initial framebuffer mode
- * @fbdev_cma: The drm_fbdev_cma struct, may be NULL
- *
- * This function is usually called from the &drm_driver.lastclose callback.
- */
-void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma)
-{
-       if (fbdev_cma)
-               drm_fb_helper_restore_fbdev_mode_unlocked(&fbdev_cma->fb_helper);
-}
-EXPORT_SYMBOL_GPL(drm_fbdev_cma_restore_mode);
-
-/**
- * drm_fbdev_cma_hotplug_event() - Poll for hotpulug events
- * @fbdev_cma: The drm_fbdev_cma struct, may be NULL
- *
- * This function is usually called from the &drm_mode_config.output_poll_changed
- * callback.
- */
-void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma)
-{
-       if (fbdev_cma)
-               drm_fb_helper_hotplug_event(&fbdev_cma->fb_helper);
-}
-EXPORT_SYMBOL_GPL(drm_fbdev_cma_hotplug_event);
index d3af098b0922320f2c8be1db7d779ae91538618d..31fcf94bf8253fce1d1f0ba621fd74526f9c5c4d 100644 (file)
@@ -1797,6 +1797,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
        int i;
        struct drm_fb_helper_surface_size sizes;
        int gamma_size = 0;
+       int best_depth = 0;
 
        memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
        sizes.surface_depth = 24;
@@ -1804,7 +1805,10 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
        sizes.fb_width = (u32)-1;
        sizes.fb_height = (u32)-1;
 
-       /* if driver picks 8 or 16 by default use that for both depth/bpp */
+       /*
+        * If driver picks 8 or 16 by default use that for both depth/bpp
+        * to begin with
+        */
        if (preferred_bpp != sizes.surface_bpp)
                sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
 
@@ -1839,6 +1843,55 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
                }
        }
 
+       /*
+        * If we run into a situation where, for example, the primary plane
+        * supports RGBA5551 (16 bpp, depth 15) but not RGB565 (16 bpp, depth
+        * 16) we need to scale down the depth of the sizes we request.
+        */
+       for (i = 0; i < fb_helper->crtc_count; i++) {
+               struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
+               struct drm_crtc *crtc = mode_set->crtc;
+               struct drm_plane *plane = crtc->primary;
+               int j;
+
+               DRM_DEBUG("test CRTC %d primary plane\n", i);
+
+               for (j = 0; j < plane->format_count; j++) {
+                       const struct drm_format_info *fmt;
+
+                       fmt = drm_format_info(plane->format_types[j]);
+
+                       /*
+                        * Do not consider YUV or other complicated formats
+                        * for framebuffers. This means only legacy formats
+                        * are supported (fmt->depth is a legacy field) but
+                        * the framebuffer emulation can only deal with such
+                        * formats, specifically RGB/BGA formats.
+                        */
+                       if (fmt->depth == 0)
+                               continue;
+
+                       /* We found a perfect fit, great */
+                       if (fmt->depth == sizes.surface_depth) {
+                               best_depth = fmt->depth;
+                               break;
+                       }
+
+                       /* Skip depths above what we're looking for */
+                       if (fmt->depth > sizes.surface_depth)
+                               continue;
+
+                       /* Best depth found so far */
+                       if (fmt->depth > best_depth)
+                               best_depth = fmt->depth;
+               }
+       }
+       if (sizes.surface_depth != best_depth) {
+               DRM_INFO("requested bpp %d, scaled depth down to %d",
+                        sizes.surface_bpp, best_depth);
+               sizes.surface_depth = best_depth;
+       }
+
        crtc_count = 0;
        for (i = 0; i < fb_helper->crtc_count; i++) {
                struct drm_display_mode *desired_mode;
@@ -2866,7 +2919,7 @@ int drm_fb_helper_fbdev_setup(struct drm_device *dev,
        return 0;
 
 err_drm_fb_helper_fini:
-       drm_fb_helper_fini(fb_helper);
+       drm_fb_helper_fbdev_teardown(dev);
 
        return ret;
 }
@@ -2961,18 +3014,16 @@ static int drm_fbdev_fb_release(struct fb_info *info, int user)
        return 0;
 }
 
-/*
- * fb_ops.fb_destroy is called by the last put_fb_info() call at the end of
- * unregister_framebuffer() or fb_release().
- */
-static void drm_fbdev_fb_destroy(struct fb_info *info)
+static void drm_fbdev_cleanup(struct drm_fb_helper *fb_helper)
 {
-       struct drm_fb_helper *fb_helper = info->par;
        struct fb_info *fbi = fb_helper->fbdev;
        struct fb_ops *fbops = NULL;
        void *shadow = NULL;
 
-       if (fbi->fbdefio) {
+       if (!fb_helper->dev)
+               return;
+
+       if (fbi && fbi->fbdefio) {
                fb_deferred_io_cleanup(fbi);
                shadow = fbi->screen_buffer;
                fbops = fbi->fbops;
@@ -2986,15 +3037,22 @@ static void drm_fbdev_fb_destroy(struct fb_info *info)
        }
 
        drm_client_framebuffer_delete(fb_helper->buffer);
-       /*
-        * FIXME:
-        * Remove conditional when all CMA drivers have been moved over to using
-        * drm_fbdev_generic_setup().
-        */
-       if (fb_helper->client.funcs) {
-               drm_client_release(&fb_helper->client);
-               kfree(fb_helper);
-       }
+}
+
+static void drm_fbdev_release(struct drm_fb_helper *fb_helper)
+{
+       drm_fbdev_cleanup(fb_helper);
+       drm_client_release(&fb_helper->client);
+       kfree(fb_helper);
+}
+
+/*
+ * fb_ops.fb_destroy is called by the last put_fb_info() call at the end of
+ * unregister_framebuffer() or fb_release().
+ */
+static void drm_fbdev_fb_destroy(struct fb_info *info)
+{
+       drm_fbdev_release(info->par);
 }
 
 static int drm_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
@@ -3047,7 +3105,6 @@ int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
        struct drm_framebuffer *fb;
        struct fb_info *fbi;
        u32 format;
-       int ret;
 
        DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
                      sizes->surface_width, sizes->surface_height,
@@ -3064,10 +3121,8 @@ int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
        fb = buffer->fb;
 
        fbi = drm_fb_helper_alloc_fbi(fb_helper);
-       if (IS_ERR(fbi)) {
-               ret = PTR_ERR(fbi);
-               goto err_free_buffer;
-       }
+       if (IS_ERR(fbi))
+               return PTR_ERR(fbi);
 
        fbi->par = fb_helper;
        fbi->fbops = &drm_fbdev_fb_ops;
@@ -3098,8 +3153,7 @@ int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
                if (!fbops || !shadow) {
                        kfree(fbops);
                        vfree(shadow);
-                       ret = -ENOMEM;
-                       goto err_fb_info_destroy;
+                       return -ENOMEM;
                }
 
                *fbops = *fbi->fbops;
@@ -3111,13 +3165,6 @@ int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
        }
 
        return 0;
-
-err_fb_info_destroy:
-       drm_fb_helper_fini(fb_helper);
-err_free_buffer:
-       drm_client_framebuffer_delete(buffer);
-
-       return ret;
 }
 EXPORT_SYMBOL(drm_fb_helper_generic_probe);
 
@@ -3129,18 +3176,11 @@ static void drm_fbdev_client_unregister(struct drm_client_dev *client)
 {
        struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
 
-       if (fb_helper->fbdev) {
-               drm_fb_helper_unregister_fbi(fb_helper);
+       if (fb_helper->fbdev)
                /* drm_fbdev_fb_destroy() takes care of cleanup */
-               return;
-       }
-
-       /* Did drm_fb_helper_fbdev_setup() run? */
-       if (fb_helper->dev)
-               drm_fb_helper_fini(fb_helper);
-
-       drm_client_release(client);
-       kfree(fb_helper);
+               drm_fb_helper_unregister_fbi(fb_helper);
+       else
+               drm_fbdev_release(fb_helper);
 }
 
 static int drm_fbdev_client_restore(struct drm_client_dev *client)
@@ -3158,7 +3198,7 @@ static int drm_fbdev_client_hotplug(struct drm_client_dev *client)
        struct drm_device *dev = client->dev;
        int ret;
 
-       /* If drm_fb_helper_fbdev_setup() failed, we only try once */
+       /* Setup is not retried if it has failed */
        if (!fb_helper->dev && fb_helper->funcs)
                return 0;
 
@@ -3170,15 +3210,34 @@ static int drm_fbdev_client_hotplug(struct drm_client_dev *client)
                return 0;
        }
 
-       ret = drm_fb_helper_fbdev_setup(dev, fb_helper, &drm_fb_helper_generic_funcs,
-                                       fb_helper->preferred_bpp, 0);
-       if (ret) {
-               fb_helper->dev = NULL;
-               fb_helper->fbdev = NULL;
-               return ret;
-       }
+       drm_fb_helper_prepare(dev, fb_helper, &drm_fb_helper_generic_funcs);
+
+       ret = drm_fb_helper_init(dev, fb_helper, dev->mode_config.num_connector);
+       if (ret)
+               goto err;
+
+       ret = drm_fb_helper_single_add_all_connectors(fb_helper);
+       if (ret)
+               goto err_cleanup;
+
+       if (!drm_drv_uses_atomic_modeset(dev))
+               drm_helper_disable_unused_functions(dev);
+
+       ret = drm_fb_helper_initial_config(fb_helper, fb_helper->preferred_bpp);
+       if (ret)
+               goto err_cleanup;
 
        return 0;
+
+err_cleanup:
+       drm_fbdev_cleanup(fb_helper);
+err:
+       fb_helper->dev = NULL;
+       fb_helper->fbdev = NULL;
+
+       DRM_DEV_ERROR(dev->dev, "fbdev: Failed to setup generic emulation (ret=%d)\n", ret);
+
+       return ret;
 }
 
 static const struct drm_client_funcs drm_fbdev_client_funcs = {
@@ -3237,6 +3296,10 @@ int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
 
        drm_client_add(&fb_helper->client);
 
+       if (!preferred_bpp)
+               preferred_bpp = dev->mode_config.preferred_depth;
+       if (!preferred_bpp)
+               preferred_bpp = 32;
        fb_helper->preferred_bpp = preferred_bpp;
 
        ret = drm_fbdev_client_hotplug(&fb_helper->client);
index 12dea16f22a843bd5012ef46b5690e983ed94b12..3da3bf5af40543bca1ff06da352ad038e7257d8e 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include <drm/drmP.h>
+#include <drm/drm_util.h>
 #include <drm/drm_flip_work.h>
 
 /**
index fcaea8f50513d845b8d736d7d3df0092dc33d67b..7abcb265a108dd3d2eb3133aa7ef275714adc15e 100644 (file)
@@ -27,6 +27,7 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_uapi.h>
 #include <drm/drm_print.h>
+#include <drm/drm_util.h>
 
 #include "drm_internal.h"
 #include "drm_crtc_internal.h"
index 8b55ece97967f43d0861d6d5f6dfc043f00b9a39..2896ff60552f5d873933ddedbb576df5a9e10b2c 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/shmem_fs.h>
 #include <linux/dma-buf.h>
 #include <linux/mem_encrypt.h>
+#include <linux/pagevec.h>
 #include <drm/drmP.h>
 #include <drm/drm_vma_manager.h>
 #include <drm/drm_gem.h>
@@ -526,6 +527,17 @@ int drm_gem_create_mmap_offset(struct drm_gem_object *obj)
 }
 EXPORT_SYMBOL(drm_gem_create_mmap_offset);
 
+/*
+ * Move pages to appropriate lru and release the pagevec, decrementing the
+ * ref count of those pages.
+ */
+static void drm_gem_check_release_pagevec(struct pagevec *pvec)
+{
+       check_move_unevictable_pages(pvec);
+       __pagevec_release(pvec);
+       cond_resched();
+}
+
 /**
  * drm_gem_get_pages - helper to allocate backing pages for a GEM object
  * from shmem
@@ -551,6 +563,7 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj)
 {
        struct address_space *mapping;
        struct page *p, **pages;
+       struct pagevec pvec;
        int i, npages;
 
        /* This is the shared memory object that backs the GEM resource */
@@ -568,6 +581,8 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj)
        if (pages == NULL)
                return ERR_PTR(-ENOMEM);
 
+       mapping_set_unevictable(mapping);
+
        for (i = 0; i < npages; i++) {
                p = shmem_read_mapping_page(mapping, i);
                if (IS_ERR(p))
@@ -586,8 +601,14 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj)
        return pages;
 
 fail:
-       while (i--)
-               put_page(pages[i]);
+       mapping_clear_unevictable(mapping);
+       pagevec_init(&pvec);
+       while (i--) {
+               if (!pagevec_add(&pvec, pages[i]))
+                       drm_gem_check_release_pagevec(&pvec);
+       }
+       if (pagevec_count(&pvec))
+               drm_gem_check_release_pagevec(&pvec);
 
        kvfree(pages);
        return ERR_CAST(p);
@@ -605,6 +626,11 @@ void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
                bool dirty, bool accessed)
 {
        int i, npages;
+       struct address_space *mapping;
+       struct pagevec pvec;
+
+       mapping = file_inode(obj->filp)->i_mapping;
+       mapping_clear_unevictable(mapping);
 
        /* We already BUG_ON() for non-page-aligned sizes in
         * drm_gem_object_init(), so we should never hit this unless
@@ -614,6 +640,7 @@ void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
 
        npages = obj->size >> PAGE_SHIFT;
 
+       pagevec_init(&pvec);
        for (i = 0; i < npages; i++) {
                if (dirty)
                        set_page_dirty(pages[i]);
@@ -622,8 +649,11 @@ void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
                        mark_page_accessed(pages[i]);
 
                /* Undo the reference we took when populating the table */
-               put_page(pages[i]);
+               if (!pagevec_add(&pvec, pages[i]))
+                       drm_gem_check_release_pagevec(&pvec);
        }
+       if (pagevec_count(&pvec))
+               drm_gem_check_release_pagevec(&pvec);
 
        kvfree(pages);
 }
index acb466d25afc28b545240149710d425ba094e9af..65edb1ccb185f01840e2395436ab51159ee67dce 100644 (file)
@@ -17,6 +17,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_uapi.h>
+#include <drm/drm_damage_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
@@ -136,10 +137,9 @@ EXPORT_SYMBOL(drm_gem_fb_create_handle);
  * @mode_cmd: Metadata from the userspace framebuffer creation request
  * @funcs: vtable to be used for the new framebuffer object
  *
- * This can be used to set &drm_framebuffer_funcs for drivers that need the
- * &drm_framebuffer_funcs.dirty callback. Use drm_gem_fb_create() if you don't
- * need to change &drm_framebuffer_funcs.
- * The function does buffer size validation.
+ * This function can be used to set &drm_framebuffer_funcs for drivers that need
+ * custom framebuffer callbacks. Use drm_gem_fb_create() if you don't need to
+ * change &drm_framebuffer_funcs. The function does buffer size validation.
  *
  * Returns:
  * Pointer to a &drm_framebuffer on success or an error pointer on failure.
@@ -215,8 +215,8 @@ static const struct drm_framebuffer_funcs drm_gem_fb_funcs = {
  *
  * If your hardware has special alignment or pitch requirements these should be
  * checked before calling this function. The function does buffer size
- * validation. Use drm_gem_fb_create_with_funcs() if you need to set
- * &drm_framebuffer_funcs.dirty.
+ * validation. Use drm_gem_fb_create_with_dirty() if you need framebuffer
+ * flushing.
  *
  * Drivers can use this as their &drm_mode_config_funcs.fb_create callback.
  * The ADDFB2 IOCTL calls into this callback.
@@ -233,6 +233,44 @@ drm_gem_fb_create(struct drm_device *dev, struct drm_file *file,
 }
 EXPORT_SYMBOL_GPL(drm_gem_fb_create);
 
+static const struct drm_framebuffer_funcs drm_gem_fb_funcs_dirtyfb = {
+       .destroy        = drm_gem_fb_destroy,
+       .create_handle  = drm_gem_fb_create_handle,
+       .dirty          = drm_atomic_helper_dirtyfb,
+};
+
+/**
+ * drm_gem_fb_create_with_dirty() - Helper function for the
+ *                       &drm_mode_config_funcs.fb_create callback
+ * @dev: DRM device
+ * @file: DRM file that holds the GEM handle(s) backing the framebuffer
+ * @mode_cmd: Metadata from the userspace framebuffer creation request
+ *
+ * This function creates a new framebuffer object described by
+ * &drm_mode_fb_cmd2. This description includes handles for the buffer(s)
+ * backing the framebuffer. drm_atomic_helper_dirtyfb() is used for the dirty
+ * callback giving framebuffer flushing through the atomic machinery. Use
+ * drm_gem_fb_create() if you don't need the dirty callback.
+ * The function does buffer size validation.
+ *
+ * Drivers should also call drm_plane_enable_fb_damage_clips() on all planes
+ * to enable userspace to use damage clips also with the ATOMIC IOCTL.
+ *
+ * Drivers can use this as their &drm_mode_config_funcs.fb_create callback.
+ * The ADDFB2 IOCTL calls into this callback.
+ *
+ * Returns:
+ * Pointer to a &drm_framebuffer on success or an error pointer on failure.
+ */
+struct drm_framebuffer *
+drm_gem_fb_create_with_dirty(struct drm_device *dev, struct drm_file *file,
+                            const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+       return drm_gem_fb_create_with_funcs(dev, file, mode_cmd,
+                                           &drm_gem_fb_funcs_dirtyfb);
+}
+EXPORT_SYMBOL_GPL(drm_gem_fb_create_with_dirty);
+
 /**
  * drm_gem_fb_prepare_fb() - Prepare a GEM backed framebuffer
  * @plane: Plane
index d9caf205e0b33448f55e3c275f6c864de4881856..251d67e04c2d9adf974e4788dbd4a4fc47107cca 100644 (file)
@@ -26,6 +26,8 @@
 #define DRM_IF_MAJOR 1
 #define DRM_IF_MINOR 4
 
+#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
+
 struct drm_prime_file_private;
 struct dma_buf;
 
index 99cba8ea5d825596d7d86120f2ad6346926c64ba..b735704653cbb7b52761a32427bc5aebd24ae420 100644 (file)
@@ -218,7 +218,7 @@ static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr
 
        idr_for_each_entry(leases, entry, object) {
                error = 0;
-               if (!idr_find(&dev->mode_config.crtc_idr, object))
+               if (!idr_find(&dev->mode_config.object_idr, object))
                        error = -ENOENT;
                else if (!_drm_lease_held_master(lessor, object))
                        error = -EACCES;
@@ -439,7 +439,7 @@ static int fill_object_idr(struct drm_device *dev,
                /*
                 * We're using an IDR to hold the set of leased
                 * objects, but we don't need to point at the object's
-                * data structure from the lease as the main crtc_idr
+                * data structure from the lease as the main object_idr
                 * will be used to actually find that. Instead, all we
                 * really want is a 'leased/not-leased' result, for
                 * which any non-NULL pointer will work fine.
@@ -687,7 +687,7 @@ int drm_mode_get_lease_ioctl(struct drm_device *dev,
 
        if (lessee->lessor == NULL)
                /* owner can use all objects */
-               object_idr = &lessee->dev->mode_config.crtc_idr;
+               object_idr = &lessee->dev->mode_config.object_idr;
        else
                /* lessee can only use allowed object */
                object_idr = &lessee->leases;
index 703bfce975bbc296c9ad470bea2b731e9cb2e385..4a1c2023ccf02bdaeb84d9b23c0d82818f84df3f 100644 (file)
@@ -393,7 +393,8 @@ void drm_mode_config_init(struct drm_device *dev)
        INIT_LIST_HEAD(&dev->mode_config.property_list);
        INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
        INIT_LIST_HEAD(&dev->mode_config.plane_list);
-       idr_init(&dev->mode_config.crtc_idr);
+       INIT_LIST_HEAD(&dev->mode_config.privobj_list);
+       idr_init(&dev->mode_config.object_idr);
        idr_init(&dev->mode_config.tile_idr);
        ida_init(&dev->mode_config.connector_ida);
        spin_lock_init(&dev->mode_config.connector_list_lock);
@@ -496,7 +497,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)
 
        ida_destroy(&dev->mode_config.connector_ida);
        idr_destroy(&dev->mode_config.tile_idr);
-       idr_destroy(&dev->mode_config.crtc_idr);
+       idr_destroy(&dev->mode_config.object_idr);
        drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
 }
 EXPORT_SYMBOL(drm_mode_config_cleanup);
index cd9bc0ce9be07bfc3169ddf5596184f3991e5bc6..a9005c1c23848791fce2a6b6a4c9920581341069 100644 (file)
@@ -38,7 +38,7 @@ int __drm_mode_object_add(struct drm_device *dev, struct drm_mode_object *obj,
        int ret;
 
        mutex_lock(&dev->mode_config.idr_mutex);
-       ret = idr_alloc(&dev->mode_config.crtc_idr, register_obj ? obj : NULL,
+       ret = idr_alloc(&dev->mode_config.object_idr, register_obj ? obj : NULL,
                        1, 0, GFP_KERNEL);
        if (ret >= 0) {
                /*
@@ -79,7 +79,7 @@ void drm_mode_object_register(struct drm_device *dev,
                              struct drm_mode_object *obj)
 {
        mutex_lock(&dev->mode_config.idr_mutex);
-       idr_replace(&dev->mode_config.crtc_idr, obj, obj->id);
+       idr_replace(&dev->mode_config.object_idr, obj, obj->id);
        mutex_unlock(&dev->mode_config.idr_mutex);
 }
 
@@ -99,7 +99,7 @@ void drm_mode_object_unregister(struct drm_device *dev,
 {
        mutex_lock(&dev->mode_config.idr_mutex);
        if (object->id) {
-               idr_remove(&dev->mode_config.crtc_idr, object->id);
+               idr_remove(&dev->mode_config.object_idr, object->id);
                object->id = 0;
        }
        mutex_unlock(&dev->mode_config.idr_mutex);
@@ -131,7 +131,7 @@ struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
        struct drm_mode_object *obj = NULL;
 
        mutex_lock(&dev->mode_config.idr_mutex);
-       obj = idr_find(&dev->mode_config.crtc_idr, id);
+       obj = idr_find(&dev->mode_config.object_idr, id);
        if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type)
                obj = NULL;
        if (obj && obj->id != id)
@@ -459,12 +459,13 @@ static int set_property_atomic(struct drm_mode_object *obj,
        struct drm_modeset_acquire_ctx ctx;
        int ret;
 
-       drm_modeset_acquire_init(&ctx, 0);
-
        state = drm_atomic_state_alloc(dev);
        if (!state)
                return -ENOMEM;
+
+       drm_modeset_acquire_init(&ctx, 0);
        state->acquire_ctx = &ctx;
+
 retry:
        if (prop == state->dev->mode_config.dpms_property) {
                if (obj->type != DRM_MODE_OBJECT_CONNECTOR) {
index 24a7504365596c32c60333ad04e25ba1c26306bf..adce9a26bac944bcbe9bec875bb95778b0ac7cc8 100644 (file)
@@ -71,11 +71,6 @@ struct drm_display_mode *drm_mode_create(struct drm_device *dev)
        if (!nmode)
                return NULL;
 
-       if (drm_mode_object_add(dev, &nmode->base, DRM_MODE_OBJECT_MODE)) {
-               kfree(nmode);
-               return NULL;
-       }
-
        return nmode;
 }
 EXPORT_SYMBOL(drm_mode_create);
@@ -92,8 +87,6 @@ void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
        if (!mode)
                return;
 
-       drm_mode_object_unregister(dev, &mode->base);
-
        kfree(mode);
 }
 EXPORT_SYMBOL(drm_mode_destroy);
@@ -911,11 +904,9 @@ EXPORT_SYMBOL(drm_mode_set_crtcinfo);
  */
 void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src)
 {
-       int id = dst->base.id;
        struct list_head head = dst->head;
 
        *dst = *src;
-       dst->base.id = id;
        dst->head = head;
 }
 EXPORT_SYMBOL(drm_mode_copy);
index 51f534db91070772e59265d16b3115a4883f2afe..81dd11901ffdd3bc6135c1d54a1a53a23e93fae8 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include <drm/drmP.h>
+#include <drm/drm_atomic.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_modeset_lock.h>
 
@@ -394,6 +395,7 @@ EXPORT_SYMBOL(drm_modeset_unlock);
 int drm_modeset_lock_all_ctx(struct drm_device *dev,
                             struct drm_modeset_acquire_ctx *ctx)
 {
+       struct drm_private_obj *privobj;
        struct drm_crtc *crtc;
        struct drm_plane *plane;
        int ret;
@@ -414,6 +416,12 @@ int drm_modeset_lock_all_ctx(struct drm_device *dev,
                        return ret;
        }
 
+       drm_for_each_privobj(privobj, dev) {
+               ret = drm_modeset_lock(&privobj->lock, ctx);
+               if (ret)
+                       return ret;
+       }
+
        return 0;
 }
 EXPORT_SYMBOL(drm_modeset_lock_all_ctx);
index 2763a5ec845b0c14bff58b8aed4d8cb58d80d0a9..f2f71d71494a276411ff4d29e4884bbd8b558a99 100644 (file)
@@ -217,9 +217,11 @@ int drm_of_encoder_active_endpoint(struct device_node *node,
 }
 EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint);
 
-/*
+/**
  * drm_of_find_panel_or_bridge - return connected panel or bridge device
  * @np: device tree node containing encoder output ports
+ * @port: port in the device tree node
+ * @endpoint: endpoint in the device tree node
  * @panel: pointer to hold returned drm_panel
  * @bridge: pointer to hold returned drm_bridge
  *
index c33f95e08e1b8bc8c6e987a95bc4ff011215618f..dbd5b873e8f2f268a6c3b07b70a82d4d7906dc66 100644 (file)
@@ -36,6 +36,9 @@ static LIST_HEAD(panel_list);
  * The DRM panel helpers allow drivers to register panel objects with a
  * central registry and provide functions to retrieve those panels in display
  * drivers.
+ *
+ * For easy integration into drivers using the &drm_bridge infrastructure please
+ * take look at drm_panel_bridge_add() and devm_drm_panel_bridge_add().
  */
 
 /**
index 5f650d8fc66b7a9514db4be47b937871f28d900f..4cfb56893b7f2e50deed2334ec904389a2c33f43 100644 (file)
@@ -220,6 +220,9 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
                        format_modifier_count++;
        }
 
+       if (format_modifier_count)
+               config->allow_fb_modifiers = true;
+
        plane->modifier_count = format_modifier_count;
        plane->modifiers = kmalloc_array(format_modifier_count,
                                         sizeof(format_modifiers[0]),
index db30a0e89db8f30825a8401d91aadc1b78a6c86e..e19525af0ccee11e39277c589beaeb8811d8c0b2 100644 (file)
 #include "drm_internal.h"
 #include <drm/drm_syncobj.h>
 
+struct syncobj_wait_entry {
+       struct list_head node;
+       struct task_struct *task;
+       struct dma_fence *fence;
+       struct dma_fence_cb fence_cb;
+};
+
+static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj,
+                                     struct syncobj_wait_entry *wait);
+
 /**
  * drm_syncobj_find - lookup and reference a sync object.
  * @file_private: drm file private pointer
@@ -82,58 +92,33 @@ struct drm_syncobj *drm_syncobj_find(struct drm_file *file_private,
 }
 EXPORT_SYMBOL(drm_syncobj_find);
 
-static void drm_syncobj_add_callback_locked(struct drm_syncobj *syncobj,
-                                           struct drm_syncobj_cb *cb,
-                                           drm_syncobj_func_t func)
+static void drm_syncobj_fence_add_wait(struct drm_syncobj *syncobj,
+                                      struct syncobj_wait_entry *wait)
 {
-       cb->func = func;
-       list_add_tail(&cb->node, &syncobj->cb_list);
-}
-
-static int drm_syncobj_fence_get_or_add_callback(struct drm_syncobj *syncobj,
-                                                struct dma_fence **fence,
-                                                struct drm_syncobj_cb *cb,
-                                                drm_syncobj_func_t func)
-{
-       int ret;
-
-       *fence = drm_syncobj_fence_get(syncobj);
-       if (*fence)
-               return 1;
+       if (wait->fence)
+               return;
 
        spin_lock(&syncobj->lock);
        /* We've already tried once to get a fence and failed.  Now that we
         * have the lock, try one more time just to be sure we don't add a
         * callback when a fence has already been set.
         */
-       if (syncobj->fence) {
-               *fence = dma_fence_get(rcu_dereference_protected(syncobj->fence,
-                                                                lockdep_is_held(&syncobj->lock)));
-               ret = 1;
-       } else {
-               *fence = NULL;
-               drm_syncobj_add_callback_locked(syncobj, cb, func);
-               ret = 0;
-       }
+       if (syncobj->fence)
+               wait->fence = dma_fence_get(
+                       rcu_dereference_protected(syncobj->fence, 1));
+       else
+               list_add_tail(&wait->node, &syncobj->cb_list);
        spin_unlock(&syncobj->lock);
-
-       return ret;
 }
 
-void drm_syncobj_add_callback(struct drm_syncobj *syncobj,
-                             struct drm_syncobj_cb *cb,
-                             drm_syncobj_func_t func)
+static void drm_syncobj_remove_wait(struct drm_syncobj *syncobj,
+                                   struct syncobj_wait_entry *wait)
 {
-       spin_lock(&syncobj->lock);
-       drm_syncobj_add_callback_locked(syncobj, cb, func);
-       spin_unlock(&syncobj->lock);
-}
+       if (!wait->node.next)
+               return;
 
-void drm_syncobj_remove_callback(struct drm_syncobj *syncobj,
-                                struct drm_syncobj_cb *cb)
-{
        spin_lock(&syncobj->lock);
-       list_del_init(&cb->node);
+       list_del_init(&wait->node);
        spin_unlock(&syncobj->lock);
 }
 
@@ -148,7 +133,7 @@ void drm_syncobj_replace_fence(struct drm_syncobj *syncobj,
                               struct dma_fence *fence)
 {
        struct dma_fence *old_fence;
-       struct drm_syncobj_cb *cur, *tmp;
+       struct syncobj_wait_entry *cur, *tmp;
 
        if (fence)
                dma_fence_get(fence);
@@ -162,7 +147,7 @@ void drm_syncobj_replace_fence(struct drm_syncobj *syncobj,
        if (fence != old_fence) {
                list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) {
                        list_del_init(&cur->node);
-                       cur->func(syncobj, cur);
+                       syncobj_wait_syncobj_func(syncobj, cur);
                }
        }
 
@@ -608,13 +593,6 @@ drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, void *data,
                                        &args->handle);
 }
 
-struct syncobj_wait_entry {
-       struct task_struct *task;
-       struct dma_fence *fence;
-       struct dma_fence_cb fence_cb;
-       struct drm_syncobj_cb syncobj_cb;
-};
-
 static void syncobj_wait_fence_func(struct dma_fence *fence,
                                    struct dma_fence_cb *cb)
 {
@@ -625,11 +603,8 @@ static void syncobj_wait_fence_func(struct dma_fence *fence,
 }
 
 static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj,
-                                     struct drm_syncobj_cb *cb)
+                                     struct syncobj_wait_entry *wait)
 {
-       struct syncobj_wait_entry *wait =
-               container_of(cb, struct syncobj_wait_entry, syncobj_cb);
-
        /* This happens inside the syncobj lock */
        wait->fence = dma_fence_get(rcu_dereference_protected(syncobj->fence,
                                                              lockdep_is_held(&syncobj->lock)));
@@ -688,12 +663,8 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
         */
 
        if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
-               for (i = 0; i < count; ++i) {
-                       drm_syncobj_fence_get_or_add_callback(syncobjs[i],
-                                                             &entries[i].fence,
-                                                             &entries[i].syncobj_cb,
-                                                             syncobj_wait_syncobj_func);
-               }
+               for (i = 0; i < count; ++i)
+                       drm_syncobj_fence_add_wait(syncobjs[i], &entries[i]);
        }
 
        do {
@@ -742,9 +713,7 @@ done_waiting:
 
 cleanup_entries:
        for (i = 0; i < count; ++i) {
-               if (entries[i].syncobj_cb.func)
-                       drm_syncobj_remove_callback(syncobjs[i],
-                                                   &entries[i].syncobj_cb);
+               drm_syncobj_remove_wait(syncobjs[i], &entries[i]);
                if (entries[i].fence_cb.func)
                        dma_fence_remove_callback(entries[i].fence,
                                                  &entries[i].fence_cb);
index 98e0911759217578a0cfaf9e299026a2eca4237b..cde71ee95a8f04ebd1b6ec25703092360b3fa9fc 100644 (file)
@@ -105,13 +105,20 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe,
        write_sequnlock(&vblank->seqlock);
 }
 
+static u32 drm_max_vblank_count(struct drm_device *dev, unsigned int pipe)
+{
+       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+
+       return vblank->max_vblank_count ?: dev->max_vblank_count;
+}
+
 /*
  * "No hw counter" fallback implementation of .get_vblank_counter() hook,
  * if there is no useable hardware frame counter available.
  */
 static u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe)
 {
-       WARN_ON_ONCE(dev->max_vblank_count != 0);
+       WARN_ON_ONCE(drm_max_vblank_count(dev, pipe) != 0);
        return 0;
 }
 
@@ -198,6 +205,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
        ktime_t t_vblank;
        int count = DRM_TIMESTAMP_MAXRETRIES;
        int framedur_ns = vblank->framedur_ns;
+       u32 max_vblank_count = drm_max_vblank_count(dev, pipe);
 
        /*
         * Interrupts were disabled prior to this call, so deal with counter
@@ -216,9 +224,9 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
                rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, in_vblank_irq);
        } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
 
-       if (dev->max_vblank_count != 0) {
+       if (max_vblank_count) {
                /* trust the hw counter when it's around */
-               diff = (cur_vblank - vblank->last) & dev->max_vblank_count;
+               diff = (cur_vblank - vblank->last) & max_vblank_count;
        } else if (rc && framedur_ns) {
                u64 diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time));
 
@@ -1204,6 +1212,37 @@ void drm_crtc_vblank_reset(struct drm_crtc *crtc)
 }
 EXPORT_SYMBOL(drm_crtc_vblank_reset);
 
+/**
+ * drm_crtc_set_max_vblank_count - configure the hw max vblank counter value
+ * @crtc: CRTC in question
+ * @max_vblank_count: max hardware vblank counter value
+ *
+ * Update the maximum hardware vblank counter value for @crtc
+ * at runtime. Useful for hardware where the operation of the
+ * hardware vblank counter depends on the currently active
+ * display configuration.
+ *
+ * For example, if the hardware vblank counter does not work
+ * when a specific connector is active the maximum can be set
+ * to zero. And when that specific connector isn't active the
+ * maximum can again be set to the appropriate non-zero value.
+ *
+ * If used, must be called before drm_vblank_on().
+ */
+void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
+                                  u32 max_vblank_count)
+{
+       struct drm_device *dev = crtc->dev;
+       unsigned int pipe = drm_crtc_index(crtc);
+       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+
+       WARN_ON(dev->max_vblank_count);
+       WARN_ON(!READ_ONCE(vblank->inmodeset));
+
+       vblank->max_vblank_count = max_vblank_count;
+}
+EXPORT_SYMBOL(drm_crtc_set_max_vblank_count);
+
 /**
  * drm_crtc_vblank_on - enable vblank events on a CRTC
  * @crtc: CRTC in question
index 1fa74226db91f6f1ed42cdc57f6d10bffe2604de..5c48915f492dee7b83ca7ea276efc9cca281b859 100644 (file)
@@ -449,7 +449,7 @@ static void etnaviv_gem_describe_fence(struct dma_fence *fence,
        const char *type, struct seq_file *m)
 {
        if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
-               seq_printf(m, "\t%9s: %s %s seq %u\n",
+               seq_printf(m, "\t%9s: %s %s seq %llu\n",
                           type,
                           fence->ops->get_driver_name(fence),
                           fence->ops->get_timeline_name(fence),
index 49a6763693f1ab372d4eeea89f72cd04bbf63442..67ae266020244dcd4cad74582920526c94a91aae 100644 (file)
@@ -109,16 +109,19 @@ static void etnaviv_sched_timedout_job(struct drm_sched_job *sched_job)
        }
 
        /* block scheduler */
-       kthread_park(gpu->sched.thread);
-       drm_sched_hw_job_reset(&gpu->sched, sched_job);
+       drm_sched_stop(&gpu->sched);
+
+       if(sched_job)
+               drm_sched_increase_karma(sched_job);
 
        /* get the GPU back into the init state */
        etnaviv_core_dump(gpu);
        etnaviv_gpu_recover_hang(gpu);
 
+       drm_sched_resubmit_jobs(&gpu->sched);
+
        /* restart scheduler after GPU is usable again */
-       drm_sched_job_recovery(&gpu->sched);
-       kthread_unpark(gpu->sched.thread);
+       drm_sched_start(&gpu->sched, true);
 }
 
 static void etnaviv_sched_free_job(struct drm_sched_job *sched_job)
index 2fd299a58297edd559b2b5928a63833b3c2622df..dd02e8a323ef524488bf68b7ff01469f44184aa5 100644 (file)
@@ -246,8 +246,8 @@ already_disabled:
 }
 
 static void mic_mode_set(struct drm_bridge *bridge,
-                       struct drm_display_mode *mode,
-                       struct drm_display_mode *adjusted_mode)
+                        const struct drm_display_mode *mode,
+                        const struct drm_display_mode *adjusted_mode)
 {
        struct exynos_mic *mic = bridge->driver_private;
 
index 2092a650df7d56b1262fc2f09036eb88ec62ce38..b857df67aff0a4b95aac290844c6ac1d85df8855 100644 (file)
@@ -819,7 +819,8 @@ static void hdmi_reg_infoframes(struct hdmi_context *hdata)
                return;
        }
 
-       ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi, m, false);
+       ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi,
+                                                      &hdata->connector, m);
        if (!ret)
                ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf));
        if (ret > 0) {
index e6a62d5a00a3af0164a113ffc971304a80f5cbb5..15e32e5d9101b0dbc29e5f2aaed2036156bb91d8 100644 (file)
@@ -22,6 +22,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
@@ -33,32 +34,15 @@ static struct kirin_dc_ops *dc_ops;
 
 static int kirin_drm_kms_cleanup(struct drm_device *dev)
 {
-       struct kirin_drm_private *priv = dev->dev_private;
-
-       if (priv->fbdev) {
-               drm_fbdev_cma_fini(priv->fbdev);
-               priv->fbdev = NULL;
-       }
-
        drm_kms_helper_poll_fini(dev);
        dc_ops->cleanup(to_platform_device(dev->dev));
        drm_mode_config_cleanup(dev);
-       devm_kfree(dev->dev, priv);
-       dev->dev_private = NULL;
 
        return 0;
 }
 
-static void kirin_fbdev_output_poll_changed(struct drm_device *dev)
-{
-       struct kirin_drm_private *priv = dev->dev_private;
-
-       drm_fbdev_cma_hotplug_event(priv->fbdev);
-}
-
 static const struct drm_mode_config_funcs kirin_drm_mode_config_funcs = {
        .fb_create = drm_gem_fb_create,
-       .output_poll_changed = kirin_fbdev_output_poll_changed,
        .atomic_check = drm_atomic_helper_check,
        .atomic_commit = drm_atomic_helper_commit,
 };
@@ -76,14 +60,8 @@ static void kirin_drm_mode_config_init(struct drm_device *dev)
 
 static int kirin_drm_kms_init(struct drm_device *dev)
 {
-       struct kirin_drm_private *priv;
        int ret;
 
-       priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       dev->dev_private = priv;
        dev_set_drvdata(dev->dev, dev);
 
        /* dev->mode_config initialization */
@@ -117,26 +95,14 @@ static int kirin_drm_kms_init(struct drm_device *dev)
        /* init kms poll for handling hpd */
        drm_kms_helper_poll_init(dev);
 
-       priv->fbdev = drm_fbdev_cma_init(dev, 32,
-                                        dev->mode_config.num_connector);
-
-       if (IS_ERR(priv->fbdev)) {
-               DRM_ERROR("failed to initialize fbdev.\n");
-               ret = PTR_ERR(priv->fbdev);
-               goto err_cleanup_poll;
-       }
        return 0;
 
-err_cleanup_poll:
-       drm_kms_helper_poll_fini(dev);
 err_unbind_all:
        component_unbind_all(dev->dev, dev);
 err_dc_cleanup:
        dc_ops->cleanup(to_platform_device(dev->dev));
 err_mode_config_cleanup:
        drm_mode_config_cleanup(dev);
-       devm_kfree(dev->dev, priv);
-       dev->dev_private = NULL;
 
        return ret;
 }
@@ -199,6 +165,8 @@ static int kirin_drm_bind(struct device *dev)
        if (ret)
                goto err_kms_cleanup;
 
+       drm_fbdev_generic_setup(drm_dev, 32);
+
        return 0;
 
 err_kms_cleanup:
index 56cb62df065cfbfc9245bc876c3e0e38b301b7c7..ad027d1cc826697ecd222de74badea79e1211034 100644 (file)
@@ -19,10 +19,6 @@ struct kirin_dc_ops {
        void (*cleanup)(struct platform_device *pdev);
 };
 
-struct kirin_drm_private {
-       struct drm_fbdev_cma *fbdev;
-};
-
 extern const struct kirin_dc_ops ade_dc_ops;
 
 #endif /* __KIRIN_DRM_DRV_H__ */
index 544a8a2d3562c2bd6f173be3e5cee0d80f9c2696..b91e48d2190d216e1f73363443b30ca5ed66bba2 100644 (file)
@@ -359,10 +359,10 @@ static int ch7006_encoder_set_property(struct drm_encoder *encoder,
        if (modes_changed) {
                drm_helper_probe_single_connector_modes(connector, 0, 0);
 
-               /* Disable the crtc to ensure a full modeset is
-                * performed whenever it's turned on again. */
                if (crtc)
-                       drm_crtc_force_disable(crtc);
+                       drm_crtc_helper_set_mode(crtc, &crtc->mode,
+                                                crtc->x, crtc->y,
+                                                crtc->primary->fb);
        }
 
        return 0;
index a7c39f39793ff2c2ce152e3cba3c3036513a7f19..ecdb8070ed357823c5f4383b14c212f27532265c 100644 (file)
@@ -845,11 +845,12 @@ static int tda998x_write_aif(struct tda998x_priv *priv,
 }
 
 static void
-tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode)
+tda998x_write_avi(struct tda998x_priv *priv, const struct drm_display_mode *mode)
 {
        union hdmi_infoframe frame;
 
-       drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
+       drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
+                                                &priv->connector, mode);
        frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
 
        tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, &frame);
@@ -1122,7 +1123,6 @@ static void tda998x_connector_destroy(struct drm_connector *connector)
 }
 
 static const struct drm_connector_funcs tda998x_connector_funcs = {
-       .dpms = drm_helper_connector_dpms,
        .reset = drm_atomic_helper_connector_reset,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .detect = tda998x_connector_detect,
@@ -1339,8 +1339,8 @@ static void tda998x_bridge_disable(struct drm_bridge *bridge)
 }
 
 static void tda998x_bridge_mode_set(struct drm_bridge *bridge,
-                                   struct drm_display_mode *mode,
-                                   struct drm_display_mode *adjusted_mode)
+                                   const struct drm_display_mode *mode,
+                                   const struct drm_display_mode *adjusted_mode)
 {
        struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
        unsigned long tmds_clock;
index 9e36ffb5eb7cdd049140ab9e4eeccc53c1020813..ad4d71161dda0f430f0346249ad33a89c857daa8 100644 (file)
@@ -21,11 +21,11 @@ config DRM_I915_DEBUG
         select DEBUG_FS
         select PREEMPT_COUNT
         select I2C_CHARDEV
+        select STACKDEPOT
         select DRM_DP_AUX_CHARDEV
         select X86_MSR # used by igt/pm_rpm
         select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks)
         select DRM_DEBUG_MM if DRM=y
-        select STACKDEPOT if DRM=y # for DRM_DEBUG_MM
        select DRM_DEBUG_SELFTEST
        select SW_SYNC # signaling validation framework (igt/syncobj*)
        select DRM_I915_SW_FENCE_DEBUG_OBJECTS
@@ -173,6 +173,7 @@ config DRM_I915_DEBUG_RUNTIME_PM
        bool "Enable extra state checking for runtime PM"
        depends on DRM_I915
        default n
+       select STACKDEPOT
        help
          Choose this option to turn on extra state checking for the
          runtime PM functionality. This may introduce overhead during
index 19b5fe5016bf6617394da4d0e795d62e8d49a857..8300efe60fe12e9a861582ce9f57854f02b0fd2a 100644 (file)
@@ -40,9 +40,10 @@ i915-y := i915_drv.o \
          i915_mm.o \
          i915_params.o \
          i915_pci.o \
-          i915_suspend.o \
-         i915_syncmap.o \
+         i915_reset.o \
+         i915_suspend.o \
          i915_sw_fence.o \
+         i915_syncmap.o \
          i915_sysfs.o \
          intel_csr.o \
          intel_device_info.o \
@@ -166,6 +167,7 @@ i915-$(CONFIG_DRM_I915_SELFTEST) += \
        selftests/i915_random.o \
        selftests/i915_selftest.o \
        selftests/igt_flush_test.o \
+       selftests/igt_live_test.o \
        selftests/igt_reset.o \
        selftests/igt_spinner.o
 
@@ -198,3 +200,4 @@ endif
 i915-y += intel_lpe_audio.o
 
 obj-$(CONFIG_DRM_I915) += i915.o
+obj-$(CONFIG_DRM_I915_GVT_KVMGT) += gvt/kvmgt.o
index 5e6a3013da49645ebf6ea0b1487fc383fc43d3b1..16e0345b711fb3cc782125aa418e804d2e09ab50 100644 (file)
@@ -24,7 +24,6 @@
 #define _INTEL_DVO_H
 
 #include <linux/i2c.h>
-#include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include "intel_drv.h"
 
index b016dc753db96774a57770b7af4d93cf66ecf997..271fb46d4dd0df3fbce52eb93097562027e86aed 100644 (file)
@@ -7,4 +7,3 @@ GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \
 
 ccflags-y                              += -I$(src) -I$(src)/$(GVT_DIR)
 i915-y                                 += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
-obj-$(CONFIG_DRM_I915_GVT_KVMGT)       += $(GVT_DIR)/kvmgt.o
index 359d37d5c958c6b258053ba62804762f75d00087..1fa2f65c3cd16f38651f14a40e12f2d58e82af3d 100644 (file)
@@ -180,7 +180,7 @@ static void free_vgpu_fence(struct intel_vgpu *vgpu)
        }
        mutex_unlock(&dev_priv->drm.struct_mutex);
 
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put_unchecked(dev_priv);
 }
 
 static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
@@ -206,7 +206,7 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
        _clear_vgpu_fence(vgpu);
 
        mutex_unlock(&dev_priv->drm.struct_mutex);
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put_unchecked(dev_priv);
        return 0;
 out_free_fence:
        gvt_vgpu_err("Failed to alloc fences\n");
@@ -219,7 +219,7 @@ out_free_fence:
                vgpu->fence.regs[i] = NULL;
        }
        mutex_unlock(&dev_priv->drm.struct_mutex);
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put_unchecked(dev_priv);
        return -ENOSPC;
 }
 
@@ -317,7 +317,7 @@ void intel_vgpu_reset_resource(struct intel_vgpu *vgpu)
 
        intel_runtime_pm_get(dev_priv);
        _clear_vgpu_fence(vgpu);
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put_unchecked(dev_priv);
 }
 
 /**
index 77ae634eb11c9e709751b9391a8f392ad9632385..35b4ec3f7618b887e5661d0d652cca99b6ed02c6 100644 (file)
@@ -55,10 +55,10 @@ struct sub_op_bits {
        int low;
 };
 struct decode_info {
-       char *name;
+       const char *name;
        int op_len;
        int nr_sub_op;
-       struct sub_op_bits *sub_op;
+       const struct sub_op_bits *sub_op;
 };
 
 #define   MAX_CMD_BUDGET                       0x7fffffff
@@ -375,7 +375,7 @@ typedef int (*parser_cmd_handler)(struct parser_exec_state *s);
 #define ADDR_FIX_5(x1, x2, x3, x4, x5)  (ADDR_FIX_1(x1) | ADDR_FIX_4(x2, x3, x4, x5))
 
 struct cmd_info {
-       char *name;
+       const char *name;
        u32 opcode;
 
 #define F_LEN_MASK     (1U<<0)
@@ -399,10 +399,10 @@ struct cmd_info {
 #define R_VECS (1 << VECS)
 #define R_ALL (R_RCS | R_VCS | R_BCS | R_VECS)
        /* rings that support this cmd: BLT/RCS/VCS/VECS */
-       uint16_t rings;
+       u16 rings;
 
        /* devices that support this cmd: SNB/IVB/HSW/... */
-       uint16_t devices;
+       u16 devices;
 
        /* which DWords are address that need fix up.
         * bit 0 means a 32-bit non address operand in command
@@ -412,20 +412,20 @@ struct cmd_info {
         * No matter the address length, each address only takes
         * one bit in the bitmap.
         */
-       uint16_t addr_bitmap;
+       u16 addr_bitmap;
 
        /* flag == F_LEN_CONST : command length
         * flag == F_LEN_VAR : length bias bits
         * Note: length is in DWord
         */
-       uint8_t len;
+       u8 len;
 
        parser_cmd_handler handler;
 };
 
 struct cmd_entry {
        struct hlist_node hlist;
-       struct cmd_info *info;
+       const struct cmd_info *info;
 };
 
 enum {
@@ -474,7 +474,7 @@ struct parser_exec_state {
        int saved_buf_addr_type;
        bool is_ctx_wa;
 
-       struct cmd_info *info;
+       const struct cmd_info *info;
 
        struct intel_vgpu_workload *workload;
 };
@@ -485,12 +485,12 @@ struct parser_exec_state {
 static unsigned long bypass_scan_mask = 0;
 
 /* ring ALL, type = 0 */
-static struct sub_op_bits sub_op_mi[] = {
+static const struct sub_op_bits sub_op_mi[] = {
        {31, 29},
        {28, 23},
 };
 
-static struct decode_info decode_info_mi = {
+static const struct decode_info decode_info_mi = {
        "MI",
        OP_LEN_MI,
        ARRAY_SIZE(sub_op_mi),
@@ -498,12 +498,12 @@ static struct decode_info decode_info_mi = {
 };
 
 /* ring RCS, command type 2 */
-static struct sub_op_bits sub_op_2d[] = {
+static const struct sub_op_bits sub_op_2d[] = {
        {31, 29},
        {28, 22},
 };
 
-static struct decode_info decode_info_2d = {
+static const struct decode_info decode_info_2d = {
        "2D",
        OP_LEN_2D,
        ARRAY_SIZE(sub_op_2d),
@@ -511,14 +511,14 @@ static struct decode_info decode_info_2d = {
 };
 
 /* ring RCS, command type 3 */
-static struct sub_op_bits sub_op_3d_media[] = {
+static const struct sub_op_bits sub_op_3d_media[] = {
        {31, 29},
        {28, 27},
        {26, 24},
        {23, 16},
 };
 
-static struct decode_info decode_info_3d_media = {
+static const struct decode_info decode_info_3d_media = {
        "3D_Media",
        OP_LEN_3D_MEDIA,
        ARRAY_SIZE(sub_op_3d_media),
@@ -526,7 +526,7 @@ static struct decode_info decode_info_3d_media = {
 };
 
 /* ring VCS, command type 3 */
-static struct sub_op_bits sub_op_mfx_vc[] = {
+static const struct sub_op_bits sub_op_mfx_vc[] = {
        {31, 29},
        {28, 27},
        {26, 24},
@@ -534,7 +534,7 @@ static struct sub_op_bits sub_op_mfx_vc[] = {
        {20, 16},
 };
 
-static struct decode_info decode_info_mfx_vc = {
+static const struct decode_info decode_info_mfx_vc = {
        "MFX_VC",
        OP_LEN_MFX_VC,
        ARRAY_SIZE(sub_op_mfx_vc),
@@ -542,7 +542,7 @@ static struct decode_info decode_info_mfx_vc = {
 };
 
 /* ring VECS, command type 3 */
-static struct sub_op_bits sub_op_vebox[] = {
+static const struct sub_op_bits sub_op_vebox[] = {
        {31, 29},
        {28, 27},
        {26, 24},
@@ -550,14 +550,14 @@ static struct sub_op_bits sub_op_vebox[] = {
        {20, 16},
 };
 
-static struct decode_info decode_info_vebox = {
+static const struct decode_info decode_info_vebox = {
        "VEBOX",
        OP_LEN_VEBOX,
        ARRAY_SIZE(sub_op_vebox),
        sub_op_vebox,
 };
 
-static struct decode_info *ring_decode_info[I915_NUM_ENGINES][8] = {
+static const struct decode_info *ring_decode_info[I915_NUM_ENGINES][8] = {
        [RCS] = {
                &decode_info_mi,
                NULL,
@@ -616,7 +616,7 @@ static struct decode_info *ring_decode_info[I915_NUM_ENGINES][8] = {
 
 static inline u32 get_opcode(u32 cmd, int ring_id)
 {
-       struct decode_info *d_info;
+       const struct decode_info *d_info;
 
        d_info = ring_decode_info[ring_id][CMD_TYPE(cmd)];
        if (d_info == NULL)
@@ -625,7 +625,7 @@ static inline u32 get_opcode(u32 cmd, int ring_id)
        return cmd >> (32 - d_info->op_len);
 }
 
-static inline struct cmd_info *find_cmd_entry(struct intel_gvt *gvt,
+static inline const struct cmd_info *find_cmd_entry(struct intel_gvt *gvt,
                unsigned int opcode, int ring_id)
 {
        struct cmd_entry *e;
@@ -638,7 +638,7 @@ static inline struct cmd_info *find_cmd_entry(struct intel_gvt *gvt,
        return NULL;
 }
 
-static inline struct cmd_info *get_cmd_info(struct intel_gvt *gvt,
+static inline const struct cmd_info *get_cmd_info(struct intel_gvt *gvt,
                u32 cmd, int ring_id)
 {
        u32 opcode;
@@ -657,7 +657,7 @@ static inline u32 sub_op_val(u32 cmd, u32 hi, u32 low)
 
 static inline void print_opcode(u32 cmd, int ring_id)
 {
-       struct decode_info *d_info;
+       const struct decode_info *d_info;
        int i;
 
        d_info = ring_decode_info[ring_id][CMD_TYPE(cmd)];
@@ -776,7 +776,7 @@ static inline int ip_gma_advance(struct parser_exec_state *s,
        return 0;
 }
 
-static inline int get_cmd_length(struct cmd_info *info, u32 cmd)
+static inline int get_cmd_length(const struct cmd_info *info, u32 cmd)
 {
        if ((info->flag & F_LEN_MASK) == F_LEN_CONST)
                return info->len;
@@ -901,7 +901,8 @@ static int cmd_reg_handler(struct parser_exec_state *s,
         * It's good enough to support initializing mmio by lri command in
         * vgpu inhibit context on KBL.
         */
-       if (IS_KABYLAKE(s->vgpu->gvt->dev_priv) &&
+       if ((IS_KABYLAKE(s->vgpu->gvt->dev_priv)
+               || IS_COFFEELAKE(s->vgpu->gvt->dev_priv)) &&
                        intel_gvt_mmio_is_in_ctx(gvt, offset) &&
                        !strncmp(cmd, "lri", 3)) {
                intel_gvt_hypervisor_read_gpa(s->vgpu,
@@ -1280,9 +1281,7 @@ static int gen8_check_mi_display_flip(struct parser_exec_state *s,
        if (!info->async_flip)
                return 0;
 
-       if (IS_SKYLAKE(dev_priv)
-               || IS_KABYLAKE(dev_priv)
-               || IS_BROXTON(dev_priv)) {
+       if (INTEL_GEN(dev_priv) >= 9) {
                stride = vgpu_vreg_t(s->vgpu, info->stride_reg) & GENMASK(9, 0);
                tile = (vgpu_vreg_t(s->vgpu, info->ctrl_reg) &
                                GENMASK(12, 10)) >> 10;
@@ -1310,9 +1309,7 @@ static int gen8_update_plane_mmio_from_mi_display_flip(
 
        set_mask_bits(&vgpu_vreg_t(vgpu, info->surf_reg), GENMASK(31, 12),
                      info->surf_val << 12);
-       if (IS_SKYLAKE(dev_priv)
-               || IS_KABYLAKE(dev_priv)
-               || IS_BROXTON(dev_priv)) {
+       if (INTEL_GEN(dev_priv) >= 9) {
                set_mask_bits(&vgpu_vreg_t(vgpu, info->stride_reg), GENMASK(9, 0),
                              info->stride_val);
                set_mask_bits(&vgpu_vreg_t(vgpu, info->ctrl_reg), GENMASK(12, 10),
@@ -1336,9 +1333,7 @@ static int decode_mi_display_flip(struct parser_exec_state *s,
 
        if (IS_BROADWELL(dev_priv))
                return gen8_decode_mi_display_flip(s, info);
-       if (IS_SKYLAKE(dev_priv)
-               || IS_KABYLAKE(dev_priv)
-               || IS_BROXTON(dev_priv))
+       if (INTEL_GEN(dev_priv) >= 9)
                return skl_decode_mi_display_flip(s, info);
 
        return -ENODEV;
@@ -1643,8 +1638,8 @@ static int batch_buffer_needs_scan(struct parser_exec_state *s)
 static int find_bb_size(struct parser_exec_state *s, unsigned long *bb_size)
 {
        unsigned long gma = 0;
-       struct cmd_info *info;
-       uint32_t cmd_len = 0;
+       const struct cmd_info *info;
+       u32 cmd_len = 0;
        bool bb_end = false;
        struct intel_vgpu *vgpu = s->vgpu;
        u32 cmd;
@@ -1842,7 +1837,7 @@ static int cmd_handler_mi_batch_buffer_start(struct parser_exec_state *s)
 
 static int mi_noop_index;
 
-static struct cmd_info cmd_info[] = {
+static const struct cmd_info cmd_info[] = {
        {"MI_NOOP", OP_MI_NOOP, F_LEN_CONST, R_ALL, D_ALL, 0, 1, NULL},
 
        {"MI_SET_PREDICATE", OP_MI_SET_PREDICATE, F_LEN_CONST, R_ALL, D_ALL,
@@ -2521,7 +2516,7 @@ static void add_cmd_entry(struct intel_gvt *gvt, struct cmd_entry *e)
 static int cmd_parser_exec(struct parser_exec_state *s)
 {
        struct intel_vgpu *vgpu = s->vgpu;
-       struct cmd_info *info;
+       const struct cmd_info *info;
        u32 cmd;
        int ret = 0;
 
@@ -2683,7 +2678,7 @@ static int scan_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
                                        I915_GTT_PAGE_SIZE)))
                return -EINVAL;
 
-       ring_tail = wa_ctx->indirect_ctx.size + 3 * sizeof(uint32_t);
+       ring_tail = wa_ctx->indirect_ctx.size + 3 * sizeof(u32);
        ring_size = round_up(wa_ctx->indirect_ctx.size + CACHELINE_BYTES,
                        PAGE_SIZE);
        gma_head = wa_ctx->indirect_ctx.guest_gma;
@@ -2850,7 +2845,7 @@ put_obj:
 
 static int combine_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
 {
-       uint32_t per_ctx_start[CACHELINE_DWORDS] = {0};
+       u32 per_ctx_start[CACHELINE_DWORDS] = {0};
        unsigned char *bb_start_sva;
 
        if (!wa_ctx->per_ctx.valid)
@@ -2895,10 +2890,10 @@ int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
        return 0;
 }
 
-static struct cmd_info *find_cmd_entry_any_ring(struct intel_gvt *gvt,
+static const struct cmd_info *find_cmd_entry_any_ring(struct intel_gvt *gvt,
                unsigned int opcode, unsigned long rings)
 {
-       struct cmd_info *info = NULL;
+       const struct cmd_info *info = NULL;
        unsigned int ring;
 
        for_each_set_bit(ring, &rings, I915_NUM_ENGINES) {
@@ -2913,7 +2908,7 @@ static int init_cmd_table(struct intel_gvt *gvt)
 {
        int i;
        struct cmd_entry *e;
-       struct cmd_info *info;
+       const struct cmd_info *info;
        unsigned int gen_type;
 
        gen_type = intel_gvt_get_device_type(gvt);
index df1e14145747ca9666dae9c8bdf7273cc69c4b46..4f25b6b7728ef32e181f3e89627c92d2d78d2033 100644 (file)
@@ -198,7 +198,8 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
                        SDE_PORTC_HOTPLUG_CPT |
                        SDE_PORTD_HOTPLUG_CPT);
 
-       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) ||
+           IS_COFFEELAKE(dev_priv)) {
                vgpu_vreg_t(vgpu, SDEISR) &= ~(SDE_PORTA_HOTPLUG_SPT |
                                SDE_PORTE_HOTPLUG_SPT);
                vgpu_vreg_t(vgpu, SKL_FUSE_STATUS) |=
@@ -273,7 +274,8 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
                vgpu_vreg_t(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDID_DETECTED;
        }
 
-       if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) &&
+       if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) ||
+            IS_COFFEELAKE(dev_priv)) &&
                        intel_vgpu_has_monitor_on_port(vgpu, PORT_E)) {
                vgpu_vreg_t(vgpu, SDEISR) |= SDE_PORTE_HOTPLUG_SPT;
        }
@@ -453,7 +455,8 @@ void intel_vgpu_clean_display(struct intel_vgpu *vgpu)
 {
        struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
 
-       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
+       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) ||
+           IS_COFFEELAKE(dev_priv))
                clean_virtual_dp_monitor(vgpu, PORT_D);
        else
                clean_virtual_dp_monitor(vgpu, PORT_B);
@@ -476,7 +479,8 @@ int intel_vgpu_init_display(struct intel_vgpu *vgpu, u64 resolution)
 
        intel_vgpu_init_i2c_edid(vgpu);
 
-       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
+       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) ||
+           IS_COFFEELAKE(dev_priv))
                return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D,
                                                resolution);
        else
index 51ed99a37803310e2d9b7e84882ae7df97e3b59c..3e7e2b80c8579017cecdda478bc6166e1f46e061 100644 (file)
@@ -29,7 +29,6 @@
  */
 
 #include <linux/dma-buf.h>
-#include <drm/drmP.h>
 #include <linux/vfio.h>
 
 #include "i915_drv.h"
@@ -164,9 +163,7 @@ static struct drm_i915_gem_object *vgpu_create_gem(struct drm_device *dev,
 
        obj->read_domains = I915_GEM_DOMAIN_GTT;
        obj->write_domain = 0;
-       if (IS_SKYLAKE(dev_priv)
-               || IS_KABYLAKE(dev_priv)
-               || IS_BROXTON(dev_priv)) {
+       if (INTEL_GEN(dev_priv) >= 9) {
                unsigned int tiling_mode = 0;
                unsigned int stride = 0;
 
index 5d4bb35bb889e932c6b2905ac06e4495d57b0cb4..1fe6124918f1bcc2a97b39e7a811548a7a611e6d 100644 (file)
@@ -77,16 +77,32 @@ static unsigned char edid_get_byte(struct intel_vgpu *vgpu)
        return chr;
 }
 
+static inline int cnp_get_port_from_gmbus0(u32 gmbus0)
+{
+       int port_select = gmbus0 & _GMBUS_PIN_SEL_MASK;
+       int port = -EINVAL;
+
+       if (port_select == GMBUS_PIN_1_BXT)
+               port = PORT_B;
+       else if (port_select == GMBUS_PIN_2_BXT)
+               port = PORT_C;
+       else if (port_select == GMBUS_PIN_3_BXT)
+               port = PORT_D;
+       else if (port_select == GMBUS_PIN_4_CNP)
+               port = PORT_E;
+       return port;
+}
+
 static inline int bxt_get_port_from_gmbus0(u32 gmbus0)
 {
        int port_select = gmbus0 & _GMBUS_PIN_SEL_MASK;
        int port = -EINVAL;
 
-       if (port_select == 1)
+       if (port_select == GMBUS_PIN_1_BXT)
                port = PORT_B;
-       else if (port_select == 2)
+       else if (port_select == GMBUS_PIN_2_BXT)
                port = PORT_C;
-       else if (port_select == 3)
+       else if (port_select == GMBUS_PIN_3_BXT)
                port = PORT_D;
        return port;
 }
@@ -96,13 +112,13 @@ static inline int get_port_from_gmbus0(u32 gmbus0)
        int port_select = gmbus0 & _GMBUS_PIN_SEL_MASK;
        int port = -EINVAL;
 
-       if (port_select == 2)
+       if (port_select == GMBUS_PIN_VGADDC)
                port = PORT_E;
-       else if (port_select == 4)
+       else if (port_select == GMBUS_PIN_DPC)
                port = PORT_C;
-       else if (port_select == 5)
+       else if (port_select == GMBUS_PIN_DPB)
                port = PORT_B;
-       else if (port_select == 6)
+       else if (port_select == GMBUS_PIN_DPD)
                port = PORT_D;
        return port;
 }
@@ -133,6 +149,8 @@ static int gmbus0_mmio_write(struct intel_vgpu *vgpu,
 
        if (IS_BROXTON(dev_priv))
                port = bxt_get_port_from_gmbus0(pin_select);
+       else if (IS_COFFEELAKE(dev_priv))
+               port = cnp_get_port_from_gmbus0(pin_select);
        else
                port = get_port_from_gmbus0(pin_select);
        if (WARN_ON(port < 0))
index 85e6736f0a327742329dc9ee3bc8cf2dce294ed3..65e847392aea788f2feb17c381f75f0defc62709 100644 (file)
@@ -151,9 +151,7 @@ static u32 intel_vgpu_get_stride(struct intel_vgpu *vgpu, int pipe,
        u32 stride_reg = vgpu_vreg_t(vgpu, DSPSTRIDE(pipe)) & stride_mask;
        u32 stride = stride_reg;
 
-       if (IS_SKYLAKE(dev_priv)
-               || IS_KABYLAKE(dev_priv)
-               || IS_BROXTON(dev_priv)) {
+       if (INTEL_GEN(dev_priv) >= 9) {
                switch (tiled) {
                case PLANE_CTL_TILED_LINEAR:
                        stride = stride_reg * 64;
@@ -217,9 +215,7 @@ int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu,
        if (!plane->enabled)
                return -ENODEV;
 
-       if (IS_SKYLAKE(dev_priv)
-               || IS_KABYLAKE(dev_priv)
-               || IS_BROXTON(dev_priv)) {
+       if (INTEL_GEN(dev_priv) >= 9) {
                plane->tiled = val & PLANE_CTL_TILED_MASK;
                fmt = skl_format_to_drm(
                        val & PLANE_CTL_FORMAT_MASK,
@@ -260,9 +256,7 @@ int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu,
        }
 
        plane->stride = intel_vgpu_get_stride(vgpu, pipe, plane->tiled,
-               (IS_SKYLAKE(dev_priv)
-               || IS_KABYLAKE(dev_priv)
-               || IS_BROXTON(dev_priv)) ?
+               (INTEL_GEN(dev_priv) >= 9) ?
                        (_PRI_PLANE_STRIDE_MASK >> 6) :
                                _PRI_PLANE_STRIDE_MASK, plane->bpp);
 
index 733a2a0d0c3096ce56feb0a3a00e56e23f4db8ae..4e8947f33bd00db2a4c4e89fc59be35dc6ce1c5b 100644 (file)
@@ -187,52 +187,6 @@ static const struct intel_gvt_ops intel_gvt_ops = {
        .write_protect_handler = intel_vgpu_page_track_handler,
 };
 
-/**
- * intel_gvt_init_host - Load MPT modules and detect if we're running in host
- *
- * This function is called at the driver loading stage. If failed to find a
- * loadable MPT module or detect currently we're running in a VM, then GVT-g
- * will be disabled
- *
- * Returns:
- * Zero on success, negative error code if failed.
- *
- */
-int intel_gvt_init_host(void)
-{
-       if (intel_gvt_host.initialized)
-               return 0;
-
-       /* Xen DOM U */
-       if (xen_domain() && !xen_initial_domain())
-               return -ENODEV;
-
-       /* Try to load MPT modules for hypervisors */
-       if (xen_initial_domain()) {
-               /* In Xen dom0 */
-               intel_gvt_host.mpt = try_then_request_module(
-                               symbol_get(xengt_mpt), "xengt");
-               intel_gvt_host.hypervisor_type = INTEL_GVT_HYPERVISOR_XEN;
-       } else {
-#if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT)
-               /* not in Xen. Try KVMGT */
-               intel_gvt_host.mpt = try_then_request_module(
-                               symbol_get(kvmgt_mpt), "kvmgt");
-               intel_gvt_host.hypervisor_type = INTEL_GVT_HYPERVISOR_KVM;
-#endif
-       }
-
-       /* Fail to load MPT modules - bail out */
-       if (!intel_gvt_host.mpt)
-               return -EINVAL;
-
-       gvt_dbg_core("Running with hypervisor %s in host mode\n",
-                       supported_hypervisors[intel_gvt_host.hypervisor_type]);
-
-       intel_gvt_host.initialized = true;
-       return 0;
-}
-
 static void init_device_info(struct intel_gvt *gvt)
 {
        struct intel_gvt_device_info *info = &gvt->device_info;
@@ -316,7 +270,6 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv)
                return;
 
        intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);
-       intel_gvt_hypervisor_host_exit(&dev_priv->drm.pdev->dev, gvt);
        intel_gvt_cleanup_vgpu_type_groups(gvt);
        intel_gvt_clean_vgpu_types(gvt);
 
@@ -352,13 +305,6 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
        struct intel_vgpu *vgpu;
        int ret;
 
-       /*
-        * Cannot initialize GVT device without intel_gvt_host gets
-        * initialized first.
-        */
-       if (WARN_ON(!intel_gvt_host.initialized))
-               return -EINVAL;
-
        if (WARN_ON(dev_priv->gvt))
                return -EEXIST;
 
@@ -420,13 +366,6 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
                goto out_clean_types;
        }
 
-       ret = intel_gvt_hypervisor_host_init(&dev_priv->drm.pdev->dev, gvt,
-                               &intel_gvt_ops);
-       if (ret) {
-               gvt_err("failed to register gvt-g host device: %d\n", ret);
-               goto out_clean_types;
-       }
-
        vgpu = intel_gvt_create_idle_vgpu(gvt);
        if (IS_ERR(vgpu)) {
                ret = PTR_ERR(vgpu);
@@ -441,6 +380,8 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
 
        gvt_dbg_core("gvt device initialization is done\n");
        dev_priv->gvt = gvt;
+       intel_gvt_host.dev = &dev_priv->drm.pdev->dev;
+       intel_gvt_host.initialized = true;
        return 0;
 
 out_clean_types:
@@ -467,6 +408,45 @@ out_clean_idr:
        return ret;
 }
 
-#if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT)
-MODULE_SOFTDEP("pre: kvmgt");
-#endif
+int
+intel_gvt_register_hypervisor(struct intel_gvt_mpt *m)
+{
+       int ret;
+       void *gvt;
+
+       if (!intel_gvt_host.initialized)
+               return -ENODEV;
+
+       if (m->type != INTEL_GVT_HYPERVISOR_KVM &&
+           m->type != INTEL_GVT_HYPERVISOR_XEN)
+               return -EINVAL;
+
+       /* Get a reference for device model module */
+       if (!try_module_get(THIS_MODULE))
+               return -ENODEV;
+
+       intel_gvt_host.mpt = m;
+       intel_gvt_host.hypervisor_type = m->type;
+       gvt = (void *)kdev_to_i915(intel_gvt_host.dev)->gvt;
+
+       ret = intel_gvt_hypervisor_host_init(intel_gvt_host.dev, gvt,
+                                            &intel_gvt_ops);
+       if (ret < 0) {
+               gvt_err("Failed to init %s hypervisor module\n",
+                       supported_hypervisors[intel_gvt_host.hypervisor_type]);
+               module_put(THIS_MODULE);
+               return -ENODEV;
+       }
+       gvt_dbg_core("Running with hypervisor %s in host mode\n",
+                    supported_hypervisors[intel_gvt_host.hypervisor_type]);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(intel_gvt_register_hypervisor);
+
+void
+intel_gvt_unregister_hypervisor(void)
+{
+       intel_gvt_hypervisor_host_exit(intel_gvt_host.dev);
+       module_put(THIS_MODULE);
+}
+EXPORT_SYMBOL_GPL(intel_gvt_unregister_hypervisor);
index b4ab1dad01434f9ebdd6375104433a28c1707f2a..fb9cc980e120507bfb52d5626049d0ccf5d265bc 100644 (file)
 
 #define GVT_MAX_VGPU 8
 
-enum {
-       INTEL_GVT_HYPERVISOR_XEN = 0,
-       INTEL_GVT_HYPERVISOR_KVM,
-};
-
 struct intel_gvt_host {
+       struct device *dev;
        bool initialized;
        int hypervisor_type;
        struct intel_gvt_mpt *mpt;
@@ -597,7 +593,7 @@ static inline void mmio_hw_access_pre(struct drm_i915_private *dev_priv)
 
 static inline void mmio_hw_access_post(struct drm_i915_private *dev_priv)
 {
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put_unchecked(dev_priv);
 }
 
 /**
index b5475c91e2ef1b337ed083aae4c67a1d94fbe2e9..9c106e47e640a5dd1a03f12ac2873262f35bd295 100644 (file)
@@ -57,6 +57,8 @@ unsigned long intel_gvt_get_device_type(struct intel_gvt *gvt)
                return D_KBL;
        else if (IS_BROXTON(gvt->dev_priv))
                return D_BXT;
+       else if (IS_COFFEELAKE(gvt->dev_priv))
+               return D_CFL;
 
        return 0;
 }
@@ -276,14 +278,12 @@ static int mul_force_wake_write(struct intel_vgpu *vgpu,
                unsigned int offset, void *p_data, unsigned int bytes)
 {
        u32 old, new;
-       uint32_t ack_reg_offset;
+       u32 ack_reg_offset;
 
        old = vgpu_vreg(vgpu, offset);
        new = CALC_MODE_MASK_REG(old, *(u32 *)p_data);
 
-       if (IS_SKYLAKE(vgpu->gvt->dev_priv)
-               || IS_KABYLAKE(vgpu->gvt->dev_priv)
-               || IS_BROXTON(vgpu->gvt->dev_priv)) {
+       if (INTEL_GEN(vgpu->gvt->dev_priv)  >=  9) {
                switch (offset) {
                case FORCEWAKE_RENDER_GEN9_REG:
                        ack_reg_offset = FORCEWAKE_ACK_RENDER_GEN9_REG;
@@ -833,7 +833,7 @@ static int dp_aux_ch_ctl_trans_done(struct intel_vgpu *vgpu, u32 value,
 }
 
 static void dp_aux_ch_ctl_link_training(struct intel_vgpu_dpcd_data *dpcd,
-               uint8_t t)
+               u8 t)
 {
        if ((t & DPCD_TRAINING_PATTERN_SET_MASK) == DPCD_TRAINING_PATTERN_1) {
                /* training pattern 1 for CR */
@@ -889,9 +889,7 @@ static int dp_aux_ch_ctl_mmio_write(struct intel_vgpu *vgpu,
        write_vreg(vgpu, offset, p_data, bytes);
        data = vgpu_vreg(vgpu, offset);
 
-       if ((IS_SKYLAKE(vgpu->gvt->dev_priv)
-               || IS_KABYLAKE(vgpu->gvt->dev_priv)
-               || IS_BROXTON(vgpu->gvt->dev_priv))
+       if ((INTEL_GEN(vgpu->gvt->dev_priv) >= 9)
                && offset != _REG_SKL_DP_AUX_CH_CTL(port_index)) {
                /* SKL DPB/C/D aux ctl register changed */
                return 0;
@@ -919,7 +917,7 @@ static int dp_aux_ch_ctl_mmio_write(struct intel_vgpu *vgpu,
 
        if (op == GVT_AUX_NATIVE_WRITE) {
                int t;
-               uint8_t buf[16];
+               u8 buf[16];
 
                if ((addr + len + 1) >= DPCD_SIZE) {
                        /*
@@ -1407,7 +1405,8 @@ static int mailbox_write(struct intel_vgpu *vgpu, unsigned int offset,
        switch (cmd) {
        case GEN9_PCODE_READ_MEM_LATENCY:
                if (IS_SKYLAKE(vgpu->gvt->dev_priv)
-                        || IS_KABYLAKE(vgpu->gvt->dev_priv)) {
+                        || IS_KABYLAKE(vgpu->gvt->dev_priv)
+                        || IS_COFFEELAKE(vgpu->gvt->dev_priv)) {
                        /**
                         * "Read memory latency" command on gen9.
                         * Below memory latency values are read
@@ -1431,7 +1430,8 @@ static int mailbox_write(struct intel_vgpu *vgpu, unsigned int offset,
                break;
        case SKL_PCODE_CDCLK_CONTROL:
                if (IS_SKYLAKE(vgpu->gvt->dev_priv)
-                        || IS_KABYLAKE(vgpu->gvt->dev_priv))
+                        || IS_KABYLAKE(vgpu->gvt->dev_priv)
+                        || IS_COFFEELAKE(vgpu->gvt->dev_priv))
                        *data0 = SKL_CDCLK_READY_FOR_CHANGE;
                break;
        case GEN6_PCODE_READ_RC6VIDS:
@@ -3041,8 +3041,8 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)
        MMIO_DFH(GEN9_WM_CHICKEN3, D_SKL_PLUS, F_MODE_MASK | F_CMD_ACCESS,
                 NULL, NULL);
 
-       MMIO_D(_MMIO(0x4ab8), D_KBL);
-       MMIO_D(_MMIO(0x2248), D_KBL | D_SKL);
+       MMIO_D(_MMIO(0x4ab8), D_KBL | D_CFL);
+       MMIO_D(_MMIO(0x2248), D_SKL_PLUS);
 
        return 0;
 }
@@ -3302,7 +3302,8 @@ int intel_gvt_setup_mmio_info(struct intel_gvt *gvt)
                if (ret)
                        goto err;
        } else if (IS_SKYLAKE(dev_priv)
-               || IS_KABYLAKE(dev_priv)) {
+               || IS_KABYLAKE(dev_priv)
+               || IS_COFFEELAKE(dev_priv)) {
                ret = init_broadwell_mmio_info(gvt);
                if (ret)
                        goto err;
index 5af11cf1b48235c46079f376686112c5234abbfd..50798868ab15ae2a0c4e4ca7bd16d727d3b8c9b3 100644 (file)
 #ifndef _GVT_HYPERCALL_H_
 #define _GVT_HYPERCALL_H_
 
+enum hypervisor_type {
+       INTEL_GVT_HYPERVISOR_XEN = 0,
+       INTEL_GVT_HYPERVISOR_KVM,
+};
+
 /*
  * Specific GVT-g MPT modules function collections. Currently GVT-g supports
  * both Xen and KVM by providing dedicated hypervisor-related MPT modules.
  */
 struct intel_gvt_mpt {
+       enum hypervisor_type type;
        int (*host_init)(struct device *dev, void *gvt, const void *ops);
-       void (*host_exit)(struct device *dev, void *gvt);
+       void (*host_exit)(struct device *dev);
        int (*attach_vgpu)(void *vgpu, unsigned long *handle);
        void (*detach_vgpu)(unsigned long handle);
        int (*inject_msi)(unsigned long handle, u32 addr, u16 data);
@@ -67,6 +73,5 @@ struct intel_gvt_mpt {
 };
 
 extern struct intel_gvt_mpt xengt_mpt;
-extern struct intel_gvt_mpt kvmgt_mpt;
 
 #endif /* _GVT_HYPERCALL_H_ */
index 6b9d1354ff29be770a68f75d1f5506070c45496d..67125c5eec6eb59c7502065ae2c4a3698b390822 100644 (file)
@@ -581,9 +581,7 @@ static void gen8_init_irq(
 
                SET_BIT_INFO(irq, 4, PRIMARY_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C);
                SET_BIT_INFO(irq, 5, SPRITE_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C);
-       } else if (IS_SKYLAKE(gvt->dev_priv)
-                       || IS_KABYLAKE(gvt->dev_priv)
-                       || IS_BROXTON(gvt->dev_priv)) {
+       } else if (INTEL_GEN(gvt->dev_priv) >= 9) {
                SET_BIT_INFO(irq, 25, AUX_CHANNEL_B, INTEL_GVT_IRQ_INFO_DE_PORT);
                SET_BIT_INFO(irq, 26, AUX_CHANNEL_C, INTEL_GVT_IRQ_INFO_DE_PORT);
                SET_BIT_INFO(irq, 27, AUX_CHANNEL_D, INTEL_GVT_IRQ_INFO_DE_PORT);
index c1072143da1dc3968767b94573383d3b06f25883..f8d44e8f86a65ed6066f8aa29cac8321276564cb 100644 (file)
@@ -627,6 +627,12 @@ static int intel_vgpu_open(struct mdev_device *mdev)
                goto undo_iommu;
        }
 
+       /* Take a module reference as mdev core doesn't take
+        * a reference for vendor driver.
+        */
+       if (!try_module_get(THIS_MODULE))
+               goto undo_group;
+
        ret = kvmgt_guest_init(mdev);
        if (ret)
                goto undo_group;
@@ -679,6 +685,9 @@ static void __intel_vgpu_release(struct intel_vgpu *vgpu)
                                        &vgpu->vdev.group_notifier);
        WARN(ret, "vfio_unregister_notifier for group failed: %d\n", ret);
 
+       /* dereference module reference taken at open */
+       module_put(THIS_MODULE);
+
        info = (struct kvmgt_guest_info *)vgpu->handle;
        kvmgt_guest_exit(info);
 
@@ -703,7 +712,7 @@ static void intel_vgpu_release_work(struct work_struct *work)
        __intel_vgpu_release(vgpu);
 }
 
-static uint64_t intel_vgpu_get_bar_addr(struct intel_vgpu *vgpu, int bar)
+static u64 intel_vgpu_get_bar_addr(struct intel_vgpu *vgpu, int bar)
 {
        u32 start_lo, start_hi;
        u32 mem_type;
@@ -730,10 +739,10 @@ static uint64_t intel_vgpu_get_bar_addr(struct intel_vgpu *vgpu, int bar)
        return ((u64)start_hi << 32) | start_lo;
 }
 
-static int intel_vgpu_bar_rw(struct intel_vgpu *vgpu, int bar, uint64_t off,
+static int intel_vgpu_bar_rw(struct intel_vgpu *vgpu, int bar, u64 off,
                             void *buf, unsigned int count, bool is_write)
 {
-       uint64_t bar_start = intel_vgpu_get_bar_addr(vgpu, bar);
+       u64 bar_start = intel_vgpu_get_bar_addr(vgpu, bar);
        int ret;
 
        if (is_write)
@@ -745,13 +754,13 @@ static int intel_vgpu_bar_rw(struct intel_vgpu *vgpu, int bar, uint64_t off,
        return ret;
 }
 
-static inline bool intel_vgpu_in_aperture(struct intel_vgpu *vgpu, uint64_t off)
+static inline bool intel_vgpu_in_aperture(struct intel_vgpu *vgpu, u64 off)
 {
        return off >= vgpu_aperture_offset(vgpu) &&
               off < vgpu_aperture_offset(vgpu) + vgpu_aperture_sz(vgpu);
 }
 
-static int intel_vgpu_aperture_rw(struct intel_vgpu *vgpu, uint64_t off,
+static int intel_vgpu_aperture_rw(struct intel_vgpu *vgpu, u64 off,
                void *buf, unsigned long count, bool is_write)
 {
        void *aperture_va;
@@ -783,7 +792,7 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf,
 {
        struct intel_vgpu *vgpu = mdev_get_drvdata(mdev);
        unsigned int index = VFIO_PCI_OFFSET_TO_INDEX(*ppos);
-       uint64_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
+       u64 pos = *ppos & VFIO_PCI_OFFSET_MASK;
        int ret = -EINVAL;
 
 
@@ -1029,7 +1038,7 @@ static int intel_vgpu_get_irq_count(struct intel_vgpu *vgpu, int type)
 
 static int intel_vgpu_set_intx_mask(struct intel_vgpu *vgpu,
                        unsigned int index, unsigned int start,
-                       unsigned int count, uint32_t flags,
+                       unsigned int count, u32 flags,
                        void *data)
 {
        return 0;
@@ -1037,21 +1046,21 @@ static int intel_vgpu_set_intx_mask(struct intel_vgpu *vgpu,
 
 static int intel_vgpu_set_intx_unmask(struct intel_vgpu *vgpu,
                        unsigned int index, unsigned int start,
-                       unsigned int count, uint32_t flags, void *data)
+                       unsigned int count, u32 flags, void *data)
 {
        return 0;
 }
 
 static int intel_vgpu_set_intx_trigger(struct intel_vgpu *vgpu,
                unsigned int index, unsigned int start, unsigned int count,
-               uint32_t flags, void *data)
+               u32 flags, void *data)
 {
        return 0;
 }
 
 static int intel_vgpu_set_msi_trigger(struct intel_vgpu *vgpu,
                unsigned int index, unsigned int start, unsigned int count,
-               uint32_t flags, void *data)
+               u32 flags, void *data)
 {
        struct eventfd_ctx *trigger;
 
@@ -1070,12 +1079,12 @@ static int intel_vgpu_set_msi_trigger(struct intel_vgpu *vgpu,
        return 0;
 }
 
-static int intel_vgpu_set_irqs(struct intel_vgpu *vgpu, uint32_t flags,
+static int intel_vgpu_set_irqs(struct intel_vgpu *vgpu, u32 flags,
                unsigned int index, unsigned int start, unsigned int count,
                void *data)
 {
        int (*func)(struct intel_vgpu *vgpu, unsigned int index,
-                       unsigned int start, unsigned int count, uint32_t flags,
+                       unsigned int start, unsigned int count, u32 flags,
                        void *data) = NULL;
 
        switch (index) {
@@ -1467,7 +1476,7 @@ static int kvmgt_host_init(struct device *dev, void *gvt, const void *ops)
        return mdev_register_device(dev, &intel_vgpu_ops);
 }
 
-static void kvmgt_host_exit(struct device *dev, void *gvt)
+static void kvmgt_host_exit(struct device *dev)
 {
        mdev_unregister_device(dev);
 }
@@ -1849,7 +1858,8 @@ static bool kvmgt_is_valid_gfn(unsigned long handle, unsigned long gfn)
        return ret;
 }
 
-struct intel_gvt_mpt kvmgt_mpt = {
+static struct intel_gvt_mpt kvmgt_mpt = {
+       .type = INTEL_GVT_HYPERVISOR_KVM,
        .host_init = kvmgt_host_init,
        .host_exit = kvmgt_host_exit,
        .attach_vgpu = kvmgt_attach_vgpu,
@@ -1868,15 +1878,17 @@ struct intel_gvt_mpt kvmgt_mpt = {
        .put_vfio_device = kvmgt_put_vfio_device,
        .is_valid_gfn = kvmgt_is_valid_gfn,
 };
-EXPORT_SYMBOL_GPL(kvmgt_mpt);
 
 static int __init kvmgt_init(void)
 {
+       if (intel_gvt_register_hypervisor(&kvmgt_mpt) < 0)
+               return -ENODEV;
        return 0;
 }
 
 static void __exit kvmgt_exit(void)
 {
+       intel_gvt_unregister_hypervisor();
 }
 
 module_init(kvmgt_init);
index 43f65848ecd6b8e4e2436d12a23f31c2bea692c9..ed4df2f6d60b6fe233b912917499505d52642d0e 100644 (file)
@@ -57,7 +57,7 @@ int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa)
        (reg >= gvt->device_info.gtt_start_offset \
         && reg < gvt->device_info.gtt_start_offset + gvt_ggtt_sz(gvt))
 
-static void failsafe_emulate_mmio_rw(struct intel_vgpu *vgpu, uint64_t pa,
+static void failsafe_emulate_mmio_rw(struct intel_vgpu *vgpu, u64 pa,
                void *p_data, unsigned int bytes, bool read)
 {
        struct intel_gvt *gvt = NULL;
@@ -99,7 +99,7 @@ static void failsafe_emulate_mmio_rw(struct intel_vgpu *vgpu, uint64_t pa,
  * Returns:
  * Zero on success, negative error code if failed
  */
-int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa,
+int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, u64 pa,
                void *p_data, unsigned int bytes)
 {
        struct intel_gvt *gvt = vgpu->gvt;
@@ -171,7 +171,7 @@ out:
  * Returns:
  * Zero on success, negative error code if failed
  */
-int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, uint64_t pa,
+int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, u64 pa,
                void *p_data, unsigned int bytes)
 {
        struct intel_gvt *gvt = vgpu->gvt;
index 1ffc69eba30e385a21469847c6681f420254d67d..5874f1cb43062cdf39f2818c4b6340ec16c4bb03 100644 (file)
@@ -43,15 +43,16 @@ struct intel_vgpu;
 #define D_SKL  (1 << 1)
 #define D_KBL  (1 << 2)
 #define D_BXT  (1 << 3)
+#define D_CFL  (1 << 4)
 
-#define D_GEN9PLUS     (D_SKL | D_KBL | D_BXT)
-#define D_GEN8PLUS     (D_BDW | D_SKL | D_KBL | D_BXT)
+#define D_GEN9PLUS     (D_SKL | D_KBL | D_BXT | D_CFL)
+#define D_GEN8PLUS     (D_BDW | D_SKL | D_KBL | D_BXT | D_CFL)
 
-#define D_SKL_PLUS     (D_SKL | D_KBL | D_BXT)
-#define D_BDW_PLUS     (D_BDW | D_SKL | D_KBL | D_BXT)
+#define D_SKL_PLUS     (D_SKL | D_KBL | D_BXT | D_CFL)
+#define D_BDW_PLUS     (D_BDW | D_SKL | D_KBL | D_BXT | D_CFL)
 
 #define D_PRE_SKL      (D_BDW)
-#define D_ALL          (D_BDW | D_SKL | D_KBL | D_BXT)
+#define D_ALL          (D_BDW | D_SKL | D_KBL | D_BXT | D_CFL)
 
 typedef int (*gvt_mmio_func)(struct intel_vgpu *, unsigned int, void *,
                             unsigned int);
index d6e02c15ef97d995fd4ec2ab203c15e5ff8ab245..7d84cfb9051ac886579648ac7bb2cc5e2a70b3fa 100644 (file)
@@ -353,8 +353,7 @@ static void handle_tlb_pending_event(struct intel_vgpu *vgpu, int ring_id)
         */
        fw = intel_uncore_forcewake_for_reg(dev_priv, reg,
                                            FW_REG_READ | FW_REG_WRITE);
-       if (ring_id == RCS && (IS_SKYLAKE(dev_priv) ||
-                       IS_KABYLAKE(dev_priv) || IS_BROXTON(dev_priv)))
+       if (ring_id == RCS && (INTEL_GEN(dev_priv) >= 9))
                fw |= FORCEWAKE_RENDER;
 
        intel_uncore_forcewake_get(dev_priv, fw);
@@ -391,7 +390,8 @@ static void switch_mocs(struct intel_vgpu *pre, struct intel_vgpu *next,
        if (WARN_ON(ring_id >= ARRAY_SIZE(regs)))
                return;
 
-       if ((IS_KABYLAKE(dev_priv) || IS_BROXTON(dev_priv)) && ring_id == RCS)
+       if ((IS_KABYLAKE(dev_priv)  || IS_BROXTON(dev_priv)
+               || IS_COFFEELAKE(dev_priv)) && ring_id == RCS)
                return;
 
        if (!pre && !gen9_render_mocs.initialized)
@@ -457,9 +457,7 @@ static void switch_mmio(struct intel_vgpu *pre,
        u32 old_v, new_v;
 
        dev_priv = pre ? pre->gvt->dev_priv : next->gvt->dev_priv;
-       if (IS_SKYLAKE(dev_priv)
-               || IS_KABYLAKE(dev_priv)
-               || IS_BROXTON(dev_priv))
+       if (INTEL_GEN(dev_priv) >= 9)
                switch_mocs(pre, next, ring_id);
 
        for (mmio = dev_priv->gvt->engine_mmio_list.mmio;
@@ -471,8 +469,8 @@ static void switch_mmio(struct intel_vgpu *pre,
                 * state image on kabylake, it's initialized by lri command and
                 * save or restore with context together.
                 */
-               if ((IS_KABYLAKE(dev_priv) || IS_BROXTON(dev_priv))
-                       && mmio->in_context)
+               if ((IS_KABYLAKE(dev_priv) || IS_BROXTON(dev_priv)
+                       || IS_COFFEELAKE(dev_priv)) && mmio->in_context)
                        continue;
 
                // save
@@ -565,9 +563,7 @@ void intel_gvt_init_engine_mmio_context(struct intel_gvt *gvt)
 {
        struct engine_mmio *mmio;
 
-       if (IS_SKYLAKE(gvt->dev_priv) ||
-               IS_KABYLAKE(gvt->dev_priv) ||
-               IS_BROXTON(gvt->dev_priv))
+       if (INTEL_GEN(gvt->dev_priv) >= 9)
                gvt->engine_mmio_list.mmio = gen9_engine_mmio_list;
        else
                gvt->engine_mmio_list.mmio = gen8_engine_mmio_list;
index 67f19992b226f29a13d408be36da8b4820095b13..9b4225d44243b9010836482133124721f4279c68 100644 (file)
  * Zero on success, negative error code if failed
  */
 static inline int intel_gvt_hypervisor_host_init(struct device *dev,
-                       void *gvt, const void *ops)
+                                                void *gvt, const void *ops)
 {
-       /* optional to provide */
        if (!intel_gvt_host.mpt->host_init)
-               return 0;
+               return -ENODEV;
 
        return intel_gvt_host.mpt->host_init(dev, gvt, ops);
 }
@@ -62,14 +61,13 @@ static inline int intel_gvt_hypervisor_host_init(struct device *dev,
 /**
  * intel_gvt_hypervisor_host_exit - exit GVT-g host side
  */
-static inline void intel_gvt_hypervisor_host_exit(struct device *dev,
-                       void *gvt)
+static inline void intel_gvt_hypervisor_host_exit(struct device *dev)
 {
        /* optional to provide */
        if (!intel_gvt_host.mpt->host_exit)
                return;
 
-       intel_gvt_host.mpt->host_exit(dev, gvt);
+       intel_gvt_host.mpt->host_exit(dev);
 }
 
 /**
@@ -362,4 +360,7 @@ static inline bool intel_gvt_hypervisor_is_valid_gfn(
        return intel_gvt_host.mpt->is_valid_gfn(vgpu->handle, gfn);
 }
 
+int intel_gvt_register_hypervisor(struct intel_gvt_mpt *);
+void intel_gvt_unregister_hypervisor(void);
+
 #endif /* _GVT_MPT_H_ */
index c32e7d5e862914b787d7cf5cbf706cb5c4a41748..1c763a27a41219614080e7a7101c2bb3de56fdf4 100644 (file)
@@ -94,7 +94,7 @@ static void gvt_balance_timeslice(struct gvt_sched_data *sched_data)
 {
        struct vgpu_sched_data *vgpu_data;
        struct list_head *pos;
-       static uint64_t stage_check;
+       static u64 stage_check;
        int stage = stage_check++ % GVT_TS_BALANCE_STAGE_NUM;
 
        /* The timeslice accumulation reset at stage 0, which is
@@ -474,6 +474,6 @@ void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu)
                }
        }
        spin_unlock_bh(&scheduler->mmio_context_lock);
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put_unchecked(dev_priv);
        mutex_unlock(&vgpu->gvt->sched_lock);
 }
index 1ad8c5e1455d782160d15c4a1c83cb6f64dad3cf..b7957eefb9763b5f310ad81c141136ce7911add8 100644 (file)
@@ -299,7 +299,8 @@ static int copy_workload_to_ring_buffer(struct intel_vgpu_workload *workload)
        void *shadow_ring_buffer_va;
        u32 *cs;
 
-       if ((IS_KABYLAKE(req->i915) || IS_BROXTON(req->i915))
+       if ((IS_KABYLAKE(req->i915) || IS_BROXTON(req->i915)
+               || IS_COFFEELAKE(req->i915))
                && is_inhibit_context(req->hw_context))
                intel_vgpu_restore_inhibit_context(vgpu, req);
 
@@ -939,9 +940,7 @@ static int workload_thread(void *priv)
        struct intel_vgpu_workload *workload = NULL;
        struct intel_vgpu *vgpu = NULL;
        int ret;
-       bool need_force_wake = IS_SKYLAKE(gvt->dev_priv)
-                       || IS_KABYLAKE(gvt->dev_priv)
-                       || IS_BROXTON(gvt->dev_priv);
+       bool need_force_wake = (INTEL_GEN(gvt->dev_priv) >= 9);
        DEFINE_WAIT_FUNC(wait, woken_wake_function);
 
        kfree(p);
@@ -997,7 +996,7 @@ complete:
                        intel_uncore_forcewake_put(gvt->dev_priv,
                                        FORCEWAKE_ALL);
 
-               intel_runtime_pm_put(gvt->dev_priv);
+               intel_runtime_pm_put_unchecked(gvt->dev_priv);
                if (ret && (vgpu_is_vm_unhealthy(ret)))
                        enter_failsafe_mode(vgpu, GVT_FAILSAFE_GUEST_ERR);
        }
@@ -1451,7 +1450,7 @@ intel_vgpu_create_workload(struct intel_vgpu *vgpu, int ring_id,
                mutex_lock(&dev_priv->drm.struct_mutex);
                ret = intel_gvt_scan_and_shadow_workload(workload);
                mutex_unlock(&dev_priv->drm.struct_mutex);
-               intel_runtime_pm_put(dev_priv);
+               intel_runtime_pm_put_unchecked(dev_priv);
        }
 
        if (ret && (vgpu_is_vm_unhealthy(ret))) {
index ca5529d0e48ef20b0d2dbdd6e33512a2234afda7..1e9eec6a32fee8fea81e365ff030af0485c6a477 100644 (file)
@@ -61,7 +61,7 @@ struct shadow_indirect_ctx {
        unsigned long guest_gma;
        unsigned long shadow_gma;
        void *shadow_va;
-       uint32_t size;
+       u32 size;
 };
 
 #define PER_CTX_ADDR_MASK 0xfffff000
index 1fd64202d74e740c684fa4637386030057500054..6d787750d279f63ed3f08e06d01a18401a52367e 100644 (file)
@@ -228,7 +228,7 @@ TRACE_EVENT(oos_sync,
 TRACE_EVENT(gvt_command,
        TP_PROTO(u8 vgpu_id, u8 ring_id, u32 ip_gma, u32 *cmd_va,
                u32 cmd_len,  u32 buf_type, u32 buf_addr_type,
-               void *workload, char *cmd_name),
+               void *workload, const char *cmd_name),
 
        TP_ARGS(vgpu_id, ring_id, ip_gma, cmd_va, cmd_len, buf_type,
                buf_addr_type, workload, cmd_name),
index c628be05fbfe907a1bce89fd4727df79906fe63f..e1c860f80eb0593dbe1948f897f7c55cfe0d6c99 100644 (file)
@@ -148,10 +148,10 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)
                gvt->types[i].avail_instance = min(low_avail / vgpu_types[i].low_mm,
                                                   high_avail / vgpu_types[i].high_mm);
 
-               if (IS_GEN8(gvt->dev_priv))
+               if (IS_GEN(gvt->dev_priv, 8))
                        sprintf(gvt->types[i].name, "GVTg_V4_%s",
                                                vgpu_types[i].name);
-               else if (IS_GEN9(gvt->dev_priv))
+               else if (IS_GEN(gvt->dev_priv, 9))
                        sprintf(gvt->types[i].name, "GVTg_V5_%s",
                                                vgpu_types[i].name);
 
index 95478db9998b51a410b927d654990967c74c5fdc..33e8eed64423af5f00fac38c6ca88dccd7b7911e 100644 (file)
@@ -865,7 +865,7 @@ void intel_engine_init_cmd_parser(struct intel_engine_cs *engine)
        int cmd_table_count;
        int ret;
 
-       if (!IS_GEN7(engine->i915))
+       if (!IS_GEN(engine->i915, 7))
                return;
 
        switch (engine->id) {
index 38dcee1ca062483272948bce3a7d9af2b4c83a7d..9a9e1da496dc8624aed4a17292d3eb2e1def56e7 100644 (file)
@@ -32,6 +32,8 @@
 #include "intel_drv.h"
 #include "intel_guc_submission.h"
 
+#include "i915_reset.h"
+
 static inline struct drm_i915_private *node_to_i915(struct drm_info_node *node)
 {
        return to_i915(node->minor->dev);
@@ -48,7 +50,7 @@ static int i915_capabilities(struct seq_file *m, void *data)
        seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev_priv));
 
        intel_device_info_dump_flags(info, &p);
-       intel_device_info_dump_runtime(info, &p);
+       intel_device_info_dump_runtime(RUNTIME_INFO(dev_priv), &p);
        intel_driver_caps_print(&dev_priv->caps, &p);
 
        kernel_param_lock(THIS_MODULE);
@@ -297,11 +299,12 @@ out:
 }
 
 struct file_stats {
-       struct drm_i915_file_private *file_priv;
+       struct i915_address_space *vm;
        unsigned long count;
        u64 total, unbound;
        u64 global, shared;
        u64 active, inactive;
+       u64 closed;
 };
 
 static int per_file_stats(int id, void *ptr, void *data)
@@ -326,9 +329,7 @@ static int per_file_stats(int id, void *ptr, void *data)
                if (i915_vma_is_ggtt(vma)) {
                        stats->global += vma->node.size;
                } else {
-                       struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vma->vm);
-
-                       if (ppgtt->vm.file != stats->file_priv)
+                       if (vma->vm != stats->vm)
                                continue;
                }
 
@@ -336,6 +337,9 @@ static int per_file_stats(int id, void *ptr, void *data)
                        stats->active += vma->node.size;
                else
                        stats->inactive += vma->node.size;
+
+               if (i915_vma_is_closed(vma))
+                       stats->closed += vma->node.size;
        }
 
        return 0;
@@ -343,7 +347,7 @@ static int per_file_stats(int id, void *ptr, void *data)
 
 #define print_file_stats(m, name, stats) do { \
        if (stats.count) \
-               seq_printf(m, "%s: %lu objects, %llu bytes (%llu active, %llu inactive, %llu global, %llu shared, %llu unbound)\n", \
+               seq_printf(m, "%s: %lu objects, %llu bytes (%llu active, %llu inactive, %llu global, %llu shared, %llu unbound, %llu closed)\n", \
                           name, \
                           stats.count, \
                           stats.total, \
@@ -351,20 +355,19 @@ static int per_file_stats(int id, void *ptr, void *data)
                           stats.inactive, \
                           stats.global, \
                           stats.shared, \
-                          stats.unbound); \
+                          stats.unbound, \
+                          stats.closed); \
 } while (0)
 
 static void print_batch_pool_stats(struct seq_file *m,
                                   struct drm_i915_private *dev_priv)
 {
        struct drm_i915_gem_object *obj;
-       struct file_stats stats;
        struct intel_engine_cs *engine;
+       struct file_stats stats = {};
        enum intel_engine_id id;
        int j;
 
-       memset(&stats, 0, sizeof(stats));
-
        for_each_engine(engine, dev_priv, id) {
                for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) {
                        list_for_each_entry(obj,
@@ -377,44 +380,47 @@ static void print_batch_pool_stats(struct seq_file *m,
        print_file_stats(m, "[k]batch pool", stats);
 }
 
-static int per_file_ctx_stats(int idx, void *ptr, void *data)
+static void print_context_stats(struct seq_file *m,
+                               struct drm_i915_private *i915)
 {
-       struct i915_gem_context *ctx = ptr;
-       struct intel_engine_cs *engine;
-       enum intel_engine_id id;
+       struct file_stats kstats = {};
+       struct i915_gem_context *ctx;
 
-       for_each_engine(engine, ctx->i915, id) {
-               struct intel_context *ce = to_intel_context(ctx, engine);
+       list_for_each_entry(ctx, &i915->contexts.list, link) {
+               struct intel_engine_cs *engine;
+               enum intel_engine_id id;
 
-               if (ce->state)
-                       per_file_stats(0, ce->state->obj, data);
-               if (ce->ring)
-                       per_file_stats(0, ce->ring->vma->obj, data);
-       }
+               for_each_engine(engine, i915, id) {
+                       struct intel_context *ce = to_intel_context(ctx, engine);
 
-       return 0;
-}
+                       if (ce->state)
+                               per_file_stats(0, ce->state->obj, &kstats);
+                       if (ce->ring)
+                               per_file_stats(0, ce->ring->vma->obj, &kstats);
+               }
 
-static void print_context_stats(struct seq_file *m,
-                               struct drm_i915_private *dev_priv)
-{
-       struct drm_device *dev = &dev_priv->drm;
-       struct file_stats stats;
-       struct drm_file *file;
+               if (!IS_ERR_OR_NULL(ctx->file_priv)) {
+                       struct file_stats stats = { .vm = &ctx->ppgtt->vm, };
+                       struct drm_file *file = ctx->file_priv->file;
+                       struct task_struct *task;
+                       char name[80];
 
-       memset(&stats, 0, sizeof(stats));
+                       spin_lock(&file->table_lock);
+                       idr_for_each(&file->object_idr, per_file_stats, &stats);
+                       spin_unlock(&file->table_lock);
 
-       mutex_lock(&dev->struct_mutex);
-       if (dev_priv->kernel_context)
-               per_file_ctx_stats(0, dev_priv->kernel_context, &stats);
+                       rcu_read_lock();
+                       task = pid_task(ctx->pid ?: file->pid, PIDTYPE_PID);
+                       snprintf(name, sizeof(name), "%s/%d",
+                                task ? task->comm : "<unknown>",
+                                ctx->user_handle);
+                       rcu_read_unlock();
 
-       list_for_each_entry(file, &dev->filelist, lhead) {
-               struct drm_i915_file_private *fpriv = file->driver_priv;
-               idr_for_each(&fpriv->context_idr, per_file_ctx_stats, &stats);
+                       print_file_stats(m, name, stats);
+               }
        }
-       mutex_unlock(&dev->struct_mutex);
 
-       print_file_stats(m, "[k]contexts", stats);
+       print_file_stats(m, "[k]contexts", kstats);
 }
 
 static int i915_gem_object_info(struct seq_file *m, void *data)
@@ -426,14 +432,9 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
        u64 size, mapped_size, purgeable_size, dpy_size, huge_size;
        struct drm_i915_gem_object *obj;
        unsigned int page_sizes = 0;
-       struct drm_file *file;
        char buf[80];
        int ret;
 
-       ret = mutex_lock_interruptible(&dev->struct_mutex);
-       if (ret)
-               return ret;
-
        seq_printf(m, "%u objects, %llu bytes\n",
                   dev_priv->mm.object_count,
                   dev_priv->mm.object_memory);
@@ -514,43 +515,14 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
                                        buf, sizeof(buf)));
 
        seq_putc(m, '\n');
-       print_batch_pool_stats(m, dev_priv);
-       mutex_unlock(&dev->struct_mutex);
-
-       mutex_lock(&dev->filelist_mutex);
-       print_context_stats(m, dev_priv);
-       list_for_each_entry_reverse(file, &dev->filelist, lhead) {
-               struct file_stats stats;
-               struct drm_i915_file_private *file_priv = file->driver_priv;
-               struct i915_request *request;
-               struct task_struct *task;
-
-               mutex_lock(&dev->struct_mutex);
 
-               memset(&stats, 0, sizeof(stats));
-               stats.file_priv = file->driver_priv;
-               spin_lock(&file->table_lock);
-               idr_for_each(&file->object_idr, per_file_stats, &stats);
-               spin_unlock(&file->table_lock);
-               /*
-                * Although we have a valid reference on file->pid, that does
-                * not guarantee that the task_struct who called get_pid() is
-                * still alive (e.g. get_pid(current) => fork() => exit()).
-                * Therefore, we need to protect this ->comm access using RCU.
-                */
-               request = list_first_entry_or_null(&file_priv->mm.request_list,
-                                                  struct i915_request,
-                                                  client_link);
-               rcu_read_lock();
-               task = pid_task(request && request->gem_context->pid ?
-                               request->gem_context->pid : file->pid,
-                               PIDTYPE_PID);
-               print_file_stats(m, task ? task->comm : "<unknown>", stats);
-               rcu_read_unlock();
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
 
-               mutex_unlock(&dev->struct_mutex);
-       }
-       mutex_unlock(&dev->filelist_mutex);
+       print_batch_pool_stats(m, dev_priv);
+       print_context_stats(m, dev_priv);
+       mutex_unlock(&dev->struct_mutex);
 
        return 0;
 }
@@ -656,10 +628,12 @@ static void gen8_display_interrupt_info(struct seq_file *m)
 
        for_each_pipe(dev_priv, pipe) {
                enum intel_display_power_domain power_domain;
+               intel_wakeref_t wakeref;
 
                power_domain = POWER_DOMAIN_PIPE(pipe);
-               if (!intel_display_power_get_if_enabled(dev_priv,
-                                                       power_domain)) {
+               wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                            power_domain);
+               if (!wakeref) {
                        seq_printf(m, "Pipe %c power disabled\n",
                                   pipe_name(pipe));
                        continue;
@@ -674,7 +648,7 @@ static void gen8_display_interrupt_info(struct seq_file *m)
                           pipe_name(pipe),
                           I915_READ(GEN8_DE_PIPE_IER(pipe)));
 
-               intel_display_power_put(dev_priv, power_domain);
+               intel_display_power_put(dev_priv, power_domain, wakeref);
        }
 
        seq_printf(m, "Display Engine port interrupt mask:\t%08x\n",
@@ -704,11 +678,14 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
+       intel_wakeref_t wakeref;
        int i, pipe;
 
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
        if (IS_CHERRYVIEW(dev_priv)) {
+               intel_wakeref_t pref;
+
                seq_printf(m, "Master Interrupt Control:\t%08x\n",
                           I915_READ(GEN8_MASTER_IRQ));
 
@@ -724,8 +701,9 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
                        enum intel_display_power_domain power_domain;
 
                        power_domain = POWER_DOMAIN_PIPE(pipe);
-                       if (!intel_display_power_get_if_enabled(dev_priv,
-                                                               power_domain)) {
+                       pref = intel_display_power_get_if_enabled(dev_priv,
+                                                                 power_domain);
+                       if (!pref) {
                                seq_printf(m, "Pipe %c power disabled\n",
                                           pipe_name(pipe));
                                continue;
@@ -735,17 +713,17 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
                                   pipe_name(pipe),
                                   I915_READ(PIPESTAT(pipe)));
 
-                       intel_display_power_put(dev_priv, power_domain);
+                       intel_display_power_put(dev_priv, power_domain, pref);
                }
 
-               intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+               pref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
                seq_printf(m, "Port hotplug:\t%08x\n",
                           I915_READ(PORT_HOTPLUG_EN));
                seq_printf(m, "DPFLIPSTAT:\t%08x\n",
                           I915_READ(VLV_DPFLIPSTAT));
                seq_printf(m, "DPINVGTT:\t%08x\n",
                           I915_READ(DPINVGTT));
-               intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+               intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, pref);
 
                for (i = 0; i < 4; i++) {
                        seq_printf(m, "GT Interrupt IMR %d:\t%08x\n",
@@ -808,10 +786,12 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
                           I915_READ(VLV_IMR));
                for_each_pipe(dev_priv, pipe) {
                        enum intel_display_power_domain power_domain;
+                       intel_wakeref_t pref;
 
                        power_domain = POWER_DOMAIN_PIPE(pipe);
-                       if (!intel_display_power_get_if_enabled(dev_priv,
-                                                               power_domain)) {
+                       pref = intel_display_power_get_if_enabled(dev_priv,
+                                                                 power_domain);
+                       if (!pref) {
                                seq_printf(m, "Pipe %c power disabled\n",
                                           pipe_name(pipe));
                                continue;
@@ -820,7 +800,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
                        seq_printf(m, "Pipe %c stat:\t%08x\n",
                                   pipe_name(pipe),
                                   I915_READ(PIPESTAT(pipe)));
-                       intel_display_power_put(dev_priv, power_domain);
+                       intel_display_power_put(dev_priv, power_domain, pref);
                }
 
                seq_printf(m, "Master IER:\t%08x\n",
@@ -907,7 +887,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
                }
        }
 
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
 
        return 0;
 }
@@ -980,12 +960,13 @@ static int i915_gpu_info_open(struct inode *inode, struct file *file)
 {
        struct drm_i915_private *i915 = inode->i_private;
        struct i915_gpu_state *gpu;
+       intel_wakeref_t wakeref;
 
-       intel_runtime_pm_get(i915);
-       gpu = i915_capture_gpu_state(i915);
-       intel_runtime_pm_put(i915);
-       if (!gpu)
-               return -ENOMEM;
+       gpu = NULL;
+       with_intel_runtime_pm(i915, wakeref)
+               gpu = i915_capture_gpu_state(i915);
+       if (IS_ERR(gpu))
+               return PTR_ERR(gpu);
 
        file->private_data = gpu;
        return 0;
@@ -1018,7 +999,13 @@ i915_error_state_write(struct file *filp,
 
 static int i915_error_state_open(struct inode *inode, struct file *file)
 {
-       file->private_data = i915_first_error_state(inode->i_private);
+       struct i915_gpu_state *error;
+
+       error = i915_first_error_state(inode->i_private);
+       if (IS_ERR(error))
+               return PTR_ERR(error);
+
+       file->private_data  = error;
        return 0;
 }
 
@@ -1032,39 +1019,16 @@ static const struct file_operations i915_error_state_fops = {
 };
 #endif
 
-static int
-i915_next_seqno_set(void *data, u64 val)
-{
-       struct drm_i915_private *dev_priv = data;
-       struct drm_device *dev = &dev_priv->drm;
-       int ret;
-
-       ret = mutex_lock_interruptible(&dev->struct_mutex);
-       if (ret)
-               return ret;
-
-       intel_runtime_pm_get(dev_priv);
-       ret = i915_gem_set_global_seqno(dev, val);
-       intel_runtime_pm_put(dev_priv);
-
-       mutex_unlock(&dev->struct_mutex);
-
-       return ret;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(i915_next_seqno_fops,
-                       NULL, i915_next_seqno_set,
-                       "0x%llx\n");
-
 static int i915_frequency_info(struct seq_file *m, void *unused)
 {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
        struct intel_rps *rps = &dev_priv->gt_pm.rps;
+       intel_wakeref_t wakeref;
        int ret = 0;
 
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
-       if (IS_GEN5(dev_priv)) {
+       if (IS_GEN(dev_priv, 5)) {
                u16 rgvswctl = I915_READ16(MEMSWCTL);
                u16 rgvstat = I915_READ16(MEMSTAT_ILK);
 
@@ -1274,7 +1238,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
        seq_printf(m, "Max CD clock frequency: %d kHz\n", dev_priv->max_cdclk_freq);
        seq_printf(m, "Max pixel clock frequency: %d kHz\n", dev_priv->max_dotclk_freq);
 
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
        return ret;
 }
 
@@ -1313,6 +1277,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
        u64 acthd[I915_NUM_ENGINES];
        u32 seqno[I915_NUM_ENGINES];
        struct intel_instdone instdone;
+       intel_wakeref_t wakeref;
        enum intel_engine_id id;
 
        if (test_bit(I915_WEDGED, &dev_priv->gpu_error.flags))
@@ -1331,17 +1296,15 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
                return 0;
        }
 
-       intel_runtime_pm_get(dev_priv);
+       with_intel_runtime_pm(dev_priv, wakeref) {
+               for_each_engine(engine, dev_priv, id) {
+                       acthd[id] = intel_engine_get_active_head(engine);
+                       seqno[id] = intel_engine_get_seqno(engine);
+               }
 
-       for_each_engine(engine, dev_priv, id) {
-               acthd[id] = intel_engine_get_active_head(engine);
-               seqno[id] = intel_engine_get_seqno(engine);
+               intel_engine_get_instdone(dev_priv->engine[RCS], &instdone);
        }
 
-       intel_engine_get_instdone(dev_priv->engine[RCS], &instdone);
-
-       intel_runtime_pm_put(dev_priv);
-
        if (timer_pending(&dev_priv->gpu_error.hangcheck_work.timer))
                seq_printf(m, "Hangcheck active, timer fires in %dms\n",
                           jiffies_to_msecs(dev_priv->gpu_error.hangcheck_work.timer.expires -
@@ -1616,18 +1579,17 @@ static int gen6_drpc_info(struct seq_file *m)
 static int i915_drpc_info(struct seq_file *m, void *unused)
 {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
-       int err;
-
-       intel_runtime_pm_get(dev_priv);
-
-       if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-               err = vlv_drpc_info(m);
-       else if (INTEL_GEN(dev_priv) >= 6)
-               err = gen6_drpc_info(m);
-       else
-               err = ironlake_drpc_info(m);
-
-       intel_runtime_pm_put(dev_priv);
+       intel_wakeref_t wakeref;
+       int err = -ENODEV;
+
+       with_intel_runtime_pm(dev_priv, wakeref) {
+               if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+                       err = vlv_drpc_info(m);
+               else if (INTEL_GEN(dev_priv) >= 6)
+                       err = gen6_drpc_info(m);
+               else
+                       err = ironlake_drpc_info(m);
+       }
 
        return err;
 }
@@ -1649,11 +1611,12 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
 {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
        struct intel_fbc *fbc = &dev_priv->fbc;
+       intel_wakeref_t wakeref;
 
        if (!HAS_FBC(dev_priv))
                return -ENODEV;
 
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
        mutex_lock(&fbc->lock);
 
        if (intel_fbc_is_active(dev_priv))
@@ -1680,7 +1643,7 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
        }
 
        mutex_unlock(&fbc->lock);
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
 
        return 0;
 }
@@ -1725,11 +1688,12 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_fbc_false_color_fops,
 static int i915_ips_status(struct seq_file *m, void *unused)
 {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
+       intel_wakeref_t wakeref;
 
        if (!HAS_IPS(dev_priv))
                return -ENODEV;
 
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
        seq_printf(m, "Enabled by kernel parameter: %s\n",
                   yesno(i915_modparams.enable_ips));
@@ -1743,7 +1707,7 @@ static int i915_ips_status(struct seq_file *m, void *unused)
                        seq_puts(m, "Currently: disabled\n");
        }
 
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
 
        return 0;
 }
@@ -1751,10 +1715,10 @@ static int i915_ips_status(struct seq_file *m, void *unused)
 static int i915_sr_status(struct seq_file *m, void *unused)
 {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
+       intel_wakeref_t wakeref;
        bool sr_enabled = false;
 
-       intel_runtime_pm_get(dev_priv);
-       intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+       wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
 
        if (INTEL_GEN(dev_priv) >= 9)
                /* no global SR status; inspect per-plane WM */;
@@ -1770,8 +1734,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
        else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
 
-       intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
-       intel_runtime_pm_put(dev_priv);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
 
        seq_printf(m, "self-refresh: %s\n", enableddisabled(sr_enabled));
 
@@ -1780,31 +1743,24 @@ static int i915_sr_status(struct seq_file *m, void *unused)
 
 static int i915_emon_status(struct seq_file *m, void *unused)
 {
-       struct drm_i915_private *dev_priv = node_to_i915(m->private);
-       struct drm_device *dev = &dev_priv->drm;
-       unsigned long temp, chipset, gfx;
-       int ret;
+       struct drm_i915_private *i915 = node_to_i915(m->private);
+       intel_wakeref_t wakeref;
 
-       if (!IS_GEN5(dev_priv))
+       if (!IS_GEN(i915, 5))
                return -ENODEV;
 
-       intel_runtime_pm_get(dev_priv);
-
-       ret = mutex_lock_interruptible(&dev->struct_mutex);
-       if (ret)
-               return ret;
-
-       temp = i915_mch_val(dev_priv);
-       chipset = i915_chipset_val(dev_priv);
-       gfx = i915_gfx_val(dev_priv);
-       mutex_unlock(&dev->struct_mutex);
+       with_intel_runtime_pm(i915, wakeref) {
+               unsigned long temp, chipset, gfx;
 
-       seq_printf(m, "GMCH temp: %ld\n", temp);
-       seq_printf(m, "Chipset power: %ld\n", chipset);
-       seq_printf(m, "GFX power: %ld\n", gfx);
-       seq_printf(m, "Total power: %ld\n", chipset + gfx);
+               temp = i915_mch_val(i915);
+               chipset = i915_chipset_val(i915);
+               gfx = i915_gfx_val(i915);
 
-       intel_runtime_pm_put(dev_priv);
+               seq_printf(m, "GMCH temp: %ld\n", temp);
+               seq_printf(m, "Chipset power: %ld\n", chipset);
+               seq_printf(m, "GFX power: %ld\n", gfx);
+               seq_printf(m, "Total power: %ld\n", chipset + gfx);
+       }
 
        return 0;
 }
@@ -1814,13 +1770,14 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
        struct intel_rps *rps = &dev_priv->gt_pm.rps;
        unsigned int max_gpu_freq, min_gpu_freq;
+       intel_wakeref_t wakeref;
        int gpu_freq, ia_freq;
        int ret;
 
        if (!HAS_LLC(dev_priv))
                return -ENODEV;
 
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
        ret = mutex_lock_interruptible(&dev_priv->pcu_lock);
        if (ret)
@@ -1853,7 +1810,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
        mutex_unlock(&dev_priv->pcu_lock);
 
 out:
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
        return ret;
 }
 
@@ -2026,15 +1983,16 @@ static const char *swizzle_string(unsigned swizzle)
 static int i915_swizzle_info(struct seq_file *m, void *data)
 {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
+       intel_wakeref_t wakeref;
 
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
        seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
                   swizzle_string(dev_priv->mm.bit_6_swizzle_x));
        seq_printf(m, "bit6 swizzle for Y-tiling = %s\n",
                   swizzle_string(dev_priv->mm.bit_6_swizzle_y));
 
-       if (IS_GEN3(dev_priv) || IS_GEN4(dev_priv)) {
+       if (IS_GEN_RANGE(dev_priv, 3, 4)) {
                seq_printf(m, "DDC = 0x%08x\n",
                           I915_READ(DCC));
                seq_printf(m, "DDC2 = 0x%08x\n",
@@ -2065,129 +2023,11 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
        if (dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES)
                seq_puts(m, "L-shaped memory detected\n");
 
-       intel_runtime_pm_put(dev_priv);
-
-       return 0;
-}
-
-static int per_file_ctx(int id, void *ptr, void *data)
-{
-       struct i915_gem_context *ctx = ptr;
-       struct seq_file *m = data;
-       struct i915_hw_ppgtt *ppgtt = ctx->ppgtt;
-
-       if (!ppgtt) {
-               seq_printf(m, "  no ppgtt for context %d\n",
-                          ctx->user_handle);
-               return 0;
-       }
-
-       if (i915_gem_context_is_default(ctx))
-               seq_puts(m, "  default context:\n");
-       else
-               seq_printf(m, "  context %d:\n", ctx->user_handle);
-       ppgtt->debug_dump(ppgtt, m);
+       intel_runtime_pm_put(dev_priv, wakeref);
 
        return 0;
 }
 
-static void gen8_ppgtt_info(struct seq_file *m,
-                           struct drm_i915_private *dev_priv)
-{
-       struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
-       struct intel_engine_cs *engine;
-       enum intel_engine_id id;
-       int i;
-
-       if (!ppgtt)
-               return;
-
-       for_each_engine(engine, dev_priv, id) {
-               seq_printf(m, "%s\n", engine->name);
-               for (i = 0; i < 4; i++) {
-                       u64 pdp = I915_READ(GEN8_RING_PDP_UDW(engine, i));
-                       pdp <<= 32;
-                       pdp |= I915_READ(GEN8_RING_PDP_LDW(engine, i));
-                       seq_printf(m, "\tPDP%d 0x%016llx\n", i, pdp);
-               }
-       }
-}
-
-static void gen6_ppgtt_info(struct seq_file *m,
-                           struct drm_i915_private *dev_priv)
-{
-       struct intel_engine_cs *engine;
-       enum intel_engine_id id;
-
-       if (IS_GEN6(dev_priv))
-               seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(GFX_MODE));
-
-       for_each_engine(engine, dev_priv, id) {
-               seq_printf(m, "%s\n", engine->name);
-               if (IS_GEN7(dev_priv))
-                       seq_printf(m, "GFX_MODE: 0x%08x\n",
-                                  I915_READ(RING_MODE_GEN7(engine)));
-               seq_printf(m, "PP_DIR_BASE: 0x%08x\n",
-                          I915_READ(RING_PP_DIR_BASE(engine)));
-               seq_printf(m, "PP_DIR_BASE_READ: 0x%08x\n",
-                          I915_READ(RING_PP_DIR_BASE_READ(engine)));
-               seq_printf(m, "PP_DIR_DCLV: 0x%08x\n",
-                          I915_READ(RING_PP_DIR_DCLV(engine)));
-       }
-       if (dev_priv->mm.aliasing_ppgtt) {
-               struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
-
-               seq_puts(m, "aliasing PPGTT:\n");
-               seq_printf(m, "pd gtt offset: 0x%08x\n", ppgtt->pd.base.ggtt_offset);
-
-               ppgtt->debug_dump(ppgtt, m);
-       }
-
-       seq_printf(m, "ECOCHK: 0x%08x\n", I915_READ(GAM_ECOCHK));
-}
-
-static int i915_ppgtt_info(struct seq_file *m, void *data)
-{
-       struct drm_i915_private *dev_priv = node_to_i915(m->private);
-       struct drm_device *dev = &dev_priv->drm;
-       struct drm_file *file;
-       int ret;
-
-       mutex_lock(&dev->filelist_mutex);
-       ret = mutex_lock_interruptible(&dev->struct_mutex);
-       if (ret)
-               goto out_unlock;
-
-       intel_runtime_pm_get(dev_priv);
-
-       if (INTEL_GEN(dev_priv) >= 8)
-               gen8_ppgtt_info(m, dev_priv);
-       else if (INTEL_GEN(dev_priv) >= 6)
-               gen6_ppgtt_info(m, dev_priv);
-
-       list_for_each_entry_reverse(file, &dev->filelist, lhead) {
-               struct drm_i915_file_private *file_priv = file->driver_priv;
-               struct task_struct *task;
-
-               task = get_pid_task(file->pid, PIDTYPE_PID);
-               if (!task) {
-                       ret = -ESRCH;
-                       goto out_rpm;
-               }
-               seq_printf(m, "\nproc: %s\n", task->comm);
-               put_task_struct(task);
-               idr_for_each(&file_priv->context_idr, per_file_ctx,
-                            (void *)(unsigned long)m);
-       }
-
-out_rpm:
-       intel_runtime_pm_put(dev_priv);
-       mutex_unlock(&dev->struct_mutex);
-out_unlock:
-       mutex_unlock(&dev->filelist_mutex);
-       return ret;
-}
-
 static int count_irq_waiters(struct drm_i915_private *i915)
 {
        struct intel_engine_cs *engine;
@@ -2220,9 +2060,10 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
        struct drm_device *dev = &dev_priv->drm;
        struct intel_rps *rps = &dev_priv->gt_pm.rps;
        u32 act_freq = rps->cur_freq;
+       intel_wakeref_t wakeref;
        struct drm_file *file;
 
-       if (intel_runtime_pm_get_if_in_use(dev_priv)) {
+       with_intel_runtime_pm_if_in_use(dev_priv, wakeref) {
                if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
                        mutex_lock(&dev_priv->pcu_lock);
                        act_freq = vlv_punit_read(dev_priv,
@@ -2233,7 +2074,6 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
                        act_freq = intel_get_cagf(dev_priv,
                                                  I915_READ(GEN6_RPSTAT1));
                }
-               intel_runtime_pm_put(dev_priv);
        }
 
        seq_printf(m, "RPS enabled? %d\n", rps->enabled);
@@ -2316,6 +2156,7 @@ static int i915_llc(struct seq_file *m, void *data)
 static int i915_huc_load_status_info(struct seq_file *m, void *data)
 {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
+       intel_wakeref_t wakeref;
        struct drm_printer p;
 
        if (!HAS_HUC(dev_priv))
@@ -2324,9 +2165,8 @@ static int i915_huc_load_status_info(struct seq_file *m, void *data)
        p = drm_seq_file_printer(m);
        intel_uc_fw_dump(&dev_priv->huc.fw, &p);
 
-       intel_runtime_pm_get(dev_priv);
-       seq_printf(m, "\nHuC status 0x%08x:\n", I915_READ(HUC_STATUS2));
-       intel_runtime_pm_put(dev_priv);
+       with_intel_runtime_pm(dev_priv, wakeref)
+               seq_printf(m, "\nHuC status 0x%08x:\n", I915_READ(HUC_STATUS2));
 
        return 0;
 }
@@ -2334,8 +2174,8 @@ static int i915_huc_load_status_info(struct seq_file *m, void *data)
 static int i915_guc_load_status_info(struct seq_file *m, void *data)
 {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
+       intel_wakeref_t wakeref;
        struct drm_printer p;
-       u32 tmp, i;
 
        if (!HAS_GUC(dev_priv))
                return -ENODEV;
@@ -2343,22 +2183,23 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data)
        p = drm_seq_file_printer(m);
        intel_uc_fw_dump(&dev_priv->guc.fw, &p);
 
-       intel_runtime_pm_get(dev_priv);
-
-       tmp = I915_READ(GUC_STATUS);
-
-       seq_printf(m, "\nGuC status 0x%08x:\n", tmp);
-       seq_printf(m, "\tBootrom status = 0x%x\n",
-               (tmp & GS_BOOTROM_MASK) >> GS_BOOTROM_SHIFT);
-       seq_printf(m, "\tuKernel status = 0x%x\n",
-               (tmp & GS_UKERNEL_MASK) >> GS_UKERNEL_SHIFT);
-       seq_printf(m, "\tMIA Core status = 0x%x\n",
-               (tmp & GS_MIA_MASK) >> GS_MIA_SHIFT);
-       seq_puts(m, "\nScratch registers:\n");
-       for (i = 0; i < 16; i++)
-               seq_printf(m, "\t%2d: \t0x%x\n", i, I915_READ(SOFT_SCRATCH(i)));
-
-       intel_runtime_pm_put(dev_priv);
+       with_intel_runtime_pm(dev_priv, wakeref) {
+               u32 tmp = I915_READ(GUC_STATUS);
+               u32 i;
+
+               seq_printf(m, "\nGuC status 0x%08x:\n", tmp);
+               seq_printf(m, "\tBootrom status = 0x%x\n",
+                          (tmp & GS_BOOTROM_MASK) >> GS_BOOTROM_SHIFT);
+               seq_printf(m, "\tuKernel status = 0x%x\n",
+                          (tmp & GS_UKERNEL_MASK) >> GS_UKERNEL_SHIFT);
+               seq_printf(m, "\tMIA Core status = 0x%x\n",
+                          (tmp & GS_MIA_MASK) >> GS_MIA_SHIFT);
+               seq_puts(m, "\nScratch registers:\n");
+               for (i = 0; i < 16; i++) {
+                       seq_printf(m, "\t%2d: \t0x%x\n",
+                                  i, I915_READ(SOFT_SCRATCH(i)));
+               }
+       }
 
        return 0;
 }
@@ -2410,7 +2251,7 @@ static void i915_guc_client_info(struct seq_file *m,
 {
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
-       uint64_t tot = 0;
+       u64 tot = 0;
 
        seq_printf(m, "\tPriority %d, GuC stage index: %u, PD offset 0x%x\n",
                client->priority, client->stage_id, client->proc_desc_offset);
@@ -2665,7 +2506,8 @@ DEFINE_SHOW_ATTRIBUTE(i915_psr_sink_status);
 static void
 psr_source_status(struct drm_i915_private *dev_priv, struct seq_file *m)
 {
-       u32 val, psr_status;
+       u32 val, status_val;
+       const char *status = "unknown";
 
        if (dev_priv->psr.psr2_enabled) {
                static const char * const live_status[] = {
@@ -2681,14 +2523,11 @@ psr_source_status(struct drm_i915_private *dev_priv, struct seq_file *m)
                        "BUF_ON",
                        "TG_ON"
                };
-               psr_status = I915_READ(EDP_PSR2_STATUS);
-               val = (psr_status & EDP_PSR2_STATUS_STATE_MASK) >>
-                       EDP_PSR2_STATUS_STATE_SHIFT;
-               if (val < ARRAY_SIZE(live_status)) {
-                       seq_printf(m, "Source PSR status: 0x%x [%s]\n",
-                                  psr_status, live_status[val]);
-                       return;
-               }
+               val = I915_READ(EDP_PSR2_STATUS);
+               status_val = (val & EDP_PSR2_STATUS_STATE_MASK) >>
+                             EDP_PSR2_STATUS_STATE_SHIFT;
+               if (status_val < ARRAY_SIZE(live_status))
+                       status = live_status[status_val];
        } else {
                static const char * const live_status[] = {
                        "IDLE",
@@ -2700,74 +2539,102 @@ psr_source_status(struct drm_i915_private *dev_priv, struct seq_file *m)
                        "SRDOFFACK",
                        "SRDENT_ON",
                };
-               psr_status = I915_READ(EDP_PSR_STATUS);
-               val = (psr_status & EDP_PSR_STATUS_STATE_MASK) >>
-                       EDP_PSR_STATUS_STATE_SHIFT;
-               if (val < ARRAY_SIZE(live_status)) {
-                       seq_printf(m, "Source PSR status: 0x%x [%s]\n",
-                                  psr_status, live_status[val]);
-                       return;
-               }
+               val = I915_READ(EDP_PSR_STATUS);
+               status_val = (val & EDP_PSR_STATUS_STATE_MASK) >>
+                             EDP_PSR_STATUS_STATE_SHIFT;
+               if (status_val < ARRAY_SIZE(live_status))
+                       status = live_status[status_val];
        }
 
-       seq_printf(m, "Source PSR status: 0x%x [%s]\n", psr_status, "unknown");
+       seq_printf(m, "Source PSR status: %s [0x%08x]\n", status, val);
 }
 
 static int i915_edp_psr_status(struct seq_file *m, void *data)
 {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
-       u32 psrperf = 0;
-       bool enabled = false;
-       bool sink_support;
+       struct i915_psr *psr = &dev_priv->psr;
+       intel_wakeref_t wakeref;
+       const char *status;
+       bool enabled;
+       u32 val;
 
        if (!HAS_PSR(dev_priv))
                return -ENODEV;
 
-       sink_support = dev_priv->psr.sink_support;
-       seq_printf(m, "Sink_Support: %s\n", yesno(sink_support));
-       if (!sink_support)
-               return 0;
+       seq_printf(m, "Sink support: %s", yesno(psr->sink_support));
+       if (psr->dp)
+               seq_printf(m, " [0x%02x]", psr->dp->psr_dpcd[0]);
+       seq_puts(m, "\n");
 
-       intel_runtime_pm_get(dev_priv);
+       if (!psr->sink_support)
+               return 0;
 
-       mutex_lock(&dev_priv->psr.lock);
-       seq_printf(m, "PSR mode: %s\n",
-                  dev_priv->psr.psr2_enabled ? "PSR2" : "PSR1");
-       seq_printf(m, "Enabled: %s\n", yesno(dev_priv->psr.enabled));
-       seq_printf(m, "Busy frontbuffer bits: 0x%03x\n",
-                  dev_priv->psr.busy_frontbuffer_bits);
+       wakeref = intel_runtime_pm_get(dev_priv);
+       mutex_lock(&psr->lock);
 
-       if (dev_priv->psr.psr2_enabled)
-               enabled = I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE;
+       if (psr->enabled)
+               status = psr->psr2_enabled ? "PSR2 enabled" : "PSR1 enabled";
        else
-               enabled = I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE;
+               status = "disabled";
+       seq_printf(m, "PSR mode: %s\n", status);
 
-       seq_printf(m, "Main link in standby mode: %s\n",
-                  yesno(dev_priv->psr.link_standby));
+       if (!psr->enabled)
+               goto unlock;
 
-       seq_printf(m, "HW Enabled & Active bit: %s\n", yesno(enabled));
+       if (psr->psr2_enabled) {
+               val = I915_READ(EDP_PSR2_CTL);
+               enabled = val & EDP_PSR2_ENABLE;
+       } else {
+               val = I915_READ(EDP_PSR_CTL);
+               enabled = val & EDP_PSR_ENABLE;
+       }
+       seq_printf(m, "Source PSR ctl: %s [0x%08x]\n",
+                  enableddisabled(enabled), val);
+       psr_source_status(dev_priv, m);
+       seq_printf(m, "Busy frontbuffer bits: 0x%08x\n",
+                  psr->busy_frontbuffer_bits);
 
        /*
         * SKL+ Perf counter is reset to 0 everytime DC state is entered
         */
        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
-               psrperf = I915_READ(EDP_PSR_PERF_CNT) &
-                       EDP_PSR_PERF_CNT_MASK;
+               val = I915_READ(EDP_PSR_PERF_CNT) & EDP_PSR_PERF_CNT_MASK;
+               seq_printf(m, "Performance counter: %u\n", val);
+       }
 
-               seq_printf(m, "Performance_Counter: %u\n", psrperf);
+       if (psr->debug & I915_PSR_DEBUG_IRQ) {
+               seq_printf(m, "Last attempted entry at: %lld\n",
+                          psr->last_entry_attempt);
+               seq_printf(m, "Last exit at: %lld\n", psr->last_exit);
        }
 
-       psr_source_status(dev_priv, m);
-       mutex_unlock(&dev_priv->psr.lock);
+       if (psr->psr2_enabled) {
+               u32 su_frames_val[3];
+               int frame;
 
-       if (READ_ONCE(dev_priv->psr.debug) & I915_PSR_DEBUG_IRQ) {
-               seq_printf(m, "Last attempted entry at: %lld\n",
-                          dev_priv->psr.last_entry_attempt);
-               seq_printf(m, "Last exit at: %lld\n",
-                          dev_priv->psr.last_exit);
+               /*
+                * Reading all 3 registers before hand to minimize crossing a
+                * frame boundary between register reads
+                */
+               for (frame = 0; frame < PSR2_SU_STATUS_FRAMES; frame += 3)
+                       su_frames_val[frame / 3] = I915_READ(PSR2_SU_STATUS(frame));
+
+               seq_puts(m, "Frame:\tPSR2 SU blocks:\n");
+
+               for (frame = 0; frame < PSR2_SU_STATUS_FRAMES; frame++) {
+                       u32 su_blocks;
+
+                       su_blocks = su_frames_val[frame / 3] &
+                                   PSR2_SU_STATUS_MASK(frame);
+                       su_blocks = su_blocks >> PSR2_SU_STATUS_SHIFT(frame);
+                       seq_printf(m, "%d\t%d\n", frame, su_blocks);
+               }
        }
 
-       intel_runtime_pm_put(dev_priv);
+unlock:
+       mutex_unlock(&psr->lock);
+       intel_runtime_pm_put(dev_priv, wakeref);
+
        return 0;
 }
 
@@ -2776,6 +2643,7 @@ i915_edp_psr_debug_set(void *data, u64 val)
 {
        struct drm_i915_private *dev_priv = data;
        struct drm_modeset_acquire_ctx ctx;
+       intel_wakeref_t wakeref;
        int ret;
 
        if (!CAN_PSR(dev_priv))
@@ -2783,7 +2651,7 @@ i915_edp_psr_debug_set(void *data, u64 val)
 
        DRM_DEBUG_KMS("Setting PSR debug to %llx\n", val);
 
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
        drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
 
@@ -2798,7 +2666,7 @@ retry:
        drm_modeset_drop_locks(&ctx);
        drm_modeset_acquire_fini(&ctx);
 
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
 
        return ret;
 }
@@ -2823,24 +2691,20 @@ static int i915_energy_uJ(struct seq_file *m, void *data)
 {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
        unsigned long long power;
+       intel_wakeref_t wakeref;
        u32 units;
 
        if (INTEL_GEN(dev_priv) < 6)
                return -ENODEV;
 
-       intel_runtime_pm_get(dev_priv);
-
-       if (rdmsrl_safe(MSR_RAPL_POWER_UNIT, &power)) {
-               intel_runtime_pm_put(dev_priv);
+       if (rdmsrl_safe(MSR_RAPL_POWER_UNIT, &power))
                return -ENODEV;
-       }
 
        units = (power & 0x1f00) >> 8;
-       power = I915_READ(MCH_SECP_NRG_STTS);
-       power = (1000000 * power) >> units; /* convert to uJ */
-
-       intel_runtime_pm_put(dev_priv);
+       with_intel_runtime_pm(dev_priv, wakeref)
+               power = I915_READ(MCH_SECP_NRG_STTS);
 
+       power = (1000000 * power) >> units; /* convert to uJ */
        seq_printf(m, "%llu", power);
 
        return 0;
@@ -2854,6 +2718,9 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused)
        if (!HAS_RUNTIME_PM(dev_priv))
                seq_puts(m, "Runtime power management not supported\n");
 
+       seq_printf(m, "Runtime power status: %s\n",
+                  enableddisabled(!dev_priv->power_domains.wakeref));
+
        seq_printf(m, "GPU idle: %s (epoch %u)\n",
                   yesno(!dev_priv->gt.awake), dev_priv->gt.epoch);
        seq_printf(m, "IRQs disabled: %s\n",
@@ -2868,6 +2735,12 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused)
                   pci_power_name(pdev->current_state),
                   pdev->current_state);
 
+       if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)) {
+               struct drm_printer p = drm_seq_file_printer(m);
+
+               print_intel_runtime_pm_wakeref(dev_priv, &p);
+       }
+
        return 0;
 }
 
@@ -2902,6 +2775,7 @@ static int i915_power_domain_info(struct seq_file *m, void *unused)
 static int i915_dmc_info(struct seq_file *m, void *unused)
 {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
+       intel_wakeref_t wakeref;
        struct intel_csr *csr;
 
        if (!HAS_CSR(dev_priv))
@@ -2909,7 +2783,7 @@ static int i915_dmc_info(struct seq_file *m, void *unused)
 
        csr = &dev_priv->csr;
 
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
        seq_printf(m, "fw loaded: %s\n", yesno(csr->dmc_payload != NULL));
        seq_printf(m, "path: %s\n", csr->fw_path);
@@ -2935,7 +2809,7 @@ out:
        seq_printf(m, "ssp base: 0x%08x\n", I915_READ(CSR_SSP_BASE));
        seq_printf(m, "htp: 0x%08x\n", I915_READ(CSR_HTP_SKL));
 
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
 
        return 0;
 }
@@ -2948,14 +2822,7 @@ static void intel_seq_print_mode(struct seq_file *m, int tabs,
        for (i = 0; i < tabs; i++)
                seq_putc(m, '\t');
 
-       seq_printf(m, "id %d:\"%s\" freq %d clock %d hdisp %d hss %d hse %d htot %d vdisp %d vss %d vse %d vtot %d type 0x%x flags 0x%x\n",
-                  mode->base.id, mode->name,
-                  mode->vrefresh, mode->clock,
-                  mode->hdisplay, mode->hsync_start,
-                  mode->hsync_end, mode->htotal,
-                  mode->vdisplay, mode->vsync_start,
-                  mode->vsync_end, mode->vtotal,
-                  mode->type, mode->flags);
+       seq_printf(m, DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
 }
 
 static void intel_encoder_info(struct seq_file *m,
@@ -3127,14 +2994,13 @@ static const char *plane_type(enum drm_plane_type type)
        return "unknown";
 }
 
-static const char *plane_rotation(unsigned int rotation)
+static void plane_rotation(char *buf, size_t bufsize, unsigned int rotation)
 {
-       static char buf[48];
        /*
         * According to doc only one DRM_MODE_ROTATE_ is allowed but this
         * will print them all to visualize if the values are misused
         */
-       snprintf(buf, sizeof(buf),
+       snprintf(buf, bufsize,
                 "%s%s%s%s%s%s(0x%08x)",
                 (rotation & DRM_MODE_ROTATE_0) ? "0 " : "",
                 (rotation & DRM_MODE_ROTATE_90) ? "90 " : "",
@@ -3143,8 +3009,6 @@ static const char *plane_rotation(unsigned int rotation)
                 (rotation & DRM_MODE_REFLECT_X) ? "FLIPX " : "",
                 (rotation & DRM_MODE_REFLECT_Y) ? "FLIPY " : "",
                 rotation);
-
-       return buf;
 }
 
 static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc)
@@ -3157,6 +3021,7 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc)
                struct drm_plane_state *state;
                struct drm_plane *plane = &intel_plane->base;
                struct drm_format_name_buf format_name;
+               char rot_str[48];
 
                if (!plane->state) {
                        seq_puts(m, "plane->state is NULL!\n");
@@ -3172,6 +3037,8 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc)
                        sprintf(format_name.str, "N/A");
                }
 
+               plane_rotation(rot_str, sizeof(rot_str), state->rotation);
+
                seq_printf(m, "\t--Plane id %d: type=%s, crtc_pos=%4dx%4d, crtc_size=%4dx%4d, src_pos=%d.%04ux%d.%04u, src_size=%d.%04ux%d.%04u, format=%s, rotation=%s\n",
                           plane->base.id,
                           plane_type(intel_plane->base.type),
@@ -3186,7 +3053,7 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc)
                           (state->src_h >> 16),
                           ((state->src_h & 0xffff) * 15625) >> 10,
                           format_name.str,
-                          plane_rotation(state->rotation));
+                          rot_str);
        }
 }
 
@@ -3225,8 +3092,10 @@ static int i915_display_info(struct seq_file *m, void *unused)
        struct intel_crtc *crtc;
        struct drm_connector *connector;
        struct drm_connector_list_iter conn_iter;
+       intel_wakeref_t wakeref;
+
+       wakeref = intel_runtime_pm_get(dev_priv);
 
-       intel_runtime_pm_get(dev_priv);
        seq_printf(m, "CRTC info\n");
        seq_printf(m, "---------\n");
        for_each_intel_crtc(dev, crtc) {
@@ -3274,7 +3143,7 @@ static int i915_display_info(struct seq_file *m, void *unused)
        drm_connector_list_iter_end(&conn_iter);
        mutex_unlock(&dev->mode_config.mutex);
 
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
 
        return 0;
 }
@@ -3283,23 +3152,24 @@ static int i915_engine_info(struct seq_file *m, void *unused)
 {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
        struct intel_engine_cs *engine;
+       intel_wakeref_t wakeref;
        enum intel_engine_id id;
        struct drm_printer p;
 
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
        seq_printf(m, "GT awake? %s (epoch %u)\n",
                   yesno(dev_priv->gt.awake), dev_priv->gt.epoch);
        seq_printf(m, "Global active requests: %d\n",
                   dev_priv->gt.active_requests);
        seq_printf(m, "CS timestamp frequency: %u kHz\n",
-                  dev_priv->info.cs_timestamp_frequency_khz);
+                  RUNTIME_INFO(dev_priv)->cs_timestamp_frequency_khz);
 
        p = drm_seq_file_printer(m);
        for_each_engine(engine, dev_priv, id)
                intel_engine_dump(engine, &p, "%s\n", engine->name);
 
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
 
        return 0;
 }
@@ -3309,7 +3179,7 @@ static int i915_rcs_topology(struct seq_file *m, void *unused)
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
        struct drm_printer p = drm_seq_file_printer(m);
 
-       intel_device_info_dump_topology(&INTEL_INFO(dev_priv)->sseu, &p);
+       intel_device_info_dump_topology(&RUNTIME_INFO(dev_priv)->sseu, &p);
 
        return 0;
 }
@@ -3412,20 +3282,21 @@ static ssize_t i915_ipc_status_write(struct file *file, const char __user *ubuf,
 {
        struct seq_file *m = file->private_data;
        struct drm_i915_private *dev_priv = m->private;
-       int ret;
+       intel_wakeref_t wakeref;
        bool enable;
+       int ret;
 
        ret = kstrtobool_from_user(ubuf, len, &enable);
        if (ret < 0)
                return ret;
 
-       intel_runtime_pm_get(dev_priv);
-       if (!dev_priv->ipc_enabled && enable)
-               DRM_INFO("Enabling IPC: WM will be proper only after next commit\n");
-       dev_priv->wm.distrust_bios_wm = true;
-       dev_priv->ipc_enabled = enable;
-       intel_enable_ipc(dev_priv);
-       intel_runtime_pm_put(dev_priv);
+       with_intel_runtime_pm(dev_priv, wakeref) {
+               if (!dev_priv->ipc_enabled && enable)
+                       DRM_INFO("Enabling IPC: WM will be proper only after next commit\n");
+               dev_priv->wm.distrust_bios_wm = true;
+               dev_priv->ipc_enabled = enable;
+               intel_enable_ipc(dev_priv);
+       }
 
        return len;
 }
@@ -3793,7 +3664,7 @@ static int i915_displayport_test_type_show(struct seq_file *m, void *data)
 }
 DEFINE_SHOW_ATTRIBUTE(i915_displayport_test_type);
 
-static void wm_latency_show(struct seq_file *m, const uint16_t wm[8])
+static void wm_latency_show(struct seq_file *m, const u16 wm[8])
 {
        struct drm_i915_private *dev_priv = m->private;
        struct drm_device *dev = &dev_priv->drm;
@@ -3836,7 +3707,7 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[8])
 static int pri_wm_latency_show(struct seq_file *m, void *data)
 {
        struct drm_i915_private *dev_priv = m->private;
-       const uint16_t *latencies;
+       const u16 *latencies;
 
        if (INTEL_GEN(dev_priv) >= 9)
                latencies = dev_priv->wm.skl_latency;
@@ -3851,7 +3722,7 @@ static int pri_wm_latency_show(struct seq_file *m, void *data)
 static int spr_wm_latency_show(struct seq_file *m, void *data)
 {
        struct drm_i915_private *dev_priv = m->private;
-       const uint16_t *latencies;
+       const u16 *latencies;
 
        if (INTEL_GEN(dev_priv) >= 9)
                latencies = dev_priv->wm.skl_latency;
@@ -3866,7 +3737,7 @@ static int spr_wm_latency_show(struct seq_file *m, void *data)
 static int cur_wm_latency_show(struct seq_file *m, void *data)
 {
        struct drm_i915_private *dev_priv = m->private;
-       const uint16_t *latencies;
+       const u16 *latencies;
 
        if (INTEL_GEN(dev_priv) >= 9)
                latencies = dev_priv->wm.skl_latency;
@@ -3909,12 +3780,12 @@ static int cur_wm_latency_open(struct inode *inode, struct file *file)
 }
 
 static ssize_t wm_latency_write(struct file *file, const char __user *ubuf,
-                               size_t len, loff_t *offp, uint16_t wm[8])
+                               size_t len, loff_t *offp, u16 wm[8])
 {
        struct seq_file *m = file->private_data;
        struct drm_i915_private *dev_priv = m->private;
        struct drm_device *dev = &dev_priv->drm;
-       uint16_t new[8] = { 0 };
+       u16 new[8] = { 0 };
        int num_levels;
        int level;
        int ret;
@@ -3959,7 +3830,7 @@ static ssize_t pri_wm_latency_write(struct file *file, const char __user *ubuf,
 {
        struct seq_file *m = file->private_data;
        struct drm_i915_private *dev_priv = m->private;
-       uint16_t *latencies;
+       u16 *latencies;
 
        if (INTEL_GEN(dev_priv) >= 9)
                latencies = dev_priv->wm.skl_latency;
@@ -3974,7 +3845,7 @@ static ssize_t spr_wm_latency_write(struct file *file, const char __user *ubuf,
 {
        struct seq_file *m = file->private_data;
        struct drm_i915_private *dev_priv = m->private;
-       uint16_t *latencies;
+       u16 *latencies;
 
        if (INTEL_GEN(dev_priv) >= 9)
                latencies = dev_priv->wm.skl_latency;
@@ -3989,7 +3860,7 @@ static ssize_t cur_wm_latency_write(struct file *file, const char __user *ubuf,
 {
        struct seq_file *m = file->private_data;
        struct drm_i915_private *dev_priv = m->private;
-       uint16_t *latencies;
+       u16 *latencies;
 
        if (INTEL_GEN(dev_priv) >= 9)
                latencies = dev_priv->wm.skl_latency;
@@ -4191,11 +4062,12 @@ static int
 i915_drop_caches_set(void *data, u64 val)
 {
        struct drm_i915_private *i915 = data;
+       intel_wakeref_t wakeref;
        int ret = 0;
 
        DRM_DEBUG("Dropping caches: 0x%08llx [0x%08llx]\n",
                  val, val & DROP_ALL);
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
        if (val & DROP_RESET_ACTIVE && !intel_engines_are_idle(i915))
                i915_gem_set_wedged(i915);
@@ -4213,9 +4085,6 @@ i915_drop_caches_set(void *data, u64 val)
                                                     I915_WAIT_LOCKED,
                                                     MAX_SCHEDULE_TIMEOUT);
 
-               if (ret == 0 && val & DROP_RESET_SEQNO)
-                       ret = i915_gem_set_global_seqno(&i915->drm, 1);
-
                if (val & DROP_RETIRE)
                        i915_retire_requests(i915);
 
@@ -4253,7 +4122,7 @@ i915_drop_caches_set(void *data, u64 val)
                i915_gem_drain_freed_objects(i915);
 
 out:
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
 
        return ret;
 }
@@ -4266,16 +4135,14 @@ static int
 i915_cache_sharing_get(void *data, u64 *val)
 {
        struct drm_i915_private *dev_priv = data;
-       u32 snpcr;
+       intel_wakeref_t wakeref;
+       u32 snpcr = 0;
 
-       if (!(IS_GEN6(dev_priv) || IS_GEN7(dev_priv)))
+       if (!(IS_GEN_RANGE(dev_priv, 6, 7)))
                return -ENODEV;
 
-       intel_runtime_pm_get(dev_priv);
-
-       snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
-
-       intel_runtime_pm_put(dev_priv);
+       with_intel_runtime_pm(dev_priv, wakeref)
+               snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
 
        *val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
 
@@ -4286,24 +4153,25 @@ static int
 i915_cache_sharing_set(void *data, u64 val)
 {
        struct drm_i915_private *dev_priv = data;
-       u32 snpcr;
+       intel_wakeref_t wakeref;
 
-       if (!(IS_GEN6(dev_priv) || IS_GEN7(dev_priv)))
+       if (!(IS_GEN_RANGE(dev_priv, 6, 7)))
                return -ENODEV;
 
        if (val > 3)
                return -EINVAL;
 
-       intel_runtime_pm_get(dev_priv);
        DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val);
+       with_intel_runtime_pm(dev_priv, wakeref) {
+               u32 snpcr;
+
+               /* Update the cache sharing policy here as well */
+               snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
+               snpcr &= ~GEN6_MBC_SNPCR_MASK;
+               snpcr |= val << GEN6_MBC_SNPCR_SHIFT;
+               I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
+       }
 
-       /* Update the cache sharing policy here as well */
-       snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
-       snpcr &= ~GEN6_MBC_SNPCR_MASK;
-       snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
-       I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
-
-       intel_runtime_pm_put(dev_priv);
        return 0;
 }
 
@@ -4348,7 +4216,7 @@ static void gen10_sseu_device_status(struct drm_i915_private *dev_priv,
                                     struct sseu_dev_info *sseu)
 {
 #define SS_MAX 6
-       const struct intel_device_info *info = INTEL_INFO(dev_priv);
+       const struct intel_runtime_info *info = RUNTIME_INFO(dev_priv);
        u32 s_reg[SS_MAX], eu_reg[2 * SS_MAX], eu_mask[2];
        int s, ss;
 
@@ -4404,7 +4272,7 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv,
                                    struct sseu_dev_info *sseu)
 {
 #define SS_MAX 3
-       const struct intel_device_info *info = INTEL_INFO(dev_priv);
+       const struct intel_runtime_info *info = RUNTIME_INFO(dev_priv);
        u32 s_reg[SS_MAX], eu_reg[2 * SS_MAX], eu_mask[2];
        int s, ss;
 
@@ -4432,7 +4300,7 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv,
 
                if (IS_GEN9_BC(dev_priv))
                        sseu->subslice_mask[s] =
-                               INTEL_INFO(dev_priv)->sseu.subslice_mask[s];
+                               RUNTIME_INFO(dev_priv)->sseu.subslice_mask[s];
 
                for (ss = 0; ss < info->sseu.max_subslices; ss++) {
                        unsigned int eu_cnt;
@@ -4466,10 +4334,10 @@ static void broadwell_sseu_device_status(struct drm_i915_private *dev_priv,
 
        if (sseu->slice_mask) {
                sseu->eu_per_subslice =
-                               INTEL_INFO(dev_priv)->sseu.eu_per_subslice;
+                       RUNTIME_INFO(dev_priv)->sseu.eu_per_subslice;
                for (s = 0; s < fls(sseu->slice_mask); s++) {
                        sseu->subslice_mask[s] =
-                               INTEL_INFO(dev_priv)->sseu.subslice_mask[s];
+                               RUNTIME_INFO(dev_priv)->sseu.subslice_mask[s];
                }
                sseu->eu_total = sseu->eu_per_subslice *
                                 sseu_subslice_total(sseu);
@@ -4477,7 +4345,7 @@ static void broadwell_sseu_device_status(struct drm_i915_private *dev_priv,
                /* subtract fused off EU(s) from enabled slice(s) */
                for (s = 0; s < fls(sseu->slice_mask); s++) {
                        u8 subslice_7eu =
-                               INTEL_INFO(dev_priv)->sseu.subslice_7eu[s];
+                               RUNTIME_INFO(dev_priv)->sseu.subslice_7eu[s];
 
                        sseu->eu_total -= hweight8(subslice_7eu);
                }
@@ -4525,34 +4393,32 @@ static int i915_sseu_status(struct seq_file *m, void *unused)
 {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
        struct sseu_dev_info sseu;
+       intel_wakeref_t wakeref;
 
        if (INTEL_GEN(dev_priv) < 8)
                return -ENODEV;
 
        seq_puts(m, "SSEU Device Info\n");
-       i915_print_sseu_info(m, true, &INTEL_INFO(dev_priv)->sseu);
+       i915_print_sseu_info(m, true, &RUNTIME_INFO(dev_priv)->sseu);
 
        seq_puts(m, "SSEU Device Status\n");
        memset(&sseu, 0, sizeof(sseu));
-       sseu.max_slices = INTEL_INFO(dev_priv)->sseu.max_slices;
-       sseu.max_subslices = INTEL_INFO(dev_priv)->sseu.max_subslices;
+       sseu.max_slices = RUNTIME_INFO(dev_priv)->sseu.max_slices;
+       sseu.max_subslices = RUNTIME_INFO(dev_priv)->sseu.max_subslices;
        sseu.max_eus_per_subslice =
-               INTEL_INFO(dev_priv)->sseu.max_eus_per_subslice;
-
-       intel_runtime_pm_get(dev_priv);
-
-       if (IS_CHERRYVIEW(dev_priv)) {
-               cherryview_sseu_device_status(dev_priv, &sseu);
-       } else if (IS_BROADWELL(dev_priv)) {
-               broadwell_sseu_device_status(dev_priv, &sseu);
-       } else if (IS_GEN9(dev_priv)) {
-               gen9_sseu_device_status(dev_priv, &sseu);
-       } else if (INTEL_GEN(dev_priv) >= 10) {
-               gen10_sseu_device_status(dev_priv, &sseu);
+               RUNTIME_INFO(dev_priv)->sseu.max_eus_per_subslice;
+
+       with_intel_runtime_pm(dev_priv, wakeref) {
+               if (IS_CHERRYVIEW(dev_priv))
+                       cherryview_sseu_device_status(dev_priv, &sseu);
+               else if (IS_BROADWELL(dev_priv))
+                       broadwell_sseu_device_status(dev_priv, &sseu);
+               else if (IS_GEN(dev_priv, 9))
+                       gen9_sseu_device_status(dev_priv, &sseu);
+               else if (INTEL_GEN(dev_priv) >= 10)
+                       gen10_sseu_device_status(dev_priv, &sseu);
        }
 
-       intel_runtime_pm_put(dev_priv);
-
        i915_print_sseu_info(m, false, &sseu);
 
        return 0;
@@ -4565,7 +4431,7 @@ static int i915_forcewake_open(struct inode *inode, struct file *file)
        if (INTEL_GEN(i915) < 6)
                return 0;
 
-       intel_runtime_pm_get(i915);
+       file->private_data = (void *)(uintptr_t)intel_runtime_pm_get(i915);
        intel_uncore_forcewake_user_get(i915);
 
        return 0;
@@ -4579,7 +4445,8 @@ static int i915_forcewake_release(struct inode *inode, struct file *file)
                return 0;
 
        intel_uncore_forcewake_user_put(i915);
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915,
+                            (intel_wakeref_t)(uintptr_t)file->private_data);
 
        return 0;
 }
@@ -4906,7 +4773,6 @@ static const struct drm_info_list i915_debugfs_list[] = {
        {"i915_context_status", i915_context_status, 0},
        {"i915_forcewake_domains", i915_forcewake_domains, 0},
        {"i915_swizzle_info", i915_swizzle_info, 0},
-       {"i915_ppgtt_info", i915_ppgtt_info, 0},
        {"i915_llc", i915_llc, 0},
        {"i915_edp_psr_status", i915_edp_psr_status, 0},
        {"i915_energy_uJ", i915_energy_uJ, 0},
@@ -4941,7 +4807,6 @@ static const struct i915_debugfs_files {
        {"i915_gpu_info", &i915_gpu_info_fops},
 #endif
        {"i915_fifo_underrun_reset", &i915_fifo_underrun_reset_ops},
-       {"i915_next_seqno", &i915_next_seqno_fops},
        {"i915_pri_wm_latency", &i915_pri_wm_latency_fops},
        {"i915_spr_wm_latency", &i915_spr_wm_latency_fops},
        {"i915_cur_wm_latency", &i915_cur_wm_latency_fops},
@@ -5014,7 +4879,7 @@ static int i915_dpcd_show(struct seq_file *m, void *data)
        struct drm_connector *connector = m->private;
        struct intel_dp *intel_dp =
                enc_to_intel_dp(&intel_attached_encoder(connector)->base);
-       uint8_t buf[16];
+       u8 buf[16];
        ssize_t err;
        int i;
 
@@ -5088,6 +4953,105 @@ static int i915_hdcp_sink_capability_show(struct seq_file *m, void *data)
 }
 DEFINE_SHOW_ATTRIBUTE(i915_hdcp_sink_capability);
 
+static int i915_dsc_fec_support_show(struct seq_file *m, void *data)
+{
+       struct drm_connector *connector = m->private;
+       struct drm_device *dev = connector->dev;
+       struct drm_crtc *crtc;
+       struct intel_dp *intel_dp;
+       struct drm_modeset_acquire_ctx ctx;
+       struct intel_crtc_state *crtc_state = NULL;
+       int ret = 0;
+       bool try_again = false;
+
+       drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
+
+       do {
+               try_again = false;
+               ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
+                                      &ctx);
+               if (ret) {
+                       ret = -EINTR;
+                       break;
+               }
+               crtc = connector->state->crtc;
+               if (connector->status != connector_status_connected || !crtc) {
+                       ret = -ENODEV;
+                       break;
+               }
+               ret = drm_modeset_lock(&crtc->mutex, &ctx);
+               if (ret == -EDEADLK) {
+                       ret = drm_modeset_backoff(&ctx);
+                       if (!ret) {
+                               try_again = true;
+                               continue;
+                       }
+                       break;
+               } else if (ret) {
+                       break;
+               }
+               intel_dp = enc_to_intel_dp(&intel_attached_encoder(connector)->base);
+               crtc_state = to_intel_crtc_state(crtc->state);
+               seq_printf(m, "DSC_Enabled: %s\n",
+                          yesno(crtc_state->dsc_params.compression_enable));
+               seq_printf(m, "DSC_Sink_Support: %s\n",
+                          yesno(drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)));
+               if (!intel_dp_is_edp(intel_dp))
+                       seq_printf(m, "FEC_Sink_Support: %s\n",
+                                  yesno(drm_dp_sink_supports_fec(intel_dp->fec_capable)));
+       } while (try_again);
+
+       drm_modeset_drop_locks(&ctx);
+       drm_modeset_acquire_fini(&ctx);
+
+       return ret;
+}
+
+static ssize_t i915_dsc_fec_support_write(struct file *file,
+                                         const char __user *ubuf,
+                                         size_t len, loff_t *offp)
+{
+       bool dsc_enable = false;
+       int ret;
+       struct drm_connector *connector =
+               ((struct seq_file *)file->private_data)->private;
+       struct intel_encoder *encoder = intel_attached_encoder(connector);
+       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+
+       if (len == 0)
+               return 0;
+
+       DRM_DEBUG_DRIVER("Copied %zu bytes from user to force DSC\n",
+                        len);
+
+       ret = kstrtobool_from_user(ubuf, len, &dsc_enable);
+       if (ret < 0)
+               return ret;
+
+       DRM_DEBUG_DRIVER("Got %s for DSC Enable\n",
+                        (dsc_enable) ? "true" : "false");
+       intel_dp->force_dsc_en = dsc_enable;
+
+       *offp += len;
+       return len;
+}
+
+static int i915_dsc_fec_support_open(struct inode *inode,
+                                    struct file *file)
+{
+       return single_open(file, i915_dsc_fec_support_show,
+                          inode->i_private);
+}
+
+static const struct file_operations i915_dsc_fec_support_fops = {
+       .owner = THIS_MODULE,
+       .open = i915_dsc_fec_support_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .write = i915_dsc_fec_support_write
+};
+
 /**
  * i915_debugfs_connector_add - add i915 specific connector debugfs files
  * @connector: pointer to a registered drm_connector
@@ -5100,6 +5064,7 @@ DEFINE_SHOW_ATTRIBUTE(i915_hdcp_sink_capability);
 int i915_debugfs_connector_add(struct drm_connector *connector)
 {
        struct dentry *root = connector->debugfs_entry;
+       struct drm_i915_private *dev_priv = to_i915(connector->dev);
 
        /* The connector must have been registered beforehands. */
        if (!root)
@@ -5124,5 +5089,11 @@ int i915_debugfs_connector_add(struct drm_connector *connector)
                                    connector, &i915_hdcp_sink_capability_fops);
        }
 
+       if (INTEL_GEN(dev_priv) >= 10 &&
+           (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
+            connector->connector_type == DRM_MODE_CONNECTOR_eDP))
+               debugfs_create_file("i915_dsc_fec_support", S_IRUGO, root,
+                                   connector, &i915_dsc_fec_support_fops);
+
        return 0;
 }
index b310a897a4adab444349252503fba2e92134814f..f462a4d28af4a03350fecb275aebe915f5a6d131 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/vt.h>
 #include <acpi/video.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/i915_drm.h>
@@ -49,6 +48,7 @@
 #include "i915_drv.h"
 #include "i915_trace.h"
 #include "i915_pmu.h"
+#include "i915_reset.h"
 #include "i915_query.h"
 #include "i915_vgpu.h"
 #include "intel_drv.h"
@@ -132,15 +132,15 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id)
        switch (id) {
        case INTEL_PCH_IBX_DEVICE_ID_TYPE:
                DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
-               WARN_ON(!IS_GEN5(dev_priv));
+               WARN_ON(!IS_GEN(dev_priv, 5));
                return PCH_IBX;
        case INTEL_PCH_CPT_DEVICE_ID_TYPE:
                DRM_DEBUG_KMS("Found CougarPoint PCH\n");
-               WARN_ON(!IS_GEN6(dev_priv) && !IS_IVYBRIDGE(dev_priv));
+               WARN_ON(!IS_GEN(dev_priv, 6) && !IS_IVYBRIDGE(dev_priv));
                return PCH_CPT;
        case INTEL_PCH_PPT_DEVICE_ID_TYPE:
                DRM_DEBUG_KMS("Found PantherPoint PCH\n");
-               WARN_ON(!IS_GEN6(dev_priv) && !IS_IVYBRIDGE(dev_priv));
+               WARN_ON(!IS_GEN(dev_priv, 6) && !IS_IVYBRIDGE(dev_priv));
                /* PantherPoint is CPT compatible */
                return PCH_CPT;
        case INTEL_PCH_LPT_DEVICE_ID_TYPE:
@@ -217,9 +217,9 @@ intel_virt_detect_pch(const struct drm_i915_private *dev_priv)
         * make an educated guess as to which PCH is really there.
         */
 
-       if (IS_GEN5(dev_priv))
+       if (IS_GEN(dev_priv, 5))
                id = INTEL_PCH_IBX_DEVICE_ID_TYPE;
-       else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
+       else if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
                id = INTEL_PCH_CPT_DEVICE_ID_TYPE;
        else if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv))
                id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE;
@@ -349,7 +349,7 @@ static int i915_getparam_ioctl(struct drm_device *dev, void *data,
                value = min_t(int, INTEL_PPGTT(dev_priv), I915_GEM_PPGTT_FULL);
                break;
        case I915_PARAM_HAS_SEMAPHORES:
-               value = HAS_LEGACY_SEMAPHORES(dev_priv);
+               value = 0;
                break;
        case I915_PARAM_HAS_SECURE_BATCHES:
                value = capable(CAP_SYS_ADMIN);
@@ -358,12 +358,12 @@ static int i915_getparam_ioctl(struct drm_device *dev, void *data,
                value = i915_cmd_parser_get_version(dev_priv);
                break;
        case I915_PARAM_SUBSLICE_TOTAL:
-               value = sseu_subslice_total(&INTEL_INFO(dev_priv)->sseu);
+               value = sseu_subslice_total(&RUNTIME_INFO(dev_priv)->sseu);
                if (!value)
                        return -ENODEV;
                break;
        case I915_PARAM_EU_TOTAL:
-               value = INTEL_INFO(dev_priv)->sseu.eu_total;
+               value = RUNTIME_INFO(dev_priv)->sseu.eu_total;
                if (!value)
                        return -ENODEV;
                break;
@@ -380,7 +380,7 @@ static int i915_getparam_ioctl(struct drm_device *dev, void *data,
                value = HAS_POOLED_EU(dev_priv);
                break;
        case I915_PARAM_MIN_EU_IN_POOL:
-               value = INTEL_INFO(dev_priv)->sseu.min_eu_in_pool;
+               value = RUNTIME_INFO(dev_priv)->sseu.min_eu_in_pool;
                break;
        case I915_PARAM_HUC_STATUS:
                value = intel_huc_check_status(&dev_priv->huc);
@@ -430,17 +430,17 @@ static int i915_getparam_ioctl(struct drm_device *dev, void *data,
                value = intel_engines_has_context_isolation(dev_priv);
                break;
        case I915_PARAM_SLICE_MASK:
-               value = INTEL_INFO(dev_priv)->sseu.slice_mask;
+               value = RUNTIME_INFO(dev_priv)->sseu.slice_mask;
                if (!value)
                        return -ENODEV;
                break;
        case I915_PARAM_SUBSLICE_MASK:
-               value = INTEL_INFO(dev_priv)->sseu.subslice_mask[0];
+               value = RUNTIME_INFO(dev_priv)->sseu.subslice_mask[0];
                if (!value)
                        return -ENODEV;
                break;
        case I915_PARAM_CS_TIMESTAMP_FREQUENCY:
-               value = 1000 * INTEL_INFO(dev_priv)->cs_timestamp_frequency_khz;
+               value = 1000 * RUNTIME_INFO(dev_priv)->cs_timestamp_frequency_khz;
                break;
        case I915_PARAM_MMAP_GTT_COHERENT:
                value = INTEL_INFO(dev_priv)->has_coherent_ggtt;
@@ -906,6 +906,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv)
        mutex_init(&dev_priv->pps_mutex);
 
        i915_memcpy_init_early(dev_priv);
+       intel_runtime_pm_init_early(dev_priv);
 
        ret = i915_workqueues_init(dev_priv);
        if (ret < 0)
@@ -966,7 +967,7 @@ static int i915_mmio_setup(struct drm_i915_private *dev_priv)
        int mmio_bar;
        int mmio_size;
 
-       mmio_bar = IS_GEN2(dev_priv) ? 1 : 0;
+       mmio_bar = IS_GEN(dev_priv, 2) ? 1 : 0;
        /*
         * Before gen4, the registers and the GTT are behind different BARs.
         * However, from gen4 onwards, the registers and the GTT are shared
@@ -1341,7 +1342,7 @@ intel_get_dram_info(struct drm_i915_private *dev_priv)
        /* Need to calculate bandwidth only for Gen9 */
        if (IS_BROXTON(dev_priv))
                ret = bxt_get_dram_info(dev_priv);
-       else if (IS_GEN9(dev_priv))
+       else if (IS_GEN(dev_priv, 9))
                ret = skl_get_dram_info(dev_priv);
        else
                ret = skl_dram_get_channels_info(dev_priv);
@@ -1374,7 +1375,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
        if (i915_inject_load_failure())
                return -ENODEV;
 
-       intel_device_info_runtime_init(mkwrite_device_info(dev_priv));
+       intel_device_info_runtime_init(dev_priv);
 
        if (HAS_PPGTT(dev_priv)) {
                if (intel_vgpu_active(dev_priv) &&
@@ -1436,7 +1437,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
        pci_set_master(pdev);
 
        /* overlay on gen2 is broken and can't address above 1G */
-       if (IS_GEN2(dev_priv)) {
+       if (IS_GEN(dev_priv, 2)) {
                ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(30));
                if (ret) {
                        DRM_ERROR("failed to set DMA mask\n");
@@ -1574,7 +1575,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
                acpi_video_register();
        }
 
-       if (IS_GEN5(dev_priv))
+       if (IS_GEN(dev_priv, 5))
                intel_gpu_ips_init(dev_priv);
 
        intel_audio_init(dev_priv);
@@ -1636,8 +1637,14 @@ static void i915_welcome_messages(struct drm_i915_private *dev_priv)
        if (drm_debug & DRM_UT_DRIVER) {
                struct drm_printer p = drm_debug_printer("i915 device info:");
 
-               intel_device_info_dump(&dev_priv->info, &p);
-               intel_device_info_dump_runtime(&dev_priv->info, &p);
+               drm_printf(&p, "pciid=0x%04x rev=0x%02x platform=%s gen=%i\n",
+                          INTEL_DEVID(dev_priv),
+                          INTEL_REVID(dev_priv),
+                          intel_platform_name(INTEL_INFO(dev_priv)->platform),
+                          INTEL_GEN(dev_priv));
+
+               intel_device_info_dump_flags(INTEL_INFO(dev_priv), &p);
+               intel_device_info_dump_runtime(RUNTIME_INFO(dev_priv), &p);
        }
 
        if (IS_ENABLED(CONFIG_DRM_I915_DEBUG))
@@ -1674,7 +1681,7 @@ i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* Setup the write-once "constant" device info */
        device_info = mkwrite_device_info(i915);
        memcpy(device_info, match_info, sizeof(*device_info));
-       device_info->device_id = pdev->device;
+       RUNTIME_INFO(i915)->device_id = pdev->device;
 
        BUILD_BUG_ON(INTEL_MAX_PLATFORMS >
                     BITS_PER_TYPE(device_info->platform_mask));
@@ -1774,6 +1781,9 @@ void i915_driver_unload(struct drm_device *dev)
 
        i915_driver_unregister(dev_priv);
 
+       /* Flush any external code that still may be under the RCU lock */
+       synchronize_rcu();
+
        if (i915_gem_suspend(dev_priv))
                DRM_ERROR("failed to idle hardware; continuing to unload!\n");
 
@@ -1802,8 +1812,7 @@ void i915_driver_unload(struct drm_device *dev)
        i915_driver_cleanup_mmio(dev_priv);
 
        enable_rpm_wakeref_asserts(dev_priv);
-
-       WARN_ON(atomic_read(&dev_priv->runtime_pm.wakeref_count));
+       intel_runtime_pm_cleanup(dev_priv);
 }
 
 static void i915_driver_release(struct drm_device *dev)
@@ -2005,6 +2014,8 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
 
 out:
        enable_rpm_wakeref_asserts(dev_priv);
+       if (!dev_priv->uncore.user_forcewake.count)
+               intel_runtime_pm_cleanup(dev_priv);
 
        return ret;
 }
@@ -2174,7 +2185,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
 
        intel_power_domains_resume(dev_priv);
 
-       intel_engines_sanitize(dev_priv);
+       intel_engines_sanitize(dev_priv, true);
 
        enable_rpm_wakeref_asserts(dev_priv);
 
@@ -2195,210 +2206,6 @@ static int i915_resume_switcheroo(struct drm_device *dev)
        return i915_drm_resume(dev);
 }
 
-/**
- * i915_reset - reset chip after a hang
- * @i915: #drm_i915_private to reset
- * @stalled_mask: mask of the stalled engines with the guilty requests
- * @reason: user error message for why we are resetting
- *
- * Reset the chip.  Useful if a hang is detected. Marks the device as wedged
- * on failure.
- *
- * Caller must hold the struct_mutex.
- *
- * Procedure is fairly simple:
- *   - reset the chip using the reset reg
- *   - re-init context state
- *   - re-init hardware status page
- *   - re-init ring buffer
- *   - re-init interrupt state
- *   - re-init display
- */
-void i915_reset(struct drm_i915_private *i915,
-               unsigned int stalled_mask,
-               const char *reason)
-{
-       struct i915_gpu_error *error = &i915->gpu_error;
-       int ret;
-       int i;
-
-       GEM_TRACE("flags=%lx\n", error->flags);
-
-       might_sleep();
-       lockdep_assert_held(&i915->drm.struct_mutex);
-       GEM_BUG_ON(!test_bit(I915_RESET_BACKOFF, &error->flags));
-
-       if (!test_bit(I915_RESET_HANDOFF, &error->flags))
-               return;
-
-       /* Clear any previous failed attempts at recovery. Time to try again. */
-       if (!i915_gem_unset_wedged(i915))
-               goto wakeup;
-
-       if (reason)
-               dev_notice(i915->drm.dev, "Resetting chip for %s\n", reason);
-       error->reset_count++;
-
-       ret = i915_gem_reset_prepare(i915);
-       if (ret) {
-               dev_err(i915->drm.dev, "GPU recovery failed\n");
-               goto taint;
-       }
-
-       if (!intel_has_gpu_reset(i915)) {
-               if (i915_modparams.reset)
-                       dev_err(i915->drm.dev, "GPU reset not supported\n");
-               else
-                       DRM_DEBUG_DRIVER("GPU reset disabled\n");
-               goto error;
-       }
-
-       for (i = 0; i < 3; i++) {
-               ret = intel_gpu_reset(i915, ALL_ENGINES);
-               if (ret == 0)
-                       break;
-
-               msleep(100);
-       }
-       if (ret) {
-               dev_err(i915->drm.dev, "Failed to reset chip\n");
-               goto taint;
-       }
-
-       /* Ok, now get things going again... */
-
-       /*
-        * Everything depends on having the GTT running, so we need to start
-        * there.
-        */
-       ret = i915_ggtt_enable_hw(i915);
-       if (ret) {
-               DRM_ERROR("Failed to re-enable GGTT following reset (%d)\n",
-                         ret);
-               goto error;
-       }
-
-       i915_gem_reset(i915, stalled_mask);
-       intel_overlay_reset(i915);
-
-       /*
-        * Next we need to restore the context, but we don't use those
-        * yet either...
-        *
-        * Ring buffer needs to be re-initialized in the KMS case, or if X
-        * was running at the time of the reset (i.e. we weren't VT
-        * switched away).
-        */
-       ret = i915_gem_init_hw(i915);
-       if (ret) {
-               DRM_ERROR("Failed to initialise HW following reset (%d)\n",
-                         ret);
-               goto error;
-       }
-
-       i915_queue_hangcheck(i915);
-
-finish:
-       i915_gem_reset_finish(i915);
-wakeup:
-       clear_bit(I915_RESET_HANDOFF, &error->flags);
-       wake_up_bit(&error->flags, I915_RESET_HANDOFF);
-       return;
-
-taint:
-       /*
-        * History tells us that if we cannot reset the GPU now, we
-        * never will. This then impacts everything that is run
-        * subsequently. On failing the reset, we mark the driver
-        * as wedged, preventing further execution on the GPU.
-        * We also want to go one step further and add a taint to the
-        * kernel so that any subsequent faults can be traced back to
-        * this failure. This is important for CI, where if the
-        * GPU/driver fails we would like to reboot and restart testing
-        * rather than continue on into oblivion. For everyone else,
-        * the system should still plod along, but they have been warned!
-        */
-       add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
-error:
-       i915_gem_set_wedged(i915);
-       i915_retire_requests(i915);
-       goto finish;
-}
-
-static inline int intel_gt_reset_engine(struct drm_i915_private *dev_priv,
-                                       struct intel_engine_cs *engine)
-{
-       return intel_gpu_reset(dev_priv, intel_engine_flag(engine));
-}
-
-/**
- * i915_reset_engine - reset GPU engine to recover from a hang
- * @engine: engine to reset
- * @msg: reason for GPU reset; or NULL for no dev_notice()
- *
- * Reset a specific GPU engine. Useful if a hang is detected.
- * Returns zero on successful reset or otherwise an error code.
- *
- * Procedure is:
- *  - identifies the request that caused the hang and it is dropped
- *  - reset engine (which will force the engine to idle)
- *  - re-init/configure engine
- */
-int i915_reset_engine(struct intel_engine_cs *engine, const char *msg)
-{
-       struct i915_gpu_error *error = &engine->i915->gpu_error;
-       struct i915_request *active_request;
-       int ret;
-
-       GEM_TRACE("%s flags=%lx\n", engine->name, error->flags);
-       GEM_BUG_ON(!test_bit(I915_RESET_ENGINE + engine->id, &error->flags));
-
-       active_request = i915_gem_reset_prepare_engine(engine);
-       if (IS_ERR_OR_NULL(active_request)) {
-               /* Either the previous reset failed, or we pardon the reset. */
-               ret = PTR_ERR(active_request);
-               goto out;
-       }
-
-       if (msg)
-               dev_notice(engine->i915->drm.dev,
-                          "Resetting %s for %s\n", engine->name, msg);
-       error->reset_engine_count[engine->id]++;
-
-       if (!engine->i915->guc.execbuf_client)
-               ret = intel_gt_reset_engine(engine->i915, engine);
-       else
-               ret = intel_guc_reset_engine(&engine->i915->guc, engine);
-       if (ret) {
-               /* If we fail here, we expect to fallback to a global reset */
-               DRM_DEBUG_DRIVER("%sFailed to reset %s, ret=%d\n",
-                                engine->i915->guc.execbuf_client ? "GuC " : "",
-                                engine->name, ret);
-               goto out;
-       }
-
-       /*
-        * The request that caused the hang is stuck on elsp, we know the
-        * active request and can drop it, adjust head to skip the offending
-        * request to resume executing remaining requests in the queue.
-        */
-       i915_gem_reset_engine(engine, active_request, true);
-
-       /*
-        * The engine and its registers (and workarounds in case of render)
-        * have been reset to their default values. Follow the init_ring
-        * process to program RING_MODE, HWSP and re-enable submission.
-        */
-       ret = engine->init_hw(engine);
-       if (ret)
-               goto out;
-
-out:
-       intel_engine_cancel_stop_cs(engine);
-       i915_gem_reset_finish_engine(engine);
-       return ret;
-}
-
 static int i915_pm_prepare(struct device *kdev)
 {
        struct pci_dev *pdev = to_pci_dev(kdev);
@@ -2959,7 +2766,7 @@ static int intel_runtime_suspend(struct device *kdev)
        }
 
        enable_rpm_wakeref_asserts(dev_priv);
-       WARN_ON_ONCE(atomic_read(&dev_priv->runtime_pm.wakeref_count));
+       intel_runtime_pm_cleanup(dev_priv);
 
        if (intel_uncore_arm_unclaimed_mmio_detection(dev_priv))
                DRM_ERROR("Unclaimed access detected prior to suspending\n");
index b1c31967194b92cc47b8a3cedafea021d82fd073..3c111ad099225dcdc5a7cfcf92c4d327f4ddad0c 100644 (file)
@@ -45,8 +45,8 @@
 #include <linux/pm_qos.h>
 #include <linux/reservation.h>
 #include <linux/shmem_fs.h>
+#include <linux/stackdepot.h>
 
-#include <drm/drmP.h>
 #include <drm/intel-gtt.h>
 #include <drm/drm_legacy.h> /* for struct drm_dma_handle */
 #include <drm/drm_gem.h>
@@ -54,6 +54,7 @@
 #include <drm/drm_cache.h>
 #include <drm/drm_util.h>
 #include <drm/drm_dsc.h>
+#include <drm/drm_connector.h>
 
 #include "i915_fixed.h"
 #include "i915_params.h"
@@ -90,8 +91,8 @@
 
 #define DRIVER_NAME            "i915"
 #define DRIVER_DESC            "Intel Graphics"
-#define DRIVER_DATE            "20181204"
-#define DRIVER_TIMESTAMP       1543944377
+#define DRIVER_DATE            "20190124"
+#define DRIVER_TIMESTAMP       1548370857
 
 /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and
  * WARN_ON()) for hw state sanity checks to check for unexpected conditions
@@ -130,6 +131,8 @@ bool i915_error_injected(void);
        __i915_printk(i915, i915_error_injected() ? KERN_DEBUG : KERN_ERR, \
                      fmt, ##__VA_ARGS__)
 
+typedef depot_stack_handle_t intel_wakeref_t;
+
 enum hpd_pin {
        HPD_NONE = 0,
        HPD_TV = HPD_NONE,     /* TV is known to be unreliable */
@@ -281,16 +284,14 @@ struct drm_i915_display_funcs {
        int (*get_fifo_size)(struct drm_i915_private *dev_priv,
                             enum i9xx_plane_id i9xx_plane);
        int (*compute_pipe_wm)(struct intel_crtc_state *cstate);
-       int (*compute_intermediate_wm)(struct drm_device *dev,
-                                      struct intel_crtc *intel_crtc,
-                                      struct intel_crtc_state *newstate);
+       int (*compute_intermediate_wm)(struct intel_crtc_state *newstate);
        void (*initial_watermarks)(struct intel_atomic_state *state,
                                   struct intel_crtc_state *cstate);
        void (*atomic_update_watermarks)(struct intel_atomic_state *state,
                                         struct intel_crtc_state *cstate);
        void (*optimize_watermarks)(struct intel_atomic_state *state,
                                    struct intel_crtc_state *cstate);
-       int (*compute_global_watermarks)(struct drm_atomic_state *state);
+       int (*compute_global_watermarks)(struct intel_atomic_state *state);
        void (*update_wm)(struct intel_crtc *crtc);
        int (*modeset_calc_cdclk)(struct drm_atomic_state *state);
        /* Returns the active state of the crtc, and if the crtc is active,
@@ -322,8 +323,8 @@ struct drm_i915_display_funcs {
        /* display clock increase/decrease */
        /* pll clock increase/decrease */
 
-       void (*load_csc_matrix)(struct drm_crtc_state *crtc_state);
-       void (*load_luts)(struct drm_crtc_state *crtc_state);
+       void (*load_csc_matrix)(struct intel_crtc_state *crtc_state);
+       void (*load_luts)(struct intel_crtc_state *crtc_state);
 };
 
 #define CSR_VERSION(major, minor)      ((major) << 16 | (minor))
@@ -333,16 +334,17 @@ struct drm_i915_display_funcs {
 struct intel_csr {
        struct work_struct work;
        const char *fw_path;
-       uint32_t required_version;
-       uint32_t max_fw_size; /* bytes */
-       uint32_t *dmc_payload;
-       uint32_t dmc_fw_size; /* dwords */
-       uint32_t version;
-       uint32_t mmio_count;
+       u32 required_version;
+       u32 max_fw_size; /* bytes */
+       u32 *dmc_payload;
+       u32 dmc_fw_size; /* dwords */
+       u32 version;
+       u32 mmio_count;
        i915_reg_t mmioaddr[8];
-       uint32_t mmiodata[8];
-       uint32_t dc_state;
-       uint32_t allowed_dc_mask;
+       u32 mmiodata[8];
+       u32 dc_state;
+       u32 allowed_dc_mask;
+       intel_wakeref_t wakeref;
 };
 
 enum i915_cache_level {
@@ -398,7 +400,7 @@ struct intel_fbc {
 
                struct {
                        unsigned int mode_flags;
-                       uint32_t hsw_bdw_pixel_rate;
+                       u32 hsw_bdw_pixel_rate;
                } crtc;
 
                struct {
@@ -417,7 +419,7 @@ struct intel_fbc {
 
                        int y;
 
-                       uint16_t pixel_blend_mode;
+                       u16 pixel_blend_mode;
                } plane;
 
                struct {
@@ -509,6 +511,7 @@ struct i915_psr {
        ktime_t last_exit;
        bool sink_not_reliable;
        bool irq_aux_error;
+       u16 su_x_granularity;
 };
 
 enum intel_pch {
@@ -556,7 +559,7 @@ struct i915_suspend_saved_registers {
        u32 saveSWF0[16];
        u32 saveSWF1[16];
        u32 saveSWF3[3];
-       uint64_t saveFENCE[I915_MAX_NUM_FENCES];
+       u64 saveFENCE[I915_MAX_NUM_FENCES];
        u32 savePCH_PORT_HOTPLUG;
        u16 saveGCDGMBUS;
 };
@@ -819,6 +822,8 @@ struct i915_power_domains {
        bool display_core_suspended;
        int power_well_count;
 
+       intel_wakeref_t wakeref;
+
        struct mutex lock;
        int domain_use_count[POWER_DOMAIN_NUM];
        struct i915_power_well *power_wells;
@@ -901,9 +906,9 @@ struct i915_gem_mm {
        atomic_t bsd_engine_dispatch_index;
 
        /** Bit 6 swizzling required for X tiling */
-       uint32_t bit_6_swizzle_x;
+       u32 bit_6_swizzle_x;
        /** Bit 6 swizzling required for Y tiling */
-       uint32_t bit_6_swizzle_y;
+       u32 bit_6_swizzle_y;
 
        /* accounting, useful for userland debugging */
        spinlock_t object_stat_lock;
@@ -930,18 +935,20 @@ struct ddi_vbt_port_info {
         * populate this field.
         */
 #define HDMI_LEVEL_SHIFT_UNKNOWN       0xff
-       uint8_t hdmi_level_shift;
+       u8 hdmi_level_shift;
 
-       uint8_t supports_dvi:1;
-       uint8_t supports_hdmi:1;
-       uint8_t supports_dp:1;
-       uint8_t supports_edp:1;
+       u8 supports_dvi:1;
+       u8 supports_hdmi:1;
+       u8 supports_dp:1;
+       u8 supports_edp:1;
+       u8 supports_typec_usb:1;
+       u8 supports_tbt:1;
 
-       uint8_t alternate_aux_channel;
-       uint8_t alternate_ddc_pin;
+       u8 alternate_aux_channel;
+       u8 alternate_ddc_pin;
 
-       uint8_t dp_boost_level;
-       uint8_t hdmi_boost_level;
+       u8 dp_boost_level;
+       u8 hdmi_boost_level;
        int dp_max_link_rate;           /* 0 for not limited by VBT */
 };
 
@@ -1032,41 +1039,41 @@ enum intel_ddb_partitioning {
 
 struct intel_wm_level {
        bool enable;
-       uint32_t pri_val;
-       uint32_t spr_val;
-       uint32_t cur_val;
-       uint32_t fbc_val;
+       u32 pri_val;
+       u32 spr_val;
+       u32 cur_val;
+       u32 fbc_val;
 };
 
 struct ilk_wm_values {
-       uint32_t wm_pipe[3];
-       uint32_t wm_lp[3];
-       uint32_t wm_lp_spr[3];
-       uint32_t wm_linetime[3];
+       u32 wm_pipe[3];
+       u32 wm_lp[3];
+       u32 wm_lp_spr[3];
+       u32 wm_linetime[3];
        bool enable_fbc_wm;
        enum intel_ddb_partitioning partitioning;
 };
 
 struct g4x_pipe_wm {
-       uint16_t plane[I915_MAX_PLANES];
-       uint16_t fbc;
+       u16 plane[I915_MAX_PLANES];
+       u16 fbc;
 };
 
 struct g4x_sr_wm {
-       uint16_t plane;
-       uint16_t cursor;
-       uint16_t fbc;
+       u16 plane;
+       u16 cursor;
+       u16 fbc;
 };
 
 struct vlv_wm_ddl_values {
-       uint8_t plane[I915_MAX_PLANES];
+       u8 plane[I915_MAX_PLANES];
 };
 
 struct vlv_wm_values {
        struct g4x_pipe_wm pipe[3];
        struct g4x_sr_wm sr;
        struct vlv_wm_ddl_values ddl[3];
-       uint8_t level;
+       u8 level;
        bool cxsr;
 };
 
@@ -1080,10 +1087,10 @@ struct g4x_wm_values {
 };
 
 struct skl_ddb_entry {
-       uint16_t start, end;    /* in number of blocks, 'end' is exclusive */
+       u16 start, end; /* in number of blocks, 'end' is exclusive */
 };
 
-static inline uint16_t skl_ddb_entry_size(const struct skl_ddb_entry *entry)
+static inline u16 skl_ddb_entry_size(const struct skl_ddb_entry *entry)
 {
        return entry->end - entry->start;
 }
@@ -1107,8 +1114,8 @@ struct skl_ddb_values {
 };
 
 struct skl_wm_level {
-       uint16_t plane_res_b;
-       uint8_t plane_res_l;
+       u16 plane_res_b;
+       u8 plane_res_l;
        bool plane_en;
 };
 
@@ -1117,15 +1124,15 @@ struct skl_wm_params {
        bool x_tiled, y_tiled;
        bool rc_surface;
        bool is_planar;
-       uint32_t width;
-       uint8_t cpp;
-       uint32_t plane_pixel_rate;
-       uint32_t y_min_scanlines;
-       uint32_t plane_bytes_per_line;
+       u32 width;
+       u8 cpp;
+       u32 plane_pixel_rate;
+       u32 y_min_scanlines;
+       u32 plane_bytes_per_line;
        uint_fixed_16_16_t plane_blocks_per_line;
        uint_fixed_16_16_t y_tile_minimum;
-       uint32_t linetime_us;
-       uint32_t dbuf_block_size;
+       u32 linetime_us;
+       u32 dbuf_block_size;
 };
 
 /*
@@ -1155,6 +1162,25 @@ struct i915_runtime_pm {
        atomic_t wakeref_count;
        bool suspended;
        bool irqs_enabled;
+
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
+       /*
+        * To aide detection of wakeref leaks and general misuse, we
+        * track all wakeref holders. With manual markup (i.e. returning
+        * a cookie to each rpm_get caller which they then supply to their
+        * paired rpm_put) we can remove corresponding pairs of and keep
+        * the array trimmed to active wakerefs.
+        */
+       struct intel_runtime_pm_debug {
+               spinlock_t lock;
+
+               depot_stack_handle_t last_acquire;
+               depot_stack_handle_t last_release;
+
+               depot_stack_handle_t *owners;
+               unsigned long count;
+       } debug;
+#endif
 };
 
 enum intel_pipe_crc_source {
@@ -1310,6 +1336,12 @@ struct i915_perf_stream {
         */
        struct list_head link;
 
+       /**
+        * @wakeref: As we keep the device awake while the perf stream is
+        * active, we track our runtime pm reference for later release.
+        */
+       intel_wakeref_t wakeref;
+
        /**
         * @sample_flags: Flags representing the `DRM_I915_PERF_PROP_SAMPLE_*`
         * properties given when opening a stream, representing the contents
@@ -1430,7 +1462,8 @@ struct drm_i915_private {
        struct kmem_cache *dependencies;
        struct kmem_cache *priorities;
 
-       const struct intel_device_info info;
+       const struct intel_device_info __info; /* Use INTEL_INFO() to access. */
+       struct intel_runtime_info __runtime; /* Use RUNTIME_INFO() to access. */
        struct intel_driver_caps caps;
 
        /**
@@ -1482,14 +1515,14 @@ struct drm_i915_private {
         * Base address of where the gmbus and gpio blocks are located (either
         * on PCH or on SoC for platforms without PCH).
         */
-       uint32_t gpio_mmio_base;
+       u32 gpio_mmio_base;
 
        /* MMIO base address for MIPI regs */
-       uint32_t mipi_mmio_base;
+       u32 mipi_mmio_base;
 
-       uint32_t psr_mmio_base;
+       u32 psr_mmio_base;
 
-       uint32_t pps_mmio_base;
+       u32 pps_mmio_base;
 
        wait_queue_head_t gmbus_wait_queue;
 
@@ -1744,17 +1777,17 @@ struct drm_i915_private {
                 * in 0.5us units for WM1+.
                 */
                /* primary */
-               uint16_t pri_latency[5];
+               u16 pri_latency[5];
                /* sprite */
-               uint16_t spr_latency[5];
+               u16 spr_latency[5];
                /* cursor */
-               uint16_t cur_latency[5];
+               u16 cur_latency[5];
                /*
                 * Raw watermark memory latency values
                 * for SKL for all 8 levels
                 * in 1us units.
                 */
-               uint16_t skl_latency[8];
+               u16 skl_latency[8];
 
                /* current hardware state */
                union {
@@ -1764,7 +1797,7 @@ struct drm_i915_private {
                        struct g4x_wm_values g4x;
                };
 
-               uint8_t max_level;
+               u8 max_level;
 
                /*
                 * Should be held around atomic WM register writing; also
@@ -1947,7 +1980,6 @@ struct drm_i915_private {
                struct list_head active_rings;
                struct list_head closed_vma;
                u32 active_requests;
-               u32 request_serial;
 
                /**
                 * Is the GPU currently considered idle, or busy executing
@@ -1956,7 +1988,7 @@ struct drm_i915_private {
                 * In order to reduce the effect on performance, there
                 * is a slight delay before we do so.
                 */
-               bool awake;
+               intel_wakeref_t awake;
 
                /**
                 * The number of times we have woken up.
@@ -2191,17 +2223,12 @@ static inline unsigned int i915_sg_segment_size(void)
        return size;
 }
 
-static inline const struct intel_device_info *
-intel_info(const struct drm_i915_private *dev_priv)
-{
-       return &dev_priv->info;
-}
-
-#define INTEL_INFO(dev_priv)   intel_info((dev_priv))
+#define INTEL_INFO(dev_priv)   (&(dev_priv)->__info)
+#define RUNTIME_INFO(dev_priv) (&(dev_priv)->__runtime)
 #define DRIVER_CAPS(dev_priv)  (&(dev_priv)->caps)
 
-#define INTEL_GEN(dev_priv)    ((dev_priv)->info.gen)
-#define INTEL_DEVID(dev_priv)  ((dev_priv)->info.device_id)
+#define INTEL_GEN(dev_priv)    (INTEL_INFO(dev_priv)->gen)
+#define INTEL_DEVID(dev_priv)  (RUNTIME_INFO(dev_priv)->device_id)
 
 #define REVID_FOREVER          0xff
 #define INTEL_REVID(dev_priv)  ((dev_priv)->drm.pdev->revision)
@@ -2212,8 +2239,12 @@ intel_info(const struct drm_i915_private *dev_priv)
        GENMASK((e) - 1, (s) - 1))
 
 /* Returns true if Gen is in inclusive range [Start, End] */
-#define IS_GEN(dev_priv, s, e) \
-       (!!((dev_priv)->info.gen_mask & INTEL_GEN_MASK((s), (e))))
+#define IS_GEN_RANGE(dev_priv, s, e) \
+       (!!(INTEL_INFO(dev_priv)->gen_mask & INTEL_GEN_MASK((s), (e))))
+
+#define IS_GEN(dev_priv, n) \
+       (BUILD_BUG_ON_ZERO(!__builtin_constant_p(n)) + \
+        INTEL_INFO(dev_priv)->gen == (n))
 
 /*
  * Return true if revision is in range [since,until] inclusive.
@@ -2223,7 +2254,7 @@ intel_info(const struct drm_i915_private *dev_priv)
 #define IS_REVID(p, since, until) \
        (INTEL_REVID(p) >= (since) && INTEL_REVID(p) <= (until))
 
-#define IS_PLATFORM(dev_priv, p) ((dev_priv)->info.platform_mask & BIT(p))
+#define IS_PLATFORM(dev_priv, p) (INTEL_INFO(dev_priv)->platform_mask & BIT(p))
 
 #define IS_I830(dev_priv)      IS_PLATFORM(dev_priv, INTEL_I830)
 #define IS_I845G(dev_priv)     IS_PLATFORM(dev_priv, INTEL_I845G)
@@ -2245,7 +2276,7 @@ intel_info(const struct drm_i915_private *dev_priv)
 #define IS_IRONLAKE_M(dev_priv)        (INTEL_DEVID(dev_priv) == 0x0046)
 #define IS_IVYBRIDGE(dev_priv) IS_PLATFORM(dev_priv, INTEL_IVYBRIDGE)
 #define IS_IVB_GT1(dev_priv)   (IS_IVYBRIDGE(dev_priv) && \
-                                (dev_priv)->info.gt == 1)
+                                INTEL_INFO(dev_priv)->gt == 1)
 #define IS_VALLEYVIEW(dev_priv)        IS_PLATFORM(dev_priv, INTEL_VALLEYVIEW)
 #define IS_CHERRYVIEW(dev_priv)        IS_PLATFORM(dev_priv, INTEL_CHERRYVIEW)
 #define IS_HASWELL(dev_priv)   IS_PLATFORM(dev_priv, INTEL_HASWELL)
@@ -2257,7 +2288,7 @@ intel_info(const struct drm_i915_private *dev_priv)
 #define IS_COFFEELAKE(dev_priv)        IS_PLATFORM(dev_priv, INTEL_COFFEELAKE)
 #define IS_CANNONLAKE(dev_priv)        IS_PLATFORM(dev_priv, INTEL_CANNONLAKE)
 #define IS_ICELAKE(dev_priv)   IS_PLATFORM(dev_priv, INTEL_ICELAKE)
-#define IS_MOBILE(dev_priv)    ((dev_priv)->info.is_mobile)
+#define IS_MOBILE(dev_priv)    (INTEL_INFO(dev_priv)->is_mobile)
 #define IS_HSW_EARLY_SDV(dev_priv) (IS_HASWELL(dev_priv) && \
                                    (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0C00)
 #define IS_BDW_ULT(dev_priv)   (IS_BROADWELL(dev_priv) && \
@@ -2268,11 +2299,13 @@ intel_info(const struct drm_i915_private *dev_priv)
 #define IS_BDW_ULX(dev_priv)   (IS_BROADWELL(dev_priv) && \
                                 (INTEL_DEVID(dev_priv) & 0xf) == 0xe)
 #define IS_BDW_GT3(dev_priv)   (IS_BROADWELL(dev_priv) && \
-                                (dev_priv)->info.gt == 3)
+                                INTEL_INFO(dev_priv)->gt == 3)
 #define IS_HSW_ULT(dev_priv)   (IS_HASWELL(dev_priv) && \
                                 (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0A00)
 #define IS_HSW_GT3(dev_priv)   (IS_HASWELL(dev_priv) && \
-                                (dev_priv)->info.gt == 3)
+                                INTEL_INFO(dev_priv)->gt == 3)
+#define IS_HSW_GT1(dev_priv)   (IS_HASWELL(dev_priv) && \
+                                INTEL_INFO(dev_priv)->gt == 1)
 /* ULX machines are also considered ULT. */
 #define IS_HSW_ULX(dev_priv)   (INTEL_DEVID(dev_priv) == 0x0A0E || \
                                 INTEL_DEVID(dev_priv) == 0x0A1E)
@@ -2295,21 +2328,21 @@ intel_info(const struct drm_i915_private *dev_priv)
 #define IS_AML_ULX(dev_priv)   (INTEL_DEVID(dev_priv) == 0x591C || \
                                 INTEL_DEVID(dev_priv) == 0x87C0)
 #define IS_SKL_GT2(dev_priv)   (IS_SKYLAKE(dev_priv) && \
-                                (dev_priv)->info.gt == 2)
+                                INTEL_INFO(dev_priv)->gt == 2)
 #define IS_SKL_GT3(dev_priv)   (IS_SKYLAKE(dev_priv) && \
-                                (dev_priv)->info.gt == 3)
+                                INTEL_INFO(dev_priv)->gt == 3)
 #define IS_SKL_GT4(dev_priv)   (IS_SKYLAKE(dev_priv) && \
-                                (dev_priv)->info.gt == 4)
+                                INTEL_INFO(dev_priv)->gt == 4)
 #define IS_KBL_GT2(dev_priv)   (IS_KABYLAKE(dev_priv) && \
-                                (dev_priv)->info.gt == 2)
+                                INTEL_INFO(dev_priv)->gt == 2)
 #define IS_KBL_GT3(dev_priv)   (IS_KABYLAKE(dev_priv) && \
-                                (dev_priv)->info.gt == 3)
+                                INTEL_INFO(dev_priv)->gt == 3)
 #define IS_CFL_ULT(dev_priv)   (IS_COFFEELAKE(dev_priv) && \
                                 (INTEL_DEVID(dev_priv) & 0x00F0) == 0x00A0)
 #define IS_CFL_GT2(dev_priv)   (IS_COFFEELAKE(dev_priv) && \
-                                (dev_priv)->info.gt == 2)
+                                INTEL_INFO(dev_priv)->gt == 2)
 #define IS_CFL_GT3(dev_priv)   (IS_COFFEELAKE(dev_priv) && \
-                                (dev_priv)->info.gt == 3)
+                                INTEL_INFO(dev_priv)->gt == 3)
 #define IS_CNL_WITH_PORT_F(dev_priv)   (IS_CANNONLAKE(dev_priv) && \
                                        (INTEL_DEVID(dev_priv) & 0x0004) == 0x0004)
 
@@ -2366,26 +2399,9 @@ intel_info(const struct drm_i915_private *dev_priv)
 #define IS_ICL_REVID(p, since, until) \
        (IS_ICELAKE(p) && IS_REVID(p, since, until))
 
-/*
- * The genX designation typically refers to the render engine, so render
- * capability related checks should use IS_GEN, while display and other checks
- * have their own (e.g. HAS_PCH_SPLIT for ILK+ display, IS_foo for particular
- * chips, etc.).
- */
-#define IS_GEN2(dev_priv)      (!!((dev_priv)->info.gen_mask & BIT(1)))
-#define IS_GEN3(dev_priv)      (!!((dev_priv)->info.gen_mask & BIT(2)))
-#define IS_GEN4(dev_priv)      (!!((dev_priv)->info.gen_mask & BIT(3)))
-#define IS_GEN5(dev_priv)      (!!((dev_priv)->info.gen_mask & BIT(4)))
-#define IS_GEN6(dev_priv)      (!!((dev_priv)->info.gen_mask & BIT(5)))
-#define IS_GEN7(dev_priv)      (!!((dev_priv)->info.gen_mask & BIT(6)))
-#define IS_GEN8(dev_priv)      (!!((dev_priv)->info.gen_mask & BIT(7)))
-#define IS_GEN9(dev_priv)      (!!((dev_priv)->info.gen_mask & BIT(8)))
-#define IS_GEN10(dev_priv)     (!!((dev_priv)->info.gen_mask & BIT(9)))
-#define IS_GEN11(dev_priv)     (!!((dev_priv)->info.gen_mask & BIT(10)))
-
 #define IS_LP(dev_priv)        (INTEL_INFO(dev_priv)->is_lp)
-#define IS_GEN9_LP(dev_priv)   (IS_GEN9(dev_priv) && IS_LP(dev_priv))
-#define IS_GEN9_BC(dev_priv)   (IS_GEN9(dev_priv) && !IS_LP(dev_priv))
+#define IS_GEN9_LP(dev_priv)   (IS_GEN(dev_priv, 9) && IS_LP(dev_priv))
+#define IS_GEN9_BC(dev_priv)   (IS_GEN(dev_priv, 9) && !IS_LP(dev_priv))
 
 #define ENGINE_MASK(id)        BIT(id)
 #define RENDER_RING    ENGINE_MASK(RCS)
@@ -2399,29 +2415,27 @@ intel_info(const struct drm_i915_private *dev_priv)
 #define ALL_ENGINES    (~0)
 
 #define HAS_ENGINE(dev_priv, id) \
-       (!!((dev_priv)->info.ring_mask & ENGINE_MASK(id)))
+       (!!(INTEL_INFO(dev_priv)->ring_mask & ENGINE_MASK(id)))
 
 #define HAS_BSD(dev_priv)      HAS_ENGINE(dev_priv, VCS)
 #define HAS_BSD2(dev_priv)     HAS_ENGINE(dev_priv, VCS2)
 #define HAS_BLT(dev_priv)      HAS_ENGINE(dev_priv, BCS)
 #define HAS_VEBOX(dev_priv)    HAS_ENGINE(dev_priv, VECS)
 
-#define HAS_LEGACY_SEMAPHORES(dev_priv) IS_GEN7(dev_priv)
-
-#define HAS_LLC(dev_priv)      ((dev_priv)->info.has_llc)
-#define HAS_SNOOP(dev_priv)    ((dev_priv)->info.has_snoop)
+#define HAS_LLC(dev_priv)      (INTEL_INFO(dev_priv)->has_llc)
+#define HAS_SNOOP(dev_priv)    (INTEL_INFO(dev_priv)->has_snoop)
 #define HAS_EDRAM(dev_priv)    (!!((dev_priv)->edram_cap & EDRAM_ENABLED))
 #define HAS_WT(dev_priv)       ((IS_HASWELL(dev_priv) || \
                                 IS_BROADWELL(dev_priv)) && HAS_EDRAM(dev_priv))
 
-#define HWS_NEEDS_PHYSICAL(dev_priv)   ((dev_priv)->info.hws_needs_physical)
+#define HWS_NEEDS_PHYSICAL(dev_priv)   (INTEL_INFO(dev_priv)->hws_needs_physical)
 
 #define HAS_LOGICAL_RING_CONTEXTS(dev_priv) \
-               ((dev_priv)->info.has_logical_ring_contexts)
+               (INTEL_INFO(dev_priv)->has_logical_ring_contexts)
 #define HAS_LOGICAL_RING_ELSQ(dev_priv) \
-               ((dev_priv)->info.has_logical_ring_elsq)
+               (INTEL_INFO(dev_priv)->has_logical_ring_elsq)
 #define HAS_LOGICAL_RING_PREEMPTION(dev_priv) \
-               ((dev_priv)->info.has_logical_ring_preemption)
+               (INTEL_INFO(dev_priv)->has_logical_ring_preemption)
 
 #define HAS_EXECLISTS(dev_priv) HAS_LOGICAL_RING_CONTEXTS(dev_priv)
 
@@ -2435,12 +2449,12 @@ intel_info(const struct drm_i915_private *dev_priv)
 
 #define HAS_PAGE_SIZES(dev_priv, sizes) ({ \
        GEM_BUG_ON((sizes) == 0); \
-       ((sizes) & ~(dev_priv)->info.page_sizes) == 0; \
+       ((sizes) & ~INTEL_INFO(dev_priv)->page_sizes) == 0; \
 })
 
-#define HAS_OVERLAY(dev_priv)           ((dev_priv)->info.display.has_overlay)
+#define HAS_OVERLAY(dev_priv)           (INTEL_INFO(dev_priv)->display.has_overlay)
 #define OVERLAY_NEEDS_PHYSICAL(dev_priv) \
-               ((dev_priv)->info.display.overlay_needs_physical)
+               (INTEL_INFO(dev_priv)->display.overlay_needs_physical)
 
 /* Early gen2 have a totally busted CS tlb and require pinned batches. */
 #define HAS_BROKEN_CS_TLB(dev_priv)    (IS_I830(dev_priv) || IS_I845G(dev_priv))
@@ -2458,42 +2472,42 @@ intel_info(const struct drm_i915_private *dev_priv)
 /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
  * rows, which changed the alignment requirements and fence programming.
  */
-#define HAS_128_BYTE_Y_TILING(dev_priv) (!IS_GEN2(dev_priv) && \
+#define HAS_128_BYTE_Y_TILING(dev_priv) (!IS_GEN(dev_priv, 2) && \
                                         !(IS_I915G(dev_priv) || \
                                         IS_I915GM(dev_priv)))
-#define SUPPORTS_TV(dev_priv)          ((dev_priv)->info.display.supports_tv)
-#define I915_HAS_HOTPLUG(dev_priv)     ((dev_priv)->info.display.has_hotplug)
+#define SUPPORTS_TV(dev_priv)          (INTEL_INFO(dev_priv)->display.supports_tv)
+#define I915_HAS_HOTPLUG(dev_priv)     (INTEL_INFO(dev_priv)->display.has_hotplug)
 
 #define HAS_FW_BLC(dev_priv)   (INTEL_GEN(dev_priv) > 2)
-#define HAS_FBC(dev_priv)      ((dev_priv)->info.display.has_fbc)
+#define HAS_FBC(dev_priv)      (INTEL_INFO(dev_priv)->display.has_fbc)
 #define HAS_CUR_FBC(dev_priv)  (!HAS_GMCH_DISPLAY(dev_priv) && INTEL_GEN(dev_priv) >= 7)
 
 #define HAS_IPS(dev_priv)      (IS_HSW_ULT(dev_priv) || IS_BROADWELL(dev_priv))
 
-#define HAS_DP_MST(dev_priv)   ((dev_priv)->info.display.has_dp_mst)
+#define HAS_DP_MST(dev_priv)   (INTEL_INFO(dev_priv)->display.has_dp_mst)
 
-#define HAS_DDI(dev_priv)               ((dev_priv)->info.display.has_ddi)
-#define HAS_FPGA_DBG_UNCLAIMED(dev_priv) ((dev_priv)->info.has_fpga_dbg)
-#define HAS_PSR(dev_priv)               ((dev_priv)->info.display.has_psr)
+#define HAS_DDI(dev_priv)               (INTEL_INFO(dev_priv)->display.has_ddi)
+#define HAS_FPGA_DBG_UNCLAIMED(dev_priv) (INTEL_INFO(dev_priv)->has_fpga_dbg)
+#define HAS_PSR(dev_priv)               (INTEL_INFO(dev_priv)->display.has_psr)
 
-#define HAS_RC6(dev_priv)               ((dev_priv)->info.has_rc6)
-#define HAS_RC6p(dev_priv)              ((dev_priv)->info.has_rc6p)
+#define HAS_RC6(dev_priv)               (INTEL_INFO(dev_priv)->has_rc6)
+#define HAS_RC6p(dev_priv)              (INTEL_INFO(dev_priv)->has_rc6p)
 #define HAS_RC6pp(dev_priv)             (false) /* HW was never validated */
 
-#define HAS_CSR(dev_priv)      ((dev_priv)->info.display.has_csr)
+#define HAS_CSR(dev_priv)      (INTEL_INFO(dev_priv)->display.has_csr)
 
-#define HAS_RUNTIME_PM(dev_priv) ((dev_priv)->info.has_runtime_pm)
-#define HAS_64BIT_RELOC(dev_priv) ((dev_priv)->info.has_64bit_reloc)
+#define HAS_RUNTIME_PM(dev_priv) (INTEL_INFO(dev_priv)->has_runtime_pm)
+#define HAS_64BIT_RELOC(dev_priv) (INTEL_INFO(dev_priv)->has_64bit_reloc)
 
-#define HAS_IPC(dev_priv)               ((dev_priv)->info.display.has_ipc)
+#define HAS_IPC(dev_priv)               (INTEL_INFO(dev_priv)->display.has_ipc)
 
 /*
  * For now, anything with a GuC requires uCode loading, and then supports
  * command submission once loaded. But these are logically independent
  * properties, so we have separate macros to test them.
  */
-#define HAS_GUC(dev_priv)      ((dev_priv)->info.has_guc)
-#define HAS_GUC_CT(dev_priv)   ((dev_priv)->info.has_guc_ct)
+#define HAS_GUC(dev_priv)      (INTEL_INFO(dev_priv)->has_guc)
+#define HAS_GUC_CT(dev_priv)   (INTEL_INFO(dev_priv)->has_guc_ct)
 #define HAS_GUC_UCODE(dev_priv)        (HAS_GUC(dev_priv))
 #define HAS_GUC_SCHED(dev_priv)        (HAS_GUC(dev_priv))
 
@@ -2502,11 +2516,11 @@ intel_info(const struct drm_i915_private *dev_priv)
 #define HAS_HUC_UCODE(dev_priv)        (HAS_GUC(dev_priv))
 
 /* Having a GuC is not the same as using a GuC */
-#define USES_GUC(dev_priv)             intel_uc_is_using_guc()
-#define USES_GUC_SUBMISSION(dev_priv)  intel_uc_is_using_guc_submission()
-#define USES_HUC(dev_priv)             intel_uc_is_using_huc()
+#define USES_GUC(dev_priv)             intel_uc_is_using_guc(dev_priv)
+#define USES_GUC_SUBMISSION(dev_priv)  intel_uc_is_using_guc_submission(dev_priv)
+#define USES_HUC(dev_priv)             intel_uc_is_using_huc(dev_priv)
 
-#define HAS_POOLED_EU(dev_priv)        ((dev_priv)->info.has_pooled_eu)
+#define HAS_POOLED_EU(dev_priv)        (INTEL_INFO(dev_priv)->has_pooled_eu)
 
 #define INTEL_PCH_DEVICE_ID_MASK               0xff80
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE           0x3b00
@@ -2546,12 +2560,12 @@ intel_info(const struct drm_i915_private *dev_priv)
 #define HAS_PCH_NOP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_NOP)
 #define HAS_PCH_SPLIT(dev_priv) (INTEL_PCH_TYPE(dev_priv) != PCH_NONE)
 
-#define HAS_GMCH_DISPLAY(dev_priv) ((dev_priv)->info.display.has_gmch_display)
+#define HAS_GMCH_DISPLAY(dev_priv) (INTEL_INFO(dev_priv)->display.has_gmch_display)
 
 #define HAS_LSPCON(dev_priv) (INTEL_GEN(dev_priv) >= 9)
 
 /* DPF == dynamic parity feature */
-#define HAS_L3_DPF(dev_priv) ((dev_priv)->info.has_l3_dpf)
+#define HAS_L3_DPF(dev_priv) (INTEL_INFO(dev_priv)->has_l3_dpf)
 #define NUM_L3_SLICES(dev_priv) (IS_HSW_GT3(dev_priv) ? \
                                 2 : HAS_L3_DPF(dev_priv))
 
@@ -2601,19 +2615,7 @@ extern const struct dev_pm_ops i915_pm_ops;
 extern int i915_driver_load(struct pci_dev *pdev,
                            const struct pci_device_id *ent);
 extern void i915_driver_unload(struct drm_device *dev);
-extern int intel_gpu_reset(struct drm_i915_private *dev_priv, u32 engine_mask);
-extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv);
-
-extern void i915_reset(struct drm_i915_private *i915,
-                      unsigned int stalled_mask,
-                      const char *reason);
-extern int i915_reset_engine(struct intel_engine_cs *engine,
-                            const char *reason);
-
-extern bool intel_has_reset_engine(struct drm_i915_private *dev_priv);
-extern int intel_reset_guc(struct drm_i915_private *dev_priv);
-extern int intel_guc_reset_engine(struct intel_guc *guc,
-                                 struct intel_engine_cs *engine);
+
 extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine);
 extern void intel_hangcheck_init(struct drm_i915_private *dev_priv);
 extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
@@ -2656,20 +2658,11 @@ static inline void i915_queue_hangcheck(struct drm_i915_private *dev_priv)
                           &dev_priv->gpu_error.hangcheck_work, delay);
 }
 
-__printf(4, 5)
-void i915_handle_error(struct drm_i915_private *dev_priv,
-                      u32 engine_mask,
-                      unsigned long flags,
-                      const char *fmt, ...);
-#define I915_ERROR_CAPTURE BIT(0)
-
 extern void intel_irq_init(struct drm_i915_private *dev_priv);
 extern void intel_irq_fini(struct drm_i915_private *dev_priv);
 int intel_irq_install(struct drm_i915_private *dev_priv);
 void intel_irq_uninstall(struct drm_i915_private *dev_priv);
 
-void i915_clear_error_registers(struct drm_i915_private *dev_priv);
-
 static inline bool intel_gvt_active(struct drm_i915_private *dev_priv)
 {
        return dev_priv->gvt;
@@ -2693,45 +2686,45 @@ i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
 void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv);
 void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv);
 void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv,
-                                  uint32_t mask,
-                                  uint32_t bits);
+                                  u32 mask,
+                                  u32 bits);
 void ilk_update_display_irq(struct drm_i915_private *dev_priv,
-                           uint32_t interrupt_mask,
-                           uint32_t enabled_irq_mask);
+                           u32 interrupt_mask,
+                           u32 enabled_irq_mask);
 static inline void
-ilk_enable_display_irq(struct drm_i915_private *dev_priv, uint32_t bits)
+ilk_enable_display_irq(struct drm_i915_private *dev_priv, u32 bits)
 {
        ilk_update_display_irq(dev_priv, bits, bits);
 }
 static inline void
-ilk_disable_display_irq(struct drm_i915_private *dev_priv, uint32_t bits)
+ilk_disable_display_irq(struct drm_i915_private *dev_priv, u32 bits)
 {
        ilk_update_display_irq(dev_priv, bits, 0);
 }
 void bdw_update_pipe_irq(struct drm_i915_private *dev_priv,
                         enum pipe pipe,
-                        uint32_t interrupt_mask,
-                        uint32_t enabled_irq_mask);
+                        u32 interrupt_mask,
+                        u32 enabled_irq_mask);
 static inline void bdw_enable_pipe_irq(struct drm_i915_private *dev_priv,
-                                      enum pipe pipe, uint32_t bits)
+                                      enum pipe pipe, u32 bits)
 {
        bdw_update_pipe_irq(dev_priv, pipe, bits, bits);
 }
 static inline void bdw_disable_pipe_irq(struct drm_i915_private *dev_priv,
-                                       enum pipe pipe, uint32_t bits)
+                                       enum pipe pipe, u32 bits)
 {
        bdw_update_pipe_irq(dev_priv, pipe, bits, 0);
 }
 void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
-                                 uint32_t interrupt_mask,
-                                 uint32_t enabled_irq_mask);
+                                 u32 interrupt_mask,
+                                 u32 enabled_irq_mask);
 static inline void
-ibx_enable_display_interrupt(struct drm_i915_private *dev_priv, uint32_t bits)
+ibx_enable_display_interrupt(struct drm_i915_private *dev_priv, u32 bits)
 {
        ibx_display_interrupt_update(dev_priv, bits, bits);
 }
 static inline void
-ibx_disable_display_interrupt(struct drm_i915_private *dev_priv, uint32_t bits)
+ibx_disable_display_interrupt(struct drm_i915_private *dev_priv, u32 bits)
 {
        ibx_display_interrupt_update(dev_priv, bits, 0);
 }
@@ -2916,13 +2909,13 @@ i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj)
        __i915_gem_object_unpin_pages(obj);
 }
 
-enum i915_mm_subclass { /* lockdep subclass for obj->mm.lock */
+enum i915_mm_subclass { /* lockdep subclass for obj->mm.lock/struct_mutex */
        I915_MM_NORMAL = 0,
-       I915_MM_SHRINKER
+       I915_MM_SHRINKER /* called "recursively" from direct-reclaim-esque */
 };
 
-void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj,
-                                enum i915_mm_subclass subclass);
+int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj,
+                               enum i915_mm_subclass subclass);
 void __i915_gem_object_invalidate(struct drm_i915_gem_object *obj);
 
 enum i915_map_type {
@@ -2991,7 +2984,7 @@ int i915_gem_dumb_create(struct drm_file *file_priv,
                         struct drm_device *dev,
                         struct drm_mode_create_dumb *args);
 int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev,
-                     uint32_t handle, uint64_t *offset);
+                     u32 handle, u64 *offset);
 int i915_gem_mmap_gtt_version(void);
 
 void i915_gem_track_fb(struct drm_i915_gem_object *old,
@@ -3034,18 +3027,8 @@ static inline u32 i915_reset_engine_count(struct i915_gpu_error *error,
        return READ_ONCE(error->reset_engine_count[engine->id]);
 }
 
-struct i915_request *
-i915_gem_reset_prepare_engine(struct intel_engine_cs *engine);
-int i915_gem_reset_prepare(struct drm_i915_private *dev_priv);
-void i915_gem_reset(struct drm_i915_private *dev_priv,
-                   unsigned int stalled_mask);
-void i915_gem_reset_finish_engine(struct intel_engine_cs *engine);
-void i915_gem_reset_finish(struct drm_i915_private *dev_priv);
 void i915_gem_set_wedged(struct drm_i915_private *dev_priv);
 bool i915_gem_unset_wedged(struct drm_i915_private *dev_priv);
-void i915_gem_reset_engine(struct intel_engine_cs *engine,
-                          struct i915_request *request,
-                          bool stalled);
 
 void i915_gem_init_mmio(struct drm_i915_private *i915);
 int __must_check i915_gem_init(struct drm_i915_private *dev_priv);
@@ -3142,7 +3125,7 @@ int i915_perf_remove_config_ioctl(struct drm_device *dev, void *data,
                                  struct drm_file *file);
 void i915_oa_init_reg_state(struct intel_engine_cs *engine,
                            struct i915_gem_context *ctx,
-                           uint32_t *reg_state);
+                           u32 *reg_state);
 
 /* i915_gem_evict.c */
 int __must_check i915_gem_evict_something(struct i915_address_space *vm,
@@ -3204,7 +3187,8 @@ unsigned long i915_gem_shrink(struct drm_i915_private *i915,
 unsigned long i915_gem_shrink_all(struct drm_i915_private *i915);
 void i915_gem_shrinker_register(struct drm_i915_private *i915);
 void i915_gem_shrinker_unregister(struct drm_i915_private *i915);
-void i915_gem_shrinker_taints_mutex(struct mutex *mutex);
+void i915_gem_shrinker_taints_mutex(struct drm_i915_private *i915,
+                                   struct mutex *mutex);
 
 /* i915_gem_tiling.c */
 static inline bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
@@ -3313,7 +3297,7 @@ static inline void intel_unregister_dsm_handler(void) { return; }
 static inline struct intel_device_info *
 mkwrite_device_info(struct drm_i915_private *dev_priv)
 {
-       return (struct intel_device_info *)&dev_priv->info;
+       return (struct intel_device_info *)INTEL_INFO(dev_priv);
 }
 
 /* modesetting */
@@ -3393,10 +3377,10 @@ bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
                            enum dpio_phy phy);
 bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv,
                              enum dpio_phy phy);
-uint8_t bxt_ddi_phy_calc_lane_lat_optim_mask(uint8_t lane_count);
+u8 bxt_ddi_phy_calc_lane_lat_optim_mask(u8 lane_count);
 void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder,
-                                    uint8_t lane_lat_optim_mask);
-uint8_t bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder);
+                                    u8 lane_lat_optim_mask);
+u8 bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder);
 
 void chv_set_phy_signal_level(struct intel_encoder *encoder,
                              u32 deemph_reg_value, u32 margin_reg_value,
@@ -3599,90 +3583,6 @@ wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms)
        }
 }
 
-static inline bool
-__i915_request_irq_complete(const struct i915_request *rq)
-{
-       struct intel_engine_cs *engine = rq->engine;
-       u32 seqno;
-
-       /* Note that the engine may have wrapped around the seqno, and
-        * so our request->global_seqno will be ahead of the hardware,
-        * even though it completed the request before wrapping. We catch
-        * this by kicking all the waiters before resetting the seqno
-        * in hardware, and also signal the fence.
-        */
-       if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags))
-               return true;
-
-       /* The request was dequeued before we were awoken. We check after
-        * inspecting the hw to confirm that this was the same request
-        * that generated the HWS update. The memory barriers within
-        * the request execution are sufficient to ensure that a check
-        * after reading the value from hw matches this request.
-        */
-       seqno = i915_request_global_seqno(rq);
-       if (!seqno)
-               return false;
-
-       /* Before we do the heavier coherent read of the seqno,
-        * check the value (hopefully) in the CPU cacheline.
-        */
-       if (__i915_request_completed(rq, seqno))
-               return true;
-
-       /* Ensure our read of the seqno is coherent so that we
-        * do not "miss an interrupt" (i.e. if this is the last
-        * request and the seqno write from the GPU is not visible
-        * by the time the interrupt fires, we will see that the
-        * request is incomplete and go back to sleep awaiting
-        * another interrupt that will never come.)
-        *
-        * Strictly, we only need to do this once after an interrupt,
-        * but it is easier and safer to do it every time the waiter
-        * is woken.
-        */
-       if (engine->irq_seqno_barrier &&
-           test_and_clear_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted)) {
-               struct intel_breadcrumbs *b = &engine->breadcrumbs;
-
-               /* The ordering of irq_posted versus applying the barrier
-                * is crucial. The clearing of the current irq_posted must
-                * be visible before we perform the barrier operation,
-                * such that if a subsequent interrupt arrives, irq_posted
-                * is reasserted and our task rewoken (which causes us to
-                * do another __i915_request_irq_complete() immediately
-                * and reapply the barrier). Conversely, if the clear
-                * occurs after the barrier, then an interrupt that arrived
-                * whilst we waited on the barrier would not trigger a
-                * barrier on the next pass, and the read may not see the
-                * seqno update.
-                */
-               engine->irq_seqno_barrier(engine);
-
-               /* If we consume the irq, but we are no longer the bottom-half,
-                * the real bottom-half may not have serialised their own
-                * seqno check with the irq-barrier (i.e. may have inspected
-                * the seqno before we believe it coherent since they see
-                * irq_posted == false but we are still running).
-                */
-               spin_lock_irq(&b->irq_lock);
-               if (b->irq_wait && b->irq_wait->tsk != current)
-                       /* Note that if the bottom-half is changed as we
-                        * are sending the wake-up, the new bottom-half will
-                        * be woken by whomever made the change. We only have
-                        * to worry about when we steal the irq-posted for
-                        * ourself.
-                        */
-                       wake_up_process(b->irq_wait->tsk);
-               spin_unlock_irq(&b->irq_lock);
-
-               if (__i915_request_completed(rq, seqno))
-                       return true;
-       }
-
-       return false;
-}
-
 void i915_memcpy_init_early(struct drm_i915_private *dev_priv);
 bool i915_memcpy_from_wc(void *dst, const void *src, unsigned long len);
 
index 216f52b744a637fca6406fe31a25f5d5befa4c2c..b359390ba22c09b46d19d75697ccafb78ac8c148 100644 (file)
  *
  */
 
-#include <drm/drmP.h>
 #include <drm/drm_vma_manager.h>
 #include <drm/i915_drm.h>
-#include "i915_drv.h"
-#include "i915_gem_clflush.h"
-#include "i915_vgpu.h"
-#include "i915_trace.h"
-#include "intel_drv.h"
-#include "intel_frontbuffer.h"
-#include "intel_mocs.h"
-#include "intel_workarounds.h"
-#include "i915_gemfs.h"
 #include <linux/dma-fence-array.h>
 #include <linux/kthread.h>
 #include <linux/reservation.h>
 #include <linux/pci.h>
 #include <linux/dma-buf.h>
 
+#include "i915_drv.h"
+#include "i915_gem_clflush.h"
+#include "i915_gemfs.h"
+#include "i915_reset.h"
+#include "i915_trace.h"
+#include "i915_vgpu.h"
+
+#include "intel_drv.h"
+#include "intel_frontbuffer.h"
+#include "intel_mocs.h"
+#include "intel_workarounds.h"
+
 static void i915_gem_flush_free_objects(struct drm_i915_private *i915);
 
 static bool cpu_write_needs_clflush(struct drm_i915_gem_object *obj)
@@ -139,6 +141,8 @@ int i915_mutex_lock_interruptible(struct drm_device *dev)
 
 static u32 __i915_gem_park(struct drm_i915_private *i915)
 {
+       intel_wakeref_t wakeref;
+
        GEM_TRACE("\n");
 
        lockdep_assert_held(&i915->drm.struct_mutex);
@@ -169,14 +173,13 @@ static u32 __i915_gem_park(struct drm_i915_private *i915)
        i915_pmu_gt_parked(i915);
        i915_vma_parked(i915);
 
-       i915->gt.awake = false;
+       wakeref = fetch_and_zero(&i915->gt.awake);
+       GEM_BUG_ON(!wakeref);
 
        if (INTEL_GEN(i915) >= 6)
                gen6_rps_idle(i915);
 
-       intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ);
-
-       intel_runtime_pm_put(i915);
+       intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ, wakeref);
 
        return i915->gt.epoch;
 }
@@ -201,12 +204,11 @@ void i915_gem_unpark(struct drm_i915_private *i915)
 
        lockdep_assert_held(&i915->drm.struct_mutex);
        GEM_BUG_ON(!i915->gt.active_requests);
+       assert_rpm_wakelock_held(i915);
 
        if (i915->gt.awake)
                return;
 
-       intel_runtime_pm_get_noresume(i915);
-
        /*
         * It seems that the DMC likes to transition between the DC states a lot
         * when there are no connected displays (no active power domains) during
@@ -218,9 +220,9 @@ void i915_gem_unpark(struct drm_i915_private *i915)
         * Work around it by grabbing a GT IRQ power domain whilst there is any
         * GT activity, preventing any DC state transitions.
         */
-       intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
+       i915->gt.awake = intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
+       GEM_BUG_ON(!i915->gt.awake);
 
-       i915->gt.awake = true;
        if (unlikely(++i915->gt.epoch == 0)) /* keep 0 as invalid */
                i915->gt.epoch = 1;
 
@@ -711,8 +713,8 @@ void i915_gem_object_free(struct drm_i915_gem_object *obj)
 static int
 i915_gem_create(struct drm_file *file,
                struct drm_i915_private *dev_priv,
-               uint64_t size,
-               uint32_t *handle_p)
+               u64 size,
+               u32 *handle_p)
 {
        struct drm_i915_gem_object *obj;
        int ret;
@@ -783,6 +785,8 @@ fb_write_origin(struct drm_i915_gem_object *obj, unsigned int domain)
 
 void i915_gem_flush_ggtt_writes(struct drm_i915_private *dev_priv)
 {
+       intel_wakeref_t wakeref;
+
        /*
         * No actual flushing is required for the GTT write domain for reads
         * from the GTT domain. Writes to it "immediately" go to main memory
@@ -809,13 +813,13 @@ void i915_gem_flush_ggtt_writes(struct drm_i915_private *dev_priv)
 
        i915_gem_chipset_flush(dev_priv);
 
-       intel_runtime_pm_get(dev_priv);
-       spin_lock_irq(&dev_priv->uncore.lock);
+       with_intel_runtime_pm(dev_priv, wakeref) {
+               spin_lock_irq(&dev_priv->uncore.lock);
 
-       POSTING_READ_FW(RING_HEAD(RENDER_RING_BASE));
+               POSTING_READ_FW(RING_HEAD(RENDER_RING_BASE));
 
-       spin_unlock_irq(&dev_priv->uncore.lock);
-       intel_runtime_pm_put(dev_priv);
+               spin_unlock_irq(&dev_priv->uncore.lock);
+       }
 }
 
 static void
@@ -859,58 +863,6 @@ flush_write_domain(struct drm_i915_gem_object *obj, unsigned int flush_domains)
        obj->write_domain = 0;
 }
 
-static inline int
-__copy_to_user_swizzled(char __user *cpu_vaddr,
-                       const char *gpu_vaddr, int gpu_offset,
-                       int length)
-{
-       int ret, cpu_offset = 0;
-
-       while (length > 0) {
-               int cacheline_end = ALIGN(gpu_offset + 1, 64);
-               int this_length = min(cacheline_end - gpu_offset, length);
-               int swizzled_gpu_offset = gpu_offset ^ 64;
-
-               ret = __copy_to_user(cpu_vaddr + cpu_offset,
-                                    gpu_vaddr + swizzled_gpu_offset,
-                                    this_length);
-               if (ret)
-                       return ret + length;
-
-               cpu_offset += this_length;
-               gpu_offset += this_length;
-               length -= this_length;
-       }
-
-       return 0;
-}
-
-static inline int
-__copy_from_user_swizzled(char *gpu_vaddr, int gpu_offset,
-                         const char __user *cpu_vaddr,
-                         int length)
-{
-       int ret, cpu_offset = 0;
-
-       while (length > 0) {
-               int cacheline_end = ALIGN(gpu_offset + 1, 64);
-               int this_length = min(cacheline_end - gpu_offset, length);
-               int swizzled_gpu_offset = gpu_offset ^ 64;
-
-               ret = __copy_from_user(gpu_vaddr + swizzled_gpu_offset,
-                                      cpu_vaddr + cpu_offset,
-                                      this_length);
-               if (ret)
-                       return ret + length;
-
-               cpu_offset += this_length;
-               gpu_offset += this_length;
-               length -= this_length;
-       }
-
-       return 0;
-}
-
 /*
  * Pins the specified object's pages and synchronizes the object with
  * GPU accesses. Sets needs_clflush to non-zero if the caller should
@@ -1030,72 +982,23 @@ err_unpin:
        return ret;
 }
 
-static void
-shmem_clflush_swizzled_range(char *addr, unsigned long length,
-                            bool swizzled)
-{
-       if (unlikely(swizzled)) {
-               unsigned long start = (unsigned long) addr;
-               unsigned long end = (unsigned long) addr + length;
-
-               /* For swizzling simply ensure that we always flush both
-                * channels. Lame, but simple and it works. Swizzled
-                * pwrite/pread is far from a hotpath - current userspace
-                * doesn't use it at all. */
-               start = round_down(start, 128);
-               end = round_up(end, 128);
-
-               drm_clflush_virt_range((void *)start, end - start);
-       } else {
-               drm_clflush_virt_range(addr, length);
-       }
-
-}
-
-/* Only difference to the fast-path function is that this can handle bit17
- * and uses non-atomic copy and kmap functions. */
 static int
-shmem_pread_slow(struct page *page, int offset, int length,
-                char __user *user_data,
-                bool page_do_bit17_swizzling, bool needs_clflush)
+shmem_pread(struct page *page, int offset, int len, char __user *user_data,
+           bool needs_clflush)
 {
        char *vaddr;
        int ret;
 
        vaddr = kmap(page);
-       if (needs_clflush)
-               shmem_clflush_swizzled_range(vaddr + offset, length,
-                                            page_do_bit17_swizzling);
 
-       if (page_do_bit17_swizzling)
-               ret = __copy_to_user_swizzled(user_data, vaddr, offset, length);
-       else
-               ret = __copy_to_user(user_data, vaddr + offset, length);
-       kunmap(page);
-
-       return ret ? - EFAULT : 0;
-}
-
-static int
-shmem_pread(struct page *page, int offset, int length, char __user *user_data,
-           bool page_do_bit17_swizzling, bool needs_clflush)
-{
-       int ret;
+       if (needs_clflush)
+               drm_clflush_virt_range(vaddr + offset, len);
 
-       ret = -ENODEV;
-       if (!page_do_bit17_swizzling) {
-               char *vaddr = kmap_atomic(page);
+       ret = __copy_to_user(user_data, vaddr + offset, len);
 
-               if (needs_clflush)
-                       drm_clflush_virt_range(vaddr + offset, length);
-               ret = __copy_to_user_inatomic(user_data, vaddr + offset, length);
-               kunmap_atomic(vaddr);
-       }
-       if (ret == 0)
-               return 0;
+       kunmap(page);
 
-       return shmem_pread_slow(page, offset, length, user_data,
-                               page_do_bit17_swizzling, needs_clflush);
+       return ret ? -EFAULT : 0;
 }
 
 static int
@@ -1104,15 +1007,10 @@ i915_gem_shmem_pread(struct drm_i915_gem_object *obj,
 {
        char __user *user_data;
        u64 remain;
-       unsigned int obj_do_bit17_swizzling;
        unsigned int needs_clflush;
        unsigned int idx, offset;
        int ret;
 
-       obj_do_bit17_swizzling = 0;
-       if (i915_gem_object_needs_bit17_swizzle(obj))
-               obj_do_bit17_swizzling = BIT(17);
-
        ret = mutex_lock_interruptible(&obj->base.dev->struct_mutex);
        if (ret)
                return ret;
@@ -1130,7 +1028,6 @@ i915_gem_shmem_pread(struct drm_i915_gem_object *obj,
                unsigned int length = min_t(u64, remain, PAGE_SIZE - offset);
 
                ret = shmem_pread(page, offset, length, user_data,
-                                 page_to_phys(page) & obj_do_bit17_swizzling,
                                  needs_clflush);
                if (ret)
                        break;
@@ -1174,6 +1071,7 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
 {
        struct drm_i915_private *i915 = to_i915(obj->base.dev);
        struct i915_ggtt *ggtt = &i915->ggtt;
+       intel_wakeref_t wakeref;
        struct drm_mm_node node;
        struct i915_vma *vma;
        void __user *user_data;
@@ -1184,7 +1082,7 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
        if (ret)
                return ret;
 
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
        vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
                                       PIN_MAPPABLE |
                                       PIN_NONFAULT |
@@ -1257,7 +1155,7 @@ out_unpin:
                i915_vma_unpin(vma);
        }
 out_unlock:
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
        mutex_unlock(&i915->drm.struct_mutex);
 
        return ret;
@@ -1358,6 +1256,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
 {
        struct drm_i915_private *i915 = to_i915(obj->base.dev);
        struct i915_ggtt *ggtt = &i915->ggtt;
+       intel_wakeref_t wakeref;
        struct drm_mm_node node;
        struct i915_vma *vma;
        u64 remain, offset;
@@ -1376,13 +1275,14 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
                 * This easily dwarfs any performance advantage from
                 * using the cache bypass of indirect GGTT access.
                 */
-               if (!intel_runtime_pm_get_if_in_use(i915)) {
+               wakeref = intel_runtime_pm_get_if_in_use(i915);
+               if (!wakeref) {
                        ret = -EFAULT;
                        goto out_unlock;
                }
        } else {
                /* No backing pages, no fallback, we must force GGTT access */
-               intel_runtime_pm_get(i915);
+               wakeref = intel_runtime_pm_get(i915);
        }
 
        vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
@@ -1464,39 +1364,12 @@ out_unpin:
                i915_vma_unpin(vma);
        }
 out_rpm:
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
 out_unlock:
        mutex_unlock(&i915->drm.struct_mutex);
        return ret;
 }
 
-static int
-shmem_pwrite_slow(struct page *page, int offset, int length,
-                 char __user *user_data,
-                 bool page_do_bit17_swizzling,
-                 bool needs_clflush_before,
-                 bool needs_clflush_after)
-{
-       char *vaddr;
-       int ret;
-
-       vaddr = kmap(page);
-       if (unlikely(needs_clflush_before || page_do_bit17_swizzling))
-               shmem_clflush_swizzled_range(vaddr + offset, length,
-                                            page_do_bit17_swizzling);
-       if (page_do_bit17_swizzling)
-               ret = __copy_from_user_swizzled(vaddr, offset, user_data,
-                                               length);
-       else
-               ret = __copy_from_user(vaddr + offset, user_data, length);
-       if (needs_clflush_after)
-               shmem_clflush_swizzled_range(vaddr + offset, length,
-                                            page_do_bit17_swizzling);
-       kunmap(page);
-
-       return ret ? -EFAULT : 0;
-}
-
 /* Per-page copy function for the shmem pwrite fastpath.
  * Flushes invalid cachelines before writing to the target if
  * needs_clflush_before is set and flushes out any written cachelines after
@@ -1504,31 +1377,24 @@ shmem_pwrite_slow(struct page *page, int offset, int length,
  */
 static int
 shmem_pwrite(struct page *page, int offset, int len, char __user *user_data,
-            bool page_do_bit17_swizzling,
             bool needs_clflush_before,
             bool needs_clflush_after)
 {
+       char *vaddr;
        int ret;
 
-       ret = -ENODEV;
-       if (!page_do_bit17_swizzling) {
-               char *vaddr = kmap_atomic(page);
+       vaddr = kmap(page);
 
-               if (needs_clflush_before)
-                       drm_clflush_virt_range(vaddr + offset, len);
-               ret = __copy_from_user_inatomic(vaddr + offset, user_data, len);
-               if (needs_clflush_after)
-                       drm_clflush_virt_range(vaddr + offset, len);
+       if (needs_clflush_before)
+               drm_clflush_virt_range(vaddr + offset, len);
 
-               kunmap_atomic(vaddr);
-       }
-       if (ret == 0)
-               return ret;
+       ret = __copy_from_user(vaddr + offset, user_data, len);
+       if (!ret && needs_clflush_after)
+               drm_clflush_virt_range(vaddr + offset, len);
+
+       kunmap(page);
 
-       return shmem_pwrite_slow(page, offset, len, user_data,
-                                page_do_bit17_swizzling,
-                                needs_clflush_before,
-                                needs_clflush_after);
+       return ret ? -EFAULT : 0;
 }
 
 static int
@@ -1538,7 +1404,6 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
        struct drm_i915_private *i915 = to_i915(obj->base.dev);
        void __user *user_data;
        u64 remain;
-       unsigned int obj_do_bit17_swizzling;
        unsigned int partial_cacheline_write;
        unsigned int needs_clflush;
        unsigned int offset, idx;
@@ -1553,10 +1418,6 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
        if (ret)
                return ret;
 
-       obj_do_bit17_swizzling = 0;
-       if (i915_gem_object_needs_bit17_swizzle(obj))
-               obj_do_bit17_swizzling = BIT(17);
-
        /* If we don't overwrite a cacheline completely we need to be
         * careful to have up-to-date data by first clflushing. Don't
         * overcomplicate things and flush the entire patch.
@@ -1573,7 +1434,6 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
                unsigned int length = min_t(u64, remain, PAGE_SIZE - offset);
 
                ret = shmem_pwrite(page, offset, length, user_data,
-                                  page_to_phys(page) & obj_do_bit17_swizzling,
                                   (offset | length) & partial_cacheline_write,
                                   needs_clflush & CLFLUSH_AFTER);
                if (ret)
@@ -1713,8 +1573,8 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
 {
        struct drm_i915_gem_set_domain *args = data;
        struct drm_i915_gem_object *obj;
-       uint32_t read_domains = args->read_domains;
-       uint32_t write_domain = args->write_domain;
+       u32 read_domains = args->read_domains;
+       u32 write_domain = args->write_domain;
        int err;
 
        /* Only handle setting domains to types used by the CPU. */
@@ -1896,7 +1756,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
        if (IS_ERR((void *)addr))
                return addr;
 
-       args->addr_ptr = (uint64_t) addr;
+       args->addr_ptr = (u64)addr;
 
        return 0;
 }
@@ -2009,6 +1869,7 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct i915_ggtt *ggtt = &dev_priv->ggtt;
        bool write = area->vm_flags & VM_WRITE;
+       intel_wakeref_t wakeref;
        struct i915_vma *vma;
        pgoff_t page_offset;
        int ret;
@@ -2038,7 +1899,7 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
        if (ret)
                goto err;
 
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
        ret = i915_mutex_lock_interruptible(dev);
        if (ret)
@@ -2116,7 +1977,7 @@ err_unpin:
 err_unlock:
        mutex_unlock(&dev->struct_mutex);
 err_rpm:
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
        i915_gem_object_unpin_pages(obj);
 err:
        switch (ret) {
@@ -2189,6 +2050,7 @@ void
 i915_gem_release_mmap(struct drm_i915_gem_object *obj)
 {
        struct drm_i915_private *i915 = to_i915(obj->base.dev);
+       intel_wakeref_t wakeref;
 
        /* Serialisation between user GTT access and our code depends upon
         * revoking the CPU's PTE whilst the mutex is held. The next user
@@ -2199,7 +2061,7 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj)
         * wakeref.
         */
        lockdep_assert_held(&i915->drm.struct_mutex);
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
        if (!obj->userfault_count)
                goto out;
@@ -2216,7 +2078,7 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj)
        wmb();
 
 out:
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
 }
 
 void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv)
@@ -2296,8 +2158,8 @@ static void i915_gem_object_free_mmap_offset(struct drm_i915_gem_object *obj)
 int
 i915_gem_mmap_gtt(struct drm_file *file,
                  struct drm_device *dev,
-                 uint32_t handle,
-                 uint64_t *offset)
+                 u32 handle,
+                 u64 *offset)
 {
        struct drm_i915_gem_object *obj;
        int ret;
@@ -2444,8 +2306,8 @@ __i915_gem_object_unset_pages(struct drm_i915_gem_object *obj)
        struct sg_table *pages;
 
        pages = fetch_and_zero(&obj->mm.pages);
-       if (!pages)
-               return NULL;
+       if (IS_ERR_OR_NULL(pages))
+               return pages;
 
        spin_lock(&i915->mm.obj_lock);
        list_del(&obj->mm.link);
@@ -2469,22 +2331,23 @@ __i915_gem_object_unset_pages(struct drm_i915_gem_object *obj)
        return pages;
 }
 
-void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj,
-                                enum i915_mm_subclass subclass)
+int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj,
+                               enum i915_mm_subclass subclass)
 {
        struct sg_table *pages;
+       int ret;
 
        if (i915_gem_object_has_pinned_pages(obj))
-               return;
+               return -EBUSY;
 
        GEM_BUG_ON(obj->bind_count);
-       if (!i915_gem_object_has_pages(obj))
-               return;
 
        /* May be called by shrinker from within get_pages() (on another bo) */
        mutex_lock_nested(&obj->mm.lock, subclass);
-       if (unlikely(atomic_read(&obj->mm.pages_pin_count)))
+       if (unlikely(atomic_read(&obj->mm.pages_pin_count))) {
+               ret = -EBUSY;
                goto unlock;
+       }
 
        /*
         * ->put_pages might need to allocate memory for the bit17 swizzle
@@ -2492,11 +2355,24 @@ void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj,
         * lists early.
         */
        pages = __i915_gem_object_unset_pages(obj);
+
+       /*
+        * XXX Temporary hijinx to avoid updating all backends to handle
+        * NULL pages. In the future, when we have more asynchronous
+        * get_pages backends we should be better able to handle the
+        * cancellation of the async task in a more uniform manner.
+        */
+       if (!pages && !i915_gem_object_needs_async_cancel(obj))
+               pages = ERR_PTR(-EINVAL);
+
        if (!IS_ERR(pages))
                obj->ops->put_pages(obj, pages);
 
+       ret = 0;
 unlock:
        mutex_unlock(&obj->mm.lock);
+
+       return ret;
 }
 
 bool i915_sg_trim(struct sg_table *orig_st)
@@ -3000,61 +2876,6 @@ i915_gem_object_pwrite_gtt(struct drm_i915_gem_object *obj,
        return 0;
 }
 
-static void i915_gem_client_mark_guilty(struct drm_i915_file_private *file_priv,
-                                       const struct i915_gem_context *ctx)
-{
-       unsigned int score;
-       unsigned long prev_hang;
-
-       if (i915_gem_context_is_banned(ctx))
-               score = I915_CLIENT_SCORE_CONTEXT_BAN;
-       else
-               score = 0;
-
-       prev_hang = xchg(&file_priv->hang_timestamp, jiffies);
-       if (time_before(jiffies, prev_hang + I915_CLIENT_FAST_HANG_JIFFIES))
-               score += I915_CLIENT_SCORE_HANG_FAST;
-
-       if (score) {
-               atomic_add(score, &file_priv->ban_score);
-
-               DRM_DEBUG_DRIVER("client %s: gained %u ban score, now %u\n",
-                                ctx->name, score,
-                                atomic_read(&file_priv->ban_score));
-       }
-}
-
-static void i915_gem_context_mark_guilty(struct i915_gem_context *ctx)
-{
-       unsigned int score;
-       bool banned, bannable;
-
-       atomic_inc(&ctx->guilty_count);
-
-       bannable = i915_gem_context_is_bannable(ctx);
-       score = atomic_add_return(CONTEXT_SCORE_GUILTY, &ctx->ban_score);
-       banned = score >= CONTEXT_SCORE_BAN_THRESHOLD;
-
-       /* Cool contexts don't accumulate client ban score */
-       if (!bannable)
-               return;
-
-       if (banned) {
-               DRM_DEBUG_DRIVER("context %s: guilty %d, score %u, banned\n",
-                                ctx->name, atomic_read(&ctx->guilty_count),
-                                score);
-               i915_gem_context_set_banned(ctx);
-       }
-
-       if (!IS_ERR_OR_NULL(ctx->file_priv))
-               i915_gem_client_mark_guilty(ctx->file_priv, ctx);
-}
-
-static void i915_gem_context_mark_innocent(struct i915_gem_context *ctx)
-{
-       atomic_inc(&ctx->active_count);
-}
-
 struct i915_request *
 i915_gem_find_active_request(struct intel_engine_cs *engine)
 {
@@ -3085,366 +2906,6 @@ i915_gem_find_active_request(struct intel_engine_cs *engine)
        return active;
 }
 
-/*
- * Ensure irq handler finishes, and not run again.
- * Also return the active request so that we only search for it once.
- */
-struct i915_request *
-i915_gem_reset_prepare_engine(struct intel_engine_cs *engine)
-{
-       struct i915_request *request;
-
-       /*
-        * During the reset sequence, we must prevent the engine from
-        * entering RC6. As the context state is undefined until we restart
-        * the engine, if it does enter RC6 during the reset, the state
-        * written to the powercontext is undefined and so we may lose
-        * GPU state upon resume, i.e. fail to restart after a reset.
-        */
-       intel_uncore_forcewake_get(engine->i915, FORCEWAKE_ALL);
-
-       request = engine->reset.prepare(engine);
-       if (request && request->fence.error == -EIO)
-               request = ERR_PTR(-EIO); /* Previous reset failed! */
-
-       return request;
-}
-
-int i915_gem_reset_prepare(struct drm_i915_private *dev_priv)
-{
-       struct intel_engine_cs *engine;
-       struct i915_request *request;
-       enum intel_engine_id id;
-       int err = 0;
-
-       for_each_engine(engine, dev_priv, id) {
-               request = i915_gem_reset_prepare_engine(engine);
-               if (IS_ERR(request)) {
-                       err = PTR_ERR(request);
-                       continue;
-               }
-
-               engine->hangcheck.active_request = request;
-       }
-
-       i915_gem_revoke_fences(dev_priv);
-       intel_uc_sanitize(dev_priv);
-
-       return err;
-}
-
-static void engine_skip_context(struct i915_request *request)
-{
-       struct intel_engine_cs *engine = request->engine;
-       struct i915_gem_context *hung_ctx = request->gem_context;
-       struct i915_timeline *timeline = request->timeline;
-       unsigned long flags;
-
-       GEM_BUG_ON(timeline == &engine->timeline);
-
-       spin_lock_irqsave(&engine->timeline.lock, flags);
-       spin_lock(&timeline->lock);
-
-       list_for_each_entry_continue(request, &engine->timeline.requests, link)
-               if (request->gem_context == hung_ctx)
-                       i915_request_skip(request, -EIO);
-
-       list_for_each_entry(request, &timeline->requests, link)
-               i915_request_skip(request, -EIO);
-
-       spin_unlock(&timeline->lock);
-       spin_unlock_irqrestore(&engine->timeline.lock, flags);
-}
-
-/* Returns the request if it was guilty of the hang */
-static struct i915_request *
-i915_gem_reset_request(struct intel_engine_cs *engine,
-                      struct i915_request *request,
-                      bool stalled)
-{
-       /* The guilty request will get skipped on a hung engine.
-        *
-        * Users of client default contexts do not rely on logical
-        * state preserved between batches so it is safe to execute
-        * queued requests following the hang. Non default contexts
-        * rely on preserved state, so skipping a batch loses the
-        * evolution of the state and it needs to be considered corrupted.
-        * Executing more queued batches on top of corrupted state is
-        * risky. But we take the risk by trying to advance through
-        * the queued requests in order to make the client behaviour
-        * more predictable around resets, by not throwing away random
-        * amount of batches it has prepared for execution. Sophisticated
-        * clients can use gem_reset_stats_ioctl and dma fence status
-        * (exported via sync_file info ioctl on explicit fences) to observe
-        * when it loses the context state and should rebuild accordingly.
-        *
-        * The context ban, and ultimately the client ban, mechanism are safety
-        * valves if client submission ends up resulting in nothing more than
-        * subsequent hangs.
-        */
-
-       if (i915_request_completed(request)) {
-               GEM_TRACE("%s pardoned global=%d (fence %llx:%d), current %d\n",
-                         engine->name, request->global_seqno,
-                         request->fence.context, request->fence.seqno,
-                         intel_engine_get_seqno(engine));
-               stalled = false;
-       }
-
-       if (stalled) {
-               i915_gem_context_mark_guilty(request->gem_context);
-               i915_request_skip(request, -EIO);
-
-               /* If this context is now banned, skip all pending requests. */
-               if (i915_gem_context_is_banned(request->gem_context))
-                       engine_skip_context(request);
-       } else {
-               /*
-                * Since this is not the hung engine, it may have advanced
-                * since the hang declaration. Double check by refinding
-                * the active request at the time of the reset.
-                */
-               request = i915_gem_find_active_request(engine);
-               if (request) {
-                       unsigned long flags;
-
-                       i915_gem_context_mark_innocent(request->gem_context);
-                       dma_fence_set_error(&request->fence, -EAGAIN);
-
-                       /* Rewind the engine to replay the incomplete rq */
-                       spin_lock_irqsave(&engine->timeline.lock, flags);
-                       request = list_prev_entry(request, link);
-                       if (&request->link == &engine->timeline.requests)
-                               request = NULL;
-                       spin_unlock_irqrestore(&engine->timeline.lock, flags);
-               }
-       }
-
-       return request;
-}
-
-void i915_gem_reset_engine(struct intel_engine_cs *engine,
-                          struct i915_request *request,
-                          bool stalled)
-{
-       /*
-        * Make sure this write is visible before we re-enable the interrupt
-        * handlers on another CPU, as tasklet_enable() resolves to just
-        * a compiler barrier which is insufficient for our purpose here.
-        */
-       smp_store_mb(engine->irq_posted, 0);
-
-       if (request)
-               request = i915_gem_reset_request(engine, request, stalled);
-
-       /* Setup the CS to resume from the breadcrumb of the hung request */
-       engine->reset.reset(engine, request);
-}
-
-void i915_gem_reset(struct drm_i915_private *dev_priv,
-                   unsigned int stalled_mask)
-{
-       struct intel_engine_cs *engine;
-       enum intel_engine_id id;
-
-       lockdep_assert_held(&dev_priv->drm.struct_mutex);
-
-       i915_retire_requests(dev_priv);
-
-       for_each_engine(engine, dev_priv, id) {
-               struct intel_context *ce;
-
-               i915_gem_reset_engine(engine,
-                                     engine->hangcheck.active_request,
-                                     stalled_mask & ENGINE_MASK(id));
-               ce = fetch_and_zero(&engine->last_retired_context);
-               if (ce)
-                       intel_context_unpin(ce);
-
-               /*
-                * Ostensibily, we always want a context loaded for powersaving,
-                * so if the engine is idle after the reset, send a request
-                * to load our scratch kernel_context.
-                *
-                * More mysteriously, if we leave the engine idle after a reset,
-                * the next userspace batch may hang, with what appears to be
-                * an incoherent read by the CS (presumably stale TLB). An
-                * empty request appears sufficient to paper over the glitch.
-                */
-               if (intel_engine_is_idle(engine)) {
-                       struct i915_request *rq;
-
-                       rq = i915_request_alloc(engine,
-                                               dev_priv->kernel_context);
-                       if (!IS_ERR(rq))
-                               i915_request_add(rq);
-               }
-       }
-
-       i915_gem_restore_fences(dev_priv);
-}
-
-void i915_gem_reset_finish_engine(struct intel_engine_cs *engine)
-{
-       engine->reset.finish(engine);
-
-       intel_uncore_forcewake_put(engine->i915, FORCEWAKE_ALL);
-}
-
-void i915_gem_reset_finish(struct drm_i915_private *dev_priv)
-{
-       struct intel_engine_cs *engine;
-       enum intel_engine_id id;
-
-       lockdep_assert_held(&dev_priv->drm.struct_mutex);
-
-       for_each_engine(engine, dev_priv, id) {
-               engine->hangcheck.active_request = NULL;
-               i915_gem_reset_finish_engine(engine);
-       }
-}
-
-static void nop_submit_request(struct i915_request *request)
-{
-       unsigned long flags;
-
-       GEM_TRACE("%s fence %llx:%d -> -EIO\n",
-                 request->engine->name,
-                 request->fence.context, request->fence.seqno);
-       dma_fence_set_error(&request->fence, -EIO);
-
-       spin_lock_irqsave(&request->engine->timeline.lock, flags);
-       __i915_request_submit(request);
-       intel_engine_init_global_seqno(request->engine, request->global_seqno);
-       spin_unlock_irqrestore(&request->engine->timeline.lock, flags);
-}
-
-void i915_gem_set_wedged(struct drm_i915_private *i915)
-{
-       struct intel_engine_cs *engine;
-       enum intel_engine_id id;
-
-       GEM_TRACE("start\n");
-
-       if (GEM_SHOW_DEBUG()) {
-               struct drm_printer p = drm_debug_printer(__func__);
-
-               for_each_engine(engine, i915, id)
-                       intel_engine_dump(engine, &p, "%s\n", engine->name);
-       }
-
-       if (test_and_set_bit(I915_WEDGED, &i915->gpu_error.flags))
-               goto out;
-
-       /*
-        * First, stop submission to hw, but do not yet complete requests by
-        * rolling the global seqno forward (since this would complete requests
-        * for which we haven't set the fence error to EIO yet).
-        */
-       for_each_engine(engine, i915, id)
-               i915_gem_reset_prepare_engine(engine);
-
-       /* Even if the GPU reset fails, it should still stop the engines */
-       if (INTEL_GEN(i915) >= 5)
-               intel_gpu_reset(i915, ALL_ENGINES);
-
-       for_each_engine(engine, i915, id) {
-               engine->submit_request = nop_submit_request;
-               engine->schedule = NULL;
-       }
-       i915->caps.scheduler = 0;
-
-       /*
-        * Make sure no request can slip through without getting completed by
-        * either this call here to intel_engine_init_global_seqno, or the one
-        * in nop_submit_request.
-        */
-       synchronize_rcu();
-
-       /* Mark all executing requests as skipped */
-       for_each_engine(engine, i915, id)
-               engine->cancel_requests(engine);
-
-       for_each_engine(engine, i915, id) {
-               i915_gem_reset_finish_engine(engine);
-               intel_engine_wakeup(engine);
-       }
-
-out:
-       GEM_TRACE("end\n");
-
-       wake_up_all(&i915->gpu_error.reset_queue);
-}
-
-bool i915_gem_unset_wedged(struct drm_i915_private *i915)
-{
-       struct i915_timeline *tl;
-
-       lockdep_assert_held(&i915->drm.struct_mutex);
-       if (!test_bit(I915_WEDGED, &i915->gpu_error.flags))
-               return true;
-
-       GEM_TRACE("start\n");
-
-       /*
-        * Before unwedging, make sure that all pending operations
-        * are flushed and errored out - we may have requests waiting upon
-        * third party fences. We marked all inflight requests as EIO, and
-        * every execbuf since returned EIO, for consistency we want all
-        * the currently pending requests to also be marked as EIO, which
-        * is done inside our nop_submit_request - and so we must wait.
-        *
-        * No more can be submitted until we reset the wedged bit.
-        */
-       list_for_each_entry(tl, &i915->gt.timelines, link) {
-               struct i915_request *rq;
-
-               rq = i915_gem_active_peek(&tl->last_request,
-                                         &i915->drm.struct_mutex);
-               if (!rq)
-                       continue;
-
-               /*
-                * We can't use our normal waiter as we want to
-                * avoid recursively trying to handle the current
-                * reset. The basic dma_fence_default_wait() installs
-                * a callback for dma_fence_signal(), which is
-                * triggered by our nop handler (indirectly, the
-                * callback enables the signaler thread which is
-                * woken by the nop_submit_request() advancing the seqno
-                * and when the seqno passes the fence, the signaler
-                * then signals the fence waking us up).
-                */
-               if (dma_fence_default_wait(&rq->fence, true,
-                                          MAX_SCHEDULE_TIMEOUT) < 0)
-                       return false;
-       }
-       i915_retire_requests(i915);
-       GEM_BUG_ON(i915->gt.active_requests);
-
-       if (!intel_gpu_reset(i915, ALL_ENGINES))
-               intel_engines_sanitize(i915);
-
-       /*
-        * Undo nop_submit_request. We prevent all new i915 requests from
-        * being queued (by disallowing execbuf whilst wedged) so having
-        * waited for all active requests above, we know the system is idle
-        * and do not have to worry about a thread being inside
-        * engine->submit_request() as we swap over. So unlike installing
-        * the nop_submit_request on reset, we can do this from normal
-        * context and do not require stop_machine().
-        */
-       intel_engines_reset_default_submission(i915);
-       i915_gem_contexts_lost(i915);
-
-       GEM_TRACE("end\n");
-
-       smp_mb__before_atomic(); /* complete takeover before enabling execbuf */
-       clear_bit(I915_WEDGED, &i915->gpu_error.flags);
-
-       return true;
-}
-
 static void
 i915_gem_retire_work_handler(struct work_struct *work)
 {
@@ -4856,8 +4317,9 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
                                    struct llist_node *freed)
 {
        struct drm_i915_gem_object *obj, *on;
+       intel_wakeref_t wakeref;
 
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
        llist_for_each_entry_safe(obj, on, freed, freed) {
                struct i915_vma *vma, *vn;
 
@@ -4918,7 +4380,7 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
                if (on)
                        cond_resched();
        }
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
 }
 
 static void i915_gem_flush_free_objects(struct drm_i915_private *i915)
@@ -5027,13 +4489,13 @@ void __i915_gem_object_release_unless_active(struct drm_i915_gem_object *obj)
 
 void i915_gem_sanitize(struct drm_i915_private *i915)
 {
-       int err;
+       intel_wakeref_t wakeref;
 
        GEM_TRACE("\n");
 
        mutex_lock(&i915->drm.struct_mutex);
 
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
        intel_uncore_forcewake_get(i915, FORCEWAKE_ALL);
 
        /*
@@ -5053,14 +4515,10 @@ void i915_gem_sanitize(struct drm_i915_private *i915)
         * it may impact the display and we are uncertain about the stability
         * of the reset, so this could be applied to even earlier gen.
         */
-       err = -ENODEV;
-       if (INTEL_GEN(i915) >= 5 && intel_has_gpu_reset(i915))
-               err = WARN_ON(intel_gpu_reset(i915, ALL_ENGINES));
-       if (!err)
-               intel_engines_sanitize(i915);
+       intel_engines_sanitize(i915, false);
 
        intel_uncore_forcewake_put(i915, FORCEWAKE_ALL);
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
 
        i915_gem_contexts_lost(i915);
        mutex_unlock(&i915->drm.struct_mutex);
@@ -5068,11 +4526,12 @@ void i915_gem_sanitize(struct drm_i915_private *i915)
 
 int i915_gem_suspend(struct drm_i915_private *i915)
 {
+       intel_wakeref_t wakeref;
        int ret;
 
        GEM_TRACE("\n");
 
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
        intel_suspend_gt_powersave(i915);
 
        mutex_lock(&i915->drm.struct_mutex);
@@ -5124,12 +4583,12 @@ int i915_gem_suspend(struct drm_i915_private *i915)
        if (WARN_ON(!intel_engines_are_idle(i915)))
                i915_gem_set_wedged(i915); /* no hope, discard everything */
 
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
        return 0;
 
 err_unlock:
        mutex_unlock(&i915->drm.struct_mutex);
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
        return ret;
 }
 
@@ -5223,15 +4682,15 @@ void i915_gem_init_swizzling(struct drm_i915_private *dev_priv)
        I915_WRITE(DISP_ARB_CTL, I915_READ(DISP_ARB_CTL) |
                                 DISP_TILE_SURFACE_SWIZZLING);
 
-       if (IS_GEN5(dev_priv))
+       if (IS_GEN(dev_priv, 5))
                return;
 
        I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_SWZCTL);
-       if (IS_GEN6(dev_priv))
+       if (IS_GEN(dev_priv, 6))
                I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_SNB));
-       else if (IS_GEN7(dev_priv))
+       else if (IS_GEN(dev_priv, 7))
                I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_IVB));
-       else if (IS_GEN8(dev_priv))
+       else if (IS_GEN(dev_priv, 8))
                I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_BDW));
        else
                BUG();
@@ -5253,10 +4712,10 @@ static void init_unused_rings(struct drm_i915_private *dev_priv)
                init_unused_ring(dev_priv, SRB1_BASE);
                init_unused_ring(dev_priv, SRB2_BASE);
                init_unused_ring(dev_priv, SRB3_BASE);
-       } else if (IS_GEN2(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 2)) {
                init_unused_ring(dev_priv, SRB0_BASE);
                init_unused_ring(dev_priv, SRB1_BASE);
-       } else if (IS_GEN3(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 3)) {
                init_unused_ring(dev_priv, PRB1_BASE);
                init_unused_ring(dev_priv, PRB2_BASE);
        }
@@ -5580,7 +5039,7 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
        }
 
        ret = i915_gem_init_scratch(dev_priv,
-                                   IS_GEN2(dev_priv) ? SZ_256K : PAGE_SIZE);
+                                   IS_GEN(dev_priv, 2) ? SZ_256K : PAGE_SIZE);
        if (ret) {
                GEM_BUG_ON(ret == -EIO);
                goto err_ggtt;
@@ -5840,6 +5299,7 @@ int i915_gem_init_early(struct drm_i915_private *dev_priv)
                          i915_gem_idle_work_handler);
        init_waitqueue_head(&dev_priv->gpu_error.wait_queue);
        init_waitqueue_head(&dev_priv->gpu_error.reset_queue);
+       mutex_init(&dev_priv->gpu_error.wedge_mutex);
 
        atomic_set(&dev_priv->mm.bsd_engine_dispatch_index, 0);
 
index 371c070870951d6d1523d828ebfc9874a56e1977..93e84751370f9228b4336c01655d740f0c575526 100644 (file)
@@ -86,7 +86,6 @@
  */
 
 #include <linux/log2.h>
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 #include "i915_trace.h"
@@ -311,7 +310,7 @@ static u32 default_desc_template(const struct drm_i915_private *i915,
                address_mode = INTEL_LEGACY_64B_CONTEXT;
        desc |= address_mode << GEN8_CTX_ADDRESSING_MODE_SHIFT;
 
-       if (IS_GEN8(i915))
+       if (IS_GEN(i915, 8))
                desc |= GEN8_CTX_L3LLC_COHERENT;
 
        /* TODO: WaDisableLiteRestore when we start using semaphore
@@ -322,6 +321,14 @@ static u32 default_desc_template(const struct drm_i915_private *i915,
        return desc;
 }
 
+void
+intel_context_init(struct intel_context *ce,
+                  struct i915_gem_context *ctx,
+                  struct intel_engine_cs *engine)
+{
+       ce->gem_context = ctx;
+}
+
 static struct i915_gem_context *
 __create_hw_context(struct drm_i915_private *dev_priv,
                    struct drm_i915_file_private *file_priv)
@@ -339,11 +346,8 @@ __create_hw_context(struct drm_i915_private *dev_priv,
        ctx->i915 = dev_priv;
        ctx->sched.priority = I915_USER_PRIORITY(I915_PRIORITY_NORMAL);
 
-       for (n = 0; n < ARRAY_SIZE(ctx->__engine); n++) {
-               struct intel_context *ce = &ctx->__engine[n];
-
-               ce->gem_context = ctx;
-       }
+       for (n = 0; n < ARRAY_SIZE(ctx->__engine); n++)
+               intel_context_init(&ctx->__engine[n], ctx, dev_priv->engine[n]);
 
        INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL);
        INIT_LIST_HEAD(&ctx->handles_list);
@@ -649,7 +653,7 @@ last_request_on_engine(struct i915_timeline *timeline,
        rq = i915_gem_active_raw(&timeline->last_request,
                                 &engine->i915->drm.struct_mutex);
        if (rq && rq->engine == engine) {
-               GEM_TRACE("last request for %s on engine %s: %llx:%d\n",
+               GEM_TRACE("last request for %s on engine %s: %llx:%llu\n",
                          timeline->name, engine->name,
                          rq->fence.context, rq->fence.seqno);
                GEM_BUG_ON(rq->timeline != timeline);
@@ -686,14 +690,14 @@ static bool engine_has_kernel_context_barrier(struct intel_engine_cs *engine)
                 * switch-to-kernel-context?
                 */
                if (!i915_timeline_sync_is_later(barrier, &rq->fence)) {
-                       GEM_TRACE("%s needs barrier for %llx:%d\n",
+                       GEM_TRACE("%s needs barrier for %llx:%lld\n",
                                  ring->timeline->name,
                                  rq->fence.context,
                                  rq->fence.seqno);
                        return false;
                }
 
-               GEM_TRACE("%s has barrier after %llx:%d\n",
+               GEM_TRACE("%s has barrier after %llx:%lld\n",
                          ring->timeline->name,
                          rq->fence.context,
                          rq->fence.seqno);
@@ -749,7 +753,7 @@ int i915_gem_switch_to_kernel_context(struct drm_i915_private *i915)
                        if (prev->gem_context == i915->kernel_context)
                                continue;
 
-                       GEM_TRACE("add barrier on %s for %llx:%d\n",
+                       GEM_TRACE("add barrier on %s for %llx:%lld\n",
                                  engine->name,
                                  prev->fence.context,
                                  prev->fence.seqno);
index f6d870b1f73e397971e4f55714d8524f68220395..3769438228f6b6637b269121d65575b83b8af66a 100644 (file)
@@ -364,4 +364,8 @@ static inline void i915_gem_context_put(struct i915_gem_context *ctx)
        kref_put(&ctx->ref, i915_gem_context_release);
 }
 
+void intel_context_init(struct intel_context *ce,
+                       struct i915_gem_context *ctx,
+                       struct intel_engine_cs *engine);
+
 #endif /* !__I915_GEM_CONTEXT_H__ */
index 82e2ca17a441eed4c9f562b9d9ee9aa45f2e740a..02f7298bfe57cda5ad1d344adb0ff99079267c00 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/dma-buf.h>
 #include <linux/reservation.h>
 
-#include <drm/drmP.h>
 
 #include "i915_drv.h"
 
index 02b83a5ed96c9ec7b539bec4bdc88ed3ac1946cd..f6855401f24714b56356f0512c32be3c61a0ba5b 100644 (file)
@@ -26,7 +26,6 @@
  *
  */
 
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 
 #include "i915_drv.h"
index 485b259127c36fdb4aeb619559e790f394ff412a..f250109e1f66300714a72c65ed637293a92a7888 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/sync_file.h>
 #include <linux/uaccess.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_syncobj.h>
 #include <drm/i915_drm.h>
 
@@ -1380,7 +1379,7 @@ eb_relocate_entry(struct i915_execbuffer *eb,
                 * batchbuffers.
                 */
                if (reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION &&
-                   IS_GEN6(eb->i915)) {
+                   IS_GEN(eb->i915, 6)) {
                        err = i915_vma_bind(target, target->obj->cache_level,
                                            PIN_GLOBAL);
                        if (WARN_ONCE(err,
@@ -1896,7 +1895,7 @@ static int i915_reset_gen7_sol_offsets(struct i915_request *rq)
        u32 *cs;
        int i;
 
-       if (!IS_GEN7(rq->i915) || rq->engine->id != RCS) {
+       if (!IS_GEN(rq->i915, 7) || rq->engine->id != RCS) {
                DRM_DEBUG("sol reset is gen7/rcs only\n");
                return -EINVAL;
        }
@@ -2203,6 +2202,7 @@ i915_gem_do_execbuffer(struct drm_device *dev,
        struct i915_execbuffer eb;
        struct dma_fence *in_fence = NULL;
        struct sync_file *out_fence = NULL;
+       intel_wakeref_t wakeref;
        int out_fence_fd = -1;
        int err;
 
@@ -2273,7 +2273,7 @@ i915_gem_do_execbuffer(struct drm_device *dev,
         * wakeref that we hold until the GPU has been idle for at least
         * 100ms.
         */
-       intel_runtime_pm_get(eb.i915);
+       wakeref = intel_runtime_pm_get(eb.i915);
 
        err = i915_mutex_lock_interruptible(dev);
        if (err)
@@ -2425,7 +2425,7 @@ err_vma:
                eb_release_vmas(&eb);
        mutex_unlock(&dev->struct_mutex);
 err_rpm:
-       intel_runtime_pm_put(eb.i915);
+       intel_runtime_pm_put(eb.i915, wakeref);
        i915_gem_context_put(eb.ctx);
 err_destroy:
        eb_destroy(&eb);
index d548ac05ccd7a45994f38960dd121e79b4d6ecf9..46e259661294e6d715765a9a390b630d3ad57f80 100644 (file)
@@ -21,7 +21,6 @@
  * IN THE SOFTWARE.
  */
 
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 
@@ -193,9 +192,9 @@ static void fence_write(struct drm_i915_fence_reg *fence,
         * and explicitly managed for internal users.
         */
 
-       if (IS_GEN2(fence->i915))
+       if (IS_GEN(fence->i915, 2))
                i830_write_fence_reg(fence, vma);
-       else if (IS_GEN3(fence->i915))
+       else if (IS_GEN(fence->i915, 3))
                i915_write_fence_reg(fence, vma);
        else
                i965_write_fence_reg(fence, vma);
@@ -210,6 +209,7 @@ static void fence_write(struct drm_i915_fence_reg *fence,
 static int fence_update(struct drm_i915_fence_reg *fence,
                        struct i915_vma *vma)
 {
+       intel_wakeref_t wakeref;
        int ret;
 
        if (vma) {
@@ -257,9 +257,10 @@ static int fence_update(struct drm_i915_fence_reg *fence,
         * If the device is currently powered down, we will defer the write
         * to the runtime resume, see i915_gem_restore_fences().
         */
-       if (intel_runtime_pm_get_if_in_use(fence->i915)) {
+       wakeref = intel_runtime_pm_get_if_in_use(fence->i915);
+       if (wakeref) {
                fence_write(fence, vma);
-               intel_runtime_pm_put(fence->i915);
+               intel_runtime_pm_put(fence->i915, wakeref);
        }
 
        if (vma) {
@@ -554,8 +555,8 @@ void i915_gem_restore_fences(struct drm_i915_private *dev_priv)
 void
 i915_gem_detect_bit_6_swizzle(struct drm_i915_private *dev_priv)
 {
-       uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
-       uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
+       u32 swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
+       u32 swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
 
        if (INTEL_GEN(dev_priv) >= 8 || IS_VALLEYVIEW(dev_priv)) {
                /*
@@ -578,7 +579,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_i915_private *dev_priv)
                                swizzle_y = I915_BIT_6_SWIZZLE_NONE;
                        }
                } else {
-                       uint32_t dimm_c0, dimm_c1;
+                       u32 dimm_c0, dimm_c1;
                        dimm_c0 = I915_READ(MAD_DIMM_C0);
                        dimm_c1 = I915_READ(MAD_DIMM_C1);
                        dimm_c0 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK;
@@ -596,13 +597,13 @@ i915_gem_detect_bit_6_swizzle(struct drm_i915_private *dev_priv)
                                swizzle_y = I915_BIT_6_SWIZZLE_NONE;
                        }
                }
-       } else if (IS_GEN5(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 5)) {
                /* On Ironlake whatever DRAM config, GPU always do
                 * same swizzling setup.
                 */
                swizzle_x = I915_BIT_6_SWIZZLE_9_10;
                swizzle_y = I915_BIT_6_SWIZZLE_9;
-       } else if (IS_GEN2(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 2)) {
                /* As far as we know, the 865 doesn't have these bit 6
                 * swizzling issues.
                 */
@@ -610,7 +611,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_i915_private *dev_priv)
                swizzle_y = I915_BIT_6_SWIZZLE_NONE;
        } else if (IS_MOBILE(dev_priv) ||
                   IS_I915G(dev_priv) || IS_I945G(dev_priv)) {
-               uint32_t dcc;
+               u32 dcc;
 
                /* On 9xx chipsets, channel interleave by the CPU is
                 * determined by DCC.  For single-channel, neither the CPU
@@ -647,7 +648,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_i915_private *dev_priv)
                }
 
                /* check for L-shaped memory aka modified enhanced addressing */
-               if (IS_GEN4(dev_priv) &&
+               if (IS_GEN(dev_priv, 4) &&
                    !(I915_READ(DCC2) & DCC2_MODIFIED_ENHANCED_DISABLE)) {
                        swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
                        swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
index add1fe7aeb930f2e21e73d12dbf96f095decc5be..9081e3bc5a59d38c2b340685be3c62b2e9cd9fc1 100644 (file)
 
 #include <asm/set_memory.h>
 
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 
 #include "i915_drv.h"
 #include "i915_vgpu.h"
+#include "i915_reset.h"
 #include "i915_trace.h"
 #include "intel_drv.h"
 #include "intel_frontbuffer.h"
@@ -474,8 +474,7 @@ static void vm_free_page(struct i915_address_space *vm, struct page *page)
        spin_unlock(&vm->free_pages.lock);
 }
 
-static void i915_address_space_init(struct i915_address_space *vm,
-                                   struct drm_i915_private *dev_priv)
+static void i915_address_space_init(struct i915_address_space *vm, int subclass)
 {
        /*
         * The vm->mutex must be reclaim safe (for use in the shrinker).
@@ -483,7 +482,8 @@ static void i915_address_space_init(struct i915_address_space *vm,
         * attempt holding the lock is immediately reported by lockdep.
         */
        mutex_init(&vm->mutex);
-       i915_gem_shrinker_taints_mutex(&vm->mutex);
+       lockdep_set_subclass(&vm->mutex, subclass);
+       i915_gem_shrinker_taints_mutex(vm->i915, &vm->mutex);
 
        GEM_BUG_ON(!vm->total);
        drm_mm_init(&vm->mm, 0, vm->total);
@@ -1423,8 +1423,6 @@ static int gen8_ppgtt_alloc_pdp(struct i915_address_space *vm,
                        gen8_initialize_pd(vm, pd);
                        gen8_ppgtt_set_pdpe(vm, pdp, pd, pdpe);
                        GEM_BUG_ON(pdp->used_pdpes > i915_pdpes_per_pdp(vm));
-
-                       mark_tlbs_dirty(i915_vm_to_ppgtt(vm));
                }
 
                ret = gen8_ppgtt_alloc_pd(vm, pd, start, length);
@@ -1490,84 +1488,6 @@ unwind:
        return -ENOMEM;
 }
 
-static void gen8_dump_pdp(struct i915_hw_ppgtt *ppgtt,
-                         struct i915_page_directory_pointer *pdp,
-                         u64 start, u64 length,
-                         gen8_pte_t scratch_pte,
-                         struct seq_file *m)
-{
-       struct i915_address_space *vm = &ppgtt->vm;
-       struct i915_page_directory *pd;
-       u32 pdpe;
-
-       gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
-               struct i915_page_table *pt;
-               u64 pd_len = length;
-               u64 pd_start = start;
-               u32 pde;
-
-               if (pdp->page_directory[pdpe] == ppgtt->vm.scratch_pd)
-                       continue;
-
-               seq_printf(m, "\tPDPE #%d\n", pdpe);
-               gen8_for_each_pde(pt, pd, pd_start, pd_len, pde) {
-                       u32 pte;
-                       gen8_pte_t *pt_vaddr;
-
-                       if (pd->page_table[pde] == ppgtt->vm.scratch_pt)
-                               continue;
-
-                       pt_vaddr = kmap_atomic_px(pt);
-                       for (pte = 0; pte < GEN8_PTES; pte += 4) {
-                               u64 va = (pdpe << GEN8_PDPE_SHIFT |
-                                         pde << GEN8_PDE_SHIFT |
-                                         pte << GEN8_PTE_SHIFT);
-                               int i;
-                               bool found = false;
-
-                               for (i = 0; i < 4; i++)
-                                       if (pt_vaddr[pte + i] != scratch_pte)
-                                               found = true;
-                               if (!found)
-                                       continue;
-
-                               seq_printf(m, "\t\t0x%llx [%03d,%03d,%04d]: =", va, pdpe, pde, pte);
-                               for (i = 0; i < 4; i++) {
-                                       if (pt_vaddr[pte + i] != scratch_pte)
-                                               seq_printf(m, " %llx", pt_vaddr[pte + i]);
-                                       else
-                                               seq_puts(m, "  SCRATCH ");
-                               }
-                               seq_puts(m, "\n");
-                       }
-                       kunmap_atomic(pt_vaddr);
-               }
-       }
-}
-
-static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m)
-{
-       struct i915_address_space *vm = &ppgtt->vm;
-       const gen8_pte_t scratch_pte = vm->scratch_pte;
-       u64 start = 0, length = ppgtt->vm.total;
-
-       if (use_4lvl(vm)) {
-               u64 pml4e;
-               struct i915_pml4 *pml4 = &ppgtt->pml4;
-               struct i915_page_directory_pointer *pdp;
-
-               gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
-                       if (pml4->pdps[pml4e] == ppgtt->vm.scratch_pdp)
-                               continue;
-
-                       seq_printf(m, "    PML4E #%llu\n", pml4e);
-                       gen8_dump_pdp(ppgtt, pdp, start, length, scratch_pte, m);
-               }
-       } else {
-               gen8_dump_pdp(ppgtt, &ppgtt->pdp, start, length, scratch_pte, m);
-       }
-}
-
 static int gen8_preallocate_top_level_pdp(struct i915_hw_ppgtt *ppgtt)
 {
        struct i915_address_space *vm = &ppgtt->vm;
@@ -1628,7 +1548,7 @@ static struct i915_hw_ppgtt *gen8_ppgtt_create(struct drm_i915_private *i915)
        /* From bdw, there is support for read-only pages in the PPGTT. */
        ppgtt->vm.has_read_only = true;
 
-       i915_address_space_init(&ppgtt->vm, i915);
+       i915_address_space_init(&ppgtt->vm, VM_CLASS_PPGTT);
 
        /* There are only few exceptions for gen >=6. chv and bxt.
         * And we are not sure about the latter so play safe for now.
@@ -1672,7 +1592,6 @@ static struct i915_hw_ppgtt *gen8_ppgtt_create(struct drm_i915_private *i915)
                gen8_ppgtt_notify_vgt(ppgtt, true);
 
        ppgtt->vm.cleanup = gen8_ppgtt_cleanup;
-       ppgtt->debug_dump = gen8_dump_ppgtt;
 
        ppgtt->vm.vma_ops.bind_vma    = ppgtt_bind_vma;
        ppgtt->vm.vma_ops.unbind_vma  = ppgtt_unbind_vma;
@@ -1688,60 +1607,6 @@ err_free:
        return ERR_PTR(err);
 }
 
-static void gen6_dump_ppgtt(struct i915_hw_ppgtt *base, struct seq_file *m)
-{
-       struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(base);
-       const gen6_pte_t scratch_pte = base->vm.scratch_pte;
-       struct i915_page_table *pt;
-       u32 pte, pde;
-
-       gen6_for_all_pdes(pt, &base->pd, pde) {
-               gen6_pte_t *vaddr;
-
-               if (pt == base->vm.scratch_pt)
-                       continue;
-
-               if (i915_vma_is_bound(ppgtt->vma, I915_VMA_GLOBAL_BIND)) {
-                       u32 expected =
-                               GEN6_PDE_ADDR_ENCODE(px_dma(pt)) |
-                               GEN6_PDE_VALID;
-                       u32 pd_entry = readl(ppgtt->pd_addr + pde);
-
-                       if (pd_entry != expected)
-                               seq_printf(m,
-                                          "\tPDE #%d mismatch: Actual PDE: %x Expected PDE: %x\n",
-                                          pde,
-                                          pd_entry,
-                                          expected);
-
-                       seq_printf(m, "\tPDE: %x\n", pd_entry);
-               }
-
-               vaddr = kmap_atomic_px(base->pd.page_table[pde]);
-               for (pte = 0; pte < GEN6_PTES; pte += 4) {
-                       int i;
-
-                       for (i = 0; i < 4; i++)
-                               if (vaddr[pte + i] != scratch_pte)
-                                       break;
-                       if (i == 4)
-                               continue;
-
-                       seq_printf(m, "\t\t(%03d, %04d) %08llx: ",
-                                  pde, pte,
-                                  (pde * GEN6_PTES + pte) * I915_GTT_PAGE_SIZE);
-                       for (i = 0; i < 4; i++) {
-                               if (vaddr[pte + i] != scratch_pte)
-                                       seq_printf(m, " %08x", vaddr[pte + i]);
-                               else
-                                       seq_puts(m, "  SCRATCH");
-                       }
-                       seq_puts(m, "\n");
-               }
-               kunmap_atomic(vaddr);
-       }
-}
-
 /* Write pde (index) from the page directory @pd to the page table @pt */
 static inline void gen6_write_pde(const struct gen6_hw_ppgtt *ppgtt,
                                  const unsigned int pde,
@@ -2075,6 +1940,7 @@ static struct i915_vma *pd_vma_create(struct gen6_hw_ppgtt *ppgtt, int size)
 int gen6_ppgtt_pin(struct i915_hw_ppgtt *base)
 {
        struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(base);
+       int err;
 
        /*
         * Workaround the limited maximum vma->pin_count and the aliasing_ppgtt
@@ -2090,9 +1956,17 @@ int gen6_ppgtt_pin(struct i915_hw_ppgtt *base)
         * allocator works in address space sizes, so it's multiplied by page
         * size. We allocate at the top of the GTT to avoid fragmentation.
         */
-       return i915_vma_pin(ppgtt->vma,
-                           0, GEN6_PD_ALIGN,
-                           PIN_GLOBAL | PIN_HIGH);
+       err = i915_vma_pin(ppgtt->vma,
+                          0, GEN6_PD_ALIGN,
+                          PIN_GLOBAL | PIN_HIGH);
+       if (err)
+               goto unpin;
+
+       return 0;
+
+unpin:
+       ppgtt->pin_count = 0;
+       return err;
 }
 
 void gen6_ppgtt_unpin(struct i915_hw_ppgtt *base)
@@ -2123,13 +1997,12 @@ static struct i915_hw_ppgtt *gen6_ppgtt_create(struct drm_i915_private *i915)
 
        ppgtt->base.vm.total = I915_PDES * GEN6_PTES * I915_GTT_PAGE_SIZE;
 
-       i915_address_space_init(&ppgtt->base.vm, i915);
+       i915_address_space_init(&ppgtt->base.vm, VM_CLASS_PPGTT);
 
        ppgtt->base.vm.allocate_va_range = gen6_alloc_va_range;
        ppgtt->base.vm.clear_range = gen6_ppgtt_clear_range;
        ppgtt->base.vm.insert_entries = gen6_ppgtt_insert_entries;
        ppgtt->base.vm.cleanup = gen6_ppgtt_cleanup;
-       ppgtt->base.debug_dump = gen6_dump_ppgtt;
 
        ppgtt->base.vm.vma_ops.bind_vma    = ppgtt_bind_vma;
        ppgtt->base.vm.vma_ops.unbind_vma  = ppgtt_unbind_vma;
@@ -2195,9 +2068,9 @@ int i915_ppgtt_init_hw(struct drm_i915_private *dev_priv)
 {
        gtt_write_workarounds(dev_priv);
 
-       if (IS_GEN6(dev_priv))
+       if (IS_GEN(dev_priv, 6))
                gen6_ppgtt_enable(dev_priv);
-       else if (IS_GEN7(dev_priv))
+       else if (IS_GEN(dev_priv, 7))
                gen7_ppgtt_enable(dev_priv);
 
        return 0;
@@ -2279,7 +2152,7 @@ static bool needs_idle_maps(struct drm_i915_private *dev_priv)
        /* Query intel_iommu to see if we need the workaround. Presumably that
         * was loaded first.
         */
-       return IS_GEN5(dev_priv) && IS_MOBILE(dev_priv) && intel_vtd_active();
+       return IS_GEN(dev_priv, 5) && IS_MOBILE(dev_priv) && intel_vtd_active();
 }
 
 static void gen6_check_faults(struct drm_i915_private *dev_priv)
@@ -2372,7 +2245,8 @@ int i915_gem_gtt_prepare_pages(struct drm_i915_gem_object *obj,
                                     DMA_ATTR_NO_WARN))
                        return 0;
 
-               /* If the DMA remap fails, one cause can be that we have
+               /*
+                * If the DMA remap fails, one cause can be that we have
                 * too many objects pinned in a small remapping table,
                 * such as swiotlb. Incrementally purge all other objects and
                 * try again - if there are no more pages to remove from
@@ -2382,8 +2256,7 @@ int i915_gem_gtt_prepare_pages(struct drm_i915_gem_object *obj,
        } while (i915_gem_shrink(to_i915(obj->base.dev),
                                 obj->base.size >> PAGE_SHIFT, NULL,
                                 I915_SHRINK_BOUND |
-                                I915_SHRINK_UNBOUND |
-                                I915_SHRINK_ACTIVE));
+                                I915_SHRINK_UNBOUND));
 
        return -ENOSPC;
 }
@@ -2655,6 +2528,7 @@ static int ggtt_bind_vma(struct i915_vma *vma,
 {
        struct drm_i915_private *i915 = vma->vm->i915;
        struct drm_i915_gem_object *obj = vma->obj;
+       intel_wakeref_t wakeref;
        u32 pte_flags;
 
        /* Applicable to VLV (gen8+ do not support RO in the GGTT) */
@@ -2662,9 +2536,8 @@ static int ggtt_bind_vma(struct i915_vma *vma,
        if (i915_gem_object_is_readonly(obj))
                pte_flags |= PTE_READ_ONLY;
 
-       intel_runtime_pm_get(i915);
-       vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
-       intel_runtime_pm_put(i915);
+       with_intel_runtime_pm(i915, wakeref)
+               vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
 
        vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
 
@@ -2681,10 +2554,10 @@ static int ggtt_bind_vma(struct i915_vma *vma,
 static void ggtt_unbind_vma(struct i915_vma *vma)
 {
        struct drm_i915_private *i915 = vma->vm->i915;
+       intel_wakeref_t wakeref;
 
-       intel_runtime_pm_get(i915);
-       vma->vm->clear_range(vma->vm, vma->node.start, vma->size);
-       intel_runtime_pm_put(i915);
+       with_intel_runtime_pm(i915, wakeref)
+               vma->vm->clear_range(vma->vm, vma->node.start, vma->size);
 }
 
 static int aliasing_gtt_bind_vma(struct i915_vma *vma,
@@ -2716,9 +2589,12 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
        }
 
        if (flags & I915_VMA_GLOBAL_BIND) {
-               intel_runtime_pm_get(i915);
-               vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
-               intel_runtime_pm_put(i915);
+               intel_wakeref_t wakeref;
+
+               with_intel_runtime_pm(i915, wakeref) {
+                       vma->vm->insert_entries(vma->vm, vma,
+                                               cache_level, pte_flags);
+               }
        }
 
        return 0;
@@ -2729,9 +2605,11 @@ static void aliasing_gtt_unbind_vma(struct i915_vma *vma)
        struct drm_i915_private *i915 = vma->vm->i915;
 
        if (vma->flags & I915_VMA_GLOBAL_BIND) {
-               intel_runtime_pm_get(i915);
-               vma->vm->clear_range(vma->vm, vma->node.start, vma->size);
-               intel_runtime_pm_put(i915);
+               struct i915_address_space *vm = vma->vm;
+               intel_wakeref_t wakeref;
+
+               with_intel_runtime_pm(i915, wakeref)
+                       vm->clear_range(vm, vma->node.start, vma->size);
        }
 
        if (vma->flags & I915_VMA_LOCAL_BIND) {
@@ -3355,7 +3233,8 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
        ggtt->vm.insert_entries = gen8_ggtt_insert_entries;
 
        /* Serialize GTT updates with aperture access on BXT if VT-d is on. */
-       if (intel_ggtt_update_needs_vtd_wa(dev_priv)) {
+       if (intel_ggtt_update_needs_vtd_wa(dev_priv) ||
+           IS_CHERRYVIEW(dev_priv) /* fails with concurrent use/update */) {
                ggtt->vm.insert_entries = bxt_vtd_ggtt_insert_entries__BKL;
                ggtt->vm.insert_page    = bxt_vtd_ggtt_insert_page__BKL;
                if (ggtt->vm.clear_range != nop_clear_range)
@@ -3556,7 +3435,7 @@ int i915_ggtt_init_hw(struct drm_i915_private *dev_priv)
         * and beyond the end of the GTT if we do not provide a guard.
         */
        mutex_lock(&dev_priv->drm.struct_mutex);
-       i915_address_space_init(&ggtt->vm, dev_priv);
+       i915_address_space_init(&ggtt->vm, VM_CLASS_GGTT);
 
        ggtt->vm.is_ggtt = true;
 
index 4874da09a3c471d24697b55b4ab7687d2d76afbf..9229b03d629b4ff2fbcfbdecc11997abb7aefa9c 100644 (file)
@@ -288,6 +288,8 @@ struct i915_address_space {
        bool closed;
 
        struct mutex mutex; /* protects vma and our lists */
+#define VM_CLASS_GGTT 0
+#define VM_CLASS_PPGTT 1
 
        u64 scratch_pte;
        struct i915_page_dma scratch_page;
@@ -413,8 +415,6 @@ struct i915_hw_ppgtt {
                struct i915_page_directory_pointer pdp; /* GEN8+ */
                struct i915_page_directory pd;          /* GEN6-7 */
        };
-
-       void (*debug_dump)(struct i915_hw_ppgtt *ppgtt, struct seq_file *m);
 };
 
 struct gen6_hw_ppgtt {
index 0d0144b2104cb3264b2048a1569bc598fde532f3..fddde1033e747ee65f0914114975f9d8d29c88de 100644 (file)
@@ -22,7 +22,6 @@
  *
  */
 
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 
index a6dd7c46de0dddb4a8f2c09a21651ac1c1a8cb21..cb1b0144d27483bac8ada25144b063ddf724f683 100644 (file)
@@ -29,7 +29,8 @@
 
 #include <drm/drm_vma_manager.h>
 #include <drm/drm_gem.h>
-#include <drm/drmP.h>
+#include <drm/drm_file.h>
+#include <drm/drm_device.h>
 
 #include <drm/i915_drm.h>
 
@@ -56,6 +57,7 @@ struct drm_i915_gem_object_ops {
 #define I915_GEM_OBJECT_HAS_STRUCT_PAGE        BIT(0)
 #define I915_GEM_OBJECT_IS_SHRINKABLE  BIT(1)
 #define I915_GEM_OBJECT_IS_PROXY       BIT(2)
+#define I915_GEM_OBJECT_ASYNC_CANCEL   BIT(3)
 
        /* Interface between the GEM object and its backing storage.
         * get_pages() is called once prior to the use of the associated set
@@ -386,6 +388,12 @@ i915_gem_object_is_proxy(const struct drm_i915_gem_object *obj)
        return obj->ops->flags & I915_GEM_OBJECT_IS_PROXY;
 }
 
+static inline bool
+i915_gem_object_needs_async_cancel(const struct drm_i915_gem_object *obj)
+{
+       return obj->ops->flags & I915_GEM_OBJECT_ASYNC_CANCEL;
+}
+
 static inline bool
 i915_gem_object_is_active(const struct drm_i915_gem_object *obj)
 {
index ea90d3a0d51143dc4a189b0e15a3ecf7c37c214c..8ceecb026910d841fd6ecd001f7b999c0dd8aad3 100644 (file)
 #include <linux/pci.h>
 #include <linux/dma-buf.h>
 #include <linux/vmalloc.h>
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 
 #include "i915_drv.h"
 #include "i915_trace.h"
 
-static bool shrinker_lock(struct drm_i915_private *i915, bool *unlock)
+static bool shrinker_lock(struct drm_i915_private *i915,
+                         unsigned int flags,
+                         bool *unlock)
 {
-       switch (mutex_trylock_recursive(&i915->drm.struct_mutex)) {
+       struct mutex *m = &i915->drm.struct_mutex;
+
+       switch (mutex_trylock_recursive(m)) {
        case MUTEX_TRYLOCK_RECURSIVE:
                *unlock = false;
                return true;
 
        case MUTEX_TRYLOCK_FAILED:
                *unlock = false;
-               preempt_disable();
-               do {
-                       cpu_relax();
-                       if (mutex_trylock(&i915->drm.struct_mutex)) {
-                               *unlock = true;
-                               break;
-                       }
-               } while (!need_resched());
-               preempt_enable();
+               if (flags & I915_SHRINK_ACTIVE &&
+                   mutex_lock_killable_nested(m, I915_MM_SHRINKER) == 0)
+                       *unlock = true;
                return *unlock;
 
        case MUTEX_TRYLOCK_SUCCESS:
@@ -156,11 +153,12 @@ i915_gem_shrink(struct drm_i915_private *i915,
                { &i915->mm.bound_list, I915_SHRINK_BOUND },
                { NULL, 0 },
        }, *phase;
+       intel_wakeref_t wakeref = 0;
        unsigned long count = 0;
        unsigned long scanned = 0;
        bool unlock;
 
-       if (!shrinker_lock(i915, &unlock))
+       if (!shrinker_lock(i915, flags, &unlock))
                return 0;
 
        /*
@@ -185,9 +183,11 @@ i915_gem_shrink(struct drm_i915_private *i915,
         * device just to recover a little memory. If absolutely necessary,
         * we will force the wake during oom-notifier.
         */
-       if ((flags & I915_SHRINK_BOUND) &&
-           !intel_runtime_pm_get_if_in_use(i915))
-               flags &= ~I915_SHRINK_BOUND;
+       if (flags & I915_SHRINK_BOUND) {
+               wakeref = intel_runtime_pm_get_if_in_use(i915);
+               if (!wakeref)
+                       flags &= ~I915_SHRINK_BOUND;
+       }
 
        /*
         * As we may completely rewrite the (un)bound list whilst unbinding
@@ -268,7 +268,7 @@ i915_gem_shrink(struct drm_i915_private *i915,
        }
 
        if (flags & I915_SHRINK_BOUND)
-               intel_runtime_pm_put(i915);
+               intel_runtime_pm_put(i915, wakeref);
 
        i915_retire_requests(i915);
 
@@ -295,14 +295,15 @@ i915_gem_shrink(struct drm_i915_private *i915,
  */
 unsigned long i915_gem_shrink_all(struct drm_i915_private *i915)
 {
-       unsigned long freed;
-
-       intel_runtime_pm_get(i915);
-       freed = i915_gem_shrink(i915, -1UL, NULL,
-                               I915_SHRINK_BOUND |
-                               I915_SHRINK_UNBOUND |
-                               I915_SHRINK_ACTIVE);
-       intel_runtime_pm_put(i915);
+       intel_wakeref_t wakeref;
+       unsigned long freed = 0;
+
+       with_intel_runtime_pm(i915, wakeref) {
+               freed = i915_gem_shrink(i915, -1UL, NULL,
+                                       I915_SHRINK_BOUND |
+                                       I915_SHRINK_UNBOUND |
+                                       I915_SHRINK_ACTIVE);
+       }
 
        return freed;
 }
@@ -357,7 +358,7 @@ i915_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
 
        sc->nr_scanned = 0;
 
-       if (!shrinker_lock(i915, &unlock))
+       if (!shrinker_lock(i915, 0, &unlock))
                return SHRINK_STOP;
 
        freed = i915_gem_shrink(i915,
@@ -373,14 +374,16 @@ i915_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
                                         I915_SHRINK_BOUND |
                                         I915_SHRINK_UNBOUND);
        if (sc->nr_scanned < sc->nr_to_scan && current_is_kswapd()) {
-               intel_runtime_pm_get(i915);
-               freed += i915_gem_shrink(i915,
-                                        sc->nr_to_scan - sc->nr_scanned,
-                                        &sc->nr_scanned,
-                                        I915_SHRINK_ACTIVE |
-                                        I915_SHRINK_BOUND |
-                                        I915_SHRINK_UNBOUND);
-               intel_runtime_pm_put(i915);
+               intel_wakeref_t wakeref;
+
+               with_intel_runtime_pm(i915, wakeref) {
+                       freed += i915_gem_shrink(i915,
+                                                sc->nr_to_scan - sc->nr_scanned,
+                                                &sc->nr_scanned,
+                                                I915_SHRINK_ACTIVE |
+                                                I915_SHRINK_BOUND |
+                                                I915_SHRINK_UNBOUND);
+               }
        }
 
        shrinker_unlock(i915, unlock);
@@ -388,31 +391,6 @@ i915_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
        return sc->nr_scanned ? freed : SHRINK_STOP;
 }
 
-static bool
-shrinker_lock_uninterruptible(struct drm_i915_private *i915, bool *unlock,
-                             int timeout_ms)
-{
-       unsigned long timeout = jiffies + msecs_to_jiffies_timeout(timeout_ms);
-
-       do {
-               if (i915_gem_wait_for_idle(i915,
-                                          0, MAX_SCHEDULE_TIMEOUT) == 0 &&
-                   shrinker_lock(i915, unlock))
-                       break;
-
-               schedule_timeout_killable(1);
-               if (fatal_signal_pending(current))
-                       return false;
-
-               if (time_after(jiffies, timeout)) {
-                       pr_err("Unable to lock GPU to purge memory.\n");
-                       return false;
-               }
-       } while (1);
-
-       return true;
-}
-
 static int
 i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
 {
@@ -420,8 +398,13 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
                container_of(nb, struct drm_i915_private, mm.oom_notifier);
        struct drm_i915_gem_object *obj;
        unsigned long unevictable, bound, unbound, freed_pages;
+       intel_wakeref_t wakeref;
 
-       freed_pages = i915_gem_shrink_all(i915);
+       freed_pages = 0;
+       with_intel_runtime_pm(i915, wakeref)
+               freed_pages += i915_gem_shrink(i915, -1UL, NULL,
+                                              I915_SHRINK_BOUND |
+                                              I915_SHRINK_UNBOUND);
 
        /* Because we may be allocating inside our own driver, we cannot
         * assert that there are no objects with pinned pages that are not
@@ -447,10 +430,6 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
                pr_info("Purging GPU memory, %lu pages freed, "
                        "%lu pages still pinned.\n",
                        freed_pages, unevictable);
-       if (unbound || bound)
-               pr_err("%lu and %lu pages still available in the "
-                      "bound and unbound GPU page lists.\n",
-                      bound, unbound);
 
        *(unsigned long *)ptr += freed_pages;
        return NOTIFY_DONE;
@@ -463,26 +442,23 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr
                container_of(nb, struct drm_i915_private, mm.vmap_notifier);
        struct i915_vma *vma, *next;
        unsigned long freed_pages = 0;
+       intel_wakeref_t wakeref;
        bool unlock;
-       int ret;
 
-       if (!shrinker_lock_uninterruptible(i915, &unlock, 5000))
+       if (!shrinker_lock(i915, 0, &unlock))
                return NOTIFY_DONE;
 
        /* Force everything onto the inactive lists */
-       ret = i915_gem_wait_for_idle(i915,
-                                    I915_WAIT_LOCKED,
-                                    MAX_SCHEDULE_TIMEOUT);
-       if (ret)
+       if (i915_gem_wait_for_idle(i915,
+                                  I915_WAIT_LOCKED,
+                                  MAX_SCHEDULE_TIMEOUT))
                goto out;
 
-       intel_runtime_pm_get(i915);
-       freed_pages += i915_gem_shrink(i915, -1UL, NULL,
-                                      I915_SHRINK_BOUND |
-                                      I915_SHRINK_UNBOUND |
-                                      I915_SHRINK_ACTIVE |
-                                      I915_SHRINK_VMAPS);
-       intel_runtime_pm_put(i915);
+       with_intel_runtime_pm(i915, wakeref)
+               freed_pages += i915_gem_shrink(i915, -1UL, NULL,
+                                              I915_SHRINK_BOUND |
+                                              I915_SHRINK_UNBOUND |
+                                              I915_SHRINK_VMAPS);
 
        /* We also want to clear any cached iomaps as they wrap vmap */
        list_for_each_entry_safe(vma, next,
@@ -533,13 +509,40 @@ void i915_gem_shrinker_unregister(struct drm_i915_private *i915)
        unregister_shrinker(&i915->mm.shrinker);
 }
 
-void i915_gem_shrinker_taints_mutex(struct mutex *mutex)
+void i915_gem_shrinker_taints_mutex(struct drm_i915_private *i915,
+                                   struct mutex *mutex)
 {
+       bool unlock = false;
+
        if (!IS_ENABLED(CONFIG_LOCKDEP))
                return;
 
+       if (!lockdep_is_held_type(&i915->drm.struct_mutex, -1)) {
+               mutex_acquire(&i915->drm.struct_mutex.dep_map,
+                             I915_MM_NORMAL, 0, _RET_IP_);
+               unlock = true;
+       }
+
        fs_reclaim_acquire(GFP_KERNEL);
-       mutex_lock(mutex);
-       mutex_unlock(mutex);
+
+       /*
+        * As we invariably rely on the struct_mutex within the shrinker,
+        * but have a complicated recursion dance, taint all the mutexes used
+        * within the shrinker with the struct_mutex. For completeness, we
+        * taint with all subclass of struct_mutex, even though we should
+        * only need tainting by I915_MM_NORMAL to catch possible ABBA
+        * deadlocks from using struct_mutex inside @mutex.
+        */
+       mutex_acquire(&i915->drm.struct_mutex.dep_map,
+                     I915_MM_SHRINKER, 0, _RET_IP_);
+
+       mutex_acquire(&mutex->dep_map, 0, 0, _RET_IP_);
+       mutex_release(&mutex->dep_map, 0, _RET_IP_);
+
+       mutex_release(&i915->drm.struct_mutex.dep_map, 0, _RET_IP_);
+
        fs_reclaim_release(GFP_KERNEL);
+
+       if (unlock)
+               mutex_release(&i915->drm.struct_mutex.dep_map, 0, _RET_IP_);
 }
index f29a7ff7c362c7d21e60c1d822465cfe6a3d2090..9df615eea2d8798c97cef5920023d4b99e0e7691 100644 (file)
@@ -26,7 +26,6 @@
  *
  */
 
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 
@@ -102,7 +101,7 @@ static int i915_adjust_stolen(struct drm_i915_private *dev_priv,
                resource_size_t ggtt_start;
 
                ggtt_start = I915_READ(PGTBL_CTL);
-               if (IS_GEN4(dev_priv))
+               if (IS_GEN(dev_priv, 4))
                        ggtt_start = (ggtt_start & PGTBL_ADDRESS_LO_MASK) |
                                     (ggtt_start & PGTBL_ADDRESS_HI_MASK) << 28;
                else
@@ -156,7 +155,7 @@ static int i915_adjust_stolen(struct drm_i915_private *dev_priv,
                 * GEN3 firmware likes to smash pci bridges into the stolen
                 * range. Apparently this works.
                 */
-               if (r == NULL && !IS_GEN3(dev_priv)) {
+               if (r == NULL && !IS_GEN(dev_priv, 3)) {
                        DRM_ERROR("conflict detected with stolen region: %pR\n",
                                  dsm);
 
@@ -194,7 +193,8 @@ static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv,
         * Whether ILK really reuses the ELK register for this is unclear.
         * Let's see if we catch anyone with this supposedly enabled on ILK.
         */
-       WARN(IS_GEN5(dev_priv), "ILK stolen reserved found? 0x%08x\n", reg_val);
+       WARN(IS_GEN(dev_priv, 5), "ILK stolen reserved found? 0x%08x\n",
+            reg_val);
 
        if (!(reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK))
                return;
index d9dc9df523b58e9a8645838e9c2ffa2080c54d61..16cc9ddbce34ae8e97e59838c2e687af6a0f52f9 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <linux/string.h>
 #include <linux/bitops.h>
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 
@@ -87,7 +86,7 @@ u32 i915_gem_fence_size(struct drm_i915_private *i915,
        }
 
        /* Previous chips need a power-of-two fence region when tiling */
-       if (IS_GEN3(i915))
+       if (IS_GEN(i915, 3))
                ggtt_size = 1024*1024;
        else
                ggtt_size = 512*1024;
@@ -162,7 +161,7 @@ i915_tiling_ok(struct drm_i915_gem_object *obj,
                        return false;
        }
 
-       if (IS_GEN2(i915) ||
+       if (IS_GEN(i915, 2) ||
            (tiling == I915_TILING_Y && HAS_128_BYTE_Y_TILING(i915)))
                tile_width = 128;
        else
index 9558582c105ec4953ba0616b23966000a095cfab..1d3f9a31ad61921c17923029712f7a943e664bd6 100644 (file)
@@ -22,7 +22,6 @@
  *
  */
 
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 #include "i915_trace.h"
@@ -50,77 +49,67 @@ struct i915_mmu_notifier {
        struct hlist_node node;
        struct mmu_notifier mn;
        struct rb_root_cached objects;
-       struct workqueue_struct *wq;
+       struct i915_mm_struct *mm;
 };
 
 struct i915_mmu_object {
        struct i915_mmu_notifier *mn;
        struct drm_i915_gem_object *obj;
        struct interval_tree_node it;
-       struct list_head link;
-       struct work_struct work;
-       bool attached;
 };
 
-static void cancel_userptr(struct work_struct *work)
+static void add_object(struct i915_mmu_object *mo)
 {
-       struct i915_mmu_object *mo = container_of(work, typeof(*mo), work);
-       struct drm_i915_gem_object *obj = mo->obj;
-       struct work_struct *active;
-
-       /* Cancel any active worker and force us to re-evaluate gup */
-       mutex_lock(&obj->mm.lock);
-       active = fetch_and_zero(&obj->userptr.work);
-       mutex_unlock(&obj->mm.lock);
-       if (active)
-               goto out;
-
-       i915_gem_object_wait(obj, I915_WAIT_ALL, MAX_SCHEDULE_TIMEOUT, NULL);
-
-       mutex_lock(&obj->base.dev->struct_mutex);
-
-       /* We are inside a kthread context and can't be interrupted */
-       if (i915_gem_object_unbind(obj) == 0)
-               __i915_gem_object_put_pages(obj, I915_MM_NORMAL);
-       WARN_ONCE(i915_gem_object_has_pages(obj),
-                 "Failed to release pages: bind_count=%d, pages_pin_count=%d, pin_global=%d\n",
-                 obj->bind_count,
-                 atomic_read(&obj->mm.pages_pin_count),
-                 obj->pin_global);
-
-       mutex_unlock(&obj->base.dev->struct_mutex);
-
-out:
-       i915_gem_object_put(obj);
+       GEM_BUG_ON(!RB_EMPTY_NODE(&mo->it.rb));
+       interval_tree_insert(&mo->it, &mo->mn->objects);
 }
 
-static void add_object(struct i915_mmu_object *mo)
+static void del_object(struct i915_mmu_object *mo)
 {
-       if (mo->attached)
+       if (RB_EMPTY_NODE(&mo->it.rb))
                return;
 
-       interval_tree_insert(&mo->it, &mo->mn->objects);
-       mo->attached = true;
+       interval_tree_remove(&mo->it, &mo->mn->objects);
+       RB_CLEAR_NODE(&mo->it.rb);
 }
 
-static void del_object(struct i915_mmu_object *mo)
+static void
+__i915_gem_userptr_set_active(struct drm_i915_gem_object *obj, bool value)
 {
-       if (!mo->attached)
+       struct i915_mmu_object *mo = obj->userptr.mmu_object;
+
+       /*
+        * During mm_invalidate_range we need to cancel any userptr that
+        * overlaps the range being invalidated. Doing so requires the
+        * struct_mutex, and that risks recursion. In order to cause
+        * recursion, the user must alias the userptr address space with
+        * a GTT mmapping (possible with a MAP_FIXED) - then when we have
+        * to invalidate that mmaping, mm_invalidate_range is called with
+        * the userptr address *and* the struct_mutex held.  To prevent that
+        * we set a flag under the i915_mmu_notifier spinlock to indicate
+        * whether this object is valid.
+        */
+       if (!mo)
                return;
 
-       interval_tree_remove(&mo->it, &mo->mn->objects);
-       mo->attached = false;
+       spin_lock(&mo->mn->lock);
+       if (value)
+               add_object(mo);
+       else
+               del_object(mo);
+       spin_unlock(&mo->mn->lock);
 }
 
-static int i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
-                       const struct mmu_notifier_range *range)
+static int
+userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
+                                 const struct mmu_notifier_range *range)
 {
        struct i915_mmu_notifier *mn =
                container_of(_mn, struct i915_mmu_notifier, mn);
-       struct i915_mmu_object *mo;
        struct interval_tree_node *it;
-       LIST_HEAD(cancelled);
+       struct mutex *unlock = NULL;
        unsigned long end;
+       int ret = 0;
 
        if (RB_EMPTY_ROOT(&mn->objects.rb_root))
                return 0;
@@ -131,11 +120,15 @@ static int i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
        spin_lock(&mn->lock);
        it = interval_tree_iter_first(&mn->objects, range->start, end);
        while (it) {
+               struct drm_i915_gem_object *obj;
+
                if (!range->blockable) {
-                       spin_unlock(&mn->lock);
-                       return -EAGAIN;
+                       ret = -EAGAIN;
+                       break;
                }
-               /* The mmu_object is released late when destroying the
+
+               /*
+                * The mmu_object is released late when destroying the
                 * GEM object so it is entirely possible to gain a
                 * reference on an object in the process of being freed
                 * since our serialisation is via the spinlock and not
@@ -144,29 +137,65 @@ static int i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
                 * use-after-free we only acquire a reference on the
                 * object if it is not in the process of being destroyed.
                 */
-               mo = container_of(it, struct i915_mmu_object, it);
-               if (kref_get_unless_zero(&mo->obj->base.refcount))
-                       queue_work(mn->wq, &mo->work);
+               obj = container_of(it, struct i915_mmu_object, it)->obj;
+               if (!kref_get_unless_zero(&obj->base.refcount)) {
+                       it = interval_tree_iter_next(it, range->start, end);
+                       continue;
+               }
+               spin_unlock(&mn->lock);
+
+               if (!unlock) {
+                       unlock = &mn->mm->i915->drm.struct_mutex;
+
+                       switch (mutex_trylock_recursive(unlock)) {
+                       default:
+                       case MUTEX_TRYLOCK_FAILED:
+                               if (mutex_lock_killable_nested(unlock, I915_MM_SHRINKER)) {
+                                       i915_gem_object_put(obj);
+                                       return -EINTR;
+                               }
+                               /* fall through */
+                       case MUTEX_TRYLOCK_SUCCESS:
+                               break;
+
+                       case MUTEX_TRYLOCK_RECURSIVE:
+                               unlock = ERR_PTR(-EEXIST);
+                               break;
+                       }
+               }
+
+               ret = i915_gem_object_unbind(obj);
+               if (ret == 0)
+                       ret = __i915_gem_object_put_pages(obj, I915_MM_SHRINKER);
+               i915_gem_object_put(obj);
+               if (ret)
+                       goto unlock;
 
-               list_add(&mo->link, &cancelled);
-               it = interval_tree_iter_next(it, range->start, end);
+               spin_lock(&mn->lock);
+
+               /*
+                * As we do not (yet) protect the mmu from concurrent insertion
+                * over this range, there is no guarantee that this search will
+                * terminate given a pathologic workload.
+                */
+               it = interval_tree_iter_first(&mn->objects, range->start, end);
        }
-       list_for_each_entry(mo, &cancelled, link)
-               del_object(mo);
        spin_unlock(&mn->lock);
 
-       if (!list_empty(&cancelled))
-               flush_workqueue(mn->wq);
+unlock:
+       if (!IS_ERR_OR_NULL(unlock))
+               mutex_unlock(unlock);
+
+       return ret;
 
-       return 0;
 }
 
 static const struct mmu_notifier_ops i915_gem_userptr_notifier = {
-       .invalidate_range_start = i915_gem_userptr_mn_invalidate_range_start,
+       .invalidate_range_start = userptr_mn_invalidate_range_start,
 };
 
 static struct i915_mmu_notifier *
-i915_mmu_notifier_create(struct mm_struct *mm)
+i915_mmu_notifier_create(struct i915_mm_struct *mm)
 {
        struct i915_mmu_notifier *mn;
 
@@ -177,13 +206,7 @@ i915_mmu_notifier_create(struct mm_struct *mm)
        spin_lock_init(&mn->lock);
        mn->mn.ops = &i915_gem_userptr_notifier;
        mn->objects = RB_ROOT_CACHED;
-       mn->wq = alloc_workqueue("i915-userptr-release",
-                                WQ_UNBOUND | WQ_MEM_RECLAIM,
-                                0);
-       if (mn->wq == NULL) {
-               kfree(mn);
-               return ERR_PTR(-ENOMEM);
-       }
+       mn->mm = mm;
 
        return mn;
 }
@@ -193,16 +216,14 @@ i915_gem_userptr_release__mmu_notifier(struct drm_i915_gem_object *obj)
 {
        struct i915_mmu_object *mo;
 
-       mo = obj->userptr.mmu_object;
-       if (mo == NULL)
+       mo = fetch_and_zero(&obj->userptr.mmu_object);
+       if (!mo)
                return;
 
        spin_lock(&mo->mn->lock);
        del_object(mo);
        spin_unlock(&mo->mn->lock);
        kfree(mo);
-
-       obj->userptr.mmu_object = NULL;
 }
 
 static struct i915_mmu_notifier *
@@ -215,7 +236,7 @@ i915_mmu_notifier_find(struct i915_mm_struct *mm)
        if (mn)
                return mn;
 
-       mn = i915_mmu_notifier_create(mm->mm);
+       mn = i915_mmu_notifier_create(mm);
        if (IS_ERR(mn))
                err = PTR_ERR(mn);
 
@@ -238,10 +259,8 @@ i915_mmu_notifier_find(struct i915_mm_struct *mm)
        mutex_unlock(&mm->i915->mm_lock);
        up_write(&mm->mm->mmap_sem);
 
-       if (mn && !IS_ERR(mn)) {
-               destroy_workqueue(mn->wq);
+       if (mn && !IS_ERR(mn))
                kfree(mn);
-       }
 
        return err ? ERR_PTR(err) : mm->mn;
 }
@@ -264,14 +283,14 @@ i915_gem_userptr_init__mmu_notifier(struct drm_i915_gem_object *obj,
                return PTR_ERR(mn);
 
        mo = kzalloc(sizeof(*mo), GFP_KERNEL);
-       if (mo == NULL)
+       if (!mo)
                return -ENOMEM;
 
        mo->mn = mn;
        mo->obj = obj;
        mo->it.start = obj->userptr.ptr;
        mo->it.last = obj->userptr.ptr + obj->base.size - 1;
-       INIT_WORK(&mo->work, cancel_userptr);
+       RB_CLEAR_NODE(&mo->it.rb);
 
        obj->userptr.mmu_object = mo;
        return 0;
@@ -285,12 +304,16 @@ i915_mmu_notifier_free(struct i915_mmu_notifier *mn,
                return;
 
        mmu_notifier_unregister(&mn->mn, mm);
-       destroy_workqueue(mn->wq);
        kfree(mn);
 }
 
 #else
 
+static void
+__i915_gem_userptr_set_active(struct drm_i915_gem_object *obj, bool value)
+{
+}
+
 static void
 i915_gem_userptr_release__mmu_notifier(struct drm_i915_gem_object *obj)
 {
@@ -459,42 +482,6 @@ alloc_table:
        return st;
 }
 
-static int
-__i915_gem_userptr_set_active(struct drm_i915_gem_object *obj,
-                             bool value)
-{
-       int ret = 0;
-
-       /* During mm_invalidate_range we need to cancel any userptr that
-        * overlaps the range being invalidated. Doing so requires the
-        * struct_mutex, and that risks recursion. In order to cause
-        * recursion, the user must alias the userptr address space with
-        * a GTT mmapping (possible with a MAP_FIXED) - then when we have
-        * to invalidate that mmaping, mm_invalidate_range is called with
-        * the userptr address *and* the struct_mutex held.  To prevent that
-        * we set a flag under the i915_mmu_notifier spinlock to indicate
-        * whether this object is valid.
-        */
-#if defined(CONFIG_MMU_NOTIFIER)
-       if (obj->userptr.mmu_object == NULL)
-               return 0;
-
-       spin_lock(&obj->userptr.mmu_object->mn->lock);
-       /* In order to serialise get_pages with an outstanding
-        * cancel_userptr, we must drop the struct_mutex and try again.
-        */
-       if (!value)
-               del_object(obj->userptr.mmu_object);
-       else if (!work_pending(&obj->userptr.mmu_object->work))
-               add_object(obj->userptr.mmu_object);
-       else
-               ret = -EAGAIN;
-       spin_unlock(&obj->userptr.mmu_object->mn->lock);
-#endif
-
-       return ret;
-}
-
 static void
 __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
 {
@@ -680,8 +667,11 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj,
        struct sgt_iter sgt_iter;
        struct page *page;
 
-       BUG_ON(obj->userptr.work != NULL);
+       /* Cancel any inflight work and force them to restart their gup */
+       obj->userptr.work = NULL;
        __i915_gem_userptr_set_active(obj, false);
+       if (!pages)
+               return;
 
        if (obj->mm.madv != I915_MADV_WILLNEED)
                obj->mm.dirty = false;
@@ -719,7 +709,8 @@ i915_gem_userptr_dmabuf_export(struct drm_i915_gem_object *obj)
 
 static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = {
        .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE |
-                I915_GEM_OBJECT_IS_SHRINKABLE,
+                I915_GEM_OBJECT_IS_SHRINKABLE |
+                I915_GEM_OBJECT_ASYNC_CANCEL,
        .get_pages = i915_gem_userptr_get_pages,
        .put_pages = i915_gem_userptr_put_pages,
        .dmabuf_export = i915_gem_userptr_dmabuf_export,
index 07465123c1663c61818fc1b63c1c04cab782ba06..1f8e80e31b499e92c8413686c9a3f89940dc5ff0 100644 (file)
@@ -594,13 +594,14 @@ static void print_error_obj(struct drm_i915_error_state_buf *m,
 
 static void err_print_capabilities(struct drm_i915_error_state_buf *m,
                                   const struct intel_device_info *info,
+                                  const struct intel_runtime_info *runtime,
                                   const struct intel_driver_caps *caps)
 {
        struct drm_printer p = i915_error_printer(m);
 
        intel_device_info_dump_flags(info, &p);
        intel_driver_caps_print(caps, &p);
-       intel_device_info_dump_topology(&info->sseu, &p);
+       intel_device_info_dump_topology(&runtime->sseu, &p);
 }
 
 static void err_print_params(struct drm_i915_error_state_buf *m,
@@ -664,7 +665,9 @@ static void __err_print_to_sgl(struct drm_i915_error_state_buf *m,
 
        if (*error->error_msg)
                err_printf(m, "%s\n", error->error_msg);
-       err_printf(m, "Kernel: %s\n", init_utsname()->release);
+       err_printf(m, "Kernel: %s %s\n",
+                  init_utsname()->release,
+                  init_utsname()->machine);
        ts = ktime_to_timespec64(error->time);
        err_printf(m, "Time: %lld s %ld us\n",
                   (s64)ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC);
@@ -735,7 +738,7 @@ static void __err_print_to_sgl(struct drm_i915_error_state_buf *m,
                err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
        }
 
-       if (IS_GEN7(m->i915))
+       if (IS_GEN(m->i915, 7))
                err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
 
        for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
@@ -844,7 +847,8 @@ static void __err_print_to_sgl(struct drm_i915_error_state_buf *m,
        if (error->display)
                intel_display_print_error_state(m, error->display);
 
-       err_print_capabilities(m, &error->device_info, &error->driver_caps);
+       err_print_capabilities(m, &error->device_info, &error->runtime_info,
+                              &error->driver_caps);
        err_print_params(m, &error->params);
        err_print_uc(m, &error->uc);
 }
@@ -963,17 +967,10 @@ static void i915_error_object_free(struct drm_i915_error_object *obj)
        kfree(obj);
 }
 
-static __always_inline void free_param(const char *type, void *x)
-{
-       if (!__builtin_strcmp(type, "char *"))
-               kfree(*(void **)x);
-}
 
 static void cleanup_params(struct i915_gpu_state *error)
 {
-#define FREE(T, x, ...) free_param(#T, &error->params.x);
-       I915_PARAMS_FOR_EACH(FREE);
-#undef FREE
+       i915_params_free(&error->params);
 }
 
 static void cleanup_uc_state(struct i915_gpu_state *error)
@@ -1037,7 +1034,7 @@ i915_error_object_create(struct drm_i915_private *i915,
        dma_addr_t dma;
        int ret;
 
-       if (!vma)
+       if (!vma || !vma->pages)
                return NULL;
 
        num_pages = min_t(u64, vma->size, vma->obj->base.size) >> PAGE_SHIFT;
@@ -1085,7 +1082,7 @@ i915_error_object_create(struct drm_i915_private *i915,
 /* The error capture is special as tries to run underneath the normal
  * locking rules - so we use the raw version of the i915_gem_active lookup.
  */
-static inline uint32_t
+static inline u32
 __active_get_seqno(struct i915_gem_active *active)
 {
        struct i915_request *request;
@@ -1156,11 +1153,11 @@ static u32 capture_error_bo(struct drm_i915_error_buffer *err,
  *
  * It's only a small step better than a random number in its current form.
  */
-static uint32_t i915_error_generate_code(struct drm_i915_private *dev_priv,
-                                        struct i915_gpu_state *error,
-                                        int *engine_id)
+static u32 i915_error_generate_code(struct drm_i915_private *dev_priv,
+                                   struct i915_gpu_state *error,
+                                   int *engine_id)
 {
-       uint32_t error_code = 0;
+       u32 error_code = 0;
        int i;
 
        /* IPEHR would be an ideal way to detect errors, as it's the gross
@@ -1314,7 +1311,7 @@ static void error_record_engine_registers(struct i915_gpu_state *error,
        if (!HWS_NEEDS_PHYSICAL(dev_priv)) {
                i915_reg_t mmio;
 
-               if (IS_GEN7(dev_priv)) {
+               if (IS_GEN(dev_priv, 7)) {
                        switch (engine->id) {
                        default:
                        case RCS:
@@ -1330,7 +1327,7 @@ static void error_record_engine_registers(struct i915_gpu_state *error,
                                mmio = VEBOX_HWS_PGA_GEN7;
                                break;
                        }
-               } else if (IS_GEN6(engine->i915)) {
+               } else if (IS_GEN(engine->i915, 6)) {
                        mmio = RING_HWS_PGA_GEN6(engine->mmio_base);
                } else {
                        /* XXX: gen8 returns to sanity */
@@ -1352,10 +1349,10 @@ static void error_record_engine_registers(struct i915_gpu_state *error,
 
                ee->vm_info.gfx_mode = I915_READ(RING_MODE_GEN7(engine));
 
-               if (IS_GEN6(dev_priv))
+               if (IS_GEN(dev_priv, 6))
                        ee->vm_info.pp_dir_base =
                                I915_READ(RING_PP_DIR_BASE_READ(engine));
-               else if (IS_GEN7(dev_priv))
+               else if (IS_GEN(dev_priv, 7))
                        ee->vm_info.pp_dir_base =
                                I915_READ(RING_PP_DIR_BASE(engine));
                else if (INTEL_GEN(dev_priv) >= 8)
@@ -1725,7 +1722,7 @@ static void capture_reg_state(struct i915_gpu_state *error)
                error->forcewake = I915_READ_FW(FORCEWAKE_VLV);
        }
 
-       if (IS_GEN7(dev_priv))
+       if (IS_GEN(dev_priv, 7))
                error->err_int = I915_READ(GEN7_ERR_INT);
 
        if (INTEL_GEN(dev_priv) >= 8) {
@@ -1733,7 +1730,7 @@ static void capture_reg_state(struct i915_gpu_state *error)
                error->fault_data1 = I915_READ(GEN8_FAULT_TLB_DATA1);
        }
 
-       if (IS_GEN6(dev_priv)) {
+       if (IS_GEN(dev_priv, 6)) {
                error->forcewake = I915_READ_FW(FORCEWAKE);
                error->gab_ctl = I915_READ(GAB_CTL);
                error->gfx_mode = I915_READ(GFX_MODE);
@@ -1753,7 +1750,7 @@ static void capture_reg_state(struct i915_gpu_state *error)
                error->ccid = I915_READ(CCID);
 
        /* 3: Feature specific registers */
-       if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) {
+       if (IS_GEN_RANGE(dev_priv, 6, 7)) {
                error->gam_ecochk = I915_READ(GAM_ECOCHK);
                error->gac_eco = I915_READ(GAC_ECO_BITS);
        }
@@ -1777,7 +1774,7 @@ static void capture_reg_state(struct i915_gpu_state *error)
                error->ier = I915_READ(DEIER);
                error->gtier[0] = I915_READ(GTIER);
                error->ngtier = 1;
-       } else if (IS_GEN2(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 2)) {
                error->ier = I915_READ16(IER);
        } else if (!IS_VALLEYVIEW(dev_priv)) {
                error->ier = I915_READ(IER);
@@ -1831,21 +1828,15 @@ static void capture_gen_state(struct i915_gpu_state *error)
        memcpy(&error->device_info,
               INTEL_INFO(i915),
               sizeof(error->device_info));
+       memcpy(&error->runtime_info,
+              RUNTIME_INFO(i915),
+              sizeof(error->runtime_info));
        error->driver_caps = i915->caps;
 }
 
-static __always_inline void dup_param(const char *type, void *x)
-{
-       if (!__builtin_strcmp(type, "char *"))
-               *(void **)x = kstrdup(*(void **)x, GFP_ATOMIC);
-}
-
 static void capture_params(struct i915_gpu_state *error)
 {
-       error->params = i915_modparams;
-#define DUP(T, x, ...) dup_param(#T, &error->params.x);
-       I915_PARAMS_FOR_EACH(DUP);
-#undef DUP
+       i915_params_copy(&error->params, &i915_modparams);
 }
 
 static unsigned long capture_find_epoch(const struct i915_gpu_state *error)
@@ -1907,9 +1898,16 @@ i915_capture_gpu_state(struct drm_i915_private *i915)
 {
        struct i915_gpu_state *error;
 
+       /* Check if GPU capture has been disabled */
+       error = READ_ONCE(i915->gpu_error.first_error);
+       if (IS_ERR(error))
+               return error;
+
        error = kzalloc(sizeof(*error), GFP_ATOMIC);
-       if (!error)
-               return NULL;
+       if (!error) {
+               i915_disable_error_state(i915, -ENOMEM);
+               return ERR_PTR(-ENOMEM);
+       }
 
        kref_init(&error->ref);
        error->i915 = i915;
@@ -1945,11 +1943,8 @@ void i915_capture_error_state(struct drm_i915_private *i915,
                return;
 
        error = i915_capture_gpu_state(i915);
-       if (!error) {
-               DRM_DEBUG_DRIVER("out of memory, not capturing error state\n");
-               i915_disable_error_state(i915, -ENOMEM);
+       if (IS_ERR(error))
                return;
-       }
 
        i915_error_capture_msg(i915, error, engine_mask, error_msg);
        DRM_INFO("%s\n", error->error_msg);
@@ -1987,7 +1982,7 @@ i915_first_error_state(struct drm_i915_private *i915)
 
        spin_lock_irq(&i915->gpu_error.lock);
        error = i915->gpu_error.first_error;
-       if (error)
+       if (!IS_ERR_OR_NULL(error))
                i915_gpu_state_get(error);
        spin_unlock_irq(&i915->gpu_error.lock);
 
@@ -2000,10 +1995,11 @@ void i915_reset_error_state(struct drm_i915_private *i915)
 
        spin_lock_irq(&i915->gpu_error.lock);
        error = i915->gpu_error.first_error;
-       i915->gpu_error.first_error = NULL;
+       if (error != ERR_PTR(-ENODEV)) /* if disabled, always disabled */
+               i915->gpu_error.first_error = NULL;
        spin_unlock_irq(&i915->gpu_error.lock);
 
-       if (!IS_ERR(error))
+       if (!IS_ERR_OR_NULL(error))
                i915_gpu_state_put(error);
 }
 
index ff2652bbb0b08bb22cab8d32f338c1bdf8643e81..604291f7762d6a21c40970273da6082cbd66289c 100644 (file)
@@ -45,6 +45,7 @@ struct i915_gpu_state {
        u32 reset_count;
        u32 suspend_count;
        struct intel_device_info device_info;
+       struct intel_runtime_info runtime_info;
        struct intel_driver_caps driver_caps;
        struct i915_params params;
 
@@ -270,8 +271,8 @@ struct i915_gpu_error {
 #define I915_RESET_BACKOFF     0
 #define I915_RESET_HANDOFF     1
 #define I915_RESET_MODESET     2
+#define I915_RESET_ENGINE      3
 #define I915_WEDGED            (BITS_PER_LONG - 1)
-#define I915_RESET_ENGINE      (I915_WEDGED - I915_NUM_ENGINES)
 
        /** Number of times an engine has been reset */
        u32 reset_engine_count[I915_NUM_ENGINES];
@@ -282,6 +283,8 @@ struct i915_gpu_error {
        /** Reason for the current *global* reset */
        const char *reason;
 
+       struct mutex wedge_mutex; /* serialises wedging/unwedging */
+
        /**
         * Waitqueue to signal when a hang is detected. Used to for waiters
         * to release the struct_mutex for the reset to procede.
index e869daf9c8a9e0c21f409506ab60240f76bd95c7..73c3e8f519e8fbfa463a4c830c28a86638eb8710 100644 (file)
@@ -28,7 +28,6 @@
  */
 #include <linux/compat.h>
 
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 
index d447d7d508f483c62baecad23035a60702fd6a3c..7056ae2d1e0ebf08a6cba08f605d6cbe7a39357a 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/sysrq.h>
 #include <linux/slab.h>
 #include <linux/circ_buf.h>
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 #include "i915_trace.h"
@@ -224,10 +223,10 @@ static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir);
 /* For display hotplug interrupt */
 static inline void
 i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv,
-                                    uint32_t mask,
-                                    uint32_t bits)
+                                    u32 mask,
+                                    u32 bits)
 {
-       uint32_t val;
+       u32 val;
 
        lockdep_assert_held(&dev_priv->irq_lock);
        WARN_ON(bits & ~mask);
@@ -251,8 +250,8 @@ i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv,
  * version is also available.
  */
 void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv,
-                                  uint32_t mask,
-                                  uint32_t bits)
+                                  u32 mask,
+                                  u32 bits)
 {
        spin_lock_irq(&dev_priv->irq_lock);
        i915_hotplug_interrupt_update_locked(dev_priv, mask, bits);
@@ -301,10 +300,10 @@ static bool gen11_reset_one_iir(struct drm_i915_private * const i915,
  * @enabled_irq_mask: mask of interrupt bits to enable
  */
 void ilk_update_display_irq(struct drm_i915_private *dev_priv,
-                           uint32_t interrupt_mask,
-                           uint32_t enabled_irq_mask)
+                           u32 interrupt_mask,
+                           u32 enabled_irq_mask)
 {
-       uint32_t new_val;
+       u32 new_val;
 
        lockdep_assert_held(&dev_priv->irq_lock);
 
@@ -331,8 +330,8 @@ void ilk_update_display_irq(struct drm_i915_private *dev_priv,
  * @enabled_irq_mask: mask of interrupt bits to enable
  */
 static void ilk_update_gt_irq(struct drm_i915_private *dev_priv,
-                             uint32_t interrupt_mask,
-                             uint32_t enabled_irq_mask)
+                             u32 interrupt_mask,
+                             u32 enabled_irq_mask)
 {
        lockdep_assert_held(&dev_priv->irq_lock);
 
@@ -346,13 +345,13 @@ static void ilk_update_gt_irq(struct drm_i915_private *dev_priv,
        I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
 }
 
-void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, u32 mask)
 {
        ilk_update_gt_irq(dev_priv, mask, mask);
        POSTING_READ_FW(GTIMR);
 }
 
-void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, u32 mask)
 {
        ilk_update_gt_irq(dev_priv, mask, 0);
 }
@@ -391,10 +390,10 @@ static i915_reg_t gen6_pm_ier(struct drm_i915_private *dev_priv)
  * @enabled_irq_mask: mask of interrupt bits to enable
  */
 static void snb_update_pm_irq(struct drm_i915_private *dev_priv,
-                             uint32_t interrupt_mask,
-                             uint32_t enabled_irq_mask)
+                             u32 interrupt_mask,
+                             u32 enabled_irq_mask)
 {
-       uint32_t new_val;
+       u32 new_val;
 
        WARN_ON(enabled_irq_mask & ~interrupt_mask);
 
@@ -578,11 +577,11 @@ void gen9_disable_guc_interrupts(struct drm_i915_private *dev_priv)
  * @enabled_irq_mask: mask of interrupt bits to enable
  */
 static void bdw_update_port_irq(struct drm_i915_private *dev_priv,
-                               uint32_t interrupt_mask,
-                               uint32_t enabled_irq_mask)
+                               u32 interrupt_mask,
+                               u32 enabled_irq_mask)
 {
-       uint32_t new_val;
-       uint32_t old_val;
+       u32 new_val;
+       u32 old_val;
 
        lockdep_assert_held(&dev_priv->irq_lock);
 
@@ -612,10 +611,10 @@ static void bdw_update_port_irq(struct drm_i915_private *dev_priv,
  */
 void bdw_update_pipe_irq(struct drm_i915_private *dev_priv,
                         enum pipe pipe,
-                        uint32_t interrupt_mask,
-                        uint32_t enabled_irq_mask)
+                        u32 interrupt_mask,
+                        u32 enabled_irq_mask)
 {
-       uint32_t new_val;
+       u32 new_val;
 
        lockdep_assert_held(&dev_priv->irq_lock);
 
@@ -642,10 +641,10 @@ void bdw_update_pipe_irq(struct drm_i915_private *dev_priv,
  * @enabled_irq_mask: mask of interrupt bits to enable
  */
 void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
-                                 uint32_t interrupt_mask,
-                                 uint32_t enabled_irq_mask)
+                                 u32 interrupt_mask,
+                                 u32 enabled_irq_mask)
 {
-       uint32_t sdeimr = I915_READ(SDEIMR);
+       u32 sdeimr = I915_READ(SDEIMR);
        sdeimr &= ~interrupt_mask;
        sdeimr |= (~enabled_irq_mask & interrupt_mask);
 
@@ -950,7 +949,7 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
        if (mode->flags & DRM_MODE_FLAG_INTERLACE)
                vtotal /= 2;
 
-       if (IS_GEN2(dev_priv))
+       if (IS_GEN(dev_priv, 2))
                position = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN2;
        else
                position = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN3;
@@ -1030,7 +1029,7 @@ static bool i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
        if (stime)
                *stime = ktime_get();
 
-       if (IS_GEN2(dev_priv) || IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5) {
+       if (IS_GEN(dev_priv, 2) || IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5) {
                /* No obvious pixelcount register. Only query vertical
                 * scanout position from Display scan line register.
                 */
@@ -1090,7 +1089,7 @@ static bool i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
        else
                position += vtotal - vbl_end;
 
-       if (IS_GEN2(dev_priv) || IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5) {
+       if (IS_GEN(dev_priv, 2) || IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5) {
                *vpos = position;
                *hpos = 0;
        } else {
@@ -1183,19 +1182,11 @@ static void notify_ring(struct intel_engine_cs *engine)
                        struct i915_request *waiter = wait->request;
 
                        if (waiter &&
-                           !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
-                                     &waiter->fence.flags) &&
+                           !i915_request_signaled(waiter) &&
                            intel_wait_check_request(wait, waiter))
                                rq = i915_request_get(waiter);
 
                        tsk = wait->tsk;
-               } else {
-                       if (engine->irq_seqno_barrier &&
-                           i915_seqno_passed(seqno, wait->seqno - 1)) {
-                               set_bit(ENGINE_IRQ_BREADCRUMB,
-                                       &engine->irq_posted);
-                               tsk = wait->tsk;
-                       }
                }
 
                engine->breadcrumbs.irq_count++;
@@ -1376,8 +1367,8 @@ static void ivybridge_parity_work(struct work_struct *work)
                container_of(work, typeof(*dev_priv), l3_parity.error_work);
        u32 error_status, row, bank, subbank;
        char *parity_event[6];
-       uint32_t misccpctl;
-       uint8_t slice = 0;
+       u32 misccpctl;
+       u8 slice = 0;
 
        /* We must turn off DOP level clock gating to access the L3 registers.
         * In order to prevent a get/put style interface, acquire struct mutex
@@ -1738,13 +1729,13 @@ static void dp_aux_irq_handler(struct drm_i915_private *dev_priv)
 #if defined(CONFIG_DEBUG_FS)
 static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
                                         enum pipe pipe,
-                                        uint32_t crc0, uint32_t crc1,
-                                        uint32_t crc2, uint32_t crc3,
-                                        uint32_t crc4)
+                                        u32 crc0, u32 crc1,
+                                        u32 crc2, u32 crc3,
+                                        u32 crc4)
 {
        struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
        struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
-       uint32_t crcs[5];
+       u32 crcs[5];
 
        spin_lock(&pipe_crc->lock);
        /*
@@ -1776,9 +1767,9 @@ static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
 static inline void
 display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
                             enum pipe pipe,
-                            uint32_t crc0, uint32_t crc1,
-                            uint32_t crc2, uint32_t crc3,
-                            uint32_t crc4) {}
+                            u32 crc0, u32 crc1,
+                            u32 crc2, u32 crc3,
+                            u32 crc4) {}
 #endif
 
 
@@ -1804,7 +1795,7 @@ static void ivb_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
 static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
                                      enum pipe pipe)
 {
-       uint32_t res1, res2;
+       u32 res1, res2;
 
        if (INTEL_GEN(dev_priv) >= 3)
                res1 = I915_READ(PIPE_CRC_RES_RES1_I915(pipe));
@@ -2547,7 +2538,7 @@ static void ilk_display_irq_handler(struct drm_i915_private *dev_priv,
                I915_WRITE(SDEIIR, pch_iir);
        }
 
-       if (IS_GEN5(dev_priv) && de_iir & DE_PCU_EVENT)
+       if (IS_GEN(dev_priv, 5) && de_iir & DE_PCU_EVENT)
                ironlake_rps_change_irq_handler(dev_priv);
 }
 
@@ -2938,46 +2929,6 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
        return IRQ_HANDLED;
 }
 
-struct wedge_me {
-       struct delayed_work work;
-       struct drm_i915_private *i915;
-       const char *name;
-};
-
-static void wedge_me(struct work_struct *work)
-{
-       struct wedge_me *w = container_of(work, typeof(*w), work.work);
-
-       dev_err(w->i915->drm.dev,
-               "%s timed out, cancelling all in-flight rendering.\n",
-               w->name);
-       i915_gem_set_wedged(w->i915);
-}
-
-static void __init_wedge(struct wedge_me *w,
-                        struct drm_i915_private *i915,
-                        long timeout,
-                        const char *name)
-{
-       w->i915 = i915;
-       w->name = name;
-
-       INIT_DELAYED_WORK_ONSTACK(&w->work, wedge_me);
-       schedule_delayed_work(&w->work, timeout);
-}
-
-static void __fini_wedge(struct wedge_me *w)
-{
-       cancel_delayed_work_sync(&w->work);
-       destroy_delayed_work_on_stack(&w->work);
-       w->i915 = NULL;
-}
-
-#define i915_wedge_on_timeout(W, DEV, TIMEOUT)                         \
-       for (__init_wedge((W), (DEV), (TIMEOUT), __func__);             \
-            (W)->i915;                                                 \
-            __fini_wedge((W)))
-
 static u32
 gen11_gt_engine_identity(struct drm_i915_private * const i915,
                         const unsigned int bank, const unsigned int bit)
@@ -3188,203 +3139,6 @@ static irqreturn_t gen11_irq_handler(int irq, void *arg)
        return IRQ_HANDLED;
 }
 
-static void i915_reset_device(struct drm_i915_private *dev_priv,
-                             u32 engine_mask,
-                             const char *reason)
-{
-       struct i915_gpu_error *error = &dev_priv->gpu_error;
-       struct kobject *kobj = &dev_priv->drm.primary->kdev->kobj;
-       char *error_event[] = { I915_ERROR_UEVENT "=1", NULL };
-       char *reset_event[] = { I915_RESET_UEVENT "=1", NULL };
-       char *reset_done_event[] = { I915_ERROR_UEVENT "=0", NULL };
-       struct wedge_me w;
-
-       kobject_uevent_env(kobj, KOBJ_CHANGE, error_event);
-
-       DRM_DEBUG_DRIVER("resetting chip\n");
-       kobject_uevent_env(kobj, KOBJ_CHANGE, reset_event);
-
-       /* Use a watchdog to ensure that our reset completes */
-       i915_wedge_on_timeout(&w, dev_priv, 5*HZ) {
-               intel_prepare_reset(dev_priv);
-
-               error->reason = reason;
-               error->stalled_mask = engine_mask;
-
-               /* Signal that locked waiters should reset the GPU */
-               smp_mb__before_atomic();
-               set_bit(I915_RESET_HANDOFF, &error->flags);
-               wake_up_all(&error->wait_queue);
-
-               /* Wait for anyone holding the lock to wakeup, without
-                * blocking indefinitely on struct_mutex.
-                */
-               do {
-                       if (mutex_trylock(&dev_priv->drm.struct_mutex)) {
-                               i915_reset(dev_priv, engine_mask, reason);
-                               mutex_unlock(&dev_priv->drm.struct_mutex);
-                       }
-               } while (wait_on_bit_timeout(&error->flags,
-                                            I915_RESET_HANDOFF,
-                                            TASK_UNINTERRUPTIBLE,
-                                            1));
-
-               error->stalled_mask = 0;
-               error->reason = NULL;
-
-               intel_finish_reset(dev_priv);
-       }
-
-       if (!test_bit(I915_WEDGED, &error->flags))
-               kobject_uevent_env(kobj, KOBJ_CHANGE, reset_done_event);
-}
-
-void i915_clear_error_registers(struct drm_i915_private *dev_priv)
-{
-       u32 eir;
-
-       if (!IS_GEN2(dev_priv))
-               I915_WRITE(PGTBL_ER, I915_READ(PGTBL_ER));
-
-       if (INTEL_GEN(dev_priv) < 4)
-               I915_WRITE(IPEIR, I915_READ(IPEIR));
-       else
-               I915_WRITE(IPEIR_I965, I915_READ(IPEIR_I965));
-
-       I915_WRITE(EIR, I915_READ(EIR));
-       eir = I915_READ(EIR);
-       if (eir) {
-               /*
-                * some errors might have become stuck,
-                * mask them.
-                */
-               DRM_DEBUG_DRIVER("EIR stuck: 0x%08x, masking\n", eir);
-               I915_WRITE(EMR, I915_READ(EMR) | eir);
-               I915_WRITE(IIR, I915_MASTER_ERROR_INTERRUPT);
-       }
-
-       if (INTEL_GEN(dev_priv) >= 8) {
-               I915_WRITE(GEN8_RING_FAULT_REG,
-                          I915_READ(GEN8_RING_FAULT_REG) & ~RING_FAULT_VALID);
-               POSTING_READ(GEN8_RING_FAULT_REG);
-       } else if (INTEL_GEN(dev_priv) >= 6) {
-               struct intel_engine_cs *engine;
-               enum intel_engine_id id;
-
-               for_each_engine(engine, dev_priv, id) {
-                       I915_WRITE(RING_FAULT_REG(engine),
-                                  I915_READ(RING_FAULT_REG(engine)) &
-                                  ~RING_FAULT_VALID);
-               }
-               POSTING_READ(RING_FAULT_REG(dev_priv->engine[RCS]));
-       }
-}
-
-/**
- * i915_handle_error - handle a gpu error
- * @dev_priv: i915 device private
- * @engine_mask: mask representing engines that are hung
- * @flags: control flags
- * @fmt: Error message format string
- *
- * Do some basic checking of register state at error time and
- * dump it to the syslog.  Also call i915_capture_error_state() to make
- * sure we get a record and make it available in debugfs.  Fire a uevent
- * so userspace knows something bad happened (should trigger collection
- * of a ring dump etc.).
- */
-void i915_handle_error(struct drm_i915_private *dev_priv,
-                      u32 engine_mask,
-                      unsigned long flags,
-                      const char *fmt, ...)
-{
-       struct intel_engine_cs *engine;
-       unsigned int tmp;
-       char error_msg[80];
-       char *msg = NULL;
-
-       if (fmt) {
-               va_list args;
-
-               va_start(args, fmt);
-               vscnprintf(error_msg, sizeof(error_msg), fmt, args);
-               va_end(args);
-
-               msg = error_msg;
-       }
-
-       /*
-        * In most cases it's guaranteed that we get here with an RPM
-        * reference held, for example because there is a pending GPU
-        * request that won't finish until the reset is done. This
-        * isn't the case at least when we get here by doing a
-        * simulated reset via debugfs, so get an RPM reference.
-        */
-       intel_runtime_pm_get(dev_priv);
-
-       engine_mask &= INTEL_INFO(dev_priv)->ring_mask;
-
-       if (flags & I915_ERROR_CAPTURE) {
-               i915_capture_error_state(dev_priv, engine_mask, msg);
-               i915_clear_error_registers(dev_priv);
-       }
-
-       /*
-        * Try engine reset when available. We fall back to full reset if
-        * single reset fails.
-        */
-       if (intel_has_reset_engine(dev_priv) &&
-           !i915_terminally_wedged(&dev_priv->gpu_error)) {
-               for_each_engine_masked(engine, dev_priv, engine_mask, tmp) {
-                       BUILD_BUG_ON(I915_RESET_MODESET >= I915_RESET_ENGINE);
-                       if (test_and_set_bit(I915_RESET_ENGINE + engine->id,
-                                            &dev_priv->gpu_error.flags))
-                               continue;
-
-                       if (i915_reset_engine(engine, msg) == 0)
-                               engine_mask &= ~intel_engine_flag(engine);
-
-                       clear_bit(I915_RESET_ENGINE + engine->id,
-                                 &dev_priv->gpu_error.flags);
-                       wake_up_bit(&dev_priv->gpu_error.flags,
-                                   I915_RESET_ENGINE + engine->id);
-               }
-       }
-
-       if (!engine_mask)
-               goto out;
-
-       /* Full reset needs the mutex, stop any other user trying to do so. */
-       if (test_and_set_bit(I915_RESET_BACKOFF, &dev_priv->gpu_error.flags)) {
-               wait_event(dev_priv->gpu_error.reset_queue,
-                          !test_bit(I915_RESET_BACKOFF,
-                                    &dev_priv->gpu_error.flags));
-               goto out;
-       }
-
-       /* Prevent any other reset-engine attempt. */
-       for_each_engine(engine, dev_priv, tmp) {
-               while (test_and_set_bit(I915_RESET_ENGINE + engine->id,
-                                       &dev_priv->gpu_error.flags))
-                       wait_on_bit(&dev_priv->gpu_error.flags,
-                                   I915_RESET_ENGINE + engine->id,
-                                   TASK_UNINTERRUPTIBLE);
-       }
-
-       i915_reset_device(dev_priv, engine_mask, msg);
-
-       for_each_engine(engine, dev_priv, tmp) {
-               clear_bit(I915_RESET_ENGINE + engine->id,
-                         &dev_priv->gpu_error.flags);
-       }
-
-       clear_bit(I915_RESET_BACKOFF, &dev_priv->gpu_error.flags);
-       wake_up_all(&dev_priv->gpu_error.reset_queue);
-
-out:
-       intel_runtime_pm_put(dev_priv);
-}
-
 /* Called from drm generic code, passed 'crtc' which
  * we use as a pipe index
  */
@@ -3417,7 +3171,7 @@ static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
        unsigned long irqflags;
-       uint32_t bit = INTEL_GEN(dev_priv) >= 7 ?
+       u32 bit = INTEL_GEN(dev_priv) >= 7 ?
                DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
@@ -3479,7 +3233,7 @@ static void ironlake_disable_vblank(struct drm_device *dev, unsigned int pipe)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
        unsigned long irqflags;
-       uint32_t bit = INTEL_GEN(dev_priv) >= 7 ?
+       u32 bit = INTEL_GEN(dev_priv) >= 7 ?
                DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
@@ -3586,11 +3340,8 @@ static void ironlake_irq_reset(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
 
-       if (IS_GEN5(dev_priv))
-               I915_WRITE(HWSTAM, 0xffffffff);
-
        GEN3_IRQ_RESET(DE);
-       if (IS_GEN7(dev_priv))
+       if (IS_GEN(dev_priv, 7))
                I915_WRITE(GEN7_ERR_INT, 0xffffffff);
 
        if (IS_HASWELL(dev_priv)) {
@@ -3700,7 +3451,7 @@ static void gen11_irq_reset(struct drm_device *dev)
 void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
                                     u8 pipe_mask)
 {
-       uint32_t extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN;
+       u32 extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN;
        enum pipe pipe;
 
        spin_lock_irq(&dev_priv->irq_lock);
@@ -4045,7 +3796,7 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev)
        }
 
        gt_irqs |= GT_RENDER_USER_INTERRUPT;
-       if (IS_GEN5(dev_priv)) {
+       if (IS_GEN(dev_priv, 5)) {
                gt_irqs |= ILK_BSD_USER_INTERRUPT;
        } else {
                gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT;
@@ -4169,7 +3920,7 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv)
 {
        /* These are interrupts we'll toggle with the ring mask register */
-       uint32_t gt_interrupts[] = {
+       u32 gt_interrupts[] = {
                GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
                        GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
                        GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT |
@@ -4183,9 +3934,6 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv)
                        GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT
                };
 
-       if (HAS_L3_DPF(dev_priv))
-               gt_interrupts[0] |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
-
        dev_priv->pm_ier = 0x0;
        dev_priv->pm_imr = ~dev_priv->pm_ier;
        GEN8_IRQ_INIT_NDX(GT, 0, ~gt_interrupts[0], gt_interrupts[0]);
@@ -4200,8 +3948,8 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv)
 
 static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
 {
-       uint32_t de_pipe_masked = GEN8_PIPE_CDCLK_CRC_DONE;
-       uint32_t de_pipe_enables;
+       u32 de_pipe_masked = GEN8_PIPE_CDCLK_CRC_DONE;
+       u32 de_pipe_enables;
        u32 de_port_masked = GEN8_AUX_CHANNEL_A;
        u32 de_port_enables;
        u32 de_misc_masked = GEN8_DE_EDP_PSR;
@@ -4341,6 +4089,7 @@ static int gen11_irq_postinstall(struct drm_device *dev)
        I915_WRITE(GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE);
 
        gen11_master_intr_enable(dev_priv->regs);
+       POSTING_READ(GEN11_GFX_MSTR_IRQ);
 
        return 0;
 }
@@ -4368,8 +4117,6 @@ static void i8xx_irq_reset(struct drm_device *dev)
 
        i9xx_pipestat_irq_reset(dev_priv);
 
-       I915_WRITE16(HWSTAM, 0xffff);
-
        GEN2_IRQ_RESET();
 }
 
@@ -4537,8 +4284,6 @@ static void i915_irq_reset(struct drm_device *dev)
 
        i9xx_pipestat_irq_reset(dev_priv);
 
-       I915_WRITE(HWSTAM, 0xffffffff);
-
        GEN3_IRQ_RESET();
 }
 
@@ -4648,8 +4393,6 @@ static void i965_irq_reset(struct drm_device *dev)
 
        i9xx_pipestat_irq_reset(dev_priv);
 
-       I915_WRITE(HWSTAM, 0xffffffff);
-
        GEN3_IRQ_RESET();
 }
 
@@ -4836,7 +4579,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
        if (INTEL_GEN(dev_priv) >= 8)
                rps->pm_intrmsk_mbz |= GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC;
 
-       if (IS_GEN2(dev_priv)) {
+       if (IS_GEN(dev_priv, 2)) {
                /* Gen2 doesn't have a hardware frame counter */
                dev->max_vblank_count = 0;
        } else if (IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5) {
@@ -4852,7 +4595,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
         * Gen2 doesn't have a hardware frame counter and so depends on
         * vblank interrupts to produce sane vblank seuquence numbers.
         */
-       if (!IS_GEN2(dev_priv))
+       if (!IS_GEN(dev_priv, 2))
                dev->vblank_disable_immediate = true;
 
        /* Most platforms treat the display irq block as an always-on
@@ -4924,14 +4667,14 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
                dev->driver->disable_vblank = ironlake_disable_vblank;
                dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup;
        } else {
-               if (IS_GEN2(dev_priv)) {
+               if (IS_GEN(dev_priv, 2)) {
                        dev->driver->irq_preinstall = i8xx_irq_reset;
                        dev->driver->irq_postinstall = i8xx_irq_postinstall;
                        dev->driver->irq_handler = i8xx_irq_handler;
                        dev->driver->irq_uninstall = i8xx_irq_reset;
                        dev->driver->enable_vblank = i8xx_enable_vblank;
                        dev->driver->disable_vblank = i8xx_disable_vblank;
-               } else if (IS_GEN3(dev_priv)) {
+               } else if (IS_GEN(dev_priv, 3)) {
                        dev->driver->irq_preinstall = i915_irq_reset;
                        dev->driver->irq_postinstall = i915_irq_postinstall;
                        dev->driver->irq_uninstall = i915_irq_reset;
index 2e0356561839d15016d72394d7960388545fb223..9f0539bdaa398dbfb4050df67f952eb0207e1c57 100644 (file)
@@ -77,7 +77,7 @@ i915_param_named(error_capture, bool, 0600,
        "triaging and debugging hangs.");
 #endif
 
-i915_param_named_unsafe(enable_hangcheck, bool, 0644,
+i915_param_named_unsafe(enable_hangcheck, bool, 0600,
        "Periodically check GPU activity for detecting hangs. "
        "WARNING: Disabling this can cause system wide hangs. "
        "(default: true)");
@@ -203,3 +203,33 @@ void i915_params_dump(const struct i915_params *params, struct drm_printer *p)
        I915_PARAMS_FOR_EACH(PRINT);
 #undef PRINT
 }
+
+static __always_inline void dup_param(const char *type, void *x)
+{
+       if (!__builtin_strcmp(type, "char *"))
+               *(void **)x = kstrdup(*(void **)x, GFP_ATOMIC);
+}
+
+void i915_params_copy(struct i915_params *dest, const struct i915_params *src)
+{
+       *dest = *src;
+#define DUP(T, x, ...) dup_param(#T, &dest->x);
+       I915_PARAMS_FOR_EACH(DUP);
+#undef DUP
+}
+
+static __always_inline void free_param(const char *type, void *x)
+{
+       if (!__builtin_strcmp(type, "char *")) {
+               kfree(*(void **)x);
+               *(void **)x = NULL;
+       }
+}
+
+/* free the allocated members, *not* the passed in params itself */
+void i915_params_free(struct i915_params *params)
+{
+#define FREE(T, x, ...) free_param(#T, &params->x);
+       I915_PARAMS_FOR_EACH(FREE);
+#undef FREE
+}
index 7e56c516c815c269230c697da6166a7fae455fd8..6efcf330bdab83fa41aefac760e0965d5531454d 100644 (file)
@@ -33,6 +33,15 @@ struct drm_printer;
 #define ENABLE_GUC_SUBMISSION          BIT(0)
 #define ENABLE_GUC_LOAD_HUC            BIT(1)
 
+/*
+ * Invoke param, a function-like macro, for each i915 param, with arguments:
+ *
+ * param(type, name, value)
+ *
+ * type: parameter type, one of {bool, int, unsigned int, char *}
+ * name: name of the parameter
+ * value: initial/default value of the parameter
+ */
 #define I915_PARAMS_FOR_EACH(param) \
        param(char *, vbt_firmware, NULL) \
        param(int, modeset, -1) \
@@ -78,6 +87,8 @@ struct i915_params {
 extern struct i915_params i915_modparams __read_mostly;
 
 void i915_params_dump(const struct i915_params *params, struct drm_printer *p);
+void i915_params_copy(struct i915_params *dest, const struct i915_params *src);
+void i915_params_free(struct i915_params *params);
 
 #endif
 
index 6350db5503cda372cedcda638680dfcec9725a7e..dd4aff2b256e910408ba5d7a5d35ca4fa34a9d5e 100644 (file)
@@ -82,6 +82,7 @@
        .display.has_overlay = 1, \
        .display.overlay_needs_physical = 1, \
        .display.has_gmch_display = 1, \
+       .gpu_reset_clobbers_display = true, \
        .hws_needs_physical = 1, \
        .unfenced_needs_alignment = 1, \
        .ring_mask = RENDER_RING, \
@@ -122,6 +123,7 @@ static const struct intel_device_info intel_i865g_info = {
        GEN(3), \
        .num_pipes = 2, \
        .display.has_gmch_display = 1, \
+       .gpu_reset_clobbers_display = true, \
        .ring_mask = RENDER_RING, \
        .has_snoop = true, \
        .has_coherent_ggtt = true, \
@@ -198,6 +200,7 @@ static const struct intel_device_info intel_pineview_info = {
        .num_pipes = 2, \
        .display.has_hotplug = 1, \
        .display.has_gmch_display = 1, \
+       .gpu_reset_clobbers_display = true, \
        .ring_mask = RENDER_RING, \
        .has_snoop = true, \
        .has_coherent_ggtt = true, \
@@ -228,6 +231,7 @@ static const struct intel_device_info intel_g45_info = {
        GEN4_FEATURES,
        PLATFORM(INTEL_G45),
        .ring_mask = RENDER_RING | BSD_RING,
+       .gpu_reset_clobbers_display = false,
 };
 
 static const struct intel_device_info intel_gm45_info = {
@@ -237,6 +241,7 @@ static const struct intel_device_info intel_gm45_info = {
        .display.has_fbc = 1,
        .display.supports_tv = 1,
        .ring_mask = RENDER_RING | BSD_RING,
+       .gpu_reset_clobbers_display = false,
 };
 
 #define GEN5_FEATURES \
@@ -532,7 +537,6 @@ static const struct intel_device_info intel_skylake_gt4_info = {
        .display.has_fbc = 1, \
        .display.has_psr = 1, \
        .has_runtime_pm = 1, \
-       .has_pooled_eu = 0, \
        .display.has_csr = 1, \
        .has_rc6 = 1, \
        .display.has_dp_mst = 1, \
index 2b2eb57ca71f2905020aed9f7797684f69c148e7..727118301f919dfbe594692229e8b53f7f958cd8 100644 (file)
@@ -1365,7 +1365,7 @@ static void i915_oa_stream_destroy(struct i915_perf_stream *stream)
        free_oa_buffer(dev_priv);
 
        intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, stream->wakeref);
 
        if (stream->ctx)
                oa_put_render_ctx_id(stream);
@@ -1796,7 +1796,7 @@ static int gen8_enable_metric_set(struct i915_perf_stream *stream)
         * be read back from automatically triggered reports, as part of the
         * RPT_ID field.
         */
-       if (IS_GEN(dev_priv, 9, 11)) {
+       if (IS_GEN_RANGE(dev_priv, 9, 11)) {
                I915_WRITE(GEN8_OA_DEBUG,
                           _MASKED_BIT_ENABLE(GEN9_OA_DEBUG_DISABLE_CLK_RATIO_REPORTS |
                                              GEN9_OA_DEBUG_INCLUDE_CLK_RATIO));
@@ -2087,7 +2087,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
         *   In our case we are expecting that taking pm + FORCEWAKE
         *   references will effectively disable RC6.
         */
-       intel_runtime_pm_get(dev_priv);
+       stream->wakeref = intel_runtime_pm_get(dev_priv);
        intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
 
        ret = alloc_oa_buffer(dev_priv);
@@ -2123,7 +2123,7 @@ err_oa_buf_alloc:
        put_oa_config(dev_priv, stream->oa_config);
 
        intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, stream->wakeref);
 
 err_config:
        if (stream->ctx)
@@ -2646,7 +2646,7 @@ err:
 static u64 oa_exponent_to_ns(struct drm_i915_private *dev_priv, int exponent)
 {
        return div64_u64(1000000000ULL * (2ULL << exponent),
-                        1000ULL * INTEL_INFO(dev_priv)->cs_timestamp_frequency_khz);
+                        1000ULL * RUNTIME_INFO(dev_priv)->cs_timestamp_frequency_khz);
 }
 
 /**
@@ -3021,7 +3021,7 @@ static bool chv_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr)
                (addr >= 0x182300 && addr <= 0x1823A4);
 }
 
-static uint32_t mask_reg_value(u32 reg, u32 val)
+static u32 mask_reg_value(u32 reg, u32 val)
 {
        /* HALF_SLICE_CHICKEN2 is programmed with a the
         * WaDisableSTUnitPowerOptimization workaround. Make sure the value
@@ -3415,7 +3415,7 @@ void i915_perf_init(struct drm_i915_private *dev_priv)
                dev_priv->perf.oa.ops.read = gen8_oa_read;
                dev_priv->perf.oa.ops.oa_hw_tail_read = gen8_oa_hw_tail_read;
 
-               if (IS_GEN8(dev_priv) || IS_GEN9(dev_priv)) {
+               if (IS_GEN_RANGE(dev_priv, 8, 9)) {
                        dev_priv->perf.oa.ops.is_valid_b_counter_reg =
                                gen7_is_valid_b_counter_addr;
                        dev_priv->perf.oa.ops.is_valid_mux_reg =
@@ -3431,7 +3431,7 @@ void i915_perf_init(struct drm_i915_private *dev_priv)
                        dev_priv->perf.oa.ops.enable_metric_set = gen8_enable_metric_set;
                        dev_priv->perf.oa.ops.disable_metric_set = gen8_disable_metric_set;
 
-                       if (IS_GEN8(dev_priv)) {
+                       if (IS_GEN(dev_priv, 8)) {
                                dev_priv->perf.oa.ctx_oactxctrl_offset = 0x120;
                                dev_priv->perf.oa.ctx_flexeu0_offset = 0x2ce;
 
@@ -3442,7 +3442,7 @@ void i915_perf_init(struct drm_i915_private *dev_priv)
 
                                dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<16);
                        }
-               } else if (IS_GEN(dev_priv, 10, 11)) {
+               } else if (IS_GEN_RANGE(dev_priv, 10, 11)) {
                        dev_priv->perf.oa.ops.is_valid_b_counter_reg =
                                gen7_is_valid_b_counter_addr;
                        dev_priv->perf.oa.ops.is_valid_mux_reg =
@@ -3471,7 +3471,7 @@ void i915_perf_init(struct drm_i915_private *dev_priv)
                spin_lock_init(&dev_priv->perf.oa.oa_buffer.ptr_lock);
 
                oa_sample_rate_hard_limit = 1000 *
-                       (INTEL_INFO(dev_priv)->cs_timestamp_frequency_khz / 2);
+                       (RUNTIME_INFO(dev_priv)->cs_timestamp_frequency_khz / 2);
                dev_priv->perf.sysctl_header = register_sysctl_table(dev_root);
 
                mutex_init(&dev_priv->perf.metrics_lock);
index d6c8f8fdfda5f106776e0a148e034e10e64ccbb7..b1cb2d3cae1606b31ba12e6380e9bb96090d28bb 100644 (file)
@@ -167,6 +167,7 @@ engines_sample(struct drm_i915_private *dev_priv, unsigned int period_ns)
 {
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
+       intel_wakeref_t wakeref;
        bool fw = false;
 
        if ((dev_priv->pmu.enable & ENGINE_SAMPLE_MASK) == 0)
@@ -175,7 +176,8 @@ engines_sample(struct drm_i915_private *dev_priv, unsigned int period_ns)
        if (!dev_priv->gt.awake)
                return;
 
-       if (!intel_runtime_pm_get_if_in_use(dev_priv))
+       wakeref = intel_runtime_pm_get_if_in_use(dev_priv);
+       if (!wakeref)
                return;
 
        for_each_engine(engine, dev_priv, id) {
@@ -210,7 +212,7 @@ engines_sample(struct drm_i915_private *dev_priv, unsigned int period_ns)
        if (fw)
                intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
 
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
 }
 
 static void
@@ -227,11 +229,12 @@ frequency_sample(struct drm_i915_private *dev_priv, unsigned int period_ns)
                u32 val;
 
                val = dev_priv->gt_pm.rps.cur_freq;
-               if (dev_priv->gt.awake &&
-                   intel_runtime_pm_get_if_in_use(dev_priv)) {
-                       val = intel_get_cagf(dev_priv,
-                                            I915_READ_NOTRACE(GEN6_RPSTAT1));
-                       intel_runtime_pm_put(dev_priv);
+               if (dev_priv->gt.awake) {
+                       intel_wakeref_t wakeref;
+
+                       with_intel_runtime_pm_if_in_use(dev_priv, wakeref)
+                               val = intel_get_cagf(dev_priv,
+                                                    I915_READ_NOTRACE(GEN6_RPSTAT1));
                }
 
                add_sample_mult(&dev_priv->pmu.sample[__I915_SAMPLE_FREQ_ACT],
@@ -443,12 +446,14 @@ static u64 __get_rc6(struct drm_i915_private *i915)
 static u64 get_rc6(struct drm_i915_private *i915)
 {
 #if IS_ENABLED(CONFIG_PM)
+       intel_wakeref_t wakeref;
        unsigned long flags;
        u64 val;
 
-       if (intel_runtime_pm_get_if_in_use(i915)) {
+       wakeref = intel_runtime_pm_get_if_in_use(i915);
+       if (wakeref) {
                val = __get_rc6(i915);
-               intel_runtime_pm_put(i915);
+               intel_runtime_pm_put(i915, wakeref);
 
                /*
                 * If we are coming back from being runtime suspended we must
index fe56465cdfd67512aca73d3cdf0bc3b7e7f6bf2f..cbcb957b7141d768541853129cdc029d5f804029 100644 (file)
@@ -13,7 +13,7 @@
 static int query_topology_info(struct drm_i915_private *dev_priv,
                               struct drm_i915_query_item *query_item)
 {
-       const struct sseu_dev_info *sseu = &INTEL_INFO(dev_priv)->sseu;
+       const struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu;
        struct drm_i915_query_topology_info topo;
        u32 slice_length, subslice_length, eu_length, total_length;
 
index 0a7d60509ca7527f018a12208316bff91c7c6be8..f4e447437d7544323ce016ecde2ef8825b1b9c91 100644 (file)
  */
 
 typedef struct {
-       uint32_t reg;
+       u32 reg;
 } i915_reg_t;
 
 #define _MMIO(r) ((const i915_reg_t){ .reg = (r) })
 
 #define INVALID_MMIO_REG _MMIO(0)
 
-static inline uint32_t i915_mmio_reg_offset(i915_reg_t reg)
+static inline u32 i915_mmio_reg_offset(i915_reg_t reg)
 {
        return reg.reg;
 }
@@ -139,6 +139,12 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
        return !i915_mmio_reg_equal(reg, INVALID_MMIO_REG);
 }
 
+#define VLV_DISPLAY_BASE               0x180000
+#define VLV_MIPI_BASE                  VLV_DISPLAY_BASE
+#define BXT_MIPI_BASE                  0x60000
+
+#define DISPLAY_MMIO_BASE(dev_priv)    (INTEL_INFO(dev_priv)->display_mmio_offset)
+
 /*
  * Given the first two numbers __a and __b of arbitrarily many evenly spaced
  * numbers, pick the 0-based __index'th value.
@@ -179,15 +185,15 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
  * Device info offset array based helpers for groups of registers with unevenly
  * spaced base offsets.
  */
-#define _MMIO_PIPE2(pipe, reg)         _MMIO(dev_priv->info.pipe_offsets[pipe] - \
-                                             dev_priv->info.pipe_offsets[PIPE_A] + (reg) + \
-                                             dev_priv->info.display_mmio_offset)
-#define _MMIO_TRANS2(pipe, reg)                _MMIO(dev_priv->info.trans_offsets[(pipe)] - \
-                                             dev_priv->info.trans_offsets[TRANSCODER_A] + (reg) + \
-                                             dev_priv->info.display_mmio_offset)
-#define _CURSOR2(pipe, reg)            _MMIO(dev_priv->info.cursor_offsets[(pipe)] - \
-                                             dev_priv->info.cursor_offsets[PIPE_A] + (reg) + \
-                                             dev_priv->info.display_mmio_offset)
+#define _MMIO_PIPE2(pipe, reg)         _MMIO(INTEL_INFO(dev_priv)->pipe_offsets[pipe] - \
+                                             INTEL_INFO(dev_priv)->pipe_offsets[PIPE_A] + (reg) + \
+                                             DISPLAY_MMIO_BASE(dev_priv))
+#define _MMIO_TRANS2(pipe, reg)                _MMIO(INTEL_INFO(dev_priv)->trans_offsets[(pipe)] - \
+                                             INTEL_INFO(dev_priv)->trans_offsets[TRANSCODER_A] + (reg) + \
+                                             DISPLAY_MMIO_BASE(dev_priv))
+#define _CURSOR2(pipe, reg)            _MMIO(INTEL_INFO(dev_priv)->cursor_offsets[(pipe)] - \
+                                             INTEL_INFO(dev_priv)->cursor_offsets[PIPE_A] + (reg) + \
+                                             DISPLAY_MMIO_BASE(dev_priv))
 
 #define __MASKED_FIELD(mask, value) ((mask) << 16 | (value))
 #define _MASKED_FIELD(mask, value) ({                                     \
@@ -347,6 +353,24 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
 #define  GEN11_GRDOM_MEDIA4            (1 << 8)
 #define  GEN11_GRDOM_VECS              (1 << 13)
 #define  GEN11_GRDOM_VECS2             (1 << 14)
+#define  GEN11_GRDOM_SFC0              (1 << 17)
+#define  GEN11_GRDOM_SFC1              (1 << 18)
+
+#define  GEN11_VCS_SFC_RESET_BIT(instance)     (GEN11_GRDOM_SFC0 << ((instance) >> 1))
+#define  GEN11_VECS_SFC_RESET_BIT(instance)    (GEN11_GRDOM_SFC0 << (instance))
+
+#define GEN11_VCS_SFC_FORCED_LOCK(engine)      _MMIO((engine)->mmio_base + 0x88C)
+#define   GEN11_VCS_SFC_FORCED_LOCK_BIT                (1 << 0)
+#define GEN11_VCS_SFC_LOCK_STATUS(engine)      _MMIO((engine)->mmio_base + 0x890)
+#define   GEN11_VCS_SFC_USAGE_BIT              (1 << 0)
+#define   GEN11_VCS_SFC_LOCK_ACK_BIT           (1 << 1)
+
+#define GEN11_VECS_SFC_FORCED_LOCK(engine)     _MMIO((engine)->mmio_base + 0x201C)
+#define   GEN11_VECS_SFC_FORCED_LOCK_BIT       (1 << 0)
+#define GEN11_VECS_SFC_LOCK_ACK(engine)                _MMIO((engine)->mmio_base + 0x2018)
+#define   GEN11_VECS_SFC_LOCK_ACK_BIT          (1 << 0)
+#define GEN11_VECS_SFC_USAGE(engine)           _MMIO((engine)->mmio_base + 0x2014)
+#define   GEN11_VECS_SFC_USAGE_BIT             (1 << 0)
 
 #define RING_PP_DIR_BASE(engine)       _MMIO((engine)->mmio_base + 0x228)
 #define RING_PP_DIR_BASE_READ(engine)  _MMIO((engine)->mmio_base + 0x518)
@@ -1790,7 +1814,7 @@ enum i915_power_well_id {
 #define _CNL_PORT_TX_C_LN0_OFFSET              0x162C40
 #define _CNL_PORT_TX_D_LN0_OFFSET              0x162E40
 #define _CNL_PORT_TX_F_LN0_OFFSET              0x162840
-#define _CNL_PORT_TX_DW_GRP(port, dw)  (_PICK((port), \
+#define _CNL_PORT_TX_DW_GRP(dw, port)  (_PICK((port), \
                                               _CNL_PORT_TX_AE_GRP_OFFSET, \
                                               _CNL_PORT_TX_B_GRP_OFFSET, \
                                               _CNL_PORT_TX_B_GRP_OFFSET, \
@@ -1798,7 +1822,7 @@ enum i915_power_well_id {
                                               _CNL_PORT_TX_AE_GRP_OFFSET, \
                                               _CNL_PORT_TX_F_GRP_OFFSET) + \
                                               4 * (dw))
-#define _CNL_PORT_TX_DW_LN0(port, dw)  (_PICK((port), \
+#define _CNL_PORT_TX_DW_LN0(dw, port)  (_PICK((port), \
                                               _CNL_PORT_TX_AE_LN0_OFFSET, \
                                               _CNL_PORT_TX_B_LN0_OFFSET, \
                                               _CNL_PORT_TX_B_LN0_OFFSET, \
@@ -1834,9 +1858,9 @@ enum i915_power_well_id {
 
 #define _CNL_PORT_TX_DW4_LN0_AE                0x162450
 #define _CNL_PORT_TX_DW4_LN1_AE                0x1624D0
-#define CNL_PORT_TX_DW4_GRP(port)      _MMIO(_CNL_PORT_TX_DW_GRP((port), 4))
-#define CNL_PORT_TX_DW4_LN0(port)      _MMIO(_CNL_PORT_TX_DW_LN0((port), 4))
-#define CNL_PORT_TX_DW4_LN(port, ln)   _MMIO(_CNL_PORT_TX_DW_LN0((port), 4) + \
+#define CNL_PORT_TX_DW4_GRP(port)      _MMIO(_CNL_PORT_TX_DW_GRP(4, (port)))
+#define CNL_PORT_TX_DW4_LN0(port)      _MMIO(_CNL_PORT_TX_DW_LN0(4, (port)))
+#define CNL_PORT_TX_DW4_LN(port, ln)   _MMIO(_CNL_PORT_TX_DW_LN0(4, (port)) + \
                                           ((ln) * (_CNL_PORT_TX_DW4_LN1_AE - \
                                                    _CNL_PORT_TX_DW4_LN0_AE)))
 #define ICL_PORT_TX_DW4_AUX(port)      _MMIO(_ICL_PORT_TX_DW_AUX(4, port))
@@ -1864,8 +1888,12 @@ enum i915_power_well_id {
 #define   RTERM_SELECT(x)              ((x) << 3)
 #define   RTERM_SELECT_MASK            (0x7 << 3)
 
-#define CNL_PORT_TX_DW7_GRP(port)      _MMIO(_CNL_PORT_TX_DW_GRP((port), 7))
-#define CNL_PORT_TX_DW7_LN0(port)      _MMIO(_CNL_PORT_TX_DW_LN0((port), 7))
+#define CNL_PORT_TX_DW7_GRP(port)      _MMIO(_CNL_PORT_TX_DW_GRP(7, (port)))
+#define CNL_PORT_TX_DW7_LN0(port)      _MMIO(_CNL_PORT_TX_DW_LN0(7, (port)))
+#define ICL_PORT_TX_DW7_AUX(port)      _MMIO(_ICL_PORT_TX_DW_AUX(7, port))
+#define ICL_PORT_TX_DW7_GRP(port)      _MMIO(_ICL_PORT_TX_DW_GRP(7, port))
+#define ICL_PORT_TX_DW7_LN0(port)      _MMIO(_ICL_PORT_TX_DW_LN(7, 0, port))
+#define ICL_PORT_TX_DW7_LN(port, ln)   _MMIO(_ICL_PORT_TX_DW_LN(7, ln, port))
 #define   N_SCALAR(x)                  ((x) << 24)
 #define   N_SCALAR_MASK                        (0x7F << 24)
 
@@ -2592,10 +2620,6 @@ enum i915_power_well_id {
 
 #define   GEN11_GFX_DISABLE_LEGACY_MODE        (1 << 3)
 
-#define VLV_DISPLAY_BASE 0x180000
-#define VLV_MIPI_BASE VLV_DISPLAY_BASE
-#define BXT_MIPI_BASE 0x60000
-
 #define VLV_GU_CTL0    _MMIO(VLV_DISPLAY_BASE + 0x2030)
 #define VLV_GU_CTL1    _MMIO(VLV_DISPLAY_BASE + 0x2034)
 #define SCPD0          _MMIO(0x209c) /* 915+ only */
@@ -3152,9 +3176,9 @@ enum i915_power_well_id {
 /*
  * Clock control & power management
  */
-#define _DPLL_A (dev_priv->info.display_mmio_offset + 0x6014)
-#define _DPLL_B (dev_priv->info.display_mmio_offset + 0x6018)
-#define _CHV_DPLL_C (dev_priv->info.display_mmio_offset + 0x6030)
+#define _DPLL_A (DISPLAY_MMIO_BASE(dev_priv) + 0x6014)
+#define _DPLL_B (DISPLAY_MMIO_BASE(dev_priv) + 0x6018)
+#define _CHV_DPLL_C (DISPLAY_MMIO_BASE(dev_priv) + 0x6030)
 #define DPLL(pipe) _MMIO_PIPE3((pipe), _DPLL_A, _DPLL_B, _CHV_DPLL_C)
 
 #define VGA0   _MMIO(0x6000)
@@ -3251,9 +3275,9 @@ enum i915_power_well_id {
 #define   SDVO_MULTIPLIER_SHIFT_HIRES          4
 #define   SDVO_MULTIPLIER_SHIFT_VGA            0
 
-#define _DPLL_A_MD (dev_priv->info.display_mmio_offset + 0x601c)
-#define _DPLL_B_MD (dev_priv->info.display_mmio_offset + 0x6020)
-#define _CHV_DPLL_C_MD (dev_priv->info.display_mmio_offset + 0x603c)
+#define _DPLL_A_MD (DISPLAY_MMIO_BASE(dev_priv) + 0x601c)
+#define _DPLL_B_MD (DISPLAY_MMIO_BASE(dev_priv) + 0x6020)
+#define _CHV_DPLL_C_MD (DISPLAY_MMIO_BASE(dev_priv) + 0x603c)
 #define DPLL_MD(pipe) _MMIO_PIPE3((pipe), _DPLL_A_MD, _DPLL_B_MD, _CHV_DPLL_C_MD)
 
 /*
@@ -3325,7 +3349,7 @@ enum i915_power_well_id {
 #define  DSTATE_PLL_D3_OFF                     (1 << 3)
 #define  DSTATE_GFX_CLOCK_GATING               (1 << 1)
 #define  DSTATE_DOT_CLOCK_GATING               (1 << 0)
-#define DSPCLK_GATE_D  _MMIO(dev_priv->info.display_mmio_offset + 0x6200)
+#define DSPCLK_GATE_D  _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x6200)
 # define DPUNIT_B_CLOCK_GATE_DISABLE           (1 << 30) /* 965 */
 # define VSUNIT_CLOCK_GATE_DISABLE             (1 << 29) /* 965 */
 # define VRHUNIT_CLOCK_GATE_DISABLE            (1 << 28) /* 965 */
@@ -3465,7 +3489,7 @@ enum i915_power_well_id {
 #define _PALETTE_A             0xa000
 #define _PALETTE_B             0xa800
 #define _CHV_PALETTE_C         0xc000
-#define PALETTE(pipe, i)       _MMIO(dev_priv->info.display_mmio_offset + \
+#define PALETTE(pipe, i)       _MMIO(DISPLAY_MMIO_BASE(dev_priv) + \
                                      _PICK((pipe), _PALETTE_A,         \
                                            _PALETTE_B, _CHV_PALETTE_C) + \
                                      (i) * 4)
@@ -4248,6 +4272,15 @@ enum {
 #define EDP_PSR2_STATUS_STATE_MASK     (0xf << 28)
 #define EDP_PSR2_STATUS_STATE_SHIFT    28
 
+#define _PSR2_SU_STATUS_0              0x6F914
+#define _PSR2_SU_STATUS_1              0x6F918
+#define _PSR2_SU_STATUS_2              0x6F91C
+#define _PSR2_SU_STATUS(index)         _MMIO(_PICK_EVEN((index), _PSR2_SU_STATUS_0, _PSR2_SU_STATUS_1))
+#define PSR2_SU_STATUS(frame)          (_PSR2_SU_STATUS((frame) / 3))
+#define PSR2_SU_STATUS_SHIFT(frame)    (((frame) % 3) * 10)
+#define PSR2_SU_STATUS_MASK(frame)     (0x3ff << PSR2_SU_STATUS_SHIFT(frame))
+#define PSR2_SU_STATUS_FRAMES          8
+
 /* VGA port control */
 #define ADPA                   _MMIO(0x61100)
 #define PCH_ADPA                _MMIO(0xe1100)
@@ -4298,7 +4331,7 @@ enum {
 
 
 /* Hotplug control (945+ only) */
-#define PORT_HOTPLUG_EN                _MMIO(dev_priv->info.display_mmio_offset + 0x61110)
+#define PORT_HOTPLUG_EN                _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61110)
 #define   PORTB_HOTPLUG_INT_EN                 (1 << 29)
 #define   PORTC_HOTPLUG_INT_EN                 (1 << 28)
 #define   PORTD_HOTPLUG_INT_EN                 (1 << 27)
@@ -4328,7 +4361,7 @@ enum {
 #define CRT_HOTPLUG_DETECT_VOLTAGE_325MV       (0 << 2)
 #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV       (1 << 2)
 
-#define PORT_HOTPLUG_STAT      _MMIO(dev_priv->info.display_mmio_offset + 0x61114)
+#define PORT_HOTPLUG_STAT      _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61114)
 /*
  * HDMI/DP bits are g4x+
  *
@@ -4410,7 +4443,7 @@ enum {
 
 #define PORT_DFT_I9XX                          _MMIO(0x61150)
 #define   DC_BALANCE_RESET                     (1 << 25)
-#define PORT_DFT2_G4X          _MMIO(dev_priv->info.display_mmio_offset + 0x61154)
+#define PORT_DFT2_G4X          _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61154)
 #define   DC_BALANCE_RESET_VLV                 (1 << 31)
 #define   PIPE_SCRAMBLE_RESET_MASK             ((1 << 14) | (0x3 << 0))
 #define   PIPE_C_SCRAMBLE_RESET                        (1 << 14) /* chv */
@@ -4663,7 +4696,6 @@ enum {
 #define  EDP_FORCE_VDD                 (1 << 3)
 #define  EDP_BLC_ENABLE                        (1 << 2)
 #define  PANEL_POWER_RESET             (1 << 1)
-#define  PANEL_POWER_OFF               (0 << 0)
 #define  PANEL_POWER_ON                        (1 << 0)
 
 #define _PP_ON_DELAYS                  0x61208
@@ -4695,7 +4727,7 @@ enum {
 #define  PANEL_POWER_CYCLE_DELAY_SHIFT 0
 
 /* Panel fitting */
-#define PFIT_CONTROL   _MMIO(dev_priv->info.display_mmio_offset + 0x61230)
+#define PFIT_CONTROL   _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61230)
 #define   PFIT_ENABLE          (1 << 31)
 #define   PFIT_PIPE_MASK       (3 << 29)
 #define   PFIT_PIPE_SHIFT      29
@@ -4713,7 +4745,7 @@ enum {
 #define   PFIT_SCALING_PROGRAMMED (1 << 26)
 #define   PFIT_SCALING_PILLAR  (2 << 26)
 #define   PFIT_SCALING_LETTER  (3 << 26)
-#define PFIT_PGM_RATIOS _MMIO(dev_priv->info.display_mmio_offset + 0x61234)
+#define PFIT_PGM_RATIOS _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61234)
 /* Pre-965 */
 #define                PFIT_VERT_SCALE_SHIFT           20
 #define                PFIT_VERT_SCALE_MASK            0xfff00000
@@ -4725,25 +4757,25 @@ enum {
 #define                PFIT_HORIZ_SCALE_SHIFT_965      0
 #define                PFIT_HORIZ_SCALE_MASK_965       0x00001fff
 
-#define PFIT_AUTO_RATIOS _MMIO(dev_priv->info.display_mmio_offset + 0x61238)
+#define PFIT_AUTO_RATIOS _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61238)
 
-#define _VLV_BLC_PWM_CTL2_A (dev_priv->info.display_mmio_offset + 0x61250)
-#define _VLV_BLC_PWM_CTL2_B (dev_priv->info.display_mmio_offset + 0x61350)
+#define _VLV_BLC_PWM_CTL2_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61250)
+#define _VLV_BLC_PWM_CTL2_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61350)
 #define VLV_BLC_PWM_CTL2(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL2_A, \
                                         _VLV_BLC_PWM_CTL2_B)
 
-#define _VLV_BLC_PWM_CTL_A (dev_priv->info.display_mmio_offset + 0x61254)
-#define _VLV_BLC_PWM_CTL_B (dev_priv->info.display_mmio_offset + 0x61354)
+#define _VLV_BLC_PWM_CTL_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61254)
+#define _VLV_BLC_PWM_CTL_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61354)
 #define VLV_BLC_PWM_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL_A, \
                                        _VLV_BLC_PWM_CTL_B)
 
-#define _VLV_BLC_HIST_CTL_A (dev_priv->info.display_mmio_offset + 0x61260)
-#define _VLV_BLC_HIST_CTL_B (dev_priv->info.display_mmio_offset + 0x61360)
+#define _VLV_BLC_HIST_CTL_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61260)
+#define _VLV_BLC_HIST_CTL_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61360)
 #define VLV_BLC_HIST_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_HIST_CTL_A, \
                                         _VLV_BLC_HIST_CTL_B)
 
 /* Backlight control */
-#define BLC_PWM_CTL2   _MMIO(dev_priv->info.display_mmio_offset + 0x61250) /* 965+ only */
+#define BLC_PWM_CTL2   _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61250) /* 965+ only */
 #define   BLM_PWM_ENABLE               (1 << 31)
 #define   BLM_COMBINATION_MODE         (1 << 30) /* gen4 only */
 #define   BLM_PIPE_SELECT              (1 << 29)
@@ -4766,7 +4798,7 @@ enum {
 #define   BLM_PHASE_IN_COUNT_MASK      (0xff << 8)
 #define   BLM_PHASE_IN_INCR_SHIFT      (0)
 #define   BLM_PHASE_IN_INCR_MASK       (0xff << 0)
-#define BLC_PWM_CTL    _MMIO(dev_priv->info.display_mmio_offset + 0x61254)
+#define BLC_PWM_CTL    _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61254)
 /*
  * This is the most significant 15 bits of the number of backlight cycles in a
  * complete cycle of the modulated backlight control.
@@ -4788,7 +4820,7 @@ enum {
 #define   BACKLIGHT_DUTY_CYCLE_MASK_PNV                (0xfffe)
 #define   BLM_POLARITY_PNV                     (1 << 0) /* pnv only */
 
-#define BLC_HIST_CTL   _MMIO(dev_priv->info.display_mmio_offset + 0x61260)
+#define BLC_HIST_CTL   _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61260)
 #define  BLM_HISTOGRAM_ENABLE                  (1 << 31)
 
 /* New registers for PCH-split platforms. Safe where new bits show up, the
@@ -5412,47 +5444,47 @@ enum {
  * is 20 bytes in each direction, hence the 5 fixed
  * data registers
  */
-#define _DPA_AUX_CH_CTL                (dev_priv->info.display_mmio_offset + 0x64010)
-#define _DPA_AUX_CH_DATA1      (dev_priv->info.display_mmio_offset + 0x64014)
-#define _DPA_AUX_CH_DATA2      (dev_priv->info.display_mmio_offset + 0x64018)
-#define _DPA_AUX_CH_DATA3      (dev_priv->info.display_mmio_offset + 0x6401c)
-#define _DPA_AUX_CH_DATA4      (dev_priv->info.display_mmio_offset + 0x64020)
-#define _DPA_AUX_CH_DATA5      (dev_priv->info.display_mmio_offset + 0x64024)
-
-#define _DPB_AUX_CH_CTL                (dev_priv->info.display_mmio_offset + 0x64110)
-#define _DPB_AUX_CH_DATA1      (dev_priv->info.display_mmio_offset + 0x64114)
-#define _DPB_AUX_CH_DATA2      (dev_priv->info.display_mmio_offset + 0x64118)
-#define _DPB_AUX_CH_DATA3      (dev_priv->info.display_mmio_offset + 0x6411c)
-#define _DPB_AUX_CH_DATA4      (dev_priv->info.display_mmio_offset + 0x64120)
-#define _DPB_AUX_CH_DATA5      (dev_priv->info.display_mmio_offset + 0x64124)
-
-#define _DPC_AUX_CH_CTL                (dev_priv->info.display_mmio_offset + 0x64210)
-#define _DPC_AUX_CH_DATA1      (dev_priv->info.display_mmio_offset + 0x64214)
-#define _DPC_AUX_CH_DATA2      (dev_priv->info.display_mmio_offset + 0x64218)
-#define _DPC_AUX_CH_DATA3      (dev_priv->info.display_mmio_offset + 0x6421c)
-#define _DPC_AUX_CH_DATA4      (dev_priv->info.display_mmio_offset + 0x64220)
-#define _DPC_AUX_CH_DATA5      (dev_priv->info.display_mmio_offset + 0x64224)
-
-#define _DPD_AUX_CH_CTL                (dev_priv->info.display_mmio_offset + 0x64310)
-#define _DPD_AUX_CH_DATA1      (dev_priv->info.display_mmio_offset + 0x64314)
-#define _DPD_AUX_CH_DATA2      (dev_priv->info.display_mmio_offset + 0x64318)
-#define _DPD_AUX_CH_DATA3      (dev_priv->info.display_mmio_offset + 0x6431c)
-#define _DPD_AUX_CH_DATA4      (dev_priv->info.display_mmio_offset + 0x64320)
-#define _DPD_AUX_CH_DATA5      (dev_priv->info.display_mmio_offset + 0x64324)
-
-#define _DPE_AUX_CH_CTL                (dev_priv->info.display_mmio_offset + 0x64410)
-#define _DPE_AUX_CH_DATA1      (dev_priv->info.display_mmio_offset + 0x64414)
-#define _DPE_AUX_CH_DATA2      (dev_priv->info.display_mmio_offset + 0x64418)
-#define _DPE_AUX_CH_DATA3      (dev_priv->info.display_mmio_offset + 0x6441c)
-#define _DPE_AUX_CH_DATA4      (dev_priv->info.display_mmio_offset + 0x64420)
-#define _DPE_AUX_CH_DATA5      (dev_priv->info.display_mmio_offset + 0x64424)
-
-#define _DPF_AUX_CH_CTL                (dev_priv->info.display_mmio_offset + 0x64510)
-#define _DPF_AUX_CH_DATA1      (dev_priv->info.display_mmio_offset + 0x64514)
-#define _DPF_AUX_CH_DATA2      (dev_priv->info.display_mmio_offset + 0x64518)
-#define _DPF_AUX_CH_DATA3      (dev_priv->info.display_mmio_offset + 0x6451c)
-#define _DPF_AUX_CH_DATA4      (dev_priv->info.display_mmio_offset + 0x64520)
-#define _DPF_AUX_CH_DATA5      (dev_priv->info.display_mmio_offset + 0x64524)
+#define _DPA_AUX_CH_CTL                (DISPLAY_MMIO_BASE(dev_priv) + 0x64010)
+#define _DPA_AUX_CH_DATA1      (DISPLAY_MMIO_BASE(dev_priv) + 0x64014)
+#define _DPA_AUX_CH_DATA2      (DISPLAY_MMIO_BASE(dev_priv) + 0x64018)
+#define _DPA_AUX_CH_DATA3      (DISPLAY_MMIO_BASE(dev_priv) + 0x6401c)
+#define _DPA_AUX_CH_DATA4      (DISPLAY_MMIO_BASE(dev_priv) + 0x64020)
+#define _DPA_AUX_CH_DATA5      (DISPLAY_MMIO_BASE(dev_priv) + 0x64024)
+
+#define _DPB_AUX_CH_CTL                (DISPLAY_MMIO_BASE(dev_priv) + 0x64110)
+#define _DPB_AUX_CH_DATA1      (DISPLAY_MMIO_BASE(dev_priv) + 0x64114)
+#define _DPB_AUX_CH_DATA2      (DISPLAY_MMIO_BASE(dev_priv) + 0x64118)
+#define _DPB_AUX_CH_DATA3      (DISPLAY_MMIO_BASE(dev_priv) + 0x6411c)
+#define _DPB_AUX_CH_DATA4      (DISPLAY_MMIO_BASE(dev_priv) + 0x64120)
+#define _DPB_AUX_CH_DATA5      (DISPLAY_MMIO_BASE(dev_priv) + 0x64124)
+
+#define _DPC_AUX_CH_CTL                (DISPLAY_MMIO_BASE(dev_priv) + 0x64210)
+#define _DPC_AUX_CH_DATA1      (DISPLAY_MMIO_BASE(dev_priv) + 0x64214)
+#define _DPC_AUX_CH_DATA2      (DISPLAY_MMIO_BASE(dev_priv) + 0x64218)
+#define _DPC_AUX_CH_DATA3      (DISPLAY_MMIO_BASE(dev_priv) + 0x6421c)
+#define _DPC_AUX_CH_DATA4      (DISPLAY_MMIO_BASE(dev_priv) + 0x64220)
+#define _DPC_AUX_CH_DATA5      (DISPLAY_MMIO_BASE(dev_priv) + 0x64224)
+
+#define _DPD_AUX_CH_CTL                (DISPLAY_MMIO_BASE(dev_priv) + 0x64310)
+#define _DPD_AUX_CH_DATA1      (DISPLAY_MMIO_BASE(dev_priv) + 0x64314)
+#define _DPD_AUX_CH_DATA2      (DISPLAY_MMIO_BASE(dev_priv) + 0x64318)
+#define _DPD_AUX_CH_DATA3      (DISPLAY_MMIO_BASE(dev_priv) + 0x6431c)
+#define _DPD_AUX_CH_DATA4      (DISPLAY_MMIO_BASE(dev_priv) + 0x64320)
+#define _DPD_AUX_CH_DATA5      (DISPLAY_MMIO_BASE(dev_priv) + 0x64324)
+
+#define _DPE_AUX_CH_CTL                (DISPLAY_MMIO_BASE(dev_priv) + 0x64410)
+#define _DPE_AUX_CH_DATA1      (DISPLAY_MMIO_BASE(dev_priv) + 0x64414)
+#define _DPE_AUX_CH_DATA2      (DISPLAY_MMIO_BASE(dev_priv) + 0x64418)
+#define _DPE_AUX_CH_DATA3      (DISPLAY_MMIO_BASE(dev_priv) + 0x6441c)
+#define _DPE_AUX_CH_DATA4      (DISPLAY_MMIO_BASE(dev_priv) + 0x64420)
+#define _DPE_AUX_CH_DATA5      (DISPLAY_MMIO_BASE(dev_priv) + 0x64424)
+
+#define _DPF_AUX_CH_CTL                (DISPLAY_MMIO_BASE(dev_priv) + 0x64510)
+#define _DPF_AUX_CH_DATA1      (DISPLAY_MMIO_BASE(dev_priv) + 0x64514)
+#define _DPF_AUX_CH_DATA2      (DISPLAY_MMIO_BASE(dev_priv) + 0x64518)
+#define _DPF_AUX_CH_DATA3      (DISPLAY_MMIO_BASE(dev_priv) + 0x6451c)
+#define _DPF_AUX_CH_DATA4      (DISPLAY_MMIO_BASE(dev_priv) + 0x64520)
+#define _DPF_AUX_CH_DATA5      (DISPLAY_MMIO_BASE(dev_priv) + 0x64524)
 
 #define DP_AUX_CH_CTL(aux_ch)  _MMIO_PORT(aux_ch, _DPA_AUX_CH_CTL, _DPB_AUX_CH_CTL)
 #define DP_AUX_CH_DATA(aux_ch, i)      _MMIO(_PORT(aux_ch, _DPA_AUX_CH_DATA1, _DPB_AUX_CH_DATA1) + (i) * 4) /* 5 registers */
@@ -5728,7 +5760,7 @@ enum {
 #define   DPINVGTT_STATUS_MASK                 0xff
 #define   DPINVGTT_STATUS_MASK_CHV             0xfff
 
-#define DSPARB                 _MMIO(dev_priv->info.display_mmio_offset + 0x70030)
+#define DSPARB                 _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x70030)
 #define   DSPARB_CSTART_MASK   (0x7f << 7)
 #define   DSPARB_CSTART_SHIFT  7
 #define   DSPARB_BSTART_MASK   (0x7f)
@@ -5763,7 +5795,7 @@ enum {
 #define   DSPARB_SPRITEF_MASK_VLV      (0xff << 8)
 
 /* pnv/gen4/g4x/vlv/chv */
-#define DSPFW1         _MMIO(dev_priv->info.display_mmio_offset + 0x70034)
+#define DSPFW1         _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x70034)
 #define   DSPFW_SR_SHIFT               23
 #define   DSPFW_SR_MASK                        (0x1ff << 23)
 #define   DSPFW_CURSORB_SHIFT          16
@@ -5774,7 +5806,7 @@ enum {
 #define   DSPFW_PLANEA_SHIFT           0
 #define   DSPFW_PLANEA_MASK            (0x7f << 0)
 #define   DSPFW_PLANEA_MASK_VLV                (0xff << 0) /* vlv/chv */
-#define DSPFW2         _MMIO(dev_priv->info.display_mmio_offset + 0x70038)
+#define DSPFW2         _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x70038)
 #define   DSPFW_FBC_SR_EN              (1 << 31)         /* g4x */
 #define   DSPFW_FBC_SR_SHIFT           28
 #define   DSPFW_FBC_SR_MASK            (0x7 << 28) /* g4x */
@@ -5790,7 +5822,7 @@ enum {
 #define   DSPFW_SPRITEA_SHIFT          0
 #define   DSPFW_SPRITEA_MASK           (0x7f << 0) /* g4x */
 #define   DSPFW_SPRITEA_MASK_VLV       (0xff << 0) /* vlv/chv */
-#define DSPFW3         _MMIO(dev_priv->info.display_mmio_offset + 0x7003c)
+#define DSPFW3         _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x7003c)
 #define   DSPFW_HPLL_SR_EN             (1 << 31)
 #define   PINEVIEW_SELF_REFRESH_EN     (1 << 30)
 #define   DSPFW_CURSOR_SR_SHIFT                24
@@ -6206,35 +6238,35 @@ enum {
  * [10:1f] all
  * [30:32] all
  */
-#define SWF0(i)        _MMIO(dev_priv->info.display_mmio_offset + 0x70410 + (i) * 4)
-#define SWF1(i)        _MMIO(dev_priv->info.display_mmio_offset + 0x71410 + (i) * 4)
-#define SWF3(i)        _MMIO(dev_priv->info.display_mmio_offset + 0x72414 + (i) * 4)
+#define SWF0(i)        _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x70410 + (i) * 4)
+#define SWF1(i)        _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x71410 + (i) * 4)
+#define SWF3(i)        _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x72414 + (i) * 4)
 #define SWF_ILK(i)     _MMIO(0x4F000 + (i) * 4)
 
 /* Pipe B */
-#define _PIPEBDSL              (dev_priv->info.display_mmio_offset + 0x71000)
-#define _PIPEBCONF             (dev_priv->info.display_mmio_offset + 0x71008)
-#define _PIPEBSTAT             (dev_priv->info.display_mmio_offset + 0x71024)
+#define _PIPEBDSL              (DISPLAY_MMIO_BASE(dev_priv) + 0x71000)
+#define _PIPEBCONF             (DISPLAY_MMIO_BASE(dev_priv) + 0x71008)
+#define _PIPEBSTAT             (DISPLAY_MMIO_BASE(dev_priv) + 0x71024)
 #define _PIPEBFRAMEHIGH                0x71040
 #define _PIPEBFRAMEPIXEL       0x71044
-#define _PIPEB_FRMCOUNT_G4X    (dev_priv->info.display_mmio_offset + 0x71040)
-#define _PIPEB_FLIPCOUNT_G4X   (dev_priv->info.display_mmio_offset + 0x71044)
+#define _PIPEB_FRMCOUNT_G4X    (DISPLAY_MMIO_BASE(dev_priv) + 0x71040)
+#define _PIPEB_FLIPCOUNT_G4X   (DISPLAY_MMIO_BASE(dev_priv) + 0x71044)
 
 
 /* Display B control */
-#define _DSPBCNTR              (dev_priv->info.display_mmio_offset + 0x71180)
+#define _DSPBCNTR              (DISPLAY_MMIO_BASE(dev_priv) + 0x71180)
 #define   DISPPLANE_ALPHA_TRANS_ENABLE         (1 << 15)
 #define   DISPPLANE_ALPHA_TRANS_DISABLE                0
 #define   DISPPLANE_SPRITE_ABOVE_DISPLAY       0
 #define   DISPPLANE_SPRITE_ABOVE_OVERLAY       (1)
-#define _DSPBADDR              (dev_priv->info.display_mmio_offset + 0x71184)
-#define _DSPBSTRIDE            (dev_priv->info.display_mmio_offset + 0x71188)
-#define _DSPBPOS               (dev_priv->info.display_mmio_offset + 0x7118C)
-#define _DSPBSIZE              (dev_priv->info.display_mmio_offset + 0x71190)
-#define _DSPBSURF              (dev_priv->info.display_mmio_offset + 0x7119C)
-#define _DSPBTILEOFF           (dev_priv->info.display_mmio_offset + 0x711A4)
-#define _DSPBOFFSET            (dev_priv->info.display_mmio_offset + 0x711A4)
-#define _DSPBSURFLIVE          (dev_priv->info.display_mmio_offset + 0x711AC)
+#define _DSPBADDR              (DISPLAY_MMIO_BASE(dev_priv) + 0x71184)
+#define _DSPBSTRIDE            (DISPLAY_MMIO_BASE(dev_priv) + 0x71188)
+#define _DSPBPOS               (DISPLAY_MMIO_BASE(dev_priv) + 0x7118C)
+#define _DSPBSIZE              (DISPLAY_MMIO_BASE(dev_priv) + 0x71190)
+#define _DSPBSURF              (DISPLAY_MMIO_BASE(dev_priv) + 0x7119C)
+#define _DSPBTILEOFF           (DISPLAY_MMIO_BASE(dev_priv) + 0x711A4)
+#define _DSPBOFFSET            (DISPLAY_MMIO_BASE(dev_priv) + 0x711A4)
+#define _DSPBSURFLIVE          (DISPLAY_MMIO_BASE(dev_priv) + 0x711AC)
 
 /* ICL DSI 0 and 1 */
 #define _PIPEDSI0CONF          0x7b008
@@ -8786,7 +8818,7 @@ enum {
 #define   GEN9_ENABLE_GPGPU_PREEMPTION (1 << 2)
 
 /* Audio */
-#define G4X_AUD_VID_DID                        _MMIO(dev_priv->info.display_mmio_offset + 0x62020)
+#define G4X_AUD_VID_DID                        _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x62020)
 #define   INTEL_AUDIO_DEVCL            0x808629FB
 #define   INTEL_AUDIO_DEVBLC           0x80862801
 #define   INTEL_AUDIO_DEVCTG           0x80862802
index ca95ab2f4cfa3bf2c4fed83a7dd67b5f6d1b34f5..f941e40fd37310387ec10ceaa3d9148e2184e789 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/sched/signal.h>
 
 #include "i915_drv.h"
+#include "i915_reset.h"
 
 static const char *i915_fence_get_driver_name(struct dma_fence *fence)
 {
@@ -111,99 +112,10 @@ i915_request_remove_from_client(struct i915_request *request)
        spin_unlock(&file_priv->mm.lock);
 }
 
-static int reset_all_global_seqno(struct drm_i915_private *i915, u32 seqno)
+static void reserve_gt(struct drm_i915_private *i915)
 {
-       struct intel_engine_cs *engine;
-       struct i915_timeline *timeline;
-       enum intel_engine_id id;
-       int ret;
-
-       /* Carefully retire all requests without writing to the rings */
-       ret = i915_gem_wait_for_idle(i915,
-                                    I915_WAIT_INTERRUPTIBLE |
-                                    I915_WAIT_LOCKED,
-                                    MAX_SCHEDULE_TIMEOUT);
-       if (ret)
-               return ret;
-
-       GEM_BUG_ON(i915->gt.active_requests);
-
-       /* If the seqno wraps around, we need to clear the breadcrumb rbtree */
-       for_each_engine(engine, i915, id) {
-               GEM_TRACE("%s seqno %d (current %d) -> %d\n",
-                         engine->name,
-                         engine->timeline.seqno,
-                         intel_engine_get_seqno(engine),
-                         seqno);
-
-               if (seqno == engine->timeline.seqno)
-                       continue;
-
-               kthread_park(engine->breadcrumbs.signaler);
-
-               if (!i915_seqno_passed(seqno, engine->timeline.seqno)) {
-                       /* Flush any waiters before we reuse the seqno */
-                       intel_engine_disarm_breadcrumbs(engine);
-                       intel_engine_init_hangcheck(engine);
-                       GEM_BUG_ON(!list_empty(&engine->breadcrumbs.signals));
-               }
-
-               /* Check we are idle before we fiddle with hw state! */
-               GEM_BUG_ON(!intel_engine_is_idle(engine));
-               GEM_BUG_ON(i915_gem_active_isset(&engine->timeline.last_request));
-
-               /* Finally reset hw state */
-               intel_engine_init_global_seqno(engine, seqno);
-               engine->timeline.seqno = seqno;
-
-               kthread_unpark(engine->breadcrumbs.signaler);
-       }
-
-       list_for_each_entry(timeline, &i915->gt.timelines, link)
-               memset(timeline->global_sync, 0, sizeof(timeline->global_sync));
-
-       i915->gt.request_serial = seqno;
-
-       return 0;
-}
-
-int i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno)
-{
-       struct drm_i915_private *i915 = to_i915(dev);
-
-       lockdep_assert_held(&i915->drm.struct_mutex);
-
-       if (seqno == 0)
-               return -EINVAL;
-
-       /* HWS page needs to be set less than what we will inject to ring */
-       return reset_all_global_seqno(i915, seqno - 1);
-}
-
-static int reserve_gt(struct drm_i915_private *i915)
-{
-       int ret;
-
-       /*
-        * Reservation is fine until we may need to wrap around
-        *
-        * By incrementing the serial for every request, we know that no
-        * individual engine may exceed that serial (as each is reset to 0
-        * on any wrap). This protects even the most pessimistic of migrations
-        * of every request from all engines onto just one.
-        */
-       while (unlikely(++i915->gt.request_serial == 0)) {
-               ret = reset_all_global_seqno(i915, 0);
-               if (ret) {
-                       i915->gt.request_serial--;
-                       return ret;
-               }
-       }
-
        if (!i915->gt.active_requests++)
                i915_gem_unpark(i915);
-
-       return 0;
 }
 
 static void unreserve_gt(struct drm_i915_private *i915)
@@ -270,7 +182,7 @@ static void free_capture_list(struct i915_request *request)
 static void __retire_engine_request(struct intel_engine_cs *engine,
                                    struct i915_request *rq)
 {
-       GEM_TRACE("%s(%s) fence %llx:%d, global=%d, current %d\n",
+       GEM_TRACE("%s(%s) fence %llx:%lld, global=%d, current %d\n",
                  __func__, engine->name,
                  rq->fence.context, rq->fence.seqno,
                  rq->global_seqno,
@@ -286,7 +198,7 @@ static void __retire_engine_request(struct intel_engine_cs *engine,
        spin_unlock(&engine->timeline.lock);
 
        spin_lock(&rq->lock);
-       if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags))
+       if (!i915_request_signaled(rq))
                dma_fence_signal_locked(&rq->fence);
        if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &rq->fence.flags))
                intel_engine_cancel_signaling(rq);
@@ -332,7 +244,7 @@ static void i915_request_retire(struct i915_request *request)
 {
        struct i915_gem_active *active, *next;
 
-       GEM_TRACE("%s fence %llx:%d, global=%d, current %d\n",
+       GEM_TRACE("%s fence %llx:%lld, global=%d, current %d\n",
                  request->engine->name,
                  request->fence.context, request->fence.seqno,
                  request->global_seqno,
@@ -395,7 +307,7 @@ void i915_request_retire_upto(struct i915_request *rq)
        struct intel_ring *ring = rq->ring;
        struct i915_request *tmp;
 
-       GEM_TRACE("%s fence %llx:%d, global=%d, current %d\n",
+       GEM_TRACE("%s fence %llx:%lld, global=%d, current %d\n",
                  rq->engine->name,
                  rq->fence.context, rq->fence.seqno,
                  rq->global_seqno,
@@ -431,12 +343,19 @@ static void move_to_timeline(struct i915_request *request,
        spin_unlock(&request->timeline->lock);
 }
 
+static u32 next_global_seqno(struct i915_timeline *tl)
+{
+       if (!++tl->seqno)
+               ++tl->seqno;
+       return tl->seqno;
+}
+
 void __i915_request_submit(struct i915_request *request)
 {
        struct intel_engine_cs *engine = request->engine;
        u32 seqno;
 
-       GEM_TRACE("%s fence %llx:%d -> global=%d, current %d\n",
+       GEM_TRACE("%s fence %llx:%lld -> global=%d, current %d\n",
                  engine->name,
                  request->fence.context, request->fence.seqno,
                  engine->timeline.seqno + 1,
@@ -447,7 +366,7 @@ void __i915_request_submit(struct i915_request *request)
 
        GEM_BUG_ON(request->global_seqno);
 
-       seqno = timeline_get_seqno(&engine->timeline);
+       seqno = next_global_seqno(&engine->timeline);
        GEM_BUG_ON(!seqno);
        GEM_BUG_ON(intel_engine_signaled(engine, seqno));
 
@@ -486,7 +405,7 @@ void __i915_request_unsubmit(struct i915_request *request)
 {
        struct intel_engine_cs *engine = request->engine;
 
-       GEM_TRACE("%s fence %llx:%d <- global=%d, current %d\n",
+       GEM_TRACE("%s fence %llx:%lld <- global=%d, current %d\n",
                  engine->name,
                  request->fence.context, request->fence.seqno,
                  request->global_seqno,
@@ -566,6 +485,38 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
        return NOTIFY_DONE;
 }
 
+static void ring_retire_requests(struct intel_ring *ring)
+{
+       struct i915_request *rq, *rn;
+
+       list_for_each_entry_safe(rq, rn, &ring->request_list, ring_link) {
+               if (!i915_request_completed(rq))
+                       break;
+
+               i915_request_retire(rq);
+       }
+}
+
+static noinline struct i915_request *
+i915_request_alloc_slow(struct intel_context *ce)
+{
+       struct intel_ring *ring = ce->ring;
+       struct i915_request *rq;
+
+       if (list_empty(&ring->request_list))
+               goto out;
+
+       /* Ratelimit ourselves to prevent oom from malicious clients */
+       rq = list_last_entry(&ring->request_list, typeof(*rq), ring_link);
+       cond_synchronize_rcu(rq->rcustate);
+
+       /* Retire our old requests in the hope that we free some */
+       ring_retire_requests(ring);
+
+out:
+       return kmem_cache_alloc(ce->gem_context->i915->requests, GFP_KERNEL);
+}
+
 /**
  * i915_request_alloc - allocate a request structure
  *
@@ -608,13 +559,7 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx)
        if (IS_ERR(ce))
                return ERR_CAST(ce);
 
-       ret = reserve_gt(i915);
-       if (ret)
-               goto err_unpin;
-
-       ret = intel_ring_wait_for_space(ce->ring, MIN_SPACE_FOR_ADD_REQUEST);
-       if (ret)
-               goto err_unreserve;
+       reserve_gt(i915);
 
        /* Move our oldest request to the slab-cache (if not in use!) */
        rq = list_first_entry(&ce->ring->request_list, typeof(*rq), ring_link);
@@ -654,15 +599,7 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx)
        rq = kmem_cache_alloc(i915->requests,
                              GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
        if (unlikely(!rq)) {
-               i915_retire_requests(i915);
-
-               /* Ratelimit ourselves to prevent oom from malicious clients */
-               rq = i915_gem_active_raw(&ce->ring->timeline->last_request,
-                                        &i915->drm.struct_mutex);
-               if (rq)
-                       cond_synchronize_rcu(rq->rcustate);
-
-               rq = kmem_cache_alloc(i915->requests, GFP_KERNEL);
+               rq = i915_request_alloc_slow(ce);
                if (!rq) {
                        ret = -ENOMEM;
                        goto err_unreserve;
@@ -707,9 +644,13 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx)
         * i915_request_add() call can't fail. Note that the reserve may need
         * to be redone if the request is not actually submitted straight
         * away, e.g. because a GPU scheduler has deferred it.
+        *
+        * Note that due to how we add reserved_space to intel_ring_begin()
+        * we need to double our request to ensure that if we need to wrap
+        * around inside i915_request_add() there is sufficient space at
+        * the beginning of the ring as well.
         */
-       rq->reserved_space = MIN_SPACE_FOR_ADD_REQUEST;
-       GEM_BUG_ON(rq->reserved_space < engine->emit_breadcrumb_sz);
+       rq->reserved_space = 2 * engine->emit_breadcrumb_sz * sizeof(u32);
 
        /*
         * Record the position of the start of the request so that
@@ -719,11 +660,6 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx)
         */
        rq->head = rq->ring->emit;
 
-       /* Unconditionally invalidate GPU caches and TLBs. */
-       ret = engine->emit_flush(rq, EMIT_INVALIDATE);
-       if (ret)
-               goto err_unwind;
-
        ret = engine->request_alloc(rq);
        if (ret)
                goto err_unwind;
@@ -748,7 +684,6 @@ err_unwind:
        kmem_cache_free(i915->requests, rq);
 err_unreserve:
        unreserve_gt(i915);
-err_unpin:
        intel_context_unpin(ce);
        return ERR_PTR(ret);
 }
@@ -776,34 +711,12 @@ i915_request_await_request(struct i915_request *to, struct i915_request *from)
                ret = i915_sw_fence_await_sw_fence_gfp(&to->submit,
                                                       &from->submit,
                                                       I915_FENCE_GFP);
-               return ret < 0 ? ret : 0;
-       }
-
-       if (to->engine->semaphore.sync_to) {
-               u32 seqno;
-
-               GEM_BUG_ON(!from->engine->semaphore.signal);
-
-               seqno = i915_request_global_seqno(from);
-               if (!seqno)
-                       goto await_dma_fence;
-
-               if (seqno <= to->timeline->global_sync[from->engine->id])
-                       return 0;
-
-               trace_i915_gem_ring_sync_to(to, from);
-               ret = to->engine->semaphore.sync_to(to, from);
-               if (ret)
-                       return ret;
-
-               to->timeline->global_sync[from->engine->id] = seqno;
-               return 0;
+       } else {
+               ret = i915_sw_fence_await_dma_fence(&to->submit,
+                                                   &from->fence, 0,
+                                                   I915_FENCE_GFP);
        }
 
-await_dma_fence:
-       ret = i915_sw_fence_await_dma_fence(&to->submit,
-                                           &from->fence, 0,
-                                           I915_FENCE_GFP);
        return ret < 0 ? ret : 0;
 }
 
@@ -961,7 +874,7 @@ void i915_request_add(struct i915_request *request)
        struct i915_request *prev;
        u32 *cs;
 
-       GEM_TRACE("%s fence %llx:%d\n",
+       GEM_TRACE("%s fence %llx:%lld\n",
                  engine->name, request->fence.context, request->fence.seqno);
 
        lockdep_assert_held(&request->i915->drm.struct_mutex);
@@ -979,8 +892,8 @@ void i915_request_add(struct i915_request *request)
         * should already have been reserved in the ring buffer. Let the ring
         * know that it is time to use that space up.
         */
+       GEM_BUG_ON(request->reserved_space > request->ring->space);
        request->reserved_space = 0;
-       engine->emit_flush(request, EMIT_FLUSH);
 
        /*
         * Record the position of the start of the breadcrumb so that
@@ -1298,13 +1211,7 @@ restart:
                set_current_state(state);
 
 wakeup:
-               /*
-                * Carefully check if the request is complete, giving time
-                * for the seqno to be visible following the interrupt.
-                * We also have to check in case we are kicked by the GPU
-                * reset in order to drop the struct_mutex.
-                */
-               if (__i915_request_irq_complete(rq))
+               if (i915_request_completed(rq))
                        break;
 
                /*
@@ -1343,19 +1250,6 @@ complete:
        return timeout;
 }
 
-static void ring_retire_requests(struct intel_ring *ring)
-{
-       struct i915_request *request, *next;
-
-       list_for_each_entry_safe(request, next,
-                                &ring->request_list, ring_link) {
-               if (!i915_request_completed(request))
-                       break;
-
-               i915_request_retire(request);
-       }
-}
-
 void i915_retire_requests(struct drm_i915_private *i915)
 {
        struct intel_ring *ring, *tmp;
index 90e9d170a0cd5e00645842e3955df058e4a8b338..c0f084ca4f29c1c1cdfbdba78558436b5ca5c343 100644 (file)
@@ -30,7 +30,6 @@
 #include "i915_gem.h"
 #include "i915_scheduler.h"
 #include "i915_sw_fence.h"
-#include "i915_scheduler.h"
 
 #include <uapi/drm/i915_drm.h>
 
@@ -281,6 +280,11 @@ long i915_request_wait(struct i915_request *rq,
 #define I915_WAIT_ALL          BIT(3) /* used by i915_gem_object_wait() */
 #define I915_WAIT_FOR_IDLE_BOOST BIT(4)
 
+static inline bool i915_request_signaled(const struct i915_request *rq)
+{
+       return test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags);
+}
+
 static inline bool intel_engine_has_started(struct intel_engine_cs *engine,
                                            u32 seqno);
 static inline bool intel_engine_has_completed(struct intel_engine_cs *engine,
diff --git a/drivers/gpu/drm/i915/i915_reset.c b/drivers/gpu/drm/i915/i915_reset.c
new file mode 100644 (file)
index 0000000..342d9ee
--- /dev/null
@@ -0,0 +1,1389 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright Â© 2008-2018 Intel Corporation
+ */
+
+#include <linux/sched/mm.h>
+
+#include "i915_drv.h"
+#include "i915_gpu_error.h"
+#include "i915_reset.h"
+
+#include "intel_guc.h"
+
+static void engine_skip_context(struct i915_request *rq)
+{
+       struct intel_engine_cs *engine = rq->engine;
+       struct i915_gem_context *hung_ctx = rq->gem_context;
+       struct i915_timeline *timeline = rq->timeline;
+       unsigned long flags;
+
+       GEM_BUG_ON(timeline == &engine->timeline);
+
+       spin_lock_irqsave(&engine->timeline.lock, flags);
+       spin_lock(&timeline->lock);
+
+       list_for_each_entry_continue(rq, &engine->timeline.requests, link)
+               if (rq->gem_context == hung_ctx)
+                       i915_request_skip(rq, -EIO);
+
+       list_for_each_entry(rq, &timeline->requests, link)
+               i915_request_skip(rq, -EIO);
+
+       spin_unlock(&timeline->lock);
+       spin_unlock_irqrestore(&engine->timeline.lock, flags);
+}
+
+static void client_mark_guilty(struct drm_i915_file_private *file_priv,
+                              const struct i915_gem_context *ctx)
+{
+       unsigned int score;
+       unsigned long prev_hang;
+
+       if (i915_gem_context_is_banned(ctx))
+               score = I915_CLIENT_SCORE_CONTEXT_BAN;
+       else
+               score = 0;
+
+       prev_hang = xchg(&file_priv->hang_timestamp, jiffies);
+       if (time_before(jiffies, prev_hang + I915_CLIENT_FAST_HANG_JIFFIES))
+               score += I915_CLIENT_SCORE_HANG_FAST;
+
+       if (score) {
+               atomic_add(score, &file_priv->ban_score);
+
+               DRM_DEBUG_DRIVER("client %s: gained %u ban score, now %u\n",
+                                ctx->name, score,
+                                atomic_read(&file_priv->ban_score));
+       }
+}
+
+static void context_mark_guilty(struct i915_gem_context *ctx)
+{
+       unsigned int score;
+       bool banned, bannable;
+
+       atomic_inc(&ctx->guilty_count);
+
+       bannable = i915_gem_context_is_bannable(ctx);
+       score = atomic_add_return(CONTEXT_SCORE_GUILTY, &ctx->ban_score);
+       banned = score >= CONTEXT_SCORE_BAN_THRESHOLD;
+
+       /* Cool contexts don't accumulate client ban score */
+       if (!bannable)
+               return;
+
+       if (banned) {
+               DRM_DEBUG_DRIVER("context %s: guilty %d, score %u, banned\n",
+                                ctx->name, atomic_read(&ctx->guilty_count),
+                                score);
+               i915_gem_context_set_banned(ctx);
+       }
+
+       if (!IS_ERR_OR_NULL(ctx->file_priv))
+               client_mark_guilty(ctx->file_priv, ctx);
+}
+
+static void context_mark_innocent(struct i915_gem_context *ctx)
+{
+       atomic_inc(&ctx->active_count);
+}
+
+static void gen3_stop_engine(struct intel_engine_cs *engine)
+{
+       struct drm_i915_private *dev_priv = engine->i915;
+       const u32 base = engine->mmio_base;
+
+       if (intel_engine_stop_cs(engine))
+               DRM_DEBUG_DRIVER("%s: timed out on STOP_RING\n", engine->name);
+
+       I915_WRITE_FW(RING_HEAD(base), I915_READ_FW(RING_TAIL(base)));
+       POSTING_READ_FW(RING_HEAD(base)); /* paranoia */
+
+       I915_WRITE_FW(RING_HEAD(base), 0);
+       I915_WRITE_FW(RING_TAIL(base), 0);
+       POSTING_READ_FW(RING_TAIL(base));
+
+       /* The ring must be empty before it is disabled */
+       I915_WRITE_FW(RING_CTL(base), 0);
+
+       /* Check acts as a post */
+       if (I915_READ_FW(RING_HEAD(base)) != 0)
+               DRM_DEBUG_DRIVER("%s: ring head not parked\n",
+                                engine->name);
+}
+
+static void i915_stop_engines(struct drm_i915_private *i915,
+                             unsigned int engine_mask)
+{
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
+
+       if (INTEL_GEN(i915) < 3)
+               return;
+
+       for_each_engine_masked(engine, i915, engine_mask, id)
+               gen3_stop_engine(engine);
+}
+
+static bool i915_in_reset(struct pci_dev *pdev)
+{
+       u8 gdrst;
+
+       pci_read_config_byte(pdev, I915_GDRST, &gdrst);
+       return gdrst & GRDOM_RESET_STATUS;
+}
+
+static int i915_do_reset(struct drm_i915_private *i915,
+                        unsigned int engine_mask,
+                        unsigned int retry)
+{
+       struct pci_dev *pdev = i915->drm.pdev;
+       int err;
+
+       /* Assert reset for at least 20 usec, and wait for acknowledgement. */
+       pci_write_config_byte(pdev, I915_GDRST, GRDOM_RESET_ENABLE);
+       usleep_range(50, 200);
+       err = wait_for(i915_in_reset(pdev), 500);
+
+       /* Clear the reset request. */
+       pci_write_config_byte(pdev, I915_GDRST, 0);
+       usleep_range(50, 200);
+       if (!err)
+               err = wait_for(!i915_in_reset(pdev), 500);
+
+       return err;
+}
+
+static bool g4x_reset_complete(struct pci_dev *pdev)
+{
+       u8 gdrst;
+
+       pci_read_config_byte(pdev, I915_GDRST, &gdrst);
+       return (gdrst & GRDOM_RESET_ENABLE) == 0;
+}
+
+static int g33_do_reset(struct drm_i915_private *i915,
+                       unsigned int engine_mask,
+                       unsigned int retry)
+{
+       struct pci_dev *pdev = i915->drm.pdev;
+
+       pci_write_config_byte(pdev, I915_GDRST, GRDOM_RESET_ENABLE);
+       return wait_for(g4x_reset_complete(pdev), 500);
+}
+
+static int g4x_do_reset(struct drm_i915_private *dev_priv,
+                       unsigned int engine_mask,
+                       unsigned int retry)
+{
+       struct pci_dev *pdev = dev_priv->drm.pdev;
+       int ret;
+
+       /* WaVcpClkGateDisableForMediaReset:ctg,elk */
+       I915_WRITE(VDECCLK_GATE_D,
+                  I915_READ(VDECCLK_GATE_D) | VCP_UNIT_CLOCK_GATE_DISABLE);
+       POSTING_READ(VDECCLK_GATE_D);
+
+       pci_write_config_byte(pdev, I915_GDRST,
+                             GRDOM_MEDIA | GRDOM_RESET_ENABLE);
+       ret =  wait_for(g4x_reset_complete(pdev), 500);
+       if (ret) {
+               DRM_DEBUG_DRIVER("Wait for media reset failed\n");
+               goto out;
+       }
+
+       pci_write_config_byte(pdev, I915_GDRST,
+                             GRDOM_RENDER | GRDOM_RESET_ENABLE);
+       ret =  wait_for(g4x_reset_complete(pdev), 500);
+       if (ret) {
+               DRM_DEBUG_DRIVER("Wait for render reset failed\n");
+               goto out;
+       }
+
+out:
+       pci_write_config_byte(pdev, I915_GDRST, 0);
+
+       I915_WRITE(VDECCLK_GATE_D,
+                  I915_READ(VDECCLK_GATE_D) & ~VCP_UNIT_CLOCK_GATE_DISABLE);
+       POSTING_READ(VDECCLK_GATE_D);
+
+       return ret;
+}
+
+static int ironlake_do_reset(struct drm_i915_private *dev_priv,
+                            unsigned int engine_mask,
+                            unsigned int retry)
+{
+       int ret;
+
+       I915_WRITE(ILK_GDSR, ILK_GRDOM_RENDER | ILK_GRDOM_RESET_ENABLE);
+       ret = intel_wait_for_register(dev_priv,
+                                     ILK_GDSR, ILK_GRDOM_RESET_ENABLE, 0,
+                                     500);
+       if (ret) {
+               DRM_DEBUG_DRIVER("Wait for render reset failed\n");
+               goto out;
+       }
+
+       I915_WRITE(ILK_GDSR, ILK_GRDOM_MEDIA | ILK_GRDOM_RESET_ENABLE);
+       ret = intel_wait_for_register(dev_priv,
+                                     ILK_GDSR, ILK_GRDOM_RESET_ENABLE, 0,
+                                     500);
+       if (ret) {
+               DRM_DEBUG_DRIVER("Wait for media reset failed\n");
+               goto out;
+       }
+
+out:
+       I915_WRITE(ILK_GDSR, 0);
+       POSTING_READ(ILK_GDSR);
+       return ret;
+}
+
+/* Reset the hardware domains (GENX_GRDOM_*) specified by mask */
+static int gen6_hw_domain_reset(struct drm_i915_private *dev_priv,
+                               u32 hw_domain_mask)
+{
+       int err;
+
+       /*
+        * GEN6_GDRST is not in the gt power well, no need to check
+        * for fifo space for the write or forcewake the chip for
+        * the read
+        */
+       I915_WRITE_FW(GEN6_GDRST, hw_domain_mask);
+
+       /* Wait for the device to ack the reset requests */
+       err = __intel_wait_for_register_fw(dev_priv,
+                                          GEN6_GDRST, hw_domain_mask, 0,
+                                          500, 0,
+                                          NULL);
+       if (err)
+               DRM_DEBUG_DRIVER("Wait for 0x%08x engines reset failed\n",
+                                hw_domain_mask);
+
+       return err;
+}
+
+static int gen6_reset_engines(struct drm_i915_private *i915,
+                             unsigned int engine_mask,
+                             unsigned int retry)
+{
+       struct intel_engine_cs *engine;
+       const u32 hw_engine_mask[I915_NUM_ENGINES] = {
+               [RCS] = GEN6_GRDOM_RENDER,
+               [BCS] = GEN6_GRDOM_BLT,
+               [VCS] = GEN6_GRDOM_MEDIA,
+               [VCS2] = GEN8_GRDOM_MEDIA2,
+               [VECS] = GEN6_GRDOM_VECS,
+       };
+       u32 hw_mask;
+
+       if (engine_mask == ALL_ENGINES) {
+               hw_mask = GEN6_GRDOM_FULL;
+       } else {
+               unsigned int tmp;
+
+               hw_mask = 0;
+               for_each_engine_masked(engine, i915, engine_mask, tmp)
+                       hw_mask |= hw_engine_mask[engine->id];
+       }
+
+       return gen6_hw_domain_reset(i915, hw_mask);
+}
+
+static u32 gen11_lock_sfc(struct drm_i915_private *dev_priv,
+                         struct intel_engine_cs *engine)
+{
+       u8 vdbox_sfc_access = RUNTIME_INFO(dev_priv)->vdbox_sfc_access;
+       i915_reg_t sfc_forced_lock, sfc_forced_lock_ack;
+       u32 sfc_forced_lock_bit, sfc_forced_lock_ack_bit;
+       i915_reg_t sfc_usage;
+       u32 sfc_usage_bit;
+       u32 sfc_reset_bit;
+
+       switch (engine->class) {
+       case VIDEO_DECODE_CLASS:
+               if ((BIT(engine->instance) & vdbox_sfc_access) == 0)
+                       return 0;
+
+               sfc_forced_lock = GEN11_VCS_SFC_FORCED_LOCK(engine);
+               sfc_forced_lock_bit = GEN11_VCS_SFC_FORCED_LOCK_BIT;
+
+               sfc_forced_lock_ack = GEN11_VCS_SFC_LOCK_STATUS(engine);
+               sfc_forced_lock_ack_bit  = GEN11_VCS_SFC_LOCK_ACK_BIT;
+
+               sfc_usage = GEN11_VCS_SFC_LOCK_STATUS(engine);
+               sfc_usage_bit = GEN11_VCS_SFC_USAGE_BIT;
+               sfc_reset_bit = GEN11_VCS_SFC_RESET_BIT(engine->instance);
+               break;
+
+       case VIDEO_ENHANCEMENT_CLASS:
+               sfc_forced_lock = GEN11_VECS_SFC_FORCED_LOCK(engine);
+               sfc_forced_lock_bit = GEN11_VECS_SFC_FORCED_LOCK_BIT;
+
+               sfc_forced_lock_ack = GEN11_VECS_SFC_LOCK_ACK(engine);
+               sfc_forced_lock_ack_bit  = GEN11_VECS_SFC_LOCK_ACK_BIT;
+
+               sfc_usage = GEN11_VECS_SFC_USAGE(engine);
+               sfc_usage_bit = GEN11_VECS_SFC_USAGE_BIT;
+               sfc_reset_bit = GEN11_VECS_SFC_RESET_BIT(engine->instance);
+               break;
+
+       default:
+               return 0;
+       }
+
+       /*
+        * Tell the engine that a software reset is going to happen. The engine
+        * will then try to force lock the SFC (if currently locked, it will
+        * remain so until we tell the engine it is safe to unlock; if currently
+        * unlocked, it will ignore this and all new lock requests). If SFC
+        * ends up being locked to the engine we want to reset, we have to reset
+        * it as well (we will unlock it once the reset sequence is completed).
+        */
+       I915_WRITE_FW(sfc_forced_lock,
+                     I915_READ_FW(sfc_forced_lock) | sfc_forced_lock_bit);
+
+       if (__intel_wait_for_register_fw(dev_priv,
+                                        sfc_forced_lock_ack,
+                                        sfc_forced_lock_ack_bit,
+                                        sfc_forced_lock_ack_bit,
+                                        1000, 0, NULL)) {
+               DRM_DEBUG_DRIVER("Wait for SFC forced lock ack failed\n");
+               return 0;
+       }
+
+       if (I915_READ_FW(sfc_usage) & sfc_usage_bit)
+               return sfc_reset_bit;
+
+       return 0;
+}
+
+static void gen11_unlock_sfc(struct drm_i915_private *dev_priv,
+                            struct intel_engine_cs *engine)
+{
+       u8 vdbox_sfc_access = RUNTIME_INFO(dev_priv)->vdbox_sfc_access;
+       i915_reg_t sfc_forced_lock;
+       u32 sfc_forced_lock_bit;
+
+       switch (engine->class) {
+       case VIDEO_DECODE_CLASS:
+               if ((BIT(engine->instance) & vdbox_sfc_access) == 0)
+                       return;
+
+               sfc_forced_lock = GEN11_VCS_SFC_FORCED_LOCK(engine);
+               sfc_forced_lock_bit = GEN11_VCS_SFC_FORCED_LOCK_BIT;
+               break;
+
+       case VIDEO_ENHANCEMENT_CLASS:
+               sfc_forced_lock = GEN11_VECS_SFC_FORCED_LOCK(engine);
+               sfc_forced_lock_bit = GEN11_VECS_SFC_FORCED_LOCK_BIT;
+               break;
+
+       default:
+               return;
+       }
+
+       I915_WRITE_FW(sfc_forced_lock,
+                     I915_READ_FW(sfc_forced_lock) & ~sfc_forced_lock_bit);
+}
+
+static int gen11_reset_engines(struct drm_i915_private *i915,
+                              unsigned int engine_mask,
+                              unsigned int retry)
+{
+       const u32 hw_engine_mask[I915_NUM_ENGINES] = {
+               [RCS] = GEN11_GRDOM_RENDER,
+               [BCS] = GEN11_GRDOM_BLT,
+               [VCS] = GEN11_GRDOM_MEDIA,
+               [VCS2] = GEN11_GRDOM_MEDIA2,
+               [VCS3] = GEN11_GRDOM_MEDIA3,
+               [VCS4] = GEN11_GRDOM_MEDIA4,
+               [VECS] = GEN11_GRDOM_VECS,
+               [VECS2] = GEN11_GRDOM_VECS2,
+       };
+       struct intel_engine_cs *engine;
+       unsigned int tmp;
+       u32 hw_mask;
+       int ret;
+
+       BUILD_BUG_ON(VECS2 + 1 != I915_NUM_ENGINES);
+
+       if (engine_mask == ALL_ENGINES) {
+               hw_mask = GEN11_GRDOM_FULL;
+       } else {
+               hw_mask = 0;
+               for_each_engine_masked(engine, i915, engine_mask, tmp) {
+                       hw_mask |= hw_engine_mask[engine->id];
+                       hw_mask |= gen11_lock_sfc(i915, engine);
+               }
+       }
+
+       ret = gen6_hw_domain_reset(i915, hw_mask);
+
+       if (engine_mask != ALL_ENGINES)
+               for_each_engine_masked(engine, i915, engine_mask, tmp)
+                       gen11_unlock_sfc(i915, engine);
+
+       return ret;
+}
+
+static int gen8_engine_reset_prepare(struct intel_engine_cs *engine)
+{
+       struct drm_i915_private *dev_priv = engine->i915;
+       int ret;
+
+       I915_WRITE_FW(RING_RESET_CTL(engine->mmio_base),
+                     _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET));
+
+       ret = __intel_wait_for_register_fw(dev_priv,
+                                          RING_RESET_CTL(engine->mmio_base),
+                                          RESET_CTL_READY_TO_RESET,
+                                          RESET_CTL_READY_TO_RESET,
+                                          700, 0,
+                                          NULL);
+       if (ret)
+               DRM_ERROR("%s: reset request timeout\n", engine->name);
+
+       return ret;
+}
+
+static void gen8_engine_reset_cancel(struct intel_engine_cs *engine)
+{
+       struct drm_i915_private *dev_priv = engine->i915;
+
+       I915_WRITE_FW(RING_RESET_CTL(engine->mmio_base),
+                     _MASKED_BIT_DISABLE(RESET_CTL_REQUEST_RESET));
+}
+
+static int gen8_reset_engines(struct drm_i915_private *i915,
+                             unsigned int engine_mask,
+                             unsigned int retry)
+{
+       struct intel_engine_cs *engine;
+       const bool reset_non_ready = retry >= 1;
+       unsigned int tmp;
+       int ret;
+
+       for_each_engine_masked(engine, i915, engine_mask, tmp) {
+               ret = gen8_engine_reset_prepare(engine);
+               if (ret && !reset_non_ready)
+                       goto skip_reset;
+
+               /*
+                * If this is not the first failed attempt to prepare,
+                * we decide to proceed anyway.
+                *
+                * By doing so we risk context corruption and with
+                * some gens (kbl), possible system hang if reset
+                * happens during active bb execution.
+                *
+                * We rather take context corruption instead of
+                * failed reset with a wedged driver/gpu. And
+                * active bb execution case should be covered by
+                * i915_stop_engines we have before the reset.
+                */
+       }
+
+       if (INTEL_GEN(i915) >= 11)
+               ret = gen11_reset_engines(i915, engine_mask, retry);
+       else
+               ret = gen6_reset_engines(i915, engine_mask, retry);
+
+skip_reset:
+       for_each_engine_masked(engine, i915, engine_mask, tmp)
+               gen8_engine_reset_cancel(engine);
+
+       return ret;
+}
+
+typedef int (*reset_func)(struct drm_i915_private *,
+                         unsigned int engine_mask,
+                         unsigned int retry);
+
+static reset_func intel_get_gpu_reset(struct drm_i915_private *i915)
+{
+       if (!i915_modparams.reset)
+               return NULL;
+
+       if (INTEL_GEN(i915) >= 8)
+               return gen8_reset_engines;
+       else if (INTEL_GEN(i915) >= 6)
+               return gen6_reset_engines;
+       else if (INTEL_GEN(i915) >= 5)
+               return ironlake_do_reset;
+       else if (IS_G4X(i915))
+               return g4x_do_reset;
+       else if (IS_G33(i915) || IS_PINEVIEW(i915))
+               return g33_do_reset;
+       else if (INTEL_GEN(i915) >= 3)
+               return i915_do_reset;
+       else
+               return NULL;
+}
+
+int intel_gpu_reset(struct drm_i915_private *i915, unsigned int engine_mask)
+{
+       reset_func reset = intel_get_gpu_reset(i915);
+       int retry;
+       int ret;
+
+       /*
+        * We want to perform per-engine reset from atomic context (e.g.
+        * softirq), which imposes the constraint that we cannot sleep.
+        * However, experience suggests that spending a bit of time waiting
+        * for a reset helps in various cases, so for a full-device reset
+        * we apply the opposite rule and wait if we want to. As we should
+        * always follow up a failed per-engine reset with a full device reset,
+        * being a little faster, stricter and more error prone for the
+        * atomic case seems an acceptable compromise.
+        *
+        * Unfortunately this leads to a bimodal routine, when the goal was
+        * to have a single reset function that worked for resetting any
+        * number of engines simultaneously.
+        */
+       might_sleep_if(engine_mask == ALL_ENGINES);
+
+       /*
+        * If the power well sleeps during the reset, the reset
+        * request may be dropped and never completes (causing -EIO).
+        */
+       intel_uncore_forcewake_get(i915, FORCEWAKE_ALL);
+       for (retry = 0; retry < 3; retry++) {
+               /*
+                * We stop engines, otherwise we might get failed reset and a
+                * dead gpu (on elk). Also as modern gpu as kbl can suffer
+                * from system hang if batchbuffer is progressing when
+                * the reset is issued, regardless of READY_TO_RESET ack.
+                * Thus assume it is best to stop engines on all gens
+                * where we have a gpu reset.
+                *
+                * WaKBLVECSSemaphoreWaitPoll:kbl (on ALL_ENGINES)
+                *
+                * WaMediaResetMainRingCleanup:ctg,elk (presumably)
+                *
+                * FIXME: Wa for more modern gens needs to be validated
+                */
+               i915_stop_engines(i915, engine_mask);
+
+               ret = -ENODEV;
+               if (reset) {
+                       GEM_TRACE("engine_mask=%x\n", engine_mask);
+                       ret = reset(i915, engine_mask, retry);
+               }
+               if (ret != -ETIMEDOUT || engine_mask != ALL_ENGINES)
+                       break;
+
+               cond_resched();
+       }
+       intel_uncore_forcewake_put(i915, FORCEWAKE_ALL);
+
+       return ret;
+}
+
+bool intel_has_gpu_reset(struct drm_i915_private *i915)
+{
+       return intel_get_gpu_reset(i915);
+}
+
+bool intel_has_reset_engine(struct drm_i915_private *i915)
+{
+       return INTEL_INFO(i915)->has_reset_engine && i915_modparams.reset >= 2;
+}
+
+int intel_reset_guc(struct drm_i915_private *i915)
+{
+       u32 guc_domain =
+               INTEL_GEN(i915) >= 11 ? GEN11_GRDOM_GUC : GEN9_GRDOM_GUC;
+       int ret;
+
+       GEM_BUG_ON(!HAS_GUC(i915));
+
+       intel_uncore_forcewake_get(i915, FORCEWAKE_ALL);
+       ret = gen6_hw_domain_reset(i915, guc_domain);
+       intel_uncore_forcewake_put(i915, FORCEWAKE_ALL);
+
+       return ret;
+}
+
+/*
+ * Ensure irq handler finishes, and not run again.
+ * Also return the active request so that we only search for it once.
+ */
+static struct i915_request *
+reset_prepare_engine(struct intel_engine_cs *engine)
+{
+       struct i915_request *rq;
+
+       /*
+        * During the reset sequence, we must prevent the engine from
+        * entering RC6. As the context state is undefined until we restart
+        * the engine, if it does enter RC6 during the reset, the state
+        * written to the powercontext is undefined and so we may lose
+        * GPU state upon resume, i.e. fail to restart after a reset.
+        */
+       intel_uncore_forcewake_get(engine->i915, FORCEWAKE_ALL);
+
+       rq = engine->reset.prepare(engine);
+       if (rq && rq->fence.error == -EIO)
+               rq = ERR_PTR(-EIO); /* Previous reset failed! */
+
+       return rq;
+}
+
+static int reset_prepare(struct drm_i915_private *i915)
+{
+       struct intel_engine_cs *engine;
+       struct i915_request *rq;
+       enum intel_engine_id id;
+       int err = 0;
+
+       for_each_engine(engine, i915, id) {
+               rq = reset_prepare_engine(engine);
+               if (IS_ERR(rq)) {
+                       err = PTR_ERR(rq);
+                       continue;
+               }
+
+               engine->hangcheck.active_request = rq;
+       }
+
+       i915_gem_revoke_fences(i915);
+       intel_uc_sanitize(i915);
+
+       return err;
+}
+
+/* Returns the request if it was guilty of the hang */
+static struct i915_request *
+reset_request(struct intel_engine_cs *engine,
+             struct i915_request *rq,
+             bool stalled)
+{
+       /*
+        * The guilty request will get skipped on a hung engine.
+        *
+        * Users of client default contexts do not rely on logical
+        * state preserved between batches so it is safe to execute
+        * queued requests following the hang. Non default contexts
+        * rely on preserved state, so skipping a batch loses the
+        * evolution of the state and it needs to be considered corrupted.
+        * Executing more queued batches on top of corrupted state is
+        * risky. But we take the risk by trying to advance through
+        * the queued requests in order to make the client behaviour
+        * more predictable around resets, by not throwing away random
+        * amount of batches it has prepared for execution. Sophisticated
+        * clients can use gem_reset_stats_ioctl and dma fence status
+        * (exported via sync_file info ioctl on explicit fences) to observe
+        * when it loses the context state and should rebuild accordingly.
+        *
+        * The context ban, and ultimately the client ban, mechanism are safety
+        * valves if client submission ends up resulting in nothing more than
+        * subsequent hangs.
+        */
+
+       if (i915_request_completed(rq)) {
+               GEM_TRACE("%s pardoned global=%d (fence %llx:%lld), current %d\n",
+                         engine->name, rq->global_seqno,
+                         rq->fence.context, rq->fence.seqno,
+                         intel_engine_get_seqno(engine));
+               stalled = false;
+       }
+
+       if (stalled) {
+               context_mark_guilty(rq->gem_context);
+               i915_request_skip(rq, -EIO);
+
+               /* If this context is now banned, skip all pending requests. */
+               if (i915_gem_context_is_banned(rq->gem_context))
+                       engine_skip_context(rq);
+       } else {
+               /*
+                * Since this is not the hung engine, it may have advanced
+                * since the hang declaration. Double check by refinding
+                * the active request at the time of the reset.
+                */
+               rq = i915_gem_find_active_request(engine);
+               if (rq) {
+                       unsigned long flags;
+
+                       context_mark_innocent(rq->gem_context);
+                       dma_fence_set_error(&rq->fence, -EAGAIN);
+
+                       /* Rewind the engine to replay the incomplete rq */
+                       spin_lock_irqsave(&engine->timeline.lock, flags);
+                       rq = list_prev_entry(rq, link);
+                       if (&rq->link == &engine->timeline.requests)
+                               rq = NULL;
+                       spin_unlock_irqrestore(&engine->timeline.lock, flags);
+               }
+       }
+
+       return rq;
+}
+
+static void reset_engine(struct intel_engine_cs *engine,
+                        struct i915_request *rq,
+                        bool stalled)
+{
+       if (rq)
+               rq = reset_request(engine, rq, stalled);
+
+       /* Setup the CS to resume from the breadcrumb of the hung request */
+       engine->reset.reset(engine, rq);
+}
+
+static void gt_reset(struct drm_i915_private *i915, unsigned int stalled_mask)
+{
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
+
+       lockdep_assert_held(&i915->drm.struct_mutex);
+
+       i915_retire_requests(i915);
+
+       for_each_engine(engine, i915, id) {
+               struct intel_context *ce;
+
+               reset_engine(engine,
+                            engine->hangcheck.active_request,
+                            stalled_mask & ENGINE_MASK(id));
+               ce = fetch_and_zero(&engine->last_retired_context);
+               if (ce)
+                       intel_context_unpin(ce);
+
+               /*
+                * Ostensibily, we always want a context loaded for powersaving,
+                * so if the engine is idle after the reset, send a request
+                * to load our scratch kernel_context.
+                *
+                * More mysteriously, if we leave the engine idle after a reset,
+                * the next userspace batch may hang, with what appears to be
+                * an incoherent read by the CS (presumably stale TLB). An
+                * empty request appears sufficient to paper over the glitch.
+                */
+               if (intel_engine_is_idle(engine)) {
+                       struct i915_request *rq;
+
+                       rq = i915_request_alloc(engine, i915->kernel_context);
+                       if (!IS_ERR(rq))
+                               i915_request_add(rq);
+               }
+       }
+
+       i915_gem_restore_fences(i915);
+}
+
+static void reset_finish_engine(struct intel_engine_cs *engine)
+{
+       engine->reset.finish(engine);
+
+       intel_uncore_forcewake_put(engine->i915, FORCEWAKE_ALL);
+}
+
+static void reset_finish(struct drm_i915_private *i915)
+{
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
+
+       lockdep_assert_held(&i915->drm.struct_mutex);
+
+       for_each_engine(engine, i915, id) {
+               engine->hangcheck.active_request = NULL;
+               reset_finish_engine(engine);
+       }
+}
+
+static void nop_submit_request(struct i915_request *request)
+{
+       unsigned long flags;
+
+       GEM_TRACE("%s fence %llx:%lld -> -EIO\n",
+                 request->engine->name,
+                 request->fence.context, request->fence.seqno);
+       dma_fence_set_error(&request->fence, -EIO);
+
+       spin_lock_irqsave(&request->engine->timeline.lock, flags);
+       __i915_request_submit(request);
+       intel_engine_write_global_seqno(request->engine, request->global_seqno);
+       spin_unlock_irqrestore(&request->engine->timeline.lock, flags);
+}
+
+void i915_gem_set_wedged(struct drm_i915_private *i915)
+{
+       struct i915_gpu_error *error = &i915->gpu_error;
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
+
+       mutex_lock(&error->wedge_mutex);
+       if (test_bit(I915_WEDGED, &error->flags)) {
+               mutex_unlock(&error->wedge_mutex);
+               return;
+       }
+
+       if (GEM_SHOW_DEBUG() && !intel_engines_are_idle(i915)) {
+               struct drm_printer p = drm_debug_printer(__func__);
+
+               for_each_engine(engine, i915, id)
+                       intel_engine_dump(engine, &p, "%s\n", engine->name);
+       }
+
+       GEM_TRACE("start\n");
+
+       /*
+        * First, stop submission to hw, but do not yet complete requests by
+        * rolling the global seqno forward (since this would complete requests
+        * for which we haven't set the fence error to EIO yet).
+        */
+       for_each_engine(engine, i915, id)
+               reset_prepare_engine(engine);
+
+       /* Even if the GPU reset fails, it should still stop the engines */
+       if (INTEL_GEN(i915) >= 5)
+               intel_gpu_reset(i915, ALL_ENGINES);
+
+       for_each_engine(engine, i915, id) {
+               engine->submit_request = nop_submit_request;
+               engine->schedule = NULL;
+       }
+       i915->caps.scheduler = 0;
+
+       /*
+        * Make sure no request can slip through without getting completed by
+        * either this call here to intel_engine_write_global_seqno, or the one
+        * in nop_submit_request.
+        */
+       synchronize_rcu();
+
+       /* Mark all executing requests as skipped */
+       for_each_engine(engine, i915, id)
+               engine->cancel_requests(engine);
+
+       for_each_engine(engine, i915, id) {
+               reset_finish_engine(engine);
+               intel_engine_wakeup(engine);
+       }
+
+       smp_mb__before_atomic();
+       set_bit(I915_WEDGED, &error->flags);
+
+       GEM_TRACE("end\n");
+       mutex_unlock(&error->wedge_mutex);
+
+       wake_up_all(&error->reset_queue);
+}
+
+bool i915_gem_unset_wedged(struct drm_i915_private *i915)
+{
+       struct i915_gpu_error *error = &i915->gpu_error;
+       struct i915_timeline *tl;
+       bool ret = false;
+
+       lockdep_assert_held(&i915->drm.struct_mutex);
+
+       if (!test_bit(I915_WEDGED, &error->flags))
+               return true;
+
+       if (!i915->gt.scratch) /* Never full initialised, recovery impossible */
+               return false;
+
+       mutex_lock(&error->wedge_mutex);
+
+       GEM_TRACE("start\n");
+
+       /*
+        * Before unwedging, make sure that all pending operations
+        * are flushed and errored out - we may have requests waiting upon
+        * third party fences. We marked all inflight requests as EIO, and
+        * every execbuf since returned EIO, for consistency we want all
+        * the currently pending requests to also be marked as EIO, which
+        * is done inside our nop_submit_request - and so we must wait.
+        *
+        * No more can be submitted until we reset the wedged bit.
+        */
+       list_for_each_entry(tl, &i915->gt.timelines, link) {
+               struct i915_request *rq;
+
+               rq = i915_gem_active_peek(&tl->last_request,
+                                         &i915->drm.struct_mutex);
+               if (!rq)
+                       continue;
+
+               /*
+                * We can't use our normal waiter as we want to
+                * avoid recursively trying to handle the current
+                * reset. The basic dma_fence_default_wait() installs
+                * a callback for dma_fence_signal(), which is
+                * triggered by our nop handler (indirectly, the
+                * callback enables the signaler thread which is
+                * woken by the nop_submit_request() advancing the seqno
+                * and when the seqno passes the fence, the signaler
+                * then signals the fence waking us up).
+                */
+               if (dma_fence_default_wait(&rq->fence, true,
+                                          MAX_SCHEDULE_TIMEOUT) < 0)
+                       goto unlock;
+       }
+       i915_retire_requests(i915);
+       GEM_BUG_ON(i915->gt.active_requests);
+
+       intel_engines_sanitize(i915, false);
+
+       /*
+        * Undo nop_submit_request. We prevent all new i915 requests from
+        * being queued (by disallowing execbuf whilst wedged) so having
+        * waited for all active requests above, we know the system is idle
+        * and do not have to worry about a thread being inside
+        * engine->submit_request() as we swap over. So unlike installing
+        * the nop_submit_request on reset, we can do this from normal
+        * context and do not require stop_machine().
+        */
+       intel_engines_reset_default_submission(i915);
+       i915_gem_contexts_lost(i915);
+
+       GEM_TRACE("end\n");
+
+       smp_mb__before_atomic(); /* complete takeover before enabling execbuf */
+       clear_bit(I915_WEDGED, &i915->gpu_error.flags);
+       ret = true;
+unlock:
+       mutex_unlock(&i915->gpu_error.wedge_mutex);
+
+       return ret;
+}
+
+/**
+ * i915_reset - reset chip after a hang
+ * @i915: #drm_i915_private to reset
+ * @stalled_mask: mask of the stalled engines with the guilty requests
+ * @reason: user error message for why we are resetting
+ *
+ * Reset the chip.  Useful if a hang is detected. Marks the device as wedged
+ * on failure.
+ *
+ * Caller must hold the struct_mutex.
+ *
+ * Procedure is fairly simple:
+ *   - reset the chip using the reset reg
+ *   - re-init context state
+ *   - re-init hardware status page
+ *   - re-init ring buffer
+ *   - re-init interrupt state
+ *   - re-init display
+ */
+void i915_reset(struct drm_i915_private *i915,
+               unsigned int stalled_mask,
+               const char *reason)
+{
+       struct i915_gpu_error *error = &i915->gpu_error;
+       int ret;
+       int i;
+
+       GEM_TRACE("flags=%lx\n", error->flags);
+
+       might_sleep();
+       lockdep_assert_held(&i915->drm.struct_mutex);
+       assert_rpm_wakelock_held(i915);
+       GEM_BUG_ON(!test_bit(I915_RESET_BACKOFF, &error->flags));
+
+       if (!test_bit(I915_RESET_HANDOFF, &error->flags))
+               return;
+
+       /* Clear any previous failed attempts at recovery. Time to try again. */
+       if (!i915_gem_unset_wedged(i915))
+               goto wakeup;
+
+       if (reason)
+               dev_notice(i915->drm.dev, "Resetting chip for %s\n", reason);
+       error->reset_count++;
+
+       ret = reset_prepare(i915);
+       if (ret) {
+               dev_err(i915->drm.dev, "GPU recovery failed\n");
+               goto taint;
+       }
+
+       if (!intel_has_gpu_reset(i915)) {
+               if (i915_modparams.reset)
+                       dev_err(i915->drm.dev, "GPU reset not supported\n");
+               else
+                       DRM_DEBUG_DRIVER("GPU reset disabled\n");
+               goto error;
+       }
+
+       for (i = 0; i < 3; i++) {
+               ret = intel_gpu_reset(i915, ALL_ENGINES);
+               if (ret == 0)
+                       break;
+
+               msleep(100);
+       }
+       if (ret) {
+               dev_err(i915->drm.dev, "Failed to reset chip\n");
+               goto taint;
+       }
+
+       /* Ok, now get things going again... */
+
+       /*
+        * Everything depends on having the GTT running, so we need to start
+        * there.
+        */
+       ret = i915_ggtt_enable_hw(i915);
+       if (ret) {
+               DRM_ERROR("Failed to re-enable GGTT following reset (%d)\n",
+                         ret);
+               goto error;
+       }
+
+       gt_reset(i915, stalled_mask);
+       intel_overlay_reset(i915);
+
+       /*
+        * Next we need to restore the context, but we don't use those
+        * yet either...
+        *
+        * Ring buffer needs to be re-initialized in the KMS case, or if X
+        * was running at the time of the reset (i.e. we weren't VT
+        * switched away).
+        */
+       ret = i915_gem_init_hw(i915);
+       if (ret) {
+               DRM_ERROR("Failed to initialise HW following reset (%d)\n",
+                         ret);
+               goto error;
+       }
+
+       i915_queue_hangcheck(i915);
+
+finish:
+       reset_finish(i915);
+wakeup:
+       clear_bit(I915_RESET_HANDOFF, &error->flags);
+       wake_up_bit(&error->flags, I915_RESET_HANDOFF);
+       return;
+
+taint:
+       /*
+        * History tells us that if we cannot reset the GPU now, we
+        * never will. This then impacts everything that is run
+        * subsequently. On failing the reset, we mark the driver
+        * as wedged, preventing further execution on the GPU.
+        * We also want to go one step further and add a taint to the
+        * kernel so that any subsequent faults can be traced back to
+        * this failure. This is important for CI, where if the
+        * GPU/driver fails we would like to reboot and restart testing
+        * rather than continue on into oblivion. For everyone else,
+        * the system should still plod along, but they have been warned!
+        */
+       add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
+error:
+       i915_gem_set_wedged(i915);
+       i915_retire_requests(i915);
+       goto finish;
+}
+
+static inline int intel_gt_reset_engine(struct drm_i915_private *i915,
+                                       struct intel_engine_cs *engine)
+{
+       return intel_gpu_reset(i915, intel_engine_flag(engine));
+}
+
+/**
+ * i915_reset_engine - reset GPU engine to recover from a hang
+ * @engine: engine to reset
+ * @msg: reason for GPU reset; or NULL for no dev_notice()
+ *
+ * Reset a specific GPU engine. Useful if a hang is detected.
+ * Returns zero on successful reset or otherwise an error code.
+ *
+ * Procedure is:
+ *  - identifies the request that caused the hang and it is dropped
+ *  - reset engine (which will force the engine to idle)
+ *  - re-init/configure engine
+ */
+int i915_reset_engine(struct intel_engine_cs *engine, const char *msg)
+{
+       struct i915_gpu_error *error = &engine->i915->gpu_error;
+       struct i915_request *active_request;
+       int ret;
+
+       GEM_TRACE("%s flags=%lx\n", engine->name, error->flags);
+       GEM_BUG_ON(!test_bit(I915_RESET_ENGINE + engine->id, &error->flags));
+
+       active_request = reset_prepare_engine(engine);
+       if (IS_ERR_OR_NULL(active_request)) {
+               /* Either the previous reset failed, or we pardon the reset. */
+               ret = PTR_ERR(active_request);
+               goto out;
+       }
+
+       if (msg)
+               dev_notice(engine->i915->drm.dev,
+                          "Resetting %s for %s\n", engine->name, msg);
+       error->reset_engine_count[engine->id]++;
+
+       if (!engine->i915->guc.execbuf_client)
+               ret = intel_gt_reset_engine(engine->i915, engine);
+       else
+               ret = intel_guc_reset_engine(&engine->i915->guc, engine);
+       if (ret) {
+               /* If we fail here, we expect to fallback to a global reset */
+               DRM_DEBUG_DRIVER("%sFailed to reset %s, ret=%d\n",
+                                engine->i915->guc.execbuf_client ? "GuC " : "",
+                                engine->name, ret);
+               goto out;
+       }
+
+       /*
+        * The request that caused the hang is stuck on elsp, we know the
+        * active request and can drop it, adjust head to skip the offending
+        * request to resume executing remaining requests in the queue.
+        */
+       reset_engine(engine, active_request, true);
+
+       /*
+        * The engine and its registers (and workarounds in case of render)
+        * have been reset to their default values. Follow the init_ring
+        * process to program RING_MODE, HWSP and re-enable submission.
+        */
+       ret = engine->init_hw(engine);
+       if (ret)
+               goto out;
+
+out:
+       intel_engine_cancel_stop_cs(engine);
+       reset_finish_engine(engine);
+       return ret;
+}
+
+static void i915_reset_device(struct drm_i915_private *i915,
+                             u32 engine_mask,
+                             const char *reason)
+{
+       struct i915_gpu_error *error = &i915->gpu_error;
+       struct kobject *kobj = &i915->drm.primary->kdev->kobj;
+       char *error_event[] = { I915_ERROR_UEVENT "=1", NULL };
+       char *reset_event[] = { I915_RESET_UEVENT "=1", NULL };
+       char *reset_done_event[] = { I915_ERROR_UEVENT "=0", NULL };
+       struct i915_wedge_me w;
+
+       kobject_uevent_env(kobj, KOBJ_CHANGE, error_event);
+
+       DRM_DEBUG_DRIVER("resetting chip\n");
+       kobject_uevent_env(kobj, KOBJ_CHANGE, reset_event);
+
+       /* Use a watchdog to ensure that our reset completes */
+       i915_wedge_on_timeout(&w, i915, 5 * HZ) {
+               intel_prepare_reset(i915);
+
+               error->reason = reason;
+               error->stalled_mask = engine_mask;
+
+               /* Signal that locked waiters should reset the GPU */
+               smp_mb__before_atomic();
+               set_bit(I915_RESET_HANDOFF, &error->flags);
+               wake_up_all(&error->wait_queue);
+
+               /*
+                * Wait for anyone holding the lock to wakeup, without
+                * blocking indefinitely on struct_mutex.
+                */
+               do {
+                       if (mutex_trylock(&i915->drm.struct_mutex)) {
+                               i915_reset(i915, engine_mask, reason);
+                               mutex_unlock(&i915->drm.struct_mutex);
+                       }
+               } while (wait_on_bit_timeout(&error->flags,
+                                            I915_RESET_HANDOFF,
+                                            TASK_UNINTERRUPTIBLE,
+                                            1));
+
+               error->stalled_mask = 0;
+               error->reason = NULL;
+
+               intel_finish_reset(i915);
+       }
+
+       if (!test_bit(I915_WEDGED, &error->flags))
+               kobject_uevent_env(kobj, KOBJ_CHANGE, reset_done_event);
+}
+
+void i915_clear_error_registers(struct drm_i915_private *dev_priv)
+{
+       u32 eir;
+
+       if (!IS_GEN(dev_priv, 2))
+               I915_WRITE(PGTBL_ER, I915_READ(PGTBL_ER));
+
+       if (INTEL_GEN(dev_priv) < 4)
+               I915_WRITE(IPEIR, I915_READ(IPEIR));
+       else
+               I915_WRITE(IPEIR_I965, I915_READ(IPEIR_I965));
+
+       I915_WRITE(EIR, I915_READ(EIR));
+       eir = I915_READ(EIR);
+       if (eir) {
+               /*
+                * some errors might have become stuck,
+                * mask them.
+                */
+               DRM_DEBUG_DRIVER("EIR stuck: 0x%08x, masking\n", eir);
+               I915_WRITE(EMR, I915_READ(EMR) | eir);
+               I915_WRITE(IIR, I915_MASTER_ERROR_INTERRUPT);
+       }
+
+       if (INTEL_GEN(dev_priv) >= 8) {
+               I915_WRITE(GEN8_RING_FAULT_REG,
+                          I915_READ(GEN8_RING_FAULT_REG) & ~RING_FAULT_VALID);
+               POSTING_READ(GEN8_RING_FAULT_REG);
+       } else if (INTEL_GEN(dev_priv) >= 6) {
+               struct intel_engine_cs *engine;
+               enum intel_engine_id id;
+
+               for_each_engine(engine, dev_priv, id) {
+                       I915_WRITE(RING_FAULT_REG(engine),
+                                  I915_READ(RING_FAULT_REG(engine)) &
+                                  ~RING_FAULT_VALID);
+               }
+               POSTING_READ(RING_FAULT_REG(dev_priv->engine[RCS]));
+       }
+}
+
+/**
+ * i915_handle_error - handle a gpu error
+ * @i915: i915 device private
+ * @engine_mask: mask representing engines that are hung
+ * @flags: control flags
+ * @fmt: Error message format string
+ *
+ * Do some basic checking of register state at error time and
+ * dump it to the syslog.  Also call i915_capture_error_state() to make
+ * sure we get a record and make it available in debugfs.  Fire a uevent
+ * so userspace knows something bad happened (should trigger collection
+ * of a ring dump etc.).
+ */
+void i915_handle_error(struct drm_i915_private *i915,
+                      u32 engine_mask,
+                      unsigned long flags,
+                      const char *fmt, ...)
+{
+       struct intel_engine_cs *engine;
+       intel_wakeref_t wakeref;
+       unsigned int tmp;
+       char error_msg[80];
+       char *msg = NULL;
+
+       if (fmt) {
+               va_list args;
+
+               va_start(args, fmt);
+               vscnprintf(error_msg, sizeof(error_msg), fmt, args);
+               va_end(args);
+
+               msg = error_msg;
+       }
+
+       /*
+        * In most cases it's guaranteed that we get here with an RPM
+        * reference held, for example because there is a pending GPU
+        * request that won't finish until the reset is done. This
+        * isn't the case at least when we get here by doing a
+        * simulated reset via debugfs, so get an RPM reference.
+        */
+       wakeref = intel_runtime_pm_get(i915);
+
+       engine_mask &= INTEL_INFO(i915)->ring_mask;
+
+       if (flags & I915_ERROR_CAPTURE) {
+               i915_capture_error_state(i915, engine_mask, msg);
+               i915_clear_error_registers(i915);
+       }
+
+       /*
+        * Try engine reset when available. We fall back to full reset if
+        * single reset fails.
+        */
+       if (intel_has_reset_engine(i915) &&
+           !i915_terminally_wedged(&i915->gpu_error)) {
+               for_each_engine_masked(engine, i915, engine_mask, tmp) {
+                       BUILD_BUG_ON(I915_RESET_MODESET >= I915_RESET_ENGINE);
+                       if (test_and_set_bit(I915_RESET_ENGINE + engine->id,
+                                            &i915->gpu_error.flags))
+                               continue;
+
+                       if (i915_reset_engine(engine, msg) == 0)
+                               engine_mask &= ~intel_engine_flag(engine);
+
+                       clear_bit(I915_RESET_ENGINE + engine->id,
+                                 &i915->gpu_error.flags);
+                       wake_up_bit(&i915->gpu_error.flags,
+                                   I915_RESET_ENGINE + engine->id);
+               }
+       }
+
+       if (!engine_mask)
+               goto out;
+
+       /* Full reset needs the mutex, stop any other user trying to do so. */
+       if (test_and_set_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags)) {
+               wait_event(i915->gpu_error.reset_queue,
+                          !test_bit(I915_RESET_BACKOFF,
+                                    &i915->gpu_error.flags));
+               goto out;
+       }
+
+       /* Prevent any other reset-engine attempt. */
+       for_each_engine(engine, i915, tmp) {
+               while (test_and_set_bit(I915_RESET_ENGINE + engine->id,
+                                       &i915->gpu_error.flags))
+                       wait_on_bit(&i915->gpu_error.flags,
+                                   I915_RESET_ENGINE + engine->id,
+                                   TASK_UNINTERRUPTIBLE);
+       }
+
+       i915_reset_device(i915, engine_mask, msg);
+
+       for_each_engine(engine, i915, tmp) {
+               clear_bit(I915_RESET_ENGINE + engine->id,
+                         &i915->gpu_error.flags);
+       }
+
+       clear_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags);
+       wake_up_all(&i915->gpu_error.reset_queue);
+
+out:
+       intel_runtime_pm_put(i915, wakeref);
+}
+
+static void i915_wedge_me(struct work_struct *work)
+{
+       struct i915_wedge_me *w = container_of(work, typeof(*w), work.work);
+
+       dev_err(w->i915->drm.dev,
+               "%s timed out, cancelling all in-flight rendering.\n",
+               w->name);
+       i915_gem_set_wedged(w->i915);
+}
+
+void __i915_init_wedge(struct i915_wedge_me *w,
+                      struct drm_i915_private *i915,
+                      long timeout,
+                      const char *name)
+{
+       w->i915 = i915;
+       w->name = name;
+
+       INIT_DELAYED_WORK_ONSTACK(&w->work, i915_wedge_me);
+       schedule_delayed_work(&w->work, timeout);
+}
+
+void __i915_fini_wedge(struct i915_wedge_me *w)
+{
+       cancel_delayed_work_sync(&w->work);
+       destroy_delayed_work_on_stack(&w->work);
+       w->i915 = NULL;
+}
diff --git a/drivers/gpu/drm/i915/i915_reset.h b/drivers/gpu/drm/i915/i915_reset.h
new file mode 100644 (file)
index 0000000..b6a519b
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright Â© 2008-2018 Intel Corporation
+ */
+
+#ifndef I915_RESET_H
+#define I915_RESET_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+struct drm_i915_private;
+struct intel_engine_cs;
+struct intel_guc;
+
+__printf(4, 5)
+void i915_handle_error(struct drm_i915_private *i915,
+                      u32 engine_mask,
+                      unsigned long flags,
+                      const char *fmt, ...);
+#define I915_ERROR_CAPTURE BIT(0)
+
+void i915_clear_error_registers(struct drm_i915_private *i915);
+
+void i915_reset(struct drm_i915_private *i915,
+               unsigned int stalled_mask,
+               const char *reason);
+int i915_reset_engine(struct intel_engine_cs *engine,
+                     const char *reason);
+
+bool intel_has_gpu_reset(struct drm_i915_private *i915);
+bool intel_has_reset_engine(struct drm_i915_private *i915);
+
+int intel_gpu_reset(struct drm_i915_private *i915, u32 engine_mask);
+
+int intel_reset_guc(struct drm_i915_private *i915);
+
+struct i915_wedge_me {
+       struct delayed_work work;
+       struct drm_i915_private *i915;
+       const char *name;
+};
+
+void __i915_init_wedge(struct i915_wedge_me *w,
+                      struct drm_i915_private *i915,
+                      long timeout,
+                      const char *name);
+void __i915_fini_wedge(struct i915_wedge_me *w);
+
+#define i915_wedge_on_timeout(W, DEV, TIMEOUT)                         \
+       for (__i915_init_wedge((W), (DEV), (TIMEOUT), __func__);        \
+            (W)->i915;                                                 \
+            __i915_fini_wedge((W)))
+
+#endif /* I915_RESET_H */
index 8f3aa4dc0c98596a3b0443e493be84403d120bc3..f18afa2bac8d87efa40fe2187d45aff240462a8b 100644 (file)
@@ -24,7 +24,6 @@
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 #include "intel_drv.h"
 #include "i915_reg.h"
@@ -65,7 +64,7 @@ int i915_save_state(struct drm_i915_private *dev_priv)
 
        i915_save_display(dev_priv);
 
-       if (IS_GEN4(dev_priv))
+       if (IS_GEN(dev_priv, 4))
                pci_read_config_word(pdev, GCDGMBUS,
                                     &dev_priv->regfile.saveGCDGMBUS);
 
@@ -77,14 +76,14 @@ int i915_save_state(struct drm_i915_private *dev_priv)
        dev_priv->regfile.saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
 
        /* Scratch space */
-       if (IS_GEN2(dev_priv) && IS_MOBILE(dev_priv)) {
+       if (IS_GEN(dev_priv, 2) && IS_MOBILE(dev_priv)) {
                for (i = 0; i < 7; i++) {
                        dev_priv->regfile.saveSWF0[i] = I915_READ(SWF0(i));
                        dev_priv->regfile.saveSWF1[i] = I915_READ(SWF1(i));
                }
                for (i = 0; i < 3; i++)
                        dev_priv->regfile.saveSWF3[i] = I915_READ(SWF3(i));
-       } else if (IS_GEN2(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 2)) {
                for (i = 0; i < 7; i++)
                        dev_priv->regfile.saveSWF1[i] = I915_READ(SWF1(i));
        } else if (HAS_GMCH_DISPLAY(dev_priv)) {
@@ -108,7 +107,7 @@ int i915_restore_state(struct drm_i915_private *dev_priv)
 
        mutex_lock(&dev_priv->drm.struct_mutex);
 
-       if (IS_GEN4(dev_priv))
+       if (IS_GEN(dev_priv, 4))
                pci_write_config_word(pdev, GCDGMBUS,
                                      dev_priv->regfile.saveGCDGMBUS);
        i915_restore_display(dev_priv);
@@ -122,14 +121,14 @@ int i915_restore_state(struct drm_i915_private *dev_priv)
        I915_WRITE(MI_ARB_STATE, dev_priv->regfile.saveMI_ARB_STATE | 0xffff0000);
 
        /* Scratch space */
-       if (IS_GEN2(dev_priv) && IS_MOBILE(dev_priv)) {
+       if (IS_GEN(dev_priv, 2) && IS_MOBILE(dev_priv)) {
                for (i = 0; i < 7; i++) {
                        I915_WRITE(SWF0(i), dev_priv->regfile.saveSWF0[i]);
                        I915_WRITE(SWF1(i), dev_priv->regfile.saveSWF1[i]);
                }
                for (i = 0; i < 3; i++)
                        I915_WRITE(SWF3(i), dev_priv->regfile.saveSWF3[i]);
-       } else if (IS_GEN2(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 2)) {
                for (i = 0; i < 7; i++)
                        I915_WRITE(SWF1(i), dev_priv->regfile.saveSWF1[i]);
        } else if (HAS_GMCH_DISPLAY(dev_priv)) {
index fc2eeab823b70e505beed80a77b6e08f56bc2810..7c58b049ecb50a47bf06d0322d6077f6e06e955d 100644 (file)
@@ -390,7 +390,7 @@ static void timer_i915_sw_fence_wake(struct timer_list *t)
        if (!fence)
                return;
 
-       pr_notice("Asynchronous wait on fence %s:%s:%x timed out (hint:%pS)\n",
+       pr_notice("Asynchronous wait on fence %s:%s:%llx timed out (hint:%pS)\n",
                  cb->dma->ops->get_driver_name(cb->dma),
                  cb->dma->ops->get_timeline_name(cb->dma),
                  cb->dma->seqno,
index 535caebd9813af5d82701b1d7e47b987563cd608..41313005af42517873fa29d94016c17cf05cd317 100644 (file)
@@ -42,11 +42,11 @@ static inline struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
 static u32 calc_residency(struct drm_i915_private *dev_priv,
                          i915_reg_t reg)
 {
-       u64 res;
+       intel_wakeref_t wakeref;
+       u64 res = 0;
 
-       intel_runtime_pm_get(dev_priv);
-       res = intel_rc6_residency_us(dev_priv, reg);
-       intel_runtime_pm_put(dev_priv);
+       with_intel_runtime_pm(dev_priv, wakeref)
+               res = intel_rc6_residency_us(dev_priv, reg);
 
        return DIV_ROUND_CLOSEST_ULL(res, 1000);
 }
@@ -258,9 +258,10 @@ static ssize_t gt_act_freq_mhz_show(struct device *kdev,
                                    struct device_attribute *attr, char *buf)
 {
        struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
+       intel_wakeref_t wakeref;
        int ret;
 
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
        mutex_lock(&dev_priv->pcu_lock);
        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
@@ -274,7 +275,7 @@ static ssize_t gt_act_freq_mhz_show(struct device *kdev,
        }
        mutex_unlock(&dev_priv->pcu_lock);
 
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
 
        return snprintf(buf, PAGE_SIZE, "%d\n", ret);
 }
@@ -354,6 +355,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 {
        struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
        struct intel_rps *rps = &dev_priv->gt_pm.rps;
+       intel_wakeref_t wakeref;
        u32 val;
        ssize_t ret;
 
@@ -361,7 +363,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
        if (ret)
                return ret;
 
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
        mutex_lock(&dev_priv->pcu_lock);
 
@@ -371,7 +373,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
            val > rps->max_freq ||
            val < rps->min_freq_softlimit) {
                mutex_unlock(&dev_priv->pcu_lock);
-               intel_runtime_pm_put(dev_priv);
+               intel_runtime_pm_put(dev_priv, wakeref);
                return -EINVAL;
        }
 
@@ -392,7 +394,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 
        mutex_unlock(&dev_priv->pcu_lock);
 
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
 
        return ret ?: count;
 }
@@ -412,6 +414,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 {
        struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
        struct intel_rps *rps = &dev_priv->gt_pm.rps;
+       intel_wakeref_t wakeref;
        u32 val;
        ssize_t ret;
 
@@ -419,7 +422,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
        if (ret)
                return ret;
 
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
        mutex_lock(&dev_priv->pcu_lock);
 
@@ -429,7 +432,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
            val > rps->max_freq ||
            val > rps->max_freq_softlimit) {
                mutex_unlock(&dev_priv->pcu_lock);
-               intel_runtime_pm_put(dev_priv);
+               intel_runtime_pm_put(dev_priv, wakeref);
                return -EINVAL;
        }
 
@@ -446,7 +449,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 
        mutex_unlock(&dev_priv->pcu_lock);
 
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
 
        return ret ?: count;
 }
@@ -521,7 +524,9 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
        ssize_t ret;
 
        gpu = i915_first_error_state(i915);
-       if (gpu) {
+       if (IS_ERR(gpu)) {
+               ret = PTR_ERR(gpu);
+       } else if (gpu) {
                ret = i915_gpu_state_copy_to_buffer(gpu, buf, off, count);
                i915_gpu_state_put(gpu);
        } else {
index ebd71b487220aec95a2bfdeb1c924f0836ae64c1..38c1e15e927a82297f5f9eb43bebed85eccf062b 100644 (file)
@@ -63,14 +63,6 @@ struct i915_timeline {
         * redundant and we can discard it without loss of generality.
         */
        struct i915_syncmap *sync;
-       /**
-        * Separately to the inter-context seqno map above, we track the last
-        * barrier (e.g. semaphore wait) to the global engine timelines. Note
-        * that this tracks global_seqno rather than the context.seqno, and
-        * so it is subject to the limitations of hw wraparound and that we
-        * may need to revoke global_seqno (on pre-emption).
-        */
-       u32 global_sync[I915_NUM_ENGINES];
 
        struct list_head link;
        const char *name;
index b50c6b829715e220c9f3edede3dfa0e83497a804..33d90eca9cdd18e1422614348df8d24e07ccca6c 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/types.h>
 #include <linux/tracepoint.h>
 
-#include <drm/drmP.h>
 #include "i915_drv.h"
 #include "intel_drv.h"
 #include "intel_ringbuffer.h"
@@ -585,35 +584,6 @@ TRACE_EVENT(i915_gem_evict_vm,
            TP_printk("dev=%d, vm=%p", __entry->dev, __entry->vm)
 );
 
-TRACE_EVENT(i915_gem_ring_sync_to,
-           TP_PROTO(struct i915_request *to, struct i915_request *from),
-           TP_ARGS(to, from),
-
-           TP_STRUCT__entry(
-                            __field(u32, dev)
-                            __field(u32, from_class)
-                            __field(u32, from_instance)
-                            __field(u32, to_class)
-                            __field(u32, to_instance)
-                            __field(u32, seqno)
-                            ),
-
-           TP_fast_assign(
-                          __entry->dev = from->i915->drm.primary->index;
-                          __entry->from_class = from->engine->uabi_class;
-                          __entry->from_instance = from->engine->instance;
-                          __entry->to_class = to->engine->uabi_class;
-                          __entry->to_instance = to->engine->instance;
-                          __entry->seqno = from->global_seqno;
-                          ),
-
-           TP_printk("dev=%u, sync-from=%u:%u, sync-to=%u:%u, seqno=%u",
-                     __entry->dev,
-                     __entry->from_class, __entry->from_instance,
-                     __entry->to_class, __entry->to_instance,
-                     __entry->seqno)
-);
-
 TRACE_EVENT(i915_request_queue,
            TP_PROTO(struct i915_request *rq, u32 flags),
            TP_ARGS(rq, flags),
index 4dd793b789962873a3523222336ba7a5d99a0677..73a7bee24a663faa672ade21cfe7ea7cb1bc4b46 100644 (file)
@@ -337,9 +337,11 @@ static void gen11_dsi_enable_io_power(struct intel_encoder *encoder)
        }
 
        for_each_dsi_port(port, intel_dsi->ports) {
-               intel_display_power_get(dev_priv, port == PORT_A ?
-                                       POWER_DOMAIN_PORT_DDI_A_IO :
-                                       POWER_DOMAIN_PORT_DDI_B_IO);
+               intel_dsi->io_wakeref[port] =
+                       intel_display_power_get(dev_priv,
+                                               port == PORT_A ?
+                                               POWER_DOMAIN_PORT_DDI_A_IO :
+                                               POWER_DOMAIN_PORT_DDI_B_IO);
        }
 }
 
@@ -1125,10 +1127,18 @@ static void gen11_dsi_disable_io_power(struct intel_encoder *encoder)
        enum port port;
        u32 tmp;
 
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PORT_DDI_A_IO);
-
-       if (intel_dsi->dual_link)
-               intel_display_power_put(dev_priv, POWER_DOMAIN_PORT_DDI_B_IO);
+       for_each_dsi_port(port, intel_dsi->ports) {
+               intel_wakeref_t wakeref;
+
+               wakeref = fetch_and_zero(&intel_dsi->io_wakeref[port]);
+               if (wakeref) {
+                       intel_display_power_put(dev_priv,
+                                               port == PORT_A ?
+                                               POWER_DOMAIN_PORT_DDI_A_IO :
+                                               POWER_DOMAIN_PORT_DDI_B_IO,
+                                               wakeref);
+               }
+       }
 
        /* set mode to DDI */
        for_each_dsi_port(port, intel_dsi->ports) {
@@ -1178,9 +1188,9 @@ static void gen11_dsi_get_config(struct intel_encoder *encoder,
        pipe_config->output_types |= BIT(INTEL_OUTPUT_DSI);
 }
 
-static bool gen11_dsi_compute_config(struct intel_encoder *encoder,
-                                    struct intel_crtc_state *pipe_config,
-                                    struct drm_connector_state *conn_state)
+static int gen11_dsi_compute_config(struct intel_encoder *encoder,
+                                   struct intel_crtc_state *pipe_config,
+                                   struct drm_connector_state *conn_state)
 {
        struct intel_dsi *intel_dsi = container_of(encoder, struct intel_dsi,
                                                   base);
@@ -1205,7 +1215,7 @@ static bool gen11_dsi_compute_config(struct intel_encoder *encoder,
        pipe_config->clock_set = true;
        pipe_config->port_clock = intel_dsi_bitrate(intel_dsi) / 5;
 
-       return true;
+       return 0;
 }
 
 static u64 gen11_dsi_get_power_domains(struct intel_encoder *encoder,
@@ -1229,13 +1239,15 @@ static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
-       u32 tmp;
-       enum port port;
        enum transcoder dsi_trans;
+       intel_wakeref_t wakeref;
+       enum port port;
        bool ret = false;
+       u32 tmp;
 
-       if (!intel_display_power_get_if_enabled(dev_priv,
-                                               encoder->power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    encoder->power_domain);
+       if (!wakeref)
                return false;
 
        for_each_dsi_port(port, intel_dsi->ports) {
@@ -1260,7 +1272,7 @@ static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
                ret = tmp & PIPECONF_ENABLE;
        }
 out:
-       intel_display_power_put(dev_priv, encoder->power_domain);
+       intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
        return ret;
 }
 
@@ -1378,6 +1390,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
        encoder->disable = gen11_dsi_disable;
        encoder->port = port;
        encoder->get_config = gen11_dsi_get_config;
+       encoder->update_pipe = intel_panel_update_backlight;
        encoder->compute_config = gen11_dsi_compute_config;
        encoder->get_hw_state = gen11_dsi_get_hw_state;
        encoder->type = INTEL_OUTPUT_DSI;
index 6ba478e57b9bc51f9cebab5f6e00ad442ea8c13a..9d142d038a7d3631ac927280e549528e86756db5 100644 (file)
@@ -6,7 +6,6 @@
  */
 #include <linux/pci.h>
 #include <linux/acpi.h>
-#include <drm/drmP.h>
 #include "i915_drv.h"
 
 #define INTEL_DSM_REVISION_ID 1 /* For Calpella anyway... */
index 8cb02f28d30cf6b12fe002c13c8bd9d17f9fa6f2..16263add3cdda4bf1ef90a1ed4f7d5adcfcacdcc 100644 (file)
@@ -29,7 +29,6 @@
  * See intel_atomic_plane.c for the plane-specific atomic functionality.
  */
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_plane_helper.h>
@@ -47,7 +46,7 @@
 int intel_digital_connector_atomic_get_property(struct drm_connector *connector,
                                                const struct drm_connector_state *state,
                                                struct drm_property *property,
-                                               uint64_t *val)
+                                               u64 *val)
 {
        struct drm_device *dev = connector->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -79,7 +78,7 @@ int intel_digital_connector_atomic_get_property(struct drm_connector *connector,
 int intel_digital_connector_atomic_set_property(struct drm_connector *connector,
                                                struct drm_connector_state *state,
                                                struct drm_property *property,
-                                               uint64_t val)
+                                               u64 val)
 {
        struct drm_device *dev = connector->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -233,7 +232,7 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta
        if (plane_state && plane_state->base.fb &&
            plane_state->base.fb->format->is_yuv &&
            plane_state->base.fb->format->num_planes > 1) {
-               if (IS_GEN9(dev_priv) &&
+               if (IS_GEN(dev_priv, 9) &&
                    !IS_GEMINILAKE(dev_priv)) {
                        mode = SKL_PS_SCALER_MODE_NV12;
                } else if (icl_is_hdr_plane(to_intel_plane(plane_state->base.plane))) {
index 0a73e6e65c2030b2f094c5a89f8248cb807a8020..9a2fdc77ebcbbab9bcbce736dafbd3440eea92f9 100644 (file)
@@ -31,7 +31,6 @@
  * prepare/check/commit/cleanup steps.
  */
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_plane_helper.h>
 #include "intel_drv.h"
@@ -312,7 +311,7 @@ int
 intel_plane_atomic_get_property(struct drm_plane *plane,
                                const struct drm_plane_state *state,
                                struct drm_property *property,
-                               uint64_t *val)
+                               u64 *val)
 {
        DRM_DEBUG_KMS("Unknown property [PROP:%d:%s]\n",
                      property->base.id, property->name);
@@ -335,7 +334,7 @@ int
 intel_plane_atomic_set_property(struct drm_plane *plane,
                                struct drm_plane_state *state,
                                struct drm_property *property,
-                               uint64_t val)
+                               u64 val)
 {
        DRM_DEBUG_KMS("Unknown property [PROP:%d:%s]\n",
                      property->base.id, property->name);
index ae55a6865d5cca98f8738cbf8db4cffe5039bfa2..de26cd0a54979672aadec40c1738e207da5a6afd 100644 (file)
@@ -27,7 +27,6 @@
 #include <drm/intel_lpe_audio.h>
 #include "intel_drv.h"
 
-#include <drm/drmP.h>
 #include <drm/drm_edid.h>
 #include "i915_drv.h"
 
@@ -749,7 +748,8 @@ static void i915_audio_component_get_power(struct device *kdev)
 
 static void i915_audio_component_put_power(struct device *kdev)
 {
-       intel_display_power_put(kdev_to_i915(kdev), POWER_DOMAIN_AUDIO);
+       intel_display_power_put_unchecked(kdev_to_i915(kdev),
+                                         POWER_DOMAIN_AUDIO);
 }
 
 static void i915_audio_component_codec_wake_override(struct device *kdev,
@@ -758,7 +758,7 @@ static void i915_audio_component_codec_wake_override(struct device *kdev,
        struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
        u32 tmp;
 
-       if (!IS_GEN9(dev_priv))
+       if (!IS_GEN(dev_priv, 9))
                return;
 
        i915_audio_component_get_power(kdev);
index 6d3e0260d49cda5b2d5ffa36152ef6eb544cc14e..561a4f9f044c03f27501a4abddb91006c26dc21d 100644 (file)
@@ -26,7 +26,6 @@
  */
 
 #include <drm/drm_dp_helper.h>
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 
@@ -453,7 +452,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, u8 bdb_version)
         * Only parse SDVO mappings on gens that could have SDVO. This isn't
         * accurate and doesn't have to be, as long as it's not too strict.
         */
-       if (!IS_GEN(dev_priv, 3, 7)) {
+       if (!IS_GEN_RANGE(dev_priv, 3, 7)) {
                DRM_DEBUG_KMS("Skipping SDVO device mapping\n");
                return;
        }
@@ -1386,8 +1385,15 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
        info->supports_dp = is_dp;
        info->supports_edp = is_edp;
 
-       DRM_DEBUG_KMS("Port %c VBT info: DP:%d HDMI:%d DVI:%d EDP:%d CRT:%d\n",
-                     port_name(port), is_dp, is_hdmi, is_dvi, is_edp, is_crt);
+       if (bdb_version >= 195)
+               info->supports_typec_usb = child->dp_usb_type_c;
+
+       if (bdb_version >= 209)
+               info->supports_tbt = child->tbt;
+
+       DRM_DEBUG_KMS("Port %c VBT info: DP:%d HDMI:%d DVI:%d EDP:%d CRT:%d TCUSB:%d TBT:%d\n",
+                     port_name(port), is_dp, is_hdmi, is_dvi, is_edp, is_crt,
+                     info->supports_typec_usb, info->supports_tbt);
 
        if (is_edp && is_dvi)
                DRM_DEBUG_KMS("Internal DP port %c is TMDS compatible\n",
@@ -1940,6 +1946,15 @@ bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port por
        };
        int i;
 
+       if (HAS_DDI(dev_priv)) {
+               const struct ddi_vbt_port_info *port_info =
+                       &dev_priv->vbt.ddi_port_info[port];
+
+               return port_info->supports_dp ||
+                      port_info->supports_dvi ||
+                      port_info->supports_hdmi;
+       }
+
        /* FIXME maybe deal with port A as well? */
        if (WARN_ON(port == PORT_A) || port >= ARRAY_SIZE(port_mapping))
                return false;
index 447c5256f63a9399f39f2439a558e3b88e4205ae..b58915b8708b27d2864e8ca1bea6eac9bb3f00e5 100644 (file)
@@ -158,36 +158,24 @@ static void intel_breadcrumbs_fake_irq(struct timer_list *t)
 
 static void irq_enable(struct intel_engine_cs *engine)
 {
-       /*
-        * FIXME: Ideally we want this on the API boundary, but for the
-        * sake of testing with mock breadcrumbs (no HW so unable to
-        * enable irqs) we place it deep within the bowels, at the point
-        * of no return.
-        */
-       GEM_BUG_ON(!intel_irqs_enabled(engine->i915));
-
-       /* Enabling the IRQ may miss the generation of the interrupt, but
-        * we still need to force the barrier before reading the seqno,
-        * just in case.
-        */
-       set_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted);
+       if (!engine->irq_enable)
+               return;
 
        /* Caller disables interrupts */
-       if (engine->irq_enable) {
-               spin_lock(&engine->i915->irq_lock);
-               engine->irq_enable(engine);
-               spin_unlock(&engine->i915->irq_lock);
-       }
+       spin_lock(&engine->i915->irq_lock);
+       engine->irq_enable(engine);
+       spin_unlock(&engine->i915->irq_lock);
 }
 
 static void irq_disable(struct intel_engine_cs *engine)
 {
+       if (!engine->irq_disable)
+               return;
+
        /* Caller disables interrupts */
-       if (engine->irq_disable) {
-               spin_lock(&engine->i915->irq_lock);
-               engine->irq_disable(engine);
-               spin_unlock(&engine->i915->irq_lock);
-       }
+       spin_lock(&engine->i915->irq_lock);
+       engine->irq_disable(engine);
+       spin_unlock(&engine->i915->irq_lock);
 }
 
 void __intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine)
@@ -299,25 +287,16 @@ static bool __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
        if (b->irq_armed)
                return false;
 
-       /* The breadcrumb irq will be disarmed on the interrupt after the
+       /*
+        * The breadcrumb irq will be disarmed on the interrupt after the
         * waiters are signaled. This gives us a single interrupt window in
         * which we can add a new waiter and avoid the cost of re-enabling
         * the irq.
         */
        b->irq_armed = true;
 
-       if (I915_SELFTEST_ONLY(b->mock)) {
-               /* For our mock objects we want to avoid interaction
-                * with the real hardware (which is not set up). So
-                * we simply pretend we have enabled the powerwell
-                * and the irq, and leave it up to the mock
-                * implementation to call intel_engine_wakeup()
-                * itself when it wants to simulate a user interrupt,
-                */
-               return true;
-       }
-
-       /* Since we are waiting on a request, the GPU should be busy
+       /*
+        * Since we are waiting on a request, the GPU should be busy
         * and should have its own rpm reference. This is tracked
         * by i915->gt.awake, we can forgo holding our own wakref
         * for the interrupt as before i915->gt.awake is released (when
@@ -652,8 +631,7 @@ static int intel_breadcrumbs_signaler(void *arg)
                                rq->signaling.wait.seqno = 0;
                                __list_del_entry(&rq->signaling.link);
 
-                               if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
-                                             &rq->fence.flags)) {
+                               if (!i915_request_signaled(rq)) {
                                        list_add_tail(&rq->signaling.link,
                                                      &list);
                                        i915_request_get(rq);
@@ -683,16 +661,6 @@ static int intel_breadcrumbs_signaler(void *arg)
                }
 
                if (unlikely(do_schedule)) {
-                       /* Before we sleep, check for a missed seqno */
-                       if (current->state & TASK_NORMAL &&
-                           !list_empty(&b->signals) &&
-                           engine->irq_seqno_barrier &&
-                           test_and_clear_bit(ENGINE_IRQ_BREADCRUMB,
-                                              &engine->irq_posted)) {
-                               engine->irq_seqno_barrier(engine);
-                               intel_engine_wakeup(engine);
-                       }
-
 sleep:
                        if (kthread_should_park())
                                kthread_parkme();
@@ -859,16 +827,6 @@ void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine)
        else
                irq_disable(engine);
 
-       /*
-        * We set the IRQ_BREADCRUMB bit when we enable the irq presuming the
-        * GPU is active and may have already executed the MI_USER_INTERRUPT
-        * before the CPU is ready to receive. However, the engine is currently
-        * idle (we haven't started it yet), there is no possibility for a
-        * missed interrupt as we enabled the irq and so we can clear the
-        * immediate wakeup (until a real interrupt arrives for the waiter).
-        */
-       clear_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted);
-
        spin_unlock_irqrestore(&b->irq_lock, flags);
 }
 
index 25e3aba9cded6e45f3751039a3f7bb20845dd7b8..15ba950dee00e789738e4362a7e3050ef9caf1d4 100644 (file)
@@ -218,7 +218,7 @@ static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
        };
        const unsigned int *vco_table;
        unsigned int vco;
-       uint8_t tmp = 0;
+       u8 tmp = 0;
 
        /* FIXME other chipsets? */
        if (IS_GM45(dev_priv))
@@ -249,13 +249,13 @@ static void g33_get_cdclk(struct drm_i915_private *dev_priv,
                          struct intel_cdclk_state *cdclk_state)
 {
        struct pci_dev *pdev = dev_priv->drm.pdev;
-       static const uint8_t div_3200[] = { 12, 10,  8,  7, 5, 16 };
-       static const uint8_t div_4000[] = { 14, 12, 10,  8, 6, 20 };
-       static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 };
-       static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 };
-       const uint8_t *div_table;
+       static const u8 div_3200[] = { 12, 10,  8,  7, 5, 16 };
+       static const u8 div_4000[] = { 14, 12, 10,  8, 6, 20 };
+       static const u8 div_4800[] = { 20, 14, 12, 10, 8, 24 };
+       static const u8 div_5333[] = { 20, 16, 12, 12, 8, 28 };
+       const u8 *div_table;
        unsigned int cdclk_sel;
-       uint16_t tmp = 0;
+       u16 tmp = 0;
 
        cdclk_state->vco = intel_hpll_vco(dev_priv);
 
@@ -330,12 +330,12 @@ static void i965gm_get_cdclk(struct drm_i915_private *dev_priv,
                             struct intel_cdclk_state *cdclk_state)
 {
        struct pci_dev *pdev = dev_priv->drm.pdev;
-       static const uint8_t div_3200[] = { 16, 10,  8 };
-       static const uint8_t div_4000[] = { 20, 12, 10 };
-       static const uint8_t div_5333[] = { 24, 16, 14 };
-       const uint8_t *div_table;
+       static const u8 div_3200[] = { 16, 10,  8 };
+       static const u8 div_4000[] = { 20, 12, 10 };
+       static const u8 div_5333[] = { 24, 16, 14 };
+       const u8 *div_table;
        unsigned int cdclk_sel;
-       uint16_t tmp = 0;
+       u16 tmp = 0;
 
        cdclk_state->vco = intel_hpll_vco(dev_priv);
 
@@ -375,7 +375,7 @@ static void gm45_get_cdclk(struct drm_i915_private *dev_priv,
 {
        struct pci_dev *pdev = dev_priv->drm.pdev;
        unsigned int cdclk_sel;
-       uint16_t tmp = 0;
+       u16 tmp = 0;
 
        cdclk_state->vco = intel_hpll_vco(dev_priv);
 
@@ -403,8 +403,8 @@ static void gm45_get_cdclk(struct drm_i915_private *dev_priv,
 static void hsw_get_cdclk(struct drm_i915_private *dev_priv,
                          struct intel_cdclk_state *cdclk_state)
 {
-       uint32_t lcpll = I915_READ(LCPLL_CTL);
-       uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
+       u32 lcpll = I915_READ(LCPLL_CTL);
+       u32 freq = lcpll & LCPLL_CLK_FREQ_MASK;
 
        if (lcpll & LCPLL_CD_SOURCE_FCLK)
                cdclk_state->cdclk = 800000;
@@ -520,6 +520,7 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv,
 {
        int cdclk = cdclk_state->cdclk;
        u32 val, cmd = cdclk_state->voltage_level;
+       intel_wakeref_t wakeref;
 
        switch (cdclk) {
        case 400000:
@@ -539,7 +540,7 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv,
         * a system suspend.  So grab the PIPE-A domain, which covers
         * the HW blocks needed for the following programming.
         */
-       intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
+       wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
 
        mutex_lock(&dev_priv->pcu_lock);
        val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
@@ -593,7 +594,7 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv,
 
        vlv_program_pfi_credits(dev_priv);
 
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A, wakeref);
 }
 
 static void chv_set_cdclk(struct drm_i915_private *dev_priv,
@@ -601,6 +602,7 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv,
 {
        int cdclk = cdclk_state->cdclk;
        u32 val, cmd = cdclk_state->voltage_level;
+       intel_wakeref_t wakeref;
 
        switch (cdclk) {
        case 333333:
@@ -619,7 +621,7 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv,
         * a system suspend.  So grab the PIPE-A domain, which covers
         * the HW blocks needed for the following programming.
         */
-       intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
+       wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
 
        mutex_lock(&dev_priv->pcu_lock);
        val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
@@ -637,7 +639,7 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv,
 
        vlv_program_pfi_credits(dev_priv);
 
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A, wakeref);
 }
 
 static int bdw_calc_cdclk(int min_cdclk)
@@ -670,8 +672,8 @@ static u8 bdw_calc_voltage_level(int cdclk)
 static void bdw_get_cdclk(struct drm_i915_private *dev_priv,
                          struct intel_cdclk_state *cdclk_state)
 {
-       uint32_t lcpll = I915_READ(LCPLL_CTL);
-       uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
+       u32 lcpll = I915_READ(LCPLL_CTL);
+       u32 freq = lcpll & LCPLL_CLK_FREQ_MASK;
 
        if (lcpll & LCPLL_CD_SOURCE_FCLK)
                cdclk_state->cdclk = 800000;
@@ -698,7 +700,7 @@ static void bdw_set_cdclk(struct drm_i915_private *dev_priv,
                          const struct intel_cdclk_state *cdclk_state)
 {
        int cdclk = cdclk_state->cdclk;
-       uint32_t val;
+       u32 val;
        int ret;
 
        if (WARN((I915_READ(LCPLL_CTL) &
@@ -1081,7 +1083,7 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv,
 
 static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
 {
-       uint32_t cdctl, expected;
+       u32 cdctl, expected;
 
        /*
         * check if the pre-os initialized the display
@@ -2140,7 +2142,7 @@ static int intel_pixel_rate_to_cdclk(struct drm_i915_private *dev_priv,
 {
        if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
                return DIV_ROUND_UP(pixel_rate, 2);
-       else if (IS_GEN9(dev_priv) ||
+       else if (IS_GEN(dev_priv, 9) ||
                 IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
                return pixel_rate;
        else if (IS_CHERRYVIEW(dev_priv))
@@ -2176,7 +2178,7 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
                if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv)) {
                        /* Display WA #1145: glk,cnl */
                        min_cdclk = max(316800, min_cdclk);
-               } else if (IS_GEN9(dev_priv) || IS_BROADWELL(dev_priv)) {
+               } else if (IS_GEN(dev_priv, 9) || IS_BROADWELL(dev_priv)) {
                        /* Display WA #1144: skl,bxt */
                        min_cdclk = max(432000, min_cdclk);
                }
@@ -2537,7 +2539,7 @@ static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
 
        if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
                return 2 * max_cdclk_freq;
-       else if (IS_GEN9(dev_priv) ||
+       else if (IS_GEN(dev_priv, 9) ||
                 IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
                return max_cdclk_freq;
        else if (IS_CHERRYVIEW(dev_priv))
@@ -2688,7 +2690,7 @@ static int vlv_hrawclk(struct drm_i915_private *dev_priv)
 
 static int g4x_hrawclk(struct drm_i915_private *dev_priv)
 {
-       uint32_t clkcfg;
+       u32 clkcfg;
 
        /* hrawclock is 1/4 the FSB frequency */
        clkcfg = I915_READ(CLKCFG);
@@ -2785,9 +2787,9 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
                dev_priv->display.get_cdclk = hsw_get_cdclk;
        else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                dev_priv->display.get_cdclk = vlv_get_cdclk;
-       else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
+       else if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
                dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
-       else if (IS_GEN5(dev_priv))
+       else if (IS_GEN(dev_priv, 5))
                dev_priv->display.get_cdclk = fixed_450mhz_get_cdclk;
        else if (IS_GM45(dev_priv))
                dev_priv->display.get_cdclk = gm45_get_cdclk;
index 5127da286a2b4f61ca5a32ce00220e01a9397f93..bc7589656a8f37b91c2b01122c4b0e5e7a5d4657 100644 (file)
 #define ILK_CSC_COEFF_1_0              \
        ((7 << 12) | ILK_CSC_COEFF_FP(CTM_COEFF_1_0, 8))
 
-static bool crtc_state_is_legacy_gamma(struct drm_crtc_state *state)
+static bool lut_is_legacy(struct drm_property_blob *lut)
 {
-       return !state->degamma_lut &&
-               !state->ctm &&
-               state->gamma_lut &&
-               drm_color_lut_size(state->gamma_lut) == LEGACY_LUT_LENGTH;
+       return drm_color_lut_size(lut) == LEGACY_LUT_LENGTH;
+}
+
+static bool crtc_state_is_legacy_gamma(struct intel_crtc_state *crtc_state)
+{
+       return !crtc_state->base.degamma_lut &&
+               !crtc_state->base.ctm &&
+               crtc_state->base.gamma_lut &&
+               lut_is_legacy(crtc_state->base.gamma_lut);
 }
 
 /*
@@ -108,10 +113,10 @@ static u64 *ctm_mult_by_limited(u64 *result, const u64 *input)
        return result;
 }
 
-static void ilk_load_ycbcr_conversion_matrix(struct intel_crtc *intel_crtc)
+static void ilk_load_ycbcr_conversion_matrix(struct intel_crtc *crtc)
 {
-       int pipe = intel_crtc->pipe;
-       struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+       int pipe = crtc->pipe;
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
        I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
        I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
@@ -132,14 +137,12 @@ static void ilk_load_ycbcr_conversion_matrix(struct intel_crtc *intel_crtc)
        I915_WRITE(PIPE_CSC_MODE(pipe), 0);
 }
 
-static void ilk_load_csc_matrix(struct drm_crtc_state *crtc_state)
+static void ilk_load_csc_matrix(struct intel_crtc_state *crtc_state)
 {
-       struct drm_crtc *crtc = crtc_state->crtc;
-       struct drm_i915_private *dev_priv = to_i915(crtc->dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int i, pipe = intel_crtc->pipe;
-       uint16_t coeffs[9] = { 0, };
-       struct intel_crtc_state *intel_crtc_state = to_intel_crtc_state(crtc_state);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       int i, pipe = crtc->pipe;
+       u16 coeffs[9] = { 0, };
        bool limited_color_range = false;
 
        /*
@@ -147,14 +150,14 @@ static void ilk_load_csc_matrix(struct drm_crtc_state *crtc_state)
         * do the range compression using the gamma LUT instead.
         */
        if (INTEL_GEN(dev_priv) >= 8 || IS_HASWELL(dev_priv))
-               limited_color_range = intel_crtc_state->limited_color_range;
+               limited_color_range = crtc_state->limited_color_range;
 
-       if (intel_crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
-           intel_crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444) {
-               ilk_load_ycbcr_conversion_matrix(intel_crtc);
+       if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
+           crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444) {
+               ilk_load_ycbcr_conversion_matrix(crtc);
                return;
-       } else if (crtc_state->ctm) {
-               struct drm_color_ctm *ctm = crtc_state->ctm->data;
+       } else if (crtc_state->base.ctm) {
+               struct drm_color_ctm *ctm = crtc_state->base.ctm->data;
                const u64 *input;
                u64 temp[9];
 
@@ -168,7 +171,7 @@ static void ilk_load_csc_matrix(struct drm_crtc_state *crtc_state)
                 * hardware.
                 */
                for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
-                       uint64_t abs_coeff = ((1ULL << 63) - 1) & input[i];
+                       u64 abs_coeff = ((1ULL << 63) - 1) & input[i];
 
                        /*
                         * Clamp input value to min/max supported by
@@ -230,7 +233,7 @@ static void ilk_load_csc_matrix(struct drm_crtc_state *crtc_state)
        I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
 
        if (INTEL_GEN(dev_priv) > 6) {
-               uint16_t postoff = 0;
+               u16 postoff = 0;
 
                if (limited_color_range)
                        postoff = (16 * (1 << 12) / 255) & 0x1fff;
@@ -241,7 +244,7 @@ static void ilk_load_csc_matrix(struct drm_crtc_state *crtc_state)
 
                I915_WRITE(PIPE_CSC_MODE(pipe), 0);
        } else {
-               uint32_t mode = CSC_MODE_YUV_TO_RGB;
+               u32 mode = CSC_MODE_YUV_TO_RGB;
 
                if (limited_color_range)
                        mode |= CSC_BLACK_SCREEN_OFFSET;
@@ -253,21 +256,20 @@ static void ilk_load_csc_matrix(struct drm_crtc_state *crtc_state)
 /*
  * Set up the pipe CSC unit on CherryView.
  */
-static void cherryview_load_csc_matrix(struct drm_crtc_state *state)
+static void cherryview_load_csc_matrix(struct intel_crtc_state *crtc_state)
 {
-       struct drm_crtc *crtc = state->crtc;
-       struct drm_device *dev = crtc->dev;
+       struct drm_device *dev = crtc_state->base.crtc->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       int pipe = to_intel_crtc(crtc)->pipe;
-       uint32_t mode;
+       int pipe = to_intel_crtc(crtc_state->base.crtc)->pipe;
+       u32 mode;
 
-       if (state->ctm) {
-               struct drm_color_ctm *ctm = state->ctm->data;
-               uint16_t coeffs[9] = { 0, };
+       if (crtc_state->base.ctm) {
+               struct drm_color_ctm *ctm = crtc_state->base.ctm->data;
+               u16 coeffs[9] = { 0, };
                int i;
 
                for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
-                       uint64_t abs_coeff =
+                       u64 abs_coeff =
                                ((1ULL << 63) - 1) & ctm->matrix[i];
 
                        /* Round coefficient. */
@@ -293,17 +295,17 @@ static void cherryview_load_csc_matrix(struct drm_crtc_state *state)
                I915_WRITE(CGM_PIPE_CSC_COEFF8(pipe), coeffs[8]);
        }
 
-       mode = (state->ctm ? CGM_PIPE_MODE_CSC : 0);
-       if (!crtc_state_is_legacy_gamma(state)) {
-               mode |= (state->degamma_lut ? CGM_PIPE_MODE_DEGAMMA : 0) |
-                       (state->gamma_lut ? CGM_PIPE_MODE_GAMMA : 0);
+       mode = (crtc_state->base.ctm ? CGM_PIPE_MODE_CSC : 0);
+       if (!crtc_state_is_legacy_gamma(crtc_state)) {
+               mode |= (crtc_state->base.degamma_lut ? CGM_PIPE_MODE_DEGAMMA : 0) |
+                       (crtc_state->base.gamma_lut ? CGM_PIPE_MODE_GAMMA : 0);
        }
        I915_WRITE(CGM_PIPE_MODE(pipe), mode);
 }
 
-void intel_color_set_csc(struct drm_crtc_state *crtc_state)
+void intel_color_set_csc(struct intel_crtc_state *crtc_state)
 {
-       struct drm_device *dev = crtc_state->crtc->dev;
+       struct drm_device *dev = crtc_state->base.crtc->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
 
        if (dev_priv->display.load_csc_matrix)
@@ -311,14 +313,12 @@ void intel_color_set_csc(struct drm_crtc_state *crtc_state)
 }
 
 /* Loads the legacy palette/gamma unit for the CRTC. */
-static void i9xx_load_luts_internal(struct drm_crtc *crtc,
-                                   struct drm_property_blob *blob,
-                                   struct intel_crtc_state *crtc_state)
+static void i9xx_load_luts_internal(struct intel_crtc_state *crtc_state,
+                                   struct drm_property_blob *blob)
 {
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       enum pipe pipe = intel_crtc->pipe;
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       enum pipe pipe = crtc->pipe;
        int i;
 
        if (HAS_GMCH_DISPLAY(dev_priv)) {
@@ -331,7 +331,7 @@ static void i9xx_load_luts_internal(struct drm_crtc *crtc,
        if (blob) {
                struct drm_color_lut *lut = blob->data;
                for (i = 0; i < 256; i++) {
-                       uint32_t word =
+                       u32 word =
                                (drm_color_lut_extract(lut[i].red, 8) << 16) |
                                (drm_color_lut_extract(lut[i].green, 8) << 8) |
                                drm_color_lut_extract(lut[i].blue, 8);
@@ -343,7 +343,7 @@ static void i9xx_load_luts_internal(struct drm_crtc *crtc,
                }
        } else {
                for (i = 0; i < 256; i++) {
-                       uint32_t word = (i << 16) | (i << 8) | i;
+                       u32 word = (i << 16) | (i << 8) | i;
 
                        if (HAS_GMCH_DISPLAY(dev_priv))
                                I915_WRITE(PALETTE(pipe, i), word);
@@ -353,56 +353,51 @@ static void i9xx_load_luts_internal(struct drm_crtc *crtc,
        }
 }
 
-static void i9xx_load_luts(struct drm_crtc_state *crtc_state)
+static void i9xx_load_luts(struct intel_crtc_state *crtc_state)
 {
-       i9xx_load_luts_internal(crtc_state->crtc, crtc_state->gamma_lut,
-                               to_intel_crtc_state(crtc_state));
+       i9xx_load_luts_internal(crtc_state, crtc_state->base.gamma_lut);
 }
 
 /* Loads the legacy palette/gamma unit for the CRTC on Haswell. */
-static void haswell_load_luts(struct drm_crtc_state *crtc_state)
+static void haswell_load_luts(struct intel_crtc_state *crtc_state)
 {
-       struct drm_crtc *crtc = crtc_state->crtc;
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct intel_crtc_state *intel_crtc_state =
-               to_intel_crtc_state(crtc_state);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        bool reenable_ips = false;
 
        /*
         * Workaround : Do not read or write the pipe palette/gamma data while
         * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
         */
-       if (IS_HASWELL(dev_priv) && intel_crtc_state->ips_enabled &&
-           (intel_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)) {
-               hsw_disable_ips(intel_crtc_state);
+       if (IS_HASWELL(dev_priv) && crtc_state->ips_enabled &&
+           (crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)) {
+               hsw_disable_ips(crtc_state);
                reenable_ips = true;
        }
 
-       intel_crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT;
-       I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT);
+       crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT;
+       I915_WRITE(GAMMA_MODE(crtc->pipe), GAMMA_MODE_MODE_8BIT);
 
        i9xx_load_luts(crtc_state);
 
        if (reenable_ips)
-               hsw_enable_ips(intel_crtc_state);
+               hsw_enable_ips(crtc_state);
 }
 
-static void bdw_load_degamma_lut(struct drm_crtc_state *state)
+static void bdw_load_degamma_lut(struct intel_crtc_state *crtc_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(state->crtc->dev);
-       enum pipe pipe = to_intel_crtc(state->crtc)->pipe;
-       uint32_t i, lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+       enum pipe pipe = to_intel_crtc(crtc_state->base.crtc)->pipe;
+       u32 i, lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
 
        I915_WRITE(PREC_PAL_INDEX(pipe),
                   PAL_PREC_SPLIT_MODE | PAL_PREC_AUTO_INCREMENT);
 
-       if (state->degamma_lut) {
-               struct drm_color_lut *lut = state->degamma_lut->data;
+       if (crtc_state->base.degamma_lut) {
+               struct drm_color_lut *lut = crtc_state->base.degamma_lut->data;
 
                for (i = 0; i < lut_size; i++) {
-                       uint32_t word =
+                       u32 word =
                        drm_color_lut_extract(lut[i].red, 10) << 20 |
                        drm_color_lut_extract(lut[i].green, 10) << 10 |
                        drm_color_lut_extract(lut[i].blue, 10);
@@ -411,7 +406,7 @@ static void bdw_load_degamma_lut(struct drm_crtc_state *state)
                }
        } else {
                for (i = 0; i < lut_size; i++) {
-                       uint32_t v = (i * ((1 << 10) - 1)) / (lut_size - 1);
+                       u32 v = (i * ((1 << 10) - 1)) / (lut_size - 1);
 
                        I915_WRITE(PREC_PAL_DATA(pipe),
                                   (v << 20) | (v << 10) | v);
@@ -419,11 +414,11 @@ static void bdw_load_degamma_lut(struct drm_crtc_state *state)
        }
 }
 
-static void bdw_load_gamma_lut(struct drm_crtc_state *state, u32 offset)
+static void bdw_load_gamma_lut(struct intel_crtc_state *crtc_state, u32 offset)
 {
-       struct drm_i915_private *dev_priv = to_i915(state->crtc->dev);
-       enum pipe pipe = to_intel_crtc(state->crtc)->pipe;
-       uint32_t i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+       enum pipe pipe = to_intel_crtc(crtc_state->base.crtc)->pipe;
+       u32 i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
 
        WARN_ON(offset & ~PAL_PREC_INDEX_VALUE_MASK);
 
@@ -432,11 +427,11 @@ static void bdw_load_gamma_lut(struct drm_crtc_state *state, u32 offset)
                   PAL_PREC_AUTO_INCREMENT |
                   offset);
 
-       if (state->gamma_lut) {
-               struct drm_color_lut *lut = state->gamma_lut->data;
+       if (crtc_state->base.gamma_lut) {
+               struct drm_color_lut *lut = crtc_state->base.gamma_lut->data;
 
                for (i = 0; i < lut_size; i++) {
-                       uint32_t word =
+                       u32 word =
                        (drm_color_lut_extract(lut[i].red, 10) << 20) |
                        (drm_color_lut_extract(lut[i].green, 10) << 10) |
                        drm_color_lut_extract(lut[i].blue, 10);
@@ -454,7 +449,7 @@ static void bdw_load_gamma_lut(struct drm_crtc_state *state, u32 offset)
                           drm_color_lut_extract(lut[i].blue, 16));
        } else {
                for (i = 0; i < lut_size; i++) {
-                       uint32_t v = (i * ((1 << 10) - 1)) / (lut_size - 1);
+                       u32 v = (i * ((1 << 10) - 1)) / (lut_size - 1);
 
                        I915_WRITE(PREC_PAL_DATA(pipe),
                                   (v << 20) | (v << 10) | v);
@@ -467,22 +462,21 @@ static void bdw_load_gamma_lut(struct drm_crtc_state *state, u32 offset)
 }
 
 /* Loads the palette/gamma unit for the CRTC on Broadwell+. */
-static void broadwell_load_luts(struct drm_crtc_state *state)
+static void broadwell_load_luts(struct intel_crtc_state *crtc_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(state->crtc->dev);
-       struct intel_crtc_state *intel_state = to_intel_crtc_state(state);
-       enum pipe pipe = to_intel_crtc(state->crtc)->pipe;
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+       enum pipe pipe = to_intel_crtc(crtc_state->base.crtc)->pipe;
 
-       if (crtc_state_is_legacy_gamma(state)) {
-               haswell_load_luts(state);
+       if (crtc_state_is_legacy_gamma(crtc_state)) {
+               haswell_load_luts(crtc_state);
                return;
        }
 
-       bdw_load_degamma_lut(state);
-       bdw_load_gamma_lut(state,
+       bdw_load_degamma_lut(crtc_state);
+       bdw_load_gamma_lut(crtc_state,
                           INTEL_INFO(dev_priv)->color.degamma_lut_size);
 
-       intel_state->gamma_mode = GAMMA_MODE_MODE_SPLIT;
+       crtc_state->gamma_mode = GAMMA_MODE_MODE_SPLIT;
        I915_WRITE(GAMMA_MODE(pipe), GAMMA_MODE_MODE_SPLIT);
        POSTING_READ(GAMMA_MODE(pipe));
 
@@ -493,12 +487,12 @@ static void broadwell_load_luts(struct drm_crtc_state *state)
        I915_WRITE(PREC_PAL_INDEX(pipe), 0);
 }
 
-static void glk_load_degamma_lut(struct drm_crtc_state *state)
+static void glk_load_degamma_lut(struct intel_crtc_state *crtc_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(state->crtc->dev);
-       enum pipe pipe = to_intel_crtc(state->crtc)->pipe;
-       const uint32_t lut_size = 33;
-       uint32_t i;
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+       enum pipe pipe = to_intel_crtc(crtc_state->base.crtc)->pipe;
+       const u32 lut_size = 33;
+       u32 i;
 
        /*
         * When setting the auto-increment bit, the hardware seems to
@@ -513,7 +507,7 @@ static void glk_load_degamma_lut(struct drm_crtc_state *state)
         *  different values per channel, so this just loads a linear table.
         */
        for (i = 0; i < lut_size; i++) {
-               uint32_t v = (i * (1 << 16)) / (lut_size - 1);
+               u32 v = (i * (1 << 16)) / (lut_size - 1);
 
                I915_WRITE(PRE_CSC_GAMC_DATA(pipe), v);
        }
@@ -523,49 +517,46 @@ static void glk_load_degamma_lut(struct drm_crtc_state *state)
                I915_WRITE(PRE_CSC_GAMC_DATA(pipe), (1 << 16));
 }
 
-static void glk_load_luts(struct drm_crtc_state *state)
+static void glk_load_luts(struct intel_crtc_state *crtc_state)
 {
-       struct drm_crtc *crtc = state->crtc;
-       struct drm_device *dev = crtc->dev;
+       struct drm_device *dev = crtc_state->base.crtc->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc_state *intel_state = to_intel_crtc_state(state);
-       enum pipe pipe = to_intel_crtc(crtc)->pipe;
+       enum pipe pipe = to_intel_crtc(crtc_state->base.crtc)->pipe;
 
-       glk_load_degamma_lut(state);
+       glk_load_degamma_lut(crtc_state);
 
-       if (crtc_state_is_legacy_gamma(state)) {
-               haswell_load_luts(state);
+       if (crtc_state_is_legacy_gamma(crtc_state)) {
+               haswell_load_luts(crtc_state);
                return;
        }
 
-       bdw_load_gamma_lut(state, 0);
+       bdw_load_gamma_lut(crtc_state, 0);
 
-       intel_state->gamma_mode = GAMMA_MODE_MODE_10BIT;
+       crtc_state->gamma_mode = GAMMA_MODE_MODE_10BIT;
        I915_WRITE(GAMMA_MODE(pipe), GAMMA_MODE_MODE_10BIT);
        POSTING_READ(GAMMA_MODE(pipe));
 }
 
 /* Loads the palette/gamma unit for the CRTC on CherryView. */
-static void cherryview_load_luts(struct drm_crtc_state *state)
+static void cherryview_load_luts(struct intel_crtc_state *crtc_state)
 {
-       struct drm_crtc *crtc = state->crtc;
+       struct drm_crtc *crtc = crtc_state->base.crtc;
        struct drm_i915_private *dev_priv = to_i915(crtc->dev);
        enum pipe pipe = to_intel_crtc(crtc)->pipe;
        struct drm_color_lut *lut;
-       uint32_t i, lut_size;
-       uint32_t word0, word1;
+       u32 i, lut_size;
+       u32 word0, word1;
 
-       if (crtc_state_is_legacy_gamma(state)) {
+       if (crtc_state_is_legacy_gamma(crtc_state)) {
                /* Turn off degamma/gamma on CGM block. */
                I915_WRITE(CGM_PIPE_MODE(pipe),
-                          (state->ctm ? CGM_PIPE_MODE_CSC : 0));
-               i9xx_load_luts_internal(crtc, state->gamma_lut,
-                                       to_intel_crtc_state(state));
+                          (crtc_state->base.ctm ? CGM_PIPE_MODE_CSC : 0));
+               i9xx_load_luts_internal(crtc_state, crtc_state->base.gamma_lut);
                return;
        }
 
-       if (state->degamma_lut) {
-               lut = state->degamma_lut->data;
+       if (crtc_state->base.degamma_lut) {
+               lut = crtc_state->base.degamma_lut->data;
                lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
                for (i = 0; i < lut_size; i++) {
                        /* Write LUT in U0.14 format. */
@@ -579,8 +570,8 @@ static void cherryview_load_luts(struct drm_crtc_state *state)
                }
        }
 
-       if (state->gamma_lut) {
-               lut = state->gamma_lut->data;
+       if (crtc_state->base.gamma_lut) {
+               lut = crtc_state->base.gamma_lut->data;
                lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
                for (i = 0; i < lut_size; i++) {
                        /* Write LUT in U0.10 format. */
@@ -595,42 +586,57 @@ static void cherryview_load_luts(struct drm_crtc_state *state)
        }
 
        I915_WRITE(CGM_PIPE_MODE(pipe),
-                  (state->ctm ? CGM_PIPE_MODE_CSC : 0) |
-                  (state->degamma_lut ? CGM_PIPE_MODE_DEGAMMA : 0) |
-                  (state->gamma_lut ? CGM_PIPE_MODE_GAMMA : 0));
+                  (crtc_state->base.ctm ? CGM_PIPE_MODE_CSC : 0) |
+                  (crtc_state->base.degamma_lut ? CGM_PIPE_MODE_DEGAMMA : 0) |
+                  (crtc_state->base.gamma_lut ? CGM_PIPE_MODE_GAMMA : 0));
 
        /*
         * Also program a linear LUT in the legacy block (behind the
         * CGM block).
         */
-       i9xx_load_luts_internal(crtc, NULL, to_intel_crtc_state(state));
+       i9xx_load_luts_internal(crtc_state, NULL);
 }
 
-void intel_color_load_luts(struct drm_crtc_state *crtc_state)
+void intel_color_load_luts(struct intel_crtc_state *crtc_state)
 {
-       struct drm_device *dev = crtc_state->crtc->dev;
+       struct drm_device *dev = crtc_state->base.crtc->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
 
        dev_priv->display.load_luts(crtc_state);
 }
 
-int intel_color_check(struct drm_crtc *crtc,
-                     struct drm_crtc_state *crtc_state)
+int intel_color_check(struct intel_crtc_state *crtc_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
        size_t gamma_length, degamma_length;
+       uint32_t tests = DRM_COLOR_LUT_NON_DECREASING;
 
        degamma_length = INTEL_INFO(dev_priv)->color.degamma_lut_size;
        gamma_length = INTEL_INFO(dev_priv)->color.gamma_lut_size;
 
+       /*
+        * All of our platforms mandate that the degamma curve be
+        * non-decreasing.  Additionally, GLK and gen11 only accept a single
+        * value for red, green, and blue in the degamma table.  Make sure
+        * userspace didn't try to pass us something we can't handle.
+        *
+        * We don't have any extra hardware constraints on the gamma table,
+        * so no need to explicitly check it.
+        */
+       if (IS_GEMINILAKE(dev_priv) || INTEL_GEN(dev_priv) >= 10)
+               tests |= DRM_COLOR_LUT_EQUAL_CHANNELS;
+
+       if (drm_color_lut_check(crtc_state->base.degamma_lut, tests) != 0)
+               return -EINVAL;
+
        /*
         * We allow both degamma & gamma luts at the right size or
         * NULL.
         */
-       if ((!crtc_state->degamma_lut ||
-            drm_color_lut_size(crtc_state->degamma_lut) == degamma_length) &&
-           (!crtc_state->gamma_lut ||
-            drm_color_lut_size(crtc_state->gamma_lut) == gamma_length))
+       if ((!crtc_state->base.degamma_lut ||
+            drm_color_lut_size(crtc_state->base.degamma_lut) == degamma_length) &&
+           (!crtc_state->base.gamma_lut ||
+            drm_color_lut_size(crtc_state->base.gamma_lut) == gamma_length))
                return 0;
 
        /*
@@ -643,11 +649,11 @@ int intel_color_check(struct drm_crtc *crtc,
        return -EINVAL;
 }
 
-void intel_color_init(struct drm_crtc *crtc)
+void intel_color_init(struct intel_crtc *crtc)
 {
-       struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
-       drm_mode_crtc_set_gamma_size(crtc, 256);
+       drm_mode_crtc_set_gamma_size(&crtc->base, 256);
 
        if (IS_CHERRYVIEW(dev_priv)) {
                dev_priv->display.load_csc_matrix = cherryview_load_csc_matrix;
@@ -669,7 +675,7 @@ void intel_color_init(struct drm_crtc *crtc)
        /* Enable color management support when we have degamma & gamma LUTs. */
        if (INTEL_INFO(dev_priv)->color.degamma_lut_size != 0 &&
            INTEL_INFO(dev_priv)->color.gamma_lut_size != 0)
-               drm_crtc_enable_color_mgmt(crtc,
+               drm_crtc_enable_color_mgmt(&crtc->base,
                                           INTEL_INFO(dev_priv)->color.degamma_lut_size,
                                           true,
                                           INTEL_INFO(dev_priv)->color.gamma_lut_size);
index 18e370f607bcc2e50105c5854b70d61611c22709..ee16758747c5d1af85d3251442993edf85eb0685 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/i2c.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_edid.h>
-#include <drm/drmP.h>
 #include "intel_drv.h"
 #include "i915_drv.h"
 
@@ -95,6 +94,10 @@ void intel_connector_destroy(struct drm_connector *connector)
        intel_panel_fini(&intel_connector->panel);
 
        drm_connector_cleanup(connector);
+
+       if (intel_connector->port)
+               drm_dp_mst_put_port_malloc(intel_connector->port);
+
        kfree(connector);
 }
 
index 68f2fb89ece3fa259bfb2da593a7a66c68c81021..c2e799a5e63e29669099bba37de81e19f62b723b 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/dmi.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
@@ -84,15 +83,17 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_crt *crt = intel_encoder_to_crt(encoder);
+       intel_wakeref_t wakeref;
        bool ret;
 
-       if (!intel_display_power_get_if_enabled(dev_priv,
-                                               encoder->power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    encoder->power_domain);
+       if (!wakeref)
                return false;
 
        ret = intel_crt_port_enabled(dev_priv, crt->adpa_reg, pipe);
 
-       intel_display_power_put(dev_priv, encoder->power_domain);
+       intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
 
        return ret;
 }
@@ -322,7 +323,7 @@ intel_crt_mode_valid(struct drm_connector *connector,
                 * DAC limit supposedly 355 MHz.
                 */
                max_clock = 270000;
-       else if (IS_GEN3(dev_priv) || IS_GEN4(dev_priv))
+       else if (IS_GEN_RANGE(dev_priv, 3, 4))
                max_clock = 400000;
        else
                max_clock = 350000;
@@ -344,51 +345,52 @@ intel_crt_mode_valid(struct drm_connector *connector,
        return MODE_OK;
 }
 
-static bool intel_crt_compute_config(struct intel_encoder *encoder,
-                                    struct intel_crtc_state *pipe_config,
-                                    struct drm_connector_state *conn_state)
+static int intel_crt_compute_config(struct intel_encoder *encoder,
+                                   struct intel_crtc_state *pipe_config,
+                                   struct drm_connector_state *conn_state)
 {
        struct drm_display_mode *adjusted_mode =
                &pipe_config->base.adjusted_mode;
 
        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
-               return false;
+               return -EINVAL;
 
        pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
-       return true;
+
+       return 0;
 }
 
-static bool pch_crt_compute_config(struct intel_encoder *encoder,
-                                  struct intel_crtc_state *pipe_config,
-                                  struct drm_connector_state *conn_state)
+static int pch_crt_compute_config(struct intel_encoder *encoder,
+                                 struct intel_crtc_state *pipe_config,
+                                 struct drm_connector_state *conn_state)
 {
        struct drm_display_mode *adjusted_mode =
                &pipe_config->base.adjusted_mode;
 
        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
-               return false;
+               return -EINVAL;
 
        pipe_config->has_pch_encoder = true;
        pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
 
-       return true;
+       return 0;
 }
 
-static bool hsw_crt_compute_config(struct intel_encoder *encoder,
-                                  struct intel_crtc_state *pipe_config,
-                                  struct drm_connector_state *conn_state)
+static int hsw_crt_compute_config(struct intel_encoder *encoder,
+                                 struct intel_crtc_state *pipe_config,
+                                 struct drm_connector_state *conn_state)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct drm_display_mode *adjusted_mode =
                &pipe_config->base.adjusted_mode;
 
        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
-               return false;
+               return -EINVAL;
 
        /* HSW/BDW FDI limited to 4k */
        if (adjusted_mode->crtc_hdisplay > 4096 ||
            adjusted_mode->crtc_hblank_start > 4096)
-               return false;
+               return -EINVAL;
 
        pipe_config->has_pch_encoder = true;
        pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
@@ -397,7 +399,7 @@ static bool hsw_crt_compute_config(struct intel_encoder *encoder,
        if (HAS_PCH_LPT(dev_priv)) {
                if (pipe_config->bw_constrained && pipe_config->pipe_bpp < 24) {
                        DRM_DEBUG_KMS("LPT only supports 24bpp\n");
-                       return false;
+                       return -EINVAL;
                }
 
                pipe_config->pipe_bpp = 24;
@@ -406,7 +408,7 @@ static bool hsw_crt_compute_config(struct intel_encoder *encoder,
        /* FDI must always be 2.7 GHz */
        pipe_config->port_clock = 135000 * 2;
 
-       return true;
+       return 0;
 }
 
 static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
@@ -629,19 +631,19 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
 }
 
 static enum drm_connector_status
-intel_crt_load_detect(struct intel_crt *crt, uint32_t pipe)
+intel_crt_load_detect(struct intel_crt *crt, u32 pipe)
 {
        struct drm_device *dev = crt->base.base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       uint32_t save_bclrpat;
-       uint32_t save_vtotal;
-       uint32_t vtotal, vactive;
-       uint32_t vsample;
-       uint32_t vblank, vblank_start, vblank_end;
-       uint32_t dsl;
+       u32 save_bclrpat;
+       u32 save_vtotal;
+       u32 vtotal, vactive;
+       u32 vsample;
+       u32 vblank, vblank_start, vblank_end;
+       u32 dsl;
        i915_reg_t bclrpat_reg, vtotal_reg,
                vblank_reg, vsync_reg, pipeconf_reg, pipe_dsl_reg;
-       uint8_t st00;
+       u8 st00;
        enum drm_connector_status status;
 
        DRM_DEBUG_KMS("starting load-detect on CRT\n");
@@ -666,8 +668,8 @@ intel_crt_load_detect(struct intel_crt *crt, uint32_t pipe)
        /* Set the border color to purple. */
        I915_WRITE(bclrpat_reg, 0x500050);
 
-       if (!IS_GEN2(dev_priv)) {
-               uint32_t pipeconf = I915_READ(pipeconf_reg);
+       if (!IS_GEN(dev_priv, 2)) {
+               u32 pipeconf = I915_READ(pipeconf_reg);
                I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER);
                POSTING_READ(pipeconf_reg);
                /* Wait for next Vblank to substitue
@@ -688,8 +690,8 @@ intel_crt_load_detect(struct intel_crt *crt, uint32_t pipe)
                * Yes, this will flicker
                */
                if (vblank_start <= vactive && vblank_end >= vtotal) {
-                       uint32_t vsync = I915_READ(vsync_reg);
-                       uint32_t vsync_start = (vsync & 0xffff) + 1;
+                       u32 vsync = I915_READ(vsync_reg);
+                       u32 vsync_start = (vsync & 0xffff) + 1;
 
                        vblank_start = vsync_start;
                        I915_WRITE(vblank_reg,
@@ -777,6 +779,7 @@ intel_crt_detect(struct drm_connector *connector,
        struct drm_i915_private *dev_priv = to_i915(connector->dev);
        struct intel_crt *crt = intel_attached_crt(connector);
        struct intel_encoder *intel_encoder = &crt->base;
+       intel_wakeref_t wakeref;
        int status, ret;
        struct intel_load_detect_pipe tmp;
 
@@ -785,7 +788,8 @@ intel_crt_detect(struct drm_connector *connector,
                      force);
 
        if (i915_modparams.load_detect_test) {
-               intel_display_power_get(dev_priv, intel_encoder->power_domain);
+               wakeref = intel_display_power_get(dev_priv,
+                                                 intel_encoder->power_domain);
                goto load_detect;
        }
 
@@ -793,7 +797,8 @@ intel_crt_detect(struct drm_connector *connector,
        if (dmi_check_system(intel_spurious_crt_detect))
                return connector_status_disconnected;
 
-       intel_display_power_get(dev_priv, intel_encoder->power_domain);
+       wakeref = intel_display_power_get(dev_priv,
+                                         intel_encoder->power_domain);
 
        if (I915_HAS_HOTPLUG(dev_priv)) {
                /* We can not rely on the HPD pin always being correctly wired
@@ -848,7 +853,7 @@ load_detect:
        }
 
 out:
-       intel_display_power_put(dev_priv, intel_encoder->power_domain);
+       intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
        return status;
 }
 
@@ -858,10 +863,12 @@ static int intel_crt_get_modes(struct drm_connector *connector)
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct intel_crt *crt = intel_attached_crt(connector);
        struct intel_encoder *intel_encoder = &crt->base;
-       int ret;
+       intel_wakeref_t wakeref;
        struct i2c_adapter *i2c;
+       int ret;
 
-       intel_display_power_get(dev_priv, intel_encoder->power_domain);
+       wakeref = intel_display_power_get(dev_priv,
+                                         intel_encoder->power_domain);
 
        i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin);
        ret = intel_crt_ddc_get_modes(connector, i2c);
@@ -873,7 +880,7 @@ static int intel_crt_get_modes(struct drm_connector *connector)
        ret = intel_crt_ddc_get_modes(connector, i2c);
 
 out:
-       intel_display_power_put(dev_priv, intel_encoder->power_domain);
+       intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
 
        return ret;
 }
@@ -981,7 +988,7 @@ void intel_crt_init(struct drm_i915_private *dev_priv)
        else
                crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 
-       if (IS_GEN2(dev_priv))
+       if (IS_GEN(dev_priv, 2))
                connector->interlace_allowed = 0;
        else
                connector->interlace_allowed = 1;
index a516697bf57dfc8d63434b95d3f15aaaff748c21..e8ac04c33e290738cf1e54edf1d4c0ddb1b234dc 100644 (file)
@@ -70,50 +70,50 @@ MODULE_FIRMWARE(BXT_CSR_PATH);
 
 struct intel_css_header {
        /* 0x09 for DMC */
-       uint32_t module_type;
+       u32 module_type;
 
        /* Includes the DMC specific header in dwords */
-       uint32_t header_len;
+       u32 header_len;
 
        /* always value would be 0x10000 */
-       uint32_t header_ver;
+       u32 header_ver;
 
        /* Not used */
-       uint32_t module_id;
+       u32 module_id;
 
        /* Not used */
-       uint32_t module_vendor;
+       u32 module_vendor;
 
        /* in YYYYMMDD format */
-       uint32_t date;
+       u32 date;
 
        /* Size in dwords (CSS_Headerlen + PackageHeaderLen + dmc FWsLen)/4 */
-       uint32_t size;
+       u32 size;
 
        /* Not used */
-       uint32_t key_size;
+       u32 key_size;
 
        /* Not used */
-       uint32_t modulus_size;
+       u32 modulus_size;
 
        /* Not used */
-       uint32_t exponent_size;
+       u32 exponent_size;
 
        /* Not used */
-       uint32_t reserved1[12];
+       u32 reserved1[12];
 
        /* Major Minor */
-       uint32_t version;
+       u32 version;
 
        /* Not used */
-       uint32_t reserved2[8];
+       u32 reserved2[8];
 
        /* Not used */
-       uint32_t kernel_header_info;
+       u32 kernel_header_info;
 } __packed;
 
 struct intel_fw_info {
-       uint16_t reserved1;
+       u16 reserved1;
 
        /* Stepping (A, B, C, ..., *). * is a wildcard */
        char stepping;
@@ -121,8 +121,8 @@ struct intel_fw_info {
        /* Sub-stepping (0, 1, ..., *). * is a wildcard */
        char substepping;
 
-       uint32_t offset;
-       uint32_t reserved2;
+       u32 offset;
+       u32 reserved2;
 } __packed;
 
 struct intel_package_header {
@@ -135,14 +135,14 @@ struct intel_package_header {
        unsigned char reserved[10];
 
        /* Number of valid entries in the FWInfo array below */
-       uint32_t num_entries;
+       u32 num_entries;
 
        struct intel_fw_info fw_info[20];
 } __packed;
 
 struct intel_dmc_header {
        /* always value would be 0x40403E3E */
-       uint32_t signature;
+       u32 signature;
 
        /* DMC binary header length */
        unsigned char header_len;
@@ -151,30 +151,30 @@ struct intel_dmc_header {
        unsigned char header_ver;
 
        /* Reserved */
-       uint16_t dmcc_ver;
+       u16 dmcc_ver;
 
        /* Major, Minor */
-       uint32_t        project;
+       u32 project;
 
        /* Firmware program size (excluding header) in dwords */
-       uint32_t        fw_size;
+       u32 fw_size;
 
        /* Major Minor version */
-       uint32_t fw_version;
+       u32 fw_version;
 
        /* Number of valid MMIO cycles present. */
-       uint32_t mmio_count;
+       u32 mmio_count;
 
        /* MMIO address */
-       uint32_t mmioaddr[8];
+       u32 mmioaddr[8];
 
        /* MMIO data */
-       uint32_t mmiodata[8];
+       u32 mmiodata[8];
 
        /* FW filename  */
        unsigned char dfile[32];
 
-       uint32_t reserved1[2];
+       u32 reserved1[2];
 } __packed;
 
 struct stepping_info {
@@ -230,7 +230,7 @@ intel_get_stepping_info(struct drm_i915_private *dev_priv)
 
 static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv)
 {
-       uint32_t val, mask;
+       u32 val, mask;
 
        mask = DC_STATE_DEBUG_MASK_MEMORY_UP;
 
@@ -257,7 +257,7 @@ static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv)
 void intel_csr_load_program(struct drm_i915_private *dev_priv)
 {
        u32 *payload = dev_priv->csr.dmc_payload;
-       uint32_t i, fw_size;
+       u32 i, fw_size;
 
        if (!HAS_CSR(dev_priv)) {
                DRM_ERROR("No CSR support available for this platform\n");
@@ -289,17 +289,17 @@ void intel_csr_load_program(struct drm_i915_private *dev_priv)
        gen9_set_dc_state_debugmask(dev_priv);
 }
 
-static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
-                             const struct firmware *fw)
+static u32 *parse_csr_fw(struct drm_i915_private *dev_priv,
+                        const struct firmware *fw)
 {
        struct intel_css_header *css_header;
        struct intel_package_header *package_header;
        struct intel_dmc_header *dmc_header;
        struct intel_csr *csr = &dev_priv->csr;
        const struct stepping_info *si = intel_get_stepping_info(dev_priv);
-       uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
-       uint32_t i;
-       uint32_t *dmc_payload;
+       u32 dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
+       u32 i;
+       u32 *dmc_payload;
 
        if (!fw)
                return NULL;
@@ -409,6 +409,21 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
        return memcpy(dmc_payload, &fw->data[readcount], nbytes);
 }
 
+static void intel_csr_runtime_pm_get(struct drm_i915_private *dev_priv)
+{
+       WARN_ON(dev_priv->csr.wakeref);
+       dev_priv->csr.wakeref =
+               intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+}
+
+static void intel_csr_runtime_pm_put(struct drm_i915_private *dev_priv)
+{
+       intel_wakeref_t wakeref __maybe_unused =
+               fetch_and_zero(&dev_priv->csr.wakeref);
+
+       intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
+}
+
 static void csr_load_work_fn(struct work_struct *work)
 {
        struct drm_i915_private *dev_priv;
@@ -424,8 +439,7 @@ static void csr_load_work_fn(struct work_struct *work)
 
        if (dev_priv->csr.dmc_payload) {
                intel_csr_load_program(dev_priv);
-
-               intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+               intel_csr_runtime_pm_put(dev_priv);
 
                DRM_INFO("Finished loading DMC firmware %s (v%u.%u)\n",
                         dev_priv->csr.fw_path,
@@ -467,7 +481,7 @@ void intel_csr_ucode_init(struct drm_i915_private *dev_priv)
         * suspend as runtime suspend *requires* a working CSR for whatever
         * reason.
         */
-       intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+       intel_csr_runtime_pm_get(dev_priv);
 
        if (INTEL_GEN(dev_priv) >= 12) {
                /* Allow to load fw via parameter using the last known size */
@@ -538,7 +552,7 @@ void intel_csr_ucode_suspend(struct drm_i915_private *dev_priv)
 
        /* Drop the reference held in case DMC isn't loaded. */
        if (!dev_priv->csr.dmc_payload)
-               intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+               intel_csr_runtime_pm_put(dev_priv);
 }
 
 /**
@@ -558,7 +572,7 @@ void intel_csr_ucode_resume(struct drm_i915_private *dev_priv)
         * loaded.
         */
        if (!dev_priv->csr.dmc_payload)
-               intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+               intel_csr_runtime_pm_get(dev_priv);
 }
 
 /**
@@ -574,6 +588,7 @@ void intel_csr_ucode_fini(struct drm_i915_private *dev_priv)
                return;
 
        intel_csr_ucode_suspend(dev_priv);
+       WARN_ON(dev_priv->csr.wakeref);
 
        kfree(dev_priv->csr.dmc_payload);
 }
index f3e1d6a0b7dda7cabb0cc882e40aecbd83a1501c..acd94354afc86b5d23f649deb2545588078e5fe0 100644 (file)
@@ -494,103 +494,58 @@ static const struct cnl_ddi_buf_trans cnl_ddi_translations_edp_1_05V[] = {
        { 0x2, 0x7F, 0x3F, 0x00, 0x00 },        /* 400   400      0.0   */
 };
 
-struct icl_combo_phy_ddi_buf_trans {
-       u32 dw2_swing_select;
-       u32 dw2_swing_scalar;
-       u32 dw4_scaling;
-};
-
-/* Voltage Swing Programming for VccIO 0.85V for DP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_85V[] = {
-                               /* Voltage mV  db    */
-       { 0x2, 0x98, 0x0018 },  /* 400         0.0   */
-       { 0x2, 0x98, 0x3015 },  /* 400         3.5   */
-       { 0x2, 0x98, 0x6012 },  /* 400         6.0   */
-       { 0x2, 0x98, 0x900F },  /* 400         9.5   */
-       { 0xB, 0x70, 0x0018 },  /* 600         0.0   */
-       { 0xB, 0x70, 0x3015 },  /* 600         3.5   */
-       { 0xB, 0x70, 0x6012 },  /* 600         6.0   */
-       { 0x5, 0x00, 0x0018 },  /* 800         0.0   */
-       { 0x5, 0x00, 0x3015 },  /* 800         3.5   */
-       { 0x6, 0x98, 0x0018 },  /* 1200        0.0   */
-};
-
-/* FIXME - After table is updated in Bspec */
-/* Voltage Swing Programming for VccIO 0.85V for eDP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_85V[] = {
-                               /* Voltage mV  db    */
-       { 0x0, 0x00, 0x00 },    /* 200         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 200         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         6.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 250         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 350         0.0   */
-};
-
-/* Voltage Swing Programming for VccIO 0.95V for DP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_95V[] = {
-                               /* Voltage mV  db    */
-       { 0x2, 0x98, 0x0018 },  /* 400         0.0   */
-       { 0x2, 0x98, 0x3015 },  /* 400         3.5   */
-       { 0x2, 0x98, 0x6012 },  /* 400         6.0   */
-       { 0x2, 0x98, 0x900F },  /* 400         9.5   */
-       { 0x4, 0x98, 0x0018 },  /* 600         0.0   */
-       { 0x4, 0x98, 0x3015 },  /* 600         3.5   */
-       { 0x4, 0x98, 0x6012 },  /* 600         6.0   */
-       { 0x5, 0x76, 0x0018 },  /* 800         0.0   */
-       { 0x5, 0x76, 0x3015 },  /* 800         3.5   */
-       { 0x6, 0x98, 0x0018 },  /* 1200        0.0   */
+/* icl_combo_phy_ddi_translations */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hbr2[] = {
+                                               /* NT mV Trans mV db    */
+       { 0xA, 0x35, 0x3F, 0x00, 0x00 },        /* 350   350      0.0   */
+       { 0xA, 0x4F, 0x37, 0x00, 0x08 },        /* 350   500      3.1   */
+       { 0xC, 0x71, 0x2F, 0x00, 0x10 },        /* 350   700      6.0   */
+       { 0x6, 0x7F, 0x2B, 0x00, 0x14 },        /* 350   900      8.2   */
+       { 0xA, 0x4C, 0x3F, 0x00, 0x00 },        /* 500   500      0.0   */
+       { 0xC, 0x73, 0x34, 0x00, 0x0B },        /* 500   700      2.9   */
+       { 0x6, 0x7F, 0x2F, 0x00, 0x10 },        /* 500   900      5.1   */
+       { 0xC, 0x6C, 0x3C, 0x00, 0x03 },        /* 650   700      0.6   */
+       { 0x6, 0x7F, 0x35, 0x00, 0x0A },        /* 600   900      3.5   */
+       { 0x6, 0x7F, 0x3F, 0x00, 0x00 },        /* 900   900      0.0   */
 };
 
-/* FIXME - After table is updated in Bspec */
-/* Voltage Swing Programming for VccIO 0.95V for eDP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_95V[] = {
-                               /* Voltage mV  db    */
-       { 0x0, 0x00, 0x00 },    /* 200         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 200         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         6.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 250         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 350         0.0   */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr2[] = {
+                                               /* NT mV Trans mV db    */
+       { 0x0, 0x7F, 0x3F, 0x00, 0x00 },        /* 200   200      0.0   */
+       { 0x8, 0x7F, 0x38, 0x00, 0x07 },        /* 200   250      1.9   */
+       { 0x1, 0x7F, 0x33, 0x00, 0x0C },        /* 200   300      3.5   */
+       { 0x9, 0x7F, 0x31, 0x00, 0x0E },        /* 200   350      4.9   */
+       { 0x8, 0x7F, 0x3F, 0x00, 0x00 },        /* 250   250      0.0   */
+       { 0x1, 0x7F, 0x38, 0x00, 0x07 },        /* 250   300      1.6   */
+       { 0x9, 0x7F, 0x35, 0x00, 0x0A },        /* 250   350      2.9   */
+       { 0x1, 0x7F, 0x3F, 0x00, 0x00 },        /* 300   300      0.0   */
+       { 0x9, 0x7F, 0x38, 0x00, 0x07 },        /* 300   350      1.3   */
+       { 0x9, 0x7F, 0x3F, 0x00, 0x00 },        /* 350   350      0.0   */
 };
 
-/* Voltage Swing Programming for VccIO 1.05V for DP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_1_05V[] = {
-                               /* Voltage mV  db    */
-       { 0x2, 0x98, 0x0018 },  /* 400         0.0   */
-       { 0x2, 0x98, 0x3015 },  /* 400         3.5   */
-       { 0x2, 0x98, 0x6012 },  /* 400         6.0   */
-       { 0x2, 0x98, 0x900F },  /* 400         9.5   */
-       { 0x4, 0x98, 0x0018 },  /* 600         0.0   */
-       { 0x4, 0x98, 0x3015 },  /* 600         3.5   */
-       { 0x4, 0x98, 0x6012 },  /* 600         6.0   */
-       { 0x5, 0x71, 0x0018 },  /* 800         0.0   */
-       { 0x5, 0x71, 0x3015 },  /* 800         3.5   */
-       { 0x6, 0x98, 0x0018 },  /* 1200        0.0   */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr3[] = {
+                                               /* NT mV Trans mV db    */
+       { 0xA, 0x35, 0x3F, 0x00, 0x00 },        /* 350   350      0.0   */
+       { 0xA, 0x4F, 0x37, 0x00, 0x08 },        /* 350   500      3.1   */
+       { 0xC, 0x71, 0x2F, 0x00, 0x10 },        /* 350   700      6.0   */
+       { 0x6, 0x7F, 0x2B, 0x00, 0x14 },        /* 350   900      8.2   */
+       { 0xA, 0x4C, 0x3F, 0x00, 0x00 },        /* 500   500      0.0   */
+       { 0xC, 0x73, 0x34, 0x00, 0x0B },        /* 500   700      2.9   */
+       { 0x6, 0x7F, 0x2F, 0x00, 0x10 },        /* 500   900      5.1   */
+       { 0xC, 0x6C, 0x3C, 0x00, 0x03 },        /* 650   700      0.6   */
+       { 0x6, 0x7F, 0x35, 0x00, 0x0A },        /* 600   900      3.5   */
+       { 0x6, 0x7F, 0x3F, 0x00, 0x00 },        /* 900   900      0.0   */
 };
 
-/* FIXME - After table is updated in Bspec */
-/* Voltage Swing Programming for VccIO 1.05V for eDP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_1_05V[] = {
-                               /* Voltage mV  db    */
-       { 0x0, 0x00, 0x00 },    /* 200         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 200         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         6.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 250         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 350         0.0   */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_hdmi[] = {
+                                               /* NT mV Trans mV db    */
+       { 0xA, 0x60, 0x3F, 0x00, 0x00 },        /* 450   450      0.0   */
+       { 0xB, 0x73, 0x36, 0x00, 0x09 },        /* 450   650      3.2   */
+       { 0x6, 0x7F, 0x31, 0x00, 0x0E },        /* 450   850      5.5   */
+       { 0xB, 0x73, 0x3F, 0x00, 0x00 },        /* 650   650      0.0   ALS */
+       { 0x6, 0x7F, 0x37, 0x00, 0x08 },        /* 650   850      2.3   */
+       { 0x6, 0x7F, 0x3F, 0x00, 0x00 },        /* 850   850      0.0   */
+       { 0x6, 0x7F, 0x35, 0x00, 0x0A },        /* 600   850      3.0   */
 };
 
 struct icl_mg_phy_ddi_buf_trans {
@@ -871,43 +826,23 @@ cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
        }
 }
 
-static const struct icl_combo_phy_ddi_buf_trans *
+static const struct cnl_ddi_buf_trans *
 icl_get_combo_buf_trans(struct drm_i915_private *dev_priv, enum port port,
-                       int type, int *n_entries)
+                       int type, int rate, int *n_entries)
 {
-       u32 voltage = I915_READ(ICL_PORT_COMP_DW3(port)) & VOLTAGE_INFO_MASK;
-
-       if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
-               switch (voltage) {
-               case VOLTAGE_INFO_0_85V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_85V);
-                       return icl_combo_phy_ddi_translations_edp_0_85V;
-               case VOLTAGE_INFO_0_95V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_95V);
-                       return icl_combo_phy_ddi_translations_edp_0_95V;
-               case VOLTAGE_INFO_1_05V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_1_05V);
-                       return icl_combo_phy_ddi_translations_edp_1_05V;
-               default:
-                       MISSING_CASE(voltage);
-                       return NULL;
-               }
-       } else {
-               switch (voltage) {
-               case VOLTAGE_INFO_0_85V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_85V);
-                       return icl_combo_phy_ddi_translations_dp_hdmi_0_85V;
-               case VOLTAGE_INFO_0_95V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_95V);
-                       return icl_combo_phy_ddi_translations_dp_hdmi_0_95V;
-               case VOLTAGE_INFO_1_05V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_1_05V);
-                       return icl_combo_phy_ddi_translations_dp_hdmi_1_05V;
-               default:
-                       MISSING_CASE(voltage);
-                       return NULL;
-               }
+       if (type == INTEL_OUTPUT_HDMI) {
+               *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_hdmi);
+               return icl_combo_phy_ddi_translations_hdmi;
+       } else if (rate > 540000 && type == INTEL_OUTPUT_EDP) {
+               *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr3);
+               return icl_combo_phy_ddi_translations_edp_hbr3;
+       } else if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
+               *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr2);
+               return icl_combo_phy_ddi_translations_edp_hbr2;
        }
+
+       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hbr2);
+       return icl_combo_phy_ddi_translations_dp_hbr2;
 }
 
 static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port)
@@ -918,8 +853,8 @@ static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port por
 
        if (IS_ICELAKE(dev_priv)) {
                if (intel_port_is_combophy(dev_priv, port))
-                       icl_get_combo_buf_trans(dev_priv, port,
-                                               INTEL_OUTPUT_HDMI, &n_entries);
+                       icl_get_combo_buf_trans(dev_priv, port, INTEL_OUTPUT_HDMI,
+                                               0, &n_entries);
                else
                        n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations);
                default_entry = n_entries - 1;
@@ -1039,7 +974,7 @@ static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
        DRM_ERROR("Timeout waiting for DDI BUF %c idle bit\n", port_name(port));
 }
 
-static uint32_t hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
+static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
 {
        switch (pll->info->id) {
        case DPLL_ID_WRPLL1:
@@ -1060,8 +995,8 @@ static uint32_t hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
        }
 }
 
-static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder,
-                                      const struct intel_crtc_state *crtc_state)
+static u32 icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder,
+                                 const struct intel_crtc_state *crtc_state)
 {
        const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
        int clock = crtc_state->port_clock;
@@ -1308,8 +1243,8 @@ static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv,
                               enum intel_dpll_id pll_id)
 {
        i915_reg_t cfgcr1_reg, cfgcr2_reg;
-       uint32_t cfgcr1_val, cfgcr2_val;
-       uint32_t p0, p1, p2, dco_freq;
+       u32 cfgcr1_val, cfgcr2_val;
+       u32 p0, p1, p2, dco_freq;
 
        cfgcr1_reg = DPLL_CFGCR1(pll_id);
        cfgcr2_reg = DPLL_CFGCR2(pll_id);
@@ -1361,14 +1296,17 @@ static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv,
        dco_freq += (((cfgcr1_val & DPLL_CFGCR1_DCO_FRACTION_MASK) >> 9) * 24 *
                1000) / 0x8000;
 
+       if (WARN_ON(p0 == 0 || p1 == 0 || p2 == 0))
+               return 0;
+
        return dco_freq / (p0 * p1 * p2 * 5);
 }
 
 int cnl_calc_wrpll_link(struct drm_i915_private *dev_priv,
                        enum intel_dpll_id pll_id)
 {
-       uint32_t cfgcr0, cfgcr1;
-       uint32_t p0, p1, p2, dco_freq, ref_clock;
+       u32 cfgcr0, cfgcr1;
+       u32 p0, p1, p2, dco_freq, ref_clock;
 
        if (INTEL_GEN(dev_priv) >= 11) {
                cfgcr0 = I915_READ(ICL_DPLL_CFGCR0(pll_id));
@@ -1533,7 +1471,7 @@ static void icl_ddi_clock_get(struct intel_encoder *encoder,
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        enum port port = encoder->port;
        int link_clock = 0;
-       uint32_t pll_id;
+       u32 pll_id;
 
        pll_id = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll);
        if (intel_port_is_combophy(dev_priv, port)) {
@@ -1558,7 +1496,7 @@ static void cnl_ddi_clock_get(struct intel_encoder *encoder,
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        int link_clock = 0;
-       uint32_t cfgcr0;
+       u32 cfgcr0;
        enum intel_dpll_id pll_id;
 
        pll_id = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll);
@@ -1612,7 +1550,7 @@ static void skl_ddi_clock_get(struct intel_encoder *encoder,
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        int link_clock = 0;
-       uint32_t dpll_ctl1;
+       u32 dpll_ctl1;
        enum intel_dpll_id pll_id;
 
        pll_id = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll);
@@ -1801,7 +1739,7 @@ void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state,
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
-       uint32_t temp;
+       u32 temp;
 
        temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
        if (state == true)
@@ -1819,7 +1757,7 @@ void intel_ddi_enable_transcoder_func(const struct intel_crtc_state *crtc_state)
        enum pipe pipe = crtc->pipe;
        enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
        enum port port = encoder->port;
-       uint32_t temp;
+       u32 temp;
 
        /* Enable TRANS_DDI_FUNC_CTL for the pipe to work in HDMI mode */
        temp = TRANS_DDI_FUNC_ENABLE;
@@ -1880,7 +1818,7 @@ void intel_ddi_enable_transcoder_func(const struct intel_crtc_state *crtc_state)
                        temp |= TRANS_DDI_MODE_SELECT_DVI;
 
                if (crtc_state->hdmi_scrambling)
-                       temp |= TRANS_DDI_HDMI_SCRAMBLING_MASK;
+                       temp |= TRANS_DDI_HDMI_SCRAMBLING;
                if (crtc_state->hdmi_high_tmds_clock_ratio)
                        temp |= TRANS_DDI_HIGH_TMDS_CHAR_RATE;
        } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
@@ -1903,7 +1841,7 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
        i915_reg_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);
-       uint32_t val = I915_READ(reg);
+       u32 val = I915_READ(reg);
 
        val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK | TRANS_DDI_DP_VC_PAYLOAD_ALLOC);
        val |= TRANS_DDI_PORT_NONE;
@@ -1922,12 +1860,14 @@ int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
 {
        struct drm_device *dev = intel_encoder->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
+       intel_wakeref_t wakeref;
        enum pipe pipe = 0;
        int ret = 0;
-       uint32_t tmp;
+       u32 tmp;
 
-       if (WARN_ON(!intel_display_power_get_if_enabled(dev_priv,
-                                               intel_encoder->power_domain)))
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    intel_encoder->power_domain);
+       if (WARN_ON(!wakeref))
                return -ENXIO;
 
        if (WARN_ON(!intel_encoder->get_hw_state(intel_encoder, &pipe))) {
@@ -1942,7 +1882,7 @@ int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
                tmp &= ~TRANS_DDI_HDCP_SIGNALLING;
        I915_WRITE(TRANS_DDI_FUNC_CTL(pipe), tmp);
 out:
-       intel_display_power_put(dev_priv, intel_encoder->power_domain);
+       intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
        return ret;
 }
 
@@ -1953,13 +1893,15 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
        struct intel_encoder *encoder = intel_connector->encoder;
        int type = intel_connector->base.connector_type;
        enum port port = encoder->port;
-       enum pipe pipe = 0;
        enum transcoder cpu_transcoder;
-       uint32_t tmp;
+       intel_wakeref_t wakeref;
+       enum pipe pipe = 0;
+       u32 tmp;
        bool ret;
 
-       if (!intel_display_power_get_if_enabled(dev_priv,
-                                               encoder->power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    encoder->power_domain);
+       if (!wakeref)
                return false;
 
        if (!encoder->get_hw_state(encoder, &pipe)) {
@@ -2001,7 +1943,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
        }
 
 out:
-       intel_display_power_put(dev_priv, encoder->power_domain);
+       intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
 
        return ret;
 }
@@ -2012,6 +1954,7 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        enum port port = encoder->port;
+       intel_wakeref_t wakeref;
        enum pipe p;
        u32 tmp;
        u8 mst_pipe_mask;
@@ -2019,8 +1962,9 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
        *pipe_mask = 0;
        *is_dp_mst = false;
 
-       if (!intel_display_power_get_if_enabled(dev_priv,
-                                               encoder->power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    encoder->power_domain);
+       if (!wakeref)
                return;
 
        tmp = I915_READ(DDI_BUF_CTL(port));
@@ -2091,7 +2035,7 @@ out:
                                  "(PHY_CTL %08x)\n", port_name(port), tmp);
        }
 
-       intel_display_power_put(dev_priv, encoder->power_domain);
+       intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
 }
 
 bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
@@ -2188,7 +2132,7 @@ void intel_ddi_disable_pipe_clock(const struct intel_crtc_state *crtc_state)
 }
 
 static void _skl_ddi_set_iboost(struct drm_i915_private *dev_priv,
-                               enum port port, uint8_t iboost)
+                               enum port port, u8 iboost)
 {
        u32 tmp;
 
@@ -2207,7 +2151,7 @@ static void skl_ddi_set_iboost(struct intel_encoder *encoder,
        struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base);
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        enum port port = encoder->port;
-       uint8_t iboost;
+       u8 iboost;
 
        if (type == INTEL_OUTPUT_HDMI)
                iboost = dev_priv->vbt.ddi_port_info[port].hdmi_boost_level;
@@ -2275,13 +2219,14 @@ static void bxt_ddi_vswing_sequence(struct intel_encoder *encoder,
 u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
        enum port port = encoder->port;
        int n_entries;
 
        if (IS_ICELAKE(dev_priv)) {
                if (intel_port_is_combophy(dev_priv, port))
                        icl_get_combo_buf_trans(dev_priv, port, encoder->type,
-                                               &n_entries);
+                                               intel_dp->link_rate, &n_entries);
                else
                        n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations);
        } else if (IS_CANNONLAKE(dev_priv)) {
@@ -2462,14 +2407,15 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder,
 }
 
 static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
-                                        u32 level, enum port port, int type)
+                                       u32 level, enum port port, int type,
+                                       int rate)
 {
-       const struct icl_combo_phy_ddi_buf_trans *ddi_translations = NULL;
+       const struct cnl_ddi_buf_trans *ddi_translations = NULL;
        u32 n_entries, val;
        int ln;
 
        ddi_translations = icl_get_combo_buf_trans(dev_priv, port, type,
-                                                  &n_entries);
+                                                  rate, &n_entries);
        if (!ddi_translations)
                return;
 
@@ -2478,34 +2424,23 @@ static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
                level = n_entries - 1;
        }
 
-       /* Set PORT_TX_DW5 Rterm Sel to 110b. */
+       /* Set PORT_TX_DW5 */
        val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
-       val &= ~RTERM_SELECT_MASK;
+       val &= ~(SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK |
+                 TAP2_DISABLE | TAP3_DISABLE);
+       val |= SCALING_MODE_SEL(0x2);
        val |= RTERM_SELECT(0x6);
-       I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
-
-       /* Program PORT_TX_DW5 */
-       val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
-       /* Set DisableTap2 and DisableTap3 if MIPI DSI
-        * Clear DisableTap2 and DisableTap3 for all other Ports
-        */
-       if (type == INTEL_OUTPUT_DSI) {
-               val |= TAP2_DISABLE;
-               val |= TAP3_DISABLE;
-       } else {
-               val &= ~TAP2_DISABLE;
-               val &= ~TAP3_DISABLE;
-       }
+       val |= TAP3_DISABLE;
        I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
 
        /* Program PORT_TX_DW2 */
        val = I915_READ(ICL_PORT_TX_DW2_LN0(port));
        val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK |
                 RCOMP_SCALAR_MASK);
-       val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select);
-       val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select);
+       val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_sel);
+       val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_sel);
        /* Program Rcomp scalar for every table entry */
-       val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar);
+       val |= RCOMP_SCALAR(0x98);
        I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val);
 
        /* Program PORT_TX_DW4 */
@@ -2514,9 +2449,17 @@ static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
                val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
                val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |
                         CURSOR_COEFF_MASK);
-               val |= ddi_translations[level].dw4_scaling;
+               val |= POST_CURSOR_1(ddi_translations[level].dw4_post_cursor_1);
+               val |= POST_CURSOR_2(ddi_translations[level].dw4_post_cursor_2);
+               val |= CURSOR_COEFF(ddi_translations[level].dw4_cursor_coeff);
                I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);
        }
+
+       /* Program PORT_TX_DW7 */
+       val = I915_READ(ICL_PORT_TX_DW7_LN0(port));
+       val &= ~N_SCALAR_MASK;
+       val |= N_SCALAR(ddi_translations[level].dw7_n_scalar);
+       I915_WRITE(ICL_PORT_TX_DW7_GRP(port), val);
 }
 
 static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
@@ -2581,7 +2524,7 @@ static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
        I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
 
        /* 5. Program swing and de-emphasis */
-       icl_ddi_combo_vswing_program(dev_priv, level, port, type);
+       icl_ddi_combo_vswing_program(dev_priv, level, port, type, rate);
 
        /* 6. Set training enable to trigger update */
        val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
@@ -2722,7 +2665,7 @@ static void icl_ddi_vswing_sequence(struct intel_encoder *encoder,
                icl_mg_phy_ddi_vswing_sequence(encoder, link_clock, level);
 }
 
-static uint32_t translate_signal_level(int signal_levels)
+static u32 translate_signal_level(int signal_levels)
 {
        int i;
 
@@ -2737,9 +2680,9 @@ static uint32_t translate_signal_level(int signal_levels)
        return 0;
 }
 
-static uint32_t intel_ddi_dp_level(struct intel_dp *intel_dp)
+static u32 intel_ddi_dp_level(struct intel_dp *intel_dp)
 {
-       uint8_t train_set = intel_dp->train_set[0];
+       u8 train_set = intel_dp->train_set[0];
        int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
                                         DP_TRAIN_PRE_EMPHASIS_MASK);
 
@@ -2764,7 +2707,7 @@ u32 bxt_signal_levels(struct intel_dp *intel_dp)
        return 0;
 }
 
-uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
+u32 ddi_signal_levels(struct intel_dp *intel_dp)
 {
        struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
        struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev);
@@ -2778,8 +2721,8 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
 }
 
 static inline
-uint32_t icl_dpclka_cfgcr0_clk_off(struct drm_i915_private *dev_priv,
-                                  enum port port)
+u32 icl_dpclka_cfgcr0_clk_off(struct drm_i915_private *dev_priv,
+                             enum port port)
 {
        if (intel_port_is_combophy(dev_priv, port)) {
                return ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(port);
@@ -2914,7 +2857,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        enum port port = encoder->port;
-       uint32_t val;
+       u32 val;
        const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
 
        if (WARN_ON(!pll))
@@ -3349,7 +3292,8 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder,
        intel_edp_panel_vdd_on(intel_dp);
        intel_edp_panel_off(intel_dp);
 
-       intel_display_power_put(dev_priv, dig_port->ddi_io_power_domain);
+       intel_display_power_put_unchecked(dev_priv,
+                                         dig_port->ddi_io_power_domain);
 
        intel_ddi_clk_disable(encoder);
 }
@@ -3369,7 +3313,8 @@ static void intel_ddi_post_disable_hdmi(struct intel_encoder *encoder,
 
        intel_disable_ddi_buf(encoder, old_crtc_state);
 
-       intel_display_power_put(dev_priv, dig_port->ddi_io_power_domain);
+       intel_display_power_put_unchecked(dev_priv,
+                                         dig_port->ddi_io_power_domain);
 
        intel_ddi_clk_disable(encoder);
 
@@ -3411,7 +3356,7 @@ void intel_ddi_fdi_post_disable(struct intel_encoder *encoder,
                                const struct drm_connector_state *old_conn_state)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
-       uint32_t val;
+       u32 val;
 
        /*
         * Bspec lists this as both step 13 (before DDI_BUF_CTL disable)
@@ -3603,6 +3548,26 @@ static void intel_disable_ddi(struct intel_encoder *encoder,
                intel_disable_ddi_dp(encoder, old_crtc_state, old_conn_state);
 }
 
+static void intel_ddi_update_pipe_dp(struct intel_encoder *encoder,
+                                    const struct intel_crtc_state *crtc_state,
+                                    const struct drm_connector_state *conn_state)
+{
+       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+
+       intel_psr_enable(intel_dp, crtc_state);
+       intel_edp_drrs_enable(intel_dp, crtc_state);
+
+       intel_panel_update_backlight(encoder, crtc_state, conn_state);
+}
+
+static void intel_ddi_update_pipe(struct intel_encoder *encoder,
+                                 const struct intel_crtc_state *crtc_state,
+                                 const struct drm_connector_state *conn_state)
+{
+       if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+               intel_ddi_update_pipe_dp(encoder, crtc_state, conn_state);
+}
+
 static void intel_ddi_set_fia_lane_count(struct intel_encoder *encoder,
                                         const struct intel_crtc_state *pipe_config,
                                         enum port port)
@@ -3671,8 +3636,8 @@ intel_ddi_post_pll_disable(struct intel_encoder *encoder,
 
        if (intel_crtc_has_dp_encoder(crtc_state) ||
            intel_port_is_tc(dev_priv, encoder->port))
-               intel_display_power_put(dev_priv,
-                                       intel_ddi_main_link_aux_domain(dig_port));
+               intel_display_power_put_unchecked(dev_priv,
+                                                 intel_ddi_main_link_aux_domain(dig_port));
 }
 
 void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
@@ -3681,7 +3646,7 @@ void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
        struct drm_i915_private *dev_priv =
                to_i915(intel_dig_port->base.base.dev);
        enum port port = intel_dig_port->base.port;
-       uint32_t val;
+       u32 val;
        bool wait = false;
 
        if (I915_READ(DP_TP_CTL(port)) & DP_TP_CTL_ENABLE) {
@@ -3793,8 +3758,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
                if (intel_dig_port->infoframe_enabled(encoder, pipe_config))
                        pipe_config->has_infoframe = true;
 
-               if ((temp & TRANS_DDI_HDMI_SCRAMBLING_MASK) ==
-                       TRANS_DDI_HDMI_SCRAMBLING_MASK)
+               if (temp & TRANS_DDI_HDMI_SCRAMBLING)
                        pipe_config->hdmi_scrambling = true;
                if (temp & TRANS_DDI_HIGH_TMDS_CHAR_RATE)
                        pipe_config->hdmi_high_tmds_clock_ratio = true;
@@ -3875,9 +3839,9 @@ intel_ddi_compute_output_type(struct intel_encoder *encoder,
        }
 }
 
-static bool intel_ddi_compute_config(struct intel_encoder *encoder,
-                                    struct intel_crtc_state *pipe_config,
-                                    struct drm_connector_state *conn_state)
+static int intel_ddi_compute_config(struct intel_encoder *encoder,
+                                   struct intel_crtc_state *pipe_config,
+                                   struct drm_connector_state *conn_state)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        enum port port = encoder->port;
@@ -3901,9 +3865,50 @@ static bool intel_ddi_compute_config(struct intel_encoder *encoder,
 
 }
 
+static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
+{
+       struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
+       struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+       intel_dp_encoder_suspend(encoder);
+
+       /*
+        * TODO: disconnect also from USB DP alternate mode once we have a
+        * way to handle the modeset restore in that mode during resume
+        * even if the sink has disappeared while being suspended.
+        */
+       if (dig_port->tc_legacy_port)
+               icl_tc_phy_disconnect(i915, dig_port);
+}
+
+static void intel_ddi_encoder_reset(struct drm_encoder *drm_encoder)
+{
+       struct intel_digital_port *dig_port = enc_to_dig_port(drm_encoder);
+       struct drm_i915_private *i915 = to_i915(drm_encoder->dev);
+
+       if (intel_port_is_tc(i915, dig_port->base.port))
+               intel_digital_port_connected(&dig_port->base);
+
+       intel_dp_encoder_reset(drm_encoder);
+}
+
+static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
+{
+       struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+       struct drm_i915_private *i915 = to_i915(encoder->dev);
+
+       intel_dp_encoder_flush_work(encoder);
+
+       if (intel_port_is_tc(i915, dig_port->base.port))
+               icl_tc_phy_disconnect(i915, dig_port);
+
+       drm_encoder_cleanup(encoder);
+       kfree(dig_port);
+}
+
 static const struct drm_encoder_funcs intel_ddi_funcs = {
-       .reset = intel_dp_encoder_reset,
-       .destroy = intel_dp_encoder_destroy,
+       .reset = intel_ddi_encoder_reset,
+       .destroy = intel_ddi_encoder_destroy,
 };
 
 static struct intel_connector *
@@ -4147,16 +4152,16 @@ intel_ddi_max_lanes(struct intel_digital_port *intel_dport)
 
 void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
 {
+       struct ddi_vbt_port_info *port_info =
+               &dev_priv->vbt.ddi_port_info[port];
        struct intel_digital_port *intel_dig_port;
        struct intel_encoder *intel_encoder;
        struct drm_encoder *encoder;
        bool init_hdmi, init_dp, init_lspcon = false;
        enum pipe pipe;
 
-
-       init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi ||
-                    dev_priv->vbt.ddi_port_info[port].supports_hdmi);
-       init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp;
+       init_hdmi = port_info->supports_dvi || port_info->supports_hdmi;
+       init_dp = port_info->supports_dp;
 
        if (intel_bios_is_lspcon_present(dev_priv, port)) {
                /*
@@ -4195,9 +4200,10 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
        intel_encoder->pre_enable = intel_ddi_pre_enable;
        intel_encoder->disable = intel_disable_ddi;
        intel_encoder->post_disable = intel_ddi_post_disable;
+       intel_encoder->update_pipe = intel_ddi_update_pipe;
        intel_encoder->get_hw_state = intel_ddi_get_hw_state;
        intel_encoder->get_config = intel_ddi_get_config;
-       intel_encoder->suspend = intel_dp_encoder_suspend;
+       intel_encoder->suspend = intel_ddi_encoder_suspend;
        intel_encoder->get_power_domains = intel_ddi_get_power_domains;
        intel_encoder->type = INTEL_OUTPUT_DDI;
        intel_encoder->power_domain = intel_port_to_power_domain(port);
@@ -4216,6 +4222,10 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
        intel_dig_port->max_lanes = intel_ddi_max_lanes(intel_dig_port);
        intel_dig_port->aux_ch = intel_bios_port_aux_ch(dev_priv, port);
 
+       intel_dig_port->tc_legacy_port = intel_port_is_tc(dev_priv, port) &&
+                                        !port_info->supports_typec_usb &&
+                                        !port_info->supports_tbt;
+
        switch (port) {
        case PORT_A:
                intel_dig_port->ddi_io_power_domain =
@@ -4274,6 +4284,10 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
        }
 
        intel_infoframe_init(intel_dig_port);
+
+       if (intel_port_is_tc(dev_priv, port))
+               intel_digital_port_connected(intel_encoder);
+
        return;
 
 err:
index 1e56319334f38ed248a2d12d93ddc3b97937d6c8..855a5074ad775c2314dbf1e645008ee8709d9bb9 100644 (file)
@@ -104,7 +104,7 @@ static void sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p)
        drm_printf(p, "has EU power gating: %s\n", yesno(sseu->has_eu_pg));
 }
 
-void intel_device_info_dump_runtime(const struct intel_device_info *info,
+void intel_device_info_dump_runtime(const struct intel_runtime_info *info,
                                    struct drm_printer *p)
 {
        sseu_dump(&info->sseu, p);
@@ -113,21 +113,6 @@ void intel_device_info_dump_runtime(const struct intel_device_info *info,
                   info->cs_timestamp_frequency_khz);
 }
 
-void intel_device_info_dump(const struct intel_device_info *info,
-                           struct drm_printer *p)
-{
-       struct drm_i915_private *dev_priv =
-               container_of(info, struct drm_i915_private, info);
-
-       drm_printf(p, "pciid=0x%04x rev=0x%02x platform=%s gen=%i\n",
-                  INTEL_DEVID(dev_priv),
-                  INTEL_REVID(dev_priv),
-                  intel_platform_name(info->platform),
-                  info->gen);
-
-       intel_device_info_dump_flags(info, p);
-}
-
 void intel_device_info_dump_topology(const struct sseu_dev_info *sseu,
                                     struct drm_printer *p)
 {
@@ -164,7 +149,7 @@ static u16 compute_eu_total(const struct sseu_dev_info *sseu)
 
 static void gen11_sseu_info_init(struct drm_i915_private *dev_priv)
 {
-       struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu;
+       struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu;
        u8 s_en;
        u32 ss_en, ss_en_mask;
        u8 eu_en;
@@ -203,7 +188,7 @@ static void gen11_sseu_info_init(struct drm_i915_private *dev_priv)
 
 static void gen10_sseu_info_init(struct drm_i915_private *dev_priv)
 {
-       struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu;
+       struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu;
        const u32 fuse2 = I915_READ(GEN8_FUSE2);
        int s, ss;
        const int eu_mask = 0xff;
@@ -280,7 +265,7 @@ static void gen10_sseu_info_init(struct drm_i915_private *dev_priv)
 
 static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv)
 {
-       struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu;
+       struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu;
        u32 fuse;
 
        fuse = I915_READ(CHV_FUSE_GT);
@@ -334,7 +319,7 @@ static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv)
 static void gen9_sseu_info_init(struct drm_i915_private *dev_priv)
 {
        struct intel_device_info *info = mkwrite_device_info(dev_priv);
-       struct sseu_dev_info *sseu = &info->sseu;
+       struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu;
        int s, ss;
        u32 fuse2, eu_disable, subslice_mask;
        const u8 eu_mask = 0xff;
@@ -437,7 +422,7 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv)
 
 static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv)
 {
-       struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu;
+       struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu;
        int s, ss;
        u32 fuse2, subslice_mask, eu_disable[3]; /* s_max */
 
@@ -519,8 +504,7 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv)
 
 static void haswell_sseu_info_init(struct drm_i915_private *dev_priv)
 {
-       struct intel_device_info *info = mkwrite_device_info(dev_priv);
-       struct sseu_dev_info *sseu = &info->sseu;
+       struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu;
        u32 fuse1;
        int s, ss;
 
@@ -528,9 +512,9 @@ static void haswell_sseu_info_init(struct drm_i915_private *dev_priv)
         * There isn't a register to tell us how many slices/subslices. We
         * work off the PCI-ids here.
         */
-       switch (info->gt) {
+       switch (INTEL_INFO(dev_priv)->gt) {
        default:
-               MISSING_CASE(info->gt);
+               MISSING_CASE(INTEL_INFO(dev_priv)->gt);
                /* fall through */
        case 1:
                sseu->slice_mask = BIT(0);
@@ -725,7 +709,7 @@ static u32 read_timestamp_frequency(struct drm_i915_private *dev_priv)
 
 /**
  * intel_device_info_runtime_init - initialize runtime info
- * @info: intel device info struct
+ * @dev_priv: the i915 device
  *
  * Determine various intel_device_info fields at runtime.
  *
@@ -739,29 +723,29 @@ static u32 read_timestamp_frequency(struct drm_i915_private *dev_priv)
  *   - after the PCH has been detected,
  *   - before the first usage of the fields it can tweak.
  */
-void intel_device_info_runtime_init(struct intel_device_info *info)
+void intel_device_info_runtime_init(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv =
-               container_of(info, struct drm_i915_private, info);
+       struct intel_device_info *info = mkwrite_device_info(dev_priv);
+       struct intel_runtime_info *runtime = RUNTIME_INFO(dev_priv);
        enum pipe pipe;
 
        if (INTEL_GEN(dev_priv) >= 10) {
                for_each_pipe(dev_priv, pipe)
-                       info->num_scalers[pipe] = 2;
-       } else if (IS_GEN9(dev_priv)) {
-               info->num_scalers[PIPE_A] = 2;
-               info->num_scalers[PIPE_B] = 2;
-               info->num_scalers[PIPE_C] = 1;
+                       runtime->num_scalers[pipe] = 2;
+       } else if (IS_GEN(dev_priv, 9)) {
+               runtime->num_scalers[PIPE_A] = 2;
+               runtime->num_scalers[PIPE_B] = 2;
+               runtime->num_scalers[PIPE_C] = 1;
        }
 
        BUILD_BUG_ON(I915_NUM_ENGINES > BITS_PER_TYPE(intel_ring_mask_t));
 
-       if (IS_GEN11(dev_priv))
+       if (IS_GEN(dev_priv, 11))
                for_each_pipe(dev_priv, pipe)
-                       info->num_sprites[pipe] = 6;
-       else if (IS_GEN10(dev_priv) || IS_GEMINILAKE(dev_priv))
+                       runtime->num_sprites[pipe] = 6;
+       else if (IS_GEN(dev_priv, 10) || IS_GEMINILAKE(dev_priv))
                for_each_pipe(dev_priv, pipe)
-                       info->num_sprites[pipe] = 3;
+                       runtime->num_sprites[pipe] = 3;
        else if (IS_BROXTON(dev_priv)) {
                /*
                 * Skylake and Broxton currently don't expose the topmost plane as its
@@ -772,22 +756,22 @@ void intel_device_info_runtime_init(struct intel_device_info *info)
                 * down the line.
                 */
 
-               info->num_sprites[PIPE_A] = 2;
-               info->num_sprites[PIPE_B] = 2;
-               info->num_sprites[PIPE_C] = 1;
+               runtime->num_sprites[PIPE_A] = 2;
+               runtime->num_sprites[PIPE_B] = 2;
+               runtime->num_sprites[PIPE_C] = 1;
        } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
                for_each_pipe(dev_priv, pipe)
-                       info->num_sprites[pipe] = 2;
+                       runtime->num_sprites[pipe] = 2;
        } else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) {
                for_each_pipe(dev_priv, pipe)
-                       info->num_sprites[pipe] = 1;
+                       runtime->num_sprites[pipe] = 1;
        }
 
        if (i915_modparams.disable_display) {
                DRM_INFO("Display disabled (module parameter)\n");
                info->num_pipes = 0;
        } else if (HAS_DISPLAY(dev_priv) &&
-                  (IS_GEN7(dev_priv) || IS_GEN8(dev_priv)) &&
+                  (IS_GEN_RANGE(dev_priv, 7, 8)) &&
                   HAS_PCH_SPLIT(dev_priv)) {
                u32 fuse_strap = I915_READ(FUSE_STRAP);
                u32 sfuse_strap = I915_READ(SFUSE_STRAP);
@@ -811,7 +795,7 @@ void intel_device_info_runtime_init(struct intel_device_info *info)
                        DRM_INFO("PipeC fused off\n");
                        info->num_pipes -= 1;
                }
-       } else if (HAS_DISPLAY(dev_priv) && IS_GEN9(dev_priv)) {
+       } else if (HAS_DISPLAY(dev_priv) && INTEL_GEN(dev_priv) >= 9) {
                u32 dfsm = I915_READ(SKL_DFSM);
                u8 disabled_mask = 0;
                bool invalid;
@@ -851,20 +835,20 @@ void intel_device_info_runtime_init(struct intel_device_info *info)
                cherryview_sseu_info_init(dev_priv);
        else if (IS_BROADWELL(dev_priv))
                broadwell_sseu_info_init(dev_priv);
-       else if (IS_GEN9(dev_priv))
+       else if (IS_GEN(dev_priv, 9))
                gen9_sseu_info_init(dev_priv);
-       else if (IS_GEN10(dev_priv))
+       else if (IS_GEN(dev_priv, 10))
                gen10_sseu_info_init(dev_priv);
        else if (INTEL_GEN(dev_priv) >= 11)
                gen11_sseu_info_init(dev_priv);
 
-       if (IS_GEN6(dev_priv) && intel_vtd_active()) {
+       if (IS_GEN(dev_priv, 6) && intel_vtd_active()) {
                DRM_INFO("Disabling ppGTT for VT-d support\n");
                info->ppgtt = INTEL_PPGTT_NONE;
        }
 
        /* Initialize command stream timestamp frequency */
-       info->cs_timestamp_frequency_khz = read_timestamp_frequency(dev_priv);
+       runtime->cs_timestamp_frequency_khz = read_timestamp_frequency(dev_priv);
 }
 
 void intel_driver_caps_print(const struct intel_driver_caps *caps,
@@ -884,35 +868,44 @@ void intel_driver_caps_print(const struct intel_driver_caps *caps,
 void intel_device_info_init_mmio(struct drm_i915_private *dev_priv)
 {
        struct intel_device_info *info = mkwrite_device_info(dev_priv);
-       u32 media_fuse;
+       unsigned int logical_vdbox = 0;
        unsigned int i;
+       u32 media_fuse;
 
        if (INTEL_GEN(dev_priv) < 11)
                return;
 
        media_fuse = ~I915_READ(GEN11_GT_VEBOX_VDBOX_DISABLE);
 
-       info->vdbox_enable = media_fuse & GEN11_GT_VDBOX_DISABLE_MASK;
-       info->vebox_enable = (media_fuse & GEN11_GT_VEBOX_DISABLE_MASK) >>
-                            GEN11_GT_VEBOX_DISABLE_SHIFT;
+       RUNTIME_INFO(dev_priv)->vdbox_enable = media_fuse & GEN11_GT_VDBOX_DISABLE_MASK;
+       RUNTIME_INFO(dev_priv)->vebox_enable = (media_fuse & GEN11_GT_VEBOX_DISABLE_MASK) >>
+               GEN11_GT_VEBOX_DISABLE_SHIFT;
 
-       DRM_DEBUG_DRIVER("vdbox enable: %04x\n", info->vdbox_enable);
+       DRM_DEBUG_DRIVER("vdbox enable: %04x\n", RUNTIME_INFO(dev_priv)->vdbox_enable);
        for (i = 0; i < I915_MAX_VCS; i++) {
                if (!HAS_ENGINE(dev_priv, _VCS(i)))
                        continue;
 
-               if (!(BIT(i) & info->vdbox_enable)) {
+               if (!(BIT(i) & RUNTIME_INFO(dev_priv)->vdbox_enable)) {
                        info->ring_mask &= ~ENGINE_MASK(_VCS(i));
                        DRM_DEBUG_DRIVER("vcs%u fused off\n", i);
+                       continue;
                }
+
+               /*
+                * In Gen11, only even numbered logical VDBOXes are
+                * hooked up to an SFC (Scaler & Format Converter) unit.
+                */
+               if (logical_vdbox++ % 2 == 0)
+                       RUNTIME_INFO(dev_priv)->vdbox_sfc_access |= BIT(i);
        }
 
-       DRM_DEBUG_DRIVER("vebox enable: %04x\n", info->vebox_enable);
+       DRM_DEBUG_DRIVER("vebox enable: %04x\n", RUNTIME_INFO(dev_priv)->vebox_enable);
        for (i = 0; i < I915_MAX_VECS; i++) {
                if (!HAS_ENGINE(dev_priv, _VECS(i)))
                        continue;
 
-               if (!(BIT(i) & info->vebox_enable)) {
+               if (!(BIT(i) & RUNTIME_INFO(dev_priv)->vebox_enable)) {
                        info->ring_mask &= ~ENGINE_MASK(_VECS(i));
                        DRM_DEBUG_DRIVER("vecs%u fused off\n", i);
                }
index 1caf24e2cf0ba5a7d332ef4add45c085f332128c..957c6527f76bc659390e0c21a76b868c2c396429 100644 (file)
@@ -89,6 +89,7 @@ enum intel_ppgtt {
        func(is_alpha_support); \
        /* Keep has_* in alphabetical order */ \
        func(has_64bit_reloc); \
+       func(gpu_reset_clobbers_display); \
        func(has_reset_engine); \
        func(has_fpga_dbg); \
        func(has_guc); \
@@ -152,12 +153,10 @@ struct sseu_dev_info {
 typedef u8 intel_ring_mask_t;
 
 struct intel_device_info {
-       u16 device_id;
        u16 gen_mask;
 
        u8 gen;
        u8 gt; /* GT number, 0 if undefined */
-       u8 num_rings;
        intel_ring_mask_t ring_mask; /* Rings supported by the HW */
 
        enum intel_platform platform;
@@ -169,8 +168,6 @@ struct intel_device_info {
        u32 display_mmio_offset;
 
        u8 num_pipes;
-       u8 num_sprites[I915_MAX_PIPES];
-       u8 num_scalers[I915_MAX_PIPES];
 
 #define DEFINE_FLAG(name) u8 name:1
        DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG);
@@ -189,6 +186,20 @@ struct intel_device_info {
        int trans_offsets[I915_MAX_TRANSCODERS];
        int cursor_offsets[I915_MAX_PIPES];
 
+       struct color_luts {
+               u16 degamma_lut_size;
+               u16 gamma_lut_size;
+       } color;
+};
+
+struct intel_runtime_info {
+       u16 device_id;
+
+       u8 num_sprites[I915_MAX_PIPES];
+       u8 num_scalers[I915_MAX_PIPES];
+
+       u8 num_rings;
+
        /* Slice/subslice/EU info */
        struct sseu_dev_info sseu;
 
@@ -198,10 +209,8 @@ struct intel_device_info {
        u8 vdbox_enable;
        u8 vebox_enable;
 
-       struct color_luts {
-               u16 degamma_lut_size;
-               u16 gamma_lut_size;
-       } color;
+       /* Media engine access to SFC per instance */
+       u8 vdbox_sfc_access;
 };
 
 struct intel_driver_caps {
@@ -258,12 +267,10 @@ static inline void sseu_set_eus(struct sseu_dev_info *sseu,
 
 const char *intel_platform_name(enum intel_platform platform);
 
-void intel_device_info_runtime_init(struct intel_device_info *info);
-void intel_device_info_dump(const struct intel_device_info *info,
-                           struct drm_printer *p);
+void intel_device_info_runtime_init(struct drm_i915_private *dev_priv);
 void intel_device_info_dump_flags(const struct intel_device_info *info,
                                  struct drm_printer *p);
-void intel_device_info_dump_runtime(const struct intel_device_info *info,
+void intel_device_info_dump_runtime(const struct intel_runtime_info *info,
                                    struct drm_printer *p);
 void intel_device_info_dump_topology(const struct sseu_dev_info *sseu,
                                     struct drm_printer *p);
index 3da9c0f9e9485c7c4b9ccf8fefe5c71f72f1ea02..36c1126cbc85376a8bbf9ca277fadf4a75155565 100644 (file)
 #include <linux/slab.h>
 #include <linux/vgaarb.h>
 #include <drm/drm_edid.h>
-#include <drm/drmP.h>
-#include "intel_drv.h"
-#include "intel_frontbuffer.h"
 #include <drm/i915_drm.h>
-#include "i915_drv.h"
-#include "i915_gem_clflush.h"
-#include "intel_dsi.h"
-#include "i915_trace.h"
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_dp_helper.h>
 #include <linux/intel-iommu.h>
 #include <linux/reservation.h>
 
+#include "intel_drv.h"
+#include "intel_dsi.h"
+#include "intel_frontbuffer.h"
+
+#include "i915_drv.h"
+#include "i915_gem_clflush.h"
+#include "i915_reset.h"
+#include "i915_trace.h"
+
 /* Primary plane formats for gen <= 3 */
-static const uint32_t i8xx_primary_formats[] = {
+static const u32 i8xx_primary_formats[] = {
        DRM_FORMAT_C8,
        DRM_FORMAT_RGB565,
        DRM_FORMAT_XRGB1555,
@@ -58,7 +60,7 @@ static const uint32_t i8xx_primary_formats[] = {
 };
 
 /* Primary plane formats for gen >= 4 */
-static const uint32_t i965_primary_formats[] = {
+static const u32 i965_primary_formats[] = {
        DRM_FORMAT_C8,
        DRM_FORMAT_RGB565,
        DRM_FORMAT_XRGB8888,
@@ -67,18 +69,18 @@ static const uint32_t i965_primary_formats[] = {
        DRM_FORMAT_XBGR2101010,
 };
 
-static const uint64_t i9xx_format_modifiers[] = {
+static const u64 i9xx_format_modifiers[] = {
        I915_FORMAT_MOD_X_TILED,
        DRM_FORMAT_MOD_LINEAR,
        DRM_FORMAT_MOD_INVALID
 };
 
 /* Cursor formats */
-static const uint32_t intel_cursor_formats[] = {
+static const u32 intel_cursor_formats[] = {
        DRM_FORMAT_ARGB8888,
 };
 
-static const uint64_t cursor_format_modifiers[] = {
+static const u64 cursor_format_modifiers[] = {
        DRM_FORMAT_MOD_LINEAR,
        DRM_FORMAT_MOD_INVALID
 };
@@ -494,7 +496,7 @@ static int pnv_calc_dpll_params(int refclk, struct dpll *clock)
        return clock->dot;
 }
 
-static uint32_t i9xx_dpll_compute_m(struct dpll *dpll)
+static u32 i9xx_dpll_compute_m(struct dpll *dpll)
 {
        return 5 * (dpll->m1 + 2) + (dpll->m2 + 2);
 }
@@ -529,8 +531,8 @@ int chv_calc_dpll_params(int refclk, struct dpll *clock)
        clock->p = clock->p1 * clock->p2;
        if (WARN_ON(clock->n == 0 || clock->p == 0))
                return 0;
-       clock->vco = DIV_ROUND_CLOSEST_ULL((uint64_t)refclk * clock->m,
-                       clock->n << 22);
+       clock->vco = DIV_ROUND_CLOSEST_ULL((u64)refclk * clock->m,
+                                          clock->n << 22);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 
        return clock->dot / 5;
@@ -892,7 +894,7 @@ chv_find_best_dpll(const struct intel_limit *limit,
        struct drm_device *dev = crtc->base.dev;
        unsigned int best_error_ppm;
        struct dpll clock;
-       uint64_t m2;
+       u64 m2;
        int found = false;
 
        memset(best_clock, 0, sizeof(*best_clock));
@@ -914,7 +916,7 @@ chv_find_best_dpll(const struct intel_limit *limit,
 
                        clock.p = clock.p1 * clock.p2;
 
-                       m2 = DIV_ROUND_CLOSEST_ULL(((uint64_t)target * clock.p *
+                       m2 = DIV_ROUND_CLOSEST_ULL(((u64)target * clock.p *
                                        clock.n) << 22, refclk * clock.m1);
 
                        if (m2 > INT_MAX/clock.m1)
@@ -984,7 +986,7 @@ static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv,
        u32 line1, line2;
        u32 line_mask;
 
-       if (IS_GEN2(dev_priv))
+       if (IS_GEN(dev_priv, 2))
                line_mask = DSL_LINEMASK_GEN2;
        else
                line_mask = DSL_LINEMASK_GEN3;
@@ -1110,7 +1112,7 @@ static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv,
        u32 val;
 
        /* ILK FDI PLL is always enabled */
-       if (IS_GEN5(dev_priv))
+       if (IS_GEN(dev_priv, 5))
                return;
 
        /* On Haswell, DDI ports are responsible for the FDI PLL setup */
@@ -1198,17 +1200,19 @@ void assert_pipe(struct drm_i915_private *dev_priv,
        enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
                                                                      pipe);
        enum intel_display_power_domain power_domain;
+       intel_wakeref_t wakeref;
 
        /* we keep both pipes enabled on 830 */
        if (IS_I830(dev_priv))
                state = true;
 
        power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
-       if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
+       wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (wakeref) {
                u32 val = I915_READ(PIPECONF(cpu_transcoder));
                cur_state = !!(val & PIPECONF_ENABLE);
 
-               intel_display_power_put(dev_priv, power_domain);
+               intel_display_power_put(dev_priv, power_domain, wakeref);
        } else {
                cur_state = false;
        }
@@ -1609,7 +1613,7 @@ static void ironlake_enable_pch_transcoder(const struct intel_crtc_state *crtc_s
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
        i915_reg_t reg;
-       uint32_t val, pipeconf_val;
+       u32 val, pipeconf_val;
 
        /* Make sure PCH DPLL is enabled */
        assert_shared_dpll_enabled(dev_priv, crtc_state->shared_dpll);
@@ -1697,7 +1701,7 @@ static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
                                            enum pipe pipe)
 {
        i915_reg_t reg;
-       uint32_t val;
+       u32 val;
 
        /* FDI relies on the transcoder */
        assert_fdi_tx_disabled(dev_priv, pipe);
@@ -1850,7 +1854,7 @@ static void intel_disable_pipe(const struct intel_crtc_state *old_crtc_state)
 
 static unsigned int intel_tile_size(const struct drm_i915_private *dev_priv)
 {
-       return IS_GEN2(dev_priv) ? 2048 : 4096;
+       return IS_GEN(dev_priv, 2) ? 2048 : 4096;
 }
 
 static unsigned int
@@ -1863,7 +1867,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)
        case DRM_FORMAT_MOD_LINEAR:
                return cpp;
        case I915_FORMAT_MOD_X_TILED:
-               if (IS_GEN2(dev_priv))
+               if (IS_GEN(dev_priv, 2))
                        return 128;
                else
                        return 512;
@@ -1872,7 +1876,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)
                        return 128;
                /* fall through */
        case I915_FORMAT_MOD_Y_TILED:
-               if (IS_GEN2(dev_priv) || HAS_128_BYTE_Y_TILING(dev_priv))
+               if (IS_GEN(dev_priv, 2) || HAS_128_BYTE_Y_TILING(dev_priv))
                        return 128;
                else
                        return 512;
@@ -2024,6 +2028,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
        struct drm_device *dev = fb->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+       intel_wakeref_t wakeref;
        struct i915_vma *vma;
        unsigned int pinctl;
        u32 alignment;
@@ -2047,7 +2052,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
         * intel_runtime_pm_put(), so it is correct to wrap only the
         * pin/unpin/fence and not more.
         */
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
        atomic_inc(&dev_priv->gpu_error.pending_fb_pin);
 
@@ -2102,7 +2107,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
 err:
        atomic_dec(&dev_priv->gpu_error.pending_fb_pin);
 
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
        return vma;
 }
 
@@ -2373,7 +2378,7 @@ static int intel_fb_offset_to_xy(int *x, int *y,
        return 0;
 }
 
-static unsigned int intel_fb_modifier_to_tiling(uint64_t fb_modifier)
+static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier)
 {
        switch (fb_modifier) {
        case I915_FORMAT_MOD_X_TILED:
@@ -3193,8 +3198,8 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
 
        dspcntr = DISPLAY_PLANE_ENABLE | DISPPLANE_GAMMA_ENABLE;
 
-       if (IS_G4X(dev_priv) || IS_GEN5(dev_priv) ||
-           IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
+       if (IS_G4X(dev_priv) || IS_GEN(dev_priv, 5) ||
+           IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
                dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
 
        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
@@ -3412,6 +3417,7 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum intel_display_power_domain power_domain;
        enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
+       intel_wakeref_t wakeref;
        bool ret;
        u32 val;
 
@@ -3421,7 +3427,8 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
         * display power wells.
         */
        power_domain = POWER_DOMAIN_PIPE(plane->pipe);
-       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (!wakeref)
                return false;
 
        val = I915_READ(DSPCNTR(i9xx_plane));
@@ -3434,7 +3441,7 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
                *pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
                        DISPPLANE_SEL_PIPE_SHIFT;
 
-       intel_display_power_put(dev_priv, power_domain);
+       intel_display_power_put(dev_priv, power_domain, wakeref);
 
        return ret;
 }
@@ -3503,7 +3510,7 @@ u32 skl_plane_stride(const struct intel_plane_state *plane_state,
        return stride / skl_plane_stride_mult(fb, color_plane, rotation);
 }
 
-static u32 skl_plane_ctl_format(uint32_t pixel_format)
+static u32 skl_plane_ctl_format(u32 pixel_format)
 {
        switch (pixel_format) {
        case DRM_FORMAT_C8:
@@ -3573,7 +3580,7 @@ static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state
        }
 }
 
-static u32 skl_plane_ctl_tiling(uint64_t fb_modifier)
+static u32 skl_plane_ctl_tiling(u64 fb_modifier)
 {
        switch (fb_modifier) {
        case DRM_FORMAT_MOD_LINEAR:
@@ -3746,8 +3753,8 @@ __intel_display_resume(struct drm_device *dev,
 
 static bool gpu_reset_clobbers_display(struct drm_i915_private *dev_priv)
 {
-       return intel_has_gpu_reset(dev_priv) &&
-               INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv);
+       return (INTEL_INFO(dev_priv)->gpu_reset_clobbers_display &&
+               intel_has_gpu_reset(dev_priv));
 }
 
 void intel_prepare_reset(struct drm_i915_private *dev_priv)
@@ -4120,7 +4127,7 @@ static void gen6_fdi_link_train(struct intel_crtc *crtc,
        temp = I915_READ(reg);
        temp &= ~FDI_LINK_TRAIN_NONE;
        temp |= FDI_LINK_TRAIN_PATTERN_2;
-       if (IS_GEN6(dev_priv)) {
+       if (IS_GEN(dev_priv, 6)) {
                temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
                /* SNB-B */
                temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
@@ -4593,7 +4600,7 @@ static void ironlake_pch_transcoder_set_timings(const struct intel_crtc_state *c
 
 static void cpt_set_fdi_bc_bifurcation(struct drm_i915_private *dev_priv, bool enable)
 {
-       uint32_t temp;
+       u32 temp;
 
        temp = I915_READ(SOUTH_CHICKEN1);
        if (!!(temp & FDI_BC_BIFURCATION_SELECT) == enable)
@@ -4919,10 +4926,10 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
        /* range checks */
        if (src_w < SKL_MIN_SRC_W || src_h < SKL_MIN_SRC_H ||
            dst_w < SKL_MIN_DST_W || dst_h < SKL_MIN_DST_H ||
-           (IS_GEN11(dev_priv) &&
+           (IS_GEN(dev_priv, 11) &&
             (src_w > ICL_MAX_SRC_W || src_h > ICL_MAX_SRC_H ||
              dst_w > ICL_MAX_DST_W || dst_h > ICL_MAX_DST_H)) ||
-           (!IS_GEN11(dev_priv) &&
+           (!IS_GEN(dev_priv, 11) &&
             (src_w > SKL_MAX_SRC_W || src_h > SKL_MAX_SRC_H ||
              dst_w > SKL_MAX_DST_W || dst_h > SKL_MAX_DST_H))) {
                DRM_DEBUG_KMS("scaler_user index %u.%u: src %ux%u dst %ux%u "
@@ -5213,7 +5220,7 @@ intel_post_enable_primary(struct drm_crtc *crtc,
         * FIXME: Need to fix the logic to work when we turn off all planes
         * but leave the pipe running.
         */
-       if (IS_GEN2(dev_priv))
+       if (IS_GEN(dev_priv, 2))
                intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
 
        /* Underruns don't always raise interrupts, so check manually. */
@@ -5234,7 +5241,7 @@ intel_pre_disable_primary_noatomic(struct drm_crtc *crtc)
         * Gen2 reports pipe underruns whenever all planes are disabled.
         * So disable underrun reporting before all the planes get disabled.
         */
-       if (IS_GEN2(dev_priv))
+       if (IS_GEN(dev_priv, 2))
                intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
 
        hsw_disable_ips(to_intel_crtc_state(crtc->state));
@@ -5292,7 +5299,7 @@ static bool needs_nv12_wa(struct drm_i915_private *dev_priv,
                return false;
 
        /* WA Display #0827: Gen9:all */
-       if (IS_GEN9(dev_priv) && !IS_GEMINILAKE(dev_priv))
+       if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv))
                return true;
 
        return false;
@@ -5365,7 +5372,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state,
                 * Gen2 reports pipe underruns whenever all planes are disabled.
                 * So disable underrun reporting before all the planes get disabled.
                 */
-               if (IS_GEN2(dev_priv) && old_primary_state->visible &&
+               if (IS_GEN(dev_priv, 2) && old_primary_state->visible &&
                    (modeset || !new_primary_state->base.visible))
                        intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false);
        }
@@ -5578,6 +5585,26 @@ static void intel_encoders_post_pll_disable(struct drm_crtc *crtc,
        }
 }
 
+static void intel_encoders_update_pipe(struct drm_crtc *crtc,
+                                      struct intel_crtc_state *crtc_state,
+                                      struct drm_atomic_state *old_state)
+{
+       struct drm_connector_state *conn_state;
+       struct drm_connector *conn;
+       int i;
+
+       for_each_new_connector_in_state(old_state, conn, conn_state, i) {
+               struct intel_encoder *encoder =
+                       to_intel_encoder(conn_state->best_encoder);
+
+               if (conn_state->crtc != crtc)
+                       continue;
+
+               if (encoder->update_pipe)
+                       encoder->update_pipe(encoder, crtc_state, conn_state);
+       }
+}
+
 static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,
                                 struct drm_atomic_state *old_state)
 {
@@ -5641,7 +5668,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,
         * On ILK+ LUT must be loaded before the pipe is running but with
         * clocks enabled
         */
-       intel_color_load_luts(&pipe_config->base);
+       intel_color_load_luts(pipe_config);
 
        if (dev_priv->display.initial_watermarks != NULL)
                dev_priv->display.initial_watermarks(old_intel_state, pipe_config);
@@ -5696,7 +5723,7 @@ static void icl_pipe_mbus_enable(struct intel_crtc *crtc)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
-       uint32_t val;
+       u32 val;
 
        val = MBUS_DBOX_A_CREDIT(2);
        val |= MBUS_DBOX_BW_CREDIT(1);
@@ -5752,7 +5779,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
 
        haswell_set_pipemisc(pipe_config);
 
-       intel_color_set_csc(&pipe_config->base);
+       intel_color_set_csc(pipe_config);
 
        intel_crtc->active = true;
 
@@ -5771,7 +5798,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
         * On ILK+ LUT must be loaded before the pipe is running but with
         * clocks enabled
         */
-       intel_color_load_luts(&pipe_config->base);
+       intel_color_load_luts(pipe_config);
 
        /*
         * Display WA #1153: enable hardware to bypass the alpha math
@@ -6087,7 +6114,7 @@ static void modeset_put_power_domains(struct drm_i915_private *dev_priv,
        enum intel_display_power_domain domain;
 
        for_each_power_domain(domain, domains)
-               intel_display_power_put(dev_priv, domain);
+               intel_display_power_put_unchecked(dev_priv, domain);
 }
 
 static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
@@ -6117,7 +6144,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
 
        i9xx_set_pipeconf(pipe_config);
 
-       intel_color_set_csc(&pipe_config->base);
+       intel_color_set_csc(pipe_config);
 
        intel_crtc->active = true;
 
@@ -6137,7 +6164,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
 
        i9xx_pfit_enable(pipe_config);
 
-       intel_color_load_luts(&pipe_config->base);
+       intel_color_load_luts(pipe_config);
 
        dev_priv->display.initial_watermarks(old_intel_state,
                                             pipe_config);
@@ -6184,7 +6211,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
 
        intel_crtc->active = true;
 
-       if (!IS_GEN2(dev_priv))
+       if (!IS_GEN(dev_priv, 2))
                intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
 
        intel_encoders_pre_enable(crtc, pipe_config, old_state);
@@ -6193,7 +6220,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
 
        i9xx_pfit_enable(pipe_config);
 
-       intel_color_load_luts(&pipe_config->base);
+       intel_color_load_luts(pipe_config);
 
        if (dev_priv->display.initial_watermarks != NULL)
                dev_priv->display.initial_watermarks(old_intel_state,
@@ -6236,7 +6263,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
         * On gen2 planes are double buffered but the pipe isn't, so we must
         * wait for planes to fully turn off before disabling the pipe.
         */
-       if (IS_GEN2(dev_priv))
+       if (IS_GEN(dev_priv, 2))
                intel_wait_for_vblank(dev_priv, pipe);
 
        intel_encoders_disable(crtc, old_crtc_state, old_state);
@@ -6261,7 +6288,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
 
        intel_encoders_post_pll_disable(crtc, old_crtc_state, old_state);
 
-       if (!IS_GEN2(dev_priv))
+       if (!IS_GEN(dev_priv, 2))
                intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
 
        if (!dev_priv->display.initial_watermarks)
@@ -6334,7 +6361,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc,
 
        domains = intel_crtc->enabled_power_domains;
        for_each_power_domain(domain, domains)
-               intel_display_power_put(dev_priv, domain);
+               intel_display_power_put_unchecked(dev_priv, domain);
        intel_crtc->enabled_power_domains = 0;
 
        dev_priv->active_crtcs &= ~(1 << intel_crtc->pipe);
@@ -6600,9 +6627,9 @@ static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
                (crtc->pipe == PIPE_A || IS_I915G(dev_priv));
 }
 
-static uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)
+static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)
 {
-       uint32_t pixel_rate;
+       u32 pixel_rate;
 
        pixel_rate = pipe_config->base.adjusted_mode.crtc_clock;
 
@@ -6612,8 +6639,8 @@ static uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)
         */
 
        if (pipe_config->pch_pfit.enabled) {
-               uint64_t pipe_w, pipe_h, pfit_w, pfit_h;
-               uint32_t pfit_size = pipe_config->pch_pfit.size;
+               u64 pipe_w, pipe_h, pfit_w, pfit_h;
+               u32 pfit_size = pipe_config->pch_pfit.size;
 
                pipe_w = pipe_config->pipe_src_w;
                pipe_h = pipe_config->pipe_src_h;
@@ -6628,7 +6655,7 @@ static uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)
                if (WARN_ON(!pfit_w || !pfit_h))
                        return pixel_rate;
 
-               pixel_rate = div_u64((uint64_t) pixel_rate * pipe_w * pipe_h,
+               pixel_rate = div_u64((u64)pixel_rate * pipe_w * pipe_h,
                                     pfit_w * pfit_h);
        }
 
@@ -6724,7 +6751,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
 }
 
 static void
-intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den)
+intel_reduce_m_n_ratio(u32 *num, u32 *den)
 {
        while (*num > DATA_LINK_M_N_MASK ||
               *den > DATA_LINK_M_N_MASK) {
@@ -6734,7 +6761,7 @@ intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den)
 }
 
 static void compute_m_n(unsigned int m, unsigned int n,
-                       uint32_t *ret_m, uint32_t *ret_n,
+                       u32 *ret_m, u32 *ret_n,
                        bool constant_n)
 {
        /*
@@ -6749,7 +6776,7 @@ static void compute_m_n(unsigned int m, unsigned int n,
        else
                *ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX);
 
-       *ret_m = div_u64((uint64_t) m * *ret_n, n);
+       *ret_m = div_u64((u64)m * *ret_n, n);
        intel_reduce_m_n_ratio(ret_m, ret_n);
 }
 
@@ -6779,12 +6806,12 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
                && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
 }
 
-static uint32_t pnv_dpll_compute_fp(struct dpll *dpll)
+static u32 pnv_dpll_compute_fp(struct dpll *dpll)
 {
        return (1 << dpll->n) << 16 | dpll->m2;
 }
 
-static uint32_t i9xx_dpll_compute_fp(struct dpll *dpll)
+static u32 i9xx_dpll_compute_fp(struct dpll *dpll)
 {
        return dpll->n << 16 | dpll->m1 << 8 | dpll->m2;
 }
@@ -6868,7 +6895,7 @@ static bool transcoder_has_m2_n2(struct drm_i915_private *dev_priv,
         * Strictly speaking some registers are available before
         * gen7, but we only support DRRS on gen7+
         */
-       return IS_GEN7(dev_priv) || IS_CHERRYVIEW(dev_priv);
+       return IS_GEN(dev_priv, 7) || IS_CHERRYVIEW(dev_priv);
 }
 
 static void intel_cpu_transcoder_set_m_n(const struct intel_crtc_state *crtc_state,
@@ -7340,7 +7367,7 @@ static void intel_set_pipe_timings(const struct intel_crtc_state *crtc_state)
        enum pipe pipe = crtc->pipe;
        enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
        const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode;
-       uint32_t crtc_vtotal, crtc_vblank_end;
+       u32 crtc_vtotal, crtc_vblank_end;
        int vsyncshift = 0;
 
        /* We need to be careful not to changed the adjusted mode, for otherwise
@@ -7415,7 +7442,7 @@ static void intel_get_pipe_timings(struct intel_crtc *crtc,
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
-       uint32_t tmp;
+       u32 tmp;
 
        tmp = I915_READ(HTOTAL(cpu_transcoder));
        pipe_config->base.adjusted_mode.crtc_hdisplay = (tmp & 0xffff) + 1;
@@ -7486,7 +7513,7 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state)
 {
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       uint32_t pipeconf;
+       u32 pipeconf;
 
        pipeconf = 0;
 
@@ -7731,7 +7758,7 @@ static void i9xx_get_pfit_config(struct intel_crtc *crtc,
                                 struct intel_crtc_state *pipe_config)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       uint32_t tmp;
+       u32 tmp;
 
        if (INTEL_GEN(dev_priv) <= 3 &&
            (IS_I830(dev_priv) || !IS_MOBILE(dev_priv)))
@@ -7946,11 +7973,13 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum intel_display_power_domain power_domain;
-       uint32_t tmp;
+       intel_wakeref_t wakeref;
+       u32 tmp;
        bool ret;
 
        power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
-       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (!wakeref)
                return false;
 
        pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
@@ -8051,7 +8080,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
        ret = true;
 
 out:
-       intel_display_power_put(dev_priv, power_domain);
+       intel_display_power_put(dev_priv, power_domain, wakeref);
 
        return ret;
 }
@@ -8225,7 +8254,7 @@ static void ironlake_init_pch_refclk(struct drm_i915_private *dev_priv)
 
 static void lpt_reset_fdi_mphy(struct drm_i915_private *dev_priv)
 {
-       uint32_t tmp;
+       u32 tmp;
 
        tmp = I915_READ(SOUTH_CHICKEN2);
        tmp |= FDI_MPHY_IOSFSB_RESET_CTL;
@@ -8247,7 +8276,7 @@ static void lpt_reset_fdi_mphy(struct drm_i915_private *dev_priv)
 /* WaMPhyProgramming:hsw */
 static void lpt_program_fdi_mphy(struct drm_i915_private *dev_priv)
 {
-       uint32_t tmp;
+       u32 tmp;
 
        tmp = intel_sbi_read(dev_priv, 0x8008, SBI_MPHY);
        tmp &= ~(0xFF << 24);
@@ -8328,7 +8357,7 @@ static void lpt_program_fdi_mphy(struct drm_i915_private *dev_priv)
 static void lpt_enable_clkout_dp(struct drm_i915_private *dev_priv,
                                 bool with_spread, bool with_fdi)
 {
-       uint32_t reg, tmp;
+       u32 reg, tmp;
 
        if (WARN(with_fdi && !with_spread, "FDI requires downspread\n"))
                with_spread = true;
@@ -8367,7 +8396,7 @@ static void lpt_enable_clkout_dp(struct drm_i915_private *dev_priv,
 /* Sequence to disable CLKOUT_DP */
 static void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv)
 {
-       uint32_t reg, tmp;
+       u32 reg, tmp;
 
        mutex_lock(&dev_priv->sb_lock);
 
@@ -8392,7 +8421,7 @@ static void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv)
 
 #define BEND_IDX(steps) ((50 + (steps)) / 5)
 
-static const uint16_t sscdivintphase[] = {
+static const u16 sscdivintphase[] = {
        [BEND_IDX( 50)] = 0x3B23,
        [BEND_IDX( 45)] = 0x3B23,
        [BEND_IDX( 40)] = 0x3C23,
@@ -8424,7 +8453,7 @@ static const uint16_t sscdivintphase[] = {
  */
 static void lpt_bend_clkout_dp(struct drm_i915_private *dev_priv, int steps)
 {
-       uint32_t tmp;
+       u32 tmp;
        int idx = BEND_IDX(steps);
 
        if (WARN_ON(steps % 5 != 0))
@@ -8490,7 +8519,7 @@ static void ironlake_set_pipeconf(const struct intel_crtc_state *crtc_state)
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
-       uint32_t val;
+       u32 val;
 
        val = 0;
 
@@ -8837,7 +8866,7 @@ static void skylake_get_pfit_config(struct intel_crtc *crtc,
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct intel_crtc_scaler_state *scaler_state = &pipe_config->scaler_state;
-       uint32_t ps_ctrl = 0;
+       u32 ps_ctrl = 0;
        int id = -1;
        int i;
 
@@ -8849,6 +8878,7 @@ static void skylake_get_pfit_config(struct intel_crtc *crtc,
                        pipe_config->pch_pfit.enabled = true;
                        pipe_config->pch_pfit.pos = I915_READ(SKL_PS_WIN_POS(crtc->pipe, i));
                        pipe_config->pch_pfit.size = I915_READ(SKL_PS_WIN_SZ(crtc->pipe, i));
+                       scaler_state->scalers[i].in_use = true;
                        break;
                }
        }
@@ -8993,7 +9023,7 @@ static void ironlake_get_pfit_config(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       uint32_t tmp;
+       u32 tmp;
 
        tmp = I915_READ(PF_CTL(crtc->pipe));
 
@@ -9005,7 +9035,7 @@ static void ironlake_get_pfit_config(struct intel_crtc *crtc,
                /* We currently do not free assignements of panel fitters on
                 * ivb/hsw (since we don't use the higher upscaling modes which
                 * differentiates them) so just WARN about this case for now. */
-               if (IS_GEN7(dev_priv)) {
+               if (IS_GEN(dev_priv, 7)) {
                        WARN_ON((tmp & PF_PIPE_SEL_MASK_IVB) !=
                                PF_PIPE_SEL_IVB(crtc->pipe));
                }
@@ -9018,11 +9048,13 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        enum intel_display_power_domain power_domain;
-       uint32_t tmp;
+       intel_wakeref_t wakeref;
+       u32 tmp;
        bool ret;
 
        power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
-       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (!wakeref)
                return false;
 
        pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
@@ -9105,7 +9137,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
        ret = true;
 
 out:
-       intel_display_power_put(dev_priv, power_domain);
+       intel_display_power_put(dev_priv, power_domain, wakeref);
 
        return ret;
 }
@@ -9145,7 +9177,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
        I915_STATE_WARN(intel_irqs_enabled(dev_priv), "IRQs enabled\n");
 }
 
-static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv)
+static u32 hsw_read_dcomp(struct drm_i915_private *dev_priv)
 {
        if (IS_HASWELL(dev_priv))
                return I915_READ(D_COMP_HSW);
@@ -9153,7 +9185,7 @@ static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv)
                return I915_READ(D_COMP_BDW);
 }
 
-static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val)
+static void hsw_write_dcomp(struct drm_i915_private *dev_priv, u32 val)
 {
        if (IS_HASWELL(dev_priv)) {
                mutex_lock(&dev_priv->pcu_lock);
@@ -9178,7 +9210,7 @@ static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val)
 static void hsw_disable_lcpll(struct drm_i915_private *dev_priv,
                              bool switch_to_fclk, bool allow_power_down)
 {
-       uint32_t val;
+       u32 val;
 
        assert_can_disable_lcpll(dev_priv);
 
@@ -9225,7 +9257,7 @@ static void hsw_disable_lcpll(struct drm_i915_private *dev_priv,
  */
 static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
 {
-       uint32_t val;
+       u32 val;
 
        val = I915_READ(LCPLL_CTL);
 
@@ -9300,7 +9332,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
  */
 void hsw_enable_pc8(struct drm_i915_private *dev_priv)
 {
-       uint32_t val;
+       u32 val;
 
        DRM_DEBUG_KMS("Enabling package C8+\n");
 
@@ -9316,7 +9348,7 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv)
 
 void hsw_disable_pc8(struct drm_i915_private *dev_priv)
 {
-       uint32_t val;
+       u32 val;
 
        DRM_DEBUG_KMS("Disabling package C8+\n");
 
@@ -9438,7 +9470,7 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv,
                                struct intel_crtc_state *pipe_config)
 {
        enum intel_dpll_id id;
-       uint32_t ddi_pll_sel = I915_READ(PORT_CLK_SEL(port));
+       u32 ddi_pll_sel = I915_READ(PORT_CLK_SEL(port));
 
        switch (ddi_pll_sel) {
        case PORT_CLK_SEL_WRPLL1:
@@ -9495,7 +9527,9 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
         * XXX: Do intel_display_power_get_if_enabled before reading this (for
         * consistency and less surprising code; it's in always on power).
         */
-       for_each_set_bit(panel_transcoder, &panel_transcoder_mask, 32) {
+       for_each_set_bit(panel_transcoder,
+                        &panel_transcoder_mask,
+                        ARRAY_SIZE(INTEL_INFO(dev_priv)->trans_offsets)) {
                enum pipe trans_pipe;
 
                tmp = I915_READ(TRANS_DDI_FUNC_CTL(panel_transcoder));
@@ -9541,6 +9575,8 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
        power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder);
        if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
+
+       WARN_ON(*power_domain_mask & BIT_ULL(power_domain));
        *power_domain_mask |= BIT_ULL(power_domain);
 
        tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder));
@@ -9568,6 +9604,8 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,
                power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
                if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                        continue;
+
+               WARN_ON(*power_domain_mask & BIT_ULL(power_domain));
                *power_domain_mask |= BIT_ULL(power_domain);
 
                /*
@@ -9602,7 +9640,7 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        struct intel_shared_dpll *pll;
        enum port port;
-       uint32_t tmp;
+       u32 tmp;
 
        tmp = I915_READ(TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder));
 
@@ -9684,7 +9722,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 
        power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
        if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
+               WARN_ON(power_domain_mask & BIT_ULL(power_domain));
                power_domain_mask |= BIT_ULL(power_domain);
+
                if (INTEL_GEN(dev_priv) >= 9)
                        skylake_get_pfit_config(crtc, pipe_config);
                else
@@ -9714,7 +9754,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 
 out:
        for_each_power_domain(power_domain, power_domain_mask)
-               intel_display_power_put(dev_priv, power_domain);
+               intel_display_power_put_unchecked(dev_priv, power_domain);
 
        return active;
 }
@@ -9964,17 +10004,19 @@ static bool i845_cursor_get_hw_state(struct intel_plane *plane,
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum intel_display_power_domain power_domain;
+       intel_wakeref_t wakeref;
        bool ret;
 
        power_domain = POWER_DOMAIN_PIPE(PIPE_A);
-       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (!wakeref)
                return false;
 
        ret = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE;
 
        *pipe = PIPE_A;
 
-       intel_display_power_put(dev_priv, power_domain);
+       intel_display_power_put(dev_priv, power_domain, wakeref);
 
        return ret;
 }
@@ -9995,7 +10037,7 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
        u32 cntl = 0;
 
-       if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
+       if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
                cntl |= MCURSOR_TRICKLE_FEED_DISABLE;
 
        if (INTEL_GEN(dev_priv) <= 10) {
@@ -10197,6 +10239,7 @@ static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum intel_display_power_domain power_domain;
+       intel_wakeref_t wakeref;
        bool ret;
        u32 val;
 
@@ -10206,7 +10249,8 @@ static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
         * display power wells.
         */
        power_domain = POWER_DOMAIN_PIPE(plane->pipe);
-       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (!wakeref)
                return false;
 
        val = I915_READ(CURCNTR(plane->pipe));
@@ -10219,7 +10263,7 @@ static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
                *pipe = (val & MCURSOR_PIPE_SELECT_MASK) >>
                        MCURSOR_PIPE_SELECT_SHIFT;
 
-       intel_display_power_put(dev_priv, power_domain);
+       intel_display_power_put(dev_priv, power_domain, wakeref);
 
        return ret;
 }
@@ -10468,7 +10512,7 @@ static int i9xx_pll_refclk(struct drm_device *dev,
                return dev_priv->vbt.lvds_ssc_freq;
        else if (HAS_PCH_SPLIT(dev_priv))
                return 120000;
-       else if (!IS_GEN2(dev_priv))
+       else if (!IS_GEN(dev_priv, 2))
                return 96000;
        else
                return 48000;
@@ -10501,7 +10545,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
                clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
        }
 
-       if (!IS_GEN2(dev_priv)) {
+       if (!IS_GEN(dev_priv, 2)) {
                if (IS_PINEVIEW(dev_priv))
                        clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW) >>
                                DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW);
@@ -10653,20 +10697,17 @@ static void intel_crtc_destroy(struct drm_crtc *crtc)
 
 /**
  * intel_wm_need_update - Check whether watermarks need updating
- * @plane: drm plane
- * @state: new plane state
+ * @cur: current plane state
+ * @new: new plane state
  *
  * Check current plane state versus the new one to determine whether
  * watermarks need to be recalculated.
  *
  * Returns true or false.
  */
-static bool intel_wm_need_update(struct drm_plane *plane,
-                                struct drm_plane_state *state)
+static bool intel_wm_need_update(struct intel_plane_state *cur,
+                                struct intel_plane_state *new)
 {
-       struct intel_plane_state *new = to_intel_plane_state(state);
-       struct intel_plane_state *cur = to_intel_plane_state(plane->state);
-
        /* Update watermarks on tiling or size changes. */
        if (new->base.visible != cur->base.visible)
                return true;
@@ -10775,7 +10816,8 @@ int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_stat
                /* must disable cxsr around plane enable/disable */
                if (plane->id != PLANE_CURSOR)
                        pipe_config->disable_cxsr = true;
-       } else if (intel_wm_need_update(&plane->base, plane_state)) {
+       } else if (intel_wm_need_update(to_intel_plane_state(plane->base.state),
+                                       to_intel_plane_state(plane_state))) {
                if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv)) {
                        /* FIXME bollocks */
                        pipe_config->update_wm_pre = true;
@@ -10815,9 +10857,12 @@ int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_stat
         * Despite the w/a only being listed for IVB we assume that
         * the ILK/SNB note has similar ramifications, hence we apply
         * the w/a on all three platforms.
+        *
+        * With experimental results seems this is needed also for primary
+        * plane, not only sprite plane.
         */
-       if (plane->id == PLANE_SPRITE0 &&
-           (IS_GEN5(dev_priv) || IS_GEN6(dev_priv) ||
+       if (plane->id != PLANE_CURSOR &&
+           (IS_GEN_RANGE(dev_priv, 5, 6) ||
             IS_IVYBRIDGE(dev_priv)) &&
            (turn_on || (!needs_scaling(old_plane_state) &&
                         needs_scaling(to_intel_plane_state(plane_state)))))
@@ -10954,8 +10999,7 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state)
 static int intel_crtc_atomic_check(struct drm_crtc *crtc,
                                   struct drm_crtc_state *crtc_state)
 {
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc->dev);
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_crtc_state *pipe_config =
                to_intel_crtc_state(crtc_state);
@@ -10975,7 +11019,7 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
        }
 
        if (crtc_state->color_mgmt_changed) {
-               ret = intel_color_check(crtc, crtc_state);
+               ret = intel_color_check(pipe_config);
                if (ret)
                        return ret;
 
@@ -11004,9 +11048,7 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
                 * old state and the new state.  We can program these
                 * immediately.
                 */
-               ret = dev_priv->display.compute_intermediate_wm(dev,
-                                                               intel_crtc,
-                                                               pipe_config);
+               ret = dev_priv->display.compute_intermediate_wm(pipe_config);
                if (ret) {
                        DRM_DEBUG_KMS("No valid intermediate pipe watermarks are possible\n");
                        return ret;
@@ -11014,7 +11056,7 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
        }
 
        if (INTEL_GEN(dev_priv) >= 9) {
-               if (mode_changed)
+               if (mode_changed || pipe_config->update_pipe)
                        ret = skl_update_scaler_crtc(pipe_config);
 
                if (!ret)
@@ -11517,10 +11559,13 @@ encoder_retry:
                        continue;
 
                encoder = to_intel_encoder(connector_state->best_encoder);
-
-               if (!(encoder->compute_config(encoder, pipe_config, connector_state))) {
-                       DRM_DEBUG_KMS("Encoder config failure\n");
-                       return -EINVAL;
+               ret = encoder->compute_config(encoder, pipe_config,
+                                             connector_state);
+               if (ret < 0) {
+                       if (ret != -EDEADLK)
+                               DRM_DEBUG_KMS("Encoder config failure: %d\n",
+                                             ret);
+                       return ret;
                }
        }
 
@@ -11656,6 +11701,11 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
                (current_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED) &&
                !(pipe_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED);
 
+       if (fixup_inherited && !i915_modparams.fastboot) {
+               DRM_DEBUG_KMS("initial modeset and fastboot not set\n");
+               ret = false;
+       }
+
 #define PIPE_CONF_CHECK_X(name) do { \
        if (current_config->name != pipe_config->name) { \
                pipe_config_err(adjust, __stringify(name), \
@@ -11964,7 +12014,7 @@ static void verify_wm_state(struct drm_crtc *crtc,
        if (INTEL_GEN(dev_priv) < 9 || !new_state->active)
                return;
 
-       skl_pipe_wm_get_hw_state(crtc, &hw_wm);
+       skl_pipe_wm_get_hw_state(intel_crtc, &hw_wm);
        sw_wm = &to_intel_crtc_state(new_state)->wm.skl.optimal;
 
        skl_pipe_ddb_get_hw_state(intel_crtc, hw_ddb_y, hw_ddb_uv);
@@ -12378,7 +12428,7 @@ static void update_scanline_offset(const struct intel_crtc_state *crtc_state)
         * However if queried just before the start of vblank we'll get an
         * answer that's slightly in the future.
         */
-       if (IS_GEN2(dev_priv)) {
+       if (IS_GEN(dev_priv, 2)) {
                const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode;
                int vtotal;
 
@@ -12619,9 +12669,9 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
  * phase.  The code here should be run after the per-crtc and per-plane 'check'
  * handlers to ensure that all derived state has been updated.
  */
-static int calc_watermark_data(struct drm_atomic_state *state)
+static int calc_watermark_data(struct intel_atomic_state *state)
 {
-       struct drm_device *dev = state->dev;
+       struct drm_device *dev = state->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
 
        /* Is there platform-specific watermark information to calculate? */
@@ -12679,8 +12729,7 @@ static int intel_atomic_check(struct drm_device *dev,
                        return ret;
                }
 
-               if (i915_modparams.fastboot &&
-                   intel_pipe_config_compare(dev_priv,
+               if (intel_pipe_config_compare(dev_priv,
                                        to_intel_crtc_state(old_crtc_state),
                                        pipe_config, true)) {
                        crtc_state->mode_changed = false;
@@ -12695,6 +12744,10 @@ static int intel_atomic_check(struct drm_device *dev,
                                       "[modeset]" : "[fastset]");
        }
 
+       ret = drm_dp_mst_atomic_check(state);
+       if (ret)
+               return ret;
+
        if (any_ms) {
                ret = intel_modeset_checks(state);
 
@@ -12713,7 +12766,7 @@ static int intel_atomic_check(struct drm_device *dev,
                return ret;
 
        intel_fbc_choose_crtc(dev_priv, intel_state);
-       return calc_watermark_data(state);
+       return calc_watermark_data(intel_state);
 }
 
 static int intel_atomic_prepare_commit(struct drm_device *dev,
@@ -12755,9 +12808,14 @@ static void intel_update_crtc(struct drm_crtc *crtc,
        } else {
                intel_pre_plane_update(to_intel_crtc_state(old_crtc_state),
                                       pipe_config);
+
+               if (pipe_config->update_pipe)
+                       intel_encoders_update_pipe(crtc, pipe_config, state);
        }
 
-       if (new_plane_state)
+       if (pipe_config->update_pipe && !pipe_config->enable_fbc)
+               intel_fbc_disable(intel_crtc);
+       else if (new_plane_state)
                intel_fbc_enable(intel_crtc, pipe_config, new_plane_state);
 
        intel_begin_crtc_commit(crtc, old_crtc_state);
@@ -12930,6 +12988,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
        struct drm_crtc *crtc;
        struct intel_crtc *intel_crtc;
        u64 put_domains[I915_MAX_PIPES] = {};
+       intel_wakeref_t wakeref = 0;
        int i;
 
        intel_atomic_commit_fence_wait(intel_state);
@@ -12937,7 +12996,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
        drm_atomic_helper_wait_for_dependencies(state);
 
        if (intel_state->modeset)
-               intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
+               wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
 
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
                old_intel_crtc_state = to_intel_crtc_state(old_crtc_state);
@@ -13074,7 +13133,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
                 * the culprit.
                 */
                intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
-               intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
+               intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET, wakeref);
        }
 
        /*
@@ -13552,8 +13611,8 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc,
        if (!modeset &&
            (intel_cstate->base.color_mgmt_changed ||
             intel_cstate->update_pipe)) {
-               intel_color_set_csc(&intel_cstate->base);
-               intel_color_load_luts(&intel_cstate->base);
+               intel_color_set_csc(intel_cstate);
+               intel_color_load_luts(intel_cstate);
        }
 
        /* Perform vblank evasion around commit operation */
@@ -13578,7 +13637,7 @@ void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
-       if (!IS_GEN2(dev_priv))
+       if (!IS_GEN(dev_priv, 2))
                intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true);
 
        if (crtc_state->has_pch_encoder) {
@@ -13702,8 +13761,8 @@ intel_legacy_cursor_update(struct drm_plane *plane,
                           struct drm_framebuffer *fb,
                           int crtc_x, int crtc_y,
                           unsigned int crtc_w, unsigned int crtc_h,
-                          uint32_t src_x, uint32_t src_y,
-                          uint32_t src_w, uint32_t src_h,
+                          u32 src_x, u32 src_y,
+                          u32 src_w, u32 src_h,
                           struct drm_modeset_acquire_ctx *ctx)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->dev);
@@ -14040,7 +14099,7 @@ static void intel_crtc_init_scalers(struct intel_crtc *crtc,
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        int i;
 
-       crtc->num_scalers = dev_priv->info.num_scalers[crtc->pipe];
+       crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[crtc->pipe];
        if (!crtc->num_scalers)
                return;
 
@@ -14126,7 +14185,7 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
 
        drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
 
-       intel_color_init(&intel_crtc->base);
+       intel_color_init(intel_crtc);
 
        WARN_ON(drm_crtc_index(&intel_crtc->base) != intel_crtc->pipe);
 
@@ -14177,7 +14236,7 @@ static int intel_encoder_clones(struct intel_encoder *encoder)
        return index_mask;
 }
 
-static bool has_edp_a(struct drm_i915_private *dev_priv)
+static bool ilk_has_edp_a(struct drm_i915_private *dev_priv)
 {
        if (!IS_MOBILE(dev_priv))
                return false;
@@ -14185,13 +14244,13 @@ static bool has_edp_a(struct drm_i915_private *dev_priv)
        if ((I915_READ(DP_A) & DP_DETECTED) == 0)
                return false;
 
-       if (IS_GEN5(dev_priv) && (I915_READ(FUSE_STRAP) & ILK_eDP_A_DISABLE))
+       if (IS_GEN(dev_priv, 5) && (I915_READ(FUSE_STRAP) & ILK_eDP_A_DISABLE))
                return false;
 
        return true;
 }
 
-static bool intel_crt_present(struct drm_i915_private *dev_priv)
+static bool intel_ddi_crt_present(struct drm_i915_private *dev_priv)
 {
        if (INTEL_GEN(dev_priv) >= 9)
                return false;
@@ -14199,15 +14258,12 @@ static bool intel_crt_present(struct drm_i915_private *dev_priv)
        if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv))
                return false;
 
-       if (IS_CHERRYVIEW(dev_priv))
-               return false;
-
        if (HAS_PCH_LPT_H(dev_priv) &&
            I915_READ(SFUSE_STRAP) & SFUSE_STRAP_CRT_DISABLED)
                return false;
 
        /* DDI E can't be used if DDI A requires 4 lanes */
-       if (HAS_DDI(dev_priv) && I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)
+       if (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)
                return false;
 
        if (!dev_priv->vbt.int_crt_support)
@@ -14262,23 +14318,19 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
        if (!HAS_DISPLAY(dev_priv))
                return;
 
-       /*
-        * intel_edp_init_connector() depends on this completing first, to
-        * prevent the registeration of both eDP and LVDS and the incorrect
-        * sharing of the PPS.
-        */
-       intel_lvds_init(dev_priv);
-
-       if (intel_crt_present(dev_priv))
-               intel_crt_init(dev_priv);
-
        if (IS_ICELAKE(dev_priv)) {
                intel_ddi_init(dev_priv, PORT_A);
                intel_ddi_init(dev_priv, PORT_B);
                intel_ddi_init(dev_priv, PORT_C);
                intel_ddi_init(dev_priv, PORT_D);
                intel_ddi_init(dev_priv, PORT_E);
-               intel_ddi_init(dev_priv, PORT_F);
+               /*
+                * On some ICL SKUs port F is not present. No strap bits for
+                * this, so rely on VBT.
+                */
+               if (intel_bios_is_port_present(dev_priv, PORT_F))
+                       intel_ddi_init(dev_priv, PORT_F);
+
                icl_dsi_init(dev_priv);
        } else if (IS_GEN9_LP(dev_priv)) {
                /*
@@ -14294,6 +14346,9 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
        } else if (HAS_DDI(dev_priv)) {
                int found;
 
+               if (intel_ddi_crt_present(dev_priv))
+                       intel_crt_init(dev_priv);
+
                /*
                 * Haswell uses DDI functions to detect digital outputs.
                 * On SKL pre-D0 the strap isn't connected, so we assume
@@ -14320,16 +14375,23 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
                 * On SKL we don't have a way to detect DDI-E so we rely on VBT.
                 */
                if (IS_GEN9_BC(dev_priv) &&
-                   (dev_priv->vbt.ddi_port_info[PORT_E].supports_dp ||
-                    dev_priv->vbt.ddi_port_info[PORT_E].supports_dvi ||
-                    dev_priv->vbt.ddi_port_info[PORT_E].supports_hdmi))
+                   intel_bios_is_port_present(dev_priv, PORT_E))
                        intel_ddi_init(dev_priv, PORT_E);
 
        } else if (HAS_PCH_SPLIT(dev_priv)) {
                int found;
+
+               /*
+                * intel_edp_init_connector() depends on this completing first,
+                * to prevent the registration of both eDP and LVDS and the
+                * incorrect sharing of the PPS.
+                */
+               intel_lvds_init(dev_priv);
+               intel_crt_init(dev_priv);
+
                dpd_is_edp = intel_dp_is_port_edp(dev_priv, PORT_D);
 
-               if (has_edp_a(dev_priv))
+               if (ilk_has_edp_a(dev_priv))
                        intel_dp_init(dev_priv, DP_A, PORT_A);
 
                if (I915_READ(PCH_HDMIB) & SDVO_DETECTED) {
@@ -14355,6 +14417,9 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
        } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
                bool has_edp, has_port;
 
+               if (IS_VALLEYVIEW(dev_priv) && dev_priv->vbt.int_crt_support)
+                       intel_crt_init(dev_priv);
+
                /*
                 * The DP_DETECTED bit is the latched state of the DDC
                 * SDA pin at boot. However since eDP doesn't require DDC
@@ -14397,9 +14462,17 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
                }
 
                vlv_dsi_init(dev_priv);
-       } else if (!IS_GEN2(dev_priv) && !IS_PINEVIEW(dev_priv)) {
+       } else if (IS_PINEVIEW(dev_priv)) {
+               intel_lvds_init(dev_priv);
+               intel_crt_init(dev_priv);
+       } else if (IS_GEN_RANGE(dev_priv, 3, 4)) {
                bool found = false;
 
+               if (IS_MOBILE(dev_priv))
+                       intel_lvds_init(dev_priv);
+
+               intel_crt_init(dev_priv);
+
                if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) {
                        DRM_DEBUG_KMS("probing SDVOB\n");
                        found = intel_sdvo_init(dev_priv, GEN3_SDVOB, PORT_B);
@@ -14431,11 +14504,16 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
 
                if (IS_G4X(dev_priv) && (I915_READ(DP_D) & DP_DETECTED))
                        intel_dp_init(dev_priv, DP_D, PORT_D);
-       } else if (IS_GEN2(dev_priv))
-               intel_dvo_init(dev_priv);
 
-       if (SUPPORTS_TV(dev_priv))
-               intel_tv_init(dev_priv);
+               if (SUPPORTS_TV(dev_priv))
+                       intel_tv_init(dev_priv);
+       } else if (IS_GEN(dev_priv, 2)) {
+               if (IS_I85X(dev_priv))
+                       intel_lvds_init(dev_priv);
+
+               intel_crt_init(dev_priv);
+               intel_dvo_init(dev_priv);
+       }
 
        intel_psr_init(dev_priv);
 
@@ -14629,7 +14707,7 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
                 * require the entire fb to accommodate that to avoid
                 * potential runtime errors at plane configuration time.
                 */
-               if (IS_GEN9(dev_priv) && i == 0 && fb->width > 3840 &&
+               if (IS_GEN(dev_priv, 9) && i == 0 && fb->width > 3840 &&
                    is_ccs_modifier(fb->modifier))
                        stride_alignment *= 4;
 
@@ -14834,7 +14912,7 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
                dev_priv->display.crtc_compute_clock = pnv_crtc_compute_clock;
                dev_priv->display.crtc_enable = i9xx_crtc_enable;
                dev_priv->display.crtc_disable = i9xx_crtc_disable;
-       } else if (!IS_GEN2(dev_priv)) {
+       } else if (!IS_GEN(dev_priv, 2)) {
                dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
                        i9xx_get_initial_plane_config;
@@ -14850,9 +14928,9 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
                dev_priv->display.crtc_disable = i9xx_crtc_disable;
        }
 
-       if (IS_GEN5(dev_priv)) {
+       if (IS_GEN(dev_priv, 5)) {
                dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
-       } else if (IS_GEN6(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 6)) {
                dev_priv->display.fdi_link_train = gen6_fdi_link_train;
        } else if (IS_IVYBRIDGE(dev_priv)) {
                /* FIXME: detect B0+ stepping and use auto training */
@@ -14984,12 +15062,12 @@ fail:
 
 static void intel_update_fdi_pll_freq(struct drm_i915_private *dev_priv)
 {
-       if (IS_GEN5(dev_priv)) {
+       if (IS_GEN(dev_priv, 5)) {
                u32 fdi_pll_clk =
                        I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK;
 
                dev_priv->fdi_pll_freq = (fdi_pll_clk + 2) * 10000;
-       } else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv)) {
                dev_priv->fdi_pll_freq = 270000;
        } else {
                return;
@@ -15105,10 +15183,10 @@ int intel_modeset_init(struct drm_device *dev)
        }
 
        /* maximum framebuffer dimensions */
-       if (IS_GEN2(dev_priv)) {
+       if (IS_GEN(dev_priv, 2)) {
                dev->mode_config.max_width = 2048;
                dev->mode_config.max_height = 2048;
-       } else if (IS_GEN3(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 3)) {
                dev->mode_config.max_width = 4096;
                dev->mode_config.max_height = 4096;
        } else {
@@ -15119,7 +15197,7 @@ int intel_modeset_init(struct drm_device *dev)
        if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
                dev->mode_config.cursor_width = IS_I845G(dev_priv) ? 64 : 512;
                dev->mode_config.cursor_height = 1023;
-       } else if (IS_GEN2(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 2)) {
                dev->mode_config.cursor_width = 64;
                dev->mode_config.cursor_height = 64;
        } else {
@@ -15476,19 +15554,25 @@ void i915_redisable_vga_power_on(struct drm_i915_private *dev_priv)
 
 void i915_redisable_vga(struct drm_i915_private *dev_priv)
 {
-       /* This function can be called both from intel_modeset_setup_hw_state or
+       intel_wakeref_t wakeref;
+
+       /*
+        * This function can be called both from intel_modeset_setup_hw_state or
         * at a very early point in our resume sequence, where the power well
         * structures are not yet restored. Since this function is at a very
         * paranoid "someone might have enabled VGA while we were not looking"
         * level, just check if the power well is enabled instead of trying to
         * follow the "don't touch the power well if we don't need it" policy
-        * the rest of the driver uses. */
-       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_VGA))
+        * the rest of the driver uses.
+        */
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    POWER_DOMAIN_VGA);
+       if (!wakeref)
                return;
 
        i915_redisable_vga_power_on(dev_priv);
 
-       intel_display_power_put(dev_priv, POWER_DOMAIN_VGA);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_VGA, wakeref);
 }
 
 /* FIXME read out full plane state for all planes */
@@ -15788,12 +15872,13 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
                             struct drm_modeset_acquire_ctx *ctx)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc *crtc;
        struct intel_crtc_state *crtc_state;
        struct intel_encoder *encoder;
+       struct intel_crtc *crtc;
+       intel_wakeref_t wakeref;
        int i;
 
-       intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+       wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
 
        intel_early_display_was(dev_priv);
        intel_modeset_readout_hw_state(dev);
@@ -15843,15 +15928,15 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
        }
 
        if (IS_G4X(dev_priv)) {
-               g4x_wm_get_hw_state(dev);
+               g4x_wm_get_hw_state(dev_priv);
                g4x_wm_sanitize(dev_priv);
        } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-               vlv_wm_get_hw_state(dev);
+               vlv_wm_get_hw_state(dev_priv);
                vlv_wm_sanitize(dev_priv);
        } else if (INTEL_GEN(dev_priv) >= 9) {
-               skl_wm_get_hw_state(dev);
+               skl_wm_get_hw_state(dev_priv);
        } else if (HAS_PCH_SPLIT(dev_priv)) {
-               ilk_wm_get_hw_state(dev);
+               ilk_wm_get_hw_state(dev_priv);
        }
 
        for_each_intel_crtc(dev, crtc) {
@@ -15863,7 +15948,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
                        modeset_put_power_domains(dev_priv, put_domains);
        }
 
-       intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
 
        intel_fbc_init_pipe_state(dev_priv);
 }
index 4262452963b31442363fe13ccf812c645a831fb7..c7c0686622884206a1fe89854527e7a6bced050e 100644 (file)
@@ -121,7 +121,7 @@ enum i9xx_plane_id {
 };
 
 #define plane_name(p) ((p) + 'A')
-#define sprite_name(p, s) ((p) * INTEL_INFO(dev_priv)->num_sprites[(p)] + (s) + 'A')
+#define sprite_name(p, s) ((p) * RUNTIME_INFO(dev_priv)->num_sprites[(p)] + (s) + 'A')
 
 /*
  * Per-pipe plane identifier.
@@ -311,12 +311,12 @@ struct intel_link_m_n {
 
 #define for_each_universal_plane(__dev_priv, __pipe, __p)              \
        for ((__p) = 0;                                                 \
-            (__p) < INTEL_INFO(__dev_priv)->num_sprites[(__pipe)] + 1; \
+            (__p) < RUNTIME_INFO(__dev_priv)->num_sprites[(__pipe)] + 1;       \
             (__p)++)
 
 #define for_each_sprite(__dev_priv, __p, __s)                          \
        for ((__s) = 0;                                                 \
-            (__s) < INTEL_INFO(__dev_priv)->num_sprites[(__p)];        \
+            (__s) < RUNTIME_INFO(__dev_priv)->num_sprites[(__p)];      \
             (__s)++)
 
 #define for_each_port_masked(__port, __ports_mask) \
index fdd2cbc56fa335b6bf084c00451eca8a0ef957e3..2e994b5ba40bd115c8b42df4ecd5bccacd087bdc 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/notifier.h>
 #include <linux/reboot.h>
 #include <asm/byteorder.h>
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
@@ -304,9 +303,11 @@ static int cnl_max_source_rate(struct intel_dp *intel_dp)
 static int icl_max_source_rate(struct intel_dp *intel_dp)
 {
        struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+       struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
        enum port port = dig_port->base.port;
 
-       if (port == PORT_B)
+       if (intel_port_is_combophy(dev_priv, port) &&
+           !intel_dp_is_edp(intel_dp))
                return 540000;
 
        return 810000;
@@ -344,7 +345,7 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp)
        if (INTEL_GEN(dev_priv) >= 10) {
                source_rates = cnl_rates;
                size = ARRAY_SIZE(cnl_rates);
-               if (IS_GEN10(dev_priv))
+               if (IS_GEN(dev_priv, 10))
                        max_rate = cnl_max_source_rate(intel_dp);
                else
                        max_rate = icl_max_source_rate(intel_dp);
@@ -428,7 +429,7 @@ static void intel_dp_set_common_rates(struct intel_dp *intel_dp)
 }
 
 static bool intel_dp_link_params_valid(struct intel_dp *intel_dp, int link_rate,
-                                      uint8_t lane_count)
+                                      u8 lane_count)
 {
        /*
         * FIXME: we need to synchronize the current link parameters with
@@ -448,7 +449,7 @@ static bool intel_dp_link_params_valid(struct intel_dp *intel_dp, int link_rate,
 
 static bool intel_dp_can_link_train_fallback_for_edp(struct intel_dp *intel_dp,
                                                     int link_rate,
-                                                    uint8_t lane_count)
+                                                    u8 lane_count)
 {
        const struct drm_display_mode *fixed_mode =
                intel_dp->attached_connector->panel.fixed_mode;
@@ -463,7 +464,7 @@ static bool intel_dp_can_link_train_fallback_for_edp(struct intel_dp *intel_dp,
 }
 
 int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
-                                           int link_rate, uint8_t lane_count)
+                                           int link_rate, u8 lane_count)
 {
        int index;
 
@@ -571,19 +572,19 @@ intel_dp_mode_valid(struct drm_connector *connector,
        return MODE_OK;
 }
 
-uint32_t intel_dp_pack_aux(const uint8_t *src, int src_bytes)
+u32 intel_dp_pack_aux(const u8 *src, int src_bytes)
 {
-       int     i;
-       uint32_t v = 0;
+       int i;
+       u32 v = 0;
 
        if (src_bytes > 4)
                src_bytes = 4;
        for (i = 0; i < src_bytes; i++)
-               v |= ((uint32_t) src[i]) << ((3-i) * 8);
+               v |= ((u32)src[i]) << ((3 - i) * 8);
        return v;
 }
 
-static void intel_dp_unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes)
+static void intel_dp_unpack_aux(u32 src, u8 *dst, int dst_bytes)
 {
        int i;
        if (dst_bytes > 4)
@@ -600,30 +601,39 @@ intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
 static void
 intel_dp_pps_init(struct intel_dp *intel_dp);
 
-static void pps_lock(struct intel_dp *intel_dp)
+static intel_wakeref_t
+pps_lock(struct intel_dp *intel_dp)
 {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+       intel_wakeref_t wakeref;
 
        /*
         * See intel_power_sequencer_reset() why we need
         * a power domain reference here.
         */
-       intel_display_power_get(dev_priv,
-                               intel_aux_power_domain(dp_to_dig_port(intel_dp)));
+       wakeref = intel_display_power_get(dev_priv,
+                                         intel_aux_power_domain(dp_to_dig_port(intel_dp)));
 
        mutex_lock(&dev_priv->pps_mutex);
+
+       return wakeref;
 }
 
-static void pps_unlock(struct intel_dp *intel_dp)
+static intel_wakeref_t
+pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wakeref)
 {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 
        mutex_unlock(&dev_priv->pps_mutex);
-
        intel_display_power_put(dev_priv,
-                               intel_aux_power_domain(dp_to_dig_port(intel_dp)));
+                               intel_aux_power_domain(dp_to_dig_port(intel_dp)),
+                               wakeref);
+       return 0;
 }
 
+#define with_pps_lock(dp, wf) \
+       for ((wf) = pps_lock(dp); (wf); (wf) = pps_unlock((dp), (wf)))
+
 static void
 vlv_power_sequencer_kick(struct intel_dp *intel_dp)
 {
@@ -633,7 +643,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
        bool pll_enabled, release_cl_override = false;
        enum dpio_phy phy = DPIO_PHY(pipe);
        enum dpio_channel ch = vlv_pipe_to_channel(pipe);
-       uint32_t DP;
+       u32 DP;
 
        if (WARN(I915_READ(intel_dp->output_reg) & DP_PORT_EN,
                 "skipping pipe %c power sequencer kick due to port %c being active\n",
@@ -972,30 +982,29 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
        struct intel_dp *intel_dp = container_of(this, typeof(* intel_dp),
                                                 edp_notifier);
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+       intel_wakeref_t wakeref;
 
        if (!intel_dp_is_edp(intel_dp) || code != SYS_RESTART)
                return 0;
 
-       pps_lock(intel_dp);
-
-       if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-               enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
-               i915_reg_t pp_ctrl_reg, pp_div_reg;
-               u32 pp_div;
-
-               pp_ctrl_reg = PP_CONTROL(pipe);
-               pp_div_reg  = PP_DIVISOR(pipe);
-               pp_div = I915_READ(pp_div_reg);
-               pp_div &= PP_REFERENCE_DIVIDER_MASK;
-
-               /* 0x1F write to PP_DIV_REG sets max cycle delay */
-               I915_WRITE(pp_div_reg, pp_div | 0x1F);
-               I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
-               msleep(intel_dp->panel_power_cycle_delay);
+       with_pps_lock(intel_dp, wakeref) {
+               if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+                       enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
+                       i915_reg_t pp_ctrl_reg, pp_div_reg;
+                       u32 pp_div;
+
+                       pp_ctrl_reg = PP_CONTROL(pipe);
+                       pp_div_reg  = PP_DIVISOR(pipe);
+                       pp_div = I915_READ(pp_div_reg);
+                       pp_div &= PP_REFERENCE_DIVIDER_MASK;
+
+                       /* 0x1F write to PP_DIV_REG sets max cycle delay */
+                       I915_WRITE(pp_div_reg, pp_div | 0x1F);
+                       I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS);
+                       msleep(intel_dp->panel_power_cycle_delay);
+               }
        }
 
-       pps_unlock(intel_dp);
-
        return 0;
 }
 
@@ -1041,12 +1050,12 @@ intel_dp_check_edp(struct intel_dp *intel_dp)
        }
 }
 
-static uint32_t
+static u32
 intel_dp_aux_wait_done(struct intel_dp *intel_dp)
 {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
        i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
-       uint32_t status;
+       u32 status;
        bool done;
 
 #define C (((status = I915_READ_NOTRACE(ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)
@@ -1059,7 +1068,7 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp)
        return status;
 }
 
-static uint32_t g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
+static u32 g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
 {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 
@@ -1073,7 +1082,7 @@ static uint32_t g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
        return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000);
 }
 
-static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
+static u32 ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
 {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
        struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
@@ -1092,7 +1101,7 @@ static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
                return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000);
 }
 
-static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
+static u32 hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
 {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
        struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
@@ -1109,7 +1118,7 @@ static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
        return ilk_get_aux_clock_divider(intel_dp, index);
 }
 
-static uint32_t skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
+static u32 skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
 {
        /*
         * SKL doesn't need us to program the AUX clock divider (Hardware will
@@ -1119,16 +1128,16 @@ static uint32_t skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
        return index ? 0 : 1;
 }
 
-static uint32_t g4x_get_aux_send_ctl(struct intel_dp *intel_dp,
-                                    int send_bytes,
-                                    uint32_t aux_clock_divider)
+static u32 g4x_get_aux_send_ctl(struct intel_dp *intel_dp,
+                               int send_bytes,
+                               u32 aux_clock_divider)
 {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct drm_i915_private *dev_priv =
                        to_i915(intel_dig_port->base.base.dev);
-       uint32_t precharge, timeout;
+       u32 precharge, timeout;
 
-       if (IS_GEN6(dev_priv))
+       if (IS_GEN(dev_priv, 6))
                precharge = 3;
        else
                precharge = 5;
@@ -1149,12 +1158,12 @@ static uint32_t g4x_get_aux_send_ctl(struct intel_dp *intel_dp,
               (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT);
 }
 
-static uint32_t skl_get_aux_send_ctl(struct intel_dp *intel_dp,
-                                     int send_bytes,
-                                     uint32_t unused)
+static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp,
+                               int send_bytes,
+                               u32 unused)
 {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-       uint32_t ret;
+       u32 ret;
 
        ret = DP_AUX_CH_CTL_SEND_BUSY |
              DP_AUX_CH_CTL_DONE |
@@ -1174,25 +1183,26 @@ static uint32_t skl_get_aux_send_ctl(struct intel_dp *intel_dp,
 
 static int
 intel_dp_aux_xfer(struct intel_dp *intel_dp,
-                 const uint8_t *send, int send_bytes,
-                 uint8_t *recv, int recv_size,
+                 const u8 *send, int send_bytes,
+                 u8 *recv, int recv_size,
                  u32 aux_send_ctl_flags)
 {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct drm_i915_private *dev_priv =
                        to_i915(intel_dig_port->base.base.dev);
        i915_reg_t ch_ctl, ch_data[5];
-       uint32_t aux_clock_divider;
+       u32 aux_clock_divider;
+       intel_wakeref_t wakeref;
        int i, ret, recv_bytes;
-       uint32_t status;
        int try, clock = 0;
+       u32 status;
        bool vdd;
 
        ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
        for (i = 0; i < ARRAY_SIZE(ch_data); i++)
                ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i);
 
-       pps_lock(intel_dp);
+       wakeref = pps_lock(intel_dp);
 
        /*
         * We will be called with VDD already enabled for dpcd/edid/oui reads.
@@ -1336,7 +1346,7 @@ out:
        if (vdd)
                edp_panel_vdd_off(intel_dp, false);
 
-       pps_unlock(intel_dp);
+       pps_unlock(intel_dp, wakeref);
 
        return ret;
 }
@@ -1358,7 +1368,7 @@ static ssize_t
 intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
 {
        struct intel_dp *intel_dp = container_of(aux, struct intel_dp, aux);
-       uint8_t txbuf[20], rxbuf[20];
+       u8 txbuf[20], rxbuf[20];
        size_t txsize, rxsize;
        int ret;
 
@@ -1691,7 +1701,7 @@ int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
 }
 
 void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
-                          uint8_t *link_bw, uint8_t *rate_select)
+                          u8 *link_bw, u8 *rate_select)
 {
        /* eDP 1.4 rate select method. */
        if (intel_dp->use_rate_select) {
@@ -1808,7 +1818,7 @@ intel_dp_adjust_compliance_config(struct intel_dp *intel_dp,
 }
 
 /* Optimize link config in order: max bpp, min clock, min lanes */
-static bool
+static int
 intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,
                                  struct intel_crtc_state *pipe_config,
                                  const struct link_config_limits *limits)
@@ -1834,17 +1844,17 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,
                                        pipe_config->pipe_bpp = bpp;
                                        pipe_config->port_clock = link_clock;
 
-                                       return true;
+                                       return 0;
                                }
                        }
                }
        }
 
-       return false;
+       return -EINVAL;
 }
 
 /* Optimize link config in order: max bpp, min lanes, min clock */
-static bool
+static int
 intel_dp_compute_link_config_fast(struct intel_dp *intel_dp,
                                  struct intel_crtc_state *pipe_config,
                                  const struct link_config_limits *limits)
@@ -1870,13 +1880,13 @@ intel_dp_compute_link_config_fast(struct intel_dp *intel_dp,
                                        pipe_config->pipe_bpp = bpp;
                                        pipe_config->port_clock = link_clock;
 
-                                       return true;
+                                       return 0;
                                }
                        }
                }
        }
 
-       return false;
+       return -EINVAL;
 }
 
 static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc)
@@ -1894,19 +1904,20 @@ static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc)
        return 0;
 }
 
-static bool intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
-                                       struct intel_crtc_state *pipe_config,
-                                       struct drm_connector_state *conn_state,
-                                       struct link_config_limits *limits)
+static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
+                                      struct intel_crtc_state *pipe_config,
+                                      struct drm_connector_state *conn_state,
+                                      struct link_config_limits *limits)
 {
        struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
        struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
        struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
        u8 dsc_max_bpc;
        int pipe_bpp;
+       int ret;
 
        if (!intel_dp_supports_dsc(intel_dp, pipe_config))
-               return false;
+               return -EINVAL;
 
        dsc_max_bpc = min_t(u8, DP_DSC_MAX_SUPPORTED_BPC,
                            conn_state->max_requested_bpc);
@@ -1914,7 +1925,7 @@ static bool intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
        pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, dsc_max_bpc);
        if (pipe_bpp < DP_DSC_MIN_SUPPORTED_BPC * 3) {
                DRM_DEBUG_KMS("No DSC support for less than 8bpc\n");
-               return false;
+               return -EINVAL;
        }
 
        /*
@@ -1948,7 +1959,7 @@ static bool intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
                                                     adjusted_mode->crtc_hdisplay);
                if (!dsc_max_output_bpp || !dsc_dp_slice_count) {
                        DRM_DEBUG_KMS("Compressed BPP/Slice Count not supported\n");
-                       return false;
+                       return -EINVAL;
                }
                pipe_config->dsc_params.compressed_bpp = min_t(u16,
                                                               dsc_max_output_bpp >> 4,
@@ -1965,16 +1976,19 @@ static bool intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
                        pipe_config->dsc_params.dsc_split = true;
                } else {
                        DRM_DEBUG_KMS("Cannot split stream to use 2 VDSC instances\n");
-                       return false;
+                       return -EINVAL;
                }
        }
-       if (intel_dp_compute_dsc_params(intel_dp, pipe_config) < 0) {
+
+       ret = intel_dp_compute_dsc_params(intel_dp, pipe_config);
+       if (ret < 0) {
                DRM_DEBUG_KMS("Cannot compute valid DSC parameters for Input Bpp = %d "
                              "Compressed BPP = %d\n",
                              pipe_config->pipe_bpp,
                              pipe_config->dsc_params.compressed_bpp);
-               return false;
+               return ret;
        }
+
        pipe_config->dsc_params.compression_enable = true;
        DRM_DEBUG_KMS("DP DSC computed with Input Bpp = %d "
                      "Compressed Bpp = %d Slice Count = %d\n",
@@ -1982,10 +1996,10 @@ static bool intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
                      pipe_config->dsc_params.compressed_bpp,
                      pipe_config->dsc_params.slice_count);
 
-       return true;
+       return 0;
 }
 
-static bool
+static int
 intel_dp_compute_link_config(struct intel_encoder *encoder,
                             struct intel_crtc_state *pipe_config,
                             struct drm_connector_state *conn_state)
@@ -1994,7 +2008,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
        struct link_config_limits limits;
        int common_len;
-       bool ret;
+       int ret;
 
        common_len = intel_dp_common_len_rate_limit(intel_dp,
                                                    intel_dp->max_link_rate);
@@ -2051,10 +2065,12 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
                                                        &limits);
 
        /* enable compression if the mode doesn't fit available BW */
-       if (!ret) {
-               if (!intel_dp_dsc_compute_config(intel_dp, pipe_config,
-                                                conn_state, &limits))
-                       return false;
+       DRM_DEBUG_KMS("Force DSC en = %d\n", intel_dp->force_dsc_en);
+       if (ret || intel_dp->force_dsc_en) {
+               ret = intel_dp_dsc_compute_config(intel_dp, pipe_config,
+                                                 conn_state, &limits);
+               if (ret < 0)
+                       return ret;
        }
 
        if (pipe_config->dsc_params.compression_enable) {
@@ -2079,10 +2095,10 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
                              intel_dp_max_data_rate(pipe_config->port_clock,
                                                     pipe_config->lane_count));
        }
-       return true;
+       return 0;
 }
 
-bool
+int
 intel_dp_compute_config(struct intel_encoder *encoder,
                        struct intel_crtc_state *pipe_config,
                        struct drm_connector_state *conn_state)
@@ -2098,6 +2114,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
                to_intel_digital_connector_state(conn_state);
        bool constant_n = drm_dp_has_quirk(&intel_dp->desc,
                                           DP_DPCD_QUIRK_CONSTANT_N);
+       int ret;
 
        if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && port != PORT_A)
                pipe_config->has_pch_encoder = true;
@@ -2119,8 +2136,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
                                       adjusted_mode);
 
                if (INTEL_GEN(dev_priv) >= 9) {
-                       int ret;
-
                        ret = skl_update_scaler_crtc(pipe_config);
                        if (ret)
                                return ret;
@@ -2135,20 +2150,21 @@ intel_dp_compute_config(struct intel_encoder *encoder,
        }
 
        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
-               return false;
+               return -EINVAL;
 
        if (HAS_GMCH_DISPLAY(dev_priv) &&
            adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
-               return false;
+               return -EINVAL;
 
        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
-               return false;
+               return -EINVAL;
 
        pipe_config->fec_enable = !intel_dp_is_edp(intel_dp) &&
                                  intel_dp_supports_fec(intel_dp, pipe_config);
 
-       if (!intel_dp_compute_link_config(encoder, pipe_config, conn_state))
-               return false;
+       ret = intel_dp_compute_link_config(encoder, pipe_config, conn_state);
+       if (ret < 0)
+               return ret;
 
        if (intel_conn_state->broadcast_rgb == INTEL_BROADCAST_RGB_AUTO) {
                /*
@@ -2196,11 +2212,11 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 
        intel_psr_compute_config(intel_dp, pipe_config);
 
-       return true;
+       return 0;
 }
 
 void intel_dp_set_link_params(struct intel_dp *intel_dp,
-                             int link_rate, uint8_t lane_count,
+                             int link_rate, u8 lane_count,
                              bool link_mst)
 {
        intel_dp->link_trained = false;
@@ -2462,15 +2478,15 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
  */
 void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
+       intel_wakeref_t wakeref;
        bool vdd;
 
        if (!intel_dp_is_edp(intel_dp))
                return;
 
-       pps_lock(intel_dp);
-       vdd = edp_panel_vdd_on(intel_dp);
-       pps_unlock(intel_dp);
-
+       vdd = false;
+       with_pps_lock(intel_dp, wakeref)
+               vdd = edp_panel_vdd_on(intel_dp);
        I915_STATE_WARN(!vdd, "eDP port %c VDD already requested on\n",
             port_name(dp_to_dig_port(intel_dp)->base.port));
 }
@@ -2509,19 +2525,21 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
        if ((pp & PANEL_POWER_ON) == 0)
                intel_dp->panel_power_off_time = ktime_get_boottime();
 
-       intel_display_power_put(dev_priv,
-                               intel_aux_power_domain(intel_dig_port));
+       intel_display_power_put_unchecked(dev_priv,
+                                         intel_aux_power_domain(intel_dig_port));
 }
 
 static void edp_panel_vdd_work(struct work_struct *__work)
 {
-       struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
-                                                struct intel_dp, panel_vdd_work);
+       struct intel_dp *intel_dp =
+               container_of(to_delayed_work(__work),
+                            struct intel_dp, panel_vdd_work);
+       intel_wakeref_t wakeref;
 
-       pps_lock(intel_dp);
-       if (!intel_dp->want_panel_vdd)
-               edp_panel_vdd_off_sync(intel_dp);
-       pps_unlock(intel_dp);
+       with_pps_lock(intel_dp, wakeref) {
+               if (!intel_dp->want_panel_vdd)
+                       edp_panel_vdd_off_sync(intel_dp);
+       }
 }
 
 static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
@@ -2585,7 +2603,7 @@ static void edp_panel_on(struct intel_dp *intel_dp)
 
        pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
        pp = ironlake_get_pp_control(intel_dp);
-       if (IS_GEN5(dev_priv)) {
+       if (IS_GEN(dev_priv, 5)) {
                /* ILK workaround: disable reset around power sequence */
                pp &= ~PANEL_POWER_RESET;
                I915_WRITE(pp_ctrl_reg, pp);
@@ -2593,7 +2611,7 @@ static void edp_panel_on(struct intel_dp *intel_dp)
        }
 
        pp |= PANEL_POWER_ON;
-       if (!IS_GEN5(dev_priv))
+       if (!IS_GEN(dev_priv, 5))
                pp |= PANEL_POWER_RESET;
 
        I915_WRITE(pp_ctrl_reg, pp);
@@ -2602,7 +2620,7 @@ static void edp_panel_on(struct intel_dp *intel_dp)
        wait_panel_on(intel_dp);
        intel_dp->last_power_on = jiffies;
 
-       if (IS_GEN5(dev_priv)) {
+       if (IS_GEN(dev_priv, 5)) {
                pp |= PANEL_POWER_RESET; /* restore panel reset bit */
                I915_WRITE(pp_ctrl_reg, pp);
                POSTING_READ(pp_ctrl_reg);
@@ -2611,12 +2629,13 @@ static void edp_panel_on(struct intel_dp *intel_dp)
 
 void intel_edp_panel_on(struct intel_dp *intel_dp)
 {
+       intel_wakeref_t wakeref;
+
        if (!intel_dp_is_edp(intel_dp))
                return;
 
-       pps_lock(intel_dp);
-       edp_panel_on(intel_dp);
-       pps_unlock(intel_dp);
+       with_pps_lock(intel_dp, wakeref)
+               edp_panel_on(intel_dp);
 }
 
 
@@ -2655,25 +2674,25 @@ static void edp_panel_off(struct intel_dp *intel_dp)
        intel_dp->panel_power_off_time = ktime_get_boottime();
 
        /* We got a reference when we enabled the VDD. */
-       intel_display_power_put(dev_priv, intel_aux_power_domain(dig_port));
+       intel_display_power_put_unchecked(dev_priv, intel_aux_power_domain(dig_port));
 }
 
 void intel_edp_panel_off(struct intel_dp *intel_dp)
 {
+       intel_wakeref_t wakeref;
+
        if (!intel_dp_is_edp(intel_dp))
                return;
 
-       pps_lock(intel_dp);
-       edp_panel_off(intel_dp);
-       pps_unlock(intel_dp);
+       with_pps_lock(intel_dp, wakeref)
+               edp_panel_off(intel_dp);
 }
 
 /* Enable backlight in the panel power control. */
 static void _intel_edp_backlight_on(struct intel_dp *intel_dp)
 {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-       u32 pp;
-       i915_reg_t pp_ctrl_reg;
+       intel_wakeref_t wakeref;
 
        /*
         * If we enable the backlight right away following a panel power
@@ -2683,17 +2702,16 @@ static void _intel_edp_backlight_on(struct intel_dp *intel_dp)
         */
        wait_backlight_on(intel_dp);
 
-       pps_lock(intel_dp);
-
-       pp = ironlake_get_pp_control(intel_dp);
-       pp |= EDP_BLC_ENABLE;
-
-       pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
+       with_pps_lock(intel_dp, wakeref) {
+               i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
+               u32 pp;
 
-       I915_WRITE(pp_ctrl_reg, pp);
-       POSTING_READ(pp_ctrl_reg);
+               pp = ironlake_get_pp_control(intel_dp);
+               pp |= EDP_BLC_ENABLE;
 
-       pps_unlock(intel_dp);
+               I915_WRITE(pp_ctrl_reg, pp);
+               POSTING_READ(pp_ctrl_reg);
+       }
 }
 
 /* Enable backlight PWM and backlight PP control. */
@@ -2715,23 +2733,21 @@ void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state,
 static void _intel_edp_backlight_off(struct intel_dp *intel_dp)
 {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-       u32 pp;
-       i915_reg_t pp_ctrl_reg;
+       intel_wakeref_t wakeref;
 
        if (!intel_dp_is_edp(intel_dp))
                return;
 
-       pps_lock(intel_dp);
-
-       pp = ironlake_get_pp_control(intel_dp);
-       pp &= ~EDP_BLC_ENABLE;
-
-       pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
+       with_pps_lock(intel_dp, wakeref) {
+               i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
+               u32 pp;
 
-       I915_WRITE(pp_ctrl_reg, pp);
-       POSTING_READ(pp_ctrl_reg);
+               pp = ironlake_get_pp_control(intel_dp);
+               pp &= ~EDP_BLC_ENABLE;
 
-       pps_unlock(intel_dp);
+               I915_WRITE(pp_ctrl_reg, pp);
+               POSTING_READ(pp_ctrl_reg);
+       }
 
        intel_dp->last_backlight_off = jiffies;
        edp_wait_backlight_off(intel_dp);
@@ -2759,12 +2775,12 @@ static void intel_edp_backlight_power(struct intel_connector *connector,
                                      bool enable)
 {
        struct intel_dp *intel_dp = intel_attached_dp(&connector->base);
+       intel_wakeref_t wakeref;
        bool is_enabled;
 
-       pps_lock(intel_dp);
-       is_enabled = ironlake_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
-       pps_unlock(intel_dp);
-
+       is_enabled = false;
+       with_pps_lock(intel_dp, wakeref)
+               is_enabled = ironlake_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
        if (is_enabled == enable)
                return;
 
@@ -2831,7 +2847,7 @@ static void ironlake_edp_pll_on(struct intel_dp *intel_dp,
         * 1. Wait for the start of vertical blank on the enabled pipe going to FDI
         * 2. Program DP PLL enable
         */
-       if (IS_GEN5(dev_priv))
+       if (IS_GEN(dev_priv, 5))
                intel_wait_for_vblank_if_active(dev_priv, !crtc->pipe);
 
        intel_dp->DP |= DP_PLL_ENABLE;
@@ -2981,16 +2997,18 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+       intel_wakeref_t wakeref;
        bool ret;
 
-       if (!intel_display_power_get_if_enabled(dev_priv,
-                                               encoder->power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    encoder->power_domain);
+       if (!wakeref)
                return false;
 
        ret = intel_dp_port_enabled(dev_priv, intel_dp->output_reg,
                                    encoder->port, pipe);
 
-       intel_display_power_put(dev_priv, encoder->power_domain);
+       intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
 
        return ret;
 }
@@ -3158,20 +3176,20 @@ static void chv_post_disable_dp(struct intel_encoder *encoder,
 
 static void
 _intel_dp_set_link_train(struct intel_dp *intel_dp,
-                        uint32_t *DP,
-                        uint8_t dp_train_pat)
+                        u32 *DP,
+                        u8 dp_train_pat)
 {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        enum port port = intel_dig_port->base.port;
-       uint8_t train_pat_mask = drm_dp_training_pattern_mask(intel_dp->dpcd);
+       u8 train_pat_mask = drm_dp_training_pattern_mask(intel_dp->dpcd);
 
        if (dp_train_pat & train_pat_mask)
                DRM_DEBUG_KMS("Using DP training pattern TPS%d\n",
                              dp_train_pat & train_pat_mask);
 
        if (HAS_DDI(dev_priv)) {
-               uint32_t temp = I915_READ(DP_TP_CTL(port));
+               u32 temp = I915_READ(DP_TP_CTL(port));
 
                if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
                        temp |= DP_TP_CTL_SCRAMBLE_DISABLE;
@@ -3270,24 +3288,23 @@ static void intel_enable_dp(struct intel_encoder *encoder,
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
        struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc);
-       uint32_t dp_reg = I915_READ(intel_dp->output_reg);
+       u32 dp_reg = I915_READ(intel_dp->output_reg);
        enum pipe pipe = crtc->pipe;
+       intel_wakeref_t wakeref;
 
        if (WARN_ON(dp_reg & DP_PORT_EN))
                return;
 
-       pps_lock(intel_dp);
-
-       if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-               vlv_init_panel_power_sequencer(encoder, pipe_config);
-
-       intel_dp_enable_port(intel_dp, pipe_config);
+       with_pps_lock(intel_dp, wakeref) {
+               if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+                       vlv_init_panel_power_sequencer(encoder, pipe_config);
 
-       edp_panel_vdd_on(intel_dp);
-       edp_panel_on(intel_dp);
-       edp_panel_vdd_off(intel_dp, true);
+               intel_dp_enable_port(intel_dp, pipe_config);
 
-       pps_unlock(intel_dp);
+               edp_panel_vdd_on(intel_dp);
+               edp_panel_on(intel_dp);
+               edp_panel_vdd_off(intel_dp, true);
+       }
 
        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
                unsigned int lane_mask = 0x0;
@@ -3490,14 +3507,14 @@ static void chv_dp_post_pll_disable(struct intel_encoder *encoder,
  * link status information
  */
 bool
-intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
+intel_dp_get_link_status(struct intel_dp *intel_dp, u8 link_status[DP_LINK_STATUS_SIZE])
 {
        return drm_dp_dpcd_read(&intel_dp->aux, DP_LANE0_1_STATUS, link_status,
                                DP_LINK_STATUS_SIZE) == DP_LINK_STATUS_SIZE;
 }
 
 /* These are source-specific values. */
-uint8_t
+u8
 intel_dp_voltage_max(struct intel_dp *intel_dp)
 {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
@@ -3516,8 +3533,8 @@ intel_dp_voltage_max(struct intel_dp *intel_dp)
                return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
 }
 
-uint8_t
-intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
+u8
+intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, u8 voltage_swing)
 {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
        struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
@@ -3562,12 +3579,12 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
        }
 }
 
-static uint32_t vlv_signal_levels(struct intel_dp *intel_dp)
+static u32 vlv_signal_levels(struct intel_dp *intel_dp)
 {
        struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
        unsigned long demph_reg_value, preemph_reg_value,
                uniqtranscale_reg_value;
-       uint8_t train_set = intel_dp->train_set[0];
+       u8 train_set = intel_dp->train_set[0];
 
        switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
        case DP_TRAIN_PRE_EMPH_LEVEL_0:
@@ -3648,12 +3665,12 @@ static uint32_t vlv_signal_levels(struct intel_dp *intel_dp)
        return 0;
 }
 
-static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
+static u32 chv_signal_levels(struct intel_dp *intel_dp)
 {
        struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
        u32 deemph_reg_value, margin_reg_value;
        bool uniq_trans_scale = false;
-       uint8_t train_set = intel_dp->train_set[0];
+       u8 train_set = intel_dp->train_set[0];
 
        switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
        case DP_TRAIN_PRE_EMPH_LEVEL_0:
@@ -3731,10 +3748,10 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
        return 0;
 }
 
-static uint32_t
-g4x_signal_levels(uint8_t train_set)
+static u32
+g4x_signal_levels(u8 train_set)
 {
-       uint32_t        signal_levels = 0;
+       u32 signal_levels = 0;
 
        switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
        case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
@@ -3770,8 +3787,8 @@ g4x_signal_levels(uint8_t train_set)
 }
 
 /* SNB CPU eDP voltage swing and pre-emphasis control */
-static uint32_t
-snb_cpu_edp_signal_levels(uint8_t train_set)
+static u32
+snb_cpu_edp_signal_levels(u8 train_set)
 {
        int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
                                         DP_TRAIN_PRE_EMPHASIS_MASK);
@@ -3798,8 +3815,8 @@ snb_cpu_edp_signal_levels(uint8_t train_set)
 }
 
 /* IVB CPU eDP voltage swing and pre-emphasis control */
-static uint32_t
-ivb_cpu_edp_signal_levels(uint8_t train_set)
+static u32
+ivb_cpu_edp_signal_levels(u8 train_set)
 {
        int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
                                         DP_TRAIN_PRE_EMPHASIS_MASK);
@@ -3834,8 +3851,8 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp)
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        enum port port = intel_dig_port->base.port;
-       uint32_t signal_levels, mask = 0;
-       uint8_t train_set = intel_dp->train_set[0];
+       u32 signal_levels, mask = 0;
+       u8 train_set = intel_dp->train_set[0];
 
        if (IS_GEN9_LP(dev_priv) || INTEL_GEN(dev_priv) >= 10) {
                signal_levels = bxt_signal_levels(intel_dp);
@@ -3849,7 +3866,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp)
        } else if (IS_IVYBRIDGE(dev_priv) && port == PORT_A) {
                signal_levels = ivb_cpu_edp_signal_levels(train_set);
                mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB;
-       } else if (IS_GEN6(dev_priv) && port == PORT_A) {
+       } else if (IS_GEN(dev_priv, 6) && port == PORT_A) {
                signal_levels = snb_cpu_edp_signal_levels(train_set);
                mask = EDP_LINK_TRAIN_VOL_EMP_MASK_SNB;
        } else {
@@ -3874,7 +3891,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp)
 
 void
 intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,
-                                      uint8_t dp_train_pat)
+                                      u8 dp_train_pat)
 {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct drm_i915_private *dev_priv =
@@ -3891,7 +3908,7 @@ void intel_dp_set_idle_link_train(struct intel_dp *intel_dp)
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        enum port port = intel_dig_port->base.port;
-       uint32_t val;
+       u32 val;
 
        if (!HAS_DDI(dev_priv))
                return;
@@ -3926,7 +3943,7 @@ intel_dp_link_down(struct intel_encoder *encoder,
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
        struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
        enum port port = encoder->port;
-       uint32_t DP = intel_dp->DP;
+       u32 DP = intel_dp->DP;
 
        if (WARN_ON(HAS_DDI(dev_priv)))
                return;
@@ -3985,12 +4002,49 @@ intel_dp_link_down(struct intel_encoder *encoder,
        intel_dp->DP = DP;
 
        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-               pps_lock(intel_dp);
-               intel_dp->active_pipe = INVALID_PIPE;
-               pps_unlock(intel_dp);
+               intel_wakeref_t wakeref;
+
+               with_pps_lock(intel_dp, wakeref)
+                       intel_dp->active_pipe = INVALID_PIPE;
        }
 }
 
+static void
+intel_dp_extended_receiver_capabilities(struct intel_dp *intel_dp)
+{
+       u8 dpcd_ext[6];
+
+       /*
+        * Prior to DP1.3 the bit represented by
+        * DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved.
+        * if it is set DP_DPCD_REV at 0000h could be at a value less than
+        * the true capability of the panel. The only way to check is to
+        * then compare 0000h and 2200h.
+        */
+       if (!(intel_dp->dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
+             DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT))
+               return;
+
+       if (drm_dp_dpcd_read(&intel_dp->aux, DP_DP13_DPCD_REV,
+                            &dpcd_ext, sizeof(dpcd_ext)) != sizeof(dpcd_ext)) {
+               DRM_ERROR("DPCD failed read at extended capabilities\n");
+               return;
+       }
+
+       if (intel_dp->dpcd[DP_DPCD_REV] > dpcd_ext[DP_DPCD_REV]) {
+               DRM_DEBUG_KMS("DPCD extended DPCD rev less than base DPCD rev\n");
+               return;
+       }
+
+       if (!memcmp(intel_dp->dpcd, dpcd_ext, sizeof(dpcd_ext)))
+               return;
+
+       DRM_DEBUG_KMS("Base DPCD: %*ph\n",
+                     (int)sizeof(intel_dp->dpcd), intel_dp->dpcd);
+
+       memcpy(intel_dp->dpcd, dpcd_ext, sizeof(dpcd_ext));
+}
+
 bool
 intel_dp_read_dpcd(struct intel_dp *intel_dp)
 {
@@ -3998,6 +4052,8 @@ intel_dp_read_dpcd(struct intel_dp *intel_dp)
                             sizeof(intel_dp->dpcd)) < 0)
                return false; /* aux transfer failed */
 
+       intel_dp_extended_receiver_capabilities(intel_dp);
+
        DRM_DEBUG_KMS("DPCD: %*ph\n", (int) sizeof(intel_dp->dpcd), intel_dp->dpcd);
 
        return intel_dp->dpcd[DP_DPCD_REV] != 0;
@@ -4228,7 +4284,7 @@ intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *sink_irq_vector)
                DP_DPRX_ESI_LEN;
 }
 
-u16 intel_dp_dsc_get_output_bpp(int link_clock, uint8_t lane_count,
+u16 intel_dp_dsc_get_output_bpp(int link_clock, u8 lane_count,
                                int mode_clock, int mode_hdisplay)
 {
        u16 bits_per_pixel, max_bpp_small_joiner_ram;
@@ -4295,7 +4351,7 @@ u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
                return 0;
        }
        /* Also take into account max slice width */
-       min_slice_count = min_t(uint8_t, min_slice_count,
+       min_slice_count = min_t(u8, min_slice_count,
                                DIV_ROUND_UP(mode_hdisplay,
                                             max_slice_width));
 
@@ -4313,11 +4369,11 @@ u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
        return 0;
 }
 
-static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)
+static u8 intel_dp_autotest_link_training(struct intel_dp *intel_dp)
 {
        int status = 0;
        int test_link_rate;
-       uint8_t test_lane_count, test_link_bw;
+       u8 test_lane_count, test_link_bw;
        /* (DP CTS 1.2)
         * 4.3.1.11
         */
@@ -4350,10 +4406,10 @@ static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)
        return DP_TEST_ACK;
 }
 
-static uint8_t intel_dp_autotest_video_pattern(struct intel_dp *intel_dp)
+static u8 intel_dp_autotest_video_pattern(struct intel_dp *intel_dp)
 {
-       uint8_t test_pattern;
-       uint8_t test_misc;
+       u8 test_pattern;
+       u8 test_misc;
        __be16 h_width, v_height;
        int status = 0;
 
@@ -4411,9 +4467,9 @@ static uint8_t intel_dp_autotest_video_pattern(struct intel_dp *intel_dp)
        return DP_TEST_ACK;
 }
 
-static uint8_t intel_dp_autotest_edid(struct intel_dp *intel_dp)
+static u8 intel_dp_autotest_edid(struct intel_dp *intel_dp)
 {
-       uint8_t test_result = DP_TEST_ACK;
+       u8 test_result = DP_TEST_ACK;
        struct intel_connector *intel_connector = intel_dp->attached_connector;
        struct drm_connector *connector = &intel_connector->base;
 
@@ -4455,16 +4511,16 @@ static uint8_t intel_dp_autotest_edid(struct intel_dp *intel_dp)
        return test_result;
 }
 
-static uint8_t intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp)
+static u8 intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp)
 {
-       uint8_t test_result = DP_TEST_NAK;
+       u8 test_result = DP_TEST_NAK;
        return test_result;
 }
 
 static void intel_dp_handle_test_request(struct intel_dp *intel_dp)
 {
-       uint8_t response = DP_TEST_NAK;
-       uint8_t request = 0;
+       u8 response = DP_TEST_NAK;
+       u8 request = 0;
        int status;
 
        status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_REQUEST, &request);
@@ -4790,8 +4846,8 @@ static enum drm_connector_status
 intel_dp_detect_dpcd(struct intel_dp *intel_dp)
 {
        struct intel_lspcon *lspcon = dp_to_lspcon(intel_dp);
-       uint8_t *dpcd = intel_dp->dpcd;
-       uint8_t type;
+       u8 *dpcd = intel_dp->dpcd;
+       u8 type;
 
        if (lspcon->active)
                lspcon_resume(lspcon);
@@ -5028,28 +5084,38 @@ static bool icl_combo_port_connected(struct drm_i915_private *dev_priv,
        return I915_READ(SDEISR) & SDE_DDI_HOTPLUG_ICP(port);
 }
 
+static const char *tc_type_name(enum tc_port_type type)
+{
+       static const char * const names[] = {
+               [TC_PORT_UNKNOWN] = "unknown",
+               [TC_PORT_LEGACY] = "legacy",
+               [TC_PORT_TYPEC] = "typec",
+               [TC_PORT_TBT] = "tbt",
+       };
+
+       if (WARN_ON(type >= ARRAY_SIZE(names)))
+               type = TC_PORT_UNKNOWN;
+
+       return names[type];
+}
+
 static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
                                    struct intel_digital_port *intel_dig_port,
                                    bool is_legacy, bool is_typec, bool is_tbt)
 {
        enum port port = intel_dig_port->base.port;
        enum tc_port_type old_type = intel_dig_port->tc_type;
-       const char *type_str;
 
        WARN_ON(is_legacy + is_typec + is_tbt != 1);
 
-       if (is_legacy) {
+       if (is_legacy)
                intel_dig_port->tc_type = TC_PORT_LEGACY;
-               type_str = "legacy";
-       } else if (is_typec) {
+       else if (is_typec)
                intel_dig_port->tc_type = TC_PORT_TYPEC;
-               type_str = "typec";
-       } else if (is_tbt) {
+       else if (is_tbt)
                intel_dig_port->tc_type = TC_PORT_TBT;
-               type_str = "tbt";
-       } else {
+       else
                return;
-       }
 
        /* Types are not supposed to be changed at runtime. */
        WARN_ON(old_type != TC_PORT_UNKNOWN &&
@@ -5057,12 +5123,9 @@ static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
 
        if (old_type != intel_dig_port->tc_type)
                DRM_DEBUG_KMS("Port %c has TC type %s\n", port_name(port),
-                             type_str);
+                             tc_type_name(intel_dig_port->tc_type));
 }
 
-static void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,
-                                 struct intel_digital_port *dig_port);
-
 /*
  * This function implements the first part of the Connect Flow described by our
  * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
@@ -5097,6 +5160,7 @@ static bool icl_tc_phy_connect(struct drm_i915_private *dev_priv,
        val = I915_READ(PORT_TX_DFLEXDPPMS);
        if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
                DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n", tc_port);
+               WARN_ON(dig_port->tc_legacy_port);
                return false;
        }
 
@@ -5128,8 +5192,8 @@ static bool icl_tc_phy_connect(struct drm_i915_private *dev_priv,
  * See the comment at the connect function. This implements the Disconnect
  * Flow.
  */
-static void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,
-                                 struct intel_digital_port *dig_port)
+void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,
+                          struct intel_digital_port *dig_port)
 {
        enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
 
@@ -5149,6 +5213,10 @@ static void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,
                I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
        }
 
+       DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
+                     port_name(dig_port->base.port),
+                     tc_type_name(dig_port->tc_type));
+
        dig_port->tc_type = TC_PORT_UNKNOWN;
 }
 
@@ -5170,7 +5238,14 @@ static bool icl_tc_port_connected(struct drm_i915_private *dev_priv,
        bool is_legacy, is_typec, is_tbt;
        u32 dpsp;
 
-       is_legacy = I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port);
+       /*
+        * WARN if we got a legacy port HPD, but VBT didn't mark the port as
+        * legacy. Treat the port as legacy from now on.
+        */
+       if (WARN_ON(!intel_dig_port->tc_legacy_port &&
+                   I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)))
+               intel_dig_port->tc_legacy_port = true;
+       is_legacy = intel_dig_port->tc_legacy_port;
 
        /*
         * The spec says we shouldn't be using the ISR bits for detecting
@@ -5182,6 +5257,7 @@ static bool icl_tc_port_connected(struct drm_i915_private *dev_priv,
 
        if (!is_legacy && !is_typec && !is_tbt) {
                icl_tc_phy_disconnect(dev_priv, intel_dig_port);
+
                return false;
        }
 
@@ -5233,17 +5309,17 @@ bool intel_digital_port_connected(struct intel_encoder *encoder)
 
        if (INTEL_GEN(dev_priv) >= 11)
                return icl_digital_port_connected(encoder);
-       else if (IS_GEN10(dev_priv) || IS_GEN9_BC(dev_priv))
+       else if (IS_GEN(dev_priv, 10) || IS_GEN9_BC(dev_priv))
                return spt_digital_port_connected(encoder);
        else if (IS_GEN9_LP(dev_priv))
                return bxt_digital_port_connected(encoder);
-       else if (IS_GEN8(dev_priv))
+       else if (IS_GEN(dev_priv, 8))
                return bdw_digital_port_connected(encoder);
-       else if (IS_GEN7(dev_priv))
+       else if (IS_GEN(dev_priv, 7))
                return ivb_digital_port_connected(encoder);
-       else if (IS_GEN6(dev_priv))
+       else if (IS_GEN(dev_priv, 6))
                return snb_digital_port_connected(encoder);
-       else if (IS_GEN5(dev_priv))
+       else if (IS_GEN(dev_priv, 5))
                return ilk_digital_port_connected(encoder);
 
        MISSING_CASE(INTEL_GEN(dev_priv));
@@ -5305,12 +5381,13 @@ intel_dp_detect(struct drm_connector *connector,
        enum drm_connector_status status;
        enum intel_display_power_domain aux_domain =
                intel_aux_power_domain(dig_port);
+       intel_wakeref_t wakeref;
 
        DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
                      connector->base.id, connector->name);
        WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
 
-       intel_display_power_get(dev_priv, aux_domain);
+       wakeref = intel_display_power_get(dev_priv, aux_domain);
 
        /* Can't disconnect eDP */
        if (intel_dp_is_edp(intel_dp))
@@ -5376,7 +5453,7 @@ intel_dp_detect(struct drm_connector *connector,
 
                ret = intel_dp_retrain_link(encoder, ctx);
                if (ret) {
-                       intel_display_power_put(dev_priv, aux_domain);
+                       intel_display_power_put(dev_priv, aux_domain, wakeref);
                        return ret;
                }
        }
@@ -5400,7 +5477,7 @@ out:
        if (status != connector_status_connected && !intel_dp->is_mst)
                intel_dp_unset_edid(intel_dp);
 
-       intel_display_power_put(dev_priv, aux_domain);
+       intel_display_power_put(dev_priv, aux_domain, wakeref);
        return status;
 }
 
@@ -5413,6 +5490,7 @@ intel_dp_force(struct drm_connector *connector)
        struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
        enum intel_display_power_domain aux_domain =
                intel_aux_power_domain(dig_port);
+       intel_wakeref_t wakeref;
 
        DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
                      connector->base.id, connector->name);
@@ -5421,11 +5499,11 @@ intel_dp_force(struct drm_connector *connector)
        if (connector->status != connector_status_connected)
                return;
 
-       intel_display_power_get(dev_priv, aux_domain);
+       wakeref = intel_display_power_get(dev_priv, aux_domain);
 
        intel_dp_set_edid(intel_dp);
 
-       intel_display_power_put(dev_priv, aux_domain);
+       intel_display_power_put(dev_priv, aux_domain, wakeref);
 }
 
 static int intel_dp_get_modes(struct drm_connector *connector)
@@ -5490,21 +5568,22 @@ intel_dp_connector_unregister(struct drm_connector *connector)
        intel_connector_unregister(connector);
 }
 
-void intel_dp_encoder_destroy(struct drm_encoder *encoder)
+void intel_dp_encoder_flush_work(struct drm_encoder *encoder)
 {
        struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
        struct intel_dp *intel_dp = &intel_dig_port->dp;
 
        intel_dp_mst_encoder_cleanup(intel_dig_port);
        if (intel_dp_is_edp(intel_dp)) {
+               intel_wakeref_t wakeref;
+
                cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
                /*
                 * vdd might still be enabled do to the delayed vdd off.
                 * Make sure vdd is actually turned off here.
                 */
-               pps_lock(intel_dp);
-               edp_panel_vdd_off_sync(intel_dp);
-               pps_unlock(intel_dp);
+               with_pps_lock(intel_dp, wakeref)
+                       edp_panel_vdd_off_sync(intel_dp);
 
                if (intel_dp->edp_notifier.notifier_call) {
                        unregister_reboot_notifier(&intel_dp->edp_notifier);
@@ -5513,14 +5592,20 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
        }
 
        intel_dp_aux_fini(intel_dp);
+}
+
+static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
+{
+       intel_dp_encoder_flush_work(encoder);
 
        drm_encoder_cleanup(encoder);
-       kfree(intel_dig_port);
+       kfree(enc_to_dig_port(encoder));
 }
 
 void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
 {
        struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+       intel_wakeref_t wakeref;
 
        if (!intel_dp_is_edp(intel_dp))
                return;
@@ -5530,9 +5615,8 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
         * Make sure vdd is actually turned off here.
         */
        cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-       pps_lock(intel_dp);
-       edp_panel_vdd_off_sync(intel_dp);
-       pps_unlock(intel_dp);
+       with_pps_lock(intel_dp, wakeref)
+               edp_panel_vdd_off_sync(intel_dp);
 }
 
 static
@@ -5545,7 +5629,7 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port,
                .address = DP_AUX_HDCP_AKSV,
                .size = DRM_HDCP_KSV_LEN,
        };
-       uint8_t txbuf[HEADER_SIZE + DRM_HDCP_KSV_LEN] = {}, rxbuf[2], reply = 0;
+       u8 txbuf[HEADER_SIZE + DRM_HDCP_KSV_LEN] = {}, rxbuf[2], reply = 0;
        ssize_t dpcd_ret;
        int ret;
 
@@ -5578,7 +5662,12 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port,
        }
 
        reply = (rxbuf[0] >> 4) & DP_AUX_NATIVE_REPLY_MASK;
-       return reply == DP_AUX_NATIVE_REPLY_ACK ? 0 : -EIO;
+       if (reply != DP_AUX_NATIVE_REPLY_ACK) {
+               DRM_DEBUG_KMS("Aksv write: no DP_AUX_NATIVE_REPLY_ACK %x\n",
+                             reply);
+               return -EIO;
+       }
+       return 0;
 }
 
 static int intel_dp_hdcp_read_bksv(struct intel_digital_port *intel_dig_port,
@@ -5808,6 +5897,7 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
        struct drm_i915_private *dev_priv = to_i915(encoder->dev);
        struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
        struct intel_lspcon *lspcon = dp_to_lspcon(intel_dp);
+       intel_wakeref_t wakeref;
 
        if (!HAS_DDI(dev_priv))
                intel_dp->DP = I915_READ(intel_dp->output_reg);
@@ -5817,18 +5907,19 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
 
        intel_dp->reset_link_params = true;
 
-       pps_lock(intel_dp);
-
-       if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-               intel_dp->active_pipe = vlv_active_pipe(intel_dp);
+       with_pps_lock(intel_dp, wakeref) {
+               if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+                       intel_dp->active_pipe = vlv_active_pipe(intel_dp);
 
-       if (intel_dp_is_edp(intel_dp)) {
-               /* Reinit the power sequencer, in case BIOS did something with it. */
-               intel_dp_pps_init(intel_dp);
-               intel_edp_panel_vdd_sanitize(intel_dp);
+               if (intel_dp_is_edp(intel_dp)) {
+                       /*
+                        * Reinit the power sequencer, in case BIOS did
+                        * something nasty with it.
+                        */
+                       intel_dp_pps_init(intel_dp);
+                       intel_edp_panel_vdd_sanitize(intel_dp);
+               }
        }
-
-       pps_unlock(intel_dp);
 }
 
 static const struct drm_connector_funcs intel_dp_connector_funcs = {
@@ -5861,6 +5952,7 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
        struct intel_dp *intel_dp = &intel_dig_port->dp;
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
        enum irqreturn ret = IRQ_NONE;
+       intel_wakeref_t wakeref;
 
        if (long_hpd && intel_dig_port->base.type == INTEL_OUTPUT_EDP) {
                /*
@@ -5883,8 +5975,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
                return IRQ_NONE;
        }
 
-       intel_display_power_get(dev_priv,
-                               intel_aux_power_domain(intel_dig_port));
+       wakeref = intel_display_power_get(dev_priv,
+                                         intel_aux_power_domain(intel_dig_port));
 
        if (intel_dp->is_mst) {
                if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
@@ -5914,7 +6006,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
 
 put_power:
        intel_display_power_put(dev_priv,
-                               intel_aux_power_domain(intel_dig_port));
+                               intel_aux_power_domain(intel_dig_port),
+                               wakeref);
 
        return ret;
 }
@@ -6361,8 +6454,8 @@ void intel_edp_drrs_enable(struct intel_dp *intel_dp,
        }
 
        mutex_lock(&dev_priv->drrs.mutex);
-       if (WARN_ON(dev_priv->drrs.dp)) {
-               DRM_ERROR("DRRS already enabled\n");
+       if (dev_priv->drrs.dp) {
+               DRM_DEBUG_KMS("DRRS already enabled\n");
                goto unlock;
        }
 
@@ -6622,8 +6715,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
        struct drm_display_mode *downclock_mode = NULL;
        bool has_dpcd;
        struct drm_display_mode *scan;
-       struct edid *edid;
        enum pipe pipe = INVALID_PIPE;
+       intel_wakeref_t wakeref;
+       struct edid *edid;
 
        if (!intel_dp_is_edp(intel_dp))
                return true;
@@ -6643,13 +6737,11 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
                return false;
        }
 
-       pps_lock(intel_dp);
-
-       intel_dp_init_panel_power_timestamps(intel_dp);
-       intel_dp_pps_init(intel_dp);
-       intel_edp_panel_vdd_sanitize(intel_dp);
-
-       pps_unlock(intel_dp);
+       with_pps_lock(intel_dp, wakeref) {
+               intel_dp_init_panel_power_timestamps(intel_dp);
+               intel_dp_pps_init(intel_dp);
+               intel_edp_panel_vdd_sanitize(intel_dp);
+       }
 
        /* Cache DPCD and EDID for edp. */
        has_dpcd = intel_edp_init_dpcd(intel_dp);
@@ -6734,9 +6826,8 @@ out_vdd_off:
         * vdd might still be enabled do to the delayed vdd off.
         * Make sure vdd is actually turned off here.
         */
-       pps_lock(intel_dp);
-       edp_panel_vdd_off_sync(intel_dp);
-       pps_unlock(intel_dp);
+       with_pps_lock(intel_dp, wakeref)
+               edp_panel_vdd_off_sync(intel_dp);
 
        return false;
 }
@@ -6910,6 +7001,7 @@ bool intel_dp_init(struct drm_i915_private *dev_priv,
        intel_encoder->compute_config = intel_dp_compute_config;
        intel_encoder->get_hw_state = intel_dp_get_hw_state;
        intel_encoder->get_config = intel_dp_get_config;
+       intel_encoder->update_pipe = intel_panel_update_backlight;
        intel_encoder->suspend = intel_dp_encoder_suspend;
        if (IS_CHERRYVIEW(dev_priv)) {
                intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable;
index 30be0e39bd5fda1afd705f44f840260d6177abbf..b59c87daa4f7a3e63251f8d681c55512c77a8ef6 100644 (file)
@@ -24,7 +24,7 @@
 #include "intel_drv.h"
 
 static void
-intel_dp_dump_link_status(const uint8_t link_status[DP_LINK_STATUS_SIZE])
+intel_dp_dump_link_status(const u8 link_status[DP_LINK_STATUS_SIZE])
 {
 
        DRM_DEBUG_KMS("ln0_1:0x%x ln2_3:0x%x align:0x%x sink:0x%x adj_req0_1:0x%x adj_req2_3:0x%x",
@@ -34,17 +34,17 @@ intel_dp_dump_link_status(const uint8_t link_status[DP_LINK_STATUS_SIZE])
 
 static void
 intel_get_adjust_train(struct intel_dp *intel_dp,
-                      const uint8_t link_status[DP_LINK_STATUS_SIZE])
+                      const u8 link_status[DP_LINK_STATUS_SIZE])
 {
-       uint8_t v = 0;
-       uint8_t p = 0;
+       u8 v = 0;
+       u8 p = 0;
        int lane;
-       uint8_t voltage_max;
-       uint8_t preemph_max;
+       u8 voltage_max;
+       u8 preemph_max;
 
        for (lane = 0; lane < intel_dp->lane_count; lane++) {
-               uint8_t this_v = drm_dp_get_adjust_request_voltage(link_status, lane);
-               uint8_t this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
+               u8 this_v = drm_dp_get_adjust_request_voltage(link_status, lane);
+               u8 this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
 
                if (this_v > v)
                        v = this_v;
@@ -66,9 +66,9 @@ intel_get_adjust_train(struct intel_dp *intel_dp,
 
 static bool
 intel_dp_set_link_train(struct intel_dp *intel_dp,
-                       uint8_t dp_train_pat)
+                       u8 dp_train_pat)
 {
-       uint8_t buf[sizeof(intel_dp->train_set) + 1];
+       u8 buf[sizeof(intel_dp->train_set) + 1];
        int ret, len;
 
        intel_dp_program_link_training_pattern(intel_dp, dp_train_pat);
@@ -92,7 +92,7 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 
 static bool
 intel_dp_reset_link_train(struct intel_dp *intel_dp,
-                       uint8_t dp_train_pat)
+                       u8 dp_train_pat)
 {
        memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
        intel_dp_set_signal_levels(intel_dp);
@@ -128,11 +128,11 @@ static bool intel_dp_link_max_vswing_reached(struct intel_dp *intel_dp)
 static bool
 intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
 {
-       uint8_t voltage;
+       u8 voltage;
        int voltage_tries, cr_tries, max_cr_tries;
        bool max_vswing_reached = false;
-       uint8_t link_config[2];
-       uint8_t link_bw, rate_select;
+       u8 link_config[2];
+       u8 link_bw, rate_select;
 
        if (intel_dp->prepare_link_retrain)
                intel_dp->prepare_link_retrain(intel_dp);
@@ -186,7 +186,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
 
        voltage_tries = 1;
        for (cr_tries = 0; cr_tries < max_cr_tries; ++cr_tries) {
-               uint8_t link_status[DP_LINK_STATUS_SIZE];
+               u8 link_status[DP_LINK_STATUS_SIZE];
 
                drm_dp_link_train_clock_recovery_delay(intel_dp->dpcd);
 
@@ -282,7 +282,7 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
 {
        int tries;
        u32 training_pattern;
-       uint8_t link_status[DP_LINK_STATUS_SIZE];
+       u8 link_status[DP_LINK_STATUS_SIZE];
        bool channel_eq = false;
 
        training_pattern = intel_dp_training_pattern(intel_dp);
index 4de247ddf05f80a89fc4d84aeaf93112c4d468f2..f90041cb336d336f9d1fe3573cfb44da2865453e 100644 (file)
  *
  */
 
-#include <drm/drmP.h>
 #include "i915_drv.h"
 #include "intel_drv.h"
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_edid.h>
 
-static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
-                                       struct intel_crtc_state *pipe_config,
-                                       struct drm_connector_state *conn_state)
+static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
+                                      struct intel_crtc_state *pipe_config,
+                                      struct drm_connector_state *conn_state)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
@@ -41,15 +40,19 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
        struct drm_connector *connector = conn_state->connector;
        void *port = to_intel_connector(connector)->port;
        struct drm_atomic_state *state = pipe_config->base.state;
+       struct drm_crtc *crtc = pipe_config->base.crtc;
+       struct drm_crtc_state *old_crtc_state =
+               drm_atomic_get_old_crtc_state(state, crtc);
        int bpp;
-       int lane_count, slots = 0;
+       int lane_count, slots =
+               to_intel_crtc_state(old_crtc_state)->dp_m_n.tu;
        const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
        int mst_pbn;
        bool constant_n = drm_dp_has_quirk(&intel_dp->desc,
                                           DP_DPCD_QUIRK_CONSTANT_N);
 
        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
-               return false;
+               return -EINVAL;
 
        pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
        pipe_config->has_pch_encoder = false;
@@ -86,7 +89,7 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
                if (slots < 0) {
                        DRM_DEBUG_KMS("failed finding vcpi slots:%d\n",
                                      slots);
-                       return false;
+                       return slots;
                }
        }
 
@@ -104,38 +107,42 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
 
        intel_ddi_compute_min_voltage_level(dev_priv, pipe_config);
 
-       return true;
+       return 0;
 }
 
-static int intel_dp_mst_atomic_check(struct drm_connector *connector,
-               struct drm_connector_state *new_conn_state)
+static int
+intel_dp_mst_atomic_check(struct drm_connector *connector,
+                         struct drm_connector_state *new_conn_state)
 {
        struct drm_atomic_state *state = new_conn_state->state;
-       struct drm_connector_state *old_conn_state;
-       struct drm_crtc *old_crtc;
+       struct drm_connector_state *old_conn_state =
+               drm_atomic_get_old_connector_state(state, connector);
+       struct intel_connector *intel_connector =
+               to_intel_connector(connector);
+       struct drm_crtc *new_crtc = new_conn_state->crtc;
        struct drm_crtc_state *crtc_state;
-       int slots, ret = 0;
-
-       old_conn_state = drm_atomic_get_old_connector_state(state, connector);
-       old_crtc = old_conn_state->crtc;
-       if (!old_crtc)
-               return ret;
+       struct drm_dp_mst_topology_mgr *mgr;
+       int ret = 0;
 
-       crtc_state = drm_atomic_get_new_crtc_state(state, old_crtc);
-       slots = to_intel_crtc_state(crtc_state)->dp_m_n.tu;
-       if (drm_atomic_crtc_needs_modeset(crtc_state) && slots > 0) {
-               struct drm_dp_mst_topology_mgr *mgr;
-               struct drm_encoder *old_encoder;
+       if (!old_conn_state->crtc)
+               return 0;
 
-               old_encoder = old_conn_state->best_encoder;
-               mgr = &enc_to_mst(old_encoder)->primary->dp.mst_mgr;
+       /* We only want to free VCPI if this state disables the CRTC on this
+        * connector
+        */
+       if (new_crtc) {
+               crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc);
 
-               ret = drm_dp_atomic_release_vcpi_slots(state, mgr, slots);
-               if (ret)
-                       DRM_DEBUG_KMS("failed releasing %d vcpi slots:%d\n", slots, ret);
-               else
-                       to_intel_crtc_state(crtc_state)->dp_m_n.tu = 0;
+               if (!crtc_state ||
+                   !drm_atomic_crtc_needs_modeset(crtc_state) ||
+                   crtc_state->enable)
+                       return 0;
        }
+
+       mgr = &enc_to_mst(old_conn_state->best_encoder)->primary->dp.mst_mgr;
+       ret = drm_dp_atomic_release_vcpi_slots(state, mgr,
+                                              intel_connector->port);
+
        return ret;
 }
 
@@ -240,7 +247,7 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder,
        struct intel_connector *connector =
                to_intel_connector(conn_state->connector);
        int ret;
-       uint32_t temp;
+       u32 temp;
 
        /* MST encoders are bound to a crtc, not to a connector,
         * force the mapping here for get_hw_state.
@@ -457,6 +464,7 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
        intel_connector->get_hw_state = intel_dp_mst_get_hw_state;
        intel_connector->mst_port = intel_dp;
        intel_connector->port = port;
+       drm_dp_mst_get_port_malloc(port);
 
        connector = &intel_connector->base;
        ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs,
@@ -517,20 +525,10 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
        drm_connector_put(connector);
 }
 
-static void intel_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
-{
-       struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr);
-       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-       struct drm_device *dev = intel_dig_port->base.base.dev;
-
-       drm_kms_helper_hotplug_event(dev);
-}
-
 static const struct drm_dp_mst_topology_cbs mst_cbs = {
        .add_connector = intel_dp_add_mst_connector,
        .register_connector = intel_dp_register_mst_connector,
        .destroy_connector = intel_dp_destroy_mst_connector,
-       .hotplug = intel_dp_mst_hotplug,
 };
 
 static struct intel_dp_mst_encoder *
index 3c7f10d1765824ba32d0899b6e50e84d488518e8..95cb8b154f87938946b22d1f867ac43e38fe9c37 100644 (file)
@@ -413,7 +413,7 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv,
        }
 
        if (phy_info->rcomp_phy != -1) {
-               uint32_t grc_code;
+               u32 grc_code;
 
                bxt_phy_wait_grc_done(dev_priv, phy_info->rcomp_phy);
 
@@ -445,7 +445,7 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv,
 void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy)
 {
        const struct bxt_ddi_phy_info *phy_info;
-       uint32_t val;
+       u32 val;
 
        phy_info = bxt_get_phy_info(dev_priv, phy);
 
@@ -515,7 +515,7 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv,
                              enum dpio_phy phy)
 {
        const struct bxt_ddi_phy_info *phy_info;
-       uint32_t mask;
+       u32 mask;
        bool ok;
 
        phy_info = bxt_get_phy_info(dev_priv, phy);
@@ -567,8 +567,8 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv,
 #undef _CHK
 }
 
-uint8_t
-bxt_ddi_phy_calc_lane_lat_optim_mask(uint8_t lane_count)
+u8
+bxt_ddi_phy_calc_lane_lat_optim_mask(u8 lane_count)
 {
        switch (lane_count) {
        case 1:
@@ -585,7 +585,7 @@ bxt_ddi_phy_calc_lane_lat_optim_mask(uint8_t lane_count)
 }
 
 void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder,
-                                    uint8_t lane_lat_optim_mask)
+                                    u8 lane_lat_optim_mask)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        enum port port = encoder->port;
@@ -610,7 +610,7 @@ void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder,
        }
 }
 
-uint8_t
+u8
 bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
@@ -618,7 +618,7 @@ bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder)
        enum dpio_phy phy;
        enum dpio_channel ch;
        int lane;
-       uint8_t mask;
+       u8 mask;
 
        bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
 
@@ -739,7 +739,7 @@ void chv_data_lane_soft_reset(struct intel_encoder *encoder,
        enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
        enum pipe pipe = crtc->pipe;
-       uint32_t val;
+       u32 val;
 
        val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
        if (reset)
index d513ca875c67693cf508c389367febdd3ae320d0..606f54dde086b2d1093e879c2182fcda1698553d 100644 (file)
@@ -345,9 +345,12 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
                                      struct intel_dpll_hw_state *hw_state)
 {
        const enum intel_dpll_id id = pll->info->id;
-       uint32_t val;
+       intel_wakeref_t wakeref;
+       u32 val;
 
-       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    POWER_DOMAIN_PLLS);
+       if (!wakeref)
                return false;
 
        val = I915_READ(PCH_DPLL(id));
@@ -355,7 +358,7 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
        hw_state->fp0 = I915_READ(PCH_FP0(id));
        hw_state->fp1 = I915_READ(PCH_FP1(id));
 
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
 
        return val & DPLL_VCO_ENABLE;
 }
@@ -487,7 +490,7 @@ static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
                                  struct intel_shared_dpll *pll)
 {
        const enum intel_dpll_id id = pll->info->id;
-       uint32_t val;
+       u32 val;
 
        val = I915_READ(WRPLL_CTL(id));
        I915_WRITE(WRPLL_CTL(id), val & ~WRPLL_PLL_ENABLE);
@@ -497,7 +500,7 @@ static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
 static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
                                 struct intel_shared_dpll *pll)
 {
-       uint32_t val;
+       u32 val;
 
        val = I915_READ(SPLL_CTL);
        I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
@@ -509,15 +512,18 @@ static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
                                       struct intel_dpll_hw_state *hw_state)
 {
        const enum intel_dpll_id id = pll->info->id;
-       uint32_t val;
+       intel_wakeref_t wakeref;
+       u32 val;
 
-       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    POWER_DOMAIN_PLLS);
+       if (!wakeref)
                return false;
 
        val = I915_READ(WRPLL_CTL(id));
        hw_state->wrpll = val;
 
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
 
        return val & WRPLL_PLL_ENABLE;
 }
@@ -526,15 +532,18 @@ static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
                                      struct intel_shared_dpll *pll,
                                      struct intel_dpll_hw_state *hw_state)
 {
-       uint32_t val;
+       intel_wakeref_t wakeref;
+       u32 val;
 
-       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    POWER_DOMAIN_PLLS);
+       if (!wakeref)
                return false;
 
        val = I915_READ(SPLL_CTL);
        hw_state->spll = val;
 
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
 
        return val & SPLL_PLL_ENABLE;
 }
@@ -630,11 +639,12 @@ static unsigned hsw_wrpll_get_budget_for_freq(int clock)
        return budget;
 }
 
-static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget,
-                                unsigned r2, unsigned n2, unsigned p,
+static void hsw_wrpll_update_rnp(u64 freq2k, unsigned int budget,
+                                unsigned int r2, unsigned int n2,
+                                unsigned int p,
                                 struct hsw_wrpll_rnp *best)
 {
-       uint64_t a, b, c, d, diff, diff_best;
+       u64 a, b, c, d, diff, diff_best;
 
        /* No best (r,n,p) yet */
        if (best->p == 0) {
@@ -693,7 +703,7 @@ static void
 hsw_ddi_calculate_wrpll(int clock /* in Hz */,
                        unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
 {
-       uint64_t freq2k;
+       u64 freq2k;
        unsigned p, n2, r2;
        struct hsw_wrpll_rnp best = { 0, 0, 0 };
        unsigned budget;
@@ -759,7 +769,7 @@ static struct intel_shared_dpll *hsw_ddi_hdmi_get_dpll(int clock,
                                                       struct intel_crtc_state *crtc_state)
 {
        struct intel_shared_dpll *pll;
-       uint32_t val;
+       u32 val;
        unsigned int p, n2, r2;
 
        hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
@@ -921,7 +931,7 @@ static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv,
                                    struct intel_shared_dpll *pll)
 {
        const enum intel_dpll_id id = pll->info->id;
-       uint32_t val;
+       u32 val;
 
        val = I915_READ(DPLL_CTRL1);
 
@@ -986,12 +996,15 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
                                     struct intel_shared_dpll *pll,
                                     struct intel_dpll_hw_state *hw_state)
 {
-       uint32_t val;
+       u32 val;
        const struct skl_dpll_regs *regs = skl_dpll_regs;
        const enum intel_dpll_id id = pll->info->id;
+       intel_wakeref_t wakeref;
        bool ret;
 
-       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    POWER_DOMAIN_PLLS);
+       if (!wakeref)
                return false;
 
        ret = false;
@@ -1011,7 +1024,7 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
        ret = true;
 
 out:
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
 
        return ret;
 }
@@ -1020,12 +1033,15 @@ static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
                                       struct intel_shared_dpll *pll,
                                       struct intel_dpll_hw_state *hw_state)
 {
-       uint32_t val;
        const struct skl_dpll_regs *regs = skl_dpll_regs;
        const enum intel_dpll_id id = pll->info->id;
+       intel_wakeref_t wakeref;
+       u32 val;
        bool ret;
 
-       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    POWER_DOMAIN_PLLS);
+       if (!wakeref)
                return false;
 
        ret = false;
@@ -1041,15 +1057,15 @@ static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
        ret = true;
 
 out:
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
 
        return ret;
 }
 
 struct skl_wrpll_context {
-       uint64_t min_deviation;         /* current minimal deviation */
-       uint64_t central_freq;          /* chosen central freq */
-       uint64_t dco_freq;              /* chosen dco freq */
+       u64 min_deviation;              /* current minimal deviation */
+       u64 central_freq;               /* chosen central freq */
+       u64 dco_freq;                   /* chosen dco freq */
        unsigned int p;                 /* chosen divider */
 };
 
@@ -1065,11 +1081,11 @@ static void skl_wrpll_context_init(struct skl_wrpll_context *ctx)
 #define SKL_DCO_MAX_NDEVIATION 600
 
 static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
-                                 uint64_t central_freq,
-                                 uint64_t dco_freq,
+                                 u64 central_freq,
+                                 u64 dco_freq,
                                  unsigned int divider)
 {
-       uint64_t deviation;
+       u64 deviation;
 
        deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq),
                              central_freq);
@@ -1143,21 +1159,21 @@ static void skl_wrpll_get_multipliers(unsigned int p,
 }
 
 struct skl_wrpll_params {
-       uint32_t        dco_fraction;
-       uint32_t        dco_integer;
-       uint32_t        qdiv_ratio;
-       uint32_t        qdiv_mode;
-       uint32_t        kdiv;
-       uint32_t        pdiv;
-       uint32_t        central_freq;
+       u32 dco_fraction;
+       u32 dco_integer;
+       u32 qdiv_ratio;
+       u32 qdiv_mode;
+       u32 kdiv;
+       u32 pdiv;
+       u32 central_freq;
 };
 
 static void skl_wrpll_params_populate(struct skl_wrpll_params *params,
-                                     uint64_t afe_clock,
-                                     uint64_t central_freq,
-                                     uint32_t p0, uint32_t p1, uint32_t p2)
+                                     u64 afe_clock,
+                                     u64 central_freq,
+                                     u32 p0, u32 p1, u32 p2)
 {
-       uint64_t dco_freq;
+       u64 dco_freq;
 
        switch (central_freq) {
        case 9600000000ULL:
@@ -1223,10 +1239,10 @@ static bool
 skl_ddi_calculate_wrpll(int clock /* in Hz */,
                        struct skl_wrpll_params *wrpll_params)
 {
-       uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
-       uint64_t dco_central_freq[3] = {8400000000ULL,
-                                       9000000000ULL,
-                                       9600000000ULL};
+       u64 afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
+       u64 dco_central_freq[3] = { 8400000000ULL,
+                                   9000000000ULL,
+                                   9600000000ULL };
        static const int even_dividers[] = {  4,  6,  8, 10, 12, 14, 16, 18, 20,
                                             24, 28, 30, 32, 36, 40, 42, 44,
                                             48, 52, 54, 56, 60, 64, 66, 68,
@@ -1250,7 +1266,7 @@ skl_ddi_calculate_wrpll(int clock /* in Hz */,
                for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) {
                        for (i = 0; i < dividers[d].n_dividers; i++) {
                                unsigned int p = dividers[d].list[i];
-                               uint64_t dco_freq = p * afe_clock;
+                               u64 dco_freq = p * afe_clock;
 
                                skl_wrpll_try_divider(&ctx,
                                                      dco_central_freq[dco],
@@ -1296,7 +1312,7 @@ static bool skl_ddi_hdmi_pll_dividers(struct intel_crtc *crtc,
                                      struct intel_crtc_state *crtc_state,
                                      int clock)
 {
-       uint32_t ctrl1, cfgcr1, cfgcr2;
+       u32 ctrl1, cfgcr1, cfgcr2;
        struct skl_wrpll_params wrpll_params = { 0, };
 
        /*
@@ -1333,7 +1349,7 @@ static bool
 skl_ddi_dp_set_dpll_hw_state(int clock,
                             struct intel_dpll_hw_state *dpll_hw_state)
 {
-       uint32_t ctrl1;
+       u32 ctrl1;
 
        /*
         * See comment in intel_dpll_hw_state to understand why we always use 0
@@ -1435,7 +1451,7 @@ static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = {
 static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
                                struct intel_shared_dpll *pll)
 {
-       uint32_t temp;
+       u32 temp;
        enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */
        enum dpio_phy phy;
        enum dpio_channel ch;
@@ -1556,7 +1572,7 @@ static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
                                        struct intel_shared_dpll *pll)
 {
        enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */
-       uint32_t temp;
+       u32 temp;
 
        temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
        temp &= ~PORT_PLL_ENABLE;
@@ -1579,14 +1595,17 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
                                        struct intel_dpll_hw_state *hw_state)
 {
        enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */
-       uint32_t val;
-       bool ret;
+       intel_wakeref_t wakeref;
        enum dpio_phy phy;
        enum dpio_channel ch;
+       u32 val;
+       bool ret;
 
        bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
 
-       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    POWER_DOMAIN_PLLS);
+       if (!wakeref)
                return false;
 
        ret = false;
@@ -1643,7 +1662,7 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
        ret = true;
 
 out:
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
 
        return ret;
 }
@@ -1651,12 +1670,12 @@ out:
 /* bxt clock parameters */
 struct bxt_clk_div {
        int clock;
-       uint32_t p1;
-       uint32_t p2;
-       uint32_t m2_int;
-       uint32_t m2_frac;
+       u32 p1;
+       u32 p2;
+       u32 m2_int;
+       u32 m2_frac;
        bool m2_frac_en;
-       uint32_t n;
+       u32 n;
 
        int vco;
 };
@@ -1723,8 +1742,8 @@ static bool bxt_ddi_set_dpll_hw_state(int clock,
                          struct intel_dpll_hw_state *dpll_hw_state)
 {
        int vco = clk_div->vco;
-       uint32_t prop_coef, int_coef, gain_ctl, targ_cnt;
-       uint32_t lanestagger;
+       u32 prop_coef, int_coef, gain_ctl, targ_cnt;
+       u32 lanestagger;
 
        if (vco >= 6200000 && vco <= 6700000) {
                prop_coef = 4;
@@ -1873,7 +1892,7 @@ static void intel_ddi_pll_init(struct drm_device *dev)
        struct drm_i915_private *dev_priv = to_i915(dev);
 
        if (INTEL_GEN(dev_priv) < 9) {
-               uint32_t val = I915_READ(LCPLL_CTL);
+               u32 val = I915_READ(LCPLL_CTL);
 
                /*
                 * The LCPLL register should be turned on by the BIOS. For now
@@ -1959,7 +1978,7 @@ static void cnl_ddi_pll_enable(struct drm_i915_private *dev_priv,
                               struct intel_shared_dpll *pll)
 {
        const enum intel_dpll_id id = pll->info->id;
-       uint32_t val;
+       u32 val;
 
        /* 1. Enable DPLL power in DPLL_ENABLE. */
        val = I915_READ(CNL_DPLL_ENABLE(id));
@@ -2034,7 +2053,7 @@ static void cnl_ddi_pll_disable(struct drm_i915_private *dev_priv,
                                struct intel_shared_dpll *pll)
 {
        const enum intel_dpll_id id = pll->info->id;
-       uint32_t val;
+       u32 val;
 
        /*
         * 1. Configure DPCLKA_CFGCR0 to turn off the clock for the DDI.
@@ -2091,10 +2110,13 @@ static bool cnl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
                                     struct intel_dpll_hw_state *hw_state)
 {
        const enum intel_dpll_id id = pll->info->id;
-       uint32_t val;
+       intel_wakeref_t wakeref;
+       u32 val;
        bool ret;
 
-       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    POWER_DOMAIN_PLLS);
+       if (!wakeref)
                return false;
 
        ret = false;
@@ -2113,7 +2135,7 @@ static bool cnl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
        ret = true;
 
 out:
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
 
        return ret;
 }
@@ -2225,7 +2247,7 @@ cnl_ddi_calculate_wrpll(int clock,
                        struct skl_wrpll_params *wrpll_params)
 {
        u32 afe_clock = clock * 5;
-       uint32_t ref_clock;
+       u32 ref_clock;
        u32 dco_min = 7998000;
        u32 dco_max = 10000000;
        u32 dco_mid = (dco_min + dco_max) / 2;
@@ -2271,7 +2293,7 @@ static bool cnl_ddi_hdmi_pll_dividers(struct intel_crtc *crtc,
                                      int clock)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       uint32_t cfgcr0, cfgcr1;
+       u32 cfgcr0, cfgcr1;
        struct skl_wrpll_params wrpll_params = { 0, };
 
        cfgcr0 = DPLL_CFGCR0_HDMI_MODE;
@@ -2300,7 +2322,7 @@ static bool
 cnl_ddi_dp_set_dpll_hw_state(int clock,
                             struct intel_dpll_hw_state *dpll_hw_state)
 {
-       uint32_t cfgcr0;
+       u32 cfgcr0;
 
        cfgcr0 = DPLL_CFGCR0_SSC_ENABLE;
 
@@ -2517,7 +2539,7 @@ static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state,
                                struct intel_dpll_hw_state *pll_state)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
-       uint32_t cfgcr0, cfgcr1;
+       u32 cfgcr0, cfgcr1;
        struct skl_wrpll_params pll_params = { 0 };
        bool ret;
 
@@ -2547,10 +2569,10 @@ static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state,
 }
 
 int icl_calc_dp_combo_pll_link(struct drm_i915_private *dev_priv,
-                              uint32_t pll_id)
+                              u32 pll_id)
 {
-       uint32_t cfgcr0, cfgcr1;
-       uint32_t pdiv, kdiv, qdiv_mode, qdiv_ratio, dco_integer, dco_fraction;
+       u32 cfgcr0, cfgcr1;
+       u32 pdiv, kdiv, qdiv_mode, qdiv_ratio, dco_integer, dco_fraction;
        const struct skl_wrpll_params *params;
        int index, n_entries, link_clock;
 
@@ -2633,10 +2655,10 @@ bool intel_dpll_is_combophy(enum intel_dpll_id id)
 }
 
 static bool icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc,
-                                    uint32_t *target_dco_khz,
+                                    u32 *target_dco_khz,
                                     struct intel_dpll_hw_state *state)
 {
-       uint32_t dco_min_freq, dco_max_freq;
+       u32 dco_min_freq, dco_max_freq;
        int div1_vals[] = {7, 5, 3, 2};
        unsigned int i;
        int div2;
@@ -2712,12 +2734,12 @@ static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state,
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        int refclk_khz = dev_priv->cdclk.hw.ref;
-       uint32_t dco_khz, m1div, m2div_int, m2div_rem, m2div_frac;
-       uint32_t iref_ndiv, iref_trim, iref_pulse_w;
-       uint32_t prop_coeff, int_coeff;
-       uint32_t tdc_targetcnt, feedfwgain;
-       uint64_t ssc_stepsize, ssc_steplen, ssc_steplog;
-       uint64_t tmp;
+       u32 dco_khz, m1div, m2div_int, m2div_rem, m2div_frac;
+       u32 iref_ndiv, iref_trim, iref_pulse_w;
+       u32 prop_coeff, int_coeff;
+       u32 tdc_targetcnt, feedfwgain;
+       u64 ssc_stepsize, ssc_steplen, ssc_steplog;
+       u64 tmp;
        bool use_ssc = false;
        bool is_dp = !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI);
 
@@ -2740,7 +2762,7 @@ static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state,
        }
        m2div_rem = dco_khz % (refclk_khz * m1div);
 
-       tmp = (uint64_t)m2div_rem * (1 << 22);
+       tmp = (u64)m2div_rem * (1 << 22);
        do_div(tmp, refclk_khz * m1div);
        m2div_frac = tmp;
 
@@ -2799,11 +2821,11 @@ static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state,
        }
 
        if (use_ssc) {
-               tmp = (uint64_t)dco_khz * 47 * 32;
+               tmp = (u64)dco_khz * 47 * 32;
                do_div(tmp, refclk_khz * m1div * 10000);
                ssc_stepsize = tmp;
 
-               tmp = (uint64_t)dco_khz * 1000;
+               tmp = (u64)dco_khz * 1000;
                ssc_steplen = DIV_ROUND_UP_ULL(tmp, 32 * 2 * 32);
        } else {
                ssc_stepsize = 0;
@@ -2950,11 +2972,14 @@ static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
                                 struct intel_dpll_hw_state *hw_state)
 {
        const enum intel_dpll_id id = pll->info->id;
-       uint32_t val;
-       enum port port;
+       intel_wakeref_t wakeref;
        bool ret = false;
+       enum port port;
+       u32 val;
 
-       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    POWER_DOMAIN_PLLS);
+       if (!wakeref)
                return false;
 
        val = I915_READ(icl_pll_id_to_enable_reg(id));
@@ -3007,7 +3032,7 @@ static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
 
        ret = true;
 out:
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
        return ret;
 }
 
@@ -3077,7 +3102,7 @@ static void icl_pll_enable(struct drm_i915_private *dev_priv,
 {
        const enum intel_dpll_id id = pll->info->id;
        i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id);
-       uint32_t val;
+       u32 val;
 
        val = I915_READ(enable_reg);
        val |= PLL_POWER_ENABLE;
@@ -3118,7 +3143,7 @@ static void icl_pll_disable(struct drm_i915_private *dev_priv,
 {
        const enum intel_dpll_id id = pll->info->id;
        i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id);
-       uint32_t val;
+       u32 val;
 
        /* The first steps are done by intel_ddi_post_disable(). */
 
index a033d8f06d4a80f726b13287067a6953b326f14d..e96e79413b5468ebfc60c096efd26c4068a10d27 100644 (file)
@@ -138,14 +138,14 @@ enum intel_dpll_id {
 
 struct intel_dpll_hw_state {
        /* i9xx, pch plls */
-       uint32_t dpll;
-       uint32_t dpll_md;
-       uint32_t fp0;
-       uint32_t fp1;
+       u32 dpll;
+       u32 dpll_md;
+       u32 fp0;
+       u32 fp1;
 
        /* hsw, bdw */
-       uint32_t wrpll;
-       uint32_t spll;
+       u32 wrpll;
+       u32 spll;
 
        /* skl */
        /*
@@ -154,34 +154,33 @@ struct intel_dpll_hw_state {
         * the register.  This allows us to easily compare the state to share
         * the DPLL.
         */
-       uint32_t ctrl1;
+       u32 ctrl1;
        /* HDMI only, 0 when used for DP */
-       uint32_t cfgcr1, cfgcr2;
+       u32 cfgcr1, cfgcr2;
 
        /* cnl */
-       uint32_t cfgcr0;
+       u32 cfgcr0;
        /* CNL also uses cfgcr1 */
 
        /* bxt */
-       uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10,
-                pcsdw12;
+       u32 ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10, pcsdw12;
 
        /*
         * ICL uses the following, already defined:
-        * uint32_t cfgcr0, cfgcr1;
-        */
-       uint32_t mg_refclkin_ctl;
-       uint32_t mg_clktop2_coreclkctl1;
-       uint32_t mg_clktop2_hsclkctl;
-       uint32_t mg_pll_div0;
-       uint32_t mg_pll_div1;
-       uint32_t mg_pll_lf;
-       uint32_t mg_pll_frac_lock;
-       uint32_t mg_pll_ssc;
-       uint32_t mg_pll_bias;
-       uint32_t mg_pll_tdc_coldst_bias;
-       uint32_t mg_pll_bias_mask;
-       uint32_t mg_pll_tdc_coldst_bias_mask;
+        * u32 cfgcr0, cfgcr1;
+        */
+       u32 mg_refclkin_ctl;
+       u32 mg_clktop2_coreclkctl1;
+       u32 mg_clktop2_hsclkctl;
+       u32 mg_pll_div0;
+       u32 mg_pll_div1;
+       u32 mg_pll_lf;
+       u32 mg_pll_frac_lock;
+       u32 mg_pll_ssc;
+       u32 mg_pll_bias;
+       u32 mg_pll_tdc_coldst_bias;
+       u32 mg_pll_bias_mask;
+       u32 mg_pll_tdc_coldst_bias_mask;
 };
 
 /**
@@ -280,7 +279,7 @@ struct dpll_info {
         *     Inform the state checker that the DPLL is kept enabled even if
         *     not in use by any CRTC.
         */
-       uint32_t flags;
+       u32 flags;
 };
 
 /**
@@ -343,7 +342,7 @@ void intel_shared_dpll_init(struct drm_device *dev);
 void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv,
                              struct intel_dpll_hw_state *hw_state);
 int icl_calc_dp_combo_pll_link(struct drm_i915_private *dev_priv,
-                              uint32_t pll_id);
+                              u32 pll_id);
 int cnl_hdmi_pll_ref_clock(struct drm_i915_private *dev_priv);
 enum intel_dpll_id icl_port_to_mg_pll_id(enum port port);
 bool intel_dpll_is_combophy(enum intel_dpll_id id);
index f94a04b4ad8788bcc1d8f9ca3073eaa00f33648a..47195320413a48d0b55f841968e9bb60093881d2 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/i2c.h>
 #include <linux/hdmi.h>
 #include <linux/sched/clock.h>
+#include <linux/stackdepot.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 #include <drm/drm_crtc.h>
@@ -41,6 +42,8 @@
 #include <drm/drm_atomic.h>
 #include <media/cec-notifier.h>
 
+struct drm_printer;
+
 /**
  * __wait_for - magic wait macro
  *
@@ -222,9 +225,9 @@ struct intel_encoder {
        enum intel_output_type (*compute_output_type)(struct intel_encoder *,
                                                      struct intel_crtc_state *,
                                                      struct drm_connector_state *);
-       bool (*compute_config)(struct intel_encoder *,
-                              struct intel_crtc_state *,
-                              struct drm_connector_state *);
+       int (*compute_config)(struct intel_encoder *,
+                             struct intel_crtc_state *,
+                             struct drm_connector_state *);
        void (*pre_pll_enable)(struct intel_encoder *,
                               const struct intel_crtc_state *,
                               const struct drm_connector_state *);
@@ -243,6 +246,9 @@ struct intel_encoder {
        void (*post_pll_disable)(struct intel_encoder *,
                                 const struct intel_crtc_state *,
                                 const struct drm_connector_state *);
+       void (*update_pipe)(struct intel_encoder *,
+                           const struct intel_crtc_state *,
+                           const struct drm_connector_state *);
        /* Read out the current hw state of this connector, returning true if
         * the encoder is active. If the encoder is enabled it also set the pipe
         * it is connected to in the pipe parameter. */
@@ -294,13 +300,12 @@ struct intel_panel {
 
                /* Connector and platform specific backlight functions */
                int (*setup)(struct intel_connector *connector, enum pipe pipe);
-               uint32_t (*get)(struct intel_connector *connector);
-               void (*set)(const struct drm_connector_state *conn_state, uint32_t level);
+               u32 (*get)(struct intel_connector *connector);
+               void (*set)(const struct drm_connector_state *conn_state, u32 level);
                void (*disable)(const struct drm_connector_state *conn_state);
                void (*enable)(const struct intel_crtc_state *crtc_state,
                               const struct drm_connector_state *conn_state);
-               uint32_t (*hz_to_pwm)(struct intel_connector *connector,
-                                     uint32_t hz);
+               u32 (*hz_to_pwm)(struct intel_connector *connector, u32 hz);
                void (*power)(struct intel_connector *, bool enable);
        } backlight;
 };
@@ -592,7 +597,7 @@ struct intel_initial_plane_config {
 
 struct intel_scaler {
        int in_use;
-       uint32_t mode;
+       u32 mode;
 };
 
 struct intel_crtc_scaler_state {
@@ -630,7 +635,7 @@ struct intel_crtc_scaler_state {
 
 struct intel_pipe_wm {
        struct intel_wm_level wm[5];
-       uint32_t linetime;
+       u32 linetime;
        bool fbc_wm_enabled;
        bool pipe_enabled;
        bool sprites_enabled;
@@ -646,7 +651,7 @@ struct skl_plane_wm {
 
 struct skl_pipe_wm {
        struct skl_plane_wm planes[I915_MAX_PLANES];
-       uint32_t linetime;
+       u32 linetime;
 };
 
 enum vlv_wm_level {
@@ -659,7 +664,7 @@ enum vlv_wm_level {
 struct vlv_wm_state {
        struct g4x_pipe_wm wm[NUM_VLV_WM_LEVELS];
        struct g4x_sr_wm sr[NUM_VLV_WM_LEVELS];
-       uint8_t num_levels;
+       u8 num_levels;
        bool cxsr;
 };
 
@@ -872,13 +877,13 @@ struct intel_crtc_state {
        /* Used by SDVO (and if we ever fix it, HDMI). */
        unsigned pixel_multiplier;
 
-       uint8_t lane_count;
+       u8 lane_count;
 
        /*
         * Used by platforms having DP/HDMI PHY with programmable lane
         * latency optimization.
         */
-       uint8_t lane_lat_optim_mask;
+       u8 lane_lat_optim_mask;
 
        /* minimum acceptable voltage level */
        u8 min_voltage_level;
@@ -922,7 +927,7 @@ struct intel_crtc_state {
        struct intel_crtc_wm_state wm;
 
        /* Gamma mode programmed on the pipe */
-       uint32_t gamma_mode;
+       u32 gamma_mode;
 
        /* bitmask of visible planes (enum plane_id) */
        u8 active_planes;
@@ -1008,7 +1013,7 @@ struct intel_plane {
        enum pipe pipe;
        bool has_fbc;
        bool has_ccs;
-       uint32_t frontbuffer_bit;
+       u32 frontbuffer_bit;
 
        struct {
                u32 base, cntl, size;
@@ -1074,7 +1079,6 @@ struct intel_hdmi {
        } dp_dual_mode;
        bool has_hdmi_sink;
        bool has_audio;
-       bool rgb_quant_range_selectable;
        struct intel_connector *attached_connector;
        struct cec_notifier *cec_notifier;
 };
@@ -1104,9 +1108,9 @@ enum link_m_n_set {
 
 struct intel_dp_compliance_data {
        unsigned long edid;
-       uint8_t video_pattern;
-       uint16_t hdisplay, vdisplay;
-       uint8_t bpc;
+       u8 video_pattern;
+       u16 hdisplay, vdisplay;
+       u8 bpc;
 };
 
 struct intel_dp_compliance {
@@ -1119,18 +1123,18 @@ struct intel_dp_compliance {
 
 struct intel_dp {
        i915_reg_t output_reg;
-       uint32_t DP;
+       u32 DP;
        int link_rate;
-       uint8_t lane_count;
-       uint8_t sink_count;
+       u8 lane_count;
+       u8 sink_count;
        bool link_mst;
        bool link_trained;
        bool has_audio;
        bool reset_link_params;
-       uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
-       uint8_t psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
-       uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
-       uint8_t edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
+       u8 dpcd[DP_RECEIVER_CAP_SIZE];
+       u8 psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
+       u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
+       u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
        u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE];
        u8 fec_capable;
        /* source rates */
@@ -1150,7 +1154,7 @@ struct intel_dp {
        /* sink or branch descriptor */
        struct drm_dp_desc desc;
        struct drm_dp_aux aux;
-       uint8_t train_set[4];
+       u8 train_set[4];
        int panel_power_up_delay;
        int panel_power_down_delay;
        int panel_power_cycle_delay;
@@ -1192,14 +1196,13 @@ struct intel_dp {
        struct intel_dp_mst_encoder *mst_encoders[I915_MAX_PIPES];
        struct drm_dp_mst_topology_mgr mst_mgr;
 
-       uint32_t (*get_aux_clock_divider)(struct intel_dp *dp, int index);
+       u32 (*get_aux_clock_divider)(struct intel_dp *dp, int index);
        /*
         * This function returns the value we have to program the AUX_CTL
         * register with to kick off an AUX transaction.
         */
-       uint32_t (*get_aux_send_ctl)(struct intel_dp *dp,
-                                    int send_bytes,
-                                    uint32_t aux_clock_divider);
+       u32 (*get_aux_send_ctl)(struct intel_dp *dp, int send_bytes,
+                               u32 aux_clock_divider);
 
        i915_reg_t (*aux_ch_ctl_reg)(struct intel_dp *dp);
        i915_reg_t (*aux_ch_data_reg)(struct intel_dp *dp, int index);
@@ -1209,6 +1212,9 @@ struct intel_dp {
 
        /* Displayport compliance testing */
        struct intel_dp_compliance compliance;
+
+       /* Display stream compression testing */
+       bool force_dsc_en;
 };
 
 enum lspcon_vendor {
@@ -1230,10 +1236,11 @@ struct intel_digital_port {
        struct intel_lspcon lspcon;
        enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool);
        bool release_cl2_override;
-       uint8_t max_lanes;
+       u8 max_lanes;
        /* Used for DP and ICL+ TypeC/DP and TypeC/HDMI ports. */
        enum aux_ch aux_ch;
        enum intel_display_power_domain ddi_io_power_domain;
+       bool tc_legacy_port:1;
        enum tc_port_type tc_type;
 
        void (*write_infoframe)(struct intel_encoder *encoder,
@@ -1464,8 +1471,8 @@ void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv);
 void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv);
 
 /* i915_irq.c */
-void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
-void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, u32 mask);
+void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, u32 mask);
 void gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask);
 void gen6_unmask_pm_irq(struct drm_i915_private *dev_priv, u32 mask);
 void gen11_reset_rps_interrupts(struct drm_i915_private *dev_priv);
@@ -1528,7 +1535,7 @@ void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state,
 void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv,
                                         struct intel_crtc_state *crtc_state);
 u32 bxt_signal_levels(struct intel_dp *intel_dp);
-uint32_t ddi_signal_levels(struct intel_dp *intel_dp);
+u32 ddi_signal_levels(struct intel_dp *intel_dp);
 u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder);
 u8 intel_ddi_dp_pre_emphasis_max(struct intel_encoder *encoder,
                                 u8 voltage_swing);
@@ -1668,11 +1675,11 @@ void intel_cleanup_plane_fb(struct drm_plane *plane,
 int intel_plane_atomic_get_property(struct drm_plane *plane,
                                    const struct drm_plane_state *state,
                                    struct drm_property *property,
-                                   uint64_t *val);
+                                   u64 *val);
 int intel_plane_atomic_set_property(struct drm_plane *plane,
                                    struct drm_plane_state *state,
                                    struct drm_property *property,
-                                   uint64_t val);
+                                   u64 val);
 int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_state,
                                    struct drm_crtc_state *crtc_state,
                                    const struct intel_plane_state *old_plane_state,
@@ -1792,10 +1799,10 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, i915_reg_t output_reg,
 bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
                             struct intel_connector *intel_connector);
 void intel_dp_set_link_params(struct intel_dp *intel_dp,
-                             int link_rate, uint8_t lane_count,
+                             int link_rate, u8 lane_count,
                              bool link_mst);
 int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
-                                           int link_rate, uint8_t lane_count);
+                                           int link_rate, u8 lane_count);
 void intel_dp_start_link_train(struct intel_dp *intel_dp);
 void intel_dp_stop_link_train(struct intel_dp *intel_dp);
 int intel_dp_retrain_link(struct intel_encoder *encoder,
@@ -1806,10 +1813,10 @@ void intel_dp_sink_set_decompression_state(struct intel_dp *intel_dp,
                                           bool enable);
 void intel_dp_encoder_reset(struct drm_encoder *encoder);
 void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder);
-void intel_dp_encoder_destroy(struct drm_encoder *encoder);
-bool intel_dp_compute_config(struct intel_encoder *encoder,
-                            struct intel_crtc_state *pipe_config,
-                            struct drm_connector_state *conn_state);
+void intel_dp_encoder_flush_work(struct drm_encoder *encoder);
+int intel_dp_compute_config(struct intel_encoder *encoder,
+                           struct intel_crtc_state *pipe_config,
+                           struct drm_connector_state *conn_state);
 bool intel_dp_is_edp(struct intel_dp *intel_dp);
 bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port);
 enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port,
@@ -1827,7 +1834,7 @@ int intel_dp_max_lane_count(struct intel_dp *intel_dp);
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate);
 void intel_dp_hot_plug(struct intel_encoder *intel_encoder);
 void intel_power_sequencer_reset(struct drm_i915_private *dev_priv);
-uint32_t intel_dp_pack_aux(const uint8_t *src, int src_bytes);
+u32 intel_dp_pack_aux(const u8 *src, int src_bytes);
 void intel_plane_destroy(struct drm_plane *plane);
 void intel_edp_drrs_enable(struct intel_dp *intel_dp,
                           const struct intel_crtc_state *crtc_state);
@@ -1840,24 +1847,24 @@ void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
 
 void
 intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,
-                                      uint8_t dp_train_pat);
+                                      u8 dp_train_pat);
 void
 intel_dp_set_signal_levels(struct intel_dp *intel_dp);
 void intel_dp_set_idle_link_train(struct intel_dp *intel_dp);
-uint8_t
+u8
 intel_dp_voltage_max(struct intel_dp *intel_dp);
-uint8_t
-intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing);
+u8
+intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, u8 voltage_swing);
 void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
-                          uint8_t *link_bw, uint8_t *rate_select);
+                          u8 *link_bw, u8 *rate_select);
 bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp);
 bool intel_dp_source_supports_hbr3(struct intel_dp *intel_dp);
 bool
-intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]);
-uint16_t intel_dp_dsc_get_output_bpp(int link_clock, uint8_t lane_count,
-                                    int mode_clock, int mode_hdisplay);
-uint8_t intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, int mode_clock,
-                                    int mode_hdisplay);
+intel_dp_get_link_status(struct intel_dp *intel_dp, u8 link_status[DP_LINK_STATUS_SIZE]);
+u16 intel_dp_dsc_get_output_bpp(int link_clock, u8 lane_count,
+                               int mode_clock, int mode_hdisplay);
+u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, int mode_clock,
+                               int mode_hdisplay);
 
 /* intel_vdsc.c */
 int intel_dp_compute_dsc_params(struct intel_dp *intel_dp,
@@ -1874,6 +1881,8 @@ bool intel_dp_read_dpcd(struct intel_dp *intel_dp);
 int intel_dp_link_required(int pixel_clock, int bpp);
 int intel_dp_max_data_rate(int max_link_clock, int max_lanes);
 bool intel_digital_port_connected(struct intel_encoder *encoder);
+void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,
+                          struct intel_digital_port *dig_port);
 
 /* intel_dp_aux_backlight.c */
 int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector);
@@ -1967,9 +1976,9 @@ void intel_hdmi_init(struct drm_i915_private *dev_priv, i915_reg_t hdmi_reg,
 void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
                               struct intel_connector *intel_connector);
 struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
-bool intel_hdmi_compute_config(struct intel_encoder *encoder,
-                              struct intel_crtc_state *pipe_config,
-                              struct drm_connector_state *conn_state);
+int intel_hdmi_compute_config(struct intel_encoder *encoder,
+                             struct intel_crtc_state *pipe_config,
+                             struct drm_connector_state *conn_state);
 bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder,
                                       struct drm_connector *connector,
                                       bool high_tmds_clock_ratio,
@@ -2014,6 +2023,9 @@ int intel_panel_setup_backlight(struct drm_connector *connector,
                                enum pipe pipe);
 void intel_panel_enable_backlight(const struct intel_crtc_state *crtc_state,
                                  const struct drm_connector_state *conn_state);
+void intel_panel_update_backlight(struct intel_encoder *encoder,
+                                 const struct intel_crtc_state *crtc_state,
+                                 const struct drm_connector_state *conn_state);
 void intel_panel_disable_backlight(const struct drm_connector_state *old_conn_state);
 extern struct drm_display_mode *intel_find_panel_downclock(
                                struct drm_i915_private *dev_priv,
@@ -2075,6 +2087,7 @@ bool intel_psr_enabled(struct intel_dp *intel_dp);
 void intel_init_quirks(struct drm_i915_private *dev_priv);
 
 /* intel_runtime_pm.c */
+void intel_runtime_pm_init_early(struct drm_i915_private *dev_priv);
 int intel_power_domains_init(struct drm_i915_private *);
 void intel_power_domains_cleanup(struct drm_i915_private *dev_priv);
 void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume);
@@ -2097,6 +2110,7 @@ void bxt_display_core_init(struct drm_i915_private *dev_priv, bool resume);
 void bxt_display_core_uninit(struct drm_i915_private *dev_priv);
 void intel_runtime_pm_enable(struct drm_i915_private *dev_priv);
 void intel_runtime_pm_disable(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_cleanup(struct drm_i915_private *dev_priv);
 const char *
 intel_display_power_domain_str(enum intel_display_power_domain domain);
 
@@ -2104,33 +2118,42 @@ bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
                                    enum intel_display_power_domain domain);
 bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
                                      enum intel_display_power_domain domain);
-void intel_display_power_get(struct drm_i915_private *dev_priv,
-                            enum intel_display_power_domain domain);
-bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
+intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,
                                        enum intel_display_power_domain domain);
+intel_wakeref_t
+intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
+                                  enum intel_display_power_domain domain);
+void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,
+                                      enum intel_display_power_domain domain);
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
 void intel_display_power_put(struct drm_i915_private *dev_priv,
-                            enum intel_display_power_domain domain);
+                            enum intel_display_power_domain domain,
+                            intel_wakeref_t wakeref);
+#else
+#define intel_display_power_put(i915, domain, wakeref) \
+       intel_display_power_put_unchecked(i915, domain)
+#endif
 void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
                            u8 req_slices);
 
 static inline void
-assert_rpm_device_not_suspended(struct drm_i915_private *dev_priv)
+assert_rpm_device_not_suspended(struct drm_i915_private *i915)
 {
-       WARN_ONCE(dev_priv->runtime_pm.suspended,
+       WARN_ONCE(i915->runtime_pm.suspended,
                  "Device suspended during HW access\n");
 }
 
 static inline void
-assert_rpm_wakelock_held(struct drm_i915_private *dev_priv)
+assert_rpm_wakelock_held(struct drm_i915_private *i915)
 {
-       assert_rpm_device_not_suspended(dev_priv);
-       WARN_ONCE(!atomic_read(&dev_priv->runtime_pm.wakeref_count),
+       assert_rpm_device_not_suspended(i915);
+       WARN_ONCE(!atomic_read(&i915->runtime_pm.wakeref_count),
                  "RPM wakelock ref not held during HW access");
 }
 
 /**
  * disable_rpm_wakeref_asserts - disable the RPM assert checks
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * This function disable asserts that check if we hold an RPM wakelock
  * reference, while keeping the device-not-suspended checks still enabled.
@@ -2147,14 +2170,14 @@ assert_rpm_wakelock_held(struct drm_i915_private *dev_priv)
  * enable_rpm_wakeref_asserts().
  */
 static inline void
-disable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv)
+disable_rpm_wakeref_asserts(struct drm_i915_private *i915)
 {
-       atomic_inc(&dev_priv->runtime_pm.wakeref_count);
+       atomic_inc(&i915->runtime_pm.wakeref_count);
 }
 
 /**
  * enable_rpm_wakeref_asserts - re-enable the RPM assert checks
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * This function re-enables the RPM assert checks after disabling them with
  * disable_rpm_wakeref_asserts. It's meant to be used only in special
@@ -2164,15 +2187,39 @@ disable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv)
  * disable_rpm_wakeref_asserts().
  */
 static inline void
-enable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv)
+enable_rpm_wakeref_asserts(struct drm_i915_private *i915)
 {
-       atomic_dec(&dev_priv->runtime_pm.wakeref_count);
+       atomic_dec(&i915->runtime_pm.wakeref_count);
 }
 
-void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
-bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv);
-void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv);
-void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
+intel_wakeref_t intel_runtime_pm_get(struct drm_i915_private *i915);
+intel_wakeref_t intel_runtime_pm_get_if_in_use(struct drm_i915_private *i915);
+intel_wakeref_t intel_runtime_pm_get_noresume(struct drm_i915_private *i915);
+
+#define with_intel_runtime_pm(i915, wf) \
+       for ((wf) = intel_runtime_pm_get(i915); (wf); \
+            intel_runtime_pm_put((i915), (wf)), (wf) = 0)
+
+#define with_intel_runtime_pm_if_in_use(i915, wf) \
+       for ((wf) = intel_runtime_pm_get_if_in_use(i915); (wf); \
+            intel_runtime_pm_put((i915), (wf)), (wf) = 0)
+
+void intel_runtime_pm_put_unchecked(struct drm_i915_private *i915);
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
+void intel_runtime_pm_put(struct drm_i915_private *i915, intel_wakeref_t wref);
+#else
+#define intel_runtime_pm_put(i915, wref) intel_runtime_pm_put_unchecked(i915)
+#endif
+
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
+void print_intel_runtime_pm_wakeref(struct drm_i915_private *i915,
+                                   struct drm_printer *p);
+#else
+static inline void print_intel_runtime_pm_wakeref(struct drm_i915_private *i915,
+                                                 struct drm_printer *p)
+{
+}
+#endif
 
 void chv_phy_powergate_lanes(struct intel_encoder *encoder,
                             bool override, unsigned int mask);
@@ -2200,16 +2247,16 @@ void gen6_rps_busy(struct drm_i915_private *dev_priv);
 void gen6_rps_reset_ei(struct drm_i915_private *dev_priv);
 void gen6_rps_idle(struct drm_i915_private *dev_priv);
 void gen6_rps_boost(struct i915_request *rq, struct intel_rps_client *rps);
-void g4x_wm_get_hw_state(struct drm_device *dev);
-void vlv_wm_get_hw_state(struct drm_device *dev);
-void ilk_wm_get_hw_state(struct drm_device *dev);
-void skl_wm_get_hw_state(struct drm_device *dev);
+void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv);
+void vlv_wm_get_hw_state(struct drm_i915_private *dev_priv);
+void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv);
+void skl_wm_get_hw_state(struct drm_i915_private *dev_priv);
 void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
                               struct skl_ddb_entry *ddb_y,
                               struct skl_ddb_entry *ddb_uv);
 void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
                          struct skl_ddb_allocation *ddb /* out */);
-void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc,
+void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc,
                              struct skl_pipe_wm *out);
 void g4x_wm_sanitize(struct drm_i915_private *dev_priv);
 void vlv_wm_sanitize(struct drm_i915_private *dev_priv);
@@ -2278,11 +2325,11 @@ void intel_tv_init(struct drm_i915_private *dev_priv);
 int intel_digital_connector_atomic_get_property(struct drm_connector *connector,
                                                const struct drm_connector_state *state,
                                                struct drm_property *property,
-                                               uint64_t *val);
+                                               u64 *val);
 int intel_digital_connector_atomic_set_property(struct drm_connector *connector,
                                                struct drm_connector_state *state,
                                                struct drm_property *property,
-                                               uint64_t val);
+                                               u64 val);
 int intel_digital_connector_atomic_check(struct drm_connector *conn,
                                         struct drm_connector_state *new_state);
 struct drm_connector_state *
@@ -2327,10 +2374,10 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_
                                        struct intel_plane_state *intel_state);
 
 /* intel_color.c */
-void intel_color_init(struct drm_crtc *crtc);
-int intel_color_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
-void intel_color_set_csc(struct drm_crtc_state *crtc_state);
-void intel_color_load_luts(struct drm_crtc_state *crtc_state);
+void intel_color_init(struct intel_crtc *crtc);
+int intel_color_check(struct intel_crtc_state *crtc_state);
+void intel_color_set_csc(struct intel_crtc_state *crtc_state);
+void intel_color_load_luts(struct intel_crtc_state *crtc_state);
 
 /* intel_lspcon.c */
 bool lspcon_init(struct intel_digital_port *intel_dig_port);
index d968f1f13e0923b7793d5ed944bc9a1fc5049c23..a9a19778dc7fc55c4b45996afa18516f6a8915a4 100644 (file)
@@ -24,7 +24,6 @@
 #ifndef _INTEL_DSI_H
 #define _INTEL_DSI_H
 
-#include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_mipi_dsi.h>
 #include "intel_drv.h"
@@ -40,6 +39,7 @@ struct intel_dsi {
        struct intel_encoder base;
 
        struct intel_dsi_host *dsi_hosts[I915_MAX_PORTS];
+       intel_wakeref_t io_wakeref[I915_MAX_PORTS];
 
        /* GPIO Desc for CRC based Panel control */
        struct gpio_desc *gpio_panel;
@@ -173,7 +173,7 @@ int vlv_dsi_pll_compute(struct intel_encoder *encoder,
 void vlv_dsi_pll_enable(struct intel_encoder *encoder,
                        const struct intel_crtc_state *config);
 void vlv_dsi_pll_disable(struct intel_encoder *encoder);
-u32 vlv_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp,
+u32 vlv_dsi_get_pclk(struct intel_encoder *encoder,
                     struct intel_crtc_state *config);
 void vlv_dsi_reset_clocks(struct intel_encoder *encoder, enum port port);
 
@@ -183,7 +183,7 @@ int bxt_dsi_pll_compute(struct intel_encoder *encoder,
 void bxt_dsi_pll_enable(struct intel_encoder *encoder,
                        const struct intel_crtc_state *config);
 void bxt_dsi_pll_disable(struct intel_encoder *encoder);
-u32 bxt_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp,
+u32 bxt_dsi_get_pclk(struct intel_encoder *encoder,
                     struct intel_crtc_state *config);
 void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port);
 
index a1a8b3790e616261c73383a22a1a08724f1d6f64..06a11c35a784fc7957227792fd46474d960cfc81 100644 (file)
  *
  */
 
-#include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
 #include <drm/i915_drm.h>
 #include <linux/gpio/consumer.h>
+#include <linux/mfd/intel_soc_pmic.h>
 #include <linux/slab.h>
 #include <video/mipi_display.h>
 #include <asm/intel-mid.h>
-#include <video/mipi_display.h>
+#include <asm/unaligned.h>
 #include "i915_drv.h"
 #include "intel_drv.h"
 #include "intel_dsi.h"
@@ -393,7 +393,25 @@ static const u8 *mipi_exec_spi(struct intel_dsi *intel_dsi, const u8 *data)
 
 static const u8 *mipi_exec_pmic(struct intel_dsi *intel_dsi, const u8 *data)
 {
-       DRM_DEBUG_KMS("Skipping PMIC element execution\n");
+#ifdef CONFIG_PMIC_OPREGION
+       u32 value, mask, reg_address;
+       u16 i2c_address;
+       int ret;
+
+       /* byte 0 aka PMIC Flag is reserved */
+       i2c_address     = get_unaligned_le16(data + 1);
+       reg_address     = get_unaligned_le32(data + 3);
+       value           = get_unaligned_le32(data + 7);
+       mask            = get_unaligned_le32(data + 11);
+
+       ret = intel_soc_pmic_exec_mipi_pmic_seq_element(i2c_address,
+                                                       reg_address,
+                                                       value, mask);
+       if (ret)
+               DRM_ERROR("%s failed, error: %d\n", __func__, ret);
+#else
+       DRM_ERROR("Your hardware requires CONFIG_PMIC_OPREGION and it is not set\n");
+#endif
 
        return data + 15;
 }
index 0042a7f69387780f6f1d5c105ca9cae43d41713d..a6c82482a841be503a3c6fe8ada5ec99981928df 100644 (file)
@@ -26,7 +26,6 @@
  */
 #include <linux/i2c.h>
 #include <linux/slab.h>
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include "intel_drv.h"
@@ -235,9 +234,9 @@ intel_dvo_mode_valid(struct drm_connector *connector,
        return intel_dvo->dev.dev_ops->mode_valid(&intel_dvo->dev, mode);
 }
 
-static bool intel_dvo_compute_config(struct intel_encoder *encoder,
-                                    struct intel_crtc_state *pipe_config,
-                                    struct drm_connector_state *conn_state)
+static int intel_dvo_compute_config(struct intel_encoder *encoder,
+                                   struct intel_crtc_state *pipe_config,
+                                   struct drm_connector_state *conn_state)
 {
        struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
        const struct drm_display_mode *fixed_mode =
@@ -254,10 +253,11 @@ static bool intel_dvo_compute_config(struct intel_encoder *encoder,
                intel_fixed_panel_mode(fixed_mode, adjusted_mode);
 
        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
-               return false;
+               return -EINVAL;
 
        pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
-       return true;
+
+       return 0;
 }
 
 static void intel_dvo_pre_enable(struct intel_encoder *encoder,
index af2873403009103730ac07d95556c3d9a04ee517..2f3c71f6d31323f67575dbaef38607d8056594a0 100644 (file)
@@ -25,6 +25,7 @@
 #include <drm/drm_print.h>
 
 #include "i915_drv.h"
+#include "i915_reset.h"
 #include "intel_ringbuffer.h"
 #include "intel_lrc.h"
 
@@ -261,6 +262,31 @@ static void __sprint_engine_name(char *name, const struct engine_info *info)
                         info->instance) >= INTEL_ENGINE_CS_MAX_NAME);
 }
 
+void intel_engine_set_hwsp_writemask(struct intel_engine_cs *engine, u32 mask)
+{
+       struct drm_i915_private *dev_priv = engine->i915;
+       i915_reg_t hwstam;
+
+       /*
+        * Though they added more rings on g4x/ilk, they did not add
+        * per-engine HWSTAM until gen6.
+        */
+       if (INTEL_GEN(dev_priv) < 6 && engine->class != RENDER_CLASS)
+               return;
+
+       hwstam = RING_HWSTAM(engine->mmio_base);
+       if (INTEL_GEN(dev_priv) >= 3)
+               I915_WRITE(hwstam, mask);
+       else
+               I915_WRITE16(hwstam, mask);
+}
+
+static void intel_engine_sanitize_mmio(struct intel_engine_cs *engine)
+{
+       /* Mask off all writes into the unknown HWSP */
+       intel_engine_set_hwsp_writemask(engine, ~0u);
+}
+
 static int
 intel_engine_setup(struct drm_i915_private *dev_priv,
                   enum intel_engine_id id)
@@ -312,6 +338,9 @@ intel_engine_setup(struct drm_i915_private *dev_priv,
 
        ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier);
 
+       /* Scrub mmio state on takeover */
+       intel_engine_sanitize_mmio(engine);
+
        dev_priv->engine_class[info->class][info->instance] = engine;
        dev_priv->engine[id] = engine;
        return 0;
@@ -365,7 +394,7 @@ int intel_engines_init_mmio(struct drm_i915_private *dev_priv)
                goto cleanup;
        }
 
-       device_info->num_rings = hweight32(mask);
+       RUNTIME_INFO(dev_priv)->num_rings = hweight32(mask);
 
        i915_check_and_clear_faults(dev_priv);
 
@@ -426,27 +455,9 @@ cleanup:
        return err;
 }
 
-void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno)
+void intel_engine_write_global_seqno(struct intel_engine_cs *engine, u32 seqno)
 {
-       struct drm_i915_private *dev_priv = engine->i915;
-
-       /* Our semaphore implementation is strictly monotonic (i.e. we proceed
-        * so long as the semaphore value in the register/page is greater
-        * than the sync value), so whenever we reset the seqno,
-        * so long as we reset the tracking semaphore value to 0, it will
-        * always be before the next request's seqno. If we don't reset
-        * the semaphore value, then when the seqno moves backwards all
-        * future waits will complete instantly (causing rendering corruption).
-        */
-       if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) {
-               I915_WRITE(RING_SYNC_0(engine->mmio_base), 0);
-               I915_WRITE(RING_SYNC_1(engine->mmio_base), 0);
-               if (HAS_VEBOX(dev_priv))
-                       I915_WRITE(RING_SYNC_2(engine->mmio_base), 0);
-       }
-
        intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
-       clear_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted);
 
        /* After manually advancing the seqno, fake the interrupt in case
         * there are any waiters for that seqno.
@@ -495,6 +506,9 @@ void intel_engine_setup_common(struct intel_engine_cs *engine)
 
 static void cleanup_status_page(struct intel_engine_cs *engine)
 {
+       /* Prevent writes into HWSP after returning the page to the system */
+       intel_engine_set_hwsp_writemask(engine, ~0u);
+
        if (HWS_NEEDS_PHYSICAL(engine->i915)) {
                void *addr = fetch_and_zero(&engine->status_page.page_addr);
 
@@ -769,12 +783,12 @@ const char *i915_cache_level_str(struct drm_i915_private *i915, int type)
 
 u32 intel_calculate_mcr_s_ss_select(struct drm_i915_private *dev_priv)
 {
-       const struct sseu_dev_info *sseu = &(INTEL_INFO(dev_priv)->sseu);
+       const struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu;
        u32 mcr_s_ss_select;
        u32 slice = fls(sseu->slice_mask);
        u32 subslice = fls(sseu->subslice_mask[slice]);
 
-       if (IS_GEN10(dev_priv))
+       if (IS_GEN(dev_priv, 10))
                mcr_s_ss_select = GEN8_MCR_SLICE(slice) |
                                  GEN8_MCR_SUBSLICE(subslice);
        else if (INTEL_GEN(dev_priv) >= 11)
@@ -786,15 +800,15 @@ u32 intel_calculate_mcr_s_ss_select(struct drm_i915_private *dev_priv)
        return mcr_s_ss_select;
 }
 
-static inline uint32_t
+static inline u32
 read_subslice_reg(struct drm_i915_private *dev_priv, int slice,
                  int subslice, i915_reg_t reg)
 {
-       uint32_t mcr_slice_subslice_mask;
-       uint32_t mcr_slice_subslice_select;
-       uint32_t default_mcr_s_ss_select;
-       uint32_t mcr;
-       uint32_t ret;
+       u32 mcr_slice_subslice_mask;
+       u32 mcr_slice_subslice_select;
+       u32 default_mcr_s_ss_select;
+       u32 mcr;
+       u32 ret;
        enum forcewake_domains fw_domains;
 
        if (INTEL_GEN(dev_priv) >= 11) {
@@ -900,10 +914,15 @@ void intel_engine_get_instdone(struct intel_engine_cs *engine,
 static bool ring_is_idle(struct intel_engine_cs *engine)
 {
        struct drm_i915_private *dev_priv = engine->i915;
+       intel_wakeref_t wakeref;
        bool idle = true;
 
+       if (I915_SELFTEST_ONLY(!engine->mmio_base))
+               return true;
+
        /* If the whole device is asleep, the engine must be idle */
-       if (!intel_runtime_pm_get_if_in_use(dev_priv))
+       wakeref = intel_runtime_pm_get_if_in_use(dev_priv);
+       if (!wakeref)
                return true;
 
        /* First check that no commands are left in the ring */
@@ -915,7 +934,7 @@ static bool ring_is_idle(struct intel_engine_cs *engine)
        if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE))
                idle = false;
 
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
 
        return idle;
 }
@@ -939,9 +958,6 @@ bool intel_engine_is_idle(struct intel_engine_cs *engine)
        if (!intel_engine_signaled(engine, intel_engine_last_submit(engine)))
                return false;
 
-       if (I915_SELFTEST_ONLY(engine->breadcrumbs.mock))
-               return true;
-
        /* Waiting to drain ELSP? */
        if (READ_ONCE(engine->execlists.active)) {
                struct tasklet_struct *t = &engine->execlists.tasklet;
@@ -967,10 +983,7 @@ bool intel_engine_is_idle(struct intel_engine_cs *engine)
                return false;
 
        /* Ring stopped? */
-       if (!ring_is_idle(engine))
-               return false;
-
-       return true;
+       return ring_is_idle(engine);
 }
 
 bool intel_engines_are_idle(struct drm_i915_private *dev_priv)
@@ -1030,22 +1043,34 @@ void intel_engines_reset_default_submission(struct drm_i915_private *i915)
                engine->set_default_submission(engine);
 }
 
+static bool reset_engines(struct drm_i915_private *i915)
+{
+       if (INTEL_INFO(i915)->gpu_reset_clobbers_display)
+               return false;
+
+       return intel_gpu_reset(i915, ALL_ENGINES) == 0;
+}
+
 /**
  * intel_engines_sanitize: called after the GPU has lost power
  * @i915: the i915 device
+ * @force: ignore a failed reset and sanitize engine state anyway
  *
  * Anytime we reset the GPU, either with an explicit GPU reset or through a
  * PCI power cycle, the GPU loses state and we must reset our state tracking
  * to match. Note that calling intel_engines_sanitize() if the GPU has not
  * been reset results in much confusion!
  */
-void intel_engines_sanitize(struct drm_i915_private *i915)
+void intel_engines_sanitize(struct drm_i915_private *i915, bool force)
 {
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
 
        GEM_TRACE("\n");
 
+       if (!reset_engines(i915) && !force)
+               return;
+
        for_each_engine(engine, i915, id) {
                if (engine->reset.reset)
                        engine->reset.reset(engine, NULL);
@@ -1201,7 +1226,7 @@ static void print_request(struct drm_printer *m,
 
        x = print_sched_attr(rq->i915, &rq->sched.attr, buf, x, sizeof(buf));
 
-       drm_printf(m, "%s%x%s [%llx:%x]%s @ %dms: %s\n",
+       drm_printf(m, "%s%x%s [%llx:%llx]%s @ %dms: %s\n",
                   prefix,
                   rq->global_seqno,
                   i915_request_completed(rq) ? "!" : "",
@@ -1248,7 +1273,7 @@ static void intel_engine_print_registers(const struct intel_engine_cs *engine,
                &engine->execlists;
        u64 addr;
 
-       if (engine->id == RCS && IS_GEN(dev_priv, 4, 7))
+       if (engine->id == RCS && IS_GEN_RANGE(dev_priv, 4, 7))
                drm_printf(m, "\tCCID: 0x%08x\n", I915_READ(CCID));
        drm_printf(m, "\tRING_START: 0x%08x\n",
                   I915_READ(RING_START(engine->mmio_base)));
@@ -1269,16 +1294,6 @@ static void intel_engine_print_registers(const struct intel_engine_cs *engine,
                drm_printf(m, "\tRING_IMR: %08x\n", I915_READ_IMR(engine));
        }
 
-       if (HAS_LEGACY_SEMAPHORES(dev_priv)) {
-               drm_printf(m, "\tSYNC_0: 0x%08x\n",
-                          I915_READ(RING_SYNC_0(engine->mmio_base)));
-               drm_printf(m, "\tSYNC_1: 0x%08x\n",
-                          I915_READ(RING_SYNC_1(engine->mmio_base)));
-               if (HAS_VEBOX(dev_priv))
-                       drm_printf(m, "\tSYNC_2: 0x%08x\n",
-                                  I915_READ(RING_SYNC_2(engine->mmio_base)));
-       }
-
        addr = intel_engine_get_active_head(engine);
        drm_printf(m, "\tACTHD:  0x%08x_%08x\n",
                   upper_32_bits(addr), lower_32_bits(addr));
@@ -1405,14 +1420,12 @@ void intel_engine_dump(struct intel_engine_cs *engine,
                       struct drm_printer *m,
                       const char *header, ...)
 {
-       const int MAX_REQUESTS_TO_SHOW = 8;
        struct intel_breadcrumbs * const b = &engine->breadcrumbs;
-       const struct intel_engine_execlists * const execlists = &engine->execlists;
        struct i915_gpu_error * const error = &engine->i915->gpu_error;
-       struct i915_request *rq, *last;
+       struct i915_request *rq;
+       intel_wakeref_t wakeref;
        unsigned long flags;
        struct rb_node *rb;
-       int count;
 
        if (header) {
                va_list ap;
@@ -1468,59 +1481,17 @@ void intel_engine_dump(struct intel_engine_cs *engine,
 
        rcu_read_unlock();
 
-       if (intel_runtime_pm_get_if_in_use(engine->i915)) {
+       wakeref = intel_runtime_pm_get_if_in_use(engine->i915);
+       if (wakeref) {
                intel_engine_print_registers(engine, m);
-               intel_runtime_pm_put(engine->i915);
+               intel_runtime_pm_put(engine->i915, wakeref);
        } else {
                drm_printf(m, "\tDevice is asleep; skipping register dump\n");
        }
 
-       local_irq_save(flags);
-       spin_lock(&engine->timeline.lock);
+       intel_execlists_show_requests(engine, m, print_request, 8);
 
-       last = NULL;
-       count = 0;
-       list_for_each_entry(rq, &engine->timeline.requests, link) {
-               if (count++ < MAX_REQUESTS_TO_SHOW - 1)
-                       print_request(m, rq, "\t\tE ");
-               else
-                       last = rq;
-       }
-       if (last) {
-               if (count > MAX_REQUESTS_TO_SHOW) {
-                       drm_printf(m,
-                                  "\t\t...skipping %d executing requests...\n",
-                                  count - MAX_REQUESTS_TO_SHOW);
-               }
-               print_request(m, last, "\t\tE ");
-       }
-
-       last = NULL;
-       count = 0;
-       drm_printf(m, "\t\tQueue priority: %d\n", execlists->queue_priority);
-       for (rb = rb_first_cached(&execlists->queue); rb; rb = rb_next(rb)) {
-               struct i915_priolist *p = rb_entry(rb, typeof(*p), node);
-               int i;
-
-               priolist_for_each_request(rq, p, i) {
-                       if (count++ < MAX_REQUESTS_TO_SHOW - 1)
-                               print_request(m, rq, "\t\tQ ");
-                       else
-                               last = rq;
-               }
-       }
-       if (last) {
-               if (count > MAX_REQUESTS_TO_SHOW) {
-                       drm_printf(m,
-                                  "\t\t...skipping %d queued requests...\n",
-                                  count - MAX_REQUESTS_TO_SHOW);
-               }
-               print_request(m, last, "\t\tQ ");
-       }
-
-       spin_unlock(&engine->timeline.lock);
-
-       spin_lock(&b->rb_lock);
+       spin_lock_irqsave(&b->rb_lock, flags);
        for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) {
                struct intel_wait *w = rb_entry(rb, typeof(*w), node);
 
@@ -1529,13 +1500,7 @@ void intel_engine_dump(struct intel_engine_cs *engine,
                           task_state_to_char(w->tsk),
                           w->seqno);
        }
-       spin_unlock(&b->rb_lock);
-       local_irq_restore(flags);
-
-       drm_printf(m, "IRQ? 0x%lx (breadcrumbs? %s)\n",
-                  engine->irq_posted,
-                  yesno(test_bit(ENGINE_IRQ_BREADCRUMB,
-                                 &engine->irq_posted)));
+       spin_unlock_irqrestore(&b->rb_lock, flags);
 
        drm_printf(m, "HWSP:\n");
        hexdump(m, engine->status_page.page_addr, PAGE_SIZE);
index f23570c44323b1ad324654fce53d3802de464ffc..ec72be4b7a7bb7a31d5c2f0ed9ab8ddcc7cde5f6 100644 (file)
@@ -84,7 +84,7 @@ static int intel_fbc_calculate_cfb_size(struct drm_i915_private *dev_priv,
        int lines;
 
        intel_fbc_get_plane_source_size(cache, NULL, &lines);
-       if (IS_GEN7(dev_priv))
+       if (IS_GEN(dev_priv, 7))
                lines = min(lines, 2048);
        else if (INTEL_GEN(dev_priv) >= 8)
                lines = min(lines, 2560);
@@ -127,7 +127,7 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv)
                cfb_pitch = params->fb.stride;
 
        /* FBC_CTL wants 32B or 64B units */
-       if (IS_GEN2(dev_priv))
+       if (IS_GEN(dev_priv, 2))
                cfb_pitch = (cfb_pitch / 32) - 1;
        else
                cfb_pitch = (cfb_pitch / 64) - 1;
@@ -136,7 +136,7 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv)
        for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++)
                I915_WRITE(FBC_TAG(i), 0);
 
-       if (IS_GEN4(dev_priv)) {
+       if (IS_GEN(dev_priv, 4)) {
                u32 fbc_ctl2;
 
                /* Set it up... */
@@ -233,9 +233,9 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
 
        if (params->flags & PLANE_HAS_FENCE) {
                dpfc_ctl |= DPFC_CTL_FENCE_EN;
-               if (IS_GEN5(dev_priv))
+               if (IS_GEN(dev_priv, 5))
                        dpfc_ctl |= params->vma->fence->id;
-               if (IS_GEN6(dev_priv)) {
+               if (IS_GEN(dev_priv, 6)) {
                        I915_WRITE(SNB_DPFC_CTL_SA,
                                   SNB_CPU_FENCE_ENABLE |
                                   params->vma->fence->id);
@@ -243,7 +243,7 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
                                   params->crtc.fence_y_offset);
                }
        } else {
-               if (IS_GEN6(dev_priv)) {
+               if (IS_GEN(dev_priv, 6)) {
                        I915_WRITE(SNB_DPFC_CTL_SA, 0);
                        I915_WRITE(DPFC_CPU_FENCE_OFFSET, 0);
                }
@@ -282,7 +282,7 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
        int threshold = dev_priv->fbc.threshold;
 
        /* Display WA #0529: skl, kbl, bxt. */
-       if (IS_GEN9(dev_priv) && !IS_GEMINILAKE(dev_priv)) {
+       if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv)) {
                u32 val = I915_READ(CHICKEN_MISC_4);
 
                val &= ~(FBC_STRIDE_OVERRIDE | FBC_STRIDE_MASK);
@@ -581,10 +581,10 @@ static bool stride_is_valid(struct drm_i915_private *dev_priv,
        if (stride < 512)
                return false;
 
-       if (IS_GEN2(dev_priv) || IS_GEN3(dev_priv))
+       if (IS_GEN(dev_priv, 2) || IS_GEN(dev_priv, 3))
                return stride == 4096 || stride == 8192;
 
-       if (IS_GEN4(dev_priv) && !IS_G4X(dev_priv) && stride < 2048)
+       if (IS_GEN(dev_priv, 4) && !IS_G4X(dev_priv) && stride < 2048)
                return false;
 
        if (stride > 16384)
@@ -594,7 +594,7 @@ static bool stride_is_valid(struct drm_i915_private *dev_priv,
 }
 
 static bool pixel_format_is_valid(struct drm_i915_private *dev_priv,
-                                 uint32_t pixel_format)
+                                 u32 pixel_format)
 {
        switch (pixel_format) {
        case DRM_FORMAT_XRGB8888:
@@ -603,7 +603,7 @@ static bool pixel_format_is_valid(struct drm_i915_private *dev_priv,
        case DRM_FORMAT_XRGB1555:
        case DRM_FORMAT_RGB565:
                /* 16bpp not supported on gen2 */
-               if (IS_GEN2(dev_priv))
+               if (IS_GEN(dev_priv, 2))
                        return false;
                /* WaFbcOnly1to1Ratio:ctg */
                if (IS_G4X(dev_priv))
@@ -626,7 +626,10 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
        struct intel_fbc *fbc = &dev_priv->fbc;
        unsigned int effective_w, effective_h, max_w, max_h;
 
-       if (INTEL_GEN(dev_priv) >= 8 || IS_HASWELL(dev_priv)) {
+       if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
+               max_w = 5120;
+               max_h = 4096;
+       } else if (INTEL_GEN(dev_priv) >= 8 || IS_HASWELL(dev_priv)) {
                max_w = 4096;
                max_h = 4096;
        } else if (IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5) {
@@ -784,7 +787,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
         * having a Y offset that isn't divisible by 4 causes FIFO underrun
         * and screen flicker.
         */
-       if (IS_GEN(dev_priv, 9, 10) &&
+       if (IS_GEN_RANGE(dev_priv, 9, 10) &&
            (fbc->state_cache.plane.adjusted_y & 3)) {
                fbc->no_fbc_reason = "plane Y offset is misaligned";
                return false;
@@ -839,7 +842,7 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc,
 
        params->cfb_size = intel_fbc_calculate_cfb_size(dev_priv, cache);
 
-       if (IS_GEN9(dev_priv) && !IS_GEMINILAKE(dev_priv))
+       if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv))
                params->gen9_wa_cfb_stride = DIV_ROUND_UP(cache->plane.src_w,
                                                32 * fbc->threshold) * 8;
 }
@@ -1126,8 +1129,6 @@ void intel_fbc_disable(struct intel_crtc *crtc)
        if (!fbc_supported(dev_priv))
                return;
 
-       WARN_ON(crtc->active);
-
        mutex_lock(&fbc->lock);
        if (fbc->crtc == crtc)
                __intel_fbc_disable(dev_priv);
index fb5bb5b32a6034d152516ae11c15913e2f97597d..3036d835bc2b517fa211490db1c9063efba9157c 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/init.h>
 #include <linux/vga_switcheroo.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_helper.h>
 #include "intel_drv.h"
@@ -178,8 +177,9 @@ static int intelfb_create(struct drm_fb_helper *helper,
        const struct i915_ggtt_view view = {
                .type = I915_GGTT_VIEW_NORMAL,
        };
-       struct fb_info *info;
        struct drm_framebuffer *fb;
+       intel_wakeref_t wakeref;
+       struct fb_info *info;
        struct i915_vma *vma;
        unsigned long flags = 0;
        bool prealloc = false;
@@ -210,7 +210,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
        }
 
        mutex_lock(&dev->struct_mutex);
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
        /* Pin the GGTT vma for our access via info->screen_base.
         * This also validates that any existing fb inherited from the
@@ -277,7 +277,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
        ifbdev->vma = vma;
        ifbdev->vma_flags = flags;
 
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
        mutex_unlock(&dev->struct_mutex);
        vga_switcheroo_client_fb_set(pdev, info);
        return 0;
@@ -285,7 +285,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
 out_unpin:
        intel_unpin_fb_vma(vma, flags);
 out_unlock:
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
        mutex_unlock(&dev->struct_mutex);
        return ret;
 }
index 77c123cc88179e7f0ac3ef40af6d75fd34f59583..3b9285130ef54a8a15c35e3f009c27418e05c40b 100644 (file)
@@ -127,8 +127,8 @@ static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev,
                                                 enum pipe pipe, bool enable)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
-       uint32_t bit = (pipe == PIPE_A) ? DE_PIPEA_FIFO_UNDERRUN :
-                                         DE_PIPEB_FIFO_UNDERRUN;
+       u32 bit = (pipe == PIPE_A) ?
+               DE_PIPEA_FIFO_UNDERRUN : DE_PIPEB_FIFO_UNDERRUN;
 
        if (enable)
                ilk_enable_display_irq(dev_priv, bit);
@@ -140,7 +140,7 @@ static void ivybridge_check_fifo_underruns(struct intel_crtc *crtc)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
-       uint32_t err_int = I915_READ(GEN7_ERR_INT);
+       u32 err_int = I915_READ(GEN7_ERR_INT);
 
        lockdep_assert_held(&dev_priv->irq_lock);
 
@@ -193,8 +193,8 @@ static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
                                            bool enable)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
-       uint32_t bit = (pch_transcoder == PIPE_A) ?
-                      SDE_TRANSA_FIFO_UNDER : SDE_TRANSB_FIFO_UNDER;
+       u32 bit = (pch_transcoder == PIPE_A) ?
+               SDE_TRANSA_FIFO_UNDER : SDE_TRANSB_FIFO_UNDER;
 
        if (enable)
                ibx_enable_display_interrupt(dev_priv, bit);
@@ -206,7 +206,7 @@ static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pch_transcoder = crtc->pipe;
-       uint32_t serr_int = I915_READ(SERR_INT);
+       u32 serr_int = I915_READ(SERR_INT);
 
        lockdep_assert_held(&dev_priv->irq_lock);
 
@@ -260,9 +260,9 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
 
        if (HAS_GMCH_DISPLAY(dev_priv))
                i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old);
-       else if (IS_GEN5(dev_priv) || IS_GEN6(dev_priv))
+       else if (IS_GEN_RANGE(dev_priv, 5, 6))
                ironlake_set_fifo_underrun_reporting(dev, pipe, enable);
-       else if (IS_GEN7(dev_priv))
+       else if (IS_GEN(dev_priv, 7))
                ivybridge_set_fifo_underrun_reporting(dev, pipe, enable, old);
        else if (INTEL_GEN(dev_priv) >= 8)
                broadwell_set_fifo_underrun_reporting(dev, pipe, enable);
@@ -423,7 +423,7 @@ void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv)
 
                if (HAS_GMCH_DISPLAY(dev_priv))
                        i9xx_check_fifo_underruns(crtc);
-               else if (IS_GEN7(dev_priv))
+               else if (IS_GEN(dev_priv, 7))
                        ivybridge_check_fifo_underruns(crtc);
        }
 
index c3379bde266f12b1d1756733943ddc14b9d628e1..16f253deaf8d559647d2b5e2449761f8369a8a75 100644 (file)
@@ -60,7 +60,6 @@
  * functions is deprecated and should be avoided.
  */
 
-#include <drm/drmP.h>
 
 #include "intel_drv.h"
 #include "intel_frontbuffer.h"
index 0f1c4f9ebfd886581ac11beefb477ee047e0ab55..744220296653202fcc40c76c809c86fbf2d55c77 100644 (file)
@@ -192,4 +192,7 @@ static inline void intel_guc_disable_msg(struct intel_guc *guc, u32 mask)
        spin_unlock_irq(&guc->irq_lock);
 }
 
+int intel_guc_reset_engine(struct intel_guc *guc,
+                          struct intel_engine_cs *engine);
+
 #endif
index a67144ee5ceb6c93a30f8a48f9d5314166e7cb94..13ff7003c6bef3f56d1fca2bdb3eb27ae63721c6 100644 (file)
@@ -77,10 +77,6 @@ static void guc_fw_select(struct intel_uc_fw *guc_fw)
                guc_fw->path = I915_KBL_GUC_UCODE;
                guc_fw->major_ver_wanted = KBL_FW_MAJOR;
                guc_fw->minor_ver_wanted = KBL_FW_MINOR;
-       } else {
-               dev_info(dev_priv->drm.dev,
-                        "%s: No firmware known for this platform!\n",
-                        intel_uc_fw_type_repr(guc_fw->type));
        }
 }
 
@@ -115,7 +111,7 @@ static void guc_prepare_xfer(struct intel_guc *guc)
        else
                I915_WRITE(GEN9_GT_PM_CONFIG, GT_DOORBELL_ENABLE);
 
-       if (IS_GEN9(dev_priv)) {
+       if (IS_GEN(dev_priv, 9)) {
                /* DOP Clock Gating Enable for GuC clocks */
                I915_WRITE(GEN7_MISCCPCTL, (GEN8_DOP_CLOCK_GATE_GUC_ENABLE |
                                            I915_READ(GEN7_MISCCPCTL)));
index d3ebdbc0182e745b0d94611b862a6f03afbb8550..b53582c0c6c100d900539b4413dbede5a94b83a8 100644 (file)
@@ -436,6 +436,7 @@ static void guc_log_capture_logs(struct intel_guc_log *log)
 {
        struct intel_guc *guc = log_to_guc(log);
        struct drm_i915_private *dev_priv = guc_to_i915(guc);
+       intel_wakeref_t wakeref;
 
        guc_read_update_log_buffer(log);
 
@@ -443,9 +444,8 @@ static void guc_log_capture_logs(struct intel_guc_log *log)
         * Generally device is expected to be active only at this
         * time, so get/put should be really quick.
         */
-       intel_runtime_pm_get(dev_priv);
-       guc_action_flush_log_complete(guc);
-       intel_runtime_pm_put(dev_priv);
+       with_intel_runtime_pm(dev_priv, wakeref)
+               guc_action_flush_log_complete(guc);
 }
 
 int intel_guc_log_create(struct intel_guc_log *log)
@@ -505,7 +505,8 @@ int intel_guc_log_set_level(struct intel_guc_log *log, u32 level)
 {
        struct intel_guc *guc = log_to_guc(log);
        struct drm_i915_private *dev_priv = guc_to_i915(guc);
-       int ret;
+       intel_wakeref_t wakeref;
+       int ret = 0;
 
        BUILD_BUG_ON(GUC_LOG_VERBOSITY_MIN != 0);
        GEM_BUG_ON(!log->vma);
@@ -519,16 +520,14 @@ int intel_guc_log_set_level(struct intel_guc_log *log, u32 level)
 
        mutex_lock(&dev_priv->drm.struct_mutex);
 
-       if (log->level == level) {
-               ret = 0;
+       if (log->level == level)
                goto out_unlock;
-       }
 
-       intel_runtime_pm_get(dev_priv);
-       ret = guc_action_control_log(guc, GUC_LOG_LEVEL_IS_VERBOSE(level),
-                                    GUC_LOG_LEVEL_IS_ENABLED(level),
-                                    GUC_LOG_LEVEL_TO_VERBOSITY(level));
-       intel_runtime_pm_put(dev_priv);
+       with_intel_runtime_pm(dev_priv, wakeref)
+               ret = guc_action_control_log(guc,
+                                            GUC_LOG_LEVEL_IS_VERBOSE(level),
+                                            GUC_LOG_LEVEL_IS_ENABLED(level),
+                                            GUC_LOG_LEVEL_TO_VERBOSITY(level));
        if (ret) {
                DRM_DEBUG_DRIVER("guc_log_control action failed %d\n", ret);
                goto out_unlock;
@@ -601,6 +600,7 @@ void intel_guc_log_relay_flush(struct intel_guc_log *log)
 {
        struct intel_guc *guc = log_to_guc(log);
        struct drm_i915_private *i915 = guc_to_i915(guc);
+       intel_wakeref_t wakeref;
 
        /*
         * Before initiating the forceful flush, wait for any pending/ongoing
@@ -608,9 +608,8 @@ void intel_guc_log_relay_flush(struct intel_guc_log *log)
         */
        flush_work(&log->relay.flush_work);
 
-       intel_runtime_pm_get(i915);
-       guc_action_flush_log(guc);
-       intel_runtime_pm_put(i915);
+       with_intel_runtime_pm(i915, wakeref)
+               guc_action_flush_log(guc);
 
        /* GuC would have updated log buffer by now, so capture it */
        guc_log_capture_logs(log);
index 1570dcbe249c0c8c6b9c8755bf0a89e2a8b2368b..ab1c49b106f2aa4c871052705c492e4a5f86765b 100644 (file)
@@ -572,7 +572,8 @@ static void inject_preempt_context(struct work_struct *work)
                if (engine->id == RCS) {
                        cs = gen8_emit_ggtt_write_rcs(cs,
                                                      GUC_PREEMPT_FINISHED,
-                                                     addr);
+                                                     addr,
+                                                     PIPE_CONTROL_CS_STALL);
                } else {
                        cs = gen8_emit_ggtt_write(cs,
                                                  GUC_PREEMPT_FINISHED,
index c22b3e18a0f5ff54530b0676aad6303d6c298889..1d7d26e4cf14f7f2e7d3c4988a354d9d5c82f62b 100644 (file)
@@ -49,6 +49,9 @@ static bool is_supported_device(struct drm_i915_private *dev_priv)
                return true;
        if (IS_BROXTON(dev_priv))
                return true;
+       if (IS_COFFEELAKE(dev_priv))
+               return true;
+
        return false;
 }
 
@@ -105,15 +108,6 @@ int intel_gvt_init(struct drm_i915_private *dev_priv)
                return -EIO;
        }
 
-       /*
-        * We're not in host or fail to find a MPT module, disable GVT-g
-        */
-       ret = intel_gvt_init_host();
-       if (ret) {
-               DRM_DEBUG_DRIVER("Not in host or MPT modules not found\n");
-               goto bail;
-       }
-
        ret = intel_gvt_init_device(dev_priv);
        if (ret) {
                DRM_DEBUG_DRIVER("Fail to init GVT device\n");
index e26d05a46451fe7f604474aa044e8f1307022177..741441daae321d68e34f08ce98ca628ea1b93b2a 100644 (file)
  */
 
 #include "i915_drv.h"
-
-static bool
-ipehr_is_semaphore_wait(struct intel_engine_cs *engine, u32 ipehr)
-{
-       ipehr &= ~MI_SEMAPHORE_SYNC_MASK;
-       return ipehr == (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE |
-                        MI_SEMAPHORE_REGISTER);
-}
-
-static struct intel_engine_cs *
-semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr,
-                                u64 offset)
-{
-       struct drm_i915_private *dev_priv = engine->i915;
-       u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK;
-       struct intel_engine_cs *signaller;
-       enum intel_engine_id id;
-
-       for_each_engine(signaller, dev_priv, id) {
-               if (engine == signaller)
-                       continue;
-
-               if (sync_bits == signaller->semaphore.mbox.wait[engine->hw_id])
-                       return signaller;
-       }
-
-       DRM_DEBUG_DRIVER("No signaller ring found for %s, ipehr 0x%08x\n",
-                        engine->name, ipehr);
-
-       return ERR_PTR(-ENODEV);
-}
-
-static struct intel_engine_cs *
-semaphore_waits_for(struct intel_engine_cs *engine, u32 *seqno)
-{
-       struct drm_i915_private *dev_priv = engine->i915;
-       void __iomem *vaddr;
-       u32 cmd, ipehr, head;
-       u64 offset = 0;
-       int i, backwards;
-
-       /*
-        * This function does not support execlist mode - any attempt to
-        * proceed further into this function will result in a kernel panic
-        * when dereferencing ring->buffer, which is not set up in execlist
-        * mode.
-        *
-        * The correct way of doing it would be to derive the currently
-        * executing ring buffer from the current context, which is derived
-        * from the currently running request. Unfortunately, to get the
-        * current request we would have to grab the struct_mutex before doing
-        * anything else, which would be ill-advised since some other thread
-        * might have grabbed it already and managed to hang itself, causing
-        * the hang checker to deadlock.
-        *
-        * Therefore, this function does not support execlist mode in its
-        * current form. Just return NULL and move on.
-        */
-       if (engine->buffer == NULL)
-               return NULL;
-
-       ipehr = I915_READ(RING_IPEHR(engine->mmio_base));
-       if (!ipehr_is_semaphore_wait(engine, ipehr))
-               return NULL;
-
-       /*
-        * HEAD is likely pointing to the dword after the actual command,
-        * so scan backwards until we find the MBOX. But limit it to just 3
-        * or 4 dwords depending on the semaphore wait command size.
-        * Note that we don't care about ACTHD here since that might
-        * point at at batch, and semaphores are always emitted into the
-        * ringbuffer itself.
-        */
-       head = I915_READ_HEAD(engine) & HEAD_ADDR;
-       backwards = (INTEL_GEN(dev_priv) >= 8) ? 5 : 4;
-       vaddr = (void __iomem *)engine->buffer->vaddr;
-
-       for (i = backwards; i; --i) {
-               /*
-                * Be paranoid and presume the hw has gone off into the wild -
-                * our ring is smaller than what the hardware (and hence
-                * HEAD_ADDR) allows. Also handles wrap-around.
-                */
-               head &= engine->buffer->size - 1;
-
-               /* This here seems to blow up */
-               cmd = ioread32(vaddr + head);
-               if (cmd == ipehr)
-                       break;
-
-               head -= 4;
-       }
-
-       if (!i)
-               return NULL;
-
-       *seqno = ioread32(vaddr + head + 4) + 1;
-       return semaphore_wait_to_signaller_ring(engine, ipehr, offset);
-}
-
-static int semaphore_passed(struct intel_engine_cs *engine)
-{
-       struct drm_i915_private *dev_priv = engine->i915;
-       struct intel_engine_cs *signaller;
-       u32 seqno;
-
-       engine->hangcheck.deadlock++;
-
-       signaller = semaphore_waits_for(engine, &seqno);
-       if (signaller == NULL)
-               return -1;
-
-       if (IS_ERR(signaller))
-               return 0;
-
-       /* Prevent pathological recursion due to driver bugs */
-       if (signaller->hangcheck.deadlock >= I915_NUM_ENGINES)
-               return -1;
-
-       if (intel_engine_signaled(signaller, seqno))
-               return 1;
-
-       /* cursory check for an unkickable deadlock */
-       if (I915_READ_CTL(signaller) & RING_WAIT_SEMAPHORE &&
-           semaphore_passed(signaller) < 0)
-               return -1;
-
-       return 0;
-}
-
-static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv)
-{
-       struct intel_engine_cs *engine;
-       enum intel_engine_id id;
-
-       for_each_engine(engine, dev_priv, id)
-               engine->hangcheck.deadlock = 0;
-}
+#include "i915_reset.h"
 
 static bool instdone_unchanged(u32 current_instdone, u32 *old_instdone)
 {
@@ -236,7 +99,7 @@ engine_stuck(struct intel_engine_cs *engine, u64 acthd)
        if (ha != ENGINE_DEAD)
                return ha;
 
-       if (IS_GEN2(dev_priv))
+       if (IS_GEN(dev_priv, 2))
                return ENGINE_DEAD;
 
        /* Is the chip hanging on a WAIT_FOR_EVENT?
@@ -252,37 +115,12 @@ engine_stuck(struct intel_engine_cs *engine, u64 acthd)
                return ENGINE_WAIT_KICK;
        }
 
-       if (IS_GEN(dev_priv, 6, 7) && tmp & RING_WAIT_SEMAPHORE) {
-               switch (semaphore_passed(engine)) {
-               default:
-                       return ENGINE_DEAD;
-               case 1:
-                       i915_handle_error(dev_priv, ALL_ENGINES, 0,
-                                         "stuck semaphore on %s",
-                                         engine->name);
-                       I915_WRITE_CTL(engine, tmp);
-                       return ENGINE_WAIT_KICK;
-               case 0:
-                       return ENGINE_WAIT;
-               }
-       }
-
        return ENGINE_DEAD;
 }
 
 static void hangcheck_load_sample(struct intel_engine_cs *engine,
                                  struct intel_engine_hangcheck *hc)
 {
-       /* We don't strictly need an irq-barrier here, as we are not
-        * serving an interrupt request, be paranoid in case the
-        * barrier has side-effects (such as preventing a broken
-        * cacheline snoop) and so be sure that we can see the seqno
-        * advance. If the seqno should stick, due to a stale
-        * cacheline, we would erroneously declare the GPU hung.
-        */
-       if (engine->irq_seqno_barrier)
-               engine->irq_seqno_barrier(engine);
-
        hc->acthd = intel_engine_get_active_head(engine);
        hc->seqno = intel_engine_get_seqno(engine);
 }
@@ -357,10 +195,6 @@ static void hangcheck_accumulate_sample(struct intel_engine_cs *engine,
                break;
 
        case ENGINE_DEAD:
-               if (GEM_SHOW_DEBUG()) {
-                       struct drm_printer p = drm_debug_printer("hangcheck");
-                       intel_engine_dump(engine, &p, "%s\n", engine->name);
-               }
                break;
 
        default:
@@ -433,8 +267,6 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
        for_each_engine(engine, dev_priv, id) {
                struct intel_engine_hangcheck hc;
 
-               semaphore_clear_deadlocks(dev_priv);
-
                hangcheck_load_sample(engine, &hc);
                hangcheck_accumulate_sample(engine, &hc);
                hangcheck_store_sample(engine, &hc);
@@ -449,6 +281,17 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
                        wedged |= intel_engine_flag(engine);
        }
 
+       if (GEM_SHOW_DEBUG() && (hung | stuck)) {
+               struct drm_printer p = drm_debug_printer("hangcheck");
+
+               for_each_engine(engine, dev_priv, id) {
+                       if (intel_engine_is_idle(engine))
+                               continue;
+
+                       intel_engine_dump(engine, &p, "%s\n", engine->name);
+               }
+       }
+
        if (wedged) {
                dev_err(dev_priv->drm.dev,
                        "GPU recovery timed out,"
index 1bf487f9425404cb85b3b5f5ef3bb43be32a0405..ce7ba3a9c0002c7fd65b5378e7d82be4fc7afd92 100644 (file)
@@ -6,7 +6,6 @@
  * Sean Paul <seanpaul@chromium.org>
  */
 
-#include <drm/drmP.h>
 #include <drm/drm_hdcp.h>
 #include <linux/i2c.h>
 #include <linux/random.h>
@@ -15,6 +14,7 @@
 #include "i915_reg.h"
 
 #define KEY_LOAD_TRIES 5
+#define ENCRYPT_STATUS_CHANGE_TIMEOUT_MS       50
 
 static
 bool intel_hdcp_is_ksv_valid(u8 *ksv)
@@ -157,10 +157,11 @@ static int intel_hdcp_load_keys(struct drm_i915_private *dev_priv)
        /*
         * Initiate loading the HDCP key from fuses.
         *
-        * BXT+ platforms, HDCP key needs to be loaded by SW. Only SKL and KBL
-        * differ in the key load trigger process from other platforms.
+        * BXT+ platforms, HDCP key needs to be loaded by SW. Only Gen 9
+        * platforms except BXT and GLK, differ in the key load trigger process
+        * from other platforms. So GEN9_BC uses the GT Driver Mailbox i/f.
         */
-       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+       if (IS_GEN9_BC(dev_priv)) {
                mutex_lock(&dev_priv->pcu_lock);
                ret = sandybridge_pcode_write(dev_priv,
                                              SKL_PCODE_LOAD_HDCP_KEYS, 1);
@@ -636,7 +637,8 @@ static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port,
 
        /* Wait for encryption confirmation */
        if (intel_wait_for_register(dev_priv, PORT_HDCP_STATUS(port),
-                                   HDCP_STATUS_ENC, HDCP_STATUS_ENC, 20)) {
+                                   HDCP_STATUS_ENC, HDCP_STATUS_ENC,
+                                   ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) {
                DRM_ERROR("Timed out waiting for encryption\n");
                return -ETIMEDOUT;
        }
@@ -666,7 +668,7 @@ static int _intel_hdcp_disable(struct intel_connector *connector)
 
        I915_WRITE(PORT_HDCP_CONF(port), 0);
        if (intel_wait_for_register(dev_priv, PORT_HDCP_STATUS(port), ~0, 0,
-                                   20)) {
+                                   ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) {
                DRM_ERROR("Failed to disable HDCP, timeout clearing status\n");
                return -ETIMEDOUT;
        }
@@ -768,8 +770,7 @@ static void intel_hdcp_prop_work(struct work_struct *work)
 bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port)
 {
        /* PORT E doesn't have HDCP, and PORT F is disabled */
-       return ((INTEL_GEN(dev_priv) >= 8 || IS_HASWELL(dev_priv)) &&
-               !IS_CHERRYVIEW(dev_priv) && port < PORT_E);
+       return INTEL_GEN(dev_priv) >= 9 && port < PORT_E;
 }
 
 int intel_hdcp_init(struct intel_connector *connector,
@@ -837,8 +838,8 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
                             struct drm_connector_state *old_state,
                             struct drm_connector_state *new_state)
 {
-       uint64_t old_cp = old_state->content_protection;
-       uint64_t new_cp = new_state->content_protection;
+       u64 old_cp = old_state->content_protection;
+       u64 new_cp = new_state->content_protection;
        struct drm_crtc_state *crtc_state;
 
        if (!new_state->crtc) {
index 07e803a604bddada573810e15eef3c01975a9dd8..97a98e1bea5607f6eadef4a58e385d218335313b 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/hdmi.h>
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
@@ -479,18 +478,14 @@ static void intel_hdmi_set_avi_infoframe(struct intel_encoder *encoder,
                                         const struct intel_crtc_state *crtc_state,
                                         const struct drm_connector_state *conn_state)
 {
-       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
        const struct drm_display_mode *adjusted_mode =
                &crtc_state->base.adjusted_mode;
-       struct drm_connector *connector = &intel_hdmi->attached_connector->base;
-       bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported ||
-          connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB420;
        union hdmi_infoframe frame;
        int ret;
 
        ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
-                                                      adjusted_mode,
-                                                      is_hdmi2_sink);
+                                                      conn_state->connector,
+                                                      adjusted_mode);
        if (ret < 0) {
                DRM_ERROR("couldn't fill AVI infoframe\n");
                return;
@@ -503,12 +498,12 @@ static void intel_hdmi_set_avi_infoframe(struct intel_encoder *encoder,
        else
                frame.avi.colorspace = HDMI_COLORSPACE_RGB;
 
-       drm_hdmi_avi_infoframe_quant_range(&frame.avi, adjusted_mode,
+       drm_hdmi_avi_infoframe_quant_range(&frame.avi,
+                                          conn_state->connector,
+                                          adjusted_mode,
                                           crtc_state->limited_color_range ?
                                           HDMI_QUANTIZATION_RANGE_LIMITED :
-                                          HDMI_QUANTIZATION_RANGE_FULL,
-                                          intel_hdmi->rgb_quant_range_selectable,
-                                          is_hdmi2_sink);
+                                          HDMI_QUANTIZATION_RANGE_FULL);
 
        drm_hdmi_avi_infoframe_content_type(&frame.avi,
                                            conn_state);
@@ -1191,15 +1186,17 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+       intel_wakeref_t wakeref;
        bool ret;
 
-       if (!intel_display_power_get_if_enabled(dev_priv,
-                                               encoder->power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    encoder->power_domain);
+       if (!wakeref)
                return false;
 
        ret = intel_sdvo_port_enabled(dev_priv, intel_hdmi->hdmi_reg, pipe);
 
-       intel_display_power_put(dev_priv, encoder->power_domain);
+       intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
 
        return ret;
 }
@@ -1707,9 +1704,9 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
        return true;
 }
 
-bool intel_hdmi_compute_config(struct intel_encoder *encoder,
-                              struct intel_crtc_state *pipe_config,
-                              struct drm_connector_state *conn_state)
+int intel_hdmi_compute_config(struct intel_encoder *encoder,
+                             struct intel_crtc_state *pipe_config,
+                             struct drm_connector_state *conn_state)
 {
        struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
@@ -1725,7 +1722,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
        bool force_dvi = intel_conn_state->force_audio == HDMI_AUDIO_OFF_DVI;
 
        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
-               return false;
+               return -EINVAL;
 
        pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
        pipe_config->has_hdmi_sink = !force_dvi && intel_hdmi->has_hdmi_sink;
@@ -1756,7 +1753,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
                                                &clock_12bpc, &clock_10bpc,
                                                &clock_8bpc)) {
                        DRM_ERROR("Can't support YCBCR420 output\n");
-                       return false;
+                       return -EINVAL;
                }
        }
 
@@ -1806,7 +1803,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
        if (hdmi_port_clock_valid(intel_hdmi, pipe_config->port_clock,
                                  false, force_dvi) != MODE_OK) {
                DRM_DEBUG_KMS("unsupported HDMI clock, rejecting mode\n");
-               return false;
+               return -EINVAL;
        }
 
        /* Set user selected PAR to incoming mode's member */
@@ -1825,7 +1822,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
                }
        }
 
-       return true;
+       return 0;
 }
 
 static void
@@ -1835,7 +1832,6 @@ intel_hdmi_unset_edid(struct drm_connector *connector)
 
        intel_hdmi->has_hdmi_sink = false;
        intel_hdmi->has_audio = false;
-       intel_hdmi->rgb_quant_range_selectable = false;
 
        intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE;
        intel_hdmi->dp_dual_mode.max_tmds_clock = 0;
@@ -1896,11 +1892,12 @@ intel_hdmi_set_edid(struct drm_connector *connector)
 {
        struct drm_i915_private *dev_priv = to_i915(connector->dev);
        struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+       intel_wakeref_t wakeref;
        struct edid *edid;
        bool connected = false;
        struct i2c_adapter *i2c;
 
-       intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
+       wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
 
        i2c = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
 
@@ -1915,13 +1912,10 @@ intel_hdmi_set_edid(struct drm_connector *connector)
 
        intel_hdmi_dp_dual_mode_detect(connector, edid != NULL);
 
-       intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
 
        to_intel_connector(connector)->detect_edid = edid;
        if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
-               intel_hdmi->rgb_quant_range_selectable =
-                       drm_rgb_quant_range_selectable(edid);
-
                intel_hdmi->has_audio = drm_detect_monitor_audio(edid);
                intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
 
@@ -1940,11 +1934,12 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
        struct drm_i915_private *dev_priv = to_i915(connector->dev);
        struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
        struct intel_encoder *encoder = &hdmi_to_dig_port(intel_hdmi)->base;
+       intel_wakeref_t wakeref;
 
        DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
                      connector->base.id, connector->name);
 
-       intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
+       wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
 
        if (IS_ICELAKE(dev_priv) &&
            !intel_digital_port_connected(encoder))
@@ -1956,7 +1951,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
                status = connector_status_connected;
 
 out:
-       intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
 
        if (status != connector_status_connected)
                cec_notifier_phys_addr_invalidate(intel_hdmi->cec_notifier);
index e24174d08fedb55ca4619e61cb96570deab6bc52..e027d2b4abe541cb317dbdb1a554f34e0f919b8b 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <linux/kernel.h>
 
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 
 #include "i915_drv.h"
@@ -227,9 +226,10 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
                container_of(work, typeof(*dev_priv),
                             hotplug.reenable_work.work);
        struct drm_device *dev = &dev_priv->drm;
+       intel_wakeref_t wakeref;
        enum hpd_pin pin;
 
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
        spin_lock_irq(&dev_priv->irq_lock);
        for_each_hpd_pin(pin) {
@@ -262,7 +262,7 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
                dev_priv->display.hpd_irq_setup(dev_priv);
        spin_unlock_irq(&dev_priv->irq_lock);
 
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
 }
 
 bool intel_encoder_hotplug(struct intel_encoder *encoder,
index bc27b691d8248473abd207138817f10b55971751..9bd1c9002c2ad9095cf6d457308df63ef20787b8 100644 (file)
@@ -115,14 +115,14 @@ fail:
 int intel_huc_check_status(struct intel_huc *huc)
 {
        struct drm_i915_private *dev_priv = huc_to_i915(huc);
-       bool status;
+       intel_wakeref_t wakeref;
+       bool status = false;
 
        if (!HAS_HUC(dev_priv))
                return -ENODEV;
 
-       intel_runtime_pm_get(dev_priv);
-       status = I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED;
-       intel_runtime_pm_put(dev_priv);
+       with_intel_runtime_pm(dev_priv, wakeref)
+               status = I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED;
 
        return status;
 }
index f93d2384d4820ee23245f5d3eeb64fe39fd7aebe..7d7bfc7f7ca70caa0e6374ac3de87522a6d233b0 100644 (file)
@@ -23,8 +23,8 @@
  */
 
 #define BXT_HUC_FW_MAJOR 01
-#define BXT_HUC_FW_MINOR 07
-#define BXT_BLD_NUM 1398
+#define BXT_HUC_FW_MINOR 8
+#define BXT_BLD_NUM 2893
 
 #define SKL_HUC_FW_MAJOR 01
 #define SKL_HUC_FW_MINOR 07
@@ -76,9 +76,6 @@ static void huc_fw_select(struct intel_uc_fw *huc_fw)
                huc_fw->path = I915_KBL_HUC_UCODE;
                huc_fw->major_ver_wanted = KBL_HUC_FW_MAJOR;
                huc_fw->minor_ver_wanted = KBL_HUC_FW_MINOR;
-       } else {
-               DRM_WARN("%s: No firmware known for this platform!\n",
-                        intel_uc_fw_type_repr(huc_fw->type));
        }
 }
 
index 802d0394ccc4ad82d92e244cce2109313c84b9a2..4f6dc8c94634e543fcc3cddef733ed7160c19304 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 #include <linux/export.h>
-#include <drm/drmP.h>
 #include <drm/drm_hdcp.h>
 #include "intel_drv.h"
 #include <drm/i915_drm.h>
@@ -698,12 +697,13 @@ out:
 static int
 gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
 {
-       struct intel_gmbus *bus = container_of(adapter, struct intel_gmbus,
-                                              adapter);
+       struct intel_gmbus *bus =
+               container_of(adapter, struct intel_gmbus, adapter);
        struct drm_i915_private *dev_priv = bus->dev_priv;
+       intel_wakeref_t wakeref;
        int ret;
 
-       intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
+       wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
 
        if (bus->force_bit) {
                ret = i2c_bit_algo.master_xfer(adapter, msgs, num);
@@ -715,17 +715,16 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
                        bus->force_bit |= GMBUS_FORCE_BIT_RETRY;
        }
 
-       intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
 
        return ret;
 }
 
 int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
 {
-       struct intel_gmbus *bus = container_of(adapter, struct intel_gmbus,
-                                              adapter);
+       struct intel_gmbus *bus =
+               container_of(adapter, struct intel_gmbus, adapter);
        struct drm_i915_private *dev_priv = bus->dev_priv;
-       int ret;
        u8 cmd = DRM_HDCP_DDC_AKSV;
        u8 buf[DRM_HDCP_KSV_LEN] = { 0 };
        struct i2c_msg msgs[] = {
@@ -742,8 +741,10 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
                        .buf = buf,
                }
        };
+       intel_wakeref_t wakeref;
+       int ret;
 
-       intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
+       wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
        mutex_lock(&dev_priv->gmbus_mutex);
 
        /*
@@ -754,7 +755,7 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
        ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs), GMBUS_AKSV_SELECT);
 
        mutex_unlock(&dev_priv->gmbus_mutex);
-       intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
 
        return ret;
 }
index 4be167dcd209ba9a9d43be93821eb59ecb1e275b..8aa8a486254319a77666e49a851b1bfad78bed7f 100644 (file)
  */
 #include <linux/interrupt.h>
 
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 #include "i915_gem_render_state.h"
@@ -303,6 +302,7 @@ static void __unwind_incomplete_requests(struct intel_engine_cs *engine)
         */
        if (!(prio & I915_PRIORITY_NEWCLIENT)) {
                prio |= I915_PRIORITY_NEWCLIENT;
+               active->sched.attr.priority = prio;
                list_move_tail(&active->sched.link,
                               i915_sched_lookup_priolist(engine, prio));
        }
@@ -363,31 +363,12 @@ execlists_context_schedule_out(struct i915_request *rq, unsigned long status)
        trace_i915_request_out(rq);
 }
 
-static void
-execlists_update_context_pdps(struct i915_hw_ppgtt *ppgtt, u32 *reg_state)
-{
-       ASSIGN_CTX_PDP(ppgtt, reg_state, 3);
-       ASSIGN_CTX_PDP(ppgtt, reg_state, 2);
-       ASSIGN_CTX_PDP(ppgtt, reg_state, 1);
-       ASSIGN_CTX_PDP(ppgtt, reg_state, 0);
-}
-
 static u64 execlists_update_context(struct i915_request *rq)
 {
-       struct i915_hw_ppgtt *ppgtt = rq->gem_context->ppgtt;
        struct intel_context *ce = rq->hw_context;
-       u32 *reg_state = ce->lrc_reg_state;
 
-       reg_state[CTX_RING_TAIL+1] = intel_ring_set_tail(rq->ring, rq->tail);
-
-       /*
-        * True 32b PPGTT with dynamic page allocation: update PDP
-        * registers and point the unallocated PDPs to scratch page.
-        * PML4 is allocated during ppgtt init, so this is not needed
-        * in 48-bit mode.
-        */
-       if (!i915_vm_is_48bit(&ppgtt->vm))
-               execlists_update_context_pdps(ppgtt, reg_state);
+       ce->lrc_reg_state[CTX_RING_TAIL + 1] =
+               intel_ring_set_tail(rq->ring, rq->tail);
 
        /*
         * Make sure the context image is complete before we submit it to HW.
@@ -455,7 +436,7 @@ static void execlists_submit_ports(struct intel_engine_cs *engine)
                        desc = execlists_update_context(rq);
                        GEM_DEBUG_EXEC(port[n].context_id = upper_32_bits(desc));
 
-                       GEM_TRACE("%s in[%d]:  ctx=%d.%d, global=%d (fence %llx:%d) (current %d), prio=%d\n",
+                       GEM_TRACE("%s in[%d]:  ctx=%d.%d, global=%d (fence %llx:%lld) (current %d), prio=%d\n",
                                  engine->name, n,
                                  port[n].context_id, count,
                                  rq->global_seqno,
@@ -645,6 +626,9 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
                int i;
 
                priolist_for_each_request_consume(rq, rn, p, i) {
+                       GEM_BUG_ON(last &&
+                                  need_preempt(engine, last, rq_prio(rq)));
+
                        /*
                         * Can we combine this request with the current port?
                         * It has to be the same context/ringbuffer and not
@@ -748,7 +732,7 @@ execlists_cancel_port_requests(struct intel_engine_execlists * const execlists)
        while (num_ports-- && port_isset(port)) {
                struct i915_request *rq = port_request(port);
 
-               GEM_TRACE("%s:port%u global=%d (fence %llx:%d), (current %d)\n",
+               GEM_TRACE("%s:port%u global=%d (fence %llx:%lld), (current %d)\n",
                          rq->engine->name,
                          (unsigned int)(port - execlists->port),
                          rq->global_seqno,
@@ -770,6 +754,13 @@ execlists_cancel_port_requests(struct intel_engine_execlists * const execlists)
        execlists_clear_all_active(execlists);
 }
 
+static inline void
+invalidate_csb_entries(const u32 *first, const u32 *last)
+{
+       clflush((void *)first);
+       clflush((void *)last);
+}
+
 static void reset_csb_pointers(struct intel_engine_execlists *execlists)
 {
        const unsigned int reset_value = GEN8_CSB_ENTRIES - 1;
@@ -785,6 +776,9 @@ static void reset_csb_pointers(struct intel_engine_execlists *execlists)
         */
        execlists->csb_head = reset_value;
        WRITE_ONCE(*execlists->csb_write, reset_value);
+
+       invalidate_csb_entries(&execlists->csb_status[0],
+                              &execlists->csb_status[GEN8_CSB_ENTRIES - 1]);
 }
 
 static void nop_submission_tasklet(unsigned long data)
@@ -826,7 +820,7 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine)
        list_for_each_entry(rq, &engine->timeline.requests, link) {
                GEM_BUG_ON(!rq->global_seqno);
 
-               if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags))
+               if (i915_request_signaled(rq))
                        continue;
 
                dma_fence_set_error(&rq->fence, -EIO);
@@ -966,7 +960,7 @@ static void process_csb(struct intel_engine_cs *engine)
                                                EXECLISTS_ACTIVE_USER));
 
                rq = port_unpack(port, &count);
-               GEM_TRACE("%s out[0]: ctx=%d.%d, global=%d (fence %llx:%d) (current %d), prio=%d\n",
+               GEM_TRACE("%s out[0]: ctx=%d.%d, global=%d (fence %llx:%lld) (current %d), prio=%d\n",
                          engine->name,
                          port->context_id, count,
                          rq ? rq->global_seqno : 0,
@@ -1020,6 +1014,19 @@ static void process_csb(struct intel_engine_cs *engine)
        } while (head != tail);
 
        execlists->csb_head = head;
+
+       /*
+        * Gen11 has proven to fail wrt global observation point between
+        * entry and tail update, failing on the ordering and thus
+        * we see an old entry in the context status buffer.
+        *
+        * Forcibly evict out entries for the next gpu csb update,
+        * to increase the odds that we get a fresh entries with non
+        * working hardware. The cost for doing so comes out mostly with
+        * the wash as hardware, working or not, will need to do the
+        * invalidation before.
+        */
+       invalidate_csb_entries(&buf[0], &buf[GEN8_CSB_ENTRIES - 1]);
 }
 
 static void __execlists_submission_tasklet(struct intel_engine_cs *const engine)
@@ -1042,7 +1049,7 @@ static void execlists_submission_tasklet(unsigned long data)
 
        GEM_TRACE("%s awake?=%d, active=%x\n",
                  engine->name,
-                 engine->i915->gt.awake,
+                 !!engine->i915->gt.awake,
                  engine->execlists.active);
 
        spin_lock_irqsave(&engine->timeline.lock, flags);
@@ -1247,29 +1254,88 @@ execlists_context_pin(struct intel_engine_cs *engine,
        return __execlists_context_pin(engine, ctx, ce);
 }
 
+static int emit_pdps(struct i915_request *rq)
+{
+       const struct intel_engine_cs * const engine = rq->engine;
+       struct i915_hw_ppgtt * const ppgtt = rq->gem_context->ppgtt;
+       int err, i;
+       u32 *cs;
+
+       GEM_BUG_ON(intel_vgpu_active(rq->i915));
+
+       /*
+        * Beware ye of the dragons, this sequence is magic!
+        *
+        * Small changes to this sequence can cause anything from
+        * GPU hangs to forcewake errors and machine lockups!
+        */
+
+       /* Flush any residual operations from the context load */
+       err = engine->emit_flush(rq, EMIT_FLUSH);
+       if (err)
+               return err;
+
+       /* Magic required to prevent forcewake errors! */
+       err = engine->emit_flush(rq, EMIT_INVALIDATE);
+       if (err)
+               return err;
+
+       cs = intel_ring_begin(rq, 4 * GEN8_3LVL_PDPES + 2);
+       if (IS_ERR(cs))
+               return PTR_ERR(cs);
+
+       /* Ensure the LRI have landed before we invalidate & continue */
+       *cs++ = MI_LOAD_REGISTER_IMM(2 * GEN8_3LVL_PDPES) | MI_LRI_FORCE_POSTED;
+       for (i = GEN8_3LVL_PDPES; i--; ) {
+               const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i);
+
+               *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_UDW(engine, i));
+               *cs++ = upper_32_bits(pd_daddr);
+               *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_LDW(engine, i));
+               *cs++ = lower_32_bits(pd_daddr);
+       }
+       *cs++ = MI_NOOP;
+
+       intel_ring_advance(rq, cs);
+
+       /* Be doubly sure the LRI have landed before proceeding */
+       err = engine->emit_flush(rq, EMIT_FLUSH);
+       if (err)
+               return err;
+
+       /* Re-invalidate the TLB for luck */
+       return engine->emit_flush(rq, EMIT_INVALIDATE);
+}
+
 static int execlists_request_alloc(struct i915_request *request)
 {
        int ret;
 
        GEM_BUG_ON(!request->hw_context->pin_count);
 
-       /* Flush enough space to reduce the likelihood of waiting after
+       /*
+        * Flush enough space to reduce the likelihood of waiting after
         * we start building the request - in which case we will just
         * have to repeat work.
         */
        request->reserved_space += EXECLISTS_REQUEST_SIZE;
 
-       ret = intel_ring_wait_for_space(request->ring, request->reserved_space);
-       if (ret)
-               return ret;
-
-       /* Note that after this point, we have committed to using
+       /*
+        * Note that after this point, we have committed to using
         * this request as it is being used to both track the
         * state of engine initialisation and liveness of the
         * golden renderstate above. Think twice before you try
         * to cancel/unwind this request now.
         */
 
+       /* Unconditionally invalidate GPU caches and TLBs. */
+       if (i915_vm_is_48bit(&request->gem_context->ppgtt->vm))
+               ret = request->engine->emit_flush(request, EMIT_INVALIDATE);
+       else
+               ret = emit_pdps(request);
+       if (ret)
+               return ret;
+
        request->reserved_space -= EXECLISTS_REQUEST_SIZE;
        return 0;
 }
@@ -1592,7 +1658,7 @@ static void enable_execlists(struct intel_engine_cs *engine)
 {
        struct drm_i915_private *dev_priv = engine->i915;
 
-       I915_WRITE(RING_HWSTAM(engine->mmio_base), 0xffffffff);
+       intel_engine_set_hwsp_writemask(engine, ~0u); /* HWSTAM */
 
        /*
         * Make sure we're not enabling the new 12-deep CSB
@@ -1633,6 +1699,7 @@ static bool unexpected_starting_state(struct intel_engine_cs *engine)
 static int gen8_init_common_ring(struct intel_engine_cs *engine)
 {
        intel_engine_apply_workarounds(engine);
+       intel_engine_apply_whitelist(engine);
 
        intel_mocs_init_engine(engine);
 
@@ -1649,43 +1716,6 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine)
        return 0;
 }
 
-static int gen8_init_render_ring(struct intel_engine_cs *engine)
-{
-       struct drm_i915_private *dev_priv = engine->i915;
-       int ret;
-
-       ret = gen8_init_common_ring(engine);
-       if (ret)
-               return ret;
-
-       intel_engine_apply_whitelist(engine);
-
-       /* We need to disable the AsyncFlip performance optimisations in order
-        * to use MI_WAIT_FOR_EVENT within the CS. It should already be
-        * programmed to '1' on all products.
-        *
-        * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv,bdw,chv
-        */
-       I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE));
-
-       I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
-
-       return 0;
-}
-
-static int gen9_init_render_ring(struct intel_engine_cs *engine)
-{
-       int ret;
-
-       ret = gen8_init_common_ring(engine);
-       if (ret)
-               return ret;
-
-       intel_engine_apply_whitelist(engine);
-
-       return 0;
-}
-
 static struct i915_request *
 execlists_reset_prepare(struct intel_engine_cs *engine)
 {
@@ -1841,56 +1871,11 @@ static void execlists_reset_finish(struct intel_engine_cs *engine)
                  atomic_read(&execlists->tasklet.count));
 }
 
-static int intel_logical_ring_emit_pdps(struct i915_request *rq)
-{
-       struct i915_hw_ppgtt *ppgtt = rq->gem_context->ppgtt;
-       struct intel_engine_cs *engine = rq->engine;
-       const int num_lri_cmds = GEN8_3LVL_PDPES * 2;
-       u32 *cs;
-       int i;
-
-       cs = intel_ring_begin(rq, num_lri_cmds * 2 + 2);
-       if (IS_ERR(cs))
-               return PTR_ERR(cs);
-
-       *cs++ = MI_LOAD_REGISTER_IMM(num_lri_cmds);
-       for (i = GEN8_3LVL_PDPES - 1; i >= 0; i--) {
-               const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i);
-
-               *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_UDW(engine, i));
-               *cs++ = upper_32_bits(pd_daddr);
-               *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_LDW(engine, i));
-               *cs++ = lower_32_bits(pd_daddr);
-       }
-
-       *cs++ = MI_NOOP;
-       intel_ring_advance(rq, cs);
-
-       return 0;
-}
-
 static int gen8_emit_bb_start(struct i915_request *rq,
                              u64 offset, u32 len,
                              const unsigned int flags)
 {
        u32 *cs;
-       int ret;
-
-       /* Don't rely in hw updating PDPs, specially in lite-restore.
-        * Ideally, we should set Force PD Restore in ctx descriptor,
-        * but we can't. Force Restore would be a second option, but
-        * it is unsafe in case of lite-restore (because the ctx is
-        * not idle). PML4 is allocated during ppgtt init so this is
-        * not needed in 48-bit.*/
-       if ((intel_engine_flag(rq->engine) & rq->gem_context->ppgtt->pd_dirty_rings) &&
-           !i915_vm_is_48bit(&rq->gem_context->ppgtt->vm) &&
-           !intel_vgpu_active(rq->i915)) {
-               ret = intel_logical_ring_emit_pdps(rq);
-               if (ret)
-                       return ret;
-
-               rq->gem_context->ppgtt->pd_dirty_rings &= ~intel_engine_flag(rq->engine);
-       }
 
        cs = intel_ring_begin(rq, 6);
        if (IS_ERR(cs))
@@ -1923,6 +1908,7 @@ static int gen8_emit_bb_start(struct i915_request *rq,
 
        *cs++ = MI_ARB_ON_OFF | MI_ARB_DISABLE;
        *cs++ = MI_NOOP;
+
        intel_ring_advance(rq, cs);
 
        return 0;
@@ -2007,7 +1993,7 @@ static int gen8_emit_flush_render(struct i915_request *request,
                 * On GEN9: before VF_CACHE_INVALIDATE we need to emit a NULL
                 * pipe control.
                 */
-               if (IS_GEN9(request->i915))
+               if (IS_GEN(request->i915, 9))
                        vf_flush_wa = true;
 
                /* WaForGAMHang:kbl */
@@ -2078,10 +2064,18 @@ static void gen8_emit_breadcrumb_rcs(struct i915_request *request, u32 *cs)
        /* We're using qword write, seqno should be aligned to 8 bytes. */
        BUILD_BUG_ON(I915_GEM_HWS_INDEX & 1);
 
-       cs = gen8_emit_ggtt_write_rcs(cs, request->global_seqno,
-                                     intel_hws_seqno_address(request->engine));
+       cs = gen8_emit_ggtt_write_rcs(cs,
+                                     request->global_seqno,
+                                     intel_hws_seqno_address(request->engine),
+                                     PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
+                                     PIPE_CONTROL_DEPTH_CACHE_FLUSH |
+                                     PIPE_CONTROL_DC_FLUSH_ENABLE |
+                                     PIPE_CONTROL_FLUSH_ENABLE |
+                                     PIPE_CONTROL_CS_STALL);
+
        *cs++ = MI_USER_INTERRUPT;
        *cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE;
+
        request->tail = intel_ring_offset(request, cs);
        assert_ring_tail_valid(request->ring, request->tail);
 
@@ -2244,6 +2238,8 @@ static int logical_ring_init(struct intel_engine_cs *engine)
        if (ret)
                return ret;
 
+       intel_engine_init_workarounds(engine);
+
        if (HAS_LOGICAL_RING_ELSQ(i915)) {
                execlists->submit_reg = i915->regs +
                        i915_mmio_reg_offset(RING_EXECLIST_SQ_CONTENTS(engine));
@@ -2276,19 +2272,11 @@ static int logical_ring_init(struct intel_engine_cs *engine)
 
 int logical_render_ring_init(struct intel_engine_cs *engine)
 {
-       struct drm_i915_private *dev_priv = engine->i915;
        int ret;
 
        logical_ring_setup(engine);
 
-       if (HAS_L3_DPF(dev_priv))
-               engine->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
-
        /* Override some for render ring. */
-       if (INTEL_GEN(dev_priv) >= 9)
-               engine->init_hw = gen9_init_render_ring;
-       else
-               engine->init_hw = gen8_init_render_ring;
        engine->init_context = gen8_init_rcs_context;
        engine->emit_flush = gen8_emit_flush_render;
        engine->emit_breadcrumb = gen8_emit_breadcrumb_rcs;
@@ -2310,7 +2298,6 @@ int logical_render_ring_init(struct intel_engine_cs *engine)
        }
 
        intel_engine_init_whitelist(engine);
-       intel_engine_init_workarounds(engine);
 
        return 0;
 }
@@ -2325,9 +2312,9 @@ int logical_xcs_ring_init(struct intel_engine_cs *engine)
 static u32
 make_rpcs(struct drm_i915_private *dev_priv)
 {
-       bool subslice_pg = INTEL_INFO(dev_priv)->sseu.has_subslice_pg;
-       u8 slices = hweight8(INTEL_INFO(dev_priv)->sseu.slice_mask);
-       u8 subslices = hweight8(INTEL_INFO(dev_priv)->sseu.subslice_mask[0]);
+       bool subslice_pg = RUNTIME_INFO(dev_priv)->sseu.has_subslice_pg;
+       u8 slices = hweight8(RUNTIME_INFO(dev_priv)->sseu.slice_mask);
+       u8 subslices = hweight8(RUNTIME_INFO(dev_priv)->sseu.subslice_mask[0]);
        u32 rpcs = 0;
 
        /*
@@ -2362,7 +2349,7 @@ make_rpcs(struct drm_i915_private *dev_priv)
         * subslices are enabled, or a count between one and four on the first
         * slice.
         */
-       if (IS_GEN11(dev_priv) && slices == 1 && subslices >= 4) {
+       if (IS_GEN(dev_priv, 11) && slices == 1 && subslices >= 4) {
                GEM_BUG_ON(subslices & 1);
 
                subslice_pg = false;
@@ -2375,7 +2362,7 @@ make_rpcs(struct drm_i915_private *dev_priv)
         * must make an explicit request through RPCS for full
         * enablement.
        */
-       if (INTEL_INFO(dev_priv)->sseu.has_slice_pg) {
+       if (RUNTIME_INFO(dev_priv)->sseu.has_slice_pg) {
                u32 mask, val = slices;
 
                if (INTEL_GEN(dev_priv) >= 11) {
@@ -2403,17 +2390,17 @@ make_rpcs(struct drm_i915_private *dev_priv)
                rpcs |= GEN8_RPCS_ENABLE | GEN8_RPCS_SS_CNT_ENABLE | val;
        }
 
-       if (INTEL_INFO(dev_priv)->sseu.has_eu_pg) {
+       if (RUNTIME_INFO(dev_priv)->sseu.has_eu_pg) {
                u32 val;
 
-               val = INTEL_INFO(dev_priv)->sseu.eu_per_subslice <<
+               val = RUNTIME_INFO(dev_priv)->sseu.eu_per_subslice <<
                      GEN8_RPCS_EU_MIN_SHIFT;
                GEM_BUG_ON(val & ~GEN8_RPCS_EU_MIN_MASK);
                val &= GEN8_RPCS_EU_MIN_MASK;
 
                rpcs |= val;
 
-               val = INTEL_INFO(dev_priv)->sseu.eu_per_subslice <<
+               val = RUNTIME_INFO(dev_priv)->sseu.eu_per_subslice <<
                      GEN8_RPCS_EU_MAX_SHIFT;
                GEM_BUG_ON(val & ~GEN8_RPCS_EU_MAX_MASK);
                val &= GEN8_RPCS_EU_MAX_MASK;
@@ -2538,6 +2525,11 @@ static void execlists_init_reg_state(u32 *regs,
                 * other PDP Descriptors are ignored.
                 */
                ASSIGN_CTX_PML4(ctx->ppgtt, regs);
+       } else {
+               ASSIGN_CTX_PDP(ctx->ppgtt, regs, 3);
+               ASSIGN_CTX_PDP(ctx->ppgtt, regs, 2);
+               ASSIGN_CTX_PDP(ctx->ppgtt, regs, 1);
+               ASSIGN_CTX_PDP(ctx->ppgtt, regs, 0);
        }
 
        if (rcs) {
@@ -2620,7 +2612,7 @@ static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
 {
        struct drm_i915_gem_object *ctx_obj;
        struct i915_vma *vma;
-       uint32_t context_size;
+       u32 context_size;
        struct intel_ring *ring;
        struct i915_timeline *timeline;
        int ret;
@@ -2714,6 +2706,64 @@ void intel_lr_context_resume(struct drm_i915_private *i915)
        }
 }
 
+void intel_execlists_show_requests(struct intel_engine_cs *engine,
+                                  struct drm_printer *m,
+                                  void (*show_request)(struct drm_printer *m,
+                                                       struct i915_request *rq,
+                                                       const char *prefix),
+                                  unsigned int max)
+{
+       const struct intel_engine_execlists *execlists = &engine->execlists;
+       struct i915_request *rq, *last;
+       unsigned long flags;
+       unsigned int count;
+       struct rb_node *rb;
+
+       spin_lock_irqsave(&engine->timeline.lock, flags);
+
+       last = NULL;
+       count = 0;
+       list_for_each_entry(rq, &engine->timeline.requests, link) {
+               if (count++ < max - 1)
+                       show_request(m, rq, "\t\tE ");
+               else
+                       last = rq;
+       }
+       if (last) {
+               if (count > max) {
+                       drm_printf(m,
+                                  "\t\t...skipping %d executing requests...\n",
+                                  count - max);
+               }
+               show_request(m, last, "\t\tE ");
+       }
+
+       last = NULL;
+       count = 0;
+       drm_printf(m, "\t\tQueue priority: %d\n", execlists->queue_priority);
+       for (rb = rb_first_cached(&execlists->queue); rb; rb = rb_next(rb)) {
+               struct i915_priolist *p = rb_entry(rb, typeof(*p), node);
+               int i;
+
+               priolist_for_each_request(rq, p, i) {
+                       if (count++ < max - 1)
+                               show_request(m, rq, "\t\tQ ");
+                       else
+                               last = rq;
+               }
+       }
+       if (last) {
+               if (count > max) {
+                       drm_printf(m,
+                                  "\t\t...skipping %d queued requests...\n",
+                                  count - max);
+               }
+               show_request(m, last, "\t\tQ ");
+       }
+
+       spin_unlock_irqrestore(&engine->timeline.lock, flags);
+}
+
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 #include "selftests/intel_lrc.c"
 #endif
index f5a5502ecf70fa475f0e866acb393f6192892584..3d86c27c6b32c41e0905c9026b631c330a944162 100644 (file)
@@ -97,11 +97,19 @@ int logical_xcs_ring_init(struct intel_engine_cs *engine);
  */
 #define LRC_HEADER_PAGES LRC_PPHWSP_PN
 
+struct drm_printer;
+
 struct drm_i915_private;
 struct i915_gem_context;
 
 void intel_lr_context_resume(struct drm_i915_private *dev_priv);
-
 void intel_execlists_set_default_submission(struct intel_engine_cs *engine);
 
+void intel_execlists_show_requests(struct intel_engine_cs *engine,
+                                  struct drm_printer *m,
+                                  void (*show_request)(struct drm_printer *m,
+                                                       struct i915_request *rq,
+                                                       const char *prefix),
+                                  unsigned int max);
+
 #endif /* _INTEL_LRC_H_ */
index 96a8d9524b0c24445972e99c5a3bc958f379b739..322bdddda164db496a4190323004ebf2ed916e86 100644 (file)
@@ -288,12 +288,12 @@ static bool lspcon_parade_fw_ready(struct drm_dp_aux *aux)
 }
 
 static bool _lspcon_parade_write_infoframe_blocks(struct drm_dp_aux *aux,
-                                                 uint8_t *avi_buf)
+                                                 u8 *avi_buf)
 {
        u8 avi_if_ctrl;
        u8 block_count = 0;
        u8 *data;
-       uint16_t reg;
+       u16 reg;
        ssize_t ret;
 
        while (block_count < 4) {
@@ -335,10 +335,10 @@ static bool _lspcon_parade_write_infoframe_blocks(struct drm_dp_aux *aux,
 }
 
 static bool _lspcon_write_avi_infoframe_parade(struct drm_dp_aux *aux,
-                                              const uint8_t *frame,
+                                              const u8 *frame,
                                               ssize_t len)
 {
-       uint8_t avi_if[LSPCON_PARADE_AVI_IF_DATA_SIZE] = {1, };
+       u8 avi_if[LSPCON_PARADE_AVI_IF_DATA_SIZE] = {1, };
 
        /*
         * Parade's frames contains 32 bytes of data, divided
@@ -367,13 +367,13 @@ static bool _lspcon_write_avi_infoframe_parade(struct drm_dp_aux *aux,
 }
 
 static bool _lspcon_write_avi_infoframe_mca(struct drm_dp_aux *aux,
-                                           const uint8_t *buffer, ssize_t len)
+                                           const u8 *buffer, ssize_t len)
 {
        int ret;
-       uint32_t val = 0;
-       uint32_t retry;
-       uint16_t reg;
-       const uint8_t *data = buffer;
+       u32 val = 0;
+       u32 retry;
+       u16 reg;
+       const u8 *data = buffer;
 
        reg = LSPCON_MCA_AVI_IF_WRITE_OFFSET;
        while (val < len) {
@@ -459,13 +459,11 @@ void lspcon_set_infoframes(struct intel_encoder *encoder,
 {
        ssize_t ret;
        union hdmi_infoframe frame;
-       uint8_t buf[VIDEO_DIP_DATA_SIZE];
+       u8 buf[VIDEO_DIP_DATA_SIZE];
        struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
        struct intel_lspcon *lspcon = &dig_port->lspcon;
-       struct intel_dp *intel_dp = &dig_port->dp;
-       struct drm_connector *connector = &intel_dp->attached_connector->base;
-       const struct drm_display_mode *mode = &crtc_state->base.adjusted_mode;
-       bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
+       const struct drm_display_mode *adjusted_mode =
+               &crtc_state->base.adjusted_mode;
 
        if (!lspcon->active) {
                DRM_ERROR("Writing infoframes while LSPCON disabled ?\n");
@@ -473,7 +471,8 @@ void lspcon_set_infoframes(struct intel_encoder *encoder,
        }
 
        ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
-                                                      mode, is_hdmi2_sink);
+                                                      conn_state->connector,
+                                                      adjusted_mode);
        if (ret < 0) {
                DRM_ERROR("couldn't fill AVI infoframe\n");
                return;
@@ -488,11 +487,12 @@ void lspcon_set_infoframes(struct intel_encoder *encoder,
                frame.avi.colorspace = HDMI_COLORSPACE_RGB;
        }
 
-       drm_hdmi_avi_infoframe_quant_range(&frame.avi, mode,
+       drm_hdmi_avi_infoframe_quant_range(&frame.avi,
+                                          conn_state->connector,
+                                          adjusted_mode,
                                           crtc_state->limited_color_range ?
                                           HDMI_QUANTIZATION_RANGE_LIMITED :
-                                          HDMI_QUANTIZATION_RANGE_FULL,
-                                          false, is_hdmi2_sink);
+                                          HDMI_QUANTIZATION_RANGE_FULL);
 
        ret = hdmi_infoframe_pack(&frame, buf, sizeof(buf));
        if (ret < 0) {
index e6c5d985ea0afd9d6f8eadb45228dad3ee6323f0..b4aa49768e90fb27997692d38e36824ac81327aa 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/vga_switcheroo.h>
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
@@ -95,15 +94,17 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
+       intel_wakeref_t wakeref;
        bool ret;
 
-       if (!intel_display_power_get_if_enabled(dev_priv,
-                                               encoder->power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    encoder->power_domain);
+       if (!wakeref)
                return false;
 
        ret = intel_lvds_port_enabled(dev_priv, lvds_encoder->reg, pipe);
 
-       intel_display_power_put(dev_priv, encoder->power_domain);
+       intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
 
        return ret;
 }
@@ -279,7 +280,7 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder,
         * special lvds dither control bit on pch-split platforms, dithering is
         * only controlled through the PIPECONF reg.
         */
-       if (IS_GEN4(dev_priv)) {
+       if (IS_GEN(dev_priv, 4)) {
                /*
                 * Bspec wording suggests that LVDS port dithering only exists
                 * for 18bpp panels.
@@ -379,9 +380,9 @@ intel_lvds_mode_valid(struct drm_connector *connector,
        return MODE_OK;
 }
 
-static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
-                                     struct intel_crtc_state *pipe_config,
-                                     struct drm_connector_state *conn_state)
+static int intel_lvds_compute_config(struct intel_encoder *intel_encoder,
+                                    struct intel_crtc_state *pipe_config,
+                                    struct drm_connector_state *conn_state)
 {
        struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
        struct intel_lvds_encoder *lvds_encoder =
@@ -395,7 +396,7 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
        /* Should never happen!! */
        if (INTEL_GEN(dev_priv) < 4 && intel_crtc->pipe == 0) {
                DRM_ERROR("Can't support LVDS on pipe A\n");
-               return false;
+               return -EINVAL;
        }
 
        if (lvds_encoder->a3_power == LVDS_A3_POWER_UP)
@@ -421,7 +422,7 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
                               adjusted_mode);
 
        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
-               return false;
+               return -EINVAL;
 
        if (HAS_PCH_SPLIT(dev_priv)) {
                pipe_config->has_pch_encoder = true;
@@ -440,7 +441,7 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
         * user's requested refresh rate.
         */
 
-       return true;
+       return 0;
 }
 
 static enum drm_connector_status
@@ -797,26 +798,6 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)
        return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;
 }
 
-static bool intel_lvds_supported(struct drm_i915_private *dev_priv)
-{
-       /*
-        * With the introduction of the PCH we gained a dedicated
-        * LVDS presence pin, use it.
-        */
-       if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
-               return true;
-
-       /*
-        * Otherwise LVDS was only attached to mobile products,
-        * except for the inglorious 830gm
-        */
-       if (INTEL_GEN(dev_priv) <= 4 &&
-           IS_MOBILE(dev_priv) && !IS_I830(dev_priv))
-               return true;
-
-       return false;
-}
-
 /**
  * intel_lvds_init - setup LVDS connectors on this device
  * @dev_priv: i915 device
@@ -841,9 +822,6 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
        u8 pin;
        u32 allowed_scalers;
 
-       if (!intel_lvds_supported(dev_priv))
-               return;
-
        /* Skip init on machines we know falsely report LVDS */
        if (dmi_check_system(intel_no_lvds)) {
                WARN(!dev_priv->vbt.int_lvds_support,
@@ -909,6 +887,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
        }
        intel_encoder->get_hw_state = intel_lvds_get_hw_state;
        intel_encoder->get_config = intel_lvds_get_config;
+       intel_encoder->update_pipe = intel_panel_update_backlight;
        intel_connector->get_hw_state = intel_connector_get_hw_state;
 
        intel_connector_attach_encoder(intel_connector, intel_encoder);
@@ -919,7 +898,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
        intel_encoder->cloneable = 0;
        if (HAS_PCH_SPLIT(dev_priv))
                intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
-       else if (IS_GEN4(dev_priv))
+       else if (IS_GEN(dev_priv, 4))
                intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
        else
                intel_encoder->crtc_mask = (1 << 1);
index 77e9871a8c9ac87ca4d2360262d7d815cd8270b0..e976c5ce5479d362ff09ee1688188cd92cae7abe 100644 (file)
@@ -193,7 +193,7 @@ static bool get_mocs_settings(struct drm_i915_private *dev_priv,
        }
 
        /* WaDisableSkipCaching:skl,bxt,kbl,glk */
-       if (IS_GEN9(dev_priv)) {
+       if (IS_GEN(dev_priv, 9)) {
                int i;
 
                for (i = 0; i < table->size; i++)
index d89080d75b80ddfc21285e5ad2def13899430937..3d99d1271b2bc515a0468fc9445a3e98c8f7f919 100644 (file)
@@ -49,7 +49,6 @@
  * context handling keep the MOCS in step.
  */
 
-#include <drm/drmP.h>
 #include "i915_drv.h"
 
 int intel_rcs_context_init_mocs(struct i915_request *rq);
index b8f106d9ecf8b1be6286b2dfaeac1c5188629528..30ae96c5c97cb1caf4911dc85d0fff11dffba92c 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/firmware.h>
 #include <acpi/video.h>
 
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 
 #include "intel_opregion.h"
index 20ea7c99d13a06e73a52b8d5b69866b8f35a32ad..c81db81e4416a11234bd3dbf72b314e9fad2ba1a 100644 (file)
@@ -25,7 +25,6 @@
  *
  * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c
  */
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 #include "i915_reg.h"
@@ -541,7 +540,7 @@ static u32 calc_swidthsw(struct drm_i915_private *dev_priv, u32 offset, u32 widt
 {
        u32 sw;
 
-       if (IS_GEN2(dev_priv))
+       if (IS_GEN(dev_priv, 2))
                sw = ALIGN((offset & 31) + width, 32);
        else
                sw = ALIGN((offset & 63) + width, 64);
@@ -778,7 +777,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
                u32 oconfig;
 
                oconfig = OCONF_CC_OUT_8BIT;
-               if (IS_GEN4(dev_priv))
+               if (IS_GEN(dev_priv, 4))
                        oconfig |= OCONF_CSC_MODE_BT709;
                oconfig |= pipe == 0 ?
                        OCONF_PIPE_A : OCONF_PIPE_B;
@@ -1012,7 +1011,7 @@ static int check_overlay_src(struct drm_i915_private *dev_priv,
 
        if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
                return -EINVAL;
-       if (IS_GEN4(dev_priv) && rec->stride_Y < 512)
+       if (IS_GEN(dev_priv, 4) && rec->stride_Y < 512)
                return -EINVAL;
 
        tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
@@ -1246,7 +1245,7 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
                attrs->contrast   = overlay->contrast;
                attrs->saturation = overlay->saturation;
 
-               if (!IS_GEN2(dev_priv)) {
+               if (!IS_GEN(dev_priv, 2)) {
                        attrs->gamma0 = I915_READ(OGAMC0);
                        attrs->gamma1 = I915_READ(OGAMC1);
                        attrs->gamma2 = I915_READ(OGAMC2);
@@ -1270,7 +1269,7 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
                update_reg_attrs(overlay, overlay->regs);
 
                if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
-                       if (IS_GEN2(dev_priv))
+                       if (IS_GEN(dev_priv, 2))
                                goto out_unlock;
 
                        if (overlay->active) {
index e6cd7b55c0182425cb7eb3bc32c9250d8cf7f601..beca98d2b035b2a84f3425a674cfbb4a4966aa13 100644 (file)
@@ -563,7 +563,7 @@ static void i9xx_set_backlight(const struct drm_connector_state *conn_state, u32
                pci_write_config_byte(dev_priv->drm.pdev, LBPC, lbpc);
        }
 
-       if (IS_GEN4(dev_priv)) {
+       if (IS_GEN(dev_priv, 4)) {
                mask = BACKLIGHT_DUTY_CYCLE_MASK;
        } else {
                level <<= 1;
@@ -929,7 +929,7 @@ static void i9xx_enable_backlight(const struct intel_crtc_state *crtc_state,
         * 855gm only, but checking for gen2 is safe, as 855gm is the only gen2
         * that has backlight.
         */
-       if (IS_GEN2(dev_priv))
+       if (IS_GEN(dev_priv, 2))
                I915_WRITE(BLC_HIST_CTL, BLM_HISTOGRAM_ENABLE);
 }
 
@@ -1087,20 +1087,11 @@ static void pwm_enable_backlight(const struct intel_crtc_state *crtc_state,
        intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
 }
 
-void intel_panel_enable_backlight(const struct intel_crtc_state *crtc_state,
-                                 const struct drm_connector_state *conn_state)
+static void __intel_panel_enable_backlight(const struct intel_crtc_state *crtc_state,
+                                          const struct drm_connector_state *conn_state)
 {
        struct intel_connector *connector = to_intel_connector(conn_state->connector);
-       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
        struct intel_panel *panel = &connector->panel;
-       enum pipe pipe = to_intel_crtc(crtc_state->base.crtc)->pipe;
-
-       if (!panel->backlight.present)
-               return;
-
-       DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
-
-       mutex_lock(&dev_priv->backlight_lock);
 
        WARN_ON(panel->backlight.max == 0);
 
@@ -1117,6 +1108,24 @@ void intel_panel_enable_backlight(const struct intel_crtc_state *crtc_state,
        panel->backlight.enabled = true;
        if (panel->backlight.device)
                panel->backlight.device->props.power = FB_BLANK_UNBLANK;
+}
+
+void intel_panel_enable_backlight(const struct intel_crtc_state *crtc_state,
+                                 const struct drm_connector_state *conn_state)
+{
+       struct intel_connector *connector = to_intel_connector(conn_state->connector);
+       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+       struct intel_panel *panel = &connector->panel;
+       enum pipe pipe = to_intel_crtc(crtc_state->base.crtc)->pipe;
+
+       if (!panel->backlight.present)
+               return;
+
+       DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
+
+       mutex_lock(&dev_priv->backlight_lock);
+
+       __intel_panel_enable_backlight(crtc_state, conn_state);
 
        mutex_unlock(&dev_priv->backlight_lock);
 }
@@ -1203,17 +1212,20 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)
        struct intel_connector *connector = bl_get_data(bd);
        struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       u32 hw_level;
-       int ret;
+       intel_wakeref_t wakeref;
+       int ret = 0;
 
-       intel_runtime_pm_get(dev_priv);
-       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+       with_intel_runtime_pm(dev_priv, wakeref) {
+               u32 hw_level;
 
-       hw_level = intel_panel_get_backlight(connector);
-       ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness);
+               drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
 
-       drm_modeset_unlock(&dev->mode_config.connection_mutex);
-       intel_runtime_pm_put(dev_priv);
+               hw_level = intel_panel_get_backlight(connector);
+               ret = scale_hw_to_user(connector,
+                                      hw_level, bd->props.max_brightness);
+
+               drm_modeset_unlock(&dev->mode_config.connection_mutex);
+       }
 
        return ret;
 }
@@ -1484,8 +1496,8 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus
 {
        struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
        struct intel_panel *panel = &connector->panel;
-       u32 pch_ctl1, pch_ctl2, val;
-       bool alt;
+       u32 cpu_ctl2, pch_ctl1, pch_ctl2, val;
+       bool alt, cpu_mode;
 
        if (HAS_PCH_LPT(dev_priv))
                alt = I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY;
@@ -1499,6 +1511,8 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus
        pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
        panel->backlight.max = pch_ctl2 >> 16;
 
+       cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
+
        if (!panel->backlight.max)
                panel->backlight.max = get_backlight_max_vbt(connector);
 
@@ -1507,12 +1521,28 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus
 
        panel->backlight.min = get_backlight_min_vbt(connector);
 
-       val = lpt_get_backlight(connector);
+       panel->backlight.enabled = pch_ctl1 & BLM_PCH_PWM_ENABLE;
+
+       cpu_mode = panel->backlight.enabled && HAS_PCH_LPT(dev_priv) &&
+                  !(pch_ctl1 & BLM_PCH_OVERRIDE_ENABLE) &&
+                  (cpu_ctl2 & BLM_PWM_ENABLE);
+       if (cpu_mode)
+               val = pch_get_backlight(connector);
+       else
+               val = lpt_get_backlight(connector);
        val = intel_panel_compute_brightness(connector, val);
        panel->backlight.level = clamp(val, panel->backlight.min,
                                       panel->backlight.max);
 
-       panel->backlight.enabled = pch_ctl1 & BLM_PCH_PWM_ENABLE;
+       if (cpu_mode) {
+               DRM_DEBUG_KMS("CPU backlight register was enabled, switching to PCH override\n");
+
+               /* Write converted CPU PWM value to PCH override register */
+               lpt_set_backlight(connector->base.state, panel->backlight.level);
+               I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_OVERRIDE_ENABLE);
+
+               I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 & ~BLM_PWM_ENABLE);
+       }
 
        return 0;
 }
@@ -1557,7 +1587,7 @@ static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unu
 
        ctl = I915_READ(BLC_PWM_CTL);
 
-       if (IS_GEN2(dev_priv) || IS_I915GM(dev_priv) || IS_I945GM(dev_priv))
+       if (IS_GEN(dev_priv, 2) || IS_I915GM(dev_priv) || IS_I945GM(dev_priv))
                panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;
 
        if (IS_PINEVIEW(dev_priv))
@@ -1773,6 +1803,24 @@ static int pwm_setup_backlight(struct intel_connector *connector,
        return 0;
 }
 
+void intel_panel_update_backlight(struct intel_encoder *encoder,
+                                 const struct intel_crtc_state *crtc_state,
+                                 const struct drm_connector_state *conn_state)
+{
+       struct intel_connector *connector = to_intel_connector(conn_state->connector);
+       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+       struct intel_panel *panel = &connector->panel;
+
+       if (!panel->backlight.present)
+               return;
+
+       mutex_lock(&dev_priv->backlight_lock);
+       if (!panel->backlight.enabled)
+               __intel_panel_enable_backlight(crtc_state, conn_state);
+
+       mutex_unlock(&dev_priv->backlight_lock);
+}
+
 int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe)
 {
        struct drm_i915_private *dev_priv = to_i915(connector->dev);
@@ -1886,7 +1934,7 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
                        panel->backlight.get = vlv_get_backlight;
                        panel->backlight.hz_to_pwm = vlv_hz_to_pwm;
                }
-       } else if (IS_GEN4(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 4)) {
                panel->backlight.setup = i965_setup_backlight;
                panel->backlight.enable = i965_enable_backlight;
                panel->backlight.disable = i965_disable_backlight;
index f3c9010e332a0eab4a7ca440e547307431dc0bb5..a8554dc4f196fb7a626173a4e8714e4ca4fe78f3 100644 (file)
@@ -44,7 +44,7 @@ static const char * const pipe_crc_sources[] = {
 };
 
 static int i8xx_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source,
-                                uint32_t *val)
+                                u32 *val)
 {
        if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
                *source = INTEL_PIPE_CRC_SOURCE_PIPE;
@@ -120,7 +120,7 @@ static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv,
 static int vlv_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
                                enum pipe pipe,
                                enum intel_pipe_crc_source *source,
-                               uint32_t *val)
+                               u32 *val)
 {
        bool need_stable_symbols = false;
 
@@ -165,7 +165,7 @@ static int vlv_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
         *   - DisplayPort scrambling: used for EMI reduction
         */
        if (need_stable_symbols) {
-               uint32_t tmp = I915_READ(PORT_DFT2_G4X);
+               u32 tmp = I915_READ(PORT_DFT2_G4X);
 
                tmp |= DC_BALANCE_RESET_VLV;
                switch (pipe) {
@@ -190,7 +190,7 @@ static int vlv_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
 static int i9xx_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
                                 enum pipe pipe,
                                 enum intel_pipe_crc_source *source,
-                                uint32_t *val)
+                                u32 *val)
 {
        bool need_stable_symbols = false;
 
@@ -244,7 +244,7 @@ static int i9xx_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
         *   - DisplayPort scrambling: used for EMI reduction
         */
        if (need_stable_symbols) {
-               uint32_t tmp = I915_READ(PORT_DFT2_G4X);
+               u32 tmp = I915_READ(PORT_DFT2_G4X);
 
                WARN_ON(!IS_G4X(dev_priv));
 
@@ -265,7 +265,7 @@ static int i9xx_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
 static void vlv_undo_pipe_scramble_reset(struct drm_i915_private *dev_priv,
                                         enum pipe pipe)
 {
-       uint32_t tmp = I915_READ(PORT_DFT2_G4X);
+       u32 tmp = I915_READ(PORT_DFT2_G4X);
 
        switch (pipe) {
        case PIPE_A:
@@ -289,7 +289,7 @@ static void vlv_undo_pipe_scramble_reset(struct drm_i915_private *dev_priv,
 static void g4x_undo_pipe_scramble_reset(struct drm_i915_private *dev_priv,
                                         enum pipe pipe)
 {
-       uint32_t tmp = I915_READ(PORT_DFT2_G4X);
+       u32 tmp = I915_READ(PORT_DFT2_G4X);
 
        if (pipe == PIPE_A)
                tmp &= ~PIPE_A_SCRAMBLE_RESET;
@@ -304,7 +304,7 @@ static void g4x_undo_pipe_scramble_reset(struct drm_i915_private *dev_priv,
 }
 
 static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source,
-                               uint32_t *val)
+                               u32 *val)
 {
        if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
                *source = INTEL_PIPE_CRC_SOURCE_PIPE;
@@ -392,7 +392,7 @@ unlock:
 static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
                                enum pipe pipe,
                                enum intel_pipe_crc_source *source,
-                               uint32_t *val,
+                               u32 *val,
                                bool set_wa)
 {
        if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
@@ -427,13 +427,13 @@ static int get_new_crc_ctl_reg(struct drm_i915_private *dev_priv,
                               enum intel_pipe_crc_source *source, u32 *val,
                               bool set_wa)
 {
-       if (IS_GEN2(dev_priv))
+       if (IS_GEN(dev_priv, 2))
                return i8xx_pipe_crc_ctl_reg(source, val);
        else if (INTEL_GEN(dev_priv) < 5)
                return i9xx_pipe_crc_ctl_reg(dev_priv, pipe, source, val);
        else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                return vlv_pipe_crc_ctl_reg(dev_priv, pipe, source, val);
-       else if (IS_GEN5(dev_priv) || IS_GEN6(dev_priv))
+       else if (IS_GEN_RANGE(dev_priv, 5, 6))
                return ilk_pipe_crc_ctl_reg(source, val);
        else
                return ivb_pipe_crc_ctl_reg(dev_priv, pipe, source, val, set_wa);
@@ -544,13 +544,13 @@ static int
 intel_is_valid_crc_source(struct drm_i915_private *dev_priv,
                          const enum intel_pipe_crc_source source)
 {
-       if (IS_GEN2(dev_priv))
+       if (IS_GEN(dev_priv, 2))
                return i8xx_crc_source_valid(dev_priv, source);
        else if (INTEL_GEN(dev_priv) < 5)
                return i9xx_crc_source_valid(dev_priv, source);
        else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                return vlv_crc_source_valid(dev_priv, source);
-       else if (IS_GEN5(dev_priv) || IS_GEN6(dev_priv))
+       else if (IS_GEN_RANGE(dev_priv, 5, 6))
                return ilk_crc_source_valid(dev_priv, source);
        else
                return ivb_crc_source_valid(dev_priv, source);
@@ -589,6 +589,7 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name)
        struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index];
        enum intel_display_power_domain power_domain;
        enum intel_pipe_crc_source source;
+       intel_wakeref_t wakeref;
        u32 val = 0; /* shut up gcc */
        int ret = 0;
 
@@ -598,7 +599,8 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name)
        }
 
        power_domain = POWER_DOMAIN_PIPE(crtc->index);
-       if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) {
+       wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (!wakeref) {
                DRM_DEBUG_KMS("Trying to capture CRC while pipe is off\n");
                return -EIO;
        }
@@ -624,7 +626,7 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name)
        pipe_crc->skipped = 0;
 
 out:
-       intel_display_power_put(dev_priv, power_domain);
+       intel_display_power_put(dev_priv, power_domain, wakeref);
 
        return ret;
 }
index a26b4eddda252659d94f5c6cab89b895ddf348a9..fdc28a3d2936f49e66c2a12440173a656b2acb3f 100644 (file)
@@ -480,7 +480,7 @@ static void vlv_get_fifo_size(struct intel_crtc_state *crtc_state)
        int sprite0_start, sprite1_start;
 
        switch (pipe) {
-               uint32_t dsparb, dsparb2, dsparb3;
+               u32 dsparb, dsparb2, dsparb3;
        case PIPE_A:
                dsparb = I915_READ(DSPARB);
                dsparb2 = I915_READ(DSPARB2);
@@ -513,7 +513,7 @@ static void vlv_get_fifo_size(struct intel_crtc_state *crtc_state)
 static int i9xx_get_fifo_size(struct drm_i915_private *dev_priv,
                              enum i9xx_plane_id i9xx_plane)
 {
-       uint32_t dsparb = I915_READ(DSPARB);
+       u32 dsparb = I915_READ(DSPARB);
        int size;
 
        size = dsparb & 0x7f;
@@ -529,7 +529,7 @@ static int i9xx_get_fifo_size(struct drm_i915_private *dev_priv,
 static int i830_get_fifo_size(struct drm_i915_private *dev_priv,
                              enum i9xx_plane_id i9xx_plane)
 {
-       uint32_t dsparb = I915_READ(DSPARB);
+       u32 dsparb = I915_READ(DSPARB);
        int size;
 
        size = dsparb & 0x1ff;
@@ -546,7 +546,7 @@ static int i830_get_fifo_size(struct drm_i915_private *dev_priv,
 static int i845_get_fifo_size(struct drm_i915_private *dev_priv,
                              enum i9xx_plane_id i9xx_plane)
 {
-       uint32_t dsparb = I915_READ(DSPARB);
+       u32 dsparb = I915_READ(DSPARB);
        int size;
 
        size = dsparb & 0x7f;
@@ -667,9 +667,9 @@ static unsigned int intel_wm_method1(unsigned int pixel_rate,
                                     unsigned int cpp,
                                     unsigned int latency)
 {
-       uint64_t ret;
+       u64 ret;
 
-       ret = (uint64_t) pixel_rate * cpp * latency;
+       ret = (u64)pixel_rate * cpp * latency;
        ret = DIV_ROUND_UP_ULL(ret, 10000);
 
        return ret;
@@ -1089,9 +1089,9 @@ static int g4x_fbc_fifo_size(int level)
        }
 }
 
-static uint16_t g4x_compute_wm(const struct intel_crtc_state *crtc_state,
-                              const struct intel_plane_state *plane_state,
-                              int level)
+static u16 g4x_compute_wm(const struct intel_crtc_state *crtc_state,
+                         const struct intel_plane_state *plane_state,
+                         int level)
 {
        struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
@@ -1188,9 +1188,9 @@ static bool g4x_raw_fbc_wm_set(struct intel_crtc_state *crtc_state,
        return dirty;
 }
 
-static uint32_t ilk_compute_fbc_wm(const struct intel_crtc_state *cstate,
-                                  const struct intel_plane_state *pstate,
-                                  uint32_t pri_val);
+static u32 ilk_compute_fbc_wm(const struct intel_crtc_state *cstate,
+                             const struct intel_plane_state *pstate,
+                             u32 pri_val);
 
 static bool g4x_raw_plane_wm_compute(struct intel_crtc_state *crtc_state,
                                     const struct intel_plane_state *plane_state)
@@ -1399,10 +1399,9 @@ static int g4x_compute_pipe_wm(struct intel_crtc_state *crtc_state)
        return 0;
 }
 
-static int g4x_compute_intermediate_wm(struct drm_device *dev,
-                                      struct intel_crtc *crtc,
-                                      struct intel_crtc_state *new_crtc_state)
+static int g4x_compute_intermediate_wm(struct intel_crtc_state *new_crtc_state)
 {
+       struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
        struct g4x_wm_state *intermediate = &new_crtc_state->wm.g4x.intermediate;
        const struct g4x_wm_state *optimal = &new_crtc_state->wm.g4x.optimal;
        struct intel_atomic_state *intel_state =
@@ -1599,9 +1598,9 @@ static void vlv_setup_wm_latency(struct drm_i915_private *dev_priv)
        }
 }
 
-static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state,
-                                    const struct intel_plane_state *plane_state,
-                                    int level)
+static u16 vlv_compute_wm_level(const struct intel_crtc_state *crtc_state,
+                               const struct intel_plane_state *plane_state,
+                               int level)
 {
        struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
@@ -1969,7 +1968,7 @@ static void vlv_atomic_update_fifo(struct intel_atomic_state *state,
        spin_lock(&dev_priv->uncore.lock);
 
        switch (crtc->pipe) {
-               uint32_t dsparb, dsparb2, dsparb3;
+               u32 dsparb, dsparb2, dsparb3;
        case PIPE_A:
                dsparb = I915_READ_FW(DSPARB);
                dsparb2 = I915_READ_FW(DSPARB2);
@@ -2032,10 +2031,9 @@ static void vlv_atomic_update_fifo(struct intel_atomic_state *state,
 
 #undef VLV_FIFO
 
-static int vlv_compute_intermediate_wm(struct drm_device *dev,
-                                      struct intel_crtc *crtc,
-                                      struct intel_crtc_state *new_crtc_state)
+static int vlv_compute_intermediate_wm(struct intel_crtc_state *new_crtc_state)
 {
+       struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
        struct vlv_wm_state *intermediate = &new_crtc_state->wm.vlv.intermediate;
        const struct vlv_wm_state *optimal = &new_crtc_state->wm.vlv.optimal;
        struct intel_atomic_state *intel_state =
@@ -2264,8 +2262,8 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc)
 {
        struct drm_i915_private *dev_priv = to_i915(unused_crtc->base.dev);
        const struct intel_watermark_params *wm_info;
-       uint32_t fwater_lo;
-       uint32_t fwater_hi;
+       u32 fwater_lo;
+       u32 fwater_hi;
        int cwm, srwm = 1;
        int fifo_size;
        int planea_wm, planeb_wm;
@@ -2273,7 +2271,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc)
 
        if (IS_I945GM(dev_priv))
                wm_info = &i945_wm_info;
-       else if (!IS_GEN2(dev_priv))
+       else if (!IS_GEN(dev_priv, 2))
                wm_info = &i915_wm_info;
        else
                wm_info = &i830_a_wm_info;
@@ -2287,7 +2285,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc)
                        crtc->base.primary->state->fb;
                int cpp;
 
-               if (IS_GEN2(dev_priv))
+               if (IS_GEN(dev_priv, 2))
                        cpp = 4;
                else
                        cpp = fb->format->cpp[0];
@@ -2302,7 +2300,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc)
                        planea_wm = wm_info->max_wm;
        }
 
-       if (IS_GEN2(dev_priv))
+       if (IS_GEN(dev_priv, 2))
                wm_info = &i830_bc_wm_info;
 
        fifo_size = dev_priv->display.get_fifo_size(dev_priv, PLANE_B);
@@ -2314,7 +2312,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc)
                        crtc->base.primary->state->fb;
                int cpp;
 
-               if (IS_GEN2(dev_priv))
+               if (IS_GEN(dev_priv, 2))
                        cpp = 4;
                else
                        cpp = fb->format->cpp[0];
@@ -2408,7 +2406,7 @@ static void i845_update_wm(struct intel_crtc *unused_crtc)
        struct drm_i915_private *dev_priv = to_i915(unused_crtc->base.dev);
        struct intel_crtc *crtc;
        const struct drm_display_mode *adjusted_mode;
-       uint32_t fwater_lo;
+       u32 fwater_lo;
        int planea_wm;
 
        crtc = single_enabled_crtc(dev_priv);
@@ -2457,8 +2455,7 @@ static unsigned int ilk_wm_method2(unsigned int pixel_rate,
        return ret;
 }
 
-static uint32_t ilk_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels,
-                          uint8_t cpp)
+static u32 ilk_wm_fbc(u32 pri_val, u32 horiz_pixels, u8 cpp)
 {
        /*
         * Neither of these should be possible since this function shouldn't be
@@ -2475,22 +2472,21 @@ static uint32_t ilk_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels,
 }
 
 struct ilk_wm_maximums {
-       uint16_t pri;
-       uint16_t spr;
-       uint16_t cur;
-       uint16_t fbc;
+       u16 pri;
+       u16 spr;
+       u16 cur;
+       u16 fbc;
 };
 
 /*
  * For both WM_PIPE and WM_LP.
  * mem_value must be in 0.1us units.
  */
-static uint32_t ilk_compute_pri_wm(const struct intel_crtc_state *cstate,
-                                  const struct intel_plane_state *pstate,
-                                  uint32_t mem_value,
-                                  bool is_lp)
+static u32 ilk_compute_pri_wm(const struct intel_crtc_state *cstate,
+                             const struct intel_plane_state *pstate,
+                             u32 mem_value, bool is_lp)
 {
-       uint32_t method1, method2;
+       u32 method1, method2;
        int cpp;
 
        if (mem_value == 0)
@@ -2518,11 +2514,11 @@ static uint32_t ilk_compute_pri_wm(const struct intel_crtc_state *cstate,
  * For both WM_PIPE and WM_LP.
  * mem_value must be in 0.1us units.
  */
-static uint32_t ilk_compute_spr_wm(const struct intel_crtc_state *cstate,
-                                  const struct intel_plane_state *pstate,
-                                  uint32_t mem_value)
+static u32 ilk_compute_spr_wm(const struct intel_crtc_state *cstate,
+                             const struct intel_plane_state *pstate,
+                             u32 mem_value)
 {
-       uint32_t method1, method2;
+       u32 method1, method2;
        int cpp;
 
        if (mem_value == 0)
@@ -2545,9 +2541,9 @@ static uint32_t ilk_compute_spr_wm(const struct intel_crtc_state *cstate,
  * For both WM_PIPE and WM_LP.
  * mem_value must be in 0.1us units.
  */
-static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate,
-                                  const struct intel_plane_state *pstate,
-                                  uint32_t mem_value)
+static u32 ilk_compute_cur_wm(const struct intel_crtc_state *cstate,
+                             const struct intel_plane_state *pstate,
+                             u32 mem_value)
 {
        int cpp;
 
@@ -2565,9 +2561,9 @@ static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate,
 }
 
 /* Only for WM_LP. */
-static uint32_t ilk_compute_fbc_wm(const struct intel_crtc_state *cstate,
-                                  const struct intel_plane_state *pstate,
-                                  uint32_t pri_val)
+static u32 ilk_compute_fbc_wm(const struct intel_crtc_state *cstate,
+                             const struct intel_plane_state *pstate,
+                             u32 pri_val)
 {
        int cpp;
 
@@ -2626,13 +2622,12 @@ static unsigned int ilk_fbc_wm_reg_max(const struct drm_i915_private *dev_priv)
 }
 
 /* Calculate the maximum primary/sprite plane watermark */
-static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
+static unsigned int ilk_plane_wm_max(const struct drm_i915_private *dev_priv,
                                     int level,
                                     const struct intel_wm_config *config,
                                     enum intel_ddb_partitioning ddb_partitioning,
                                     bool is_sprite)
 {
-       struct drm_i915_private *dev_priv = to_i915(dev);
        unsigned int fifo_size = ilk_display_fifo_size(dev_priv);
 
        /* if sprites aren't enabled, sprites get nothing */
@@ -2668,7 +2663,7 @@ static unsigned int ilk_plane_wm_max(const struct drm_device *dev,
 }
 
 /* Calculate the maximum cursor plane watermark */
-static unsigned int ilk_cursor_wm_max(const struct drm_device *dev,
+static unsigned int ilk_cursor_wm_max(const struct drm_i915_private *dev_priv,
                                      int level,
                                      const struct intel_wm_config *config)
 {
@@ -2677,19 +2672,19 @@ static unsigned int ilk_cursor_wm_max(const struct drm_device *dev,
                return 64;
 
        /* otherwise just report max that registers can hold */
-       return ilk_cursor_wm_reg_max(to_i915(dev), level);
+       return ilk_cursor_wm_reg_max(dev_priv, level);
 }
 
-static void ilk_compute_wm_maximums(const struct drm_device *dev,
+static void ilk_compute_wm_maximums(const struct drm_i915_private *dev_priv,
                                    int level,
                                    const struct intel_wm_config *config,
                                    enum intel_ddb_partitioning ddb_partitioning,
                                    struct ilk_wm_maximums *max)
 {
-       max->pri = ilk_plane_wm_max(dev, level, config, ddb_partitioning, false);
-       max->spr = ilk_plane_wm_max(dev, level, config, ddb_partitioning, true);
-       max->cur = ilk_cursor_wm_max(dev, level, config);
-       max->fbc = ilk_fbc_wm_reg_max(to_i915(dev));
+       max->pri = ilk_plane_wm_max(dev_priv, level, config, ddb_partitioning, false);
+       max->spr = ilk_plane_wm_max(dev_priv, level, config, ddb_partitioning, true);
+       max->cur = ilk_cursor_wm_max(dev_priv, level, config);
+       max->fbc = ilk_fbc_wm_reg_max(dev_priv);
 }
 
 static void ilk_compute_wm_reg_maximums(const struct drm_i915_private *dev_priv,
@@ -2734,9 +2729,9 @@ static bool ilk_validate_wm_level(int level,
                        DRM_DEBUG_KMS("Cursor WM%d too large %u (max %u)\n",
                                      level, result->cur_val, max->cur);
 
-               result->pri_val = min_t(uint32_t, result->pri_val, max->pri);
-               result->spr_val = min_t(uint32_t, result->spr_val, max->spr);
-               result->cur_val = min_t(uint32_t, result->cur_val, max->cur);
+               result->pri_val = min_t(u32, result->pri_val, max->pri);
+               result->spr_val = min_t(u32, result->spr_val, max->spr);
+               result->cur_val = min_t(u32, result->cur_val, max->cur);
                result->enable = true;
        }
 
@@ -2752,9 +2747,9 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv,
                                 const struct intel_plane_state *curstate,
                                 struct intel_wm_level *result)
 {
-       uint16_t pri_latency = dev_priv->wm.pri_latency[level];
-       uint16_t spr_latency = dev_priv->wm.spr_latency[level];
-       uint16_t cur_latency = dev_priv->wm.cur_latency[level];
+       u16 pri_latency = dev_priv->wm.pri_latency[level];
+       u16 spr_latency = dev_priv->wm.spr_latency[level];
+       u16 cur_latency = dev_priv->wm.cur_latency[level];
 
        /* WM1+ latency values stored in 0.5us units */
        if (level > 0) {
@@ -2778,7 +2773,7 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv,
        result->enable = true;
 }
 
-static uint32_t
+static u32
 hsw_compute_linetime_wm(const struct intel_crtc_state *cstate)
 {
        const struct intel_atomic_state *intel_state =
@@ -2807,10 +2802,10 @@ hsw_compute_linetime_wm(const struct intel_crtc_state *cstate)
 }
 
 static void intel_read_wm_latency(struct drm_i915_private *dev_priv,
-                                 uint16_t wm[8])
+                                 u16 wm[8])
 {
        if (INTEL_GEN(dev_priv) >= 9) {
-               uint32_t val;
+               u32 val;
                int ret, i;
                int level, max_level = ilk_wm_max_level(dev_priv);
 
@@ -2894,7 +2889,7 @@ static void intel_read_wm_latency(struct drm_i915_private *dev_priv,
                        wm[0] += 1;
 
        } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
-               uint64_t sskpd = I915_READ64(MCH_SSKPD);
+               u64 sskpd = I915_READ64(MCH_SSKPD);
 
                wm[0] = (sskpd >> 56) & 0xFF;
                if (wm[0] == 0)
@@ -2904,14 +2899,14 @@ static void intel_read_wm_latency(struct drm_i915_private *dev_priv,
                wm[3] = (sskpd >> 20) & 0x1FF;
                wm[4] = (sskpd >> 32) & 0x1FF;
        } else if (INTEL_GEN(dev_priv) >= 6) {
-               uint32_t sskpd = I915_READ(MCH_SSKPD);
+               u32 sskpd = I915_READ(MCH_SSKPD);
 
                wm[0] = (sskpd >> SSKPD_WM0_SHIFT) & SSKPD_WM_MASK;
                wm[1] = (sskpd >> SSKPD_WM1_SHIFT) & SSKPD_WM_MASK;
                wm[2] = (sskpd >> SSKPD_WM2_SHIFT) & SSKPD_WM_MASK;
                wm[3] = (sskpd >> SSKPD_WM3_SHIFT) & SSKPD_WM_MASK;
        } else if (INTEL_GEN(dev_priv) >= 5) {
-               uint32_t mltr = I915_READ(MLTR_ILK);
+               u32 mltr = I915_READ(MLTR_ILK);
 
                /* ILK primary LP0 latency is 700 ns */
                wm[0] = 7;
@@ -2923,18 +2918,18 @@ static void intel_read_wm_latency(struct drm_i915_private *dev_priv,
 }
 
 static void intel_fixup_spr_wm_latency(struct drm_i915_private *dev_priv,
-                                      uint16_t wm[5])
+                                      u16 wm[5])
 {
        /* ILK sprite LP0 latency is 1300 ns */
-       if (IS_GEN5(dev_priv))
+       if (IS_GEN(dev_priv, 5))
                wm[0] = 13;
 }
 
 static void intel_fixup_cur_wm_latency(struct drm_i915_private *dev_priv,
-                                      uint16_t wm[5])
+                                      u16 wm[5])
 {
        /* ILK cursor LP0 latency is 1300 ns */
-       if (IS_GEN5(dev_priv))
+       if (IS_GEN(dev_priv, 5))
                wm[0] = 13;
 }
 
@@ -2953,7 +2948,7 @@ int ilk_wm_max_level(const struct drm_i915_private *dev_priv)
 
 static void intel_print_wm_latency(struct drm_i915_private *dev_priv,
                                   const char *name,
-                                  const uint16_t wm[8])
+                                  const u16 wm[8])
 {
        int level, max_level = ilk_wm_max_level(dev_priv);
 
@@ -2982,7 +2977,7 @@ static void intel_print_wm_latency(struct drm_i915_private *dev_priv,
 }
 
 static bool ilk_increase_wm_latency(struct drm_i915_private *dev_priv,
-                                   uint16_t wm[5], uint16_t min)
+                                   u16 wm[5], u16 min)
 {
        int level, max_level = ilk_wm_max_level(dev_priv);
 
@@ -2991,7 +2986,7 @@ static bool ilk_increase_wm_latency(struct drm_i915_private *dev_priv,
 
        wm[0] = max(wm[0], min);
        for (level = 1; level <= max_level; level++)
-               wm[level] = max_t(uint16_t, wm[level], DIV_ROUND_UP(min, 5));
+               wm[level] = max_t(u16, wm[level], DIV_ROUND_UP(min, 5));
 
        return true;
 }
@@ -3061,7 +3056,7 @@ static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv)
        intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency);
        intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency);
 
-       if (IS_GEN6(dev_priv)) {
+       if (IS_GEN(dev_priv, 6)) {
                snb_wm_latency_quirk(dev_priv);
                snb_wm_lp3_irq_quirk(dev_priv);
        }
@@ -3073,7 +3068,7 @@ static void skl_setup_wm_latency(struct drm_i915_private *dev_priv)
        intel_print_wm_latency(dev_priv, "Gen9 Plane", dev_priv->wm.skl_latency);
 }
 
-static bool ilk_validate_pipe_wm(struct drm_device *dev,
+static bool ilk_validate_pipe_wm(const struct drm_i915_private *dev_priv,
                                 struct intel_pipe_wm *pipe_wm)
 {
        /* LP0 watermark maximums depend on this pipe alone */
@@ -3085,7 +3080,7 @@ static bool ilk_validate_pipe_wm(struct drm_device *dev,
        struct ilk_wm_maximums max;
 
        /* LP0 watermarks always use 1/2 DDB partitioning */
-       ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
+       ilk_compute_wm_maximums(dev_priv, 0, &config, INTEL_DDB_PART_1_2, &max);
 
        /* At least LP0 must be valid */
        if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0])) {
@@ -3150,7 +3145,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate)
        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
                pipe_wm->linetime = hsw_compute_linetime_wm(cstate);
 
-       if (!ilk_validate_pipe_wm(dev, pipe_wm))
+       if (!ilk_validate_pipe_wm(dev_priv, pipe_wm))
                return -EINVAL;
 
        ilk_compute_wm_reg_maximums(dev_priv, 1, &max);
@@ -3180,17 +3175,17 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate)
  * state and the new state.  These can be programmed to the hardware
  * immediately.
  */
-static int ilk_compute_intermediate_wm(struct drm_device *dev,
-                                      struct intel_crtc *intel_crtc,
-                                      struct intel_crtc_state *newstate)
+static int ilk_compute_intermediate_wm(struct intel_crtc_state *newstate)
 {
+       struct intel_crtc *intel_crtc = to_intel_crtc(newstate->base.crtc);
+       struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
        struct intel_pipe_wm *a = &newstate->wm.ilk.intermediate;
        struct intel_atomic_state *intel_state =
                to_intel_atomic_state(newstate->base.state);
        const struct intel_crtc_state *oldstate =
                intel_atomic_get_old_crtc_state(intel_state, intel_crtc);
        const struct intel_pipe_wm *b = &oldstate->wm.ilk.optimal;
-       int level, max_level = ilk_wm_max_level(to_i915(dev));
+       int level, max_level = ilk_wm_max_level(dev_priv);
 
        /*
         * Start with the final, target watermarks, then combine with the
@@ -3223,7 +3218,7 @@ static int ilk_compute_intermediate_wm(struct drm_device *dev,
         * there's no safe way to transition from the old state to
         * the new state, so we need to fail the atomic transaction.
         */
-       if (!ilk_validate_pipe_wm(dev, a))
+       if (!ilk_validate_pipe_wm(dev_priv, a))
                return -EINVAL;
 
        /*
@@ -3239,7 +3234,7 @@ static int ilk_compute_intermediate_wm(struct drm_device *dev,
 /*
  * Merge the watermarks from all active pipes for a specific level.
  */
-static void ilk_merge_wm_level(struct drm_device *dev,
+static void ilk_merge_wm_level(struct drm_i915_private *dev_priv,
                               int level,
                               struct intel_wm_level *ret_wm)
 {
@@ -3247,7 +3242,7 @@ static void ilk_merge_wm_level(struct drm_device *dev,
 
        ret_wm->enable = true;
 
-       for_each_intel_crtc(dev, intel_crtc) {
+       for_each_intel_crtc(&dev_priv->drm, intel_crtc) {
                const struct intel_pipe_wm *active = &intel_crtc->wm.active.ilk;
                const struct intel_wm_level *wm = &active->wm[level];
 
@@ -3272,12 +3267,11 @@ static void ilk_merge_wm_level(struct drm_device *dev,
 /*
  * Merge all low power watermarks for all active pipes.
  */
-static void ilk_wm_merge(struct drm_device *dev,
+static void ilk_wm_merge(struct drm_i915_private *dev_priv,
                         const struct intel_wm_config *config,
                         const struct ilk_wm_maximums *max,
                         struct intel_pipe_wm *merged)
 {
-       struct drm_i915_private *dev_priv = to_i915(dev);
        int level, max_level = ilk_wm_max_level(dev_priv);
        int last_enabled_level = max_level;
 
@@ -3293,7 +3287,7 @@ static void ilk_wm_merge(struct drm_device *dev,
        for (level = 1; level <= max_level; level++) {
                struct intel_wm_level *wm = &merged->wm[level];
 
-               ilk_merge_wm_level(dev, level, wm);
+               ilk_merge_wm_level(dev_priv, level, wm);
 
                if (level > last_enabled_level)
                        wm->enable = false;
@@ -3318,7 +3312,7 @@ static void ilk_wm_merge(struct drm_device *dev,
         * What we should check here is whether FBC can be
         * enabled sometime later.
         */
-       if (IS_GEN5(dev_priv) && !merged->fbc_wm_enabled &&
+       if (IS_GEN(dev_priv, 5) && !merged->fbc_wm_enabled &&
            intel_fbc_is_active(dev_priv)) {
                for (level = 2; level <= max_level; level++) {
                        struct intel_wm_level *wm = &merged->wm[level];
@@ -3335,22 +3329,20 @@ static int ilk_wm_lp_to_level(int wm_lp, const struct intel_pipe_wm *pipe_wm)
 }
 
 /* The value we need to program into the WM_LPx latency field */
-static unsigned int ilk_wm_lp_latency(struct drm_device *dev, int level)
+static unsigned int ilk_wm_lp_latency(struct drm_i915_private *dev_priv,
+                                     int level)
 {
-       struct drm_i915_private *dev_priv = to_i915(dev);
-
        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
                return 2 * level;
        else
                return dev_priv->wm.pri_latency[level];
 }
 
-static void ilk_compute_wm_results(struct drm_device *dev,
+static void ilk_compute_wm_results(struct drm_i915_private *dev_priv,
                                   const struct intel_pipe_wm *merged,
                                   enum intel_ddb_partitioning partitioning,
                                   struct ilk_wm_values *results)
 {
-       struct drm_i915_private *dev_priv = to_i915(dev);
        struct intel_crtc *intel_crtc;
        int level, wm_lp;
 
@@ -3370,7 +3362,7 @@ static void ilk_compute_wm_results(struct drm_device *dev,
                 * disabled. Doing otherwise could cause underruns.
                 */
                results->wm_lp[wm_lp - 1] =
-                       (ilk_wm_lp_latency(dev, level) << WM1_LP_LATENCY_SHIFT) |
+                       (ilk_wm_lp_latency(dev_priv, level) << WM1_LP_LATENCY_SHIFT) |
                        (r->pri_val << WM1_LP_SR_SHIFT) |
                        r->cur_val;
 
@@ -3396,7 +3388,7 @@ static void ilk_compute_wm_results(struct drm_device *dev,
        }
 
        /* LP0 register values */
-       for_each_intel_crtc(dev, intel_crtc) {
+       for_each_intel_crtc(&dev_priv->drm, intel_crtc) {
                enum pipe pipe = intel_crtc->pipe;
                const struct intel_wm_level *r =
                        &intel_crtc->wm.active.ilk.wm[0];
@@ -3415,11 +3407,12 @@ static void ilk_compute_wm_results(struct drm_device *dev,
 
 /* Find the result with the highest level enabled. Check for enable_fbc_wm in
  * case both are at the same level. Prefer r1 in case they're the same. */
-static struct intel_pipe_wm *ilk_find_best_result(struct drm_device *dev,
-                                                 struct intel_pipe_wm *r1,
-                                                 struct intel_pipe_wm *r2)
+static struct intel_pipe_wm *
+ilk_find_best_result(struct drm_i915_private *dev_priv,
+                    struct intel_pipe_wm *r1,
+                    struct intel_pipe_wm *r2)
 {
-       int level, max_level = ilk_wm_max_level(to_i915(dev));
+       int level, max_level = ilk_wm_max_level(dev_priv);
        int level1 = 0, level2 = 0;
 
        for (level = 1; level <= max_level; level++) {
@@ -3540,7 +3533,7 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
 {
        struct ilk_wm_values *previous = &dev_priv->wm.hw;
        unsigned int dirty;
-       uint32_t val;
+       u32 val;
 
        dirty = ilk_compute_wm_dirty(dev_priv, previous, results);
        if (!dirty)
@@ -3756,9 +3749,9 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state)
        if (!intel_has_sagv(dev_priv))
                return false;
 
-       if (IS_GEN9(dev_priv))
+       if (IS_GEN(dev_priv, 9))
                sagv_block_time_us = 30;
-       else if (IS_GEN10(dev_priv))
+       else if (IS_GEN(dev_priv, 10))
                sagv_block_time_us = 20;
        else
                sagv_block_time_us = 10;
@@ -3994,10 +3987,12 @@ void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum intel_display_power_domain power_domain;
        enum pipe pipe = crtc->pipe;
+       intel_wakeref_t wakeref;
        enum plane_id plane_id;
 
        power_domain = POWER_DOMAIN_PIPE(pipe);
-       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (!wakeref)
                return;
 
        for_each_plane_id_on_crtc(crtc, plane_id)
@@ -4006,7 +4001,7 @@ void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
                                           &ddb_y[plane_id],
                                           &ddb_uv[plane_id]);
 
-       intel_display_power_put(dev_priv, power_domain);
+       intel_display_power_put(dev_priv, power_domain, wakeref);
 }
 
 void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
@@ -4036,7 +4031,7 @@ skl_plane_downscale_amount(const struct intel_crtc_state *cstate,
                           const struct intel_plane_state *pstate)
 {
        struct intel_plane *plane = to_intel_plane(pstate->base.plane);
-       uint32_t src_w, src_h, dst_w, dst_h;
+       u32 src_w, src_h, dst_w, dst_h;
        uint_fixed_16_16_t fp_w_ratio, fp_h_ratio;
        uint_fixed_16_16_t downscale_h, downscale_w;
 
@@ -4082,8 +4077,8 @@ skl_pipe_downscale_amount(const struct intel_crtc_state *crtc_state)
                return pipe_downscale;
 
        if (crtc_state->pch_pfit.enabled) {
-               uint32_t src_w, src_h, dst_w, dst_h;
-               uint32_t pfit_size = crtc_state->pch_pfit.size;
+               u32 src_w, src_h, dst_w, dst_h;
+               u32 pfit_size = crtc_state->pch_pfit.size;
                uint_fixed_16_16_t fp_w_ratio, fp_h_ratio;
                uint_fixed_16_16_t downscale_h, downscale_w;
 
@@ -4116,7 +4111,7 @@ int skl_check_pipe_max_pixel_rate(struct intel_crtc *intel_crtc,
        const struct drm_plane_state *pstate;
        struct intel_plane_state *intel_pstate;
        int crtc_clock, dotclk;
-       uint32_t pipe_max_pixel_rate;
+       u32 pipe_max_pixel_rate;
        uint_fixed_16_16_t pipe_downscale;
        uint_fixed_16_16_t max_downscale = u32_to_fixed16(1);
 
@@ -4172,8 +4167,8 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
 {
        struct intel_plane *intel_plane =
                to_intel_plane(intel_pstate->base.plane);
-       uint32_t data_rate;
-       uint32_t width = 0, height = 0;
+       u32 data_rate;
+       u32 width = 0, height = 0;
        struct drm_framebuffer *fb;
        u32 format;
        uint_fixed_16_16_t down_scale_amount;
@@ -4306,102 +4301,6 @@ icl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate,
        return total_data_rate;
 }
 
-static uint16_t
-skl_ddb_min_alloc(const struct drm_plane_state *pstate, const int plane)
-{
-       struct drm_framebuffer *fb = pstate->fb;
-       struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate);
-       uint32_t src_w, src_h;
-       uint32_t min_scanlines = 8;
-       uint8_t plane_bpp;
-
-       if (WARN_ON(!fb))
-               return 0;
-
-       /* For packed formats, and uv-plane, return 0 */
-       if (plane == 1 && fb->format->format != DRM_FORMAT_NV12)
-               return 0;
-
-       /* For Non Y-tile return 8-blocks */
-       if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
-           fb->modifier != I915_FORMAT_MOD_Yf_TILED &&
-           fb->modifier != I915_FORMAT_MOD_Y_TILED_CCS &&
-           fb->modifier != I915_FORMAT_MOD_Yf_TILED_CCS)
-               return 8;
-
-       /*
-        * Src coordinates are already rotated by 270 degrees for
-        * the 90/270 degree plane rotation cases (to match the
-        * GTT mapping), hence no need to account for rotation here.
-        */
-       src_w = drm_rect_width(&intel_pstate->base.src) >> 16;
-       src_h = drm_rect_height(&intel_pstate->base.src) >> 16;
-
-       /* Halve UV plane width and height for NV12 */
-       if (plane == 1) {
-               src_w /= 2;
-               src_h /= 2;
-       }
-
-       plane_bpp = fb->format->cpp[plane];
-
-       if (drm_rotation_90_or_270(pstate->rotation)) {
-               switch (plane_bpp) {
-               case 1:
-                       min_scanlines = 32;
-                       break;
-               case 2:
-                       min_scanlines = 16;
-                       break;
-               case 4:
-                       min_scanlines = 8;
-                       break;
-               case 8:
-                       min_scanlines = 4;
-                       break;
-               default:
-                       WARN(1, "Unsupported pixel depth %u for rotation",
-                            plane_bpp);
-                       min_scanlines = 32;
-               }
-       }
-
-       return DIV_ROUND_UP((4 * src_w * plane_bpp), 512) * min_scanlines/4 + 3;
-}
-
-static void
-skl_ddb_calc_min(const struct intel_crtc_state *cstate, int num_active,
-                uint16_t *minimum, uint16_t *uv_minimum)
-{
-       const struct drm_plane_state *pstate;
-       struct drm_plane *plane;
-
-       drm_atomic_crtc_state_for_each_plane_state(plane, pstate, &cstate->base) {
-               enum plane_id plane_id = to_intel_plane(plane)->id;
-               struct intel_plane_state *plane_state = to_intel_plane_state(pstate);
-
-               if (plane_id == PLANE_CURSOR)
-                       continue;
-
-               /* slave plane must be invisible and calculated from master */
-               if (!pstate->visible || WARN_ON(plane_state->slave))
-                       continue;
-
-               if (!plane_state->linked_plane) {
-                       minimum[plane_id] = skl_ddb_min_alloc(pstate, 0);
-                       uv_minimum[plane_id] = skl_ddb_min_alloc(pstate, 1);
-               } else {
-                       enum plane_id y_plane_id =
-                               plane_state->linked_plane->id;
-
-                       minimum[y_plane_id] = skl_ddb_min_alloc(pstate, 0);
-                       minimum[plane_id] = skl_ddb_min_alloc(pstate, 1);
-               }
-       }
-
-       minimum[PLANE_CURSOR] = skl_cursor_allocation(num_active);
-}
-
 static int
 skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
                      struct skl_ddb_allocation *ddb /* out */)
@@ -4411,15 +4310,17 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
        struct drm_i915_private *dev_priv = to_i915(crtc->dev);
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct skl_ddb_entry *alloc = &cstate->wm.skl.ddb;
-       uint16_t alloc_size, start;
-       uint16_t minimum[I915_MAX_PLANES] = {};
-       uint16_t uv_minimum[I915_MAX_PLANES] = {};
+       struct skl_plane_wm *wm;
+       u16 alloc_size, start = 0;
+       u16 total[I915_MAX_PLANES] = {};
+       u16 uv_total[I915_MAX_PLANES] = {};
        u64 total_data_rate;
        enum plane_id plane_id;
        int num_active;
        u64 plane_data_rate[I915_MAX_PLANES] = {};
        u64 uv_plane_data_rate[I915_MAX_PLANES] = {};
-       uint16_t total_min_blocks = 0;
+       u16 blocks = 0;
+       int level;
 
        /* Clear the partitioning for disabled planes. */
        memset(cstate->wm.skl.plane_ddb_y, 0, sizeof(cstate->wm.skl.plane_ddb_y));
@@ -4449,81 +4350,135 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
        if (alloc_size == 0)
                return 0;
 
-       skl_ddb_calc_min(cstate, num_active, minimum, uv_minimum);
+       /* Allocate fixed number of blocks for cursor. */
+       total[PLANE_CURSOR] = skl_cursor_allocation(num_active);
+       alloc_size -= total[PLANE_CURSOR];
+       cstate->wm.skl.plane_ddb_y[PLANE_CURSOR].start =
+               alloc->end - total[PLANE_CURSOR];
+       cstate->wm.skl.plane_ddb_y[PLANE_CURSOR].end = alloc->end;
+
+       if (total_data_rate == 0)
+               return 0;
 
        /*
-        * 1. Allocate the mininum required blocks for each active plane
-        * and allocate the cursor, it doesn't require extra allocation
-        * proportional to the data rate.
+        * Find the highest watermark level for which we can satisfy the block
+        * requirement of active planes.
         */
+       for (level = ilk_wm_max_level(dev_priv); level >= 0; level--) {
+               blocks = 0;
+               for_each_plane_id_on_crtc(intel_crtc, plane_id) {
+                       if (plane_id == PLANE_CURSOR)
+                               continue;
 
-       for_each_plane_id_on_crtc(intel_crtc, plane_id) {
-               total_min_blocks += minimum[plane_id];
-               total_min_blocks += uv_minimum[plane_id];
+                       wm = &cstate->wm.skl.optimal.planes[plane_id];
+                       blocks += wm->wm[level].plane_res_b;
+                       blocks += wm->uv_wm[level].plane_res_b;
+               }
+
+               if (blocks < alloc_size) {
+                       alloc_size -= blocks;
+                       break;
+               }
        }
 
-       if (total_min_blocks > alloc_size) {
+       if (level < 0) {
                DRM_DEBUG_KMS("Requested display configuration exceeds system DDB limitations");
-               DRM_DEBUG_KMS("minimum required %d/%d\n", total_min_blocks,
-                                                       alloc_size);
+               DRM_DEBUG_KMS("minimum required %d/%d\n", blocks,
+                             alloc_size);
                return -EINVAL;
        }
 
-       alloc_size -= total_min_blocks;
-       cstate->wm.skl.plane_ddb_y[PLANE_CURSOR].start = alloc->end - minimum[PLANE_CURSOR];
-       cstate->wm.skl.plane_ddb_y[PLANE_CURSOR].end = alloc->end;
-
        /*
-        * 2. Distribute the remaining space in proportion to the amount of
-        * data each plane needs to fetch from memory.
-        *
-        * FIXME: we may not allocate every single block here.
+        * Grant each plane the blocks it requires at the highest achievable
+        * watermark level, plus an extra share of the leftover blocks
+        * proportional to its relative data rate.
         */
-       if (total_data_rate == 0)
-               return 0;
-
-       start = alloc->start;
        for_each_plane_id_on_crtc(intel_crtc, plane_id) {
-               u64 data_rate, uv_data_rate;
-               uint16_t plane_blocks, uv_plane_blocks;
+               u64 rate;
+               u16 extra;
 
                if (plane_id == PLANE_CURSOR)
                        continue;
 
-               data_rate = plane_data_rate[plane_id];
-
                /*
-                * allocation for (packed formats) or (uv-plane part of planar format):
-                * promote the expression to 64 bits to avoid overflowing, the
-                * result is < available as data_rate / total_data_rate < 1
+                * We've accounted for all active planes; remaining planes are
+                * all disabled.
                 */
-               plane_blocks = minimum[plane_id];
-               plane_blocks += div64_u64(alloc_size * data_rate, total_data_rate);
+               if (total_data_rate == 0)
+                       break;
 
-               /* Leave disabled planes at (0,0) */
-               if (data_rate) {
-                       cstate->wm.skl.plane_ddb_y[plane_id].start = start;
-                       cstate->wm.skl.plane_ddb_y[plane_id].end = start + plane_blocks;
-               }
+               wm = &cstate->wm.skl.optimal.planes[plane_id];
 
-               start += plane_blocks;
+               rate = plane_data_rate[plane_id];
+               extra = min_t(u16, alloc_size,
+                             DIV64_U64_ROUND_UP(alloc_size * rate,
+                                                total_data_rate));
+               total[plane_id] = wm->wm[level].plane_res_b + extra;
+               alloc_size -= extra;
+               total_data_rate -= rate;
 
-               /* Allocate DDB for UV plane for planar format/NV12 */
-               uv_data_rate = uv_plane_data_rate[plane_id];
+               if (total_data_rate == 0)
+                       break;
+
+               rate = uv_plane_data_rate[plane_id];
+               extra = min_t(u16, alloc_size,
+                             DIV64_U64_ROUND_UP(alloc_size * rate,
+                                                total_data_rate));
+               uv_total[plane_id] = wm->uv_wm[level].plane_res_b + extra;
+               alloc_size -= extra;
+               total_data_rate -= rate;
+       }
+       WARN_ON(alloc_size != 0 || total_data_rate != 0);
+
+       /* Set the actual DDB start/end points for each plane */
+       start = alloc->start;
+       for_each_plane_id_on_crtc(intel_crtc, plane_id) {
+               struct skl_ddb_entry *plane_alloc, *uv_plane_alloc;
+
+               if (plane_id == PLANE_CURSOR)
+                       continue;
 
-               uv_plane_blocks = uv_minimum[plane_id];
-               uv_plane_blocks += div64_u64(alloc_size * uv_data_rate, total_data_rate);
+               plane_alloc = &cstate->wm.skl.plane_ddb_y[plane_id];
+               uv_plane_alloc = &cstate->wm.skl.plane_ddb_uv[plane_id];
 
                /* Gen11+ uses a separate plane for UV watermarks */
-               WARN_ON(INTEL_GEN(dev_priv) >= 11 && uv_plane_blocks);
+               WARN_ON(INTEL_GEN(dev_priv) >= 11 && uv_total[plane_id]);
 
-               if (uv_data_rate) {
-                       cstate->wm.skl.plane_ddb_uv[plane_id].start = start;
-                       cstate->wm.skl.plane_ddb_uv[plane_id].end =
-                               start + uv_plane_blocks;
+               /* Leave disabled planes at (0,0) */
+               if (total[plane_id]) {
+                       plane_alloc->start = start;
+                       start += total[plane_id];
+                       plane_alloc->end = start;
+               }
+
+               if (uv_total[plane_id]) {
+                       uv_plane_alloc->start = start;
+                       start += uv_total[plane_id];
+                       uv_plane_alloc->end = start;
+               }
+       }
+
+       /*
+        * When we calculated watermark values we didn't know how high
+        * of a level we'd actually be able to hit, so we just marked
+        * all levels as "enabled."  Go back now and disable the ones
+        * that aren't actually possible.
+        */
+       for (level++; level <= ilk_wm_max_level(dev_priv); level++) {
+               for_each_plane_id_on_crtc(intel_crtc, plane_id) {
+                       wm = &cstate->wm.skl.optimal.planes[plane_id];
+                       memset(&wm->wm[level], 0, sizeof(wm->wm[level]));
                }
+       }
 
-               start += uv_plane_blocks;
+       /*
+        * Go back and disable the transition watermark if it turns out we
+        * don't have enough DDB blocks for it.
+        */
+       for_each_plane_id_on_crtc(intel_crtc, plane_id) {
+               wm = &cstate->wm.skl.optimal.planes[plane_id];
+               if (wm->trans_wm.plane_res_b > total[plane_id])
+                       memset(&wm->trans_wm, 0, sizeof(wm->trans_wm));
        }
 
        return 0;
@@ -4536,10 +4491,10 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
  * 2xcdclk is 1350 MHz and the pixel rate should never exceed that.
 */
 static uint_fixed_16_16_t
-skl_wm_method1(const struct drm_i915_private *dev_priv, uint32_t pixel_rate,
-              uint8_t cpp, uint32_t latency, uint32_t dbuf_block_size)
+skl_wm_method1(const struct drm_i915_private *dev_priv, u32 pixel_rate,
+              u8 cpp, u32 latency, u32 dbuf_block_size)
 {
-       uint32_t wm_intermediate_val;
+       u32 wm_intermediate_val;
        uint_fixed_16_16_t ret;
 
        if (latency == 0)
@@ -4554,12 +4509,11 @@ skl_wm_method1(const struct drm_i915_private *dev_priv, uint32_t pixel_rate,
        return ret;
 }
 
-static uint_fixed_16_16_t skl_wm_method2(uint32_t pixel_rate,
-                       uint32_t pipe_htotal,
-                       uint32_t latency,
-                       uint_fixed_16_16_t plane_blocks_per_line)
+static uint_fixed_16_16_t
+skl_wm_method2(u32 pixel_rate, u32 pipe_htotal, u32 latency,
+              uint_fixed_16_16_t plane_blocks_per_line)
 {
-       uint32_t wm_intermediate_val;
+       u32 wm_intermediate_val;
        uint_fixed_16_16_t ret;
 
        if (latency == 0)
@@ -4575,8 +4529,8 @@ static uint_fixed_16_16_t skl_wm_method2(uint32_t pixel_rate,
 static uint_fixed_16_16_t
 intel_get_linetime_us(const struct intel_crtc_state *cstate)
 {
-       uint32_t pixel_rate;
-       uint32_t crtc_htotal;
+       u32 pixel_rate;
+       u32 crtc_htotal;
        uint_fixed_16_16_t linetime_us;
 
        if (!cstate->base.active)
@@ -4593,11 +4547,11 @@ intel_get_linetime_us(const struct intel_crtc_state *cstate)
        return linetime_us;
 }
 
-static uint32_t
+static u32
 skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cstate,
                              const struct intel_plane_state *pstate)
 {
-       uint64_t adjusted_pixel_rate;
+       u64 adjusted_pixel_rate;
        uint_fixed_16_16_t downscale_amount;
 
        /* Shouldn't reach here on disabled planes... */
@@ -4624,7 +4578,7 @@ skl_compute_plane_wm_params(const struct intel_crtc_state *cstate,
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        const struct drm_plane_state *pstate = &intel_pstate->base;
        const struct drm_framebuffer *fb = pstate->fb;
-       uint32_t interm_pbpl;
+       u32 interm_pbpl;
        struct intel_atomic_state *state =
                to_intel_atomic_state(cstate->base.state);
        bool apply_memory_bw_wa = skl_needs_memory_bw_wa(state);
@@ -4702,7 +4656,7 @@ skl_compute_plane_wm_params(const struct intel_crtc_state *cstate,
 
                wp->plane_blocks_per_line = div_fixed16(interm_pbpl,
                                                        wp->y_min_scanlines);
-       } else if (wp->x_tiled && IS_GEN9(dev_priv)) {
+       } else if (wp->x_tiled && IS_GEN(dev_priv, 9)) {
                interm_pbpl = DIV_ROUND_UP(wp->plane_bytes_per_line,
                                           wp->dbuf_block_size);
                wp->plane_blocks_per_line = u32_to_fixed16(interm_pbpl);
@@ -4720,28 +4674,22 @@ skl_compute_plane_wm_params(const struct intel_crtc_state *cstate,
        return 0;
 }
 
-static int skl_compute_plane_wm(const struct intel_crtc_state *cstate,
-                               const struct intel_plane_state *intel_pstate,
-                               uint16_t ddb_allocation,
-                               int level,
-                               const struct skl_wm_params *wp,
-                               const struct skl_wm_level *result_prev,
-                               struct skl_wm_level *result /* out */)
+static void skl_compute_plane_wm(const struct intel_crtc_state *cstate,
+                                const struct intel_plane_state *intel_pstate,
+                                int level,
+                                const struct skl_wm_params *wp,
+                                const struct skl_wm_level *result_prev,
+                                struct skl_wm_level *result /* out */)
 {
        struct drm_i915_private *dev_priv =
                to_i915(intel_pstate->base.plane->dev);
-       const struct drm_plane_state *pstate = &intel_pstate->base;
-       uint32_t latency = dev_priv->wm.skl_latency[level];
+       u32 latency = dev_priv->wm.skl_latency[level];
        uint_fixed_16_16_t method1, method2;
        uint_fixed_16_16_t selected_result;
-       uint32_t res_blocks, res_lines;
+       u32 res_blocks, res_lines;
        struct intel_atomic_state *state =
                to_intel_atomic_state(cstate->base.state);
        bool apply_memory_bw_wa = skl_needs_memory_bw_wa(state);
-       uint32_t min_disp_buf_needed;
-
-       if (latency == 0)
-               return level == 0 ? -EINVAL : 0;
 
        /* Display WA #1141: kbl,cfl */
        if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv) ||
@@ -4766,15 +4714,8 @@ static int skl_compute_plane_wm(const struct intel_crtc_state *cstate,
                     wp->dbuf_block_size < 1) &&
                     (wp->plane_bytes_per_line / wp->dbuf_block_size < 1)) {
                        selected_result = method2;
-               } else if (ddb_allocation >=
-                        fixed16_to_u32_round_up(wp->plane_blocks_per_line)) {
-                       if (IS_GEN9(dev_priv) &&
-                           !IS_GEMINILAKE(dev_priv))
-                               selected_result = min_fixed16(method1, method2);
-                       else
-                               selected_result = method2;
                } else if (latency >= wp->linetime_us) {
-                       if (IS_GEN9(dev_priv) &&
+                       if (IS_GEN(dev_priv, 9) &&
                            !IS_GEMINILAKE(dev_priv))
                                selected_result = min_fixed16(method1, method2);
                        else
@@ -4788,85 +4729,51 @@ static int skl_compute_plane_wm(const struct intel_crtc_state *cstate,
        res_lines = div_round_up_fixed16(selected_result,
                                         wp->plane_blocks_per_line);
 
-       /* Display WA #1125: skl,bxt,kbl,glk */
-       if (level == 0 && wp->rc_surface)
-               res_blocks += fixed16_to_u32_round_up(wp->y_tile_minimum);
-
-       /* Display WA #1126: skl,bxt,kbl,glk */
-       if (level >= 1 && level <= 7) {
-               if (wp->y_tiled) {
-                       res_blocks += fixed16_to_u32_round_up(
-                                                       wp->y_tile_minimum);
-                       res_lines += wp->y_min_scanlines;
-               } else {
-                       res_blocks++;
-               }
-
-               /*
-                * Make sure result blocks for higher latency levels are atleast
-                * as high as level below the current level.
-                * Assumption in DDB algorithm optimization for special cases.
-                * Also covers Display WA #1125 for RC.
-                */
-               if (result_prev->plane_res_b > res_blocks)
-                       res_blocks = result_prev->plane_res_b;
-       }
-
-       if (INTEL_GEN(dev_priv) >= 11) {
-               if (wp->y_tiled) {
-                       uint32_t extra_lines;
-                       uint_fixed_16_16_t fp_min_disp_buf_needed;
-
-                       if (res_lines % wp->y_min_scanlines == 0)
-                               extra_lines = wp->y_min_scanlines;
-                       else
-                               extra_lines = wp->y_min_scanlines * 2 -
-                                             res_lines % wp->y_min_scanlines;
-
-                       fp_min_disp_buf_needed = mul_u32_fixed16(res_lines +
-                                               extra_lines,
-                                               wp->plane_blocks_per_line);
-                       min_disp_buf_needed = fixed16_to_u32_round_up(
-                                               fp_min_disp_buf_needed);
-               } else {
-                       min_disp_buf_needed = DIV_ROUND_UP(res_blocks * 11, 10);
-               }
-       } else {
-               min_disp_buf_needed = res_blocks;
-       }
-
-       if ((level > 0 && res_lines > 31) ||
-           res_blocks >= ddb_allocation ||
-           min_disp_buf_needed >= ddb_allocation) {
-               /*
-                * If there are no valid level 0 watermarks, then we can't
-                * support this display configuration.
-                */
-               if (level) {
-                       return 0;
-               } else {
-                       struct drm_plane *plane = pstate->plane;
+       if (IS_GEN9_BC(dev_priv) || IS_BROXTON(dev_priv)) {
+               /* Display WA #1125: skl,bxt,kbl */
+               if (level == 0 && wp->rc_surface)
+                       res_blocks +=
+                               fixed16_to_u32_round_up(wp->y_tile_minimum);
+
+               /* Display WA #1126: skl,bxt,kbl */
+               if (level >= 1 && level <= 7) {
+                       if (wp->y_tiled) {
+                               res_blocks +=
+                                   fixed16_to_u32_round_up(wp->y_tile_minimum);
+                               res_lines += wp->y_min_scanlines;
+                       } else {
+                               res_blocks++;
+                       }
 
-                       DRM_DEBUG_KMS("Requested display configuration exceeds system watermark limitations\n");
-                       DRM_DEBUG_KMS("[PLANE:%d:%s] blocks required = %u/%u, lines required = %u/31\n",
-                                     plane->base.id, plane->name,
-                                     res_blocks, ddb_allocation, res_lines);
-                       return -EINVAL;
+                       /*
+                        * Make sure result blocks for higher latency levels are
+                        * atleast as high as level below the current level.
+                        * Assumption in DDB algorithm optimization for special
+                        * cases. Also covers Display WA #1125 for RC.
+                        */
+                       if (result_prev->plane_res_b > res_blocks)
+                               res_blocks = result_prev->plane_res_b;
                }
        }
 
        /* The number of lines are ignored for the level 0 watermark. */
+       if (level > 0 && res_lines > 31)
+               return;
+
+       /*
+        * If res_lines is valid, assume we can use this watermark level
+        * for now.  We'll come back and disable it after we calculate the
+        * DDB allocation if it turns out we don't actually have enough
+        * blocks to satisfy it.
+        */
        result->plane_res_b = res_blocks;
        result->plane_res_l = res_lines;
        result->plane_en = true;
-
-       return 0;
 }
 
-static int
+static void
 skl_compute_wm_levels(const struct intel_crtc_state *cstate,
                      const struct intel_plane_state *intel_pstate,
-                     uint16_t ddb_blocks,
                      const struct skl_wm_params *wm_params,
                      struct skl_wm_level *levels)
 {
@@ -4874,34 +4781,24 @@ skl_compute_wm_levels(const struct intel_crtc_state *cstate,
                to_i915(intel_pstate->base.plane->dev);
        int level, max_level = ilk_wm_max_level(dev_priv);
        struct skl_wm_level *result_prev = &levels[0];
-       int ret;
 
        for (level = 0; level <= max_level; level++) {
                struct skl_wm_level *result = &levels[level];
 
-               ret = skl_compute_plane_wm(cstate,
-                                          intel_pstate,
-                                          ddb_blocks,
-                                          level,
-                                          wm_params,
-                                          result_prev,
-                                          result);
-               if (ret)
-                       return ret;
+               skl_compute_plane_wm(cstate, intel_pstate, level, wm_params,
+                                    result_prev, result);
 
                result_prev = result;
        }
-
-       return 0;
 }
 
-static uint32_t
+static u32
 skl_compute_linetime_wm(const struct intel_crtc_state *cstate)
 {
        struct drm_atomic_state *state = cstate->base.state;
        struct drm_i915_private *dev_priv = to_i915(state->dev);
        uint_fixed_16_16_t linetime_us;
-       uint32_t linetime_wm;
+       u32 linetime_wm;
 
        linetime_us = intel_get_linetime_us(cstate);
 
@@ -4920,14 +4817,13 @@ skl_compute_linetime_wm(const struct intel_crtc_state *cstate)
 
 static void skl_compute_transition_wm(const struct intel_crtc_state *cstate,
                                      const struct skl_wm_params *wp,
-                                     struct skl_plane_wm *wm,
-                                     uint16_t ddb_allocation)
+                                     struct skl_plane_wm *wm)
 {
        struct drm_device *dev = cstate->base.crtc->dev;
        const struct drm_i915_private *dev_priv = to_i915(dev);
-       uint16_t trans_min, trans_y_tile_min;
-       const uint16_t trans_amount = 10; /* This is configurable amount */
-       uint16_t wm0_sel_res_b, trans_offset_b, res_blocks;
+       u16 trans_min, trans_y_tile_min;
+       const u16 trans_amount = 10; /* This is configurable amount */
+       u16 wm0_sel_res_b, trans_offset_b, res_blocks;
 
        /* Transition WM are not recommended by HW team for GEN9 */
        if (INTEL_GEN(dev_priv) <= 9)
@@ -4956,8 +4852,8 @@ static void skl_compute_transition_wm(const struct intel_crtc_state *cstate,
        wm0_sel_res_b = wm->wm[0].plane_res_b - 1;
 
        if (wp->y_tiled) {
-               trans_y_tile_min = (uint16_t) mul_round_up_u32_fixed16(2,
-                                                       wp->y_tile_minimum);
+               trans_y_tile_min =
+                       (u16)mul_round_up_u32_fixed16(2, wp->y_tile_minimum);
                res_blocks = max(wm0_sel_res_b, trans_y_tile_min) +
                                trans_offset_b;
        } else {
@@ -4969,12 +4865,13 @@ static void skl_compute_transition_wm(const struct intel_crtc_state *cstate,
 
        }
 
-       res_blocks += 1;
-
-       if (res_blocks < ddb_allocation) {
-               wm->trans_wm.plane_res_b = res_blocks;
-               wm->trans_wm.plane_en = true;
-       }
+       /*
+        * Just assume we can enable the transition watermark.  After
+        * computing the DDB we'll come back and disable it if that
+        * assumption turns out to be false.
+        */
+       wm->trans_wm.plane_res_b = res_blocks + 1;
+       wm->trans_wm.plane_en = true;
 }
 
 static int skl_build_plane_wm_single(struct intel_crtc_state *crtc_state,
@@ -4982,7 +4879,6 @@ static int skl_build_plane_wm_single(struct intel_crtc_state *crtc_state,
                                     enum plane_id plane_id, int color_plane)
 {
        struct skl_plane_wm *wm = &crtc_state->wm.skl.optimal.planes[plane_id];
-       u16 ddb_blocks = skl_ddb_entry_size(&crtc_state->wm.skl.plane_ddb_y[plane_id]);
        struct skl_wm_params wm_params;
        int ret;
 
@@ -4991,12 +4887,8 @@ static int skl_build_plane_wm_single(struct intel_crtc_state *crtc_state,
        if (ret)
                return ret;
 
-       ret = skl_compute_wm_levels(crtc_state, plane_state,
-                                   ddb_blocks, &wm_params, wm->wm);
-       if (ret)
-               return ret;
-
-       skl_compute_transition_wm(crtc_state, &wm_params, wm, ddb_blocks);
+       skl_compute_wm_levels(crtc_state, plane_state, &wm_params, wm->wm);
+       skl_compute_transition_wm(crtc_state, &wm_params, wm);
 
        return 0;
 }
@@ -5006,7 +4898,6 @@ static int skl_build_plane_wm_uv(struct intel_crtc_state *crtc_state,
                                 enum plane_id plane_id)
 {
        struct skl_plane_wm *wm = &crtc_state->wm.skl.optimal.planes[plane_id];
-       u16 ddb_blocks = skl_ddb_entry_size(&crtc_state->wm.skl.plane_ddb_uv[plane_id]);
        struct skl_wm_params wm_params;
        int ret;
 
@@ -5018,10 +4909,7 @@ static int skl_build_plane_wm_uv(struct intel_crtc_state *crtc_state,
        if (ret)
                return ret;
 
-       ret = skl_compute_wm_levels(crtc_state, plane_state,
-                                   ddb_blocks, &wm_params, wm->uv_wm);
-       if (ret)
-               return ret;
+       skl_compute_wm_levels(crtc_state, plane_state, &wm_params, wm->uv_wm);
 
        return 0;
 }
@@ -5139,7 +5027,7 @@ static void skl_write_wm_level(struct drm_i915_private *dev_priv,
                               i915_reg_t reg,
                               const struct skl_wm_level *level)
 {
-       uint32_t val = 0;
+       u32 val = 0;
 
        if (level->plane_en) {
                val |= PLANE_WM_EN;
@@ -5251,15 +5139,14 @@ bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry *ddb,
        return false;
 }
 
-static int skl_update_pipe_wm(struct drm_crtc_state *cstate,
+static int skl_update_pipe_wm(struct intel_crtc_state *cstate,
                              const struct skl_pipe_wm *old_pipe_wm,
                              struct skl_pipe_wm *pipe_wm, /* out */
                              bool *changed /* out */)
 {
-       struct intel_crtc_state *intel_cstate = to_intel_crtc_state(cstate);
        int ret;
 
-       ret = skl_build_pipe_wm(intel_cstate, pipe_wm);
+       ret = skl_build_pipe_wm(cstate, pipe_wm);
        if (ret)
                return ret;
 
@@ -5271,15 +5158,15 @@ static int skl_update_pipe_wm(struct drm_crtc_state *cstate,
        return 0;
 }
 
-static uint32_t
-pipes_modified(struct drm_atomic_state *state)
+static u32
+pipes_modified(struct intel_atomic_state *state)
 {
-       struct drm_crtc *crtc;
-       struct drm_crtc_state *cstate;
-       uint32_t i, ret = 0;
+       struct intel_crtc *crtc;
+       struct intel_crtc_state *cstate;
+       u32 i, ret = 0;
 
-       for_each_new_crtc_in_state(state, crtc, cstate, i)
-               ret |= drm_crtc_mask(crtc);
+       for_each_new_intel_crtc_in_state(state, crtc, cstate, i)
+               ret |= drm_crtc_mask(&crtc->base);
 
        return ret;
 }
@@ -5314,11 +5201,10 @@ skl_ddb_add_affected_planes(const struct intel_crtc_state *old_crtc_state,
 }
 
 static int
-skl_compute_ddb(struct drm_atomic_state *state)
+skl_compute_ddb(struct intel_atomic_state *state)
 {
-       const struct drm_i915_private *dev_priv = to_i915(state->dev);
-       struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
-       struct skl_ddb_allocation *ddb = &intel_state->wm_results.ddb;
+       const struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+       struct skl_ddb_allocation *ddb = &state->wm_results.ddb;
        struct intel_crtc_state *old_crtc_state;
        struct intel_crtc_state *new_crtc_state;
        struct intel_crtc *crtc;
@@ -5326,7 +5212,7 @@ skl_compute_ddb(struct drm_atomic_state *state)
 
        memcpy(ddb, &dev_priv->wm.skl_hw.ddb, sizeof(*ddb));
 
-       for_each_oldnew_intel_crtc_in_state(intel_state, crtc, old_crtc_state,
+       for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
                                            new_crtc_state, i) {
                ret = skl_allocate_pipe_ddb(new_crtc_state, ddb);
                if (ret)
@@ -5372,15 +5258,13 @@ skl_print_wm_changes(struct intel_atomic_state *state)
 }
 
 static int
-skl_ddb_add_affected_pipes(struct drm_atomic_state *state, bool *changed)
+skl_ddb_add_affected_pipes(struct intel_atomic_state *state, bool *changed)
 {
-       struct drm_device *dev = state->dev;
+       struct drm_device *dev = state->base.dev;
        const struct drm_i915_private *dev_priv = to_i915(dev);
-       const struct drm_crtc *crtc;
-       const struct drm_crtc_state *cstate;
-       struct intel_crtc *intel_crtc;
-       struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
-       uint32_t realloc_pipes = pipes_modified(state);
+       struct intel_crtc *crtc;
+       struct intel_crtc_state *crtc_state;
+       u32 realloc_pipes = pipes_modified(state);
        int ret, i;
 
        /*
@@ -5398,7 +5282,7 @@ skl_ddb_add_affected_pipes(struct drm_atomic_state *state, bool *changed)
         * since any racing commits that want to update them would need to
         * hold _all_ CRTC state mutexes.
         */
-       for_each_new_crtc_in_state(state, crtc, cstate, i)
+       for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i)
                (*changed) = true;
 
        if (!*changed)
@@ -5412,20 +5296,20 @@ skl_ddb_add_affected_pipes(struct drm_atomic_state *state, bool *changed)
         */
        if (dev_priv->wm.distrust_bios_wm) {
                ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
-                                      state->acquire_ctx);
+                                      state->base.acquire_ctx);
                if (ret)
                        return ret;
 
-               intel_state->active_pipe_changes = ~0;
+               state->active_pipe_changes = ~0;
 
                /*
-                * We usually only initialize intel_state->active_crtcs if we
+                * We usually only initialize state->active_crtcs if we
                 * we're doing a modeset; make sure this field is always
                 * initialized during the sanitization process that happens
                 * on the first commit too.
                 */
-               if (!intel_state->modeset)
-                       intel_state->active_crtcs = dev_priv->active_crtcs;
+               if (!state->modeset)
+                       state->active_crtcs = dev_priv->active_crtcs;
        }
 
        /*
@@ -5441,21 +5325,19 @@ skl_ddb_add_affected_pipes(struct drm_atomic_state *state, bool *changed)
         * any other display updates race with this transaction, so we need
         * to grab the lock on *all* CRTC's.
         */
-       if (intel_state->active_pipe_changes || intel_state->modeset) {
+       if (state->active_pipe_changes || state->modeset) {
                realloc_pipes = ~0;
-               intel_state->wm_results.dirty_pipes = ~0;
+               state->wm_results.dirty_pipes = ~0;
        }
 
        /*
         * We're not recomputing for the pipes not included in the commit, so
         * make sure we start with the current state.
         */
-       for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) {
-               struct intel_crtc_state *cstate;
-
-               cstate = intel_atomic_get_crtc_state(state, intel_crtc);
-               if (IS_ERR(cstate))
-                       return PTR_ERR(cstate);
+       for_each_intel_crtc_mask(dev, crtc, realloc_pipes) {
+               crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
+               if (IS_ERR(crtc_state))
+                       return PTR_ERR(crtc_state);
        }
 
        return 0;
@@ -5522,12 +5404,12 @@ static int skl_wm_add_affected_planes(struct intel_atomic_state *state,
 }
 
 static int
-skl_compute_wm(struct drm_atomic_state *state)
+skl_compute_wm(struct intel_atomic_state *state)
 {
-       struct drm_crtc *crtc;
-       struct drm_crtc_state *cstate;
-       struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
-       struct skl_ddb_values *results = &intel_state->wm_results;
+       struct intel_crtc *crtc;
+       struct intel_crtc_state *cstate;
+       struct intel_crtc_state *old_crtc_state;
+       struct skl_ddb_values *results = &state->wm_results;
        struct skl_pipe_wm *pipe_wm;
        bool changed = false;
        int ret, i;
@@ -5539,47 +5421,35 @@ skl_compute_wm(struct drm_atomic_state *state)
        if (ret || !changed)
                return ret;
 
-       ret = skl_compute_ddb(state);
-       if (ret)
-               return ret;
-
        /*
         * Calculate WM's for all pipes that are part of this transaction.
-        * Note that the DDB allocation above may have added more CRTC's that
+        * Note that skl_ddb_add_affected_pipes may have added more CRTC's that
         * weren't otherwise being modified (and set bits in dirty_pipes) if
         * pipe allocations had to change.
-        *
-        * FIXME:  Now that we're doing this in the atomic check phase, we
-        * should allow skl_update_pipe_wm() to return failure in cases where
-        * no suitable watermark values can be found.
         */
-       for_each_new_crtc_in_state(state, crtc, cstate, i) {
-               struct intel_crtc_state *intel_cstate =
-                       to_intel_crtc_state(cstate);
+       for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
+                                           cstate, i) {
                const struct skl_pipe_wm *old_pipe_wm =
-                       &to_intel_crtc_state(crtc->state)->wm.skl.optimal;
+                       &old_crtc_state->wm.skl.optimal;
 
-               pipe_wm = &intel_cstate->wm.skl.optimal;
+               pipe_wm = &cstate->wm.skl.optimal;
                ret = skl_update_pipe_wm(cstate, old_pipe_wm, pipe_wm, &changed);
                if (ret)
                        return ret;
 
-               ret = skl_wm_add_affected_planes(intel_state,
-                                                to_intel_crtc(crtc));
+               ret = skl_wm_add_affected_planes(state, crtc);
                if (ret)
                        return ret;
 
                if (changed)
-                       results->dirty_pipes |= drm_crtc_mask(crtc);
-
-               if ((results->dirty_pipes & drm_crtc_mask(crtc)) == 0)
-                       /* This pipe's WM's did not change */
-                       continue;
-
-               intel_cstate->update_wm_pre = true;
+                       results->dirty_pipes |= drm_crtc_mask(&crtc->base);
        }
 
-       skl_print_wm_changes(intel_state);
+       ret = skl_compute_ddb(state);
+       if (ret)
+               return ret;
+
+       skl_print_wm_changes(state);
 
        return 0;
 }
@@ -5617,13 +5487,13 @@ static void skl_initial_wm(struct intel_atomic_state *state,
        mutex_unlock(&dev_priv->wm.wm_mutex);
 }
 
-static void ilk_compute_wm_config(struct drm_device *dev,
+static void ilk_compute_wm_config(struct drm_i915_private *dev_priv,
                                  struct intel_wm_config *config)
 {
        struct intel_crtc *crtc;
 
        /* Compute the currently _active_ config */
-       for_each_intel_crtc(dev, crtc) {
+       for_each_intel_crtc(&dev_priv->drm, crtc) {
                const struct intel_pipe_wm *wm = &crtc->wm.active.ilk;
 
                if (!wm->pipe_enabled)
@@ -5637,25 +5507,24 @@ static void ilk_compute_wm_config(struct drm_device *dev,
 
 static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
 {
-       struct drm_device *dev = &dev_priv->drm;
        struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
        struct ilk_wm_maximums max;
        struct intel_wm_config config = {};
        struct ilk_wm_values results = {};
        enum intel_ddb_partitioning partitioning;
 
-       ilk_compute_wm_config(dev, &config);
+       ilk_compute_wm_config(dev_priv, &config);
 
-       ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
-       ilk_wm_merge(dev, &config, &max, &lp_wm_1_2);
+       ilk_compute_wm_maximums(dev_priv, 1, &config, INTEL_DDB_PART_1_2, &max);
+       ilk_wm_merge(dev_priv, &config, &max, &lp_wm_1_2);
 
        /* 5/6 split only in single pipe config on IVB+ */
        if (INTEL_GEN(dev_priv) >= 7 &&
            config.num_pipes_active == 1 && config.sprites_enabled) {
-               ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
-               ilk_wm_merge(dev, &config, &max, &lp_wm_5_6);
+               ilk_compute_wm_maximums(dev_priv, 1, &config, INTEL_DDB_PART_5_6, &max);
+               ilk_wm_merge(dev_priv, &config, &max, &lp_wm_5_6);
 
-               best_lp_wm = ilk_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
+               best_lp_wm = ilk_find_best_result(dev_priv, &lp_wm_1_2, &lp_wm_5_6);
        } else {
                best_lp_wm = &lp_wm_1_2;
        }
@@ -5663,7 +5532,7 @@ static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
        partitioning = (best_lp_wm == &lp_wm_1_2) ?
                       INTEL_DDB_PART_1_2 : INTEL_DDB_PART_5_6;
 
-       ilk_compute_wm_results(dev, best_lp_wm, partitioning, &results);
+       ilk_compute_wm_results(dev_priv, best_lp_wm, partitioning, &results);
 
        ilk_write_wm_values(dev_priv, &results);
 }
@@ -5694,7 +5563,7 @@ static void ilk_optimize_watermarks(struct intel_atomic_state *state,
        mutex_unlock(&dev_priv->wm.wm_mutex);
 }
 
-static inline void skl_wm_level_from_reg_val(uint32_t val,
+static inline void skl_wm_level_from_reg_val(u32 val,
                                             struct skl_wm_level *level)
 {
        level->plane_en = val & PLANE_WM_EN;
@@ -5703,19 +5572,18 @@ static inline void skl_wm_level_from_reg_val(uint32_t val,
                PLANE_WM_LINES_MASK;
 }
 
-void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc,
+void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc,
                              struct skl_pipe_wm *out)
 {
-       struct drm_i915_private *dev_priv = to_i915(crtc->dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       enum pipe pipe = intel_crtc->pipe;
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       enum pipe pipe = crtc->pipe;
        int level, max_level;
        enum plane_id plane_id;
-       uint32_t val;
+       u32 val;
 
        max_level = ilk_wm_max_level(dev_priv);
 
-       for_each_plane_id_on_crtc(intel_crtc, plane_id) {
+       for_each_plane_id_on_crtc(crtc, plane_id) {
                struct skl_plane_wm *wm = &out->planes[plane_id];
 
                for (level = 0; level <= max_level; level++) {
@@ -5735,30 +5603,27 @@ void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc,
                skl_wm_level_from_reg_val(val, &wm->trans_wm);
        }
 
-       if (!intel_crtc->active)
+       if (!crtc->active)
                return;
 
        out->linetime = I915_READ(PIPE_WM_LINETIME(pipe));
 }
 
-void skl_wm_get_hw_state(struct drm_device *dev)
+void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv = to_i915(dev);
        struct skl_ddb_values *hw = &dev_priv->wm.skl_hw;
        struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb;
-       struct drm_crtc *crtc;
-       struct intel_crtc *intel_crtc;
+       struct intel_crtc *crtc;
        struct intel_crtc_state *cstate;
 
        skl_ddb_get_hw_state(dev_priv, ddb);
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               intel_crtc = to_intel_crtc(crtc);
-               cstate = to_intel_crtc_state(crtc->state);
+       for_each_intel_crtc(&dev_priv->drm, crtc) {
+               cstate = to_intel_crtc_state(crtc->base.state);
 
                skl_pipe_wm_get_hw_state(crtc, &cstate->wm.skl.optimal);
 
-               if (intel_crtc->active)
-                       hw->dirty_pipes |= drm_crtc_mask(crtc);
+               if (crtc->active)
+                       hw->dirty_pipes |= drm_crtc_mask(&crtc->base);
        }
 
        if (dev_priv->active_crtcs) {
@@ -5767,15 +5632,14 @@ void skl_wm_get_hw_state(struct drm_device *dev)
        }
 }
 
-static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
+static void ilk_pipe_wm_get_hw_state(struct intel_crtc *crtc)
 {
-       struct drm_device *dev = crtc->dev;
+       struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct ilk_wm_values *hw = &dev_priv->wm.hw;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
+       struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->base.state);
        struct intel_pipe_wm *active = &cstate->wm.ilk.optimal;
-       enum pipe pipe = intel_crtc->pipe;
+       enum pipe pipe = crtc->pipe;
        static const i915_reg_t wm0_pipe_reg[] = {
                [PIPE_A] = WM0_PIPEA_ILK,
                [PIPE_B] = WM0_PIPEB_ILK,
@@ -5788,7 +5652,7 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
 
        memset(active, 0, sizeof(*active));
 
-       active->pipe_enabled = intel_crtc->active;
+       active->pipe_enabled = crtc->active;
 
        if (active->pipe_enabled) {
                u32 tmp = hw->wm_pipe[pipe];
@@ -5816,7 +5680,7 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
                        active->wm[level].enable = true;
        }
 
-       intel_crtc->wm.active.ilk = *active;
+       crtc->wm.active.ilk = *active;
 }
 
 #define _FW_WM(value, plane) \
@@ -5827,7 +5691,7 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
 static void g4x_read_wm_values(struct drm_i915_private *dev_priv,
                               struct g4x_wm_values *wm)
 {
-       uint32_t tmp;
+       u32 tmp;
 
        tmp = I915_READ(DSPFW1);
        wm->sr.plane = _FW_WM(tmp, SR);
@@ -5854,7 +5718,7 @@ static void vlv_read_wm_values(struct drm_i915_private *dev_priv,
                               struct vlv_wm_values *wm)
 {
        enum pipe pipe;
-       uint32_t tmp;
+       u32 tmp;
 
        for_each_pipe(dev_priv, pipe) {
                tmp = I915_READ(VLV_DDL(pipe));
@@ -5926,9 +5790,8 @@ static void vlv_read_wm_values(struct drm_i915_private *dev_priv,
 #undef _FW_WM
 #undef _FW_WM_VLV
 
-void g4x_wm_get_hw_state(struct drm_device *dev)
+void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv = to_i915(dev);
        struct g4x_wm_values *wm = &dev_priv->wm.g4x;
        struct intel_crtc *crtc;
 
@@ -5936,7 +5799,7 @@ void g4x_wm_get_hw_state(struct drm_device *dev)
 
        wm->cxsr = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN;
 
-       for_each_intel_crtc(dev, crtc) {
+       for_each_intel_crtc(&dev_priv->drm, crtc) {
                struct intel_crtc_state *crtc_state =
                        to_intel_crtc_state(crtc->base.state);
                struct g4x_wm_state *active = &crtc->wm.active.g4x;
@@ -6067,9 +5930,8 @@ void g4x_wm_sanitize(struct drm_i915_private *dev_priv)
        mutex_unlock(&dev_priv->wm.wm_mutex);
 }
 
-void vlv_wm_get_hw_state(struct drm_device *dev)
+void vlv_wm_get_hw_state(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv = to_i915(dev);
        struct vlv_wm_values *wm = &dev_priv->wm.vlv;
        struct intel_crtc *crtc;
        u32 val;
@@ -6113,7 +5975,7 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
                mutex_unlock(&dev_priv->pcu_lock);
        }
 
-       for_each_intel_crtc(dev, crtc) {
+       for_each_intel_crtc(&dev_priv->drm, crtc) {
                struct intel_crtc_state *crtc_state =
                        to_intel_crtc_state(crtc->base.state);
                struct vlv_wm_state *active = &crtc->wm.active.vlv;
@@ -6230,15 +6092,14 @@ static void ilk_init_lp_watermarks(struct drm_i915_private *dev_priv)
         */
 }
 
-void ilk_wm_get_hw_state(struct drm_device *dev)
+void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv = to_i915(dev);
        struct ilk_wm_values *hw = &dev_priv->wm.hw;
-       struct drm_crtc *crtc;
+       struct intel_crtc *crtc;
 
        ilk_init_lp_watermarks(dev_priv);
 
-       for_each_crtc(dev, crtc)
+       for_each_intel_crtc(&dev_priv->drm, crtc)
                ilk_pipe_wm_get_hw_state(crtc);
 
        hw->wm_lp[0] = I915_READ(WM1_LP_ILK);
@@ -6339,10 +6200,6 @@ void intel_init_ipc(struct drm_i915_private *dev_priv)
  */
 DEFINE_SPINLOCK(mchdev_lock);
 
-/* Global for IPS driver to get at the current i915 device. Protected by
- * mchdev_lock. */
-static struct drm_i915_private *i915_mch_dev;
-
 bool ironlake_set_drps(struct drm_i915_private *dev_priv, u8 val)
 {
        u16 rgvswctl;
@@ -6805,7 +6662,7 @@ void gen6_rps_boost(struct i915_request *rq,
        if (!rps->enabled)
                return;
 
-       if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags))
+       if (i915_request_signaled(rq))
                return;
 
        /* Serializes with i915_request_retire() */
@@ -7049,7 +6906,7 @@ static void gen9_enable_rps(struct drm_i915_private *dev_priv)
        intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
 
        /* Program defaults and thresholds for RPS */
-       if (IS_GEN9(dev_priv))
+       if (IS_GEN(dev_priv, 9))
                I915_WRITE(GEN6_RC_VIDEO_FREQ,
                        GEN9_FREQUENCY(dev_priv->gt_pm.rps.rp1_freq));
 
@@ -7285,9 +7142,9 @@ static void gen6_enable_rc6(struct drm_i915_private *dev_priv)
 
        rc6vids = 0;
        ret = sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids);
-       if (IS_GEN6(dev_priv) && ret) {
+       if (IS_GEN(dev_priv, 6) && ret) {
                DRM_DEBUG_DRIVER("Couldn't check for BIOS workaround\n");
-       } else if (IS_GEN6(dev_priv) && (GEN6_DECODE_RC6_VID(rc6vids & 0xff) < 450)) {
+       } else if (IS_GEN(dev_priv, 6) && (GEN6_DECODE_RC6_VID(rc6vids & 0xff) < 450)) {
                DRM_DEBUG_DRIVER("You should update your BIOS. Correcting minimum rc6 voltage (%dmV->%dmV)\n",
                          GEN6_DECODE_RC6_VID(rc6vids & 0xff), 450);
                rc6vids &= 0xffff00;
@@ -7412,7 +7269,7 @@ static int cherryview_rps_max_freq(struct drm_i915_private *dev_priv)
 
        val = vlv_punit_read(dev_priv, FB_GFX_FMAX_AT_VMAX_FUSE);
 
-       switch (INTEL_INFO(dev_priv)->sseu.eu_total) {
+       switch (RUNTIME_INFO(dev_priv)->sseu.eu_total) {
        case 8:
                /* (2 * 4) config */
                rp0 = (val >> FB_GFX_FMAX_AT_VMAX_2SS4EU_FUSE_SHIFT);
@@ -7985,16 +7842,17 @@ static unsigned long __i915_chipset_val(struct drm_i915_private *dev_priv)
 
 unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
 {
-       unsigned long val;
+       intel_wakeref_t wakeref;
+       unsigned long val = 0;
 
-       if (!IS_GEN5(dev_priv))
+       if (!IS_GEN(dev_priv, 5))
                return 0;
 
-       spin_lock_irq(&mchdev_lock);
-
-       val = __i915_chipset_val(dev_priv);
-
-       spin_unlock_irq(&mchdev_lock);
+       with_intel_runtime_pm(dev_priv, wakeref) {
+               spin_lock_irq(&mchdev_lock);
+               val = __i915_chipset_val(dev_priv);
+               spin_unlock_irq(&mchdev_lock);
+       }
 
        return val;
 }
@@ -8071,14 +7929,16 @@ static void __i915_update_gfx_val(struct drm_i915_private *dev_priv)
 
 void i915_update_gfx_val(struct drm_i915_private *dev_priv)
 {
-       if (!IS_GEN5(dev_priv))
-               return;
+       intel_wakeref_t wakeref;
 
-       spin_lock_irq(&mchdev_lock);
-
-       __i915_update_gfx_val(dev_priv);
+       if (!IS_GEN(dev_priv, 5))
+               return;
 
-       spin_unlock_irq(&mchdev_lock);
+       with_intel_runtime_pm(dev_priv, wakeref) {
+               spin_lock_irq(&mchdev_lock);
+               __i915_update_gfx_val(dev_priv);
+               spin_unlock_irq(&mchdev_lock);
+       }
 }
 
 static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv)
@@ -8120,18 +7980,34 @@ static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv)
 
 unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
 {
-       unsigned long val;
+       intel_wakeref_t wakeref;
+       unsigned long val = 0;
 
-       if (!IS_GEN5(dev_priv))
+       if (!IS_GEN(dev_priv, 5))
                return 0;
 
-       spin_lock_irq(&mchdev_lock);
+       with_intel_runtime_pm(dev_priv, wakeref) {
+               spin_lock_irq(&mchdev_lock);
+               val = __i915_gfx_val(dev_priv);
+               spin_unlock_irq(&mchdev_lock);
+       }
 
-       val = __i915_gfx_val(dev_priv);
+       return val;
+}
 
-       spin_unlock_irq(&mchdev_lock);
+static struct drm_i915_private *i915_mch_dev;
 
-       return val;
+static struct drm_i915_private *mchdev_get(void)
+{
+       struct drm_i915_private *i915;
+
+       rcu_read_lock();
+       i915 = i915_mch_dev;
+       if (!kref_get_unless_zero(&i915->drm.ref))
+               i915 = NULL;
+       rcu_read_unlock();
+
+       return i915;
 }
 
 /**
@@ -8142,23 +8018,24 @@ unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
  */
 unsigned long i915_read_mch_val(void)
 {
-       struct drm_i915_private *dev_priv;
-       unsigned long chipset_val, graphics_val, ret = 0;
-
-       spin_lock_irq(&mchdev_lock);
-       if (!i915_mch_dev)
-               goto out_unlock;
-       dev_priv = i915_mch_dev;
-
-       chipset_val = __i915_chipset_val(dev_priv);
-       graphics_val = __i915_gfx_val(dev_priv);
+       struct drm_i915_private *i915;
+       unsigned long chipset_val = 0;
+       unsigned long graphics_val = 0;
+       intel_wakeref_t wakeref;
 
-       ret = chipset_val + graphics_val;
+       i915 = mchdev_get();
+       if (!i915)
+               return 0;
 
-out_unlock:
-       spin_unlock_irq(&mchdev_lock);
+       with_intel_runtime_pm(i915, wakeref) {
+               spin_lock_irq(&mchdev_lock);
+               chipset_val = __i915_chipset_val(i915);
+               graphics_val = __i915_gfx_val(i915);
+               spin_unlock_irq(&mchdev_lock);
+       }
 
-       return ret;
+       drm_dev_put(&i915->drm);
+       return chipset_val + graphics_val;
 }
 EXPORT_SYMBOL_GPL(i915_read_mch_val);
 
@@ -8169,23 +8046,19 @@ EXPORT_SYMBOL_GPL(i915_read_mch_val);
  */
 bool i915_gpu_raise(void)
 {
-       struct drm_i915_private *dev_priv;
-       bool ret = true;
-
-       spin_lock_irq(&mchdev_lock);
-       if (!i915_mch_dev) {
-               ret = false;
-               goto out_unlock;
-       }
-       dev_priv = i915_mch_dev;
+       struct drm_i915_private *i915;
 
-       if (dev_priv->ips.max_delay > dev_priv->ips.fmax)
-               dev_priv->ips.max_delay--;
+       i915 = mchdev_get();
+       if (!i915)
+               return false;
 
-out_unlock:
+       spin_lock_irq(&mchdev_lock);
+       if (i915->ips.max_delay > i915->ips.fmax)
+               i915->ips.max_delay--;
        spin_unlock_irq(&mchdev_lock);
 
-       return ret;
+       drm_dev_put(&i915->drm);
+       return true;
 }
 EXPORT_SYMBOL_GPL(i915_gpu_raise);
 
@@ -8197,23 +8070,19 @@ EXPORT_SYMBOL_GPL(i915_gpu_raise);
  */
 bool i915_gpu_lower(void)
 {
-       struct drm_i915_private *dev_priv;
-       bool ret = true;
+       struct drm_i915_private *i915;
 
-       spin_lock_irq(&mchdev_lock);
-       if (!i915_mch_dev) {
-               ret = false;
-               goto out_unlock;
-       }
-       dev_priv = i915_mch_dev;
-
-       if (dev_priv->ips.max_delay < dev_priv->ips.min_delay)
-               dev_priv->ips.max_delay++;
+       i915 = mchdev_get();
+       if (!i915)
+               return false;
 
-out_unlock:
+       spin_lock_irq(&mchdev_lock);
+       if (i915->ips.max_delay < i915->ips.min_delay)
+               i915->ips.max_delay++;
        spin_unlock_irq(&mchdev_lock);
 
-       return ret;
+       drm_dev_put(&i915->drm);
+       return true;
 }
 EXPORT_SYMBOL_GPL(i915_gpu_lower);
 
@@ -8224,13 +8093,16 @@ EXPORT_SYMBOL_GPL(i915_gpu_lower);
  */
 bool i915_gpu_busy(void)
 {
-       bool ret = false;
+       struct drm_i915_private *i915;
+       bool ret;
 
-       spin_lock_irq(&mchdev_lock);
-       if (i915_mch_dev)
-               ret = i915_mch_dev->gt.awake;
-       spin_unlock_irq(&mchdev_lock);
+       i915 = mchdev_get();
+       if (!i915)
+               return false;
 
+       ret = i915->gt.awake;
+
+       drm_dev_put(&i915->drm);
        return ret;
 }
 EXPORT_SYMBOL_GPL(i915_gpu_busy);
@@ -8243,24 +8115,19 @@ EXPORT_SYMBOL_GPL(i915_gpu_busy);
  */
 bool i915_gpu_turbo_disable(void)
 {
-       struct drm_i915_private *dev_priv;
-       bool ret = true;
-
-       spin_lock_irq(&mchdev_lock);
-       if (!i915_mch_dev) {
-               ret = false;
-               goto out_unlock;
-       }
-       dev_priv = i915_mch_dev;
-
-       dev_priv->ips.max_delay = dev_priv->ips.fstart;
+       struct drm_i915_private *i915;
+       bool ret;
 
-       if (!ironlake_set_drps(dev_priv, dev_priv->ips.fstart))
-               ret = false;
+       i915 = mchdev_get();
+       if (!i915)
+               return false;
 
-out_unlock:
+       spin_lock_irq(&mchdev_lock);
+       i915->ips.max_delay = i915->ips.fstart;
+       ret = ironlake_set_drps(i915, i915->ips.fstart);
        spin_unlock_irq(&mchdev_lock);
 
+       drm_dev_put(&i915->drm);
        return ret;
 }
 EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
@@ -8289,18 +8156,14 @@ void intel_gpu_ips_init(struct drm_i915_private *dev_priv)
 {
        /* We only register the i915 ips part with intel-ips once everything is
         * set up, to avoid intel-ips sneaking in and reading bogus values. */
-       spin_lock_irq(&mchdev_lock);
-       i915_mch_dev = dev_priv;
-       spin_unlock_irq(&mchdev_lock);
+       rcu_assign_pointer(i915_mch_dev, dev_priv);
 
        ips_ping_for_i915_load();
 }
 
 void intel_gpu_ips_teardown(void)
 {
-       spin_lock_irq(&mchdev_lock);
-       i915_mch_dev = NULL;
-       spin_unlock_irq(&mchdev_lock);
+       rcu_assign_pointer(i915_mch_dev, NULL);
 }
 
 static void intel_init_emon(struct drm_i915_private *dev_priv)
@@ -8410,7 +8273,7 @@ void intel_init_gt_powersave(struct drm_i915_private *dev_priv)
                              intel_freq_opcode(dev_priv, 450));
 
        /* After setting max-softlimit, find the overclock max freq */
-       if (IS_GEN6(dev_priv) ||
+       if (IS_GEN(dev_priv, 6) ||
            IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv)) {
                u32 params = 0;
 
@@ -8639,7 +8502,7 @@ static void g4x_disable_trickle_feed(struct drm_i915_private *dev_priv)
 
 static void ilk_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-       uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE;
+       u32 dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE;
 
        /*
         * Required for FBC
@@ -8711,7 +8574,7 @@ static void ilk_init_clock_gating(struct drm_i915_private *dev_priv)
 static void cpt_init_clock_gating(struct drm_i915_private *dev_priv)
 {
        int pipe;
-       uint32_t val;
+       u32 val;
 
        /*
         * On Ibex Peak and Cougar Point, we need to disable clock
@@ -8746,7 +8609,7 @@ static void cpt_init_clock_gating(struct drm_i915_private *dev_priv)
 
 static void gen6_check_mch_setup(struct drm_i915_private *dev_priv)
 {
-       uint32_t tmp;
+       u32 tmp;
 
        tmp = I915_READ(MCH_SSKPD);
        if ((tmp & MCH_SSKPD_WM0_MASK) != MCH_SSKPD_WM0_VAL)
@@ -8756,7 +8619,7 @@ static void gen6_check_mch_setup(struct drm_i915_private *dev_priv)
 
 static void gen6_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-       uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE;
+       u32 dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE;
 
        I915_WRITE(ILK_DSPCLK_GATE_D, dspclk_gate);
 
@@ -8850,7 +8713,7 @@ static void gen6_init_clock_gating(struct drm_i915_private *dev_priv)
 
 static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv)
 {
-       uint32_t reg = I915_READ(GEN7_FF_THREAD_MODE);
+       u32 reg = I915_READ(GEN7_FF_THREAD_MODE);
 
        /*
         * WaVSThreadDispatchOverride:ivb,vlv
@@ -8886,7 +8749,7 @@ static void lpt_init_clock_gating(struct drm_i915_private *dev_priv)
 static void lpt_suspend_hw(struct drm_i915_private *dev_priv)
 {
        if (HAS_PCH_LPT_LP(dev_priv)) {
-               uint32_t val = I915_READ(SOUTH_DSPCLK_GATE_D);
+               u32 val = I915_READ(SOUTH_DSPCLK_GATE_D);
 
                val &= ~PCH_LP_PARTITION_LEVEL_DISABLE;
                I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
@@ -9124,7 +8987,7 @@ static void hsw_init_clock_gating(struct drm_i915_private *dev_priv)
 
 static void ivb_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-       uint32_t snpcr;
+       u32 snpcr;
 
        I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE);
 
@@ -9333,7 +9196,7 @@ static void chv_init_clock_gating(struct drm_i915_private *dev_priv)
 
 static void g4x_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-       uint32_t dspclk_gate;
+       u32 dspclk_gate;
 
        I915_WRITE(RENCLK_GATE_D1, 0);
        I915_WRITE(RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE |
@@ -9480,9 +9343,9 @@ void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv)
                dev_priv->display.init_clock_gating = ivb_init_clock_gating;
        else if (IS_VALLEYVIEW(dev_priv))
                dev_priv->display.init_clock_gating = vlv_init_clock_gating;
-       else if (IS_GEN6(dev_priv))
+       else if (IS_GEN(dev_priv, 6))
                dev_priv->display.init_clock_gating = gen6_init_clock_gating;
-       else if (IS_GEN5(dev_priv))
+       else if (IS_GEN(dev_priv, 5))
                dev_priv->display.init_clock_gating = ilk_init_clock_gating;
        else if (IS_G4X(dev_priv))
                dev_priv->display.init_clock_gating = g4x_init_clock_gating;
@@ -9490,11 +9353,11 @@ void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv)
                dev_priv->display.init_clock_gating = i965gm_init_clock_gating;
        else if (IS_I965G(dev_priv))
                dev_priv->display.init_clock_gating = i965g_init_clock_gating;
-       else if (IS_GEN3(dev_priv))
+       else if (IS_GEN(dev_priv, 3))
                dev_priv->display.init_clock_gating = gen3_init_clock_gating;
        else if (IS_I85X(dev_priv) || IS_I865G(dev_priv))
                dev_priv->display.init_clock_gating = i85x_init_clock_gating;
-       else if (IS_GEN2(dev_priv))
+       else if (IS_GEN(dev_priv, 2))
                dev_priv->display.init_clock_gating = i830_init_clock_gating;
        else {
                MISSING_CASE(INTEL_DEVID(dev_priv));
@@ -9508,7 +9371,7 @@ void intel_init_pm(struct drm_i915_private *dev_priv)
        /* For cxsr */
        if (IS_PINEVIEW(dev_priv))
                i915_pineview_get_mem_freq(dev_priv);
-       else if (IS_GEN5(dev_priv))
+       else if (IS_GEN(dev_priv, 5))
                i915_ironlake_get_mem_freq(dev_priv);
 
        /* For FIFO watermark updates */
@@ -9520,9 +9383,9 @@ void intel_init_pm(struct drm_i915_private *dev_priv)
        } else if (HAS_PCH_SPLIT(dev_priv)) {
                ilk_setup_wm_latency(dev_priv);
 
-               if ((IS_GEN5(dev_priv) && dev_priv->wm.pri_latency[1] &&
+               if ((IS_GEN(dev_priv, 5) && dev_priv->wm.pri_latency[1] &&
                     dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) ||
-                   (!IS_GEN5(dev_priv) && dev_priv->wm.pri_latency[0] &&
+                   (!IS_GEN(dev_priv, 5) && dev_priv->wm.pri_latency[0] &&
                     dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
                        dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm;
                        dev_priv->display.compute_intermediate_wm =
@@ -9563,12 +9426,12 @@ void intel_init_pm(struct drm_i915_private *dev_priv)
                        dev_priv->display.update_wm = NULL;
                } else
                        dev_priv->display.update_wm = pineview_update_wm;
-       } else if (IS_GEN4(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 4)) {
                dev_priv->display.update_wm = i965_update_wm;
-       } else if (IS_GEN3(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 3)) {
                dev_priv->display.update_wm = i9xx_update_wm;
                dev_priv->display.get_fifo_size = i9xx_get_fifo_size;
-       } else if (IS_GEN2(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 2)) {
                if (INTEL_INFO(dev_priv)->num_pipes == 1) {
                        dev_priv->display.update_wm = i845_update_wm;
                        dev_priv->display.get_fifo_size = i845_get_fifo_size;
@@ -9583,7 +9446,7 @@ void intel_init_pm(struct drm_i915_private *dev_priv)
 
 static inline int gen6_check_mailbox_status(struct drm_i915_private *dev_priv)
 {
-       uint32_t flags =
+       u32 flags =
                I915_READ_FW(GEN6_PCODE_MAILBOX) & GEN6_PCODE_ERROR_MASK;
 
        switch (flags) {
@@ -9606,7 +9469,7 @@ static inline int gen6_check_mailbox_status(struct drm_i915_private *dev_priv)
 
 static inline int gen7_check_mailbox_status(struct drm_i915_private *dev_priv)
 {
-       uint32_t flags =
+       u32 flags =
                I915_READ_FW(GEN6_PCODE_MAILBOX) & GEN6_PCODE_ERROR_MASK;
 
        switch (flags) {
index 419e563425239951bdaa43bc05dae5c83c5484d5..84a0fb98156135839b5bc966dfcd09ea81f98556 100644 (file)
@@ -51,7 +51,6 @@
  * must be correctly synchronized/cancelled when shutting down the pipe."
  */
 
-#include <drm/drmP.h>
 
 #include "intel_drv.h"
 #include "i915_drv.h"
@@ -71,17 +70,17 @@ static bool psr_global_enabled(u32 debug)
 static bool intel_psr2_enabled(struct drm_i915_private *dev_priv,
                               const struct intel_crtc_state *crtc_state)
 {
-       /* Disable PSR2 by default for all platforms */
-       if (i915_modparams.enable_psr == -1)
-               return false;
-
        /* Cannot enable DSC and PSR2 simultaneously */
        WARN_ON(crtc_state->dsc_params.compression_enable &&
                crtc_state->has_psr2);
 
        switch (dev_priv->psr.debug & I915_PSR_DEBUG_MODE_MASK) {
+       case I915_PSR_DEBUG_DISABLE:
        case I915_PSR_DEBUG_FORCE_PSR1:
                return false;
+       case I915_PSR_DEBUG_DEFAULT:
+               if (i915_modparams.enable_psr <= 0)
+                       return false;
        default:
                return crtc_state->has_psr2;
        }
@@ -231,7 +230,7 @@ void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir)
 
 static bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp)
 {
-       uint8_t dprx = 0;
+       u8 dprx = 0;
 
        if (drm_dp_dpcd_readb(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST,
                              &dprx) != 1)
@@ -241,7 +240,7 @@ static bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp)
 
 static bool intel_dp_get_alpm_status(struct intel_dp *intel_dp)
 {
-       uint8_t alpm_caps = 0;
+       u8 alpm_caps = 0;
 
        if (drm_dp_dpcd_readb(&intel_dp->aux, DP_RECEIVER_ALPM_CAP,
                              &alpm_caps) != 1)
@@ -261,6 +260,32 @@ static u8 intel_dp_get_sink_sync_latency(struct intel_dp *intel_dp)
        return val;
 }
 
+static u16 intel_dp_get_su_x_granulartiy(struct intel_dp *intel_dp)
+{
+       u16 val;
+       ssize_t r;
+
+       /*
+        * Returning the default X granularity if granularity not required or
+        * if DPCD read fails
+        */
+       if (!(intel_dp->psr_dpcd[1] & DP_PSR2_SU_GRANULARITY_REQUIRED))
+               return 4;
+
+       r = drm_dp_dpcd_read(&intel_dp->aux, DP_PSR2_SU_X_GRANULARITY, &val, 2);
+       if (r != 2)
+               DRM_DEBUG_KMS("Unable to read DP_PSR2_SU_X_GRANULARITY\n");
+
+       /*
+        * Spec says that if the value read is 0 the default granularity should
+        * be used instead.
+        */
+       if (r != 2 || val == 0)
+               val = 4;
+
+       return val;
+}
+
 void intel_psr_init_dpcd(struct intel_dp *intel_dp)
 {
        struct drm_i915_private *dev_priv =
@@ -274,10 +299,16 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
        DRM_DEBUG_KMS("eDP panel supports PSR version %x\n",
                      intel_dp->psr_dpcd[0]);
 
+       if (drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_NO_PSR)) {
+               DRM_DEBUG_KMS("PSR support not currently available for this panel\n");
+               return;
+       }
+
        if (!(intel_dp->edp_dpcd[1] & DP_EDP_SET_POWER_CAP)) {
                DRM_DEBUG_KMS("Panel lacks power state control, PSR cannot be enabled\n");
                return;
        }
+
        dev_priv->psr.sink_support = true;
        dev_priv->psr.sink_sync_latency =
                intel_dp_get_sink_sync_latency(intel_dp);
@@ -309,6 +340,8 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
                if (dev_priv->psr.sink_psr2_support) {
                        dev_priv->psr.colorimetry_support =
                                intel_dp_get_colorimetry_status(intel_dp);
+                       dev_priv->psr.su_x_granularity =
+                               intel_dp_get_su_x_granulartiy(intel_dp);
                }
        }
 }
@@ -351,7 +384,7 @@ static void hsw_psr_setup_aux(struct intel_dp *intel_dp)
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
        u32 aux_clock_divider, aux_ctl;
        int i;
-       static const uint8_t aux_msg[] = {
+       static const u8 aux_msg[] = {
                [0] = DP_AUX_NATIVE_WRITE << 4,
                [1] = DP_SET_POWER >> 8,
                [2] = DP_SET_POWER & 0xff,
@@ -388,13 +421,15 @@ static void intel_psr_enable_sink(struct intel_dp *intel_dp)
        if (dev_priv->psr.psr2_enabled) {
                drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG,
                                   DP_ALPM_ENABLE);
-               dpcd_val |= DP_PSR_ENABLE_PSR2;
+               dpcd_val |= DP_PSR_ENABLE_PSR2 | DP_PSR_IRQ_HPD_WITH_CRC_ERRORS;
+       } else {
+               if (dev_priv->psr.link_standby)
+                       dpcd_val |= DP_PSR_MAIN_LINK_ACTIVE;
+
+               if (INTEL_GEN(dev_priv) >= 8)
+                       dpcd_val |= DP_PSR_CRC_VERIFICATION;
        }
 
-       if (dev_priv->psr.link_standby)
-               dpcd_val |= DP_PSR_MAIN_LINK_ACTIVE;
-       if (!dev_priv->psr.psr2_enabled && INTEL_GEN(dev_priv) >= 8)
-               dpcd_val |= DP_PSR_CRC_VERIFICATION;
        drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, dpcd_val);
 
        drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
@@ -468,9 +503,6 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
        idle_frames = max(idle_frames, dev_priv->psr.sink_sync_latency + 1);
        val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT;
 
-       /* FIXME: selective update is probably totally broken because it doesn't
-        * mesh at all with our frontbuffer tracking. And the hw alone isn't
-        * good enough. */
        val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE;
        if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
                val |= EDP_Y_COORDINATE_ENABLE;
@@ -519,7 +551,7 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
        if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
                psr_max_h = 4096;
                psr_max_v = 2304;
-       } else if (IS_GEN9(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 9)) {
                psr_max_h = 3640;
                psr_max_v = 2304;
        }
@@ -531,6 +563,18 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
                return false;
        }
 
+       /*
+        * HW sends SU blocks of size four scan lines, which means the starting
+        * X coordinate and Y granularity requirements will always be met. We
+        * only need to validate the SU block width is a multiple of
+        * x granularity.
+        */
+       if (crtc_hdisplay % dev_priv->psr.su_x_granularity) {
+               DRM_DEBUG_KMS("PSR2 not enabled, hdisplay(%d) not multiple of %d\n",
+                             crtc_hdisplay, dev_priv->psr.su_x_granularity);
+               return false;
+       }
+
        return true;
 }
 
@@ -641,17 +685,14 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
                hsw_psr_setup_aux(intel_dp);
 
-       if (dev_priv->psr.psr2_enabled) {
+       if (dev_priv->psr.psr2_enabled && (IS_GEN(dev_priv, 9) &&
+                                          !IS_GEMINILAKE(dev_priv))) {
                i915_reg_t reg = gen9_chicken_trans_reg(dev_priv,
                                                        cpu_transcoder);
                u32 chicken = I915_READ(reg);
 
-               if (IS_GEN9(dev_priv) && !IS_GEMINILAKE(dev_priv))
-                       chicken |= (PSR2_VSC_ENABLE_PROG_HEADER
-                                  | PSR2_ADD_VERTICAL_LINE_COUNT);
-
-               else
-                       chicken &= ~VSC_DATA_SEL_SOFTWARE_CONTROL;
+               chicken |= PSR2_VSC_ENABLE_PROG_HEADER |
+                          PSR2_ADD_VERTICAL_LINE_COUNT;
                I915_WRITE(reg, chicken);
        }
 
index fbeaec3994e7fff3d4a72f94225dd85fa536c832..e39e483d8d16b0bc224a97c4074f32cbb800e120 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <linux/log2.h>
 
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 
 #include "i915_drv.h"
@@ -133,7 +132,7 @@ gen4_render_ring_flush(struct i915_request *rq, u32 mode)
        cmd = MI_FLUSH;
        if (mode & EMIT_INVALIDATE) {
                cmd |= MI_EXE_FLUSH;
-               if (IS_G4X(rq->i915) || IS_GEN5(rq->i915))
+               if (IS_G4X(rq->i915) || IS_GEN(rq->i915, 5))
                        cmd |= MI_INVALIDATE_ISP;
        }
 
@@ -217,7 +216,7 @@ gen4_render_ring_flush(struct i915_request *rq, u32 mode)
  * really our business.  That leaves only stall at scoreboard.
  */
 static int
-intel_emit_post_sync_nonzero_flush(struct i915_request *rq)
+gen6_emit_post_sync_nonzero_flush(struct i915_request *rq)
 {
        u32 scratch_addr = i915_scratch_offset(rq->i915) + 2 * CACHELINE_BYTES;
        u32 *cs;
@@ -257,7 +256,7 @@ gen6_render_ring_flush(struct i915_request *rq, u32 mode)
        int ret;
 
        /* Force SNB workarounds for PIPE_CONTROL flushes */
-       ret = intel_emit_post_sync_nonzero_flush(rq);
+       ret = gen6_emit_post_sync_nonzero_flush(rq);
        if (ret)
                return ret;
 
@@ -300,6 +299,37 @@ gen6_render_ring_flush(struct i915_request *rq, u32 mode)
        return 0;
 }
 
+static void gen6_rcs_emit_breadcrumb(struct i915_request *rq, u32 *cs)
+{
+       /* First we do the gen6_emit_post_sync_nonzero_flush w/a */
+       *cs++ = GFX_OP_PIPE_CONTROL(4);
+       *cs++ = PIPE_CONTROL_CS_STALL | PIPE_CONTROL_STALL_AT_SCOREBOARD;
+       *cs++ = 0;
+       *cs++ = 0;
+
+       *cs++ = GFX_OP_PIPE_CONTROL(4);
+       *cs++ = PIPE_CONTROL_QW_WRITE;
+       *cs++ = i915_scratch_offset(rq->i915) | PIPE_CONTROL_GLOBAL_GTT;
+       *cs++ = 0;
+
+       /* Finally we can flush and with it emit the breadcrumb */
+       *cs++ = GFX_OP_PIPE_CONTROL(4);
+       *cs++ = (PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
+                PIPE_CONTROL_DEPTH_CACHE_FLUSH |
+                PIPE_CONTROL_DC_FLUSH_ENABLE |
+                PIPE_CONTROL_QW_WRITE |
+                PIPE_CONTROL_CS_STALL);
+       *cs++ = intel_hws_seqno_address(rq->engine) | PIPE_CONTROL_GLOBAL_GTT;
+       *cs++ = rq->global_seqno;
+
+       *cs++ = MI_USER_INTERRUPT;
+       *cs++ = MI_NOOP;
+
+       rq->tail = intel_ring_offset(rq, cs);
+       assert_ring_tail_valid(rq->ring, rq->tail);
+}
+static const int gen6_rcs_emit_breadcrumb_sz = 14;
+
 static int
 gen7_render_ring_cs_stall_wa(struct i915_request *rq)
 {
@@ -379,11 +409,86 @@ gen7_render_ring_flush(struct i915_request *rq, u32 mode)
        return 0;
 }
 
-static void ring_setup_phys_status_page(struct intel_engine_cs *engine)
+static void gen7_rcs_emit_breadcrumb(struct i915_request *rq, u32 *cs)
+{
+       *cs++ = GFX_OP_PIPE_CONTROL(4);
+       *cs++ = (PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
+                PIPE_CONTROL_DEPTH_CACHE_FLUSH |
+                PIPE_CONTROL_DC_FLUSH_ENABLE |
+                PIPE_CONTROL_FLUSH_ENABLE |
+                PIPE_CONTROL_QW_WRITE |
+                PIPE_CONTROL_GLOBAL_GTT_IVB |
+                PIPE_CONTROL_CS_STALL);
+       *cs++ = intel_hws_seqno_address(rq->engine);
+       *cs++ = rq->global_seqno;
+
+       *cs++ = MI_USER_INTERRUPT;
+       *cs++ = MI_NOOP;
+
+       rq->tail = intel_ring_offset(rq, cs);
+       assert_ring_tail_valid(rq->ring, rq->tail);
+}
+static const int gen7_rcs_emit_breadcrumb_sz = 6;
+
+static void gen6_xcs_emit_breadcrumb(struct i915_request *rq, u32 *cs)
+{
+       *cs++ = MI_FLUSH_DW | MI_FLUSH_DW_OP_STOREDW;
+       *cs++ = intel_hws_seqno_address(rq->engine) | MI_FLUSH_DW_USE_GTT;
+       *cs++ = rq->global_seqno;
+       *cs++ = MI_USER_INTERRUPT;
+
+       rq->tail = intel_ring_offset(rq, cs);
+       assert_ring_tail_valid(rq->ring, rq->tail);
+}
+static const int gen6_xcs_emit_breadcrumb_sz = 4;
+
+#define GEN7_XCS_WA 32
+static void gen7_xcs_emit_breadcrumb(struct i915_request *rq, u32 *cs)
+{
+       int i;
+
+       *cs++ = MI_FLUSH_DW | MI_FLUSH_DW_OP_STOREDW;
+       *cs++ = intel_hws_seqno_address(rq->engine) | MI_FLUSH_DW_USE_GTT;
+       *cs++ = rq->global_seqno;
+
+       for (i = 0; i < GEN7_XCS_WA; i++) {
+               *cs++ = MI_STORE_DWORD_INDEX;
+               *cs++ = I915_GEM_HWS_INDEX_ADDR;
+               *cs++ = rq->global_seqno;
+       }
+
+       *cs++ = MI_FLUSH_DW;
+       *cs++ = 0;
+       *cs++ = 0;
+
+       *cs++ = MI_USER_INTERRUPT;
+       *cs++ = MI_NOOP;
+
+       rq->tail = intel_ring_offset(rq, cs);
+       assert_ring_tail_valid(rq->ring, rq->tail);
+}
+static const int gen7_xcs_emit_breadcrumb_sz = 8 + GEN7_XCS_WA * 3;
+#undef GEN7_XCS_WA
+
+static void set_hwstam(struct intel_engine_cs *engine, u32 mask)
+{
+       /*
+        * Keep the render interrupt unmasked as this papers over
+        * lost interrupts following a reset.
+        */
+       if (engine->class == RENDER_CLASS) {
+               if (INTEL_GEN(engine->i915) >= 6)
+                       mask &= ~BIT(0);
+               else
+                       mask &= ~I915_USER_INTERRUPT;
+       }
+
+       intel_engine_set_hwsp_writemask(engine, mask);
+}
+
+static void set_hws_pga(struct intel_engine_cs *engine, phys_addr_t phys)
 {
        struct drm_i915_private *dev_priv = engine->i915;
-       struct page *page = virt_to_page(engine->status_page.page_addr);
-       phys_addr_t phys = PFN_PHYS(page_to_pfn(page));
        u32 addr;
 
        addr = lower_32_bits(phys);
@@ -393,15 +498,25 @@ static void ring_setup_phys_status_page(struct intel_engine_cs *engine)
        I915_WRITE(HWS_PGA, addr);
 }
 
-static void intel_ring_setup_status_page(struct intel_engine_cs *engine)
+static void ring_setup_phys_status_page(struct intel_engine_cs *engine)
+{
+       struct page *page = virt_to_page(engine->status_page.page_addr);
+       phys_addr_t phys = PFN_PHYS(page_to_pfn(page));
+
+       set_hws_pga(engine, phys);
+       set_hwstam(engine, ~0u);
+}
+
+static void set_hwsp(struct intel_engine_cs *engine, u32 offset)
 {
        struct drm_i915_private *dev_priv = engine->i915;
-       i915_reg_t mmio;
+       i915_reg_t hwsp;
 
-       /* The ring status page addresses are no longer next to the rest of
+       /*
+        * The ring status page addresses are no longer next to the rest of
         * the ring registers as of gen7.
         */
-       if (IS_GEN7(dev_priv)) {
+       if (IS_GEN(dev_priv, 7)) {
                switch (engine->id) {
                /*
                 * No more rings exist on Gen7. Default case is only to shut up
@@ -410,56 +525,55 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *engine)
                default:
                        GEM_BUG_ON(engine->id);
                case RCS:
-                       mmio = RENDER_HWS_PGA_GEN7;
+                       hwsp = RENDER_HWS_PGA_GEN7;
                        break;
                case BCS:
-                       mmio = BLT_HWS_PGA_GEN7;
+                       hwsp = BLT_HWS_PGA_GEN7;
                        break;
                case VCS:
-                       mmio = BSD_HWS_PGA_GEN7;
+                       hwsp = BSD_HWS_PGA_GEN7;
                        break;
                case VECS:
-                       mmio = VEBOX_HWS_PGA_GEN7;
+                       hwsp = VEBOX_HWS_PGA_GEN7;
                        break;
                }
-       } else if (IS_GEN6(dev_priv)) {
-               mmio = RING_HWS_PGA_GEN6(engine->mmio_base);
+       } else if (IS_GEN(dev_priv, 6)) {
+               hwsp = RING_HWS_PGA_GEN6(engine->mmio_base);
        } else {
-               mmio = RING_HWS_PGA(engine->mmio_base);
+               hwsp = RING_HWS_PGA(engine->mmio_base);
        }
 
-       if (INTEL_GEN(dev_priv) >= 6) {
-               u32 mask = ~0u;
+       I915_WRITE(hwsp, offset);
+       POSTING_READ(hwsp);
+}
 
-               /*
-                * Keep the render interrupt unmasked as this papers over
-                * lost interrupts following a reset.
-                */
-               if (engine->id == RCS)
-                       mask &= ~BIT(0);
+static void flush_cs_tlb(struct intel_engine_cs *engine)
+{
+       struct drm_i915_private *dev_priv = engine->i915;
+       i915_reg_t instpm = RING_INSTPM(engine->mmio_base);
 
-               I915_WRITE(RING_HWSTAM(engine->mmio_base), mask);
-       }
+       if (!IS_GEN_RANGE(dev_priv, 6, 7))
+               return;
 
-       I915_WRITE(mmio, engine->status_page.ggtt_offset);
-       POSTING_READ(mmio);
+       /* ring should be idle before issuing a sync flush*/
+       WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0);
 
-       /* Flush the TLB for this page */
-       if (IS_GEN(dev_priv, 6, 7)) {
-               i915_reg_t reg = RING_INSTPM(engine->mmio_base);
+       I915_WRITE(instpm,
+                  _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE |
+                                     INSTPM_SYNC_FLUSH));
+       if (intel_wait_for_register(dev_priv,
+                                   instpm, INSTPM_SYNC_FLUSH, 0,
+                                   1000))
+               DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n",
+                         engine->name);
+}
 
-               /* ring should be idle before issuing a sync flush*/
-               WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0);
+static void ring_setup_status_page(struct intel_engine_cs *engine)
+{
+       set_hwsp(engine, engine->status_page.ggtt_offset);
+       set_hwstam(engine, ~0u);
 
-               I915_WRITE(reg,
-                          _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE |
-                                             INSTPM_SYNC_FLUSH));
-               if (intel_wait_for_register(dev_priv,
-                                           reg, INSTPM_SYNC_FLUSH, 0,
-                                           1000))
-                       DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n",
-                                 engine->name);
-       }
+       flush_cs_tlb(engine);
 }
 
 static bool stop_ring(struct intel_engine_cs *engine)
@@ -529,17 +643,10 @@ static int init_ring_common(struct intel_engine_cs *engine)
        if (HWS_NEEDS_PHYSICAL(dev_priv))
                ring_setup_phys_status_page(engine);
        else
-               intel_ring_setup_status_page(engine);
+               ring_setup_status_page(engine);
 
        intel_engine_reset_breadcrumbs(engine);
 
-       if (HAS_LEGACY_SEMAPHORES(engine->i915)) {
-               I915_WRITE(RING_SYNC_0(engine->mmio_base), 0);
-               I915_WRITE(RING_SYNC_1(engine->mmio_base), 0);
-               if (HAS_VEBOX(dev_priv))
-                       I915_WRITE(RING_SYNC_2(engine->mmio_base), 0);
-       }
-
        /* Enforce ordering by reading HEAD register back */
        I915_READ_HEAD(engine);
 
@@ -603,10 +710,6 @@ out:
 static struct i915_request *reset_prepare(struct intel_engine_cs *engine)
 {
        intel_engine_stop_cs(engine);
-
-       if (engine->irq_seqno_barrier)
-               engine->irq_seqno_barrier(engine);
-
        return i915_gem_find_active_request(engine);
 }
 
@@ -679,7 +782,7 @@ static int init_render_ring(struct intel_engine_cs *engine)
                return ret;
 
        /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */
-       if (IS_GEN(dev_priv, 4, 6))
+       if (IS_GEN_RANGE(dev_priv, 4, 6))
                I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH));
 
        /* We need to disable the AsyncFlip performance optimisations in order
@@ -688,22 +791,22 @@ static int init_render_ring(struct intel_engine_cs *engine)
         *
         * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv
         */
-       if (IS_GEN(dev_priv, 6, 7))
+       if (IS_GEN_RANGE(dev_priv, 6, 7))
                I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE));
 
        /* Required for the hardware to program scanline values for waiting */
        /* WaEnableFlushTlbInvalidationMode:snb */
-       if (IS_GEN6(dev_priv))
+       if (IS_GEN(dev_priv, 6))
                I915_WRITE(GFX_MODE,
                           _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT));
 
        /* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */
-       if (IS_GEN7(dev_priv))
+       if (IS_GEN(dev_priv, 7))
                I915_WRITE(GFX_MODE_GEN7,
                           _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) |
                           _MASKED_BIT_ENABLE(GFX_REPLAY_MODE));
 
-       if (IS_GEN6(dev_priv)) {
+       if (IS_GEN(dev_priv, 6)) {
                /* From the Sandybridge PRM, volume 1 part 3, page 24:
                 * "If this bit is set, STCunit will have LRA as replacement
                 *  policy. [...] This bit must be reset.  LRA replacement
@@ -713,7 +816,7 @@ static int init_render_ring(struct intel_engine_cs *engine)
                           _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
        }
 
-       if (IS_GEN(dev_priv, 6, 7))
+       if (IS_GEN_RANGE(dev_priv, 6, 7))
                I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
 
        if (INTEL_GEN(dev_priv) >= 6)
@@ -722,33 +825,6 @@ static int init_render_ring(struct intel_engine_cs *engine)
        return 0;
 }
 
-static u32 *gen6_signal(struct i915_request *rq, u32 *cs)
-{
-       struct drm_i915_private *dev_priv = rq->i915;
-       struct intel_engine_cs *engine;
-       enum intel_engine_id id;
-       int num_rings = 0;
-
-       for_each_engine(engine, dev_priv, id) {
-               i915_reg_t mbox_reg;
-
-               if (!(BIT(engine->hw_id) & GEN6_SEMAPHORES_MASK))
-                       continue;
-
-               mbox_reg = rq->engine->semaphore.mbox.signal[engine->hw_id];
-               if (i915_mmio_reg_valid(mbox_reg)) {
-                       *cs++ = MI_LOAD_REGISTER_IMM(1);
-                       *cs++ = i915_mmio_reg_offset(mbox_reg);
-                       *cs++ = rq->global_seqno;
-                       num_rings++;
-               }
-       }
-       if (num_rings & 1)
-               *cs++ = MI_NOOP;
-
-       return cs;
-}
-
 static void cancel_requests(struct intel_engine_cs *engine)
 {
        struct i915_request *request;
@@ -760,8 +836,7 @@ static void cancel_requests(struct intel_engine_cs *engine)
        list_for_each_entry(request, &engine->timeline.requests, link) {
                GEM_BUG_ON(!request->global_seqno);
 
-               if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
-                            &request->fence.flags))
+               if (i915_request_signaled(request))
                        continue;
 
                dma_fence_set_error(&request->fence, -EIO);
@@ -788,92 +863,41 @@ static void i9xx_submit_request(struct i915_request *request)
 
 static void i9xx_emit_breadcrumb(struct i915_request *rq, u32 *cs)
 {
+       *cs++ = MI_FLUSH;
+
        *cs++ = MI_STORE_DWORD_INDEX;
-       *cs++ = I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT;
+       *cs++ = I915_GEM_HWS_INDEX_ADDR;
        *cs++ = rq->global_seqno;
+
        *cs++ = MI_USER_INTERRUPT;
+       *cs++ = MI_NOOP;
 
        rq->tail = intel_ring_offset(rq, cs);
        assert_ring_tail_valid(rq->ring, rq->tail);
 }
+static const int i9xx_emit_breadcrumb_sz = 6;
 
-static const int i9xx_emit_breadcrumb_sz = 4;
-
-static void gen6_sema_emit_breadcrumb(struct i915_request *rq, u32 *cs)
-{
-       return i9xx_emit_breadcrumb(rq, rq->engine->semaphore.signal(rq, cs));
-}
-
-static int
-gen6_ring_sync_to(struct i915_request *rq, struct i915_request *signal)
+#define GEN5_WA_STORES 8 /* must be at least 1! */
+static void gen5_emit_breadcrumb(struct i915_request *rq, u32 *cs)
 {
-       u32 dw1 = MI_SEMAPHORE_MBOX |
-                 MI_SEMAPHORE_COMPARE |
-                 MI_SEMAPHORE_REGISTER;
-       u32 wait_mbox = signal->engine->semaphore.mbox.wait[rq->engine->hw_id];
-       u32 *cs;
-
-       WARN_ON(wait_mbox == MI_SEMAPHORE_SYNC_INVALID);
-
-       cs = intel_ring_begin(rq, 4);
-       if (IS_ERR(cs))
-               return PTR_ERR(cs);
-
-       *cs++ = dw1 | wait_mbox;
-       /* Throughout all of the GEM code, seqno passed implies our current
-        * seqno is >= the last seqno executed. However for hardware the
-        * comparison is strictly greater than.
-        */
-       *cs++ = signal->global_seqno - 1;
-       *cs++ = 0;
-       *cs++ = MI_NOOP;
-       intel_ring_advance(rq, cs);
+       int i;
 
-       return 0;
-}
+       *cs++ = MI_FLUSH;
 
-static void
-gen5_seqno_barrier(struct intel_engine_cs *engine)
-{
-       /* MI_STORE are internally buffered by the GPU and not flushed
-        * either by MI_FLUSH or SyncFlush or any other combination of
-        * MI commands.
-        *
-        * "Only the submission of the store operation is guaranteed.
-        * The write result will be complete (coherent) some time later
-        * (this is practically a finite period but there is no guaranteed
-        * latency)."
-        *
-        * Empirically, we observe that we need a delay of at least 75us to
-        * be sure that the seqno write is visible by the CPU.
-        */
-       usleep_range(125, 250);
-}
+       BUILD_BUG_ON(GEN5_WA_STORES < 1);
+       for (i = 0; i < GEN5_WA_STORES; i++) {
+               *cs++ = MI_STORE_DWORD_INDEX;
+               *cs++ = I915_GEM_HWS_INDEX_ADDR;
+               *cs++ = rq->global_seqno;
+       }
 
-static void
-gen6_seqno_barrier(struct intel_engine_cs *engine)
-{
-       struct drm_i915_private *dev_priv = engine->i915;
+       *cs++ = MI_USER_INTERRUPT;
 
-       /* Workaround to force correct ordering between irq and seqno writes on
-        * ivb (and maybe also on snb) by reading from a CS register (like
-        * ACTHD) before reading the status page.
-        *
-        * Note that this effectively stalls the read by the time it takes to
-        * do a memory transaction, which more or less ensures that the write
-        * from the GPU has sufficient time to invalidate the CPU cacheline.
-        * Alternatively we could delay the interrupt from the CS ring to give
-        * the write time to land, but that would incur a delay after every
-        * batch i.e. much more frequent than a delay when waiting for the
-        * interrupt (with the same net latency).
-        *
-        * Also note that to prevent whole machine hangs on gen7, we have to
-        * take the spinlock to guard against concurrent cacheline access.
-        */
-       spin_lock_irq(&dev_priv->uncore.lock);
-       POSTING_READ_FW(RING_ACTHD(engine->mmio_base));
-       spin_unlock_irq(&dev_priv->uncore.lock);
+       rq->tail = intel_ring_offset(rq, cs);
+       assert_ring_tail_valid(rq->ring, rq->tail);
 }
+static const int gen5_emit_breadcrumb_sz = GEN5_WA_STORES * 3 + 2;
+#undef GEN5_WA_STORES
 
 static void
 gen5_irq_enable(struct intel_engine_cs *engine)
@@ -948,6 +972,10 @@ gen6_irq_enable(struct intel_engine_cs *engine)
        I915_WRITE_IMR(engine,
                       ~(engine->irq_enable_mask |
                         engine->irq_keep_mask));
+
+       /* Flush/delay to ensure the RING_IMR is active before the GT IMR */
+       POSTING_READ_FW(RING_IMR(engine->mmio_base));
+
        gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask);
 }
 
@@ -966,6 +994,10 @@ hsw_vebox_irq_enable(struct intel_engine_cs *engine)
        struct drm_i915_private *dev_priv = engine->i915;
 
        I915_WRITE_IMR(engine, ~engine->irq_enable_mask);
+
+       /* Flush/delay to ensure the RING_IMR is active before the GT IMR */
+       POSTING_READ_FW(RING_IMR(engine->mmio_base));
+
        gen6_unmask_pm_irq(dev_priv, engine->irq_enable_mask);
 }
 
@@ -1581,10 +1613,7 @@ static inline int mi_set_context(struct i915_request *rq, u32 flags)
        struct intel_engine_cs *engine = rq->engine;
        enum intel_engine_id id;
        const int num_rings =
-               /* Use an extended w/a on gen7 if signalling from other rings */
-               (HAS_LEGACY_SEMAPHORES(i915) && IS_GEN7(i915)) ?
-               INTEL_INFO(i915)->num_rings - 1 :
-               0;
+               IS_HSW_GT1(i915) ? RUNTIME_INFO(i915)->num_rings - 1 : 0;
        bool force_restore = false;
        int len;
        u32 *cs;
@@ -1597,7 +1626,7 @@ static inline int mi_set_context(struct i915_request *rq, u32 flags)
                flags |= MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN;
 
        len = 4;
-       if (IS_GEN7(i915))
+       if (IS_GEN(i915, 7))
                len += 2 + (num_rings ? 4*num_rings + 6 : 0);
        if (flags & MI_FORCE_RESTORE) {
                GEM_BUG_ON(flags & MI_RESTORE_INHIBIT);
@@ -1611,7 +1640,7 @@ static inline int mi_set_context(struct i915_request *rq, u32 flags)
                return PTR_ERR(cs);
 
        /* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */
-       if (IS_GEN7(i915)) {
+       if (IS_GEN(i915, 7)) {
                *cs++ = MI_ARB_ON_OFF | MI_ARB_DISABLE;
                if (num_rings) {
                        struct intel_engine_cs *signaller;
@@ -1658,7 +1687,7 @@ static inline int mi_set_context(struct i915_request *rq, u32 flags)
         */
        *cs++ = MI_NOOP;
 
-       if (IS_GEN7(i915)) {
+       if (IS_GEN(i915, 7)) {
                if (num_rings) {
                        struct intel_engine_cs *signaller;
                        i915_reg_t last_reg = {}; /* keep gcc quiet */
@@ -1829,17 +1858,19 @@ static int ring_request_alloc(struct i915_request *request)
 
        GEM_BUG_ON(!request->hw_context->pin_count);
 
-       /* Flush enough space to reduce the likelihood of waiting after
+       /*
+        * Flush enough space to reduce the likelihood of waiting after
         * we start building the request - in which case we will just
         * have to repeat work.
         */
        request->reserved_space += LEGACY_REQUEST_SIZE;
 
-       ret = intel_ring_wait_for_space(request->ring, request->reserved_space);
+       ret = switch_context(request);
        if (ret)
                return ret;
 
-       ret = switch_context(request);
+       /* Unconditionally invalidate GPU caches and TLBs. */
+       ret = request->engine->emit_flush(request, EMIT_INVALIDATE);
        if (ret)
                return ret;
 
@@ -1881,22 +1912,6 @@ static noinline int wait_for_space(struct intel_ring *ring, unsigned int bytes)
        return 0;
 }
 
-int intel_ring_wait_for_space(struct intel_ring *ring, unsigned int bytes)
-{
-       GEM_BUG_ON(bytes > ring->effective_size);
-       if (unlikely(bytes > ring->effective_size - ring->emit))
-               bytes += ring->size - ring->emit;
-
-       if (unlikely(bytes > ring->space)) {
-               int ret = wait_for_space(ring, bytes);
-               if (unlikely(ret))
-                       return ret;
-       }
-
-       GEM_BUG_ON(ring->space < bytes);
-       return 0;
-}
-
 u32 *intel_ring_begin(struct i915_request *rq, unsigned int num_dwords)
 {
        struct intel_ring *ring = rq->ring;
@@ -2129,77 +2144,15 @@ static int gen6_ring_flush(struct i915_request *rq, u32 mode)
        return gen6_flush_dw(rq, mode, MI_INVALIDATE_TLB);
 }
 
-static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv,
-                                      struct intel_engine_cs *engine)
-{
-       int i;
-
-       if (!HAS_LEGACY_SEMAPHORES(dev_priv))
-               return;
-
-       GEM_BUG_ON(INTEL_GEN(dev_priv) < 6);
-       engine->semaphore.sync_to = gen6_ring_sync_to;
-       engine->semaphore.signal = gen6_signal;
-
-       /*
-        * The current semaphore is only applied on pre-gen8
-        * platform.  And there is no VCS2 ring on the pre-gen8
-        * platform. So the semaphore between RCS and VCS2 is
-        * initialized as INVALID.
-        */
-       for (i = 0; i < GEN6_NUM_SEMAPHORES; i++) {
-               static const struct {
-                       u32 wait_mbox;
-                       i915_reg_t mbox_reg;
-               } sem_data[GEN6_NUM_SEMAPHORES][GEN6_NUM_SEMAPHORES] = {
-                       [RCS_HW] = {
-                               [VCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_RV,  .mbox_reg = GEN6_VRSYNC },
-                               [BCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_RB,  .mbox_reg = GEN6_BRSYNC },
-                               [VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_RVE, .mbox_reg = GEN6_VERSYNC },
-                       },
-                       [VCS_HW] = {
-                               [RCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VR,  .mbox_reg = GEN6_RVSYNC },
-                               [BCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VB,  .mbox_reg = GEN6_BVSYNC },
-                               [VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VVE, .mbox_reg = GEN6_VEVSYNC },
-                       },
-                       [BCS_HW] = {
-                               [RCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_BR,  .mbox_reg = GEN6_RBSYNC },
-                               [VCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_BV,  .mbox_reg = GEN6_VBSYNC },
-                               [VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_BVE, .mbox_reg = GEN6_VEBSYNC },
-                       },
-                       [VECS_HW] = {
-                               [RCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VER, .mbox_reg = GEN6_RVESYNC },
-                               [VCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VEV, .mbox_reg = GEN6_VVESYNC },
-                               [BCS_HW] =  { .wait_mbox = MI_SEMAPHORE_SYNC_VEB, .mbox_reg = GEN6_BVESYNC },
-                       },
-               };
-               u32 wait_mbox;
-               i915_reg_t mbox_reg;
-
-               if (i == engine->hw_id) {
-                       wait_mbox = MI_SEMAPHORE_SYNC_INVALID;
-                       mbox_reg = GEN6_NOSYNC;
-               } else {
-                       wait_mbox = sem_data[engine->hw_id][i].wait_mbox;
-                       mbox_reg = sem_data[engine->hw_id][i].mbox_reg;
-               }
-
-               engine->semaphore.mbox.wait[i] = wait_mbox;
-               engine->semaphore.mbox.signal[i] = mbox_reg;
-       }
-}
-
 static void intel_ring_init_irq(struct drm_i915_private *dev_priv,
                                struct intel_engine_cs *engine)
 {
        if (INTEL_GEN(dev_priv) >= 6) {
                engine->irq_enable = gen6_irq_enable;
                engine->irq_disable = gen6_irq_disable;
-               engine->irq_seqno_barrier = gen6_seqno_barrier;
        } else if (INTEL_GEN(dev_priv) >= 5) {
                engine->irq_enable = gen5_irq_enable;
                engine->irq_disable = gen5_irq_disable;
-               engine->irq_seqno_barrier = gen5_seqno_barrier;
        } else if (INTEL_GEN(dev_priv) >= 3) {
                engine->irq_enable = i9xx_irq_enable;
                engine->irq_disable = i9xx_irq_disable;
@@ -2231,7 +2184,6 @@ static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv,
        GEM_BUG_ON(INTEL_GEN(dev_priv) >= 8);
 
        intel_ring_init_irq(dev_priv, engine);
-       intel_ring_init_semaphores(dev_priv, engine);
 
        engine->init_hw = init_ring_common;
        engine->reset.prepare = reset_prepare;
@@ -2243,15 +2195,9 @@ static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv,
 
        engine->emit_breadcrumb = i9xx_emit_breadcrumb;
        engine->emit_breadcrumb_sz = i9xx_emit_breadcrumb_sz;
-       if (HAS_LEGACY_SEMAPHORES(dev_priv)) {
-               int num_rings;
-
-               engine->emit_breadcrumb = gen6_sema_emit_breadcrumb;
-
-               num_rings = INTEL_INFO(dev_priv)->num_rings - 1;
-               engine->emit_breadcrumb_sz += num_rings * 3;
-               if (num_rings & 1)
-                       engine->emit_breadcrumb_sz++;
+       if (IS_GEN(dev_priv, 5)) {
+               engine->emit_breadcrumb = gen5_emit_breadcrumb;
+               engine->emit_breadcrumb_sz = gen5_emit_breadcrumb_sz;
        }
 
        engine->set_default_submission = i9xx_set_default_submission;
@@ -2278,12 +2224,17 @@ int intel_init_render_ring_buffer(struct intel_engine_cs *engine)
 
        engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
 
-       if (INTEL_GEN(dev_priv) >= 6) {
+       if (INTEL_GEN(dev_priv) >= 7) {
                engine->init_context = intel_rcs_ctx_init;
                engine->emit_flush = gen7_render_ring_flush;
-               if (IS_GEN6(dev_priv))
-                       engine->emit_flush = gen6_render_ring_flush;
-       } else if (IS_GEN5(dev_priv)) {
+               engine->emit_breadcrumb = gen7_rcs_emit_breadcrumb;
+               engine->emit_breadcrumb_sz = gen7_rcs_emit_breadcrumb_sz;
+       } else if (IS_GEN(dev_priv, 6)) {
+               engine->init_context = intel_rcs_ctx_init;
+               engine->emit_flush = gen6_render_ring_flush;
+               engine->emit_breadcrumb = gen6_rcs_emit_breadcrumb;
+               engine->emit_breadcrumb_sz = gen6_rcs_emit_breadcrumb_sz;
+       } else if (IS_GEN(dev_priv, 5)) {
                engine->emit_flush = gen4_render_ring_flush;
        } else {
                if (INTEL_GEN(dev_priv) < 4)
@@ -2313,13 +2264,21 @@ int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine)
 
        if (INTEL_GEN(dev_priv) >= 6) {
                /* gen6 bsd needs a special wa for tail updates */
-               if (IS_GEN6(dev_priv))
+               if (IS_GEN(dev_priv, 6))
                        engine->set_default_submission = gen6_bsd_set_default_submission;
                engine->emit_flush = gen6_bsd_ring_flush;
                engine->irq_enable_mask = GT_BSD_USER_INTERRUPT;
+
+               if (IS_GEN(dev_priv, 6)) {
+                       engine->emit_breadcrumb = gen6_xcs_emit_breadcrumb;
+                       engine->emit_breadcrumb_sz = gen6_xcs_emit_breadcrumb_sz;
+               } else {
+                       engine->emit_breadcrumb = gen7_xcs_emit_breadcrumb;
+                       engine->emit_breadcrumb_sz = gen7_xcs_emit_breadcrumb_sz;
+               }
        } else {
                engine->emit_flush = bsd_ring_flush;
-               if (IS_GEN5(dev_priv))
+               if (IS_GEN(dev_priv, 5))
                        engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT;
                else
                        engine->irq_enable_mask = I915_BSD_USER_INTERRUPT;
@@ -2332,11 +2291,21 @@ int intel_init_blt_ring_buffer(struct intel_engine_cs *engine)
 {
        struct drm_i915_private *dev_priv = engine->i915;
 
+       GEM_BUG_ON(INTEL_GEN(dev_priv) < 6);
+
        intel_ring_default_vfuncs(dev_priv, engine);
 
        engine->emit_flush = gen6_ring_flush;
        engine->irq_enable_mask = GT_BLT_USER_INTERRUPT;
 
+       if (IS_GEN(dev_priv, 6)) {
+               engine->emit_breadcrumb = gen6_xcs_emit_breadcrumb;
+               engine->emit_breadcrumb_sz = gen6_xcs_emit_breadcrumb_sz;
+       } else {
+               engine->emit_breadcrumb = gen7_xcs_emit_breadcrumb;
+               engine->emit_breadcrumb_sz = gen7_xcs_emit_breadcrumb_sz;
+       }
+
        return intel_init_ring_buffer(engine);
 }
 
@@ -2344,6 +2313,8 @@ int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine)
 {
        struct drm_i915_private *dev_priv = engine->i915;
 
+       GEM_BUG_ON(INTEL_GEN(dev_priv) < 7);
+
        intel_ring_default_vfuncs(dev_priv, engine);
 
        engine->emit_flush = gen6_ring_flush;
@@ -2351,5 +2322,8 @@ int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine)
        engine->irq_enable = hsw_vebox_irq_enable;
        engine->irq_disable = hsw_vebox_irq_disable;
 
+       engine->emit_breadcrumb = gen7_xcs_emit_breadcrumb;
+       engine->emit_breadcrumb_sz = gen7_xcs_emit_breadcrumb_sz;
+
        return intel_init_ring_buffer(engine);
 }
index 72edaa7ff4114fc61894f298f8d3952e8c5855c9..c3ef0f9bf321a442bba48fdd78b533c1e4d071bc 100644 (file)
@@ -28,7 +28,7 @@ struct i915_sched_attr;
  * workarounds!
  */
 #define CACHELINE_BYTES 64
-#define CACHELINE_DWORDS (CACHELINE_BYTES / sizeof(uint32_t))
+#define CACHELINE_DWORDS (CACHELINE_BYTES / sizeof(u32))
 
 struct intel_hw_status_page {
        struct i915_vma *vma;
@@ -94,12 +94,12 @@ hangcheck_action_to_str(const enum intel_engine_hangcheck_action a)
 #define I915_MAX_SUBSLICES 8
 
 #define instdone_slice_mask(dev_priv__) \
-       (IS_GEN7(dev_priv__) ? \
-        1 : INTEL_INFO(dev_priv__)->sseu.slice_mask)
+       (IS_GEN(dev_priv__, 7) ? \
+        1 : RUNTIME_INFO(dev_priv__)->sseu.slice_mask)
 
 #define instdone_subslice_mask(dev_priv__) \
-       (IS_GEN7(dev_priv__) ? \
-        1 : INTEL_INFO(dev_priv__)->sseu.subslice_mask[0])
+       (IS_GEN(dev_priv__, 7) ? \
+        1 : RUNTIME_INFO(dev_priv__)->sseu.subslice_mask[0])
 
 #define for_each_instdone_slice_subslice(dev_priv__, slice__, subslice__) \
        for ((slice__) = 0, (subslice__) = 0; \
@@ -365,9 +365,6 @@ struct intel_engine_cs {
        struct drm_i915_gem_object *default_state;
        void *pinned_default_state;
 
-       unsigned long irq_posted;
-#define ENGINE_IRQ_BREADCRUMB 0
-
        /* Rather than have every client wait upon all user interrupts,
         * with the herd waking after every interrupt and each doing the
         * heavyweight seqno dance, we delegate the task (of being the
@@ -401,7 +398,6 @@ struct intel_engine_cs {
                unsigned int irq_count;
 
                bool irq_armed : 1;
-               I915_SELFTEST_DECLARE(bool mock : 1);
        } breadcrumbs;
 
        struct {
@@ -501,69 +497,8 @@ struct intel_engine_cs {
         */
        void            (*cancel_requests)(struct intel_engine_cs *engine);
 
-       /* Some chipsets are not quite as coherent as advertised and need
-        * an expensive kick to force a true read of the up-to-date seqno.
-        * However, the up-to-date seqno is not always required and the last
-        * seen value is good enough. Note that the seqno will always be
-        * monotonic, even if not coherent.
-        */
-       void            (*irq_seqno_barrier)(struct intel_engine_cs *engine);
        void            (*cleanup)(struct intel_engine_cs *engine);
 
-       /* GEN8 signal/wait table - never trust comments!
-        *        signal to     signal to    signal to   signal to      signal to
-        *          RCS            VCS          BCS        VECS          VCS2
-        *      --------------------------------------------------------------------
-        *  RCS | NOP (0x00) | VCS (0x08) | BCS (0x10) | VECS (0x18) | VCS2 (0x20) |
-        *      |-------------------------------------------------------------------
-        *  VCS | RCS (0x28) | NOP (0x30) | BCS (0x38) | VECS (0x40) | VCS2 (0x48) |
-        *      |-------------------------------------------------------------------
-        *  BCS | RCS (0x50) | VCS (0x58) | NOP (0x60) | VECS (0x68) | VCS2 (0x70) |
-        *      |-------------------------------------------------------------------
-        * VECS | RCS (0x78) | VCS (0x80) | BCS (0x88) |  NOP (0x90) | VCS2 (0x98) |
-        *      |-------------------------------------------------------------------
-        * VCS2 | RCS (0xa0) | VCS (0xa8) | BCS (0xb0) | VECS (0xb8) | NOP  (0xc0) |
-        *      |-------------------------------------------------------------------
-        *
-        * Generalization:
-        *  f(x, y) := (x->id * NUM_RINGS * seqno_size) + (seqno_size * y->id)
-        *  ie. transpose of g(x, y)
-        *
-        *       sync from      sync from    sync from    sync from     sync from
-        *          RCS            VCS          BCS        VECS          VCS2
-        *      --------------------------------------------------------------------
-        *  RCS | NOP (0x00) | VCS (0x28) | BCS (0x50) | VECS (0x78) | VCS2 (0xa0) |
-        *      |-------------------------------------------------------------------
-        *  VCS | RCS (0x08) | NOP (0x30) | BCS (0x58) | VECS (0x80) | VCS2 (0xa8) |
-        *      |-------------------------------------------------------------------
-        *  BCS | RCS (0x10) | VCS (0x38) | NOP (0x60) | VECS (0x88) | VCS2 (0xb0) |
-        *      |-------------------------------------------------------------------
-        * VECS | RCS (0x18) | VCS (0x40) | BCS (0x68) |  NOP (0x90) | VCS2 (0xb8) |
-        *      |-------------------------------------------------------------------
-        * VCS2 | RCS (0x20) | VCS (0x48) | BCS (0x70) | VECS (0x98) |  NOP (0xc0) |
-        *      |-------------------------------------------------------------------
-        *
-        * Generalization:
-        *  g(x, y) := (y->id * NUM_RINGS * seqno_size) + (seqno_size * x->id)
-        *  ie. transpose of f(x, y)
-        */
-       struct {
-#define GEN6_SEMAPHORE_LAST    VECS_HW
-#define GEN6_NUM_SEMAPHORES    (GEN6_SEMAPHORE_LAST + 1)
-#define GEN6_SEMAPHORES_MASK   GENMASK(GEN6_SEMAPHORE_LAST, 0)
-               struct {
-                       /* our mbox written by others */
-                       u32             wait[GEN6_NUM_SEMAPHORES];
-                       /* mboxes this ring signals to */
-                       i915_reg_t      signal[GEN6_NUM_SEMAPHORES];
-               } mbox;
-
-               /* AKA wait() */
-               int     (*sync_to)(struct i915_request *rq,
-                                  struct i915_request *signal);
-               u32     *(*signal)(struct i915_request *rq, u32 *cs);
-       } semaphore;
-
        struct intel_engine_execlists execlists;
 
        /* Contexts are pinned whilst they are active on the GPU. The last
@@ -808,7 +743,6 @@ void intel_legacy_submission_resume(struct drm_i915_private *dev_priv);
 
 int __must_check intel_ring_cacheline_align(struct i915_request *rq);
 
-int intel_ring_wait_for_space(struct intel_ring *ring, unsigned int bytes);
 u32 __must_check *intel_ring_begin(struct i915_request *rq, unsigned int n);
 
 static inline void intel_ring_advance(struct i915_request *rq, u32 *cs)
@@ -889,7 +823,7 @@ intel_ring_set_tail(struct intel_ring *ring, unsigned int tail)
        return tail;
 }
 
-void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno);
+void intel_engine_write_global_seqno(struct intel_engine_cs *engine, u32 seqno);
 
 void intel_engine_setup_common(struct intel_engine_cs *engine);
 int intel_engine_init_common(struct intel_engine_cs *engine);
@@ -903,6 +837,8 @@ int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine);
 int intel_engine_stop_cs(struct intel_engine_cs *engine);
 void intel_engine_cancel_stop_cs(struct intel_engine_cs *engine);
 
+void intel_engine_set_hwsp_writemask(struct intel_engine_cs *engine, u32 mask);
+
 u64 intel_engine_get_active_head(const struct intel_engine_cs *engine);
 u64 intel_engine_get_last_batch_head(const struct intel_engine_cs *engine);
 
@@ -947,15 +883,6 @@ static inline bool intel_engine_has_started(struct intel_engine_cs *engine,
 void intel_engine_get_instdone(struct intel_engine_cs *engine,
                               struct intel_instdone *instdone);
 
-/*
- * Arbitrary size for largest possible 'add request' sequence. The code paths
- * are complex and variable. Empirical measurement shows that the worst case
- * is BDW at 192 bytes (6 + 6 + 36 dwords), then ILK at 136 bytes. However,
- * we need to allocate double the largest single packet within that emission
- * to account for tail wraparound (so 6 + 6 + 72 dwords for BDW).
- */
-#define MIN_SPACE_FOR_ADD_REQUEST 336
-
 static inline u32 intel_hws_seqno_address(struct intel_engine_cs *engine)
 {
        return engine->status_page.ggtt_offset + I915_GEM_HWS_INDEX_ADDR;
@@ -1055,7 +982,7 @@ static inline u32 *gen8_emit_pipe_control(u32 *batch, u32 flags, u32 offset)
 }
 
 static inline u32 *
-gen8_emit_ggtt_write_rcs(u32 *cs, u32 value, u32 gtt_offset)
+gen8_emit_ggtt_write_rcs(u32 *cs, u32 value, u32 gtt_offset, u32 flags)
 {
        /* We're using qword write, offset should be aligned to 8 bytes. */
        GEM_BUG_ON(!IS_ALIGNED(gtt_offset, 8));
@@ -1065,8 +992,7 @@ gen8_emit_ggtt_write_rcs(u32 *cs, u32 value, u32 gtt_offset)
         * following the batch.
         */
        *cs++ = GFX_OP_PIPE_CONTROL(6);
-       *cs++ = PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_CS_STALL |
-               PIPE_CONTROL_QW_WRITE;
+       *cs++ = flags | PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_GLOBAL_GTT_IVB;
        *cs++ = gtt_offset;
        *cs++ = 0;
        *cs++ = value;
@@ -1092,7 +1018,7 @@ gen8_emit_ggtt_write(u32 *cs, u32 value, u32 gtt_offset)
        return cs;
 }
 
-void intel_engines_sanitize(struct drm_i915_private *i915);
+void intel_engines_sanitize(struct drm_i915_private *i915, bool force);
 
 bool intel_engine_is_idle(struct intel_engine_cs *engine);
 bool intel_engines_are_idle(struct drm_i915_private *dev_priv);
index 4350a5270423c1b924a5e69a75ea0ff27b0ec31f..a017a4232c0fae4580da8b0a59bf54a9ba7fdecb 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/pm_runtime.h>
 #include <linux/vgaarb.h>
 
+#include <drm/drm_print.h>
+
 #include "i915_drv.h"
 #include "intel_drv.h"
 
  * present for a given platform.
  */
 
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
+
+#include <linux/sort.h>
+
+#define STACKDEPTH 8
+
+static noinline depot_stack_handle_t __save_depot_stack(void)
+{
+       unsigned long entries[STACKDEPTH];
+       struct stack_trace trace = {
+               .entries = entries,
+               .max_entries = ARRAY_SIZE(entries),
+               .skip = 1,
+       };
+
+       save_stack_trace(&trace);
+       if (trace.nr_entries &&
+           trace.entries[trace.nr_entries - 1] == ULONG_MAX)
+               trace.nr_entries--;
+
+       return depot_save_stack(&trace, GFP_NOWAIT | __GFP_NOWARN);
+}
+
+static void __print_depot_stack(depot_stack_handle_t stack,
+                               char *buf, int sz, int indent)
+{
+       unsigned long entries[STACKDEPTH];
+       struct stack_trace trace = {
+               .entries = entries,
+               .max_entries = ARRAY_SIZE(entries),
+       };
+
+       depot_fetch_stack(stack, &trace);
+       snprint_stack_trace(buf, sz, &trace, indent);
+}
+
+static void init_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+{
+       struct i915_runtime_pm *rpm = &i915->runtime_pm;
+
+       spin_lock_init(&rpm->debug.lock);
+}
+
+static noinline depot_stack_handle_t
+track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+{
+       struct i915_runtime_pm *rpm = &i915->runtime_pm;
+       depot_stack_handle_t stack, *stacks;
+       unsigned long flags;
+
+       atomic_inc(&rpm->wakeref_count);
+       assert_rpm_wakelock_held(i915);
+
+       if (!HAS_RUNTIME_PM(i915))
+               return -1;
+
+       stack = __save_depot_stack();
+       if (!stack)
+               return -1;
+
+       spin_lock_irqsave(&rpm->debug.lock, flags);
+
+       if (!rpm->debug.count)
+               rpm->debug.last_acquire = stack;
+
+       stacks = krealloc(rpm->debug.owners,
+                         (rpm->debug.count + 1) * sizeof(*stacks),
+                         GFP_NOWAIT | __GFP_NOWARN);
+       if (stacks) {
+               stacks[rpm->debug.count++] = stack;
+               rpm->debug.owners = stacks;
+       } else {
+               stack = -1;
+       }
+
+       spin_unlock_irqrestore(&rpm->debug.lock, flags);
+
+       return stack;
+}
+
+static void cancel_intel_runtime_pm_wakeref(struct drm_i915_private *i915,
+                                           depot_stack_handle_t stack)
+{
+       struct i915_runtime_pm *rpm = &i915->runtime_pm;
+       unsigned long flags, n;
+       bool found = false;
+
+       if (unlikely(stack == -1))
+               return;
+
+       spin_lock_irqsave(&rpm->debug.lock, flags);
+       for (n = rpm->debug.count; n--; ) {
+               if (rpm->debug.owners[n] == stack) {
+                       memmove(rpm->debug.owners + n,
+                               rpm->debug.owners + n + 1,
+                               (--rpm->debug.count - n) * sizeof(stack));
+                       found = true;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&rpm->debug.lock, flags);
+
+       if (WARN(!found,
+                "Unmatched wakeref (tracking %lu), count %u\n",
+                rpm->debug.count, atomic_read(&rpm->wakeref_count))) {
+               char *buf;
+
+               buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+               if (!buf)
+                       return;
+
+               __print_depot_stack(stack, buf, PAGE_SIZE, 2);
+               DRM_DEBUG_DRIVER("wakeref %x from\n%s", stack, buf);
+
+               stack = READ_ONCE(rpm->debug.last_release);
+               if (stack) {
+                       __print_depot_stack(stack, buf, PAGE_SIZE, 2);
+                       DRM_DEBUG_DRIVER("wakeref last released at\n%s", buf);
+               }
+
+               kfree(buf);
+       }
+}
+
+static int cmphandle(const void *_a, const void *_b)
+{
+       const depot_stack_handle_t * const a = _a, * const b = _b;
+
+       if (*a < *b)
+               return -1;
+       else if (*a > *b)
+               return 1;
+       else
+               return 0;
+}
+
+static void
+__print_intel_runtime_pm_wakeref(struct drm_printer *p,
+                                const struct intel_runtime_pm_debug *dbg)
+{
+       unsigned long i;
+       char *buf;
+
+       buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!buf)
+               return;
+
+       if (dbg->last_acquire) {
+               __print_depot_stack(dbg->last_acquire, buf, PAGE_SIZE, 2);
+               drm_printf(p, "Wakeref last acquired:\n%s", buf);
+       }
+
+       if (dbg->last_release) {
+               __print_depot_stack(dbg->last_release, buf, PAGE_SIZE, 2);
+               drm_printf(p, "Wakeref last released:\n%s", buf);
+       }
+
+       drm_printf(p, "Wakeref count: %lu\n", dbg->count);
+
+       sort(dbg->owners, dbg->count, sizeof(*dbg->owners), cmphandle, NULL);
+
+       for (i = 0; i < dbg->count; i++) {
+               depot_stack_handle_t stack = dbg->owners[i];
+               unsigned long rep;
+
+               rep = 1;
+               while (i + 1 < dbg->count && dbg->owners[i + 1] == stack)
+                       rep++, i++;
+               __print_depot_stack(stack, buf, PAGE_SIZE, 2);
+               drm_printf(p, "Wakeref x%lu taken at:\n%s", rep, buf);
+       }
+
+       kfree(buf);
+}
+
+static noinline void
+untrack_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+{
+       struct i915_runtime_pm *rpm = &i915->runtime_pm;
+       struct intel_runtime_pm_debug dbg = {};
+       struct drm_printer p;
+       unsigned long flags;
+
+       assert_rpm_wakelock_held(i915);
+       if (atomic_dec_and_lock_irqsave(&rpm->wakeref_count,
+                                       &rpm->debug.lock,
+                                       flags)) {
+               dbg = rpm->debug;
+
+               rpm->debug.owners = NULL;
+               rpm->debug.count = 0;
+               rpm->debug.last_release = __save_depot_stack();
+
+               spin_unlock_irqrestore(&rpm->debug.lock, flags);
+       }
+       if (!dbg.count)
+               return;
+
+       p = drm_debug_printer("i915");
+       __print_intel_runtime_pm_wakeref(&p, &dbg);
+
+       kfree(dbg.owners);
+}
+
+void print_intel_runtime_pm_wakeref(struct drm_i915_private *i915,
+                                   struct drm_printer *p)
+{
+       struct intel_runtime_pm_debug dbg = {};
+
+       do {
+               struct i915_runtime_pm *rpm = &i915->runtime_pm;
+               unsigned long alloc = dbg.count;
+               depot_stack_handle_t *s;
+
+               spin_lock_irq(&rpm->debug.lock);
+               dbg.count = rpm->debug.count;
+               if (dbg.count <= alloc) {
+                       memcpy(dbg.owners,
+                              rpm->debug.owners,
+                              dbg.count * sizeof(*s));
+               }
+               dbg.last_acquire = rpm->debug.last_acquire;
+               dbg.last_release = rpm->debug.last_release;
+               spin_unlock_irq(&rpm->debug.lock);
+               if (dbg.count <= alloc)
+                       break;
+
+               s = krealloc(dbg.owners, dbg.count * sizeof(*s), GFP_KERNEL);
+               if (!s)
+                       goto out;
+
+               dbg.owners = s;
+       } while (1);
+
+       __print_intel_runtime_pm_wakeref(p, &dbg);
+
+out:
+       kfree(dbg.owners);
+}
+
+#else
+
+static void init_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+{
+}
+
+static depot_stack_handle_t
+track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+{
+       atomic_inc(&i915->runtime_pm.wakeref_count);
+       assert_rpm_wakelock_held(i915);
+       return -1;
+}
+
+static void untrack_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+{
+       assert_rpm_wakelock_held(i915);
+       atomic_dec(&i915->runtime_pm.wakeref_count);
+}
+
+#endif
+
 bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
                                         enum i915_power_well_id power_well_id);
 
@@ -509,7 +773,7 @@ static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv,
         * BIOS's own request bits, which are forced-on for these power wells
         * when exiting DC5/6.
         */
-       if (IS_GEN9(dev_priv) && !IS_GEN9_LP(dev_priv) &&
+       if (IS_GEN(dev_priv, 9) && !IS_GEN9_LP(dev_priv) &&
            (id == SKL_DISP_PW_1 || id == SKL_DISP_PW_MISC_IO))
                val |= I915_READ(regs->bios);
 
@@ -639,10 +903,10 @@ void gen9_sanitize_dc_state(struct drm_i915_private *dev_priv)
  * back on and register state is restored. This is guaranteed by the MMIO write
  * to DC_STATE_EN blocking until the state is restored.
  */
-static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state)
+static void gen9_set_dc_state(struct drm_i915_private *dev_priv, u32 state)
 {
-       uint32_t val;
-       uint32_t mask;
+       u32 val;
+       u32 mask;
 
        if (WARN_ON_ONCE(state & ~dev_priv->csr.allowed_dc_mask))
                state &= dev_priv->csr.allowed_dc_mask;
@@ -1274,7 +1538,7 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
 {
        enum dpio_phy phy;
        enum pipe pipe;
-       uint32_t tmp;
+       u32 tmp;
 
        WARN_ON_ONCE(power_well->desc->id != VLV_DISP_PW_DPIO_CMN_BC &&
                     power_well->desc->id != CHV_DISP_PW_DPIO_CMN_D);
@@ -1591,18 +1855,19 @@ __intel_display_power_get_domain(struct drm_i915_private *dev_priv,
  * Any power domain reference obtained by this function must have a symmetric
  * call to intel_display_power_put() to release the reference again.
  */
-void intel_display_power_get(struct drm_i915_private *dev_priv,
-                            enum intel_display_power_domain domain)
+intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,
+                                       enum intel_display_power_domain domain)
 {
        struct i915_power_domains *power_domains = &dev_priv->power_domains;
-
-       intel_runtime_pm_get(dev_priv);
+       intel_wakeref_t wakeref = intel_runtime_pm_get(dev_priv);
 
        mutex_lock(&power_domains->lock);
 
        __intel_display_power_get_domain(dev_priv, domain);
 
        mutex_unlock(&power_domains->lock);
+
+       return wakeref;
 }
 
 /**
@@ -1617,13 +1882,16 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
  * Any power domain reference obtained by this function must have a symmetric
  * call to intel_display_power_put() to release the reference again.
  */
-bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
-                                       enum intel_display_power_domain domain)
+intel_wakeref_t
+intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
+                                  enum intel_display_power_domain domain)
 {
        struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       intel_wakeref_t wakeref;
        bool is_enabled;
 
-       if (!intel_runtime_pm_get_if_in_use(dev_priv))
+       wakeref = intel_runtime_pm_get_if_in_use(dev_priv);
+       if (!wakeref)
                return false;
 
        mutex_lock(&power_domains->lock);
@@ -1637,23 +1905,16 @@ bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
 
        mutex_unlock(&power_domains->lock);
 
-       if (!is_enabled)
-               intel_runtime_pm_put(dev_priv);
+       if (!is_enabled) {
+               intel_runtime_pm_put(dev_priv, wakeref);
+               wakeref = 0;
+       }
 
-       return is_enabled;
+       return wakeref;
 }
 
-/**
- * intel_display_power_put - release a power domain reference
- * @dev_priv: i915 device instance
- * @domain: power domain to reference
- *
- * This function drops the power domain reference obtained by
- * intel_display_power_get() and might power down the corresponding hardware
- * block right away if this is the last reference.
- */
-void intel_display_power_put(struct drm_i915_private *dev_priv,
-                            enum intel_display_power_domain domain)
+static void __intel_display_power_put(struct drm_i915_private *dev_priv,
+                                     enum intel_display_power_domain domain)
 {
        struct i915_power_domains *power_domains;
        struct i915_power_well *power_well;
@@ -1671,9 +1932,33 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
                intel_power_well_put(dev_priv, power_well);
 
        mutex_unlock(&power_domains->lock);
+}
+
+/**
+ * intel_display_power_put - release a power domain reference
+ * @dev_priv: i915 device instance
+ * @domain: power domain to reference
+ *
+ * This function drops the power domain reference obtained by
+ * intel_display_power_get() and might power down the corresponding hardware
+ * block right away if this is the last reference.
+ */
+void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,
+                                      enum intel_display_power_domain domain)
+{
+       __intel_display_power_put(dev_priv, domain);
+       intel_runtime_pm_put_unchecked(dev_priv);
+}
 
-       intel_runtime_pm_put(dev_priv);
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
+void intel_display_power_put(struct drm_i915_private *dev_priv,
+                            enum intel_display_power_domain domain,
+                            intel_wakeref_t wakeref)
+{
+       __intel_display_power_put(dev_priv, domain);
+       intel_runtime_pm_put(dev_priv, wakeref);
 }
+#endif
 
 #define I830_PIPES_POWER_DOMAINS (             \
        BIT_ULL(POWER_DOMAIN_PIPE_A) |          \
@@ -3043,10 +3328,10 @@ sanitize_disable_power_well_option(const struct drm_i915_private *dev_priv,
        return 1;
 }
 
-static uint32_t get_allowed_dc_mask(const struct drm_i915_private *dev_priv,
-                                   int enable_dc)
+static u32 get_allowed_dc_mask(const struct drm_i915_private *dev_priv,
+                              int enable_dc)
 {
-       uint32_t mask;
+       u32 mask;
        int requested_dc;
        int max_dc;
 
@@ -3058,7 +3343,7 @@ static uint32_t get_allowed_dc_mask(const struct drm_i915_private *dev_priv,
                 * suspend/resume, so allow it unconditionally.
                 */
                mask = DC_STATE_EN_DC9;
-       } else if (IS_GEN10(dev_priv) || IS_GEN9_BC(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 10) || IS_GEN9_BC(dev_priv)) {
                max_dc = 2;
                mask = 0;
        } else if (IS_GEN9_LP(dev_priv)) {
@@ -3311,7 +3596,7 @@ static void icl_dbuf_disable(struct drm_i915_private *dev_priv)
 
 static void icl_mbus_init(struct drm_i915_private *dev_priv)
 {
-       uint32_t val;
+       u32 val;
 
        val = MBUS_ABOX_BT_CREDIT_POOL1(16) |
              MBUS_ABOX_BT_CREDIT_POOL2(16) |
@@ -3622,7 +3907,7 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv)
         * current lane status.
         */
        if (cmn_bc->desc->ops->is_enabled(dev_priv, cmn_bc)) {
-               uint32_t status = I915_READ(DPLL(PIPE_A));
+               u32 status = I915_READ(DPLL(PIPE_A));
                unsigned int mask;
 
                mask = status & DPLL_PORTB_READY_MASK;
@@ -3653,7 +3938,7 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv)
        }
 
        if (cmn_d->desc->ops->is_enabled(dev_priv, cmn_d)) {
-               uint32_t status = I915_READ(DPIO_PHY_STATUS);
+               u32 status = I915_READ(DPIO_PHY_STATUS);
                unsigned int mask;
 
                mask = status & DPLL_PORTD_READY_MASK;
@@ -3712,7 +3997,7 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv);
 
 /**
  * intel_power_domains_init_hw - initialize hardware power domain state
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  * @resume: Called from resume code paths or not
  *
  * This function initializes the hardware power domain state and enables all
@@ -3726,30 +4011,31 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv);
  * intel_power_domains_enable()) and must be paired with
  * intel_power_domains_fini_hw().
  */
-void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
+void intel_power_domains_init_hw(struct drm_i915_private *i915, bool resume)
 {
-       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       struct i915_power_domains *power_domains = &i915->power_domains;
 
        power_domains->initializing = true;
 
-       if (IS_ICELAKE(dev_priv)) {
-               icl_display_core_init(dev_priv, resume);
-       } else if (IS_CANNONLAKE(dev_priv)) {
-               cnl_display_core_init(dev_priv, resume);
-       } else if (IS_GEN9_BC(dev_priv)) {
-               skl_display_core_init(dev_priv, resume);
-       } else if (IS_GEN9_LP(dev_priv)) {
-               bxt_display_core_init(dev_priv, resume);
-       } else if (IS_CHERRYVIEW(dev_priv)) {
+       if (IS_ICELAKE(i915)) {
+               icl_display_core_init(i915, resume);
+       } else if (IS_CANNONLAKE(i915)) {
+               cnl_display_core_init(i915, resume);
+       } else if (IS_GEN9_BC(i915)) {
+               skl_display_core_init(i915, resume);
+       } else if (IS_GEN9_LP(i915)) {
+               bxt_display_core_init(i915, resume);
+       } else if (IS_CHERRYVIEW(i915)) {
                mutex_lock(&power_domains->lock);
-               chv_phy_control_init(dev_priv);
+               chv_phy_control_init(i915);
                mutex_unlock(&power_domains->lock);
-       } else if (IS_VALLEYVIEW(dev_priv)) {
+       } else if (IS_VALLEYVIEW(i915)) {
                mutex_lock(&power_domains->lock);
-               vlv_cmnlane_wa(dev_priv);
+               vlv_cmnlane_wa(i915);
                mutex_unlock(&power_domains->lock);
-       } else if (IS_IVYBRIDGE(dev_priv) || INTEL_GEN(dev_priv) >= 7)
-               intel_pch_reset_handshake(dev_priv, !HAS_PCH_NOP(dev_priv));
+       } else if (IS_IVYBRIDGE(i915) || INTEL_GEN(i915) >= 7) {
+               intel_pch_reset_handshake(i915, !HAS_PCH_NOP(i915));
+       }
 
        /*
         * Keep all power wells enabled for any dependent HW access during
@@ -3757,18 +4043,20 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
         * resources powered until display HW readout is complete. We drop
         * this reference in intel_power_domains_enable().
         */
-       intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+       power_domains->wakeref =
+               intel_display_power_get(i915, POWER_DOMAIN_INIT);
+
        /* Disable power support if the user asked so. */
        if (!i915_modparams.disable_power_well)
-               intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
-       intel_power_domains_sync_hw(dev_priv);
+               intel_display_power_get(i915, POWER_DOMAIN_INIT);
+       intel_power_domains_sync_hw(i915);
 
        power_domains->initializing = false;
 }
 
 /**
  * intel_power_domains_fini_hw - deinitialize hw power domain state
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * De-initializes the display power domain HW state. It also ensures that the
  * device stays powered up so that the driver can be reloaded.
@@ -3777,21 +4065,24 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
  * intel_power_domains_disable()) and must be paired with
  * intel_power_domains_init_hw().
  */
-void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
+void intel_power_domains_fini_hw(struct drm_i915_private *i915)
 {
-       /* Keep the power well enabled, but cancel its rpm wakeref. */
-       intel_runtime_pm_put(dev_priv);
+       intel_wakeref_t wakeref __maybe_unused =
+               fetch_and_zero(&i915->power_domains.wakeref);
 
        /* Remove the refcount we took to keep power well support disabled. */
        if (!i915_modparams.disable_power_well)
-               intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+               intel_display_power_put_unchecked(i915, POWER_DOMAIN_INIT);
+
+       intel_power_domains_verify_state(i915);
 
-       intel_power_domains_verify_state(dev_priv);
+       /* Keep the power well enabled, but cancel its rpm wakeref. */
+       intel_runtime_pm_put(i915, wakeref);
 }
 
 /**
  * intel_power_domains_enable - enable toggling of display power wells
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * Enable the ondemand enabling/disabling of the display power wells. Note that
  * power wells not belonging to POWER_DOMAIN_INIT are allowed to be toggled
@@ -3801,30 +4092,36 @@ void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
  * of display HW readout (which will acquire the power references reflecting
  * the current HW state).
  */
-void intel_power_domains_enable(struct drm_i915_private *dev_priv)
+void intel_power_domains_enable(struct drm_i915_private *i915)
 {
-       intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+       intel_wakeref_t wakeref __maybe_unused =
+               fetch_and_zero(&i915->power_domains.wakeref);
 
-       intel_power_domains_verify_state(dev_priv);
+       intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
+       intel_power_domains_verify_state(i915);
 }
 
 /**
  * intel_power_domains_disable - disable toggling of display power wells
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * Disable the ondemand enabling/disabling of the display power wells. See
  * intel_power_domains_enable() for which power wells this call controls.
  */
-void intel_power_domains_disable(struct drm_i915_private *dev_priv)
+void intel_power_domains_disable(struct drm_i915_private *i915)
 {
-       intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+       struct i915_power_domains *power_domains = &i915->power_domains;
 
-       intel_power_domains_verify_state(dev_priv);
+       WARN_ON(power_domains->wakeref);
+       power_domains->wakeref =
+               intel_display_power_get(i915, POWER_DOMAIN_INIT);
+
+       intel_power_domains_verify_state(i915);
 }
 
 /**
  * intel_power_domains_suspend - suspend power domain state
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  * @suspend_mode: specifies the target suspend state (idle, mem, hibernation)
  *
  * This function prepares the hardware power domain state before entering
@@ -3833,12 +4130,14 @@ void intel_power_domains_disable(struct drm_i915_private *dev_priv)
  * It must be called with power domains already disabled (after a call to
  * intel_power_domains_disable()) and paired with intel_power_domains_resume().
  */
-void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
+void intel_power_domains_suspend(struct drm_i915_private *i915,
                                 enum i915_drm_suspend_mode suspend_mode)
 {
-       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       struct i915_power_domains *power_domains = &i915->power_domains;
+       intel_wakeref_t wakeref __maybe_unused =
+               fetch_and_zero(&power_domains->wakeref);
 
-       intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+       intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
 
        /*
         * In case of suspend-to-idle (aka S0ix) on a DMC platform without DC9
@@ -3847,10 +4146,10 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
         * resources as required and also enable deeper system power states
         * that would be blocked if the firmware was inactive.
         */
-       if (!(dev_priv->csr.allowed_dc_mask & DC_STATE_EN_DC9) &&
+       if (!(i915->csr.allowed_dc_mask & DC_STATE_EN_DC9) &&
            suspend_mode == I915_DRM_SUSPEND_IDLE &&
-           dev_priv->csr.dmc_payload != NULL) {
-               intel_power_domains_verify_state(dev_priv);
+           i915->csr.dmc_payload) {
+               intel_power_domains_verify_state(i915);
                return;
        }
 
@@ -3859,25 +4158,25 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
         * power wells if power domains must be deinitialized for suspend.
         */
        if (!i915_modparams.disable_power_well) {
-               intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
-               intel_power_domains_verify_state(dev_priv);
+               intel_display_power_put_unchecked(i915, POWER_DOMAIN_INIT);
+               intel_power_domains_verify_state(i915);
        }
 
-       if (IS_ICELAKE(dev_priv))
-               icl_display_core_uninit(dev_priv);
-       else if (IS_CANNONLAKE(dev_priv))
-               cnl_display_core_uninit(dev_priv);
-       else if (IS_GEN9_BC(dev_priv))
-               skl_display_core_uninit(dev_priv);
-       else if (IS_GEN9_LP(dev_priv))
-               bxt_display_core_uninit(dev_priv);
+       if (IS_ICELAKE(i915))
+               icl_display_core_uninit(i915);
+       else if (IS_CANNONLAKE(i915))
+               cnl_display_core_uninit(i915);
+       else if (IS_GEN9_BC(i915))
+               skl_display_core_uninit(i915);
+       else if (IS_GEN9_LP(i915))
+               bxt_display_core_uninit(i915);
 
        power_domains->display_core_suspended = true;
 }
 
 /**
  * intel_power_domains_resume - resume power domain state
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * This function resume the hardware power domain state during system resume.
  *
@@ -3885,28 +4184,30 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
  * intel_power_domains_enable()) and must be paired with
  * intel_power_domains_suspend().
  */
-void intel_power_domains_resume(struct drm_i915_private *dev_priv)
+void intel_power_domains_resume(struct drm_i915_private *i915)
 {
-       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       struct i915_power_domains *power_domains = &i915->power_domains;
 
        if (power_domains->display_core_suspended) {
-               intel_power_domains_init_hw(dev_priv, true);
+               intel_power_domains_init_hw(i915, true);
                power_domains->display_core_suspended = false;
        } else {
-               intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+               WARN_ON(power_domains->wakeref);
+               power_domains->wakeref =
+                       intel_display_power_get(i915, POWER_DOMAIN_INIT);
        }
 
-       intel_power_domains_verify_state(dev_priv);
+       intel_power_domains_verify_state(i915);
 }
 
 #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
 
-static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv)
+static void intel_power_domains_dump_info(struct drm_i915_private *i915)
 {
-       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       struct i915_power_domains *power_domains = &i915->power_domains;
        struct i915_power_well *power_well;
 
-       for_each_power_well(dev_priv, power_well) {
+       for_each_power_well(i915, power_well) {
                enum intel_display_power_domain domain;
 
                DRM_DEBUG_DRIVER("%-25s %d\n",
@@ -3921,7 +4222,7 @@ static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv)
 
 /**
  * intel_power_domains_verify_state - verify the HW/SW state for all power wells
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * Verify if the reference count of each power well matches its HW enabled
  * state and the total refcount of the domains it belongs to. This must be
@@ -3929,22 +4230,21 @@ static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv)
  * acquiring reference counts for any power wells in use and disabling the
  * ones left on by BIOS but not required by any active output.
  */
-static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
+static void intel_power_domains_verify_state(struct drm_i915_private *i915)
 {
-       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       struct i915_power_domains *power_domains = &i915->power_domains;
        struct i915_power_well *power_well;
        bool dump_domain_info;
 
        mutex_lock(&power_domains->lock);
 
        dump_domain_info = false;
-       for_each_power_well(dev_priv, power_well) {
+       for_each_power_well(i915, power_well) {
                enum intel_display_power_domain domain;
                int domains_count;
                bool enabled;
 
-               enabled = power_well->desc->ops->is_enabled(dev_priv,
-                                                           power_well);
+               enabled = power_well->desc->ops->is_enabled(i915, power_well);
                if ((power_well->count || power_well->desc->always_on) !=
                    enabled)
                        DRM_ERROR("power well %s state mismatch (refcount %d/enabled %d)",
@@ -3968,7 +4268,7 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
                static bool dumped;
 
                if (!dumped) {
-                       intel_power_domains_dump_info(dev_priv);
+                       intel_power_domains_dump_info(i915);
                        dumped = true;
                }
        }
@@ -3978,7 +4278,7 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
 
 #else
 
-static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
+static void intel_power_domains_verify_state(struct drm_i915_private *i915)
 {
 }
 
@@ -3986,30 +4286,31 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
 
 /**
  * intel_runtime_pm_get - grab a runtime pm reference
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * This function grabs a device-level runtime pm reference (mostly used for GEM
  * code to ensure the GTT or GT is on) and ensures that it is powered up.
  *
  * Any runtime pm reference obtained by this function must have a symmetric
  * call to intel_runtime_pm_put() to release the reference again.
+ *
+ * Returns: the wakeref cookie to pass to intel_runtime_pm_put()
  */
-void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
+intel_wakeref_t intel_runtime_pm_get(struct drm_i915_private *i915)
 {
-       struct pci_dev *pdev = dev_priv->drm.pdev;
+       struct pci_dev *pdev = i915->drm.pdev;
        struct device *kdev = &pdev->dev;
        int ret;
 
        ret = pm_runtime_get_sync(kdev);
        WARN_ONCE(ret < 0, "pm_runtime_get_sync() failed: %d\n", ret);
 
-       atomic_inc(&dev_priv->runtime_pm.wakeref_count);
-       assert_rpm_wakelock_held(dev_priv);
+       return track_intel_runtime_pm_wakeref(i915);
 }
 
 /**
  * intel_runtime_pm_get_if_in_use - grab a runtime pm reference if device in use
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * This function grabs a device-level runtime pm reference if the device is
  * already in use and ensures that it is powered up. It is illegal to try
@@ -4018,12 +4319,13 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
  * Any runtime pm reference obtained by this function must have a symmetric
  * call to intel_runtime_pm_put() to release the reference again.
  *
- * Returns: True if the wakeref was acquired, or False otherwise.
+ * Returns: the wakeref cookie to pass to intel_runtime_pm_put(), evaluates
+ * as True if the wakeref was acquired, or False otherwise.
  */
-bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv)
+intel_wakeref_t intel_runtime_pm_get_if_in_use(struct drm_i915_private *i915)
 {
        if (IS_ENABLED(CONFIG_PM)) {
-               struct pci_dev *pdev = dev_priv->drm.pdev;
+               struct pci_dev *pdev = i915->drm.pdev;
                struct device *kdev = &pdev->dev;
 
                /*
@@ -4033,18 +4335,15 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv)
                 * atm to the late/early system suspend/resume handlers.
                 */
                if (pm_runtime_get_if_in_use(kdev) <= 0)
-                       return false;
+                       return 0;
        }
 
-       atomic_inc(&dev_priv->runtime_pm.wakeref_count);
-       assert_rpm_wakelock_held(dev_priv);
-
-       return true;
+       return track_intel_runtime_pm_wakeref(i915);
 }
 
 /**
  * intel_runtime_pm_get_noresume - grab a runtime pm reference
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * This function grabs a device-level runtime pm reference (mostly used for GEM
  * code to ensure the GTT or GT is on).
@@ -4058,41 +4357,50 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv)
  *
  * Any runtime pm reference obtained by this function must have a symmetric
  * call to intel_runtime_pm_put() to release the reference again.
+ *
+ * Returns: the wakeref cookie to pass to intel_runtime_pm_put()
  */
-void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv)
+intel_wakeref_t intel_runtime_pm_get_noresume(struct drm_i915_private *i915)
 {
-       struct pci_dev *pdev = dev_priv->drm.pdev;
+       struct pci_dev *pdev = i915->drm.pdev;
        struct device *kdev = &pdev->dev;
 
-       assert_rpm_wakelock_held(dev_priv);
+       assert_rpm_wakelock_held(i915);
        pm_runtime_get_noresume(kdev);
 
-       atomic_inc(&dev_priv->runtime_pm.wakeref_count);
+       return track_intel_runtime_pm_wakeref(i915);
 }
 
 /**
  * intel_runtime_pm_put - release a runtime pm reference
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * This function drops the device-level runtime pm reference obtained by
  * intel_runtime_pm_get() and might power down the corresponding
  * hardware block right away if this is the last reference.
  */
-void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
+void intel_runtime_pm_put_unchecked(struct drm_i915_private *i915)
 {
-       struct pci_dev *pdev = dev_priv->drm.pdev;
+       struct pci_dev *pdev = i915->drm.pdev;
        struct device *kdev = &pdev->dev;
 
-       assert_rpm_wakelock_held(dev_priv);
-       atomic_dec(&dev_priv->runtime_pm.wakeref_count);
+       untrack_intel_runtime_pm_wakeref(i915);
 
        pm_runtime_mark_last_busy(kdev);
        pm_runtime_put_autosuspend(kdev);
 }
 
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
+void intel_runtime_pm_put(struct drm_i915_private *i915, intel_wakeref_t wref)
+{
+       cancel_intel_runtime_pm_wakeref(i915, wref);
+       intel_runtime_pm_put_unchecked(i915);
+}
+#endif
+
 /**
  * intel_runtime_pm_enable - enable runtime pm
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * This function enables runtime pm at the end of the driver load sequence.
  *
@@ -4100,9 +4408,9 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
  * subordinate display power domains. That is done by
  * intel_power_domains_enable().
  */
-void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
+void intel_runtime_pm_enable(struct drm_i915_private *i915)
 {
-       struct pci_dev *pdev = dev_priv->drm.pdev;
+       struct pci_dev *pdev = i915->drm.pdev;
        struct device *kdev = &pdev->dev;
 
        /*
@@ -4124,7 +4432,7 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
         * so the driver's own RPM reference tracking asserts also work on
         * platforms without RPM support.
         */
-       if (!HAS_RUNTIME_PM(dev_priv)) {
+       if (!HAS_RUNTIME_PM(i915)) {
                int ret;
 
                pm_runtime_dont_use_autosuspend(kdev);
@@ -4142,17 +4450,35 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
        pm_runtime_put_autosuspend(kdev);
 }
 
-void intel_runtime_pm_disable(struct drm_i915_private *dev_priv)
+void intel_runtime_pm_disable(struct drm_i915_private *i915)
 {
-       struct pci_dev *pdev = dev_priv->drm.pdev;
+       struct pci_dev *pdev = i915->drm.pdev;
        struct device *kdev = &pdev->dev;
 
        /* Transfer rpm ownership back to core */
-       WARN(pm_runtime_get_sync(&dev_priv->drm.pdev->dev) < 0,
+       WARN(pm_runtime_get_sync(kdev) < 0,
             "Failed to pass rpm ownership back to core\n");
 
        pm_runtime_dont_use_autosuspend(kdev);
 
-       if (!HAS_RUNTIME_PM(dev_priv))
+       if (!HAS_RUNTIME_PM(i915))
                pm_runtime_put(kdev);
 }
+
+void intel_runtime_pm_cleanup(struct drm_i915_private *i915)
+{
+       struct i915_runtime_pm *rpm = &i915->runtime_pm;
+       int count;
+
+       count = atomic_fetch_inc(&rpm->wakeref_count); /* balance untrack */
+       WARN(count,
+            "i915->runtime_pm.wakeref_count=%d on cleanup\n",
+            count);
+
+       untrack_intel_runtime_pm_wakeref(i915);
+}
+
+void intel_runtime_pm_init_early(struct drm_i915_private *i915)
+{
+       init_intel_runtime_pm_wakeref(i915);
+}
index 5805ec1aba122495736167c0f66ee86cd5da249d..e7b0884ba5a57f825a4d3b722e7a9c8b33496551 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/export.h>
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
@@ -77,7 +76,7 @@ struct intel_sdvo {
        i915_reg_t sdvo_reg;
 
        /* Active outputs controlled by this SDVO output */
-       uint16_t controlled_output;
+       u16 controlled_output;
 
        /*
         * Capabilities of the SDVO device returned by
@@ -92,33 +91,32 @@ struct intel_sdvo {
        * For multiple function SDVO device,
        * this is for current attached outputs.
        */
-       uint16_t attached_output;
+       u16 attached_output;
 
        /*
         * Hotplug activation bits for this device
         */
-       uint16_t hotplug_active;
+       u16 hotplug_active;
 
        enum port port;
 
        bool has_hdmi_monitor;
        bool has_hdmi_audio;
-       bool rgb_quant_range_selectable;
 
        /* DDC bus used by this SDVO encoder */
-       uint8_t ddc_bus;
+       u8 ddc_bus;
 
        /*
         * the sdvo flag gets lost in round trip: dtd->adjusted_mode->dtd
         */
-       uint8_t dtd_sdvo_flags;
+       u8 dtd_sdvo_flags;
 };
 
 struct intel_sdvo_connector {
        struct intel_connector base;
 
        /* Mark the type of connector */
-       uint16_t output_flag;
+       u16 output_flag;
 
        /* This contains all current supported TV format */
        u8 tv_format_supported[TV_FORMAT_NUM];
@@ -186,7 +184,7 @@ to_intel_sdvo_connector(struct drm_connector *connector)
        container_of((conn_state), struct intel_sdvo_connector_state, base.base)
 
 static bool
-intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags);
+intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags);
 static bool
 intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo,
                              struct intel_sdvo_connector *intel_sdvo_connector,
@@ -748,9 +746,9 @@ static bool intel_sdvo_get_input_timing(struct intel_sdvo *intel_sdvo,
 static bool
 intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo,
                                         struct intel_sdvo_connector *intel_sdvo_connector,
-                                        uint16_t clock,
-                                        uint16_t width,
-                                        uint16_t height)
+                                        u16 clock,
+                                        u16 width,
+                                        u16 height)
 {
        struct intel_sdvo_preferred_input_timing_args args;
 
@@ -793,9 +791,9 @@ static bool intel_sdvo_set_clock_rate_mult(struct intel_sdvo *intel_sdvo, u8 val
 static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd,
                                         const struct drm_display_mode *mode)
 {
-       uint16_t width, height;
-       uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len;
-       uint16_t h_sync_offset, v_sync_offset;
+       u16 width, height;
+       u16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
+       u16 h_sync_offset, v_sync_offset;
        int mode_clock;
 
        memset(dtd, 0, sizeof(*dtd));
@@ -900,13 +898,13 @@ static bool intel_sdvo_check_supp_encode(struct intel_sdvo *intel_sdvo)
 }
 
 static bool intel_sdvo_set_encode(struct intel_sdvo *intel_sdvo,
-                                 uint8_t mode)
+                                 u8 mode)
 {
        return intel_sdvo_set_value(intel_sdvo, SDVO_CMD_SET_ENCODE, &mode, 1);
 }
 
 static bool intel_sdvo_set_colorimetry(struct intel_sdvo *intel_sdvo,
-                                      uint8_t mode)
+                                      u8 mode)
 {
        return intel_sdvo_set_value(intel_sdvo, SDVO_CMD_SET_COLORIMETRY, &mode, 1);
 }
@@ -915,11 +913,11 @@ static bool intel_sdvo_set_colorimetry(struct intel_sdvo *intel_sdvo,
 static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
 {
        int i, j;
-       uint8_t set_buf_index[2];
-       uint8_t av_split;
-       uint8_t buf_size;
-       uint8_t buf[48];
-       uint8_t *pos;
+       u8 set_buf_index[2];
+       u8 av_split;
+       u8 buf_size;
+       u8 buf[48];
+       u8 *pos;
 
        intel_sdvo_get_value(encoder, SDVO_CMD_GET_HBUF_AV_SPLIT, &av_split, 1);
 
@@ -942,11 +940,11 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
 #endif
 
 static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
-                                      unsigned if_index, uint8_t tx_rate,
-                                      const uint8_t *data, unsigned length)
+                                      unsigned int if_index, u8 tx_rate,
+                                      const u8 *data, unsigned int length)
 {
-       uint8_t set_buf_index[2] = { if_index, 0 };
-       uint8_t hbuf_size, tmp[8];
+       u8 set_buf_index[2] = { if_index, 0 };
+       u8 hbuf_size, tmp[8];
        int i;
 
        if (!intel_sdvo_set_value(intel_sdvo,
@@ -981,29 +979,30 @@ static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
 }
 
 static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo,
-                                        const struct intel_crtc_state *pipe_config)
+                                        const struct intel_crtc_state *pipe_config,
+                                        const struct drm_connector_state *conn_state)
 {
-       uint8_t sdvo_data[HDMI_INFOFRAME_SIZE(AVI)];
+       const struct drm_display_mode *adjusted_mode =
+               &pipe_config->base.adjusted_mode;
+       u8 sdvo_data[HDMI_INFOFRAME_SIZE(AVI)];
        union hdmi_infoframe frame;
        int ret;
        ssize_t len;
 
        ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
-                                                      &pipe_config->base.adjusted_mode,
-                                                      false);
+                                                      conn_state->connector,
+                                                      adjusted_mode);
        if (ret < 0) {
                DRM_ERROR("couldn't fill AVI infoframe\n");
                return false;
        }
 
-       if (intel_sdvo->rgb_quant_range_selectable) {
-               if (pipe_config->limited_color_range)
-                       frame.avi.quantization_range =
-                               HDMI_QUANTIZATION_RANGE_LIMITED;
-               else
-                       frame.avi.quantization_range =
-                               HDMI_QUANTIZATION_RANGE_FULL;
-       }
+       drm_hdmi_avi_infoframe_quant_range(&frame.avi,
+                                          conn_state->connector,
+                                          adjusted_mode,
+                                          pipe_config->limited_color_range ?
+                                          HDMI_QUANTIZATION_RANGE_LIMITED :
+                                          HDMI_QUANTIZATION_RANGE_FULL);
 
        len = hdmi_infoframe_pack(&frame, sdvo_data, sizeof(sdvo_data));
        if (len < 0)
@@ -1018,7 +1017,7 @@ static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo,
                                     const struct drm_connector_state *conn_state)
 {
        struct intel_sdvo_tv_format format;
-       uint32_t format_map;
+       u32 format_map;
 
        format_map = 1 << conn_state->tv.mode;
        memset(&format, 0, sizeof(format));
@@ -1108,9 +1107,9 @@ static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc_state *pipe_config)
        pipe_config->clock_set = true;
 }
 
-static bool intel_sdvo_compute_config(struct intel_encoder *encoder,
-                                     struct intel_crtc_state *pipe_config,
-                                     struct drm_connector_state *conn_state)
+static int intel_sdvo_compute_config(struct intel_encoder *encoder,
+                                    struct intel_crtc_state *pipe_config,
+                                    struct drm_connector_state *conn_state)
 {
        struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
        struct intel_sdvo_connector_state *intel_sdvo_state =
@@ -1135,7 +1134,7 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder,
         */
        if (IS_TV(intel_sdvo_connector)) {
                if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode))
-                       return false;
+                       return -EINVAL;
 
                (void) intel_sdvo_get_preferred_input_mode(intel_sdvo,
                                                           intel_sdvo_connector,
@@ -1145,7 +1144,7 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder,
        } else if (IS_LVDS(intel_sdvo_connector)) {
                if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo,
                                                             intel_sdvo_connector->base.panel.fixed_mode))
-                       return false;
+                       return -EINVAL;
 
                (void) intel_sdvo_get_preferred_input_mode(intel_sdvo,
                                                           intel_sdvo_connector,
@@ -1154,7 +1153,7 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder,
        }
 
        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
-               return false;
+               return -EINVAL;
 
        /*
         * Make the CRTC code factor in the SDVO pixel multiplier.  The
@@ -1194,7 +1193,7 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder,
        if (intel_sdvo_connector->is_hdmi)
                adjusted_mode->picture_aspect_ratio = conn_state->picture_aspect_ratio;
 
-       return true;
+       return 0;
 }
 
 #define UPDATE_PROPERTY(input, NAME) \
@@ -1209,7 +1208,7 @@ static void intel_sdvo_update_props(struct intel_sdvo *intel_sdvo,
        const struct drm_connector_state *conn_state = &sdvo_state->base.base;
        struct intel_sdvo_connector *intel_sdvo_conn =
                to_intel_sdvo_connector(conn_state->connector);
-       uint16_t val;
+       u16 val;
 
        if (intel_sdvo_conn->left)
                UPDATE_PROPERTY(sdvo_state->tv.overscan_h, OVERSCAN_H);
@@ -1316,7 +1315,8 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder,
                intel_sdvo_set_encode(intel_sdvo, SDVO_ENCODE_HDMI);
                intel_sdvo_set_colorimetry(intel_sdvo,
                                           SDVO_COLORIMETRY_RGB256);
-               intel_sdvo_set_avi_infoframe(intel_sdvo, crtc_state);
+               intel_sdvo_set_avi_infoframe(intel_sdvo,
+                                            crtc_state, conn_state);
        } else
                intel_sdvo_set_encode(intel_sdvo, SDVO_ENCODE_DVI);
 
@@ -1692,10 +1692,10 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in
        return true;
 }
 
-static uint16_t intel_sdvo_get_hotplug_support(struct intel_sdvo *intel_sdvo)
+static u16 intel_sdvo_get_hotplug_support(struct intel_sdvo *intel_sdvo)
 {
        struct drm_i915_private *dev_priv = to_i915(intel_sdvo->base.base.dev);
-       uint16_t hotplug;
+       u16 hotplug;
 
        if (!I915_HAS_HOTPLUG(dev_priv))
                return 0;
@@ -1802,8 +1802,6 @@ intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
                        if (intel_sdvo_connector->is_hdmi) {
                                intel_sdvo->has_hdmi_monitor = drm_detect_hdmi_monitor(edid);
                                intel_sdvo->has_hdmi_audio = drm_detect_monitor_audio(edid);
-                               intel_sdvo->rgb_quant_range_selectable =
-                                       drm_rgb_quant_range_selectable(edid);
                        }
                } else
                        status = connector_status_disconnected;
@@ -1828,7 +1826,7 @@ intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo,
 static enum drm_connector_status
 intel_sdvo_detect(struct drm_connector *connector, bool force)
 {
-       uint16_t response;
+       u16 response;
        struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
        struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
        enum drm_connector_status ret;
@@ -1852,7 +1850,6 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
 
        intel_sdvo->has_hdmi_monitor = false;
        intel_sdvo->has_hdmi_audio = false;
-       intel_sdvo->rgb_quant_range_selectable = false;
 
        if ((intel_sdvo_connector->output_flag & response) == 0)
                ret = connector_status_disconnected;
@@ -1980,7 +1977,7 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
        struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
        const struct drm_connector_state *conn_state = connector->state;
        struct intel_sdvo_sdtv_resolution_request tv_res;
-       uint32_t reply = 0, format_map = 0;
+       u32 reply = 0, format_map = 0;
        int i;
 
        DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
@@ -2065,7 +2062,7 @@ static int
 intel_sdvo_connector_atomic_get_property(struct drm_connector *connector,
                                         const struct drm_connector_state *state,
                                         struct drm_property *property,
-                                        uint64_t *val)
+                                        u64 *val)
 {
        struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
        const struct intel_sdvo_connector_state *sdvo_state = to_intel_sdvo_connector_state((void *)state);
@@ -2124,7 +2121,7 @@ static int
 intel_sdvo_connector_atomic_set_property(struct drm_connector *connector,
                                         struct drm_connector_state *state,
                                         struct drm_property *property,
-                                        uint64_t val)
+                                        u64 val)
 {
        struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
        struct intel_sdvo_connector_state *sdvo_state = to_intel_sdvo_connector_state(state);
@@ -2273,7 +2270,7 @@ static const struct drm_encoder_funcs intel_sdvo_enc_funcs = {
 static void
 intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo)
 {
-       uint16_t mask = 0;
+       u16 mask = 0;
        unsigned int num_bits;
 
        /*
@@ -2674,7 +2671,7 @@ err:
 }
 
 static bool
-intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags)
+intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags)
 {
        /* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/
 
@@ -2750,7 +2747,7 @@ static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo,
 {
        struct drm_device *dev = intel_sdvo->base.base.dev;
        struct intel_sdvo_tv_format format;
-       uint32_t format_map, i;
+       u32 format_map, i;
 
        if (!intel_sdvo_set_target_output(intel_sdvo, type))
                return false;
@@ -2817,7 +2814,7 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo,
        struct drm_connector_state *conn_state = connector->state;
        struct intel_sdvo_connector_state *sdvo_state =
                to_intel_sdvo_connector_state(conn_state);
-       uint16_t response, data_value[2];
+       u16 response, data_value[2];
 
        /* when horizontal overscan is supported, Add the left/right property */
        if (enhancements.overscan_h) {
@@ -2928,7 +2925,7 @@ intel_sdvo_create_enhance_property_lvds(struct intel_sdvo *intel_sdvo,
 {
        struct drm_device *dev = intel_sdvo->base.base.dev;
        struct drm_connector *connector = &intel_sdvo_connector->base.base;
-       uint16_t response, data_value[2];
+       u16 response, data_value[2];
 
        ENHANCEMENT(&connector->state->tv, brightness, BRIGHTNESS);
 
@@ -2942,7 +2939,7 @@ static bool intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo,
 {
        union {
                struct intel_sdvo_enhancements_reply reply;
-               uint16_t response;
+               u16 response;
        } enhancements;
 
        BUILD_BUG_ON(sizeof(enhancements) != 2);
index d2e003d8f3dbe64247cac7de9baf6a6fcaa0c986..b02d3d9809e30e598942230940263de866c25b17 100644 (file)
@@ -29,7 +29,6 @@
  * registers; newer ones are much simpler and we can use the new DRM plane
  * support.
  */
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_fourcc.h>
@@ -322,8 +321,8 @@ skl_program_scaler(struct intel_plane *plane,
                &crtc_state->scaler_state.scalers[scaler_id];
        int crtc_x = plane_state->base.dst.x1;
        int crtc_y = plane_state->base.dst.y1;
-       uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
-       uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
+       u32 crtc_w = drm_rect_width(&plane_state->base.dst);
+       u32 crtc_h = drm_rect_height(&plane_state->base.dst);
        u16 y_hphase, uv_rgb_hphase;
        u16 y_vphase, uv_rgb_vphase;
        int hscale, vscale;
@@ -478,10 +477,10 @@ skl_program_plane(struct intel_plane *plane,
        u32 aux_stride = skl_plane_stride(plane_state, 1);
        int crtc_x = plane_state->base.dst.x1;
        int crtc_y = plane_state->base.dst.y1;
-       uint32_t x = plane_state->color_plane[color_plane].x;
-       uint32_t y = plane_state->color_plane[color_plane].y;
-       uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
-       uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
+       u32 x = plane_state->color_plane[color_plane].x;
+       u32 y = plane_state->color_plane[color_plane].y;
+       u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
+       u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
        struct intel_plane *linked = plane_state->linked_plane;
        const struct drm_framebuffer *fb = plane_state->base.fb;
        u8 alpha = plane_state->base.alpha >> 8;
@@ -619,17 +618,19 @@ skl_plane_get_hw_state(struct intel_plane *plane,
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum intel_display_power_domain power_domain;
        enum plane_id plane_id = plane->id;
+       intel_wakeref_t wakeref;
        bool ret;
 
        power_domain = POWER_DOMAIN_PIPE(plane->pipe);
-       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (!wakeref)
                return false;
 
        ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
 
        *pipe = plane->pipe;
 
-       intel_display_power_put(dev_priv, power_domain);
+       intel_display_power_put(dev_priv, power_domain, wakeref);
 
        return ret;
 }
@@ -813,10 +814,10 @@ vlv_update_plane(struct intel_plane *plane,
        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
        int crtc_x = plane_state->base.dst.x1;
        int crtc_y = plane_state->base.dst.y1;
-       uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
-       uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
-       uint32_t x = plane_state->color_plane[0].x;
-       uint32_t y = plane_state->color_plane[0].y;
+       u32 crtc_w = drm_rect_width(&plane_state->base.dst);
+       u32 crtc_h = drm_rect_height(&plane_state->base.dst);
+       u32 x = plane_state->color_plane[0].x;
+       u32 y = plane_state->color_plane[0].y;
        unsigned long irqflags;
 
        /* Sizes are 0 based */
@@ -883,17 +884,19 @@ vlv_plane_get_hw_state(struct intel_plane *plane,
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum intel_display_power_domain power_domain;
        enum plane_id plane_id = plane->id;
+       intel_wakeref_t wakeref;
        bool ret;
 
        power_domain = POWER_DOMAIN_PIPE(plane->pipe);
-       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (!wakeref)
                return false;
 
        ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
 
        *pipe = plane->pipe;
 
-       intel_display_power_put(dev_priv, power_domain);
+       intel_display_power_put(dev_priv, power_domain, wakeref);
 
        return ret;
 }
@@ -973,12 +976,12 @@ ivb_update_plane(struct intel_plane *plane,
        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
        int crtc_x = plane_state->base.dst.x1;
        int crtc_y = plane_state->base.dst.y1;
-       uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
-       uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
-       uint32_t x = plane_state->color_plane[0].x;
-       uint32_t y = plane_state->color_plane[0].y;
-       uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
-       uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
+       u32 crtc_w = drm_rect_width(&plane_state->base.dst);
+       u32 crtc_h = drm_rect_height(&plane_state->base.dst);
+       u32 x = plane_state->color_plane[0].x;
+       u32 y = plane_state->color_plane[0].y;
+       u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
+       u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
        unsigned long irqflags;
 
        /* Sizes are 0 based */
@@ -1052,17 +1055,19 @@ ivb_plane_get_hw_state(struct intel_plane *plane,
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum intel_display_power_domain power_domain;
+       intel_wakeref_t wakeref;
        bool ret;
 
        power_domain = POWER_DOMAIN_PIPE(plane->pipe);
-       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (!wakeref)
                return false;
 
        ret =  I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;
 
        *pipe = plane->pipe;
 
-       intel_display_power_put(dev_priv, power_domain);
+       intel_display_power_put(dev_priv, power_domain, wakeref);
 
        return ret;
 }
@@ -1087,7 +1092,7 @@ static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
 
        dvscntr = DVS_ENABLE | DVS_GAMMA_ENABLE;
 
-       if (IS_GEN6(dev_priv))
+       if (IS_GEN(dev_priv, 6))
                dvscntr |= DVS_TRICKLE_FEED_DISABLE;
 
        switch (fb->format->format) {
@@ -1147,12 +1152,12 @@ g4x_update_plane(struct intel_plane *plane,
        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
        int crtc_x = plane_state->base.dst.x1;
        int crtc_y = plane_state->base.dst.y1;
-       uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
-       uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
-       uint32_t x = plane_state->color_plane[0].x;
-       uint32_t y = plane_state->color_plane[0].y;
-       uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
-       uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
+       u32 crtc_w = drm_rect_width(&plane_state->base.dst);
+       u32 crtc_h = drm_rect_height(&plane_state->base.dst);
+       u32 x = plane_state->color_plane[0].x;
+       u32 y = plane_state->color_plane[0].y;
+       u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
+       u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
        unsigned long irqflags;
 
        /* Sizes are 0 based */
@@ -1218,17 +1223,19 @@ g4x_plane_get_hw_state(struct intel_plane *plane,
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum intel_display_power_domain power_domain;
+       intel_wakeref_t wakeref;
        bool ret;
 
        power_domain = POWER_DOMAIN_PIPE(plane->pipe);
-       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (!wakeref)
                return false;
 
        ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;
 
        *pipe = plane->pipe;
 
-       intel_display_power_put(dev_priv, power_domain);
+       intel_display_power_put(dev_priv, power_domain, wakeref);
 
        return ret;
 }
@@ -1699,7 +1706,7 @@ out:
        return ret;
 }
 
-static const uint32_t g4x_plane_formats[] = {
+static const u32 g4x_plane_formats[] = {
        DRM_FORMAT_XRGB8888,
        DRM_FORMAT_YUYV,
        DRM_FORMAT_YVYU,
@@ -1707,13 +1714,13 @@ static const uint32_t g4x_plane_formats[] = {
        DRM_FORMAT_VYUY,
 };
 
-static const uint64_t i9xx_plane_format_modifiers[] = {
+static const u64 i9xx_plane_format_modifiers[] = {
        I915_FORMAT_MOD_X_TILED,
        DRM_FORMAT_MOD_LINEAR,
        DRM_FORMAT_MOD_INVALID
 };
 
-static const uint32_t snb_plane_formats[] = {
+static const u32 snb_plane_formats[] = {
        DRM_FORMAT_XBGR8888,
        DRM_FORMAT_XRGB8888,
        DRM_FORMAT_YUYV,
@@ -1722,7 +1729,7 @@ static const uint32_t snb_plane_formats[] = {
        DRM_FORMAT_VYUY,
 };
 
-static const uint32_t vlv_plane_formats[] = {
+static const u32 vlv_plane_formats[] = {
        DRM_FORMAT_RGB565,
        DRM_FORMAT_ABGR8888,
        DRM_FORMAT_ARGB8888,
@@ -1736,7 +1743,7 @@ static const uint32_t vlv_plane_formats[] = {
        DRM_FORMAT_VYUY,
 };
 
-static const uint32_t skl_plane_formats[] = {
+static const u32 skl_plane_formats[] = {
        DRM_FORMAT_C8,
        DRM_FORMAT_RGB565,
        DRM_FORMAT_XRGB8888,
@@ -1751,7 +1758,7 @@ static const uint32_t skl_plane_formats[] = {
        DRM_FORMAT_VYUY,
 };
 
-static const uint32_t skl_planar_formats[] = {
+static const u32 skl_planar_formats[] = {
        DRM_FORMAT_C8,
        DRM_FORMAT_RGB565,
        DRM_FORMAT_XRGB8888,
@@ -1767,7 +1774,7 @@ static const uint32_t skl_planar_formats[] = {
        DRM_FORMAT_NV12,
 };
 
-static const uint64_t skl_plane_format_modifiers_noccs[] = {
+static const u64 skl_plane_format_modifiers_noccs[] = {
        I915_FORMAT_MOD_Yf_TILED,
        I915_FORMAT_MOD_Y_TILED,
        I915_FORMAT_MOD_X_TILED,
@@ -1775,7 +1782,7 @@ static const uint64_t skl_plane_format_modifiers_noccs[] = {
        DRM_FORMAT_MOD_INVALID
 };
 
-static const uint64_t skl_plane_format_modifiers_ccs[] = {
+static const u64 skl_plane_format_modifiers_ccs[] = {
        I915_FORMAT_MOD_Yf_TILED_CCS,
        I915_FORMAT_MOD_Y_TILED_CCS,
        I915_FORMAT_MOD_Yf_TILED,
@@ -1983,7 +1990,7 @@ static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
        if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
                return false;
 
-       if (IS_GEN9(dev_priv) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
+       if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
                return false;
 
        if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
@@ -2163,7 +2170,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
                plane->check_plane = g4x_sprite_check;
 
                modifiers = i9xx_plane_format_modifiers;
-               if (IS_GEN6(dev_priv)) {
+               if (IS_GEN(dev_priv, 6)) {
                        formats = snb_plane_formats;
                        num_formats = ARRAY_SIZE(snb_plane_formats);
 
index 860f306a23bafbda312d63bafb2039ce67b91069..bd5536f0ec9262ffc230186846b50f680f68e416 100644 (file)
@@ -30,7 +30,6 @@
  * Integrated TV-out support for the 915GM and 945GM.
  */
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
@@ -870,7 +869,7 @@ intel_tv_get_config(struct intel_encoder *encoder,
        pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock;
 }
 
-static bool
+static int
 intel_tv_compute_config(struct intel_encoder *encoder,
                        struct intel_crtc_state *pipe_config,
                        struct drm_connector_state *conn_state)
@@ -880,10 +879,10 @@ intel_tv_compute_config(struct intel_encoder *encoder,
                &pipe_config->base.adjusted_mode;
 
        if (!tv_mode)
-               return false;
+               return -EINVAL;
 
        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
-               return false;
+               return -EINVAL;
 
        pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
        adjusted_mode->crtc_clock = tv_mode->clock;
@@ -898,7 +897,7 @@ intel_tv_compute_config(struct intel_encoder *encoder,
         * or whether userspace is doing something stupid.
         */
 
-       return true;
+       return 0;
 }
 
 static void
index b34c318b238dad37a027aad52b5a920e2c73f3dc..e711eb3268bccb39f631e6018567fe09b9e053f0 100644 (file)
@@ -26,6 +26,7 @@
 #include "intel_guc_submission.h"
 #include "intel_guc.h"
 #include "i915_drv.h"
+#include "i915_reset.h"
 
 static void guc_free_load_err_log(struct intel_guc *guc);
 
@@ -71,7 +72,7 @@ static int __get_default_guc_log_level(struct drm_i915_private *i915)
 {
        int guc_log_level;
 
-       if (!HAS_GUC(i915) || !intel_uc_is_using_guc())
+       if (!HAS_GUC(i915) || !intel_uc_is_using_guc(i915))
                guc_log_level = GUC_LOG_LEVEL_DISABLED;
        else if (IS_ENABLED(CONFIG_DRM_I915_DEBUG) ||
                 IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
@@ -112,11 +113,11 @@ static void sanitize_options_early(struct drm_i915_private *i915)
 
        DRM_DEBUG_DRIVER("enable_guc=%d (submission:%s huc:%s)\n",
                         i915_modparams.enable_guc,
-                        yesno(intel_uc_is_using_guc_submission()),
-                        yesno(intel_uc_is_using_huc()));
+                        yesno(intel_uc_is_using_guc_submission(i915)),
+                        yesno(intel_uc_is_using_huc(i915)));
 
        /* Verify GuC firmware availability */
-       if (intel_uc_is_using_guc() && !intel_uc_fw_is_selected(guc_fw)) {
+       if (intel_uc_is_using_guc(i915) && !intel_uc_fw_is_selected(guc_fw)) {
                DRM_WARN("Incompatible option detected: %s=%d, %s!\n",
                         "enable_guc", i915_modparams.enable_guc,
                         !HAS_GUC(i915) ? "no GuC hardware" :
@@ -124,7 +125,7 @@ static void sanitize_options_early(struct drm_i915_private *i915)
        }
 
        /* Verify HuC firmware availability */
-       if (intel_uc_is_using_huc() && !intel_uc_fw_is_selected(huc_fw)) {
+       if (intel_uc_is_using_huc(i915) && !intel_uc_fw_is_selected(huc_fw)) {
                DRM_WARN("Incompatible option detected: %s=%d, %s!\n",
                         "enable_guc", i915_modparams.enable_guc,
                         !HAS_HUC(i915) ? "no HuC hardware" :
@@ -136,7 +137,7 @@ static void sanitize_options_early(struct drm_i915_private *i915)
                i915_modparams.guc_log_level =
                        __get_default_guc_log_level(i915);
 
-       if (i915_modparams.guc_log_level > 0 && !intel_uc_is_using_guc()) {
+       if (i915_modparams.guc_log_level > 0 && !intel_uc_is_using_guc(i915)) {
                DRM_WARN("Incompatible option detected: %s=%d, %s!\n",
                         "guc_log_level", i915_modparams.guc_log_level,
                         !HAS_GUC(i915) ? "no GuC hardware" :
@@ -354,7 +355,7 @@ int intel_uc_init_hw(struct drm_i915_private *i915)
 
        /* WaEnableuKernelHeaderValidFix:skl */
        /* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */
-       if (IS_GEN9(i915))
+       if (IS_GEN(i915, 9))
                attempts = 3;
        else
                attempts = 1;
index 25d73ada74ae455fed80d2699b69fcb4978adae6..870faf9011b979c4d450146d241e1c8a2f1dce56 100644 (file)
@@ -41,19 +41,19 @@ void intel_uc_fini(struct drm_i915_private *dev_priv);
 int intel_uc_suspend(struct drm_i915_private *dev_priv);
 int intel_uc_resume(struct drm_i915_private *dev_priv);
 
-static inline bool intel_uc_is_using_guc(void)
+static inline bool intel_uc_is_using_guc(struct drm_i915_private *i915)
 {
        GEM_BUG_ON(i915_modparams.enable_guc < 0);
        return i915_modparams.enable_guc > 0;
 }
 
-static inline bool intel_uc_is_using_guc_submission(void)
+static inline bool intel_uc_is_using_guc_submission(struct drm_i915_private *i915)
 {
        GEM_BUG_ON(i915_modparams.enable_guc < 0);
        return i915_modparams.enable_guc & ENABLE_GUC_SUBMISSION;
 }
 
-static inline bool intel_uc_is_using_huc(void)
+static inline bool intel_uc_is_using_huc(struct drm_i915_private *i915)
 {
        GEM_BUG_ON(i915_modparams.enable_guc < 0);
        return i915_modparams.enable_guc & ENABLE_GUC_LOAD_HUC;
index fd496416087c491bfaeffd94caa131707cd28f07..becf05ebae4d3597fe021e0a7b706ba3fc2cd10e 100644 (file)
@@ -46,12 +46,17 @@ void intel_uc_fw_fetch(struct drm_i915_private *dev_priv,
        size_t size;
        int err;
 
+       if (!uc_fw->path) {
+               dev_info(dev_priv->drm.dev,
+                        "%s: No firmware was defined for %s!\n",
+                        intel_uc_fw_type_repr(uc_fw->type),
+                        intel_platform_name(INTEL_INFO(dev_priv)->platform));
+               return;
+       }
+
        DRM_DEBUG_DRIVER("%s fw fetch %s\n",
                         intel_uc_fw_type_repr(uc_fw->type), uc_fw->path);
 
-       if (!uc_fw->path)
-               return;
-
        uc_fw->fetch_status = INTEL_UC_FIRMWARE_PENDING;
        DRM_DEBUG_DRIVER("%s fw fetch %s\n",
                         intel_uc_fw_type_repr(uc_fw->type),
index 9289515108c3182a6b0aa363639a631eed97e7a0..e88f0252d77e74c19b1f8c8cf257dd3ac80cac00 100644 (file)
@@ -528,7 +528,7 @@ check_for_unclaimed_mmio(struct drm_i915_private *dev_priv)
        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                ret |= vlv_check_for_unclaimed_mmio(dev_priv);
 
-       if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv))
+       if (IS_GEN_RANGE(dev_priv, 6, 7))
                ret |= gen6_check_for_fifo_debug(dev_priv);
 
        return ret;
@@ -556,7 +556,7 @@ static void __intel_uncore_early_sanitize(struct drm_i915_private *dev_priv,
                dev_priv->uncore.funcs.force_wake_get(dev_priv,
                                                      restore_forcewake);
 
-               if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv))
+               if (IS_GEN_RANGE(dev_priv, 6, 7))
                        dev_priv->uncore.fifo_count =
                                fifo_free_entries(dev_priv);
                spin_unlock_irq(&dev_priv->uncore.lock);
@@ -1398,7 +1398,7 @@ static void intel_uncore_fw_domains_init(struct drm_i915_private *dev_priv)
        if (INTEL_GEN(dev_priv) <= 5 || intel_vgpu_active(dev_priv))
                return;
 
-       if (IS_GEN6(dev_priv)) {
+       if (IS_GEN(dev_priv, 6)) {
                dev_priv->uncore.fw_reset = 0;
                dev_priv->uncore.fw_set = FORCEWAKE_KERNEL;
                dev_priv->uncore.fw_clear = 0;
@@ -1437,7 +1437,7 @@ static void intel_uncore_fw_domains_init(struct drm_i915_private *dev_priv)
                                       FORCEWAKE_MEDIA_VEBOX_GEN11(i),
                                       FORCEWAKE_ACK_MEDIA_VEBOX_GEN11(i));
                }
-       } else if (IS_GEN10(dev_priv) || IS_GEN9(dev_priv)) {
+       } else if (IS_GEN_RANGE(dev_priv, 9, 10)) {
                dev_priv->uncore.funcs.force_wake_get =
                        fw_domains_get_with_fallback;
                dev_priv->uncore.funcs.force_wake_put = fw_domains_put;
@@ -1503,7 +1503,7 @@ static void intel_uncore_fw_domains_init(struct drm_i915_private *dev_priv)
                        fw_domain_init(dev_priv, FW_DOMAIN_ID_RENDER,
                                       FORCEWAKE, FORCEWAKE_ACK);
                }
-       } else if (IS_GEN6(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 6)) {
                dev_priv->uncore.funcs.force_wake_get =
                        fw_domains_get_with_thread_status;
                dev_priv->uncore.funcs.force_wake_put = fw_domains_put;
@@ -1567,13 +1567,13 @@ void intel_uncore_init(struct drm_i915_private *dev_priv)
        dev_priv->uncore.pmic_bus_access_nb.notifier_call =
                i915_pmic_bus_access_notifier;
 
-       if (IS_GEN(dev_priv, 2, 4) || intel_vgpu_active(dev_priv)) {
+       if (IS_GEN_RANGE(dev_priv, 2, 4) || intel_vgpu_active(dev_priv)) {
                ASSIGN_WRITE_MMIO_VFUNCS(dev_priv, gen2);
                ASSIGN_READ_MMIO_VFUNCS(dev_priv, gen2);
-       } else if (IS_GEN5(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 5)) {
                ASSIGN_WRITE_MMIO_VFUNCS(dev_priv, gen5);
                ASSIGN_READ_MMIO_VFUNCS(dev_priv, gen5);
-       } else if (IS_GEN(dev_priv, 6, 7)) {
+       } else if (IS_GEN_RANGE(dev_priv, 6, 7)) {
                ASSIGN_WRITE_MMIO_VFUNCS(dev_priv, gen6);
 
                if (IS_VALLEYVIEW(dev_priv)) {
@@ -1582,7 +1582,7 @@ void intel_uncore_init(struct drm_i915_private *dev_priv)
                } else {
                        ASSIGN_READ_MMIO_VFUNCS(dev_priv, gen6);
                }
-       } else if (IS_GEN8(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 8)) {
                if (IS_CHERRYVIEW(dev_priv)) {
                        ASSIGN_FW_DOMAINS_TABLE(__chv_fw_ranges);
                        ASSIGN_WRITE_MMIO_VFUNCS(dev_priv, fwtable);
@@ -1592,7 +1592,7 @@ void intel_uncore_init(struct drm_i915_private *dev_priv)
                        ASSIGN_WRITE_MMIO_VFUNCS(dev_priv, gen8);
                        ASSIGN_READ_MMIO_VFUNCS(dev_priv, gen6);
                }
-       } else if (IS_GEN(dev_priv, 9, 10)) {
+       } else if (IS_GEN_RANGE(dev_priv, 9, 10)) {
                ASSIGN_FW_DOMAINS_TABLE(__gen9_fw_ranges);
                ASSIGN_WRITE_MMIO_VFUNCS(dev_priv, fwtable);
                ASSIGN_READ_MMIO_VFUNCS(dev_priv, fwtable);
@@ -1670,6 +1670,7 @@ int i915_reg_read_ioctl(struct drm_device *dev,
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct drm_i915_reg_read *reg = data;
        struct reg_whitelist const *entry;
+       intel_wakeref_t wakeref;
        unsigned int flags;
        int remain;
        int ret = 0;
@@ -1695,286 +1696,25 @@ int i915_reg_read_ioctl(struct drm_device *dev,
 
        flags = reg->offset & (entry->size - 1);
 
-       intel_runtime_pm_get(dev_priv);
-       if (entry->size == 8 && flags == I915_REG_READ_8B_WA)
-               reg->val = I915_READ64_2x32(entry->offset_ldw,
-                                           entry->offset_udw);
-       else if (entry->size == 8 && flags == 0)
-               reg->val = I915_READ64(entry->offset_ldw);
-       else if (entry->size == 4 && flags == 0)
-               reg->val = I915_READ(entry->offset_ldw);
-       else if (entry->size == 2 && flags == 0)
-               reg->val = I915_READ16(entry->offset_ldw);
-       else if (entry->size == 1 && flags == 0)
-               reg->val = I915_READ8(entry->offset_ldw);
-       else
-               ret = -EINVAL;
-       intel_runtime_pm_put(dev_priv);
-
-       return ret;
-}
-
-static void gen3_stop_engine(struct intel_engine_cs *engine)
-{
-       struct drm_i915_private *dev_priv = engine->i915;
-       const u32 base = engine->mmio_base;
-
-       if (intel_engine_stop_cs(engine))
-               DRM_DEBUG_DRIVER("%s: timed out on STOP_RING\n", engine->name);
-
-       I915_WRITE_FW(RING_HEAD(base), I915_READ_FW(RING_TAIL(base)));
-       POSTING_READ_FW(RING_HEAD(base)); /* paranoia */
-
-       I915_WRITE_FW(RING_HEAD(base), 0);
-       I915_WRITE_FW(RING_TAIL(base), 0);
-       POSTING_READ_FW(RING_TAIL(base));
-
-       /* The ring must be empty before it is disabled */
-       I915_WRITE_FW(RING_CTL(base), 0);
-
-       /* Check acts as a post */
-       if (I915_READ_FW(RING_HEAD(base)) != 0)
-               DRM_DEBUG_DRIVER("%s: ring head not parked\n",
-                                engine->name);
-}
-
-static void i915_stop_engines(struct drm_i915_private *dev_priv,
-                             unsigned int engine_mask)
-{
-       struct intel_engine_cs *engine;
-       enum intel_engine_id id;
-
-       if (INTEL_GEN(dev_priv) < 3)
-               return;
-
-       for_each_engine_masked(engine, dev_priv, engine_mask, id)
-               gen3_stop_engine(engine);
-}
-
-static bool i915_in_reset(struct pci_dev *pdev)
-{
-       u8 gdrst;
-
-       pci_read_config_byte(pdev, I915_GDRST, &gdrst);
-       return gdrst & GRDOM_RESET_STATUS;
-}
-
-static int i915_do_reset(struct drm_i915_private *dev_priv,
-                        unsigned int engine_mask,
-                        unsigned int retry)
-{
-       struct pci_dev *pdev = dev_priv->drm.pdev;
-       int err;
-
-       /* Assert reset for at least 20 usec, and wait for acknowledgement. */
-       pci_write_config_byte(pdev, I915_GDRST, GRDOM_RESET_ENABLE);
-       usleep_range(50, 200);
-       err = wait_for(i915_in_reset(pdev), 500);
-
-       /* Clear the reset request. */
-       pci_write_config_byte(pdev, I915_GDRST, 0);
-       usleep_range(50, 200);
-       if (!err)
-               err = wait_for(!i915_in_reset(pdev), 500);
-
-       return err;
-}
-
-static bool g4x_reset_complete(struct pci_dev *pdev)
-{
-       u8 gdrst;
-
-       pci_read_config_byte(pdev, I915_GDRST, &gdrst);
-       return (gdrst & GRDOM_RESET_ENABLE) == 0;
-}
-
-static int g33_do_reset(struct drm_i915_private *dev_priv,
-                       unsigned int engine_mask,
-                       unsigned int retry)
-{
-       struct pci_dev *pdev = dev_priv->drm.pdev;
-
-       pci_write_config_byte(pdev, I915_GDRST, GRDOM_RESET_ENABLE);
-       return wait_for(g4x_reset_complete(pdev), 500);
-}
-
-static int g4x_do_reset(struct drm_i915_private *dev_priv,
-                       unsigned int engine_mask,
-                       unsigned int retry)
-{
-       struct pci_dev *pdev = dev_priv->drm.pdev;
-       int ret;
-
-       /* WaVcpClkGateDisableForMediaReset:ctg,elk */
-       I915_WRITE(VDECCLK_GATE_D,
-                  I915_READ(VDECCLK_GATE_D) | VCP_UNIT_CLOCK_GATE_DISABLE);
-       POSTING_READ(VDECCLK_GATE_D);
-
-       pci_write_config_byte(pdev, I915_GDRST,
-                             GRDOM_MEDIA | GRDOM_RESET_ENABLE);
-       ret =  wait_for(g4x_reset_complete(pdev), 500);
-       if (ret) {
-               DRM_DEBUG_DRIVER("Wait for media reset failed\n");
-               goto out;
-       }
-
-       pci_write_config_byte(pdev, I915_GDRST,
-                             GRDOM_RENDER | GRDOM_RESET_ENABLE);
-       ret =  wait_for(g4x_reset_complete(pdev), 500);
-       if (ret) {
-               DRM_DEBUG_DRIVER("Wait for render reset failed\n");
-               goto out;
-       }
-
-out:
-       pci_write_config_byte(pdev, I915_GDRST, 0);
-
-       I915_WRITE(VDECCLK_GATE_D,
-                  I915_READ(VDECCLK_GATE_D) & ~VCP_UNIT_CLOCK_GATE_DISABLE);
-       POSTING_READ(VDECCLK_GATE_D);
-
-       return ret;
-}
-
-static int ironlake_do_reset(struct drm_i915_private *dev_priv,
-                            unsigned int engine_mask,
-                            unsigned int retry)
-{
-       int ret;
-
-       I915_WRITE(ILK_GDSR, ILK_GRDOM_RENDER | ILK_GRDOM_RESET_ENABLE);
-       ret = intel_wait_for_register(dev_priv,
-                                     ILK_GDSR, ILK_GRDOM_RESET_ENABLE, 0,
-                                     500);
-       if (ret) {
-               DRM_DEBUG_DRIVER("Wait for render reset failed\n");
-               goto out;
-       }
-
-       I915_WRITE(ILK_GDSR, ILK_GRDOM_MEDIA | ILK_GRDOM_RESET_ENABLE);
-       ret = intel_wait_for_register(dev_priv,
-                                     ILK_GDSR, ILK_GRDOM_RESET_ENABLE, 0,
-                                     500);
-       if (ret) {
-               DRM_DEBUG_DRIVER("Wait for media reset failed\n");
-               goto out;
+       with_intel_runtime_pm(dev_priv, wakeref) {
+               if (entry->size == 8 && flags == I915_REG_READ_8B_WA)
+                       reg->val = I915_READ64_2x32(entry->offset_ldw,
+                                                   entry->offset_udw);
+               else if (entry->size == 8 && flags == 0)
+                       reg->val = I915_READ64(entry->offset_ldw);
+               else if (entry->size == 4 && flags == 0)
+                       reg->val = I915_READ(entry->offset_ldw);
+               else if (entry->size == 2 && flags == 0)
+                       reg->val = I915_READ16(entry->offset_ldw);
+               else if (entry->size == 1 && flags == 0)
+                       reg->val = I915_READ8(entry->offset_ldw);
+               else
+                       ret = -EINVAL;
        }
 
-out:
-       I915_WRITE(ILK_GDSR, 0);
-       POSTING_READ(ILK_GDSR);
        return ret;
 }
 
-/* Reset the hardware domains (GENX_GRDOM_*) specified by mask */
-static int gen6_hw_domain_reset(struct drm_i915_private *dev_priv,
-                               u32 hw_domain_mask)
-{
-       int err;
-
-       /* GEN6_GDRST is not in the gt power well, no need to check
-        * for fifo space for the write or forcewake the chip for
-        * the read
-        */
-       __raw_i915_write32(dev_priv, GEN6_GDRST, hw_domain_mask);
-
-       /* Wait for the device to ack the reset requests */
-       err = __intel_wait_for_register_fw(dev_priv,
-                                          GEN6_GDRST, hw_domain_mask, 0,
-                                          500, 0,
-                                          NULL);
-       if (err)
-               DRM_DEBUG_DRIVER("Wait for 0x%08x engines reset failed\n",
-                                hw_domain_mask);
-
-       return err;
-}
-
-/**
- * gen6_reset_engines - reset individual engines
- * @dev_priv: i915 device
- * @engine_mask: mask of intel_ring_flag() engines or ALL_ENGINES for full reset
- * @retry: the count of of previous attempts to reset.
- *
- * This function will reset the individual engines that are set in engine_mask.
- * If you provide ALL_ENGINES as mask, full global domain reset will be issued.
- *
- * Note: It is responsibility of the caller to handle the difference between
- * asking full domain reset versus reset for all available individual engines.
- *
- * Returns 0 on success, nonzero on error.
- */
-static int gen6_reset_engines(struct drm_i915_private *dev_priv,
-                             unsigned int engine_mask,
-                             unsigned int retry)
-{
-       struct intel_engine_cs *engine;
-       const u32 hw_engine_mask[I915_NUM_ENGINES] = {
-               [RCS] = GEN6_GRDOM_RENDER,
-               [BCS] = GEN6_GRDOM_BLT,
-               [VCS] = GEN6_GRDOM_MEDIA,
-               [VCS2] = GEN8_GRDOM_MEDIA2,
-               [VECS] = GEN6_GRDOM_VECS,
-       };
-       u32 hw_mask;
-
-       if (engine_mask == ALL_ENGINES) {
-               hw_mask = GEN6_GRDOM_FULL;
-       } else {
-               unsigned int tmp;
-
-               hw_mask = 0;
-               for_each_engine_masked(engine, dev_priv, engine_mask, tmp)
-                       hw_mask |= hw_engine_mask[engine->id];
-       }
-
-       return gen6_hw_domain_reset(dev_priv, hw_mask);
-}
-
-/**
- * gen11_reset_engines - reset individual engines
- * @dev_priv: i915 device
- * @engine_mask: mask of intel_ring_flag() engines or ALL_ENGINES for full reset
- *
- * This function will reset the individual engines that are set in engine_mask.
- * If you provide ALL_ENGINES as mask, full global domain reset will be issued.
- *
- * Note: It is responsibility of the caller to handle the difference between
- * asking full domain reset versus reset for all available individual engines.
- *
- * Returns 0 on success, nonzero on error.
- */
-static int gen11_reset_engines(struct drm_i915_private *dev_priv,
-                              unsigned int engine_mask)
-{
-       struct intel_engine_cs *engine;
-       const u32 hw_engine_mask[I915_NUM_ENGINES] = {
-               [RCS] = GEN11_GRDOM_RENDER,
-               [BCS] = GEN11_GRDOM_BLT,
-               [VCS] = GEN11_GRDOM_MEDIA,
-               [VCS2] = GEN11_GRDOM_MEDIA2,
-               [VCS3] = GEN11_GRDOM_MEDIA3,
-               [VCS4] = GEN11_GRDOM_MEDIA4,
-               [VECS] = GEN11_GRDOM_VECS,
-               [VECS2] = GEN11_GRDOM_VECS2,
-       };
-       u32 hw_mask;
-
-       BUILD_BUG_ON(VECS2 + 1 != I915_NUM_ENGINES);
-
-       if (engine_mask == ALL_ENGINES) {
-               hw_mask = GEN11_GRDOM_FULL;
-       } else {
-               unsigned int tmp;
-
-               hw_mask = 0;
-               for_each_engine_masked(engine, dev_priv, engine_mask, tmp)
-                       hw_mask |= hw_engine_mask[engine->id];
-       }
-
-       return gen6_hw_domain_reset(dev_priv, hw_mask);
-}
-
 /**
  * __intel_wait_for_register_fw - wait until register matches expected state
  * @dev_priv: the i915 device
@@ -2085,196 +1825,6 @@ int __intel_wait_for_register(struct drm_i915_private *dev_priv,
        return ret;
 }
 
-static int gen8_engine_reset_prepare(struct intel_engine_cs *engine)
-{
-       struct drm_i915_private *dev_priv = engine->i915;
-       int ret;
-
-       I915_WRITE_FW(RING_RESET_CTL(engine->mmio_base),
-                     _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET));
-
-       ret = __intel_wait_for_register_fw(dev_priv,
-                                          RING_RESET_CTL(engine->mmio_base),
-                                          RESET_CTL_READY_TO_RESET,
-                                          RESET_CTL_READY_TO_RESET,
-                                          700, 0,
-                                          NULL);
-       if (ret)
-               DRM_ERROR("%s: reset request timeout\n", engine->name);
-
-       return ret;
-}
-
-static void gen8_engine_reset_cancel(struct intel_engine_cs *engine)
-{
-       struct drm_i915_private *dev_priv = engine->i915;
-
-       I915_WRITE_FW(RING_RESET_CTL(engine->mmio_base),
-                     _MASKED_BIT_DISABLE(RESET_CTL_REQUEST_RESET));
-}
-
-static int reset_engines(struct drm_i915_private *i915,
-                        unsigned int engine_mask,
-                        unsigned int retry)
-{
-       if (INTEL_GEN(i915) >= 11)
-               return gen11_reset_engines(i915, engine_mask);
-       else
-               return gen6_reset_engines(i915, engine_mask, retry);
-}
-
-static int gen8_reset_engines(struct drm_i915_private *dev_priv,
-                             unsigned int engine_mask,
-                             unsigned int retry)
-{
-       struct intel_engine_cs *engine;
-       const bool reset_non_ready = retry >= 1;
-       unsigned int tmp;
-       int ret;
-
-       for_each_engine_masked(engine, dev_priv, engine_mask, tmp) {
-               ret = gen8_engine_reset_prepare(engine);
-               if (ret && !reset_non_ready)
-                       goto skip_reset;
-
-               /*
-                * If this is not the first failed attempt to prepare,
-                * we decide to proceed anyway.
-                *
-                * By doing so we risk context corruption and with
-                * some gens (kbl), possible system hang if reset
-                * happens during active bb execution.
-                *
-                * We rather take context corruption instead of
-                * failed reset with a wedged driver/gpu. And
-                * active bb execution case should be covered by
-                * i915_stop_engines we have before the reset.
-                */
-       }
-
-       ret = reset_engines(dev_priv, engine_mask, retry);
-
-skip_reset:
-       for_each_engine_masked(engine, dev_priv, engine_mask, tmp)
-               gen8_engine_reset_cancel(engine);
-
-       return ret;
-}
-
-typedef int (*reset_func)(struct drm_i915_private *,
-                         unsigned int engine_mask, unsigned int retry);
-
-static reset_func intel_get_gpu_reset(struct drm_i915_private *dev_priv)
-{
-       if (!i915_modparams.reset)
-               return NULL;
-
-       if (INTEL_GEN(dev_priv) >= 8)
-               return gen8_reset_engines;
-       else if (INTEL_GEN(dev_priv) >= 6)
-               return gen6_reset_engines;
-       else if (IS_GEN5(dev_priv))
-               return ironlake_do_reset;
-       else if (IS_G4X(dev_priv))
-               return g4x_do_reset;
-       else if (IS_G33(dev_priv) || IS_PINEVIEW(dev_priv))
-               return g33_do_reset;
-       else if (INTEL_GEN(dev_priv) >= 3)
-               return i915_do_reset;
-       else
-               return NULL;
-}
-
-int intel_gpu_reset(struct drm_i915_private *dev_priv,
-                   const unsigned int engine_mask)
-{
-       reset_func reset = intel_get_gpu_reset(dev_priv);
-       unsigned int retry;
-       int ret;
-
-       GEM_BUG_ON(!engine_mask);
-
-       /*
-        * We want to perform per-engine reset from atomic context (e.g.
-        * softirq), which imposes the constraint that we cannot sleep.
-        * However, experience suggests that spending a bit of time waiting
-        * for a reset helps in various cases, so for a full-device reset
-        * we apply the opposite rule and wait if we want to. As we should
-        * always follow up a failed per-engine reset with a full device reset,
-        * being a little faster, stricter and more error prone for the
-        * atomic case seems an acceptable compromise.
-        *
-        * Unfortunately this leads to a bimodal routine, when the goal was
-        * to have a single reset function that worked for resetting any
-        * number of engines simultaneously.
-        */
-       might_sleep_if(engine_mask == ALL_ENGINES);
-
-       /*
-        * If the power well sleeps during the reset, the reset
-        * request may be dropped and never completes (causing -EIO).
-        */
-       intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
-       for (retry = 0; retry < 3; retry++) {
-
-               /*
-                * We stop engines, otherwise we might get failed reset and a
-                * dead gpu (on elk). Also as modern gpu as kbl can suffer
-                * from system hang if batchbuffer is progressing when
-                * the reset is issued, regardless of READY_TO_RESET ack.
-                * Thus assume it is best to stop engines on all gens
-                * where we have a gpu reset.
-                *
-                * WaKBLVECSSemaphoreWaitPoll:kbl (on ALL_ENGINES)
-                *
-                * WaMediaResetMainRingCleanup:ctg,elk (presumably)
-                *
-                * FIXME: Wa for more modern gens needs to be validated
-                */
-               i915_stop_engines(dev_priv, engine_mask);
-
-               ret = -ENODEV;
-               if (reset) {
-                       ret = reset(dev_priv, engine_mask, retry);
-                       GEM_TRACE("engine_mask=%x, ret=%d, retry=%d\n",
-                                 engine_mask, ret, retry);
-               }
-               if (ret != -ETIMEDOUT || engine_mask != ALL_ENGINES)
-                       break;
-
-               cond_resched();
-       }
-       intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
-
-       return ret;
-}
-
-bool intel_has_gpu_reset(struct drm_i915_private *dev_priv)
-{
-       return intel_get_gpu_reset(dev_priv) != NULL;
-}
-
-bool intel_has_reset_engine(struct drm_i915_private *dev_priv)
-{
-       return (dev_priv->info.has_reset_engine &&
-               i915_modparams.reset >= 2);
-}
-
-int intel_reset_guc(struct drm_i915_private *dev_priv)
-{
-       u32 guc_domain = INTEL_GEN(dev_priv) >= 11 ? GEN11_GRDOM_GUC :
-                                                    GEN9_GRDOM_GUC;
-       int ret;
-
-       GEM_BUG_ON(!HAS_GUC(dev_priv));
-
-       intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
-       ret = gen6_hw_domain_reset(dev_priv, guc_domain);
-       intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
-
-       return ret;
-}
-
 bool intel_uncore_unclaimed_mmio(struct drm_i915_private *dev_priv)
 {
        return check_for_unclaimed_mmio(dev_priv);
@@ -2321,7 +1871,7 @@ intel_uncore_forcewake_for_read(struct drm_i915_private *dev_priv,
        } else if (INTEL_GEN(dev_priv) >= 6) {
                fw_domains = __gen6_reg_read_fw_domains(offset);
        } else {
-               WARN_ON(!IS_GEN(dev_priv, 2, 5));
+               WARN_ON(!IS_GEN_RANGE(dev_priv, 2, 5));
                fw_domains = 0;
        }
 
@@ -2341,12 +1891,12 @@ intel_uncore_forcewake_for_write(struct drm_i915_private *dev_priv,
                fw_domains = __gen11_fwtable_reg_write_fw_domains(offset);
        } else if (HAS_FWTABLE(dev_priv) && !IS_VALLEYVIEW(dev_priv)) {
                fw_domains = __fwtable_reg_write_fw_domains(offset);
-       } else if (IS_GEN8(dev_priv)) {
+       } else if (IS_GEN(dev_priv, 8)) {
                fw_domains = __gen8_reg_write_fw_domains(offset);
-       } else if (IS_GEN(dev_priv, 6, 7)) {
+       } else if (IS_GEN_RANGE(dev_priv, 6, 7)) {
                fw_domains = FORCEWAKE_RENDER;
        } else {
-               WARN_ON(!IS_GEN(dev_priv, 2, 5));
+               WARN_ON(!IS_GEN_RANGE(dev_priv, 2, 5));
                fw_domains = 0;
        }
 
index c56ba0e04044aea9bf68ecdd9fabfa4453b3bf64..23abf03736e7262cba70668e7eba9217fbeb3a75 100644 (file)
@@ -6,7 +6,6 @@
  *         Manasi Navare <manasi.d.navare@intel.com>
  */
 
-#include <drm/drmP.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 #include "intel_drv.h"
@@ -1083,6 +1082,6 @@ void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state)
        I915_WRITE(dss_ctl2_reg, dss_ctl2_val);
 
        /* Disable Power wells for VDSC/joining */
-       intel_display_power_put(dev_priv,
-                               intel_dsc_power_domain(old_crtc_state));
+       intel_display_power_put_unchecked(dev_priv,
+                                         intel_dsc_power_domain(old_crtc_state));
 }
index 92cb82dd0c0731fdb09c3d51a66b089768b1c7b0..f82a415ea2ba383397905cfccea8d28efa6add3b 100644 (file)
@@ -130,11 +130,11 @@ static inline int check_hw_restriction(struct drm_i915_private *i915,
 {
        int err = 0;
 
-       if (IS_GEN9(i915))
+       if (IS_GEN(i915, 9))
                err = gen9_check_dword_gap(guc_wopcm_base, guc_wopcm_size);
 
        if (!err &&
-           (IS_GEN9(i915) || IS_CNL_REVID(i915, CNL_REVID_A0, CNL_REVID_A0)))
+           (IS_GEN(i915, 9) || IS_CNL_REVID(i915, CNL_REVID_A0, CNL_REVID_A0)))
                err = gen9_check_huc_fw_fits(guc_wopcm_size, huc_fw_size);
 
        return err;
@@ -163,7 +163,7 @@ int intel_wopcm_init(struct intel_wopcm *wopcm)
        u32 guc_wopcm_rsvd;
        int err;
 
-       if (!USES_GUC(dev_priv))
+       if (!USES_GUC(i915))
                return 0;
 
        GEM_BUG_ON(!wopcm->size);
index 4f41e326f3f3fd77e0a8d519e1f33933a5a0d92b..3210ad4e08f7bf9e8cb52f865e97ca0f555c6019 100644 (file)
@@ -366,7 +366,7 @@ static void skl_tune_iz_hashing(struct intel_engine_cs *engine)
                 * Only consider slices where one, and only one, subslice has 7
                 * EUs
                 */
-               if (!is_power_of_2(INTEL_INFO(i915)->sseu.subslice_7eu[i]))
+               if (!is_power_of_2(RUNTIME_INFO(i915)->sseu.subslice_7eu[i]))
                        continue;
 
                /*
@@ -375,7 +375,7 @@ static void skl_tune_iz_hashing(struct intel_engine_cs *engine)
                 *
                 * ->    0 <= ss <= 3;
                 */
-               ss = ffs(INTEL_INFO(i915)->sseu.subslice_7eu[i]) - 1;
+               ss = ffs(RUNTIME_INFO(i915)->sseu.subslice_7eu[i]) - 1;
                vals[i] = 3 - ss;
        }
 
@@ -639,10 +639,9 @@ wa_write_or(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
        wa_write_masked_or(wal, reg, val, val);
 }
 
-static void gen9_gt_workarounds_init(struct drm_i915_private *i915)
+static void
+gen9_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
 {
-       struct i915_wa_list *wal = &i915->gt_wa_list;
-
        /* WaDisableKillLogic:bxt,skl,kbl */
        if (!IS_COFFEELAKE(i915))
                wa_write_or(wal,
@@ -666,11 +665,10 @@ static void gen9_gt_workarounds_init(struct drm_i915_private *i915)
                    BDW_DISABLE_HDC_INVALIDATION);
 }
 
-static void skl_gt_workarounds_init(struct drm_i915_private *i915)
+static void
+skl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
 {
-       struct i915_wa_list *wal = &i915->gt_wa_list;
-
-       gen9_gt_workarounds_init(i915);
+       gen9_gt_workarounds_init(i915, wal);
 
        /* WaDisableGafsUnitClkGating:skl */
        wa_write_or(wal,
@@ -684,11 +682,10 @@ static void skl_gt_workarounds_init(struct drm_i915_private *i915)
                            GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
 }
 
-static void bxt_gt_workarounds_init(struct drm_i915_private *i915)
+static void
+bxt_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
 {
-       struct i915_wa_list *wal = &i915->gt_wa_list;
-
-       gen9_gt_workarounds_init(i915);
+       gen9_gt_workarounds_init(i915, wal);
 
        /* WaInPlaceDecompressionHang:bxt */
        wa_write_or(wal,
@@ -696,11 +693,10 @@ static void bxt_gt_workarounds_init(struct drm_i915_private *i915)
                    GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
 }
 
-static void kbl_gt_workarounds_init(struct drm_i915_private *i915)
+static void
+kbl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
 {
-       struct i915_wa_list *wal = &i915->gt_wa_list;
-
-       gen9_gt_workarounds_init(i915);
+       gen9_gt_workarounds_init(i915, wal);
 
        /* WaDisableDynamicCreditSharing:kbl */
        if (IS_KBL_REVID(i915, 0, KBL_REVID_B0))
@@ -719,16 +715,16 @@ static void kbl_gt_workarounds_init(struct drm_i915_private *i915)
                    GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
 }
 
-static void glk_gt_workarounds_init(struct drm_i915_private *i915)
+static void
+glk_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
 {
-       gen9_gt_workarounds_init(i915);
+       gen9_gt_workarounds_init(i915, wal);
 }
 
-static void cfl_gt_workarounds_init(struct drm_i915_private *i915)
+static void
+cfl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
 {
-       struct i915_wa_list *wal = &i915->gt_wa_list;
-
-       gen9_gt_workarounds_init(i915);
+       gen9_gt_workarounds_init(i915, wal);
 
        /* WaDisableGafsUnitClkGating:cfl */
        wa_write_or(wal,
@@ -741,10 +737,10 @@ static void cfl_gt_workarounds_init(struct drm_i915_private *i915)
                    GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
 }
 
-static void wa_init_mcr(struct drm_i915_private *dev_priv)
+static void
+wa_init_mcr(struct drm_i915_private *dev_priv, struct i915_wa_list *wal)
 {
-       const struct sseu_dev_info *sseu = &(INTEL_INFO(dev_priv)->sseu);
-       struct i915_wa_list *wal = &dev_priv->gt_wa_list;
+       const struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu;
        u32 mcr_slice_subslice_mask;
 
        /*
@@ -804,11 +800,10 @@ static void wa_init_mcr(struct drm_i915_private *dev_priv)
                           intel_calculate_mcr_s_ss_select(dev_priv));
 }
 
-static void cnl_gt_workarounds_init(struct drm_i915_private *i915)
+static void
+cnl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
 {
-       struct i915_wa_list *wal = &i915->gt_wa_list;
-
-       wa_init_mcr(i915);
+       wa_init_mcr(i915, wal);
 
        /* WaDisableI2mCycleOnWRPort:cnl (pre-prod) */
        if (IS_CNL_REVID(i915, CNL_REVID_B0, CNL_REVID_B0))
@@ -822,11 +817,10 @@ static void cnl_gt_workarounds_init(struct drm_i915_private *i915)
                    GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
 }
 
-static void icl_gt_workarounds_init(struct drm_i915_private *i915)
+static void
+icl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
 {
-       struct i915_wa_list *wal = &i915->gt_wa_list;
-
-       wa_init_mcr(i915);
+       wa_init_mcr(i915, wal);
 
        /* WaInPlaceDecompressionHang:icl */
        wa_write_or(wal,
@@ -879,12 +873,9 @@ static void icl_gt_workarounds_init(struct drm_i915_private *i915)
                    GAMT_CHKN_DISABLE_L3_COH_PIPE);
 }
 
-void intel_gt_init_workarounds(struct drm_i915_private *i915)
+static void
+gt_init_workarounds(struct drm_i915_private *i915, struct i915_wa_list *wal)
 {
-       struct i915_wa_list *wal = &i915->gt_wa_list;
-
-       wa_init_start(wal, "GT");
-
        if (INTEL_GEN(i915) < 8)
                return;
        else if (IS_BROADWELL(i915))
@@ -892,22 +883,29 @@ void intel_gt_init_workarounds(struct drm_i915_private *i915)
        else if (IS_CHERRYVIEW(i915))
                return;
        else if (IS_SKYLAKE(i915))
-               skl_gt_workarounds_init(i915);
+               skl_gt_workarounds_init(i915, wal);
        else if (IS_BROXTON(i915))
-               bxt_gt_workarounds_init(i915);
+               bxt_gt_workarounds_init(i915, wal);
        else if (IS_KABYLAKE(i915))
-               kbl_gt_workarounds_init(i915);
+               kbl_gt_workarounds_init(i915, wal);
        else if (IS_GEMINILAKE(i915))
-               glk_gt_workarounds_init(i915);
+               glk_gt_workarounds_init(i915, wal);
        else if (IS_COFFEELAKE(i915))
-               cfl_gt_workarounds_init(i915);
+               cfl_gt_workarounds_init(i915, wal);
        else if (IS_CANNONLAKE(i915))
-               cnl_gt_workarounds_init(i915);
+               cnl_gt_workarounds_init(i915, wal);
        else if (IS_ICELAKE(i915))
-               icl_gt_workarounds_init(i915);
+               icl_gt_workarounds_init(i915, wal);
        else
                MISSING_CASE(INTEL_GEN(i915));
+}
 
+void intel_gt_init_workarounds(struct drm_i915_private *i915)
+{
+       struct i915_wa_list *wal = &i915->gt_wa_list;
+
+       wa_init_start(wal, "GT");
+       gt_init_workarounds(i915, wal);
        wa_init_finish(wal);
 }
 
@@ -955,8 +953,6 @@ wa_list_apply(struct drm_i915_private *dev_priv, const struct i915_wa_list *wal)
 
        intel_uncore_forcewake_put__locked(dev_priv, fw);
        spin_unlock_irqrestore(&dev_priv->uncore.lock, flags);
-
-       DRM_DEBUG_DRIVER("Applied %u %s workarounds\n", wal->count, wal->name);
 }
 
 void intel_gt_apply_workarounds(struct drm_i915_private *dev_priv)
@@ -1126,14 +1122,12 @@ void intel_engine_apply_whitelist(struct intel_engine_cs *engine)
        for (; i < RING_MAX_NONPRIV_SLOTS; i++)
                I915_WRITE(RING_FORCE_TO_NONPRIV(base, i),
                           i915_mmio_reg_offset(RING_NOPID(base)));
-
-       DRM_DEBUG_DRIVER("Applied %u %s workarounds\n", wal->count, wal->name);
 }
 
-static void rcs_engine_wa_init(struct intel_engine_cs *engine)
+static void
+rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
 {
        struct drm_i915_private *i915 = engine->i915;
-       struct i915_wa_list *wal = &engine->wa_list;
 
        if (IS_ICELAKE(i915)) {
                /* This is not an Wa. Enable for better image quality */
@@ -1190,7 +1184,7 @@ static void rcs_engine_wa_init(struct intel_engine_cs *engine)
                                    GEN7_DISABLE_SAMPLER_PREFETCH);
        }
 
-       if (IS_GEN9(i915) || IS_CANNONLAKE(i915)) {
+       if (IS_GEN(i915, 9) || IS_CANNONLAKE(i915)) {
                /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl,cfl,cnl */
                wa_masked_en(wal,
                             GEN7_FF_SLICE_CS_CHICKEN1,
@@ -1211,7 +1205,7 @@ static void rcs_engine_wa_init(struct intel_engine_cs *engine)
                             GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE);
        }
 
-       if (IS_GEN9(i915)) {
+       if (IS_GEN(i915, 9)) {
                /* WaContextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl,glk,cfl */
                wa_masked_en(wal,
                             GEN9_CSFE_CHICKEN1_RCS,
@@ -1237,10 +1231,10 @@ static void rcs_engine_wa_init(struct intel_engine_cs *engine)
        }
 }
 
-static void xcs_engine_wa_init(struct intel_engine_cs *engine)
+static void
+xcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
 {
        struct drm_i915_private *i915 = engine->i915;
-       struct i915_wa_list *wal = &engine->wa_list;
 
        /* WaKBLVECSSemaphoreWaitPoll:kbl */
        if (IS_KBL_REVID(i915, KBL_REVID_A0, KBL_REVID_E0)) {
@@ -1250,6 +1244,18 @@ static void xcs_engine_wa_init(struct intel_engine_cs *engine)
        }
 }
 
+static void
+engine_init_workarounds(struct intel_engine_cs *engine, struct i915_wa_list *wal)
+{
+       if (I915_SELFTEST_ONLY(INTEL_GEN(engine->i915) < 8))
+               return;
+
+       if (engine->id == RCS)
+               rcs_engine_wa_init(engine, wal);
+       else
+               xcs_engine_wa_init(engine, wal);
+}
+
 void intel_engine_init_workarounds(struct intel_engine_cs *engine)
 {
        struct i915_wa_list *wal = &engine->wa_list;
@@ -1258,12 +1264,7 @@ void intel_engine_init_workarounds(struct intel_engine_cs *engine)
                return;
 
        wa_init_start(wal, engine->name);
-
-       if (engine->id == RCS)
-               rcs_engine_wa_init(engine);
-       else
-               xcs_engine_wa_init(engine);
-
+       engine_init_workarounds(engine, wal);
        wa_init_finish(wal);
 }
 
@@ -1273,11 +1274,5 @@ void intel_engine_apply_workarounds(struct intel_engine_cs *engine)
 }
 
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
-static bool intel_engine_verify_workarounds(struct intel_engine_cs *engine,
-                                           const char *from)
-{
-       return wa_list_verify(engine->i915, &engine->wa_list, from);
-}
-
 #include "selftests/intel_workarounds.c"
 #endif
index 26c065c8d2c0a7e3b550dc96fa94ee611daae296..a9a2fa35876fe5537db2e4693334097aae4f7def 100644 (file)
@@ -972,7 +972,6 @@ static int gpu_write(struct i915_vma *vma,
 {
        struct i915_request *rq;
        struct i915_vma *batch;
-       int flags = 0;
        int err;
 
        GEM_BUG_ON(!intel_engine_can_store_dword(engine));
@@ -981,14 +980,14 @@ static int gpu_write(struct i915_vma *vma,
        if (err)
                return err;
 
-       rq = i915_request_alloc(engine, ctx);
-       if (IS_ERR(rq))
-               return PTR_ERR(rq);
-
        batch = gpu_write_dw(vma, dword * sizeof(u32), value);
-       if (IS_ERR(batch)) {
-               err = PTR_ERR(batch);
-               goto err_request;
+       if (IS_ERR(batch))
+               return PTR_ERR(batch);
+
+       rq = i915_request_alloc(engine, ctx);
+       if (IS_ERR(rq)) {
+               err = PTR_ERR(rq);
+               goto err_batch;
        }
 
        err = i915_vma_move_to_active(batch, rq, 0);
@@ -996,21 +995,21 @@ static int gpu_write(struct i915_vma *vma,
                goto err_request;
 
        i915_gem_object_set_active_reference(batch->obj);
-       i915_vma_unpin(batch);
-       i915_vma_close(batch);
 
-       err = engine->emit_bb_start(rq,
-                                   batch->node.start, batch->node.size,
-                                   flags);
+       err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
        if (err)
                goto err_request;
 
-       err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
+       err = engine->emit_bb_start(rq,
+                                   batch->node.start, batch->node.size,
+                                   0);
+err_request:
        if (err)
                i915_request_skip(rq, err);
-
-err_request:
        i915_request_add(rq);
+err_batch:
+       i915_vma_unpin(batch);
+       i915_vma_close(batch);
 
        return err;
 }
@@ -1450,7 +1449,7 @@ static int igt_ppgtt_pin_update(void *arg)
         * huge-gtt-pages.
         */
 
-       if (!HAS_FULL_48BIT_PPGTT(dev_priv)) {
+       if (!ppgtt || !i915_vm_is_48bit(&ppgtt->vm)) {
                pr_info("48b PPGTT not supported, skipping\n");
                return 0;
        }
@@ -1703,7 +1702,6 @@ int i915_gem_huge_page_mock_selftests(void)
        };
        struct drm_i915_private *dev_priv;
        struct i915_hw_ppgtt *ppgtt;
-       struct pci_dev *pdev;
        int err;
 
        dev_priv = mock_gem_device();
@@ -1713,9 +1711,6 @@ int i915_gem_huge_page_mock_selftests(void)
        /* Pretend to be a device which supports the 48b PPGTT */
        mkwrite_device_info(dev_priv)->ppgtt = INTEL_PPGTT_FULL_4LVL;
 
-       pdev = dev_priv->drm.pdev;
-       dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(39));
-
        mutex_lock(&dev_priv->drm.struct_mutex);
        ppgtt = i915_ppgtt_create(dev_priv, ERR_PTR(-ENODEV));
        if (IS_ERR(ppgtt)) {
@@ -1761,6 +1756,7 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *dev_priv)
        };
        struct drm_file *file;
        struct i915_gem_context *ctx;
+       intel_wakeref_t wakeref;
        int err;
 
        if (!HAS_PPGTT(dev_priv)) {
@@ -1776,7 +1772,7 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *dev_priv)
                return PTR_ERR(file);
 
        mutex_lock(&dev_priv->drm.struct_mutex);
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
        ctx = live_context(dev_priv, file);
        if (IS_ERR(ctx)) {
@@ -1790,7 +1786,7 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *dev_priv)
        err = i915_subtests(tests, ctx);
 
 out_unlock:
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
        mutex_unlock(&dev_priv->drm.struct_mutex);
 
        mock_file_free(dev_priv, file);
index d0aa19d176536c0f2d4f273be4c113d472de89c5..e77b7ed449ae8ec5380ffbcd18184056c6757efa 100644 (file)
@@ -16,9 +16,10 @@ static int switch_to_context(struct drm_i915_private *i915,
 {
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
+       intel_wakeref_t wakeref;
        int err = 0;
 
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
        for_each_engine(engine, i915, id) {
                struct i915_request *rq;
@@ -32,7 +33,7 @@ static int switch_to_context(struct drm_i915_private *i915,
                i915_request_add(rq);
        }
 
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
 
        return err;
 }
@@ -65,7 +66,9 @@ static void trash_stolen(struct drm_i915_private *i915)
 
 static void simulate_hibernate(struct drm_i915_private *i915)
 {
-       intel_runtime_pm_get(i915);
+       intel_wakeref_t wakeref;
+
+       wakeref = intel_runtime_pm_get(i915);
 
        /*
         * As a final sting in the tail, invalidate stolen. Under a real S4,
@@ -76,7 +79,7 @@ static void simulate_hibernate(struct drm_i915_private *i915)
         */
        trash_stolen(i915);
 
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
 }
 
 static int pm_prepare(struct drm_i915_private *i915)
@@ -93,39 +96,39 @@ static int pm_prepare(struct drm_i915_private *i915)
 
 static void pm_suspend(struct drm_i915_private *i915)
 {
-       intel_runtime_pm_get(i915);
-
-       i915_gem_suspend_gtt_mappings(i915);
-       i915_gem_suspend_late(i915);
+       intel_wakeref_t wakeref;
 
-       intel_runtime_pm_put(i915);
+       with_intel_runtime_pm(i915, wakeref) {
+               i915_gem_suspend_gtt_mappings(i915);
+               i915_gem_suspend_late(i915);
+       }
 }
 
 static void pm_hibernate(struct drm_i915_private *i915)
 {
-       intel_runtime_pm_get(i915);
+       intel_wakeref_t wakeref;
 
-       i915_gem_suspend_gtt_mappings(i915);
+       with_intel_runtime_pm(i915, wakeref) {
+               i915_gem_suspend_gtt_mappings(i915);
 
-       i915_gem_freeze(i915);
-       i915_gem_freeze_late(i915);
-
-       intel_runtime_pm_put(i915);
+               i915_gem_freeze(i915);
+               i915_gem_freeze_late(i915);
+       }
 }
 
 static void pm_resume(struct drm_i915_private *i915)
 {
+       intel_wakeref_t wakeref;
+
        /*
         * Both suspend and hibernate follow the same wakeup path and assume
         * that runtime-pm just works.
         */
-       intel_runtime_pm_get(i915);
-
-       intel_engines_sanitize(i915);
-       i915_gem_sanitize(i915);
-       i915_gem_resume(i915);
-
-       intel_runtime_pm_put(i915);
+       with_intel_runtime_pm(i915, wakeref) {
+               intel_engines_sanitize(i915, false);
+               i915_gem_sanitize(i915);
+               i915_gem_resume(i915);
+       }
 }
 
 static int igt_gem_suspend(void *arg)
index f7392c1ffe755cf3011f7457fac0294e2e41201d..fd89a5a33c1a0b1719c8bbbeb354c55ec498484f 100644 (file)
@@ -279,6 +279,7 @@ static int igt_gem_coherency(void *arg)
        struct drm_i915_private *i915 = arg;
        const struct igt_coherency_mode *read, *write, *over;
        struct drm_i915_gem_object *obj;
+       intel_wakeref_t wakeref;
        unsigned long count, n;
        u32 *offsets, *values;
        int err = 0;
@@ -298,7 +299,7 @@ static int igt_gem_coherency(void *arg)
        values = offsets + ncachelines;
 
        mutex_lock(&i915->drm.struct_mutex);
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
        for (over = igt_coherency_mode; over->name; over++) {
                if (!over->set)
                        continue;
@@ -376,7 +377,7 @@ static int igt_gem_coherency(void *arg)
                }
        }
 unlock:
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
        mutex_unlock(&i915->drm.struct_mutex);
        kfree(offsets);
        return err;
index 7d82043aff1099c82a35fde7fe0bce2f4b454bcb..e2c1f0bc2abe4685c8c5b2877597ee7e8b754366 100644 (file)
@@ -27,6 +27,7 @@
 #include "../i915_selftest.h"
 #include "i915_random.h"
 #include "igt_flush_test.h"
+#include "igt_live_test.h"
 
 #include "mock_drm.h"
 #include "mock_gem_device.h"
 
 #define DW_PER_PAGE (PAGE_SIZE / sizeof(u32))
 
-struct live_test {
-       struct drm_i915_private *i915;
-       const char *func;
-       const char *name;
-
-       unsigned int reset_global;
-       unsigned int reset_engine[I915_NUM_ENGINES];
-};
-
-static int begin_live_test(struct live_test *t,
-                          struct drm_i915_private *i915,
-                          const char *func,
-                          const char *name)
-{
-       struct intel_engine_cs *engine;
-       enum intel_engine_id id;
-       int err;
-
-       t->i915 = i915;
-       t->func = func;
-       t->name = name;
-
-       err = i915_gem_wait_for_idle(i915,
-                                    I915_WAIT_LOCKED,
-                                    MAX_SCHEDULE_TIMEOUT);
-       if (err) {
-               pr_err("%s(%s): failed to idle before, with err=%d!",
-                      func, name, err);
-               return err;
-       }
-
-       i915->gpu_error.missed_irq_rings = 0;
-       t->reset_global = i915_reset_count(&i915->gpu_error);
-
-       for_each_engine(engine, i915, id)
-               t->reset_engine[id] =
-                       i915_reset_engine_count(&i915->gpu_error, engine);
-
-       return 0;
-}
-
-static int end_live_test(struct live_test *t)
-{
-       struct drm_i915_private *i915 = t->i915;
-       struct intel_engine_cs *engine;
-       enum intel_engine_id id;
-
-       if (igt_flush_test(i915, I915_WAIT_LOCKED))
-               return -EIO;
-
-       if (t->reset_global != i915_reset_count(&i915->gpu_error)) {
-               pr_err("%s(%s): GPU was reset %d times!\n",
-                      t->func, t->name,
-                      i915_reset_count(&i915->gpu_error) - t->reset_global);
-               return -EIO;
-       }
-
-       for_each_engine(engine, i915, id) {
-               if (t->reset_engine[id] ==
-                   i915_reset_engine_count(&i915->gpu_error, engine))
-                       continue;
-
-               pr_err("%s(%s): engine '%s' was reset %d times!\n",
-                      t->func, t->name, engine->name,
-                      i915_reset_engine_count(&i915->gpu_error, engine) -
-                      t->reset_engine[id]);
-               return -EIO;
-       }
-
-       if (i915->gpu_error.missed_irq_rings) {
-               pr_err("%s(%s): Missed interrupts on engines %lx\n",
-                      t->func, t->name, i915->gpu_error.missed_irq_rings);
-               return -EIO;
-       }
-
-       return 0;
-}
-
 static int live_nop_switch(void *arg)
 {
        const unsigned int nctx = 1024;
@@ -119,8 +42,9 @@ static int live_nop_switch(void *arg)
        struct intel_engine_cs *engine;
        struct i915_gem_context **ctx;
        enum intel_engine_id id;
+       intel_wakeref_t wakeref;
+       struct igt_live_test t;
        struct drm_file *file;
-       struct live_test t;
        unsigned long n;
        int err = -ENODEV;
 
@@ -140,7 +64,7 @@ static int live_nop_switch(void *arg)
                return PTR_ERR(file);
 
        mutex_lock(&i915->drm.struct_mutex);
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
        ctx = kcalloc(nctx, sizeof(*ctx), GFP_KERNEL);
        if (!ctx) {
@@ -184,7 +108,7 @@ static int live_nop_switch(void *arg)
                pr_info("Populated %d contexts on %s in %lluns\n",
                        nctx, engine->name, ktime_to_ns(times[1] - times[0]));
 
-               err = begin_live_test(&t, i915, __func__, engine->name);
+               err = igt_live_test_begin(&t, i915, __func__, engine->name);
                if (err)
                        goto out_unlock;
 
@@ -232,7 +156,7 @@ static int live_nop_switch(void *arg)
                                break;
                }
 
-               err = end_live_test(&t);
+               err = igt_live_test_end(&t);
                if (err)
                        goto out_unlock;
 
@@ -243,7 +167,7 @@ static int live_nop_switch(void *arg)
        }
 
 out_unlock:
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
        mutex_unlock(&i915->drm.struct_mutex);
        mock_file_free(i915, file);
        return err;
@@ -553,10 +477,10 @@ static int igt_ctx_exec(void *arg)
        struct drm_i915_private *i915 = arg;
        struct drm_i915_gem_object *obj = NULL;
        unsigned long ncontexts, ndwords, dw;
+       struct igt_live_test t;
        struct drm_file *file;
        IGT_TIMEOUT(end_time);
        LIST_HEAD(objects);
-       struct live_test t;
        int err = -ENODEV;
 
        /*
@@ -574,7 +498,7 @@ static int igt_ctx_exec(void *arg)
 
        mutex_lock(&i915->drm.struct_mutex);
 
-       err = begin_live_test(&t, i915, __func__, "");
+       err = igt_live_test_begin(&t, i915, __func__, "");
        if (err)
                goto out_unlock;
 
@@ -593,6 +517,8 @@ static int igt_ctx_exec(void *arg)
                }
 
                for_each_engine(engine, i915, id) {
+                       intel_wakeref_t wakeref;
+
                        if (!engine->context_size)
                                continue; /* No logical context support in HW */
 
@@ -607,9 +533,9 @@ static int igt_ctx_exec(void *arg)
                                }
                        }
 
-                       intel_runtime_pm_get(i915);
-                       err = gpu_fill(obj, ctx, engine, dw);
-                       intel_runtime_pm_put(i915);
+                       err = 0;
+                       with_intel_runtime_pm(i915, wakeref)
+                               err = gpu_fill(obj, ctx, engine, dw);
                        if (err) {
                                pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
                                       ndwords, dw, max_dwords(obj),
@@ -627,7 +553,7 @@ static int igt_ctx_exec(void *arg)
                ncontexts++;
        }
        pr_info("Submitted %lu contexts (across %u engines), filling %lu dwords\n",
-               ncontexts, INTEL_INFO(i915)->num_rings, ndwords);
+               ncontexts, RUNTIME_INFO(i915)->num_rings, ndwords);
 
        dw = 0;
        list_for_each_entry(obj, &objects, st_link) {
@@ -642,7 +568,7 @@ static int igt_ctx_exec(void *arg)
        }
 
 out_unlock:
-       if (end_live_test(&t))
+       if (igt_live_test_end(&t))
                err = -EIO;
        mutex_unlock(&i915->drm.struct_mutex);
 
@@ -657,11 +583,11 @@ static int igt_ctx_readonly(void *arg)
        struct i915_gem_context *ctx;
        struct i915_hw_ppgtt *ppgtt;
        unsigned long ndwords, dw;
+       struct igt_live_test t;
        struct drm_file *file;
        I915_RND_STATE(prng);
        IGT_TIMEOUT(end_time);
        LIST_HEAD(objects);
-       struct live_test t;
        int err = -ENODEV;
 
        /*
@@ -676,7 +602,7 @@ static int igt_ctx_readonly(void *arg)
 
        mutex_lock(&i915->drm.struct_mutex);
 
-       err = begin_live_test(&t, i915, __func__, "");
+       err = igt_live_test_begin(&t, i915, __func__, "");
        if (err)
                goto out_unlock;
 
@@ -699,6 +625,8 @@ static int igt_ctx_readonly(void *arg)
                unsigned int id;
 
                for_each_engine(engine, i915, id) {
+                       intel_wakeref_t wakeref;
+
                        if (!intel_engine_can_store_dword(engine))
                                continue;
 
@@ -713,9 +641,9 @@ static int igt_ctx_readonly(void *arg)
                                        i915_gem_object_set_readonly(obj);
                        }
 
-                       intel_runtime_pm_get(i915);
-                       err = gpu_fill(obj, ctx, engine, dw);
-                       intel_runtime_pm_put(i915);
+                       err = 0;
+                       with_intel_runtime_pm(i915, wakeref)
+                               err = gpu_fill(obj, ctx, engine, dw);
                        if (err) {
                                pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
                                       ndwords, dw, max_dwords(obj),
@@ -732,7 +660,7 @@ static int igt_ctx_readonly(void *arg)
                }
        }
        pr_info("Submitted %lu dwords (across %u engines)\n",
-               ndwords, INTEL_INFO(i915)->num_rings);
+               ndwords, RUNTIME_INFO(i915)->num_rings);
 
        dw = 0;
        list_for_each_entry(obj, &objects, st_link) {
@@ -752,7 +680,7 @@ static int igt_ctx_readonly(void *arg)
        }
 
 out_unlock:
-       if (end_live_test(&t))
+       if (igt_live_test_end(&t))
                err = -EIO;
        mutex_unlock(&i915->drm.struct_mutex);
 
@@ -976,10 +904,11 @@ static int igt_vm_isolation(void *arg)
        struct drm_i915_private *i915 = arg;
        struct i915_gem_context *ctx_a, *ctx_b;
        struct intel_engine_cs *engine;
+       intel_wakeref_t wakeref;
+       struct igt_live_test t;
        struct drm_file *file;
        I915_RND_STATE(prng);
        unsigned long count;
-       struct live_test t;
        unsigned int id;
        u64 vm_total;
        int err;
@@ -998,7 +927,7 @@ static int igt_vm_isolation(void *arg)
 
        mutex_lock(&i915->drm.struct_mutex);
 
-       err = begin_live_test(&t, i915, __func__, "");
+       err = igt_live_test_begin(&t, i915, __func__, "");
        if (err)
                goto out_unlock;
 
@@ -1022,7 +951,7 @@ static int igt_vm_isolation(void *arg)
        GEM_BUG_ON(ctx_b->ppgtt->vm.total != vm_total);
        vm_total -= I915_GTT_PAGE_SIZE;
 
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
        count = 0;
        for_each_engine(engine, i915, id) {
@@ -1064,12 +993,12 @@ static int igt_vm_isolation(void *arg)
                count += this;
        }
        pr_info("Checked %lu scratch offsets across %d engines\n",
-               count, INTEL_INFO(i915)->num_rings);
+               count, RUNTIME_INFO(i915)->num_rings);
 
 out_rpm:
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
 out_unlock:
-       if (end_live_test(&t))
+       if (igt_live_test_end(&t))
                err = -EIO;
        mutex_unlock(&i915->drm.struct_mutex);
 
@@ -1165,6 +1094,7 @@ static int igt_switch_to_kernel_context(void *arg)
        struct intel_engine_cs *engine;
        struct i915_gem_context *ctx;
        enum intel_engine_id id;
+       intel_wakeref_t wakeref;
        int err;
 
        /*
@@ -1175,7 +1105,7 @@ static int igt_switch_to_kernel_context(void *arg)
         */
 
        mutex_lock(&i915->drm.struct_mutex);
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
        ctx = kernel_context(i915);
        if (IS_ERR(ctx)) {
@@ -1200,7 +1130,7 @@ out_unlock:
        if (igt_flush_test(i915, I915_WAIT_LOCKED))
                err = -EIO;
 
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
        mutex_unlock(&i915->drm.struct_mutex);
 
        kernel_context_close(ctx);
index 4365979d82228fa83c275f8a0f43b0ca6d11df60..d0553bc697055a0710a3dcf4d0120acbbecdcd04 100644 (file)
 #include "mock_drm.h"
 #include "mock_gem_device.h"
 
-static int populate_ggtt(struct drm_i915_private *i915)
+static void quirk_add(struct drm_i915_gem_object *obj,
+                     struct list_head *objects)
 {
+       /* quirk is only for live tiled objects, use it to declare ownership */
+       GEM_BUG_ON(obj->mm.quirked);
+       obj->mm.quirked = true;
+       list_add(&obj->st_link, objects);
+}
+
+static int populate_ggtt(struct drm_i915_private *i915,
+                        struct list_head *objects)
+{
+       unsigned long unbound, bound, count;
        struct drm_i915_gem_object *obj;
        u64 size;
 
+       count = 0;
        for (size = 0;
             size + I915_GTT_PAGE_SIZE <= i915->ggtt.vm.total;
             size += I915_GTT_PAGE_SIZE) {
@@ -43,17 +55,32 @@ static int populate_ggtt(struct drm_i915_private *i915)
                if (IS_ERR(obj))
                        return PTR_ERR(obj);
 
+               quirk_add(obj, objects);
+
                vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
                if (IS_ERR(vma))
                        return PTR_ERR(vma);
+
+               count++;
        }
 
-       if (!list_empty(&i915->mm.unbound_list)) {
-               size = 0;
-               list_for_each_entry(obj, &i915->mm.unbound_list, mm.link)
-                       size++;
+       unbound = 0;
+       list_for_each_entry(obj, &i915->mm.unbound_list, mm.link)
+               if (obj->mm.quirked)
+                       unbound++;
+       if (unbound) {
+               pr_err("%s: Found %lu objects unbound, expected %u!\n",
+                      __func__, unbound, 0);
+               return -EINVAL;
+       }
 
-               pr_err("Found %lld objects unbound!\n", size);
+       bound = 0;
+       list_for_each_entry(obj, &i915->mm.bound_list, mm.link)
+               if (obj->mm.quirked)
+                       bound++;
+       if (bound != count) {
+               pr_err("%s: Found %lu objects bound, expected %lu!\n",
+                      __func__, bound, count);
                return -EINVAL;
        }
 
@@ -70,18 +97,20 @@ static void unpin_ggtt(struct drm_i915_private *i915)
        struct i915_vma *vma;
 
        list_for_each_entry(vma, &i915->ggtt.vm.inactive_list, vm_link)
-               i915_vma_unpin(vma);
+               if (vma->obj->mm.quirked)
+                       i915_vma_unpin(vma);
 }
 
-static void cleanup_objects(struct drm_i915_private *i915)
+static void cleanup_objects(struct drm_i915_private *i915,
+                           struct list_head *list)
 {
        struct drm_i915_gem_object *obj, *on;
 
-       list_for_each_entry_safe(obj, on, &i915->mm.unbound_list, mm.link)
-               i915_gem_object_put(obj);
-
-       list_for_each_entry_safe(obj, on, &i915->mm.bound_list, mm.link)
+       list_for_each_entry_safe(obj, on, list, st_link) {
+               GEM_BUG_ON(!obj->mm.quirked);
+               obj->mm.quirked = false;
                i915_gem_object_put(obj);
+       }
 
        mutex_unlock(&i915->drm.struct_mutex);
 
@@ -94,11 +123,12 @@ static int igt_evict_something(void *arg)
 {
        struct drm_i915_private *i915 = arg;
        struct i915_ggtt *ggtt = &i915->ggtt;
+       LIST_HEAD(objects);
        int err;
 
        /* Fill the GGTT with pinned objects and try to evict one. */
 
-       err = populate_ggtt(i915);
+       err = populate_ggtt(i915, &objects);
        if (err)
                goto cleanup;
 
@@ -127,7 +157,7 @@ static int igt_evict_something(void *arg)
        }
 
 cleanup:
-       cleanup_objects(i915);
+       cleanup_objects(i915, &objects);
        return err;
 }
 
@@ -136,13 +166,14 @@ static int igt_overcommit(void *arg)
        struct drm_i915_private *i915 = arg;
        struct drm_i915_gem_object *obj;
        struct i915_vma *vma;
+       LIST_HEAD(objects);
        int err;
 
        /* Fill the GGTT with pinned objects and then try to pin one more.
         * We expect it to fail.
         */
 
-       err = populate_ggtt(i915);
+       err = populate_ggtt(i915, &objects);
        if (err)
                goto cleanup;
 
@@ -152,6 +183,8 @@ static int igt_overcommit(void *arg)
                goto cleanup;
        }
 
+       quirk_add(obj, &objects);
+
        vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
        if (!IS_ERR(vma) || PTR_ERR(vma) != -ENOSPC) {
                pr_err("Failed to evict+insert, i915_gem_object_ggtt_pin returned err=%d\n", (int)PTR_ERR(vma));
@@ -160,7 +193,7 @@ static int igt_overcommit(void *arg)
        }
 
 cleanup:
-       cleanup_objects(i915);
+       cleanup_objects(i915, &objects);
        return err;
 }
 
@@ -172,11 +205,12 @@ static int igt_evict_for_vma(void *arg)
                .start = 0,
                .size = 4096,
        };
+       LIST_HEAD(objects);
        int err;
 
        /* Fill the GGTT with pinned objects and try to evict a range. */
 
-       err = populate_ggtt(i915);
+       err = populate_ggtt(i915, &objects);
        if (err)
                goto cleanup;
 
@@ -199,7 +233,7 @@ static int igt_evict_for_vma(void *arg)
        }
 
 cleanup:
-       cleanup_objects(i915);
+       cleanup_objects(i915, &objects);
        return err;
 }
 
@@ -222,6 +256,7 @@ static int igt_evict_for_cache_color(void *arg)
        };
        struct drm_i915_gem_object *obj;
        struct i915_vma *vma;
+       LIST_HEAD(objects);
        int err;
 
        /* Currently the use of color_adjust is limited to cache domains within
@@ -237,6 +272,7 @@ static int igt_evict_for_cache_color(void *arg)
                goto cleanup;
        }
        i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
+       quirk_add(obj, &objects);
 
        vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
                                       I915_GTT_PAGE_SIZE | flags);
@@ -252,6 +288,7 @@ static int igt_evict_for_cache_color(void *arg)
                goto cleanup;
        }
        i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
+       quirk_add(obj, &objects);
 
        /* Neighbouring; same colour - should fit */
        vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
@@ -287,7 +324,7 @@ static int igt_evict_for_cache_color(void *arg)
 
 cleanup:
        unpin_ggtt(i915);
-       cleanup_objects(i915);
+       cleanup_objects(i915, &objects);
        ggtt->vm.mm.color_adjust = NULL;
        return err;
 }
@@ -296,11 +333,12 @@ static int igt_evict_vm(void *arg)
 {
        struct drm_i915_private *i915 = arg;
        struct i915_ggtt *ggtt = &i915->ggtt;
+       LIST_HEAD(objects);
        int err;
 
        /* Fill the GGTT with pinned objects and try to evict everything. */
 
-       err = populate_ggtt(i915);
+       err = populate_ggtt(i915, &objects);
        if (err)
                goto cleanup;
 
@@ -322,7 +360,7 @@ static int igt_evict_vm(void *arg)
        }
 
 cleanup:
-       cleanup_objects(i915);
+       cleanup_objects(i915, &objects);
        return err;
 }
 
@@ -336,6 +374,7 @@ static int igt_evict_contexts(void *arg)
                struct drm_mm_node node;
                struct reserved *next;
        } *reserved = NULL;
+       intel_wakeref_t wakeref;
        struct drm_mm_node hole;
        unsigned long count;
        int err;
@@ -355,7 +394,7 @@ static int igt_evict_contexts(void *arg)
                return 0;
 
        mutex_lock(&i915->drm.struct_mutex);
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
        /* Reserve a block so that we know we have enough to fit a few rq */
        memset(&hole, 0, sizeof(hole));
@@ -400,8 +439,10 @@ static int igt_evict_contexts(void *arg)
                struct drm_file *file;
 
                file = mock_file(i915);
-               if (IS_ERR(file))
-                       return PTR_ERR(file);
+               if (IS_ERR(file)) {
+                       err = PTR_ERR(file);
+                       break;
+               }
 
                count = 0;
                mutex_lock(&i915->drm.struct_mutex);
@@ -464,7 +505,7 @@ out_locked:
        }
        if (drm_mm_node_allocated(&hole))
                drm_mm_remove_node(&hole);
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
        mutex_unlock(&i915->drm.struct_mutex);
 
        return err;
@@ -480,14 +521,17 @@ int i915_gem_evict_mock_selftests(void)
                SUBTEST(igt_overcommit),
        };
        struct drm_i915_private *i915;
-       int err;
+       intel_wakeref_t wakeref;
+       int err = 0;
 
        i915 = mock_gem_device();
        if (!i915)
                return -ENOMEM;
 
        mutex_lock(&i915->drm.struct_mutex);
-       err = i915_subtests(tests, i915);
+       with_intel_runtime_pm(i915, wakeref)
+               err = i915_subtests(tests, i915);
+
        mutex_unlock(&i915->drm.struct_mutex);
 
        drm_dev_put(&i915->drm);
index a9ed0ecc94e2d77fa23a721fb9ace38655851597..06bde4a273cbd6da9fdd39c559906f67e57ac994 100644 (file)
@@ -275,6 +275,7 @@ static int lowlevel_hole(struct drm_i915_private *i915,
 
                for (n = 0; n < count; n++) {
                        u64 addr = hole_start + order[n] * BIT_ULL(size);
+                       intel_wakeref_t wakeref;
 
                        GEM_BUG_ON(addr + BIT_ULL(size) > vm->total);
 
@@ -293,9 +294,9 @@ static int lowlevel_hole(struct drm_i915_private *i915,
                        mock_vma.node.size = BIT_ULL(size);
                        mock_vma.node.start = addr;
 
-                       intel_runtime_pm_get(i915);
+                       wakeref = intel_runtime_pm_get(i915);
                        vm->insert_entries(vm, &mock_vma, I915_CACHE_NONE, 0);
-                       intel_runtime_pm_put(i915);
+                       intel_runtime_pm_put(i915, wakeref);
                }
                count = n;
 
@@ -1144,6 +1145,7 @@ static int igt_ggtt_page(void *arg)
        struct drm_i915_private *i915 = arg;
        struct i915_ggtt *ggtt = &i915->ggtt;
        struct drm_i915_gem_object *obj;
+       intel_wakeref_t wakeref;
        struct drm_mm_node tmp;
        unsigned int *order, n;
        int err;
@@ -1169,7 +1171,7 @@ static int igt_ggtt_page(void *arg)
        if (err)
                goto out_unpin;
 
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
        for (n = 0; n < count; n++) {
                u64 offset = tmp.start + n * PAGE_SIZE;
@@ -1216,7 +1218,7 @@ static int igt_ggtt_page(void *arg)
        kfree(order);
 out_remove:
        ggtt->vm.clear_range(&ggtt->vm, tmp.start, tmp.size);
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
        drm_mm_remove_node(&tmp);
 out_unpin:
        i915_gem_object_unpin_pages(obj);
@@ -1265,27 +1267,35 @@ static int exercise_mock(struct drm_i915_private *i915,
 
 static int igt_mock_fill(void *arg)
 {
-       return exercise_mock(arg, fill_hole);
+       struct i915_ggtt *ggtt = arg;
+
+       return exercise_mock(ggtt->vm.i915, fill_hole);
 }
 
 static int igt_mock_walk(void *arg)
 {
-       return exercise_mock(arg, walk_hole);
+       struct i915_ggtt *ggtt = arg;
+
+       return exercise_mock(ggtt->vm.i915, walk_hole);
 }
 
 static int igt_mock_pot(void *arg)
 {
-       return exercise_mock(arg, pot_hole);
+       struct i915_ggtt *ggtt = arg;
+
+       return exercise_mock(ggtt->vm.i915, pot_hole);
 }
 
 static int igt_mock_drunk(void *arg)
 {
-       return exercise_mock(arg, drunk_hole);
+       struct i915_ggtt *ggtt = arg;
+
+       return exercise_mock(ggtt->vm.i915, drunk_hole);
 }
 
 static int igt_gtt_reserve(void *arg)
 {
-       struct drm_i915_private *i915 = arg;
+       struct i915_ggtt *ggtt = arg;
        struct drm_i915_gem_object *obj, *on;
        LIST_HEAD(objects);
        u64 total;
@@ -1298,11 +1308,12 @@ static int igt_gtt_reserve(void *arg)
 
        /* Start by filling the GGTT */
        for (total = 0;
-            total + 2*I915_GTT_PAGE_SIZE <= i915->ggtt.vm.total;
-            total += 2*I915_GTT_PAGE_SIZE) {
+            total + 2 * I915_GTT_PAGE_SIZE <= ggtt->vm.total;
+            total += 2 * I915_GTT_PAGE_SIZE) {
                struct i915_vma *vma;
 
-               obj = i915_gem_object_create_internal(i915, 2*PAGE_SIZE);
+               obj = i915_gem_object_create_internal(ggtt->vm.i915,
+                                                     2 * PAGE_SIZE);
                if (IS_ERR(obj)) {
                        err = PTR_ERR(obj);
                        goto out;
@@ -1316,20 +1327,20 @@ static int igt_gtt_reserve(void *arg)
 
                list_add(&obj->st_link, &objects);
 
-               vma = i915_vma_instance(obj, &i915->ggtt.vm, NULL);
+               vma = i915_vma_instance(obj, &ggtt->vm, NULL);
                if (IS_ERR(vma)) {
                        err = PTR_ERR(vma);
                        goto out;
                }
 
-               err = i915_gem_gtt_reserve(&i915->ggtt.vm, &vma->node,
+               err = i915_gem_gtt_reserve(&ggtt->vm, &vma->node,
                                           obj->base.size,
                                           total,
                                           obj->cache_level,
                                           0);
                if (err) {
                        pr_err("i915_gem_gtt_reserve (pass 1) failed at %llu/%llu with err=%d\n",
-                              total, i915->ggtt.vm.total, err);
+                              total, ggtt->vm.total, err);
                        goto out;
                }
                track_vma_bind(vma);
@@ -1347,11 +1358,12 @@ static int igt_gtt_reserve(void *arg)
 
        /* Now we start forcing evictions */
        for (total = I915_GTT_PAGE_SIZE;
-            total + 2*I915_GTT_PAGE_SIZE <= i915->ggtt.vm.total;
-            total += 2*I915_GTT_PAGE_SIZE) {
+            total + 2 * I915_GTT_PAGE_SIZE <= ggtt->vm.total;
+            total += 2 * I915_GTT_PAGE_SIZE) {
                struct i915_vma *vma;
 
-               obj = i915_gem_object_create_internal(i915, 2*PAGE_SIZE);
+               obj = i915_gem_object_create_internal(ggtt->vm.i915,
+                                                     2 * PAGE_SIZE);
                if (IS_ERR(obj)) {
                        err = PTR_ERR(obj);
                        goto out;
@@ -1365,20 +1377,20 @@ static int igt_gtt_reserve(void *arg)
 
                list_add(&obj->st_link, &objects);
 
-               vma = i915_vma_instance(obj, &i915->ggtt.vm, NULL);
+               vma = i915_vma_instance(obj, &ggtt->vm, NULL);
                if (IS_ERR(vma)) {
                        err = PTR_ERR(vma);
                        goto out;
                }
 
-               err = i915_gem_gtt_reserve(&i915->ggtt.vm, &vma->node,
+               err = i915_gem_gtt_reserve(&ggtt->vm, &vma->node,
                                           obj->base.size,
                                           total,
                                           obj->cache_level,
                                           0);
                if (err) {
                        pr_err("i915_gem_gtt_reserve (pass 2) failed at %llu/%llu with err=%d\n",
-                              total, i915->ggtt.vm.total, err);
+                              total, ggtt->vm.total, err);
                        goto out;
                }
                track_vma_bind(vma);
@@ -1399,7 +1411,7 @@ static int igt_gtt_reserve(void *arg)
                struct i915_vma *vma;
                u64 offset;
 
-               vma = i915_vma_instance(obj, &i915->ggtt.vm, NULL);
+               vma = i915_vma_instance(obj, &ggtt->vm, NULL);
                if (IS_ERR(vma)) {
                        err = PTR_ERR(vma);
                        goto out;
@@ -1411,18 +1423,18 @@ static int igt_gtt_reserve(void *arg)
                        goto out;
                }
 
-               offset = random_offset(0, i915->ggtt.vm.total,
+               offset = random_offset(0, ggtt->vm.total,
                                       2*I915_GTT_PAGE_SIZE,
                                       I915_GTT_MIN_ALIGNMENT);
 
-               err = i915_gem_gtt_reserve(&i915->ggtt.vm, &vma->node,
+               err = i915_gem_gtt_reserve(&ggtt->vm, &vma->node,
                                           obj->base.size,
                                           offset,
                                           obj->cache_level,
                                           0);
                if (err) {
                        pr_err("i915_gem_gtt_reserve (pass 3) failed at %llu/%llu with err=%d\n",
-                              total, i915->ggtt.vm.total, err);
+                              total, ggtt->vm.total, err);
                        goto out;
                }
                track_vma_bind(vma);
@@ -1448,7 +1460,7 @@ out:
 
 static int igt_gtt_insert(void *arg)
 {
-       struct drm_i915_private *i915 = arg;
+       struct i915_ggtt *ggtt = arg;
        struct drm_i915_gem_object *obj, *on;
        struct drm_mm_node tmp = {};
        const struct invalid_insert {
@@ -1457,8 +1469,8 @@ static int igt_gtt_insert(void *arg)
                u64 start, end;
        } invalid_insert[] = {
                {
-                       i915->ggtt.vm.total + I915_GTT_PAGE_SIZE, 0,
-                       0, i915->ggtt.vm.total,
+                       ggtt->vm.total + I915_GTT_PAGE_SIZE, 0,
+                       0, ggtt->vm.total,
                },
                {
                        2*I915_GTT_PAGE_SIZE, 0,
@@ -1488,7 +1500,7 @@ static int igt_gtt_insert(void *arg)
 
        /* Check a couple of obviously invalid requests */
        for (ii = invalid_insert; ii->size; ii++) {
-               err = i915_gem_gtt_insert(&i915->ggtt.vm, &tmp,
+               err = i915_gem_gtt_insert(&ggtt->vm, &tmp,
                                          ii->size, ii->alignment,
                                          I915_COLOR_UNEVICTABLE,
                                          ii->start, ii->end,
@@ -1503,11 +1515,12 @@ static int igt_gtt_insert(void *arg)
 
        /* Start by filling the GGTT */
        for (total = 0;
-            total + I915_GTT_PAGE_SIZE <= i915->ggtt.vm.total;
+            total + I915_GTT_PAGE_SIZE <= ggtt->vm.total;
             total += I915_GTT_PAGE_SIZE) {
                struct i915_vma *vma;
 
-               obj = i915_gem_object_create_internal(i915, I915_GTT_PAGE_SIZE);
+               obj = i915_gem_object_create_internal(ggtt->vm.i915,
+                                                     I915_GTT_PAGE_SIZE);
                if (IS_ERR(obj)) {
                        err = PTR_ERR(obj);
                        goto out;
@@ -1521,15 +1534,15 @@ static int igt_gtt_insert(void *arg)
 
                list_add(&obj->st_link, &objects);
 
-               vma = i915_vma_instance(obj, &i915->ggtt.vm, NULL);
+               vma = i915_vma_instance(obj, &ggtt->vm, NULL);
                if (IS_ERR(vma)) {
                        err = PTR_ERR(vma);
                        goto out;
                }
 
-               err = i915_gem_gtt_insert(&i915->ggtt.vm, &vma->node,
+               err = i915_gem_gtt_insert(&ggtt->vm, &vma->node,
                                          obj->base.size, 0, obj->cache_level,
-                                         0, i915->ggtt.vm.total,
+                                         0, ggtt->vm.total,
                                          0);
                if (err == -ENOSPC) {
                        /* maxed out the GGTT space */
@@ -1538,7 +1551,7 @@ static int igt_gtt_insert(void *arg)
                }
                if (err) {
                        pr_err("i915_gem_gtt_insert (pass 1) failed at %llu/%llu with err=%d\n",
-                              total, i915->ggtt.vm.total, err);
+                              total, ggtt->vm.total, err);
                        goto out;
                }
                track_vma_bind(vma);
@@ -1550,7 +1563,7 @@ static int igt_gtt_insert(void *arg)
        list_for_each_entry(obj, &objects, st_link) {
                struct i915_vma *vma;
 
-               vma = i915_vma_instance(obj, &i915->ggtt.vm, NULL);
+               vma = i915_vma_instance(obj, &ggtt->vm, NULL);
                if (IS_ERR(vma)) {
                        err = PTR_ERR(vma);
                        goto out;
@@ -1570,7 +1583,7 @@ static int igt_gtt_insert(void *arg)
                struct i915_vma *vma;
                u64 offset;
 
-               vma = i915_vma_instance(obj, &i915->ggtt.vm, NULL);
+               vma = i915_vma_instance(obj, &ggtt->vm, NULL);
                if (IS_ERR(vma)) {
                        err = PTR_ERR(vma);
                        goto out;
@@ -1585,13 +1598,13 @@ static int igt_gtt_insert(void *arg)
                        goto out;
                }
 
-               err = i915_gem_gtt_insert(&i915->ggtt.vm, &vma->node,
+               err = i915_gem_gtt_insert(&ggtt->vm, &vma->node,
                                          obj->base.size, 0, obj->cache_level,
-                                         0, i915->ggtt.vm.total,
+                                         0, ggtt->vm.total,
                                          0);
                if (err) {
                        pr_err("i915_gem_gtt_insert (pass 2) failed at %llu/%llu with err=%d\n",
-                              total, i915->ggtt.vm.total, err);
+                              total, ggtt->vm.total, err);
                        goto out;
                }
                track_vma_bind(vma);
@@ -1607,11 +1620,12 @@ static int igt_gtt_insert(void *arg)
 
        /* And then force evictions */
        for (total = 0;
-            total + 2*I915_GTT_PAGE_SIZE <= i915->ggtt.vm.total;
-            total += 2*I915_GTT_PAGE_SIZE) {
+            total + 2 * I915_GTT_PAGE_SIZE <= ggtt->vm.total;
+            total += 2 * I915_GTT_PAGE_SIZE) {
                struct i915_vma *vma;
 
-               obj = i915_gem_object_create_internal(i915, 2*I915_GTT_PAGE_SIZE);
+               obj = i915_gem_object_create_internal(ggtt->vm.i915,
+                                                     2 * I915_GTT_PAGE_SIZE);
                if (IS_ERR(obj)) {
                        err = PTR_ERR(obj);
                        goto out;
@@ -1625,19 +1639,19 @@ static int igt_gtt_insert(void *arg)
 
                list_add(&obj->st_link, &objects);
 
-               vma = i915_vma_instance(obj, &i915->ggtt.vm, NULL);
+               vma = i915_vma_instance(obj, &ggtt->vm, NULL);
                if (IS_ERR(vma)) {
                        err = PTR_ERR(vma);
                        goto out;
                }
 
-               err = i915_gem_gtt_insert(&i915->ggtt.vm, &vma->node,
+               err = i915_gem_gtt_insert(&ggtt->vm, &vma->node,
                                          obj->base.size, 0, obj->cache_level,
-                                         0, i915->ggtt.vm.total,
+                                         0, ggtt->vm.total,
                                          0);
                if (err) {
                        pr_err("i915_gem_gtt_insert (pass 3) failed at %llu/%llu with err=%d\n",
-                              total, i915->ggtt.vm.total, err);
+                              total, ggtt->vm.total, err);
                        goto out;
                }
                track_vma_bind(vma);
@@ -1664,17 +1678,25 @@ int i915_gem_gtt_mock_selftests(void)
                SUBTEST(igt_gtt_insert),
        };
        struct drm_i915_private *i915;
+       struct i915_ggtt ggtt;
        int err;
 
        i915 = mock_gem_device();
        if (!i915)
                return -ENOMEM;
 
+       mock_init_ggtt(i915, &ggtt);
+
        mutex_lock(&i915->drm.struct_mutex);
-       err = i915_subtests(tests, i915);
+       err = i915_subtests(tests, &ggtt);
+       mock_device_flush(i915);
        mutex_unlock(&i915->drm.struct_mutex);
 
+       i915_gem_drain_freed_objects(i915);
+
+       mock_fini_ggtt(&ggtt);
        drm_dev_put(&i915->drm);
+
        return err;
 }
 
index c3999dd2021e4b76816a50ab0df6396205df5e2b..395ae878e0f7c3529ede2201b3b388a0a46dc785 100644 (file)
@@ -238,6 +238,7 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
                u32 *cpu;
 
                GEM_BUG_ON(view.partial.size > nreal);
+               cond_resched();
 
                err = i915_gem_object_set_to_gtt_domain(obj, true);
                if (err) {
@@ -307,6 +308,7 @@ static int igt_partial_tiling(void *arg)
        const unsigned int nreal = 1 << 12; /* largest tile row x2 */
        struct drm_i915_private *i915 = arg;
        struct drm_i915_gem_object *obj;
+       intel_wakeref_t wakeref;
        int tiling;
        int err;
 
@@ -332,7 +334,7 @@ static int igt_partial_tiling(void *arg)
        }
 
        mutex_lock(&i915->drm.struct_mutex);
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
        if (1) {
                IGT_TIMEOUT(end);
@@ -443,7 +445,7 @@ next_tiling: ;
        }
 
 out_unlock:
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
        mutex_unlock(&i915->drm.struct_mutex);
        i915_gem_object_unpin_pages(obj);
 out:
@@ -505,11 +507,13 @@ static void disable_retire_worker(struct drm_i915_private *i915)
 
        mutex_lock(&i915->drm.struct_mutex);
        if (!i915->gt.active_requests++) {
-               intel_runtime_pm_get(i915);
-               i915_gem_unpark(i915);
-               intel_runtime_pm_put(i915);
+               intel_wakeref_t wakeref;
+
+               with_intel_runtime_pm(i915, wakeref)
+                       i915_gem_unpark(i915);
        }
        mutex_unlock(&i915->drm.struct_mutex);
+
        cancel_delayed_work_sync(&i915->gt.retire_work);
        cancel_delayed_work_sync(&i915->gt.idle_work);
 }
@@ -577,6 +581,8 @@ static int igt_mmap_offset_exhaustion(void *arg)
 
        /* Now fill with busy dead objects that we expect to reap */
        for (loop = 0; loop < 3; loop++) {
+               intel_wakeref_t wakeref;
+
                if (i915_terminally_wedged(&i915->gpu_error))
                        break;
 
@@ -586,10 +592,10 @@ static int igt_mmap_offset_exhaustion(void *arg)
                        goto out;
                }
 
+               err = 0;
                mutex_lock(&i915->drm.struct_mutex);
-               intel_runtime_pm_get(i915);
-               err = make_obj_busy(obj);
-               intel_runtime_pm_put(i915);
+               with_intel_runtime_pm(i915, wakeref)
+                       err = make_obj_busy(obj);
                mutex_unlock(&i915->drm.struct_mutex);
                if (err) {
                        pr_err("[loop %d] Failed to busy the object\n", loop);
index 07e5578153088cbdb434b58afae4ae1f1ddccc08..4d4b86b5fa1135dc663547aeab2522b2c95f908e 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/prime_numbers.h>
 
 #include "../i915_selftest.h"
+#include "igt_live_test.h"
 
 #include "mock_context.h"
 #include "mock_gem_device.h"
@@ -255,84 +256,27 @@ int i915_request_mock_selftests(void)
                SUBTEST(igt_request_rewind),
        };
        struct drm_i915_private *i915;
-       int err;
+       intel_wakeref_t wakeref;
+       int err = 0;
 
        i915 = mock_gem_device();
        if (!i915)
                return -ENOMEM;
 
-       err = i915_subtests(tests, i915);
+       with_intel_runtime_pm(i915, wakeref)
+               err = i915_subtests(tests, i915);
+
        drm_dev_put(&i915->drm);
 
        return err;
 }
 
-struct live_test {
-       struct drm_i915_private *i915;
-       const char *func;
-       const char *name;
-
-       unsigned int reset_count;
-};
-
-static int begin_live_test(struct live_test *t,
-                          struct drm_i915_private *i915,
-                          const char *func,
-                          const char *name)
-{
-       int err;
-
-       t->i915 = i915;
-       t->func = func;
-       t->name = name;
-
-       err = i915_gem_wait_for_idle(i915,
-                                    I915_WAIT_LOCKED,
-                                    MAX_SCHEDULE_TIMEOUT);
-       if (err) {
-               pr_err("%s(%s): failed to idle before, with err=%d!",
-                      func, name, err);
-               return err;
-       }
-
-       i915->gpu_error.missed_irq_rings = 0;
-       t->reset_count = i915_reset_count(&i915->gpu_error);
-
-       return 0;
-}
-
-static int end_live_test(struct live_test *t)
-{
-       struct drm_i915_private *i915 = t->i915;
-
-       i915_retire_requests(i915);
-
-       if (wait_for(intel_engines_are_idle(i915), 10)) {
-               pr_err("%s(%s): GPU not idle\n", t->func, t->name);
-               return -EIO;
-       }
-
-       if (t->reset_count != i915_reset_count(&i915->gpu_error)) {
-               pr_err("%s(%s): GPU was reset %d times!\n",
-                      t->func, t->name,
-                      i915_reset_count(&i915->gpu_error) - t->reset_count);
-               return -EIO;
-       }
-
-       if (i915->gpu_error.missed_irq_rings) {
-               pr_err("%s(%s): Missed interrupts on engines %lx\n",
-                      t->func, t->name, i915->gpu_error.missed_irq_rings);
-               return -EIO;
-       }
-
-       return 0;
-}
-
 static int live_nop_request(void *arg)
 {
        struct drm_i915_private *i915 = arg;
        struct intel_engine_cs *engine;
-       struct live_test t;
+       intel_wakeref_t wakeref;
+       struct igt_live_test t;
        unsigned int id;
        int err = -ENODEV;
 
@@ -342,7 +286,7 @@ static int live_nop_request(void *arg)
         */
 
        mutex_lock(&i915->drm.struct_mutex);
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
        for_each_engine(engine, i915, id) {
                struct i915_request *request = NULL;
@@ -350,7 +294,7 @@ static int live_nop_request(void *arg)
                IGT_TIMEOUT(end_time);
                ktime_t times[2] = {};
 
-               err = begin_live_test(&t, i915, __func__, engine->name);
+               err = igt_live_test_begin(&t, i915, __func__, engine->name);
                if (err)
                        goto out_unlock;
 
@@ -392,7 +336,7 @@ static int live_nop_request(void *arg)
                                break;
                }
 
-               err = end_live_test(&t);
+               err = igt_live_test_end(&t);
                if (err)
                        goto out_unlock;
 
@@ -403,7 +347,7 @@ static int live_nop_request(void *arg)
        }
 
 out_unlock:
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
        mutex_unlock(&i915->drm.struct_mutex);
        return err;
 }
@@ -478,7 +422,8 @@ static int live_empty_request(void *arg)
 {
        struct drm_i915_private *i915 = arg;
        struct intel_engine_cs *engine;
-       struct live_test t;
+       intel_wakeref_t wakeref;
+       struct igt_live_test t;
        struct i915_vma *batch;
        unsigned int id;
        int err = 0;
@@ -489,7 +434,7 @@ static int live_empty_request(void *arg)
         */
 
        mutex_lock(&i915->drm.struct_mutex);
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
        batch = empty_batch(i915);
        if (IS_ERR(batch)) {
@@ -503,7 +448,7 @@ static int live_empty_request(void *arg)
                unsigned long n, prime;
                ktime_t times[2] = {};
 
-               err = begin_live_test(&t, i915, __func__, engine->name);
+               err = igt_live_test_begin(&t, i915, __func__, engine->name);
                if (err)
                        goto out_batch;
 
@@ -539,7 +484,7 @@ static int live_empty_request(void *arg)
                                break;
                }
 
-               err = end_live_test(&t);
+               err = igt_live_test_end(&t);
                if (err)
                        goto out_batch;
 
@@ -553,7 +498,7 @@ out_batch:
        i915_vma_unpin(batch);
        i915_vma_put(batch);
 out_unlock:
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
        mutex_unlock(&i915->drm.struct_mutex);
        return err;
 }
@@ -637,8 +582,9 @@ static int live_all_engines(void *arg)
        struct drm_i915_private *i915 = arg;
        struct intel_engine_cs *engine;
        struct i915_request *request[I915_NUM_ENGINES];
+       intel_wakeref_t wakeref;
+       struct igt_live_test t;
        struct i915_vma *batch;
-       struct live_test t;
        unsigned int id;
        int err;
 
@@ -648,9 +594,9 @@ static int live_all_engines(void *arg)
         */
 
        mutex_lock(&i915->drm.struct_mutex);
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
-       err = begin_live_test(&t, i915, __func__, "");
+       err = igt_live_test_begin(&t, i915, __func__, "");
        if (err)
                goto out_unlock;
 
@@ -722,7 +668,7 @@ static int live_all_engines(void *arg)
                request[id] = NULL;
        }
 
-       err = end_live_test(&t);
+       err = igt_live_test_end(&t);
 
 out_request:
        for_each_engine(engine, i915, id)
@@ -731,7 +677,7 @@ out_request:
        i915_vma_unpin(batch);
        i915_vma_put(batch);
 out_unlock:
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
        mutex_unlock(&i915->drm.struct_mutex);
        return err;
 }
@@ -742,7 +688,8 @@ static int live_sequential_engines(void *arg)
        struct i915_request *request[I915_NUM_ENGINES] = {};
        struct i915_request *prev = NULL;
        struct intel_engine_cs *engine;
-       struct live_test t;
+       intel_wakeref_t wakeref;
+       struct igt_live_test t;
        unsigned int id;
        int err;
 
@@ -753,9 +700,9 @@ static int live_sequential_engines(void *arg)
         */
 
        mutex_lock(&i915->drm.struct_mutex);
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
-       err = begin_live_test(&t, i915, __func__, "");
+       err = igt_live_test_begin(&t, i915, __func__, "");
        if (err)
                goto out_unlock;
 
@@ -838,7 +785,7 @@ static int live_sequential_engines(void *arg)
                GEM_BUG_ON(!i915_request_completed(request[id]));
        }
 
-       err = end_live_test(&t);
+       err = igt_live_test_end(&t);
 
 out_request:
        for_each_engine(engine, i915, id) {
@@ -860,7 +807,7 @@ out_request:
                i915_request_put(request[id]);
        }
 out_unlock:
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
        mutex_unlock(&i915->drm.struct_mutex);
        return err;
 }
index ffa74290e0547a77f762a890b992277f2459419f..f0a32edfb9b16731f314d2ff849da8955b0b53d6 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "mock_gem_device.h"
 #include "mock_context.h"
+#include "mock_gtt.h"
 
 static bool assert_vma(struct i915_vma *vma,
                       struct drm_i915_gem_object *obj,
@@ -141,7 +142,8 @@ static int create_vmas(struct drm_i915_private *i915,
 
 static int igt_vma_create(void *arg)
 {
-       struct drm_i915_private *i915 = arg;
+       struct i915_ggtt *ggtt = arg;
+       struct drm_i915_private *i915 = ggtt->vm.i915;
        struct drm_i915_gem_object *obj, *on;
        struct i915_gem_context *ctx, *cn;
        unsigned long num_obj, num_ctx;
@@ -245,7 +247,7 @@ static bool assert_pin_einval(const struct i915_vma *vma,
 
 static int igt_vma_pin1(void *arg)
 {
-       struct drm_i915_private *i915 = arg;
+       struct i915_ggtt *ggtt = arg;
        const struct pin_mode modes[] = {
 #define VALID(sz, fl) { .size = (sz), .flags = (fl), .assert = assert_pin_valid, .string = #sz ", " #fl ", (valid) " }
 #define __INVALID(sz, fl, check, eval) { .size = (sz), .flags = (fl), .assert = (check), .string = #sz ", " #fl ", (invalid " #eval ")" }
@@ -256,30 +258,30 @@ static int igt_vma_pin1(void *arg)
 
                VALID(0, PIN_GLOBAL | PIN_OFFSET_BIAS | 4096),
                VALID(0, PIN_GLOBAL | PIN_OFFSET_BIAS | 8192),
-               VALID(0, PIN_GLOBAL | PIN_OFFSET_BIAS | (i915->ggtt.mappable_end - 4096)),
-               VALID(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_BIAS | (i915->ggtt.mappable_end - 4096)),
-               VALID(0, PIN_GLOBAL | PIN_OFFSET_BIAS | (i915->ggtt.vm.total - 4096)),
-
-               VALID(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_FIXED | (i915->ggtt.mappable_end - 4096)),
-               INVALID(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_FIXED | i915->ggtt.mappable_end),
-               VALID(0, PIN_GLOBAL | PIN_OFFSET_FIXED | (i915->ggtt.vm.total - 4096)),
-               INVALID(0, PIN_GLOBAL | PIN_OFFSET_FIXED | i915->ggtt.vm.total),
+               VALID(0, PIN_GLOBAL | PIN_OFFSET_BIAS | (ggtt->mappable_end - 4096)),
+               VALID(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_BIAS | (ggtt->mappable_end - 4096)),
+               VALID(0, PIN_GLOBAL | PIN_OFFSET_BIAS | (ggtt->vm.total - 4096)),
+
+               VALID(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_FIXED | (ggtt->mappable_end - 4096)),
+               INVALID(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_FIXED | ggtt->mappable_end),
+               VALID(0, PIN_GLOBAL | PIN_OFFSET_FIXED | (ggtt->vm.total - 4096)),
+               INVALID(0, PIN_GLOBAL | PIN_OFFSET_FIXED | ggtt->vm.total),
                INVALID(0, PIN_GLOBAL | PIN_OFFSET_FIXED | round_down(U64_MAX, PAGE_SIZE)),
 
                VALID(4096, PIN_GLOBAL),
                VALID(8192, PIN_GLOBAL),
-               VALID(i915->ggtt.mappable_end - 4096, PIN_GLOBAL | PIN_MAPPABLE),
-               VALID(i915->ggtt.mappable_end, PIN_GLOBAL | PIN_MAPPABLE),
-               NOSPACE(i915->ggtt.mappable_end + 4096, PIN_GLOBAL | PIN_MAPPABLE),
-               VALID(i915->ggtt.vm.total - 4096, PIN_GLOBAL),
-               VALID(i915->ggtt.vm.total, PIN_GLOBAL),
-               NOSPACE(i915->ggtt.vm.total + 4096, PIN_GLOBAL),
+               VALID(ggtt->mappable_end - 4096, PIN_GLOBAL | PIN_MAPPABLE),
+               VALID(ggtt->mappable_end, PIN_GLOBAL | PIN_MAPPABLE),
+               NOSPACE(ggtt->mappable_end + 4096, PIN_GLOBAL | PIN_MAPPABLE),
+               VALID(ggtt->vm.total - 4096, PIN_GLOBAL),
+               VALID(ggtt->vm.total, PIN_GLOBAL),
+               NOSPACE(ggtt->vm.total + 4096, PIN_GLOBAL),
                NOSPACE(round_down(U64_MAX, PAGE_SIZE), PIN_GLOBAL),
-               INVALID(8192, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_FIXED | (i915->ggtt.mappable_end - 4096)),
-               INVALID(8192, PIN_GLOBAL | PIN_OFFSET_FIXED | (i915->ggtt.vm.total - 4096)),
+               INVALID(8192, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_FIXED | (ggtt->mappable_end - 4096)),
+               INVALID(8192, PIN_GLOBAL | PIN_OFFSET_FIXED | (ggtt->vm.total - 4096)),
                INVALID(8192, PIN_GLOBAL | PIN_OFFSET_FIXED | (round_down(U64_MAX, PAGE_SIZE) - 4096)),
 
-               VALID(8192, PIN_GLOBAL | PIN_OFFSET_BIAS | (i915->ggtt.mappable_end - 4096)),
+               VALID(8192, PIN_GLOBAL | PIN_OFFSET_BIAS | (ggtt->mappable_end - 4096)),
 
 #if !IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
                /* Misusing BIAS is a programming error (it is not controllable
@@ -287,10 +289,10 @@ static int igt_vma_pin1(void *arg)
                 * However, the tests are still quite interesting for checking
                 * variable start, end and size.
                 */
-               NOSPACE(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_BIAS | i915->ggtt.mappable_end),
-               NOSPACE(0, PIN_GLOBAL | PIN_OFFSET_BIAS | i915->ggtt.vm.total),
-               NOSPACE(8192, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_BIAS | (i915->ggtt.mappable_end - 4096)),
-               NOSPACE(8192, PIN_GLOBAL | PIN_OFFSET_BIAS | (i915->ggtt.vm.total - 4096)),
+               NOSPACE(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_BIAS | ggtt->mappable_end),
+               NOSPACE(0, PIN_GLOBAL | PIN_OFFSET_BIAS | ggtt->vm.total),
+               NOSPACE(8192, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_BIAS | (ggtt->mappable_end - 4096)),
+               NOSPACE(8192, PIN_GLOBAL | PIN_OFFSET_BIAS | (ggtt->vm.total - 4096)),
 #endif
                { },
 #undef NOSPACE
@@ -306,13 +308,13 @@ static int igt_vma_pin1(void *arg)
         * focusing on error handling of boundary conditions.
         */
 
-       GEM_BUG_ON(!drm_mm_clean(&i915->ggtt.vm.mm));
+       GEM_BUG_ON(!drm_mm_clean(&ggtt->vm.mm));
 
-       obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
+       obj = i915_gem_object_create_internal(ggtt->vm.i915, PAGE_SIZE);
        if (IS_ERR(obj))
                return PTR_ERR(obj);
 
-       vma = checked_vma_instance(obj, &i915->ggtt.vm, NULL);
+       vma = checked_vma_instance(obj, &ggtt->vm, NULL);
        if (IS_ERR(vma))
                goto out;
 
@@ -403,8 +405,8 @@ static unsigned int rotated_size(const struct intel_rotation_plane_info *a,
 
 static int igt_vma_rotate(void *arg)
 {
-       struct drm_i915_private *i915 = arg;
-       struct i915_address_space *vm = &i915->ggtt.vm;
+       struct i915_ggtt *ggtt = arg;
+       struct i915_address_space *vm = &ggtt->vm;
        struct drm_i915_gem_object *obj;
        const struct intel_rotation_plane_info planes[] = {
                { .width = 1, .height = 1, .stride = 1 },
@@ -431,7 +433,7 @@ static int igt_vma_rotate(void *arg)
         * that the page layout within the rotated VMA match our expectations.
         */
 
-       obj = i915_gem_object_create_internal(i915, max_pages * PAGE_SIZE);
+       obj = i915_gem_object_create_internal(vm->i915, max_pages * PAGE_SIZE);
        if (IS_ERR(obj))
                goto out;
 
@@ -602,8 +604,8 @@ static bool assert_pin(struct i915_vma *vma,
 
 static int igt_vma_partial(void *arg)
 {
-       struct drm_i915_private *i915 = arg;
-       struct i915_address_space *vm = &i915->ggtt.vm;
+       struct i915_ggtt *ggtt = arg;
+       struct i915_address_space *vm = &ggtt->vm;
        const unsigned int npages = 1021; /* prime! */
        struct drm_i915_gem_object *obj;
        const struct phase {
@@ -621,7 +623,7 @@ static int igt_vma_partial(void *arg)
         * we are returned the same VMA when we later request the same range.
         */
 
-       obj = i915_gem_object_create_internal(i915, npages*PAGE_SIZE);
+       obj = i915_gem_object_create_internal(vm->i915, npages * PAGE_SIZE);
        if (IS_ERR(obj))
                goto out;
 
@@ -723,17 +725,24 @@ int i915_vma_mock_selftests(void)
                SUBTEST(igt_vma_partial),
        };
        struct drm_i915_private *i915;
+       struct i915_ggtt ggtt;
        int err;
 
        i915 = mock_gem_device();
        if (!i915)
                return -ENOMEM;
 
+       mock_init_ggtt(i915, &ggtt);
+
        mutex_lock(&i915->drm.struct_mutex);
-       err = i915_subtests(tests, i915);
+       err = i915_subtests(tests, &ggtt);
+       mock_device_flush(i915);
        mutex_unlock(&i915->drm.struct_mutex);
 
+       i915_gem_drain_freed_objects(i915);
+
+       mock_fini_ggtt(&ggtt);
        drm_dev_put(&i915->drm);
+
        return err;
 }
-
diff --git a/drivers/gpu/drm/i915/selftests/igt_live_test.c b/drivers/gpu/drm/i915/selftests/igt_live_test.c
new file mode 100644 (file)
index 0000000..5deb485
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright Â© 2018 Intel Corporation
+ */
+
+#include "../i915_drv.h"
+
+#include "../i915_selftest.h"
+#include "igt_flush_test.h"
+#include "igt_live_test.h"
+
+int igt_live_test_begin(struct igt_live_test *t,
+                       struct drm_i915_private *i915,
+                       const char *func,
+                       const char *name)
+{
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
+       int err;
+
+       lockdep_assert_held(&i915->drm.struct_mutex);
+
+       t->i915 = i915;
+       t->func = func;
+       t->name = name;
+
+       err = i915_gem_wait_for_idle(i915,
+                                    I915_WAIT_INTERRUPTIBLE |
+                                    I915_WAIT_LOCKED,
+                                    MAX_SCHEDULE_TIMEOUT);
+       if (err) {
+               pr_err("%s(%s): failed to idle before, with err=%d!",
+                      func, name, err);
+               return err;
+       }
+
+       i915->gpu_error.missed_irq_rings = 0;
+       t->reset_global = i915_reset_count(&i915->gpu_error);
+
+       for_each_engine(engine, i915, id)
+               t->reset_engine[id] =
+                       i915_reset_engine_count(&i915->gpu_error, engine);
+
+       return 0;
+}
+
+int igt_live_test_end(struct igt_live_test *t)
+{
+       struct drm_i915_private *i915 = t->i915;
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
+
+       lockdep_assert_held(&i915->drm.struct_mutex);
+
+       if (igt_flush_test(i915, I915_WAIT_LOCKED))
+               return -EIO;
+
+       if (t->reset_global != i915_reset_count(&i915->gpu_error)) {
+               pr_err("%s(%s): GPU was reset %d times!\n",
+                      t->func, t->name,
+                      i915_reset_count(&i915->gpu_error) - t->reset_global);
+               return -EIO;
+       }
+
+       for_each_engine(engine, i915, id) {
+               if (t->reset_engine[id] ==
+                   i915_reset_engine_count(&i915->gpu_error, engine))
+                       continue;
+
+               pr_err("%s(%s): engine '%s' was reset %d times!\n",
+                      t->func, t->name, engine->name,
+                      i915_reset_engine_count(&i915->gpu_error, engine) -
+                      t->reset_engine[id]);
+               return -EIO;
+       }
+
+       if (i915->gpu_error.missed_irq_rings) {
+               pr_err("%s(%s): Missed interrupts on engines %lx\n",
+                      t->func, t->name, i915->gpu_error.missed_irq_rings);
+               return -EIO;
+       }
+
+       return 0;
+}
diff --git a/drivers/gpu/drm/i915/selftests/igt_live_test.h b/drivers/gpu/drm/i915/selftests/igt_live_test.h
new file mode 100644 (file)
index 0000000..c0e9f99
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright Â© 2019 Intel Corporation
+ */
+
+#ifndef IGT_LIVE_TEST_H
+#define IGT_LIVE_TEST_H
+
+#include "../i915_gem.h"
+
+struct drm_i915_private;
+
+struct igt_live_test {
+       struct drm_i915_private *i915;
+       const char *func;
+       const char *name;
+
+       unsigned int reset_global;
+       unsigned int reset_engine[I915_NUM_ENGINES];
+};
+
+/*
+ * Flush the GPU state before and after the test to ensure that no residual
+ * code is running on the GPU that may affect this test. Also compare the
+ * state before and after the test and alert if it unexpectedly changes,
+ * e.g. if the GPU was reset.
+ */
+int igt_live_test_begin(struct igt_live_test *t,
+                       struct drm_i915_private *i915,
+                       const char *func,
+                       const char *name);
+int igt_live_test_end(struct igt_live_test *t);
+
+#endif /* IGT_LIVE_TEST_H */
index 8cd34f6e6859d6882b0c2ac11b78d8566a8996c8..0e70df0230b83c1c9a976b8ae1937c3aef344868 100644 (file)
@@ -68,48 +68,65 @@ static u64 hws_address(const struct i915_vma *hws,
        return hws->node.start + seqno_offset(rq->fence.context);
 }
 
-static int emit_recurse_batch(struct igt_spinner *spin,
-                             struct i915_request *rq,
-                             u32 arbitration_command)
+static int move_to_active(struct i915_vma *vma,
+                         struct i915_request *rq,
+                         unsigned int flags)
 {
-       struct i915_address_space *vm = &rq->gem_context->ppgtt->vm;
+       int err;
+
+       err = i915_vma_move_to_active(vma, rq, flags);
+       if (err)
+               return err;
+
+       if (!i915_gem_object_has_active_reference(vma->obj)) {
+               i915_gem_object_get(vma->obj);
+               i915_gem_object_set_active_reference(vma->obj);
+       }
+
+       return 0;
+}
+
+struct i915_request *
+igt_spinner_create_request(struct igt_spinner *spin,
+                          struct i915_gem_context *ctx,
+                          struct intel_engine_cs *engine,
+                          u32 arbitration_command)
+{
+       struct i915_address_space *vm = &ctx->ppgtt->vm;
+       struct i915_request *rq = NULL;
        struct i915_vma *hws, *vma;
        u32 *batch;
        int err;
 
        vma = i915_vma_instance(spin->obj, vm, NULL);
        if (IS_ERR(vma))
-               return PTR_ERR(vma);
+               return ERR_CAST(vma);
 
        hws = i915_vma_instance(spin->hws, vm, NULL);
        if (IS_ERR(hws))
-               return PTR_ERR(hws);
+               return ERR_CAST(hws);
 
        err = i915_vma_pin(vma, 0, 0, PIN_USER);
        if (err)
-               return err;
+               return ERR_PTR(err);
 
        err = i915_vma_pin(hws, 0, 0, PIN_USER);
        if (err)
                goto unpin_vma;
 
-       err = i915_vma_move_to_active(vma, rq, 0);
-       if (err)
+       rq = i915_request_alloc(engine, ctx);
+       if (IS_ERR(rq)) {
+               err = PTR_ERR(rq);
                goto unpin_hws;
-
-       if (!i915_gem_object_has_active_reference(vma->obj)) {
-               i915_gem_object_get(vma->obj);
-               i915_gem_object_set_active_reference(vma->obj);
        }
 
-       err = i915_vma_move_to_active(hws, rq, 0);
+       err = move_to_active(vma, rq, 0);
        if (err)
-               goto unpin_hws;
+               goto cancel_rq;
 
-       if (!i915_gem_object_has_active_reference(hws->obj)) {
-               i915_gem_object_get(hws->obj);
-               i915_gem_object_set_active_reference(hws->obj);
-       }
+       err = move_to_active(hws, rq, 0);
+       if (err)
+               goto cancel_rq;
 
        batch = spin->batch;
 
@@ -127,35 +144,18 @@ static int emit_recurse_batch(struct igt_spinner *spin,
 
        i915_gem_chipset_flush(spin->i915);
 
-       err = rq->engine->emit_bb_start(rq, vma->node.start, PAGE_SIZE, 0);
+       err = engine->emit_bb_start(rq, vma->node.start, PAGE_SIZE, 0);
 
+cancel_rq:
+       if (err) {
+               i915_request_skip(rq, err);
+               i915_request_add(rq);
+       }
 unpin_hws:
        i915_vma_unpin(hws);
 unpin_vma:
        i915_vma_unpin(vma);
-       return err;
-}
-
-struct i915_request *
-igt_spinner_create_request(struct igt_spinner *spin,
-                          struct i915_gem_context *ctx,
-                          struct intel_engine_cs *engine,
-                          u32 arbitration_command)
-{
-       struct i915_request *rq;
-       int err;
-
-       rq = i915_request_alloc(engine, ctx);
-       if (IS_ERR(rq))
-               return rq;
-
-       err = emit_recurse_batch(spin, rq, arbitration_command);
-       if (err) {
-               i915_request_add(rq);
-               return ERR_PTR(err);
-       }
-
-       return rq;
+       return err ? ERR_PTR(err) : rq;
 }
 
 static u32
index 32cba4cae31afad754a8e66df51bd01bdaff19cf..c5e0a0e98fcb16d499b082357f99a48a27359011 100644 (file)
@@ -137,12 +137,13 @@ static bool client_doorbell_in_sync(struct intel_guc_client *client)
 static int igt_guc_clients(void *args)
 {
        struct drm_i915_private *dev_priv = args;
+       intel_wakeref_t wakeref;
        struct intel_guc *guc;
        int err = 0;
 
        GEM_BUG_ON(!HAS_GUC(dev_priv));
        mutex_lock(&dev_priv->drm.struct_mutex);
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
        guc = &dev_priv->guc;
        if (!guc) {
@@ -225,7 +226,7 @@ out:
        guc_clients_create(guc);
        guc_clients_enable(guc);
 unlock:
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
        mutex_unlock(&dev_priv->drm.struct_mutex);
        return err;
 }
@@ -238,13 +239,14 @@ unlock:
 static int igt_guc_doorbells(void *arg)
 {
        struct drm_i915_private *dev_priv = arg;
+       intel_wakeref_t wakeref;
        struct intel_guc *guc;
        int i, err = 0;
        u16 db_id;
 
        GEM_BUG_ON(!HAS_GUC(dev_priv));
        mutex_lock(&dev_priv->drm.struct_mutex);
-       intel_runtime_pm_get(dev_priv);
+       wakeref = intel_runtime_pm_get(dev_priv);
 
        guc = &dev_priv->guc;
        if (!guc) {
@@ -337,7 +339,7 @@ out:
                        guc_client_free(clients[i]);
                }
 unlock:
-       intel_runtime_pm_put(dev_priv);
+       intel_runtime_pm_put(dev_priv, wakeref);
        mutex_unlock(&dev_priv->drm.struct_mutex);
        return err;
 }
index 40efbed611de8d80e8734e223d91fd5604e1d4f3..12550b55c42facd6b0792282d7b2a988d986f11d 100644 (file)
@@ -103,52 +103,87 @@ static u64 hws_address(const struct i915_vma *hws,
        return hws->node.start + offset_in_page(sizeof(u32)*rq->fence.context);
 }
 
-static int emit_recurse_batch(struct hang *h,
-                             struct i915_request *rq)
+static int move_to_active(struct i915_vma *vma,
+                         struct i915_request *rq,
+                         unsigned int flags)
+{
+       int err;
+
+       err = i915_vma_move_to_active(vma, rq, flags);
+       if (err)
+               return err;
+
+       if (!i915_gem_object_has_active_reference(vma->obj)) {
+               i915_gem_object_get(vma->obj);
+               i915_gem_object_set_active_reference(vma->obj);
+       }
+
+       return 0;
+}
+
+static struct i915_request *
+hang_create_request(struct hang *h, struct intel_engine_cs *engine)
 {
        struct drm_i915_private *i915 = h->i915;
        struct i915_address_space *vm =
-               rq->gem_context->ppgtt ?
-               &rq->gem_context->ppgtt->vm :
-               &i915->ggtt.vm;
+               h->ctx->ppgtt ? &h->ctx->ppgtt->vm : &i915->ggtt.vm;
+       struct i915_request *rq = NULL;
        struct i915_vma *hws, *vma;
        unsigned int flags;
        u32 *batch;
        int err;
 
+       if (i915_gem_object_is_active(h->obj)) {
+               struct drm_i915_gem_object *obj;
+               void *vaddr;
+
+               obj = i915_gem_object_create_internal(h->i915, PAGE_SIZE);
+               if (IS_ERR(obj))
+                       return ERR_CAST(obj);
+
+               vaddr = i915_gem_object_pin_map(obj,
+                                               i915_coherent_map_type(h->i915));
+               if (IS_ERR(vaddr)) {
+                       i915_gem_object_put(obj);
+                       return ERR_CAST(vaddr);
+               }
+
+               i915_gem_object_unpin_map(h->obj);
+               i915_gem_object_put(h->obj);
+
+               h->obj = obj;
+               h->batch = vaddr;
+       }
+
        vma = i915_vma_instance(h->obj, vm, NULL);
        if (IS_ERR(vma))
-               return PTR_ERR(vma);
+               return ERR_CAST(vma);
 
        hws = i915_vma_instance(h->hws, vm, NULL);
        if (IS_ERR(hws))
-               return PTR_ERR(hws);
+               return ERR_CAST(hws);
 
        err = i915_vma_pin(vma, 0, 0, PIN_USER);
        if (err)
-               return err;
+               return ERR_PTR(err);
 
        err = i915_vma_pin(hws, 0, 0, PIN_USER);
        if (err)
                goto unpin_vma;
 
-       err = i915_vma_move_to_active(vma, rq, 0);
-       if (err)
+       rq = i915_request_alloc(engine, h->ctx);
+       if (IS_ERR(rq)) {
+               err = PTR_ERR(rq);
                goto unpin_hws;
-
-       if (!i915_gem_object_has_active_reference(vma->obj)) {
-               i915_gem_object_get(vma->obj);
-               i915_gem_object_set_active_reference(vma->obj);
        }
 
-       err = i915_vma_move_to_active(hws, rq, 0);
+       err = move_to_active(vma, rq, 0);
        if (err)
-               goto unpin_hws;
+               goto cancel_rq;
 
-       if (!i915_gem_object_has_active_reference(hws->obj)) {
-               i915_gem_object_get(hws->obj);
-               i915_gem_object_set_active_reference(hws->obj);
-       }
+       err = move_to_active(hws, rq, 0);
+       if (err)
+               goto cancel_rq;
 
        batch = h->batch;
        if (INTEL_GEN(i915) >= 8) {
@@ -213,52 +248,16 @@ static int emit_recurse_batch(struct hang *h,
 
        err = rq->engine->emit_bb_start(rq, vma->node.start, PAGE_SIZE, flags);
 
+cancel_rq:
+       if (err) {
+               i915_request_skip(rq, err);
+               i915_request_add(rq);
+       }
 unpin_hws:
        i915_vma_unpin(hws);
 unpin_vma:
        i915_vma_unpin(vma);
-       return err;
-}
-
-static struct i915_request *
-hang_create_request(struct hang *h, struct intel_engine_cs *engine)
-{
-       struct i915_request *rq;
-       int err;
-
-       if (i915_gem_object_is_active(h->obj)) {
-               struct drm_i915_gem_object *obj;
-               void *vaddr;
-
-               obj = i915_gem_object_create_internal(h->i915, PAGE_SIZE);
-               if (IS_ERR(obj))
-                       return ERR_CAST(obj);
-
-               vaddr = i915_gem_object_pin_map(obj,
-                                               i915_coherent_map_type(h->i915));
-               if (IS_ERR(vaddr)) {
-                       i915_gem_object_put(obj);
-                       return ERR_CAST(vaddr);
-               }
-
-               i915_gem_object_unpin_map(h->obj);
-               i915_gem_object_put(h->obj);
-
-               h->obj = obj;
-               h->batch = vaddr;
-       }
-
-       rq = i915_request_alloc(engine, h->ctx);
-       if (IS_ERR(rq))
-               return rq;
-
-       err = emit_recurse_batch(h, rq);
-       if (err) {
-               i915_request_add(rq);
-               return ERR_PTR(err);
-       }
-
-       return rq;
+       return err ? ERR_PTR(err) : rq;
 }
 
 static u32 hws_seqno(const struct hang *h, const struct i915_request *rq)
@@ -386,6 +385,31 @@ static int igt_global_reset(void *arg)
        return err;
 }
 
+static int igt_wedged_reset(void *arg)
+{
+       struct drm_i915_private *i915 = arg;
+       intel_wakeref_t wakeref;
+
+       /* Check that we can recover a wedged device with a GPU reset */
+
+       igt_global_reset_lock(i915);
+       mutex_lock(&i915->drm.struct_mutex);
+       wakeref = intel_runtime_pm_get(i915);
+
+       i915_gem_set_wedged(i915);
+       GEM_BUG_ON(!i915_terminally_wedged(&i915->gpu_error));
+
+       set_bit(I915_RESET_HANDOFF, &i915->gpu_error.flags);
+       i915_reset(i915, ALL_ENGINES, NULL);
+       GEM_BUG_ON(test_bit(I915_RESET_HANDOFF, &i915->gpu_error.flags));
+
+       intel_runtime_pm_put(i915, wakeref);
+       mutex_unlock(&i915->drm.struct_mutex);
+       igt_global_reset_unlock(i915);
+
+       return i915_terminally_wedged(&i915->gpu_error) ? -EIO : 0;
+}
+
 static bool wait_for_idle(struct intel_engine_cs *engine)
 {
        return wait_for(intel_engine_is_idle(engine), IGT_IDLE_TIMEOUT) == 0;
@@ -451,7 +475,7 @@ static int __igt_reset_engine(struct drm_i915_private *i915, bool active)
                                if (!wait_until_running(&h, rq)) {
                                        struct drm_printer p = drm_info_printer(i915->drm.dev);
 
-                                       pr_err("%s: Failed to start request %x, at %x\n",
+                                       pr_err("%s: Failed to start request %llx, at %x\n",
                                               __func__, rq->fence.seqno, hws_seqno(&h, rq));
                                        intel_engine_dump(engine, &p,
                                                          "%s\n", engine->name);
@@ -552,7 +576,7 @@ static int active_request_put(struct i915_request *rq)
                return 0;
 
        if (i915_request_wait(rq, 0, 5 * HZ) < 0) {
-               GEM_TRACE("%s timed out waiting for completion of fence %llx:%d, seqno %d.\n",
+               GEM_TRACE("%s timed out waiting for completion of fence %llx:%lld, seqno %d.\n",
                          rq->engine->name,
                          rq->fence.context,
                          rq->fence.seqno,
@@ -729,7 +753,7 @@ static int __igt_reset_engines(struct drm_i915_private *i915,
                                if (!wait_until_running(&h, rq)) {
                                        struct drm_printer p = drm_info_printer(i915->drm.dev);
 
-                                       pr_err("%s: Failed to start request %x, at %x\n",
+                                       pr_err("%s: Failed to start request %llx, at %x\n",
                                               __func__, rq->fence.seqno, hws_seqno(&h, rq));
                                        intel_engine_dump(engine, &p,
                                                          "%s\n", engine->name);
@@ -928,7 +952,7 @@ static int igt_reset_wait(void *arg)
        if (!wait_until_running(&h, rq)) {
                struct drm_printer p = drm_info_printer(i915->drm.dev);
 
-               pr_err("%s: Failed to start request %x, at %x\n",
+               pr_err("%s: Failed to start request %llx, at %x\n",
                       __func__, rq->fence.seqno, hws_seqno(&h, rq));
                intel_engine_dump(rq->engine, &p, "%s\n", rq->engine->name);
 
@@ -1107,7 +1131,7 @@ static int __igt_reset_evict_vma(struct drm_i915_private *i915,
        if (!wait_until_running(&h, rq)) {
                struct drm_printer p = drm_info_printer(i915->drm.dev);
 
-               pr_err("%s: Failed to start request %x, at %x\n",
+               pr_err("%s: Failed to start request %llx, at %x\n",
                       __func__, rq->fence.seqno, hws_seqno(&h, rq));
                intel_engine_dump(rq->engine, &p, "%s\n", rq->engine->name);
 
@@ -1302,7 +1326,7 @@ static int igt_reset_queue(void *arg)
                        if (!wait_until_running(&h, prev)) {
                                struct drm_printer p = drm_info_printer(i915->drm.dev);
 
-                               pr_err("%s(%s): Failed to start request %x, at %x\n",
+                               pr_err("%s(%s): Failed to start request %llx, at %x\n",
                                       __func__, engine->name,
                                       prev->fence.seqno, hws_seqno(&h, prev));
                                intel_engine_dump(engine, &p,
@@ -1413,7 +1437,7 @@ static int igt_handle_error(void *arg)
        if (!wait_until_running(&h, rq)) {
                struct drm_printer p = drm_info_printer(i915->drm.dev);
 
-               pr_err("%s: Failed to start request %x, at %x\n",
+               pr_err("%s: Failed to start request %llx, at %x\n",
                       __func__, rq->fence.seqno, hws_seqno(&h, rq));
                intel_engine_dump(rq->engine, &p, "%s\n", rq->engine->name);
 
@@ -1449,10 +1473,183 @@ err_unlock:
        return err;
 }
 
+static void __preempt_begin(void)
+{
+       preempt_disable();
+}
+
+static void __preempt_end(void)
+{
+       preempt_enable();
+}
+
+static void __softirq_begin(void)
+{
+       local_bh_disable();
+}
+
+static void __softirq_end(void)
+{
+       local_bh_enable();
+}
+
+static void __hardirq_begin(void)
+{
+       local_irq_disable();
+}
+
+static void __hardirq_end(void)
+{
+       local_irq_enable();
+}
+
+struct atomic_section {
+       const char *name;
+       void (*critical_section_begin)(void);
+       void (*critical_section_end)(void);
+};
+
+static int __igt_atomic_reset_engine(struct intel_engine_cs *engine,
+                                    const struct atomic_section *p,
+                                    const char *mode)
+{
+       struct tasklet_struct * const t = &engine->execlists.tasklet;
+       int err;
+
+       GEM_TRACE("i915_reset_engine(%s:%s) under %s\n",
+                 engine->name, mode, p->name);
+
+       tasklet_disable_nosync(t);
+       p->critical_section_begin();
+
+       err = i915_reset_engine(engine, NULL);
+
+       p->critical_section_end();
+       tasklet_enable(t);
+
+       if (err)
+               pr_err("i915_reset_engine(%s:%s) failed under %s\n",
+                      engine->name, mode, p->name);
+
+       return err;
+}
+
+static int igt_atomic_reset_engine(struct intel_engine_cs *engine,
+                                  const struct atomic_section *p)
+{
+       struct drm_i915_private *i915 = engine->i915;
+       struct i915_request *rq;
+       struct hang h;
+       int err;
+
+       err = __igt_atomic_reset_engine(engine, p, "idle");
+       if (err)
+               return err;
+
+       err = hang_init(&h, i915);
+       if (err)
+               return err;
+
+       rq = hang_create_request(&h, engine);
+       if (IS_ERR(rq)) {
+               err = PTR_ERR(rq);
+               goto out;
+       }
+
+       i915_request_get(rq);
+       i915_request_add(rq);
+
+       if (wait_until_running(&h, rq)) {
+               err = __igt_atomic_reset_engine(engine, p, "active");
+       } else {
+               pr_err("%s(%s): Failed to start request %llx, at %x\n",
+                      __func__, engine->name,
+                      rq->fence.seqno, hws_seqno(&h, rq));
+               err = -EIO;
+       }
+
+       if (err == 0) {
+               struct igt_wedge_me w;
+
+               igt_wedge_on_timeout(&w, i915, HZ / 20 /* 50ms timeout*/)
+                       i915_request_wait(rq,
+                                         I915_WAIT_LOCKED,
+                                         MAX_SCHEDULE_TIMEOUT);
+               if (i915_terminally_wedged(&i915->gpu_error))
+                       err = -EIO;
+       }
+
+       i915_request_put(rq);
+out:
+       hang_fini(&h);
+       return err;
+}
+
+static void force_reset(struct drm_i915_private *i915)
+{
+       i915_gem_set_wedged(i915);
+       set_bit(I915_RESET_HANDOFF, &i915->gpu_error.flags);
+       i915_reset(i915, 0, NULL);
+}
+
+static int igt_atomic_reset(void *arg)
+{
+       static const struct atomic_section phases[] = {
+               { "preempt", __preempt_begin, __preempt_end },
+               { "softirq", __softirq_begin, __softirq_end },
+               { "hardirq", __hardirq_begin, __hardirq_end },
+               { }
+       };
+       struct drm_i915_private *i915 = arg;
+       intel_wakeref_t wakeref;
+       int err = 0;
+
+       /* Check that the resets are usable from atomic context */
+
+       if (USES_GUC_SUBMISSION(i915))
+               return 0; /* guc is dead; long live the guc */
+
+       igt_global_reset_lock(i915);
+       mutex_lock(&i915->drm.struct_mutex);
+       wakeref = intel_runtime_pm_get(i915);
+
+       /* Flush any requests before we get started and check basics */
+       force_reset(i915);
+       if (i915_terminally_wedged(&i915->gpu_error))
+               goto unlock;
+
+       if (intel_has_reset_engine(i915)) {
+               struct intel_engine_cs *engine;
+               enum intel_engine_id id;
+
+               for_each_engine(engine, i915, id) {
+                       const typeof(*phases) *p;
+
+                       for (p = phases; p->name; p++) {
+                               err = igt_atomic_reset_engine(engine, p);
+                               if (err)
+                                       goto out;
+                       }
+               }
+       }
+
+out:
+       /* As we poke around the guts, do a full reset before continuing. */
+       force_reset(i915);
+
+unlock:
+       intel_runtime_pm_put(i915, wakeref);
+       mutex_unlock(&i915->drm.struct_mutex);
+       igt_global_reset_unlock(i915);
+
+       return err;
+}
+
 int intel_hangcheck_live_selftests(struct drm_i915_private *i915)
 {
        static const struct i915_subtest tests[] = {
                SUBTEST(igt_global_reset), /* attempt to recover GPU first */
+               SUBTEST(igt_wedged_reset),
                SUBTEST(igt_hang_sanitycheck),
                SUBTEST(igt_reset_idle_engine),
                SUBTEST(igt_reset_active_engine),
@@ -1463,7 +1660,9 @@ int intel_hangcheck_live_selftests(struct drm_i915_private *i915)
                SUBTEST(igt_reset_evict_ppgtt),
                SUBTEST(igt_reset_evict_fence),
                SUBTEST(igt_handle_error),
+               SUBTEST(igt_atomic_reset),
        };
+       intel_wakeref_t wakeref;
        bool saved_hangcheck;
        int err;
 
@@ -1473,7 +1672,7 @@ int intel_hangcheck_live_selftests(struct drm_i915_private *i915)
        if (i915_terminally_wedged(&i915->gpu_error))
                return -EIO; /* we're long past hope of a successful reset */
 
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
        saved_hangcheck = fetch_and_zero(&i915_modparams.enable_hangcheck);
 
        err = i915_subtests(tests, i915);
@@ -1483,7 +1682,7 @@ int intel_hangcheck_live_selftests(struct drm_i915_private *i915)
        mutex_unlock(&i915->drm.struct_mutex);
 
        i915_modparams.enable_hangcheck = saved_hangcheck;
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
 
        return err;
 }
index ca461e3a5f27ffe8bd85b9f0dc4e17078ff5468d..2b2ecd76c2ac2efdf40fc91519c7aa30e6c9989f 100644 (file)
@@ -4,6 +4,8 @@
  * Copyright Â© 2018 Intel Corporation
  */
 
+#include "../i915_reset.h"
+
 #include "../i915_selftest.h"
 #include "igt_flush_test.h"
 #include "igt_spinner.h"
@@ -18,13 +20,14 @@ static int live_sanitycheck(void *arg)
        struct i915_gem_context *ctx;
        enum intel_engine_id id;
        struct igt_spinner spin;
+       intel_wakeref_t wakeref;
        int err = -ENOMEM;
 
        if (!HAS_LOGICAL_RING_CONTEXTS(i915))
                return 0;
 
        mutex_lock(&i915->drm.struct_mutex);
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
        if (igt_spinner_init(&spin, i915))
                goto err_unlock;
@@ -65,7 +68,7 @@ err_spin:
        igt_spinner_fini(&spin);
 err_unlock:
        igt_flush_test(i915, I915_WAIT_LOCKED);
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
        mutex_unlock(&i915->drm.struct_mutex);
        return err;
 }
@@ -77,13 +80,14 @@ static int live_preempt(void *arg)
        struct igt_spinner spin_hi, spin_lo;
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
+       intel_wakeref_t wakeref;
        int err = -ENOMEM;
 
        if (!HAS_LOGICAL_RING_PREEMPTION(i915))
                return 0;
 
        mutex_lock(&i915->drm.struct_mutex);
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
        if (igt_spinner_init(&spin_hi, i915))
                goto err_unlock;
@@ -158,7 +162,7 @@ err_spin_hi:
        igt_spinner_fini(&spin_hi);
 err_unlock:
        igt_flush_test(i915, I915_WAIT_LOCKED);
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
        mutex_unlock(&i915->drm.struct_mutex);
        return err;
 }
@@ -171,13 +175,14 @@ static int live_late_preempt(void *arg)
        struct intel_engine_cs *engine;
        struct i915_sched_attr attr = {};
        enum intel_engine_id id;
+       intel_wakeref_t wakeref;
        int err = -ENOMEM;
 
        if (!HAS_LOGICAL_RING_PREEMPTION(i915))
                return 0;
 
        mutex_lock(&i915->drm.struct_mutex);
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
        if (igt_spinner_init(&spin_hi, i915))
                goto err_unlock;
@@ -251,7 +256,7 @@ err_spin_hi:
        igt_spinner_fini(&spin_hi);
 err_unlock:
        igt_flush_test(i915, I915_WAIT_LOCKED);
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
        mutex_unlock(&i915->drm.struct_mutex);
        return err;
 
@@ -270,6 +275,7 @@ static int live_preempt_hang(void *arg)
        struct igt_spinner spin_hi, spin_lo;
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
+       intel_wakeref_t wakeref;
        int err = -ENOMEM;
 
        if (!HAS_LOGICAL_RING_PREEMPTION(i915))
@@ -279,7 +285,7 @@ static int live_preempt_hang(void *arg)
                return 0;
 
        mutex_lock(&i915->drm.struct_mutex);
-       intel_runtime_pm_get(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
        if (igt_spinner_init(&spin_hi, i915))
                goto err_unlock;
@@ -374,7 +380,7 @@ err_spin_hi:
        igt_spinner_fini(&spin_hi);
 err_unlock:
        igt_flush_test(i915, I915_WAIT_LOCKED);
-       intel_runtime_pm_put(i915);
+       intel_runtime_pm_put(i915, wakeref);
        mutex_unlock(&i915->drm.struct_mutex);
        return err;
 }
@@ -522,7 +528,7 @@ static int smoke_crescendo(struct preempt_smoke *smoke, unsigned int flags)
 
        pr_info("Submitted %lu crescendo:%x requests across %d engines and %d contexts\n",
                count, flags,
-               INTEL_INFO(smoke->i915)->num_rings, smoke->ncontext);
+               RUNTIME_INFO(smoke->i915)->num_rings, smoke->ncontext);
        return 0;
 }
 
@@ -550,7 +556,7 @@ static int smoke_random(struct preempt_smoke *smoke, unsigned int flags)
 
        pr_info("Submitted %lu random:%x requests across %d engines and %d contexts\n",
                count, flags,
-               INTEL_INFO(smoke->i915)->num_rings, smoke->ncontext);
+               RUNTIME_INFO(smoke->i915)->num_rings, smoke->ncontext);
        return 0;
 }
 
@@ -562,6 +568,7 @@ static int live_preempt_smoke(void *arg)
                .ncontext = 1024,
        };
        const unsigned int phase[] = { 0, BATCH };
+       intel_wakeref_t wakeref;
        int err = -ENOMEM;
        u32 *cs;
        int n;
@@ -576,7 +583,7 @@ static int live_preempt_smoke(void *arg)
                return -ENOMEM;
 
        mutex_lock(&smoke.i915->drm.struct_mutex);
-       intel_runtime_pm_get(smoke.i915);
+       wakeref = intel_runtime_pm_get(smoke.i915);
 
        smoke.batch = i915_gem_object_create_internal(smoke.i915, PAGE_SIZE);
        if (IS_ERR(smoke.batch)) {
@@ -627,7 +634,7 @@ err_ctx:
 err_batch:
        i915_gem_object_put(smoke.batch);
 err_unlock:
-       intel_runtime_pm_put(smoke.i915);
+       intel_runtime_pm_put(smoke.i915, wakeref);
        mutex_unlock(&smoke.i915->drm.struct_mutex);
        kfree(smoke.contexts);
 
index 67017d5175b8c6cfcb8c5df8b2a90314f517b621..a8cac56be83576b4ab133a7c7348f7a0dfe05b8c 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include "../i915_selftest.h"
+#include "../i915_reset.h"
 
 #include "igt_flush_test.h"
 #include "igt_reset.h"
 #include "igt_wedge_me.h"
 #include "mock_context.h"
 
+#define REF_NAME_MAX (INTEL_ENGINE_CS_MAX_NAME + 4)
+struct wa_lists {
+       struct i915_wa_list gt_wa_list;
+       struct {
+               char name[REF_NAME_MAX];
+               struct i915_wa_list wa_list;
+       } engine[I915_NUM_ENGINES];
+};
+
+static void
+reference_lists_init(struct drm_i915_private *i915, struct wa_lists *lists)
+{
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
+
+       memset(lists, 0, sizeof(*lists));
+
+       wa_init_start(&lists->gt_wa_list, "GT_REF");
+       gt_init_workarounds(i915, &lists->gt_wa_list);
+       wa_init_finish(&lists->gt_wa_list);
+
+       for_each_engine(engine, i915, id) {
+               struct i915_wa_list *wal = &lists->engine[id].wa_list;
+               char *name = lists->engine[id].name;
+
+               snprintf(name, REF_NAME_MAX, "%s_REF", engine->name);
+
+               wa_init_start(wal, name);
+               engine_init_workarounds(engine, wal);
+               wa_init_finish(wal);
+       }
+}
+
+static void
+reference_lists_fini(struct drm_i915_private *i915, struct wa_lists *lists)
+{
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
+
+       for_each_engine(engine, i915, id)
+               intel_wa_list_free(&lists->engine[id].wa_list);
+
+       intel_wa_list_free(&lists->gt_wa_list);
+}
+
 static struct drm_i915_gem_object *
 read_nonprivs(struct i915_gem_context *ctx, struct intel_engine_cs *engine)
 {
+       const u32 base = engine->mmio_base;
        struct drm_i915_gem_object *result;
+       intel_wakeref_t wakeref;
        struct i915_request *rq;
        struct i915_vma *vma;
-       const u32 base = engine->mmio_base;
        u32 srm, *cs;
        int err;
        int i;
@@ -47,9 +94,9 @@ read_nonprivs(struct i915_gem_context *ctx, struct intel_engine_cs *engine)
        if (err)
                goto err_obj;
 
-       intel_runtime_pm_get(engine->i915);
-       rq = i915_request_alloc(engine, ctx);
-       intel_runtime_pm_put(engine->i915);
+       rq = ERR_PTR(-ENODEV);
+       with_intel_runtime_pm(engine->i915, wakeref)
+               rq = i915_request_alloc(engine, ctx);
        if (IS_ERR(rq)) {
                err = PTR_ERR(rq);
                goto err_pin;
@@ -183,20 +230,22 @@ switch_to_scratch_context(struct intel_engine_cs *engine,
 {
        struct i915_gem_context *ctx;
        struct i915_request *rq;
+       intel_wakeref_t wakeref;
        int err = 0;
 
        ctx = kernel_context(engine->i915);
        if (IS_ERR(ctx))
                return PTR_ERR(ctx);
 
-       intel_runtime_pm_get(engine->i915);
-
-       if (spin)
-               rq = igt_spinner_create_request(spin, ctx, engine, MI_NOOP);
-       else
-               rq = i915_request_alloc(engine, ctx);
-
-       intel_runtime_pm_put(engine->i915);
+       rq = ERR_PTR(-ENODEV);
+       with_intel_runtime_pm(engine->i915, wakeref) {
+               if (spin)
+                       rq = igt_spinner_create_request(spin,
+                                                       ctx, engine,
+                                                       MI_NOOP);
+               else
+                       rq = i915_request_alloc(engine, ctx);
+       }
 
        kernel_context_close(ctx);
 
@@ -228,6 +277,7 @@ static int check_whitelist_across_reset(struct intel_engine_cs *engine,
        bool want_spin = reset == do_engine_reset;
        struct i915_gem_context *ctx;
        struct igt_spinner spin;
+       intel_wakeref_t wakeref;
        int err;
 
        pr_info("Checking %d whitelisted registers (RING_NONPRIV) [%s]\n",
@@ -253,9 +303,8 @@ static int check_whitelist_across_reset(struct intel_engine_cs *engine,
        if (err)
                goto out;
 
-       intel_runtime_pm_get(i915);
-       err = reset(engine);
-       intel_runtime_pm_put(i915);
+       with_intel_runtime_pm(i915, wakeref)
+               err = reset(engine);
 
        if (want_spin) {
                igt_spinner_end(&spin);
@@ -326,16 +375,17 @@ out:
        return err;
 }
 
-static bool verify_gt_engine_wa(struct drm_i915_private *i915, const char *str)
+static bool verify_gt_engine_wa(struct drm_i915_private *i915,
+                               struct wa_lists *lists, const char *str)
 {
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
        bool ok = true;
 
-       ok &= intel_gt_verify_workarounds(i915, str);
+       ok &= wa_list_verify(i915, &lists->gt_wa_list, str);
 
        for_each_engine(engine, i915, id)
-               ok &= intel_engine_verify_workarounds(engine, str);
+               ok &= wa_list_verify(i915, &lists->engine[id].wa_list, str);
 
        return ok;
 }
@@ -345,6 +395,8 @@ live_gpu_reset_gt_engine_workarounds(void *arg)
 {
        struct drm_i915_private *i915 = arg;
        struct i915_gpu_error *error = &i915->gpu_error;
+       intel_wakeref_t wakeref;
+       struct wa_lists lists;
        bool ok;
 
        if (!intel_has_gpu_reset(i915))
@@ -353,19 +405,22 @@ live_gpu_reset_gt_engine_workarounds(void *arg)
        pr_info("Verifying after GPU reset...\n");
 
        igt_global_reset_lock(i915);
+       wakeref = intel_runtime_pm_get(i915);
 
-       ok = verify_gt_engine_wa(i915, "before reset");
+       reference_lists_init(i915, &lists);
+
+       ok = verify_gt_engine_wa(i915, &lists, "before reset");
        if (!ok)
                goto out;
 
-       intel_runtime_pm_get(i915);
        set_bit(I915_RESET_HANDOFF, &error->flags);
        i915_reset(i915, ALL_ENGINES, "live_workarounds");
-       intel_runtime_pm_put(i915);
 
-       ok = verify_gt_engine_wa(i915, "after reset");
+       ok = verify_gt_engine_wa(i915, &lists, "after reset");
 
 out:
+       reference_lists_fini(i915, &lists);
+       intel_runtime_pm_put(i915, wakeref);
        igt_global_reset_unlock(i915);
 
        return ok ? 0 : -ESRCH;
@@ -380,6 +435,8 @@ live_engine_reset_gt_engine_workarounds(void *arg)
        struct igt_spinner spin;
        enum intel_engine_id id;
        struct i915_request *rq;
+       intel_wakeref_t wakeref;
+       struct wa_lists lists;
        int ret = 0;
 
        if (!intel_has_reset_engine(i915))
@@ -390,23 +447,24 @@ live_engine_reset_gt_engine_workarounds(void *arg)
                return PTR_ERR(ctx);
 
        igt_global_reset_lock(i915);
+       wakeref = intel_runtime_pm_get(i915);
+
+       reference_lists_init(i915, &lists);
 
        for_each_engine(engine, i915, id) {
                bool ok;
 
                pr_info("Verifying after %s reset...\n", engine->name);
 
-               ok = verify_gt_engine_wa(i915, "before reset");
+               ok = verify_gt_engine_wa(i915, &lists, "before reset");
                if (!ok) {
                        ret = -ESRCH;
                        goto err;
                }
 
-               intel_runtime_pm_get(i915);
                i915_reset_engine(engine, "live_workarounds");
-               intel_runtime_pm_put(i915);
 
-               ok = verify_gt_engine_wa(i915, "after idle reset");
+               ok = verify_gt_engine_wa(i915, &lists, "after idle reset");
                if (!ok) {
                        ret = -ESRCH;
                        goto err;
@@ -416,13 +474,10 @@ live_engine_reset_gt_engine_workarounds(void *arg)
                if (ret)
                        goto err;
 
-               intel_runtime_pm_get(i915);
-
                rq = igt_spinner_create_request(&spin, ctx, engine, MI_NOOP);
                if (IS_ERR(rq)) {
                        ret = PTR_ERR(rq);
                        igt_spinner_fini(&spin);
-                       intel_runtime_pm_put(i915);
                        goto err;
                }
 
@@ -431,19 +486,16 @@ live_engine_reset_gt_engine_workarounds(void *arg)
                if (!igt_wait_for_spinner(&spin, rq)) {
                        pr_err("Spinner failed to start\n");
                        igt_spinner_fini(&spin);
-                       intel_runtime_pm_put(i915);
                        ret = -ETIMEDOUT;
                        goto err;
                }
 
                i915_reset_engine(engine, "live_workarounds");
 
-               intel_runtime_pm_put(i915);
-
                igt_spinner_end(&spin);
                igt_spinner_fini(&spin);
 
-               ok = verify_gt_engine_wa(i915, "after busy reset");
+               ok = verify_gt_engine_wa(i915, &lists, "after busy reset");
                if (!ok) {
                        ret = -ESRCH;
                        goto err;
@@ -451,6 +503,8 @@ live_engine_reset_gt_engine_workarounds(void *arg)
        }
 
 err:
+       reference_lists_fini(i915, &lists);
+       intel_runtime_pm_put(i915, wakeref);
        igt_global_reset_unlock(i915);
        kernel_context_close(ctx);
 
index d937bdff26f99cec944a4550f02fddd3ad482772..b646cdcdd6029a95bace9ed5f537abcf28464abb 100644 (file)
@@ -45,11 +45,8 @@ mock_context(struct drm_i915_private *i915,
        INIT_LIST_HEAD(&ctx->handles_list);
        INIT_LIST_HEAD(&ctx->hw_id_link);
 
-       for (n = 0; n < ARRAY_SIZE(ctx->__engine); n++) {
-               struct intel_context *ce = &ctx->__engine[n];
-
-               ce->gem_context = ctx;
-       }
+       for (n = 0; n < ARRAY_SIZE(ctx->__engine); n++)
+               intel_context_init(&ctx->__engine[n], ctx, i915->engine[n]);
 
        ret = i915_gem_context_pin_hw_id(ctx);
        if (ret < 0)
index d0c44c18db429cd064c55dd51439ef01087c5779..442ec2aeec81def7708a334f9d88261f541f7607 100644 (file)
@@ -30,6 +30,36 @@ struct mock_ring {
        struct i915_timeline timeline;
 };
 
+static struct intel_ring *mock_ring(struct intel_engine_cs *engine)
+{
+       const unsigned long sz = PAGE_SIZE / 2;
+       struct mock_ring *ring;
+
+       ring = kzalloc(sizeof(*ring) + sz, GFP_KERNEL);
+       if (!ring)
+               return NULL;
+
+       i915_timeline_init(engine->i915, &ring->timeline, engine->name);
+
+       ring->base.size = sz;
+       ring->base.effective_size = sz;
+       ring->base.vaddr = (void *)(ring + 1);
+       ring->base.timeline = &ring->timeline;
+
+       INIT_LIST_HEAD(&ring->base.request_list);
+       intel_ring_update_space(&ring->base);
+
+       return &ring->base;
+}
+
+static void mock_ring_free(struct intel_ring *base)
+{
+       struct mock_ring *ring = container_of(base, typeof(*ring), base);
+
+       i915_timeline_fini(&ring->timeline);
+       kfree(ring);
+}
+
 static struct mock_request *first_request(struct mock_engine *engine)
 {
        return list_first_entry_or_null(&engine->hw_queue,
@@ -37,11 +67,10 @@ static struct mock_request *first_request(struct mock_engine *engine)
                                        link);
 }
 
-static void advance(struct mock_engine *engine,
-                   struct mock_request *request)
+static void advance(struct mock_request *request)
 {
        list_del_init(&request->link);
-       mock_seqno_advance(&engine->base, request->base.global_seqno);
+       mock_seqno_advance(request->base.engine, request->base.global_seqno);
 }
 
 static void hw_delay_complete(struct timer_list *t)
@@ -54,7 +83,7 @@ static void hw_delay_complete(struct timer_list *t)
        /* Timer fired, first request is complete */
        request = first_request(engine);
        if (request)
-               advance(engine, request);
+               advance(request);
 
        /*
         * Also immediately signal any subsequent 0-delay requests, but
@@ -66,7 +95,7 @@ static void hw_delay_complete(struct timer_list *t)
                        break;
                }
 
-               advance(engine, request);
+               advance(request);
        }
 
        spin_unlock(&engine->hw_lock);
@@ -80,6 +109,9 @@ static void mock_context_unpin(struct intel_context *ce)
 static void mock_context_destroy(struct intel_context *ce)
 {
        GEM_BUG_ON(ce->pin_count);
+
+       if (ce->ring)
+               mock_ring_free(ce->ring);
 }
 
 static const struct intel_context_ops mock_context_ops = {
@@ -93,13 +125,22 @@ mock_context_pin(struct intel_engine_cs *engine,
 {
        struct intel_context *ce = to_intel_context(ctx, engine);
 
-       if (!ce->pin_count++) {
-               i915_gem_context_get(ctx);
-               ce->ring = engine->buffer;
-               ce->ops = &mock_context_ops;
+       if (ce->pin_count++)
+               return ce;
+
+       if (!ce->ring) {
+               ce->ring = mock_ring(engine);
+               if (!ce->ring)
+                       goto err;
        }
 
+       ce->ops = &mock_context_ops;
+       i915_gem_context_get(ctx);
        return ce;
+
+err:
+       ce->pin_count = 0;
+       return ERR_PTR(-ENOMEM);
 }
 
 static int mock_request_alloc(struct i915_request *request)
@@ -138,43 +179,11 @@ static void mock_submit_request(struct i915_request *request)
                if (mock->delay)
                        mod_timer(&engine->hw_delay, jiffies + mock->delay);
                else
-                       advance(engine, mock);
+                       advance(mock);
        }
        spin_unlock_irq(&engine->hw_lock);
 }
 
-static struct intel_ring *mock_ring(struct intel_engine_cs *engine)
-{
-       const unsigned long sz = PAGE_SIZE / 2;
-       struct mock_ring *ring;
-
-       BUILD_BUG_ON(MIN_SPACE_FOR_ADD_REQUEST > sz);
-
-       ring = kzalloc(sizeof(*ring) + sz, GFP_KERNEL);
-       if (!ring)
-               return NULL;
-
-       i915_timeline_init(engine->i915, &ring->timeline, engine->name);
-
-       ring->base.size = sz;
-       ring->base.effective_size = sz;
-       ring->base.vaddr = (void *)(ring + 1);
-       ring->base.timeline = &ring->timeline;
-
-       INIT_LIST_HEAD(&ring->base.request_list);
-       intel_ring_update_space(&ring->base);
-
-       return &ring->base;
-}
-
-static void mock_ring_free(struct intel_ring *base)
-{
-       struct mock_ring *ring = container_of(base, typeof(*ring), base);
-
-       i915_timeline_fini(&ring->timeline);
-       kfree(ring);
-}
-
 struct intel_engine_cs *mock_engine(struct drm_i915_private *i915,
                                    const char *name,
                                    int id)
@@ -203,24 +212,17 @@ struct intel_engine_cs *mock_engine(struct drm_i915_private *i915,
        i915_timeline_set_subclass(&engine->base.timeline, TIMELINE_ENGINE);
 
        intel_engine_init_breadcrumbs(&engine->base);
-       engine->base.breadcrumbs.mock = true; /* prevent touching HW for irqs */
 
        /* fake hw queue */
        spin_lock_init(&engine->hw_lock);
        timer_setup(&engine->hw_delay, hw_delay_complete, 0);
        INIT_LIST_HEAD(&engine->hw_queue);
 
-       engine->base.buffer = mock_ring(&engine->base);
-       if (!engine->base.buffer)
-               goto err_breadcrumbs;
-
        if (IS_ERR(intel_context_pin(i915->kernel_context, &engine->base)))
-               goto err_ring;
+               goto err_breadcrumbs;
 
        return &engine->base;
 
-err_ring:
-       mock_ring_free(engine->base.buffer);
 err_breadcrumbs:
        intel_engine_fini_breadcrumbs(&engine->base);
        i915_timeline_fini(&engine->base.timeline);
@@ -237,10 +239,8 @@ void mock_engine_flush(struct intel_engine_cs *engine)
        del_timer_sync(&mock->hw_delay);
 
        spin_lock_irq(&mock->hw_lock);
-       list_for_each_entry_safe(request, rn, &mock->hw_queue, link) {
-               list_del_init(&request->link);
-               mock_seqno_advance(&mock->base, request->base.global_seqno);
-       }
+       list_for_each_entry_safe(request, rn, &mock->hw_queue, link)
+               advance(request);
        spin_unlock_irq(&mock->hw_lock);
 }
 
@@ -263,8 +263,6 @@ void mock_engine_free(struct intel_engine_cs *engine)
 
        __intel_context_unpin(engine->i915->kernel_context, engine);
 
-       mock_ring_free(engine->buffer);
-
        intel_engine_fini_breadcrumbs(engine);
        i915_timeline_fini(&engine->timeline);
 
index 43ed8b28aeaa0ce86c6162814b5b9f30ce981b70..5477ad4a7e7deff1e5d94d9118d6c590e83e6250 100644 (file)
@@ -72,7 +72,7 @@ static void mock_device_release(struct drm_device *dev)
        i915_gem_drain_freed_objects(i915);
 
        mutex_lock(&i915->drm.struct_mutex);
-       mock_fini_ggtt(i915);
+       mock_fini_ggtt(&i915->ggtt);
        mutex_unlock(&i915->drm.struct_mutex);
        WARN_ON(!list_empty(&i915->gt.timelines));
 
@@ -147,22 +147,24 @@ struct drm_i915_private *mock_gem_device(void)
        pdev->class = PCI_BASE_CLASS_DISPLAY << 16;
        pdev->dev.release = release_dev;
        dev_set_name(&pdev->dev, "mock");
-       dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
 
 #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU)
        /* hack to disable iommu for the fake device; force identity mapping */
        pdev->dev.archdata.iommu = (void *)-1;
 #endif
 
+       i915 = (struct drm_i915_private *)(pdev + 1);
+       pci_set_drvdata(pdev, i915);
+
+       intel_runtime_pm_init_early(i915);
+
        dev_pm_domain_set(&pdev->dev, &pm_domain);
        pm_runtime_enable(&pdev->dev);
        pm_runtime_dont_use_autosuspend(&pdev->dev);
        if (pm_runtime_enabled(&pdev->dev))
                WARN_ON(pm_runtime_get_sync(&pdev->dev));
 
-       i915 = (struct drm_i915_private *)(pdev + 1);
-       pci_set_drvdata(pdev, i915);
-
        err = drm_dev_init(&i915->drm, &mock_driver, &pdev->dev);
        if (err) {
                pr_err("Failed to initialise mock GEM device: err=%d\n", err);
@@ -186,6 +188,7 @@ struct drm_i915_private *mock_gem_device(void)
 
        init_waitqueue_head(&i915->gpu_error.wait_queue);
        init_waitqueue_head(&i915->gpu_error.reset_queue);
+       mutex_init(&i915->gpu_error.wedge_mutex);
 
        i915->wq = alloc_ordered_workqueue("mock", 0);
        if (!i915->wq)
@@ -229,7 +232,7 @@ struct drm_i915_private *mock_gem_device(void)
 
        mutex_lock(&i915->drm.struct_mutex);
 
-       mock_init_ggtt(i915);
+       mock_init_ggtt(i915, &i915->ggtt);
 
        mkwrite_device_info(i915)->ring_mask = BIT(0);
        i915->kernel_context = mock_context(i915, NULL);
index 6ae418c76015b2187dd31437f3a460868765c5d5..cd83929fde8e120902b12615463594ee4080c9ae 100644 (file)
@@ -70,7 +70,7 @@ mock_ppgtt(struct drm_i915_private *i915,
        ppgtt->vm.total = round_down(U64_MAX, PAGE_SIZE);
        ppgtt->vm.file = ERR_PTR(-ENODEV);
 
-       i915_address_space_init(&ppgtt->vm, i915);
+       i915_address_space_init(&ppgtt->vm, VM_CLASS_PPGTT);
 
        ppgtt->vm.clear_range = nop_clear_range;
        ppgtt->vm.insert_page = mock_insert_page;
@@ -97,11 +97,12 @@ static void mock_unbind_ggtt(struct i915_vma *vma)
 {
 }
 
-void mock_init_ggtt(struct drm_i915_private *i915)
+void mock_init_ggtt(struct drm_i915_private *i915, struct i915_ggtt *ggtt)
 {
-       struct i915_ggtt *ggtt = &i915->ggtt;
+       memset(ggtt, 0, sizeof(*ggtt));
 
        ggtt->vm.i915 = i915;
+       ggtt->vm.is_ggtt = true;
 
        ggtt->gmadr = (struct resource) DEFINE_RES_MEM(0, 2048 * PAGE_SIZE);
        ggtt->mappable_end = resource_size(&ggtt->gmadr);
@@ -117,14 +118,10 @@ void mock_init_ggtt(struct drm_i915_private *i915)
        ggtt->vm.vma_ops.set_pages   = ggtt_set_pages;
        ggtt->vm.vma_ops.clear_pages = clear_pages;
 
-       i915_address_space_init(&ggtt->vm, i915);
-
-       ggtt->vm.is_ggtt = true;
+       i915_address_space_init(&ggtt->vm, VM_CLASS_GGTT);
 }
 
-void mock_fini_ggtt(struct drm_i915_private *i915)
+void mock_fini_ggtt(struct i915_ggtt *ggtt)
 {
-       struct i915_ggtt *ggtt = &i915->ggtt;
-
        i915_address_space_fini(&ggtt->vm);
 }
index 9a0a833bb545556e9655677154af4367f22c72db..40d544bde1d5cd9afbdc2e61b5142fbca3e0834b 100644 (file)
@@ -25,8 +25,8 @@
 #ifndef __MOCK_GTT_H
 #define __MOCK_GTT_H
 
-void mock_init_ggtt(struct drm_i915_private *i915);
-void mock_fini_ggtt(struct drm_i915_private *i915);
+void mock_init_ggtt(struct drm_i915_private *i915, struct i915_ggtt *ggtt);
+void mock_fini_ggtt(struct i915_ggtt *ggtt);
 
 struct i915_hw_ppgtt *
 mock_ppgtt(struct drm_i915_private *i915,
index 361e962a7969044aba1c8464096edfa493b4d0c7..696b750acd1dd05e66f6c8fad58219955cedeb46 100644 (file)
@@ -23,7 +23,6 @@
  * Author: Jani Nikula <jani.nikula@intel.com>
  */
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
@@ -257,9 +256,9 @@ static void band_gap_reset(struct drm_i915_private *dev_priv)
        mutex_unlock(&dev_priv->sb_lock);
 }
 
-static bool intel_dsi_compute_config(struct intel_encoder *encoder,
-                                    struct intel_crtc_state *pipe_config,
-                                    struct drm_connector_state *conn_state)
+static int intel_dsi_compute_config(struct intel_encoder *encoder,
+                                   struct intel_crtc_state *pipe_config,
+                                   struct drm_connector_state *conn_state)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_dsi *intel_dsi = container_of(encoder, struct intel_dsi,
@@ -285,11 +284,16 @@ static bool intel_dsi_compute_config(struct intel_encoder *encoder,
        }
 
        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
-               return false;
+               return -EINVAL;
 
        /* DSI uses short packets for sync events, so clear mode flags for DSI */
        adjusted_mode->flags = 0;
 
+       if (intel_dsi->pixel_format == MIPI_DSI_FMT_RGB888)
+               pipe_config->pipe_bpp = 24;
+       else
+               pipe_config->pipe_bpp = 18;
+
        if (IS_GEN9_LP(dev_priv)) {
                /* Enable Frame time stamp based scanline reporting */
                adjusted_mode->private_flags |=
@@ -303,16 +307,16 @@ static bool intel_dsi_compute_config(struct intel_encoder *encoder,
 
                ret = bxt_dsi_pll_compute(encoder, pipe_config);
                if (ret)
-                       return false;
+                       return -EINVAL;
        } else {
                ret = vlv_dsi_pll_compute(encoder, pipe_config);
                if (ret)
-                       return false;
+                       return -EINVAL;
        }
 
        pipe_config->clock_set = true;
 
-       return true;
+       return 0;
 }
 
 static bool glk_dsi_enable_io(struct intel_encoder *encoder)
@@ -674,6 +678,10 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder,
                                        LANE_CONFIGURATION_DUAL_LINK_B :
                                        LANE_CONFIGURATION_DUAL_LINK_A;
                }
+
+               if (intel_dsi->pixel_format != MIPI_DSI_FMT_RGB888)
+                       temp |= DITHERING_ENABLE;
+
                /* assert ip_tg_enable signal */
                I915_WRITE(port_ctrl, temp | DPI_ENABLE);
                POSTING_READ(port_ctrl);
@@ -960,13 +968,15 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+       intel_wakeref_t wakeref;
        enum port port;
        bool active = false;
 
        DRM_DEBUG_KMS("\n");
 
-       if (!intel_display_power_get_if_enabled(dev_priv,
-                                               encoder->power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                    encoder->power_domain);
+       if (!wakeref)
                return false;
 
        /*
@@ -1022,7 +1032,7 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
        }
 
 out_put_power:
-       intel_display_power_put(dev_priv, encoder->power_domain);
+       intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
 
        return active;
 }
@@ -1058,10 +1068,8 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder,
        }
 
        fmt = I915_READ(MIPI_DSI_FUNC_PRG(port)) & VID_MODE_FORMAT_MASK;
-       pipe_config->pipe_bpp =
-                       mipi_dsi_pixel_format_to_bpp(
-                               pixel_format_from_register_bits(fmt));
-       bpp = pipe_config->pipe_bpp;
+       bpp = mipi_dsi_pixel_format_to_bpp(
+                       pixel_format_from_register_bits(fmt));
 
        /* Enable Frame time stamo based scanline reporting */
        adjusted_mode->private_flags |=
@@ -1199,11 +1207,9 @@ static void intel_dsi_get_config(struct intel_encoder *encoder,
 
        if (IS_GEN9_LP(dev_priv)) {
                bxt_dsi_get_pipe_config(encoder, pipe_config);
-               pclk = bxt_dsi_get_pclk(encoder, pipe_config->pipe_bpp,
-                                       pipe_config);
+               pclk = bxt_dsi_get_pclk(encoder, pipe_config);
        } else {
-               pclk = vlv_dsi_get_pclk(encoder, pipe_config->pipe_bpp,
-                                       pipe_config);
+               pclk = vlv_dsi_get_pclk(encoder, pipe_config);
        }
 
        if (pclk) {
@@ -1575,6 +1581,7 @@ vlv_dsi_get_hw_panel_orientation(struct intel_connector *connector)
        enum drm_panel_orientation orientation;
        struct intel_plane *plane;
        struct intel_crtc *crtc;
+       intel_wakeref_t wakeref;
        enum pipe pipe;
        u32 val;
 
@@ -1585,7 +1592,8 @@ vlv_dsi_get_hw_panel_orientation(struct intel_connector *connector)
        plane = to_intel_plane(crtc->base.primary);
 
        power_domain = POWER_DOMAIN_PIPE(pipe);
-       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+       wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (!wakeref)
                return DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
 
        val = I915_READ(DSPCNTR(plane->i9xx_plane));
@@ -1597,7 +1605,7 @@ vlv_dsi_get_hw_panel_orientation(struct intel_connector *connector)
        else
                orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
 
-       intel_display_power_put(dev_priv, power_domain);
+       intel_display_power_put(dev_priv, power_domain, wakeref);
 
        return orientation;
 }
@@ -1689,6 +1697,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
        intel_encoder->post_disable = intel_dsi_post_disable;
        intel_encoder->get_hw_state = intel_dsi_get_hw_state;
        intel_encoder->get_config = intel_dsi_get_config;
+       intel_encoder->update_pipe = intel_panel_update_backlight;
 
        intel_connector->get_hw_state = intel_connector_get_hw_state;
 
index a132a8037ecc6b2a317229918e8d2471cdbcb9dd..954d5a8c4fa761841b8cb8bcdd579809dd0c9014 100644 (file)
@@ -252,20 +252,12 @@ void bxt_dsi_pll_disable(struct intel_encoder *encoder)
                DRM_ERROR("Timeout waiting for PLL lock deassertion\n");
 }
 
-static void assert_bpp_mismatch(enum mipi_dsi_pixel_format fmt, int pipe_bpp)
-{
-       int bpp = mipi_dsi_pixel_format_to_bpp(fmt);
-
-       WARN(bpp != pipe_bpp,
-            "bpp match assertion failure (expected %d, current %d)\n",
-            bpp, pipe_bpp);
-}
-
-u32 vlv_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp,
+u32 vlv_dsi_get_pclk(struct intel_encoder *encoder,
                     struct intel_crtc_state *config)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+       int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
        u32 dsi_clock, pclk;
        u32 pll_ctl, pll_div;
        u32 m = 0, p = 0, n;
@@ -319,15 +311,12 @@ u32 vlv_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp,
 
        dsi_clock = (m * refclk) / (p * n);
 
-       /* pixel_format and pipe_bpp should agree */
-       assert_bpp_mismatch(intel_dsi->pixel_format, pipe_bpp);
-
-       pclk = DIV_ROUND_CLOSEST(dsi_clock * intel_dsi->lane_count, pipe_bpp);
+       pclk = DIV_ROUND_CLOSEST(dsi_clock * intel_dsi->lane_count, bpp);
 
        return pclk;
 }
 
-u32 bxt_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp,
+u32 bxt_dsi_get_pclk(struct intel_encoder *encoder,
                     struct intel_crtc_state *config)
 {
        u32 pclk;
@@ -335,12 +324,7 @@ u32 bxt_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp,
        u32 dsi_ratio;
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
-
-       /* Divide by zero */
-       if (!pipe_bpp) {
-               DRM_ERROR("Invalid BPP(0)\n");
-               return 0;
-       }
+       int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
 
        config->dsi_pll.ctrl = I915_READ(BXT_DSI_PLL_CTL);
 
@@ -348,10 +332,7 @@ u32 bxt_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp,
 
        dsi_clk = (dsi_ratio * BXT_REF_CLOCK_KHZ) / 2;
 
-       /* pixel_format and pipe_bpp should agree */
-       assert_bpp_mismatch(intel_dsi->pixel_format, pipe_bpp);
-
-       pclk = DIV_ROUND_CLOSEST(dsi_clk * intel_dsi->lane_count, pipe_bpp);
+       pclk = DIV_ROUND_CLOSEST(dsi_clk * intel_dsi->lane_count, bpp);
 
        DRM_DEBUG_DRIVER("Calculated pclk=%u\n", pclk);
        return pclk;
index 862f3ec221318800f9850755e2ec2d89deec7df4..12ad00d010630adf9637f8c87c18c1511658b91c 100644 (file)
@@ -981,7 +981,8 @@ static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi,
        u8 buffer[17];
        ssize_t err;
 
-       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
+       err = drm_hdmi_avi_infoframe_from_display_mode(&frame,
+                                                      &hdmi->conn, mode);
        if (err < 0) {
                dev_err(hdmi->dev,
                        "Failed to get AVI infoframe from mode: %zd\n", err);
@@ -1370,8 +1371,8 @@ static void mtk_hdmi_bridge_post_disable(struct drm_bridge *bridge)
 }
 
 static void mtk_hdmi_bridge_mode_set(struct drm_bridge *bridge,
-                                    struct drm_display_mode *mode,
-                                    struct drm_display_mode *adjusted_mode)
+                               const struct drm_display_mode *mode,
+                               const struct drm_display_mode *adjusted_mode)
 {
        struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
 
index 3ee4d4a4ecbae1e59c1fb5e0dfb873b24bf4497c..1e360828ac384ab1f69728293b23332fbeb2593a 100644 (file)
@@ -152,6 +152,23 @@ static void meson_vpu_init(struct meson_drm *priv)
        writel_relaxed(0x20000, priv->io_base + _REG(VPU_WRARB_MODE_L2C1));
 }
 
+static void meson_remove_framebuffers(void)
+{
+       struct apertures_struct *ap;
+
+       ap = alloc_apertures(1);
+       if (!ap)
+               return;
+
+       /* The framebuffer can be located anywhere in RAM */
+       ap->ranges[0].base = 0;
+       ap->ranges[0].size = ~0;
+
+       drm_fb_helper_remove_conflicting_framebuffers(ap, "meson-drm-fb",
+                                                     false);
+       kfree(ap);
+}
+
 static int meson_drv_bind_master(struct device *dev, bool has_components)
 {
        struct platform_device *pdev = to_platform_device(dev);
@@ -262,6 +279,9 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
        if (ret)
                goto free_drm;
 
+       /* Remove early framebuffers (ie. simplefb) */
+       meson_remove_framebuffers();
+
        drm_mode_config_init(drm);
        drm->mode_config.max_width = 3840;
        drm->mode_config.max_height = 2160;
index 807111ebfdd97785ac2b6855a1af14dc5067a8f9..bc25001b820759dc1d3e1e56c27fa813d29732d9 100644 (file)
@@ -365,7 +365,7 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
        unsigned int wr_clk =
                readl_relaxed(priv->io_base + _REG(VPU_HDMI_SETTING));
 
-       DRM_DEBUG_DRIVER("%d:\"%s\"\n", mode->base.id, mode->name);
+       DRM_DEBUG_DRIVER("\"%s\"\n", mode->name);
 
        /* Enable clocks */
        regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
@@ -555,12 +555,7 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
        int vic = drm_match_cea_mode(mode);
        enum drm_mode_status status;
 
-       DRM_DEBUG_DRIVER("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
-               mode->base.id, mode->name, mode->vrefresh, mode->clock,
-               mode->hdisplay, mode->hsync_start,
-               mode->hsync_end, mode->htotal,
-               mode->vdisplay, mode->vsync_start,
-               mode->vsync_end, mode->vtotal, mode->type, mode->flags);
+       DRM_DEBUG_DRIVER("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
 
        /* Check against non-VIC supported modes */
        if (!vic) {
@@ -650,8 +645,7 @@ static void meson_venc_hdmi_encoder_mode_set(struct drm_encoder *encoder,
        struct meson_drm *priv = dw_hdmi->priv;
        int vic = drm_match_cea_mode(mode);
 
-       DRM_DEBUG_DRIVER("%d:\"%s\" vic %d\n",
-                        mode->base.id, mode->name, vic);
+       DRM_DEBUG_DRIVER("\"%s\" vic %d\n", mode->name, vic);
 
        /* VENC + VENC-DVI Mode setup */
        meson_venc_hdmi_mode_set(priv, vic, mode);
index 30726c9fe28c810486a127c3dfbd92c07836b2e3..6893934b26c0387a390540b770ec1e49252902bb 100644 (file)
@@ -12,6 +12,7 @@
  */
 #include <linux/module.h>
 #include <drm/drmP.h>
+#include <drm/drm_util.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
 
index 8f2359dc87b4ea5b34aabe77bb288a365f5f3233..cc32ea5f4289eca3ecea7ddf889ea78f13e84e90 100644 (file)
@@ -244,14 +244,8 @@ static void mdp4_crtc_mode_set_nofb(struct drm_crtc *crtc)
 
        mode = &crtc->state->adjusted_mode;
 
-       DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
-                       mdp4_crtc->name, mode->base.id, mode->name,
-                       mode->vrefresh, mode->clock,
-                       mode->hdisplay, mode->hsync_start,
-                       mode->hsync_end, mode->htotal,
-                       mode->vdisplay, mode->vsync_start,
-                       mode->vsync_end, mode->vtotal,
-                       mode->type, mode->flags);
+       DBG("%s: set mode: " DRM_MODE_FMT,
+                       mdp4_crtc->name, DRM_MODE_ARG(mode));
 
        mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_SIZE(dma),
                        MDP4_DMA_SRC_SIZE_WIDTH(mode->hdisplay) |
index 6a1ebdace391d947e54b856e42c020e1f105d98f..48ce218b8463d5958e8ec0a3119e5abf2dcc6294 100644 (file)
@@ -58,14 +58,7 @@ static void mdp4_dsi_encoder_mode_set(struct drm_encoder *encoder,
 
        mode = adjusted_mode;
 
-       DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
-                       mode->base.id, mode->name,
-                       mode->vrefresh, mode->clock,
-                       mode->hdisplay, mode->hsync_start,
-                       mode->hsync_end, mode->htotal,
-                       mode->vdisplay, mode->vsync_start,
-                       mode->vsync_end, mode->vtotal,
-                       mode->type, mode->flags);
+       DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
 
        ctrl_pol = 0;
        if (mode->flags & DRM_MODE_FLAG_NHSYNC)
index a8fd14d4846b37d95160b6b00ea84c32a270c2bc..ff8f2da160c0c15308aec3a931da6147f05ef8eb 100644 (file)
@@ -104,14 +104,7 @@ static void mdp4_dtv_encoder_mode_set(struct drm_encoder *encoder,
 
        mode = adjusted_mode;
 
-       DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
-                       mode->base.id, mode->name,
-                       mode->vrefresh, mode->clock,
-                       mode->hdisplay, mode->hsync_start,
-                       mode->hsync_end, mode->htotal,
-                       mode->vdisplay, mode->vsync_start,
-                       mode->vsync_end, mode->vtotal,
-                       mode->type, mode->flags);
+       DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
 
        mdp4_dtv_encoder->pixclock = mode->clock * 1000;
 
index c9e34501a89e8c485743b8a27632783bde4355bb..fff77a4b12c2d15fdc30f9049f852672cf076c20 100644 (file)
@@ -273,14 +273,7 @@ static void mdp4_lcdc_encoder_mode_set(struct drm_encoder *encoder,
 
        mode = adjusted_mode;
 
-       DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
-                       mode->base.id, mode->name,
-                       mode->vrefresh, mode->clock,
-                       mode->hdisplay, mode->hsync_start,
-                       mode->hsync_end, mode->htotal,
-                       mode->vdisplay, mode->vsync_start,
-                       mode->vsync_end, mode->vtotal,
-                       mode->type, mode->flags);
+       DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
 
        mdp4_lcdc_encoder->pixclock = mode->clock * 1000;
 
index c1962f29ec7d688e98ec57f40c9375210fc47af0..976585d8bfd631aed30299633345f307b0e04908 100644 (file)
@@ -134,14 +134,7 @@ void mdp5_cmd_encoder_mode_set(struct drm_encoder *encoder,
 {
        mode = adjusted_mode;
 
-       DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
-                       mode->base.id, mode->name,
-                       mode->vrefresh, mode->clock,
-                       mode->hdisplay, mode->hsync_start,
-                       mode->hsync_end, mode->htotal,
-                       mode->vdisplay, mode->vsync_start,
-                       mode->vsync_end, mode->vtotal,
-                       mode->type, mode->flags);
+       DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
        pingpong_tearcheck_setup(encoder, mode);
        mdp5_crtc_set_pipeline(encoder->crtc);
 }
index c5fde1a4191aaa03d7a002e52b803a2689519667..2f95e65255896739f448ddfcfc7cacac85793759 100644 (file)
@@ -384,14 +384,7 @@ static void mdp5_crtc_mode_set_nofb(struct drm_crtc *crtc)
 
        mode = &crtc->state->adjusted_mode;
 
-       DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
-                       crtc->name, mode->base.id, mode->name,
-                       mode->vrefresh, mode->clock,
-                       mode->hdisplay, mode->hsync_start,
-                       mode->hsync_end, mode->htotal,
-                       mode->vdisplay, mode->vsync_start,
-                       mode->vsync_end, mode->vtotal,
-                       mode->type, mode->flags);
+       DBG("%s: set mode: " DRM_MODE_FMT, crtc->name, DRM_MODE_ARG(mode));
 
        mixer_width = mode->hdisplay;
        if (r_mixer)
index fcd44d1d10682b6bf063ecf60848c635283689eb..d2a56e55e53d9604bd185fe96457c64c7319020f 100644 (file)
@@ -118,14 +118,7 @@ static void mdp5_vid_encoder_mode_set(struct drm_encoder *encoder,
 
        mode = adjusted_mode;
 
-       DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
-                       mode->base.id, mode->name,
-                       mode->vrefresh, mode->clock,
-                       mode->hdisplay, mode->hsync_start,
-                       mode->hsync_end, mode->htotal,
-                       mode->vdisplay, mode->vsync_start,
-                       mode->vsync_end, mode->vtotal,
-                       mode->type, mode->flags);
+       DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
 
        ctrl_pol = 0;
 
index d27e35a217bd77f3ffbfe88f452bf1f7c8c7f51e..97179bec8902fc500f78639b15eaee8cccbc1cee 100644 (file)
@@ -144,7 +144,7 @@ static int mdp5_global_obj_init(struct mdp5_kms *mdp5_kms)
 
        state->mdp5_kms = mdp5_kms;
 
-       drm_atomic_private_obj_init(&mdp5_kms->glob_state,
+       drm_atomic_private_obj_init(mdp5_kms->dev, &mdp5_kms->glob_state,
                                    &state->base,
                                    &mdp5_global_state_funcs);
        return 0;
index 7cebcb2b3a379246e55faef1dcce6657d2ec3a3a..6153514db04c2a209c7d08b756ec1397e532c8b5 100644 (file)
@@ -16,6 +16,7 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <drm/drm_util.h>
 
 #include "mdp5_kms.h"
 #include "mdp5_smp.h"
index 08f3fc6771b7829de66c1af953cbb3abb16ccee2..9c6b31c2d79f01948836c77cbdf1b8628708441e 100644 (file)
@@ -168,7 +168,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host,
                        bool is_dual_dsi);
 int msm_dsi_host_power_off(struct mipi_dsi_host *host);
 int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host,
-                                       struct drm_display_mode *mode);
+                                 const struct drm_display_mode *mode);
 struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host,
                                        unsigned long *panel_flags);
 struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host);
index 38e481d2d606f9f8d3a0600c8e5f5495db00a848..610183db1daf640498568fe272e6100a75d22b93 100644 (file)
@@ -2424,7 +2424,7 @@ unlock_ret:
 }
 
 int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host,
-                                       struct drm_display_mode *mode)
+                                 const struct drm_display_mode *mode)
 {
        struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 
index 80aa6344185e13068ad4442e069fbe2a91cb1e52..979a8e9293412349f1d29d894fb4e2f64d1d5cc2 100644 (file)
@@ -527,8 +527,8 @@ disable_phy:
 }
 
 static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
-               struct drm_display_mode *mode,
-               struct drm_display_mode *adjusted_mode)
+               const struct drm_display_mode *mode,
+               const struct drm_display_mode *adjusted_mode)
 {
        int id = dsi_mgr_bridge_get_id(bridge);
        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
@@ -536,14 +536,7 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
        struct mipi_dsi_host *host = msm_dsi->host;
        bool is_dual_dsi = IS_DUAL_DSI();
 
-       DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
-                       mode->base.id, mode->name,
-                       mode->vrefresh, mode->clock,
-                       mode->hdisplay, mode->hsync_start,
-                       mode->hsync_end, mode->htotal,
-                       mode->vdisplay, mode->vsync_start,
-                       mode->vsync_end, mode->vtotal,
-                       mode->type, mode->flags);
+       DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
 
        if (is_dual_dsi && !IS_MASTER_DSI_LINK(id))
                return;
index 931a5c97cccf6fc65066b4bf77a67a6e274cecaa..11166bf232ffcdecc56dc5a9925455a784fa00ee 100644 (file)
@@ -52,22 +52,15 @@ static void edp_bridge_post_disable(struct drm_bridge *bridge)
 }
 
 static void edp_bridge_mode_set(struct drm_bridge *bridge,
-               struct drm_display_mode *mode,
-               struct drm_display_mode *adjusted_mode)
+               const struct drm_display_mode *mode,
+               const struct drm_display_mode *adjusted_mode)
 {
        struct drm_device *dev = bridge->dev;
        struct drm_connector *connector;
        struct edp_bridge *edp_bridge = to_edp_bridge(bridge);
        struct msm_edp *edp = edp_bridge->edp;
 
-       DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
-                       mode->base.id, mode->name,
-                       mode->vrefresh, mode->clock,
-                       mode->hdisplay, mode->hsync_start,
-                       mode->hsync_end, mode->htotal,
-                       mode->vdisplay, mode->vsync_start,
-                       mode->vsync_end, mode->vtotal,
-                       mode->type, mode->flags);
+       DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
 
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                if ((connector->encoder != NULL) &&
index 98d61c690260f49a09228c75ee325738ed484aa5..03197b8959ba640e73f63b0201797edebb9e941e 100644 (file)
@@ -101,7 +101,8 @@ static void msm_hdmi_config_avi_infoframe(struct hdmi *hdmi)
        u32 val;
        int len;
 
-       drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
+       drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
+                                                hdmi->connector, mode);
 
        len = hdmi_infoframe_pack(&frame, buffer, sizeof(buffer));
        if (len < 0) {
@@ -207,8 +208,8 @@ static void msm_hdmi_bridge_post_disable(struct drm_bridge *bridge)
 }
 
 static void msm_hdmi_bridge_mode_set(struct drm_bridge *bridge,
-                struct drm_display_mode *mode,
-                struct drm_display_mode *adjusted_mode)
+                const struct drm_display_mode *mode,
+                const struct drm_display_mode *adjusted_mode)
 {
        struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
        struct hdmi *hdmi = hdmi_bridge->hdmi;
index 51a95da694d8d498dee29bd91ddb880b3478c356..20c979a7fc9c39f6d2f0034da4a6fa21b62ffc24 100644 (file)
@@ -758,7 +758,7 @@ static void describe_fence(struct dma_fence *fence, const char *type,
                struct seq_file *m)
 {
        if (!dma_fence_is_signaled(fence))
-               seq_printf(m, "\t%9s: %s %s seq %u\n", type,
+               seq_printf(m, "\t%9s: %s %s seq %llu\n", type,
                                fence->ops->get_driver_name(fence),
                                fence->ops->get_timeline_name(fence),
                                fence->seqno);
index 88ba003979e6b841cce82bd390282335ebb13028..13e778825098b807b23ef9062b83454853e91e60 100644 (file)
@@ -263,23 +263,12 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
 
        drm_kms_helper_poll_init(drm);
 
-       mxsfb->fbdev = drm_fbdev_cma_init(drm, 32,
-                                         drm->mode_config.num_connector);
-       if (IS_ERR(mxsfb->fbdev)) {
-               ret = PTR_ERR(mxsfb->fbdev);
-               mxsfb->fbdev = NULL;
-               dev_err(drm->dev, "Failed to init FB CMA area\n");
-               goto err_cma;
-       }
-
        platform_set_drvdata(pdev, drm);
 
        drm_helper_hpd_irq_event(drm);
 
        return 0;
 
-err_cma:
-       drm_irq_uninstall(drm);
 err_irq:
        drm_panel_detach(mxsfb->panel);
 err_vblank:
@@ -290,11 +279,6 @@ err_vblank:
 
 static void mxsfb_unload(struct drm_device *drm)
 {
-       struct mxsfb_drm_private *mxsfb = drm->dev_private;
-
-       if (mxsfb->fbdev)
-               drm_fbdev_cma_fini(mxsfb->fbdev);
-
        drm_kms_helper_poll_fini(drm);
        drm_mode_config_cleanup(drm);
 
@@ -307,13 +291,6 @@ static void mxsfb_unload(struct drm_device *drm)
        pm_runtime_disable(drm->dev);
 }
 
-static void mxsfb_lastclose(struct drm_device *drm)
-{
-       struct mxsfb_drm_private *mxsfb = drm->dev_private;
-
-       drm_fbdev_cma_restore_mode(mxsfb->fbdev);
-}
-
 static void mxsfb_irq_preinstall(struct drm_device *drm)
 {
        struct mxsfb_drm_private *mxsfb = drm->dev_private;
@@ -347,7 +324,6 @@ static struct drm_driver mxsfb_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET |
                                  DRIVER_PRIME | DRIVER_ATOMIC |
                                  DRIVER_HAVE_IRQ,
-       .lastclose              = mxsfb_lastclose,
        .irq_handler            = mxsfb_irq_handler,
        .irq_preinstall         = mxsfb_irq_preinstall,
        .irq_uninstall          = mxsfb_irq_preinstall,
@@ -412,6 +388,8 @@ static int mxsfb_probe(struct platform_device *pdev)
        if (ret)
                goto err_unload;
 
+       drm_fbdev_generic_setup(drm, 32);
+
        return 0;
 
 err_unload:
index 5d0883fc805bc1e7822e9caa1903e05d786f0ba4..bedd6801edca5ef715aa947a15b31803fcd90522 100644 (file)
@@ -37,7 +37,6 @@ struct mxsfb_drm_private {
        struct drm_simple_display_pipe  pipe;
        struct drm_connector            connector;
        struct drm_panel                *panel;
-       struct drm_fbdev_cma            *fbdev;
 };
 
 int mxsfb_setup_crtc(struct drm_device *dev);
index 6a4ca139cf5d71efb67427dd2f79eb886482d817..8fd8124d72ba7100bc02050013323aa5b7e272df 100644 (file)
@@ -750,7 +750,9 @@ static int nv17_tv_set_property(struct drm_encoder *encoder,
                /* Disable the crtc to ensure a full modeset is
                 * performed whenever it's turned on again. */
                if (crtc)
-                       drm_crtc_force_disable(crtc);
+                       drm_crtc_helper_set_mode(crtc, &crtc->mode,
+                                                crtc->x, crtc->y,
+                                                crtc->primary->fb);
        }
 
        return 0;
index 134701a837c8f9a43768c269222fda98324536a7..67107f0b129927eacad628c27a10e57d37b73385 100644 (file)
@@ -561,7 +561,7 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
        u32 max_ac_packet;
        union hdmi_infoframe avi_frame;
        union hdmi_infoframe vendor_frame;
-       bool scdc_supported, high_tmds_clock_ratio = false, scrambling = false;
+       bool high_tmds_clock_ratio = false, scrambling = false;
        u8 config;
        int ret;
        int size;
@@ -571,10 +571,9 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
                return;
 
        hdmi = &nv_connector->base.display_info.hdmi;
-       scdc_supported = hdmi->scdc.supported;
 
-       ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, mode,
-                                                      scdc_supported);
+       ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi,
+                                                      &nv_connector->base, mode);
        if (!ret) {
                /* We have an AVI InfoFrame, populate it to the display */
                args.pwr.avi_infoframe_length
@@ -680,6 +679,8 @@ nv50_msto_payload(struct nv50_msto *msto)
        struct nv50_mstm *mstm = mstc->mstm;
        int vcpi = mstc->port->vcpi.vcpi, i;
 
+       WARN_ON(!mutex_is_locked(&mstm->mgr.payload_lock));
+
        NV_ATOMIC(drm, "%s: vcpi %d\n", msto->encoder.name, vcpi);
        for (i = 0; i < mstm->mgr.max_payloads; i++) {
                struct drm_dp_payload *payload = &mstm->mgr.payloads[i];
@@ -704,14 +705,16 @@ nv50_msto_cleanup(struct nv50_msto *msto)
        struct nv50_mstc *mstc = msto->mstc;
        struct nv50_mstm *mstm = mstc->mstm;
 
+       if (!msto->disabled)
+               return;
+
        NV_ATOMIC(drm, "%s: msto cleanup\n", msto->encoder.name);
-       if (mstc->port && mstc->port->vcpi.vcpi > 0 && !nv50_msto_payload(msto))
-               drm_dp_mst_deallocate_vcpi(&mstm->mgr, mstc->port);
-       if (msto->disabled) {
-               msto->mstc = NULL;
-               msto->head = NULL;
-               msto->disabled = false;
-       }
+
+       drm_dp_mst_deallocate_vcpi(&mstm->mgr, mstc->port);
+
+       msto->mstc = NULL;
+       msto->head = NULL;
+       msto->disabled = false;
 }
 
 static void
@@ -731,8 +734,10 @@ nv50_msto_prepare(struct nv50_msto *msto)
                               (0x0100 << msto->head->base.index),
        };
 
+       mutex_lock(&mstm->mgr.payload_lock);
+
        NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name);
-       if (mstc->port && mstc->port->vcpi.vcpi > 0) {
+       if (mstc->port->vcpi.vcpi > 0) {
                struct drm_dp_payload *payload = nv50_msto_payload(msto);
                if (payload) {
                        args.vcpi.start_slot = payload->start_slot;
@@ -746,7 +751,9 @@ nv50_msto_prepare(struct nv50_msto *msto)
                  msto->encoder.name, msto->head->base.base.name,
                  args.vcpi.start_slot, args.vcpi.num_slots,
                  args.vcpi.pbn, args.vcpi.aligned_pbn);
+
        nvif_mthd(&drm->display->disp.object, 0, &args, sizeof(args));
+       mutex_unlock(&mstm->mgr.payload_lock);
 }
 
 static int
@@ -754,16 +761,23 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
                       struct drm_crtc_state *crtc_state,
                       struct drm_connector_state *conn_state)
 {
-       struct nv50_mstc *mstc = nv50_mstc(conn_state->connector);
+       struct drm_atomic_state *state = crtc_state->state;
+       struct drm_connector *connector = conn_state->connector;
+       struct nv50_mstc *mstc = nv50_mstc(connector);
        struct nv50_mstm *mstm = mstc->mstm;
-       int bpp = conn_state->connector->display_info.bpc * 3;
+       int bpp = connector->display_info.bpc * 3;
        int slots;
 
-       mstc->pbn = drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock, bpp);
+       mstc->pbn = drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock,
+                                        bpp);
 
-       slots = drm_dp_find_vcpi_slots(&mstm->mgr, mstc->pbn);
-       if (slots < 0)
-               return slots;
+       if (drm_atomic_crtc_needs_modeset(crtc_state) &&
+           !drm_connector_is_unregistered(connector)) {
+               slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr,
+                                                     mstc->port, mstc->pbn);
+               if (slots < 0)
+                       return slots;
+       }
 
        return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
                                           mstc->native);
@@ -829,8 +843,7 @@ nv50_msto_disable(struct drm_encoder *encoder)
        struct nv50_mstc *mstc = msto->mstc;
        struct nv50_mstm *mstm = mstc->mstm;
 
-       if (mstc->port)
-               drm_dp_mst_reset_vcpi_slots(&mstm->mgr, mstc->port);
+       drm_dp_mst_reset_vcpi_slots(&mstm->mgr, mstc->port);
 
        mstm->outp->update(mstm->outp, msto->head->base.index, NULL, 0, 0);
        mstm->modified = true;
@@ -927,12 +940,43 @@ nv50_mstc_get_modes(struct drm_connector *connector)
        return ret;
 }
 
+static int
+nv50_mstc_atomic_check(struct drm_connector *connector,
+                      struct drm_connector_state *new_conn_state)
+{
+       struct drm_atomic_state *state = new_conn_state->state;
+       struct nv50_mstc *mstc = nv50_mstc(connector);
+       struct drm_dp_mst_topology_mgr *mgr = &mstc->mstm->mgr;
+       struct drm_connector_state *old_conn_state =
+               drm_atomic_get_old_connector_state(state, connector);
+       struct drm_crtc_state *crtc_state;
+       struct drm_crtc *new_crtc = new_conn_state->crtc;
+
+       if (!old_conn_state->crtc)
+               return 0;
+
+       /* We only want to free VCPI if this state disables the CRTC on this
+        * connector
+        */
+       if (new_crtc) {
+               crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc);
+
+               if (!crtc_state ||
+                   !drm_atomic_crtc_needs_modeset(crtc_state) ||
+                   crtc_state->enable)
+                       return 0;
+       }
+
+       return drm_dp_atomic_release_vcpi_slots(state, mgr, mstc->port);
+}
+
 static const struct drm_connector_helper_funcs
 nv50_mstc_help = {
        .get_modes = nv50_mstc_get_modes,
        .mode_valid = nv50_mstc_mode_valid,
        .best_encoder = nv50_mstc_best_encoder,
        .atomic_best_encoder = nv50_mstc_atomic_best_encoder,
+       .atomic_check = nv50_mstc_atomic_check,
 };
 
 static enum drm_connector_status
@@ -942,7 +986,7 @@ nv50_mstc_detect(struct drm_connector *connector, bool force)
        enum drm_connector_status conn_status;
        int ret;
 
-       if (!mstc->port)
+       if (drm_connector_is_unregistered(connector))
                return connector_status_disconnected;
 
        ret = pm_runtime_get_sync(connector->dev->dev);
@@ -961,7 +1005,10 @@ static void
 nv50_mstc_destroy(struct drm_connector *connector)
 {
        struct nv50_mstc *mstc = nv50_mstc(connector);
+
        drm_connector_cleanup(&mstc->connector);
+       drm_dp_mst_put_port_malloc(mstc->port);
+
        kfree(mstc);
 }
 
@@ -1009,6 +1056,7 @@ nv50_mstc_new(struct nv50_mstm *mstm, struct drm_dp_mst_port *port,
        drm_object_attach_property(&mstc->connector.base, dev->mode_config.path_property, 0);
        drm_object_attach_property(&mstc->connector.base, dev->mode_config.tile_property, 0);
        drm_connector_set_path_property(&mstc->connector, path);
+       drm_dp_mst_get_port_malloc(port);
        return 0;
 }
 
@@ -1062,13 +1110,6 @@ nv50_mstm_prepare(struct nv50_mstm *mstm)
        }
 }
 
-static void
-nv50_mstm_hotplug(struct drm_dp_mst_topology_mgr *mgr)
-{
-       struct nv50_mstm *mstm = nv50_mstm(mgr);
-       drm_kms_helper_hotplug_event(mstm->outp->base.base.dev);
-}
-
 static void
 nv50_mstm_destroy_connector(struct drm_dp_mst_topology_mgr *mgr,
                            struct drm_connector *connector)
@@ -1080,10 +1121,6 @@ nv50_mstm_destroy_connector(struct drm_dp_mst_topology_mgr *mgr,
 
        drm_fb_helper_remove_one_connector(&drm->fbcon->helper, &mstc->connector);
 
-       drm_modeset_lock(&drm->dev->mode_config.connection_mutex, NULL);
-       mstc->port = NULL;
-       drm_modeset_unlock(&drm->dev->mode_config.connection_mutex);
-
        drm_connector_put(&mstc->connector);
 }
 
@@ -1106,11 +1143,8 @@ nv50_mstm_add_connector(struct drm_dp_mst_topology_mgr *mgr,
        int ret;
 
        ret = nv50_mstc_new(mstm, port, path, &mstc);
-       if (ret) {
-               if (mstc)
-                       mstc->connector.funcs->destroy(&mstc->connector);
+       if (ret)
                return NULL;
-       }
 
        return &mstc->connector;
 }
@@ -1120,7 +1154,6 @@ nv50_mstm = {
        .add_connector = nv50_mstm_add_connector,
        .register_connector = nv50_mstm_register_connector,
        .destroy_connector = nv50_mstm_destroy_connector,
-       .hotplug = nv50_mstm_hotplug,
 };
 
 void
@@ -2125,6 +2158,10 @@ nv50_disp_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
                        return ret;
        }
 
+       ret = drm_dp_mst_atomic_check(state);
+       if (ret)
+               return ret;
+
        return 0;
 }
 
index f326ffd867664cd98dfc9dea789f91917c21856a..5d273a65547951afe2a47e96698030ab03b680b7 100644 (file)
@@ -453,7 +453,7 @@ nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime)
                if (drm_drv_uses_atomic_modeset(dev))
                        drm_atomic_helper_shutdown(dev);
                else
-                       drm_crtc_force_disable_all(dev);
+                       drm_helper_force_disable_all(dev);
        }
 
        /* disable flip completion events */
index b81302c4bf9e6d49a678ff8e34829b8c0bc7dbc3..874d8f3cbff650aa0cb324ecb30f9571c35496b5 100644 (file)
@@ -305,14 +305,9 @@ static int omap_connector_mode_valid(struct drm_connector *connector,
        drm_mode_destroy(dev, new_mode);
 
 done:
-       DBG("connector: mode %s: "
-                       "%d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
+       DBG("connector: mode %s: " DRM_MODE_FMT,
                        (ret == MODE_OK) ? "valid" : "invalid",
-                       mode->base.id, mode->name, mode->vrefresh, mode->clock,
-                       mode->hdisplay, mode->hsync_start,
-                       mode->hsync_end, mode->htotal,
-                       mode->vdisplay, mode->vsync_start,
-                       mode->vsync_end, mode->vtotal, mode->type, mode->flags);
+                       DRM_MODE_ARG(mode));
 
        return ret;
 }
index caffc547ef97e385cb913f77fd3ebe55a082d486..40acf4ce7c9f3a59f6e79971d25d11c192aa0a10 100644 (file)
@@ -427,12 +427,8 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc)
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
        struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 
-       DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
-           omap_crtc->name, mode->base.id, mode->name,
-           mode->vrefresh, mode->clock,
-           mode->hdisplay, mode->hsync_start, mode->hsync_end, mode->htotal,
-           mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal,
-           mode->type, mode->flags);
+       DBG("%s: set mode: " DRM_MODE_FMT,
+           omap_crtc->name, DRM_MODE_ARG(mode));
 
        drm_display_mode_to_videomode(mode, &omap_crtc->vm);
 }
index 933ebc9f9faaaf35049a53aef49551e3ff1e740a..148b6b20274fc56a08df4176549785e0c84aa67b 100644 (file)
@@ -76,8 +76,8 @@ static void omap_encoder_hdmi_mode_set(struct drm_encoder *encoder,
                struct hdmi_avi_infoframe avi;
                int r;
 
-               r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode,
-                                                            false);
+               r = drm_hdmi_avi_infoframe_from_display_mode(&avi, connector,
+                                                            adjusted_mode);
                if (r == 0)
                        dssdev->ops->hdmi.set_infoframe(dssdev, &avi);
        }
index aee99194499f1675be7e160b96241f1f62dbbcd1..851c59f07eb1fc3c73d5f03599b78b0e67c2b49e 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <drm/drm_crtc.h>
+#include <drm/drm_util.h>
 #include <drm/drm_fb_helper.h>
 
 #include "omap_drv.h"
index 3f3537719beb2eddaa6c132236da3a8f2ff0bdc7..a71f4419127373d8ce469d68231a38d8c45f5d4a 100644 (file)
@@ -204,6 +204,15 @@ config DRM_PANEL_SITRONIX_ST7789V
          Say Y here if you want to enable support for the Sitronix
          ST7789V controller for 240x320 LCD panels
 
+config DRM_PANEL_TPO_TPG110
+       tristate "TPO TPG 800x400 panel"
+       depends on OF && SPI && GPIOLIB
+       depends on BACKLIGHT_CLASS_DEVICE
+       help
+         Say Y here if you want to enable support for TPO TPG110
+         400CH LTPS TFT LCD Single Chip Digital Driver for up to
+         800x400 LCD panels.
+
 config DRM_PANEL_TRULY_NT35597_WQXGA
        tristate "Truly WQXGA"
        depends on OF
index 4396658a7996466c62ae24b8391757044eb0e712..cd14ca39c6e0228ecc51affdbd9e232e58f0eebf 100644 (file)
@@ -21,4 +21,5 @@ obj-$(CONFIG_DRM_PANEL_SEIKO_43WVF1G) += panel-seiko-43wvf1g.o
 obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o
 obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o
 obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o
+obj-$(CONFIG_DRM_PANEL_TPO_TPG110) += panel-tpo-tpg110.o
 obj-$(CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA) += panel-truly-nt35597.o
index ca4ae45dd307c6cb29b16efb99caa1c1965736a5..8e5724b63f1f80f2ef50a6b4d2ca8c4a92d7e4dd 100644 (file)
@@ -70,18 +70,12 @@ static inline struct innolux_panel *to_innolux_panel(struct drm_panel *panel)
 static int innolux_panel_disable(struct drm_panel *panel)
 {
        struct innolux_panel *innolux = to_innolux_panel(panel);
-       int err;
 
        if (!innolux->enabled)
                return 0;
 
        backlight_disable(innolux->backlight);
 
-       err = mipi_dsi_dcs_set_display_off(innolux->link);
-       if (err < 0)
-               DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n",
-                             err);
-
        innolux->enabled = false;
 
        return 0;
@@ -95,6 +89,11 @@ static int innolux_panel_unprepare(struct drm_panel *panel)
        if (!innolux->prepared)
                return 0;
 
+       err = mipi_dsi_dcs_set_display_off(innolux->link);
+       if (err < 0)
+               DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n",
+                             err);
+
        err = mipi_dsi_dcs_enter_sleep_mode(innolux->link);
        if (err < 0) {
                DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n",
diff --git a/drivers/gpu/drm/panel/panel-tpo-tpg110.c b/drivers/gpu/drm/panel/panel-tpo-tpg110.c
new file mode 100644 (file)
index 0000000..5a9f8f4
--- /dev/null
@@ -0,0 +1,496 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Panel driver for the TPO TPG110 400CH LTPS TFT LCD Single Chip
+ * Digital Driver.
+ *
+ * This chip drives a TFT LCD, so it does not know what kind of
+ * display is actually connected to it, so the width and height of that
+ * display needs to be supplied from the machine configuration.
+ *
+ * Author:
+ * Linus Walleij <linus.walleij@linaro.org>
+ */
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+
+#include <linux/backlight.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+#define TPG110_TEST                    0x00
+#define TPG110_CHIPID                  0x01
+#define TPG110_CTRL1                   0x02
+#define TPG110_RES_MASK                        GENMASK(2, 0)
+#define TPG110_RES_800X480             0x07
+#define TPG110_RES_640X480             0x06
+#define TPG110_RES_480X272             0x05
+#define TPG110_RES_480X640             0x04
+#define TPG110_RES_480X272_D           0x01 /* Dual scan: outputs 800x480 */
+#define TPG110_RES_400X240_D           0x00 /* Dual scan: outputs 800x480 */
+#define TPG110_CTRL2                   0x03
+#define TPG110_CTRL2_PM                        BIT(0)
+#define TPG110_CTRL2_RES_PM_CTRL       BIT(7)
+
+/**
+ * struct tpg110_panel_mode - lookup struct for the supported modes
+ */
+struct tpg110_panel_mode {
+       /**
+        * @name: the name of this panel
+        */
+       const char *name;
+       /**
+        * @magic: the magic value from the detection register
+        */
+       u32 magic;
+       /**
+        * @mode: the DRM display mode for this panel
+        */
+       struct drm_display_mode mode;
+       /**
+        * @bus_flags: the DRM bus flags for this panel e.g. inverted clock
+        */
+       u32 bus_flags;
+};
+
+/**
+ * struct tpg110 - state container for the TPG110 panel
+ */
+struct tpg110 {
+       /**
+        * @dev: the container device
+        */
+       struct device *dev;
+       /**
+        * @spi: the corresponding SPI device
+        */
+       struct spi_device *spi;
+       /**
+        * @panel: the DRM panel instance for this device
+        */
+       struct drm_panel panel;
+       /**
+        * @backlight: backlight for this panel
+        */
+       struct backlight_device *backlight;
+       /**
+        * @panel_type: the panel mode as detected
+        */
+       const struct tpg110_panel_mode *panel_mode;
+       /**
+        * @width: the width of this panel in mm
+        */
+       u32 width;
+       /**
+        * @height: the height of this panel in mm
+        */
+       u32 height;
+       /**
+        * @grestb: reset GPIO line
+        */
+       struct gpio_desc *grestb;
+};
+
+/*
+ * TPG110 modes, these are the simple modes, the dualscan modes that
+ * take 400x240 or 480x272 in and display as 800x480 are not listed.
+ */
+static const struct tpg110_panel_mode tpg110_modes[] = {
+       {
+               .name = "800x480 RGB",
+               .magic = TPG110_RES_800X480,
+               .mode = {
+                       .clock = 33200,
+                       .hdisplay = 800,
+                       .hsync_start = 800 + 40,
+                       .hsync_end = 800 + 40 + 1,
+                       .htotal = 800 + 40 + 1 + 216,
+                       .vdisplay = 480,
+                       .vsync_start = 480 + 10,
+                       .vsync_end = 480 + 10 + 1,
+                       .vtotal = 480 + 10 + 1 + 35,
+                       .vrefresh = 60,
+               },
+               .bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE,
+       },
+       {
+               .name = "640x480 RGB",
+               .magic = TPG110_RES_640X480,
+               .mode = {
+                       .clock = 25200,
+                       .hdisplay = 640,
+                       .hsync_start = 640 + 24,
+                       .hsync_end = 640 + 24 + 1,
+                       .htotal = 640 + 24 + 1 + 136,
+                       .vdisplay = 480,
+                       .vsync_start = 480 + 18,
+                       .vsync_end = 480 + 18 + 1,
+                       .vtotal = 480 + 18 + 1 + 27,
+                       .vrefresh = 60,
+               },
+               .bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE,
+       },
+       {
+               .name = "480x272 RGB",
+               .magic = TPG110_RES_480X272,
+               .mode = {
+                       .clock = 9000,
+                       .hdisplay = 480,
+                       .hsync_start = 480 + 2,
+                       .hsync_end = 480 + 2 + 1,
+                       .htotal = 480 + 2 + 1 + 43,
+                       .vdisplay = 272,
+                       .vsync_start = 272 + 2,
+                       .vsync_end = 272 + 2 + 1,
+                       .vtotal = 272 + 2 + 1 + 12,
+                       .vrefresh = 60,
+               },
+               .bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE,
+       },
+       {
+               .name = "480x640 RGB",
+               .magic = TPG110_RES_480X640,
+               .mode = {
+                       .clock = 20500,
+                       .hdisplay = 480,
+                       .hsync_start = 480 + 2,
+                       .hsync_end = 480 + 2 + 1,
+                       .htotal = 480 + 2 + 1 + 43,
+                       .vdisplay = 640,
+                       .vsync_start = 640 + 4,
+                       .vsync_end = 640 + 4 + 1,
+                       .vtotal = 640 + 4 + 1 + 8,
+                       .vrefresh = 60,
+               },
+               .bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE,
+       },
+       {
+               .name = "400x240 RGB",
+               .magic = TPG110_RES_400X240_D,
+               .mode = {
+                       .clock = 8300,
+                       .hdisplay = 400,
+                       .hsync_start = 400 + 20,
+                       .hsync_end = 400 + 20 + 1,
+                       .htotal = 400 + 20 + 1 + 108,
+                       .vdisplay = 240,
+                       .vsync_start = 240 + 2,
+                       .vsync_end = 240 + 2 + 1,
+                       .vtotal = 240 + 2 + 1 + 20,
+                       .vrefresh = 60,
+               },
+               .bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE,
+       },
+};
+
+static inline struct tpg110 *
+to_tpg110(struct drm_panel *panel)
+{
+       return container_of(panel, struct tpg110, panel);
+}
+
+static u8 tpg110_readwrite_reg(struct tpg110 *tpg, bool write,
+                              u8 address, u8 outval)
+{
+       struct spi_message m;
+       struct spi_transfer t[2];
+       u8 buf[2];
+       int ret;
+
+       spi_message_init(&m);
+       memset(t, 0, sizeof(t));
+
+       if (write) {
+               /*
+                * Clear address bit 0, 1 when writing, just to be sure
+                * The actual bit indicating a write here is bit 1, bit
+                * 0 is just surplus to pad it up to 8 bits.
+                */
+               buf[0] = address << 2;
+               buf[0] &= ~0x03;
+               buf[1] = outval;
+
+               t[0].bits_per_word = 8;
+               t[0].tx_buf = &buf[0];
+               t[0].len = 1;
+
+               t[1].tx_buf = &buf[1];
+               t[1].len = 1;
+               t[1].bits_per_word = 8;
+       } else {
+               /* Set address bit 0 to 1 to read */
+               buf[0] = address << 1;
+               buf[0] |= 0x01;
+
+               /*
+                * The last bit/clock is Hi-Z turnaround cycle, so we need
+                * to send only 7 bits here. The 8th bit is the high impedance
+                * turn-around cycle.
+                */
+               t[0].bits_per_word = 7;
+               t[0].tx_buf = &buf[0];
+               t[0].len = 1;
+
+               t[1].rx_buf = &buf[1];
+               t[1].len = 1;
+               t[1].bits_per_word = 8;
+       }
+
+       spi_message_add_tail(&t[0], &m);
+       spi_message_add_tail(&t[1], &m);
+       ret = spi_sync(tpg->spi, &m);
+       if (ret) {
+               DRM_DEV_ERROR(tpg->dev, "SPI message error %d\n", ret);
+               return ret;
+       }
+       if (write)
+               return 0;
+       /* Read */
+       return buf[1];
+}
+
+static u8 tpg110_read_reg(struct tpg110 *tpg, u8 address)
+{
+       return tpg110_readwrite_reg(tpg, false, address, 0);
+}
+
+static void tpg110_write_reg(struct tpg110 *tpg, u8 address, u8 outval)
+{
+       tpg110_readwrite_reg(tpg, true, address, outval);
+}
+
+static int tpg110_startup(struct tpg110 *tpg)
+{
+       u8 val;
+       int i;
+
+       /* De-assert the reset signal */
+       gpiod_set_value_cansleep(tpg->grestb, 0);
+       usleep_range(1000, 2000);
+       DRM_DEV_DEBUG(tpg->dev, "de-asserted GRESTB\n");
+
+       /* Test display communication */
+       tpg110_write_reg(tpg, TPG110_TEST, 0x55);
+       val = tpg110_read_reg(tpg, TPG110_TEST);
+       if (val != 0x55) {
+               DRM_DEV_ERROR(tpg->dev, "failed communication test\n");
+               return -ENODEV;
+       }
+
+       val = tpg110_read_reg(tpg, TPG110_CHIPID);
+       DRM_DEV_INFO(tpg->dev, "TPG110 chip ID: %d version: %d\n",
+                val >> 4, val & 0x0f);
+
+       /* Show display resolution */
+       val = tpg110_read_reg(tpg, TPG110_CTRL1);
+       val &= TPG110_RES_MASK;
+       switch (val) {
+       case TPG110_RES_400X240_D:
+               DRM_DEV_INFO(tpg->dev,
+                        "IN 400x240 RGB -> OUT 800x480 RGB (dual scan)\n");
+               break;
+       case TPG110_RES_480X272_D:
+               DRM_DEV_INFO(tpg->dev,
+                        "IN 480x272 RGB -> OUT 800x480 RGB (dual scan)\n");
+               break;
+       case TPG110_RES_480X640:
+               DRM_DEV_INFO(tpg->dev, "480x640 RGB\n");
+               break;
+       case TPG110_RES_480X272:
+               DRM_DEV_INFO(tpg->dev, "480x272 RGB\n");
+               break;
+       case TPG110_RES_640X480:
+               DRM_DEV_INFO(tpg->dev, "640x480 RGB\n");
+               break;
+       case TPG110_RES_800X480:
+               DRM_DEV_INFO(tpg->dev, "800x480 RGB\n");
+               break;
+       default:
+               DRM_DEV_ERROR(tpg->dev, "ILLEGAL RESOLUTION 0x%02x\n", val);
+               break;
+       }
+
+       /* From the producer side, this is the same resolution */
+       if (val == TPG110_RES_480X272_D)
+               val = TPG110_RES_480X272;
+
+       for (i = 0; i < ARRAY_SIZE(tpg110_modes); i++) {
+               const struct tpg110_panel_mode *pm;
+
+               pm = &tpg110_modes[i];
+               if (pm->magic == val) {
+                       tpg->panel_mode = pm;
+                       break;
+               }
+       }
+       if (i == ARRAY_SIZE(tpg110_modes)) {
+               DRM_DEV_ERROR(tpg->dev, "unsupported mode (%02x) detected\n",
+                       val);
+               return -ENODEV;
+       }
+
+       val = tpg110_read_reg(tpg, TPG110_CTRL2);
+       DRM_DEV_INFO(tpg->dev, "resolution and standby is controlled by %s\n",
+                (val & TPG110_CTRL2_RES_PM_CTRL) ? "software" : "hardware");
+       /* Take control over resolution and standby */
+       val |= TPG110_CTRL2_RES_PM_CTRL;
+       tpg110_write_reg(tpg, TPG110_CTRL2, val);
+
+       return 0;
+}
+
+static int tpg110_disable(struct drm_panel *panel)
+{
+       struct tpg110 *tpg = to_tpg110(panel);
+       u8 val;
+
+       /* Put chip into standby */
+       val = tpg110_read_reg(tpg, TPG110_CTRL2_PM);
+       val &= ~TPG110_CTRL2_PM;
+       tpg110_write_reg(tpg, TPG110_CTRL2_PM, val);
+
+       backlight_disable(tpg->backlight);
+
+       return 0;
+}
+
+static int tpg110_enable(struct drm_panel *panel)
+{
+       struct tpg110 *tpg = to_tpg110(panel);
+       u8 val;
+
+       backlight_enable(tpg->backlight);
+
+       /* Take chip out of standby */
+       val = tpg110_read_reg(tpg, TPG110_CTRL2_PM);
+       val |= TPG110_CTRL2_PM;
+       tpg110_write_reg(tpg, TPG110_CTRL2_PM, val);
+
+       return 0;
+}
+
+/**
+ * tpg110_get_modes() - return the appropriate mode
+ * @panel: the panel to get the mode for
+ *
+ * This currently does not present a forest of modes, instead it
+ * presents the mode that is configured for the system under use,
+ * and which is detected by reading the registers of the display.
+ */
+static int tpg110_get_modes(struct drm_panel *panel)
+{
+       struct drm_connector *connector = panel->connector;
+       struct tpg110 *tpg = to_tpg110(panel);
+       struct drm_display_mode *mode;
+
+       strncpy(connector->display_info.name, tpg->panel_mode->name,
+               DRM_DISPLAY_INFO_LEN);
+       connector->display_info.width_mm = tpg->width;
+       connector->display_info.height_mm = tpg->height;
+       connector->display_info.bus_flags = tpg->panel_mode->bus_flags;
+
+       mode = drm_mode_duplicate(panel->drm, &tpg->panel_mode->mode);
+       drm_mode_set_name(mode);
+       mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+
+       mode->width_mm = tpg->width;
+       mode->height_mm = tpg->height;
+
+       drm_mode_probed_add(connector, mode);
+
+       return 1;
+}
+
+static const struct drm_panel_funcs tpg110_drm_funcs = {
+       .disable = tpg110_disable,
+       .enable = tpg110_enable,
+       .get_modes = tpg110_get_modes,
+};
+
+static int tpg110_probe(struct spi_device *spi)
+{
+       struct device *dev = &spi->dev;
+       struct device_node *np = dev->of_node;
+       struct tpg110 *tpg;
+       int ret;
+
+       tpg = devm_kzalloc(dev, sizeof(*tpg), GFP_KERNEL);
+       if (!tpg)
+               return -ENOMEM;
+       tpg->dev = dev;
+
+       /* We get the physical display dimensions from the DT */
+       ret = of_property_read_u32(np, "width-mm", &tpg->width);
+       if (ret)
+               DRM_DEV_ERROR(dev, "no panel width specified\n");
+       ret = of_property_read_u32(np, "height-mm", &tpg->height);
+       if (ret)
+               DRM_DEV_ERROR(dev, "no panel height specified\n");
+
+       /* Look for some optional backlight */
+       tpg->backlight = devm_of_find_backlight(dev);
+       if (IS_ERR(tpg->backlight))
+               return PTR_ERR(tpg->backlight);
+
+       /* This asserts the GRESTB signal, putting the display into reset */
+       tpg->grestb = devm_gpiod_get(dev, "grestb", GPIOD_OUT_HIGH);
+       if (IS_ERR(tpg->grestb)) {
+               DRM_DEV_ERROR(dev, "no GRESTB GPIO\n");
+               return -ENODEV;
+       }
+
+       spi->bits_per_word = 8;
+       spi->mode |= SPI_3WIRE_HIZ;
+       ret = spi_setup(spi);
+       if (ret < 0) {
+               DRM_DEV_ERROR(dev, "spi setup failed.\n");
+               return ret;
+       }
+       tpg->spi = spi;
+
+       ret = tpg110_startup(tpg);
+       if (ret)
+               return ret;
+
+       drm_panel_init(&tpg->panel);
+       tpg->panel.dev = dev;
+       tpg->panel.funcs = &tpg110_drm_funcs;
+       spi_set_drvdata(spi, tpg);
+
+       return drm_panel_add(&tpg->panel);
+}
+
+static int tpg110_remove(struct spi_device *spi)
+{
+       struct tpg110 *tpg = spi_get_drvdata(spi);
+
+       drm_panel_remove(&tpg->panel);
+       return 0;
+}
+
+static const struct of_device_id tpg110_match[] = {
+       { .compatible = "tpo,tpg110", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, tpg110_match);
+
+static struct spi_driver tpg110_driver = {
+       .probe          = tpg110_probe,
+       .remove         = tpg110_remove,
+       .driver         = {
+               .name   = "tpo-tpg110-panel",
+               .of_match_table = tpg110_match,
+       },
+};
+module_spi_driver(tpg110_driver);
+
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
+MODULE_DESCRIPTION("TPO TPG110 panel driver");
+MODULE_LICENSE("GPL v2");
index dffc5093ff16b96cbd8f6f4ee0b99670f8032303..2e100f644236b6e4289b026e66428435b2a30b7b 100644 (file)
@@ -25,6 +25,8 @@
 
 /* QXL cmd/ring handling */
 
+#include <drm/drm_util.h>
+
 #include "qxl_drv.h"
 #include "qxl_object.h"
 
index ce0b9c40fc212fb88ebc37391a1cf0be2a0a763a..1f8fddcc34d61a9880464f3f9334d10d7ebf0e34 100644 (file)
@@ -48,8 +48,8 @@ static int qxl_alloc_client_monitors_config(struct qxl_device *qdev,
        }
        if (!qdev->client_monitors_config) {
                qdev->client_monitors_config = kzalloc(
-                               sizeof(struct qxl_monitors_config) +
-                               sizeof(struct qxl_head) * count, GFP_KERNEL);
+                               struct_size(qdev->client_monitors_config,
+                               heads, count), GFP_KERNEL);
                if (!qdev->client_monitors_config)
                        return -ENOMEM;
        }
@@ -1010,7 +1010,6 @@ static void qxl_conn_destroy(struct drm_connector *connector)
 }
 
 static const struct drm_connector_funcs qxl_connector_funcs = {
-       .dpms = drm_helper_connector_dpms,
        .detect = qxl_conn_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .destroy = qxl_conn_destroy,
index c9890afe69d6b0376c686c2442045b91c657f6a3..b91af1bf531b1a05461b3d8094b86617209dc1da 100644 (file)
@@ -560,11 +560,12 @@ static int r128_do_init_cce(struct drm_device *dev, drm_r128_init_t *init)
                dev_priv->gart_info.addr = NULL;
                dev_priv->gart_info.bus_addr = 0;
                dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
-               if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
+               rc = drm_ati_pcigart_init(dev, &dev_priv->gart_info);
+               if (rc) {
                        DRM_ERROR("failed to init PCI GART!\n");
                        dev->dev_private = (void *)dev_priv;
                        r128_do_cleanup_cce(dev);
-                       return -ENOMEM;
+                       return rc;
                }
                R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr);
 #if IS_ENABLED(CONFIG_AGP)
index e55cbeee7a5376bb8008042dd53a160bc6e06f95..ac98ad5618700d54564cfb51cba5d25f4b8b9464 100644 (file)
@@ -27,6 +27,8 @@
 #include <linux/slab.h>
 #include <asm/unaligned.h>
 
+#include <drm/drm_util.h>
+
 #define ATOM_DEBUG
 
 #include "atom.h"
index d587779a80b4d0748785b5430078a638ef290798..a97294ac96d5914b2cfdd561649a0ccdf56a9fb6 100644 (file)
@@ -5676,7 +5676,7 @@ int ci_dpm_init(struct radeon_device *rdev)
        u16 data_offset, size;
        u8 frev, crev;
        struct ci_power_info *pi;
-       enum pci_bus_speed speed_cap;
+       enum pci_bus_speed speed_cap = PCI_SPEED_UNKNOWN;
        struct pci_dev *root = rdev->pdev->bus->self;
        int ret;
 
@@ -5685,7 +5685,8 @@ int ci_dpm_init(struct radeon_device *rdev)
                return -ENOMEM;
        rdev->pm.dpm.priv = pi;
 
-       speed_cap = pcie_get_speed_cap(root);
+       if (!pci_is_root_bus(rdev->pdev->bus))
+               speed_cap = pcie_get_speed_cap(root);
        if (speed_cap == PCI_SPEED_UNKNOWN) {
                pi->sys_pcie_mask = 0;
        } else {
index 770e31f5fd1b0c720762aeb8b9eee949c5c01aa0..96f71114237a869e7fa7d92068f3916712511ee2 100644 (file)
@@ -516,21 +516,17 @@ static int radeon_audio_set_avi_packet(struct drm_encoder *encoder,
        if (!connector)
                return -EINVAL;
 
-       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
+       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, connector, mode);
        if (err < 0) {
                DRM_ERROR("failed to setup AVI infoframe: %d\n", err);
                return err;
        }
 
        if (radeon_encoder->output_csc != RADEON_OUTPUT_CSC_BYPASS) {
-               if (drm_rgb_quant_range_selectable(radeon_connector_edid(connector))) {
-                       if (radeon_encoder->output_csc == RADEON_OUTPUT_CSC_TVRGB)
-                               frame.quantization_range = HDMI_QUANTIZATION_RANGE_LIMITED;
-                       else
-                               frame.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
-               } else {
-                       frame.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
-               }
+               drm_hdmi_avi_infoframe_quant_range(&frame, connector, mode,
+                                                  radeon_encoder->output_csc == RADEON_OUTPUT_CSC_TVRGB ?
+                                                  HDMI_QUANTIZATION_RANGE_LIMITED :
+                                                  HDMI_QUANTIZATION_RANGE_FULL);
        }
 
        err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
index 9d3ac8b981dab3d324e2864495c5fe739f4d675f..b190478ad087fff6027f29892b8ba036505da873 100644 (file)
@@ -1646,7 +1646,7 @@ void radeon_modeset_fini(struct radeon_device *rdev)
        if (rdev->mode_info.mode_config_initialized) {
                drm_kms_helper_poll_fini(rdev->ddev);
                radeon_hpd_fini(rdev);
-               drm_crtc_force_disable_all(rdev->ddev);
+               drm_helper_force_disable_all(rdev->ddev);
                radeon_fbdev_fini(rdev);
                radeon_afmt_fini(rdev);
                drm_mode_config_cleanup(rdev->ddev);
index 84b3ad2172a37300195bb23c73abc601b1b69e43..a0c70e27ab65a48ad78fd9e48ef636c1e12e03cc 100644 (file)
@@ -320,19 +320,10 @@ static void radeon_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
        DRM_DEBUG_KMS("\n");
 }
 
-static void radeon_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
-{
-       struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr);
-       struct drm_device *dev = master->base.dev;
-
-       drm_kms_helper_hotplug_event(dev);
-}
-
 static const struct drm_dp_mst_topology_cbs mst_cbs = {
        .add_connector = radeon_dp_add_mst_connector,
        .register_connector = radeon_dp_register_mst_connector,
        .destroy_connector = radeon_dp_destroy_mst_connector,
-       .hotplug = radeon_dp_mst_hotplug,
 };
 
 static struct
index 222a1fa41d7c96c2e1853fcddfd3f6d64f56a196..7e3257e8fd5604f72366aa8febc8e0de1198d920 100644 (file)
@@ -24,6 +24,7 @@
  *          Alex Deucher
  */
 #include <drm/drmP.h>
+#include <drm/drm_util.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/radeon_drm.h>
 #include "radeon.h"
index 8fb60b3af015804d6d5ee3ef5d6f24ba74e2b1d9..0a785ef0ab660f41c2a204fb766068c93dcfa044 100644 (file)
@@ -6899,7 +6899,7 @@ int si_dpm_init(struct radeon_device *rdev)
        struct ni_power_info *ni_pi;
        struct si_power_info *si_pi;
        struct atom_clock_dividers dividers;
-       enum pci_bus_speed speed_cap;
+       enum pci_bus_speed speed_cap = PCI_SPEED_UNKNOWN;
        struct pci_dev *root = rdev->pdev->bus->self;
        int ret;
 
@@ -6911,7 +6911,8 @@ int si_dpm_init(struct radeon_device *rdev)
        eg_pi = &ni_pi->eg;
        pi = &eg_pi->rv7xx;
 
-       speed_cap = pcie_get_speed_cap(root);
+       if (!pci_is_root_bus(rdev->pdev->bus))
+               speed_cap = pcie_get_speed_cap(root);
        if (speed_cap == PCI_SPEED_UNKNOWN) {
                si_pi->sys_pcie_mask = 0;
        } else {
index 90dacab67be5a8629525ed30665d58b93eeb2878..771b460c721630e56f5d4238d0c57ce3ef5d8d18 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/mutex.h>
 #include <linux/sys_soc.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
@@ -22,6 +21,7 @@
 
 #include "rcar_du_crtc.h"
 #include "rcar_du_drv.h"
+#include "rcar_du_encoder.h"
 #include "rcar_du_kms.h"
 #include "rcar_du_plane.h"
 #include "rcar_du_regs.h"
@@ -316,26 +316,6 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
        rcar_du_crtc_write(rcrtc, DEWR,  mode->hdisplay);
 }
 
-void rcar_du_crtc_route_output(struct drm_crtc *crtc,
-                              enum rcar_du_output output)
-{
-       struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
-       struct rcar_du_device *rcdu = rcrtc->group->dev;
-
-       /*
-        * Store the route from the CRTC output to the DU output. The DU will be
-        * configured when starting the CRTC.
-        */
-       rcrtc->outputs |= BIT(output);
-
-       /*
-        * Store RGB routing to DPAD0, the hardware will be configured when
-        * starting the CRTC.
-        */
-       if (output == RCAR_DU_OUTPUT_DPAD0)
-               rcdu->dpad0_source = rcrtc->index;
-}
-
 static unsigned int plane_zpos(struct rcar_du_plane *plane)
 {
        return plane->plane.state->normalized_zpos;
@@ -655,6 +635,24 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
  * CRTC Functions
  */
 
+static int rcar_du_crtc_atomic_check(struct drm_crtc *crtc,
+                                    struct drm_crtc_state *state)
+{
+       struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(state);
+       struct drm_encoder *encoder;
+
+       /* Store the routes from the CRTC output to the DU outputs. */
+       rstate->outputs = 0;
+
+       drm_for_each_encoder_mask(encoder, crtc->dev, state->encoder_mask) {
+               struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
+
+               rstate->outputs |= BIT(renc->output);
+       }
+
+       return 0;
+}
+
 static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
                                       struct drm_crtc_state *old_state)
 {
@@ -678,8 +676,6 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
                crtc->state->event = NULL;
        }
        spin_unlock_irq(&crtc->dev->event_lock);
-
-       rcrtc->outputs = 0;
 }
 
 static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -755,6 +751,7 @@ enum drm_mode_status rcar_du_crtc_mode_valid(struct drm_crtc *crtc,
 }
 
 static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
+       .atomic_check = rcar_du_crtc_atomic_check,
        .atomic_begin = rcar_du_crtc_atomic_begin,
        .atomic_flush = rcar_du_crtc_atomic_flush,
        .atomic_enable = rcar_du_crtc_atomic_enable,
index 59ac6e7d22c932777d1ca96dcee8f537d9d24ea1..bcb35b0b761202008af2a0df010154e2d747c316 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/spinlock.h>
 #include <linux/wait.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 
 #include <media/vsp1.h>
@@ -37,7 +36,6 @@ struct rcar_du_vsp;
  * @vblank_lock: protects vblank_wait and vblank_count
  * @vblank_wait: wait queue used to signal vertical blanking
  * @vblank_count: number of vertical blanking interrupts to wait for
- * @outputs: bitmask of the outputs (enum rcar_du_output) driven by this CRTC
  * @group: CRTC group this CRTC belongs to
  * @vsp: VSP feeding video to this CRTC
  * @vsp_pipe: index of the VSP pipeline feeding video to this CRTC
@@ -61,8 +59,6 @@ struct rcar_du_crtc {
        wait_queue_head_t vblank_wait;
        unsigned int vblank_count;
 
-       unsigned int outputs;
-
        struct rcar_du_group *group;
        struct rcar_du_vsp *vsp;
        unsigned int vsp_pipe;
@@ -77,11 +73,13 @@ struct rcar_du_crtc {
  * struct rcar_du_crtc_state - Driver-specific CRTC state
  * @state: base DRM CRTC state
  * @crc: CRC computation configuration
+ * @outputs: bitmask of the outputs (enum rcar_du_output) driven by this CRTC
  */
 struct rcar_du_crtc_state {
        struct drm_crtc_state state;
 
        struct vsp1_du_crc_config crc;
+       unsigned int outputs;
 };
 
 #define to_rcar_crtc_state(s) container_of(s, struct rcar_du_crtc_state, state)
@@ -102,8 +100,6 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
 void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc);
 void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc);
 
-void rcar_du_crtc_route_output(struct drm_crtc *crtc,
-                              enum rcar_du_output output);
 void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc);
 
 void rcar_du_crtc_dsysr_clr_set(struct rcar_du_crtc *rcrtc, u32 clr, u32 set);
index f50a3b1864bbe199c97d9df4a6ac018b12da7e67..d1f305694367e1896f1ad678ba9f2de4c7d7ee37 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/slab.h>
 #include <linux/wait.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_cma_helper.h>
@@ -36,7 +35,6 @@
 static const struct rcar_du_device_info rzg1_du_r8a7743_info = {
        .gen = 2,
        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
-                 | RCAR_DU_FEATURE_EXT_CTRL_REGS
                  | RCAR_DU_FEATURE_INTERLACED
                  | RCAR_DU_FEATURE_TVM_SYNC,
        .channels_mask = BIT(1) | BIT(0),
@@ -59,7 +57,6 @@ static const struct rcar_du_device_info rzg1_du_r8a7743_info = {
 static const struct rcar_du_device_info rzg1_du_r8a7745_info = {
        .gen = 2,
        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
-                 | RCAR_DU_FEATURE_EXT_CTRL_REGS
                  | RCAR_DU_FEATURE_INTERLACED
                  | RCAR_DU_FEATURE_TVM_SYNC,
        .channels_mask = BIT(1) | BIT(0),
@@ -81,7 +78,6 @@ static const struct rcar_du_device_info rzg1_du_r8a7745_info = {
 static const struct rcar_du_device_info rzg1_du_r8a77470_info = {
        .gen = 2,
        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
-                 | RCAR_DU_FEATURE_EXT_CTRL_REGS
                  | RCAR_DU_FEATURE_INTERLACED
                  | RCAR_DU_FEATURE_TVM_SYNC,
        .channels_mask = BIT(1) | BIT(0),
@@ -105,8 +101,34 @@ static const struct rcar_du_device_info rzg1_du_r8a77470_info = {
        },
 };
 
+static const struct rcar_du_device_info rcar_du_r8a774c0_info = {
+       .gen = 3,
+       .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
+                 | RCAR_DU_FEATURE_VSP1_SOURCE,
+       .channels_mask = BIT(1) | BIT(0),
+       .routes = {
+               /*
+                * R8A774C0 has one RGB output and two LVDS outputs
+                */
+               [RCAR_DU_OUTPUT_DPAD0] = {
+                       .possible_crtcs = BIT(0) | BIT(1),
+                       .port = 0,
+               },
+               [RCAR_DU_OUTPUT_LVDS0] = {
+                       .possible_crtcs = BIT(0),
+                       .port = 1,
+               },
+               [RCAR_DU_OUTPUT_LVDS1] = {
+                       .possible_crtcs = BIT(1),
+                       .port = 2,
+               },
+       },
+       .num_lvds = 2,
+       .lvds_clk_mask =  BIT(1) | BIT(0),
+};
+
 static const struct rcar_du_device_info rcar_du_r8a7779_info = {
-       .gen = 2,
+       .gen = 1,
        .features = RCAR_DU_FEATURE_INTERLACED
                  | RCAR_DU_FEATURE_TVM_SYNC,
        .channels_mask = BIT(1) | BIT(0),
@@ -129,7 +151,6 @@ static const struct rcar_du_device_info rcar_du_r8a7779_info = {
 static const struct rcar_du_device_info rcar_du_r8a7790_info = {
        .gen = 2,
        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
-                 | RCAR_DU_FEATURE_EXT_CTRL_REGS
                  | RCAR_DU_FEATURE_INTERLACED
                  | RCAR_DU_FEATURE_TVM_SYNC,
        .quirks = RCAR_DU_QUIRK_ALIGN_128B,
@@ -159,7 +180,6 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = {
 static const struct rcar_du_device_info rcar_du_r8a7791_info = {
        .gen = 2,
        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
-                 | RCAR_DU_FEATURE_EXT_CTRL_REGS
                  | RCAR_DU_FEATURE_INTERLACED
                  | RCAR_DU_FEATURE_TVM_SYNC,
        .channels_mask = BIT(1) | BIT(0),
@@ -183,7 +203,6 @@ static const struct rcar_du_device_info rcar_du_r8a7791_info = {
 static const struct rcar_du_device_info rcar_du_r8a7792_info = {
        .gen = 2,
        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
-                 | RCAR_DU_FEATURE_EXT_CTRL_REGS
                  | RCAR_DU_FEATURE_INTERLACED
                  | RCAR_DU_FEATURE_TVM_SYNC,
        .channels_mask = BIT(1) | BIT(0),
@@ -203,7 +222,6 @@ static const struct rcar_du_device_info rcar_du_r8a7792_info = {
 static const struct rcar_du_device_info rcar_du_r8a7794_info = {
        .gen = 2,
        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
-                 | RCAR_DU_FEATURE_EXT_CTRL_REGS
                  | RCAR_DU_FEATURE_INTERLACED
                  | RCAR_DU_FEATURE_TVM_SYNC,
        .channels_mask = BIT(1) | BIT(0),
@@ -226,7 +244,6 @@ static const struct rcar_du_device_info rcar_du_r8a7794_info = {
 static const struct rcar_du_device_info rcar_du_r8a7795_info = {
        .gen = 3,
        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
-                 | RCAR_DU_FEATURE_EXT_CTRL_REGS
                  | RCAR_DU_FEATURE_VSP1_SOURCE
                  | RCAR_DU_FEATURE_INTERLACED
                  | RCAR_DU_FEATURE_TVM_SYNC,
@@ -260,7 +277,6 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = {
 static const struct rcar_du_device_info rcar_du_r8a7796_info = {
        .gen = 3,
        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
-                 | RCAR_DU_FEATURE_EXT_CTRL_REGS
                  | RCAR_DU_FEATURE_VSP1_SOURCE
                  | RCAR_DU_FEATURE_INTERLACED
                  | RCAR_DU_FEATURE_TVM_SYNC,
@@ -290,7 +306,6 @@ static const struct rcar_du_device_info rcar_du_r8a7796_info = {
 static const struct rcar_du_device_info rcar_du_r8a77965_info = {
        .gen = 3,
        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
-                 | RCAR_DU_FEATURE_EXT_CTRL_REGS
                  | RCAR_DU_FEATURE_VSP1_SOURCE
                  | RCAR_DU_FEATURE_INTERLACED
                  | RCAR_DU_FEATURE_TVM_SYNC,
@@ -320,7 +335,6 @@ static const struct rcar_du_device_info rcar_du_r8a77965_info = {
 static const struct rcar_du_device_info rcar_du_r8a77970_info = {
        .gen = 3,
        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
-                 | RCAR_DU_FEATURE_EXT_CTRL_REGS
                  | RCAR_DU_FEATURE_VSP1_SOURCE
                  | RCAR_DU_FEATURE_INTERLACED
                  | RCAR_DU_FEATURE_TVM_SYNC,
@@ -342,7 +356,6 @@ static const struct rcar_du_device_info rcar_du_r8a77970_info = {
 static const struct rcar_du_device_info rcar_du_r8a7799x_info = {
        .gen = 3,
        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
-                 | RCAR_DU_FEATURE_EXT_CTRL_REGS
                  | RCAR_DU_FEATURE_VSP1_SOURCE,
        .channels_mask = BIT(1) | BIT(0),
        .routes = {
@@ -372,6 +385,7 @@ static const struct of_device_id rcar_du_of_table[] = {
        { .compatible = "renesas,du-r8a7744", .data = &rzg1_du_r8a7743_info },
        { .compatible = "renesas,du-r8a7745", .data = &rzg1_du_r8a7745_info },
        { .compatible = "renesas,du-r8a77470", .data = &rzg1_du_r8a77470_info },
+       { .compatible = "renesas,du-r8a774c0", .data = &rcar_du_r8a774c0_info },
        { .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
        { .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
        { .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
index a68da79b424ee50308ad18a7447d03f6fba300c2..6c187d0bf7c29e546bf27d7c468151186a74c135 100644 (file)
 struct clk;
 struct device;
 struct drm_device;
+struct drm_property;
 struct rcar_du_device;
 
 #define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK BIT(0)  /* Per-CRTC IRQ and clock */
-#define RCAR_DU_FEATURE_EXT_CTRL_REGS  BIT(1)  /* Has extended control registers */
-#define RCAR_DU_FEATURE_VSP1_SOURCE    BIT(2)  /* Has inputs from VSP1 */
-#define RCAR_DU_FEATURE_INTERLACED     BIT(3)  /* HW supports interlaced */
-#define RCAR_DU_FEATURE_TVM_SYNC       BIT(4)  /* Has TV switch/sync modes */
+#define RCAR_DU_FEATURE_VSP1_SOURCE    BIT(1)  /* Has inputs from VSP1 */
+#define RCAR_DU_FEATURE_INTERLACED     BIT(2)  /* HW supports interlaced */
+#define RCAR_DU_FEATURE_TVM_SYNC       BIT(3)  /* Has TV switch/sync modes */
 
 #define RCAR_DU_QUIRK_ALIGN_128B       BIT(0)  /* Align pitches to 128 bytes */
 
@@ -89,6 +89,7 @@ struct rcar_du_device {
        } props;
 
        unsigned int dpad0_source;
+       unsigned int dpad1_source;
        unsigned int vspd1_sink;
 };
 
index 1877764bd6d93fa566f3122bc55b845e07de28c0..f162094991172af0216b30588066f92dd86ec25d 100644 (file)
@@ -9,7 +9,6 @@
 
 #include <linux/export.h>
 
-#include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_panel.h>
  * Encoder
  */
 
-static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
-                                    struct drm_crtc_state *crtc_state,
-                                    struct drm_connector_state *conn_state)
-{
-       struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
-
-       rcar_du_crtc_route_output(crtc_state->crtc, renc->output);
-}
-
 static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
-       .atomic_mode_set = rcar_du_encoder_mode_set,
 };
 
 static const struct drm_encoder_funcs encoder_funcs = {
index ce3cbc85695eb985b1f0fecdf83082a329cab5d8..552f2a02e5b5d178e077d8b97c880ce975406137 100644 (file)
 #ifndef __RCAR_DU_ENCODER_H__
 #define __RCAR_DU_ENCODER_H__
 
-#include <drm/drm_crtc.h>
 #include <drm/drm_encoder.h>
 
-struct drm_panel;
 struct rcar_du_device;
 
 struct rcar_du_encoder {
index cebf313c6e1f9290dd8817099fb6388d25649032..9eee47969e77818805ba5b9baf595eab05f9dc67 100644 (file)
@@ -147,7 +147,7 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
 
        rcar_du_group_setup_pins(rgrp);
 
-       if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) {
+       if (rcdu->info->gen >= 2) {
                rcar_du_group_setup_defr8(rgrp);
                rcar_du_group_setup_didsr(rgrp);
        }
@@ -262,7 +262,7 @@ int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu)
        unsigned int index;
        int ret;
 
-       if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_EXT_CTRL_REGS))
+       if (rcdu->info->gen < 2)
                return 0;
 
        /*
@@ -287,9 +287,50 @@ int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu)
        return 0;
 }
 
+static void rcar_du_group_set_dpad_levels(struct rcar_du_group *rgrp)
+{
+       static const u32 doflr_values[2] = {
+               DOFLR_HSYCFL0 | DOFLR_VSYCFL0 | DOFLR_ODDFL0 |
+               DOFLR_DISPFL0 | DOFLR_CDEFL0  | DOFLR_RGBFL0,
+               DOFLR_HSYCFL1 | DOFLR_VSYCFL1 | DOFLR_ODDFL1 |
+               DOFLR_DISPFL1 | DOFLR_CDEFL1  | DOFLR_RGBFL1,
+       };
+       static const u32 dpad_mask = BIT(RCAR_DU_OUTPUT_DPAD1)
+                                  | BIT(RCAR_DU_OUTPUT_DPAD0);
+       struct rcar_du_device *rcdu = rgrp->dev;
+       u32 doflr = DOFLR_CODE;
+       unsigned int i;
+
+       if (rcdu->info->gen < 2)
+               return;
+
+       /*
+        * The DPAD outputs can't be controlled directly. However, the parallel
+        * output of the DU channels routed to DPAD can be set to fixed levels
+        * through the DOFLR group register. Use this to turn the DPAD on or off
+        * by driving fixed low-level signals at the output of any DU channel
+        * not routed to a DPAD output. This doesn't affect the DU output
+        * signals going to other outputs, such as the internal LVDS and HDMI
+        * encoders.
+        */
+
+       for (i = 0; i < rgrp->num_crtcs; ++i) {
+               struct rcar_du_crtc_state *rstate;
+               struct rcar_du_crtc *rcrtc;
+
+               rcrtc = &rcdu->crtcs[rgrp->index * 2 + i];
+               rstate = to_rcar_crtc_state(rcrtc->crtc.state);
+
+               if (!(rstate->outputs & dpad_mask))
+                       doflr |= doflr_values[i];
+       }
+
+       rcar_du_group_write(rgrp, DOFLR, doflr);
+}
+
 int rcar_du_group_set_routing(struct rcar_du_group *rgrp)
 {
-       struct rcar_du_crtc *crtc0 = &rgrp->dev->crtcs[rgrp->index * 2];
+       struct rcar_du_device *rcdu = rgrp->dev;
        u32 dorcr = rcar_du_group_read(rgrp, DORCR);
 
        dorcr &= ~(DORCR_PG2T | DORCR_DK2S | DORCR_PG2D_MASK);
@@ -299,12 +340,14 @@ int rcar_du_group_set_routing(struct rcar_du_group *rgrp)
         * CRTC 1 in all other cases to avoid cloning CRTC 0 to DPAD0 and DPAD1
         * by default.
         */
-       if (crtc0->outputs & BIT(RCAR_DU_OUTPUT_DPAD1))
+       if (rcdu->dpad1_source == rgrp->index * 2)
                dorcr |= DORCR_PG2D_DS1;
        else
                dorcr |= DORCR_PG2T | DORCR_DK2S | DORCR_PG2D_DS2;
 
        rcar_du_group_write(rgrp, DORCR, dorcr);
 
+       rcar_du_group_set_dpad_levels(rgrp);
+
        return rcar_du_set_dpad0_vsp1_routing(rgrp->dev);
 }
index 9c7007d45408b921ce7a909ee1f4d661ca55db67..e4b248e368d634411092c847ab04f6913186116a 100644 (file)
@@ -7,7 +7,6 @@
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  */
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
@@ -278,6 +277,28 @@ static int rcar_du_atomic_check(struct drm_device *dev,
 static void rcar_du_atomic_commit_tail(struct drm_atomic_state *old_state)
 {
        struct drm_device *dev = old_state->dev;
+       struct rcar_du_device *rcdu = dev->dev_private;
+       struct drm_crtc_state *crtc_state;
+       struct drm_crtc *crtc;
+       unsigned int i;
+
+       /*
+        * Store RGB routing to DPAD0 and DPAD1, the hardware will be configured
+        * when starting the CRTCs.
+        */
+       rcdu->dpad1_source = -1;
+
+       for_each_new_crtc_in_state(old_state, crtc, crtc_state, i) {
+               struct rcar_du_crtc_state *rcrtc_state =
+                       to_rcar_crtc_state(crtc_state);
+               struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
+
+               if (rcrtc_state->outputs & BIT(RCAR_DU_OUTPUT_DPAD0))
+                       rcdu->dpad0_source = rcrtc->index;
+
+               if (rcrtc_state->outputs & BIT(RCAR_DU_OUTPUT_DPAD1))
+                       rcdu->dpad1_source = rcrtc->index;
+       }
 
        /* Apply the atomic update. */
        drm_atomic_helper_commit_modeset_disables(dev, old_state);
index 579753e04f3b37127cb37046532c29ec3bbce5f6..8bee4e787a0ab4eb06646b56f0ddff92cad130b5 100644 (file)
@@ -7,70 +7,63 @@
 
 /dts-v1/;
 /plugin/;
-/ {
-       fragment@0 {
-               target-path = "/";
-               __overlay__ {
-                       #address-cells = <2>;
-                       #size-cells = <2>;
 
-                       lvds@feb90000 {
-                               compatible = "renesas,r8a7790-lvds";
-                               reg = <0 0xfeb90000 0 0x1c>;
+&{/} {
+       #address-cells = <2>;
+       #size-cells = <2>;
 
-                               ports {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
+       lvds@feb90000 {
+               compatible = "renesas,r8a7790-lvds";
+               reg = <0 0xfeb90000 0 0x1c>;
 
-                                       port@0 {
-                                               reg = <0>;
-                                               lvds0_input: endpoint {
-                                               };
-                                       };
-                                       port@1 {
-                                               reg = <1>;
-                                               lvds0_out: endpoint {
-                                               };
-                                       };
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               lvds0_input: endpoint {
                                };
                        };
-
-                       lvds@feb94000 {
-                               compatible = "renesas,r8a7790-lvds";
-                               reg = <0 0xfeb94000 0 0x1c>;
-
-                               ports {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
-
-                                       port@0 {
-                                               reg = <0>;
-                                               lvds1_input: endpoint {
-                                               };
-                                       };
-                                       port@1 {
-                                               reg = <1>;
-                                               lvds1_out: endpoint {
-                                               };
-                                       };
+                       port@1 {
+                               reg = <1>;
+                               lvds0_out: endpoint {
                                };
                        };
                };
        };
 
-       fragment@1 {
-               target-path = "/display@feb00000/ports";
-               __overlay__ {
-                       port@1 {
-                               endpoint {
-                                       remote-endpoint = <&lvds0_input>;
+       lvds@feb94000 {
+               compatible = "renesas,r8a7790-lvds";
+               reg = <0 0xfeb94000 0 0x1c>;
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               lvds1_input: endpoint {
                                };
                        };
-                       port@2 {
-                               endpoint {
-                                       remote-endpoint = <&lvds1_input>;
+                       port@1 {
+                               reg = <1>;
+                               lvds1_out: endpoint {
                                };
                        };
                };
        };
 };
+
+&{/display@feb00000/ports} {
+       port@1 {
+               endpoint {
+                       remote-endpoint = <&lvds0_input>;
+               };
+       };
+       port@2 {
+               endpoint {
+                       remote-endpoint = <&lvds1_input>;
+               };
+       };
+};
index cb9da1f3942b5b30e4e731e659afddd7d562e566..92c0509971ec3df5aada19718020170253857f73 100644 (file)
@@ -7,44 +7,37 @@
 
 /dts-v1/;
 /plugin/;
-/ {
-       fragment@0 {
-               target-path = "/";
-               __overlay__ {
-                       #address-cells = <2>;
-                       #size-cells = <2>;
 
-                       lvds@feb90000 {
-                               compatible = "renesas,r8a7791-lvds";
-                               reg = <0 0xfeb90000 0 0x1c>;
+&{/} {
+       #address-cells = <2>;
+       #size-cells = <2>;
 
-                               ports {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
+       lvds@feb90000 {
+               compatible = "renesas,r8a7791-lvds";
+               reg = <0 0xfeb90000 0 0x1c>;
 
-                                       port@0 {
-                                               reg = <0>;
-                                               lvds0_input: endpoint {
-                                               };
-                                       };
-                                       port@1 {
-                                               reg = <1>;
-                                               lvds0_out: endpoint {
-                                               };
-                                       };
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               lvds0_input: endpoint {
                                };
                        };
-               };
-       };
-
-       fragment@1 {
-               target-path = "/display@feb00000/ports";
-               __overlay__ {
                        port@1 {
-                               endpoint {
-                                       remote-endpoint = <&lvds0_input>;
+                               reg = <1>;
+                               lvds0_out: endpoint {
                                };
                        };
                };
        };
 };
+
+&{/display@feb00000/ports} {
+       port@1 {
+               endpoint {
+                       remote-endpoint = <&lvds0_input>;
+               };
+       };
+};
index e7b8804dc3c1a1c5568340162fe2689c8c21a601..c8b93f21de0fbb8ed456e216aec54c463485032c 100644 (file)
@@ -7,44 +7,37 @@
 
 /dts-v1/;
 /plugin/;
-/ {
-       fragment@0 {
-               target-path = "/";
-               __overlay__ {
-                       #address-cells = <2>;
-                       #size-cells = <2>;
 
-                       lvds@feb90000 {
-                               compatible = "renesas,r8a7793-lvds";
-                               reg = <0 0xfeb90000 0 0x1c>;
+&{/} {
+       #address-cells = <2>;
+       #size-cells = <2>;
 
-                               ports {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
+       lvds@feb90000 {
+               compatible = "renesas,r8a7793-lvds";
+               reg = <0 0xfeb90000 0 0x1c>;
 
-                                       port@0 {
-                                               reg = <0>;
-                                               lvds0_input: endpoint {
-                                               };
-                                       };
-                                       port@1 {
-                                               reg = <1>;
-                                               lvds0_out: endpoint {
-                                               };
-                                       };
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               lvds0_input: endpoint {
                                };
                        };
-               };
-       };
-
-       fragment@1 {
-               target-path = "/display@feb00000/ports";
-               __overlay__ {
                        port@1 {
-                               endpoint {
-                                       remote-endpoint = <&lvds0_input>;
+                               reg = <1>;
+                               lvds0_out: endpoint {
                                };
                        };
                };
        };
 };
+
+&{/display@feb00000/ports} {
+       port@1 {
+               endpoint {
+                       remote-endpoint = <&lvds0_input>;
+               };
+       };
+};
index a1327443e6fa4d310e7c883e8885a32d9935cd03..16c2d03cb016c4701a88a81473b1a01c0e26cbec 100644 (file)
@@ -7,44 +7,37 @@
 
 /dts-v1/;
 /plugin/;
-/ {
-       fragment@0 {
-               target-path = "/soc";
-               __overlay__ {
-                       #address-cells = <2>;
-                       #size-cells = <2>;
 
-                       lvds@feb90000 {
-                               compatible = "renesas,r8a7795-lvds";
-                               reg = <0 0xfeb90000 0 0x14>;
+&{/soc} {
+       #address-cells = <2>;
+       #size-cells = <2>;
 
-                               ports {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
+       lvds@feb90000 {
+               compatible = "renesas,r8a7795-lvds";
+               reg = <0 0xfeb90000 0 0x14>;
 
-                                       port@0 {
-                                               reg = <0>;
-                                               lvds0_input: endpoint {
-                                               };
-                                       };
-                                       port@1 {
-                                               reg = <1>;
-                                               lvds0_out: endpoint {
-                                               };
-                                       };
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               lvds0_input: endpoint {
+                               };
+                       };
+                       port@1 {
+                               reg = <1>;
+                               lvds0_out: endpoint {
                                };
                        };
                };
        };
+};
 
-       fragment@1 {
-               target-path = "/soc/display@feb00000/ports";
-               __overlay__ {
-                       port@3 {
-                               endpoint {
-                                       remote-endpoint = <&lvds0_input>;
-                               };
-                       };
+&{/soc/display@feb00000/ports} {
+       port@3 {
+               endpoint {
+                       remote-endpoint = <&lvds0_input>;
                };
        };
 };
index b23d6466c4152b6f7c1c8cab4491e08aa71c6a57..680e923ac036c9321d8cc07115381cf52760ae28 100644 (file)
@@ -7,44 +7,37 @@
 
 /dts-v1/;
 /plugin/;
-/ {
-       fragment@0 {
-               target-path = "/soc";
-               __overlay__ {
-                       #address-cells = <2>;
-                       #size-cells = <2>;
 
-                       lvds@feb90000 {
-                               compatible = "renesas,r8a7796-lvds";
-                               reg = <0 0xfeb90000 0 0x14>;
+&{/soc} {
+       #address-cells = <2>;
+       #size-cells = <2>;
 
-                               ports {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
+       lvds@feb90000 {
+               compatible = "renesas,r8a7796-lvds";
+               reg = <0 0xfeb90000 0 0x14>;
 
-                                       port@0 {
-                                               reg = <0>;
-                                               lvds0_input: endpoint {
-                                               };
-                                       };
-                                       port@1 {
-                                               reg = <1>;
-                                               lvds0_out: endpoint {
-                                               };
-                                       };
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               lvds0_input: endpoint {
+                               };
+                       };
+                       port@1 {
+                               reg = <1>;
+                               lvds0_out: endpoint {
                                };
                        };
                };
        };
+};
 
-       fragment@1 {
-               target-path = "/soc/display@feb00000/ports";
-               __overlay__ {
-                       port@3 {
-                               endpoint {
-                                       remote-endpoint = <&lvds0_input>;
-                               };
-                       };
+&{/soc/display@feb00000/ports} {
+       port@3 {
+               endpoint {
+                       remote-endpoint = <&lvds0_input>;
                };
        };
 };
index 39d5ae3fdf72b1de5ffa079751b378a080a2087d..fa6b9aabc832e7add9204826a8ab78f44859ec8b 100644 (file)
@@ -7,7 +7,6 @@
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  */
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
index 2f223a4c1d3344c7d8f05452b07fe57d856a86f7..81bbf207ad0edd4045ed5423c99b91f0b1696ba0 100644 (file)
@@ -10,8 +10,7 @@
 #ifndef __RCAR_DU_PLANE_H__
 #define __RCAR_DU_PLANE_H__
 
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
+#include <drm/drm_plane.h>
 
 struct rcar_du_format_info;
 struct rcar_du_group;
index 4576119e7777f5e4105c0b3a7d43b93fd59982ce..dec314a687e097dc3743bd90eacfd1c93545be71 100644 (file)
@@ -7,7 +7,6 @@
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  */
 
-#include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
index e8c14dc5cb93f2aba129c363a9c47af88fb931a3..db232037f24a0394151d029676ab41fba363db4b 100644 (file)
@@ -10,8 +10,7 @@
 #ifndef __RCAR_DU_VSP_H__
 #define __RCAR_DU_VSP_H__
 
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
+#include <drm/drm_plane.h>
 
 struct rcar_du_format_info;
 struct rcar_du_vsp;
index 75490a3e0a2ab096b63e6b269b67c26bfe25cf23..452461dc96f28bb7028e4cd9cefaf6e3e45cbff1 100644 (file)
@@ -7,10 +7,12 @@
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  */
 
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
 #include <drm/bridge/dw_hdmi.h>
+#include <drm/drm_modes.h>
 
 #define RCAR_HDMI_PHY_OPMODE_PLLCFG    0x06    /* Mode of operation and PLL dividers */
 #define RCAR_HDMI_PHY_PLLCURRGMPCTRL   0x10    /* PLL current and Gmp (conductance) */
@@ -35,6 +37,20 @@ static const struct rcar_hdmi_phy_params rcar_hdmi_phy_params[] = {
        { ~0UL,      0x0000, 0x0000, 0x0000 },
 };
 
+static enum drm_mode_status
+rcar_hdmi_mode_valid(struct drm_connector *connector,
+                    const struct drm_display_mode *mode)
+{
+       /*
+        * The maximum supported clock frequency is 297 MHz, as shown in the PHY
+        * parameters table.
+        */
+       if (mode->clock > 297000)
+               return MODE_CLOCK_HIGH;
+
+       return MODE_OK;
+}
+
 static int rcar_hdmi_phy_configure(struct dw_hdmi *hdmi,
                                   const struct dw_hdmi_plat_data *pdata,
                                   unsigned long mpixelclock)
@@ -59,6 +75,7 @@ static int rcar_hdmi_phy_configure(struct dw_hdmi *hdmi,
 }
 
 static const struct dw_hdmi_plat_data rcar_dw_hdmi_plat_data = {
+       .mode_valid = rcar_hdmi_mode_valid,
        .configure_phy  = rcar_hdmi_phy_configure,
 };
 
index 534a128a869d51e438ed5e5c7172ec306ef5a025..96d749a35b258408f4632d86d59bd49e7ea70197 100644 (file)
@@ -520,8 +520,8 @@ static void rcar_lvds_get_lvds_mode(struct rcar_lvds *lvds)
 }
 
 static void rcar_lvds_mode_set(struct drm_bridge *bridge,
-                              struct drm_display_mode *mode,
-                              struct drm_display_mode *adjusted_mode)
+                              const struct drm_display_mode *mode,
+                              const struct drm_display_mode *adjusted_mode)
 {
        struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
 
@@ -785,6 +785,7 @@ static const struct rcar_lvds_device_info rcar_lvds_r8a77995_info = {
 
 static const struct of_device_id rcar_lvds_of_table[] = {
        { .compatible = "renesas,r8a7743-lvds", .data = &rcar_lvds_gen2_info },
+       { .compatible = "renesas,r8a774c0-lvds", .data = &rcar_lvds_r8a77990_info },
        { .compatible = "renesas,r8a7790-lvds", .data = &rcar_lvds_r8a7790_info },
        { .compatible = "renesas,r8a7791-lvds", .data = &rcar_lvds_gen2_info },
        { .compatible = "renesas,r8a7793-lvds", .data = &rcar_lvds_gen2_info },
index 7ee359bcee62521b5e83ef2533fcb065998440b9..ef8486e5e2cd121681a0710e4b5b41e06f24bd50 100644 (file)
@@ -467,7 +467,7 @@ static int dw_mipi_dsi_phy_init(void *priv_data)
 }
 
 static int
-dw_mipi_dsi_get_lane_mbps(void *priv_data, struct drm_display_mode *mode,
+dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
                          unsigned long mode_flags, u32 lanes, u32 format,
                          unsigned int *lane_mbps)
 {
index 1c02b3e61299c800549519a9f065ac2691f665fc..27c945e030a0baa766694a4f0402666fe94c1659 100644 (file)
@@ -295,7 +295,9 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
        union hdmi_infoframe frame;
        int rc;
 
-       rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
+       rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
+                                                     &hdmi->connector,
+                                                     mode);
 
        if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
                frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
index ea18cb2a76c0dc7c7e9052307dda301743a607c2..08bec50d9c5d9955e1f131d88120d92104758b2a 100644 (file)
@@ -127,42 +127,6 @@ err_gem_object_unreference:
        return ERR_PTR(ret);
 }
 
-static void
-rockchip_drm_psr_inhibit_get_state(struct drm_atomic_state *state)
-{
-       struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
-       struct drm_encoder *encoder;
-       u32 encoder_mask = 0;
-       int i;
-
-       for_each_old_crtc_in_state(state, crtc, crtc_state, i) {
-               encoder_mask |= crtc_state->encoder_mask;
-               encoder_mask |= crtc->state->encoder_mask;
-       }
-
-       drm_for_each_encoder_mask(encoder, state->dev, encoder_mask)
-               rockchip_drm_psr_inhibit_get(encoder);
-}
-
-static void
-rockchip_drm_psr_inhibit_put_state(struct drm_atomic_state *state)
-{
-       struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
-       struct drm_encoder *encoder;
-       u32 encoder_mask = 0;
-       int i;
-
-       for_each_old_crtc_in_state(state, crtc, crtc_state, i) {
-               encoder_mask |= crtc_state->encoder_mask;
-               encoder_mask |= crtc->state->encoder_mask;
-       }
-
-       drm_for_each_encoder_mask(encoder, state->dev, encoder_mask)
-               rockchip_drm_psr_inhibit_put(encoder);
-}
-
 static void
 rockchip_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state)
 {
index 01ff3c8588750ea466be307a1f820f4ed73f2fff..22a70ab6e214bb43c4db5580f58a05d46f80741f 100644 (file)
@@ -13,6 +13,7 @@
  */
 
 #include <drm/drmP.h>
+#include <drm/drm_atomic.h>
 #include <drm/drm_crtc_helper.h>
 
 #include "rockchip_drm_drv.h"
@@ -109,6 +110,42 @@ int rockchip_drm_psr_inhibit_put(struct drm_encoder *encoder)
 }
 EXPORT_SYMBOL(rockchip_drm_psr_inhibit_put);
 
+void rockchip_drm_psr_inhibit_get_state(struct drm_atomic_state *state)
+{
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *crtc_state;
+       struct drm_encoder *encoder;
+       u32 encoder_mask = 0;
+       int i;
+
+       for_each_old_crtc_in_state(state, crtc, crtc_state, i) {
+               encoder_mask |= crtc_state->encoder_mask;
+               encoder_mask |= crtc->state->encoder_mask;
+       }
+
+       drm_for_each_encoder_mask(encoder, state->dev, encoder_mask)
+               rockchip_drm_psr_inhibit_get(encoder);
+}
+EXPORT_SYMBOL(rockchip_drm_psr_inhibit_get_state);
+
+void rockchip_drm_psr_inhibit_put_state(struct drm_atomic_state *state)
+{
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *crtc_state;
+       struct drm_encoder *encoder;
+       u32 encoder_mask = 0;
+       int i;
+
+       for_each_old_crtc_in_state(state, crtc, crtc_state, i) {
+               encoder_mask |= crtc_state->encoder_mask;
+               encoder_mask |= crtc->state->encoder_mask;
+       }
+
+       drm_for_each_encoder_mask(encoder, state->dev, encoder_mask)
+               rockchip_drm_psr_inhibit_put(encoder);
+}
+EXPORT_SYMBOL(rockchip_drm_psr_inhibit_put_state);
+
 /**
  * rockchip_drm_psr_inhibit_get - acquire PSR inhibit on given encoder
  * @encoder: encoder to obtain the PSR encoder
index 860c62494496e67665267ac5fccba76040fa46fb..25350ba3237b6648cec2a751b2b04bd72cefa21e 100644 (file)
@@ -20,6 +20,9 @@ void rockchip_drm_psr_flush_all(struct drm_device *dev);
 int rockchip_drm_psr_inhibit_put(struct drm_encoder *encoder);
 int rockchip_drm_psr_inhibit_get(struct drm_encoder *encoder);
 
+void rockchip_drm_psr_inhibit_get_state(struct drm_atomic_state *state);
+void rockchip_drm_psr_inhibit_put_state(struct drm_atomic_state *state);
+
 int rockchip_drm_psr_register(struct drm_encoder *encoder,
                        int (*psr_set)(struct drm_encoder *, bool enable));
 void rockchip_drm_psr_unregister(struct drm_encoder *encoder);
index fb70fb486fbf4a57da6755a4c513d2dd426d1f33..619b6db05d58c361aa35a41e404485f24fe0ffeb 100644 (file)
 #include <drm/drm.h>
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_uapi.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_flip_work.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_plane_helper.h>
 #ifdef CONFIG_DRM_ANALOGIX_DP
 #include <drm/bridge/analogix_dp.h>
 #include "rockchip_drm_vop.h"
 #include "rockchip_rgb.h"
 
-#define VOP_WIN_SET(x, win, name, v) \
+#define VOP_WIN_SET(vop, win, name, v) \
                vop_reg_set(vop, &win->phy->name, win->base, ~0, v, #name)
-#define VOP_SCL_SET(x, win, name, v) \
+#define VOP_SCL_SET(vop, win, name, v) \
                vop_reg_set(vop, &win->phy->scl->name, win->base, ~0, v, #name)
-#define VOP_SCL_SET_EXT(x, win, name, v) \
+#define VOP_SCL_SET_EXT(vop, win, name, v) \
                vop_reg_set(vop, &win->phy->scl->ext->name, \
                            win->base, ~0, v, #name)
 
+#define VOP_WIN_YUV2YUV_SET(vop, win_yuv2yuv, name, v) \
+       do { \
+               if (win_yuv2yuv && win_yuv2yuv->name.mask) \
+                       vop_reg_set(vop, &win_yuv2yuv->name, 0, ~0, v, #name); \
+       } while (0)
+
+#define VOP_WIN_YUV2YUV_COEFFICIENT_SET(vop, win_yuv2yuv, name, v) \
+       do { \
+               if (win_yuv2yuv && win_yuv2yuv->phy->name.mask) \
+                       vop_reg_set(vop, &win_yuv2yuv->phy->name, win_yuv2yuv->base, ~0, v, #name); \
+       } while (0)
+
 #define VOP_INTR_SET_MASK(vop, name, mask, v) \
                vop_reg_set(vop, &vop->data->intr->name, 0, mask, v, #name)
 
 #define VOP_INTR_GET_TYPE(vop, name, type) \
                vop_get_intr_type(vop, &vop->data->intr->name, type)
 
-#define VOP_WIN_GET(x, win, name) \
-               vop_read_reg(x, win->offset, win->phy->name)
+#define VOP_WIN_GET(vop, win, name) \
+               vop_read_reg(vop, win->offset, win->phy->name)
+
+#define VOP_WIN_HAS_REG(win, name) \
+       (!!(win->phy->name.mask))
 
 #define VOP_WIN_GET_YRGBADDR(vop, win) \
                vop_readl(vop, win->base + win->phy->yrgb_mst.offset)
 #define to_vop(x) container_of(x, struct vop, crtc)
 #define to_vop_win(x) container_of(x, struct vop_win, base)
 
+/*
+ * The coefficients of the following matrix are all fixed points.
+ * The format is S2.10 for the 3x3 part of the matrix, and S9.12 for the offsets.
+ * They are all represented in two's complement.
+ */
+static const uint32_t bt601_yuv2rgb[] = {
+       0x4A8, 0x0,    0x662,
+       0x4A8, 0x1E6F, 0x1CBF,
+       0x4A8, 0x812,  0x0,
+       0x321168, 0x0877CF, 0x2EB127
+};
+
 enum vop_pending {
        VOP_PENDING_FB_UNREF,
 };
@@ -91,6 +120,7 @@ enum vop_pending {
 struct vop_win {
        struct drm_plane base;
        const struct vop_win_data *data;
+       const struct vop_win_yuv2yuv_data *yuv2yuv_data;
        struct vop *vop;
 };
 
@@ -685,6 +715,11 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
                return -EINVAL;
        }
 
+       if (fb->format->is_yuv && state->rotation & DRM_MODE_REFLECT_Y) {
+               DRM_ERROR("Invalid Source: Yuv format does not support this rotation\n");
+               return -EINVAL;
+       }
+
        return 0;
 }
 
@@ -712,6 +747,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
        struct drm_crtc *crtc = state->crtc;
        struct vop_win *vop_win = to_vop_win(plane);
        const struct vop_win_data *win = vop_win->data;
+       const struct vop_win_yuv2yuv_data *win_yuv2yuv = vop_win->yuv2yuv_data;
        struct vop *vop = to_vop(state->crtc);
        struct drm_framebuffer *fb = state->fb;
        unsigned int actual_w, actual_h;
@@ -727,6 +763,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
        bool rb_swap;
        int win_index = VOP_WIN_TO_INDEX(vop_win);
        int format;
+       int is_yuv = fb->format->is_yuv;
+       int i;
 
        /*
         * can't update plane when vop is disabled.
@@ -760,6 +798,13 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
        offset += (src->y1 >> 16) * fb->pitches[0];
        dma_addr = rk_obj->dma_addr + offset + fb->offsets[0];
 
+       /*
+        * For y-mirroring we need to move address
+        * to the beginning of the last line.
+        */
+       if (state->rotation & DRM_MODE_REFLECT_Y)
+               dma_addr += (actual_h - 1) * fb->pitches[0];
+
        format = vop_convert_format(fb->format->format);
 
        spin_lock(&vop->reg_lock);
@@ -767,7 +812,13 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
        VOP_WIN_SET(vop, win, format, format);
        VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4));
        VOP_WIN_SET(vop, win, yrgb_mst, dma_addr);
-       if (fb->format->is_yuv) {
+       VOP_WIN_YUV2YUV_SET(vop, win_yuv2yuv, y2r_en, is_yuv);
+       VOP_WIN_SET(vop, win, y_mir_en,
+                   (state->rotation & DRM_MODE_REFLECT_Y) ? 1 : 0);
+       VOP_WIN_SET(vop, win, x_mir_en,
+                   (state->rotation & DRM_MODE_REFLECT_X) ? 1 : 0);
+
+       if (is_yuv) {
                int hsub = drm_format_horz_chroma_subsampling(fb->format->format);
                int vsub = drm_format_vert_chroma_subsampling(fb->format->format);
                int bpp = fb->format->cpp[1];
@@ -781,6 +832,13 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
                dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1];
                VOP_WIN_SET(vop, win, uv_vir, DIV_ROUND_UP(fb->pitches[1], 4));
                VOP_WIN_SET(vop, win, uv_mst, dma_addr);
+
+               for (i = 0; i < NUM_YUV2YUV_COEFFICIENTS; i++) {
+                       VOP_WIN_YUV2YUV_COEFFICIENT_SET(vop,
+                                                       win_yuv2yuv,
+                                                       y2r_coefficients[i],
+                                                       bt601_yuv2rgb[i]);
+               }
        }
 
        if (win->phy->scl)
@@ -819,10 +877,84 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
        spin_unlock(&vop->reg_lock);
 }
 
+static int vop_plane_atomic_async_check(struct drm_plane *plane,
+                                       struct drm_plane_state *state)
+{
+       struct vop_win *vop_win = to_vop_win(plane);
+       const struct vop_win_data *win = vop_win->data;
+       int min_scale = win->phy->scl ? FRAC_16_16(1, 8) :
+                                       DRM_PLANE_HELPER_NO_SCALING;
+       int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :
+                                       DRM_PLANE_HELPER_NO_SCALING;
+       struct drm_crtc_state *crtc_state;
+
+       if (plane != state->crtc->cursor)
+               return -EINVAL;
+
+       if (!plane->state)
+               return -EINVAL;
+
+       if (!plane->state->fb)
+               return -EINVAL;
+
+       if (state->state)
+               crtc_state = drm_atomic_get_existing_crtc_state(state->state,
+                                                               state->crtc);
+       else /* Special case for asynchronous cursor updates. */
+               crtc_state = plane->crtc->state;
+
+       return drm_atomic_helper_check_plane_state(plane->state, crtc_state,
+                                                  min_scale, max_scale,
+                                                  true, true);
+}
+
+static void vop_plane_atomic_async_update(struct drm_plane *plane,
+                                         struct drm_plane_state *new_state)
+{
+       struct vop *vop = to_vop(plane->state->crtc);
+       struct drm_plane_state *plane_state;
+
+       plane_state = plane->funcs->atomic_duplicate_state(plane);
+       plane_state->crtc_x = new_state->crtc_x;
+       plane_state->crtc_y = new_state->crtc_y;
+       plane_state->crtc_h = new_state->crtc_h;
+       plane_state->crtc_w = new_state->crtc_w;
+       plane_state->src_x = new_state->src_x;
+       plane_state->src_y = new_state->src_y;
+       plane_state->src_h = new_state->src_h;
+       plane_state->src_w = new_state->src_w;
+
+       if (plane_state->fb != new_state->fb)
+               drm_atomic_set_fb_for_plane(plane_state, new_state->fb);
+
+       swap(plane_state, plane->state);
+
+       if (plane->state->fb && plane->state->fb != new_state->fb) {
+               drm_framebuffer_get(plane->state->fb);
+               WARN_ON(drm_crtc_vblank_get(plane->state->crtc) != 0);
+               drm_flip_work_queue(&vop->fb_unref_work, plane->state->fb);
+               set_bit(VOP_PENDING_FB_UNREF, &vop->pending);
+       }
+
+       if (vop->is_enabled) {
+               rockchip_drm_psr_inhibit_get_state(new_state->state);
+               vop_plane_atomic_update(plane, plane->state);
+               spin_lock(&vop->reg_lock);
+               vop_cfg_done(vop);
+               spin_unlock(&vop->reg_lock);
+               rockchip_drm_psr_inhibit_put_state(new_state->state);
+       }
+
+       plane->funcs->atomic_destroy_state(plane, plane_state);
+}
+
 static const struct drm_plane_helper_funcs plane_helper_funcs = {
        .atomic_check = vop_plane_atomic_check,
        .atomic_update = vop_plane_atomic_update,
        .atomic_disable = vop_plane_atomic_disable,
+       .atomic_async_check = vop_plane_atomic_async_check,
+       .atomic_async_update = vop_plane_atomic_async_update,
+       .prepare_fb = drm_gem_fb_prepare_fb,
 };
 
 static const struct drm_plane_funcs vop_plane_funcs = {
@@ -1272,6 +1404,18 @@ out:
        return ret;
 }
 
+static void vop_plane_add_properties(struct drm_plane *plane,
+                                    const struct vop_win_data *win_data)
+{
+       unsigned int flags = 0;
+
+       flags |= VOP_WIN_HAS_REG(win_data, x_mir_en) ? DRM_MODE_REFLECT_X : 0;
+       flags |= VOP_WIN_HAS_REG(win_data, y_mir_en) ? DRM_MODE_REFLECT_Y : 0;
+       if (flags)
+               drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
+                                                  DRM_MODE_ROTATE_0 | flags);
+}
+
 static int vop_create_crtc(struct vop *vop)
 {
        const struct vop_data *vop_data = vop->data;
@@ -1309,6 +1453,7 @@ static int vop_create_crtc(struct vop *vop)
 
                plane = &vop_win->base;
                drm_plane_helper_add(plane, &plane_helper_funcs);
+               vop_plane_add_properties(plane, win_data);
                if (plane->type == DRM_PLANE_TYPE_PRIMARY)
                        primary = plane;
                else if (plane->type == DRM_PLANE_TYPE_CURSOR)
@@ -1346,6 +1491,7 @@ static int vop_create_crtc(struct vop *vop)
                        goto err_cleanup_crtc;
                }
                drm_plane_helper_add(&vop_win->base, &plane_helper_funcs);
+               vop_plane_add_properties(&vop_win->base, win_data);
        }
 
        port = of_get_child_by_name(dev->of_node, "port");
@@ -1529,6 +1675,7 @@ static void vop_win_init(struct vop *vop)
 
                vop_win->data = win_data;
                vop_win->vop = vop;
+               vop_win->yuv2yuv_data = &vop_data->win_yuv2yuv[i];
        }
 }
 
index 0fe40e1983d97bef4d12f9f8e305fdc38767066b..04ed401d2325e6288225aed9a6bbdba37f2c447d 100644 (file)
@@ -23,6 +23,8 @@
 #define VOP_MAJOR(version)             ((version) >> 8)
 #define VOP_MINOR(version)             ((version) & 0xff)
 
+#define NUM_YUV2YUV_COEFFICIENTS 12
+
 enum vop_data_format {
        VOP_FMT_ARGB8888 = 0,
        VOP_FMT_RGB888,
@@ -124,6 +126,10 @@ struct vop_scl_regs {
        struct vop_reg scale_cbcr_y;
 };
 
+struct vop_yuv2yuv_phy {
+       struct vop_reg y2r_coefficients[NUM_YUV2YUV_COEFFICIENTS];
+};
+
 struct vop_win_phy {
        const struct vop_scl_regs *scl;
        const uint32_t *data_formats;
@@ -140,12 +146,20 @@ struct vop_win_phy {
        struct vop_reg uv_mst;
        struct vop_reg yrgb_vir;
        struct vop_reg uv_vir;
+       struct vop_reg y_mir_en;
+       struct vop_reg x_mir_en;
 
        struct vop_reg dst_alpha_ctl;
        struct vop_reg src_alpha_ctl;
        struct vop_reg channel;
 };
 
+struct vop_win_yuv2yuv_data {
+       uint32_t base;
+       const struct vop_yuv2yuv_phy *phy;
+       struct vop_reg y2r_en;
+};
+
 struct vop_win_data {
        uint32_t base;
        const struct vop_win_phy *phy;
@@ -159,6 +173,7 @@ struct vop_data {
        const struct vop_misc *misc;
        const struct vop_modeset *modeset;
        const struct vop_output *output;
+       const struct vop_win_yuv2yuv_data *win_yuv2yuv;
        const struct vop_win_data *win;
        unsigned int win_size;
 
index 08fc40af52c89d36b4964fc0714990d2d82b4ea6..bd76328c0fdb5f378ac5b2e91f7f7867db24fdcc 100644 (file)
@@ -299,6 +299,114 @@ static const struct vop_data px30_vop_lit = {
        .win_size = ARRAY_SIZE(px30_vop_lit_win_data),
 };
 
+static const struct vop_scl_regs rk3066_win_scl = {
+       .scale_yrgb_x = VOP_REG(RK3066_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
+       .scale_yrgb_y = VOP_REG(RK3066_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
+       .scale_cbcr_x = VOP_REG(RK3066_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
+       .scale_cbcr_y = VOP_REG(RK3066_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
+};
+
+static const struct vop_win_phy rk3066_win0_data = {
+       .scl = &rk3066_win_scl,
+       .data_formats = formats_win_full,
+       .nformats = ARRAY_SIZE(formats_win_full),
+       .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 0),
+       .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 4),
+       .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 19),
+       .act_info = VOP_REG(RK3066_WIN0_ACT_INFO, 0x1fff1fff, 0),
+       .dsp_info = VOP_REG(RK3066_WIN0_DSP_INFO, 0x0fff0fff, 0),
+       .dsp_st = VOP_REG(RK3066_WIN0_DSP_ST, 0x1fff1fff, 0),
+       .yrgb_mst = VOP_REG(RK3066_WIN0_YRGB_MST0, 0xffffffff, 0),
+       .uv_mst = VOP_REG(RK3066_WIN0_CBR_MST0, 0xffffffff, 0),
+       .yrgb_vir = VOP_REG(RK3066_WIN0_VIR, 0xffff, 0),
+       .uv_vir = VOP_REG(RK3066_WIN0_VIR, 0x1fff, 16),
+};
+
+static const struct vop_win_phy rk3066_win1_data = {
+       .scl = &rk3066_win_scl,
+       .data_formats = formats_win_full,
+       .nformats = ARRAY_SIZE(formats_win_full),
+       .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 1),
+       .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 7),
+       .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 23),
+       .act_info = VOP_REG(RK3066_WIN1_ACT_INFO, 0x1fff1fff, 0),
+       .dsp_info = VOP_REG(RK3066_WIN1_DSP_INFO, 0x0fff0fff, 0),
+       .dsp_st = VOP_REG(RK3066_WIN1_DSP_ST, 0x1fff1fff, 0),
+       .yrgb_mst = VOP_REG(RK3066_WIN1_YRGB_MST, 0xffffffff, 0),
+       .uv_mst = VOP_REG(RK3066_WIN1_CBR_MST, 0xffffffff, 0),
+       .yrgb_vir = VOP_REG(RK3066_WIN1_VIR, 0xffff, 0),
+       .uv_vir = VOP_REG(RK3066_WIN1_VIR, 0x1fff, 16),
+};
+
+static const struct vop_win_phy rk3066_win2_data = {
+       .data_formats = formats_win_lite,
+       .nformats = ARRAY_SIZE(formats_win_lite),
+       .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 2),
+       .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 10),
+       .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 27),
+       .dsp_info = VOP_REG(RK3066_WIN2_DSP_INFO, 0x0fff0fff, 0),
+       .dsp_st = VOP_REG(RK3066_WIN2_DSP_ST, 0x1fff1fff, 0),
+       .yrgb_mst = VOP_REG(RK3066_WIN2_MST, 0xffffffff, 0),
+       .yrgb_vir = VOP_REG(RK3066_WIN2_VIR, 0xffff, 0),
+};
+
+static const struct vop_modeset rk3066_modeset = {
+       .htotal_pw = VOP_REG(RK3066_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
+       .hact_st_end = VOP_REG(RK3066_DSP_HACT_ST_END, 0x1fff1fff, 0),
+       .vtotal_pw = VOP_REG(RK3066_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
+       .vact_st_end = VOP_REG(RK3066_DSP_VACT_ST_END, 0x1fff1fff, 0),
+};
+
+static const struct vop_output rk3066_output = {
+       .pin_pol = VOP_REG(RK3066_DSP_CTRL0, 0x7, 4),
+};
+
+static const struct vop_common rk3066_common = {
+       .standby = VOP_REG(RK3066_SYS_CTRL0, 0x1, 1),
+       .out_mode = VOP_REG(RK3066_DSP_CTRL0, 0xf, 0),
+       .cfg_done = VOP_REG(RK3066_REG_CFG_DONE, 0x1, 0),
+       .dsp_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 24),
+};
+
+static const struct vop_win_data rk3066_vop_win_data[] = {
+       { .base = 0x00, .phy = &rk3066_win0_data,
+         .type = DRM_PLANE_TYPE_PRIMARY },
+       { .base = 0x00, .phy = &rk3066_win1_data,
+         .type = DRM_PLANE_TYPE_OVERLAY },
+       { .base = 0x00, .phy = &rk3066_win2_data,
+         .type = DRM_PLANE_TYPE_CURSOR },
+};
+
+static const int rk3066_vop_intrs[] = {
+       /*
+        * hs_start interrupt fires at frame-start, so serves
+        * the same purpose as dsp_hold in the driver.
+        */
+       DSP_HOLD_VALID_INTR,
+       FS_INTR,
+       LINE_FLAG_INTR,
+       BUS_ERROR_INTR,
+};
+
+static const struct vop_intr rk3066_intr = {
+       .intrs = rk3066_vop_intrs,
+       .nintrs = ARRAY_SIZE(rk3066_vop_intrs),
+       .line_flag_num[0] = VOP_REG(RK3066_INT_STATUS, 0xfff, 12),
+       .status = VOP_REG(RK3066_INT_STATUS, 0xf, 0),
+       .enable = VOP_REG(RK3066_INT_STATUS, 0xf, 4),
+       .clear = VOP_REG(RK3066_INT_STATUS, 0xf, 8),
+};
+
+static const struct vop_data rk3066_vop = {
+       .version = VOP_VERSION(2, 1),
+       .intr = &rk3066_intr,
+       .common = &rk3066_common,
+       .modeset = &rk3066_modeset,
+       .output = &rk3066_output,
+       .win = rk3066_vop_win_data,
+       .win_size = ARRAY_SIZE(rk3066_vop_win_data),
+};
+
 static const struct vop_scl_regs rk3188_win_scl = {
        .scale_yrgb_x = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
        .scale_yrgb_y = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
@@ -550,6 +658,27 @@ static const struct vop_intr rk3368_vop_intr = {
        .clear = VOP_REG_MASK_SYNC(RK3368_INTR_CLEAR, 0x3fff, 0),
 };
 
+static const struct vop_win_phy rk3368_win01_data = {
+       .scl = &rk3288_win_full_scl,
+       .data_formats = formats_win_full,
+       .nformats = ARRAY_SIZE(formats_win_full),
+       .enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0),
+       .format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1),
+       .rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12),
+       .x_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 21),
+       .y_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 22),
+       .act_info = VOP_REG(RK3368_WIN0_ACT_INFO, 0x1fff1fff, 0),
+       .dsp_info = VOP_REG(RK3368_WIN0_DSP_INFO, 0x0fff0fff, 0),
+       .dsp_st = VOP_REG(RK3368_WIN0_DSP_ST, 0x1fff1fff, 0),
+       .yrgb_mst = VOP_REG(RK3368_WIN0_YRGB_MST, 0xffffffff, 0),
+       .uv_mst = VOP_REG(RK3368_WIN0_CBR_MST, 0xffffffff, 0),
+       .yrgb_vir = VOP_REG(RK3368_WIN0_VIR, 0x3fff, 0),
+       .uv_vir = VOP_REG(RK3368_WIN0_VIR, 0x3fff, 16),
+       .src_alpha_ctl = VOP_REG(RK3368_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
+       .dst_alpha_ctl = VOP_REG(RK3368_WIN0_DST_ALPHA_CTRL, 0xff, 0),
+       .channel = VOP_REG(RK3368_WIN0_CTRL2, 0xff, 0),
+};
+
 static const struct vop_win_phy rk3368_win23_data = {
        .data_formats = formats_win_lite,
        .nformats = ARRAY_SIZE(formats_win_lite),
@@ -557,6 +686,7 @@ static const struct vop_win_phy rk3368_win23_data = {
        .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4),
        .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5),
        .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20),
+       .y_mir_en = VOP_REG(RK3368_WIN2_CTRL1, 0x1, 15),
        .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0),
        .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0),
        .yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0),
@@ -566,9 +696,9 @@ static const struct vop_win_phy rk3368_win23_data = {
 };
 
 static const struct vop_win_data rk3368_vop_win_data[] = {
-       { .base = 0x00, .phy = &rk3288_win01_data,
+       { .base = 0x00, .phy = &rk3368_win01_data,
          .type = DRM_PLANE_TYPE_PRIMARY },
-       { .base = 0x40, .phy = &rk3288_win01_data,
+       { .base = 0x40, .phy = &rk3368_win01_data,
          .type = DRM_PLANE_TYPE_OVERLAY },
        { .base = 0x00, .phy = &rk3368_win23_data,
          .type = DRM_PLANE_TYPE_OVERLAY },
@@ -637,6 +767,34 @@ static const struct vop_output rk3399_output = {
        .mipi_dual_channel_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 3),
 };
 
+static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win01_data = {
+       .y2r_coefficients = {
+               VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 0),
+               VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 16),
+               VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 4, 0xffff, 0),
+               VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 4, 0xffff, 16),
+               VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 8, 0xffff, 0),
+               VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 8, 0xffff, 16),
+               VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 12, 0xffff, 0),
+               VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 12, 0xffff, 16),
+               VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 16, 0xffff, 0),
+               VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 20, 0xffffffff, 0),
+               VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 24, 0xffffffff, 0),
+               VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 28, 0xffffffff, 0),
+       },
+};
+
+static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win23_data = { };
+
+static const struct vop_win_yuv2yuv_data rk3399_vop_big_win_yuv2yuv_data[] = {
+       { .base = 0x00, .phy = &rk3399_yuv2yuv_win01_data,
+         .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1) },
+       { .base = 0x60, .phy = &rk3399_yuv2yuv_win01_data,
+         .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 9) },
+       { .base = 0xC0, .phy = &rk3399_yuv2yuv_win23_data },
+       { .base = 0x120, .phy = &rk3399_yuv2yuv_win23_data },
+};
+
 static const struct vop_data rk3399_vop_big = {
        .version = VOP_VERSION(3, 5),
        .feature = VOP_FEATURE_OUTPUT_RGB10,
@@ -647,15 +805,22 @@ static const struct vop_data rk3399_vop_big = {
        .misc = &rk3368_misc,
        .win = rk3368_vop_win_data,
        .win_size = ARRAY_SIZE(rk3368_vop_win_data),
+       .win_yuv2yuv = rk3399_vop_big_win_yuv2yuv_data,
 };
 
 static const struct vop_win_data rk3399_vop_lit_win_data[] = {
-       { .base = 0x00, .phy = &rk3288_win01_data,
+       { .base = 0x00, .phy = &rk3368_win01_data,
          .type = DRM_PLANE_TYPE_PRIMARY },
        { .base = 0x00, .phy = &rk3368_win23_data,
          .type = DRM_PLANE_TYPE_CURSOR},
 };
 
+static const struct vop_win_yuv2yuv_data rk3399_vop_lit_win_yuv2yuv_data[] = {
+       { .base = 0x00, .phy = &rk3399_yuv2yuv_win01_data,
+         .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1)},
+       { .base = 0x60, .phy = &rk3399_yuv2yuv_win23_data },
+};
+
 static const struct vop_data rk3399_vop_lit = {
        .version = VOP_VERSION(3, 6),
        .intr = &rk3366_vop_intr,
@@ -665,6 +830,7 @@ static const struct vop_data rk3399_vop_lit = {
        .misc = &rk3368_misc,
        .win = rk3399_vop_lit_win_data,
        .win_size = ARRAY_SIZE(rk3399_vop_lit_win_data),
+       .win_yuv2yuv = rk3399_vop_lit_win_yuv2yuv_data,
 };
 
 static const struct vop_win_data rk3228_vop_win_data[] = {
@@ -730,11 +896,11 @@ static const struct vop_intr rk3328_vop_intr = {
 };
 
 static const struct vop_win_data rk3328_vop_win_data[] = {
-       { .base = 0xd0, .phy = &rk3288_win01_data,
+       { .base = 0xd0, .phy = &rk3368_win01_data,
          .type = DRM_PLANE_TYPE_PRIMARY },
-       { .base = 0x1d0, .phy = &rk3288_win01_data,
+       { .base = 0x1d0, .phy = &rk3368_win01_data,
          .type = DRM_PLANE_TYPE_OVERLAY },
-       { .base = 0x2d0, .phy = &rk3288_win01_data,
+       { .base = 0x2d0, .phy = &rk3368_win01_data,
          .type = DRM_PLANE_TYPE_CURSOR },
 };
 
@@ -759,6 +925,8 @@ static const struct of_device_id vop_driver_dt_match[] = {
          .data = &px30_vop_big },
        { .compatible = "rockchip,px30-vop-lit",
          .data = &px30_vop_lit },
+       { .compatible = "rockchip,rk3066-vop",
+         .data = &rk3066_vop },
        { .compatible = "rockchip,rk3188-vop",
          .data = &rk3188_vop },
        { .compatible = "rockchip,rk3288-vop",
index 7348c68352ed96d873230efb6129a0ed7f916243..d837d4a7df4a1106537d46bed7dff72610ba2ce3 100644 (file)
 #define RK3188_REG_CFG_DONE            0x90
 /* rk3188 register definition end */
 
+/* rk3066 register definition */
+#define RK3066_SYS_CTRL0               0x00
+#define RK3066_SYS_CTRL1               0x04
+#define RK3066_DSP_CTRL0               0x08
+#define RK3066_DSP_CTRL1               0x0c
+#define RK3066_INT_STATUS              0x10
+#define RK3066_MCU_CTRL                        0x14
+#define RK3066_BLEND_CTRL              0x18
+#define RK3066_WIN0_COLOR_KEY_CTRL     0x1c
+#define RK3066_WIN1_COLOR_KEY_CTRL     0x20
+#define RK3066_WIN2_COLOR_KEY_CTRL     0x24
+#define RK3066_WIN0_YRGB_MST0          0x28
+#define RK3066_WIN0_CBR_MST0           0x2c
+#define RK3066_WIN0_YRGB_MST1          0x30
+#define RK3066_WIN0_CBR_MST1           0x34
+#define RK3066_WIN0_VIR                        0x38
+#define RK3066_WIN0_ACT_INFO           0x3c
+#define RK3066_WIN0_DSP_INFO           0x40
+#define RK3066_WIN0_DSP_ST             0x44
+#define RK3066_WIN0_SCL_FACTOR_YRGB    0x48
+#define RK3066_WIN0_SCL_FACTOR_CBR     0x4c
+#define RK3066_WIN0_SCL_OFFSET         0x50
+#define RK3066_WIN1_YRGB_MST           0x54
+#define RK3066_WIN1_CBR_MST            0x58
+#define RK3066_WIN1_VIR                        0x5c
+#define RK3066_WIN1_ACT_INFO           0x60
+#define RK3066_WIN1_DSP_INFO           0x64
+#define RK3066_WIN1_DSP_ST             0x68
+#define RK3066_WIN1_SCL_FACTOR_YRGB    0x6c
+#define RK3066_WIN1_SCL_FACTOR_CBR     0x70
+#define RK3066_WIN1_SCL_OFFSET         0x74
+#define RK3066_WIN2_MST                        0x78
+#define RK3066_WIN2_VIR                        0x7c
+#define RK3066_WIN2_DSP_INFO           0x80
+#define RK3066_WIN2_DSP_ST             0x84
+#define RK3066_HWC_MST                 0x88
+#define RK3066_HWC_DSP_ST              0x8c
+#define RK3066_HWC_COLOR_LUT0          0x90
+#define RK3066_HWC_COLOR_LUT1          0x94
+#define RK3066_HWC_COLOR_LUT2          0x98
+#define RK3066_DSP_HTOTAL_HS_END       0x9c
+#define RK3066_DSP_HACT_ST_END         0xa0
+#define RK3066_DSP_VTOTAL_VS_END       0xa4
+#define RK3066_DSP_VACT_ST_END         0xa8
+#define RK3066_DSP_VS_ST_END_F1                0xac
+#define RK3066_DSP_VACT_ST_END_F1      0xb0
+#define RK3066_REG_CFG_DONE            0xc0
+#define RK3066_MCU_BYPASS_WPORT                0x100
+#define RK3066_MCU_BYPASS_RPORT                0x200
+#define RK3066_WIN2_LUT_ADDR           0x400
+#define RK3066_DSP_LUT_ADDR            0x800
+/* rk3066 register definition end */
+
 #endif /* _ROCKCHIP_VOP_REG_H */
index dbb69063b3d5e21ee7f3b696cd54d198e7ee92be..19fc601c9eeb52fc9704bbfc7c164dbfa71b7717 100644 (file)
@@ -60,8 +60,6 @@
 
 static void drm_sched_process_job(struct dma_fence *f, struct dma_fence_cb *cb);
 
-static void drm_sched_expel_job_unlocked(struct drm_sched_job *s_job);
-
 /**
  * drm_sched_rq_init - initialize a given run queue struct
  *
@@ -286,8 +284,6 @@ static void drm_sched_job_finish(struct work_struct *work)
        cancel_delayed_work_sync(&sched->work_tdr);
 
        spin_lock_irqsave(&sched->job_list_lock, flags);
-       /* remove job from ring_mirror_list */
-       list_del_init(&s_job->node);
        /* queue TDR for next job */
        drm_sched_start_timeout(sched);
        spin_unlock_irqrestore(&sched->job_list_lock, flags);
@@ -295,22 +291,11 @@ static void drm_sched_job_finish(struct work_struct *work)
        sched->ops->free_job(s_job);
 }
 
-static void drm_sched_job_finish_cb(struct dma_fence *f,
-                                   struct dma_fence_cb *cb)
-{
-       struct drm_sched_job *job = container_of(cb, struct drm_sched_job,
-                                                finish_cb);
-       schedule_work(&job->finish_work);
-}
-
 static void drm_sched_job_begin(struct drm_sched_job *s_job)
 {
        struct drm_gpu_scheduler *sched = s_job->sched;
        unsigned long flags;
 
-       dma_fence_add_callback(&s_job->s_fence->finished, &s_job->finish_cb,
-                              drm_sched_job_finish_cb);
-
        spin_lock_irqsave(&sched->job_list_lock, flags);
        list_add_tail(&s_job->node, &sched->ring_mirror_list);
        drm_sched_start_timeout(sched);
@@ -335,6 +320,51 @@ static void drm_sched_job_timedout(struct work_struct *work)
        spin_unlock_irqrestore(&sched->job_list_lock, flags);
 }
 
+ /**
+  * drm_sched_increase_karma - Update sched_entity guilty flag
+  *
+  * @bad: The job guilty of time out
+  *
+  * Increment on every hang caused by the 'bad' job. If this exceeds the hang
+  * limit of the scheduler then the respective sched entity is marked guilty and
+  * jobs from it will not be scheduled further
+  */
+void drm_sched_increase_karma(struct drm_sched_job *bad)
+{
+       int i;
+       struct drm_sched_entity *tmp;
+       struct drm_sched_entity *entity;
+       struct drm_gpu_scheduler *sched = bad->sched;
+
+       /* don't increase @bad's karma if it's from KERNEL RQ,
+        * because sometimes GPU hang would cause kernel jobs (like VM updating jobs)
+        * corrupt but keep in mind that kernel jobs always considered good.
+        */
+       if (bad->s_priority != DRM_SCHED_PRIORITY_KERNEL) {
+               atomic_inc(&bad->karma);
+               for (i = DRM_SCHED_PRIORITY_MIN; i < DRM_SCHED_PRIORITY_KERNEL;
+                    i++) {
+                       struct drm_sched_rq *rq = &sched->sched_rq[i];
+
+                       spin_lock(&rq->lock);
+                       list_for_each_entry_safe(entity, tmp, &rq->entities, list) {
+                               if (bad->s_fence->scheduled.context ==
+                                   entity->fence_context) {
+                                       if (atomic_read(&bad->karma) >
+                                           bad->sched->hang_limit)
+                                               if (entity->guilty)
+                                                       atomic_set(entity->guilty, 1);
+                                       break;
+                               }
+                       }
+                       spin_unlock(&rq->lock);
+                       if (&entity->list != &rq->entities)
+                               break;
+               }
+       }
+}
+EXPORT_SYMBOL(drm_sched_increase_karma);
+
 /**
  * drm_sched_hw_job_reset - stop the scheduler if it contains the bad job
  *
@@ -342,50 +372,42 @@ static void drm_sched_job_timedout(struct work_struct *work)
  * @bad: bad scheduler job
  *
  */
-void drm_sched_hw_job_reset(struct drm_gpu_scheduler *sched, struct drm_sched_job *bad)
+void drm_sched_stop(struct drm_gpu_scheduler *sched)
 {
        struct drm_sched_job *s_job;
-       struct drm_sched_entity *entity, *tmp;
        unsigned long flags;
-       int i;
+       struct dma_fence *last_fence =  NULL;
 
+       kthread_park(sched->thread);
+
+       /*
+        * Verify all the signaled jobs in mirror list are removed from the ring
+        * by waiting for the latest job to enter the list. This should insure that
+        * also all the previous jobs that were in flight also already singaled
+        * and removed from the list.
+        */
        spin_lock_irqsave(&sched->job_list_lock, flags);
        list_for_each_entry_reverse(s_job, &sched->ring_mirror_list, node) {
                if (s_job->s_fence->parent &&
                    dma_fence_remove_callback(s_job->s_fence->parent,
-                                             &s_job->s_fence->cb)) {
+                                             &s_job->cb)) {
                        dma_fence_put(s_job->s_fence->parent);
                        s_job->s_fence->parent = NULL;
                        atomic_dec(&sched->hw_rq_count);
+               } else {
+                        last_fence = dma_fence_get(&s_job->s_fence->finished);
+                        break;
                }
        }
        spin_unlock_irqrestore(&sched->job_list_lock, flags);
 
-       if (bad && bad->s_priority != DRM_SCHED_PRIORITY_KERNEL) {
-               atomic_inc(&bad->karma);
-               /* don't increase @bad's karma if it's from KERNEL RQ,
-                * becuase sometimes GPU hang would cause kernel jobs (like VM updating jobs)
-                * corrupt but keep in mind that kernel jobs always considered good.
-                */
-               for (i = DRM_SCHED_PRIORITY_MIN; i < DRM_SCHED_PRIORITY_KERNEL; i++ ) {
-                       struct drm_sched_rq *rq = &sched->sched_rq[i];
-
-                       spin_lock(&rq->lock);
-                       list_for_each_entry_safe(entity, tmp, &rq->entities, list) {
-                               if (bad->s_fence->scheduled.context == entity->fence_context) {
-                                   if (atomic_read(&bad->karma) > bad->sched->hang_limit)
-                                               if (entity->guilty)
-                                                       atomic_set(entity->guilty, 1);
-                                       break;
-                               }
-                       }
-                       spin_unlock(&rq->lock);
-                       if (&entity->list != &rq->entities)
-                               break;
-               }
+       if (last_fence) {
+               dma_fence_wait(last_fence, false);
+               dma_fence_put(last_fence);
        }
 }
-EXPORT_SYMBOL(drm_sched_hw_job_reset);
+
+EXPORT_SYMBOL(drm_sched_stop);
 
 /**
  * drm_sched_job_recovery - recover jobs after a reset
@@ -393,18 +415,58 @@ EXPORT_SYMBOL(drm_sched_hw_job_reset);
  * @sched: scheduler instance
  *
  */
-void drm_sched_job_recovery(struct drm_gpu_scheduler *sched)
+void drm_sched_start(struct drm_gpu_scheduler *sched, bool full_recovery)
 {
        struct drm_sched_job *s_job, *tmp;
-       bool found_guilty = false;
-       unsigned long flags;
        int r;
 
-       spin_lock_irqsave(&sched->job_list_lock, flags);
+       if (!full_recovery)
+               goto unpark;
+
+       /*
+        * Locking the list is not required here as the sched thread is parked
+        * so no new jobs are being pushed in to HW and in drm_sched_stop we
+        * flushed all the jobs who were still in mirror list but who already
+        * signaled and removed them self from the list. Also concurrent
+        * GPU recovers can't run in parallel.
+        */
+       list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) {
+               struct dma_fence *fence = s_job->s_fence->parent;
+
+               if (fence) {
+                       r = dma_fence_add_callback(fence, &s_job->cb,
+                                                  drm_sched_process_job);
+                       if (r == -ENOENT)
+                               drm_sched_process_job(fence, &s_job->cb);
+                       else if (r)
+                               DRM_ERROR("fence add callback failed (%d)\n",
+                                         r);
+               } else
+                       drm_sched_process_job(NULL, &s_job->cb);
+       }
+
+       drm_sched_start_timeout(sched);
+
+unpark:
+       kthread_unpark(sched->thread);
+}
+EXPORT_SYMBOL(drm_sched_start);
+
+/**
+ * drm_sched_resubmit_jobs - helper to relunch job from mirror ring list
+ *
+ * @sched: scheduler instance
+ *
+ */
+void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched)
+{
+       struct drm_sched_job *s_job, *tmp;
+       uint64_t guilty_context;
+       bool found_guilty = false;
+
+       /*TODO DO we need spinlock here ? */
        list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) {
                struct drm_sched_fence *s_fence = s_job->s_fence;
-               struct dma_fence *fence;
-               uint64_t guilty_context;
 
                if (!found_guilty && atomic_read(&s_job->karma) > sched->hang_limit) {
                        found_guilty = true;
@@ -414,31 +476,11 @@ void drm_sched_job_recovery(struct drm_gpu_scheduler *sched)
                if (found_guilty && s_job->s_fence->scheduled.context == guilty_context)
                        dma_fence_set_error(&s_fence->finished, -ECANCELED);
 
-               spin_unlock_irqrestore(&sched->job_list_lock, flags);
-               fence = sched->ops->run_job(s_job);
+               s_job->s_fence->parent = sched->ops->run_job(s_job);
                atomic_inc(&sched->hw_rq_count);
-
-               if (fence) {
-                       s_fence->parent = dma_fence_get(fence);
-                       r = dma_fence_add_callback(fence, &s_fence->cb,
-                                                  drm_sched_process_job);
-                       if (r == -ENOENT)
-                               drm_sched_process_job(fence, &s_fence->cb);
-                       else if (r)
-                               DRM_ERROR("fence add callback failed (%d)\n",
-                                         r);
-                       dma_fence_put(fence);
-               } else {
-                       if (s_fence->finished.error < 0)
-                               drm_sched_expel_job_unlocked(s_job);
-                       drm_sched_process_job(NULL, &s_fence->cb);
-               }
-               spin_lock_irqsave(&sched->job_list_lock, flags);
        }
-       drm_sched_start_timeout(sched);
-       spin_unlock_irqrestore(&sched->job_list_lock, flags);
 }
-EXPORT_SYMBOL(drm_sched_job_recovery);
+EXPORT_SYMBOL(drm_sched_resubmit_jobs);
 
 /**
  * drm_sched_job_init - init a scheduler job
@@ -552,18 +594,27 @@ drm_sched_select_entity(struct drm_gpu_scheduler *sched)
  */
 static void drm_sched_process_job(struct dma_fence *f, struct dma_fence_cb *cb)
 {
-       struct drm_sched_fence *s_fence =
-               container_of(cb, struct drm_sched_fence, cb);
+       struct drm_sched_job *s_job = container_of(cb, struct drm_sched_job, cb);
+       struct drm_sched_fence *s_fence = s_job->s_fence;
        struct drm_gpu_scheduler *sched = s_fence->sched;
+       unsigned long flags;
+
+       cancel_delayed_work(&sched->work_tdr);
 
-       dma_fence_get(&s_fence->finished);
        atomic_dec(&sched->hw_rq_count);
        atomic_dec(&sched->num_jobs);
+
+       spin_lock_irqsave(&sched->job_list_lock, flags);
+       /* remove job from ring_mirror_list */
+       list_del_init(&s_job->node);
+       spin_unlock_irqrestore(&sched->job_list_lock, flags);
+
        drm_sched_fence_finished(s_fence);
 
        trace_drm_sched_process_job(s_fence);
-       dma_fence_put(&s_fence->finished);
        wake_up_interruptible(&sched->wake_up_worker);
+
+       schedule_work(&s_job->finish_work);
 }
 
 /**
@@ -626,34 +677,22 @@ static int drm_sched_main(void *param)
 
                if (fence) {
                        s_fence->parent = dma_fence_get(fence);
-                       r = dma_fence_add_callback(fence, &s_fence->cb,
+                       r = dma_fence_add_callback(fence, &sched_job->cb,
                                                   drm_sched_process_job);
                        if (r == -ENOENT)
-                               drm_sched_process_job(fence, &s_fence->cb);
+                               drm_sched_process_job(fence, &sched_job->cb);
                        else if (r)
                                DRM_ERROR("fence add callback failed (%d)\n",
                                          r);
                        dma_fence_put(fence);
-               } else {
-                       if (s_fence->finished.error < 0)
-                               drm_sched_expel_job_unlocked(sched_job);
-                       drm_sched_process_job(NULL, &s_fence->cb);
-               }
+               } else
+                       drm_sched_process_job(NULL, &sched_job->cb);
 
                wake_up(&sched->job_scheduled);
        }
        return 0;
 }
 
-static void drm_sched_expel_job_unlocked(struct drm_sched_job *s_job)
-{
-       struct drm_gpu_scheduler *sched = s_job->sched;
-
-       spin_lock(&sched->job_list_lock);
-       list_del_init(&s_job->node);
-       spin_unlock(&sched->job_list_lock);
-}
-
 /**
  * drm_sched_init - Init a gpu scheduler instance
  *
index 8554102a6ead189e3b29f380c89867f942b2b73e..f2cfd1698b7809f225b747dabd1ed7d8dbb4bf42 100644 (file)
@@ -229,8 +229,8 @@ static int shmob_drm_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        sdev->mmio = devm_ioremap_resource(&pdev->dev, res);
-       if (sdev->mmio == NULL)
-               return -ENOMEM;
+       if (IS_ERR(sdev->mmio))
+               return PTR_ERR(sdev->mmio);
 
        ret = shmob_drm_setup_clocks(sdev, pdata->clk_source);
        if (ret < 0)
index ed76e52eb21333dd3d042bafe938f062c1069e4f..ec9f87483e395583f5e163ab5a0304ecc407d447 100644 (file)
@@ -53,18 +53,10 @@ sti_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode)
        struct clk *compo_clk, *pix_clk;
        int rate = mode->clock * 1000;
 
-       DRM_DEBUG_KMS("CRTC:%d (%s) mode:%d (%s)\n",
-                     crtc->base.id, sti_mixer_to_str(mixer),
-                     mode->base.id, mode->name);
-
-       DRM_DEBUG_KMS("%d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
-                     mode->vrefresh, mode->clock,
-                     mode->hdisplay,
-                     mode->hsync_start, mode->hsync_end,
-                     mode->htotal,
-                     mode->vdisplay,
-                     mode->vsync_start, mode->vsync_end,
-                     mode->vtotal, mode->type, mode->flags);
+       DRM_DEBUG_KMS("CRTC:%d (%s) mode: (%s)\n",
+                     crtc->base.id, sti_mixer_to_str(mixer), mode->name);
+
+       DRM_DEBUG_KMS(DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
 
        if (mixer->id == STI_MIXER_MAIN) {
                compo_clk = compo->clk_compo_main;
index b08376b7611b896fbcb8fd6b3e91fe44dd4b7015..6d33772f77eb11c7d3bd66ec31949daa31dc9892 100644 (file)
@@ -277,8 +277,8 @@ static void sti_dvo_pre_enable(struct drm_bridge *bridge)
 }
 
 static void sti_dvo_set_mode(struct drm_bridge *bridge,
-                            struct drm_display_mode *mode,
-                            struct drm_display_mode *adjusted_mode)
+                            const struct drm_display_mode *mode,
+                            const struct drm_display_mode *adjusted_mode)
 {
        struct sti_dvo *dvo = bridge->driver_private;
        struct sti_mixer *mixer = to_sti_mixer(dvo->encoder->crtc);
index 19b9b5ed129700730e5c77ea5c37e9edbb0db5e0..a63dd5eb70819361746dd937126801ae155dea6d 100644 (file)
@@ -508,8 +508,8 @@ static void sti_hda_pre_enable(struct drm_bridge *bridge)
 }
 
 static void sti_hda_set_mode(struct drm_bridge *bridge,
-               struct drm_display_mode *mode,
-               struct drm_display_mode *adjusted_mode)
+                            const struct drm_display_mode *mode,
+                            const struct drm_display_mode *adjusted_mode)
 {
        struct sti_hda *hda = bridge->driver_private;
        u32 mode_idx;
index ccf718404a1c23e557dd6ff097d779f3bff9729c..458fcb5a93f2233742abc5909c743be614ec8449 100644 (file)
@@ -434,7 +434,8 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
 
        DRM_DEBUG_DRIVER("\n");
 
-       ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode, false);
+       ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe,
+                                                      hdmi->drm_connector, mode);
        if (ret < 0) {
                DRM_ERROR("failed to setup AVI infoframe: %d\n", ret);
                return ret;
@@ -917,8 +918,8 @@ static void sti_hdmi_pre_enable(struct drm_bridge *bridge)
 }
 
 static void sti_hdmi_set_mode(struct drm_bridge *bridge,
-               struct drm_display_mode *mode,
-               struct drm_display_mode *adjusted_mode)
+                             const struct drm_display_mode *mode,
+                             const struct drm_display_mode *adjusted_mode)
 {
        struct sti_hdmi *hdmi = bridge->driver_private;
        int ret;
index a514b593f37c531b2a1f7fa3b04d625f64edd8a3..a672b59a22262c949c8519840e9f29c1225d5f83 100644 (file)
@@ -215,7 +215,7 @@ static int dw_mipi_dsi_phy_init(void *priv_data)
 }
 
 static int
-dw_mipi_dsi_get_lane_mbps(void *priv_data, struct drm_display_mode *mode,
+dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
                          unsigned long mode_flags, u32 lanes, u32 format,
                          unsigned int *lane_mbps)
 {
index 61dd661aa0acbde3abfe9481c9a32f4d20c79240..a91e04139595ab38e66ae094ae6cb6d620183d47 100644 (file)
@@ -691,7 +691,7 @@ static int ltdc_plane_atomic_check(struct drm_plane *plane,
                                   struct drm_plane_state *state)
 {
        struct drm_framebuffer *fb = state->fb;
-       u32 src_x, src_y, src_w, src_h;
+       u32 src_w, src_h;
 
        DRM_DEBUG_DRIVER("\n");
 
@@ -699,8 +699,6 @@ static int ltdc_plane_atomic_check(struct drm_plane *plane,
                return 0;
 
        /* convert src_ from 16:16 format */
-       src_x = state->src_x >> 16;
-       src_y = state->src_y >> 16;
        src_w = state->src_w >> 16;
        src_h = state->src_h >> 16;
 
index 9e9255ee59cd83138f5572f0d31df50aec9cc244..892197f525577a1b02bc8072c67b63624335a61a 100644 (file)
@@ -45,28 +45,6 @@ static const u32 sunxi_rgb2yuv_coef[12] = {
        0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808
 };
 
-/*
- * These coefficients are taken from the A33 BSP from Allwinner.
- *
- * The first three values of each row are coded as 13-bit signed fixed-point
- * numbers, with 10 bits for the fractional part. The fourth value is a
- * constant coded as a 14-bit signed fixed-point number with 4 bits for the
- * fractional part.
- *
- * The values in table order give the following colorspace translation:
- * G = 1.164 * Y - 0.391 * U - 0.813 * V + 135
- * R = 1.164 * Y + 1.596 * V - 222
- * B = 1.164 * Y + 2.018 * U + 276
- *
- * This seems to be a conversion from Y[16:235] UV[16:240] to RGB[0:255],
- * following the BT601 spec.
- */
-static const u32 sunxi_bt601_yuv2rgb_coef[12] = {
-       0x000004a7, 0x00001e6f, 0x00001cbf, 0x00000877,
-       0x000004a7, 0x00000000, 0x00000662, 0x00003211,
-       0x000004a7, 0x00000812, 0x00000000, 0x00002eb1,
-};
-
 static void sun4i_backend_apply_color_correction(struct sunxi_engine *engine)
 {
        int i;
@@ -245,7 +223,8 @@ static int sun4i_backend_update_yuv_format(struct sun4i_backend *backend,
                           SUN4I_BACKEND_ATTCTL_REG0_LAY_YUVEN);
 
        /* TODO: Add support for the multi-planar YUV formats */
-       if (format->num_planes == 1)
+       if (drm_format_info_is_yuv_packed(format) &&
+           drm_format_info_is_yuv_sampling_422(format))
                val |= SUN4I_BACKEND_IYUVCTL_FBFMT_PACKED_YUV422;
        else
                DRM_DEBUG_DRIVER("Unsupported YUV format (0x%x)\n", fmt);
index 9e4c375ccc96fac1edfed181f9ffe2de540ce2be..93da837194cfc3e96572441e42e5672a31f686b7 100644 (file)
@@ -97,6 +97,7 @@ static int sun4i_drv_bind(struct device *dev)
        }
 
        drm_mode_config_init(drm);
+       drm->mode_config.allow_fb_modifiers = true;
 
        ret = component_bind_all(drm->dev, drm);
        if (ret) {
index 1a7ebc45747ec9d9c498adb6a793625661eff945..e8239d4d4dd5d28ac83c90acb4cf57720c6c3057 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
@@ -48,10 +49,38 @@ static const u32 sun4i_frontend_horz_coef[64] = {
        0x03ff0000, 0x0000fd41, 0x01ff0000, 0x0000fe42,
 };
 
+/*
+ * These coefficients are taken from the A33 BSP from Allwinner.
+ *
+ * The first three values of each row are coded as 13-bit signed fixed-point
+ * numbers, with 10 bits for the fractional part. The fourth value is a
+ * constant coded as a 14-bit signed fixed-point number with 4 bits for the
+ * fractional part.
+ *
+ * The values in table order give the following colorspace translation:
+ * G = 1.164 * Y - 0.391 * U - 0.813 * V + 135
+ * R = 1.164 * Y + 1.596 * V - 222
+ * B = 1.164 * Y + 2.018 * U + 276
+ *
+ * This seems to be a conversion from Y[16:235] UV[16:240] to RGB[0:255],
+ * following the BT601 spec.
+ */
+const u32 sunxi_bt601_yuv2rgb_coef[12] = {
+       0x000004a7, 0x00001e6f, 0x00001cbf, 0x00000877,
+       0x000004a7, 0x00000000, 0x00000662, 0x00003211,
+       0x000004a7, 0x00000812, 0x00000000, 0x00002eb1,
+};
+EXPORT_SYMBOL(sunxi_bt601_yuv2rgb_coef);
+
 static void sun4i_frontend_scaler_init(struct sun4i_frontend *frontend)
 {
        int i;
 
+       if (frontend->data->has_coef_access_ctrl)
+               regmap_write_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG,
+                                 SUN4I_FRONTEND_FRM_CTRL_COEF_ACCESS_CTRL,
+                                 SUN4I_FRONTEND_FRM_CTRL_COEF_ACCESS_CTRL);
+
        for (i = 0; i < 32; i++) {
                regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZCOEF0_REG(i),
                             sun4i_frontend_horz_coef[2 * i]);
@@ -67,9 +96,11 @@ static void sun4i_frontend_scaler_init(struct sun4i_frontend *frontend)
                             sun4i_frontend_vert_coef[i]);
        }
 
-       regmap_update_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG,
-                          SUN4I_FRONTEND_FRM_CTRL_COEF_ACCESS_CTRL,
-                          SUN4I_FRONTEND_FRM_CTRL_COEF_ACCESS_CTRL);
+       if (frontend->data->has_coef_rdy)
+               regmap_write_bits(frontend->regs,
+                                 SUN4I_FRONTEND_FRM_CTRL_REG,
+                                 SUN4I_FRONTEND_FRM_CTRL_COEF_RDY,
+                                 SUN4I_FRONTEND_FRM_CTRL_COEF_RDY);
 }
 
 int sun4i_frontend_init(struct sun4i_frontend *frontend)
@@ -84,59 +115,228 @@ void sun4i_frontend_exit(struct sun4i_frontend *frontend)
 }
 EXPORT_SYMBOL(sun4i_frontend_exit);
 
+static bool sun4i_frontend_format_chroma_requires_swap(uint32_t fmt)
+{
+       switch (fmt) {
+       case DRM_FORMAT_YVU411:
+       case DRM_FORMAT_YVU420:
+       case DRM_FORMAT_YVU422:
+       case DRM_FORMAT_YVU444:
+               return true;
+
+       default:
+               return false;
+       }
+}
+
+static bool sun4i_frontend_format_supports_tiling(uint32_t fmt)
+{
+       switch (fmt) {
+       case DRM_FORMAT_NV12:
+       case DRM_FORMAT_NV16:
+       case DRM_FORMAT_NV21:
+       case DRM_FORMAT_NV61:
+       case DRM_FORMAT_YUV411:
+       case DRM_FORMAT_YUV420:
+       case DRM_FORMAT_YUV422:
+       case DRM_FORMAT_YVU420:
+       case DRM_FORMAT_YVU422:
+       case DRM_FORMAT_YVU411:
+               return true;
+
+       default:
+               return false;
+       }
+}
+
 void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend,
                                  struct drm_plane *plane)
 {
        struct drm_plane_state *state = plane->state;
        struct drm_framebuffer *fb = state->fb;
+       unsigned int strides[3] = {};
+
        dma_addr_t paddr;
+       bool swap;
+
+       if (fb->modifier == DRM_FORMAT_MOD_ALLWINNER_TILED) {
+               unsigned int width = state->src_w >> 16;
+               unsigned int offset;
+
+               strides[0] = SUN4I_FRONTEND_LINESTRD_TILED(fb->pitches[0]);
+
+               /*
+                * The X1 offset is the offset to the bottom-right point in the
+                * end tile, which is the final pixel (at offset width - 1)
+                * within the end tile (with a 32-byte mask).
+                */
+               offset = (width - 1) & (32 - 1);
+
+               regmap_write(frontend->regs, SUN4I_FRONTEND_TB_OFF0_REG,
+                            SUN4I_FRONTEND_TB_OFF_X1(offset));
+
+               if (fb->format->num_planes > 1) {
+                       strides[1] =
+                               SUN4I_FRONTEND_LINESTRD_TILED(fb->pitches[1]);
+
+                       regmap_write(frontend->regs, SUN4I_FRONTEND_TB_OFF1_REG,
+                                    SUN4I_FRONTEND_TB_OFF_X1(offset));
+               }
+
+               if (fb->format->num_planes > 2) {
+                       strides[2] =
+                               SUN4I_FRONTEND_LINESTRD_TILED(fb->pitches[2]);
+
+                       regmap_write(frontend->regs, SUN4I_FRONTEND_TB_OFF2_REG,
+                                    SUN4I_FRONTEND_TB_OFF_X1(offset));
+               }
+       } else {
+               strides[0] = fb->pitches[0];
+
+               if (fb->format->num_planes > 1)
+                       strides[1] = fb->pitches[1];
+
+               if (fb->format->num_planes > 2)
+                       strides[2] = fb->pitches[2];
+       }
 
        /* Set the line width */
        DRM_DEBUG_DRIVER("Frontend stride: %d bytes\n", fb->pitches[0]);
        regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD0_REG,
-                    fb->pitches[0]);
+                    strides[0]);
+
+       if (fb->format->num_planes > 1)
+               regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD1_REG,
+                            strides[1]);
+
+       if (fb->format->num_planes > 2)
+               regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD2_REG,
+                            strides[2]);
+
+       /* Some planar formats require chroma channel swapping by hand. */
+       swap = sun4i_frontend_format_chroma_requires_swap(fb->format->format);
 
        /* Set the physical address of the buffer in memory */
        paddr = drm_fb_cma_get_gem_addr(fb, state, 0);
        paddr -= PHYS_OFFSET;
-       DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
+       DRM_DEBUG_DRIVER("Setting buffer #0 address to %pad\n", &paddr);
        regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, paddr);
+
+       if (fb->format->num_planes > 1) {
+               paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 2 : 1);
+               paddr -= PHYS_OFFSET;
+               DRM_DEBUG_DRIVER("Setting buffer #1 address to %pad\n", &paddr);
+               regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR1_REG,
+                            paddr);
+       }
+
+       if (fb->format->num_planes > 2) {
+               paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 1 : 2);
+               paddr -= PHYS_OFFSET;
+               DRM_DEBUG_DRIVER("Setting buffer #2 address to %pad\n", &paddr);
+               regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR2_REG,
+                            paddr);
+       }
 }
 EXPORT_SYMBOL(sun4i_frontend_update_buffer);
 
-static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val)
+static int
+sun4i_frontend_drm_format_to_input_fmt(const struct drm_format_info *format,
+                                      u32 *val)
 {
-       switch (fmt) {
-       case DRM_FORMAT_XRGB8888:
+       if (!format->is_yuv)
                *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB;
-               return 0;
-
-       default:
+       else if (drm_format_info_is_yuv_sampling_411(format))
+               *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV411;
+       else if (drm_format_info_is_yuv_sampling_420(format))
+               *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV420;
+       else if (drm_format_info_is_yuv_sampling_422(format))
+               *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV422;
+       else if (drm_format_info_is_yuv_sampling_444(format))
+               *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV444;
+       else
                return -EINVAL;
-       }
+
+       return 0;
 }
 
-static int sun4i_frontend_drm_format_to_input_mode(uint32_t fmt, u32 *val)
+static int
+sun4i_frontend_drm_format_to_input_mode(const struct drm_format_info *format,
+                                       uint64_t modifier, u32 *val)
 {
-       if (drm_format_num_planes(fmt) == 1)
+       bool tiled = (modifier == DRM_FORMAT_MOD_ALLWINNER_TILED);
+
+       switch (format->num_planes) {
+       case 1:
                *val = SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED;
-       else
-               return -EINVAL;
+               return 0;
 
-       return 0;
+       case 2:
+               *val = tiled ? SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_MB32_SEMIPLANAR
+                            : SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_SEMIPLANAR;
+               return 0;
+
+       case 3:
+               *val = tiled ? SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_MB32_PLANAR
+                            : SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PLANAR;
+               return 0;
+
+       default:
+               return -EINVAL;
+       }
 }
 
-static int sun4i_frontend_drm_format_to_input_sequence(uint32_t fmt, u32 *val)
+static int
+sun4i_frontend_drm_format_to_input_sequence(const struct drm_format_info *format,
+                                           u32 *val)
 {
-       switch (fmt) {
+       /* Planar formats have an explicit input sequence. */
+       if (drm_format_info_is_yuv_planar(format)) {
+               *val = 0;
+               return 0;
+       }
+
+       switch (format->format) {
        case DRM_FORMAT_BGRX8888:
                *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX;
                return 0;
 
+       case DRM_FORMAT_NV12:
+               *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_UV;
+               return 0;
+
+       case DRM_FORMAT_NV16:
+               *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_UV;
+               return 0;
+
+       case DRM_FORMAT_NV21:
+               *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_VU;
+               return 0;
+
+       case DRM_FORMAT_NV61:
+               *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_VU;
+               return 0;
+
+       case DRM_FORMAT_UYVY:
+               *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_UYVY;
+               return 0;
+
+       case DRM_FORMAT_VYUY:
+               *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_VYUY;
+               return 0;
+
        case DRM_FORMAT_XRGB8888:
                *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB;
                return 0;
 
+       case DRM_FORMAT_YUYV:
+               *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_YUYV;
+               return 0;
+
+       case DRM_FORMAT_YVYU:
+               *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_YVYU;
+               return 0;
+
        default:
                return -EINVAL;
        }
@@ -160,14 +360,32 @@ static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val)
 
 static const uint32_t sun4i_frontend_formats[] = {
        DRM_FORMAT_BGRX8888,
+       DRM_FORMAT_NV12,
+       DRM_FORMAT_NV16,
+       DRM_FORMAT_NV21,
+       DRM_FORMAT_NV61,
+       DRM_FORMAT_UYVY,
+       DRM_FORMAT_VYUY,
        DRM_FORMAT_XRGB8888,
+       DRM_FORMAT_YUV411,
+       DRM_FORMAT_YUV420,
+       DRM_FORMAT_YUV422,
+       DRM_FORMAT_YUV444,
+       DRM_FORMAT_YUYV,
+       DRM_FORMAT_YVU411,
+       DRM_FORMAT_YVU420,
+       DRM_FORMAT_YVU422,
+       DRM_FORMAT_YVU444,
+       DRM_FORMAT_YVYU,
 };
 
 bool sun4i_frontend_format_is_supported(uint32_t fmt, uint64_t modifier)
 {
        unsigned int i;
 
-       if (modifier != DRM_FORMAT_MOD_LINEAR)
+       if (modifier == DRM_FORMAT_MOD_ALLWINNER_TILED)
+               return sun4i_frontend_format_supports_tiling(fmt);
+       else if (modifier != DRM_FORMAT_MOD_LINEAR)
                return false;
 
        for (i = 0; i < ARRAY_SIZE(sun4i_frontend_formats); i++)
@@ -183,9 +401,12 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
 {
        struct drm_plane_state *state = plane->state;
        struct drm_framebuffer *fb = state->fb;
-       uint32_t format = fb->format->format;
+       const struct drm_format_info *format = fb->format;
+       uint64_t modifier = fb->modifier;
        u32 out_fmt_val;
        u32 in_fmt_val, in_mod_val, in_ps_val;
+       unsigned int i;
+       u32 bypass;
        int ret;
 
        ret = sun4i_frontend_drm_format_to_input_fmt(format, &in_fmt_val);
@@ -194,7 +415,8 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
                return ret;
        }
 
-       ret = sun4i_frontend_drm_format_to_input_mode(format, &in_mod_val);
+       ret = sun4i_frontend_drm_format_to_input_mode(format, modifier,
+                                                     &in_mod_val);
        if (ret) {
                DRM_DEBUG_DRIVER("Invalid input mode\n");
                return ret;
@@ -216,16 +438,39 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
         * I have no idea what this does exactly, but it seems to be
         * related to the scaler FIR filter phase parameters.
         */
-       regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZPHASE_REG, 0x400);
-       regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZPHASE_REG, 0x400);
-       regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE0_REG, 0x400);
-       regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE0_REG, 0x400);
-       regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG, 0x400);
-       regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG, 0x400);
+       regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZPHASE_REG,
+                    frontend->data->ch_phase[0].horzphase);
+       regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZPHASE_REG,
+                    frontend->data->ch_phase[1].horzphase);
+       regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE0_REG,
+                    frontend->data->ch_phase[0].vertphase[0]);
+       regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE0_REG,
+                    frontend->data->ch_phase[1].vertphase[0]);
+       regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG,
+                    frontend->data->ch_phase[0].vertphase[1]);
+       regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG,
+                    frontend->data->ch_phase[1].vertphase[1]);
+
+       /*
+        * Checking the input format is sufficient since we currently only
+        * support RGB output formats to the backend. If YUV output formats
+        * ever get supported, an YUV input and output would require bypassing
+        * the CSC engine too.
+        */
+       if (format->is_yuv) {
+               /* Setup the CSC engine for YUV to RGB conversion. */
+               bypass = 0;
+
+               for (i = 0; i < ARRAY_SIZE(sunxi_bt601_yuv2rgb_coef); i++)
+                       regmap_write(frontend->regs,
+                                    SUN4I_FRONTEND_CSC_COEF_REG(i),
+                                    sunxi_bt601_yuv2rgb_coef[i]);
+       } else {
+               bypass = SUN4I_FRONTEND_BYPASS_CSC_EN;
+       }
 
        regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG,
-                          SUN4I_FRONTEND_BYPASS_CSC_EN,
-                          SUN4I_FRONTEND_BYPASS_CSC_EN);
+                          SUN4I_FRONTEND_BYPASS_CSC_EN, bypass);
 
        regmap_write(frontend->regs, SUN4I_FRONTEND_INPUT_FMT_REG,
                     in_mod_val | in_fmt_val | in_ps_val);
@@ -321,6 +566,10 @@ static int sun4i_frontend_bind(struct device *dev, struct device *master,
        frontend->dev = dev;
        frontend->node = dev->of_node;
 
+       frontend->data = of_device_get_match_data(dev);
+       if (!frontend->data)
+               return -ENODEV;
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        regs = devm_ioremap_resource(dev, res);
        if (IS_ERR(regs))
@@ -433,8 +682,47 @@ static const struct dev_pm_ops sun4i_frontend_pm_ops = {
        .runtime_suspend        = sun4i_frontend_runtime_suspend,
 };
 
+static const struct sun4i_frontend_data sun4i_a10_frontend = {
+       .ch_phase               = {
+               {
+                       .horzphase = 0,
+                       .vertphase = { 0, 0 },
+               },
+               {
+                       .horzphase = 0xfc000,
+                       .vertphase = { 0xfc000, 0xfc000 },
+               },
+       },
+       .has_coef_rdy           = true,
+};
+
+static const struct sun4i_frontend_data sun8i_a33_frontend = {
+       .ch_phase               = {
+               {
+                       .horzphase = 0x400,
+                       .vertphase = { 0x400, 0x400 },
+               },
+               {
+                       .horzphase = 0x400,
+                       .vertphase = { 0x400, 0x400 },
+               },
+       },
+       .has_coef_access_ctrl   = true,
+};
+
 const struct of_device_id sun4i_frontend_of_table[] = {
-       { .compatible = "allwinner,sun8i-a33-display-frontend" },
+       {
+               .compatible = "allwinner,sun4i-a10-display-frontend",
+               .data = &sun4i_a10_frontend
+       },
+       {
+               .compatible = "allwinner,sun7i-a20-display-frontend",
+               .data = &sun4i_a10_frontend
+       },
+       {
+               .compatible = "allwinner,sun8i-a33-display-frontend",
+               .data = &sun8i_a33_frontend
+       },
        { }
 };
 EXPORT_SYMBOL(sun4i_frontend_of_table);
index ad146e8d8d70d1d05e82420cd45bb0f7e4257bef..0c382c1ddb0fe81b0eb8f63999d0f6e2856d650c 100644 (file)
 #define SUN4I_FRONTEND_BYPASS_CSC_EN                   BIT(1)
 
 #define SUN4I_FRONTEND_BUF_ADDR0_REG           0x020
+#define SUN4I_FRONTEND_BUF_ADDR1_REG           0x024
+#define SUN4I_FRONTEND_BUF_ADDR2_REG           0x028
+
+#define SUN4I_FRONTEND_TB_OFF0_REG             0x030
+#define SUN4I_FRONTEND_TB_OFF1_REG             0x034
+#define SUN4I_FRONTEND_TB_OFF2_REG             0x038
+#define SUN4I_FRONTEND_TB_OFF_X1(x1)                   ((x1) << 16)
+#define SUN4I_FRONTEND_TB_OFF_Y0(y0)                   ((y0) << 8)
+#define SUN4I_FRONTEND_TB_OFF_X0(x0)                   (x0)
 
 #define SUN4I_FRONTEND_LINESTRD0_REG           0x040
+#define SUN4I_FRONTEND_LINESTRD1_REG           0x044
+#define SUN4I_FRONTEND_LINESTRD2_REG           0x048
+
+/*
+ * In tiled mode, the stride is defined as the distance between the start of the
+ * end line of the current tile and the start of the first line in the next
+ * vertical tile.
+ *
+ * Tiles are represented in row-major order, thus the end line of current tile
+ * starts at: 31 * 32 (31 lines of 32 cols), the next vertical tile starts at:
+ * 32-bit-aligned-width * 32 and the distance is:
+ * 32 * (32-bit-aligned-width - 31).
+ */
+#define SUN4I_FRONTEND_LINESTRD_TILED(stride)          (((stride) - 31) * 32)
 
 #define SUN4I_FRONTEND_INPUT_FMT_REG           0x04c
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PLANAR       (0 << 8)
 #define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED       (1 << 8)
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_SEMIPLANAR   (2 << 8)
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_MB32_PLANAR  (4 << 8)
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_MB32_SEMIPLANAR (6 << 8)
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV444       (0 << 4)
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV422       (1 << 4)
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV420       (2 << 4)
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_YUV411       (3 << 4)
 #define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB          (5 << 4)
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_UYVY          0
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_YUYV          1
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_VYUY          2
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_YVYU          3
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_UV            0
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_VU            1
 #define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX          0
 #define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB          1
 
@@ -35,6 +72,8 @@
 #define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_BGRX8888    1
 #define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_XRGB8888    2
 
+#define SUN4I_FRONTEND_CSC_COEF_REG(c)         (0x070 + (0x4 * (c)))
+
 #define SUN4I_FRONTEND_CH0_INSIZE_REG          0x100
 #define SUN4I_FRONTEND_INSIZE(h, w)                    ((((h) - 1) << 16) | (((w) - 1)))
 
@@ -73,6 +112,16 @@ struct drm_plane;
 struct regmap;
 struct reset_control;
 
+struct sun4i_frontend_data {
+       bool    has_coef_access_ctrl;
+       bool    has_coef_rdy;
+
+       struct {
+               u32     horzphase;
+               u32     vertphase[2];
+       } ch_phase[2];
+};
+
 struct sun4i_frontend {
        struct list_head        list;
        struct device           *dev;
@@ -83,9 +132,12 @@ struct sun4i_frontend {
        struct clk              *ram_clk;
        struct regmap           *regs;
        struct reset_control    *reset;
+
+       const struct sun4i_frontend_data        *data;
 };
 
 extern const struct of_device_id sun4i_frontend_of_table[];
+extern const u32 sunxi_bt601_yuv2rgb_coef[12];
 
 int sun4i_frontend_init(struct sun4i_frontend *frontend);
 void sun4i_frontend_exit(struct sun4i_frontend *frontend);
index 061d2e0d9011ee88991b3f0fb1b4e2dd54925bee..554a6f4561f3cfc47b7f4250722e5a92ba857451 100644 (file)
@@ -52,7 +52,8 @@ static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi,
        u8 buffer[17];
        int i, ret;
 
-       ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
+       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;
index 29631e0efde37ce709023995634dceac8c412f6a..c5a999ca1d72a90e8debfd108fb3b13fdeec6272 100644 (file)
@@ -114,6 +114,13 @@ static void sun4i_backend_layer_atomic_update(struct drm_plane *plane,
        sun4i_backend_layer_enable(backend, layer->id, true);
 }
 
+static bool sun4i_layer_format_mod_supported(struct drm_plane *plane,
+                                            uint32_t format, uint64_t modifier)
+{
+       return sun4i_backend_format_is_supported(format, modifier) ||
+              sun4i_frontend_format_is_supported(format, modifier);
+}
+
 static const struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = {
        .prepare_fb     = drm_gem_fb_prepare_fb,
        .atomic_disable = sun4i_backend_layer_atomic_disable,
@@ -127,6 +134,7 @@ static const struct drm_plane_funcs sun4i_backend_layer_funcs = {
        .disable_plane          = drm_atomic_helper_disable_plane,
        .reset                  = sun4i_backend_layer_reset,
        .update_plane           = drm_atomic_helper_update_plane,
+       .format_mod_supported   = sun4i_layer_format_mod_supported,
 };
 
 static const uint32_t sun4i_layer_formats[] = {
@@ -138,13 +146,31 @@ static const uint32_t sun4i_layer_formats[] = {
        DRM_FORMAT_RGBA4444,
        DRM_FORMAT_RGB888,
        DRM_FORMAT_RGB565,
+       DRM_FORMAT_NV12,
+       DRM_FORMAT_NV16,
+       DRM_FORMAT_NV21,
+       DRM_FORMAT_NV61,
        DRM_FORMAT_UYVY,
        DRM_FORMAT_VYUY,
        DRM_FORMAT_XRGB8888,
+       DRM_FORMAT_YUV411,
+       DRM_FORMAT_YUV420,
+       DRM_FORMAT_YUV422,
+       DRM_FORMAT_YUV444,
        DRM_FORMAT_YUYV,
+       DRM_FORMAT_YVU411,
+       DRM_FORMAT_YVU420,
+       DRM_FORMAT_YVU422,
+       DRM_FORMAT_YVU444,
        DRM_FORMAT_YVYU,
 };
 
+static const uint64_t sun4i_layer_modifiers[] = {
+       DRM_FORMAT_MOD_LINEAR,
+       DRM_FORMAT_MOD_ALLWINNER_TILED,
+       DRM_FORMAT_MOD_INVALID
+};
+
 static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
                                                struct sun4i_backend *backend,
                                                enum drm_plane_type type)
@@ -161,7 +187,7 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
                                       &sun4i_backend_layer_funcs,
                                       sun4i_layer_formats,
                                       ARRAY_SIZE(sun4i_layer_formats),
-                                      NULL, type, NULL);
+                                      sun4i_layer_modifiers, type, NULL);
        if (ret) {
                dev_err(drm->dev, "Couldn't initialize layer\n");
                return ERR_PTR(ret);
index 0082468f703c8c12ec89b142142b61b84b22fe89..a7566c67bfb05685dc8281c700196e10d4610022 100644 (file)
@@ -741,7 +741,8 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
        u8 buffer[17];
        ssize_t err;
 
-       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
+       err = drm_hdmi_avi_infoframe_from_display_mode(&frame,
+                                                      &hdmi->output.connector, mode);
        if (err < 0) {
                dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err);
                return;
index 922a48d5a483fbc217197e09984d9d1c7c7c2ed1..71cc3cf60066316a6a8686e79cff9fb29fbe26d4 100644 (file)
@@ -716,7 +716,7 @@ static int tegra_display_hub_init(struct host1x_client *client)
        if (!state)
                return -ENOMEM;
 
-       drm_atomic_private_obj_init(&hub->base, &state->base,
+       drm_atomic_private_obj_init(drm, &hub->base, &state->base,
                                    &tegra_display_hub_state_funcs);
 
        tegra->hub = hub;
index ef8692b7075ab0f82262b0aae3cb6c57f160d160..44feac2a03594445d180e8f2399288cbf9278f06 100644 (file)
@@ -2116,7 +2116,8 @@ tegra_sor_hdmi_setup_avi_infoframe(struct tegra_sor *sor,
        value &= ~INFOFRAME_CTRL_ENABLE;
        tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL);
 
-       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
+       err = drm_hdmi_avi_infoframe_from_display_mode(&frame,
+                                                      &sor->output.connector, mode);
        if (err < 0) {
                dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err);
                return err;
index 3dac08b24140fe5c16c90c76f2379f6d63ecd9ba..337e86a1d5eaa59c358e4cf0393510ea5c045605 100644 (file)
@@ -183,6 +183,12 @@ static void tilcdc_fini(struct drm_device *dev)
 {
        struct tilcdc_drm_private *priv = dev->dev_private;
 
+#ifdef CONFIG_CPU_FREQ
+       if (priv->freq_transition.notifier_call)
+               cpufreq_unregister_notifier(&priv->freq_transition,
+                                           CPUFREQ_TRANSITION_NOTIFIER);
+#endif
+
        if (priv->crtc)
                tilcdc_crtc_shutdown(priv->crtc);
 
@@ -194,12 +200,6 @@ static void tilcdc_fini(struct drm_device *dev)
        drm_mode_config_cleanup(dev);
        tilcdc_remove_external_device(dev);
 
-#ifdef CONFIG_CPU_FREQ
-       if (priv->freq_transition.notifier_call)
-               cpufreq_unregister_notifier(&priv->freq_transition,
-                                           CPUFREQ_TRANSITION_NOTIFIER);
-#endif
-
        if (priv->clk)
                clk_put(priv->clk);
 
@@ -270,17 +270,6 @@ static int tilcdc_init(struct drm_driver *ddrv, struct device *dev)
                goto init_failed;
        }
 
-#ifdef CONFIG_CPU_FREQ
-       priv->freq_transition.notifier_call = cpufreq_transition;
-       ret = cpufreq_register_notifier(&priv->freq_transition,
-                       CPUFREQ_TRANSITION_NOTIFIER);
-       if (ret) {
-               dev_err(dev, "failed to register cpufreq notifier\n");
-               priv->freq_transition.notifier_call = NULL;
-               goto init_failed;
-       }
-#endif
-
        if (of_property_read_u32(node, "max-bandwidth", &priv->max_bandwidth))
                priv->max_bandwidth = TILCDC_DEFAULT_MAX_BANDWIDTH;
 
@@ -357,6 +346,17 @@ static int tilcdc_init(struct drm_driver *ddrv, struct device *dev)
        }
        modeset_init(ddev);
 
+#ifdef CONFIG_CPU_FREQ
+       priv->freq_transition.notifier_call = cpufreq_transition;
+       ret = cpufreq_register_notifier(&priv->freq_transition,
+                       CPUFREQ_TRANSITION_NOTIFIER);
+       if (ret) {
+               dev_err(dev, "failed to register cpufreq notifier\n");
+               priv->freq_transition.notifier_call = NULL;
+               goto init_failed;
+       }
+#endif
+
        if (priv->is_componentized) {
                ret = component_bind_all(dev, ddev);
                if (ret < 0)
index 01a6f2d42440e0c2f3573698abfe6ea70f3408b1..614f532ea89f652755a9ebca76c522e89573973d 100644 (file)
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_print.h>
 #include <drm/tinydrm/tinydrm.h>
 #include <linux/device.h>
 #include <linux/dma-buf.h>
+#include <linux/module.h>
 
 /**
  * DOC: overview
  * and registers the DRM device using devm_tinydrm_register().
  */
 
-static struct drm_framebuffer *
-tinydrm_fb_create(struct drm_device *drm, struct drm_file *file_priv,
-                 const struct drm_mode_fb_cmd2 *mode_cmd)
-{
-       struct tinydrm_device *tdev = drm->dev_private;
-
-       return drm_gem_fb_create_with_funcs(drm, file_priv, mode_cmd,
-                                           tdev->fb_funcs);
-}
-
 static const struct drm_mode_config_funcs tinydrm_mode_config_funcs = {
-       .fb_create = tinydrm_fb_create,
+       .fb_create = drm_gem_fb_create_with_dirty,
        .atomic_check = drm_atomic_helper_check,
        .atomic_commit = drm_atomic_helper_commit,
 };
 
 static int tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
-                       const struct drm_framebuffer_funcs *fb_funcs,
                        struct drm_driver *driver)
 {
        struct drm_device *drm;
 
-       mutex_init(&tdev->dirty_lock);
-       tdev->fb_funcs = fb_funcs;
-
        /*
         * We don't embed drm_device, because that prevent us from using
         * devm_kzalloc() to allocate tinydrm_device in the driver since
@@ -83,7 +72,6 @@ static int tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
 static void tinydrm_fini(struct tinydrm_device *tdev)
 {
        drm_mode_config_cleanup(tdev->drm);
-       mutex_destroy(&tdev->dirty_lock);
        tdev->drm->dev_private = NULL;
        drm_dev_put(tdev->drm);
 }
@@ -97,7 +85,6 @@ static void devm_tinydrm_release(void *data)
  * devm_tinydrm_init - Initialize tinydrm device
  * @parent: Parent device object
  * @tdev: tinydrm device
- * @fb_funcs: Framebuffer functions
  * @driver: DRM driver
  *
  * This function initializes @tdev, the underlying DRM device and it's
@@ -108,12 +95,11 @@ static void devm_tinydrm_release(void *data)
  * Zero on success, negative error code on failure.
  */
 int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
-                     const struct drm_framebuffer_funcs *fb_funcs,
                      struct drm_driver *driver)
 {
        int ret;
 
-       ret = tinydrm_init(parent, tdev, fb_funcs, driver);
+       ret = tinydrm_init(parent, tdev, driver);
        if (ret)
                return ret;
 
index bf6bfbc5d412c8c2bb2e8a14fed1d16a139f1b88..2737b6fdadc85d5e60ef939fd5fd82d88ef5d526 100644 (file)
 #include <drm/drm_device.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_fourcc.h>
+#include <drm/drm_framebuffer.h>
 #include <drm/drm_print.h>
-#include <drm/tinydrm/tinydrm.h>
+#include <drm/drm_rect.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
-#include <uapi/drm/drm.h>
 
 static unsigned int spi_max;
 module_param(spi_max, uint, 0400);
 MODULE_PARM_DESC(spi_max, "Set a lower SPI max transfer size");
 
-/**
- * tinydrm_merge_clips - Merge clip rectangles
- * @dst: Destination clip rectangle
- * @src: Source clip rectangle(s)
- * @num_clips: Number of @src clip rectangles
- * @flags: Dirty fb ioctl flags
- * @max_width: Maximum width of @dst
- * @max_height: Maximum height of @dst
- *
- * This function merges @src clip rectangle(s) into @dst. If @src is NULL,
- * @max_width and @min_width is used to set a full @dst clip rectangle.
- *
- * Returns:
- * true if it's a full clip, false otherwise
- */
-bool tinydrm_merge_clips(struct drm_clip_rect *dst,
-                        struct drm_clip_rect *src, unsigned int num_clips,
-                        unsigned int flags, u32 max_width, u32 max_height)
-{
-       unsigned int i;
-
-       if (!src || !num_clips) {
-               dst->x1 = 0;
-               dst->x2 = max_width;
-               dst->y1 = 0;
-               dst->y2 = max_height;
-               return true;
-       }
-
-       dst->x1 = ~0;
-       dst->y1 = ~0;
-       dst->x2 = 0;
-       dst->y2 = 0;
-
-       for (i = 0; i < num_clips; i++) {
-               if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY)
-                       i++;
-               dst->x1 = min(dst->x1, src[i].x1);
-               dst->x2 = max(dst->x2, src[i].x2);
-               dst->y1 = min(dst->y1, src[i].y1);
-               dst->y2 = max(dst->y2, src[i].y2);
-       }
-
-       if (dst->x2 > max_width || dst->y2 > max_height ||
-           dst->x1 >= dst->x2 || dst->y1 >= dst->y2) {
-               DRM_DEBUG_KMS("Illegal clip: x1=%u, x2=%u, y1=%u, y2=%u\n",
-                             dst->x1, dst->x2, dst->y1, dst->y2);
-               dst->x1 = 0;
-               dst->y1 = 0;
-               dst->x2 = max_width;
-               dst->y2 = max_height;
-       }
-
-       return (dst->x2 - dst->x1) == max_width &&
-              (dst->y2 - dst->y1) == max_height;
-}
-EXPORT_SYMBOL(tinydrm_merge_clips);
-
-int tinydrm_fb_dirty(struct drm_framebuffer *fb,
-                    struct drm_file *file_priv,
-                    unsigned int flags, unsigned int color,
-                    struct drm_clip_rect *clips,
-                    unsigned int num_clips)
-{
-       struct tinydrm_device *tdev = fb->dev->dev_private;
-       struct drm_plane *plane = &tdev->pipe.plane;
-       int ret = 0;
-
-       drm_modeset_lock(&plane->mutex, NULL);
-
-       /* fbdev can flush even when we're not interested */
-       if (plane->state->fb == fb) {
-               mutex_lock(&tdev->dirty_lock);
-               ret = tdev->fb_dirty(fb, file_priv, flags,
-                                    color, clips, num_clips);
-               mutex_unlock(&tdev->dirty_lock);
-       }
-
-       drm_modeset_unlock(&plane->mutex);
-
-       if (ret)
-               dev_err_once(fb->dev->dev,
-                            "Failed to update display %d\n", ret);
-
-       return ret;
-}
-EXPORT_SYMBOL(tinydrm_fb_dirty);
-
 /**
  * tinydrm_memcpy - Copy clip buffer
  * @dst: Destination buffer
@@ -122,7 +34,7 @@ EXPORT_SYMBOL(tinydrm_fb_dirty);
  * @clip: Clip rectangle area to copy
  */
 void tinydrm_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb,
-                   struct drm_clip_rect *clip)
+                   struct drm_rect *clip)
 {
        unsigned int cpp = drm_format_plane_cpp(fb->format->format, 0);
        unsigned int pitch = fb->pitches[0];
@@ -146,7 +58,7 @@ EXPORT_SYMBOL(tinydrm_memcpy);
  * @clip: Clip rectangle area to copy
  */
 void tinydrm_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb,
-                   struct drm_clip_rect *clip)
+                   struct drm_rect *clip)
 {
        size_t len = (clip->x2 - clip->x1) * sizeof(u16);
        unsigned int x, y;
@@ -186,7 +98,7 @@ EXPORT_SYMBOL(tinydrm_swab16);
  */
 void tinydrm_xrgb8888_to_rgb565(u16 *dst, void *vaddr,
                                struct drm_framebuffer *fb,
-                               struct drm_clip_rect *clip, bool swap)
+                               struct drm_rect *clip, bool swap)
 {
        size_t len = (clip->x2 - clip->x1) * sizeof(u32);
        unsigned int x, y;
@@ -235,7 +147,7 @@ EXPORT_SYMBOL(tinydrm_xrgb8888_to_rgb565);
  * ITU BT.601 is used for the RGB -> luma (brightness) conversion.
  */
 void tinydrm_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb,
-                              struct drm_clip_rect *clip)
+                              struct drm_rect *clip)
 {
        unsigned int len = (clip->x2 - clip->x1) * sizeof(u32);
        unsigned int x, y;
index eacfc0ec8ff1dd0a1db5c9501b495e9c3f9b27d7..323564329535ef6b6bcb955d96411231d4e3c78f 100644 (file)
@@ -9,8 +9,10 @@
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_modes.h>
+#include <drm/drm_print.h>
 #include <drm/tinydrm/tinydrm.h>
 
 struct tinydrm_connector {
@@ -108,36 +110,6 @@ tinydrm_connector_create(struct drm_device *drm,
        return connector;
 }
 
-/**
- * tinydrm_display_pipe_update - Display pipe update helper
- * @pipe: Simple display pipe
- * @old_state: Old plane state
- *
- * This function does a full framebuffer flush if the plane framebuffer
- * has changed. It also handles vblank events. Drivers can use this as their
- * &drm_simple_display_pipe_funcs->update callback.
- */
-void tinydrm_display_pipe_update(struct drm_simple_display_pipe *pipe,
-                                struct drm_plane_state *old_state)
-{
-       struct tinydrm_device *tdev = pipe_to_tinydrm(pipe);
-       struct drm_framebuffer *fb = pipe->plane.state->fb;
-       struct drm_crtc *crtc = &tdev->pipe.crtc;
-
-       if (fb && (fb != old_state->fb)) {
-               if (tdev->fb_dirty)
-                       tdev->fb_dirty(fb, NULL, 0, 0, NULL, 0);
-       }
-
-       if (crtc->state->event) {
-               spin_lock_irq(&crtc->dev->event_lock);
-               drm_crtc_send_vblank_event(crtc, crtc->state->event);
-               spin_unlock_irq(&crtc->dev->event_lock);
-               crtc->state->event = NULL;
-       }
-}
-EXPORT_SYMBOL(tinydrm_display_pipe_update);
-
 static int tinydrm_rotate_mode(struct drm_display_mode *mode,
                               unsigned int rotation)
 {
index 81a2bbeb25d41cc3c63388f3de50aa7b60f60a51..8bbd0beafc6a415fb134db7ddacb03e62685c2f5 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/property.h>
 #include <linux/spi/spi.h>
 
+#include <drm/drm_drv.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_modeset_helper.h>
@@ -175,7 +176,7 @@ out_enable:
 static const struct drm_simple_display_pipe_funcs hx8357d_pipe_funcs = {
        .enable = yx240qv29_enable,
        .disable = mipi_dbi_pipe_disable,
-       .update = tinydrm_display_pipe_update,
+       .update = mipi_dbi_pipe_update,
        .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
 };
 
index 78f7c2d1b4494078ec42959e22afd5429b06080e..43a3b68d90a20a1f6e023433f16e840d2eb038e9 100644 (file)
 #include <linux/spi/spi.h>
 #include <video/mipi_display.h>
 
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_rect.h>
+#include <drm/drm_vblank.h>
 #include <drm/tinydrm/mipi-dbi.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
 
@@ -73,16 +78,14 @@ static inline int ili9225_command(struct mipi_dbi *mipi, u8 cmd, u16 data)
        return mipi_dbi_command_buf(mipi, cmd, par, 2);
 }
 
-static int ili9225_fb_dirty(struct drm_framebuffer *fb,
-                           struct drm_file *file_priv, unsigned int flags,
-                           unsigned int color, struct drm_clip_rect *clips,
-                           unsigned int num_clips)
+static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
 {
        struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
        struct tinydrm_device *tdev = fb->dev->dev_private;
        struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
+       unsigned int height = rect->y2 - rect->y1;
+       unsigned int width = rect->x2 - rect->x1;
        bool swap = mipi->swap_bytes;
-       struct drm_clip_rect clip;
        u16 x_start, y_start;
        u16 x1, x2, y1, y2;
        int ret = 0;
@@ -90,54 +93,52 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb,
        void *tr;
 
        if (!mipi->enabled)
-               return 0;
+               return;
 
-       full = tinydrm_merge_clips(&clip, clips, num_clips, flags,
-                                  fb->width, fb->height);
+       full = width == fb->width && height == fb->height;
 
-       DRM_DEBUG("Flushing [FB:%d] x1=%u, x2=%u, y1=%u, y2=%u\n", fb->base.id,
-                 clip.x1, clip.x2, clip.y1, clip.y2);
+       DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
 
        if (!mipi->dc || !full || swap ||
            fb->format->format == DRM_FORMAT_XRGB8888) {
                tr = mipi->tx_buf;
-               ret = mipi_dbi_buf_copy(mipi->tx_buf, fb, &clip, swap);
+               ret = mipi_dbi_buf_copy(mipi->tx_buf, fb, rect, swap);
                if (ret)
-                       return ret;
+                       goto err_msg;
        } else {
                tr = cma_obj->vaddr;
        }
 
        switch (mipi->rotation) {
        default:
-               x1 = clip.x1;
-               x2 = clip.x2 - 1;
-               y1 = clip.y1;
-               y2 = clip.y2 - 1;
+               x1 = rect->x1;
+               x2 = rect->x2 - 1;
+               y1 = rect->y1;
+               y2 = rect->y2 - 1;
                x_start = x1;
                y_start = y1;
                break;
        case 90:
-               x1 = clip.y1;
-               x2 = clip.y2 - 1;
-               y1 = fb->width - clip.x2;
-               y2 = fb->width - clip.x1 - 1;
+               x1 = rect->y1;
+               x2 = rect->y2 - 1;
+               y1 = fb->width - rect->x2;
+               y2 = fb->width - rect->x1 - 1;
                x_start = x1;
                y_start = y2;
                break;
        case 180:
-               x1 = fb->width - clip.x2;
-               x2 = fb->width - clip.x1 - 1;
-               y1 = fb->height - clip.y2;
-               y2 = fb->height - clip.y1 - 1;
+               x1 = fb->width - rect->x2;
+               x2 = fb->width - rect->x1 - 1;
+               y1 = fb->height - rect->y2;
+               y2 = fb->height - rect->y1 - 1;
                x_start = x2;
                y_start = y2;
                break;
        case 270:
-               x1 = fb->height - clip.y2;
-               x2 = fb->height - clip.y1 - 1;
-               y1 = clip.x1;
-               y2 = clip.x2 - 1;
+               x1 = fb->height - rect->y2;
+               x2 = fb->height - rect->y1 - 1;
+               y1 = rect->x1;
+               y2 = rect->x2 - 1;
                x_start = x2;
                y_start = y1;
                break;
@@ -152,16 +153,29 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb,
        ili9225_command(mipi, ILI9225_RAM_ADDRESS_SET_2, y_start);
 
        ret = mipi_dbi_command_buf(mipi, ILI9225_WRITE_DATA_TO_GRAM, tr,
-                               (clip.x2 - clip.x1) * (clip.y2 - clip.y1) * 2);
-
-       return ret;
+                                  width * height * 2);
+err_msg:
+       if (ret)
+               dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret);
 }
 
-static const struct drm_framebuffer_funcs ili9225_fb_funcs = {
-       .destroy        = drm_gem_fb_destroy,
-       .create_handle  = drm_gem_fb_create_handle,
-       .dirty          = tinydrm_fb_dirty,
-};
+static void ili9225_pipe_update(struct drm_simple_display_pipe *pipe,
+                               struct drm_plane_state *old_state)
+{
+       struct drm_plane_state *state = pipe->plane.state;
+       struct drm_crtc *crtc = &pipe->crtc;
+       struct drm_rect rect;
+
+       if (drm_atomic_helper_damage_merged(old_state, state, &rect))
+               ili9225_fb_dirty(state->fb, &rect);
+
+       if (crtc->state->event) {
+               spin_lock_irq(&crtc->dev->event_lock);
+               drm_crtc_send_vblank_event(crtc, crtc->state->event);
+               spin_unlock_irq(&crtc->dev->event_lock);
+               crtc->state->event = NULL;
+       }
+}
 
 static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
                                struct drm_crtc_state *crtc_state,
@@ -169,7 +183,14 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
 {
        struct tinydrm_device *tdev = pipe_to_tinydrm(pipe);
        struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
+       struct drm_framebuffer *fb = plane_state->fb;
        struct device *dev = tdev->drm->dev;
+       struct drm_rect rect = {
+               .x1 = 0,
+               .x2 = fb->width,
+               .y1 = 0,
+               .y2 = fb->height,
+       };
        int ret;
        u8 am_id;
 
@@ -257,7 +278,8 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
 
        ili9225_command(mipi, ILI9225_DISPLAY_CONTROL_1, 0x1017);
 
-       mipi_dbi_enable_flush(mipi, crtc_state, plane_state);
+       mipi->enabled = true;
+       ili9225_fb_dirty(fb, &rect);
 }
 
 static void ili9225_pipe_disable(struct drm_simple_display_pipe *pipe)
@@ -302,59 +324,10 @@ static int ili9225_dbi_command(struct mipi_dbi *mipi, u8 cmd, u8 *par,
        return tinydrm_spi_transfer(spi, speed_hz, NULL, bpw, par, num);
 }
 
-static const u32 ili9225_formats[] = {
-       DRM_FORMAT_RGB565,
-       DRM_FORMAT_XRGB8888,
-};
-
-static int ili9225_init(struct device *dev, struct mipi_dbi *mipi,
-                       const struct drm_simple_display_pipe_funcs *pipe_funcs,
-                       struct drm_driver *driver,
-                       const struct drm_display_mode *mode,
-                       unsigned int rotation)
-{
-       size_t bufsize = mode->vdisplay * mode->hdisplay * sizeof(u16);
-       struct tinydrm_device *tdev = &mipi->tinydrm;
-       int ret;
-
-       if (!mipi->command)
-               return -EINVAL;
-
-       mutex_init(&mipi->cmdlock);
-
-       mipi->tx_buf = devm_kmalloc(dev, bufsize, GFP_KERNEL);
-       if (!mipi->tx_buf)
-               return -ENOMEM;
-
-       ret = devm_tinydrm_init(dev, tdev, &ili9225_fb_funcs, driver);
-       if (ret)
-               return ret;
-
-       tdev->fb_dirty = ili9225_fb_dirty;
-
-       ret = tinydrm_display_pipe_init(tdev, pipe_funcs,
-                                       DRM_MODE_CONNECTOR_VIRTUAL,
-                                       ili9225_formats,
-                                       ARRAY_SIZE(ili9225_formats), mode,
-                                       rotation);
-       if (ret)
-               return ret;
-
-       tdev->drm->mode_config.preferred_depth = 16;
-       mipi->rotation = rotation;
-
-       drm_mode_config_reset(tdev->drm);
-
-       DRM_DEBUG_KMS("preferred_depth=%u, rotation = %u\n",
-                     tdev->drm->mode_config.preferred_depth, rotation);
-
-       return 0;
-}
-
 static const struct drm_simple_display_pipe_funcs ili9225_pipe_funcs = {
        .enable         = ili9225_pipe_enable,
        .disable        = ili9225_pipe_disable,
-       .update         = tinydrm_display_pipe_update,
+       .update         = ili9225_pipe_update,
        .prepare_fb     = drm_gem_fb_simple_display_pipe_prepare_fb,
 };
 
@@ -421,8 +394,8 @@ static int ili9225_probe(struct spi_device *spi)
        /* override the command function set in  mipi_dbi_spi_init() */
        mipi->command = ili9225_dbi_command;
 
-       ret = ili9225_init(&spi->dev, mipi, &ili9225_pipe_funcs,
-                          &ili9225_driver, &ili9225_mode, rotation);
+       ret = mipi_dbi_init(&spi->dev, mipi, &ili9225_pipe_funcs,
+                           &ili9225_driver, &ili9225_mode, rotation);
        if (ret)
                return ret;
 
index 51395bdc6ca22a731d5bf9cd70d4bc29ca1387d1..713bb2dd7e04c6582ab516dbd41371b922b862b4 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/property.h>
 #include <linux/spi/spi.h>
 
+#include <drm/drm_drv.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_modeset_helper.h>
@@ -131,7 +132,7 @@ out_enable:
 static const struct drm_simple_display_pipe_funcs ili9341_pipe_funcs = {
        .enable = yx240qv29_enable,
        .disable = mipi_dbi_pipe_disable,
-       .update = tinydrm_display_pipe_update,
+       .update = mipi_dbi_pipe_update,
        .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
 };
 
index 3fa62e77c30b2ceff4a3aeaf9c6f5b8d7eafce6a..82a92ec9ae3cedbe776a1bd9997c8b186d110918 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 
+#include <drm/drm_drv.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_modeset_helper.h>
@@ -139,7 +140,7 @@ out_enable:
 static const struct drm_simple_display_pipe_funcs mi0283qt_pipe_funcs = {
        .enable = mi0283qt_enable,
        .disable = mipi_dbi_pipe_disable,
-       .update = tinydrm_display_pipe_update,
+       .update = mipi_dbi_pipe_update,
        .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
 };
 
index 3a05e56f9b0d81c0cd15780478927086ee3af3c9..918f77c7de34e149080808e0161bad941bd8b3e3 100644 (file)
  */
 
 #include <linux/debugfs.h>
+#include <linux/delay.h>
 #include <linux/dma-buf.h>
 #include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_vblank.h>
+#include <drm/drm_rect.h>
 #include <drm/tinydrm/mipi-dbi.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
-#include <uapi/drm/drm.h>
 #include <video/mipi_display.h>
 
 #define MIPI_DBI_MAX_SPI_READ_SPEED 2000000 /* 2MHz */
@@ -169,7 +174,7 @@ EXPORT_SYMBOL(mipi_dbi_command_buf);
  * Zero on success, negative error code on failure.
  */
 int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
-                     struct drm_clip_rect *clip, bool swap)
+                     struct drm_rect *clip, bool swap)
 {
        struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
        struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
@@ -208,58 +213,75 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
 }
 EXPORT_SYMBOL(mipi_dbi_buf_copy);
 
-static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb,
-                            struct drm_file *file_priv,
-                            unsigned int flags, unsigned int color,
-                            struct drm_clip_rect *clips,
-                            unsigned int num_clips)
+static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
 {
        struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
        struct tinydrm_device *tdev = fb->dev->dev_private;
        struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
+       unsigned int height = rect->y2 - rect->y1;
+       unsigned int width = rect->x2 - rect->x1;
        bool swap = mipi->swap_bytes;
-       struct drm_clip_rect clip;
        int ret = 0;
        bool full;
        void *tr;
 
        if (!mipi->enabled)
-               return 0;
+               return;
 
-       full = tinydrm_merge_clips(&clip, clips, num_clips, flags,
-                                  fb->width, fb->height);
+       full = width == fb->width && height == fb->height;
 
-       DRM_DEBUG("Flushing [FB:%d] x1=%u, x2=%u, y1=%u, y2=%u\n", fb->base.id,
-                 clip.x1, clip.x2, clip.y1, clip.y2);
+       DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
 
        if (!mipi->dc || !full || swap ||
            fb->format->format == DRM_FORMAT_XRGB8888) {
                tr = mipi->tx_buf;
-               ret = mipi_dbi_buf_copy(mipi->tx_buf, fb, &clip, swap);
+               ret = mipi_dbi_buf_copy(mipi->tx_buf, fb, rect, swap);
                if (ret)
-                       return ret;
+                       goto err_msg;
        } else {
                tr = cma_obj->vaddr;
        }
 
        mipi_dbi_command(mipi, MIPI_DCS_SET_COLUMN_ADDRESS,
-                        (clip.x1 >> 8) & 0xFF, clip.x1 & 0xFF,
-                        ((clip.x2 - 1) >> 8) & 0xFF, (clip.x2 - 1) & 0xFF);
+                        (rect->x1 >> 8) & 0xff, rect->x1 & 0xff,
+                        ((rect->x2 - 1) >> 8) & 0xff, (rect->x2 - 1) & 0xff);
        mipi_dbi_command(mipi, MIPI_DCS_SET_PAGE_ADDRESS,
-                        (clip.y1 >> 8) & 0xFF, clip.y1 & 0xFF,
-                        ((clip.y2 - 1) >> 8) & 0xFF, (clip.y2 - 1) & 0xFF);
+                        (rect->y1 >> 8) & 0xff, rect->y1 & 0xff,
+                        ((rect->y2 - 1) >> 8) & 0xff, (rect->y2 - 1) & 0xff);
 
        ret = mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START, tr,
-                               (clip.x2 - clip.x1) * (clip.y2 - clip.y1) * 2);
-
-       return ret;
+                                  width * height * 2);
+err_msg:
+       if (ret)
+               dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret);
 }
 
-static const struct drm_framebuffer_funcs mipi_dbi_fb_funcs = {
-       .destroy        = drm_gem_fb_destroy,
-       .create_handle  = drm_gem_fb_create_handle,
-       .dirty          = tinydrm_fb_dirty,
-};
+/**
+ * mipi_dbi_pipe_update - Display pipe update helper
+ * @pipe: Simple display pipe
+ * @old_state: Old plane state
+ *
+ * This function handles framebuffer flushing and vblank events. Drivers can use
+ * this as their &drm_simple_display_pipe_funcs->update callback.
+ */
+void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe,
+                         struct drm_plane_state *old_state)
+{
+       struct drm_plane_state *state = pipe->plane.state;
+       struct drm_crtc *crtc = &pipe->crtc;
+       struct drm_rect rect;
+
+       if (drm_atomic_helper_damage_merged(old_state, state, &rect))
+               mipi_dbi_fb_dirty(state->fb, &rect);
+
+       if (crtc->state->event) {
+               spin_lock_irq(&crtc->dev->event_lock);
+               drm_crtc_send_vblank_event(crtc, crtc->state->event);
+               spin_unlock_irq(&crtc->dev->event_lock);
+               crtc->state->event = NULL;
+       }
+}
+EXPORT_SYMBOL(mipi_dbi_pipe_update);
 
 /**
  * mipi_dbi_enable_flush - MIPI DBI enable helper
@@ -270,18 +292,25 @@ static const struct drm_framebuffer_funcs mipi_dbi_fb_funcs = {
  * This function sets &mipi_dbi->enabled, flushes the whole framebuffer and
  * enables the backlight. Drivers can use this in their
  * &drm_simple_display_pipe_funcs->enable callback.
+ *
+ * Note: Drivers which don't use mipi_dbi_pipe_update() because they have custom
+ * framebuffer flushing, can't use this function since they both use the same
+ * flushing code.
  */
 void mipi_dbi_enable_flush(struct mipi_dbi *mipi,
                           struct drm_crtc_state *crtc_state,
                           struct drm_plane_state *plane_state)
 {
-       struct tinydrm_device *tdev = &mipi->tinydrm;
        struct drm_framebuffer *fb = plane_state->fb;
+       struct drm_rect rect = {
+               .x1 = 0,
+               .x2 = fb->width,
+               .y1 = 0,
+               .y2 = fb->height,
+       };
 
        mipi->enabled = true;
-       if (fb)
-               tdev->fb_dirty(fb, NULL, 0, 0, NULL, 0);
-
+       mipi_dbi_fb_dirty(fb, &rect);
        backlight_enable(mipi->backlight);
 }
 EXPORT_SYMBOL(mipi_dbi_enable_flush);
@@ -373,12 +402,10 @@ int mipi_dbi_init(struct device *dev, struct mipi_dbi *mipi,
        if (!mipi->tx_buf)
                return -ENOMEM;
 
-       ret = devm_tinydrm_init(dev, tdev, &mipi_dbi_fb_funcs, driver);
+       ret = devm_tinydrm_init(dev, tdev, driver);
        if (ret)
                return ret;
 
-       tdev->fb_dirty = mipi_dbi_fb_dirty;
-
        /* TODO: Maybe add DRM_MODE_CONNECTOR_SPI */
        ret = tinydrm_display_pipe_init(tdev, pipe_funcs,
                                        DRM_MODE_CONNECTOR_VIRTUAL,
@@ -388,6 +415,8 @@ int mipi_dbi_init(struct device *dev, struct mipi_dbi *mipi,
        if (ret)
                return ret;
 
+       drm_plane_enable_fb_damage_clips(&tdev->pipe.plane);
+
        tdev->drm->mode_config.preferred_depth = 16;
        mipi->rotation = rotation;
 
index 54d6fe0f37ce8b2a72133027d4a313bd4458557c..b037c6540cf389de2dd8777ab909309bcdf83a10 100644 (file)
 #include <linux/spi/spi.h>
 #include <linux/thermal.h>
 
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_rect.h>
+#include <drm/drm_vblank.h>
 #include <drm/tinydrm/tinydrm.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
 
@@ -521,17 +525,13 @@ static void repaper_gray8_to_mono_reversed(u8 *buf, u32 width, u32 height)
                }
 }
 
-static int repaper_fb_dirty(struct drm_framebuffer *fb,
-                           struct drm_file *file_priv,
-                           unsigned int flags, unsigned int color,
-                           struct drm_clip_rect *clips,
-                           unsigned int num_clips)
+static int repaper_fb_dirty(struct drm_framebuffer *fb)
 {
        struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
        struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
        struct tinydrm_device *tdev = fb->dev->dev_private;
        struct repaper_epd *epd = epd_from_tinydrm(tdev);
-       struct drm_clip_rect clip;
+       struct drm_rect clip;
        u8 *buf = NULL;
        int ret = 0;
 
@@ -624,12 +624,6 @@ out_free:
        return ret;
 }
 
-static const struct drm_framebuffer_funcs repaper_fb_funcs = {
-       .destroy        = drm_gem_fb_destroy,
-       .create_handle  = drm_gem_fb_create_handle,
-       .dirty          = tinydrm_fb_dirty,
-};
-
 static void power_off(struct repaper_epd *epd)
 {
        /* Turn off power and all signals */
@@ -793,9 +787,7 @@ static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe)
 
        DRM_DEBUG_DRIVER("\n");
 
-       mutex_lock(&tdev->dirty_lock);
        epd->enabled = false;
-       mutex_unlock(&tdev->dirty_lock);
 
        /* Nothing frame */
        for (line = 0; line < epd->height; line++)
@@ -838,10 +830,28 @@ static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe)
        power_off(epd);
 }
 
+static void repaper_pipe_update(struct drm_simple_display_pipe *pipe,
+                               struct drm_plane_state *old_state)
+{
+       struct drm_plane_state *state = pipe->plane.state;
+       struct drm_crtc *crtc = &pipe->crtc;
+       struct drm_rect rect;
+
+       if (drm_atomic_helper_damage_merged(old_state, state, &rect))
+               repaper_fb_dirty(state->fb);
+
+       if (crtc->state->event) {
+               spin_lock_irq(&crtc->dev->event_lock);
+               drm_crtc_send_vblank_event(crtc, crtc->state->event);
+               spin_unlock_irq(&crtc->dev->event_lock);
+               crtc->state->event = NULL;
+       }
+}
+
 static const struct drm_simple_display_pipe_funcs repaper_pipe_funcs = {
        .enable = repaper_pipe_enable,
        .disable = repaper_pipe_disable,
-       .update = tinydrm_display_pipe_update,
+       .update = repaper_pipe_update,
        .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
 };
 
@@ -1055,12 +1065,10 @@ static int repaper_probe(struct spi_device *spi)
 
        tdev = &epd->tinydrm;
 
-       ret = devm_tinydrm_init(dev, tdev, &repaper_fb_funcs, &repaper_driver);
+       ret = devm_tinydrm_init(dev, tdev, &repaper_driver);
        if (ret)
                return ret;
 
-       tdev->fb_dirty = repaper_fb_dirty;
-
        ret = tinydrm_display_pipe_init(tdev, &repaper_pipe_funcs,
                                        DRM_MODE_CONNECTOR_VIRTUAL,
                                        repaper_formats,
index a6a8a1081b73de27256d12b00bda06a4204a4017..01a8077954b341046087ae0d8c6230e10ff18707 100644 (file)
 #include <linux/spi/spi.h>
 #include <video/mipi_display.h>
 
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_rect.h>
+#include <drm/drm_vblank.h>
 #include <drm/tinydrm/mipi-dbi.h>
 #include <drm/tinydrm/tinydrm-helpers.h>
 
@@ -61,7 +65,7 @@ static const u8 st7586_lookup[] = { 0x7, 0x4, 0x2, 0x0 };
 
 static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr,
                                       struct drm_framebuffer *fb,
-                                      struct drm_clip_rect *clip)
+                                      struct drm_rect *clip)
 {
        size_t len = (clip->x2 - clip->x1) * (clip->y2 - clip->y1);
        unsigned int x, y;
@@ -87,7 +91,7 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr,
 }
 
 static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb,
-                          struct drm_clip_rect *clip)
+                          struct drm_rect *clip)
 {
        struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
        struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
@@ -110,57 +114,62 @@ static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb,
        return ret;
 }
 
-static int st7586_fb_dirty(struct drm_framebuffer *fb,
-                          struct drm_file *file_priv, unsigned int flags,
-                          unsigned int color, struct drm_clip_rect *clips,
-                          unsigned int num_clips)
+static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
 {
        struct tinydrm_device *tdev = fb->dev->dev_private;
        struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
-       struct drm_clip_rect clip;
        int start, end;
        int ret = 0;
 
        if (!mipi->enabled)
-               return 0;
-
-       tinydrm_merge_clips(&clip, clips, num_clips, flags, fb->width,
-                           fb->height);
+               return;
 
        /* 3 pixels per byte, so grow clip to nearest multiple of 3 */
-       clip.x1 = rounddown(clip.x1, 3);
-       clip.x2 = roundup(clip.x2, 3);
+       rect->x1 = rounddown(rect->x1, 3);
+       rect->x2 = roundup(rect->x2, 3);
 
-       DRM_DEBUG("Flushing [FB:%d] x1=%u, x2=%u, y1=%u, y2=%u\n", fb->base.id,
-                 clip.x1, clip.x2, clip.y1, clip.y2);
+       DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
 
-       ret = st7586_buf_copy(mipi->tx_buf, fb, &clip);
+       ret = st7586_buf_copy(mipi->tx_buf, fb, rect);
        if (ret)
-               return ret;
+               goto err_msg;
 
        /* Pixels are packed 3 per byte */
-       start = clip.x1 / 3;
-       end = clip.x2 / 3;
+       start = rect->x1 / 3;
+       end = rect->x2 / 3;
 
        mipi_dbi_command(mipi, MIPI_DCS_SET_COLUMN_ADDRESS,
                         (start >> 8) & 0xFF, start & 0xFF,
                         (end >> 8) & 0xFF, (end - 1) & 0xFF);
        mipi_dbi_command(mipi, MIPI_DCS_SET_PAGE_ADDRESS,
-                        (clip.y1 >> 8) & 0xFF, clip.y1 & 0xFF,
-                        (clip.y2 >> 8) & 0xFF, (clip.y2 - 1) & 0xFF);
+                        (rect->y1 >> 8) & 0xFF, rect->y1 & 0xFF,
+                        (rect->y2 >> 8) & 0xFF, (rect->y2 - 1) & 0xFF);
 
        ret = mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START,
                                   (u8 *)mipi->tx_buf,
-                                  (end - start) * (clip.y2 - clip.y1));
-
-       return ret;
+                                  (end - start) * (rect->y2 - rect->y1));
+err_msg:
+       if (ret)
+               dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret);
 }
 
-static const struct drm_framebuffer_funcs st7586_fb_funcs = {
-       .destroy        = drm_gem_fb_destroy,
-       .create_handle  = drm_gem_fb_create_handle,
-       .dirty          = tinydrm_fb_dirty,
-};
+static void st7586_pipe_update(struct drm_simple_display_pipe *pipe,
+                              struct drm_plane_state *old_state)
+{
+       struct drm_plane_state *state = pipe->plane.state;
+       struct drm_crtc *crtc = &pipe->crtc;
+       struct drm_rect rect;
+
+       if (drm_atomic_helper_damage_merged(old_state, state, &rect))
+               st7586_fb_dirty(state->fb, &rect);
+
+       if (crtc->state->event) {
+               spin_lock_irq(&crtc->dev->event_lock);
+               drm_crtc_send_vblank_event(crtc, crtc->state->event);
+               spin_unlock_irq(&crtc->dev->event_lock);
+               crtc->state->event = NULL;
+       }
+}
 
 static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
                               struct drm_crtc_state *crtc_state,
@@ -168,6 +177,13 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
 {
        struct tinydrm_device *tdev = pipe_to_tinydrm(pipe);
        struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
+       struct drm_framebuffer *fb = plane_state->fb;
+       struct drm_rect rect = {
+               .x1 = 0,
+               .x2 = fb->width,
+               .y1 = 0,
+               .y2 = fb->height,
+       };
        int ret;
        u8 addr_mode;
 
@@ -224,9 +240,10 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
 
        msleep(100);
 
-       mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON);
+       mipi->enabled = true;
+       st7586_fb_dirty(fb, &rect);
 
-       mipi_dbi_enable_flush(mipi, crtc_state, plane_state);
+       mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON);
 }
 
 static void st7586_pipe_disable(struct drm_simple_display_pipe *pipe)
@@ -262,12 +279,10 @@ static int st7586_init(struct device *dev, struct mipi_dbi *mipi,
        if (!mipi->tx_buf)
                return -ENOMEM;
 
-       ret = devm_tinydrm_init(dev, tdev, &st7586_fb_funcs, driver);
+       ret = devm_tinydrm_init(dev, tdev, driver);
        if (ret)
                return ret;
 
-       tdev->fb_dirty = st7586_fb_dirty;
-
        ret = tinydrm_display_pipe_init(tdev, pipe_funcs,
                                        DRM_MODE_CONNECTOR_VIRTUAL,
                                        st7586_formats,
@@ -276,6 +291,8 @@ static int st7586_init(struct device *dev, struct mipi_dbi *mipi,
        if (ret)
                return ret;
 
+       drm_plane_enable_fb_damage_clips(&tdev->pipe.plane);
+
        tdev->drm->mode_config.preferred_depth = 32;
        mipi->rotation = rotation;
 
@@ -290,7 +307,7 @@ static int st7586_init(struct device *dev, struct mipi_dbi *mipi,
 static const struct drm_simple_display_pipe_funcs st7586_pipe_funcs = {
        .enable         = st7586_pipe_enable,
        .disable        = st7586_pipe_disable,
-       .update         = tinydrm_display_pipe_update,
+       .update         = st7586_pipe_update,
        .prepare_fb     = drm_gem_fb_simple_display_pipe_prepare_fb,
 };
 
index b39779e0dcd8765c58be58b97e63c60848aa82ea..3bab9a9569a67744b86e856368a6cfbb30401e77 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/spi/spi.h>
 #include <video/mipi_display.h>
 
+#include <drm/drm_drv.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/tinydrm/mipi-dbi.h>
@@ -105,7 +106,7 @@ static void jd_t18003_t01_pipe_enable(struct drm_simple_display_pipe *pipe,
 static const struct drm_simple_display_pipe_funcs jd_t18003_t01_pipe_funcs = {
        .enable         = jd_t18003_t01_pipe_enable,
        .disable        = mipi_dbi_pipe_disable,
-       .update         = tinydrm_display_pipe_update,
+       .update         = mipi_dbi_pipe_update,
        .prepare_fb     = drm_gem_fb_simple_display_pipe_prepare_fb,
 };
 
index 0ec08394e17a6a818c98a931551371db1c0362c4..de088c8070fb377c921e982627fbb89c0bd32b7b 100644 (file)
@@ -198,19 +198,22 @@ static void ttm_bo_ref_bug(struct kref *list_kref)
 
 void ttm_bo_del_from_lru(struct ttm_buffer_object *bo)
 {
+       struct ttm_bo_device *bdev = bo->bdev;
+       bool notify = false;
+
        if (!list_empty(&bo->swap)) {
                list_del_init(&bo->swap);
                kref_put(&bo->list_kref, ttm_bo_ref_bug);
+               notify = true;
        }
        if (!list_empty(&bo->lru)) {
                list_del_init(&bo->lru);
                kref_put(&bo->list_kref, ttm_bo_ref_bug);
+               notify = true;
        }
 
-       /*
-        * TODO: Add a driver hook to delete from
-        * driver-specific LRU's here.
-        */
+       if (notify && bdev->driver->del_from_lru_notify)
+               bdev->driver->del_from_lru_notify(bo);
 }
 
 void ttm_bo_del_sub_from_lru(struct ttm_buffer_object *bo)
index a1d977fbade5502c8edad616e537702d75dc1673..e86a29a1e51f2ca225ad0ba8e6edd2eecf5430f1 100644 (file)
@@ -71,7 +71,7 @@ static vm_fault_t ttm_bo_vm_fault_idle(struct ttm_buffer_object *bo,
                ttm_bo_get(bo);
                up_read(&vmf->vma->vm_mm->mmap_sem);
                (void) dma_fence_wait(bo->moving, true);
-               ttm_bo_unreserve(bo);
+               reservation_object_unlock(bo->resv);
                ttm_bo_put(bo);
                goto out_unlock;
        }
@@ -131,11 +131,7 @@ static vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf)
         * for reserve, and if it fails, retry the fault after waiting
         * for the buffer to become unreserved.
         */
-       err = ttm_bo_reserve(bo, true, true, NULL);
-       if (unlikely(err != 0)) {
-               if (err != -EBUSY)
-                       return VM_FAULT_NOPAGE;
-
+       if (unlikely(!reservation_object_trylock(bo->resv))) {
                if (vmf->flags & FAULT_FLAG_ALLOW_RETRY) {
                        if (!(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) {
                                ttm_bo_get(bo);
@@ -165,6 +161,8 @@ static vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf)
        }
 
        if (bdev->driver->fault_reserve_notify) {
+               struct dma_fence *moving = dma_fence_get(bo->moving);
+
                err = bdev->driver->fault_reserve_notify(bo);
                switch (err) {
                case 0:
@@ -177,6 +175,13 @@ static vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf)
                        ret = VM_FAULT_SIGBUS;
                        goto out_unlock;
                }
+
+               if (bo->moving != moving) {
+                       spin_lock(&bdev->glob->lru_lock);
+                       ttm_bo_move_to_lru_tail(bo, NULL);
+                       spin_unlock(&bdev->glob->lru_lock);
+               }
+               dma_fence_put(moving);
        }
 
        /*
@@ -291,7 +296,7 @@ static vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf)
 out_io_unlock:
        ttm_mem_io_unlock(man);
 out_unlock:
-       ttm_bo_unreserve(bo);
+       reservation_object_unlock(bo->resv);
        return ret;
 }
 
index dcb772a191919c15c567bd7cbb7c1292e635835d..fdda3037f7af743fe3e699b43751fa8cc0b75d02 100644 (file)
@@ -308,7 +308,6 @@ void v3d_exec_put(struct v3d_exec_info *exec);
 void v3d_tfu_job_put(struct v3d_tfu_job *exec);
 void v3d_reset(struct v3d_dev *v3d);
 void v3d_invalidate_caches(struct v3d_dev *v3d);
-void v3d_flush_caches(struct v3d_dev *v3d);
 
 /* v3d_irq.c */
 void v3d_irq_init(struct v3d_dev *v3d);
index 05ca6319065e2287cc9264c41c3aec994c000413..803f31467ec1a9fedfabe2ad0dee5a408a59f958 100644 (file)
@@ -130,38 +130,31 @@ v3d_flush_l3(struct v3d_dev *v3d)
        }
 }
 
-/* Invalidates the (read-only) L2 cache. */
+/* Invalidates the (read-only) L2C cache.  This was the L2 cache for
+ * uniforms and instructions on V3D 3.2.
+ */
 static void
-v3d_invalidate_l2(struct v3d_dev *v3d, int core)
+v3d_invalidate_l2c(struct v3d_dev *v3d, int core)
 {
+       if (v3d->ver > 32)
+               return;
+
        V3D_CORE_WRITE(core, V3D_CTL_L2CACTL,
                       V3D_L2CACTL_L2CCLR |
                       V3D_L2CACTL_L2CENA);
 }
 
-static void
-v3d_invalidate_l1td(struct v3d_dev *v3d, int core)
-{
-       V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF);
-       if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
-                      V3D_L2TCACTL_L2TFLS), 100)) {
-               DRM_ERROR("Timeout waiting for L1T write combiner flush\n");
-       }
-}
-
 /* Invalidates texture L2 cachelines */
 static void
 v3d_flush_l2t(struct v3d_dev *v3d, int core)
 {
-       v3d_invalidate_l1td(v3d, core);
-
+       /* While there is a busy bit (V3D_L2TCACTL_L2TFLS), we don't
+        * need to wait for completion before dispatching the job --
+        * L2T accesses will be stalled until the flush has completed.
+        */
        V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
                       V3D_L2TCACTL_L2TFLS |
                       V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM));
-       if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
-                      V3D_L2TCACTL_L2TFLS), 100)) {
-               DRM_ERROR("Timeout waiting for L2T flush\n");
-       }
 }
 
 /* Invalidates the slice caches.  These are read-only caches. */
@@ -175,35 +168,18 @@ v3d_invalidate_slices(struct v3d_dev *v3d, int core)
                       V3D_SET_FIELD(0xf, V3D_SLCACTL_ICC));
 }
 
-/* Invalidates texture L2 cachelines */
-static void
-v3d_invalidate_l2t(struct v3d_dev *v3d, int core)
-{
-       V3D_CORE_WRITE(core,
-                      V3D_CTL_L2TCACTL,
-                      V3D_L2TCACTL_L2TFLS |
-                      V3D_SET_FIELD(V3D_L2TCACTL_FLM_CLEAR, V3D_L2TCACTL_FLM));
-       if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
-                      V3D_L2TCACTL_L2TFLS), 100)) {
-               DRM_ERROR("Timeout waiting for L2T invalidate\n");
-       }
-}
-
 void
 v3d_invalidate_caches(struct v3d_dev *v3d)
 {
+       /* Invalidate the caches from the outside in.  That way if
+        * another CL's concurrent use of nearby memory were to pull
+        * an invalidated cacheline back in, we wouldn't leave stale
+        * data in the inner cache.
+        */
        v3d_flush_l3(v3d);
-
-       v3d_invalidate_l2(v3d, 0);
-       v3d_invalidate_slices(v3d, 0);
+       v3d_invalidate_l2c(v3d, 0);
        v3d_flush_l2t(v3d, 0);
-}
-
-void
-v3d_flush_caches(struct v3d_dev *v3d)
-{
-       v3d_invalidate_l1td(v3d, 0);
-       v3d_invalidate_l2t(v3d, 0);
+       v3d_invalidate_slices(v3d, 0);
 }
 
 static void
index f7508e907536c63b1d5542f90749f2919ad32a5f..4704b2df3688816b51f5dfadeda17c9c328e2731 100644 (file)
@@ -234,18 +234,21 @@ v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job)
        for (q = 0; q < V3D_MAX_QUEUES; q++) {
                struct drm_gpu_scheduler *sched = &v3d->queue[q].sched;
 
-               kthread_park(sched->thread);
-               drm_sched_hw_job_reset(sched, (sched_job->sched == sched ?
-                                              sched_job : NULL));
+               drm_sched_stop(sched);
+
+               if(sched_job)
+                       drm_sched_increase_karma(sched_job);
        }
 
        /* get the GPU back into the init state */
        v3d_reset(v3d);
 
+       for (q = 0; q < V3D_MAX_QUEUES; q++)
+               drm_sched_resubmit_jobs(sched_job->sched);
+
        /* Unblock schedulers and restart their jobs. */
        for (q = 0; q < V3D_MAX_QUEUES; q++) {
-               drm_sched_job_recovery(&v3d->queue[q].sched);
-               kthread_unpark(v3d->queue[q].sched.thread);
+               drm_sched_start(&v3d->queue[q].sched, true);
        }
 
        mutex_unlock(&v3d->reset_lock);
index 3ce136ba8791999f81c89c74e2b976ebe42905b2..97caf1671dd06f883db650de9c52253e0680aa82 100644 (file)
@@ -49,6 +49,13 @@ struct vc4_crtc_state {
        struct drm_mm_node mm;
        bool feed_txp;
        bool txp_armed;
+
+       struct {
+               unsigned int left;
+               unsigned int right;
+               unsigned int top;
+               unsigned int bottom;
+       } margins;
 };
 
 static inline struct vc4_crtc_state *
@@ -624,6 +631,37 @@ static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc,
        return MODE_OK;
 }
 
+void vc4_crtc_get_margins(struct drm_crtc_state *state,
+                         unsigned int *left, unsigned int *right,
+                         unsigned int *top, unsigned int *bottom)
+{
+       struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state);
+       struct drm_connector_state *conn_state;
+       struct drm_connector *conn;
+       int i;
+
+       *left = vc4_state->margins.left;
+       *right = vc4_state->margins.right;
+       *top = vc4_state->margins.top;
+       *bottom = vc4_state->margins.bottom;
+
+       /* We have to interate over all new connector states because
+        * vc4_crtc_get_margins() might be called before
+        * vc4_crtc_atomic_check() which means margins info in vc4_crtc_state
+        * might be outdated.
+        */
+       for_each_new_connector_in_state(state->state, conn, conn_state, i) {
+               if (conn_state->crtc != state->crtc)
+                       continue;
+
+               *left = conn_state->tv.margins.left;
+               *right = conn_state->tv.margins.right;
+               *top = conn_state->tv.margins.top;
+               *bottom = conn_state->tv.margins.bottom;
+               break;
+       }
+}
+
 static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
                                 struct drm_crtc_state *state)
 {
@@ -671,6 +709,10 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
                        vc4_state->feed_txp = false;
                }
 
+               vc4_state->margins.left = conn_state->tv.margins.left;
+               vc4_state->margins.right = conn_state->tv.margins.right;
+               vc4_state->margins.top = conn_state->tv.margins.top;
+               vc4_state->margins.bottom = conn_state->tv.margins.bottom;
                break;
        }
 
@@ -972,6 +1014,7 @@ static struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc)
 
        old_vc4_state = to_vc4_crtc_state(crtc->state);
        vc4_state->feed_txp = old_vc4_state->feed_txp;
+       vc4_state->margins = old_vc4_state->margins;
 
        __drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
        return &vc4_state->base;
index 4f87b03f837d11d547ef649b16de99ec4c764658..2c635f001c711b03b83614d1fba7fbe472b094dc 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/mm_types.h>
 #include <linux/reservation.h>
 #include <drm/drmP.h>
+#include <drm/drm_util.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_atomic.h>
@@ -707,6 +708,9 @@ bool vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
                             const struct drm_display_mode *mode);
 void vc4_crtc_handle_vblank(struct vc4_crtc *crtc);
 void vc4_crtc_txp_armed(struct drm_crtc_state *state);
+void vc4_crtc_get_margins(struct drm_crtc_state *state,
+                         unsigned int *right, unsigned int *left,
+                         unsigned int *top, unsigned int *bottom);
 
 /* vc4_debugfs.c */
 int vc4_debugfs_init(struct drm_minor *minor);
index fd5522fd179e56399c63ce819e0f2a3580bc9ec1..051b61b62541f1701750c5f1a01e0ffd36df4435 100644 (file)
@@ -109,7 +109,6 @@ struct vc4_hdmi_encoder {
        struct vc4_encoder base;
        bool hdmi_monitor;
        bool limited_rgb_range;
-       bool rgb_range_selectable;
 };
 
 static inline struct vc4_hdmi_encoder *
@@ -280,11 +279,6 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
 
        vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
 
-       if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
-               vc4_encoder->rgb_range_selectable =
-                       drm_rgb_quant_range_selectable(edid);
-       }
-
        drm_connector_update_edid_property(connector, edid);
        ret = drm_add_edid_modes(connector, edid);
        kfree(edid);
@@ -310,6 +304,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
 {
        struct drm_connector *connector;
        struct vc4_hdmi_connector *hdmi_connector;
+       int ret;
 
        hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector),
                                      GFP_KERNEL);
@@ -323,6 +318,13 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
                           DRM_MODE_CONNECTOR_HDMIA);
        drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs);
 
+       /* Create and attach TV margin props to this connector. */
+       ret = drm_mode_create_tv_margin_properties(dev);
+       if (ret)
+               return ERR_PTR(ret);
+
+       drm_connector_attach_tv_margin_properties(connector);
+
        connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
                             DRM_CONNECTOR_POLL_DISCONNECT);
 
@@ -408,23 +410,31 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
 static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
 {
        struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+       struct vc4_dev *vc4 = encoder->dev->dev_private;
+       struct vc4_hdmi *hdmi = vc4->hdmi;
+       struct drm_connector_state *cstate = hdmi->connector->state;
        struct drm_crtc *crtc = encoder->crtc;
        const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
        union hdmi_infoframe frame;
        int ret;
 
-       ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
+       ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
+                                                      hdmi->connector, mode);
        if (ret < 0) {
                DRM_ERROR("couldn't fill AVI infoframe\n");
                return;
        }
 
-       drm_hdmi_avi_infoframe_quant_range(&frame.avi, mode,
+       drm_hdmi_avi_infoframe_quant_range(&frame.avi,
+                                          hdmi->connector, mode,
                                           vc4_encoder->limited_rgb_range ?
                                           HDMI_QUANTIZATION_RANGE_LIMITED :
-                                          HDMI_QUANTIZATION_RANGE_FULL,
-                                          vc4_encoder->rgb_range_selectable,
-                                          false);
+                                          HDMI_QUANTIZATION_RANGE_FULL);
+
+       frame.avi.right_bar = cstate->tv.margins.right;
+       frame.avi.left_bar = cstate->tv.margins.left;
+       frame.avi.top_bar = cstate->tv.margins.top;
+       frame.avi.bottom_bar = cstate->tv.margins.bottom;
 
        vc4_hdmi_write_infoframe(encoder, &frame);
 }
index 1f94b9affe4bbafddede75306c3109b1368bc172..0490edb192a193d893d6c99166a9af26aa3584fa 100644 (file)
@@ -432,7 +432,8 @@ int vc4_kms_load(struct drm_device *dev)
        ctm_state = kzalloc(sizeof(*ctm_state), GFP_KERNEL);
        if (!ctm_state)
                return -ENOMEM;
-       drm_atomic_private_obj_init(&vc4->ctm_manager, &ctm_state->base,
+
+       drm_atomic_private_obj_init(dev, &vc4->ctm_manager, &ctm_state->base,
                                    &vc4_ctm_state_funcs);
 
        drm_mode_config_reset(dev);
index 75db62cbe468df2324d395a2a33446c0a81cf172..d098337c10e9394d843c192ab08595566f631c59 100644 (file)
@@ -258,6 +258,52 @@ static u32 vc4_get_scl_field(struct drm_plane_state *state, int plane)
        }
 }
 
+static int vc4_plane_margins_adj(struct drm_plane_state *pstate)
+{
+       struct vc4_plane_state *vc4_pstate = to_vc4_plane_state(pstate);
+       unsigned int left, right, top, bottom, adjhdisplay, adjvdisplay;
+       struct drm_crtc_state *crtc_state;
+
+       crtc_state = drm_atomic_get_new_crtc_state(pstate->state,
+                                                  pstate->crtc);
+
+       vc4_crtc_get_margins(crtc_state, &left, &right, &top, &bottom);
+       if (!left && !right && !top && !bottom)
+               return 0;
+
+       if (left + right >= crtc_state->mode.hdisplay ||
+           top + bottom >= crtc_state->mode.vdisplay)
+               return -EINVAL;
+
+       adjhdisplay = crtc_state->mode.hdisplay - (left + right);
+       vc4_pstate->crtc_x = DIV_ROUND_CLOSEST(vc4_pstate->crtc_x *
+                                              adjhdisplay,
+                                              crtc_state->mode.hdisplay);
+       vc4_pstate->crtc_x += left;
+       if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - left)
+               vc4_pstate->crtc_x = crtc_state->mode.hdisplay - left;
+
+       adjvdisplay = crtc_state->mode.vdisplay - (top + bottom);
+       vc4_pstate->crtc_y = DIV_ROUND_CLOSEST(vc4_pstate->crtc_y *
+                                              adjvdisplay,
+                                              crtc_state->mode.vdisplay);
+       vc4_pstate->crtc_y += top;
+       if (vc4_pstate->crtc_y > crtc_state->mode.vdisplay - top)
+               vc4_pstate->crtc_y = crtc_state->mode.vdisplay - top;
+
+       vc4_pstate->crtc_w = DIV_ROUND_CLOSEST(vc4_pstate->crtc_w *
+                                              adjhdisplay,
+                                              crtc_state->mode.hdisplay);
+       vc4_pstate->crtc_h = DIV_ROUND_CLOSEST(vc4_pstate->crtc_h *
+                                              adjvdisplay,
+                                              crtc_state->mode.vdisplay);
+
+       if (!vc4_pstate->crtc_w || !vc4_pstate->crtc_h)
+               return -EINVAL;
+
+       return 0;
+}
+
 static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state)
 {
        struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
@@ -306,6 +352,10 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state)
        vc4_state->crtc_w = state->dst.x2 - state->dst.x1;
        vc4_state->crtc_h = state->dst.y2 - state->dst.y1;
 
+       ret = vc4_plane_margins_adj(state);
+       if (ret)
+               return ret;
+
        vc4_state->x_scaling[0] = vc4_get_scaling_mode(vc4_state->src_w[0],
                                                       vc4_state->crtc_w);
        vc4_state->y_scaling[0] = vc4_get_scaling_mode(vc4_state->src_h[0],
@@ -492,8 +542,9 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
        bool mix_plane_alpha;
        bool covers_screen;
        u32 scl0, scl1, pitch0;
-       u32 tiling;
+       u32 tiling, src_y;
        u32 hvs_format = format->hvs;
+       unsigned int rotation;
        int ret, i;
 
        if (vc4_state->dlist_initialized)
@@ -520,6 +571,16 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
        h_subsample = drm_format_horz_chroma_subsampling(format->drm);
        v_subsample = drm_format_vert_chroma_subsampling(format->drm);
 
+       rotation = drm_rotation_simplify(state->rotation,
+                                        DRM_MODE_ROTATE_0 |
+                                        DRM_MODE_REFLECT_X |
+                                        DRM_MODE_REFLECT_Y);
+
+       /* We must point to the last line when Y reflection is enabled. */
+       src_y = vc4_state->src_y;
+       if (rotation & DRM_MODE_REFLECT_Y)
+               src_y += vc4_state->src_h[0] - 1;
+
        switch (base_format_mod) {
        case DRM_FORMAT_MOD_LINEAR:
                tiling = SCALER_CTL0_TILING_LINEAR;
@@ -529,9 +590,10 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
                 * out.
                 */
                for (i = 0; i < num_planes; i++) {
-                       vc4_state->offsets[i] += vc4_state->src_y /
+                       vc4_state->offsets[i] += src_y /
                                                 (i ? v_subsample : 1) *
                                                 fb->pitches[i];
+
                        vc4_state->offsets[i] += vc4_state->src_x /
                                                 (i ? h_subsample : 1) *
                                                 fb->format->cpp[i];
@@ -557,22 +619,38 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
                u32 tiles_w = fb->pitches[0] >> (tile_size_shift - tile_h_shift);
                u32 tiles_l = vc4_state->src_x >> tile_w_shift;
                u32 tiles_r = tiles_w - tiles_l;
-               u32 tiles_t = vc4_state->src_y >> tile_h_shift;
+               u32 tiles_t = src_y >> tile_h_shift;
                /* Intra-tile offsets, which modify the base address (the
                 * SCALER_PITCH0_TILE_Y_OFFSET tells HVS how to walk from that
                 * base address).
                 */
-               u32 tile_y = (vc4_state->src_y >> 4) & 1;
-               u32 subtile_y = (vc4_state->src_y >> 2) & 3;
-               u32 utile_y = vc4_state->src_y & 3;
+               u32 tile_y = (src_y >> 4) & 1;
+               u32 subtile_y = (src_y >> 2) & 3;
+               u32 utile_y = src_y & 3;
                u32 x_off = vc4_state->src_x & tile_w_mask;
-               u32 y_off = vc4_state->src_y & tile_h_mask;
+               u32 y_off = src_y & tile_h_mask;
+
+               /* When Y reflection is requested we must set the
+                * SCALER_PITCH0_TILE_LINE_DIR flag to tell HVS that all lines
+                * after the initial one should be fetched in descending order,
+                * which makes sense since we start from the last line and go
+                * backward.
+                * Don't know why we need y_off = max_y_off - y_off, but it's
+                * definitely required (I guess it's also related to the "going
+                * backward" situation).
+                */
+               if (rotation & DRM_MODE_REFLECT_Y) {
+                       y_off = tile_h_mask - y_off;
+                       pitch0 = SCALER_PITCH0_TILE_LINE_DIR;
+               } else {
+                       pitch0 = 0;
+               }
 
                tiling = SCALER_CTL0_TILING_256B_OR_T;
-               pitch0 = (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) |
-                         VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) |
-                         VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) |
-                         VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R));
+               pitch0 |= (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) |
+                          VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) |
+                          VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) |
+                          VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R));
                vc4_state->offsets[0] += tiles_t * (tiles_w << tile_size_shift);
                vc4_state->offsets[0] += subtile_y << 8;
                vc4_state->offsets[0] += utile_y << 4;
@@ -595,31 +673,22 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
        case DRM_FORMAT_MOD_BROADCOM_SAND128:
        case DRM_FORMAT_MOD_BROADCOM_SAND256: {
                uint32_t param = fourcc_mod_broadcom_param(fb->modifier);
+               u32 tile_w, tile, x_off, pix_per_tile;
 
-               /* Column-based NV12 or RGBA.
-                */
-               if (fb->format->num_planes > 1) {
-                       if (hvs_format != HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE) {
-                               DRM_DEBUG_KMS("SAND format only valid for NV12/21");
-                               return -EINVAL;
-                       }
-                       hvs_format = HVS_PIXEL_FORMAT_H264;
-               } else {
-                       if (base_format_mod == DRM_FORMAT_MOD_BROADCOM_SAND256) {
-                               DRM_DEBUG_KMS("SAND256 format only valid for H.264");
-                               return -EINVAL;
-                       }
-               }
+               hvs_format = HVS_PIXEL_FORMAT_H264;
 
                switch (base_format_mod) {
                case DRM_FORMAT_MOD_BROADCOM_SAND64:
                        tiling = SCALER_CTL0_TILING_64B;
+                       tile_w = 64;
                        break;
                case DRM_FORMAT_MOD_BROADCOM_SAND128:
                        tiling = SCALER_CTL0_TILING_128B;
+                       tile_w = 128;
                        break;
                case DRM_FORMAT_MOD_BROADCOM_SAND256:
                        tiling = SCALER_CTL0_TILING_256B_OR_T;
+                       tile_w = 256;
                        break;
                default:
                        break;
@@ -630,6 +699,23 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
                        return -EINVAL;
                }
 
+               pix_per_tile = tile_w / fb->format->cpp[0];
+               tile = vc4_state->src_x / pix_per_tile;
+               x_off = vc4_state->src_x % pix_per_tile;
+
+               /* Adjust the base pointer to the first pixel to be scanned
+                * out.
+                */
+               for (i = 0; i < num_planes; i++) {
+                       vc4_state->offsets[i] += param * tile_w * tile;
+                       vc4_state->offsets[i] += src_y /
+                                                (i ? v_subsample : 1) *
+                                                tile_w;
+                       vc4_state->offsets[i] += x_off /
+                                                (i ? h_subsample : 1) *
+                                                fb->format->cpp[i];
+               }
+
                pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT);
                break;
        }
@@ -643,6 +729,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
        /* Control word */
        vc4_dlist_write(vc4_state,
                        SCALER_CTL0_VALID |
+                       (rotation & DRM_MODE_REFLECT_X ? SCALER_CTL0_HFLIP : 0) |
+                       (rotation & DRM_MODE_REFLECT_Y ? SCALER_CTL0_VFLIP : 0) |
                        VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) |
                        (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) |
                        (hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
@@ -1050,8 +1138,6 @@ static bool vc4_format_mod_supported(struct drm_plane *plane,
                switch (fourcc_mod_broadcom_mod(modifier)) {
                case DRM_FORMAT_MOD_LINEAR:
                case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
-               case DRM_FORMAT_MOD_BROADCOM_SAND64:
-               case DRM_FORMAT_MOD_BROADCOM_SAND128:
                        return true;
                default:
                        return false;
@@ -1123,6 +1209,11 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
        drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
 
        drm_plane_create_alpha_property(plane);
+       drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
+                                          DRM_MODE_ROTATE_0 |
+                                          DRM_MODE_ROTATE_180 |
+                                          DRM_MODE_REFLECT_X |
+                                          DRM_MODE_REFLECT_Y);
 
        return plane;
 }
index c1c420afe2dd130af9b4faf1df1fa649c1820f92..eb17c0cd3727a46498bc6dc0d0c77ec70cde0cfb 100644 (file)
@@ -53,13 +53,13 @@ static void vgem_fence_release(struct dma_fence *base)
 
 static void vgem_fence_value_str(struct dma_fence *fence, char *str, int size)
 {
-       snprintf(str, size, "%u", fence->seqno);
+       snprintf(str, size, "%llu", fence->seqno);
 }
 
 static void vgem_fence_timeline_value_str(struct dma_fence *fence, char *str,
                                          int size)
 {
-       snprintf(str, size, "%u",
+       snprintf(str, size, "%llu",
                 dma_fence_is_signaled(fence) ? fence->seqno : 0);
 }
 
index f29deec83d1f0478550b2d5b400e918a99607b55..4e90cc8fa651c596052aeedb310d58ee2bb119ba 100644 (file)
@@ -3,7 +3,7 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
-virtio-gpu-y := virtgpu_drv.o virtgpu_kms.o virtgpu_drm_bus.o virtgpu_gem.o \
+virtio-gpu-y := virtgpu_drv.o virtgpu_kms.o virtgpu_gem.o \
        virtgpu_fb.o virtgpu_display.o virtgpu_vq.o virtgpu_ttm.o \
        virtgpu_fence.o virtgpu_object.o virtgpu_debugfs.o virtgpu_plane.o \
        virtgpu_ioctl.o virtgpu_prime.o
index b5580b11a063606e79d8d43005b4cf4423ef5629..87d7c49cf057f2f003d2a04c8dbd18ac9b21b68d 100644 (file)
@@ -243,12 +243,8 @@ static enum drm_connector_status virtio_gpu_conn_detect(
 
 static void virtio_gpu_conn_destroy(struct drm_connector *connector)
 {
-       struct virtio_gpu_output *virtio_gpu_output =
-               drm_connector_to_virtio_gpu_output(connector);
-
        drm_connector_unregister(connector);
        drm_connector_cleanup(connector);
-       kfree(virtio_gpu_output);
 }
 
 static const struct drm_connector_funcs virtio_gpu_connector_funcs = {
@@ -362,7 +358,7 @@ static const struct drm_mode_config_funcs virtio_gpu_mode_funcs = {
        .atomic_commit = drm_atomic_helper_commit,
 };
 
-int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev)
+void virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev)
 {
        int i;
 
@@ -381,7 +377,6 @@ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev)
                vgdev_output_init(vgdev, i);
 
        drm_mode_config_reset(vgdev->ddev);
-       return 0;
 }
 
 void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev)
@@ -390,6 +385,5 @@ void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev)
 
        for (i = 0 ; i < vgdev->num_scanouts; ++i)
                kfree(vgdev->outputs[i].edid);
-       virtio_gpu_fbdev_fini(vgdev);
        drm_mode_config_cleanup(vgdev->ddev);
 }
diff --git a/drivers/gpu/drm/virtio/virtgpu_drm_bus.c b/drivers/gpu/drm/virtio/virtgpu_drm_bus.c
deleted file mode 100644 (file)
index 0887e0b..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2015 Red Hat, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) 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 OWNER(S) 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.
- */
-
-#include <linux/pci.h>
-#include <drm/drm_fb_helper.h>
-
-#include "virtgpu_drv.h"
-
-int drm_virtio_init(struct drm_driver *driver, struct virtio_device *vdev)
-{
-       struct drm_device *dev;
-       int ret;
-
-       dev = drm_dev_alloc(driver, &vdev->dev);
-       if (IS_ERR(dev))
-               return PTR_ERR(dev);
-       vdev->priv = dev;
-
-       if (strcmp(vdev->dev.parent->bus->name, "pci") == 0) {
-               struct pci_dev *pdev = to_pci_dev(vdev->dev.parent);
-               const char *pname = dev_name(&pdev->dev);
-               bool vga = (pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA;
-               char unique[20];
-
-               DRM_INFO("pci: %s detected at %s\n",
-                        vga ? "virtio-vga" : "virtio-gpu-pci",
-                        pname);
-               dev->pdev = pdev;
-               if (vga)
-                       drm_fb_helper_remove_conflicting_pci_framebuffers(pdev,
-                                                                         0,
-                                                                         "virtiodrmfb");
-
-               /*
-                * Normally the drm_dev_set_unique() call is done by core DRM.
-                * The following comment covers, why virtio cannot rely on it.
-                *
-                * Unlike the other virtual GPU drivers, virtio abstracts the
-                * underlying bus type by using struct virtio_device.
-                *
-                * Hence the dev_is_pci() check, used in core DRM, will fail
-                * and the unique returned will be the virtio_device "virtio0",
-                * while a "pci:..." one is required.
-                *
-                * A few other ideas were considered:
-                * - Extend the dev_is_pci() check [in drm_set_busid] to
-                *   consider virtio.
-                *   Seems like a bigger hack than what we have already.
-                *
-                * - Point drm_device::dev to the parent of the virtio_device
-                *   Semantic changes:
-                *   * Using the wrong device for i2c, framebuffer_alloc and
-                *     prime import.
-                *   Visual changes:
-                *   * Helpers such as DRM_DEV_ERROR, dev_info, drm_printer,
-                *     will print the wrong information.
-                *
-                * We could address the latter issues, by introducing
-                * drm_device::bus_dev, ... which would be used solely for this.
-                *
-                * So for the moment keep things as-is, with a bulky comment
-                * for the next person who feels like removing this
-                * drm_dev_set_unique() quirk.
-                */
-               snprintf(unique, sizeof(unique), "pci:%s", pname);
-               ret = drm_dev_set_unique(dev, unique);
-               if (ret)
-                       goto err_free;
-
-       }
-
-       ret = drm_dev_register(dev, 0);
-       if (ret)
-               goto err_free;
-
-       return 0;
-
-err_free:
-       drm_dev_put(dev);
-       return ret;
-}
index f7f32a885af79902a4c02ce4c4c801c1a119cc83..af92964b6889dd0dbfaadac5558cb27ee78b3d56 100644 (file)
@@ -40,21 +40,101 @@ static int virtio_gpu_modeset = -1;
 MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
 module_param_named(modeset, virtio_gpu_modeset, int, 0400);
 
+static int virtio_gpu_pci_quirk(struct drm_device *dev, struct virtio_device *vdev)
+{
+       struct pci_dev *pdev = to_pci_dev(vdev->dev.parent);
+       const char *pname = dev_name(&pdev->dev);
+       bool vga = (pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA;
+       char unique[20];
+
+       DRM_INFO("pci: %s detected at %s\n",
+                vga ? "virtio-vga" : "virtio-gpu-pci",
+                pname);
+       dev->pdev = pdev;
+       if (vga)
+               drm_fb_helper_remove_conflicting_pci_framebuffers(pdev,
+                                                                 0,
+                                                                 "virtiodrmfb");
+
+       /*
+        * Normally the drm_dev_set_unique() call is done by core DRM.
+        * The following comment covers, why virtio cannot rely on it.
+        *
+        * Unlike the other virtual GPU drivers, virtio abstracts the
+        * underlying bus type by using struct virtio_device.
+        *
+        * Hence the dev_is_pci() check, used in core DRM, will fail
+        * and the unique returned will be the virtio_device "virtio0",
+        * while a "pci:..." one is required.
+        *
+        * A few other ideas were considered:
+        * - Extend the dev_is_pci() check [in drm_set_busid] to
+        *   consider virtio.
+        *   Seems like a bigger hack than what we have already.
+        *
+        * - Point drm_device::dev to the parent of the virtio_device
+        *   Semantic changes:
+        *   * Using the wrong device for i2c, framebuffer_alloc and
+        *     prime import.
+        *   Visual changes:
+        *   * Helpers such as DRM_DEV_ERROR, dev_info, drm_printer,
+        *     will print the wrong information.
+        *
+        * We could address the latter issues, by introducing
+        * drm_device::bus_dev, ... which would be used solely for this.
+        *
+        * So for the moment keep things as-is, with a bulky comment
+        * for the next person who feels like removing this
+        * drm_dev_set_unique() quirk.
+        */
+       snprintf(unique, sizeof(unique), "pci:%s", pname);
+       return drm_dev_set_unique(dev, unique);
+}
+
 static int virtio_gpu_probe(struct virtio_device *vdev)
 {
+       struct drm_device *dev;
+       int ret;
+
        if (vgacon_text_force() && virtio_gpu_modeset == -1)
                return -EINVAL;
 
        if (virtio_gpu_modeset == 0)
                return -EINVAL;
 
-       return drm_virtio_init(&driver, vdev);
+       dev = drm_dev_alloc(&driver, &vdev->dev);
+       if (IS_ERR(dev))
+               return PTR_ERR(dev);
+       vdev->priv = dev;
+
+       if (!strcmp(vdev->dev.parent->bus->name, "pci")) {
+               ret = virtio_gpu_pci_quirk(dev, vdev);
+               if (ret)
+                       goto err_free;
+       }
+
+       ret = virtio_gpu_init(dev);
+       if (ret)
+               goto err_free;
+
+       ret = drm_dev_register(dev, 0);
+       if (ret)
+               goto err_free;
+
+       drm_fbdev_generic_setup(vdev->priv, 32);
+       return 0;
+
+err_free:
+       drm_dev_put(dev);
+       return ret;
 }
 
 static void virtio_gpu_remove(struct virtio_device *vdev)
 {
        struct drm_device *dev = vdev->priv;
 
+       drm_dev_unregister(dev);
+       virtio_gpu_deinit(dev);
        drm_put_dev(dev);
 }
 
@@ -116,8 +196,6 @@ static const struct file_operations virtio_gpu_driver_fops = {
 
 static struct drm_driver driver = {
        .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER | DRIVER_ATOMIC,
-       .load = virtio_gpu_driver_load,
-       .unload = virtio_gpu_driver_unload,
        .open = virtio_gpu_driver_open,
        .postclose = virtio_gpu_driver_postclose,
 
index 1deb41d42ea4d2ffa7d08a06c15d411be556cce4..cf896d879382fe30355f7e8434d5091320782934 100644 (file)
@@ -50,9 +50,6 @@
 #define DRIVER_MINOR 1
 #define DRIVER_PATCHLEVEL 0
 
-/* virtgpu_drm_bus.c */
-int drm_virtio_init(struct drm_driver *driver, struct virtio_device *vdev);
-
 struct virtio_gpu_object {
        struct drm_gem_object gem_base;
        uint32_t hw_res_handle;
@@ -137,19 +134,10 @@ struct virtio_gpu_framebuffer {
 #define to_virtio_gpu_framebuffer(x) \
        container_of(x, struct virtio_gpu_framebuffer, base)
 
-struct virtio_gpu_fbdev {
-       struct drm_fb_helper           helper;
-       struct virtio_gpu_framebuffer  vgfb;
-       struct virtio_gpu_device       *vgdev;
-       struct delayed_work            work;
-};
-
 struct virtio_gpu_mman {
        struct ttm_bo_device            bdev;
 };
 
-struct virtio_gpu_fbdev;
-
 struct virtio_gpu_queue {
        struct virtqueue *vq;
        spinlock_t qlock;
@@ -180,8 +168,6 @@ struct virtio_gpu_device {
 
        struct virtio_gpu_mman mman;
 
-       /* pointer to fbdev info structure */
-       struct virtio_gpu_fbdev *vgfbdev;
        struct virtio_gpu_output outputs[VIRTIO_GPU_MAX_SCANOUTS];
        uint32_t num_scanouts;
 
@@ -220,8 +206,8 @@ struct virtio_gpu_fpriv {
 extern struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS];
 
 /* virtio_kms.c */
-int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags);
-void virtio_gpu_driver_unload(struct drm_device *dev);
+int virtio_gpu_init(struct drm_device *dev);
+void virtio_gpu_deinit(struct drm_device *dev);
 int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file);
 void virtio_gpu_driver_postclose(struct drm_device *dev, struct drm_file *file);
 
@@ -249,9 +235,6 @@ int virtio_gpu_mode_dumb_mmap(struct drm_file *file_priv,
                              uint32_t handle, uint64_t *offset_p);
 
 /* virtio_fb */
-#define VIRTIO_GPUFB_CONN_LIMIT 1
-int virtio_gpu_fbdev_init(struct virtio_gpu_device *vgdev);
-void virtio_gpu_fbdev_fini(struct virtio_gpu_device *vgdev);
 int virtio_gpu_surface_dirty(struct virtio_gpu_framebuffer *qfb,
                             struct drm_clip_rect *clips,
                             unsigned int num_clips);
@@ -334,7 +317,7 @@ int virtio_gpu_framebuffer_init(struct drm_device *dev,
                                struct virtio_gpu_framebuffer *vgfb,
                                const struct drm_mode_fb_cmd2 *mode_cmd,
                                struct drm_gem_object *obj);
-int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev);
+void virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev);
 void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev);
 
 /* virtio_gpu_plane.c */
@@ -351,7 +334,6 @@ int virtio_gpu_mmap(struct file *filp, struct vm_area_struct *vma);
 /* virtio_gpu_fence.c */
 struct virtio_gpu_fence *virtio_gpu_fence_alloc(
        struct virtio_gpu_device *vgdev);
-void virtio_gpu_fence_cleanup(struct virtio_gpu_fence *fence);
 int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,
                          struct virtio_gpu_ctrl_hdr *cmd_hdr,
                          struct virtio_gpu_fence *fence);
index fb1cc8b2f119d9aadd794583c500f9715c1525fa..b07584b1c2bf7be15a40a72f545138f204dd0177 100644 (file)
@@ -27,8 +27,6 @@
 #include <drm/drm_fb_helper.h>
 #include "virtgpu_drv.h"
 
-#define VIRTIO_GPU_FBCON_POLL_PERIOD (HZ / 60)
-
 static int virtio_gpu_dirty_update(struct virtio_gpu_framebuffer *fb,
                                   bool store, int x, int y,
                                   int width, int height)
@@ -150,192 +148,3 @@ int virtio_gpu_surface_dirty(struct virtio_gpu_framebuffer *vgfb,
                                      left, top, right - left, bottom - top);
        return 0;
 }
-
-static void virtio_gpu_fb_dirty_work(struct work_struct *work)
-{
-       struct delayed_work *delayed_work = to_delayed_work(work);
-       struct virtio_gpu_fbdev *vfbdev =
-               container_of(delayed_work, struct virtio_gpu_fbdev, work);
-       struct virtio_gpu_framebuffer *vgfb = &vfbdev->vgfb;
-
-       virtio_gpu_dirty_update(&vfbdev->vgfb, false, vgfb->x1, vgfb->y1,
-                               vgfb->x2 - vgfb->x1, vgfb->y2 - vgfb->y1);
-}
-
-static void virtio_gpu_3d_fillrect(struct fb_info *info,
-                                  const struct fb_fillrect *rect)
-{
-       struct virtio_gpu_fbdev *vfbdev = info->par;
-
-       drm_fb_helper_sys_fillrect(info, rect);
-       virtio_gpu_dirty_update(&vfbdev->vgfb, true, rect->dx, rect->dy,
-                            rect->width, rect->height);
-       schedule_delayed_work(&vfbdev->work, VIRTIO_GPU_FBCON_POLL_PERIOD);
-}
-
-static void virtio_gpu_3d_copyarea(struct fb_info *info,
-                                  const struct fb_copyarea *area)
-{
-       struct virtio_gpu_fbdev *vfbdev = info->par;
-
-       drm_fb_helper_sys_copyarea(info, area);
-       virtio_gpu_dirty_update(&vfbdev->vgfb, true, area->dx, area->dy,
-                          area->width, area->height);
-       schedule_delayed_work(&vfbdev->work, VIRTIO_GPU_FBCON_POLL_PERIOD);
-}
-
-static void virtio_gpu_3d_imageblit(struct fb_info *info,
-                                   const struct fb_image *image)
-{
-       struct virtio_gpu_fbdev *vfbdev = info->par;
-
-       drm_fb_helper_sys_imageblit(info, image);
-       virtio_gpu_dirty_update(&vfbdev->vgfb, true, image->dx, image->dy,
-                            image->width, image->height);
-       schedule_delayed_work(&vfbdev->work, VIRTIO_GPU_FBCON_POLL_PERIOD);
-}
-
-static struct fb_ops virtio_gpufb_ops = {
-       .owner = THIS_MODULE,
-       DRM_FB_HELPER_DEFAULT_OPS,
-       .fb_fillrect = virtio_gpu_3d_fillrect,
-       .fb_copyarea = virtio_gpu_3d_copyarea,
-       .fb_imageblit = virtio_gpu_3d_imageblit,
-};
-
-static int virtio_gpufb_create(struct drm_fb_helper *helper,
-                              struct drm_fb_helper_surface_size *sizes)
-{
-       struct virtio_gpu_fbdev *vfbdev =
-               container_of(helper, struct virtio_gpu_fbdev, helper);
-       struct drm_device *dev = helper->dev;
-       struct virtio_gpu_device *vgdev = dev->dev_private;
-       struct fb_info *info;
-       struct drm_framebuffer *fb;
-       struct drm_mode_fb_cmd2 mode_cmd = {};
-       struct virtio_gpu_object *obj;
-       uint32_t format, size;
-       int ret;
-
-       mode_cmd.width = sizes->surface_width;
-       mode_cmd.height = sizes->surface_height;
-       mode_cmd.pitches[0] = mode_cmd.width * 4;
-       mode_cmd.pixel_format = DRM_FORMAT_HOST_XRGB8888;
-
-       format = virtio_gpu_translate_format(mode_cmd.pixel_format);
-       if (format == 0)
-               return -EINVAL;
-
-       size = mode_cmd.pitches[0] * mode_cmd.height;
-       obj = virtio_gpu_alloc_object(dev, size, false, true);
-       if (IS_ERR(obj))
-               return PTR_ERR(obj);
-
-       virtio_gpu_cmd_create_resource(vgdev, obj, format,
-                                      mode_cmd.width, mode_cmd.height);
-
-       ret = virtio_gpu_object_kmap(obj);
-       if (ret) {
-               DRM_ERROR("failed to kmap fb %d\n", ret);
-               goto err_obj_vmap;
-       }
-
-       /* attach the object to the resource */
-       ret = virtio_gpu_object_attach(vgdev, obj, NULL);
-       if (ret)
-               goto err_obj_attach;
-
-       info = drm_fb_helper_alloc_fbi(helper);
-       if (IS_ERR(info)) {
-               ret = PTR_ERR(info);
-               goto err_fb_alloc;
-       }
-
-       info->par = helper;
-
-       ret = virtio_gpu_framebuffer_init(dev, &vfbdev->vgfb,
-                                         &mode_cmd, &obj->gem_base);
-       if (ret)
-               goto err_fb_alloc;
-
-       fb = &vfbdev->vgfb.base;
-
-       vfbdev->helper.fb = fb;
-
-       strcpy(info->fix.id, "virtiodrmfb");
-       info->fbops = &virtio_gpufb_ops;
-       info->pixmap.flags = FB_PIXMAP_SYSTEM;
-
-       info->screen_buffer = obj->vmap;
-       info->screen_size = obj->gem_base.size;
-       drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
-       drm_fb_helper_fill_var(info, &vfbdev->helper,
-                              sizes->fb_width, sizes->fb_height);
-
-       info->fix.mmio_start = 0;
-       info->fix.mmio_len = 0;
-       return 0;
-
-err_fb_alloc:
-       virtio_gpu_object_detach(vgdev, obj);
-err_obj_attach:
-err_obj_vmap:
-       virtio_gpu_gem_free_object(&obj->gem_base);
-       return ret;
-}
-
-static int virtio_gpu_fbdev_destroy(struct drm_device *dev,
-                                   struct virtio_gpu_fbdev *vgfbdev)
-{
-       struct virtio_gpu_framebuffer *vgfb = &vgfbdev->vgfb;
-
-       drm_fb_helper_unregister_fbi(&vgfbdev->helper);
-
-       if (vgfb->base.obj[0])
-               vgfb->base.obj[0] = NULL;
-       drm_fb_helper_fini(&vgfbdev->helper);
-       drm_framebuffer_cleanup(&vgfb->base);
-
-       return 0;
-}
-static const struct drm_fb_helper_funcs virtio_gpu_fb_helper_funcs = {
-       .fb_probe = virtio_gpufb_create,
-};
-
-int virtio_gpu_fbdev_init(struct virtio_gpu_device *vgdev)
-{
-       struct virtio_gpu_fbdev *vgfbdev;
-       int bpp_sel = 32; /* TODO: parameter from somewhere? */
-       int ret;
-
-       vgfbdev = kzalloc(sizeof(struct virtio_gpu_fbdev), GFP_KERNEL);
-       if (!vgfbdev)
-               return -ENOMEM;
-
-       vgfbdev->vgdev = vgdev;
-       vgdev->vgfbdev = vgfbdev;
-       INIT_DELAYED_WORK(&vgfbdev->work, virtio_gpu_fb_dirty_work);
-
-       drm_fb_helper_prepare(vgdev->ddev, &vgfbdev->helper,
-                             &virtio_gpu_fb_helper_funcs);
-       ret = drm_fb_helper_init(vgdev->ddev, &vgfbdev->helper,
-                                VIRTIO_GPUFB_CONN_LIMIT);
-       if (ret) {
-               kfree(vgfbdev);
-               return ret;
-       }
-
-       drm_fb_helper_single_add_all_connectors(&vgfbdev->helper);
-       drm_fb_helper_initial_config(&vgfbdev->helper, bpp_sel);
-       return 0;
-}
-
-void virtio_gpu_fbdev_fini(struct virtio_gpu_device *vgdev)
-{
-       if (!vgdev->vgfbdev)
-               return;
-
-       virtio_gpu_fbdev_destroy(vgdev->ddev, vgdev->vgfbdev);
-       kfree(vgdev->vgfbdev);
-       vgdev->vgfbdev = NULL;
-}
index 4d6826b27814ee3002eb119216c2cc569ea880c2..21bd4c4a32d141b3efef38cb5ec040857abd0fa9 100644 (file)
@@ -81,14 +81,6 @@ struct virtio_gpu_fence *virtio_gpu_fence_alloc(struct virtio_gpu_device *vgdev)
        return fence;
 }
 
-void virtio_gpu_fence_cleanup(struct virtio_gpu_fence *fence)
-{
-       if (!fence)
-               return;
-
-       dma_fence_put(&fence->f);
-}
-
 int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,
                          struct virtio_gpu_ctrl_hdr *cmd_hdr,
                          struct virtio_gpu_fence *fence)
index 161b80fee492564346262d954a0bb8d9864aaae4..14ce8188c05237e3cadbd4def670817e81ddd4c2 100644 (file)
@@ -351,7 +351,7 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
                virtio_gpu_cmd_resource_create_3d(vgdev, qobj, &rc_3d);
                ret = virtio_gpu_object_attach(vgdev, qobj, fence);
                if (ret) {
-                       virtio_gpu_fence_cleanup(fence);
+                       dma_fence_put(&fence->f);
                        goto fail_backoff;
                }
                ttm_eu_fence_buffer_objects(&ticket, &validate_list, &fence->f);
index 3af6181c05a852cccf91880e34388f78723e1835..84b6a6bf00c68222cfde74ec7f9d64c43b0ed9f3 100644 (file)
 #include <drm/drmP.h>
 #include "virtgpu_drv.h"
 
-static int virtio_gpu_fbdev = 1;
-
-MODULE_PARM_DESC(fbdev, "Disable/Enable framebuffer device & console");
-module_param_named(fbdev, virtio_gpu_fbdev, int, 0400);
-
 static void virtio_gpu_config_changed_work_func(struct work_struct *work)
 {
        struct virtio_gpu_device *vgdev =
@@ -111,7 +106,7 @@ static void virtio_gpu_get_capsets(struct virtio_gpu_device *vgdev,
        vgdev->num_capsets = num_capsets;
 }
 
-int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
+int virtio_gpu_init(struct drm_device *dev)
 {
        static vq_callback_t *callbacks[] = {
                virtio_gpu_ctrl_ack, virtio_gpu_cursor_ack
@@ -198,9 +193,7 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
                     num_capsets, &num_capsets);
        DRM_INFO("number of cap sets: %d\n", num_capsets);
 
-       ret = virtio_gpu_modeset_init(vgdev);
-       if (ret)
-               goto err_modeset;
+       virtio_gpu_modeset_init(vgdev);
 
        virtio_device_ready(vgdev->vdev);
        vgdev->vqs_ready = true;
@@ -212,12 +205,8 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
        virtio_gpu_cmd_get_display_info(vgdev);
        wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending,
                           5 * HZ);
-       if (virtio_gpu_fbdev)
-               virtio_gpu_fbdev_init(vgdev);
-
        return 0;
 
-err_modeset:
 err_scanouts:
        virtio_gpu_ttm_fini(vgdev);
 err_ttm:
@@ -239,7 +228,7 @@ static void virtio_gpu_cleanup_cap_cache(struct virtio_gpu_device *vgdev)
        }
 }
 
-void virtio_gpu_driver_unload(struct drm_device *dev)
+void virtio_gpu_deinit(struct drm_device *dev)
 {
        struct virtio_gpu_device *vgdev = dev->dev_private;
 
@@ -247,6 +236,7 @@ void virtio_gpu_driver_unload(struct drm_device *dev)
        flush_work(&vgdev->ctrlq.dequeue_work);
        flush_work(&vgdev->cursorq.dequeue_work);
        flush_work(&vgdev->config_changed_work);
+       vgdev->vdev->config->reset(vgdev->vdev);
        vgdev->vdev->config->del_vqs(vgdev->vdev);
 
        virtio_gpu_modeset_fini(vgdev);
index ead5c53d4e2163f02f9b859ca79d600ad9ae00ac..024c2aa0c929eab8ccdb9ef43b879447704b97b3 100644 (file)
@@ -130,11 +130,12 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
                                   plane->state->src_h >> 16,
                                   plane->state->src_x >> 16,
                                   plane->state->src_y >> 16);
-       virtio_gpu_cmd_resource_flush(vgdev, handle,
-                                     plane->state->src_x >> 16,
-                                     plane->state->src_y >> 16,
-                                     plane->state->src_w >> 16,
-                                     plane->state->src_h >> 16);
+       if (handle)
+               virtio_gpu_cmd_resource_flush(vgdev, handle,
+                                             plane->state->src_x >> 16,
+                                             plane->state->src_y >> 16,
+                                             plane->state->src_w >> 16,
+                                             plane->state->src_h >> 16);
 }
 
 static int virtio_gpu_cursor_prepare_fb(struct drm_plane *plane,
@@ -168,8 +169,10 @@ static void virtio_gpu_cursor_cleanup_fb(struct drm_plane *plane,
                return;
 
        vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
-       if (vgfb->fence)
-               virtio_gpu_fence_cleanup(vgfb->fence);
+       if (vgfb->fence) {
+               dma_fence_put(&vgfb->fence->f);
+               vgfb->fence = NULL;
+       }
 }
 
 static void virtio_gpu_cursor_plane_update(struct drm_plane *plane,
index e27c4aedb8093e16a886aa74c1a20a85062ba1f4..6bc2008b0d0db1196c9b4d738265073a7ea4130b 100644 (file)
@@ -192,8 +192,16 @@ void virtio_gpu_dequeue_ctrl_func(struct work_struct *work)
 
        list_for_each_entry_safe(entry, tmp, &reclaim_list, list) {
                resp = (struct virtio_gpu_ctrl_hdr *)entry->resp_buf;
-               if (resp->type != cpu_to_le32(VIRTIO_GPU_RESP_OK_NODATA))
-                       DRM_DEBUG("response 0x%x\n", le32_to_cpu(resp->type));
+               if (resp->type != cpu_to_le32(VIRTIO_GPU_RESP_OK_NODATA)) {
+                       if (resp->type >= cpu_to_le32(VIRTIO_GPU_RESP_ERR_UNSPEC)) {
+                               struct virtio_gpu_ctrl_hdr *cmd;
+                               cmd = (struct virtio_gpu_ctrl_hdr *)entry->buf;
+                               DRM_ERROR("response 0x%x (command 0x%x)\n",
+                                         le32_to_cpu(resp->type),
+                                         le32_to_cpu(cmd->type));
+                       } else
+                               DRM_DEBUG("response 0x%x\n", le32_to_cpu(resp->type));
+               }
                if (resp->flags & cpu_to_le32(VIRTIO_GPU_FLAG_FENCE)) {
                        u64 f = le64_to_cpu(resp->fence_id);
 
index 83087877565cf77b9104d67636c183231fdd19c4..2a16b86196dcd17a557114936bdb51562d2e3c40 100644 (file)
@@ -95,6 +95,7 @@ static int vkms_modeset_init(struct vkms_device *vkmsdev)
        dev->mode_config.min_height = YRES_MIN;
        dev->mode_config.max_width = XRES_MAX;
        dev->mode_config.max_height = YRES_MAX;
+       dev->mode_config.preferred_depth = 24;
 
        return vkms_output_init(vkmsdev);
 }
index c91ae532fa55eda2f47aa5b09d7df340bc5ea02a..54af2669b1b37696545a0dda0e4533d47cecf528 100644 (file)
@@ -89,7 +89,6 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = {
 };
 
 static const struct drm_connector_funcs connector_funcs = {
-       .dpms = drm_helper_connector_dpms,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .destroy = drm_connector_cleanup,
        .reset = drm_atomic_helper_connector_reset,
index 78655269d84343d683fc2278740ff21e075c3d1d..9fc98bb4f3d9e452128ab104e803540f4ced1d39 100644 (file)
@@ -125,7 +125,9 @@ static int zx_hdmi_config_video_avi(struct zx_hdmi *hdmi,
        union hdmi_infoframe frame;
        int ret;
 
-       ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
+       ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
+                                                      &hdmi->connector,
+                                                      mode);
        if (ret) {
                DRM_DEV_ERROR(hdmi->dev, "failed to get avi infoframe: %d\n",
                              ret);
index 6b7aa23dfc0aaf99eefc54979fa2f94a49f65ee6..397496cf0bdf605d017fb9ff8015910dba7f6790 100644 (file)
@@ -95,11 +95,6 @@ int vboxfb_create(struct drm_fb_helper *helper,
 
        strcpy(info->fix.id, "vboxdrmfb");
 
-       /*
-        * The last flag forces a mode set on VT switches even if the kernel
-        * does not think it is needed.
-        */
-       info->flags = FBINFO_DEFAULT | FBINFO_MISC_ALWAYS_SETPAR;
        info->fbops = &vboxfb_ops;
 
        /*
index 9c56412bb2cf2e0e3e64bb06306f17bfb76a362f..9f93895dde888de87939bde846e4d20d465beb84 100644 (file)
 #ifndef __DW_HDMI__
 #define __DW_HDMI__
 
-#include <drm/drmP.h>
-
+struct drm_connector;
+struct drm_display_mode;
+struct drm_encoder;
 struct dw_hdmi;
+struct platform_device;
 
 /**
  * DOC: Supported input formats and encodings
index 48a671e782cafd6ec3ef405f615802c187733ff5..7d3dd69a5caa73a6b23ee11f74c5d4a98f640028 100644 (file)
@@ -14,7 +14,8 @@ struct dw_mipi_dsi;
 
 struct dw_mipi_dsi_phy_ops {
        int (*init)(void *priv_data);
-       int (*get_lane_mbps)(void *priv_data, struct drm_display_mode *mode,
+       int (*get_lane_mbps)(void *priv_data,
+                            const struct drm_display_mode *mode,
                             unsigned long mode_flags, u32 lanes, u32 format,
                             unsigned int *lane_mbps);
 };
index bdb0d5548f39ede087a64e626f34b215834733d5..3f5c577c9dbde93d7f8ba8bff046434eb1087880 100644 (file)
@@ -94,25 +94,11 @@ struct dma_buf_attachment;
 struct pci_dev;
 struct pci_controller;
 
-#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
-
-#define DRM_SWITCH_POWER_ON 0
-#define DRM_SWITCH_POWER_OFF 1
-#define DRM_SWITCH_POWER_CHANGING 2
-#define DRM_SWITCH_POWER_DYNAMIC_OFF 3
-
-/* returns true if currently okay to sleep */
-static inline bool drm_can_sleep(void)
-{
-       if (in_atomic() || in_dbg_master() || irqs_disabled())
-               return false;
-       return true;
-}
-
-#if defined(CONFIG_DRM_DEBUG_SELFTEST_MODULE)
-#define EXPORT_SYMBOL_FOR_TESTS_ONLY(x) EXPORT_SYMBOL(x)
-#else
-#define EXPORT_SYMBOL_FOR_TESTS_ONLY(x)
-#endif
+/*
+ * NOTE: drmP.h is obsolete - do NOT add anything to this file
+ *
+ * Do not include drmP.h in new files.
+ * Work is ongoing to remove drmP.h includes from existing files
+ */
 
 #endif
index f9b35834c45d0e544fe7c2944353577072818ac2..811b4a92568f463c16d3c5d9fbca9cda9efd049e 100644 (file)
@@ -139,9 +139,9 @@ struct drm_crtc_commit {
        /**
         * @abort_completion:
         *
-        * A flag that's set after drm_atomic_helper_setup_commit takes a second
-        * reference for the completion of $drm_crtc_state.event. It's used by
-        * the free code to remove the second reference if commit fails.
+        * A flag that's set after drm_atomic_helper_setup_commit() takes a
+        * second reference for the completion of $drm_crtc_state.event. It's
+        * used by the free code to remove the second reference if commit fails.
         */
        bool abort_completion;
 };
@@ -228,8 +228,30 @@ struct drm_private_state_funcs {
  * Currently only tracks the state update functions and the opaque driver
  * private state itself, but in the future might also track which
  * &drm_modeset_lock is required to duplicate and update this object's state.
+ *
+ * All private objects must be initialized before the DRM device they are
+ * attached to is registered to the DRM subsystem (call to drm_dev_register())
+ * and should stay around until this DRM device is unregistered (call to
+ * drm_dev_unregister()). In other words, private objects lifetime is tied
+ * to the DRM device lifetime. This implies that:
+ *
+ * 1/ all calls to drm_atomic_private_obj_init() must be done before calling
+ *    drm_dev_register()
+ * 2/ all calls to drm_atomic_private_obj_fini() must be done after calling
+ *    drm_dev_unregister()
  */
 struct drm_private_obj {
+       /**
+        * @head: List entry used to attach a private object to a &drm_device
+        * (queued to &drm_mode_config.privobj_list).
+        */
+       struct list_head head;
+
+       /**
+        * @lock: Modeset lock to protect the state object.
+        */
+       struct drm_modeset_lock lock;
+
        /**
         * @state: Current atomic state for this driver private object.
         */
@@ -244,6 +266,18 @@ struct drm_private_obj {
        const struct drm_private_state_funcs *funcs;
 };
 
+/**
+ * drm_for_each_privobj() - private object iterator
+ *
+ * @privobj: pointer to the current private object. Updated after each
+ *          iteration
+ * @dev: the DRM device we want get private objects from
+ *
+ * Allows one to iterate over all private objects attached to @dev
+ */
+#define drm_for_each_privobj(privobj, dev) \
+       list_for_each_entry(privobj, &(dev)->mode_config.privobj_list, head)
+
 /**
  * struct drm_private_state - base struct for driver private object state
  * @state: backpointer to global drm_atomic_state
@@ -400,7 +434,8 @@ struct drm_connector_state * __must_check
 drm_atomic_get_connector_state(struct drm_atomic_state *state,
                               struct drm_connector *connector);
 
-void drm_atomic_private_obj_init(struct drm_private_obj *obj,
+void drm_atomic_private_obj_init(struct drm_device *dev,
+                                struct drm_private_obj *obj,
                                 struct drm_private_state *state,
                                 const struct drm_private_state_funcs *funcs);
 void drm_atomic_private_obj_fini(struct drm_private_obj *obj);
index bd850747ce5472fe477919db42f4cb5d1911f61f..9da8c93f79764ab5c246afa612a7eb748962153a 100644 (file)
@@ -196,8 +196,8 @@ struct drm_bridge_funcs {
         * the DRM framework will have to be extended with DRM bridge states.
         */
        void (*mode_set)(struct drm_bridge *bridge,
-                        struct drm_display_mode *mode,
-                        struct drm_display_mode *adjusted_mode);
+                        const struct drm_display_mode *mode,
+                        const struct drm_display_mode *adjusted_mode);
        /**
         * @pre_enable:
         *
@@ -310,8 +310,8 @@ enum drm_mode_status drm_bridge_mode_valid(struct drm_bridge *bridge,
 void drm_bridge_disable(struct drm_bridge *bridge);
 void drm_bridge_post_disable(struct drm_bridge *bridge);
 void drm_bridge_mode_set(struct drm_bridge *bridge,
-                        struct drm_display_mode *mode,
-                        struct drm_display_mode *adjusted_mode);
+                        const struct drm_display_mode *mode,
+                        const struct drm_display_mode *adjusted_mode);
 void drm_bridge_pre_enable(struct drm_bridge *bridge);
 void drm_bridge_enable(struct drm_bridge *bridge);
 
index 90ef9996d9a4ab2896f34b1e87ad72e6cc44749c..6affbda6d9cb114cd8f0ff58e62a1ae70d9f3067 100644 (file)
@@ -69,4 +69,33 @@ int drm_plane_create_color_properties(struct drm_plane *plane,
                                      u32 supported_ranges,
                                      enum drm_color_encoding default_encoding,
                                      enum drm_color_range default_range);
+
+/**
+ * enum drm_color_lut_tests - hw-specific LUT tests to perform
+ *
+ * The drm_color_lut_check() function takes a bitmask of the values here to
+ * determine which tests to apply to a userspace-provided LUT.
+ */
+enum drm_color_lut_tests {
+       /**
+        * @DRM_COLOR_LUT_EQUAL_CHANNELS:
+        *
+        * Checks whether the entries of a LUT all have equal values for the
+        * red, green, and blue channels.  Intended for hardware that only
+        * accepts a single value per LUT entry and assumes that value applies
+        * to all three color components.
+        */
+       DRM_COLOR_LUT_EQUAL_CHANNELS = BIT(0),
+
+       /**
+        * @DRM_COLOR_LUT_NON_DECREASING:
+        *
+        * Checks whether the entries of a LUT are always flat or increasing
+        * (never decreasing).
+        */
+       DRM_COLOR_LUT_NON_DECREASING = BIT(1),
+};
+
+int drm_color_lut_check(struct drm_property_blob *lut,
+                       uint32_t tests);
 #endif
index 9be2181b3ed7a065afb8770b7dfd39b0537c4e26..994161374a4928e33e668674f8120589d6661bc1 100644 (file)
@@ -365,6 +365,12 @@ struct drm_display_info {
         */
        bool has_hdmi_infoframe;
 
+       /**
+        * @rgb_quant_range_selectable: Does the sink support selecting
+        * the RGB quantization range?
+        */
+       bool rgb_quant_range_selectable;
+
        /**
         * @edid_hdmi_dc_modes: Mask of supported hdmi deep color modes. Even
         * more stuff redundant with @bus_formats.
@@ -394,7 +400,7 @@ int drm_display_info_set_bus_formats(struct drm_display_info *info,
 /**
  * struct drm_tv_connector_state - TV connector related states
  * @subconnector: selected subconnector
- * @margins: margins
+ * @margins: margins (all margins are expressed in pixels)
  * @margins.left: left margin
  * @margins.right: right margin
  * @margins.top: top margin
@@ -1249,9 +1255,11 @@ const char *drm_get_tv_select_name(int val);
 const char *drm_get_content_protection_name(int val);
 
 int drm_mode_create_dvi_i_properties(struct drm_device *dev);
+int drm_mode_create_tv_margin_properties(struct drm_device *dev);
 int drm_mode_create_tv_properties(struct drm_device *dev,
                                  unsigned int num_modes,
                                  const char * const modes[]);
+void drm_connector_attach_tv_margin_properties(struct drm_connector *conn);
 int drm_mode_create_scaling_mode_property(struct drm_device *dev);
 int drm_connector_attach_content_type_property(struct drm_connector *dev);
 int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
index 39c3900aab3cea107a0771b6fe0d5dc510ac4c11..85abd3fe9e832d4bad14a710e69504821e4bcd3d 100644 (file)
@@ -1149,9 +1149,6 @@ static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc)
        return 1 << drm_crtc_index(crtc);
 }
 
-int drm_crtc_force_disable(struct drm_crtc *crtc);
-int drm_crtc_force_disable_all(struct drm_device *dev);
-
 int drm_mode_set_config_internal(struct drm_mode_set *set);
 struct drm_crtc *drm_crtc_from_index(struct drm_device *dev, int idx);
 
index d65f034843cea620a3d99ff7b28261e8e33122a9..0ee9a96b70dab6a6b9b0c61991bc9d61842b7841 100644 (file)
@@ -56,6 +56,7 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
 int drm_helper_connector_dpms(struct drm_connector *connector, int mode);
 
 void drm_helper_resume_force_mode(struct drm_device *dev);
+int drm_helper_force_disable_all(struct drm_device *dev);
 
 /* drm_probe_helper.c */
 int drm_helper_probe_single_connector_modes(struct drm_connector
index 4487660b26b8d198ba25f64728f88e09adccaf97..40c34a5bf1498223760b99146dd99159697abb11 100644 (file)
@@ -78,6 +78,9 @@ drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter,
 bool
 drm_atomic_helper_damage_iter_next(struct drm_atomic_helper_damage_iter *iter,
                                   struct drm_rect *rect);
+bool drm_atomic_helper_damage_merged(const struct drm_plane_state *old_state,
+                                    struct drm_plane_state *state,
+                                    struct drm_rect *rect);
 
 /**
  * drm_helper_get_plane_damage_clips - Returns damage clips in &drm_rect.
index 42411b3ea0c82e4133b4f5fc97dfe1150c99f63b..d5e092dccf3e5578c90356e0bab6f929116dac74 100644 (file)
@@ -24,25 +24,79 @@ struct inode;
 struct pci_dev;
 struct pci_controller;
 
+
 /**
- * DRM device structure. This structure represent a complete card that
+ * enum drm_switch_power - power state of drm device
+ */
+
+enum switch_power_state {
+       /** @DRM_SWITCH_POWER_ON: Power state is ON */
+       DRM_SWITCH_POWER_ON = 0,
+
+       /** @DRM_SWITCH_POWER_OFF: Power state is OFF */
+       DRM_SWITCH_POWER_OFF = 1,
+
+       /** @DRM_SWITCH_POWER_CHANGING: Power state is changing */
+       DRM_SWITCH_POWER_CHANGING = 2,
+
+       /** @DRM_SWITCH_POWER_DYNAMIC_OFF: Suspended */
+       DRM_SWITCH_POWER_DYNAMIC_OFF = 3,
+};
+
+/**
+ * struct drm_device - DRM device structure
+ *
+ * This structure represent a complete card that
  * may contain multiple heads.
  */
 struct drm_device {
-       struct list_head legacy_dev_list;/**< list of devices per driver for stealth attach cleanup */
-       int if_version;                 /**< Highest interface version set */
-
-       /** \name Lifetime Management */
-       /*@{ */
-       struct kref ref;                /**< Object ref-count */
-       struct device *dev;             /**< Device structure of bus-device */
-       struct drm_driver *driver;      /**< DRM driver managing the device */
-       void *dev_private;              /**< DRM driver private data */
-       struct drm_minor *primary;              /**< Primary node */
-       struct drm_minor *render;               /**< Render node */
+       /**
+        * @legacy_dev_list:
+        *
+        * List of devices per driver for stealth attach cleanup
+        */
+       struct list_head legacy_dev_list;
+
+       /** @if_version: Highest interface version set */
+       int if_version;
+
+       /** @ref: Object ref-count */
+       struct kref ref;
+
+       /** @dev: Device structure of bus-device */
+       struct device *dev;
+
+       /** @driver: DRM driver managing the device */
+       struct drm_driver *driver;
+
+       /**
+        * @dev_private:
+        *
+        * DRM driver private data. Instead of using this pointer it is
+        * recommended that drivers use drm_dev_init() and embed struct
+        * &drm_device in their larger per-device structure.
+        */
+       void *dev_private;
+
+       /** @primary: Primary node */
+       struct drm_minor *primary;
+
+       /** @render: Render node */
+       struct drm_minor *render;
+
+       /**
+        * @registered:
+        *
+        * Internally used by drm_dev_register() and drm_connector_register().
+        */
        bool registered;
 
-       /* currently active master for this device. Protected by master_mutex */
+       /**
+        * @master:
+        *
+        * Currently active master for this device.
+        * Protected by &master_mutex
+        */
        struct drm_master *master;
 
        /**
@@ -63,76 +117,65 @@ struct drm_device {
         */
        bool unplugged;
 
-       struct inode *anon_inode;               /**< inode for private address-space */
-       char *unique;                           /**< unique name of the device */
-       /*@} */
+       /** @anon_inode: inode for private address-space */
+       struct inode *anon_inode;
+
+       /** @unique: Unique name of the device */
+       char *unique;
 
-       /** \name Locks */
-       /*@{ */
-       struct mutex struct_mutex;      /**< For others */
-       struct mutex master_mutex;      /**< For drm_minor::master and drm_file::is_master */
-       /*@} */
+       /**
+        * @struct_mutex:
+        *
+        * Lock for others (not &drm_minor.master and &drm_file.is_master)
+        */
+       struct mutex struct_mutex;
 
-       /** \name Usage Counters */
-       /*@{ */
-       int open_count;                 /**< Outstanding files open, protected by drm_global_mutex. */
-       spinlock_t buf_lock;            /**< For drm_device::buf_use and a few other things. */
-       int buf_use;                    /**< Buffers in use -- cannot alloc */
-       atomic_t buf_alloc;             /**< Buffer allocation in progress */
-       /*@} */
+       /**
+        * @master_mutex:
+        *
+        * Lock for &drm_minor.master and &drm_file.is_master
+        */
+       struct mutex master_mutex;
+
+       /**
+        * @open_count:
+        *
+        * Usage counter for outstanding files open,
+        * protected by drm_global_mutex
+        */
+       int open_count;
 
+       /** @filelist_mutex: Protects @filelist. */
        struct mutex filelist_mutex;
+       /**
+        * @filelist:
+        *
+        * List of userspace clients, linked through &drm_file.lhead.
+        */
        struct list_head filelist;
 
        /**
         * @filelist_internal:
         *
-        * List of open DRM files for in-kernel clients. Protected by @filelist_mutex.
+        * List of open DRM files for in-kernel clients.
+        * Protected by &filelist_mutex.
         */
        struct list_head filelist_internal;
 
        /**
         * @clientlist_mutex:
         *
-        * Protects @clientlist access.
+        * Protects &clientlist access.
         */
        struct mutex clientlist_mutex;
 
        /**
         * @clientlist:
         *
-        * List of in-kernel clients. Protected by @clientlist_mutex.
+        * List of in-kernel clients. Protected by &clientlist_mutex.
         */
        struct list_head clientlist;
 
-       /** \name Memory management */
-       /*@{ */
-       struct list_head maplist;       /**< Linked list of regions */
-       struct drm_open_hash map_hash;  /**< User token hash table for maps */
-
-       /** \name Context handle management */
-       /*@{ */
-       struct list_head ctxlist;       /**< Linked list of context handles */
-       struct mutex ctxlist_mutex;     /**< For ctxlist */
-
-       struct idr ctx_idr;
-
-       struct list_head vmalist;       /**< List of vmas (for debugging) */
-
-       /*@} */
-
-       /** \name DMA support */
-       /*@{ */
-       struct drm_device_dma *dma;             /**< Optional pointer for DMA support */
-       /*@} */
-
-       /** \name Context support */
-       /*@{ */
-
-       __volatile__ long context_flag; /**< Context swapping flag */
-       int last_context;               /**< Last current context */
-       /*@} */
-
        /**
         * @irq_enabled:
         *
@@ -141,6 +184,10 @@ struct drm_device {
         * to true manually.
         */
        bool irq_enabled;
+
+       /**
+        * @irq: Used by the drm_irq_install() and drm_irq_unistall() helpers.
+        */
        int irq;
 
        /**
@@ -168,7 +215,16 @@ struct drm_device {
         */
        struct drm_vblank_crtc *vblank;
 
-       spinlock_t vblank_time_lock;    /**< Protects vblank count and time updates during vblank enable/disable */
+       /**
+        * @vblank_time_lock:
+        *
+        *  Protects vblank count and time updates during vblank enable/disable
+        */
+       spinlock_t vblank_time_lock;
+       /**
+        * @vbl_lock: Top-level vblank references lock, wraps the low-level
+        * @vblank_time_lock.
+        */
        spinlock_t vbl_lock;
 
        /**
@@ -184,45 +240,61 @@ struct drm_device {
         * races and imprecision over longer time periods, hence exposing a
         * hardware vblank counter is always recommended.
         *
-        * If non-zeor, &drm_crtc_funcs.get_vblank_counter must be set.
+        * This is the statically configured device wide maximum. The driver
+        * can instead choose to use a runtime configurable per-crtc value
+        * &drm_vblank_crtc.max_vblank_count, in which case @max_vblank_count
+        * must be left at zero. See drm_crtc_set_max_vblank_count() on how
+        * to use the per-crtc value.
+        *
+        * If non-zero, &drm_crtc_funcs.get_vblank_counter must be set.
         */
-       u32 max_vblank_count;           /**< size of vblank counter register */
+       u32 max_vblank_count;
+
+       /** @vblank_event_list: List of vblank events */
+       struct list_head vblank_event_list;
 
        /**
-        * List of events
+        * @event_lock:
+        *
+        * Protects @vblank_event_list and event delivery in
+        * general. See drm_send_event() and drm_send_event_locked().
         */
-       struct list_head vblank_event_list;
        spinlock_t event_lock;
 
-       /*@} */
+       /** @agp: AGP data */
+       struct drm_agp_head *agp;
 
-       struct drm_agp_head *agp;       /**< AGP data */
+       /** @pdev: PCI device structure */
+       struct pci_dev *pdev;
 
-       struct pci_dev *pdev;           /**< PCI device structure */
 #ifdef __alpha__
+       /** @hose: PCI hose, only used on ALPHA platforms. */
        struct pci_controller *hose;
 #endif
+       /** @num_crtcs: Number of CRTCs on this device */
+       unsigned int num_crtcs;
 
-       struct drm_sg_mem *sg;  /**< Scatter gather memory */
-       unsigned int num_crtcs;                  /**< Number of CRTCs on this device */
+       /** @mode_config: Current mode config */
+       struct drm_mode_config mode_config;
 
-       struct {
-               int context;
-               struct drm_hw_lock *lock;
-       } sigdata;
-
-       struct drm_local_map *agp_buffer_map;
-       unsigned int agp_buffer_token;
-
-       struct drm_mode_config mode_config;     /**< Current mode config */
-
-       /** \name GEM information */
-       /*@{ */
+       /** @object_name_lock: GEM information */
        struct mutex object_name_lock;
+
+       /** @object_name_idr: GEM information */
        struct idr object_name_idr;
+
+       /** @vma_offset_manager: GEM information */
        struct drm_vma_offset_manager *vma_offset_manager;
-       /*@} */
-       int switch_power_state;
+
+       /**
+        * @switch_power_state:
+        *
+        * Power state of the client.
+        * Used by drivers supporting the switcheroo driver.
+        * The state is maintained in the
+        * &vga_switcheroo_client_ops.set_gpu_state callback
+        */
+       enum switch_power_state switch_power_state;
 
        /**
         * @fb_helper:
@@ -231,6 +303,56 @@ struct drm_device {
         * Set by drm_fb_helper_init() and cleared by drm_fb_helper_fini().
         */
        struct drm_fb_helper *fb_helper;
+
+       /* Everything below here is for legacy driver, never use! */
+       /* private: */
+
+       /* Context handle management - linked list of context handles */
+       struct list_head ctxlist;
+
+       /* Context handle management - mutex for &ctxlist */
+       struct mutex ctxlist_mutex;
+
+       /* Context handle management */
+       struct idr ctx_idr;
+
+       /* Memory management - linked list of regions */
+       struct list_head maplist;
+
+       /* Memory management - user token hash table for maps */
+       struct drm_open_hash map_hash;
+
+       /* Context handle management - list of vmas (for debugging) */
+       struct list_head vmalist;
+
+       /* Optional pointer for DMA support */
+       struct drm_device_dma *dma;
+
+       /* Context swapping flag */
+       __volatile__ long context_flag;
+
+       /* Last current context */
+       int last_context;
+
+       /* Lock for &buf_use and a few other things. */
+       spinlock_t buf_lock;
+
+       /* Usage counter for buffers in use -- cannot alloc */
+       int buf_use;
+
+       /* Buffer allocation in progress */
+       atomic_t buf_alloc;
+
+       struct {
+               int context;
+               struct drm_hw_lock *lock;
+       } sigdata;
+
+       struct drm_local_map *agp_buffer_map;
+       unsigned int agp_buffer_token;
+
+       /* Scatter gather memory */
+       struct drm_sg_mem *sg;
 };
 
 #endif
index 5736c942c85b7d9d96707e9160d98d5dbe116cb1..c223c87ef11919cb588f63448af5e8dc81f4d063 100644 (file)
 # define DP_PSR_SETUP_TIME_SHIFT            1
 # define DP_PSR2_SU_Y_COORDINATE_REQUIRED   (1 << 4)  /* eDP 1.4a */
 # define DP_PSR2_SU_GRANULARITY_REQUIRED    (1 << 5)  /* eDP 1.4b */
+
+#define DP_PSR2_SU_X_GRANULARITY           0x072 /* eDP 1.4b */
+#define DP_PSR2_SU_Y_GRANULARITY           0x074 /* eDP 1.4b */
+
 /*
  * 0x80-0x8f describe downstream port capabilities, but there are two layouts
  * based on whether DP_DETAILED_CAP_INFO_AVAILABLE was set.  If it was not,
@@ -1365,6 +1369,13 @@ enum drm_dp_quirk {
         * to 16 bits. So will give a constant value (0x8000) for compatability.
         */
        DP_DPCD_QUIRK_CONSTANT_N,
+       /**
+        * @DP_DPCD_QUIRK_NO_PSR:
+        *
+        * The device does not support PSR even if reports that it supports or
+        * driver still need to implement proper handling for such device.
+        */
+       DP_DPCD_QUIRK_NO_PSR,
 };
 
 /**
index 59f005b419cf7c18625ca40e42ec97e29dff47a8..451d020f0137b924218967990bf7e76a62141041 100644 (file)
@@ -44,7 +44,6 @@ struct drm_dp_vcpi {
 
 /**
  * struct drm_dp_mst_port - MST port
- * @kref: reference count for this port.
  * @port_num: port number
  * @input: if this port is an input port.
  * @mcs: message capability status - DP 1.2 spec.
@@ -67,7 +66,18 @@ struct drm_dp_vcpi {
  * in the MST topology.
  */
 struct drm_dp_mst_port {
-       struct kref kref;
+       /**
+        * @topology_kref: refcount for this port's lifetime in the topology,
+        * only the DP MST helpers should need to touch this
+        */
+       struct kref topology_kref;
+
+       /**
+        * @malloc_kref: refcount for the memory allocation containing this
+        * structure. See drm_dp_mst_get_port_malloc() and
+        * drm_dp_mst_put_port_malloc().
+        */
+       struct kref malloc_kref;
 
        u8 port_num;
        bool input;
@@ -102,7 +112,6 @@ struct drm_dp_mst_port {
 
 /**
  * struct drm_dp_mst_branch - MST branch device.
- * @kref: reference count for this port.
  * @rad: Relative Address to talk to this branch device.
  * @lct: Link count total to talk to this branch device.
  * @num_ports: number of ports on the branch.
@@ -121,7 +130,19 @@ struct drm_dp_mst_port {
  * to downstream port of parent branches.
  */
 struct drm_dp_mst_branch {
-       struct kref kref;
+       /**
+        * @topology_kref: refcount for this branch device's lifetime in the
+        * topology, only the DP MST helpers should need to touch this
+        */
+       struct kref topology_kref;
+
+       /**
+        * @malloc_kref: refcount for the memory allocation containing this
+        * structure. See drm_dp_mst_get_mstb_malloc() and
+        * drm_dp_mst_put_mstb_malloc().
+        */
+       struct kref malloc_kref;
+
        u8 rad[8];
        u8 lct;
        int num_ports;
@@ -387,8 +408,6 @@ struct drm_dp_mst_topology_cbs {
        void (*register_connector)(struct drm_connector *connector);
        void (*destroy_connector)(struct drm_dp_mst_topology_mgr *mgr,
                                  struct drm_connector *connector);
-       void (*hotplug)(struct drm_dp_mst_topology_mgr *mgr);
-
 };
 
 #define DP_MAX_PAYLOAD (sizeof(unsigned long) * 8)
@@ -406,9 +425,15 @@ struct drm_dp_payload {
 
 #define to_dp_mst_topology_state(x) container_of(x, struct drm_dp_mst_topology_state, base)
 
+struct drm_dp_vcpi_allocation {
+       struct drm_dp_mst_port *port;
+       int vcpi;
+       struct list_head next;
+};
+
 struct drm_dp_mst_topology_state {
        struct drm_private_state base;
-       int avail_slots;
+       struct list_head vcpis;
        struct drm_dp_mst_topology_mgr *mgr;
 };
 
@@ -619,13 +644,115 @@ void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr);
 int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr);
 struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
                                                                    struct drm_dp_mst_topology_mgr *mgr);
-int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
-                                 struct drm_dp_mst_topology_mgr *mgr,
-                                 struct drm_dp_mst_port *port, int pbn);
-int drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state,
-                                    struct drm_dp_mst_topology_mgr *mgr,
-                                    int slots);
+int __must_check
+drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
+                             struct drm_dp_mst_topology_mgr *mgr,
+                             struct drm_dp_mst_port *port, int pbn);
+int __must_check
+drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state,
+                                struct drm_dp_mst_topology_mgr *mgr,
+                                struct drm_dp_mst_port *port);
 int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr,
                                 struct drm_dp_mst_port *port, bool power_up);
+int __must_check drm_dp_mst_atomic_check(struct drm_atomic_state *state);
+
+void drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port);
+void drm_dp_mst_put_port_malloc(struct drm_dp_mst_port *port);
+
+extern const struct drm_private_state_funcs drm_dp_mst_topology_state_funcs;
+
+/**
+ * __drm_dp_mst_state_iter_get - private atomic state iterator function for
+ * macro-internal use
+ * @state: &struct drm_atomic_state pointer
+ * @mgr: pointer to the &struct drm_dp_mst_topology_mgr iteration cursor
+ * @old_state: optional pointer to the old &struct drm_dp_mst_topology_state
+ * iteration cursor
+ * @new_state: optional pointer to the new &struct drm_dp_mst_topology_state
+ * iteration cursor
+ * @i: int iteration cursor, for macro-internal use
+ *
+ * Used by for_each_oldnew_mst_mgr_in_state(),
+ * for_each_old_mst_mgr_in_state(), and for_each_new_mst_mgr_in_state(). Don't
+ * call this directly.
+ *
+ * Returns:
+ * True if the current &struct drm_private_obj is a &struct
+ * drm_dp_mst_topology_mgr, false otherwise.
+ */
+static inline bool
+__drm_dp_mst_state_iter_get(struct drm_atomic_state *state,
+                           struct drm_dp_mst_topology_mgr **mgr,
+                           struct drm_dp_mst_topology_state **old_state,
+                           struct drm_dp_mst_topology_state **new_state,
+                           int i)
+{
+       struct __drm_private_objs_state *objs_state = &state->private_objs[i];
+
+       if (objs_state->ptr->funcs != &drm_dp_mst_topology_state_funcs)
+               return false;
+
+       *mgr = to_dp_mst_topology_mgr(objs_state->ptr);
+       if (old_state)
+               *old_state = to_dp_mst_topology_state(objs_state->old_state);
+       if (new_state)
+               *new_state = to_dp_mst_topology_state(objs_state->new_state);
+
+       return true;
+}
+
+/**
+ * for_each_oldnew_mst_mgr_in_state - iterate over all DP MST topology
+ * managers in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor
+ * @old_state: &struct drm_dp_mst_topology_state iteration cursor for the old
+ * state
+ * @new_state: &struct drm_dp_mst_topology_state iteration cursor for the new
+ * state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all DRM DP MST topology managers in an atomic update,
+ * tracking both old and new state. This is useful in places where the state
+ * delta needs to be considered, for example in atomic check functions.
+ */
+#define for_each_oldnew_mst_mgr_in_state(__state, mgr, old_state, new_state, __i) \
+       for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \
+               for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), &(old_state), &(new_state), (__i)))
+
+/**
+ * for_each_old_mst_mgr_in_state - iterate over all DP MST topology managers
+ * in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor
+ * @old_state: &struct drm_dp_mst_topology_state iteration cursor for the old
+ * state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all DRM DP MST topology managers in an atomic update,
+ * tracking only the old state. This is useful in disable functions, where we
+ * need the old state the hardware is still in.
+ */
+#define for_each_old_mst_mgr_in_state(__state, mgr, old_state, __i) \
+       for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \
+               for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), &(old_state), NULL, (__i)))
+
+/**
+ * for_each_new_mst_mgr_in_state - iterate over all DP MST topology managers
+ * in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @mgr: &struct drm_dp_mst_topology_mgr iteration cursor
+ * @new_state: &struct drm_dp_mst_topology_state iteration cursor for the new
+ * state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all DRM DP MST topology managers in an atomic update,
+ * tracking only the new state. This is useful in enable functions, where we
+ * need the new state the hardware should be in when the atomic commit
+ * operation has completed.
+ */
+#define for_each_new_mst_mgr_in_state(__state, mgr, new_state, __i) \
+       for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \
+               for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), NULL, &(new_state), (__i)))
 
 #endif
index e3c40483311569f26bac07cfbe007986860d22d0..8dc1a081fb36d112e950fbdb80444470b43bb391 100644 (file)
@@ -352,18 +352,17 @@ drm_load_edid_firmware(struct drm_connector *connector)
 
 int
 drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
-                                        const struct drm_display_mode *mode,
-                                        bool is_hdmi2_sink);
+                                        struct drm_connector *connector,
+                                        const struct drm_display_mode *mode);
 int
 drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
                                            struct drm_connector *connector,
                                            const struct drm_display_mode *mode);
 void
 drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame,
+                                  struct drm_connector *connector,
                                   const struct drm_display_mode *mode,
-                                  enum hdmi_quantization_range rgb_quant_range,
-                                  bool rgb_quant_range_selectable,
-                                  bool is_hdmi2_sink);
+                                  enum hdmi_quantization_range rgb_quant_range);
 
 /**
  * drm_eld_mnl - Get ELD monitor name length in bytes.
@@ -471,7 +470,6 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match);
 enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code);
 bool drm_detect_hdmi_monitor(struct edid *edid);
 bool drm_detect_monitor_audio(struct edid *edid);
-bool drm_rgb_quant_range_selectable(struct edid *edid);
 enum hdmi_quantization_range
 drm_default_rgb_quant_range(const struct drm_display_mode *mode);
 int drm_add_modes_noedid(struct drm_connector *connector,
index 1107b4b1c599f4ee962ed444670d73ee2d210046..a09864f6d68489f09101c4395a8a7eaee10d9ae0 100644 (file)
@@ -27,7 +27,6 @@
 #ifndef __DRM_ENCODER_SLAVE_H__
 #define __DRM_ENCODER_SLAVE_H__
 
-#include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_encoder.h>
 
index 8dbbe1eece1bd28eb18e4ee82788b8ad840b670f..4becb09975a457124489b9d6933b5e4829adc6b0 100644 (file)
@@ -2,31 +2,9 @@
 #ifndef __DRM_FB_CMA_HELPER_H__
 #define __DRM_FB_CMA_HELPER_H__
 
-struct drm_fbdev_cma;
-struct drm_gem_cma_object;
-
-struct drm_fb_helper_surface_size;
-struct drm_framebuffer_funcs;
-struct drm_fb_helper_funcs;
 struct drm_framebuffer;
-struct drm_fb_helper;
-struct drm_device;
-struct drm_file;
-struct drm_mode_fb_cmd2;
-struct drm_plane;
 struct drm_plane_state;
 
-int drm_fb_cma_fbdev_init(struct drm_device *dev, unsigned int preferred_bpp,
-                         unsigned int max_conn_count);
-void drm_fb_cma_fbdev_fini(struct drm_device *dev);
-
-struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
-       unsigned int preferred_bpp, unsigned int max_conn_count);
-void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma);
-
-void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma);
-void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma);
-
 struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
        unsigned int plane);
 
index 84ac79219e4ce64ccf062931b5e323b5cbb789e7..6710b612e2f6f7050eab3885668da34822ef0579 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <linux/types.h>
 #include <linux/completion.h>
+#include <linux/idr.h>
 
 #include <uapi/drm/drm.h>
 
index bcb389f04618a25a924637e0ccbb4d4f7af340c7..b3d9d88ab2902e360b6adff982be9e5a438e7ba9 100644 (file)
@@ -143,6 +143,123 @@ struct drm_format_name_buf {
        char str[32];
 };
 
+/**
+ * drm_format_info_is_yuv_packed - check that the format info matches a YUV
+ * format with data laid in a single plane
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a packed YUV format.
+ */
+static inline bool
+drm_format_info_is_yuv_packed(const struct drm_format_info *info)
+{
+       return info->is_yuv && info->num_planes == 1;
+}
+
+/**
+ * drm_format_info_is_yuv_semiplanar - check that the format info matches a YUV
+ * format with data laid in two planes (luminance and chrominance)
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a semiplanar YUV format.
+ */
+static inline bool
+drm_format_info_is_yuv_semiplanar(const struct drm_format_info *info)
+{
+       return info->is_yuv && info->num_planes == 2;
+}
+
+/**
+ * drm_format_info_is_yuv_planar - check that the format info matches a YUV
+ * format with data laid in three planes (one for each YUV component)
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a planar YUV format.
+ */
+static inline bool
+drm_format_info_is_yuv_planar(const struct drm_format_info *info)
+{
+       return info->is_yuv && info->num_planes == 3;
+}
+
+/**
+ * drm_format_info_is_yuv_sampling_410 - check that the format info matches a
+ * YUV format with 4:1:0 sub-sampling
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a YUV format with 4:1:0
+ * sub-sampling.
+ */
+static inline bool
+drm_format_info_is_yuv_sampling_410(const struct drm_format_info *info)
+{
+       return info->is_yuv && info->hsub == 4 && info->vsub == 4;
+}
+
+/**
+ * drm_format_info_is_yuv_sampling_411 - check that the format info matches a
+ * YUV format with 4:1:1 sub-sampling
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a YUV format with 4:1:1
+ * sub-sampling.
+ */
+static inline bool
+drm_format_info_is_yuv_sampling_411(const struct drm_format_info *info)
+{
+       return info->is_yuv && info->hsub == 4 && info->vsub == 1;
+}
+
+/**
+ * drm_format_info_is_yuv_sampling_420 - check that the format info matches a
+ * YUV format with 4:2:0 sub-sampling
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a YUV format with 4:2:0
+ * sub-sampling.
+ */
+static inline bool
+drm_format_info_is_yuv_sampling_420(const struct drm_format_info *info)
+{
+       return info->is_yuv && info->hsub == 2 && info->vsub == 2;
+}
+
+/**
+ * drm_format_info_is_yuv_sampling_422 - check that the format info matches a
+ * YUV format with 4:2:2 sub-sampling
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a YUV format with 4:2:2
+ * sub-sampling.
+ */
+static inline bool
+drm_format_info_is_yuv_sampling_422(const struct drm_format_info *info)
+{
+       return info->is_yuv && info->hsub == 2 && info->vsub == 1;
+}
+
+/**
+ * drm_format_info_is_yuv_sampling_444 - check that the format info matches a
+ * YUV format with 4:4:4 sub-sampling
+ * @info: format info
+ *
+ * Returns:
+ * A boolean indicating whether the format info matches a YUV format with 4:4:4
+ * sub-sampling.
+ */
+static inline bool
+drm_format_info_is_yuv_sampling_444(const struct drm_format_info *info)
+{
+       return info->is_yuv && info->hsub == 1 && info->vsub == 1;
+}
+
 const struct drm_format_info *__drm_format_info(u32 format);
 const struct drm_format_info *drm_format_info(u32 format);
 const struct drm_format_info *
index c94acedfb08ebf4efcd3adba8365d64860905012..f0b34c977ec5765c54c4c653ce93e95325f68950 100644 (file)
 #ifndef __DRM_FRAMEBUFFER_H__
 #define __DRM_FRAMEBUFFER_H__
 
-#include <linux/list.h>
 #include <linux/ctype.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+
 #include <drm/drm_mode_object.h>
 
-struct drm_framebuffer;
-struct drm_file;
+struct drm_clip_rect;
 struct drm_device;
+struct drm_file;
+struct drm_framebuffer;
+struct drm_gem_object;
 
 /**
  * struct drm_framebuffer_funcs - framebuffer hooks
index 07c504940ba16c169f32c58a6d25b82ae900c758..947ac95eb24a98dffb436ebffba9f2de2dfab7d4 100644 (file)
@@ -2,9 +2,12 @@
 #ifndef __DRM_GEM_CMA_HELPER_H__
 #define __DRM_GEM_CMA_HELPER_H__
 
-#include <drm/drmP.h>
+#include <drm/drm_file.h>
+#include <drm/drm_ioctl.h>
 #include <drm/drm_gem.h>
 
+struct drm_mode_create_dumb;
+
 /**
  * struct drm_gem_cma_object - GEM object backed by CMA memory allocations
  * @base: base GEM object
index a38de7eb55b49fde782b78214dfaa804052bca08..7f307e834eef3a66739cf3b3920dd14ffccfb66b 100644 (file)
@@ -25,6 +25,9 @@ drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file,
 struct drm_framebuffer *
 drm_gem_fb_create(struct drm_device *dev, struct drm_file *file,
                  const struct drm_mode_fb_cmd2 *mode_cmd);
+struct drm_framebuffer *
+drm_gem_fb_create_with_dirty(struct drm_device *dev, struct drm_file *file,
+                            const struct drm_mode_fb_cmd2 *mode_cmd);
 
 int drm_gem_fb_prepare_fb(struct drm_plane *plane,
                          struct drm_plane_state *state);
index a6de09c5e47f500b1c93b5302fc3a00fef267988..d6dfef8cff6a4996dbe9b90c50d9d75913a27a40 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef _DRM_HDCP_H_INCLUDED_
 #define _DRM_HDCP_H_INCLUDED_
 
+#include <linux/types.h>
+
 /* Period of hdcp checks (to ensure we're still authenticated) */
 #define DRM_HDCP_CHECK_PERIOD_MS               (128 * 16)
 
index 8fad66f88e4f3559b4aae78666cc6abaca950499..3e99ab69c122b9f3e29f4737e592a929bffeba8a 100644 (file)
@@ -2,6 +2,9 @@
 #define __DRM_DRM_LEGACY_H__
 
 #include <drm/drm_auth.h>
+#include <drm/drm_hashtab.h>
+
+struct drm_device;
 
 /*
  * Legacy driver interfaces for the Direct Rendering Manager
@@ -156,6 +159,7 @@ struct drm_map_list {
 int drm_legacy_addmap(struct drm_device *d, resource_size_t offset,
                      unsigned int size, enum drm_map_type type,
                      enum drm_map_flags flags, struct drm_local_map **map_p);
+struct drm_local_map *drm_legacy_findmap(struct drm_device *dev, unsigned int token);
 void drm_legacy_rmmap(struct drm_device *d, struct drm_local_map *map);
 int drm_legacy_rmmap_locked(struct drm_device *d, struct drm_local_map *map);
 void drm_legacy_master_rmmaps(struct drm_device *dev,
@@ -194,14 +198,4 @@ void drm_legacy_ioremap(struct drm_local_map *map, struct drm_device *dev);
 void drm_legacy_ioremap_wc(struct drm_local_map *map, struct drm_device *dev);
 void drm_legacy_ioremapfree(struct drm_local_map *map, struct drm_device *dev);
 
-static inline struct drm_local_map *drm_legacy_findmap(struct drm_device *dev,
-                                                      unsigned int token)
-{
-       struct drm_map_list *_entry;
-       list_for_each_entry(_entry, &dev->maplist, head)
-           if (_entry->user_token == token)
-               return _entry->map;
-       return NULL;
-}
-
 #endif /* __DRM_DRM_LEGACY_H__ */
index 572274ccbec7426a26083fd5f8a951b7ff8a2dd2..1e6cb885994d0d60ccbdbff15f9c5c6010371586 100644 (file)
@@ -391,18 +391,18 @@ struct drm_mode_config {
        /**
         * @idr_mutex:
         *
-        * Mutex for KMS ID allocation and management. Protects both @crtc_idr
+        * Mutex for KMS ID allocation and management. Protects both @object_idr
         * and @tile_idr.
         */
        struct mutex idr_mutex;
 
        /**
-        * @crtc_idr:
+        * @object_idr:
         *
         * Main KMS ID tracking object. Use this idr for all IDs, fb, crtc,
         * connector, modes - just makes life easier to have only one.
         */
-       struct idr crtc_idr;
+       struct idr object_idr;
 
        /**
         * @tile_idr:
@@ -512,6 +512,15 @@ struct drm_mode_config {
         */
        struct list_head property_list;
 
+       /**
+        * @privobj_list:
+        *
+        * List of private objects linked with &drm_private_obj.head. This is
+        * invariant over the lifetime of a device and hence doesn't need any
+        * locks.
+        */
+       struct list_head privobj_list;
+
        int min_width, min_height;
        int max_width, max_height;
        const struct drm_mode_config_funcs *funcs;
@@ -688,22 +697,22 @@ struct drm_mode_config {
        struct drm_property *tv_mode_property;
        /**
         * @tv_left_margin_property: Optional TV property to set the left
-        * margin.
+        * margin (expressed in pixels).
         */
        struct drm_property *tv_left_margin_property;
        /**
         * @tv_right_margin_property: Optional TV property to set the right
-        * margin.
+        * margin (expressed in pixels).
         */
        struct drm_property *tv_right_margin_property;
        /**
         * @tv_top_margin_property: Optional TV property to set the right
-        * margin.
+        * margin (expressed in pixels).
         */
        struct drm_property *tv_top_margin_property;
        /**
         * @tv_bottom_margin_property: Optional TV property to set the right
-        * margin.
+        * margin (expressed in pixels).
         */
        struct drm_property *tv_bottom_margin_property;
        /**
index baded65144563b219657f0082b974a8fa6faf64f..be4fed97e7273b481ba05e28d53d66b755c673f4 100644 (file)
@@ -136,8 +136,7 @@ enum drm_mode_status {
        .hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \
        .htotal = (ht), .hskew = (hsk), .vdisplay = (vd), \
        .vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), \
-       .vscan = (vs), .flags = (f), \
-       .base.type = DRM_MODE_OBJECT_MODE
+       .vscan = (vs), .flags = (f)
 
 #define CRTC_INTERLACE_HALVE_V (1 << 0) /* halve V values for interlacing */
 #define CRTC_STEREO_DOUBLE     (1 << 1) /* adjust timings for stereo modes */
@@ -213,20 +212,6 @@ struct drm_display_mode {
         */
        struct list_head head;
 
-       /**
-        * @base:
-        *
-        * A display mode is a normal modeset object, possibly including public
-        * userspace id.
-        *
-        * FIXME:
-        *
-        * This can probably be removed since the entire concept of userspace
-        * managing modes explicitly has never landed in upstream kernel mode
-        * setting support.
-        */
-       struct drm_mode_object base;
-
        /**
         * @name:
         *
@@ -429,14 +414,14 @@ struct drm_display_mode {
 /**
  * DRM_MODE_FMT - printf string for &struct drm_display_mode
  */
-#define DRM_MODE_FMT    "%d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x"
+#define DRM_MODE_FMT    "\"%s\": %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x"
 
 /**
  * DRM_MODE_ARG - printf arguments for &struct drm_display_mode
  * @m: display mode
  */
 #define DRM_MODE_ARG(m) \
-       (m)->base.id, (m)->name, (m)->vrefresh, (m)->clock, \
+       (m)->name, (m)->vrefresh, (m)->clock, \
        (m)->hdisplay, (m)->hsync_start, (m)->hsync_end, (m)->htotal, \
        (m)->vdisplay, (m)->vsync_start, (m)->vsync_end, (m)->vtotal, \
        (m)->type, (m)->flags
index b1fe921f8e8f23132f1411e84a44a13e97411f69..0311c9fdbd2f2107ba39cf40dd64a0f97641b416 100644 (file)
@@ -26,9 +26,9 @@
 #ifndef __DRM_SYNCOBJ_H__
 #define __DRM_SYNCOBJ_H__
 
-#include "linux/dma-fence.h"
+#include <linux/dma-fence.h>
 
-struct drm_syncobj_cb;
+struct drm_file;
 
 /**
  * struct drm_syncobj - sync object.
@@ -62,25 +62,6 @@ struct drm_syncobj {
        struct file *file;
 };
 
-typedef void (*drm_syncobj_func_t)(struct drm_syncobj *syncobj,
-                                  struct drm_syncobj_cb *cb);
-
-/**
- * struct drm_syncobj_cb - callback for drm_syncobj_add_callback
- * @node: used by drm_syncob_add_callback to append this struct to
- *       &drm_syncobj.cb_list
- * @func: drm_syncobj_func_t to call
- *
- * This struct will be initialized by drm_syncobj_add_callback, additional
- * data can be passed along by embedding drm_syncobj_cb in another struct.
- * The callback will get called the next time drm_syncobj_replace_fence is
- * called.
- */
-struct drm_syncobj_cb {
-       struct list_head node;
-       drm_syncobj_func_t func;
-};
-
 void drm_syncobj_free(struct kref *kref);
 
 /**
index 88abdca89baadb91e0a17b3ee40cf9bd52f93e5c..07b8e9f04599801434041b7a23e5f914bbaa3a10 100644 (file)
 #ifndef _DRM_UTIL_H_
 #define _DRM_UTIL_H_
 
-/* helper for handling conditionals in various for_each macros */
+/**
+ * DOC: drm utils
+ *
+ * Macros and inline functions that does not naturally belong in other places
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kgdb.h>
+#include <linux/preempt.h>
+#include <linux/smp.h>
+
+/*
+ * Use EXPORT_SYMBOL_FOR_TESTS_ONLY() for functions that shall
+ * only be visible for drmselftests.
+ */
+#if defined(CONFIG_DRM_DEBUG_SELFTEST_MODULE)
+#define EXPORT_SYMBOL_FOR_TESTS_ONLY(x) EXPORT_SYMBOL(x)
+#else
+#define EXPORT_SYMBOL_FOR_TESTS_ONLY(x)
+#endif
+
+/**
+ * for_each_if - helper for handling conditionals in various for_each macros
+ * @condition: The condition to check
+ *
+ * Typical use::
+ *
+ *     #define for_each_foo_bar(x, y) \'
+ *             list_for_each_entry(x, y->list, head) \'
+ *                     for_each_if(x->something == SOMETHING)
+ *
+ * The for_each_if() macro makes the use of for_each_foo_bar() less error
+ * prone.
+ */
 #define for_each_if(condition) if (!(condition)) {} else
 
+/**
+ * drm_can_sleep - returns true if currently okay to sleep
+ *
+ * This function shall not be used in new code.
+ * The check for running in atomic context may not work - see linux/preempt.h.
+ *
+ * FIXME: All users of drm_can_sleep should be removed (see todo.rst)
+ *
+ * Returns:
+ * False if kgdb is active, we are in atomic context or irqs are disabled.
+ */
+static inline bool drm_can_sleep(void)
+{
+       if (in_atomic() || in_dbg_master() || irqs_disabled())
+               return false;
+       return true;
+}
+
 #endif
index 6ad9630d4f48e04c991a68753e580c7f173e51d9..e528bb2f659d95296062c8206dc1b3f2bad29241 100644 (file)
@@ -128,6 +128,26 @@ struct drm_vblank_crtc {
         * @last: Protected by &drm_device.vbl_lock, used for wraparound handling.
         */
        u32 last;
+       /**
+        * @max_vblank_count:
+        *
+        * Maximum value of the vblank registers for this crtc. This value +1
+        * will result in a wrap-around of the vblank register. It is used
+        * by the vblank core to handle wrap-arounds.
+        *
+        * If set to zero the vblank core will try to guess the elapsed vblanks
+        * between times when the vblank interrupt is disabled through
+        * high-precision timestamps. That approach is suffering from small
+        * races and imprecision over longer time periods, hence exposing a
+        * hardware vblank counter is always recommended.
+        *
+        * This is the runtime configurable per-crtc maximum set through
+        * drm_crtc_set_max_vblank_count(). If this is used the driver
+        * must leave the device wide &drm_device.max_vblank_count at zero.
+        *
+        * If non-zero, &drm_crtc_funcs.get_vblank_counter must be set.
+        */
+       u32 max_vblank_count;
        /**
         * @inmodeset: Tracks whether the vblank is disabled due to a modeset.
         * For legacy driver bit 2 additionally tracks whether an additional
@@ -206,4 +226,6 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
 void drm_calc_timestamping_constants(struct drm_crtc *crtc,
                                     const struct drm_display_mode *mode);
 wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc);
+void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
+                                  u32 max_vblank_count);
 #endif
index 47e19796c45087f76664b161d5e1a9b654ed9f2b..0daca4d8dad9819f788c7d2116c54c53aefc6541 100644 (file)
@@ -137,10 +137,6 @@ struct drm_sched_fence {
          */
        struct dma_fence                finished;
 
-        /**
-         * @cb: the callback for the parent fence below.
-         */
-       struct dma_fence_cb             cb;
         /**
          * @parent: the fence returned by &drm_sched_backend_ops.run_job
          * when scheduling the job on hardware. We signal the
@@ -181,6 +177,7 @@ struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f);
  *         be scheduled further.
  * @s_priority: the priority of the job.
  * @entity: the entity to which this job belongs.
+ * @cb: the callback for the parent fence in s_fence.
  *
  * A job is created by the driver using drm_sched_job_init(), and
  * should call drm_sched_entity_push_job() once it wants the scheduler
@@ -197,6 +194,7 @@ struct drm_sched_job {
        atomic_t                        karma;
        enum drm_sched_priority         s_priority;
        struct drm_sched_entity  *entity;
+       struct dma_fence_cb             cb;
 };
 
 static inline bool drm_sched_invalidate_job(struct drm_sched_job *s_job,
@@ -298,9 +296,10 @@ int drm_sched_job_init(struct drm_sched_job *job,
                       void *owner);
 void drm_sched_job_cleanup(struct drm_sched_job *job);
 void drm_sched_wakeup(struct drm_gpu_scheduler *sched);
-void drm_sched_hw_job_reset(struct drm_gpu_scheduler *sched,
-                           struct drm_sched_job *job);
-void drm_sched_job_recovery(struct drm_gpu_scheduler *sched);
+void drm_sched_stop(struct drm_gpu_scheduler *sched);
+void drm_sched_start(struct drm_gpu_scheduler *sched, bool full_recovery);
+void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched);
+void drm_sched_increase_karma(struct drm_sched_job *bad);
 bool drm_sched_dependency_optimized(struct dma_fence* fence,
                                    struct drm_sched_entity *entity);
 void drm_sched_fault(struct drm_gpu_scheduler *sched);
index 192667144693a0ab3adb7ae12d04a420b7567b37..df72be7e8b883c56917999b0da9440b19d409052 100644 (file)
        INTEL_VGA_DEVICE(0x8A51, info), \
        INTEL_VGA_DEVICE(0x8A5C, info), \
        INTEL_VGA_DEVICE(0x8A5D, info), \
+       INTEL_VGA_DEVICE(0x8A59, info), \
+       INTEL_VGA_DEVICE(0x8A58, info), \
        INTEL_VGA_DEVICE(0x8A52, info), \
        INTEL_VGA_DEVICE(0x8A5A, info), \
        INTEL_VGA_DEVICE(0x8A5B, info), \
+       INTEL_VGA_DEVICE(0x8A57, info), \
+       INTEL_VGA_DEVICE(0x8A56, info), \
        INTEL_VGA_DEVICE(0x8A71, info), \
        INTEL_VGA_DEVICE(0x8A70, info)
 
index 2324c84a25c02eca5d26e0f639fe32beb9979cfc..71d81923e6b06ca1614ac7188c584a62ba4d7bba 100644 (file)
@@ -4,6 +4,9 @@
 #ifndef _DRM_INTEL_GTT_H
 #define        _DRM_INTEL_GTT_H
 
+#include <linux/agp_backend.h>
+#include <linux/kernel.h>
+
 void intel_gtt_get(u64 *gtt_total,
                   phys_addr_t *mappable_base,
                   resource_size_t *mappable_end);
index b8ba5886198678b9fd490a8794e8c794fe47bd47..f4ec2834bc229ba55939ea8a3a64aeb866536d2d 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <drm/tinydrm/tinydrm.h>
 
+struct drm_rect;
 struct spi_device;
 struct gpio_desc;
 struct regulator;
@@ -67,6 +68,8 @@ int mipi_dbi_init(struct device *dev, struct mipi_dbi *mipi,
                  const struct drm_simple_display_pipe_funcs *pipe_funcs,
                  struct drm_driver *driver,
                  const struct drm_display_mode *mode, unsigned int rotation);
+void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe,
+                         struct drm_plane_state *old_state);
 void mipi_dbi_enable_flush(struct mipi_dbi *mipi,
                           struct drm_crtc_state *crtc_state,
                           struct drm_plane_state *plan_state);
@@ -80,7 +83,7 @@ u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len);
 int mipi_dbi_command_read(struct mipi_dbi *mipi, u8 cmd, u8 *val);
 int mipi_dbi_command_buf(struct mipi_dbi *mipi, u8 cmd, u8 *data, size_t len);
 int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
-                     struct drm_clip_rect *clip, bool swap);
+                     struct drm_rect *clip, bool swap);
 /**
  * mipi_dbi_command - MIPI DCS command with optional parameter(s)
  * @mipi: MIPI structure
index 5b96f0b12c8cefb76554abf8faf281a5689634e5..f0d598789e4d34adbd461215c6782df6337735ae 100644 (file)
@@ -11,8 +11,8 @@
 #define __LINUX_TINYDRM_HELPERS_H
 
 struct backlight_device;
-struct tinydrm_device;
-struct drm_clip_rect;
+struct drm_framebuffer;
+struct drm_rect;
 struct spi_transfer;
 struct spi_message;
 struct spi_device;
@@ -33,23 +33,15 @@ static inline bool tinydrm_machine_little_endian(void)
 #endif
 }
 
-bool tinydrm_merge_clips(struct drm_clip_rect *dst,
-                        struct drm_clip_rect *src, unsigned int num_clips,
-                        unsigned int flags, u32 max_width, u32 max_height);
-int tinydrm_fb_dirty(struct drm_framebuffer *fb,
-                    struct drm_file *file_priv,
-                    unsigned int flags, unsigned int color,
-                    struct drm_clip_rect *clips,
-                    unsigned int num_clips);
 void tinydrm_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb,
-                   struct drm_clip_rect *clip);
+                   struct drm_rect *clip);
 void tinydrm_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb,
-                   struct drm_clip_rect *clip);
+                   struct drm_rect *clip);
 void tinydrm_xrgb8888_to_rgb565(u16 *dst, void *vaddr,
                                struct drm_framebuffer *fb,
-                               struct drm_clip_rect *clip, bool swap);
+                               struct drm_rect *clip, bool swap);
 void tinydrm_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb,
-                              struct drm_clip_rect *clip);
+                              struct drm_rect *clip);
 
 size_t tinydrm_spi_max_transfer_size(struct spi_device *spi, size_t max_len);
 bool tinydrm_spi_bpw_supported(struct spi_device *spi, u8 bpw);
index 448aa5ea4722da2007fcfe8ee79855ccb22bb6ef..5621688edcc0aec7f9f23fd4ab60886a45502c8b 100644 (file)
 #ifndef __LINUX_TINYDRM_H
 #define __LINUX_TINYDRM_H
 
-#include <linux/mutex.h>
 #include <drm/drm_simple_kms_helper.h>
 
-struct drm_clip_rect;
 struct drm_driver;
-struct drm_file;
-struct drm_framebuffer;
-struct drm_framebuffer_funcs;
 
 /**
  * struct tinydrm_device - tinydrm device
@@ -32,24 +27,6 @@ struct tinydrm_device {
         * @pipe: Display pipe structure
         */
        struct drm_simple_display_pipe pipe;
-
-       /**
-        * @dirty_lock: Serializes framebuffer flushing
-        */
-       struct mutex dirty_lock;
-
-       /**
-        * @fb_funcs: Framebuffer functions used when creating framebuffers
-        */
-       const struct drm_framebuffer_funcs *fb_funcs;
-
-       /**
-        * @fb_dirty: Framebuffer dirty callback
-        */
-       int (*fb_dirty)(struct drm_framebuffer *framebuffer,
-                       struct drm_file *file_priv, unsigned flags,
-                       unsigned color, struct drm_clip_rect *clips,
-                       unsigned num_clips);
 };
 
 static inline struct tinydrm_device *
@@ -82,13 +59,10 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe)
        .clock = 1 /* pass validation */
 
 int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
-                     const struct drm_framebuffer_funcs *fb_funcs,
                      struct drm_driver *driver);
 int devm_tinydrm_register(struct tinydrm_device *tdev);
 void tinydrm_shutdown(struct tinydrm_device *tdev);
 
-void tinydrm_display_pipe_update(struct drm_simple_display_pipe *pipe,
-                                struct drm_plane_state *old_state);
 int
 tinydrm_display_pipe_init(struct tinydrm_device *tdev,
                          const struct drm_simple_display_pipe_funcs *funcs,
index 1021106438b2a581c9ba642caf68bac2411f7694..15829b24277c8eb0b99d0d4c26f7a8560d9cd526 100644 (file)
@@ -381,6 +381,15 @@ struct ttm_bo_driver {
         */
        int (*access_memory)(struct ttm_buffer_object *bo, unsigned long offset,
                             void *buf, int len, int write);
+
+       /**
+        * struct ttm_bo_driver member del_from_lru_notify
+        *
+        * @bo: the buffer object deleted from lru
+        *
+        * notify driver that a BO was deleted from LRU.
+        */
+       void (*del_from_lru_notify)(struct ttm_buffer_object *bo);
 };
 
 /**
index bc8940ca280dc74c36c706dc6d7c831a39381cc4..c0ff417b477063d50eb7e168679843001a122efe 100644 (file)
@@ -40,6 +40,7 @@ struct dma_fence_array_cb {
  * @num_fences: number of fences in the array
  * @num_pending: fences in the array still pending
  * @fences: array of the fences
+ * @work: internal irq_work function
  */
 struct dma_fence_array {
        struct dma_fence base;
index 999e4b1044103fb3e9c0e1e041fb394be58043ca..6b788467b2e3b650d4688f036f5e28a90fea8938 100644 (file)
@@ -77,7 +77,7 @@ struct dma_fence {
        struct list_head cb_list;
        spinlock_t *lock;
        u64 context;
-       unsigned seqno;
+       u64 seqno;
        unsigned long flags;
        ktime_t timestamp;
        int error;
@@ -244,7 +244,7 @@ struct dma_fence_ops {
 };
 
 void dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops,
-                   spinlock_t *lock, u64 context, unsigned seqno);
+                   spinlock_t *lock, u64 context, u64 seqno);
 
 void dma_fence_release(struct kref *kref);
 void dma_fence_free(struct dma_fence *fence);
@@ -414,9 +414,17 @@ dma_fence_is_signaled(struct dma_fence *fence)
  * Returns true if f1 is chronologically later than f2. Both fences must be
  * from the same context, since a seqno is not common across contexts.
  */
-static inline bool __dma_fence_is_later(u32 f1, u32 f2)
+static inline bool __dma_fence_is_later(u64 f1, u64 f2)
 {
-       return (int)(f1 - f2) > 0;
+       /* This is for backward compatibility with drivers which can only handle
+        * 32bit sequence numbers. Use a 64bit compare when any of the higher
+        * bits are none zero, otherwise use a 32bit compare with wrap around
+        * handling.
+        */
+       if (upper_32_bits(f1) || upper_32_bits(f2))
+               return f1 > f2;
+
+       return (int)(lower_32_bits(f1) - lower_32_bits(f2)) > 0;
 }
 
 /**
@@ -548,21 +556,21 @@ u64 dma_fence_context_alloc(unsigned num);
        do {                                                            \
                struct dma_fence *__ff = (f);                           \
                if (IS_ENABLED(CONFIG_DMA_FENCE_TRACE))                 \
-                       pr_info("f %llu#%u: " fmt,                      \
+                       pr_info("f %llu#%llu: " fmt,                    \
                                __ff->context, __ff->seqno, ##args);    \
        } while (0)
 
 #define DMA_FENCE_WARN(f, fmt, args...) \
        do {                                                            \
                struct dma_fence *__ff = (f);                           \
-               pr_warn("f %llu#%u: " fmt, __ff->context, __ff->seqno,  \
+               pr_warn("f %llu#%llu: " fmt, __ff->context, __ff->seqno,\
                         ##args);                                       \
        } while (0)
 
 #define DMA_FENCE_ERR(f, fmt, args...) \
        do {                                                            \
                struct dma_fence *__ff = (f);                           \
-               pr_err("f %llu#%u: " fmt, __ff->context, __ff->seqno,   \
+               pr_err("f %llu#%llu: " fmt, __ff->context, __ff->seqno, \
                        ##args);                                        \
        } while (0)
 
index ed1dfba5e5f9e64eabb6c70fa837ece75cbf463f..bfecd6bd499057e29962aefa4ec74a8ff2f3273c 100644 (file)
@@ -26,4 +26,7 @@ struct intel_soc_pmic {
        struct device *dev;
 };
 
+int intel_soc_pmic_exec_mipi_pmic_seq_element(u16 i2c_address, u32 reg_address,
+                                             u32 value, u32 mask);
+
 #endif /* __INTEL_SOC_PMIC_H__ */
index df014ede4e574ad431acbebb444c644fc4b9dcd1..93a341d278a67406168864bf673c0cb7a5fdc5bf 100644 (file)
@@ -238,6 +238,8 @@ extern "C" {
 #define DRM_FORMAT_MOD_VENDOR_VIVANTE 0x06
 #define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07
 #define DRM_FORMAT_MOD_VENDOR_ARM     0x08
+#define DRM_FORMAT_MOD_VENDOR_ALLWINNER 0x09
+
 /* add more to the end as needed */
 
 #define DRM_FORMAT_RESERVED          ((1ULL << 56) - 1)
@@ -584,10 +586,18 @@ extern "C" {
  * Indicates the superblock size(s) used for the AFBC buffer. The buffer
  * size (in pixels) must be aligned to a multiple of the superblock size.
  * Four lowest significant bits(LSBs) are reserved for block size.
+ *
+ * Where one superblock size is specified, it applies to all planes of the
+ * buffer (e.g. 16x16, 32x8). When multiple superblock sizes are specified,
+ * the first applies to the Luma plane and the second applies to the Chroma
+ * plane(s). e.g. (32x8_64x4 means 32x8 Luma, with 64x4 Chroma).
+ * Multiple superblock sizes are only valid for multi-plane YCbCr formats.
  */
 #define AFBC_FORMAT_MOD_BLOCK_SIZE_MASK      0xf
 #define AFBC_FORMAT_MOD_BLOCK_SIZE_16x16     (1ULL)
 #define AFBC_FORMAT_MOD_BLOCK_SIZE_32x8      (2ULL)
+#define AFBC_FORMAT_MOD_BLOCK_SIZE_64x4      (3ULL)
+#define AFBC_FORMAT_MOD_BLOCK_SIZE_32x8_64x4 (4ULL)
 
 /*
  * AFBC lossless colorspace transform
@@ -647,6 +657,35 @@ extern "C" {
  */
 #define AFBC_FORMAT_MOD_SC      (1ULL <<  9)
 
+/*
+ * AFBC double-buffer
+ *
+ * Indicates that the buffer is allocated in a layout safe for front-buffer
+ * rendering.
+ */
+#define AFBC_FORMAT_MOD_DB      (1ULL << 10)
+
+/*
+ * AFBC buffer content hints
+ *
+ * Indicates that the buffer includes per-superblock content hints.
+ */
+#define AFBC_FORMAT_MOD_BCH     (1ULL << 11)
+
+/*
+ * Allwinner tiled modifier
+ *
+ * This tiling mode is implemented by the VPU found on all Allwinner platforms,
+ * codenamed sunxi. It is associated with a YUV format that uses either 2 or 3
+ * planes.
+ *
+ * With this tiling, the luminance samples are disposed in tiles representing
+ * 32x32 pixels and the chrominance samples in tiles representing 32x64 pixels.
+ * The pixel order in each tile is linear and the tiles are disposed linearly,
+ * both in row-major order.
+ */
+#define DRM_FORMAT_MOD_ALLWINNER_TILED fourcc_mod_code(ALLWINNER, 1)
+
 #if defined(__cplusplus)
 }
 #endif
index 35c7d813c66e297d3814710d7bfddbf05b2c346c..ea70669d2138389776fbaf653674c02d14a1a3fd 100644 (file)
@@ -52,6 +52,14 @@ extern "C" {
  *
  * This asks the kernel to have the GPU execute an optional binner
  * command list, and a render command list.
+ *
+ * The L1T, slice, L2C, L2T, and GCA caches will be flushed before
+ * each CL executes.  The VCD cache should be flushed (if necessary)
+ * by the submitted CLs.  The TLB writes are guaranteed to have been
+ * flushed by the time the render done IRQ happens, which is the
+ * trigger for out_sync.  Any dirtying of cachelines by the job (only
+ * possible using TMU writes) must be flushed by the caller using the
+ * CL's cache flush commands.
  */
 struct drm_v3d_submit_cl {
        /* Pointer to the binner command list.