]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge tag 'drm-misc-next-2019-10-24-2' of git://anongit.freedesktop.org/drm/drm-misc...
authorDave Airlie <airlied@redhat.com>
Tue, 29 Oct 2019 20:10:59 +0000 (06:10 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 29 Oct 2019 20:11:47 +0000 (06:11 +1000)
drm-misc-next for 5.5:

UAPI Changes:
-syncobj: allow querying the last submitted timeline value (David)
-fourcc: explicitly defineDRM_FORMAT_BIG_ENDIAN as unsigned (Adam)
-omap: revert the OMAP_BO_* flags that were added -- no userspace (Sean)

Cross-subsystem Changes:
-MAINTAINERS: add Mihail as komeda co-maintainer (Mihail)

Core Changes:
-edid: a few cleanups, add AVI infoframe bar info (Ville)
-todo: remove i915 device_link item and add difficulty levels (Daniel)
-dp_helpers: add a few new helpers to parse dpcd (Thierry)

Driver Changes:
-gma500: fix a few memory disclosure leaks (Kangjie)
-qxl: convert to use the new drm_gem_object_funcs.mmap (Gerd)
-various: open code dp_link helpers in preparation for helper removal (Thierry)

Cc: Chunming Zhou <david1.zhou@amd.com>
Cc: Adam Jackson <ajax@redhat.com>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Kangjie Lu <kjlu@umn.edu>
Cc: Mihail Atanassov <mihail.atanassov@arm.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Thierry Reding <treding@nvidia.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Sean Paul <sean@poorly.run>
Link: https://patchwork.freedesktop.org/patch/msgid/20191024155535.GA10294@art_vandelay
361 files changed:
Documentation/gpu/amdgpu.rst
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_arcturus.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h
drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
drivers/gpu/drm/amd/amdgpu/amdgpu_job.h
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c [new file with mode: 0644]
drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h
drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.c [new file with mode: 0644]
drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h [new file with mode: 0644]
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.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_ras.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h
drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c [new file with mode: 0644]
drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
drivers/gpu/drm/amd/amdgpu/arct_reg_init.c
drivers/gpu/drm/amd/amdgpu/cik.c
drivers/gpu/drm/amd/amdgpu/cik.h
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/df_v1_7.c
drivers/gpu/drm/amd/amdgpu/df_v3_6.c
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c
drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c
drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.h
drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v7_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/mmhub_v1_0.c
drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.h
drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c [new file with mode: 0644]
drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h [new file with mode: 0644]
drivers/gpu/drm/amd/amdgpu/navi10_ih.c
drivers/gpu/drm/amd/amdgpu/navi10_reg_init.c
drivers/gpu/drm/amd/amdgpu/navi12_reg_init.c
drivers/gpu/drm/amd/amdgpu/navi14_reg_init.c
drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c
drivers/gpu/drm/amd/amdgpu/nbio_v2_3.h
drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c
drivers/gpu/drm/amd/amdgpu/nbio_v6_1.h
drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c
drivers/gpu/drm/amd/amdgpu/nbio_v7_0.h
drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
drivers/gpu/drm/amd/amdgpu/nbio_v7_4.h
drivers/gpu/drm/amd/amdgpu/nv.c
drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/amdgpu/soc15.h
drivers/gpu/drm/amd/amdgpu/umc_v6_0.c [new file with mode: 0644]
drivers/gpu/drm/amd/amdgpu/umc_v6_0.h [new file with mode: 0644]
drivers/gpu/drm/amd/amdgpu/umc_v6_1.c
drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
drivers/gpu/drm/amd/amdgpu/vcn_v2_5.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/amdgpu/vi.h
drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c
drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h
drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
drivers/gpu/drm/amd/amdkfd/kfd_crat.c
drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c
drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.c
drivers/gpu/drm/amd/amdkfd/kfd_device.c
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
drivers/gpu/drm/amd/amdkfd/kfd_events.c
drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c
drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c
drivers/gpu/drm/amd/amdkfd/kfd_iommu.c
drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
drivers/gpu/drm/amd/amdkfd/kfd_module.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c
drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c
drivers/gpu/drm/amd/amdkfd/kfd_priv.h
drivers/gpu/drm/amd/amdkfd/kfd_process.c
drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
drivers/gpu/drm/amd/amdkfd/kfd_topology.c
drivers/gpu/drm/amd/amdkfd/kfd_topology.h
drivers/gpu/drm/amd/display/Kconfig
drivers/gpu/drm/amd/display/Makefile
drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.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/clk_mgr/clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.h
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.h
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/dc.h
drivers/gpu/drm/amd/display/dc/dc_dsc.h
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_abm.c
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_dmcu.c
drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h
drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c
drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.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_resource.c
drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.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_link_encoder.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
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/dcn20/dcn20_dccg.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn21/Makefile
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_link_encoder.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_link_encoder.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
drivers/gpu/drm/amd/display/dc/dm_cp_psp.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dm_helpers.h
drivers/gpu/drm/amd/display/dc/dm_pp_smu.h
drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c
drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c
drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c
drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h
drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c
drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c
drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c
drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c
drivers/gpu/drm/amd/display/dc/hdcp/Makefile [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c [new file with mode: 0644]
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/dc_link_dp.h
drivers/gpu/drm/amd/display/dc/inc/hw/aux_engine.h
drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h
drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h
drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
drivers/gpu/drm/amd/display/include/ddc_service_types.h
drivers/gpu/drm/amd/display/include/hdcp_types.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/modules/freesync/freesync.c
drivers/gpu/drm/amd/display/modules/hdcp/Makefile [new file with mode: 0644]
drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
drivers/gpu/drm/amd/display/modules/power/power_helpers.c
drivers/gpu/drm/amd/display/modules/power/power_helpers.h
drivers/gpu/drm/amd/include/asic_reg/bif/bif_4_1_d.h
drivers/gpu/drm/amd/include/asic_reg/bif/bif_4_1_sh_mask.h
drivers/gpu/drm/amd/include/asic_reg/bif/bif_5_0_d.h
drivers/gpu/drm/amd/include/asic_reg/bif/bif_5_0_sh_mask.h
drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_2_1_0_offset.h
drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_0_offset.h
drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_0_sh_mask.h
drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_4_0_smn.h
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/oss/osssys_4_0_sh_mask.h
drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_0_1_d.h
drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_0_1_sh_mask.h
drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_d.h
drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_sh_mask.h
drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_d.h
drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_sh_mask.h
drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_11_0_0_offset.h
drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_11_0_0_sh_mask.h
drivers/gpu/drm/amd/include/atomfirmware.h
drivers/gpu/drm/amd/include/discovery.h
drivers/gpu/drm/amd/include/ivsrcid/nbio/irqsrcs_nbif_7_4.h [new file with mode: 0644]
drivers/gpu/drm/amd/include/kgd_kfd_interface.h
drivers/gpu/drm/amd/include/kgd_pp_interface.h
drivers/gpu/drm/amd/include/renoir_ip_offset.h
drivers/gpu/drm/amd/include/vega10_enum.h
drivers/gpu/drm/amd/powerplay/amd_powerplay.c
drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
drivers/gpu/drm/amd/powerplay/hwmgr/Makefile
drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.c [new file with mode: 0644]
drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.h [new file with mode: 0644]
drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.c
drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.h
drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.c [new file with mode: 0644]
drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.h [new file with mode: 0644]
drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.c [new file with mode: 0644]
drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.h [new file with mode: 0644]
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.c [new file with mode: 0644]
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.h [new file with mode: 0644]
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.c [new file with mode: 0644]
drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.h [new file with mode: 0644]
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
drivers/gpu/drm/amd/powerplay/inc/arcturus_ppsmc.h
drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_arcturus.h
drivers/gpu/drm/amd/powerplay/inc/smu_types.h
drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h
drivers/gpu/drm/amd/powerplay/inc/vega20_ppsmc.h
drivers/gpu/drm/amd/powerplay/navi10_ppt.c
drivers/gpu/drm/amd/powerplay/navi10_ppt.h
drivers/gpu/drm/amd/powerplay/renoir_ppt.c
drivers/gpu/drm/amd/powerplay/smu_v11_0.c
drivers/gpu/drm/amd/powerplay/smu_v12_0.c
drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c
drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c
drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.c
drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c
drivers/gpu/drm/amd/powerplay/vega20_ppt.c
drivers/gpu/drm/radeon/radeon_audio.c
drivers/gpu/drm/ttm/ttm_bo.c
include/drm/amd_asic_type.h
include/linux/device_cgroup.h
include/uapi/drm/amdgpu_drm.h
security/device_cgroup.c

index 5acdd1842ea20f3cb1f11ed5297f7cc2c1a71237..5b9eaf23558ee7236ff3b1c93086e06e316a9178 100644 (file)
@@ -79,12 +79,32 @@ AMDGPU XGMI Support
 .. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
    :internal:
 
-AMDGPU RAS debugfs control interface
-====================================
+AMDGPU RAS Support
+==================
+
+RAS debugfs/sysfs Control and Error Injection Interfaces
+--------------------------------------------------------
 
 .. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
    :doc: AMDGPU RAS debugfs control interface
 
+RAS Error Count sysfs Interface
+-------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+   :doc: AMDGPU RAS sysfs Error Count Interface
+
+RAS EEPROM debugfs Interface
+----------------------------
+
+.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+   :doc: AMDGPU RAS debugfs EEPROM table reset interface
+
+RAS VRAM Bad Pages sysfs Interface
+----------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+   :doc: AMDGPU RAS sysfs gpu_vram_bad_pages Interface
 
 .. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
    :internal:
@@ -130,11 +150,11 @@ pp_od_clk_voltage
 .. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
    :doc: pp_od_clk_voltage
 
-pp_dpm_sclk pp_dpm_mclk pp_dpm_pcie
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+pp_dpm_*
+~~~~~~~~
 
 .. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
-   :doc: pp_dpm_sclk pp_dpm_mclk pp_dpm_pcie
+   :doc: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_dcefclk pp_dpm_pcie
 
 pp_power_profile_mode
 ~~~~~~~~~~~~~~~~~~~~~
index 36357a36a28107bd62057e60b16508eaf58bd2be..dba57ca0c9d94c89748f706755b845eb50926997 100644 (file)
@@ -232,9 +232,9 @@ config DRM_AMDGPU
        tristate "AMD GPU"
        depends on DRM && PCI && MMU
        select FW_LOADER
-        select DRM_KMS_HELPER
+       select DRM_KMS_HELPER
        select DRM_SCHED
-        select DRM_TTM
+       select DRM_TTM
        select POWER_SUPPLY
        select HWMON
        select BACKLIGHT_CLASS_DEVICE
index 00962a659009b27f81c5e68d5b1932c9c1e563ff..ca0e435559d5c446e5a77730703e1462c01ab9b2 100644 (file)
@@ -53,8 +53,9 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
        amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \
        amdgpu_gtt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o amdgpu_atomfirmware.o \
        amdgpu_vf_error.o amdgpu_sched.o amdgpu_debugfs.o amdgpu_ids.o \
-       amdgpu_gmc.o amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \
-       amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o smu_v11_0_i2c.o
+       amdgpu_gmc.o amdgpu_mmhub.o amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \
+       amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.o \
+       amdgpu_umc.o smu_v11_0_i2c.o
 
 amdgpu-$(CONFIG_PERF_EVENTS) += amdgpu_pmu.o
 
@@ -67,7 +68,7 @@ amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce
 amdgpu-y += \
        vi.o mxgpu_vi.o nbio_v6_1.o soc15.o emu_soc.o mxgpu_ai.o nbio_v7_0.o vega10_reg_init.o \
        vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o navi10_reg_init.o navi14_reg_init.o \
-       arct_reg_init.o navi12_reg_init.o
+       arct_reg_init.o navi12_reg_init.o mxgpu_nv.o
 
 # add DF block
 amdgpu-y += \
@@ -83,7 +84,7 @@ amdgpu-y += \
 
 # add UMC block
 amdgpu-y += \
-       umc_v6_1.o
+       umc_v6_1.o umc_v6_0.o
 
 # add IH block
 amdgpu-y += \
index bd37df5dd6d0489e0ec6edbdafa4333b9e324d2d..4a2b413c8a25414ce4a6c6305dae822d79b85101 100644 (file)
@@ -73,6 +73,7 @@
 #include "amdgpu_gmc.h"
 #include "amdgpu_gfx.h"
 #include "amdgpu_sdma.h"
+#include "amdgpu_nbio.h"
 #include "amdgpu_dm.h"
 #include "amdgpu_virt.h"
 #include "amdgpu_csa.h"
@@ -106,6 +107,8 @@ struct amdgpu_mgpu_info
        uint32_t                        num_apu;
 };
 
+#define AMDGPU_MAX_TIMEOUT_PARAM_LENTH 256
+
 /*
  * Modules parameters.
  */
@@ -122,6 +125,7 @@ extern int amdgpu_disp_priority;
 extern int amdgpu_hw_i2c;
 extern int amdgpu_pcie_gen2;
 extern int amdgpu_msi;
+extern char amdgpu_lockup_timeout[AMDGPU_MAX_TIMEOUT_PARAM_LENTH];
 extern int amdgpu_dpm;
 extern int amdgpu_fw_load_type;
 extern int amdgpu_aspm;
@@ -146,11 +150,7 @@ extern uint amdgpu_sdma_phase_quantum;
 extern char *amdgpu_disable_cu;
 extern char *amdgpu_virtual_display;
 extern uint amdgpu_pp_feature_mask;
-extern int amdgpu_ngg;
-extern int amdgpu_prim_buf_per_se;
-extern int amdgpu_pos_buf_per_se;
-extern int amdgpu_cntl_sb_buf_per_se;
-extern int amdgpu_param_buf_per_se;
+extern uint amdgpu_force_long_training;
 extern int amdgpu_job_hang_limit;
 extern int amdgpu_lbpw;
 extern int amdgpu_compute_multipipe;
@@ -167,6 +167,12 @@ extern int amdgpu_mcbp;
 extern int amdgpu_discovery;
 extern int amdgpu_mes;
 extern int amdgpu_noretry;
+extern int amdgpu_force_asic_type;
+#ifdef CONFIG_HSA_AMD
+extern int sched_policy;
+#else
+static const int sched_policy = KFD_SCHED_POLICY_HWS;
+#endif
 
 #ifdef CONFIG_DRM_AMDGPU_SI
 extern int amdgpu_si_support;
@@ -283,6 +289,9 @@ struct amdgpu_ip_block_version {
        const struct amd_ip_funcs *funcs;
 };
 
+#define HW_REV(_Major, _Minor, _Rev) \
+       ((((uint32_t) (_Major)) << 16) | ((uint32_t) (_Minor) << 8) | ((uint32_t) (_Rev)))
+
 struct amdgpu_ip_block {
        struct amdgpu_ip_block_status status;
        const struct amdgpu_ip_block_version *version;
@@ -425,7 +434,6 @@ struct amdgpu_fpriv {
 };
 
 int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv);
-int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev);
 
 int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm,
                  unsigned size, struct amdgpu_ib *ib);
@@ -477,7 +485,6 @@ struct amdgpu_cs_parser {
        uint64_t                        bytes_moved_vis_threshold;
        uint64_t                        bytes_moved;
        uint64_t                        bytes_moved_vis;
-       struct amdgpu_bo_list_entry     *evictable;
 
        /* user fence */
        struct amdgpu_bo_list_entry     uf_entry;
@@ -624,6 +631,11 @@ struct amdgpu_fw_vram_usage {
        u64 size;
        struct amdgpu_bo *reserved_bo;
        void *va;
+
+       /* Offset on the top of VRAM, used as c2p write buffer.
+       */
+       u64 mem_train_fb_loc;
+       bool mem_train_support;
 };
 
 /*
@@ -644,71 +656,14 @@ typedef void (*amdgpu_wreg64_t)(struct amdgpu_device*, uint32_t, uint64_t);
 typedef uint32_t (*amdgpu_block_rreg_t)(struct amdgpu_device*, uint32_t, uint32_t);
 typedef void (*amdgpu_block_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t, uint32_t);
 
-
-/*
- * amdgpu nbio functions
- *
- */
-struct nbio_hdp_flush_reg {
-       u32 ref_and_mask_cp0;
-       u32 ref_and_mask_cp1;
-       u32 ref_and_mask_cp2;
-       u32 ref_and_mask_cp3;
-       u32 ref_and_mask_cp4;
-       u32 ref_and_mask_cp5;
-       u32 ref_and_mask_cp6;
-       u32 ref_and_mask_cp7;
-       u32 ref_and_mask_cp8;
-       u32 ref_and_mask_cp9;
-       u32 ref_and_mask_sdma0;
-       u32 ref_and_mask_sdma1;
-       u32 ref_and_mask_sdma2;
-       u32 ref_and_mask_sdma3;
-       u32 ref_and_mask_sdma4;
-       u32 ref_and_mask_sdma5;
-       u32 ref_and_mask_sdma6;
-       u32 ref_and_mask_sdma7;
-};
-
 struct amdgpu_mmio_remap {
        u32 reg_offset;
        resource_size_t bus_addr;
 };
 
-struct amdgpu_nbio_funcs {
-       const struct nbio_hdp_flush_reg *hdp_flush_reg;
-       u32 (*get_hdp_flush_req_offset)(struct amdgpu_device *adev);
-       u32 (*get_hdp_flush_done_offset)(struct amdgpu_device *adev);
-       u32 (*get_pcie_index_offset)(struct amdgpu_device *adev);
-       u32 (*get_pcie_data_offset)(struct amdgpu_device *adev);
-       u32 (*get_rev_id)(struct amdgpu_device *adev);
-       void (*mc_access_enable)(struct amdgpu_device *adev, bool enable);
-       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, int doorbell_size);
-       void (*vcn_doorbell_range)(struct amdgpu_device *adev, bool use_doorbell,
-                                  int doorbell_index, int instance);
-       void (*enable_doorbell_aperture)(struct amdgpu_device *adev,
-                                        bool enable);
-       void (*enable_doorbell_selfring_aperture)(struct amdgpu_device *adev,
-                                                 bool enable);
-       void (*ih_doorbell_range)(struct amdgpu_device *adev,
-                                 bool use_doorbell, int doorbell_index);
-       void (*update_medium_grain_clock_gating)(struct amdgpu_device *adev,
-                                                bool enable);
-       void (*update_medium_grain_light_sleep)(struct amdgpu_device *adev,
-                                               bool enable);
-       void (*get_clockgating_state)(struct amdgpu_device *adev,
-                                     u32 *flags);
-       void (*ih_control)(struct amdgpu_device *adev);
-       void (*init_registers)(struct amdgpu_device *adev);
-       void (*detect_hw_virt)(struct amdgpu_device *adev);
-       void (*remap_hdp_registers)(struct amdgpu_device *adev);
-};
-
 struct amdgpu_df_funcs {
        void (*sw_init)(struct amdgpu_device *adev);
+       void (*sw_fini)(struct amdgpu_device *adev);
        void (*enable_broadcast_mode)(struct amdgpu_device *adev,
                                      bool enable);
        u32 (*get_fb_channel_number)(struct amdgpu_device *adev);
@@ -813,6 +768,7 @@ struct amdgpu_device {
        uint8_t                         *bios;
        uint32_t                        bios_size;
        struct amdgpu_bo                *stolen_vga_memory;
+       struct amdgpu_bo                *discovery_memory;
        uint32_t                        bios_scratch_reg_offset;
        uint32_t                        bios_scratch[AMDGPU_BIOS_NUM_SCRATCH];
 
@@ -921,6 +877,12 @@ struct amdgpu_device {
        u32                             cg_flags;
        u32                             pg_flags;
 
+       /* nbio */
+       struct amdgpu_nbio              nbio;
+
+       /* mmhub */
+       struct amdgpu_mmhub             mmhub;
+
        /* gfx */
        struct amdgpu_gfx               gfx;
 
@@ -974,9 +936,7 @@ struct amdgpu_device {
        /* soc15 register offset based on ip, instance and  segment */
        uint32_t                *reg_offset[MAX_HWIP][HWIP_MAX_INSTANCE];
 
-       const struct amdgpu_nbio_funcs  *nbio_funcs;
        const struct amdgpu_df_funcs    *df_funcs;
-       const struct amdgpu_mmhub_funcs *mmhub_funcs;
 
        /* delayed work_func for deferring clockgating during resume */
        struct delayed_work     delayed_init_work;
@@ -1009,8 +969,6 @@ struct amdgpu_device {
        int asic_reset_res;
        struct work_struct              xgmi_reset_work;
 
-       bool                            in_baco_reset;
-
        long                            gfx_timeout;
        long                            sdma_timeout;
        long                            video_timeout;
@@ -1032,6 +990,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
 void amdgpu_device_fini(struct amdgpu_device *adev);
 int amdgpu_gpu_wait_for_idle(struct amdgpu_device *adev);
 
+void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
+                              uint32_t *buf, size_t size, bool write);
 uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg,
                        uint32_t acc_flags);
 void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v,
index 07eb29885372ae2457fd0ddfc9ded3fc56e2e368..8c531793fe17bb5c6587509552e16244f49b0cf9 100644 (file)
@@ -63,45 +63,10 @@ void amdgpu_amdkfd_fini(void)
 
 void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev)
 {
-       const struct kfd2kgd_calls *kfd2kgd;
-
-       switch (adev->asic_type) {
-#ifdef CONFIG_DRM_AMDGPU_CIK
-       case CHIP_KAVERI:
-       case CHIP_HAWAII:
-               kfd2kgd = amdgpu_amdkfd_gfx_7_get_functions();
-               break;
-#endif
-       case CHIP_CARRIZO:
-       case CHIP_TONGA:
-       case CHIP_FIJI:
-       case CHIP_POLARIS10:
-       case CHIP_POLARIS11:
-       case CHIP_POLARIS12:
-       case CHIP_VEGAM:
-               kfd2kgd = amdgpu_amdkfd_gfx_8_0_get_functions();
-               break;
-       case CHIP_VEGA10:
-       case CHIP_VEGA12:
-       case CHIP_VEGA20:
-       case CHIP_RAVEN:
-               kfd2kgd = amdgpu_amdkfd_gfx_9_0_get_functions();
-               break;
-       case CHIP_ARCTURUS:
-               kfd2kgd = amdgpu_amdkfd_arcturus_get_functions();
-               break;
-       case CHIP_NAVI10:
-       case CHIP_NAVI14:
-       case CHIP_NAVI12:
-               kfd2kgd = amdgpu_amdkfd_gfx_10_0_get_functions();
-               break;
-       default:
-               dev_info(adev->dev, "kfd not supported on this ASIC\n");
-               return;
-       }
+       bool vf = amdgpu_sriov_vf(adev);
 
        adev->kfd.dev = kgd2kfd_probe((struct kgd_dev *)adev,
-                                     adev->pdev, kfd2kgd);
+                                     adev->pdev, adev->asic_type, vf);
 
        if (adev->kfd.dev)
                amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size;
@@ -202,7 +167,7 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
                                        adev->doorbell_index.last_non_cp;
                }
 
-               kgd2kfd_device_init(adev->kfd.dev, &gpu_resources);
+               kgd2kfd_device_init(adev->kfd.dev, adev->ddev, &gpu_resources);
        }
 }
 
@@ -709,38 +674,14 @@ int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem, struct mm_struct *mm)
        return 0;
 }
 
-struct kfd2kgd_calls *amdgpu_amdkfd_gfx_7_get_functions(void)
-{
-       return NULL;
-}
-
-struct kfd2kgd_calls *amdgpu_amdkfd_gfx_8_0_get_functions(void)
-{
-       return NULL;
-}
-
-struct kfd2kgd_calls *amdgpu_amdkfd_gfx_9_0_get_functions(void)
-{
-       return NULL;
-}
-
-struct kfd2kgd_calls *amdgpu_amdkfd_arcturus_get_functions(void)
-{
-       return NULL;
-}
-
-struct kfd2kgd_calls *amdgpu_amdkfd_gfx_10_0_get_functions(void)
-{
-       return NULL;
-}
-
 struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev,
-                             const struct kfd2kgd_calls *f2g)
+                             unsigned int asic_type, bool vf)
 {
        return NULL;
 }
 
 bool kgd2kfd_device_init(struct kfd_dev *kfd,
+                        struct drm_device *ddev,
                         const struct kgd2kfd_shared_resources *gpu_resources)
 {
        return false;
index e519df3fd2b6fd1d706e58300f2f6e23aa56c257..069d5d230810c96bfd6a582dc81072dc47ce0de3 100644 (file)
@@ -57,7 +57,7 @@ struct kgd_mem {
        unsigned int mapped_to_gpu_memory;
        uint64_t va;
 
-       uint32_t mapping_flags;
+       uint32_t alloc_flags;
 
        atomic_t invalid;
        struct amdkfd_process_info *process_info;
@@ -137,12 +137,6 @@ int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine,
 void amdgpu_amdkfd_set_compute_idle(struct kgd_dev *kgd, bool idle);
 bool amdgpu_amdkfd_have_atomics_support(struct kgd_dev *kgd);
 
-struct kfd2kgd_calls *amdgpu_amdkfd_gfx_7_get_functions(void);
-struct kfd2kgd_calls *amdgpu_amdkfd_gfx_8_0_get_functions(void);
-struct kfd2kgd_calls *amdgpu_amdkfd_gfx_9_0_get_functions(void);
-struct kfd2kgd_calls *amdgpu_amdkfd_arcturus_get_functions(void);
-struct kfd2kgd_calls *amdgpu_amdkfd_gfx_10_0_get_functions(void);
-
 bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid);
 
 int amdgpu_amdkfd_pre_reset(struct amdgpu_device *adev);
@@ -179,10 +173,17 @@ uint64_t amdgpu_amdkfd_get_mmio_remap_phys_addr(struct kgd_dev *kgd);
 uint32_t amdgpu_amdkfd_get_num_gws(struct kgd_dev *kgd);
 uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *src);
 
+/* Read user wptr from a specified user address space with page fault
+ * disabled. The memory must be pinned and mapped to the hardware when
+ * this is called in hqd_load functions, so it should never fault in
+ * the first place. This resolves a circular lock dependency involving
+ * four locks, including the DQM lock and mmap_sem.
+ */
 #define read_user_wptr(mmptr, wptr, dst)                               \
        ({                                                              \
                bool valid = false;                                     \
                if ((mmptr) && (wptr)) {                                \
+                       pagefault_disable();                            \
                        if ((mmptr) == current->mm) {                   \
                                valid = !get_user((dst), (wptr));       \
                        } else if (current->mm == NULL) {               \
@@ -190,6 +191,7 @@ uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *s
                                valid = !get_user((dst), (wptr));       \
                                unuse_mm(mmptr);                        \
                        }                                               \
+                       pagefault_enable();                             \
                }                                                       \
                valid;                                                  \
        })
@@ -240,8 +242,9 @@ void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo);
 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);
+                             unsigned int asic_type, bool vf);
 bool kgd2kfd_device_init(struct kfd_dev *kfd,
+                        struct drm_device *ddev,
                         const struct kgd2kfd_shared_resources *gpu_resources);
 void kgd2kfd_device_exit(struct kfd_dev *kfd);
 void kgd2kfd_suspend(struct kfd_dev *kfd);
index c79aaebeeaf03fbd4f4aaa3500914bbdc4aa55af..e1fbbebce4fd06eda868d7c908d106e3c6192c80 100644 (file)
@@ -69,11 +69,11 @@ static inline struct v9_sdma_mqd *get_sdma_mqd(void *mqd)
        return (struct v9_sdma_mqd *)mqd;
 }
 
-static uint32_t get_sdma_base_addr(struct amdgpu_device *adev,
+static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev,
                                unsigned int engine_id,
                                unsigned int queue_id)
 {
-       uint32_t base[8] = {
+       uint32_t sdma_engine_reg_base[8] = {
                SOC15_REG_OFFSET(SDMA0, 0,
                                 mmSDMA0_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL,
                SOC15_REG_OFFSET(SDMA1, 0,
@@ -91,111 +91,82 @@ static uint32_t get_sdma_base_addr(struct amdgpu_device *adev,
                SOC15_REG_OFFSET(SDMA7, 0,
                                 mmSDMA7_RLC0_RB_CNTL) - mmSDMA7_RLC0_RB_CNTL
        };
-       uint32_t retval;
 
-       retval = base[engine_id] + queue_id * (mmSDMA0_RLC1_RB_CNTL -
-                                              mmSDMA0_RLC0_RB_CNTL);
+       uint32_t retval = sdma_engine_reg_base[engine_id]
+               + queue_id * (mmSDMA0_RLC1_RB_CNTL - mmSDMA0_RLC0_RB_CNTL);
 
-       pr_debug("sdma base address: 0x%x\n", retval);
+       pr_debug("RLC register offset for SDMA%d RLC%d: 0x%x\n", engine_id,
+                       queue_id, retval);
 
        return retval;
 }
 
-static u32 sdma_v4_0_get_reg_offset(struct amdgpu_device *adev,
-               u32 instance, u32 offset)
-{
-       switch (instance) {
-       case 0:
-               return (adev->reg_offset[SDMA0_HWIP][0][0] + offset);
-       case 1:
-               return (adev->reg_offset[SDMA1_HWIP][0][1] + offset);
-       case 2:
-               return (adev->reg_offset[SDMA2_HWIP][0][1] + offset);
-       case 3:
-               return (adev->reg_offset[SDMA3_HWIP][0][1] + offset);
-       case 4:
-               return (adev->reg_offset[SDMA4_HWIP][0][1] + offset);
-       case 5:
-               return (adev->reg_offset[SDMA5_HWIP][0][1] + offset);
-       case 6:
-               return (adev->reg_offset[SDMA6_HWIP][0][1] + offset);
-       case 7:
-               return (adev->reg_offset[SDMA7_HWIP][0][1] + offset);
-       default:
-               break;
-       }
-       return 0;
-}
-
 static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
                             uint32_t __user *wptr, struct mm_struct *mm)
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
        struct v9_sdma_mqd *m;
-       uint32_t sdma_base_addr, sdmax_gfx_context_cntl;
+       uint32_t sdma_rlc_reg_offset;
        unsigned long end_jiffies;
        uint32_t data;
        uint64_t data64;
        uint64_t __user *wptr64 = (uint64_t __user *)wptr;
 
        m = get_sdma_mqd(mqd);
-       sdma_base_addr = get_sdma_base_addr(adev, m->sdma_engine_id,
+       sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
                                            m->sdma_queue_id);
-       sdmax_gfx_context_cntl = sdma_v4_0_get_reg_offset(adev,
-                       m->sdma_engine_id, mmSDMA0_GFX_CONTEXT_CNTL);
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL,
                m->sdmax_rlcx_rb_cntl & (~SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK));
 
        end_jiffies = msecs_to_jiffies(2000) + jiffies;
        while (true) {
-               data = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS);
+               data = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_CONTEXT_STATUS);
                if (data & SDMA0_RLC0_CONTEXT_STATUS__IDLE_MASK)
                        break;
-               if (time_after(jiffies, end_jiffies))
+               if (time_after(jiffies, end_jiffies)) {
+                       pr_err("SDMA RLC not idle in %s\n", __func__);
                        return -ETIME;
+               }
                usleep_range(500, 1000);
        }
-       data = RREG32(sdmax_gfx_context_cntl);
-       data = REG_SET_FIELD(data, SDMA0_GFX_CONTEXT_CNTL,
-                            RESUME_CTX, 0);
-       WREG32(sdmax_gfx_context_cntl, data);
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL_OFFSET,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_DOORBELL_OFFSET,
               m->sdmax_rlcx_doorbell_offset);
 
        data = REG_SET_FIELD(m->sdmax_rlcx_doorbell, SDMA0_RLC0_DOORBELL,
                             ENABLE, 1);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, data);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR, m->sdmax_rlcx_rb_rptr);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_HI,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_DOORBELL, data);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR,
+                               m->sdmax_rlcx_rb_rptr);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_HI,
                                m->sdmax_rlcx_rb_rptr_hi);
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_MINOR_PTR_UPDATE, 1);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_MINOR_PTR_UPDATE, 1);
        if (read_user_wptr(mm, wptr64, data64)) {
-               WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR,
+               WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR,
                       lower_32_bits(data64));
-               WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR_HI,
+               WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR_HI,
                       upper_32_bits(data64));
        } else {
-               WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR,
+               WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR,
                       m->sdmax_rlcx_rb_rptr);
-               WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR_HI,
+               WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR_HI,
                       m->sdmax_rlcx_rb_rptr_hi);
        }
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_MINOR_PTR_UPDATE, 0);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_MINOR_PTR_UPDATE, 0);
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE, m->sdmax_rlcx_rb_base);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE_HI,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_BASE, m->sdmax_rlcx_rb_base);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_BASE_HI,
                        m->sdmax_rlcx_rb_base_hi);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_LO,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_ADDR_LO,
                        m->sdmax_rlcx_rb_rptr_addr_lo);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_HI,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_ADDR_HI,
                        m->sdmax_rlcx_rb_rptr_addr_hi);
 
        data = REG_SET_FIELD(m->sdmax_rlcx_rb_cntl, SDMA0_RLC0_RB_CNTL,
                             RB_ENABLE, 1);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL, data);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL, data);
 
        return 0;
 }
@@ -205,7 +176,8 @@ static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
                             uint32_t (**dump)[2], uint32_t *n_regs)
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
-       uint32_t sdma_base_addr = get_sdma_base_addr(adev, engine_id, queue_id);
+       uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
+                       engine_id, queue_id);
        uint32_t i = 0, reg;
 #undef HQD_N_REGS
 #define HQD_N_REGS (19+6+7+10)
@@ -215,15 +187,15 @@ static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
                return -ENOMEM;
 
        for (reg = mmSDMA0_RLC0_RB_CNTL; reg <= mmSDMA0_RLC0_DOORBELL; reg++)
-               DUMP_REG(sdma_base_addr + reg);
+               DUMP_REG(sdma_rlc_reg_offset + reg);
        for (reg = mmSDMA0_RLC0_STATUS; reg <= mmSDMA0_RLC0_CSA_ADDR_HI; reg++)
-               DUMP_REG(sdma_base_addr + reg);
+               DUMP_REG(sdma_rlc_reg_offset + reg);
        for (reg = mmSDMA0_RLC0_IB_SUB_REMAIN;
             reg <= mmSDMA0_RLC0_MINOR_PTR_UPDATE; reg++)
-               DUMP_REG(sdma_base_addr + reg);
+               DUMP_REG(sdma_rlc_reg_offset + reg);
        for (reg = mmSDMA0_RLC0_MIDCMD_DATA0;
             reg <= mmSDMA0_RLC0_MIDCMD_CNTL; reg++)
-               DUMP_REG(sdma_base_addr + reg);
+               DUMP_REG(sdma_rlc_reg_offset + reg);
 
        WARN_ON_ONCE(i != HQD_N_REGS);
        *n_regs = i;
@@ -235,14 +207,14 @@ static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
        struct v9_sdma_mqd *m;
-       uint32_t sdma_base_addr;
+       uint32_t sdma_rlc_reg_offset;
        uint32_t sdma_rlc_rb_cntl;
 
        m = get_sdma_mqd(mqd);
-       sdma_base_addr = get_sdma_base_addr(adev, m->sdma_engine_id,
+       sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
                                            m->sdma_queue_id);
 
-       sdma_rlc_rb_cntl = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL);
+       sdma_rlc_rb_cntl = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL);
 
        if (sdma_rlc_rb_cntl & SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK)
                return true;
@@ -255,40 +227,42 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
        struct v9_sdma_mqd *m;
-       uint32_t sdma_base_addr;
+       uint32_t sdma_rlc_reg_offset;
        uint32_t temp;
        unsigned long end_jiffies = (utimeout * HZ / 1000) + jiffies;
 
        m = get_sdma_mqd(mqd);
-       sdma_base_addr = get_sdma_base_addr(adev, m->sdma_engine_id,
+       sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
                                            m->sdma_queue_id);
 
-       temp = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL);
+       temp = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL);
        temp = temp & ~SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK;
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL, temp);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL, temp);
 
        while (true) {
-               temp = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS);
+               temp = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_CONTEXT_STATUS);
                if (temp & SDMA0_RLC0_CONTEXT_STATUS__IDLE_MASK)
                        break;
-               if (time_after(jiffies, end_jiffies))
+               if (time_after(jiffies, end_jiffies)) {
+                       pr_err("SDMA RLC not idle in %s\n", __func__);
                        return -ETIME;
+               }
                usleep_range(500, 1000);
        }
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, 0);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL,
-               RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL) |
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_DOORBELL, 0);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL,
+               RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL) |
                SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK);
 
-       m->sdmax_rlcx_rb_rptr = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR);
+       m->sdmax_rlcx_rb_rptr = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR);
        m->sdmax_rlcx_rb_rptr_hi =
-               RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_HI);
+               RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_HI);
 
        return 0;
 }
 
-static const struct kfd2kgd_calls kfd2kgd = {
+const struct kfd2kgd_calls arcturus_kfd2kgd = {
        .program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings,
        .set_pasid_vmid_mapping = kgd_gfx_v9_set_pasid_vmid_mapping,
        .init_interrupts = kgd_gfx_v9_init_interrupts,
@@ -304,20 +278,11 @@ static const struct kfd2kgd_calls kfd2kgd = {
        .address_watch_execute = kgd_gfx_v9_address_watch_execute,
        .wave_control_execute = kgd_gfx_v9_wave_control_execute,
        .address_watch_get_offset = kgd_gfx_v9_address_watch_get_offset,
-       .get_atc_vmid_pasid_mapping_pasid =
-                       kgd_gfx_v9_get_atc_vmid_pasid_mapping_pasid,
-       .get_atc_vmid_pasid_mapping_valid =
-                       kgd_gfx_v9_get_atc_vmid_pasid_mapping_valid,
-       .set_scratch_backing_va = kgd_gfx_v9_set_scratch_backing_va,
+       .get_atc_vmid_pasid_mapping_info =
+                       kgd_gfx_v9_get_atc_vmid_pasid_mapping_info,
        .get_tile_config = kgd_gfx_v9_get_tile_config,
        .set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base,
        .invalidate_tlbs = kgd_gfx_v9_invalidate_tlbs,
        .invalidate_tlbs_vmid = kgd_gfx_v9_invalidate_tlbs_vmid,
        .get_hive_id = amdgpu_amdkfd_get_hive_id,
 };
-
-struct kfd2kgd_calls *amdgpu_amdkfd_arcturus_get_functions(void)
-{
-       return (struct kfd2kgd_calls *)&kfd2kgd;
-}
-
index d10f483f5e2735a88fd77d84874a786933620e25..0878f59ec340a16040eb8b748ec9612b598c43ac 100644 (file)
 #undef pr_fmt
 #define pr_fmt(fmt) "kfd2kgd: " fmt
 
-#include <linux/module.h>
-#include <linux/fdtable.h>
-#include <linux/uaccess.h>
-#include <linux/firmware.h>
 #include <linux/mmu_context.h>
 #include "amdgpu.h"
 #include "amdgpu_amdkfd.h"
-#include "amdgpu_ucode.h"
-#include "soc15_hw_ip.h"
 #include "gc/gc_10_1_0_offset.h"
 #include "gc/gc_10_1_0_sh_mask.h"
 #include "navi10_enum.h"
@@ -42,6 +36,7 @@
 #include "v10_structs.h"
 #include "nv.h"
 #include "nvd.h"
+#include "gfxhub_v2_0.h"
 
 enum hqd_dequeue_request_type {
        NO_ACTION = 0,
@@ -50,63 +45,6 @@ enum hqd_dequeue_request_type {
        SAVE_WAVES
 };
 
-/*
- * Register access functions
- */
-
-static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
-               uint32_t sh_mem_config,
-               uint32_t sh_mem_ape1_base, uint32_t sh_mem_ape1_limit,
-               uint32_t sh_mem_bases);
-static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,
-               unsigned int vmid);
-static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id);
-static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
-                       uint32_t queue_id, uint32_t __user *wptr,
-                       uint32_t wptr_shift, uint32_t wptr_mask,
-                       struct mm_struct *mm);
-static int kgd_hqd_dump(struct kgd_dev *kgd,
-                       uint32_t pipe_id, uint32_t queue_id,
-                       uint32_t (**dump)[2], uint32_t *n_regs);
-static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
-                            uint32_t __user *wptr, struct mm_struct *mm);
-static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
-                            uint32_t engine_id, uint32_t queue_id,
-                            uint32_t (**dump)[2], uint32_t *n_regs);
-static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
-               uint32_t pipe_id, uint32_t queue_id);
-static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd);
-static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
-                               enum kfd_preempt_type reset_type,
-                               unsigned int utimeout, uint32_t pipe_id,
-                               uint32_t queue_id);
-static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
-                               unsigned int utimeout);
-#if 0
-static uint32_t get_watch_base_addr(struct amdgpu_device *adev);
-#endif
-static int kgd_address_watch_disable(struct kgd_dev *kgd);
-static int kgd_address_watch_execute(struct kgd_dev *kgd,
-                                       unsigned int watch_point_id,
-                                       uint32_t cntl_val,
-                                       uint32_t addr_hi,
-                                       uint32_t addr_lo);
-static int kgd_wave_control_execute(struct kgd_dev *kgd,
-                                       uint32_t gfx_index_val,
-                                       uint32_t sq_cmd);
-static uint32_t kgd_address_watch_get_offset(struct kgd_dev *kgd,
-                                       unsigned int watch_point_id,
-                                       unsigned int reg_offset);
-
-static bool get_atc_vmid_pasid_mapping_valid(struct kgd_dev *kgd,
-               uint8_t vmid);
-static uint16_t get_atc_vmid_pasid_mapping_pasid(struct kgd_dev *kgd,
-               uint8_t vmid);
-static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
-               uint64_t page_table_base);
-static int invalidate_tlbs(struct kgd_dev *kgd, uint16_t pasid);
-static int invalidate_tlbs_vmid(struct kgd_dev *kgd, uint16_t vmid);
-
 /* Because of REG_GET_FIELD() being used, we put this function in the
  * asic specific file.
  */
@@ -139,37 +77,6 @@ static int amdgpu_amdkfd_get_tile_config(struct kgd_dev *kgd,
        return 0;
 }
 
-static const struct kfd2kgd_calls kfd2kgd = {
-       .program_sh_mem_settings = kgd_program_sh_mem_settings,
-       .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping,
-       .init_interrupts = kgd_init_interrupts,
-       .hqd_load = kgd_hqd_load,
-       .hqd_sdma_load = kgd_hqd_sdma_load,
-       .hqd_dump = kgd_hqd_dump,
-       .hqd_sdma_dump = kgd_hqd_sdma_dump,
-       .hqd_is_occupied = kgd_hqd_is_occupied,
-       .hqd_sdma_is_occupied = kgd_hqd_sdma_is_occupied,
-       .hqd_destroy = kgd_hqd_destroy,
-       .hqd_sdma_destroy = kgd_hqd_sdma_destroy,
-       .address_watch_disable = kgd_address_watch_disable,
-       .address_watch_execute = kgd_address_watch_execute,
-       .wave_control_execute = kgd_wave_control_execute,
-       .address_watch_get_offset = kgd_address_watch_get_offset,
-       .get_atc_vmid_pasid_mapping_pasid =
-                       get_atc_vmid_pasid_mapping_pasid,
-       .get_atc_vmid_pasid_mapping_valid =
-                       get_atc_vmid_pasid_mapping_valid,
-       .invalidate_tlbs = invalidate_tlbs,
-       .invalidate_tlbs_vmid = invalidate_tlbs_vmid,
-       .set_vm_context_page_table_base = set_vm_context_page_table_base,
-       .get_tile_config = amdgpu_amdkfd_get_tile_config,
-};
-
-struct kfd2kgd_calls *amdgpu_amdkfd_gfx_10_0_get_functions()
-{
-       return (struct kfd2kgd_calls *)&kfd2kgd;
-}
-
 static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
 {
        return (struct amdgpu_device *)kgd;
@@ -250,11 +157,6 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,
                        ATC_VMID0_PASID_MAPPING__VALID_MASK;
 
        pr_debug("pasid 0x%x vmid %d, reg value %x\n", pasid, vmid, pasid_mapping);
-       /*
-        * need to do this twice, once for gfx and once for mmhub
-        * for ATC add 16 to VMID for mmhub, for IH different registers.
-        * ATC_VMID0..15 registers are separate from ATC_VMID16..31.
-        */
 
        pr_debug("ATHUB, reg %x\n", SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING) + vmid);
        WREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING) + vmid,
@@ -306,11 +208,11 @@ static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id)
        return 0;
 }
 
-static uint32_t get_sdma_base_addr(struct amdgpu_device *adev,
+static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev,
                                unsigned int engine_id,
                                unsigned int queue_id)
 {
-       uint32_t base[2] = {
+       uint32_t sdma_engine_reg_base[2] = {
                SOC15_REG_OFFSET(SDMA0, 0,
                                 mmSDMA0_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL,
                /* On gfx10, mmSDMA1_xxx registers are defined NOT based
@@ -322,12 +224,12 @@ static uint32_t get_sdma_base_addr(struct amdgpu_device *adev,
                SOC15_REG_OFFSET(SDMA1, 0,
                                 mmSDMA1_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL
        };
-       uint32_t retval;
 
-       retval = base[engine_id] + queue_id * (mmSDMA0_RLC1_RB_CNTL -
-                                              mmSDMA0_RLC0_RB_CNTL);
+       uint32_t retval = sdma_engine_reg_base[engine_id]
+               + queue_id * (mmSDMA0_RLC1_RB_CNTL - mmSDMA0_RLC0_RB_CNTL);
 
-       pr_debug("sdma base address: 0x%x\n", retval);
+       pr_debug("RLC register offset for SDMA%d RLC%d: 0x%x\n", engine_id,
+                       queue_id, retval);
 
        return retval;
 }
@@ -488,72 +390,67 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
        struct v10_sdma_mqd *m;
-       uint32_t sdma_base_addr, sdmax_gfx_context_cntl;
+       uint32_t sdma_rlc_reg_offset;
        unsigned long end_jiffies;
        uint32_t data;
        uint64_t data64;
        uint64_t __user *wptr64 = (uint64_t __user *)wptr;
 
        m = get_sdma_mqd(mqd);
-       sdma_base_addr = get_sdma_base_addr(adev, m->sdma_engine_id,
+       sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
                                            m->sdma_queue_id);
-       pr_debug("sdma load base addr %x for engine %d, queue %d\n", sdma_base_addr, m->sdma_engine_id, m->sdma_queue_id);
-       sdmax_gfx_context_cntl = m->sdma_engine_id ?
-               SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_GFX_CONTEXT_CNTL) :
-               SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_GFX_CONTEXT_CNTL);
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL,
                m->sdmax_rlcx_rb_cntl & (~SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK));
 
        end_jiffies = msecs_to_jiffies(2000) + jiffies;
        while (true) {
-               data = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS);
+               data = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_CONTEXT_STATUS);
                if (data & SDMA0_RLC0_CONTEXT_STATUS__IDLE_MASK)
                        break;
-               if (time_after(jiffies, end_jiffies))
+               if (time_after(jiffies, end_jiffies)) {
+                       pr_err("SDMA RLC not idle in %s\n", __func__);
                        return -ETIME;
+               }
                usleep_range(500, 1000);
        }
-       data = RREG32(sdmax_gfx_context_cntl);
-       data = REG_SET_FIELD(data, SDMA0_GFX_CONTEXT_CNTL,
-                            RESUME_CTX, 0);
-       WREG32(sdmax_gfx_context_cntl, data);
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL_OFFSET,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_DOORBELL_OFFSET,
               m->sdmax_rlcx_doorbell_offset);
 
        data = REG_SET_FIELD(m->sdmax_rlcx_doorbell, SDMA0_RLC0_DOORBELL,
                             ENABLE, 1);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, data);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR, m->sdmax_rlcx_rb_rptr);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_HI,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_DOORBELL, data);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR,
+                               m->sdmax_rlcx_rb_rptr);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_HI,
                                m->sdmax_rlcx_rb_rptr_hi);
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_MINOR_PTR_UPDATE, 1);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_MINOR_PTR_UPDATE, 1);
        if (read_user_wptr(mm, wptr64, data64)) {
-               WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR,
+               WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR,
                       lower_32_bits(data64));
-               WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR_HI,
+               WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR_HI,
                       upper_32_bits(data64));
        } else {
-               WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR,
+               WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR,
                       m->sdmax_rlcx_rb_rptr);
-               WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR_HI,
+               WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR_HI,
                       m->sdmax_rlcx_rb_rptr_hi);
        }
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_MINOR_PTR_UPDATE, 0);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_MINOR_PTR_UPDATE, 0);
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE, m->sdmax_rlcx_rb_base);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE_HI,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_BASE, m->sdmax_rlcx_rb_base);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_BASE_HI,
                        m->sdmax_rlcx_rb_base_hi);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_LO,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_ADDR_LO,
                        m->sdmax_rlcx_rb_rptr_addr_lo);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_HI,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_ADDR_HI,
                        m->sdmax_rlcx_rb_rptr_addr_hi);
 
        data = REG_SET_FIELD(m->sdmax_rlcx_rb_cntl, SDMA0_RLC0_RB_CNTL,
                             RB_ENABLE, 1);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL, data);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL, data);
 
        return 0;
 }
@@ -563,28 +460,26 @@ static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
                             uint32_t (**dump)[2], uint32_t *n_regs)
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
-       uint32_t sdma_base_addr = get_sdma_base_addr(adev, engine_id, queue_id);
+       uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
+                       engine_id, queue_id);
        uint32_t i = 0, reg;
 #undef HQD_N_REGS
 #define HQD_N_REGS (19+6+7+10)
 
-       pr_debug("sdma dump engine id %d queue_id %d\n", engine_id, queue_id);
-       pr_debug("sdma base addr %x\n", sdma_base_addr);
-
        *dump = kmalloc(HQD_N_REGS*2*sizeof(uint32_t), GFP_KERNEL);
        if (*dump == NULL)
                return -ENOMEM;
 
        for (reg = mmSDMA0_RLC0_RB_CNTL; reg <= mmSDMA0_RLC0_DOORBELL; reg++)
-               DUMP_REG(sdma_base_addr + reg);
+               DUMP_REG(sdma_rlc_reg_offset + reg);
        for (reg = mmSDMA0_RLC0_STATUS; reg <= mmSDMA0_RLC0_CSA_ADDR_HI; reg++)
-               DUMP_REG(sdma_base_addr + reg);
+               DUMP_REG(sdma_rlc_reg_offset + reg);
        for (reg = mmSDMA0_RLC0_IB_SUB_REMAIN;
             reg <= mmSDMA0_RLC0_MINOR_PTR_UPDATE; reg++)
-               DUMP_REG(sdma_base_addr + reg);
+               DUMP_REG(sdma_rlc_reg_offset + reg);
        for (reg = mmSDMA0_RLC0_MIDCMD_DATA0;
             reg <= mmSDMA0_RLC0_MIDCMD_CNTL; reg++)
-               DUMP_REG(sdma_base_addr + reg);
+               DUMP_REG(sdma_rlc_reg_offset + reg);
 
        WARN_ON_ONCE(i != HQD_N_REGS);
        *n_regs = i;
@@ -618,14 +513,14 @@ static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
        struct v10_sdma_mqd *m;
-       uint32_t sdma_base_addr;
+       uint32_t sdma_rlc_reg_offset;
        uint32_t sdma_rlc_rb_cntl;
 
        m = get_sdma_mqd(mqd);
-       sdma_base_addr = get_sdma_base_addr(adev, m->sdma_engine_id,
+       sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
                                            m->sdma_queue_id);
 
-       sdma_rlc_rb_cntl = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL);
+       sdma_rlc_rb_cntl = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL);
 
        if (sdma_rlc_rb_cntl & SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK)
                return true;
@@ -746,59 +641,52 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
        struct v10_sdma_mqd *m;
-       uint32_t sdma_base_addr;
+       uint32_t sdma_rlc_reg_offset;
        uint32_t temp;
        unsigned long end_jiffies = (utimeout * HZ / 1000) + jiffies;
 
        m = get_sdma_mqd(mqd);
-       sdma_base_addr = get_sdma_base_addr(adev, m->sdma_engine_id,
+       sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
                                            m->sdma_queue_id);
 
-       temp = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL);
+       temp = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL);
        temp = temp & ~SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK;
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL, temp);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL, temp);
 
        while (true) {
-               temp = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS);
+               temp = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_CONTEXT_STATUS);
                if (temp & SDMA0_RLC0_CONTEXT_STATUS__IDLE_MASK)
                        break;
-               if (time_after(jiffies, end_jiffies))
+               if (time_after(jiffies, end_jiffies)) {
+                       pr_err("SDMA RLC not idle in %s\n", __func__);
                        return -ETIME;
+               }
                usleep_range(500, 1000);
        }
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, 0);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL,
-               RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL) |
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_DOORBELL, 0);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL,
+               RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL) |
                SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK);
 
-       m->sdmax_rlcx_rb_rptr = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR);
+       m->sdmax_rlcx_rb_rptr = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR);
        m->sdmax_rlcx_rb_rptr_hi =
-               RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_HI);
+               RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_HI);
 
        return 0;
 }
 
-static bool get_atc_vmid_pasid_mapping_valid(struct kgd_dev *kgd,
-                                                       uint8_t vmid)
+static bool get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
+                                       uint8_t vmid, uint16_t *p_pasid)
 {
-       uint32_t reg;
+       uint32_t value;
        struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
 
-       reg = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING)
+       value = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING)
                     + vmid);
-       return reg & ATC_VMID0_PASID_MAPPING__VALID_MASK;
-}
-
-static uint16_t get_atc_vmid_pasid_mapping_pasid(struct kgd_dev *kgd,
-                                                               uint8_t vmid)
-{
-       uint32_t reg;
-       struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
+       *p_pasid = value & ATC_VMID0_PASID_MAPPING__PASID_MASK;
 
-       reg = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING)
-                    + vmid);
-       return reg & ATC_VMID0_PASID_MAPPING__PASID_MASK;
+       return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
 }
 
 static int invalidate_tlbs_with_kiq(struct amdgpu_device *adev, uint16_t pasid)
@@ -830,6 +718,8 @@ static int invalidate_tlbs(struct kgd_dev *kgd, uint16_t pasid)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
        int vmid;
+       uint16_t queried_pasid;
+       bool ret;
        struct amdgpu_ring *ring = &adev->gfx.kiq.ring;
 
        if (amdgpu_emu_mode == 0 && ring->sched.ready)
@@ -838,13 +728,13 @@ static int invalidate_tlbs(struct kgd_dev *kgd, uint16_t pasid)
        for (vmid = 0; vmid < 16; vmid++) {
                if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid))
                        continue;
-               if (get_atc_vmid_pasid_mapping_valid(kgd, vmid)) {
-                       if (get_atc_vmid_pasid_mapping_pasid(kgd, vmid)
-                               == pasid) {
-                               amdgpu_gmc_flush_gpu_tlb(adev, vmid,
-                                               AMDGPU_GFXHUB_0, 0);
-                               break;
-                       }
+
+               ret = get_atc_vmid_pasid_mapping_info(kgd, vmid,
+                               &queried_pasid);
+               if (ret && queried_pasid == pasid) {
+                       amdgpu_gmc_flush_gpu_tlb(adev, vmid,
+                                       AMDGPU_GFXHUB_0, 0);
+                       break;
                }
        }
 
@@ -914,7 +804,6 @@ static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
                uint64_t page_table_base)
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
-       uint64_t base = page_table_base | AMDGPU_PTE_VALID;
 
        if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
                pr_err("trying to set page table base for wrong VMID %u\n",
@@ -922,18 +811,31 @@ static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
                return;
        }
 
-       /* TODO: take advantage of per-process address space size. For
-        * now, all processes share the same address space size, like
-        * on GFX8 and older.
-        */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32) + (vmid*2), 0);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32) + (vmid*2), 0);
-
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32) + (vmid*2),
-                       lower_32_bits(adev->vm_manager.max_pfn - 1));
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32) + (vmid*2),
-                       upper_32_bits(adev->vm_manager.max_pfn - 1));
-
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32) + (vmid*2), lower_32_bits(base));
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32) + (vmid*2), upper_32_bits(base));
+       /* SDMA is on gfxhub as well for Navi1* series */
+       gfxhub_v2_0_setup_vm_pt_regs(adev, vmid, page_table_base);
 }
+
+const struct kfd2kgd_calls gfx_v10_kfd2kgd = {
+       .program_sh_mem_settings = kgd_program_sh_mem_settings,
+       .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping,
+       .init_interrupts = kgd_init_interrupts,
+       .hqd_load = kgd_hqd_load,
+       .hqd_sdma_load = kgd_hqd_sdma_load,
+       .hqd_dump = kgd_hqd_dump,
+       .hqd_sdma_dump = kgd_hqd_sdma_dump,
+       .hqd_is_occupied = kgd_hqd_is_occupied,
+       .hqd_sdma_is_occupied = kgd_hqd_sdma_is_occupied,
+       .hqd_destroy = kgd_hqd_destroy,
+       .hqd_sdma_destroy = kgd_hqd_sdma_destroy,
+       .address_watch_disable = kgd_address_watch_disable,
+       .address_watch_execute = kgd_address_watch_execute,
+       .wave_control_execute = kgd_wave_control_execute,
+       .address_watch_get_offset = kgd_address_watch_get_offset,
+       .get_atc_vmid_pasid_mapping_info =
+                       get_atc_vmid_pasid_mapping_info,
+       .get_tile_config = amdgpu_amdkfd_get_tile_config,
+       .set_vm_context_page_table_base = set_vm_context_page_table_base,
+       .invalidate_tlbs = invalidate_tlbs,
+       .invalidate_tlbs_vmid = invalidate_tlbs_vmid,
+       .get_hive_id = amdgpu_amdkfd_get_hive_id,
+};
index 5f459bf5f6222b71030eff48282e31a8c7dce138..6e6f0a99ec066cabcefd755a02b1f98835260c36 100644 (file)
@@ -20,8 +20,6 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include <linux/fdtable.h>
-#include <linux/uaccess.h>
 #include <linux/mmu_context.h>
 
 #include "amdgpu.h"
@@ -86,65 +84,6 @@ union TCP_WATCH_CNTL_BITS {
        float f32All;
 };
 
-/*
- * Register access functions
- */
-
-static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
-               uint32_t sh_mem_config, uint32_t sh_mem_ape1_base,
-               uint32_t sh_mem_ape1_limit, uint32_t sh_mem_bases);
-
-static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,
-                                       unsigned int vmid);
-
-static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id);
-static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
-                       uint32_t queue_id, uint32_t __user *wptr,
-                       uint32_t wptr_shift, uint32_t wptr_mask,
-                       struct mm_struct *mm);
-static int kgd_hqd_dump(struct kgd_dev *kgd,
-                       uint32_t pipe_id, uint32_t queue_id,
-                       uint32_t (**dump)[2], uint32_t *n_regs);
-static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
-                            uint32_t __user *wptr, struct mm_struct *mm);
-static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
-                            uint32_t engine_id, uint32_t queue_id,
-                            uint32_t (**dump)[2], uint32_t *n_regs);
-static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
-                               uint32_t pipe_id, uint32_t queue_id);
-
-static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
-                               enum kfd_preempt_type reset_type,
-                               unsigned int utimeout, uint32_t pipe_id,
-                               uint32_t queue_id);
-static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd);
-static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
-                               unsigned int utimeout);
-static int kgd_address_watch_disable(struct kgd_dev *kgd);
-static int kgd_address_watch_execute(struct kgd_dev *kgd,
-                                       unsigned int watch_point_id,
-                                       uint32_t cntl_val,
-                                       uint32_t addr_hi,
-                                       uint32_t addr_lo);
-static int kgd_wave_control_execute(struct kgd_dev *kgd,
-                                       uint32_t gfx_index_val,
-                                       uint32_t sq_cmd);
-static uint32_t kgd_address_watch_get_offset(struct kgd_dev *kgd,
-                                       unsigned int watch_point_id,
-                                       unsigned int reg_offset);
-
-static bool get_atc_vmid_pasid_mapping_valid(struct kgd_dev *kgd, uint8_t vmid);
-static uint16_t get_atc_vmid_pasid_mapping_pasid(struct kgd_dev *kgd,
-                                                       uint8_t vmid);
-
-static void set_scratch_backing_va(struct kgd_dev *kgd,
-                                       uint64_t va, uint32_t vmid);
-static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
-               uint64_t page_table_base);
-static int invalidate_tlbs(struct kgd_dev *kgd, uint16_t pasid);
-static int invalidate_tlbs_vmid(struct kgd_dev *kgd, uint16_t vmid);
-static uint32_t read_vmid_from_vmfault_reg(struct kgd_dev *kgd);
-
 /* Because of REG_GET_FIELD() being used, we put this function in the
  * asic specific file.
  */
@@ -170,37 +109,6 @@ static int get_tile_config(struct kgd_dev *kgd,
        return 0;
 }
 
-static const struct kfd2kgd_calls kfd2kgd = {
-       .program_sh_mem_settings = kgd_program_sh_mem_settings,
-       .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping,
-       .init_interrupts = kgd_init_interrupts,
-       .hqd_load = kgd_hqd_load,
-       .hqd_sdma_load = kgd_hqd_sdma_load,
-       .hqd_dump = kgd_hqd_dump,
-       .hqd_sdma_dump = kgd_hqd_sdma_dump,
-       .hqd_is_occupied = kgd_hqd_is_occupied,
-       .hqd_sdma_is_occupied = kgd_hqd_sdma_is_occupied,
-       .hqd_destroy = kgd_hqd_destroy,
-       .hqd_sdma_destroy = kgd_hqd_sdma_destroy,
-       .address_watch_disable = kgd_address_watch_disable,
-       .address_watch_execute = kgd_address_watch_execute,
-       .wave_control_execute = kgd_wave_control_execute,
-       .address_watch_get_offset = kgd_address_watch_get_offset,
-       .get_atc_vmid_pasid_mapping_pasid = get_atc_vmid_pasid_mapping_pasid,
-       .get_atc_vmid_pasid_mapping_valid = get_atc_vmid_pasid_mapping_valid,
-       .set_scratch_backing_va = set_scratch_backing_va,
-       .get_tile_config = get_tile_config,
-       .set_vm_context_page_table_base = set_vm_context_page_table_base,
-       .invalidate_tlbs = invalidate_tlbs,
-       .invalidate_tlbs_vmid = invalidate_tlbs_vmid,
-       .read_vmid_from_vmfault_reg = read_vmid_from_vmfault_reg,
-};
-
-struct kfd2kgd_calls *amdgpu_amdkfd_gfx_7_get_functions(void)
-{
-       return (struct kfd2kgd_calls *)&kfd2kgd;
-}
-
 static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
 {
        return (struct amdgpu_device *)kgd;
@@ -303,14 +211,15 @@ static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id)
        return 0;
 }
 
-static inline uint32_t get_sdma_base_addr(struct cik_sdma_rlc_registers *m)
+static inline uint32_t get_sdma_rlc_reg_offset(struct cik_sdma_rlc_registers *m)
 {
        uint32_t retval;
 
        retval = m->sdma_engine_id * SDMA1_REGISTER_OFFSET +
                        m->sdma_queue_id * KFD_CIK_SDMA_QUEUE_OFFSET;
 
-       pr_debug("sdma base address: 0x%x\n", retval);
+       pr_debug("RLC register offset for SDMA%d RLC%d: 0x%x\n",
+                       m->sdma_engine_id, m->sdma_queue_id, retval);
 
        return retval;
 }
@@ -413,60 +322,52 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
        struct cik_sdma_rlc_registers *m;
        unsigned long end_jiffies;
-       uint32_t sdma_base_addr;
+       uint32_t sdma_rlc_reg_offset;
        uint32_t data;
 
        m = get_sdma_mqd(mqd);
-       sdma_base_addr = get_sdma_base_addr(m);
+       sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(m);
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL,
                m->sdma_rlc_rb_cntl & (~SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK));
 
        end_jiffies = msecs_to_jiffies(2000) + jiffies;
        while (true) {
-               data = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS);
+               data = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_CONTEXT_STATUS);
                if (data & SDMA0_RLC0_CONTEXT_STATUS__IDLE_MASK)
                        break;
-               if (time_after(jiffies, end_jiffies))
+               if (time_after(jiffies, end_jiffies)) {
+                       pr_err("SDMA RLC not idle in %s\n", __func__);
                        return -ETIME;
+               }
                usleep_range(500, 1000);
        }
-       if (m->sdma_engine_id) {
-               data = RREG32(mmSDMA1_GFX_CONTEXT_CNTL);
-               data = REG_SET_FIELD(data, SDMA1_GFX_CONTEXT_CNTL,
-                               RESUME_CTX, 0);
-               WREG32(mmSDMA1_GFX_CONTEXT_CNTL, data);
-       } else {
-               data = RREG32(mmSDMA0_GFX_CONTEXT_CNTL);
-               data = REG_SET_FIELD(data, SDMA0_GFX_CONTEXT_CNTL,
-                               RESUME_CTX, 0);
-               WREG32(mmSDMA0_GFX_CONTEXT_CNTL, data);
-       }
 
        data = REG_SET_FIELD(m->sdma_rlc_doorbell, SDMA0_RLC0_DOORBELL,
                             ENABLE, 1);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, data);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR, m->sdma_rlc_rb_rptr);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_DOORBELL, data);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR,
+                               m->sdma_rlc_rb_rptr);
 
        if (read_user_wptr(mm, wptr, data))
-               WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR, data);
+               WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR, data);
        else
-               WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR,
+               WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR,
                       m->sdma_rlc_rb_rptr);
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_VIRTUAL_ADDR,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_VIRTUAL_ADDR,
                                m->sdma_rlc_virtual_addr);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE, m->sdma_rlc_rb_base);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE_HI,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_BASE, m->sdma_rlc_rb_base);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_BASE_HI,
                        m->sdma_rlc_rb_base_hi);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_LO,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_ADDR_LO,
                        m->sdma_rlc_rb_rptr_addr_lo);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_HI,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_ADDR_HI,
                        m->sdma_rlc_rb_rptr_addr_hi);
 
        data = REG_SET_FIELD(m->sdma_rlc_rb_cntl, SDMA0_RLC0_RB_CNTL,
                             RB_ENABLE, 1);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL, data);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL, data);
 
        return 0;
 }
@@ -524,13 +425,13 @@ static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
        struct cik_sdma_rlc_registers *m;
-       uint32_t sdma_base_addr;
+       uint32_t sdma_rlc_reg_offset;
        uint32_t sdma_rlc_rb_cntl;
 
        m = get_sdma_mqd(mqd);
-       sdma_base_addr = get_sdma_base_addr(m);
+       sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(m);
 
-       sdma_rlc_rb_cntl = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL);
+       sdma_rlc_rb_cntl = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL);
 
        if (sdma_rlc_rb_cntl & SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK)
                return true;
@@ -645,32 +546,34 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
        struct cik_sdma_rlc_registers *m;
-       uint32_t sdma_base_addr;
+       uint32_t sdma_rlc_reg_offset;
        uint32_t temp;
        unsigned long end_jiffies = (utimeout * HZ / 1000) + jiffies;
 
        m = get_sdma_mqd(mqd);
-       sdma_base_addr = get_sdma_base_addr(m);
+       sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(m);
 
-       temp = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL);
+       temp = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL);
        temp = temp & ~SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK;
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL, temp);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL, temp);
 
        while (true) {
-               temp = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS);
+               temp = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_CONTEXT_STATUS);
                if (temp & SDMA0_RLC0_CONTEXT_STATUS__IDLE_MASK)
                        break;
-               if (time_after(jiffies, end_jiffies))
+               if (time_after(jiffies, end_jiffies)) {
+                       pr_err("SDMA RLC not idle in %s\n", __func__);
                        return -ETIME;
+               }
                usleep_range(500, 1000);
        }
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, 0);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL,
-               RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL) |
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_DOORBELL, 0);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL,
+               RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL) |
                SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK);
 
-       m->sdma_rlc_rb_rptr = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR);
+       m->sdma_rlc_rb_rptr = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR);
 
        return 0;
 }
@@ -758,24 +661,16 @@ static uint32_t kgd_address_watch_get_offset(struct kgd_dev *kgd,
        return watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX + reg_offset];
 }
 
-static bool get_atc_vmid_pasid_mapping_valid(struct kgd_dev *kgd,
-                                                       uint8_t vmid)
+static bool get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
+                                       uint8_t vmid, uint16_t *p_pasid)
 {
-       uint32_t reg;
+       uint32_t value;
        struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
 
-       reg = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
-       return reg & ATC_VMID0_PASID_MAPPING__VALID_MASK;
-}
-
-static uint16_t get_atc_vmid_pasid_mapping_pasid(struct kgd_dev *kgd,
-                                                               uint8_t vmid)
-{
-       uint32_t reg;
-       struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
+       value = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
+       *p_pasid = value & ATC_VMID0_PASID_MAPPING__PASID_MASK;
 
-       reg = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
-       return reg & ATC_VMID0_PASID_MAPPING__PASID_MASK;
+       return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
 }
 
 static void set_scratch_backing_va(struct kgd_dev *kgd,
@@ -855,3 +750,28 @@ static uint32_t read_vmid_from_vmfault_reg(struct kgd_dev *kgd)
 
        return REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS, VMID);
 }
+
+const struct kfd2kgd_calls gfx_v7_kfd2kgd = {
+       .program_sh_mem_settings = kgd_program_sh_mem_settings,
+       .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping,
+       .init_interrupts = kgd_init_interrupts,
+       .hqd_load = kgd_hqd_load,
+       .hqd_sdma_load = kgd_hqd_sdma_load,
+       .hqd_dump = kgd_hqd_dump,
+       .hqd_sdma_dump = kgd_hqd_sdma_dump,
+       .hqd_is_occupied = kgd_hqd_is_occupied,
+       .hqd_sdma_is_occupied = kgd_hqd_sdma_is_occupied,
+       .hqd_destroy = kgd_hqd_destroy,
+       .hqd_sdma_destroy = kgd_hqd_sdma_destroy,
+       .address_watch_disable = kgd_address_watch_disable,
+       .address_watch_execute = kgd_address_watch_execute,
+       .wave_control_execute = kgd_wave_control_execute,
+       .address_watch_get_offset = kgd_address_watch_get_offset,
+       .get_atc_vmid_pasid_mapping_info = get_atc_vmid_pasid_mapping_info,
+       .set_scratch_backing_va = set_scratch_backing_va,
+       .get_tile_config = get_tile_config,
+       .set_vm_context_page_table_base = set_vm_context_page_table_base,
+       .invalidate_tlbs = invalidate_tlbs,
+       .invalidate_tlbs_vmid = invalidate_tlbs_vmid,
+       .read_vmid_from_vmfault_reg = read_vmid_from_vmfault_reg,
+};
index 6d2f6144960667c296f636fcb112517887b4e07c..bfbddedb2380c9a92682e7f0bab623a2af829877 100644 (file)
@@ -20,9 +20,6 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include <linux/module.h>
-#include <linux/fdtable.h>
-#include <linux/uaccess.h>
 #include <linux/mmu_context.h>
 
 #include "amdgpu.h"
@@ -44,62 +41,6 @@ enum hqd_dequeue_request_type {
        RESET_WAVES
 };
 
-/*
- * Register access functions
- */
-
-static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid,
-               uint32_t sh_mem_config,
-               uint32_t sh_mem_ape1_base, uint32_t sh_mem_ape1_limit,
-               uint32_t sh_mem_bases);
-static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,
-               unsigned int vmid);
-static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id);
-static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
-                       uint32_t queue_id, uint32_t __user *wptr,
-                       uint32_t wptr_shift, uint32_t wptr_mask,
-                       struct mm_struct *mm);
-static int kgd_hqd_dump(struct kgd_dev *kgd,
-                       uint32_t pipe_id, uint32_t queue_id,
-                       uint32_t (**dump)[2], uint32_t *n_regs);
-static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
-                            uint32_t __user *wptr, struct mm_struct *mm);
-static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
-                            uint32_t engine_id, uint32_t queue_id,
-                            uint32_t (**dump)[2], uint32_t *n_regs);
-static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address,
-               uint32_t pipe_id, uint32_t queue_id);
-static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd);
-static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
-                               enum kfd_preempt_type reset_type,
-                               unsigned int utimeout, uint32_t pipe_id,
-                               uint32_t queue_id);
-static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
-                               unsigned int utimeout);
-static int kgd_address_watch_disable(struct kgd_dev *kgd);
-static int kgd_address_watch_execute(struct kgd_dev *kgd,
-                                       unsigned int watch_point_id,
-                                       uint32_t cntl_val,
-                                       uint32_t addr_hi,
-                                       uint32_t addr_lo);
-static int kgd_wave_control_execute(struct kgd_dev *kgd,
-                                       uint32_t gfx_index_val,
-                                       uint32_t sq_cmd);
-static uint32_t kgd_address_watch_get_offset(struct kgd_dev *kgd,
-                                       unsigned int watch_point_id,
-                                       unsigned int reg_offset);
-
-static bool get_atc_vmid_pasid_mapping_valid(struct kgd_dev *kgd,
-               uint8_t vmid);
-static uint16_t get_atc_vmid_pasid_mapping_pasid(struct kgd_dev *kgd,
-               uint8_t vmid);
-static void set_scratch_backing_va(struct kgd_dev *kgd,
-                                       uint64_t va, uint32_t vmid);
-static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
-               uint64_t page_table_base);
-static int invalidate_tlbs(struct kgd_dev *kgd, uint16_t pasid);
-static int invalidate_tlbs_vmid(struct kgd_dev *kgd, uint16_t vmid);
-
 /* Because of REG_GET_FIELD() being used, we put this function in the
  * asic specific file.
  */
@@ -125,38 +66,6 @@ static int get_tile_config(struct kgd_dev *kgd,
        return 0;
 }
 
-static const struct kfd2kgd_calls kfd2kgd = {
-       .program_sh_mem_settings = kgd_program_sh_mem_settings,
-       .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping,
-       .init_interrupts = kgd_init_interrupts,
-       .hqd_load = kgd_hqd_load,
-       .hqd_sdma_load = kgd_hqd_sdma_load,
-       .hqd_dump = kgd_hqd_dump,
-       .hqd_sdma_dump = kgd_hqd_sdma_dump,
-       .hqd_is_occupied = kgd_hqd_is_occupied,
-       .hqd_sdma_is_occupied = kgd_hqd_sdma_is_occupied,
-       .hqd_destroy = kgd_hqd_destroy,
-       .hqd_sdma_destroy = kgd_hqd_sdma_destroy,
-       .address_watch_disable = kgd_address_watch_disable,
-       .address_watch_execute = kgd_address_watch_execute,
-       .wave_control_execute = kgd_wave_control_execute,
-       .address_watch_get_offset = kgd_address_watch_get_offset,
-       .get_atc_vmid_pasid_mapping_pasid =
-                       get_atc_vmid_pasid_mapping_pasid,
-       .get_atc_vmid_pasid_mapping_valid =
-                       get_atc_vmid_pasid_mapping_valid,
-       .set_scratch_backing_va = set_scratch_backing_va,
-       .get_tile_config = get_tile_config,
-       .set_vm_context_page_table_base = set_vm_context_page_table_base,
-       .invalidate_tlbs = invalidate_tlbs,
-       .invalidate_tlbs_vmid = invalidate_tlbs_vmid,
-};
-
-struct kfd2kgd_calls *amdgpu_amdkfd_gfx_8_0_get_functions(void)
-{
-       return (struct kfd2kgd_calls *)&kfd2kgd;
-}
-
 static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
 {
        return (struct amdgpu_device *)kgd;
@@ -260,13 +169,15 @@ static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id)
        return 0;
 }
 
-static inline uint32_t get_sdma_base_addr(struct vi_sdma_mqd *m)
+static inline uint32_t get_sdma_rlc_reg_offset(struct vi_sdma_mqd *m)
 {
        uint32_t retval;
 
        retval = m->sdma_engine_id * SDMA1_REGISTER_OFFSET +
                m->sdma_queue_id * KFD_VI_SDMA_QUEUE_OFFSET;
-       pr_debug("sdma base address: 0x%x\n", retval);
+
+       pr_debug("RLC register offset for SDMA%d RLC%d: 0x%x\n",
+                       m->sdma_engine_id, m->sdma_queue_id, retval);
 
        return retval;
 }
@@ -398,59 +309,51 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
        struct vi_sdma_mqd *m;
        unsigned long end_jiffies;
-       uint32_t sdma_base_addr;
+       uint32_t sdma_rlc_reg_offset;
        uint32_t data;
 
        m = get_sdma_mqd(mqd);
-       sdma_base_addr = get_sdma_base_addr(m);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL,
+       sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(m);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL,
                m->sdmax_rlcx_rb_cntl & (~SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK));
 
        end_jiffies = msecs_to_jiffies(2000) + jiffies;
        while (true) {
-               data = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS);
+               data = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_CONTEXT_STATUS);
                if (data & SDMA0_RLC0_CONTEXT_STATUS__IDLE_MASK)
                        break;
-               if (time_after(jiffies, end_jiffies))
+               if (time_after(jiffies, end_jiffies)) {
+                       pr_err("SDMA RLC not idle in %s\n", __func__);
                        return -ETIME;
+               }
                usleep_range(500, 1000);
        }
-       if (m->sdma_engine_id) {
-               data = RREG32(mmSDMA1_GFX_CONTEXT_CNTL);
-               data = REG_SET_FIELD(data, SDMA1_GFX_CONTEXT_CNTL,
-                               RESUME_CTX, 0);
-               WREG32(mmSDMA1_GFX_CONTEXT_CNTL, data);
-       } else {
-               data = RREG32(mmSDMA0_GFX_CONTEXT_CNTL);
-               data = REG_SET_FIELD(data, SDMA0_GFX_CONTEXT_CNTL,
-                               RESUME_CTX, 0);
-               WREG32(mmSDMA0_GFX_CONTEXT_CNTL, data);
-       }
 
        data = REG_SET_FIELD(m->sdmax_rlcx_doorbell, SDMA0_RLC0_DOORBELL,
                             ENABLE, 1);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, data);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR, m->sdmax_rlcx_rb_rptr);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_DOORBELL, data);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR,
+                               m->sdmax_rlcx_rb_rptr);
 
        if (read_user_wptr(mm, wptr, data))
-               WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR, data);
+               WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR, data);
        else
-               WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR,
+               WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR,
                       m->sdmax_rlcx_rb_rptr);
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_VIRTUAL_ADDR,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_VIRTUAL_ADDR,
                                m->sdmax_rlcx_virtual_addr);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE, m->sdmax_rlcx_rb_base);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE_HI,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_BASE, m->sdmax_rlcx_rb_base);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_BASE_HI,
                        m->sdmax_rlcx_rb_base_hi);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_LO,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_ADDR_LO,
                        m->sdmax_rlcx_rb_rptr_addr_lo);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_HI,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_ADDR_HI,
                        m->sdmax_rlcx_rb_rptr_addr_hi);
 
        data = REG_SET_FIELD(m->sdmax_rlcx_rb_cntl, SDMA0_RLC0_RB_CNTL,
                             RB_ENABLE, 1);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL, data);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL, data);
 
        return 0;
 }
@@ -517,13 +420,13 @@ static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
        struct vi_sdma_mqd *m;
-       uint32_t sdma_base_addr;
+       uint32_t sdma_rlc_reg_offset;
        uint32_t sdma_rlc_rb_cntl;
 
        m = get_sdma_mqd(mqd);
-       sdma_base_addr = get_sdma_base_addr(m);
+       sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(m);
 
-       sdma_rlc_rb_cntl = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL);
+       sdma_rlc_rb_cntl = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL);
 
        if (sdma_rlc_rb_cntl & SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK)
                return true;
@@ -641,54 +544,48 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
        struct vi_sdma_mqd *m;
-       uint32_t sdma_base_addr;
+       uint32_t sdma_rlc_reg_offset;
        uint32_t temp;
        unsigned long end_jiffies = (utimeout * HZ / 1000) + jiffies;
 
        m = get_sdma_mqd(mqd);
-       sdma_base_addr = get_sdma_base_addr(m);
+       sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(m);
 
-       temp = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL);
+       temp = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL);
        temp = temp & ~SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK;
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL, temp);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL, temp);
 
        while (true) {
-               temp = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS);
+               temp = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_CONTEXT_STATUS);
                if (temp & SDMA0_RLC0_CONTEXT_STATUS__IDLE_MASK)
                        break;
-               if (time_after(jiffies, end_jiffies))
+               if (time_after(jiffies, end_jiffies)) {
+                       pr_err("SDMA RLC not idle in %s\n", __func__);
                        return -ETIME;
+               }
                usleep_range(500, 1000);
        }
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, 0);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL,
-               RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL) |
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_DOORBELL, 0);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL,
+               RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL) |
                SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK);
 
-       m->sdmax_rlcx_rb_rptr = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR);
+       m->sdmax_rlcx_rb_rptr = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR);
 
        return 0;
 }
 
-static bool get_atc_vmid_pasid_mapping_valid(struct kgd_dev *kgd,
-                                                       uint8_t vmid)
+static bool get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
+                                       uint8_t vmid, uint16_t *p_pasid)
 {
-       uint32_t reg;
+       uint32_t value;
        struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
 
-       reg = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
-       return reg & ATC_VMID0_PASID_MAPPING__VALID_MASK;
-}
+       value = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
+       *p_pasid = value & ATC_VMID0_PASID_MAPPING__PASID_MASK;
 
-static uint16_t get_atc_vmid_pasid_mapping_pasid(struct kgd_dev *kgd,
-                                                               uint8_t vmid)
-{
-       uint32_t reg;
-       struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
-
-       reg = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
-       return reg & ATC_VMID0_PASID_MAPPING__PASID_MASK;
+       return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
 }
 
 static int kgd_address_watch_disable(struct kgd_dev *kgd)
@@ -798,3 +695,28 @@ static int invalidate_tlbs_vmid(struct kgd_dev *kgd, uint16_t vmid)
        RREG32(mmVM_INVALIDATE_RESPONSE);
        return 0;
 }
+
+const struct kfd2kgd_calls gfx_v8_kfd2kgd = {
+       .program_sh_mem_settings = kgd_program_sh_mem_settings,
+       .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping,
+       .init_interrupts = kgd_init_interrupts,
+       .hqd_load = kgd_hqd_load,
+       .hqd_sdma_load = kgd_hqd_sdma_load,
+       .hqd_dump = kgd_hqd_dump,
+       .hqd_sdma_dump = kgd_hqd_sdma_dump,
+       .hqd_is_occupied = kgd_hqd_is_occupied,
+       .hqd_sdma_is_occupied = kgd_hqd_sdma_is_occupied,
+       .hqd_destroy = kgd_hqd_destroy,
+       .hqd_sdma_destroy = kgd_hqd_sdma_destroy,
+       .address_watch_disable = kgd_address_watch_disable,
+       .address_watch_execute = kgd_address_watch_execute,
+       .wave_control_execute = kgd_wave_control_execute,
+       .address_watch_get_offset = kgd_address_watch_get_offset,
+       .get_atc_vmid_pasid_mapping_info =
+                       get_atc_vmid_pasid_mapping_info,
+       .set_scratch_backing_va = set_scratch_backing_va,
+       .get_tile_config = get_tile_config,
+       .set_vm_context_page_table_base = set_vm_context_page_table_base,
+       .invalidate_tlbs = invalidate_tlbs,
+       .invalidate_tlbs_vmid = invalidate_tlbs_vmid,
+};
index e262f2ac07a3590e6360960e60248d932c71ad00..c72246f2c08af4e6531d5cf4f1189a1d7dd803af 100644 (file)
 
 #define pr_fmt(fmt) "kfd2kgd: " fmt
 
-#include <linux/module.h>
-#include <linux/fdtable.h>
-#include <linux/uaccess.h>
 #include <linux/mmu_context.h>
 
 #include "amdgpu.h"
 #include "amdgpu_amdkfd.h"
-#include "soc15_hw_ip.h"
 #include "gc/gc_9_0_offset.h"
 #include "gc/gc_9_0_sh_mask.h"
 #include "vega10_enum.h"
@@ -50,9 +46,6 @@
 #include "gmc_v9_0.h"
 
 
-#define V9_PIPE_PER_MEC                (4)
-#define V9_QUEUES_PER_PIPE_MEC (8)
-
 enum hqd_dequeue_request_type {
        NO_ACTION = 0,
        DRAIN_PIPE,
@@ -226,22 +219,21 @@ int kgd_gfx_v9_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id)
        return 0;
 }
 
-static uint32_t get_sdma_base_addr(struct amdgpu_device *adev,
+static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev,
                                unsigned int engine_id,
                                unsigned int queue_id)
 {
-       uint32_t base[2] = {
+       uint32_t sdma_engine_reg_base[2] = {
                SOC15_REG_OFFSET(SDMA0, 0,
                                 mmSDMA0_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL,
                SOC15_REG_OFFSET(SDMA1, 0,
                                 mmSDMA1_RLC0_RB_CNTL) - mmSDMA1_RLC0_RB_CNTL
        };
-       uint32_t retval;
-
-       retval = base[engine_id] + queue_id * (mmSDMA0_RLC1_RB_CNTL -
-                                              mmSDMA0_RLC0_RB_CNTL);
+       uint32_t retval = sdma_engine_reg_base[engine_id]
+               + queue_id * (mmSDMA0_RLC1_RB_CNTL - mmSDMA0_RLC0_RB_CNTL);
 
-       pr_debug("sdma base address: 0x%x\n", retval);
+       pr_debug("RLC register offset for SDMA%d RLC%d: 0x%x\n", engine_id,
+                       queue_id, retval);
 
        return retval;
 }
@@ -388,71 +380,67 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
        struct v9_sdma_mqd *m;
-       uint32_t sdma_base_addr, sdmax_gfx_context_cntl;
+       uint32_t sdma_rlc_reg_offset;
        unsigned long end_jiffies;
        uint32_t data;
        uint64_t data64;
        uint64_t __user *wptr64 = (uint64_t __user *)wptr;
 
        m = get_sdma_mqd(mqd);
-       sdma_base_addr = get_sdma_base_addr(adev, m->sdma_engine_id,
+       sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
                                            m->sdma_queue_id);
-       sdmax_gfx_context_cntl = m->sdma_engine_id ?
-               SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_GFX_CONTEXT_CNTL) :
-               SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_GFX_CONTEXT_CNTL);
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL,
                m->sdmax_rlcx_rb_cntl & (~SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK));
 
        end_jiffies = msecs_to_jiffies(2000) + jiffies;
        while (true) {
-               data = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS);
+               data = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_CONTEXT_STATUS);
                if (data & SDMA0_RLC0_CONTEXT_STATUS__IDLE_MASK)
                        break;
-               if (time_after(jiffies, end_jiffies))
+               if (time_after(jiffies, end_jiffies)) {
+                       pr_err("SDMA RLC not idle in %s\n", __func__);
                        return -ETIME;
+               }
                usleep_range(500, 1000);
        }
-       data = RREG32(sdmax_gfx_context_cntl);
-       data = REG_SET_FIELD(data, SDMA0_GFX_CONTEXT_CNTL,
-                            RESUME_CTX, 0);
-       WREG32(sdmax_gfx_context_cntl, data);
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL_OFFSET,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_DOORBELL_OFFSET,
               m->sdmax_rlcx_doorbell_offset);
 
        data = REG_SET_FIELD(m->sdmax_rlcx_doorbell, SDMA0_RLC0_DOORBELL,
                             ENABLE, 1);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, data);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR, m->sdmax_rlcx_rb_rptr);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_HI,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_DOORBELL, data);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR,
+                               m->sdmax_rlcx_rb_rptr);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_HI,
                                m->sdmax_rlcx_rb_rptr_hi);
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_MINOR_PTR_UPDATE, 1);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_MINOR_PTR_UPDATE, 1);
        if (read_user_wptr(mm, wptr64, data64)) {
-               WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR,
+               WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR,
                       lower_32_bits(data64));
-               WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR_HI,
+               WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR_HI,
                       upper_32_bits(data64));
        } else {
-               WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR,
+               WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR,
                       m->sdmax_rlcx_rb_rptr);
-               WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR_HI,
+               WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR_HI,
                       m->sdmax_rlcx_rb_rptr_hi);
        }
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_MINOR_PTR_UPDATE, 0);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_MINOR_PTR_UPDATE, 0);
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE, m->sdmax_rlcx_rb_base);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE_HI,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_BASE, m->sdmax_rlcx_rb_base);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_BASE_HI,
                        m->sdmax_rlcx_rb_base_hi);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_LO,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_ADDR_LO,
                        m->sdmax_rlcx_rb_rptr_addr_lo);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_HI,
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_ADDR_HI,
                        m->sdmax_rlcx_rb_rptr_addr_hi);
 
        data = REG_SET_FIELD(m->sdmax_rlcx_rb_cntl, SDMA0_RLC0_RB_CNTL,
                             RB_ENABLE, 1);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL, data);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL, data);
 
        return 0;
 }
@@ -462,7 +450,8 @@ static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
                             uint32_t (**dump)[2], uint32_t *n_regs)
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
-       uint32_t sdma_base_addr = get_sdma_base_addr(adev, engine_id, queue_id);
+       uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
+                       engine_id, queue_id);
        uint32_t i = 0, reg;
 #undef HQD_N_REGS
 #define HQD_N_REGS (19+6+7+10)
@@ -472,15 +461,15 @@ static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
                return -ENOMEM;
 
        for (reg = mmSDMA0_RLC0_RB_CNTL; reg <= mmSDMA0_RLC0_DOORBELL; reg++)
-               DUMP_REG(sdma_base_addr + reg);
+               DUMP_REG(sdma_rlc_reg_offset + reg);
        for (reg = mmSDMA0_RLC0_STATUS; reg <= mmSDMA0_RLC0_CSA_ADDR_HI; reg++)
-               DUMP_REG(sdma_base_addr + reg);
+               DUMP_REG(sdma_rlc_reg_offset + reg);
        for (reg = mmSDMA0_RLC0_IB_SUB_REMAIN;
             reg <= mmSDMA0_RLC0_MINOR_PTR_UPDATE; reg++)
-               DUMP_REG(sdma_base_addr + reg);
+               DUMP_REG(sdma_rlc_reg_offset + reg);
        for (reg = mmSDMA0_RLC0_MIDCMD_DATA0;
             reg <= mmSDMA0_RLC0_MIDCMD_CNTL; reg++)
-               DUMP_REG(sdma_base_addr + reg);
+               DUMP_REG(sdma_rlc_reg_offset + reg);
 
        WARN_ON_ONCE(i != HQD_N_REGS);
        *n_regs = i;
@@ -514,14 +503,14 @@ static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd)
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
        struct v9_sdma_mqd *m;
-       uint32_t sdma_base_addr;
+       uint32_t sdma_rlc_reg_offset;
        uint32_t sdma_rlc_rb_cntl;
 
        m = get_sdma_mqd(mqd);
-       sdma_base_addr = get_sdma_base_addr(adev, m->sdma_engine_id,
+       sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
                                            m->sdma_queue_id);
 
-       sdma_rlc_rb_cntl = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL);
+       sdma_rlc_rb_cntl = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL);
 
        if (sdma_rlc_rb_cntl & SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK)
                return true;
@@ -584,59 +573,52 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
 {
        struct amdgpu_device *adev = get_amdgpu_device(kgd);
        struct v9_sdma_mqd *m;
-       uint32_t sdma_base_addr;
+       uint32_t sdma_rlc_reg_offset;
        uint32_t temp;
        unsigned long end_jiffies = (utimeout * HZ / 1000) + jiffies;
 
        m = get_sdma_mqd(mqd);
-       sdma_base_addr = get_sdma_base_addr(adev, m->sdma_engine_id,
+       sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
                                            m->sdma_queue_id);
 
-       temp = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL);
+       temp = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL);
        temp = temp & ~SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK;
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL, temp);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL, temp);
 
        while (true) {
-               temp = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS);
+               temp = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_CONTEXT_STATUS);
                if (temp & SDMA0_RLC0_CONTEXT_STATUS__IDLE_MASK)
                        break;
-               if (time_after(jiffies, end_jiffies))
+               if (time_after(jiffies, end_jiffies)) {
+                       pr_err("SDMA RLC not idle in %s\n", __func__);
                        return -ETIME;
+               }
                usleep_range(500, 1000);
        }
 
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, 0);
-       WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL,
-               RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL) |
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_DOORBELL, 0);
+       WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL,
+               RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL) |
                SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK);
 
-       m->sdmax_rlcx_rb_rptr = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR);
+       m->sdmax_rlcx_rb_rptr = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR);
        m->sdmax_rlcx_rb_rptr_hi =
-               RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_HI);
+               RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_HI);
 
        return 0;
 }
 
-bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_valid(struct kgd_dev *kgd,
-                                                       uint8_t vmid)
+bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
+                                       uint8_t vmid, uint16_t *p_pasid)
 {
-       uint32_t reg;
+       uint32_t value;
        struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
 
-       reg = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING)
+       value = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING)
                     + vmid);
-       return reg & ATC_VMID0_PASID_MAPPING__VALID_MASK;
-}
-
-uint16_t kgd_gfx_v9_get_atc_vmid_pasid_mapping_pasid(struct kgd_dev *kgd,
-                                                               uint8_t vmid)
-{
-       uint32_t reg;
-       struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
+       *p_pasid = value & ATC_VMID0_PASID_MAPPING__PASID_MASK;
 
-       reg = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING)
-                    + vmid);
-       return reg & ATC_VMID0_PASID_MAPPING__PASID_MASK;
+       return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
 }
 
 static int invalidate_tlbs_with_kiq(struct amdgpu_device *adev, uint16_t pasid,
@@ -671,6 +653,8 @@ int kgd_gfx_v9_invalidate_tlbs(struct kgd_dev *kgd, uint16_t pasid)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
        int vmid, i;
+       uint16_t queried_pasid;
+       bool ret;
        struct amdgpu_ring *ring = &adev->gfx.kiq.ring;
        uint32_t flush_type = 0;
 
@@ -686,14 +670,14 @@ int kgd_gfx_v9_invalidate_tlbs(struct kgd_dev *kgd, uint16_t pasid)
        for (vmid = 0; vmid < 16; vmid++) {
                if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid))
                        continue;
-               if (kgd_gfx_v9_get_atc_vmid_pasid_mapping_valid(kgd, vmid)) {
-                       if (kgd_gfx_v9_get_atc_vmid_pasid_mapping_pasid(kgd, vmid)
-                               == pasid) {
-                               for (i = 0; i < adev->num_vmhubs; i++)
-                                       amdgpu_gmc_flush_gpu_tlb(adev, vmid,
-                                                               i, flush_type);
-                               break;
-                       }
+
+               ret = kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(kgd, vmid,
+                               &queried_pasid);
+               if (ret && queried_pasid == pasid) {
+                       for (i = 0; i < adev->num_vmhubs; i++)
+                               amdgpu_gmc_flush_gpu_tlb(adev, vmid,
+                                                       i, flush_type);
+                       break;
                }
        }
 
@@ -777,15 +761,6 @@ uint32_t kgd_gfx_v9_address_watch_get_offset(struct kgd_dev *kgd,
        return 0;
 }
 
-void kgd_gfx_v9_set_scratch_backing_va(struct kgd_dev *kgd,
-                                       uint64_t va, uint32_t vmid)
-{
-       /* No longer needed on GFXv9. The scratch base address is
-        * passed to the shader by the CP. It's the user mode driver's
-        * responsibility.
-        */
-}
-
 void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
                uint64_t page_table_base)
 {
@@ -811,7 +786,7 @@ void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmi
        gfxhub_v1_0_setup_vm_pt_regs(adev, vmid, page_table_base);
 }
 
-static const struct kfd2kgd_calls kfd2kgd = {
+const struct kfd2kgd_calls gfx_v9_kfd2kgd = {
        .program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings,
        .set_pasid_vmid_mapping = kgd_gfx_v9_set_pasid_vmid_mapping,
        .init_interrupts = kgd_gfx_v9_init_interrupts,
@@ -827,19 +802,11 @@ static const struct kfd2kgd_calls kfd2kgd = {
        .address_watch_execute = kgd_gfx_v9_address_watch_execute,
        .wave_control_execute = kgd_gfx_v9_wave_control_execute,
        .address_watch_get_offset = kgd_gfx_v9_address_watch_get_offset,
-       .get_atc_vmid_pasid_mapping_pasid =
-                       kgd_gfx_v9_get_atc_vmid_pasid_mapping_pasid,
-       .get_atc_vmid_pasid_mapping_valid =
-                       kgd_gfx_v9_get_atc_vmid_pasid_mapping_valid,
-       .set_scratch_backing_va = kgd_gfx_v9_set_scratch_backing_va,
+       .get_atc_vmid_pasid_mapping_info =
+                       kgd_gfx_v9_get_atc_vmid_pasid_mapping_info,
        .get_tile_config = kgd_gfx_v9_get_tile_config,
        .set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base,
        .invalidate_tlbs = kgd_gfx_v9_invalidate_tlbs,
        .invalidate_tlbs_vmid = kgd_gfx_v9_invalidate_tlbs_vmid,
        .get_hive_id = amdgpu_amdkfd_get_hive_id,
 };
-
-struct kfd2kgd_calls *amdgpu_amdkfd_gfx_9_0_get_functions(void)
-{
-       return (struct kfd2kgd_calls *)&kfd2kgd;
-}
index 26d8879bff9d04faa31cd77fa65ec873458be969..d9e9ad22b2bd98763a01a859301331d582840812 100644 (file)
@@ -55,14 +55,10 @@ uint32_t kgd_gfx_v9_address_watch_get_offset(struct kgd_dev *kgd,
                                        unsigned int watch_point_id,
                                        unsigned int reg_offset);
 
-bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_valid(struct kgd_dev *kgd,
-               uint8_t vmid);
-uint16_t kgd_gfx_v9_get_atc_vmid_pasid_mapping_pasid(struct kgd_dev *kgd,
-               uint8_t vmid);
+bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd,
+                                       uint8_t vmid, uint16_t *p_pasid);
 void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
                uint64_t page_table_base);
-void kgd_gfx_v9_set_scratch_backing_va(struct kgd_dev *kgd,
-                                       uint64_t va, uint32_t vmid);
 int kgd_gfx_v9_invalidate_tlbs(struct kgd_dev *kgd, uint16_t pasid);
 int kgd_gfx_v9_invalidate_tlbs_vmid(struct kgd_dev *kgd, uint16_t vmid);
 int kgd_gfx_v9_get_tile_config(struct kgd_dev *kgd,
index 6d021ecc8d598fad17d6a092ea0b6a1136ed0dd3..a07897e21526145e6ee28fd9b9f38efaedb4d4e2 100644 (file)
 #include "amdgpu_amdkfd.h"
 #include "amdgpu_dma_buf.h"
 
-/* Special VM and GART address alignment needed for VI pre-Fiji due to
- * a HW bug.
- */
-#define VI_BO_SIZE_ALIGN (0x8000)
-
 /* BO flag to indicate a KFD userptr BO */
 #define AMDGPU_AMDKFD_USERPTR_BO (1ULL << 63)
 
@@ -349,13 +344,46 @@ static int vm_update_pds(struct amdgpu_vm *vm, struct amdgpu_sync *sync)
        struct amdgpu_device *adev = amdgpu_ttm_adev(pd->tbo.bdev);
        int ret;
 
-       ret = amdgpu_vm_update_directories(adev, vm);
+       ret = amdgpu_vm_update_pdes(adev, vm, false);
        if (ret)
                return ret;
 
        return amdgpu_sync_fence(NULL, sync, vm->last_update, false);
 }
 
+static uint64_t get_pte_flags(struct amdgpu_device *adev, struct kgd_mem *mem)
+{
+       struct amdgpu_device *bo_adev = amdgpu_ttm_adev(mem->bo->tbo.bdev);
+       bool coherent = mem->alloc_flags & ALLOC_MEM_FLAGS_COHERENT;
+       uint32_t mapping_flags;
+
+       mapping_flags = AMDGPU_VM_PAGE_READABLE;
+       if (mem->alloc_flags & ALLOC_MEM_FLAGS_WRITABLE)
+               mapping_flags |= AMDGPU_VM_PAGE_WRITEABLE;
+       if (mem->alloc_flags & ALLOC_MEM_FLAGS_EXECUTABLE)
+               mapping_flags |= AMDGPU_VM_PAGE_EXECUTABLE;
+
+       switch (adev->asic_type) {
+       case CHIP_ARCTURUS:
+               if (mem->alloc_flags & ALLOC_MEM_FLAGS_VRAM) {
+                       if (bo_adev == adev)
+                               mapping_flags |= coherent ?
+                                       AMDGPU_VM_MTYPE_CC : AMDGPU_VM_MTYPE_RW;
+                       else
+                               mapping_flags |= AMDGPU_VM_MTYPE_UC;
+               } else {
+                       mapping_flags |= coherent ?
+                               AMDGPU_VM_MTYPE_UC : AMDGPU_VM_MTYPE_NC;
+               }
+               break;
+       default:
+               mapping_flags |= coherent ?
+                       AMDGPU_VM_MTYPE_UC : AMDGPU_VM_MTYPE_NC;
+       }
+
+       return amdgpu_gem_va_map_flags(adev, mapping_flags);
+}
+
 /* add_bo_to_vm - Add a BO to a VM
  *
  * Everything that needs to bo done only once when a BO is first added
@@ -404,8 +432,7 @@ static int add_bo_to_vm(struct amdgpu_device *adev, struct kgd_mem *mem,
        }
 
        bo_va_entry->va = va;
-       bo_va_entry->pte_flags = amdgpu_gmc_get_pte_flags(adev,
-                                                        mem->mapping_flags);
+       bo_va_entry->pte_flags = get_pte_flags(adev, mem);
        bo_va_entry->kgd_dev = (void *)adev;
        list_add(&bo_va_entry->bo_list, list_bo_va);
 
@@ -1079,10 +1106,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
        uint64_t user_addr = 0;
        struct amdgpu_bo *bo;
        struct amdgpu_bo_param bp;
-       int byte_align;
        u32 domain, alloc_domain;
        u64 alloc_flags;
-       uint32_t mapping_flags;
        int ret;
 
        /*
@@ -1135,25 +1160,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
        if ((*mem)->aql_queue)
                size = size >> 1;
 
-       /* Workaround for TLB bug on older VI chips */
-       byte_align = (adev->family == AMDGPU_FAMILY_VI &&
-                       adev->asic_type != CHIP_FIJI &&
-                       adev->asic_type != CHIP_POLARIS10 &&
-                       adev->asic_type != CHIP_POLARIS11 &&
-                       adev->asic_type != CHIP_POLARIS12 &&
-                       adev->asic_type != CHIP_VEGAM) ?
-                       VI_BO_SIZE_ALIGN : 1;
-
-       mapping_flags = AMDGPU_VM_PAGE_READABLE;
-       if (flags & ALLOC_MEM_FLAGS_WRITABLE)
-               mapping_flags |= AMDGPU_VM_PAGE_WRITEABLE;
-       if (flags & ALLOC_MEM_FLAGS_EXECUTABLE)
-               mapping_flags |= AMDGPU_VM_PAGE_EXECUTABLE;
-       if (flags & ALLOC_MEM_FLAGS_COHERENT)
-               mapping_flags |= AMDGPU_VM_MTYPE_UC;
-       else
-               mapping_flags |= AMDGPU_VM_MTYPE_NC;
-       (*mem)->mapping_flags = mapping_flags;
+       (*mem)->alloc_flags = flags;
 
        amdgpu_sync_create(&(*mem)->sync);
 
@@ -1168,7 +1175,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
 
        memset(&bp, 0, sizeof(bp));
        bp.size = size;
-       bp.byte_align = byte_align;
+       bp.byte_align = 1;
        bp.domain = alloc_domain;
        bp.flags = alloc_flags;
        bp.type = bo_type;
@@ -1626,9 +1633,10 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd,
 
        INIT_LIST_HEAD(&(*mem)->bo_va_list);
        mutex_init(&(*mem)->lock);
-       (*mem)->mapping_flags =
-               AMDGPU_VM_PAGE_READABLE | AMDGPU_VM_PAGE_WRITEABLE |
-               AMDGPU_VM_PAGE_EXECUTABLE | AMDGPU_VM_MTYPE_NC;
+       (*mem)->alloc_flags =
+               ((bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) ?
+                ALLOC_MEM_FLAGS_VRAM : ALLOC_MEM_FLAGS_GTT) |
+               ALLOC_MEM_FLAGS_WRITABLE | ALLOC_MEM_FLAGS_EXECUTABLE;
 
        (*mem)->bo = amdgpu_bo_ref(bo);
        (*mem)->va = va;
index 1c9d40f97a9b225979a743f0d1cccaf51ac30452..72232fccf61a75d5a90d9e56542395d7ede99f50 100644 (file)
@@ -2038,6 +2038,11 @@ int amdgpu_atombios_init(struct amdgpu_device *adev)
        if (adev->is_atom_fw) {
                amdgpu_atomfirmware_scratch_regs_init(adev);
                amdgpu_atomfirmware_allocate_fb_scratch(adev);
+               ret = amdgpu_atomfirmware_get_mem_train_fb_loc(adev);
+               if (ret) {
+                       DRM_ERROR("Failed to get mem train fb location.\n");
+                       return ret;
+               }
        } else {
                amdgpu_atombios_scratch_regs_init(adev);
                amdgpu_atombios_allocate_fb_scratch(adev);
index daf687428cdb7a08fbb69e87bf1dcf8e19240f5d..ff4eb96bdfb542bd259af896d412bba4a2827946 100644 (file)
@@ -27,6 +27,7 @@
 #include "amdgpu_atomfirmware.h"
 #include "atom.h"
 #include "atombios.h"
+#include "soc15_hw_ip.h"
 
 bool amdgpu_atomfirmware_gpu_supports_virtualization(struct amdgpu_device *adev)
 {
@@ -120,65 +121,14 @@ union vram_info {
        struct atom_vram_info_header_v2_3 v23;
        struct atom_vram_info_header_v2_4 v24;
 };
-/*
- * Return vram width from integrated system info table, if available,
- * or 0 if not.
- */
-int amdgpu_atomfirmware_get_vram_width(struct amdgpu_device *adev)
-{
-       struct amdgpu_mode_info *mode_info = &adev->mode_info;
-       int index;
-       u16 data_offset, size;
-       union igp_info *igp_info;
-       union vram_info *vram_info;
-       u32 mem_channel_number;
-       u32 mem_channel_width;
-       u8 frev, crev;
-
-       if (adev->flags & AMD_IS_APU)
-               index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
-                                                   integratedsysteminfo);
-       else
-               index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
-                                                   vram_info);
 
-       /* get any igp specific overrides */
-       if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, &size,
-                                  &frev, &crev, &data_offset)) {
-               if (adev->flags & AMD_IS_APU) {
-                       igp_info = (union igp_info *)
-                               (mode_info->atom_context->bios + data_offset);
-                       switch (crev) {
-                       case 11:
-                               mem_channel_number = igp_info->v11.umachannelnumber;
-                               /* channel width is 64 */
-                               return mem_channel_number * 64;
-                       default:
-                               return 0;
-                       }
-               } else {
-                       vram_info = (union vram_info *)
-                               (mode_info->atom_context->bios + data_offset);
-                       switch (crev) {
-                       case 3:
-                               mem_channel_number = vram_info->v23.vram_module[0].channel_num;
-                               mem_channel_width = vram_info->v23.vram_module[0].channel_width;
-                               return mem_channel_number * (1 << mem_channel_width);
-                       case 4:
-                               mem_channel_number = vram_info->v24.vram_module[0].channel_num;
-                               mem_channel_width = vram_info->v24.vram_module[0].channel_width;
-                               return mem_channel_number * (1 << mem_channel_width);
-                       default:
-                               return 0;
-                       }
-               }
-       }
-
-       return 0;
-}
+union vram_module {
+       struct atom_vram_module_v9 v9;
+       struct atom_vram_module_v10 v10;
+};
 
-static int convert_atom_mem_type_to_vram_type (struct amdgpu_device *adev,
-                                              int atom_mem_type)
+static int convert_atom_mem_type_to_vram_type(struct amdgpu_device *adev,
+                                             int atom_mem_type)
 {
        int vram_type;
 
@@ -219,19 +169,25 @@ static int convert_atom_mem_type_to_vram_type (struct amdgpu_device *adev,
 
        return vram_type;
 }
-/*
- * Return vram type from either integrated system info table
- * or umc info table, if available, or 0 (TYPE_UNKNOWN) if not
- */
-int amdgpu_atomfirmware_get_vram_type(struct amdgpu_device *adev)
+
+
+int
+amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
+                                 int *vram_width, int *vram_type,
+                                 int *vram_vendor)
 {
        struct amdgpu_mode_info *mode_info = &adev->mode_info;
-       int index;
+       int index, i = 0;
        u16 data_offset, size;
        union igp_info *igp_info;
        union vram_info *vram_info;
+       union vram_module *vram_module;
        u8 frev, crev;
        u8 mem_type;
+       u8 mem_vendor;
+       u32 mem_channel_number;
+       u32 mem_channel_width;
+       u32 module_id;
 
        if (adev->flags & AMD_IS_APU)
                index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
@@ -239,6 +195,7 @@ int amdgpu_atomfirmware_get_vram_type(struct amdgpu_device *adev)
        else
                index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
                                                    vram_info);
+
        if (amdgpu_atom_parse_data_header(mode_info->atom_context,
                                          index, &size,
                                          &frev, &crev, &data_offset)) {
@@ -247,25 +204,67 @@ int amdgpu_atomfirmware_get_vram_type(struct amdgpu_device *adev)
                                (mode_info->atom_context->bios + data_offset);
                        switch (crev) {
                        case 11:
+                               mem_channel_number = igp_info->v11.umachannelnumber;
+                               /* channel width is 64 */
+                               if (vram_width)
+                                       *vram_width = mem_channel_number * 64;
                                mem_type = igp_info->v11.memorytype;
-                               return convert_atom_mem_type_to_vram_type(adev, mem_type);
+                               if (vram_type)
+                                       *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
+                               break;
                        default:
-                               return 0;
+                               return -EINVAL;
                        }
                } else {
                        vram_info = (union vram_info *)
                                (mode_info->atom_context->bios + data_offset);
+                       module_id = (RREG32(adev->bios_scratch_reg_offset + 4) & 0x00ff0000) >> 16;
                        switch (crev) {
                        case 3:
-                               mem_type = vram_info->v23.vram_module[0].memory_type;
-                               return convert_atom_mem_type_to_vram_type(adev, mem_type);
+                               if (module_id > vram_info->v23.vram_module_num)
+                                       module_id = 0;
+                               vram_module = (union vram_module *)vram_info->v23.vram_module;
+                               while (i < module_id) {
+                                       vram_module = (union vram_module *)
+                                               ((u8 *)vram_module + vram_module->v9.vram_module_size);
+                                       i++;
+                               }
+                               mem_type = vram_module->v9.memory_type;
+                               if (vram_type)
+                                       *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
+                               mem_channel_number = vram_module->v9.channel_num;
+                               mem_channel_width = vram_module->v9.channel_width;
+                               if (vram_width)
+                                       *vram_width = mem_channel_number * (1 << mem_channel_width);
+                               mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;
+                               if (vram_vendor)
+                                       *vram_vendor = mem_vendor;
+                               break;
                        case 4:
-                               mem_type = vram_info->v24.vram_module[0].memory_type;
-                               return convert_atom_mem_type_to_vram_type(adev, mem_type);
+                               if (module_id > vram_info->v24.vram_module_num)
+                                       module_id = 0;
+                               vram_module = (union vram_module *)vram_info->v24.vram_module;
+                               while (i < module_id) {
+                                       vram_module = (union vram_module *)
+                                               ((u8 *)vram_module + vram_module->v10.vram_module_size);
+                                       i++;
+                               }
+                               mem_type = vram_module->v10.memory_type;
+                               if (vram_type)
+                                       *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
+                               mem_channel_number = vram_module->v10.channel_num;
+                               mem_channel_width = vram_module->v10.channel_width;
+                               if (vram_width)
+                                       *vram_width = mem_channel_number * (1 << mem_channel_width);
+                               mem_vendor = (vram_module->v10.vender_rev_id) & 0xF;
+                               if (vram_vendor)
+                                       *vram_vendor = mem_vendor;
+                               break;
                        default:
-                               return 0;
+                               return -EINVAL;
                        }
                }
+
        }
 
        return 0;
@@ -464,3 +463,138 @@ int amdgpu_atomfirmware_get_gfx_info(struct amdgpu_device *adev)
        }
        return -EINVAL;
 }
+
+/*
+ * Check if VBIOS supports GDDR6 training data save/restore
+ */
+static bool gddr6_mem_train_vbios_support(struct amdgpu_device *adev)
+{
+       uint16_t data_offset;
+       int index;
+
+       index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
+                                           firmwareinfo);
+       if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, NULL,
+                                         NULL, NULL, &data_offset)) {
+               struct atom_firmware_info_v3_1 *firmware_info =
+                       (struct atom_firmware_info_v3_1 *)(adev->mode_info.atom_context->bios +
+                                                          data_offset);
+
+               DRM_DEBUG("atom firmware capability:0x%08x.\n",
+                         le32_to_cpu(firmware_info->firmware_capability));
+
+               if (le32_to_cpu(firmware_info->firmware_capability) &
+                   ATOM_FIRMWARE_CAP_ENABLE_2STAGE_BIST_TRAINING)
+                       return true;
+       }
+
+       return false;
+}
+
+static int gddr6_mem_train_support(struct amdgpu_device *adev)
+{
+       int ret;
+       uint32_t major, minor, revision, hw_v;
+
+       if (gddr6_mem_train_vbios_support(adev)) {
+               amdgpu_discovery_get_ip_version(adev, MP0_HWID, &major, &minor, &revision);
+               hw_v = HW_REV(major, minor, revision);
+               /*
+                * treat 0 revision as a special case since register for MP0 and MMHUB is missing
+                * for some Navi10 A0, preventing driver from discovering the hwip information since
+                * none of the functions will be initialized, it should not cause any problems
+                */
+               switch (hw_v) {
+               case HW_REV(11, 0, 0):
+               case HW_REV(11, 0, 5):
+                       ret = 1;
+                       break;
+               default:
+                       DRM_ERROR("memory training vbios supports but psp hw(%08x)"
+                                 " doesn't support!\n", hw_v);
+                       ret = -1;
+                       break;
+               }
+       } else {
+               ret = 0;
+               hw_v = -1;
+       }
+
+
+       DRM_DEBUG("mp0 hw_v %08x, ret:%d.\n", hw_v, ret);
+       return ret;
+}
+
+int amdgpu_atomfirmware_get_mem_train_fb_loc(struct amdgpu_device *adev)
+{
+       struct atom_context *ctx = adev->mode_info.atom_context;
+       unsigned char *bios = ctx->bios;
+       struct vram_reserve_block *reserved_block;
+       int index, block_number;
+       uint8_t frev, crev;
+       uint16_t data_offset, size;
+       uint32_t start_address_in_kb;
+       uint64_t offset;
+       int ret;
+
+       adev->fw_vram_usage.mem_train_support = false;
+
+       if (adev->asic_type != CHIP_NAVI10 &&
+           adev->asic_type != CHIP_NAVI14)
+               return 0;
+
+       if (amdgpu_sriov_vf(adev))
+               return 0;
+
+       ret = gddr6_mem_train_support(adev);
+       if (ret == -1)
+               return -EINVAL;
+       else if (ret == 0)
+               return 0;
+
+       index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
+                                           vram_usagebyfirmware);
+       ret = amdgpu_atom_parse_data_header(ctx, index, &size, &frev, &crev,
+                                           &data_offset);
+       if (ret == 0) {
+               DRM_ERROR("parse data header failed.\n");
+               return -EINVAL;
+       }
+
+       DRM_DEBUG("atom firmware common table header size:0x%04x, frev:0x%02x,"
+                 " crev:0x%02x, data_offset:0x%04x.\n", size, frev, crev, data_offset);
+       /* only support 2.1+ */
+       if (((uint16_t)frev << 8 | crev) < 0x0201) {
+               DRM_ERROR("frev:0x%02x, crev:0x%02x < 2.1 !\n", frev, crev);
+               return -EINVAL;
+       }
+
+       reserved_block = (struct vram_reserve_block *)
+               (bios + data_offset + sizeof(struct atom_common_table_header));
+       block_number = ((unsigned int)size - sizeof(struct atom_common_table_header))
+               / sizeof(struct vram_reserve_block);
+       reserved_block += (block_number > 0) ? block_number-1 : 0;
+       DRM_DEBUG("block_number:0x%04x, last block: 0x%08xkb sz, %dkb fw, %dkb drv.\n",
+                 block_number,
+                 le32_to_cpu(reserved_block->start_address_in_kb),
+                 le16_to_cpu(reserved_block->used_by_firmware_in_kb),
+                 le16_to_cpu(reserved_block->used_by_driver_in_kb));
+       if (reserved_block->used_by_firmware_in_kb > 0) {
+               start_address_in_kb = le32_to_cpu(reserved_block->start_address_in_kb);
+               offset = (uint64_t)start_address_in_kb * ONE_KiB;
+               if ((offset & (ONE_MiB - 1)) < (4 * ONE_KiB + 1) ) {
+                       offset -= ONE_MiB;
+               }
+
+               offset &= ~(ONE_MiB - 1);
+               adev->fw_vram_usage.mem_train_fb_loc = offset;
+               adev->fw_vram_usage.mem_train_support = true;
+               DRM_DEBUG("mem_train_fb_loc:0x%09llx.\n", offset);
+               ret = 0;
+       } else {
+               DRM_ERROR("used_by_firmware_in_kb is 0!\n");
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
index 5ec6f92f353cbf8da8e4b6f7130d6c9aaa4d7c9a..f871af5ea6f37ba30ee72f0f4f78e682d954c9f3 100644 (file)
@@ -29,8 +29,9 @@
 bool amdgpu_atomfirmware_gpu_supports_virtualization(struct amdgpu_device *adev);
 void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev);
 int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev);
-int amdgpu_atomfirmware_get_vram_width(struct amdgpu_device *adev);
-int amdgpu_atomfirmware_get_vram_type(struct amdgpu_device *adev);
+int amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
+       int *vram_width, int *vram_type, int *vram_vendor);
+int amdgpu_atomfirmware_get_mem_train_fb_loc(struct amdgpu_device *adev);
 int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev);
 int amdgpu_atomfirmware_get_gfx_info(struct amdgpu_device *adev);
 bool amdgpu_atomfirmware_mem_ecc_supported(struct amdgpu_device *adev);
index 3e35a8f2c5e553e4c714deff5e838ac1510a2f59..a97fb759e2f42a94b004743219881f47e79a20ee 100644 (file)
@@ -613,17 +613,7 @@ static bool amdgpu_atpx_detect(void)
        bool d3_supported = false;
        struct pci_dev *parent_pdev;
 
-       while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
-               vga_count++;
-
-               has_atpx |= (amdgpu_atpx_pci_probe_handle(pdev) == true);
-
-               parent_pdev = pci_upstream_bridge(pdev);
-               d3_supported |= parent_pdev && parent_pdev->bridge_d3;
-               amdgpu_atpx_get_quirks(pdev);
-       }
-
-       while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
+       while ((pdev = pci_get_class(PCI_BASE_CLASS_DISPLAY << 16, pdev)) != NULL) {
                vga_count++;
 
                has_atpx |= (amdgpu_atpx_pci_probe_handle(pdev) == true);
index 61e38e43ad1d524f811ad2d7dfaf155a16d97f89..85b0515c0fdcf7c0e69558988fdbb534c9efa302 100644 (file)
@@ -140,7 +140,12 @@ int amdgpu_bo_list_create(struct amdgpu_device *adev, struct drm_file *filp,
        return 0;
 
 error_free:
-       while (i--) {
+       for (i = 0; i < last_entry; ++i) {
+               struct amdgpu_bo *bo = ttm_to_amdgpu_bo(array[i].tv.bo);
+
+               amdgpu_bo_unref(&bo);
+       }
+       for (i = first_userptr; i < num_entries; ++i) {
                struct amdgpu_bo *bo = ttm_to_amdgpu_bo(array[i].tv.bo);
 
                amdgpu_bo_unref(&bo);
index d8729285f7310f510858a971559388b21f65a6a7..a62cbc8199de0a6ce786238908a7fb4a98b3f810 100644 (file)
@@ -1019,8 +1019,12 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
                         */
                        if (amdgpu_connector->shared_ddc && (ret == connector_status_connected)) {
                                struct drm_connector *list_connector;
+                               struct drm_connector_list_iter iter;
                                struct amdgpu_connector *list_amdgpu_connector;
-                               list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) {
+
+                               drm_connector_list_iter_begin(dev, &iter);
+                               drm_for_each_connector_iter(list_connector,
+                                                           &iter) {
                                        if (connector == list_connector)
                                                continue;
                                        list_amdgpu_connector = to_amdgpu_connector(list_connector);
@@ -1037,6 +1041,7 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
                                                }
                                        }
                                }
+                               drm_connector_list_iter_end(&iter);
                        }
                }
        }
@@ -1494,6 +1499,7 @@ amdgpu_connector_add(struct amdgpu_device *adev,
 {
        struct drm_device *dev = adev->ddev;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
        struct amdgpu_connector *amdgpu_connector;
        struct amdgpu_connector_atom_dig *amdgpu_dig_connector;
        struct drm_encoder *encoder;
@@ -1508,10 +1514,12 @@ amdgpu_connector_add(struct amdgpu_device *adev,
                return;
 
        /* see if we already added it */
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                amdgpu_connector = to_amdgpu_connector(connector);
                if (amdgpu_connector->connector_id == connector_id) {
                        amdgpu_connector->devices |= supported_device;
+                       drm_connector_list_iter_end(&iter);
                        return;
                }
                if (amdgpu_connector->ddc_bus && i2c_bus->valid) {
@@ -1526,6 +1534,7 @@ amdgpu_connector_add(struct amdgpu_device *adev,
                        }
                }
        }
+       drm_connector_list_iter_end(&iter);
 
        /* check if it's a dp bridge */
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
index 2e53feed40e230f7d7f0733678932ef07873db0f..6cfaa984cc3d6f47171190c95bb018ca68e34e39 100644 (file)
@@ -35,6 +35,7 @@
 #include "amdgpu_trace.h"
 #include "amdgpu_gmc.h"
 #include "amdgpu_gem.h"
+#include "amdgpu_ras.h"
 
 static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p,
                                      struct drm_amdgpu_cs_chunk_fence *data,
@@ -449,75 +450,12 @@ static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p,
        return r;
 }
 
-/* Last resort, try to evict something from the current working set */
-static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p,
-                               struct amdgpu_bo *validated)
-{
-       uint32_t domain = validated->allowed_domains;
-       struct ttm_operation_ctx ctx = { true, false };
-       int r;
-
-       if (!p->evictable)
-               return false;
-
-       for (;&p->evictable->tv.head != &p->validated;
-            p->evictable = list_prev_entry(p->evictable, tv.head)) {
-
-               struct amdgpu_bo_list_entry *candidate = p->evictable;
-               struct amdgpu_bo *bo = ttm_to_amdgpu_bo(candidate->tv.bo);
-               struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
-               bool update_bytes_moved_vis;
-               uint32_t other;
-
-               /* If we reached our current BO we can forget it */
-               if (bo == validated)
-                       break;
-
-               /* We can't move pinned BOs here */
-               if (bo->pin_count)
-                       continue;
-
-               other = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
-
-               /* Check if this BO is in one of the domains we need space for */
-               if (!(other & domain))
-                       continue;
-
-               /* Check if we can move this BO somewhere else */
-               other = bo->allowed_domains & ~domain;
-               if (!other)
-                       continue;
-
-               /* Good we can try to move this BO somewhere else */
-               update_bytes_moved_vis =
-                               !amdgpu_gmc_vram_full_visible(&adev->gmc) &&
-                               amdgpu_bo_in_cpu_visible_vram(bo);
-               amdgpu_bo_placement_from_domain(bo, other);
-               r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
-               p->bytes_moved += ctx.bytes_moved;
-               if (update_bytes_moved_vis)
-                       p->bytes_moved_vis += ctx.bytes_moved;
-
-               if (unlikely(r))
-                       break;
-
-               p->evictable = list_prev_entry(p->evictable, tv.head);
-               list_move(&candidate->tv.head, &p->validated);
-
-               return true;
-       }
-
-       return false;
-}
-
 static int amdgpu_cs_validate(void *param, struct amdgpu_bo *bo)
 {
        struct amdgpu_cs_parser *p = param;
        int r;
 
-       do {
-               r = amdgpu_cs_bo_validate(p, bo);
-       } while (r == -ENOMEM && amdgpu_cs_try_evict(p, bo));
+       r = amdgpu_cs_bo_validate(p, bo);
        if (r)
                return r;
 
@@ -536,7 +474,6 @@ static int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p,
 
        list_for_each_entry(lobj, validated, tv.head) {
                struct amdgpu_bo *bo = ttm_to_amdgpu_bo(lobj->tv.bo);
-               bool binding_userptr = false;
                struct mm_struct *usermm;
 
                usermm = amdgpu_ttm_tt_get_usermm(bo->tbo.ttm);
@@ -553,20 +490,14 @@ static int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p,
 
                        amdgpu_ttm_tt_set_user_pages(bo->tbo.ttm,
                                                     lobj->user_pages);
-                       binding_userptr = true;
                }
 
-               if (p->evictable == lobj)
-                       p->evictable = NULL;
-
                r = amdgpu_cs_validate(p, bo);
                if (r)
                        return r;
 
-               if (binding_userptr) {
-                       kvfree(lobj->user_pages);
-                       lobj->user_pages = NULL;
-               }
+               kvfree(lobj->user_pages);
+               lobj->user_pages = NULL;
        }
        return 0;
 }
@@ -661,9 +592,6 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
                                          &p->bytes_moved_vis_threshold);
        p->bytes_moved = 0;
        p->bytes_moved_vis = 0;
-       p->evictable = list_last_entry(&p->validated,
-                                      struct amdgpu_bo_list_entry,
-                                      tv.head);
 
        r = amdgpu_vm_validate_pt_bos(p->adev, &fpriv->vm,
                                      amdgpu_cs_validate, p);
@@ -915,7 +843,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
        if (r)
                return r;
 
-       r = amdgpu_vm_update_directories(adev, vm);
+       r = amdgpu_vm_update_pdes(adev, vm, false);
        if (r)
                return r;
 
@@ -1359,6 +1287,9 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        bool reserved_buffers = false;
        int i, r;
 
+       if (amdgpu_ras_intr_triggered())
+               return -EHWPOISON;
+
        if (!adev->accel_working)
                return -EBUSY;
 
index 5652cc72ed3a9b3adcf004a654e8be57b9cd2552..cb94627fc0f4984a095e7c0f0bf1374258ac1b18 100644 (file)
@@ -1077,8 +1077,7 @@ static int amdgpu_debugfs_ib_preempt(void *data, u64 val)
 
        ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched);
 
-       if (fences)
-               kfree(fences);
+       kfree(fences);
 
        return 0;
 }
@@ -1103,8 +1102,7 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
 
 void amdgpu_debugfs_preempt_cleanup(struct amdgpu_device *adev)
 {
-       if (adev->debugfs_preempt)
-               debugfs_remove(adev->debugfs_preempt);
+       debugfs_remove(adev->debugfs_preempt);
 }
 
 #else
index 5a1939dbd4e3e6785066854f4224f6ffe881f7fd..46218b36dc9ed0023f8154121f21d0cf803e8cef 100644 (file)
@@ -65,6 +65,8 @@
 #include "amdgpu_ras.h"
 #include "amdgpu_pmu.h"
 
+#include <linux/suspend.h>
+
 MODULE_FIRMWARE("amdgpu/vega10_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/vega12_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/raven_gpu_info.bin");
@@ -78,7 +80,7 @@ MODULE_FIRMWARE("amdgpu/navi12_gpu_info.bin");
 
 #define AMDGPU_RESUME_MS               2000
 
-static const char *amdgpu_asic_name[] = {
+const char *amdgpu_asic_name[] = {
        "TAHITI",
        "PITCAIRN",
        "VERDE",
@@ -151,6 +153,36 @@ bool amdgpu_device_is_px(struct drm_device *dev)
        return false;
 }
 
+/**
+ * VRAM access helper functions.
+ *
+ * amdgpu_device_vram_access - read/write a buffer in vram
+ *
+ * @adev: amdgpu_device pointer
+ * @pos: offset of the buffer in vram
+ * @buf: virtual address of the buffer in system memory
+ * @size: read/write size, sizeof(@buf) must > @size
+ * @write: true - write to vram, otherwise - read from vram
+ */
+void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
+                              uint32_t *buf, size_t size, bool write)
+{
+       uint64_t last;
+       unsigned long flags;
+
+       last = size - 4;
+       for (last += pos; pos <= last; pos += 4) {
+               spin_lock_irqsave(&adev->mmio_idx_lock, flags);
+               WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)pos) | 0x80000000);
+               WREG32_NO_KIQ(mmMM_INDEX_HI, pos >> 31);
+               if (write)
+                       WREG32_NO_KIQ(mmMM_DATA, *buf++);
+               else
+                       *buf++ = RREG32_NO_KIQ(mmMM_DATA);
+               spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
+       }
+}
+
 /*
  * MMIO register access helper functions.
  */
@@ -1023,12 +1055,6 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev)
 
        amdgpu_device_check_block_size(adev);
 
-       ret = amdgpu_device_get_job_timeout_settings(adev);
-       if (ret) {
-               dev_err(adev->dev, "invalid lockup_timeout parameter syntax\n");
-               return ret;
-       }
-
        adev->firmware.load_type = amdgpu_ucode_get_load_type(adev, amdgpu_fw_load_type);
 
        return ret;
@@ -1469,6 +1495,9 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
                        (const struct gpu_info_firmware_v1_0 *)(adev->firmware.gpu_info_fw->data +
                                                                le32_to_cpu(hdr->header.ucode_array_offset_bytes));
 
+               if (amdgpu_discovery && adev->asic_type >= CHIP_NAVI10)
+                       goto parse_soc_bounding_box;
+
                adev->gfx.config.max_shader_engines = le32_to_cpu(gpu_info_fw->gc_num_se);
                adev->gfx.config.max_cu_per_sh = le32_to_cpu(gpu_info_fw->gc_num_cu_per_sh);
                adev->gfx.config.max_sh_per_se = le32_to_cpu(gpu_info_fw->gc_num_sh_per_se);
@@ -1496,7 +1525,13 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
                        adev->gfx.config.num_packer_per_sc =
                                le32_to_cpu(gpu_info_fw->num_packer_per_sc);
                }
+
+parse_soc_bounding_box:
 #ifdef CONFIG_DRM_AMD_DC_DCN2_0
+               /*
+                * soc bounding box info is not integrated in disocovery table,
+                * we always need to parse it from gpu info firmware.
+                */
                if (hdr->version_minor == 2) {
                        const struct gpu_info_firmware_v1_2 *gpu_info_fw =
                                (const struct gpu_info_firmware_v1_2 *)(adev->firmware.gpu_info_fw->data +
@@ -1613,6 +1648,9 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
        if (r)
                return r;
 
+       if (amdgpu_discovery && adev->asic_type >= CHIP_NAVI10)
+               amdgpu_discovery_get_gfx_info(adev);
+
        amdgpu_amdkfd_device_probe(adev);
 
        if (amdgpu_sriov_vf(adev)) {
@@ -1622,7 +1660,7 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
        }
 
        adev->pm.pp_feature = amdgpu_pp_feature_mask;
-       if (amdgpu_sriov_vf(adev))
+       if (amdgpu_sriov_vf(adev) || sched_policy == KFD_SCHED_POLICY_NO_HWS)
                adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
 
        for (i = 0; i < adev->num_ip_blocks; i++) {
@@ -2231,17 +2269,17 @@ static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev)
                /* handle putting the SMC in the appropriate state */
                if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) {
                        if (is_support_sw_smu(adev)) {
-                               /* todo */
+                               r = smu_set_mp1_state(&adev->smu, adev->mp1_state);
                        } else if (adev->powerplay.pp_funcs &&
                                           adev->powerplay.pp_funcs->set_mp1_state) {
                                r = adev->powerplay.pp_funcs->set_mp1_state(
                                        adev->powerplay.pp_handle,
                                        adev->mp1_state);
-                               if (r) {
-                                       DRM_ERROR("SMC failed to set mp1 state %d, %d\n",
-                                                 adev->mp1_state, r);
-                                       return r;
-                               }
+                       }
+                       if (r) {
+                               DRM_ERROR("SMC failed to set mp1 state %d, %d\n",
+                                         adev->mp1_state, r);
+                               return r;
                        }
                }
 
@@ -2556,6 +2594,73 @@ static void amdgpu_device_xgmi_reset_func(struct work_struct *__work)
                         adev->asic_reset_res, adev->ddev->unique);
 }
 
+static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev)
+{
+       char *input = amdgpu_lockup_timeout;
+       char *timeout_setting = NULL;
+       int index = 0;
+       long timeout;
+       int ret = 0;
+
+       /*
+        * By default timeout for non compute jobs is 10000.
+        * And there is no timeout enforced on compute jobs.
+        * In SR-IOV or passthrough mode, timeout for compute
+        * jobs are 10000 by default.
+        */
+       adev->gfx_timeout = msecs_to_jiffies(10000);
+       adev->sdma_timeout = adev->video_timeout = adev->gfx_timeout;
+       if (amdgpu_sriov_vf(adev) || amdgpu_passthrough(adev))
+               adev->compute_timeout = adev->gfx_timeout;
+       else
+               adev->compute_timeout = MAX_SCHEDULE_TIMEOUT;
+
+       if (strnlen(input, AMDGPU_MAX_TIMEOUT_PARAM_LENTH)) {
+               while ((timeout_setting = strsep(&input, ",")) &&
+                               strnlen(timeout_setting, AMDGPU_MAX_TIMEOUT_PARAM_LENTH)) {
+                       ret = kstrtol(timeout_setting, 0, &timeout);
+                       if (ret)
+                               return ret;
+
+                       if (timeout == 0) {
+                               index++;
+                               continue;
+                       } else if (timeout < 0) {
+                               timeout = MAX_SCHEDULE_TIMEOUT;
+                       } else {
+                               timeout = msecs_to_jiffies(timeout);
+                       }
+
+                       switch (index++) {
+                       case 0:
+                               adev->gfx_timeout = timeout;
+                               break;
+                       case 1:
+                               adev->compute_timeout = timeout;
+                               break;
+                       case 2:
+                               adev->sdma_timeout = timeout;
+                               break;
+                       case 3:
+                               adev->video_timeout = timeout;
+                               break;
+                       default:
+                               break;
+                       }
+               }
+               /*
+                * There is only one value specified and
+                * it should apply to all non-compute jobs.
+                */
+               if (index == 1) {
+                       adev->sdma_timeout = adev->video_timeout = adev->gfx_timeout;
+                       if (amdgpu_sriov_vf(adev) || amdgpu_passthrough(adev))
+                               adev->compute_timeout = adev->gfx_timeout;
+               }
+       }
+
+       return ret;
+}
 
 /**
  * amdgpu_device_init - initialize the driver
@@ -2583,7 +2688,12 @@ int amdgpu_device_init(struct amdgpu_device *adev,
        adev->ddev = ddev;
        adev->pdev = pdev;
        adev->flags = flags;
-       adev->asic_type = flags & AMD_ASIC_MASK;
+
+       if (amdgpu_force_asic_type >= 0 && amdgpu_force_asic_type < CHIP_LAST)
+               adev->asic_type = amdgpu_force_asic_type;
+       else
+               adev->asic_type = flags & AMD_ASIC_MASK;
+
        adev->usec_timeout = AMDGPU_MAX_USEC_TIMEOUT;
        if (amdgpu_emu_mode == 1)
                adev->usec_timeout *= 2;
@@ -2726,6 +2836,12 @@ int amdgpu_device_init(struct amdgpu_device *adev,
        if (r)
                return r;
 
+       r = amdgpu_device_get_job_timeout_settings(adev);
+       if (r) {
+               dev_err(adev->dev, "invalid lockup_timeout parameter syntax\n");
+               return r;
+       }
+
        /* doorbell bar mapping and doorbell index init*/
        amdgpu_device_doorbell_init(adev);
 
@@ -3007,6 +3123,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
        struct amdgpu_device *adev;
        struct drm_crtc *crtc;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
        int r;
 
        if (dev == NULL || dev->dev_private == NULL) {
@@ -3029,9 +3146,11 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
        if (!amdgpu_device_has_dc_support(adev)) {
                /* turn off display hw */
                drm_modeset_lock_all(dev);
-               list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-                       drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
-               }
+               drm_connector_list_iter_begin(dev, &iter);
+               drm_for_each_connector_iter(connector, &iter)
+                       drm_helper_connector_dpms(connector,
+                                                 DRM_MODE_DPMS_OFF);
+               drm_connector_list_iter_end(&iter);
                drm_modeset_unlock_all(dev);
                        /* unpin the front buffers and cursors */
                list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -3082,15 +3201,11 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
         */
        amdgpu_bo_evict_vram(adev);
 
-       pci_save_state(dev->pdev);
        if (suspend) {
+               pci_save_state(dev->pdev);
                /* Shut down the device */
                pci_disable_device(dev->pdev);
                pci_set_power_state(dev->pdev, PCI_D3hot);
-       } else {
-               r = amdgpu_asic_reset(adev);
-               if (r)
-                       DRM_ERROR("amdgpu asic reset failed\n");
        }
 
        return 0;
@@ -3110,6 +3225,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
 int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
 {
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
        struct amdgpu_device *adev = dev->dev_private;
        struct drm_crtc *crtc;
        int r = 0;
@@ -3180,9 +3296,13 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
 
                        /* turn on display hw */
                        drm_modeset_lock_all(dev);
-                       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-                               drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
-                       }
+
+                       drm_connector_list_iter_begin(dev, &iter);
+                       drm_for_each_connector_iter(connector, &iter)
+                               drm_helper_connector_dpms(connector,
+                                                         DRM_MODE_DPMS_ON);
+                       drm_connector_list_iter_end(&iter);
+
                        drm_modeset_unlock_all(dev);
                }
                amdgpu_fbdev_set_suspend(adev, 0);
@@ -3628,11 +3748,6 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive,
                                                break;
                                }
                        }
-
-                       list_for_each_entry(tmp_adev, device_list_handle,
-                                       gmc.xgmi.head) {
-                               amdgpu_ras_reserve_bad_pages(tmp_adev);
-                       }
                }
        }
 
@@ -3736,25 +3851,18 @@ static bool amdgpu_device_lock_adev(struct amdgpu_device *adev, bool trylock)
                adev->mp1_state = PP_MP1_STATE_NONE;
                break;
        }
-       /* Block kfd: SRIOV would do it separately */
-       if (!amdgpu_sriov_vf(adev))
-                amdgpu_amdkfd_pre_reset(adev);
 
        return true;
 }
 
 static void amdgpu_device_unlock_adev(struct amdgpu_device *adev)
 {
-       /*unlock kfd: SRIOV would do it separately */
-       if (!amdgpu_sriov_vf(adev))
-                amdgpu_amdkfd_post_reset(adev);
        amdgpu_vf_error_trans_all(adev);
        adev->mp1_state = PP_MP1_STATE_NONE;
        adev->in_gpu_reset = 0;
        mutex_unlock(&adev->lock_reset);
 }
 
-
 /**
  * amdgpu_device_gpu_recover - reset the asic and recover scheduler
  *
@@ -3774,11 +3882,24 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
        struct amdgpu_hive_info *hive = NULL;
        struct amdgpu_device *tmp_adev = NULL;
        int i, r = 0;
+       bool in_ras_intr = amdgpu_ras_intr_triggered();
+
+       /*
+        * Flush RAM to disk so that after reboot
+        * the user can read log and see why the system rebooted.
+        */
+       if (in_ras_intr && amdgpu_ras_get_context(adev)->reboot) {
+
+               DRM_WARN("Emergency reboot.");
+
+               ksys_sync_helper();
+               emergency_restart();
+       }
 
        need_full_reset = job_signaled = false;
        INIT_LIST_HEAD(&device_list);
 
-       dev_info(adev->dev, "GPU reset begin!\n");
+       dev_info(adev->dev, "GPU %s begin!\n", in_ras_intr ? "jobs stop":"reset");
 
        cancel_delayed_work_sync(&adev->delayed_init_work);
 
@@ -3805,9 +3926,16 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
                return 0;
        }
 
+       /* Block kfd: SRIOV would do it separately */
+       if (!amdgpu_sriov_vf(adev))
+                amdgpu_amdkfd_pre_reset(adev);
+
        /* Build list of devices to reset */
        if  (adev->gmc.xgmi.num_physical_nodes > 1) {
                if (!hive) {
+                       /*unlock kfd: SRIOV would do it separately */
+                       if (!amdgpu_sriov_vf(adev))
+                               amdgpu_amdkfd_post_reset(adev);
                        amdgpu_device_unlock_adev(adev);
                        return -ENODEV;
                }
@@ -3823,17 +3951,22 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
                device_list_handle = &device_list;
        }
 
-       /*
-        * Mark these ASICs to be reseted as untracked first
-        * And add them back after reset completed
-        */
-       list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head)
-               amdgpu_unregister_gpu_instance(tmp_adev);
-
        /* block all schedulers and reset given job's ring */
        list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
+               if (tmp_adev != adev) {
+                       amdgpu_device_lock_adev(tmp_adev, false);
+                       if (!amdgpu_sriov_vf(tmp_adev))
+                                       amdgpu_amdkfd_pre_reset(tmp_adev);
+               }
+
+               /*
+                * Mark these ASICs to be reseted as untracked first
+                * And add them back after reset completed
+                */
+               amdgpu_unregister_gpu_instance(tmp_adev);
+
                /* disable ras on ALL IPs */
-               if (amdgpu_device_ip_need_full_reset(tmp_adev))
+               if (!in_ras_intr && amdgpu_device_ip_need_full_reset(tmp_adev))
                        amdgpu_ras_suspend(tmp_adev);
 
                for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
@@ -3843,10 +3976,16 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
                                continue;
 
                        drm_sched_stop(&ring->sched, job ? &job->base : NULL);
+
+                       if (in_ras_intr)
+                               amdgpu_job_stop_all_jobs_on_sched(&ring->sched);
                }
        }
 
 
+       if (in_ras_intr)
+               goto skip_sched_resume;
+
        /*
         * Must check guilty signal here since after this point all old
         * HW fences are force signaled.
@@ -3857,9 +3996,6 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
            dma_fence_is_signaled(job->base.s_fence->parent))
                job_signaled = true;
 
-       if (!amdgpu_device_ip_need_full_reset(adev))
-               device_list_handle = &device_list;
-
        if (job_signaled) {
                dev_info(adev->dev, "Guilty job already signaled, skipping HW reset");
                goto skip_hw_reset;
@@ -3881,7 +4017,6 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
                if (tmp_adev == adev)
                        continue;
 
-               amdgpu_device_lock_adev(tmp_adev, false);
                r = amdgpu_device_pre_asic_reset(tmp_adev,
                                                 NULL,
                                                 &need_full_reset);
@@ -3909,6 +4044,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
 
        /* Post ASIC reset for all devs .*/
        list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
+
                for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
                        struct amdgpu_ring *ring = tmp_adev->rings[i];
 
@@ -3930,12 +4066,18 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
 
                if (r) {
                        /* bad news, how to tell it to userspace ? */
-                       dev_info(tmp_adev->dev, "GPU reset(%d) failed\n", atomic_read(&adev->gpu_reset_counter));
+                       dev_info(tmp_adev->dev, "GPU reset(%d) failed\n", atomic_read(&tmp_adev->gpu_reset_counter));
                        amdgpu_vf_error_put(tmp_adev, AMDGIM_ERROR_VF_GPU_RESET_FAIL, 0, r);
                } else {
-                       dev_info(tmp_adev->dev, "GPU reset(%d) succeeded!\n", atomic_read(&adev->gpu_reset_counter));
+                       dev_info(tmp_adev->dev, "GPU reset(%d) succeeded!\n", atomic_read(&tmp_adev->gpu_reset_counter));
                }
+       }
 
+skip_sched_resume:
+       list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
+               /*unlock kfd: SRIOV would do it separately */
+               if (!in_ras_intr && !amdgpu_sriov_vf(tmp_adev))
+                       amdgpu_amdkfd_post_reset(tmp_adev);
                amdgpu_device_unlock_adev(tmp_adev);
        }
 
index 1481899f86c166ed25c0639c80031ec2b9fdea90..f95092741c38af4dc776054fc7c542b0d5f7f987 100644 (file)
@@ -134,20 +134,10 @@ static int hw_id_map[MAX_HWIP] = {
 
 static int amdgpu_discovery_read_binary(struct amdgpu_device *adev, uint8_t *binary)
 {
-       uint32_t *p = (uint32_t *)binary;
        uint64_t vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;
-       uint64_t pos = vram_size - BINARY_MAX_SIZE;
-       unsigned long flags;
-
-       while (pos < vram_size) {
-               spin_lock_irqsave(&adev->mmio_idx_lock, flags);
-               WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)pos) | 0x80000000);
-               WREG32_NO_KIQ(mmMM_INDEX_HI, pos >> 31);
-               *p++ = RREG32_NO_KIQ(mmMM_DATA);
-               spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
-               pos += 4;
-       }
+       uint64_t pos = vram_size - DISCOVERY_TMR_SIZE;
 
+       amdgpu_device_vram_access(adev, pos, (uint32_t *)binary, DISCOVERY_TMR_SIZE, false);
        return 0;
 }
 
@@ -179,7 +169,7 @@ int amdgpu_discovery_init(struct amdgpu_device *adev)
        uint16_t checksum;
        int r;
 
-       adev->discovery = kzalloc(BINARY_MAX_SIZE, GFP_KERNEL);
+       adev->discovery = kzalloc(DISCOVERY_TMR_SIZE, GFP_KERNEL);
        if (!adev->discovery)
                return -ENOMEM;
 
@@ -333,7 +323,7 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
 }
 
 int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id,
-                                   int *major, int *minor)
+                                   int *major, int *minor, int *revision)
 {
        struct binary_header *bhdr;
        struct ip_discovery_header *ihdr;
@@ -369,6 +359,8 @@ int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id,
                                        *major = ip->major;
                                if (minor)
                                        *minor = ip->minor;
+                               if (revision)
+                                       *revision = ip->revision;
                                return 0;
                        }
                        ip_offset += sizeof(*ip) + 4 * (ip->num_base_address - 1);
index 85b8c4d4d5763735fa9edf561bf095c59ae1a559..ba78e15d9b055b3ecca1e9aba31d2fb268507c87 100644 (file)
 #ifndef __AMDGPU_DISCOVERY__
 #define __AMDGPU_DISCOVERY__
 
+#define DISCOVERY_TMR_SIZE  (64 << 10)
+
 int amdgpu_discovery_init(struct amdgpu_device *adev);
 void amdgpu_discovery_fini(struct amdgpu_device *adev);
 int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev);
 int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id,
-                                    int *major, int *minor);
+                                    int *major, int *minor, int *revision);
 int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev);
 
 #endif /* __AMDGPU_DISCOVERY__ */
index 1d4aaa9580f4b50ec4ffb8d86ea082f313b29877..d2dd59a95e8a360fe7e9596d6248b481ffd4b81a 100644 (file)
@@ -370,11 +370,13 @@ void amdgpu_display_print_display_setup(struct drm_device *dev)
        struct amdgpu_connector *amdgpu_connector;
        struct drm_encoder *encoder;
        struct amdgpu_encoder *amdgpu_encoder;
+       struct drm_connector_list_iter iter;
        uint32_t devices;
        int i = 0;
 
+       drm_connector_list_iter_begin(dev, &iter);
        DRM_INFO("AMDGPU Display Connectors\n");
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_for_each_connector_iter(connector, &iter) {
                amdgpu_connector = to_amdgpu_connector(connector);
                DRM_INFO("Connector %d:\n", i);
                DRM_INFO("  %s\n", connector->name);
@@ -438,6 +440,7 @@ void amdgpu_display_print_display_setup(struct drm_device *dev)
                }
                i++;
        }
+       drm_connector_list_iter_end(&iter);
 }
 
 /**
index 61f108ec2b5c3c159a7efa517bb380665bc26d1d..4917b548b7f2d87efff68c234f62ad9991076f96 100644 (file)
@@ -321,7 +321,6 @@ const struct dma_buf_ops amdgpu_dmabuf_ops = {
 
 /**
  * amdgpu_gem_prime_export - &drm_driver.gem_prime_export implementation
- * @dev: DRM device
  * @gobj: GEM BO
  * @flags: Flags such as DRM_CLOEXEC and DRM_RDWR.
  *
index 4da1d7fb10f4d4038a75385a72a55e7d4c299b59..01f6a3b9e0395ce8151ec59a32fb3ec798566600 100644 (file)
@@ -43,6 +43,8 @@
 
 #include "amdgpu_amdkfd.h"
 
+#include "amdgpu_ras.h"
+
 /*
  * KMS wrapper.
  * - 3.0.0 - initial driver
@@ -87,8 +89,6 @@
 #define KMS_DRIVER_MINOR       35
 #define KMS_DRIVER_PATCHLEVEL  0
 
-#define AMDGPU_MAX_TIMEOUT_PARAM_LENTH 256
-
 int amdgpu_vram_limit = 0;
 int amdgpu_vis_vram_limit = 0;
 int amdgpu_gart_size = -1; /* auto */
@@ -128,11 +128,7 @@ char *amdgpu_disable_cu = NULL;
 char *amdgpu_virtual_display = NULL;
 /* OverDrive(bit 14) disabled by default*/
 uint amdgpu_pp_feature_mask = 0xffffbfff;
-int amdgpu_ngg = 0;
-int amdgpu_prim_buf_per_se = 0;
-int amdgpu_pos_buf_per_se = 0;
-int amdgpu_cntl_sb_buf_per_se = 0;
-int amdgpu_param_buf_per_se = 0;
+uint amdgpu_force_long_training = 0;
 int amdgpu_job_hang_limit = 0;
 int amdgpu_lbpw = -1;
 int amdgpu_compute_multipipe = -1;
@@ -146,12 +142,13 @@ int amdgpu_mcbp = 0;
 int amdgpu_discovery = -1;
 int amdgpu_mes = 0;
 int amdgpu_noretry = 1;
+int amdgpu_force_asic_type = -1;
 
 struct amdgpu_mgpu_info mgpu_info = {
        .mutex = __MUTEX_INITIALIZER(mgpu_info.mutex),
 };
 int amdgpu_ras_enable = -1;
-uint amdgpu_ras_mask = 0xfffffffb;
+uint amdgpu_ras_mask = 0xffffffff;
 
 /**
  * DOC: vramlimit (int)
@@ -244,16 +241,21 @@ module_param_named(msi, amdgpu_msi, int, 0444);
  *
  * The format can be [Non-Compute] or [GFX,Compute,SDMA,Video]. That is there can be one or
  * multiple values specified. 0 and negative values are invalidated. They will be adjusted
- * to default timeout.
- *  - With one value specified, the setting will apply to all non-compute jobs.
- *  - With multiple values specified, the first one will be for GFX. The second one is for Compute.
- *    And the third and fourth ones are for SDMA and Video.
+ * to the default timeout.
+ *
+ * - With one value specified, the setting will apply to all non-compute jobs.
+ * - With multiple values specified, the first one will be for GFX.
+ *   The second one is for Compute. The third and fourth ones are
+ *   for SDMA and Video.
+ *
  * By default(with no lockup_timeout settings), the timeout for all non-compute(GFX, SDMA and Video)
  * jobs is 10000. And there is no timeout enforced on compute jobs.
  */
-MODULE_PARM_DESC(lockup_timeout, "GPU lockup timeout in ms (default: 10000 for non-compute jobs and infinity timeout for compute jobs."
+MODULE_PARM_DESC(lockup_timeout, "GPU lockup timeout in ms (default: for bare metal 10000 for non-compute jobs and infinity timeout for compute jobs; "
+               "for passthrough or sriov, 10000 for all jobs."
                " 0: keep default value. negative: infinity timeout), "
-               "format is [Non-Compute] or [GFX,Compute,SDMA,Video]");
+               "format: for bare metal [Non-Compute] or [GFX,Compute,SDMA,Video]; "
+               "for passthrough or sriov [all jobs] or [GFX,Compute,SDMA,Video].");
 module_param_string(lockup_timeout, amdgpu_lockup_timeout, sizeof(amdgpu_lockup_timeout), 0444);
 
 /**
@@ -391,6 +393,14 @@ module_param_named(sched_hw_submission, amdgpu_sched_hw_submission, int, 0444);
 MODULE_PARM_DESC(ppfeaturemask, "all power features enabled (default))");
 module_param_named(ppfeaturemask, amdgpu_pp_feature_mask, uint, 0444);
 
+/**
+ * DOC: forcelongtraining (uint)
+ * Force long memory training in resume.
+ * The default is zero, indicates short training in resume.
+ */
+MODULE_PARM_DESC(forcelongtraining, "force memory long training");
+module_param_named(forcelongtraining, amdgpu_force_long_training, uint, 0444);
+
 /**
  * DOC: pcie_gen_cap (uint)
  * Override PCIE gen speed capabilities. See the CAIL flags in drivers/gpu/drm/amd/include/amd_pcie.h.
@@ -448,42 +458,6 @@ MODULE_PARM_DESC(virtual_display,
                 "Enable virtual display feature (the virtual_display will be set like xxxx:xx:xx.x,x;xxxx:xx:xx.x,x)");
 module_param_named(virtual_display, amdgpu_virtual_display, charp, 0444);
 
-/**
- * DOC: ngg (int)
- * Set to enable Next Generation Graphics (1 = enable). The default is 0 (disabled).
- */
-MODULE_PARM_DESC(ngg, "Next Generation Graphics (1 = enable, 0 = disable(default depending on gfx))");
-module_param_named(ngg, amdgpu_ngg, int, 0444);
-
-/**
- * DOC: prim_buf_per_se (int)
- * Override the size of Primitive Buffer per Shader Engine in Byte. The default is 0 (depending on gfx).
- */
-MODULE_PARM_DESC(prim_buf_per_se, "the size of Primitive Buffer per Shader Engine (default depending on gfx)");
-module_param_named(prim_buf_per_se, amdgpu_prim_buf_per_se, int, 0444);
-
-/**
- * DOC: pos_buf_per_se (int)
- * Override the size of Position Buffer per Shader Engine in Byte. The default is 0 (depending on gfx).
- */
-MODULE_PARM_DESC(pos_buf_per_se, "the size of Position Buffer per Shader Engine (default depending on gfx)");
-module_param_named(pos_buf_per_se, amdgpu_pos_buf_per_se, int, 0444);
-
-/**
- * DOC: cntl_sb_buf_per_se (int)
- * Override the size of Control Sideband per Shader Engine in Byte. The default is 0 (depending on gfx).
- */
-MODULE_PARM_DESC(cntl_sb_buf_per_se, "the size of Control Sideband per Shader Engine (default depending on gfx)");
-module_param_named(cntl_sb_buf_per_se, amdgpu_cntl_sb_buf_per_se, int, 0444);
-
-/**
- * DOC: param_buf_per_se (int)
- * Override the size of Off-Chip Parameter Cache per Shader Engine in Byte.
- * The default is 0 (depending on gfx).
- */
-MODULE_PARM_DESC(param_buf_per_se, "the size of Off-Chip Parameter Cache per Shader Engine (default depending on gfx)");
-module_param_named(param_buf_per_se, amdgpu_param_buf_per_se, int, 0444);
-
 /**
  * DOC: job_hang_limit (int)
  * Set how much time allow a job hang and not drop it. The default is 0.
@@ -616,6 +590,16 @@ MODULE_PARM_DESC(noretry,
        "Disable retry faults (0 = retry enabled, 1 = retry disabled (default))");
 module_param_named(noretry, amdgpu_noretry, int, 0644);
 
+/**
+ * DOC: force_asic_type (int)
+ * A non negative value used to specify the asic type for all supported GPUs.
+ */
+MODULE_PARM_DESC(force_asic_type,
+       "A non negative value used to specify the asic type for all supported GPUs");
+module_param_named(force_asic_type, amdgpu_force_asic_type, int, 0444);
+
+
+
 #ifdef CONFIG_HSA_AMD
 /**
  * DOC: sched_policy (int)
@@ -1022,6 +1006,7 @@ static const struct pci_device_id pciidlist[] = {
 
        /* Navi12 */
        {0x1002, 0x7360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12|AMD_EXP_HW_SUPPORT},
+       {0x1002, 0x7362, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12|AMD_EXP_HW_SUPPORT},
 
        {0, 0, 0}
 };
@@ -1127,7 +1112,10 @@ amdgpu_pci_remove(struct pci_dev *pdev)
 {
        struct drm_device *dev = pci_get_drvdata(pdev);
 
-       DRM_ERROR("Device removal is currently not supported outside of fbcon\n");
+#ifdef MODULE
+       if (THIS_MODULE->state != MODULE_STATE_GOING)
+#endif
+               DRM_ERROR("Hotplug removal is not supported\n");
        drm_dev_unplug(dev);
        drm_dev_put(dev);
        pci_disable_device(pdev);
@@ -1140,6 +1128,9 @@ amdgpu_pci_shutdown(struct pci_dev *pdev)
        struct drm_device *dev = pci_get_drvdata(pdev);
        struct amdgpu_device *adev = dev->dev_private;
 
+       if (amdgpu_ras_intr_triggered())
+               return;
+
        /* if we are running in a VM, make sure the device
         * torn down properly on reboot/shutdown.
         * unfortunately we can't detect certain
@@ -1174,8 +1165,13 @@ static int amdgpu_pmops_resume(struct device *dev)
 static int amdgpu_pmops_freeze(struct device *dev)
 {
        struct drm_device *drm_dev = dev_get_drvdata(dev);
+       struct amdgpu_device *adev = drm_dev->dev_private;
+       int r;
 
-       return amdgpu_device_suspend(drm_dev, false, true);
+       r = amdgpu_device_suspend(drm_dev, false, true);
+       if (r)
+               return r;
+       return amdgpu_asic_reset(adev);
 }
 
 static int amdgpu_pmops_thaw(struct device *dev)
@@ -1347,66 +1343,6 @@ int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv)
        return 0;
 }
 
-int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev)
-{
-       char *input = amdgpu_lockup_timeout;
-       char *timeout_setting = NULL;
-       int index = 0;
-       long timeout;
-       int ret = 0;
-
-       /*
-        * By default timeout for non compute jobs is 10000.
-        * And there is no timeout enforced on compute jobs.
-        */
-       adev->gfx_timeout = msecs_to_jiffies(10000);
-       adev->sdma_timeout = adev->video_timeout = adev->gfx_timeout;
-       adev->compute_timeout = MAX_SCHEDULE_TIMEOUT;
-
-       if (strnlen(input, AMDGPU_MAX_TIMEOUT_PARAM_LENTH)) {
-               while ((timeout_setting = strsep(&input, ",")) &&
-                               strnlen(timeout_setting, AMDGPU_MAX_TIMEOUT_PARAM_LENTH)) {
-                       ret = kstrtol(timeout_setting, 0, &timeout);
-                       if (ret)
-                               return ret;
-
-                       if (timeout == 0) {
-                               index++;
-                               continue;
-                       } else if (timeout < 0) {
-                               timeout = MAX_SCHEDULE_TIMEOUT;
-                       } else {
-                               timeout = msecs_to_jiffies(timeout);
-                       }
-
-                       switch (index++) {
-                       case 0:
-                               adev->gfx_timeout = timeout;
-                               break;
-                       case 1:
-                               adev->compute_timeout = timeout;
-                               break;
-                       case 2:
-                               adev->sdma_timeout = timeout;
-                               break;
-                       case 3:
-                               adev->video_timeout = timeout;
-                               break;
-                       default:
-                               break;
-                       }
-               }
-               /*
-                * There is only one value specified and
-                * it should apply to all non-compute jobs.
-                */
-               if (index == 1)
-                       adev->sdma_timeout = adev->video_timeout = adev->gfx_timeout;
-       }
-
-       return ret;
-}
-
 static bool
 amdgpu_get_crtc_scanout_position(struct drm_device *dev, unsigned int pipe,
                                 bool in_vblank_irq, int *vpos, int *hpos,
index 571a6dfb473e1f5025dec2461a9d6c83da2b5656..61fcf247a638926d986237d95244fbc5800f1fc0 100644 (file)
@@ -37,12 +37,14 @@ amdgpu_link_encoder_connector(struct drm_device *dev)
 {
        struct amdgpu_device *adev = dev->dev_private;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
        struct amdgpu_connector *amdgpu_connector;
        struct drm_encoder *encoder;
        struct amdgpu_encoder *amdgpu_encoder;
 
+       drm_connector_list_iter_begin(dev, &iter);
        /* walk the list and link encoders to connectors */
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_for_each_connector_iter(connector, &iter) {
                amdgpu_connector = to_amdgpu_connector(connector);
                list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
                        amdgpu_encoder = to_amdgpu_encoder(encoder);
@@ -55,6 +57,7 @@ amdgpu_link_encoder_connector(struct drm_device *dev)
                        }
                }
        }
+       drm_connector_list_iter_end(&iter);
 }
 
 void amdgpu_encoder_set_active_device(struct drm_encoder *encoder)
@@ -62,8 +65,10 @@ void amdgpu_encoder_set_active_device(struct drm_encoder *encoder)
        struct drm_device *dev = encoder->dev;
        struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                if (connector->encoder == encoder) {
                        struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
                        amdgpu_encoder->active_device = amdgpu_encoder->devices & amdgpu_connector->devices;
@@ -72,6 +77,7 @@ void amdgpu_encoder_set_active_device(struct drm_encoder *encoder)
                                  amdgpu_connector->devices, encoder->encoder_type);
                }
        }
+       drm_connector_list_iter_end(&iter);
 }
 
 struct drm_connector *
@@ -79,15 +85,20 @@ amdgpu_get_connector_for_encoder(struct drm_encoder *encoder)
 {
        struct drm_device *dev = encoder->dev;
        struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
-       struct drm_connector *connector;
+       struct drm_connector *connector, *found = NULL;
+       struct drm_connector_list_iter iter;
        struct amdgpu_connector *amdgpu_connector;
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                amdgpu_connector = to_amdgpu_connector(connector);
-               if (amdgpu_encoder->active_device & amdgpu_connector->devices)
-                       return connector;
+               if (amdgpu_encoder->active_device & amdgpu_connector->devices) {
+                       found = connector;
+                       break;
+               }
        }
-       return NULL;
+       drm_connector_list_iter_end(&iter);
+       return found;
 }
 
 struct drm_connector *
@@ -95,15 +106,20 @@ amdgpu_get_connector_for_encoder_init(struct drm_encoder *encoder)
 {
        struct drm_device *dev = encoder->dev;
        struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
-       struct drm_connector *connector;
+       struct drm_connector *connector, *found = NULL;
+       struct drm_connector_list_iter iter;
        struct amdgpu_connector *amdgpu_connector;
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                amdgpu_connector = to_amdgpu_connector(connector);
-               if (amdgpu_encoder->devices & amdgpu_connector->devices)
-                       return connector;
+               if (amdgpu_encoder->devices & amdgpu_connector->devices) {
+                       found = connector;
+                       break;
+               }
        }
-       return NULL;
+       drm_connector_list_iter_end(&iter);
+       return found;
 }
 
 struct drm_encoder *amdgpu_get_external_encoder(struct drm_encoder *encoder)
index 23085b352cf2d91886d13660a21ba9e98a3b4c44..377fe20bce23ca540f5d4eba6996f8ec7674f2af 100644 (file)
@@ -462,18 +462,7 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
                        timeout = adev->gfx_timeout;
                        break;
                case AMDGPU_RING_TYPE_COMPUTE:
-                       /*
-                        * For non-sriov case, no timeout enforce
-                        * on compute ring by default. Unless user
-                        * specifies a timeout for compute ring.
-                        *
-                        * For sriov case, always use the timeout
-                        * as gfx ring
-                        */
-                       if (!amdgpu_sriov_vf(ring->adev))
-                               timeout = adev->compute_timeout;
-                       else
-                               timeout = adev->gfx_timeout;
+                       timeout = adev->compute_timeout;
                        break;
                case AMDGPU_RING_TYPE_SDMA:
                        timeout = adev->sdma_timeout;
index 8ceb44925947e37e0383fc25d99dbc72c396b96e..6cf8862ebba1df1866f06885aad60be94c0d5930 100644 (file)
@@ -527,13 +527,41 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
                        goto error;
        }
 
-       r = amdgpu_vm_update_directories(adev, vm);
+       r = amdgpu_vm_update_pdes(adev, vm, false);
 
 error:
        if (r && r != -ERESTARTSYS)
                DRM_ERROR("Couldn't update BO_VA (%d)\n", r);
 }
 
+/**
+ * amdgpu_gem_va_map_flags - map GEM UAPI flags into hardware flags
+ *
+ * @adev: amdgpu_device pointer
+ * @flags: GEM UAPI flags
+ *
+ * Returns the GEM UAPI flags mapped into hardware for the ASIC.
+ */
+uint64_t amdgpu_gem_va_map_flags(struct amdgpu_device *adev, uint32_t flags)
+{
+       uint64_t pte_flag = 0;
+
+       if (flags & AMDGPU_VM_PAGE_EXECUTABLE)
+               pte_flag |= AMDGPU_PTE_EXECUTABLE;
+       if (flags & AMDGPU_VM_PAGE_READABLE)
+               pte_flag |= AMDGPU_PTE_READABLE;
+       if (flags & AMDGPU_VM_PAGE_WRITEABLE)
+               pte_flag |= AMDGPU_PTE_WRITEABLE;
+       if (flags & AMDGPU_VM_PAGE_PRT)
+               pte_flag |= AMDGPU_PTE_PRT;
+
+       if (adev->gmc.gmc_funcs->map_mtype)
+               pte_flag |= amdgpu_gmc_map_mtype(adev,
+                                                flags & AMDGPU_VM_MTYPE_MASK);
+
+       return pte_flag;
+}
+
 int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
                          struct drm_file *filp)
 {
@@ -631,7 +659,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
 
        switch (args->operation) {
        case AMDGPU_VA_OP_MAP:
-               va_flags = amdgpu_gmc_get_pte_flags(adev, args->flags);
+               va_flags = amdgpu_gem_va_map_flags(adev, args->flags);
                r = amdgpu_vm_bo_map(adev, bo_va, args->va_address,
                                     args->offset_in_bo, args->map_size,
                                     va_flags);
@@ -646,7 +674,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
                                                args->map_size);
                break;
        case AMDGPU_VA_OP_REPLACE:
-               va_flags = amdgpu_gmc_get_pte_flags(adev, args->flags);
+               va_flags = amdgpu_gem_va_map_flags(adev, args->flags);
                r = amdgpu_vm_bo_replace_map(adev, bo_va, args->va_address,
                                             args->offset_in_bo, args->map_size,
                                             va_flags);
index 0b66d2e6b5d524d94b5577e976678007e0e517df..e0f025dd1b14aa4b0002f5c16f19811115fccd98 100644 (file)
@@ -67,6 +67,7 @@ int amdgpu_gem_mmap_ioctl(struct drm_device *dev, void *data,
                          struct drm_file *filp);
 int amdgpu_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
                              struct drm_file *filp);
+uint64_t amdgpu_gem_va_map_flags(struct amdgpu_device *adev, uint32_t flags);
 int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
                          struct drm_file *filp);
 int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
index f9bef3154b99833eff9a5f595c39a9a269176a79..069515f57c2a6611d2ea4f3f9bedd8671a186b65 100644 (file)
@@ -26,6 +26,7 @@
 #include "amdgpu.h"
 #include "amdgpu_gfx.h"
 #include "amdgpu_rlc.h"
+#include "amdgpu_ras.h"
 
 /* delay 0.1 second to enable gfx off feature */
 #define GFX_OFF_DELAY_ENABLE         msecs_to_jiffies(100)
@@ -231,12 +232,10 @@ void amdgpu_gfx_compute_queue_acquire(struct amdgpu_device *adev)
 
 void amdgpu_gfx_graphics_queue_acquire(struct amdgpu_device *adev)
 {
-       int i, queue, pipe, me;
+       int i, queue, me;
 
        for (i = 0; i < AMDGPU_MAX_GFX_QUEUES; ++i) {
                queue = i % adev->gfx.me.num_queue_per_pipe;
-               pipe = (i / adev->gfx.me.num_queue_per_pipe)
-                       % adev->gfx.me.num_pipe_per_me;
                me = (i / adev->gfx.me.num_queue_per_pipe)
                      / adev->gfx.me.num_pipe_per_me;
 
@@ -569,3 +568,102 @@ void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable)
 
        mutex_unlock(&adev->gfx.gfx_off_mutex);
 }
+
+int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev)
+{
+       int r;
+       struct ras_fs_if fs_info = {
+               .sysfs_name = "gfx_err_count",
+               .debugfs_name = "gfx_err_inject",
+       };
+       struct ras_ih_if ih_info = {
+               .cb = amdgpu_gfx_process_ras_data_cb,
+       };
+
+       if (!adev->gfx.ras_if) {
+               adev->gfx.ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL);
+               if (!adev->gfx.ras_if)
+                       return -ENOMEM;
+               adev->gfx.ras_if->block = AMDGPU_RAS_BLOCK__GFX;
+               adev->gfx.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
+               adev->gfx.ras_if->sub_block_index = 0;
+               strcpy(adev->gfx.ras_if->name, "gfx");
+       }
+       fs_info.head = ih_info.head = *adev->gfx.ras_if;
+
+       r = amdgpu_ras_late_init(adev, adev->gfx.ras_if,
+                                &fs_info, &ih_info);
+       if (r)
+               goto free;
+
+       if (amdgpu_ras_is_supported(adev, adev->gfx.ras_if->block)) {
+               r = amdgpu_irq_get(adev, &adev->gfx.cp_ecc_error_irq, 0);
+               if (r)
+                       goto late_fini;
+       } else {
+               /* free gfx ras_if if ras is not supported */
+               r = 0;
+               goto free;
+       }
+
+       return 0;
+late_fini:
+       amdgpu_ras_late_fini(adev, adev->gfx.ras_if, &ih_info);
+free:
+       kfree(adev->gfx.ras_if);
+       adev->gfx.ras_if = NULL;
+       return r;
+}
+
+void amdgpu_gfx_ras_fini(struct amdgpu_device *adev)
+{
+       if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX) &&
+                       adev->gfx.ras_if) {
+               struct ras_common_if *ras_if = adev->gfx.ras_if;
+               struct ras_ih_if ih_info = {
+                       .head = *ras_if,
+                       .cb = amdgpu_gfx_process_ras_data_cb,
+               };
+
+               amdgpu_ras_late_fini(adev, ras_if, &ih_info);
+               kfree(ras_if);
+       }
+}
+
+int amdgpu_gfx_process_ras_data_cb(struct amdgpu_device *adev,
+               void *err_data,
+               struct amdgpu_iv_entry *entry)
+{
+       /* TODO ue will trigger an interrupt.
+        *
+        * When “Full RAS” is enabled, the per-IP interrupt sources should
+        * be disabled and the driver should only look for the aggregated
+        * interrupt via sync flood
+        */
+       if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX)) {
+               kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
+               if (adev->gfx.funcs->query_ras_error_count)
+                       adev->gfx.funcs->query_ras_error_count(adev, err_data);
+               amdgpu_ras_reset_gpu(adev, 0);
+       }
+       return AMDGPU_RAS_SUCCESS;
+}
+
+int amdgpu_gfx_cp_ecc_error_irq(struct amdgpu_device *adev,
+                                 struct amdgpu_irq_src *source,
+                                 struct amdgpu_iv_entry *entry)
+{
+       struct ras_common_if *ras_if = adev->gfx.ras_if;
+       struct ras_dispatch_if ih_data = {
+               .entry = entry,
+       };
+
+       if (!ras_if)
+               return 0;
+
+       ih_data.head = *ras_if;
+
+       DRM_ERROR("CP ECC ERROR IRQ\n");
+       amdgpu_ras_interrupt_dispatch(adev, &ih_data);
+       return 0;
+}
index 6ee4021910e2cddbad2900f7bb2fe8860f592100..35eff9e6ce1605d5e3b7c6331ed34fe7073cc155 100644 (file)
@@ -201,28 +201,6 @@ struct amdgpu_gfx_funcs {
        int (*query_ras_error_count) (struct amdgpu_device *adev, void *ras_error_status);
 };
 
-struct amdgpu_ngg_buf {
-       struct amdgpu_bo        *bo;
-       uint64_t                gpu_addr;
-       uint32_t                size;
-       uint32_t                bo_size;
-};
-
-enum {
-       NGG_PRIM = 0,
-       NGG_POS,
-       NGG_CNTL,
-       NGG_PARAM,
-       NGG_BUF_MAX
-};
-
-struct amdgpu_ngg {
-       struct amdgpu_ngg_buf   buf[NGG_BUF_MAX];
-       uint32_t                gds_reserve_addr;
-       uint32_t                gds_reserve_size;
-       bool                    init;
-};
-
 struct sq_work {
        struct work_struct      work;
        unsigned ih_data;
@@ -311,9 +289,6 @@ struct amdgpu_gfx {
        uint32_t                        grbm_soft_reset;
        uint32_t                        srbm_soft_reset;
 
-       /* NGG */
-       struct amdgpu_ngg               ngg;
-
        /* gfx off */
        bool                            gfx_off_state; /* true: enabled, false: disabled */
        struct mutex                    gfx_off_mutex;
@@ -384,5 +359,12 @@ void amdgpu_gfx_bit_to_me_queue(struct amdgpu_device *adev, int bit,
 bool amdgpu_gfx_is_me_queue_enabled(struct amdgpu_device *adev, int me,
                                    int pipe, int queue);
 void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable);
-
+int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev);
+void amdgpu_gfx_ras_fini(struct amdgpu_device *adev);
+int amdgpu_gfx_process_ras_data_cb(struct amdgpu_device *adev,
+               void *err_data,
+               struct amdgpu_iv_entry *entry);
+int amdgpu_gfx_cp_ecc_error_irq(struct amdgpu_device *adev,
+                                 struct amdgpu_irq_src *source,
+                                 struct amdgpu_iv_entry *entry);
 #endif
index 5790db61fa2c013711d7438f9a92e7441f280f0b..a12f33c0f5df0d15e4295f8a6f072c5a03ad0c9a 100644 (file)
@@ -27,6 +27,8 @@
 #include <linux/io-64-nonatomic-lo-hi.h>
 
 #include "amdgpu.h"
+#include "amdgpu_ras.h"
+#include "amdgpu_xgmi.h"
 
 /**
  * amdgpu_gmc_get_pde_for_bo - get the PDE for a BO
@@ -305,3 +307,29 @@ bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev, uint64_t addr,
        gmc->fault_hash[hash].idx = gmc->last_fault++;
        return false;
 }
+
+int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev)
+{
+       int r;
+
+       if (adev->umc.funcs && adev->umc.funcs->ras_late_init) {
+               r = adev->umc.funcs->ras_late_init(adev);
+               if (r)
+                       return r;
+       }
+
+       if (adev->mmhub.funcs && adev->mmhub.funcs->ras_late_init) {
+               r = adev->mmhub.funcs->ras_late_init(adev);
+               if (r)
+                       return r;
+       }
+
+       return amdgpu_xgmi_ras_late_init(adev);
+}
+
+void amdgpu_gmc_ras_fini(struct amdgpu_device *adev)
+{
+       amdgpu_umc_ras_fini(adev);
+       amdgpu_mmhub_ras_fini(adev);
+       amdgpu_xgmi_ras_fini(adev);
+}
index b6e1d98ef01e145b1f91a2e96fea13ec67954914..555d8e57fae98add5345271cc2bb81529e363e17 100644 (file)
@@ -99,12 +99,15 @@ struct amdgpu_gmc_funcs {
                                   unsigned pasid);
        /* enable/disable PRT support */
        void (*set_prt)(struct amdgpu_device *adev, bool enable);
-       /* set pte flags based per asic */
-       uint64_t (*get_vm_pte_flags)(struct amdgpu_device *adev,
-                                    uint32_t flags);
+       /* map mtype to hardware flags */
+       uint64_t (*map_mtype)(struct amdgpu_device *adev, uint32_t flags);
        /* get the pde for a given mc addr */
        void (*get_vm_pde)(struct amdgpu_device *adev, int level,
                           u64 *dst, u64 *flags);
+       /* get the pte flags to use for a BO VA mapping */
+       void (*get_vm_pte)(struct amdgpu_device *adev,
+                          struct amdgpu_bo_va_mapping *mapping,
+                          uint64_t *flags);
 };
 
 struct amdgpu_xgmi {
@@ -120,6 +123,7 @@ struct amdgpu_xgmi {
        /* gpu list in the same hive */
        struct list_head head;
        bool supported;
+       struct ras_common_if *ras_if;
 };
 
 struct amdgpu_gmc {
@@ -153,6 +157,7 @@ struct amdgpu_gmc {
        uint32_t                fw_version;
        struct amdgpu_irq_src   vm_fault;
        uint32_t                vram_type;
+       uint8_t                 vram_vendor;
        uint32_t                srbm_soft_reset;
        bool                    prt_warning;
        uint64_t                stolen_size;
@@ -177,15 +182,14 @@ struct amdgpu_gmc {
 
        struct amdgpu_xgmi xgmi;
        struct amdgpu_irq_src   ecc_irq;
-       struct ras_common_if    *umc_ras_if;
-       struct ras_common_if    *mmhub_ras_if;
 };
 
 #define amdgpu_gmc_flush_gpu_tlb(adev, vmid, vmhub, type) ((adev)->gmc.gmc_funcs->flush_gpu_tlb((adev), (vmid), (vmhub), (type)))
 #define amdgpu_gmc_emit_flush_gpu_tlb(r, vmid, addr) (r)->adev->gmc.gmc_funcs->emit_flush_gpu_tlb((r), (vmid), (addr))
 #define amdgpu_gmc_emit_pasid_mapping(r, vmid, pasid) (r)->adev->gmc.gmc_funcs->emit_pasid_mapping((r), (vmid), (pasid))
+#define amdgpu_gmc_map_mtype(adev, flags) (adev)->gmc.gmc_funcs->map_mtype((adev),(flags))
 #define amdgpu_gmc_get_vm_pde(adev, level, dst, flags) (adev)->gmc.gmc_funcs->get_vm_pde((adev), (level), (dst), (flags))
-#define amdgpu_gmc_get_pte_flags(adev, flags) (adev)->gmc.gmc_funcs->get_vm_pte_flags((adev),(flags))
+#define amdgpu_gmc_get_vm_pte(adev, mapping, flags) (adev)->gmc.gmc_funcs->get_vm_pte((adev), (mapping), (flags))
 
 /**
  * amdgpu_gmc_vram_full_visible - Check if full VRAM is visible through the BAR
@@ -230,5 +234,7 @@ void amdgpu_gmc_agp_location(struct amdgpu_device *adev,
                             struct amdgpu_gmc *mc);
 bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev, uint64_t addr,
                              uint16_t pasid, uint64_t timestamp);
+int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev);
+void amdgpu_gmc_ras_fini(struct amdgpu_device *adev);
 
 #endif
index 53734da1c2df12361cb111ae4d309c639ec265e6..6f9289735e31a368b852af71c9ec6f3af280f6a6 100644 (file)
@@ -282,7 +282,7 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm,
            !dma_fence_is_later(updates, (*id)->flushed_updates))
            updates = NULL;
 
-       if ((*id)->owner != vm->entity.fence_context ||
+       if ((*id)->owner != vm->direct.fence_context ||
            job->vm_pd_addr != (*id)->pd_gpu_addr ||
            updates || !(*id)->last_flush ||
            ((*id)->last_flush->context != fence_context &&
@@ -349,7 +349,7 @@ static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm,
                struct dma_fence *flushed;
 
                /* Check all the prerequisites to using this VMID */
-               if ((*id)->owner != vm->entity.fence_context)
+               if ((*id)->owner != vm->direct.fence_context)
                        continue;
 
                if ((*id)->pd_gpu_addr != job->vm_pd_addr)
@@ -449,7 +449,7 @@ int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
        }
 
        id->pd_gpu_addr = job->vm_pd_addr;
-       id->owner = vm->entity.fence_context;
+       id->owner = vm->direct.fence_context;
 
        if (job->vm_needs_flush) {
                dma_fence_put(id->last_flush);
index 2a3f5ec298dbc7c74f632ba921c12ba8dd25299f..6f3b03f6224f1a7640d9d3df0649dfc977af4b5e 100644 (file)
@@ -87,10 +87,13 @@ static void amdgpu_hotplug_work_func(struct work_struct *work)
        struct drm_device *dev = adev->ddev;
        struct drm_mode_config *mode_config = &dev->mode_config;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
 
        mutex_lock(&mode_config->mutex);
-       list_for_each_entry(connector, &mode_config->connector_list, head)
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter)
                amdgpu_connector_hotplug(connector);
+       drm_connector_list_iter_end(&iter);
        mutex_unlock(&mode_config->mutex);
        /* Just fire off a uevent and let userspace tell us what to do */
        drm_helper_hpd_irq_event(dev);
@@ -153,6 +156,20 @@ irqreturn_t amdgpu_irq_handler(int irq, void *arg)
        ret = amdgpu_ih_process(adev, &adev->irq.ih);
        if (ret == IRQ_HANDLED)
                pm_runtime_mark_last_busy(dev->dev);
+
+       /* For the hardware that cannot enable bif ring for both ras_controller_irq
+         * and ras_err_evnet_athub_irq ih cookies, the driver has to poll status
+        * register to check whether the interrupt is triggered or not, and properly
+        * ack the interrupt if it is there
+        */
+       if (adev->nbio.funcs &&
+           adev->nbio.funcs->handle_ras_controller_intr_no_bifring)
+               adev->nbio.funcs->handle_ras_controller_intr_no_bifring(adev);
+
+       if (adev->nbio.funcs &&
+           adev->nbio.funcs->handle_ras_err_event_athub_intr_no_bifring)
+               adev->nbio.funcs->handle_ras_err_event_athub_intr_no_bifring(adev);
+
        return ret;
 }
 
@@ -228,10 +245,19 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
        adev->irq.msi_enabled = false;
 
        if (amdgpu_msi_ok(adev)) {
-               int ret = pci_enable_msi(adev->pdev);
-               if (!ret) {
+               int nvec = pci_msix_vec_count(adev->pdev);
+               unsigned int flags;
+
+               if (nvec <= 0) {
+                       flags = PCI_IRQ_MSI;
+               } else {
+                       flags = PCI_IRQ_MSI | PCI_IRQ_MSIX;
+               }
+               /* we only need one vector */
+               nvec = pci_alloc_irq_vectors(adev->pdev, 1, 1, flags);
+               if (nvec > 0) {
                        adev->irq.msi_enabled = true;
-                       dev_dbg(adev->dev, "amdgpu: using MSI.\n");
+                       dev_dbg(adev->dev, "amdgpu: using MSI/MSI-X.\n");
                }
        }
 
@@ -254,7 +280,8 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
        INIT_WORK(&adev->irq.ih2_work, amdgpu_irq_handle_ih2);
 
        adev->irq.installed = true;
-       r = drm_irq_install(adev->ddev, adev->ddev->pdev->irq);
+       /* Use vector 0 for MSI-X */
+       r = drm_irq_install(adev->ddev, pci_irq_vector(adev->pdev, 0));
        if (r) {
                adev->irq.installed = false;
                if (!amdgpu_device_has_dc_support(adev))
@@ -369,7 +396,7 @@ int amdgpu_irq_add_id(struct amdgpu_device *adev,
  * amdgpu_irq_dispatch - dispatch IRQ to IP blocks
  *
  * @adev: amdgpu device pointer
- * @entry: interrupt vector pointer
+ * @ih: interrupt ring instance
  *
  * Dispatches IRQ to IP blocks.
  */
index 9d76e0923a5a3a4d705a0905b63036344b3f3bd7..e1bad992e83bffff71b71b9a571f60d443b4aa21 100644 (file)
@@ -246,6 +246,44 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job)
        return fence;
 }
 
+#define to_drm_sched_job(sched_job)            \
+               container_of((sched_job), struct drm_sched_job, queue_node)
+
+void amdgpu_job_stop_all_jobs_on_sched(struct drm_gpu_scheduler *sched)
+{
+       struct drm_sched_job *s_job;
+       struct drm_sched_entity *s_entity = NULL;
+       int i;
+
+       /* Signal all jobs not yet scheduled */
+       for (i = DRM_SCHED_PRIORITY_MAX - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) {
+               struct drm_sched_rq *rq = &sched->sched_rq[i];
+
+               if (!rq)
+                       continue;
+
+               spin_lock(&rq->lock);
+               list_for_each_entry(s_entity, &rq->entities, list) {
+                       while ((s_job = to_drm_sched_job(spsc_queue_pop(&s_entity->job_queue)))) {
+                               struct drm_sched_fence *s_fence = s_job->s_fence;
+
+                               dma_fence_signal(&s_fence->scheduled);
+                               dma_fence_set_error(&s_fence->finished, -EHWPOISON);
+                               dma_fence_signal(&s_fence->finished);
+                       }
+               }
+               spin_unlock(&rq->lock);
+       }
+
+       /* Signal all jobs already scheduled to HW */
+       list_for_each_entry(s_job, &sched->ring_mirror_list, node) {
+               struct drm_sched_fence *s_fence = s_job->s_fence;
+
+               dma_fence_set_error(&s_fence->finished, -EHWPOISON);
+               dma_fence_signal(&s_fence->finished);
+       }
+}
+
 const struct drm_sched_backend_ops amdgpu_sched_ops = {
        .dependency = amdgpu_job_dependency,
        .run_job = amdgpu_job_run,
index 51e62504c2798a6f444d978cf66dbdfad1f81bc9..dc7ee9358dcd6ed01cd4cda96ce97a612c4ac61f 100644 (file)
@@ -76,4 +76,7 @@ int amdgpu_job_submit(struct amdgpu_job *job, struct drm_sched_entity *entity,
                      void *owner, struct dma_fence **f);
 int amdgpu_job_submit_direct(struct amdgpu_job *job, struct amdgpu_ring *ring,
                             struct dma_fence **fence);
+
+void amdgpu_job_stop_all_jobs_on_sched(struct drm_gpu_scheduler *sched);
+
 #endif
index d55f5baa83d37343edad07b6946f35fb04c698ac..137a8573d5569ca58ab9445438d37ece65c5111f 100644 (file)
@@ -584,9 +584,12 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
                struct drm_amdgpu_info_vram_gtt vram_gtt;
 
                vram_gtt.vram_size = adev->gmc.real_vram_size -
-                       atomic64_read(&adev->vram_pin_size);
-               vram_gtt.vram_cpu_accessible_size = adev->gmc.visible_vram_size -
-                       atomic64_read(&adev->visible_pin_size);
+                       atomic64_read(&adev->vram_pin_size) -
+                       AMDGPU_VM_RESERVED_VRAM;
+               vram_gtt.vram_cpu_accessible_size =
+                       min(adev->gmc.visible_vram_size -
+                           atomic64_read(&adev->visible_pin_size),
+                           vram_gtt.vram_size);
                vram_gtt.gtt_size = adev->mman.bdev.man[TTM_PL_TT].size;
                vram_gtt.gtt_size *= PAGE_SIZE;
                vram_gtt.gtt_size -= atomic64_read(&adev->gart_pin_size);
@@ -599,15 +602,18 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
                memset(&mem, 0, sizeof(mem));
                mem.vram.total_heap_size = adev->gmc.real_vram_size;
                mem.vram.usable_heap_size = adev->gmc.real_vram_size -
-                       atomic64_read(&adev->vram_pin_size);
+                       atomic64_read(&adev->vram_pin_size) -
+                       AMDGPU_VM_RESERVED_VRAM;
                mem.vram.heap_usage =
                        amdgpu_vram_mgr_usage(&adev->mman.bdev.man[TTM_PL_VRAM]);
                mem.vram.max_allocation = mem.vram.usable_heap_size * 3 / 4;
 
                mem.cpu_accessible_vram.total_heap_size =
                        adev->gmc.visible_vram_size;
-               mem.cpu_accessible_vram.usable_heap_size = adev->gmc.visible_vram_size -
-                       atomic64_read(&adev->visible_pin_size);
+               mem.cpu_accessible_vram.usable_heap_size =
+                       min(adev->gmc.visible_vram_size -
+                           atomic64_read(&adev->visible_pin_size),
+                           mem.vram.usable_heap_size);
                mem.cpu_accessible_vram.heap_usage =
                        amdgpu_vram_mgr_vis_usage(&adev->mman.bdev.man[TTM_PL_VRAM]);
                mem.cpu_accessible_vram.max_allocation =
@@ -729,17 +735,6 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
                dev_info.vce_harvest_config = adev->vce.harvest_config;
                dev_info.gc_double_offchip_lds_buf =
                        adev->gfx.config.double_offchip_lds_buf;
-
-               if (amdgpu_ngg) {
-                       dev_info.prim_buf_gpu_addr = adev->gfx.ngg.buf[NGG_PRIM].gpu_addr;
-                       dev_info.prim_buf_size = adev->gfx.ngg.buf[NGG_PRIM].size;
-                       dev_info.pos_buf_gpu_addr = adev->gfx.ngg.buf[NGG_POS].gpu_addr;
-                       dev_info.pos_buf_size = adev->gfx.ngg.buf[NGG_POS].size;
-                       dev_info.cntl_sb_buf_gpu_addr = adev->gfx.ngg.buf[NGG_CNTL].gpu_addr;
-                       dev_info.cntl_sb_buf_size = adev->gfx.ngg.buf[NGG_CNTL].size;
-                       dev_info.param_buf_gpu_addr = adev->gfx.ngg.buf[NGG_PARAM].gpu_addr;
-                       dev_info.param_buf_size = adev->gfx.ngg.buf[NGG_PARAM].size;
-               }
                dev_info.wave_front_size = adev->gfx.cu_info.wave_front_size;
                dev_info.num_shader_visible_vgprs = adev->gfx.config.max_gprs;
                dev_info.num_cu_per_sh = adev->gfx.config.max_cu_per_sh;
@@ -968,6 +963,12 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
        /* Ensure IB tests are run on ring */
        flush_delayed_work(&adev->delayed_init_work);
 
+
+       if (amdgpu_ras_intr_triggered()) {
+               DRM_ERROR("RAS Intr triggered, device disabled!!");
+               return -EHWPOISON;
+       }
+
        file_priv->driver_priv = NULL;
 
        r = pm_runtime_get_sync(dev->dev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c
new file mode 100644 (file)
index 0000000..676c48c
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright 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) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "amdgpu.h"
+#include "amdgpu_ras.h"
+
+int amdgpu_mmhub_ras_late_init(struct amdgpu_device *adev)
+{
+       int r;
+       struct ras_ih_if ih_info = {
+               .cb = NULL,
+       };
+       struct ras_fs_if fs_info = {
+               .sysfs_name = "mmhub_err_count",
+               .debugfs_name = "mmhub_err_inject",
+       };
+
+       if (!adev->mmhub.ras_if) {
+               adev->mmhub.ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL);
+               if (!adev->mmhub.ras_if)
+                       return -ENOMEM;
+               adev->mmhub.ras_if->block = AMDGPU_RAS_BLOCK__MMHUB;
+               adev->mmhub.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
+               adev->mmhub.ras_if->sub_block_index = 0;
+               strcpy(adev->mmhub.ras_if->name, "mmhub");
+       }
+       ih_info.head = fs_info.head = *adev->mmhub.ras_if;
+       r = amdgpu_ras_late_init(adev, adev->mmhub.ras_if,
+                                &fs_info, &ih_info);
+       if (r || !amdgpu_ras_is_supported(adev, adev->mmhub.ras_if->block)) {
+               kfree(adev->mmhub.ras_if);
+               adev->mmhub.ras_if = NULL;
+       }
+
+       return r;
+}
+
+void amdgpu_mmhub_ras_fini(struct amdgpu_device *adev)
+{
+       if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__MMHUB) &&
+                       adev->mmhub.ras_if) {
+               struct ras_common_if *ras_if = adev->mmhub.ras_if;
+               struct ras_ih_if ih_info = {
+                       .cb = NULL,
+               };
+
+               amdgpu_ras_late_fini(adev, ras_if, &ih_info);
+               kfree(ras_if);
+       }
+}
index 2d75ecfa199b61bbe1fd5192c2c42254b6bcf72f..1cd78940cf828b88a1a49b8de8ecfffae88b5ae5 100644 (file)
 
 struct amdgpu_mmhub_funcs {
        void (*ras_init)(struct amdgpu_device *adev);
+       int (*ras_late_init)(struct amdgpu_device *adev);
        void (*query_ras_error_count)(struct amdgpu_device *adev,
                                        void *ras_error_status);
 };
 
+struct amdgpu_mmhub {
+       struct ras_common_if *ras_if;
+       const struct amdgpu_mmhub_funcs *funcs;
+};
+
+int amdgpu_mmhub_ras_late_init(struct amdgpu_device *adev);
+void amdgpu_mmhub_ras_fini(struct amdgpu_device *adev);
 #endif
 
index 31d4deb5d294846aa6fc66c9f7ec8a7963604854..392300f77b1304b0e30df0ad6906e61fb4a0d4f6 100644 (file)
@@ -136,6 +136,7 @@ void amdgpu_mn_unlock(struct amdgpu_mn *mn)
  * amdgpu_mn_read_lock - take the read side lock for this notifier
  *
  * @amn: our notifier
+ * @blockable: is the notifier blockable
  */
 static int amdgpu_mn_read_lock(struct amdgpu_mn *amn, bool blockable)
 {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.c
new file mode 100644 (file)
index 0000000..7d5c3a9
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#include "amdgpu.h"
+#include "amdgpu_ras.h"
+
+int amdgpu_nbio_ras_late_init(struct amdgpu_device *adev)
+{
+       int r;
+       struct ras_ih_if ih_info = {
+               .cb = NULL,
+       };
+       struct ras_fs_if fs_info = {
+               .sysfs_name = "pcie_bif_err_count",
+               .debugfs_name = "pcie_bif_err_inject",
+       };
+
+       if (!adev->nbio.ras_if) {
+               adev->nbio.ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL);
+               if (!adev->nbio.ras_if)
+                       return -ENOMEM;
+               adev->nbio.ras_if->block = AMDGPU_RAS_BLOCK__PCIE_BIF;
+               adev->nbio.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
+               adev->nbio.ras_if->sub_block_index = 0;
+               strcpy(adev->nbio.ras_if->name, "pcie_bif");
+       }
+       ih_info.head = fs_info.head = *adev->nbio.ras_if;
+       r = amdgpu_ras_late_init(adev, adev->nbio.ras_if,
+                                &fs_info, &ih_info);
+       if (r)
+               goto free;
+
+       if (amdgpu_ras_is_supported(adev, adev->nbio.ras_if->block)) {
+               r = amdgpu_irq_get(adev, &adev->nbio.ras_controller_irq, 0);
+               if (r)
+                       goto late_fini;
+               r = amdgpu_irq_get(adev, &adev->nbio.ras_err_event_athub_irq, 0);
+               if (r)
+                       goto late_fini;
+       } else {
+               r = 0;
+               goto free;
+       }
+
+       return 0;
+late_fini:
+       amdgpu_ras_late_fini(adev, adev->nbio.ras_if, &ih_info);
+free:
+       kfree(adev->nbio.ras_if);
+       adev->nbio.ras_if = NULL;
+       return r;
+}
+
+void amdgpu_nbio_ras_fini(struct amdgpu_device *adev)
+{
+       if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__PCIE_BIF) &&
+                       adev->nbio.ras_if) {
+               struct ras_common_if *ras_if = adev->nbio.ras_if;
+               struct ras_ih_if ih_info = {
+                       .cb = NULL,
+               };
+
+               amdgpu_ras_late_fini(adev, ras_if, &ih_info);
+               kfree(ras_if);
+       }
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h
new file mode 100644 (file)
index 0000000..919bd56
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright 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) 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 __AMDGPU_NBIO_H__
+#define __AMDGPU_NBIO_H__
+
+/*
+ * amdgpu nbio functions
+ */
+struct nbio_hdp_flush_reg {
+       u32 ref_and_mask_cp0;
+       u32 ref_and_mask_cp1;
+       u32 ref_and_mask_cp2;
+       u32 ref_and_mask_cp3;
+       u32 ref_and_mask_cp4;
+       u32 ref_and_mask_cp5;
+       u32 ref_and_mask_cp6;
+       u32 ref_and_mask_cp7;
+       u32 ref_and_mask_cp8;
+       u32 ref_and_mask_cp9;
+       u32 ref_and_mask_sdma0;
+       u32 ref_and_mask_sdma1;
+       u32 ref_and_mask_sdma2;
+       u32 ref_and_mask_sdma3;
+       u32 ref_and_mask_sdma4;
+       u32 ref_and_mask_sdma5;
+       u32 ref_and_mask_sdma6;
+       u32 ref_and_mask_sdma7;
+};
+
+struct amdgpu_nbio_funcs {
+       const struct nbio_hdp_flush_reg *hdp_flush_reg;
+       u32 (*get_hdp_flush_req_offset)(struct amdgpu_device *adev);
+       u32 (*get_hdp_flush_done_offset)(struct amdgpu_device *adev);
+       u32 (*get_pcie_index_offset)(struct amdgpu_device *adev);
+       u32 (*get_pcie_data_offset)(struct amdgpu_device *adev);
+       u32 (*get_rev_id)(struct amdgpu_device *adev);
+       void (*mc_access_enable)(struct amdgpu_device *adev, bool enable);
+       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, int doorbell_size);
+       void (*vcn_doorbell_range)(struct amdgpu_device *adev, bool use_doorbell,
+                                  int doorbell_index, int instance);
+       void (*enable_doorbell_aperture)(struct amdgpu_device *adev,
+                                        bool enable);
+       void (*enable_doorbell_selfring_aperture)(struct amdgpu_device *adev,
+                                                 bool enable);
+       void (*ih_doorbell_range)(struct amdgpu_device *adev,
+                                 bool use_doorbell, int doorbell_index);
+       void (*enable_doorbell_interrupt)(struct amdgpu_device *adev,
+                                         bool enable);
+       void (*update_medium_grain_clock_gating)(struct amdgpu_device *adev,
+                                                bool enable);
+       void (*update_medium_grain_light_sleep)(struct amdgpu_device *adev,
+                                               bool enable);
+       void (*get_clockgating_state)(struct amdgpu_device *adev,
+                                     u32 *flags);
+       void (*ih_control)(struct amdgpu_device *adev);
+       void (*init_registers)(struct amdgpu_device *adev);
+       void (*detect_hw_virt)(struct amdgpu_device *adev);
+       void (*remap_hdp_registers)(struct amdgpu_device *adev);
+       void (*handle_ras_controller_intr_no_bifring)(struct amdgpu_device *adev);
+       void (*handle_ras_err_event_athub_intr_no_bifring)(struct amdgpu_device *adev);
+       int (*init_ras_controller_interrupt)(struct amdgpu_device *adev);
+       int (*init_ras_err_event_athub_interrupt)(struct amdgpu_device *adev);
+       void (*query_ras_error_count)(struct amdgpu_device *adev,
+                                       void *ras_error_status);
+       int (*ras_late_init)(struct amdgpu_device *adev);
+};
+
+struct amdgpu_nbio {
+       const struct nbio_hdp_flush_reg *hdp_flush_reg;
+       struct amdgpu_irq_src ras_controller_irq;
+       struct amdgpu_irq_src ras_err_event_athub_irq;
+       struct ras_common_if *ras_if;
+       const struct amdgpu_nbio_funcs *funcs;
+};
+
+int amdgpu_nbio_ras_late_init(struct amdgpu_device *adev);
+void amdgpu_nbio_ras_fini(struct amdgpu_device *adev);
+#endif
index 6f0b789a0b49a9d07e526cf74ebdd058d86bc87e..e3f16b49e970826023c52e8fa474d27414d0c5e7 100644 (file)
@@ -342,6 +342,70 @@ int amdgpu_bo_create_kernel(struct amdgpu_device *adev,
        return 0;
 }
 
+/**
+ * amdgpu_bo_create_kernel_at - create BO for kernel use at specific location
+ *
+ * @adev: amdgpu device object
+ * @offset: offset of the BO
+ * @size: size of the BO
+ * @domain: where to place it
+ * @bo_ptr:  used to initialize BOs in structures
+ * @cpu_addr: optional CPU address mapping
+ *
+ * Creates a kernel BO at a specific offset in the address space of the domain.
+ *
+ * Returns:
+ * 0 on success, negative error code otherwise.
+ */
+int amdgpu_bo_create_kernel_at(struct amdgpu_device *adev,
+                              uint64_t offset, uint64_t size, uint32_t domain,
+                              struct amdgpu_bo **bo_ptr, void **cpu_addr)
+{
+       struct ttm_operation_ctx ctx = { false, false };
+       unsigned int i;
+       int r;
+
+       offset &= PAGE_MASK;
+       size = ALIGN(size, PAGE_SIZE);
+
+       r = amdgpu_bo_create_reserved(adev, size, PAGE_SIZE, domain, bo_ptr,
+                                     NULL, cpu_addr);
+       if (r)
+               return r;
+
+       /*
+        * Remove the original mem node and create a new one at the request
+        * position.
+        */
+       if (cpu_addr)
+               amdgpu_bo_kunmap(*bo_ptr);
+
+       ttm_bo_mem_put(&(*bo_ptr)->tbo, &(*bo_ptr)->tbo.mem);
+
+       for (i = 0; i < (*bo_ptr)->placement.num_placement; ++i) {
+               (*bo_ptr)->placements[i].fpfn = offset >> PAGE_SHIFT;
+               (*bo_ptr)->placements[i].lpfn = (offset + size) >> PAGE_SHIFT;
+       }
+       r = ttm_bo_mem_space(&(*bo_ptr)->tbo, &(*bo_ptr)->placement,
+                            &(*bo_ptr)->tbo.mem, &ctx);
+       if (r)
+               goto error;
+
+       if (cpu_addr) {
+               r = amdgpu_bo_kmap(*bo_ptr, cpu_addr);
+               if (r)
+                       goto error;
+       }
+
+       amdgpu_bo_unreserve(*bo_ptr);
+       return 0;
+
+error:
+       amdgpu_bo_unreserve(*bo_ptr);
+       amdgpu_bo_unref(bo_ptr);
+       return r;
+}
+
 /**
  * amdgpu_bo_free_kernel - free BO for kernel use
  *
@@ -451,9 +515,10 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev,
 {
        struct ttm_operation_ctx ctx = {
                .interruptible = (bp->type != ttm_bo_type_kernel),
-               .no_wait_gpu = false,
+               .no_wait_gpu = bp->no_wait_gpu,
                .resv = bp->resv,
-               .flags = TTM_OPT_FLAG_ALLOW_RES_EVICT
+               .flags = bp->type != ttm_bo_type_kernel ?
+                       TTM_OPT_FLAG_ALLOW_RES_EVICT : 0
        };
        struct amdgpu_bo *bo;
        unsigned long page_align, size = bp->size;
index 658f4c9779b704831c8ebe472ba343921da62429..7e99f6c58c4871dd36ccf039f6ff4e02211ac821 100644 (file)
@@ -41,6 +41,7 @@ struct amdgpu_bo_param {
        u32                             preferred_domain;
        u64                             flags;
        enum ttm_bo_type                type;
+       bool                            no_wait_gpu;
        struct dma_resv *resv;
 };
 
@@ -237,6 +238,9 @@ int amdgpu_bo_create_kernel(struct amdgpu_device *adev,
                            unsigned long size, int align,
                            u32 domain, struct amdgpu_bo **bo_ptr,
                            u64 *gpu_addr, void **cpu_addr);
+int amdgpu_bo_create_kernel_at(struct amdgpu_device *adev,
+                              uint64_t offset, uint64_t size, uint32_t domain,
+                              struct amdgpu_bo **bo_ptr, void **cpu_addr);
 void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr,
                           void **cpu_addr);
 int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr);
index 03930313c2638f5138a6a023a0a06c58cb804e68..d638661644965e0843e0deeee7278243e547396e 100644 (file)
@@ -805,8 +805,7 @@ static ssize_t amdgpu_get_pp_feature_status(struct device *dev,
 }
 
 /**
- * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_dcefclk
- * pp_dpm_pcie
+ * 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,
@@ -822,9 +821,15 @@ static ssize_t amdgpu_get_pp_feature_status(struct device *dev,
  *
  * To manually adjust these states, first select manual using
  * power_dpm_force_performance_level.
- * Secondly,Enter a new value for each level by inputing a string that
+ * 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.
+ * E.g.,
+ *
+ * .. code-block:: bash
+ *
+ *     echo "4 5 6" > pp_dpm_sclk
+ *
+ * will enable sclk levels 4, 5, and 6.
  *
  * NOTE: change to the dcefclk max dpm level is not supported now
  */
@@ -2196,9 +2201,9 @@ static ssize_t amdgpu_hwmon_show_mclk_label(struct device *dev,
  *
  * - fan1_input: fan speed in RPM
  *
- * - fan[1-*]_target: Desired fan speed Unit: revolution/min (RPM)
+ * - fan[1-\*]_target: Desired fan speed Unit: revolution/min (RPM)
  *
- * - fan[1-*]_enable: Enable or disable the sensors.1: Enable 0: Disable
+ * - fan[1-\*]_enable: Enable or disable the sensors.1: Enable 0: Disable
  *
  * hwmon interfaces for GPU clocks:
  *
index 4d71537a960d72e14638acc34c763480e762d75c..b996b5bc5804961a0430e5489fb4b10ca6f04c8a 100644 (file)
@@ -88,6 +88,17 @@ static int psp_sw_init(void *handle)
                return ret;
        }
 
+       ret = psp_mem_training_init(psp);
+       if (ret) {
+               DRM_ERROR("Failed to initliaze memory training!\n");
+               return ret;
+       }
+       ret = psp_mem_training(psp, PSP_MEM_TRAIN_COLD_BOOT);
+       if (ret) {
+               DRM_ERROR("Failed to process memory training!\n");
+               return ret;
+       }
+
        return 0;
 }
 
@@ -95,6 +106,7 @@ static int psp_sw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       psp_mem_training_fini(&adev->psp);
        release_firmware(adev->psp.sos_fw);
        adev->psp.sos_fw = NULL;
        release_firmware(adev->psp.asd_fw);
@@ -151,10 +163,12 @@ psp_cmd_submit_buf(struct psp_context *psp,
                return ret;
        }
 
+       amdgpu_asic_invalidate_hdp(psp->adev, NULL);
        while (*((unsigned int *)psp->fence_buf) != index) {
                if (--timeout == 0)
                        break;
                msleep(1);
+               amdgpu_asic_invalidate_hdp(psp->adev, NULL);
        }
 
        /* In some cases, psp response status is not 0 even there is no
@@ -168,8 +182,9 @@ psp_cmd_submit_buf(struct psp_context *psp,
                if (ucode)
                        DRM_WARN("failed to load ucode id (%d) ",
                                  ucode->ucode_id);
-               DRM_WARN("psp command failed and response status is (0x%X)\n",
-                         psp->cmd_buf_mem->resp.status & GFX_CMD_STATUS_MASK);
+               DRM_DEBUG_DRIVER("psp command (0x%X) failed and response status is (0x%X)\n",
+                        psp->cmd_buf_mem->cmd_id,
+                        psp->cmd_buf_mem->resp.status & GFX_CMD_STATUS_MASK);
                if (!timeout) {
                        mutex_unlock(&psp->mutex);
                        return -EINVAL;
@@ -253,7 +268,8 @@ static int psp_tmr_init(struct psp_context *psp)
 
        /* For ASICs support RLC autoload, psp will parse the toc
         * and calculate the total size of TMR needed */
-       if (psp->toc_start_addr &&
+       if (!amdgpu_sriov_vf(psp->adev) &&
+           psp->toc_start_addr &&
            psp->toc_bin_size &&
            psp->fw_pri_buf) {
                ret = psp_load_toc(psp, &tmr_size);
@@ -287,15 +303,9 @@ static int psp_tmr_load(struct psp_context *psp)
 
        ret = psp_cmd_submit_buf(psp, NULL, cmd,
                                 psp->fence_buf_mc_addr);
-       if (ret)
-               goto failed;
 
        kfree(cmd);
 
-       return 0;
-
-failed:
-       kfree(cmd);
        return ret;
 }
 
@@ -772,6 +782,324 @@ static int psp_ras_initialize(struct psp_context *psp)
 }
 // ras end
 
+// HDCP start
+static void psp_prep_hdcp_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd,
+                                         uint64_t hdcp_ta_mc,
+                                         uint64_t hdcp_mc_shared,
+                                         uint32_t hdcp_ta_size,
+                                         uint32_t shared_size)
+{
+       cmd->cmd_id = GFX_CMD_ID_LOAD_TA;
+       cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(hdcp_ta_mc);
+       cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(hdcp_ta_mc);
+       cmd->cmd.cmd_load_ta.app_len = hdcp_ta_size;
+
+       cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo =
+               lower_32_bits(hdcp_mc_shared);
+       cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi =
+               upper_32_bits(hdcp_mc_shared);
+       cmd->cmd.cmd_load_ta.cmd_buf_len = shared_size;
+}
+
+static int psp_hdcp_init_shared_buf(struct psp_context *psp)
+{
+       int ret;
+
+       /*
+        * Allocate 16k memory aligned to 4k from Frame Buffer (local
+        * physical) for hdcp ta <-> Driver
+        */
+       ret = amdgpu_bo_create_kernel(psp->adev, PSP_HDCP_SHARED_MEM_SIZE,
+                                     PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
+                                     &psp->hdcp_context.hdcp_shared_bo,
+                                     &psp->hdcp_context.hdcp_shared_mc_addr,
+                                     &psp->hdcp_context.hdcp_shared_buf);
+
+       return ret;
+}
+
+static int psp_hdcp_load(struct psp_context *psp)
+{
+       int ret;
+       struct psp_gfx_cmd_resp *cmd;
+
+       /*
+        * TODO: bypass the loading in sriov for now
+        */
+       if (amdgpu_sriov_vf(psp->adev))
+               return 0;
+
+       cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
+       if (!cmd)
+               return -ENOMEM;
+
+       memset(psp->fw_pri_buf, 0, PSP_1_MEG);
+       memcpy(psp->fw_pri_buf, psp->ta_hdcp_start_addr,
+              psp->ta_hdcp_ucode_size);
+
+       psp_prep_hdcp_ta_load_cmd_buf(cmd, psp->fw_pri_mc_addr,
+                                     psp->hdcp_context.hdcp_shared_mc_addr,
+                                     psp->ta_hdcp_ucode_size,
+                                     PSP_HDCP_SHARED_MEM_SIZE);
+
+       ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
+
+       if (!ret) {
+               psp->hdcp_context.hdcp_initialized = 1;
+               psp->hdcp_context.session_id = cmd->resp.session_id;
+       }
+
+       kfree(cmd);
+
+       return ret;
+}
+static int psp_hdcp_initialize(struct psp_context *psp)
+{
+       int ret;
+
+       if (!psp->hdcp_context.hdcp_initialized) {
+               ret = psp_hdcp_init_shared_buf(psp);
+               if (ret)
+                       return ret;
+       }
+
+       ret = psp_hdcp_load(psp);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+static void psp_prep_hdcp_ta_unload_cmd_buf(struct psp_gfx_cmd_resp *cmd,
+                                           uint32_t hdcp_session_id)
+{
+       cmd->cmd_id = GFX_CMD_ID_UNLOAD_TA;
+       cmd->cmd.cmd_unload_ta.session_id = hdcp_session_id;
+}
+
+static int psp_hdcp_unload(struct psp_context *psp)
+{
+       int ret;
+       struct psp_gfx_cmd_resp *cmd;
+
+       /*
+        * TODO: bypass the unloading in sriov for now
+        */
+       if (amdgpu_sriov_vf(psp->adev))
+               return 0;
+
+       cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
+       if (!cmd)
+               return -ENOMEM;
+
+       psp_prep_hdcp_ta_unload_cmd_buf(cmd, psp->hdcp_context.session_id);
+
+       ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
+
+       kfree(cmd);
+
+       return ret;
+}
+
+static void psp_prep_hdcp_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd,
+                                           uint32_t ta_cmd_id,
+                                           uint32_t hdcp_session_id)
+{
+       cmd->cmd_id = GFX_CMD_ID_INVOKE_CMD;
+       cmd->cmd.cmd_invoke_cmd.session_id = hdcp_session_id;
+       cmd->cmd.cmd_invoke_cmd.ta_cmd_id = ta_cmd_id;
+       /* Note: cmd_invoke_cmd.buf is not used for now */
+}
+
+int psp_hdcp_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
+{
+       int ret;
+       struct psp_gfx_cmd_resp *cmd;
+
+       /*
+        * TODO: bypass the loading in sriov for now
+        */
+       if (amdgpu_sriov_vf(psp->adev))
+               return 0;
+
+       cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
+       if (!cmd)
+               return -ENOMEM;
+
+       psp_prep_hdcp_ta_invoke_cmd_buf(cmd, ta_cmd_id,
+                                       psp->hdcp_context.session_id);
+
+       ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
+
+       kfree(cmd);
+
+       return ret;
+}
+
+static int psp_hdcp_terminate(struct psp_context *psp)
+{
+       int ret;
+
+       if (!psp->hdcp_context.hdcp_initialized)
+               return 0;
+
+       ret = psp_hdcp_unload(psp);
+       if (ret)
+               return ret;
+
+       psp->hdcp_context.hdcp_initialized = 0;
+
+       /* free hdcp shared memory */
+       amdgpu_bo_free_kernel(&psp->hdcp_context.hdcp_shared_bo,
+                             &psp->hdcp_context.hdcp_shared_mc_addr,
+                             &psp->hdcp_context.hdcp_shared_buf);
+
+       return 0;
+}
+// HDCP end
+
+// DTM start
+static void psp_prep_dtm_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd,
+                                        uint64_t dtm_ta_mc,
+                                        uint64_t dtm_mc_shared,
+                                        uint32_t dtm_ta_size,
+                                        uint32_t shared_size)
+{
+       cmd->cmd_id = GFX_CMD_ID_LOAD_TA;
+       cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(dtm_ta_mc);
+       cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(dtm_ta_mc);
+       cmd->cmd.cmd_load_ta.app_len = dtm_ta_size;
+
+       cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = lower_32_bits(dtm_mc_shared);
+       cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = upper_32_bits(dtm_mc_shared);
+       cmd->cmd.cmd_load_ta.cmd_buf_len = shared_size;
+}
+
+static int psp_dtm_init_shared_buf(struct psp_context *psp)
+{
+       int ret;
+
+       /*
+        * Allocate 16k memory aligned to 4k from Frame Buffer (local
+        * physical) for dtm ta <-> Driver
+        */
+       ret = amdgpu_bo_create_kernel(psp->adev, PSP_DTM_SHARED_MEM_SIZE,
+                                     PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
+                                     &psp->dtm_context.dtm_shared_bo,
+                                     &psp->dtm_context.dtm_shared_mc_addr,
+                                     &psp->dtm_context.dtm_shared_buf);
+
+       return ret;
+}
+
+static int psp_dtm_load(struct psp_context *psp)
+{
+       int ret;
+       struct psp_gfx_cmd_resp *cmd;
+
+       /*
+        * TODO: bypass the loading in sriov for now
+        */
+       if (amdgpu_sriov_vf(psp->adev))
+               return 0;
+
+       cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
+       if (!cmd)
+               return -ENOMEM;
+
+       memset(psp->fw_pri_buf, 0, PSP_1_MEG);
+       memcpy(psp->fw_pri_buf, psp->ta_dtm_start_addr, psp->ta_dtm_ucode_size);
+
+       psp_prep_dtm_ta_load_cmd_buf(cmd, psp->fw_pri_mc_addr,
+                                    psp->dtm_context.dtm_shared_mc_addr,
+                                    psp->ta_dtm_ucode_size,
+                                    PSP_DTM_SHARED_MEM_SIZE);
+
+       ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
+
+       if (!ret) {
+               psp->dtm_context.dtm_initialized = 1;
+               psp->dtm_context.session_id = cmd->resp.session_id;
+       }
+
+       kfree(cmd);
+
+       return ret;
+}
+
+static int psp_dtm_initialize(struct psp_context *psp)
+{
+       int ret;
+
+       if (!psp->dtm_context.dtm_initialized) {
+               ret = psp_dtm_init_shared_buf(psp);
+               if (ret)
+                       return ret;
+       }
+
+       ret = psp_dtm_load(psp);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static void psp_prep_dtm_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd,
+                                          uint32_t ta_cmd_id,
+                                          uint32_t dtm_session_id)
+{
+       cmd->cmd_id = GFX_CMD_ID_INVOKE_CMD;
+       cmd->cmd.cmd_invoke_cmd.session_id = dtm_session_id;
+       cmd->cmd.cmd_invoke_cmd.ta_cmd_id = ta_cmd_id;
+       /* Note: cmd_invoke_cmd.buf is not used for now */
+}
+
+int psp_dtm_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
+{
+       int ret;
+       struct psp_gfx_cmd_resp *cmd;
+
+       /*
+        * TODO: bypass the loading in sriov for now
+        */
+       if (amdgpu_sriov_vf(psp->adev))
+               return 0;
+
+       cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
+       if (!cmd)
+               return -ENOMEM;
+
+       psp_prep_dtm_ta_invoke_cmd_buf(cmd, ta_cmd_id,
+                                      psp->dtm_context.session_id);
+
+       ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
+
+       kfree(cmd);
+
+       return ret;
+}
+
+static int psp_dtm_terminate(struct psp_context *psp)
+{
+       int ret;
+
+       if (!psp->dtm_context.dtm_initialized)
+               return 0;
+
+       ret = psp_hdcp_unload(psp);
+       if (ret)
+               return ret;
+
+       psp->dtm_context.dtm_initialized = 0;
+
+       /* free hdcp shared memory */
+       amdgpu_bo_free_kernel(&psp->dtm_context.dtm_shared_bo,
+                             &psp->dtm_context.dtm_shared_mc_addr,
+                             &psp->dtm_context.dtm_shared_buf);
+
+       return 0;
+}
+// DTM end
+
 static int psp_hw_start(struct psp_context *psp)
 {
        struct amdgpu_device *adev = psp->adev;
@@ -845,6 +1173,16 @@ static int psp_hw_start(struct psp_context *psp)
                if (ret)
                        dev_err(psp->adev->dev,
                                        "RAS: Failed to initialize RAS\n");
+
+               ret = psp_hdcp_initialize(psp);
+               if (ret)
+                       dev_err(psp->adev->dev,
+                               "HDCP: Failed to initialize HDCP\n");
+
+               ret = psp_dtm_initialize(psp);
+               if (ret)
+                       dev_err(psp->adev->dev,
+                               "DTM: Failed to initialize DTM\n");
        }
 
        return 0;
@@ -950,21 +1288,7 @@ static void psp_print_fw_hdr(struct psp_context *psp,
                             struct amdgpu_firmware_info *ucode)
 {
        struct amdgpu_device *adev = psp->adev;
-       const struct sdma_firmware_header_v1_0 *sdma_hdr =
-               (const struct sdma_firmware_header_v1_0 *)
-               adev->sdma.instance[ucode->ucode_id - AMDGPU_UCODE_ID_SDMA0].fw->data;
-       const struct gfx_firmware_header_v1_0 *ce_hdr =
-               (const struct gfx_firmware_header_v1_0 *)adev->gfx.ce_fw->data;
-       const struct gfx_firmware_header_v1_0 *pfp_hdr =
-               (const struct gfx_firmware_header_v1_0 *)adev->gfx.pfp_fw->data;
-       const struct gfx_firmware_header_v1_0 *me_hdr =
-               (const struct gfx_firmware_header_v1_0 *)adev->gfx.me_fw->data;
-       const struct gfx_firmware_header_v1_0 *mec_hdr =
-               (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
-       const struct rlc_firmware_header_v2_0 *rlc_hdr =
-               (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
-       const struct smc_firmware_header_v1_0 *smc_hdr =
-               (const struct smc_firmware_header_v1_0 *)adev->pm.fw->data;
+       struct common_firmware_header *hdr;
 
        switch (ucode->ucode_id) {
        case AMDGPU_UCODE_ID_SDMA0:
@@ -975,25 +1299,33 @@ static void psp_print_fw_hdr(struct psp_context *psp,
        case AMDGPU_UCODE_ID_SDMA5:
        case AMDGPU_UCODE_ID_SDMA6:
        case AMDGPU_UCODE_ID_SDMA7:
-               amdgpu_ucode_print_sdma_hdr(&sdma_hdr->header);
+               hdr = (struct common_firmware_header *)
+                       adev->sdma.instance[ucode->ucode_id - AMDGPU_UCODE_ID_SDMA0].fw->data;
+               amdgpu_ucode_print_sdma_hdr(hdr);
                break;
        case AMDGPU_UCODE_ID_CP_CE:
-               amdgpu_ucode_print_gfx_hdr(&ce_hdr->header);
+               hdr = (struct common_firmware_header *)adev->gfx.ce_fw->data;
+               amdgpu_ucode_print_gfx_hdr(hdr);
                break;
        case AMDGPU_UCODE_ID_CP_PFP:
-               amdgpu_ucode_print_gfx_hdr(&pfp_hdr->header);
+               hdr = (struct common_firmware_header *)adev->gfx.pfp_fw->data;
+               amdgpu_ucode_print_gfx_hdr(hdr);
                break;
        case AMDGPU_UCODE_ID_CP_ME:
-               amdgpu_ucode_print_gfx_hdr(&me_hdr->header);
+               hdr = (struct common_firmware_header *)adev->gfx.me_fw->data;
+               amdgpu_ucode_print_gfx_hdr(hdr);
                break;
        case AMDGPU_UCODE_ID_CP_MEC1:
-               amdgpu_ucode_print_gfx_hdr(&mec_hdr->header);
+               hdr = (struct common_firmware_header *)adev->gfx.mec_fw->data;
+               amdgpu_ucode_print_gfx_hdr(hdr);
                break;
        case AMDGPU_UCODE_ID_RLC_G:
-               amdgpu_ucode_print_rlc_hdr(&rlc_hdr->header);
+               hdr = (struct common_firmware_header *)adev->gfx.rlc_fw->data;
+               amdgpu_ucode_print_rlc_hdr(hdr);
                break;
        case AMDGPU_UCODE_ID_SMC:
-               amdgpu_ucode_print_smc_hdr(&smc_hdr->header);
+               hdr = (struct common_firmware_header *)adev->pm.fw->data;
+               amdgpu_ucode_print_smc_hdr(hdr);
                break;
        default:
                break;
@@ -1079,10 +1411,6 @@ static int psp_np_fw_load(struct psp_context *psp)
                     ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC2_JT))
                        /* skip mec JT when autoload is enabled */
                        continue;
-               /* Renoir only needs to load mec jump table one time */
-               if (adev->asic_type == CHIP_RENOIR &&
-                   ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC2_JT)
-                       continue;
 
                psp_print_fw_hdr(psp, ucode);
 
@@ -1091,7 +1419,8 @@ static int psp_np_fw_load(struct psp_context *psp)
                        return ret;
 
                /* Start rlc autoload after psp recieved all the gfx firmware */
-               if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM) {
+               if (psp->autoload_supported && ucode->ucode_id ==
+                       AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM) {
                        ret = psp_rlc_autoload(psp);
                        if (ret) {
                                DRM_ERROR("Failed to start rlc autoload\n");
@@ -1216,8 +1545,11 @@ static int psp_hw_fini(void *handle)
            psp->xgmi_context.initialized == 1)
                 psp_xgmi_terminate(psp);
 
-       if (psp->adev->psp.ta_fw)
+       if (psp->adev->psp.ta_fw) {
                psp_ras_terminate(psp);
+               psp_dtm_terminate(psp);
+               psp_hdcp_terminate(psp);
+       }
 
        psp_ring_destroy(psp, PSP_RING_TYPE__KM);
 
@@ -1259,6 +1591,16 @@ static int psp_suspend(void *handle)
                        DRM_ERROR("Failed to terminate ras ta\n");
                        return ret;
                }
+               ret = psp_hdcp_terminate(psp);
+               if (ret) {
+                       DRM_ERROR("Failed to terminate hdcp ta\n");
+                       return ret;
+               }
+               ret = psp_dtm_terminate(psp);
+               if (ret) {
+                       DRM_ERROR("Failed to terminate dtm ta\n");
+                       return ret;
+               }
        }
 
        ret = psp_ring_stop(psp, PSP_RING_TYPE__KM);
@@ -1278,6 +1620,12 @@ static int psp_resume(void *handle)
 
        DRM_INFO("PSP is resuming...\n");
 
+       ret = psp_mem_training(psp, PSP_MEM_TRAIN_RESUME);
+       if (ret) {
+               DRM_ERROR("Failed to process memory training!\n");
+               return ret;
+       }
+
        mutex_lock(&adev->firmware.mutex);
 
        ret = psp_hw_start(psp);
@@ -1317,9 +1665,6 @@ int psp_rlc_autoload_start(struct psp_context *psp)
        int ret;
        struct psp_gfx_cmd_resp *cmd;
 
-       if (amdgpu_sriov_vf(psp->adev))
-               return 0;
-
        cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
        if (!cmd)
                return -ENOMEM;
index bc0947f6bc8a929226e64303bfe8be6cd434be9a..09c5474ebcc348b7b4461395832c9511092aed31 100644 (file)
@@ -37,6 +37,9 @@
 #define PSP_RAS_SHARED_MEM_SIZE 0x4000
 #define PSP_1_MEG              0x100000
 #define PSP_TMR_SIZE   0x400000
+#define PSP_HDCP_SHARED_MEM_SIZE       0x4000
+#define PSP_DTM_SHARED_MEM_SIZE        0x4000
+#define PSP_SHARED_MEM_SIZE            0x4000
 
 struct psp_context;
 struct psp_xgmi_node_info;
@@ -46,6 +49,8 @@ enum psp_bootloader_cmd {
        PSP_BL__LOAD_SYSDRV             = 0x10000,
        PSP_BL__LOAD_SOSDRV             = 0x20000,
        PSP_BL__LOAD_KEY_DATABASE       = 0x80000,
+       PSP_BL__DRAM_LONG_TRAIN         = 0x100000,
+       PSP_BL__DRAM_SHORT_TRAIN        = 0x200000,
 };
 
 enum psp_ring_type
@@ -108,6 +113,9 @@ struct psp_funcs
                        struct ta_ras_trigger_error_input *info);
        int (*ras_cure_posion)(struct psp_context *psp, uint64_t *mode_ptr);
        int (*rlc_autoload_start)(struct psp_context *psp);
+       int (*mem_training_init)(struct psp_context *psp);
+       void (*mem_training_fini)(struct psp_context *psp);
+       int (*mem_training)(struct psp_context *psp, uint32_t ops);
 };
 
 #define AMDGPU_XGMI_MAX_CONNECTED_NODES                64
@@ -142,6 +150,65 @@ struct psp_ras_context {
        struct amdgpu_ras       *ras;
 };
 
+struct psp_hdcp_context {
+       bool                    hdcp_initialized;
+       uint32_t                session_id;
+       struct amdgpu_bo        *hdcp_shared_bo;
+       uint64_t                hdcp_shared_mc_addr;
+       void                    *hdcp_shared_buf;
+};
+
+struct psp_dtm_context {
+       bool                    dtm_initialized;
+       uint32_t                session_id;
+       struct amdgpu_bo        *dtm_shared_bo;
+       uint64_t                dtm_shared_mc_addr;
+       void                    *dtm_shared_buf;
+};
+
+#define MEM_TRAIN_SYSTEM_SIGNATURE             0x54534942
+#define GDDR6_MEM_TRAINING_DATA_SIZE_IN_BYTES  0x1000
+#define GDDR6_MEM_TRAINING_OFFSET              0x8000
+
+enum psp_memory_training_init_flag {
+       PSP_MEM_TRAIN_NOT_SUPPORT       = 0x0,
+       PSP_MEM_TRAIN_SUPPORT           = 0x1,
+       PSP_MEM_TRAIN_INIT_FAILED       = 0x2,
+       PSP_MEM_TRAIN_RESERVE_SUCCESS   = 0x4,
+       PSP_MEM_TRAIN_INIT_SUCCESS      = 0x8,
+};
+
+enum psp_memory_training_ops {
+       PSP_MEM_TRAIN_SEND_LONG_MSG     = 0x1,
+       PSP_MEM_TRAIN_SAVE              = 0x2,
+       PSP_MEM_TRAIN_RESTORE           = 0x4,
+       PSP_MEM_TRAIN_SEND_SHORT_MSG    = 0x8,
+       PSP_MEM_TRAIN_COLD_BOOT         = PSP_MEM_TRAIN_SEND_LONG_MSG,
+       PSP_MEM_TRAIN_RESUME            = PSP_MEM_TRAIN_SEND_SHORT_MSG,
+};
+
+struct psp_memory_training_context {
+       /*training data size*/
+       u64 train_data_size;
+       /*
+        * sys_cache
+        * cpu virtual address
+        * system memory buffer that used to store the training data.
+        */
+       void *sys_cache;
+
+       /*vram offset of the p2c training data*/
+       u64 p2c_train_data_offset;
+       struct amdgpu_bo *p2c_bo;
+
+       /*vram offset of the c2p training data*/
+       u64 c2p_train_data_offset;
+       struct amdgpu_bo *c2p_bo;
+
+       enum psp_memory_training_init_flag init;
+       u32 training_cnt;
+};
+
 struct psp_context
 {
        struct amdgpu_device            *adev;
@@ -206,9 +273,21 @@ struct psp_context
        uint32_t                        ta_ras_ucode_version;
        uint32_t                        ta_ras_ucode_size;
        uint8_t                         *ta_ras_start_addr;
+
+       uint32_t                        ta_hdcp_ucode_version;
+       uint32_t                        ta_hdcp_ucode_size;
+       uint8_t                         *ta_hdcp_start_addr;
+
+       uint32_t                        ta_dtm_ucode_version;
+       uint32_t                        ta_dtm_ucode_size;
+       uint8_t                         *ta_dtm_start_addr;
+
        struct psp_xgmi_context         xgmi_context;
        struct psp_ras_context          ras;
+       struct psp_hdcp_context         hdcp_context;
+       struct psp_dtm_context          dtm_context;
        struct mutex                    mutex;
+       struct psp_memory_training_context mem_train_ctx;
 };
 
 struct amdgpu_psp_funcs {
@@ -251,6 +330,12 @@ struct amdgpu_psp_funcs {
                (psp)->funcs->xgmi_set_topology_info((psp), (num_device), (topology)) : -EINVAL)
 #define psp_rlc_autoload(psp) \
                ((psp)->funcs->rlc_autoload_start ? (psp)->funcs->rlc_autoload_start((psp)) : 0)
+#define psp_mem_training_init(psp) \
+       ((psp)->funcs->mem_training_init ? (psp)->funcs->mem_training_init((psp)) : 0)
+#define psp_mem_training_fini(psp) \
+       ((psp)->funcs->mem_training_fini ? (psp)->funcs->mem_training_fini((psp)) : 0)
+#define psp_mem_training(psp, ops) \
+       ((psp)->funcs->mem_training ? (psp)->funcs->mem_training((psp), (ops)) : 0)
 
 #define amdgpu_psp_check_fw_loading_status(adev, i) (adev)->firmware.funcs->check_fw_loading_status((adev), (i))
 
@@ -279,6 +364,8 @@ int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id);
 int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id);
 int psp_ras_enable_features(struct psp_context *psp,
                union ta_ras_cmd_input *info, bool enable);
+int psp_hdcp_invoke(struct psp_context *psp, uint32_t ta_cmd_id);
+int psp_dtm_invoke(struct psp_context *psp, uint32_t ta_cmd_id);
 
 int psp_rlc_autoload_start(struct psp_context *psp);
 
index 016ea274b955cac5ba37418701084faa0c7e41cd..6220394521e42da5980b4c147417ca41ef183af3 100644 (file)
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/uaccess.h>
+#include <linux/reboot.h>
+#include <linux/syscalls.h>
 
 #include "amdgpu.h"
 #include "amdgpu_ras.h"
 #include "amdgpu_atomfirmware.h"
+#include "ivsrcid/nbio/irqsrcs_nbif_7_4.h"
 
 const char *ras_error_string[] = {
        "none",
@@ -65,11 +68,11 @@ const char *ras_block_string[] = {
 /* inject address is 52 bits */
 #define        RAS_UMC_INJECT_ADDR_LIMIT       (0x1ULL << 52)
 
-static int amdgpu_ras_reserve_vram(struct amdgpu_device *adev,
-               uint64_t offset, uint64_t size,
-               struct amdgpu_bo **bo_ptr);
-static int amdgpu_ras_release_vram(struct amdgpu_device *adev,
-               struct amdgpu_bo **bo_ptr);
+
+atomic_t amdgpu_ras_in_intr = ATOMIC_INIT(0);
+
+static bool amdgpu_ras_check_bad_page(struct amdgpu_device *adev,
+                               uint64_t addr);
 
 static ssize_t amdgpu_ras_debugfs_read(struct file *f, char __user *buf,
                                        size_t size, loff_t *pos)
@@ -150,6 +153,8 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file *f,
                op = 1;
        else if (sscanf(str, "inject %32s %8s", block_name, err) == 2)
                op = 2;
+       else if (sscanf(str, "reboot %32s", block_name) == 1)
+               op = 3;
        else if (str[0] && str[1] && str[2] && str[3])
                /* ascii string, but commands are not matched. */
                return -EINVAL;
@@ -189,6 +194,10 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file *f,
 
        return 0;
 }
+
+static struct ras_manager *amdgpu_ras_find_obj(struct amdgpu_device *adev,
+               struct ras_common_if *head);
+
 /**
  * DOC: AMDGPU RAS debugfs control interface
  *
@@ -209,30 +218,38 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file *f,
  * value to the address.
  *
  * Second member: struct ras_debug_if::op.
- * It has three kinds of operations.
- *  0: disable RAS on the block. Take ::head as its data.
- *  1: enable RAS on the block. Take ::head as its data.
- *  2: inject errors on the block. Take ::inject as its data.
+ * It has four kinds of operations.
+ *
+ * - 0: disable RAS on the block. Take ::head as its data.
+ * - 1: enable RAS on the block. Take ::head as its data.
+ * - 2: inject errors on the block. Take ::inject as its data.
+ * - 3: reboot on unrecoverable error
  *
  * How to use the interface?
  * programs:
  * copy the struct ras_debug_if in your codes and initialize it.
  * write the struct to the control node.
  *
- * bash:
- * echo op block [error [sub_blcok address value]] > .../ras/ras_ctrl
- *     op: disable, enable, inject
- *             disable: only block is needed
- *             enable: block and error are needed
- *             inject: error, address, value are needed
- *     block: umc, smda, gfx, .........
- *             see ras_block_string[] for details
- *     error: ue, ce
- *             ue: multi_uncorrectable
- *             ce: single_correctable
- *     sub_block: sub block index, pass 0 if there is no sub block
+ * .. code-block:: bash
+ *
+ *     echo op block [error [sub_block address value]] > .../ras/ras_ctrl
+ *
+ * op: disable, enable, inject
+ *     disable: only block is needed
+ *     enable: block and error are needed
+ *     inject: error, address, value are needed
+ * block: umc, sdma, gfx, .........
+ *     see ras_block_string[] for details
+ * error: ue, ce
+ *     ue: multi_uncorrectable
+ *     ce: single_correctable
+ * sub_block:
+ *     sub block index, pass 0 if there is no sub block
+ *
+ * here are some examples for bash commands:
+ *
+ * .. code-block:: bash
  *
- * here are some examples for bash commands,
  *     echo inject umc ue 0x0 0x0 0x0 > /sys/kernel/debug/dri/0/ras/ras_ctrl
  *     echo inject umc ce 0 0 0 > /sys/kernel/debug/dri/0/ras/ras_ctrl
  *     echo disable umc > /sys/kernel/debug/dri/0/ras/ras_ctrl
@@ -245,8 +262,9 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file *f,
  * For inject, please check corresponding err count at
  * /sys/class/drm/card[0/1/2...]/device/ras/[gfx/sdma/...]_err_count
  *
- * NOTE: operation is only allowed on blocks which are supported.
- * Please check ras mask at /sys/module/amdgpu/parameters/ras_mask
+ * .. note::
+ *     Operation is only allowed on blocks which are supported.
+ *     Please check ras mask at /sys/module/amdgpu/parameters/ras_mask
  */
 static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user *buf,
                size_t size, loff_t *pos)
@@ -276,9 +294,20 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user *
                        break;
                }
 
+               /* umc ce/ue error injection for a bad page is not allowed */
+               if ((data.head.block == AMDGPU_RAS_BLOCK__UMC) &&
+                   amdgpu_ras_check_bad_page(adev, data.inject.address)) {
+                       DRM_WARN("RAS WARN: 0x%llx has been marked as bad before error injection!\n",
+                                       data.inject.address);
+                       break;
+               }
+
                /* data.inject.address is offset instead of absolute gpu address */
                ret = amdgpu_ras_error_inject(adev, &data.inject);
                break;
+       case 3:
+               amdgpu_ras_get_context(adev)->reboot = true;
+               break;
        default:
                ret = -EINVAL;
                break;
@@ -290,6 +319,33 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user *
        return size;
 }
 
+/**
+ * DOC: AMDGPU RAS debugfs EEPROM table reset interface
+ *
+ * Some boards contain an EEPROM which is used to persistently store a list of
+ * bad pages containing ECC errors detected in vram.  This interface provides
+ * a way to reset the EEPROM, e.g., after testing error injection.
+ *
+ * Usage:
+ *
+ * .. code-block:: bash
+ *
+ *     echo 1 > ../ras/ras_eeprom_reset
+ *
+ * will reset EEPROM table to 0 entries.
+ *
+ */
+static ssize_t amdgpu_ras_debugfs_eeprom_write(struct file *f, const char __user *buf,
+               size_t size, loff_t *pos)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
+       int ret;
+
+       ret = amdgpu_ras_eeprom_reset_table(&adev->psp.ras.ras->eeprom_control);
+
+       return ret == 1 ? size : -EIO;
+}
+
 static const struct file_operations amdgpu_ras_debugfs_ctrl_ops = {
        .owner = THIS_MODULE,
        .read = NULL,
@@ -297,6 +353,34 @@ static const struct file_operations amdgpu_ras_debugfs_ctrl_ops = {
        .llseek = default_llseek
 };
 
+static const struct file_operations amdgpu_ras_debugfs_eeprom_ops = {
+       .owner = THIS_MODULE,
+       .read = NULL,
+       .write = amdgpu_ras_debugfs_eeprom_write,
+       .llseek = default_llseek
+};
+
+/**
+ * DOC: AMDGPU RAS sysfs Error Count Interface
+ *
+ * It allows user to read the error count for each IP block on the gpu through
+ * /sys/class/drm/card[0/1/2...]/device/ras/[gfx/sdma/...]_err_count
+ *
+ * It outputs the multiple lines which report the uncorrected (ue) and corrected
+ * (ce) error counts.
+ *
+ * The format of one line is below,
+ *
+ * [ce|ue]: count
+ *
+ * Example:
+ *
+ * .. code-block:: bash
+ *
+ *     ue: 0
+ *     ce: 1
+ *
+ */
 static ssize_t amdgpu_ras_sysfs_read(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
@@ -615,8 +699,12 @@ int amdgpu_ras_error_query(struct amdgpu_device *adev,
                        adev->gfx.funcs->query_ras_error_count(adev, &err_data);
                break;
        case AMDGPU_RAS_BLOCK__MMHUB:
-               if (adev->mmhub_funcs->query_ras_error_count)
-                       adev->mmhub_funcs->query_ras_error_count(adev, &err_data);
+               if (adev->mmhub.funcs->query_ras_error_count)
+                       adev->mmhub.funcs->query_ras_error_count(adev, &err_data);
+               break;
+       case AMDGPU_RAS_BLOCK__PCIE_BIF:
+               if (adev->nbio.funcs->query_ras_error_count)
+                       adev->nbio.funcs->query_ras_error_count(adev, &err_data);
                break;
        default:
                break;
@@ -628,12 +716,14 @@ int amdgpu_ras_error_query(struct amdgpu_device *adev,
        info->ue_count = obj->err_data.ue_count;
        info->ce_count = obj->err_data.ce_count;
 
-       if (err_data.ce_count)
+       if (err_data.ce_count) {
                dev_info(adev->dev, "%ld correctable errors detected in %s block\n",
                         obj->err_data.ce_count, ras_block_str(info->head.block));
-       if (err_data.ue_count)
+       }
+       if (err_data.ue_count) {
                dev_info(adev->dev, "%ld uncorrectable errors detected in %s block\n",
                         obj->err_data.ue_count, ras_block_str(info->head.block));
+       }
 
        return 0;
 }
@@ -664,6 +754,8 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev,
                break;
        case AMDGPU_RAS_BLOCK__UMC:
        case AMDGPU_RAS_BLOCK__MMHUB:
+       case AMDGPU_RAS_BLOCK__XGMI_WAFL:
+       case AMDGPU_RAS_BLOCK__PCIE_BIF:
                ret = psp_ras_trigger_error(&adev->psp, &block_info);
                break;
        default:
@@ -733,8 +825,8 @@ static char *amdgpu_ras_badpage_flags_str(unsigned int flags)
        };
 }
 
-/*
- * DOC: ras sysfs gpu_vram_bad_pages interface
+/**
+ * DOC: AMDGPU RAS sysfs gpu_vram_bad_pages Interface
  *
  * It allows user to read the bad pages of vram on the gpu through
  * /sys/class/drm/card[0/1/2...]/device/ras/gpu_vram_bad_pages
@@ -746,14 +838,21 @@ static char *amdgpu_ras_badpage_flags_str(unsigned int flags)
  *
  * gpu pfn and gpu page size are printed in hex format.
  * flags can be one of below character,
+ *
  * R: reserved, this gpu page is reserved and not able to use.
+ *
  * P: pending for reserve, this gpu page is marked as bad, will be reserved
- *    in next window of page_reserve.
+ * in next window of page_reserve.
+ *
  * F: unable to reserve. this gpu page can't be reserved due to some reasons.
  *
- * examples:
- * 0x00000001 : 0x00001000 : R
- * 0x00000002 : 0x00001000 : P
+ * Examples:
+ *
+ * .. code-block:: bash
+ *
+ *     0x00000001 : 0x00001000 : R
+ *     0x00000002 : 0x00001000 : P
+ *
  */
 
 static ssize_t amdgpu_ras_sysfs_badpages_read(struct file *f,
@@ -934,8 +1033,10 @@ static void amdgpu_ras_debugfs_create_ctrl_node(struct amdgpu_device *adev)
        struct drm_minor *minor = adev->ddev->primary;
 
        con->dir = debugfs_create_dir("ras", minor->debugfs_root);
-       con->ent = debugfs_create_file("ras_ctrl", S_IWUGO | S_IRUGO, con->dir,
-                                      adev, &amdgpu_ras_debugfs_ctrl_ops);
+       debugfs_create_file("ras_ctrl", S_IWUGO | S_IRUGO, con->dir,
+                               adev, &amdgpu_ras_debugfs_ctrl_ops);
+       debugfs_create_file("ras_eeprom_reset", S_IWUGO | S_IRUGO, con->dir,
+                               adev, &amdgpu_ras_debugfs_eeprom_ops);
 }
 
 void amdgpu_ras_debugfs_create(struct amdgpu_device *adev,
@@ -980,10 +1081,8 @@ static void amdgpu_ras_debugfs_remove_all(struct amdgpu_device *adev)
                amdgpu_ras_debugfs_remove(adev, &obj->head);
        }
 
-       debugfs_remove(con->ent);
-       debugfs_remove(con->dir);
+       debugfs_remove_recursive(con->dir);
        con->dir = NULL;
-       con->ent = NULL;
 }
 /* debugfs end */
 
@@ -1188,14 +1287,14 @@ static int amdgpu_ras_badpages_read(struct amdgpu_device *adev,
 
        for (; i < data->count; i++) {
                (*bps)[i] = (struct ras_badpage){
-                       .bp = data->bps[i].bp,
+                       .bp = data->bps[i].retired_page,
                        .size = AMDGPU_GPU_PAGE_SIZE,
                        .flags = 0,
                };
 
                if (data->last_reserved <= i)
                        (*bps)[i].flags = 1;
-               else if (data->bps[i].bo == NULL)
+               else if (data->bps_bo[i] == NULL)
                        (*bps)[i].flags = 2;
        }
 
@@ -1214,105 +1313,46 @@ static void amdgpu_ras_do_recovery(struct work_struct *work)
        atomic_set(&ras->in_recovery, 0);
 }
 
-static int amdgpu_ras_release_vram(struct amdgpu_device *adev,
-               struct amdgpu_bo **bo_ptr)
-{
-       /* no need to free it actually. */
-       amdgpu_bo_free_kernel(bo_ptr, NULL, NULL);
-       return 0;
-}
-
-/* reserve vram with size@offset */
-static int amdgpu_ras_reserve_vram(struct amdgpu_device *adev,
-               uint64_t offset, uint64_t size,
-               struct amdgpu_bo **bo_ptr)
-{
-       struct ttm_operation_ctx ctx = { false, false };
-       struct amdgpu_bo_param bp;
-       int r = 0;
-       int i;
-       struct amdgpu_bo *bo;
-
-       if (bo_ptr)
-               *bo_ptr = NULL;
-       memset(&bp, 0, sizeof(bp));
-       bp.size = size;
-       bp.byte_align = PAGE_SIZE;
-       bp.domain = AMDGPU_GEM_DOMAIN_VRAM;
-       bp.flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
-               AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
-       bp.type = ttm_bo_type_kernel;
-       bp.resv = NULL;
-
-       r = amdgpu_bo_create(adev, &bp, &bo);
-       if (r)
-               return -EINVAL;
-
-       r = amdgpu_bo_reserve(bo, false);
-       if (r)
-               goto error_reserve;
-
-       offset = ALIGN(offset, PAGE_SIZE);
-       for (i = 0; i < bo->placement.num_placement; ++i) {
-               bo->placements[i].fpfn = offset >> PAGE_SHIFT;
-               bo->placements[i].lpfn = (offset + size) >> PAGE_SHIFT;
-       }
-
-       ttm_bo_mem_put(&bo->tbo, &bo->tbo.mem);
-       r = ttm_bo_mem_space(&bo->tbo, &bo->placement, &bo->tbo.mem, &ctx);
-       if (r)
-               goto error_pin;
-
-       r = amdgpu_bo_pin_restricted(bo,
-                       AMDGPU_GEM_DOMAIN_VRAM,
-                       offset,
-                       offset + size);
-       if (r)
-               goto error_pin;
-
-       if (bo_ptr)
-               *bo_ptr = bo;
-
-       amdgpu_bo_unreserve(bo);
-       return r;
-
-error_pin:
-       amdgpu_bo_unreserve(bo);
-error_reserve:
-       amdgpu_bo_unref(&bo);
-       return r;
-}
-
 /* alloc/realloc bps array */
 static int amdgpu_ras_realloc_eh_data_space(struct amdgpu_device *adev,
                struct ras_err_handler_data *data, int pages)
 {
        unsigned int old_space = data->count + data->space_left;
        unsigned int new_space = old_space + pages;
-       unsigned int align_space = ALIGN(new_space, 1024);
-       void *tmp = kmalloc(align_space * sizeof(*data->bps), GFP_KERNEL);
-
-       if (!tmp)
+       unsigned int align_space = ALIGN(new_space, 512);
+       void *bps = kmalloc(align_space * sizeof(*data->bps), GFP_KERNEL);
+       struct amdgpu_bo **bps_bo =
+                       kmalloc(align_space * sizeof(*data->bps_bo), GFP_KERNEL);
+
+       if (!bps || !bps_bo) {
+               kfree(bps);
+               kfree(bps_bo);
                return -ENOMEM;
+       }
 
        if (data->bps) {
-               memcpy(tmp, data->bps,
+               memcpy(bps, data->bps,
                                data->count * sizeof(*data->bps));
                kfree(data->bps);
        }
+       if (data->bps_bo) {
+               memcpy(bps_bo, data->bps_bo,
+                               data->count * sizeof(*data->bps_bo));
+               kfree(data->bps_bo);
+       }
 
-       data->bps = tmp;
+       data->bps = bps;
+       data->bps_bo = bps_bo;
        data->space_left += align_space - old_space;
        return 0;
 }
 
 /* it deal with vram only. */
 int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev,
-               unsigned long *bps, int pages)
+               struct eeprom_table_record *bps, int pages)
 {
        struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
        struct ras_err_handler_data *data;
-       int i = pages;
        int ret = 0;
 
        if (!con || !con->eh_data || !bps || pages <= 0)
@@ -1329,24 +1369,120 @@ int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev,
                        goto out;
                }
 
-       while (i--)
-               data->bps[data->count++].bp = bps[i];
-
+       memcpy(&data->bps[data->count], bps, pages * sizeof(*data->bps));
+       data->count += pages;
        data->space_left -= pages;
+
 out:
        mutex_unlock(&con->recovery_lock);
 
        return ret;
 }
 
+/*
+ * write error record array to eeprom, the function should be
+ * protected by recovery_lock
+ */
+static int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev)
+{
+       struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
+       struct ras_err_handler_data *data;
+       struct amdgpu_ras_eeprom_control *control;
+       int save_count;
+
+       if (!con || !con->eh_data)
+               return 0;
+
+       control = &con->eeprom_control;
+       data = con->eh_data;
+       save_count = data->count - control->num_recs;
+       /* only new entries are saved */
+       if (save_count > 0)
+               if (amdgpu_ras_eeprom_process_recods(control,
+                                                       &data->bps[control->num_recs],
+                                                       true,
+                                                       save_count)) {
+                       DRM_ERROR("Failed to save EEPROM table data!");
+                       return -EIO;
+               }
+
+       return 0;
+}
+
+/*
+ * read error record array in eeprom and reserve enough space for
+ * storing new bad pages
+ */
+static int amdgpu_ras_load_bad_pages(struct amdgpu_device *adev)
+{
+       struct amdgpu_ras_eeprom_control *control =
+                                       &adev->psp.ras.ras->eeprom_control;
+       struct eeprom_table_record *bps = NULL;
+       int ret = 0;
+
+       /* no bad page record, skip eeprom access */
+       if (!control->num_recs)
+               return ret;
+
+       bps = kcalloc(control->num_recs, sizeof(*bps), GFP_KERNEL);
+       if (!bps)
+               return -ENOMEM;
+
+       if (amdgpu_ras_eeprom_process_recods(control, bps, false,
+               control->num_recs)) {
+               DRM_ERROR("Failed to load EEPROM table records!");
+               ret = -EIO;
+               goto out;
+       }
+
+       ret = amdgpu_ras_add_bad_pages(adev, bps, control->num_recs);
+
+out:
+       kfree(bps);
+       return ret;
+}
+
+/*
+ * check if an address belongs to bad page
+ *
+ * Note: this check is only for umc block
+ */
+static bool amdgpu_ras_check_bad_page(struct amdgpu_device *adev,
+                               uint64_t addr)
+{
+       struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
+       struct ras_err_handler_data *data;
+       int i;
+       bool ret = false;
+
+       if (!con || !con->eh_data)
+               return ret;
+
+       mutex_lock(&con->recovery_lock);
+       data = con->eh_data;
+       if (!data)
+               goto out;
+
+       addr >>= AMDGPU_GPU_PAGE_SHIFT;
+       for (i = 0; i < data->count; i++)
+               if (addr == data->bps[i].retired_page) {
+                       ret = true;
+                       goto out;
+               }
+
+out:
+       mutex_unlock(&con->recovery_lock);
+       return ret;
+}
+
 /* called in gpu recovery/init */
 int amdgpu_ras_reserve_bad_pages(struct amdgpu_device *adev)
 {
        struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
        struct ras_err_handler_data *data;
        uint64_t bp;
-       struct amdgpu_bo *bo;
-       int i;
+       struct amdgpu_bo *bo = NULL;
+       int i, ret = 0;
 
        if (!con || !con->eh_data)
                return 0;
@@ -1357,18 +1493,29 @@ int amdgpu_ras_reserve_bad_pages(struct amdgpu_device *adev)
                goto out;
        /* reserve vram at driver post stage. */
        for (i = data->last_reserved; i < data->count; i++) {
-               bp = data->bps[i].bp;
+               bp = data->bps[i].retired_page;
 
-               if (amdgpu_ras_reserve_vram(adev, bp << PAGE_SHIFT,
-                                       PAGE_SIZE, &bo))
-                       DRM_ERROR("RAS ERROR: reserve vram %llx fail\n", bp);
+               /* There are two cases of reserve error should be ignored:
+                * 1) a ras bad page has been allocated (used by someone);
+                * 2) a ras bad page has been reserved (duplicate error injection
+                *    for one page);
+                */
+               if (amdgpu_bo_create_kernel_at(adev, bp << AMDGPU_GPU_PAGE_SHIFT,
+                                              AMDGPU_GPU_PAGE_SIZE,
+                                              AMDGPU_GEM_DOMAIN_VRAM,
+                                              &bo, NULL))
+                       DRM_WARN("RAS WARN: reserve vram for retired page %llx fail\n", bp);
 
-               data->bps[i].bo = bo;
+               data->bps_bo[i] = bo;
                data->last_reserved = i + 1;
+               bo = NULL;
        }
+
+       /* continue to save bad pages to eeprom even reesrve_vram fails */
+       ret = amdgpu_ras_save_bad_pages(adev);
 out:
        mutex_unlock(&con->recovery_lock);
-       return 0;
+       return ret;
 }
 
 /* called when driver unload */
@@ -1388,11 +1535,11 @@ static int amdgpu_ras_release_bad_pages(struct amdgpu_device *adev)
                goto out;
 
        for (i = data->last_reserved - 1; i >= 0; i--) {
-               bo = data->bps[i].bo;
+               bo = data->bps_bo[i];
 
-               amdgpu_ras_release_vram(adev, &bo);
+               amdgpu_bo_free_kernel(&bo, NULL, NULL);
 
-               data->bps[i].bo = bo;
+               data->bps_bo[i] = bo;
                data->last_reserved = i;
        }
 out:
@@ -1400,41 +1547,54 @@ static int amdgpu_ras_release_bad_pages(struct amdgpu_device *adev)
        return 0;
 }
 
-static int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev)
-{
-       /* TODO
-        * write the array to eeprom when SMU disabled.
-        */
-       return 0;
-}
-
-static int amdgpu_ras_load_bad_pages(struct amdgpu_device *adev)
-{
-       /* TODO
-        * read the array to eeprom when SMU disabled.
-        */
-       return 0;
-}
-
-static int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
+int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
 {
        struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
-       struct ras_err_handler_data **data = &con->eh_data;
+       struct ras_err_handler_data **data;
+       int ret;
 
-       *data = kmalloc(sizeof(**data),
-                       GFP_KERNEL|__GFP_ZERO);
-       if (!*data)
-               return -ENOMEM;
+       if (con)
+               data = &con->eh_data;
+       else
+               return 0;
+
+       *data = kmalloc(sizeof(**data), GFP_KERNEL | __GFP_ZERO);
+       if (!*data) {
+               ret = -ENOMEM;
+               goto out;
+       }
 
        mutex_init(&con->recovery_lock);
        INIT_WORK(&con->recovery_work, amdgpu_ras_do_recovery);
        atomic_set(&con->in_recovery, 0);
        con->adev = adev;
 
-       amdgpu_ras_load_bad_pages(adev);
-       amdgpu_ras_reserve_bad_pages(adev);
+       ret = amdgpu_ras_eeprom_init(&con->eeprom_control);
+       if (ret)
+               goto free;
+
+       if (con->eeprom_control.num_recs) {
+               ret = amdgpu_ras_load_bad_pages(adev);
+               if (ret)
+                       goto free;
+               ret = amdgpu_ras_reserve_bad_pages(adev);
+               if (ret)
+                       goto release;
+       }
 
        return 0;
+
+release:
+       amdgpu_ras_release_bad_pages(adev);
+free:
+       kfree((*data)->bps);
+       kfree((*data)->bps_bo);
+       kfree(*data);
+       con->eh_data = NULL;
+out:
+       DRM_WARN("Failed to initialize ras recovery!\n");
+
+       return ret;
 }
 
 static int amdgpu_ras_recovery_fini(struct amdgpu_device *adev)
@@ -1442,13 +1602,17 @@ static int amdgpu_ras_recovery_fini(struct amdgpu_device *adev)
        struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
        struct ras_err_handler_data *data = con->eh_data;
 
+       /* recovery_init failed to init it, fini is useless */
+       if (!data)
+               return 0;
+
        cancel_work_sync(&con->recovery_work);
-       amdgpu_ras_save_bad_pages(adev);
        amdgpu_ras_release_bad_pages(adev);
 
        mutex_lock(&con->recovery_lock);
        con->eh_data = NULL;
        kfree(data->bps);
+       kfree(data->bps_bo);
        kfree(data);
        mutex_unlock(&con->recovery_lock);
 
@@ -1500,6 +1664,7 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev,
 int amdgpu_ras_init(struct amdgpu_device *adev)
 {
        struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
+       int r;
 
        if (con)
                return 0;
@@ -1527,31 +1692,106 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
        /* Might need get this flag from vbios. */
        con->flags = RAS_DEFAULT_FLAGS;
 
-       if (amdgpu_ras_recovery_init(adev))
-               goto recovery_out;
+       if (adev->nbio.funcs->init_ras_controller_interrupt) {
+               r = adev->nbio.funcs->init_ras_controller_interrupt(adev);
+               if (r)
+                       return r;
+       }
+
+       if (adev->nbio.funcs->init_ras_err_event_athub_interrupt) {
+               r = adev->nbio.funcs->init_ras_err_event_athub_interrupt(adev);
+               if (r)
+                       return r;
+       }
 
        amdgpu_ras_mask &= AMDGPU_RAS_BLOCK_MASK;
 
        if (amdgpu_ras_fs_init(adev))
                goto fs_out;
 
-       /* ras init for each ras block */
-       if (adev->umc.funcs->ras_init)
-               adev->umc.funcs->ras_init(adev);
-
        DRM_INFO("RAS INFO: ras initialized successfully, "
                        "hardware ability[%x] ras_mask[%x]\n",
                        con->hw_supported, con->supported);
        return 0;
 fs_out:
-       amdgpu_ras_recovery_fini(adev);
-recovery_out:
        amdgpu_ras_set_context(adev, NULL);
        kfree(con);
 
        return -EINVAL;
 }
 
+/* helper function to handle common stuff in ip late init phase */
+int amdgpu_ras_late_init(struct amdgpu_device *adev,
+                        struct ras_common_if *ras_block,
+                        struct ras_fs_if *fs_info,
+                        struct ras_ih_if *ih_info)
+{
+       int r;
+
+       /* disable RAS feature per IP block if it is not supported */
+       if (!amdgpu_ras_is_supported(adev, ras_block->block)) {
+               amdgpu_ras_feature_enable_on_boot(adev, ras_block, 0);
+               return 0;
+       }
+
+       r = amdgpu_ras_feature_enable_on_boot(adev, ras_block, 1);
+       if (r) {
+               if (r == -EAGAIN) {
+                       /* request gpu reset. will run again */
+                       amdgpu_ras_request_reset_on_boot(adev,
+                                       ras_block->block);
+                       return 0;
+               } else if (adev->in_suspend || adev->in_gpu_reset) {
+                       /* in resume phase, if fail to enable ras,
+                        * clean up all ras fs nodes, and disable ras */
+                       goto cleanup;
+               } else
+                       return r;
+       }
+
+       /* in resume phase, no need to create ras fs node */
+       if (adev->in_suspend || adev->in_gpu_reset)
+               return 0;
+
+       if (ih_info->cb) {
+               r = amdgpu_ras_interrupt_add_handler(adev, ih_info);
+               if (r)
+                       goto interrupt;
+       }
+
+       amdgpu_ras_debugfs_create(adev, fs_info);
+
+       r = amdgpu_ras_sysfs_create(adev, fs_info);
+       if (r)
+               goto sysfs;
+
+       return 0;
+cleanup:
+       amdgpu_ras_sysfs_remove(adev, ras_block);
+sysfs:
+       amdgpu_ras_debugfs_remove(adev, ras_block);
+       if (ih_info->cb)
+               amdgpu_ras_interrupt_remove_handler(adev, ih_info);
+interrupt:
+       amdgpu_ras_feature_enable(adev, ras_block, 0);
+       return r;
+}
+
+/* helper function to remove ras fs node and interrupt handler */
+void amdgpu_ras_late_fini(struct amdgpu_device *adev,
+                         struct ras_common_if *ras_block,
+                         struct ras_ih_if *ih_info)
+{
+       if (!ras_block || !ih_info)
+               return;
+
+       amdgpu_ras_sysfs_remove(adev, ras_block);
+       amdgpu_ras_debugfs_remove(adev, ras_block);
+       if (ih_info->cb)
+                amdgpu_ras_interrupt_remove_handler(adev, ih_info);
+       amdgpu_ras_feature_enable(adev, ras_block, 0);
+}
+
 /* do some init work after IP late init as dependence.
  * and it runs in resume/gpu reset/booting up cases.
  */
@@ -1645,3 +1885,18 @@ int amdgpu_ras_fini(struct amdgpu_device *adev)
 
        return 0;
 }
+
+void amdgpu_ras_global_ras_isr(struct amdgpu_device *adev)
+{
+       uint32_t hw_supported, supported;
+
+       amdgpu_ras_check_supported(adev, &hw_supported, &supported);
+       if (!hw_supported)
+               return;
+
+       if (atomic_cmpxchg(&amdgpu_ras_in_intr, 0, 1) == 0) {
+               DRM_WARN("RAS event of type ERREVENT_ATHUB_INTERRUPT detected!\n");
+
+               amdgpu_ras_reset_gpu(adev, false);
+       }
+}
index 6c76bb2a684325925ca7952d0d0a41c3372096e4..f80fd3428c98ea449e8b907a8eec40366dd66fbd 100644 (file)
@@ -317,8 +317,6 @@ struct amdgpu_ras {
        struct list_head head;
        /* debugfs */
        struct dentry *dir;
-       /* debugfs ctrl */
-       struct dentry *ent;
        /* sysfs */
        struct device_attribute features_attr;
        struct bin_attribute badpages_attr;
@@ -334,7 +332,7 @@ struct amdgpu_ras {
        struct mutex recovery_lock;
 
        uint32_t flags;
-
+       bool reboot;
        struct amdgpu_ras_eeprom_control eeprom_control;
 };
 
@@ -347,15 +345,14 @@ struct ras_err_data {
        unsigned long ue_count;
        unsigned long ce_count;
        unsigned long err_addr_cnt;
-       uint64_t *err_addr;
+       struct eeprom_table_record *err_addr;
 };
 
 struct ras_err_handler_data {
-       /* point to bad pages array */
-       struct {
-               unsigned long bp;
-               struct amdgpu_bo *bo;
-       } *bps;
+       /* point to bad page records array */
+       struct eeprom_table_record *bps;
+       /* point to reserved bo array */
+       struct amdgpu_bo **bps_bo;
        /* the count of entries */
        int count;
        /* the space can place new entries */
@@ -365,7 +362,7 @@ struct ras_err_handler_data {
 };
 
 typedef int (*ras_ih_cb)(struct amdgpu_device *adev,
-               struct ras_err_data *err_data,
+               void *err_data,
                struct amdgpu_iv_entry *entry);
 
 struct ras_ih_data {
@@ -481,6 +478,7 @@ static inline int amdgpu_ras_is_supported(struct amdgpu_device *adev,
        return ras && (ras->supported & (1 << block));
 }
 
+int amdgpu_ras_recovery_init(struct amdgpu_device *adev);
 int amdgpu_ras_request_reset_on_boot(struct amdgpu_device *adev,
                unsigned int block);
 
@@ -492,7 +490,7 @@ unsigned long amdgpu_ras_query_error_count(struct amdgpu_device *adev,
 
 /* error handling functions */
 int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev,
-               unsigned long *bps, int pages);
+               struct eeprom_table_record *bps, int pages);
 
 int amdgpu_ras_reserve_bad_pages(struct amdgpu_device *adev);
 
@@ -501,6 +499,12 @@ static inline int amdgpu_ras_reset_gpu(struct amdgpu_device *adev,
 {
        struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
 
+       /* save bad page to eeprom before gpu reset,
+        * i2c may be unstable in gpu reset
+        */
+       if (in_task())
+               amdgpu_ras_reserve_bad_pages(adev);
+
        if (atomic_cmpxchg(&ras->in_recovery, 0, 1) == 0)
                schedule_work(&ras->recovery_work);
        return 0;
@@ -566,6 +570,13 @@ amdgpu_ras_error_to_ta(enum amdgpu_ras_error_type error) {
 int amdgpu_ras_init(struct amdgpu_device *adev);
 int amdgpu_ras_fini(struct amdgpu_device *adev);
 int amdgpu_ras_pre_fini(struct amdgpu_device *adev);
+int amdgpu_ras_late_init(struct amdgpu_device *adev,
+                        struct ras_common_if *ras_block,
+                        struct ras_fs_if *fs_info,
+                        struct ras_ih_if *ih_info);
+void amdgpu_ras_late_fini(struct amdgpu_device *adev,
+                         struct ras_common_if *ras_block,
+                         struct ras_ih_if *ih_info);
 
 int amdgpu_ras_feature_enable(struct amdgpu_device *adev,
                struct ras_common_if *head, bool enable);
@@ -599,4 +610,14 @@ int amdgpu_ras_interrupt_remove_handler(struct amdgpu_device *adev,
 
 int amdgpu_ras_interrupt_dispatch(struct amdgpu_device *adev,
                struct ras_dispatch_if *info);
+
+extern atomic_t amdgpu_ras_in_intr;
+
+static inline bool amdgpu_ras_intr_triggered(void)
+{
+       return !!atomic_read(&amdgpu_ras_in_intr);
+}
+
+void amdgpu_ras_global_ras_isr(struct amdgpu_device *adev);
+
 #endif
index 8a32b5c93778b6811e392761dd6cea779abfe6a5..20af0a17d00b3075abd25d38045034c0cbc84ee8 100644 (file)
@@ -100,7 +100,101 @@ static int __update_table_header(struct amdgpu_ras_eeprom_control *control,
        return ret;
 }
 
-static uint32_t  __calc_hdr_byte_sum(struct amdgpu_ras_eeprom_control *control);
+
+
+static uint32_t  __calc_hdr_byte_sum(struct amdgpu_ras_eeprom_control *control)
+{
+       int i;
+       uint32_t tbl_sum = 0;
+
+       /* Header checksum, skip checksum field in the calculation */
+       for (i = 0; i < sizeof(control->tbl_hdr) - sizeof(control->tbl_hdr.checksum); i++)
+               tbl_sum += *(((unsigned char *)&control->tbl_hdr) + i);
+
+       return tbl_sum;
+}
+
+static uint32_t  __calc_recs_byte_sum(struct eeprom_table_record *records,
+                                     int num)
+{
+       int i, j;
+       uint32_t tbl_sum = 0;
+
+       /* Records checksum */
+       for (i = 0; i < num; i++) {
+               struct eeprom_table_record *record = &records[i];
+
+               for (j = 0; j < sizeof(*record); j++) {
+                       tbl_sum += *(((unsigned char *)record) + j);
+               }
+       }
+
+       return tbl_sum;
+}
+
+static inline uint32_t  __calc_tbl_byte_sum(struct amdgpu_ras_eeprom_control *control,
+                                 struct eeprom_table_record *records, int num)
+{
+       return __calc_hdr_byte_sum(control) + __calc_recs_byte_sum(records, num);
+}
+
+/* Checksum = 256 -((sum of all table entries) mod 256) */
+static void __update_tbl_checksum(struct amdgpu_ras_eeprom_control *control,
+                                 struct eeprom_table_record *records, int num,
+                                 uint32_t old_hdr_byte_sum)
+{
+       /*
+        * This will update the table sum with new records.
+        *
+        * TODO: What happens when the EEPROM table is to be wrapped around
+        * and old records from start will get overridden.
+        */
+
+       /* need to recalculate updated header byte sum */
+       control->tbl_byte_sum -= old_hdr_byte_sum;
+       control->tbl_byte_sum += __calc_tbl_byte_sum(control, records, num);
+
+       control->tbl_hdr.checksum = 256 - (control->tbl_byte_sum % 256);
+}
+
+/* table sum mod 256 + checksum must equals 256 */
+static bool __validate_tbl_checksum(struct amdgpu_ras_eeprom_control *control,
+                           struct eeprom_table_record *records, int num)
+{
+       control->tbl_byte_sum = __calc_tbl_byte_sum(control, records, num);
+
+       if (control->tbl_hdr.checksum + (control->tbl_byte_sum % 256) != 256) {
+               DRM_WARN("Checksum mismatch, checksum: %u ", control->tbl_hdr.checksum);
+               return false;
+       }
+
+       return true;
+}
+
+int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control)
+{
+       unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE] = { 0 };
+       struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
+       int ret = 0;
+
+       mutex_lock(&control->tbl_mutex);
+
+       hdr->header = EEPROM_TABLE_HDR_VAL;
+       hdr->version = EEPROM_TABLE_VER;
+       hdr->first_rec_offset = EEPROM_RECORD_START;
+       hdr->tbl_size = EEPROM_TABLE_HEADER_SIZE;
+
+       control->tbl_byte_sum = 0;
+       __update_tbl_checksum(control, NULL, 0, 0);
+       control->next_addr = EEPROM_RECORD_START;
+
+       ret = __update_table_header(control, buff);
+
+       mutex_unlock(&control->tbl_mutex);
+
+       return ret;
+
+}
 
 int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
 {
@@ -143,25 +237,18 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
        if (hdr->header == EEPROM_TABLE_HDR_VAL) {
                control->num_recs = (hdr->tbl_size - EEPROM_TABLE_HEADER_SIZE) /
                                    EEPROM_TABLE_RECORD_SIZE;
+               control->tbl_byte_sum = __calc_hdr_byte_sum(control);
+               control->next_addr = EEPROM_RECORD_START;
+
                DRM_DEBUG_DRIVER("Found existing EEPROM table with %d records",
                                 control->num_recs);
 
        } else {
                DRM_INFO("Creating new EEPROM table");
 
-               hdr->header = EEPROM_TABLE_HDR_VAL;
-               hdr->version = EEPROM_TABLE_VER;
-               hdr->first_rec_offset = EEPROM_RECORD_START;
-               hdr->tbl_size = EEPROM_TABLE_HEADER_SIZE;
-
-               adev->psp.ras.ras->eeprom_control.tbl_byte_sum =
-                               __calc_hdr_byte_sum(&adev->psp.ras.ras->eeprom_control);
-               ret = __update_table_header(control, buff);
+               ret = amdgpu_ras_eeprom_reset_table(control);
        }
 
-       /* Start inserting records from here */
-       adev->psp.ras.ras->eeprom_control.next_addr = EEPROM_RECORD_START;
-
        return ret == 1 ? 0 : -EIO;
 }
 
@@ -226,8 +313,8 @@ static void __decode_table_record_from_buff(struct amdgpu_ras_eeprom_control *co
        record->offset = (le64_to_cpu(tmp) & 0xffffffffffff);
        i += 6;
 
-       buff[i++] = record->mem_channel;
-       buff[i++] = record->mcumc_id;
+       record->mem_channel = buff[i++];
+       record->mcumc_id = buff[i++];
 
        memcpy(&tmp, buff + i,  6);
        record->retired_page = (le64_to_cpu(tmp) & 0xffffffffffff);
@@ -266,84 +353,15 @@ static uint32_t __correct_eeprom_dest_address(uint32_t curr_address)
        return curr_address;
 }
 
-
-static uint32_t  __calc_hdr_byte_sum(struct amdgpu_ras_eeprom_control *control)
-{
-       int i;
-       uint32_t tbl_sum = 0;
-
-       /* Header checksum, skip checksum field in the calculation */
-       for (i = 0; i < sizeof(control->tbl_hdr) - sizeof(control->tbl_hdr.checksum); i++)
-               tbl_sum += *(((unsigned char *)&control->tbl_hdr) + i);
-
-       return tbl_sum;
-}
-
-static uint32_t  __calc_recs_byte_sum(struct eeprom_table_record *records,
-                                     int num)
-{
-       int i, j;
-       uint32_t tbl_sum = 0;
-
-       /* Records checksum */
-       for (i = 0; i < num; i++) {
-               struct eeprom_table_record *record = &records[i];
-
-               for (j = 0; j < sizeof(*record); j++) {
-                       tbl_sum += *(((unsigned char *)record) + j);
-               }
-       }
-
-       return tbl_sum;
-}
-
-static inline uint32_t  __calc_tbl_byte_sum(struct amdgpu_ras_eeprom_control *control,
-                                 struct eeprom_table_record *records, int num)
-{
-       return __calc_hdr_byte_sum(control) + __calc_recs_byte_sum(records, num);
-}
-
-/* Checksum = 256 -((sum of all table entries) mod 256) */
-static void __update_tbl_checksum(struct amdgpu_ras_eeprom_control *control,
-                                 struct eeprom_table_record *records, int num,
-                                 uint32_t old_hdr_byte_sum)
-{
-       /*
-        * This will update the table sum with new records.
-        *
-        * TODO: What happens when the EEPROM table is to be wrapped around
-        * and old records from start will get overridden.
-        */
-
-       /* need to recalculate updated header byte sum */
-       control->tbl_byte_sum -= old_hdr_byte_sum;
-       control->tbl_byte_sum += __calc_tbl_byte_sum(control, records, num);
-
-       control->tbl_hdr.checksum = 256 - (control->tbl_byte_sum % 256);
-}
-
-/* table sum mod 256 + checksum must equals 256 */
-static bool __validate_tbl_checksum(struct amdgpu_ras_eeprom_control *control,
-                           struct eeprom_table_record *records, int num)
-{
-       control->tbl_byte_sum = __calc_tbl_byte_sum(control, records, num);
-
-       if (control->tbl_hdr.checksum + (control->tbl_byte_sum % 256) != 256) {
-               DRM_WARN("Checksum mismatch, checksum: %u ", control->tbl_hdr.checksum);
-               return false;
-       }
-
-       return true;
-}
-
 int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
                                            struct eeprom_table_record *records,
                                            bool write,
                                            int num)
 {
        int i, ret = 0;
-       struct i2c_msg *msgs;
-       unsigned char *buffs;
+       struct i2c_msg *msgs, *msg;
+       unsigned char *buffs, *buff;
+       struct eeprom_table_record *record;
        struct amdgpu_device *adev = to_amdgpu_device(control);
 
        if (adev->asic_type != CHIP_VEGA20)
@@ -373,9 +391,9 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
         * 256b
         */
        for (i = 0; i < num; i++) {
-               unsigned char *buff = &buffs[i * (EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE)];
-               struct eeprom_table_record *record = &records[i];
-               struct i2c_msg *msg = &msgs[i];
+               buff = &buffs[i * (EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE)];
+               record = &records[i];
+               msg = &msgs[i];
 
                control->next_addr = __correct_eeprom_dest_address(control->next_addr);
 
@@ -415,8 +433,8 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
 
        if (!write) {
                for (i = 0; i < num; i++) {
-                       unsigned char *buff = &buffs[i*(EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE)];
-                       struct eeprom_table_record *record = &records[i];
+                       buff = &buffs[i*(EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE)];
+                       record = &records[i];
 
                        __decode_table_record_from_buff(control, record, buff + EEPROM_ADDRESS_SIZE);
                }
index 41f3fcb9a29bfce68ad9a457c7560d45246f888a..622269957c1b992ed9d38106aa02bcae081e722a 100644 (file)
@@ -79,6 +79,7 @@ struct eeprom_table_record {
 
 int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control);
 void amdgpu_ras_eeprom_fini(struct amdgpu_ras_eeprom_control *control);
+int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control);
 
 int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
                                            struct eeprom_table_record *records,
index 5c13c503e61f7ca72ad385dba21aa8e3a5625fd9..6010999d90208321378e660c35ce5ab6b9c7af13 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "amdgpu.h"
 #include "amdgpu_sdma.h"
+#include "amdgpu_ras.h"
 
 #define AMDGPU_CSA_SDMA_SIZE 64
 /* SDMA CSA reside in the 3rd page of CSA */
@@ -83,3 +84,101 @@ uint64_t amdgpu_sdma_get_csa_mc_addr(struct amdgpu_ring *ring,
 
        return csa_mc_addr;
 }
+
+int amdgpu_sdma_ras_late_init(struct amdgpu_device *adev,
+                             void *ras_ih_info)
+{
+       int r, i;
+       struct ras_ih_if *ih_info = (struct ras_ih_if *)ras_ih_info;
+       struct ras_fs_if fs_info = {
+               .sysfs_name = "sdma_err_count",
+               .debugfs_name = "sdma_err_inject",
+       };
+
+       if (!ih_info)
+               return -EINVAL;
+
+       if (!adev->sdma.ras_if) {
+               adev->sdma.ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL);
+               if (!adev->sdma.ras_if)
+                       return -ENOMEM;
+               adev->sdma.ras_if->block = AMDGPU_RAS_BLOCK__SDMA;
+               adev->sdma.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
+               adev->sdma.ras_if->sub_block_index = 0;
+               strcpy(adev->sdma.ras_if->name, "sdma");
+       }
+       fs_info.head = ih_info->head = *adev->sdma.ras_if;
+
+       r = amdgpu_ras_late_init(adev, adev->sdma.ras_if,
+                                &fs_info, ih_info);
+       if (r)
+               goto free;
+
+       if (amdgpu_ras_is_supported(adev, adev->sdma.ras_if->block)) {
+               for (i = 0; i < adev->sdma.num_instances; i++) {
+                       r = amdgpu_irq_get(adev, &adev->sdma.ecc_irq,
+                               AMDGPU_SDMA_IRQ_INSTANCE0 + i);
+                       if (r)
+                               goto late_fini;
+               }
+       } else {
+               r = 0;
+               goto free;
+       }
+
+        return 0;
+
+late_fini:
+       amdgpu_ras_late_fini(adev, adev->sdma.ras_if, ih_info);
+free:
+       kfree(adev->sdma.ras_if);
+       adev->sdma.ras_if = NULL;
+       return r;
+}
+
+void amdgpu_sdma_ras_fini(struct amdgpu_device *adev)
+{
+       if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__SDMA) &&
+                       adev->sdma.ras_if) {
+               struct ras_common_if *ras_if = adev->sdma.ras_if;
+               struct ras_ih_if ih_info = {
+                       .head = *ras_if,
+                       /* the cb member will not be used by
+                        * amdgpu_ras_interrupt_remove_handler, init it only
+                        * to cheat the check in ras_late_fini
+                        */
+                       .cb = amdgpu_sdma_process_ras_data_cb,
+               };
+
+               amdgpu_ras_late_fini(adev, ras_if, &ih_info);
+               kfree(ras_if);
+       }
+}
+
+int amdgpu_sdma_process_ras_data_cb(struct amdgpu_device *adev,
+               void *err_data,
+               struct amdgpu_iv_entry *entry)
+{
+       kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
+       amdgpu_ras_reset_gpu(adev, 0);
+
+       return AMDGPU_RAS_SUCCESS;
+}
+
+int amdgpu_sdma_process_ecc_irq(struct amdgpu_device *adev,
+                                     struct amdgpu_irq_src *source,
+                                     struct amdgpu_iv_entry *entry)
+{
+       struct ras_common_if *ras_if = adev->sdma.ras_if;
+       struct ras_dispatch_if ih_data = {
+               .entry = entry,
+       };
+
+       if (!ras_if)
+               return 0;
+
+       ih_data.head = *ras_if;
+
+       amdgpu_ras_interrupt_dispatch(adev, &ih_data);
+       return 0;
+}
index a9ae0d8a05894c54327b417728bc446af09937ee..761ff8be63147559621219d13a4d25ba30a70024 100644 (file)
@@ -104,4 +104,13 @@ struct amdgpu_sdma_instance *
 amdgpu_sdma_get_instance_from_ring(struct amdgpu_ring *ring);
 int amdgpu_sdma_get_index_from_ring(struct amdgpu_ring *ring, uint32_t *index);
 uint64_t amdgpu_sdma_get_csa_mc_addr(struct amdgpu_ring *ring, unsigned vmid);
+int amdgpu_sdma_ras_late_init(struct amdgpu_device *adev,
+                             void *ras_ih_info);
+void amdgpu_sdma_ras_fini(struct amdgpu_device *adev);
+int amdgpu_sdma_process_ras_data_cb(struct amdgpu_device *adev,
+               void *err_data,
+               struct amdgpu_iv_entry *entry);
+int amdgpu_sdma_process_ecc_irq(struct amdgpu_device *adev,
+                                     struct amdgpu_irq_src *source,
+                                     struct amdgpu_iv_entry *entry);
 #endif
index 77674a7b96163ebb9f84bae7ca87b59f9c6ca8ad..f940526c58896c4f4109038488aff0a58c6f91f0 100644 (file)
@@ -170,7 +170,7 @@ TRACE_EVENT(amdgpu_cs_ioctl,
                             __field(unsigned int, context)
                             __field(unsigned int, seqno)
                             __field(struct dma_fence *, fence)
-                            __field(char *, ring_name)
+                            __string(ring, to_amdgpu_ring(job->base.sched)->name)
                             __field(u32, num_ibs)
                             ),
 
@@ -179,12 +179,12 @@ TRACE_EVENT(amdgpu_cs_ioctl,
                           __assign_str(timeline, AMDGPU_JOB_GET_TIMELINE_NAME(job))
                           __entry->context = job->base.s_fence->finished.context;
                           __entry->seqno = job->base.s_fence->finished.seqno;
-                          __entry->ring_name = to_amdgpu_ring(job->base.sched)->name;
+                          __assign_str(ring, to_amdgpu_ring(job->base.sched)->name)
                           __entry->num_ibs = job->num_ibs;
                           ),
            TP_printk("sched_job=%llu, timeline=%s, context=%u, seqno=%u, ring_name=%s, num_ibs=%u",
                      __entry->sched_job_id, __get_str(timeline), __entry->context,
-                     __entry->seqno, __entry->ring_name, __entry->num_ibs)
+                     __entry->seqno, __get_str(ring), __entry->num_ibs)
 );
 
 TRACE_EVENT(amdgpu_sched_run_job,
@@ -195,7 +195,7 @@ TRACE_EVENT(amdgpu_sched_run_job,
                             __string(timeline, AMDGPU_JOB_GET_TIMELINE_NAME(job))
                             __field(unsigned int, context)
                             __field(unsigned int, seqno)
-                            __field(char *, ring_name)
+                            __string(ring, to_amdgpu_ring(job->base.sched)->name)
                             __field(u32, num_ibs)
                             ),
 
@@ -204,12 +204,12 @@ TRACE_EVENT(amdgpu_sched_run_job,
                           __assign_str(timeline, AMDGPU_JOB_GET_TIMELINE_NAME(job))
                           __entry->context = job->base.s_fence->finished.context;
                           __entry->seqno = job->base.s_fence->finished.seqno;
-                          __entry->ring_name = to_amdgpu_ring(job->base.sched)->name;
+                          __assign_str(ring, to_amdgpu_ring(job->base.sched)->name)
                           __entry->num_ibs = job->num_ibs;
                           ),
            TP_printk("sched_job=%llu, timeline=%s, context=%u, seqno=%u, ring_name=%s, num_ibs=%u",
                      __entry->sched_job_id, __get_str(timeline), __entry->context,
-                     __entry->seqno, __entry->ring_name, __entry->num_ibs)
+                     __entry->seqno, __get_str(ring), __entry->num_ibs)
 );
 
 
@@ -323,14 +323,15 @@ DEFINE_EVENT(amdgpu_vm_mapping, amdgpu_vm_bo_cs,
 
 TRACE_EVENT(amdgpu_vm_set_ptes,
            TP_PROTO(uint64_t pe, uint64_t addr, unsigned count,
-                    uint32_t incr, uint64_t flags),
-           TP_ARGS(pe, addr, count, incr, flags),
+                    uint32_t incr, uint64_t flags, bool direct),
+           TP_ARGS(pe, addr, count, incr, flags, direct),
            TP_STRUCT__entry(
                             __field(u64, pe)
                             __field(u64, addr)
                             __field(u32, count)
                             __field(u32, incr)
                             __field(u64, flags)
+                            __field(bool, direct)
                             ),
 
            TP_fast_assign(
@@ -339,28 +340,32 @@ TRACE_EVENT(amdgpu_vm_set_ptes,
                           __entry->count = count;
                           __entry->incr = incr;
                           __entry->flags = flags;
+                          __entry->direct = direct;
                           ),
-           TP_printk("pe=%010Lx, addr=%010Lx, incr=%u, flags=%llx, count=%u",
-                     __entry->pe, __entry->addr, __entry->incr,
-                     __entry->flags, __entry->count)
+           TP_printk("pe=%010Lx, addr=%010Lx, incr=%u, flags=%llx, count=%u, "
+                     "direct=%d", __entry->pe, __entry->addr, __entry->incr,
+                     __entry->flags, __entry->count, __entry->direct)
 );
 
 TRACE_EVENT(amdgpu_vm_copy_ptes,
-           TP_PROTO(uint64_t pe, uint64_t src, unsigned count),
-           TP_ARGS(pe, src, count),
+           TP_PROTO(uint64_t pe, uint64_t src, unsigned count, bool direct),
+           TP_ARGS(pe, src, count, direct),
            TP_STRUCT__entry(
                             __field(u64, pe)
                             __field(u64, src)
                             __field(u32, count)
+                            __field(bool, direct)
                             ),
 
            TP_fast_assign(
                           __entry->pe = pe;
                           __entry->src = src;
                           __entry->count = count;
+                          __entry->direct = direct;
                           ),
-           TP_printk("pe=%010Lx, src=%010Lx, count=%u",
-                     __entry->pe, __entry->src, __entry->count)
+           TP_printk("pe=%010Lx, src=%010Lx, count=%u, direct=%d",
+                     __entry->pe, __entry->src, __entry->count,
+                     __entry->direct)
 );
 
 TRACE_EVENT(amdgpu_vm_flush,
@@ -468,7 +473,7 @@ TRACE_EVENT(amdgpu_ib_pipe_sync,
            TP_PROTO(struct amdgpu_job *sched_job, struct dma_fence *fence),
            TP_ARGS(sched_job, fence),
            TP_STRUCT__entry(
-                            __field(const char *,name)
+                            __string(ring, sched_job->base.sched->name);
                             __field(uint64_t, id)
                             __field(struct dma_fence *, fence)
                             __field(uint64_t, ctx)
@@ -476,14 +481,14 @@ TRACE_EVENT(amdgpu_ib_pipe_sync,
                             ),
 
            TP_fast_assign(
-                          __entry->name = sched_job->base.sched->name;
+                          __assign_str(ring, sched_job->base.sched->name)
                           __entry->id = sched_job->base.id;
                           __entry->fence = fence;
                           __entry->ctx = fence->context;
                           __entry->seqno = fence->seqno;
                           ),
            TP_printk("job ring=%s, id=%llu, need pipe sync to fence=%p, context=%llu, seq=%u",
-                     __entry->name, __entry->id,
+                     __get_str(ring), __entry->id,
                      __entry->fence, __entry->ctx,
                      __entry->seqno)
 );
index 8e867b8b432f3f0f0cc985579f7af70e8cfd0778..a61b0d9ab9865749ff306547b764fa2e5c6d00b8 100644 (file)
@@ -54,6 +54,7 @@
 #include "amdgpu_trace.h"
 #include "amdgpu_amdkfd.h"
 #include "amdgpu_sdma.h"
+#include "amdgpu_ras.h"
 #include "bif/bif_4_1_d.h"
 
 static int amdgpu_map_buffer(struct ttm_buffer_object *bo,
@@ -1634,81 +1635,105 @@ static void amdgpu_ttm_fw_reserve_vram_fini(struct amdgpu_device *adev)
  */
 static int amdgpu_ttm_fw_reserve_vram_init(struct amdgpu_device *adev)
 {
-       struct ttm_operation_ctx ctx = { false, false };
-       struct amdgpu_bo_param bp;
-       int r = 0;
-       int i;
-       u64 vram_size = adev->gmc.visible_vram_size;
-       u64 offset = adev->fw_vram_usage.start_offset;
-       u64 size = adev->fw_vram_usage.size;
-       struct amdgpu_bo *bo;
-
-       memset(&bp, 0, sizeof(bp));
-       bp.size = adev->fw_vram_usage.size;
-       bp.byte_align = PAGE_SIZE;
-       bp.domain = AMDGPU_GEM_DOMAIN_VRAM;
-       bp.flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
-               AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
-       bp.type = ttm_bo_type_kernel;
-       bp.resv = NULL;
+       uint64_t vram_size = adev->gmc.visible_vram_size;
+
        adev->fw_vram_usage.va = NULL;
        adev->fw_vram_usage.reserved_bo = NULL;
 
-       if (adev->fw_vram_usage.size > 0 &&
-               adev->fw_vram_usage.size <= vram_size) {
+       if (adev->fw_vram_usage.size == 0 ||
+           adev->fw_vram_usage.size > vram_size)
+               return 0;
 
-               r = amdgpu_bo_create(adev, &bp,
-                                    &adev->fw_vram_usage.reserved_bo);
-               if (r)
-                       goto error_create;
+       return amdgpu_bo_create_kernel_at(adev,
+                                         adev->fw_vram_usage.start_offset,
+                                         adev->fw_vram_usage.size,
+                                         AMDGPU_GEM_DOMAIN_VRAM,
+                                         &adev->fw_vram_usage.reserved_bo,
+                                         &adev->fw_vram_usage.va);
+}
 
-               r = amdgpu_bo_reserve(adev->fw_vram_usage.reserved_bo, false);
-               if (r)
-                       goto error_reserve;
+/*
+ * Memoy training reservation functions
+ */
 
-               /* remove the original mem node and create a new one at the
-                * request position
-                */
-               bo = adev->fw_vram_usage.reserved_bo;
-               offset = ALIGN(offset, PAGE_SIZE);
-               for (i = 0; i < bo->placement.num_placement; ++i) {
-                       bo->placements[i].fpfn = offset >> PAGE_SHIFT;
-                       bo->placements[i].lpfn = (offset + size) >> PAGE_SHIFT;
-               }
+/**
+ * amdgpu_ttm_training_reserve_vram_fini - free memory training reserved vram
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * free memory training reserved vram if it has been reserved.
+ */
+static int amdgpu_ttm_training_reserve_vram_fini(struct amdgpu_device *adev)
+{
+       struct psp_memory_training_context *ctx = &adev->psp.mem_train_ctx;
 
-               ttm_bo_mem_put(&bo->tbo, &bo->tbo.mem);
-               r = ttm_bo_mem_space(&bo->tbo, &bo->placement,
-                                    &bo->tbo.mem, &ctx);
-               if (r)
-                       goto error_pin;
+       ctx->init = PSP_MEM_TRAIN_NOT_SUPPORT;
+       amdgpu_bo_free_kernel(&ctx->c2p_bo, NULL, NULL);
+       ctx->c2p_bo = NULL;
 
-               r = amdgpu_bo_pin_restricted(adev->fw_vram_usage.reserved_bo,
-                       AMDGPU_GEM_DOMAIN_VRAM,
-                       adev->fw_vram_usage.start_offset,
-                       (adev->fw_vram_usage.start_offset +
-                       adev->fw_vram_usage.size));
-               if (r)
-                       goto error_pin;
-               r = amdgpu_bo_kmap(adev->fw_vram_usage.reserved_bo,
-                       &adev->fw_vram_usage.va);
-               if (r)
-                       goto error_kmap;
+       amdgpu_bo_free_kernel(&ctx->p2c_bo, NULL, NULL);
+       ctx->p2c_bo = NULL;
+
+       return 0;
+}
+
+/**
+ * amdgpu_ttm_training_reserve_vram_init - create bo vram reservation from memory training
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * create bo vram reservation from memory training.
+ */
+static int amdgpu_ttm_training_reserve_vram_init(struct amdgpu_device *adev)
+{
+       int ret;
+       struct psp_memory_training_context *ctx = &adev->psp.mem_train_ctx;
 
-               amdgpu_bo_unreserve(adev->fw_vram_usage.reserved_bo);
+       memset(ctx, 0, sizeof(*ctx));
+       if (!adev->fw_vram_usage.mem_train_support) {
+               DRM_DEBUG("memory training does not support!\n");
+               return 0;
        }
-       return r;
 
-error_kmap:
-       amdgpu_bo_unpin(adev->fw_vram_usage.reserved_bo);
-error_pin:
-       amdgpu_bo_unreserve(adev->fw_vram_usage.reserved_bo);
-error_reserve:
-       amdgpu_bo_unref(&adev->fw_vram_usage.reserved_bo);
-error_create:
-       adev->fw_vram_usage.va = NULL;
-       adev->fw_vram_usage.reserved_bo = NULL;
-       return r;
+       ctx->c2p_train_data_offset = adev->fw_vram_usage.mem_train_fb_loc;
+       ctx->p2c_train_data_offset = (adev->gmc.mc_vram_size - GDDR6_MEM_TRAINING_OFFSET);
+       ctx->train_data_size = GDDR6_MEM_TRAINING_DATA_SIZE_IN_BYTES;
+
+       DRM_DEBUG("train_data_size:%llx,p2c_train_data_offset:%llx,c2p_train_data_offset:%llx.\n",
+                 ctx->train_data_size,
+                 ctx->p2c_train_data_offset,
+                 ctx->c2p_train_data_offset);
+
+       ret = amdgpu_bo_create_kernel_at(adev,
+                                        ctx->p2c_train_data_offset,
+                                        ctx->train_data_size,
+                                        AMDGPU_GEM_DOMAIN_VRAM,
+                                        &ctx->p2c_bo,
+                                        NULL);
+       if (ret) {
+               DRM_ERROR("alloc p2c_bo failed(%d)!\n", ret);
+               goto Err_out;
+       }
+
+       ret = amdgpu_bo_create_kernel_at(adev,
+                                        ctx->c2p_train_data_offset,
+                                        ctx->train_data_size,
+                                        AMDGPU_GEM_DOMAIN_VRAM,
+                                        &ctx->c2p_bo,
+                                        NULL);
+       if (ret) {
+               DRM_ERROR("alloc c2p_bo failed(%d)!\n", ret);
+               goto Err_out;
+       }
+
+       ctx->init = PSP_MEM_TRAIN_RESERVE_SUCCESS;
+       return 0;
+
+Err_out:
+       amdgpu_ttm_training_reserve_vram_fini(adev);
+       return ret;
 }
+
 /**
  * amdgpu_ttm_init - Init the memory management (ttm) as well as various
  * gtt/vram related fields.
@@ -1763,6 +1788,17 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
                                                adev->gmc.visible_vram_size);
 #endif
 
+       /*
+        * retired pages will be loaded from eeprom and reserved here,
+        * it should be called after ttm init since new bo may be created,
+        * recovery_init may fail, but it can free all resources allocated by
+        * itself and its failure should not stop amdgpu init process.
+        *
+        * Note: theoretically, this should be called before all vram allocations
+        * to protect retired page from abusing
+        */
+       amdgpu_ras_recovery_init(adev);
+
        /*
         *The reserved vram for firmware must be pinned to the specified
         *place on the VRAM, so reserve it early.
@@ -1772,6 +1808,14 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
                return r;
        }
 
+       /*
+        *The reserved vram for memory training must be pinned to the specified
+        *place on the VRAM, so reserve it early.
+        */
+       r = amdgpu_ttm_training_reserve_vram_init(adev);
+       if (r)
+               return r;
+
        /* allocate memory as required for VGA
         * This is used for VGA emulation and pre-OS scanout buffers to
         * avoid display artifacts while transitioning between pre-OS
@@ -1782,6 +1826,20 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
                                    NULL, &stolen_vga_buf);
        if (r)
                return r;
+
+       /*
+        * reserve one TMR (64K) memory at the top of VRAM which holds
+        * IP Discovery data and is protected by PSP.
+        */
+       r = amdgpu_bo_create_kernel_at(adev,
+                                      adev->gmc.real_vram_size - DISCOVERY_TMR_SIZE,
+                                      DISCOVERY_TMR_SIZE,
+                                      AMDGPU_GEM_DOMAIN_VRAM,
+                                      &adev->discovery_memory,
+                                      NULL);
+       if (r)
+               return r;
+
        DRM_INFO("amdgpu: %uM of VRAM memory ready\n",
                 (unsigned) (adev->gmc.real_vram_size / (1024 * 1024)));
 
@@ -1846,6 +1904,9 @@ void amdgpu_ttm_late_init(struct amdgpu_device *adev)
        void *stolen_vga_buf;
        /* return the VGA stolen memory (if any) back to VRAM */
        amdgpu_bo_free_kernel(&adev->stolen_vga_memory, NULL, &stolen_vga_buf);
+
+       /* return the IP Discovery TMR memory back to VRAM */
+       amdgpu_bo_free_kernel(&adev->discovery_memory, NULL, NULL);
 }
 
 /**
@@ -1857,6 +1918,7 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
                return;
 
        amdgpu_ttm_debugfs_fini(adev);
+       amdgpu_ttm_training_reserve_vram_fini(adev);
        amdgpu_ttm_fw_reserve_vram_fini(adev);
        if (adev->mman.aper_base_kaddr)
                iounmap(adev->mman.aper_base_kaddr);
@@ -1953,10 +2015,7 @@ static int amdgpu_map_buffer(struct ttm_buffer_object *bo,
        *addr += (u64)window * AMDGPU_GTT_MAX_TRANSFER_SIZE *
                AMDGPU_GPU_PAGE_SIZE;
 
-       num_dw = adev->mman.buffer_funcs->copy_num_dw;
-       while (num_dw & 0x7)
-               num_dw++;
-
+       num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8);
        num_bytes = num_pages * 8;
 
        r = amdgpu_job_alloc_with_ib(adev, num_dw * 4 + num_bytes, &job);
@@ -2016,11 +2075,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset,
 
        max_bytes = adev->mman.buffer_funcs->copy_max_bytes;
        num_loops = DIV_ROUND_UP(byte_count, max_bytes);
-       num_dw = num_loops * adev->mman.buffer_funcs->copy_num_dw;
-
-       /* for IB padding */
-       while (num_dw & 0x7)
-               num_dw++;
+       num_dw = ALIGN(num_loops * adev->mman.buffer_funcs->copy_num_dw, 8);
 
        r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, &job);
        if (r)
index 3a6115ad0196544e20f5b9b3aed891225c4f60fc..833fc4b68940bfb5e69b130aae24b0e5a4586c41 100644 (file)
@@ -360,6 +360,7 @@ amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type)
        case CHIP_RAVEN:
        case CHIP_VEGA12:
        case CHIP_VEGA20:
+       case CHIP_ARCTURUS:
        case CHIP_RENOIR:
        case CHIP_NAVI10:
        case CHIP_NAVI14:
@@ -368,8 +369,6 @@ amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type)
                        return AMDGPU_FW_LOAD_DIRECT;
                else
                        return AMDGPU_FW_LOAD_PSP;
-       case CHIP_ARCTURUS:
-               return AMDGPU_FW_LOAD_DIRECT;
 
        default:
                DRM_ERROR("Unknown firmware load type\n");
index b34f00d420499d447ceb26464b687247edd891d6..410587b950f3c8490c881c982281e1e45aae2b20 100644 (file)
@@ -108,6 +108,12 @@ struct ta_firmware_header_v1_0 {
        uint32_t ta_ras_ucode_version;
        uint32_t ta_ras_offset_bytes;
        uint32_t ta_ras_size_bytes;
+       uint32_t ta_hdcp_ucode_version;
+       uint32_t ta_hdcp_offset_bytes;
+       uint32_t ta_hdcp_size_bytes;
+       uint32_t ta_dtm_ucode_version;
+       uint32_t ta_dtm_offset_bytes;
+       uint32_t ta_dtm_size_bytes;
 };
 
 /* version_major=1, version_minor=0 */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
new file mode 100644 (file)
index 0000000..d4fb9cf
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright 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) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "amdgpu_ras.h"
+
+int amdgpu_umc_ras_late_init(struct amdgpu_device *adev)
+{
+       int r;
+       struct ras_fs_if fs_info = {
+               .sysfs_name = "umc_err_count",
+               .debugfs_name = "umc_err_inject",
+       };
+       struct ras_ih_if ih_info = {
+               .cb = amdgpu_umc_process_ras_data_cb,
+       };
+
+       if (!adev->umc.ras_if) {
+               adev->umc.ras_if =
+                       kmalloc(sizeof(struct ras_common_if), GFP_KERNEL);
+               if (!adev->umc.ras_if)
+                       return -ENOMEM;
+               adev->umc.ras_if->block = AMDGPU_RAS_BLOCK__UMC;
+               adev->umc.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
+               adev->umc.ras_if->sub_block_index = 0;
+               strcpy(adev->umc.ras_if->name, "umc");
+       }
+       ih_info.head = fs_info.head = *adev->umc.ras_if;
+
+       r = amdgpu_ras_late_init(adev, adev->umc.ras_if,
+                                &fs_info, &ih_info);
+       if (r)
+               goto free;
+
+       if (amdgpu_ras_is_supported(adev, adev->umc.ras_if->block)) {
+               r = amdgpu_irq_get(adev, &adev->gmc.ecc_irq, 0);
+               if (r)
+                       goto late_fini;
+       } else {
+               r = 0;
+               goto free;
+       }
+
+       /* ras init of specific umc version */
+       if (adev->umc.funcs && adev->umc.funcs->err_cnt_init)
+               adev->umc.funcs->err_cnt_init(adev);
+
+       return 0;
+
+late_fini:
+       amdgpu_ras_late_fini(adev, adev->umc.ras_if, &ih_info);
+free:
+       kfree(adev->umc.ras_if);
+       adev->umc.ras_if = NULL;
+       return r;
+}
+
+void amdgpu_umc_ras_fini(struct amdgpu_device *adev)
+{
+       if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC) &&
+                       adev->umc.ras_if) {
+               struct ras_common_if *ras_if = adev->umc.ras_if;
+               struct ras_ih_if ih_info = {
+                       .head = *ras_if,
+                       .cb = amdgpu_umc_process_ras_data_cb,
+               };
+
+               amdgpu_ras_late_fini(adev, ras_if, &ih_info);
+               kfree(ras_if);
+       }
+}
+
+int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev,
+               void *ras_error_status,
+               struct amdgpu_iv_entry *entry)
+{
+       struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
+
+       /* When “Full RAS” is enabled, the per-IP interrupt sources should
+        * be disabled and the driver should only look for the aggregated
+        * interrupt via sync flood
+        */
+       if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX))
+               return AMDGPU_RAS_SUCCESS;
+
+       kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
+       if (adev->umc.funcs &&
+           adev->umc.funcs->query_ras_error_count)
+           adev->umc.funcs->query_ras_error_count(adev, ras_error_status);
+
+       if (adev->umc.funcs &&
+           adev->umc.funcs->query_ras_error_address &&
+           adev->umc.max_ras_err_cnt_per_query) {
+               err_data->err_addr =
+                       kcalloc(adev->umc.max_ras_err_cnt_per_query,
+                               sizeof(struct eeprom_table_record), GFP_KERNEL);
+               /* still call query_ras_error_address to clear error status
+                * even NOMEM error is encountered
+                */
+               if(!err_data->err_addr)
+                       DRM_WARN("Failed to alloc memory for umc error address record!\n");
+
+               /* umc query_ras_error_address is also responsible for clearing
+                * error status
+                */
+               adev->umc.funcs->query_ras_error_address(adev, ras_error_status);
+       }
+
+       /* only uncorrectable error needs gpu reset */
+       if (err_data->ue_count) {
+               if (err_data->err_addr_cnt &&
+                   amdgpu_ras_add_bad_pages(adev, err_data->err_addr,
+                                               err_data->err_addr_cnt))
+                       DRM_WARN("Failed to add ras bad page!\n");
+
+               amdgpu_ras_reset_gpu(adev, 0);
+       }
+
+       kfree(err_data->err_addr);
+       return AMDGPU_RAS_SUCCESS;
+}
+
+int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev,
+               struct amdgpu_irq_src *source,
+               struct amdgpu_iv_entry *entry)
+{
+       struct ras_common_if *ras_if = adev->umc.ras_if;
+       struct ras_dispatch_if ih_data = {
+               .entry = entry,
+       };
+
+       if (!ras_if)
+               return 0;
+
+       ih_data.head = *ras_if;
+
+       amdgpu_ras_interrupt_dispatch(adev, &ih_data);
+       return 0;
+}
index 975afa04df090e7fcedc4947893888a5b21ff2cc..3283032a78e50baa7d4febb9d626296116efcf87 100644 (file)
@@ -54,7 +54,8 @@
        adev->umc.funcs->disable_umc_index_mode(adev);
 
 struct amdgpu_umc_funcs {
-       void (*ras_init)(struct amdgpu_device *adev);
+       void (*err_cnt_init)(struct amdgpu_device *adev);
+       int (*ras_late_init)(struct amdgpu_device *adev);
        void (*query_ras_error_count)(struct amdgpu_device *adev,
                                        void *ras_error_status);
        void (*query_ras_error_address)(struct amdgpu_device *adev,
@@ -62,6 +63,7 @@ struct amdgpu_umc_funcs {
        void (*enable_umc_index_mode)(struct amdgpu_device *adev,
                                        uint32_t umc_instance);
        void (*disable_umc_index_mode)(struct amdgpu_device *adev);
+       void (*init_registers)(struct amdgpu_device *adev);
 };
 
 struct amdgpu_umc {
@@ -75,8 +77,17 @@ struct amdgpu_umc {
        uint32_t channel_offs;
        /* channel index table of interleaved memory */
        const uint32_t *channel_idx_tbl;
+       struct ras_common_if *ras_if;
 
        const struct amdgpu_umc_funcs *funcs;
 };
 
+int amdgpu_umc_ras_late_init(struct amdgpu_device *adev);
+void amdgpu_umc_ras_fini(struct amdgpu_device *adev);
+int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev,
+               void *ras_error_status,
+               struct amdgpu_iv_entry *entry);
+int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev,
+               struct amdgpu_irq_src *source,
+               struct amdgpu_iv_entry *entry);
 #endif
index b70b3c45bb294f142998aca526e8dcd55920cf15..703677f2ff6fa5f2ee72dc599bea0e130c3b2f6f 100644 (file)
@@ -80,6 +80,11 @@ MODULE_FIRMWARE(FIRMWARE_VEGA12);
 MODULE_FIRMWARE(FIRMWARE_VEGA20);
 
 static void amdgpu_vce_idle_work_handler(struct work_struct *work);
+static int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
+                                    struct amdgpu_bo *bo,
+                                    struct dma_fence **fence);
+static int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
+                                     bool direct, struct dma_fence **fence);
 
 /**
  * amdgpu_vce_init - allocate memory, load vce firmware
@@ -428,14 +433,15 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
  *
  * Open up a stream for HW test
  */
-int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
-                             struct dma_fence **fence)
+static int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
+                                    struct amdgpu_bo *bo,
+                                    struct dma_fence **fence)
 {
        const unsigned ib_size_dw = 1024;
        struct amdgpu_job *job;
        struct amdgpu_ib *ib;
        struct dma_fence *f = NULL;
-       uint64_t dummy;
+       uint64_t addr;
        int i, r;
 
        r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
@@ -444,7 +450,7 @@ int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
 
        ib = &job->ibs[0];
 
-       dummy = ib->gpu_addr + 1024;
+       addr = amdgpu_bo_gpu_offset(bo);
 
        /* stitch together an VCE create msg */
        ib->length_dw = 0;
@@ -476,8 +482,8 @@ int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
 
        ib->ptr[ib->length_dw++] = 0x00000014; /* len */
        ib->ptr[ib->length_dw++] = 0x05000005; /* feedback buffer */
-       ib->ptr[ib->length_dw++] = upper_32_bits(dummy);
-       ib->ptr[ib->length_dw++] = dummy;
+       ib->ptr[ib->length_dw++] = upper_32_bits(addr);
+       ib->ptr[ib->length_dw++] = addr;
        ib->ptr[ib->length_dw++] = 0x00000001;
 
        for (i = ib->length_dw; i < ib_size_dw; ++i)
@@ -507,8 +513,8 @@ int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
  *
  * Close up a stream for HW test or if userspace failed to do so
  */
-int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
-                              bool direct, struct dma_fence **fence)
+static int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
+                                     bool direct, struct dma_fence **fence)
 {
        const unsigned ib_size_dw = 1024;
        struct amdgpu_job *job;
@@ -1110,13 +1116,20 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring)
 int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout)
 {
        struct dma_fence *fence = NULL;
+       struct amdgpu_bo *bo = NULL;
        long r;
 
        /* skip vce ring1/2 ib test for now, since it's not reliable */
        if (ring != &ring->adev->vce.ring[0])
                return 0;
 
-       r = amdgpu_vce_get_create_msg(ring, 1, NULL);
+       r = amdgpu_bo_create_reserved(ring->adev, 512, PAGE_SIZE,
+                                     AMDGPU_GEM_DOMAIN_VRAM,
+                                     &bo, NULL, NULL);
+       if (r)
+               return r;
+
+       r = amdgpu_vce_get_create_msg(ring, 1, bo, NULL);
        if (r)
                goto error;
 
@@ -1132,5 +1145,7 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout)
 
 error:
        dma_fence_put(fence);
+       amdgpu_bo_unreserve(bo);
+       amdgpu_bo_unref(&bo);
        return r;
 }
index 30ea54dd91173b57dbf48e9a9d12915f752d0e13..d6d83a3ec8030234a8d0970c0ea498f0cdc5f5c4 100644 (file)
@@ -58,10 +58,6 @@ int amdgpu_vce_sw_fini(struct amdgpu_device *adev);
 int amdgpu_vce_entity_init(struct amdgpu_device *adev);
 int amdgpu_vce_suspend(struct amdgpu_device *adev);
 int amdgpu_vce_resume(struct amdgpu_device *adev);
-int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
-                             struct dma_fence **fence);
-int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
-                              bool direct, struct dma_fence **fence);
 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);
index 7a6beb2e7c4e8aede558f98f9a3b37aff0affc7a..3199e4a5ff126a86156df7d4b94cdd1a53795bdf 100644 (file)
@@ -569,13 +569,14 @@ int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring)
 }
 
 static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
-                             struct dma_fence **fence)
+                                        struct amdgpu_bo *bo,
+                                        struct dma_fence **fence)
 {
        const unsigned ib_size_dw = 16;
        struct amdgpu_job *job;
        struct amdgpu_ib *ib;
        struct dma_fence *f = NULL;
-       uint64_t dummy;
+       uint64_t addr;
        int i, r;
 
        r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
@@ -583,14 +584,14 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
                return r;
 
        ib = &job->ibs[0];
-       dummy = ib->gpu_addr + 1024;
+       addr = amdgpu_bo_gpu_offset(bo);
 
        ib->length_dw = 0;
        ib->ptr[ib->length_dw++] = 0x00000018;
        ib->ptr[ib->length_dw++] = 0x00000001; /* session info */
        ib->ptr[ib->length_dw++] = handle;
-       ib->ptr[ib->length_dw++] = upper_32_bits(dummy);
-       ib->ptr[ib->length_dw++] = dummy;
+       ib->ptr[ib->length_dw++] = upper_32_bits(addr);
+       ib->ptr[ib->length_dw++] = addr;
        ib->ptr[ib->length_dw++] = 0x0000000b;
 
        ib->ptr[ib->length_dw++] = 0x00000014;
@@ -621,13 +622,14 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
 }
 
 static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
-                               struct dma_fence **fence)
+                                         struct amdgpu_bo *bo,
+                                         struct dma_fence **fence)
 {
        const unsigned ib_size_dw = 16;
        struct amdgpu_job *job;
        struct amdgpu_ib *ib;
        struct dma_fence *f = NULL;
-       uint64_t dummy;
+       uint64_t addr;
        int i, r;
 
        r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
@@ -635,14 +637,14 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
                return r;
 
        ib = &job->ibs[0];
-       dummy = ib->gpu_addr + 1024;
+       addr = amdgpu_bo_gpu_offset(bo);
 
        ib->length_dw = 0;
        ib->ptr[ib->length_dw++] = 0x00000018;
        ib->ptr[ib->length_dw++] = 0x00000001;
        ib->ptr[ib->length_dw++] = handle;
-       ib->ptr[ib->length_dw++] = upper_32_bits(dummy);
-       ib->ptr[ib->length_dw++] = dummy;
+       ib->ptr[ib->length_dw++] = upper_32_bits(addr);
+       ib->ptr[ib->length_dw++] = addr;
        ib->ptr[ib->length_dw++] = 0x0000000b;
 
        ib->ptr[ib->length_dw++] = 0x00000014;
@@ -675,13 +677,20 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
 int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)
 {
        struct dma_fence *fence = NULL;
+       struct amdgpu_bo *bo = NULL;
        long r;
 
-       r = amdgpu_vcn_enc_get_create_msg(ring, 1, NULL);
+       r = amdgpu_bo_create_reserved(ring->adev, 128 * 1024, PAGE_SIZE,
+                                     AMDGPU_GEM_DOMAIN_VRAM,
+                                     &bo, NULL, NULL);
+       if (r)
+               return r;
+
+       r = amdgpu_vcn_enc_get_create_msg(ring, 1, bo, NULL);
        if (r)
                goto error;
 
-       r = amdgpu_vcn_enc_get_destroy_msg(ring, 1, &fence);
+       r = amdgpu_vcn_enc_get_destroy_msg(ring, 1, bo, &fence);
        if (r)
                goto error;
 
@@ -693,6 +702,8 @@ int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)
 
 error:
        dma_fence_put(fence);
+       amdgpu_bo_unreserve(bo);
+       amdgpu_bo_unref(&bo);
        return r;
 }
 
index 5251352f59228733c6009598638332386eb52a5b..397bf5677ff251a86bb4c8522950d01c0b41b23f 100644 (file)
@@ -130,7 +130,8 @@ static unsigned amdgpu_vm_num_entries(struct amdgpu_device *adev,
 
        if (level == adev->vm_manager.root_level)
                /* For the root directory */
-               return round_up(adev->vm_manager.max_pfn, 1ULL << shift) >> shift;
+               return round_up(adev->vm_manager.max_pfn, 1ULL << shift)
+                       >> shift;
        else if (level != AMDGPU_VM_PTB)
                /* Everything in between */
                return 512;
@@ -341,7 +342,7 @@ static struct amdgpu_vm_pt *amdgpu_vm_pt_parent(struct amdgpu_vm_pt *pt)
        return container_of(parent->vm_bo, struct amdgpu_vm_pt, base);
 }
 
-/**
+/*
  * amdgpu_vm_pt_cursor - state for for_each_amdgpu_vm_pt
  */
 struct amdgpu_vm_pt_cursor {
@@ -482,6 +483,7 @@ static void amdgpu_vm_pt_next(struct amdgpu_device *adev,
  *
  * @adev: amdgpu_device structure
  * @vm: amdgpu_vm structure
+ * @start: optional cursor to start with
  * @cursor: state to initialize
  *
  * Starts a deep first traversal of the PD/PT tree.
@@ -535,7 +537,7 @@ static void amdgpu_vm_pt_next_dfs(struct amdgpu_device *adev,
                amdgpu_vm_pt_ancestor(cursor);
 }
 
-/**
+/*
  * for_each_amdgpu_vm_pt_dfs_safe - safe deep first search of all PDs/PTs
  */
 #define for_each_amdgpu_vm_pt_dfs_safe(adev, vm, start, cursor, entry)         \
@@ -566,6 +568,14 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
        list_add(&entry->tv.head, validated);
 }
 
+/**
+ * amdgpu_vm_del_from_lru_notify - update bulk_moveable flag
+ *
+ * @bo: BO which was removed from the LRU
+ *
+ * Make sure the bulk_moveable flag is updated when a BO is removed from the
+ * LRU.
+ */
 void amdgpu_vm_del_from_lru_notify(struct ttm_buffer_object *bo)
 {
        struct amdgpu_bo *abo;
@@ -693,6 +703,7 @@ bool amdgpu_vm_ready(struct amdgpu_vm *vm)
  * @adev: amdgpu_device pointer
  * @vm: VM to clear BO from
  * @bo: BO to clear
+ * @direct: use a direct update
  *
  * Root PD needs to be reserved when calling this.
  *
@@ -701,7 +712,8 @@ bool amdgpu_vm_ready(struct amdgpu_vm *vm)
  */
 static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
                              struct amdgpu_vm *vm,
-                             struct amdgpu_bo *bo)
+                             struct amdgpu_bo *bo,
+                             bool direct)
 {
        struct ttm_operation_ctx ctx = { true, false };
        unsigned level = adev->vm_manager.root_level;
@@ -760,6 +772,7 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
        memset(&params, 0, sizeof(params));
        params.adev = adev;
        params.vm = vm;
+       params.direct = direct;
 
        r = vm->update_funcs->prepare(&params, AMDGPU_FENCE_OWNER_KFD, NULL);
        if (r)
@@ -813,10 +826,13 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
  *
  * @adev: amdgpu_device pointer
  * @vm: requesting vm
+ * @level: the page table level
+ * @direct: use a direct update
  * @bp: resulting BO allocation parameters
  */
 static void amdgpu_vm_bo_param(struct amdgpu_device *adev, struct amdgpu_vm *vm,
-                              int level, struct amdgpu_bo_param *bp)
+                              int level, bool direct,
+                              struct amdgpu_bo_param *bp)
 {
        memset(bp, 0, sizeof(*bp));
 
@@ -831,6 +847,7 @@ static void amdgpu_vm_bo_param(struct amdgpu_device *adev, struct amdgpu_vm *vm,
        else if (!vm->root.base.bo || vm->root.base.bo->shadow)
                bp->flags |= AMDGPU_GEM_CREATE_SHADOW;
        bp->type = ttm_bo_type_kernel;
+       bp->no_wait_gpu = direct;
        if (vm->root.base.bo)
                bp->resv = vm->root.base.bo->tbo.base.resv;
 }
@@ -841,6 +858,7 @@ static void amdgpu_vm_bo_param(struct amdgpu_device *adev, struct amdgpu_vm *vm,
  * @adev: amdgpu_device pointer
  * @vm: VM to allocate page tables for
  * @cursor: Which page table to allocate
+ * @direct: use a direct update
  *
  * Make sure a specific page table or directory is allocated.
  *
@@ -850,7 +868,8 @@ static void amdgpu_vm_bo_param(struct amdgpu_device *adev, struct amdgpu_vm *vm,
  */
 static int amdgpu_vm_alloc_pts(struct amdgpu_device *adev,
                               struct amdgpu_vm *vm,
-                              struct amdgpu_vm_pt_cursor *cursor)
+                              struct amdgpu_vm_pt_cursor *cursor,
+                              bool direct)
 {
        struct amdgpu_vm_pt *entry = cursor->entry;
        struct amdgpu_bo_param bp;
@@ -871,7 +890,7 @@ static int amdgpu_vm_alloc_pts(struct amdgpu_device *adev,
        if (entry->base.bo)
                return 0;
 
-       amdgpu_vm_bo_param(adev, vm, cursor->level, &bp);
+       amdgpu_vm_bo_param(adev, vm, cursor->level, direct, &bp);
 
        r = amdgpu_bo_create(adev, &bp, &pt);
        if (r)
@@ -883,7 +902,7 @@ static int amdgpu_vm_alloc_pts(struct amdgpu_device *adev,
        pt->parent = amdgpu_bo_ref(cursor->parent->base.bo);
        amdgpu_vm_bo_base_init(&entry->base, vm, pt);
 
-       r = amdgpu_vm_clear_bo(adev, vm, pt);
+       r = amdgpu_vm_clear_bo(adev, vm, pt, direct);
        if (r)
                goto error_free_pt;
 
@@ -1020,7 +1039,8 @@ bool amdgpu_vm_need_pipeline_sync(struct amdgpu_ring *ring,
  * Returns:
  * 0 on success, errno otherwise.
  */
-int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_pipe_sync)
+int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
+                   bool need_pipe_sync)
 {
        struct amdgpu_device *adev = ring->adev;
        unsigned vmhub = ring->funcs->vmhub;
@@ -1034,10 +1054,8 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_
                id->oa_base != job->oa_base ||
                id->oa_size != job->oa_size);
        bool vm_flush_needed = job->vm_needs_flush;
-       bool pasid_mapping_needed = id->pasid != job->pasid ||
-               !id->pasid_mapping ||
-               !dma_fence_is_signaled(id->pasid_mapping);
        struct dma_fence *fence = NULL;
+       bool pasid_mapping_needed = false;
        unsigned patch_offset = 0;
        int r;
 
@@ -1047,6 +1065,12 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_
                pasid_mapping_needed = true;
        }
 
+       mutex_lock(&id_mgr->lock);
+       if (id->pasid != job->pasid || !id->pasid_mapping ||
+           !dma_fence_is_signaled(id->pasid_mapping))
+               pasid_mapping_needed = true;
+       mutex_unlock(&id_mgr->lock);
+
        gds_switch_needed &= !!ring->funcs->emit_gds_switch;
        vm_flush_needed &= !!ring->funcs->emit_vm_flush  &&
                        job->vm_pd_addr != AMDGPU_BO_INVALID_OFFSET;
@@ -1086,9 +1110,11 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_
        }
 
        if (pasid_mapping_needed) {
+               mutex_lock(&id_mgr->lock);
                id->pasid = job->pasid;
                dma_fence_put(id->pasid_mapping);
                id->pasid_mapping = dma_fence_get(fence);
+               mutex_unlock(&id_mgr->lock);
        }
        dma_fence_put(fence);
 
@@ -1172,10 +1198,10 @@ uint64_t amdgpu_vm_map_gart(const dma_addr_t *pages_addr, uint64_t addr)
        return result;
 }
 
-/*
+/**
  * amdgpu_vm_update_pde - update a single level in the hierarchy
  *
- * @param: parameters for the update
+ * @params: parameters for the update
  * @vm: requested vm
  * @entry: entry to update
  *
@@ -1199,7 +1225,7 @@ static int amdgpu_vm_update_pde(struct amdgpu_vm_update_params *params,
        return vm->update_funcs->update(params, bo, pde, pt, 1, 0, flags);
 }
 
-/*
+/**
  * amdgpu_vm_invalidate_pds - mark all PDs as invalid
  *
  * @adev: amdgpu_device pointer
@@ -1218,19 +1244,20 @@ static void amdgpu_vm_invalidate_pds(struct amdgpu_device *adev,
                        amdgpu_vm_bo_relocated(&entry->base);
 }
 
-/*
- * amdgpu_vm_update_directories - make sure that all directories are valid
+/**
+ * amdgpu_vm_update_pdes - make sure that all directories are valid
  *
  * @adev: amdgpu_device pointer
  * @vm: requested vm
+ * @direct: submit directly to the paging queue
  *
  * Makes sure all directories are up to date.
  *
  * Returns:
  * 0 for success, error for failure.
  */
-int amdgpu_vm_update_directories(struct amdgpu_device *adev,
-                                struct amdgpu_vm *vm)
+int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
+                         struct amdgpu_vm *vm, bool direct)
 {
        struct amdgpu_vm_update_params params;
        int r;
@@ -1241,6 +1268,7 @@ int amdgpu_vm_update_directories(struct amdgpu_device *adev,
        memset(&params, 0, sizeof(params));
        params.adev = adev;
        params.vm = vm;
+       params.direct = direct;
 
        r = vm->update_funcs->prepare(&params, AMDGPU_FENCE_OWNER_VM, NULL);
        if (r)
@@ -1268,7 +1296,7 @@ int amdgpu_vm_update_directories(struct amdgpu_device *adev,
        return r;
 }
 
-/**
+/*
  * amdgpu_vm_update_flags - figure out flags for PTE updates
  *
  * Make sure to set the right flags for the PTEs at the desired level.
@@ -1391,7 +1419,8 @@ static int amdgpu_vm_update_ptes(struct amdgpu_vm_update_params *params,
                uint64_t incr, entry_end, pe_start;
                struct amdgpu_bo *pt;
 
-               r = amdgpu_vm_alloc_pts(params->adev, params->vm, &cursor);
+               r = amdgpu_vm_alloc_pts(params->adev, params->vm, &cursor,
+                                       params->direct);
                if (r)
                        return r;
 
@@ -1482,13 +1511,14 @@ static int amdgpu_vm_update_ptes(struct amdgpu_vm_update_params *params,
  * amdgpu_vm_bo_update_mapping - update a mapping in the vm page table
  *
  * @adev: amdgpu_device pointer
- * @exclusive: fence we need to sync to
- * @pages_addr: DMA addresses to use for mapping
  * @vm: requested vm
+ * @direct: direct submission in a page fault
+ * @exclusive: fence we need to sync to
  * @start: start of mapped range
  * @last: last mapped entry
  * @flags: flags for the entries
  * @addr: addr to set the area to
+ * @pages_addr: DMA addresses to use for mapping
  * @fence: optional resulting fence
  *
  * Fill in the page table entries between @start and @last.
@@ -1497,11 +1527,11 @@ static int amdgpu_vm_update_ptes(struct amdgpu_vm_update_params *params,
  * 0 for success, -EINVAL for failure.
  */
 static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
+                                      struct amdgpu_vm *vm, bool direct,
                                       struct dma_fence *exclusive,
-                                      dma_addr_t *pages_addr,
-                                      struct amdgpu_vm *vm,
                                       uint64_t start, uint64_t last,
                                       uint64_t flags, uint64_t addr,
+                                      dma_addr_t *pages_addr,
                                       struct dma_fence **fence)
 {
        struct amdgpu_vm_update_params params;
@@ -1511,6 +1541,7 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
        memset(&params, 0, sizeof(params));
        params.adev = adev;
        params.vm = vm;
+       params.direct = direct;
        params.pages_addr = pages_addr;
 
        /* sync to everything except eviction fences on unmapping */
@@ -1569,27 +1600,8 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev,
        if (!(mapping->flags & AMDGPU_PTE_WRITEABLE))
                flags &= ~AMDGPU_PTE_WRITEABLE;
 
-       flags &= ~AMDGPU_PTE_EXECUTABLE;
-       flags |= mapping->flags & AMDGPU_PTE_EXECUTABLE;
-
-       if (adev->asic_type >= CHIP_NAVI10) {
-               flags &= ~AMDGPU_PTE_MTYPE_NV10_MASK;
-               flags |= (mapping->flags & AMDGPU_PTE_MTYPE_NV10_MASK);
-       } else {
-               flags &= ~AMDGPU_PTE_MTYPE_VG10_MASK;
-               flags |= (mapping->flags & AMDGPU_PTE_MTYPE_VG10_MASK);
-       }
-
-       if ((mapping->flags & AMDGPU_PTE_PRT) &&
-           (adev->asic_type >= CHIP_VEGA10)) {
-               flags |= AMDGPU_PTE_PRT;
-               if (adev->asic_type >= CHIP_NAVI10) {
-                       flags |= AMDGPU_PTE_SNOOPED;
-                       flags |= AMDGPU_PTE_LOG;
-                       flags |= AMDGPU_PTE_SYSTEM;
-               }
-               flags &= ~AMDGPU_PTE_VALID;
-       }
+       /* Apply ASIC specific mapping flags */
+       amdgpu_gmc_get_vm_pte(adev, mapping, &flags);
 
        trace_amdgpu_vm_bo_update(mapping);
 
@@ -1633,7 +1645,8 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev,
                                dma_addr = pages_addr;
                        } else {
                                addr = pages_addr[pfn];
-                               max_entries = count * AMDGPU_GPU_PAGES_IN_CPU_PAGE;
+                               max_entries = count *
+                                       AMDGPU_GPU_PAGES_IN_CPU_PAGE;
                        }
 
                } else if (flags & AMDGPU_PTE_VALID) {
@@ -1642,9 +1655,9 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev,
                }
 
                last = min((uint64_t)mapping->last, start + max_entries - 1);
-               r = amdgpu_vm_bo_update_mapping(adev, exclusive, dma_addr, vm,
+               r = amdgpu_vm_bo_update_mapping(adev, vm, false, exclusive,
                                                start, last, flags, addr,
-                                               fence);
+                                               dma_addr, fence);
                if (r)
                        return r;
 
@@ -1672,8 +1685,7 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev,
  * Returns:
  * 0 for success, -EINVAL for failure.
  */
-int amdgpu_vm_bo_update(struct amdgpu_device *adev,
-                       struct amdgpu_bo_va *bo_va,
+int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va,
                        bool clear)
 {
        struct amdgpu_bo *bo = bo_va->base.bo;
@@ -1700,7 +1712,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev,
                        ttm = container_of(bo->tbo.ttm, struct ttm_dma_tt, ttm);
                        pages_addr = ttm->dma_address;
                }
-               exclusive = dma_resv_get_excl(bo->tbo.base.resv);
+               exclusive = bo->tbo.moving;
        }
 
        if (bo) {
@@ -1731,12 +1743,6 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev,
                        return r;
        }
 
-       if (vm->use_cpu_for_update) {
-               /* Flush HDP */
-               mb();
-               amdgpu_asic_flush_hdp(adev, NULL);
-       }
-
        /* If the BO is not in its preferred location add it back to
         * the evicted list so that it gets validated again on the
         * next command submission.
@@ -1744,7 +1750,8 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev,
        if (bo && bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv) {
                uint32_t mem_type = bo->tbo.mem.mem_type;
 
-               if (!(bo->preferred_domains & amdgpu_mem_type_to_domain(mem_type)))
+               if (!(bo->preferred_domains &
+                     amdgpu_mem_type_to_domain(mem_type)))
                        amdgpu_vm_bo_evicted(&bo_va->base);
                else
                        amdgpu_vm_bo_idle(&bo_va->base);
@@ -1938,9 +1945,9 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
                    mapping->start < AMDGPU_GMC_HOLE_START)
                        init_pte_value = AMDGPU_PTE_DEFAULT_ATC;
 
-               r = amdgpu_vm_bo_update_mapping(adev, NULL, NULL, vm,
+               r = amdgpu_vm_bo_update_mapping(adev, vm, false, NULL,
                                                mapping->start, mapping->last,
-                                               init_pte_value, 0, &f);
+                                               init_pte_value, 0, NULL, &f);
                amdgpu_vm_free_mapping(adev, vm, mapping, f);
                if (r) {
                        dma_fence_put(f);
@@ -2682,12 +2689,17 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
        spin_lock_init(&vm->invalidated_lock);
        INIT_LIST_HEAD(&vm->freed);
 
-       /* create scheduler entity for page table updates */
-       r = drm_sched_entity_init(&vm->entity, adev->vm_manager.vm_pte_rqs,
+       /* create scheduler entities for page table updates */
+       r = drm_sched_entity_init(&vm->direct, adev->vm_manager.vm_pte_rqs,
                                  adev->vm_manager.vm_pte_num_rqs, NULL);
        if (r)
                return r;
 
+       r = drm_sched_entity_init(&vm->delayed, adev->vm_manager.vm_pte_rqs,
+                                 adev->vm_manager.vm_pte_num_rqs, NULL);
+       if (r)
+               goto error_free_direct;
+
        vm->pte_support_ats = false;
 
        if (vm_context == AMDGPU_VM_CONTEXT_COMPUTE) {
@@ -2702,7 +2714,8 @@ 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");
 
        if (vm->use_cpu_for_update)
@@ -2711,12 +2724,12 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
                vm->update_funcs = &amdgpu_vm_sdma_funcs;
        vm->last_update = NULL;
 
-       amdgpu_vm_bo_param(adev, vm, adev->vm_manager.root_level, &bp);
+       amdgpu_vm_bo_param(adev, vm, adev->vm_manager.root_level, false, &bp);
        if (vm_context == AMDGPU_VM_CONTEXT_COMPUTE)
                bp.flags &= ~AMDGPU_GEM_CREATE_SHADOW;
        r = amdgpu_bo_create(adev, &bp, &root);
        if (r)
-               goto error_free_sched_entity;
+               goto error_free_delayed;
 
        r = amdgpu_bo_reserve(root, true);
        if (r)
@@ -2728,7 +2741,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
 
        amdgpu_vm_bo_base_init(&vm->root.base, vm, root);
 
-       r = amdgpu_vm_clear_bo(adev, vm, root);
+       r = amdgpu_vm_clear_bo(adev, vm, root, false);
        if (r)
                goto error_unreserve;
 
@@ -2759,8 +2772,11 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
        amdgpu_bo_unref(&vm->root.base.bo);
        vm->root.base.bo = NULL;
 
-error_free_sched_entity:
-       drm_sched_entity_destroy(&vm->entity);
+error_free_delayed:
+       drm_sched_entity_destroy(&vm->delayed);
+
+error_free_direct:
+       drm_sched_entity_destroy(&vm->direct);
 
        return r;
 }
@@ -2801,6 +2817,7 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev,
  *
  * @adev: amdgpu_device pointer
  * @vm: requested vm
+ * @pasid: pasid to use
  *
  * This only works on GFX VMs that don't have any BOs added and no
  * page tables allocated yet.
@@ -2816,7 +2833,8 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev,
  * Returns:
  * 0 for success, -errno for errors.
  */
-int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, unsigned int pasid)
+int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+                          unsigned int pasid)
 {
        bool pte_support_ats = (adev->asic_type == CHIP_RAVEN);
        int r;
@@ -2848,7 +2866,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, uns
         */
        if (pte_support_ats != vm->pte_support_ats) {
                vm->pte_support_ats = pte_support_ats;
-               r = amdgpu_vm_clear_bo(adev, vm, vm->root.base.bo);
+               r = amdgpu_vm_clear_bo(adev, vm, vm->root.base.bo, false);
                if (r)
                        goto free_idr;
        }
@@ -2858,7 +2876,8 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, uns
                                    AMDGPU_VM_USE_CPU_FOR_COMPUTE);
        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->use_cpu_for_update)
@@ -2937,19 +2956,38 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
        struct amdgpu_bo_va_mapping *mapping, *tmp;
        bool prt_fini_needed = !!adev->gmc.gmc_funcs->set_prt;
        struct amdgpu_bo *root;
-       int i, r;
+       int i;
 
        amdgpu_amdkfd_gpuvm_destroy_cb(adev, vm);
 
+       root = amdgpu_bo_ref(vm->root.base.bo);
+       amdgpu_bo_reserve(root, true);
        if (vm->pasid) {
                unsigned long flags;
 
                spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
                idr_remove(&adev->vm_manager.pasid_idr, vm->pasid);
                spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
+               vm->pasid = 0;
+       }
+
+       list_for_each_entry_safe(mapping, tmp, &vm->freed, list) {
+               if (mapping->flags & AMDGPU_PTE_PRT && prt_fini_needed) {
+                       amdgpu_vm_prt_fini(adev, vm);
+                       prt_fini_needed = false;
+               }
+
+               list_del(&mapping->list);
+               amdgpu_vm_free_mapping(adev, vm, mapping, NULL);
        }
 
-       drm_sched_entity_destroy(&vm->entity);
+       amdgpu_vm_free_pts(adev, vm, NULL);
+       amdgpu_bo_unreserve(root);
+       amdgpu_bo_unref(&root);
+       WARN_ON(vm->root.base.bo);
+
+       drm_sched_entity_destroy(&vm->direct);
+       drm_sched_entity_destroy(&vm->delayed);
 
        if (!RB_EMPTY_ROOT(&vm->va.rb_root)) {
                dev_err(adev->dev, "still active bo inside vm\n");
@@ -2962,26 +3000,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
                list_del(&mapping->list);
                kfree(mapping);
        }
-       list_for_each_entry_safe(mapping, tmp, &vm->freed, list) {
-               if (mapping->flags & AMDGPU_PTE_PRT && prt_fini_needed) {
-                       amdgpu_vm_prt_fini(adev, vm);
-                       prt_fini_needed = false;
-               }
-
-               list_del(&mapping->list);
-               amdgpu_vm_free_mapping(adev, vm, mapping, NULL);
-       }
 
-       root = amdgpu_bo_ref(vm->root.base.bo);
-       r = amdgpu_bo_reserve(root, true);
-       if (r) {
-               dev_err(adev->dev, "Leaking page tables because BO reservation failed\n");
-       } else {
-               amdgpu_vm_free_pts(adev, vm, NULL);
-               amdgpu_bo_unreserve(root);
-       }
-       amdgpu_bo_unref(&root);
-       WARN_ON(vm->root.base.bo);
        dma_fence_put(vm->last_update);
        for (i = 0; i < AMDGPU_MAX_VMHUBS; i++)
                amdgpu_vmid_free_reserved(adev, vm, i);
@@ -3065,8 +3084,9 @@ int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 
        switch (args->in.op) {
        case AMDGPU_VM_OP_RESERVE_VMID:
-               /* current, we only have requirement to reserve vmid from gfxhub */
-               r = amdgpu_vmid_alloc_reserved(adev, &fpriv->vm, AMDGPU_GFXHUB_0);
+               /* We only have requirement to reserve vmid from gfxhub */
+               r = amdgpu_vmid_alloc_reserved(adev, &fpriv->vm,
+                                              AMDGPU_GFXHUB_0);
                if (r)
                        return r;
                break;
@@ -3109,13 +3129,88 @@ void amdgpu_vm_get_task_info(struct amdgpu_device *adev, unsigned int pasid,
  */
 void amdgpu_vm_set_task_info(struct amdgpu_vm *vm)
 {
-       if (!vm->task_info.pid) {
-               vm->task_info.pid = current->pid;
-               get_task_comm(vm->task_info.task_name, current);
+       if (vm->task_info.pid)
+               return;
 
-               if (current->group_leader->mm == current->mm) {
-                       vm->task_info.tgid = current->group_leader->pid;
-                       get_task_comm(vm->task_info.process_name, current->group_leader);
-               }
+       vm->task_info.pid = current->pid;
+       get_task_comm(vm->task_info.task_name, current);
+
+       if (current->group_leader->mm != current->mm)
+               return;
+
+       vm->task_info.tgid = current->group_leader->pid;
+       get_task_comm(vm->task_info.process_name, current->group_leader);
+}
+
+/**
+ * amdgpu_vm_handle_fault - graceful handling of VM faults.
+ * @adev: amdgpu device pointer
+ * @pasid: PASID of the VM
+ * @addr: Address of the fault
+ *
+ * Try to gracefully handle a VM fault. Return true if the fault was handled and
+ * shouldn't be reported any more.
+ */
+bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, unsigned int pasid,
+                           uint64_t addr)
+{
+       struct amdgpu_bo *root;
+       uint64_t value, flags;
+       struct amdgpu_vm *vm;
+       long r;
+
+       spin_lock(&adev->vm_manager.pasid_lock);
+       vm = idr_find(&adev->vm_manager.pasid_idr, pasid);
+       if (vm)
+               root = amdgpu_bo_ref(vm->root.base.bo);
+       else
+               root = NULL;
+       spin_unlock(&adev->vm_manager.pasid_lock);
+
+       if (!root)
+               return false;
+
+       r = amdgpu_bo_reserve(root, true);
+       if (r)
+               goto error_unref;
+
+       /* Double check that the VM still exists */
+       spin_lock(&adev->vm_manager.pasid_lock);
+       vm = idr_find(&adev->vm_manager.pasid_idr, pasid);
+       if (vm && vm->root.base.bo != root)
+               vm = NULL;
+       spin_unlock(&adev->vm_manager.pasid_lock);
+       if (!vm)
+               goto error_unlock;
+
+       addr /= AMDGPU_GPU_PAGE_SIZE;
+       flags = AMDGPU_PTE_VALID | AMDGPU_PTE_SNOOPED |
+               AMDGPU_PTE_SYSTEM;
+
+       if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_NEVER) {
+               /* Redirect the access to the dummy page */
+               value = adev->dummy_page_addr;
+               flags |= AMDGPU_PTE_EXECUTABLE | AMDGPU_PTE_READABLE |
+                       AMDGPU_PTE_WRITEABLE;
+       } else {
+               /* Let the hw retry silently on the PTE */
+               value = 0;
        }
+
+       r = amdgpu_vm_bo_update_mapping(adev, vm, true, NULL, addr, addr + 1,
+                                       flags, value, NULL, NULL);
+       if (r)
+               goto error_unlock;
+
+       r = amdgpu_vm_update_pdes(adev, vm, true);
+
+error_unlock:
+       amdgpu_bo_unreserve(root);
+       if (r < 0)
+               DRM_ERROR("Can't handle page fault (%ld)\n", r);
+
+error_unref:
+       amdgpu_bo_unref(&root);
+
+       return false;
 }
index 2eda3a8c330d37472d3957c7a3d750cf060481a7..4dbbe1b6b413604e33ae7be5abfffc36dcdd45f4 100644 (file)
@@ -99,6 +99,9 @@ struct amdgpu_bo_list_entry;
 #define AMDGPU_VM_FAULT_STOP_FIRST     1
 #define AMDGPU_VM_FAULT_STOP_ALWAYS    2
 
+/* Reserve 4MB VRAM for page tables */
+#define AMDGPU_VM_RESERVED_VRAM                (4ULL << 20)
+
 /* max number of VMHUB */
 #define AMDGPU_MAX_VMHUBS                      3
 #define AMDGPU_GFXHUB_0                                0
@@ -198,6 +201,11 @@ struct amdgpu_vm_update_params {
         */
        struct amdgpu_vm *vm;
 
+       /**
+        * @direct: if changes should be made directly
+        */
+       bool direct;
+
        /**
         * @pages_addr:
         *
@@ -254,8 +262,9 @@ struct amdgpu_vm {
        struct amdgpu_vm_pt     root;
        struct dma_fence        *last_update;
 
-       /* Scheduler entity for page table updates */
-       struct drm_sched_entity entity;
+       /* Scheduler entities for page table updates */
+       struct drm_sched_entity direct;
+       struct drm_sched_entity delayed;
 
        unsigned int            pasid;
        /* dedicated to vm */
@@ -357,8 +366,8 @@ int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
                              int (*callback)(void *p, struct amdgpu_bo *bo),
                              void *param);
 int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_pipe_sync);
-int amdgpu_vm_update_directories(struct amdgpu_device *adev,
-                                struct amdgpu_vm *vm);
+int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
+                         struct amdgpu_vm *vm, bool direct);
 int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
                          struct amdgpu_vm *vm,
                          struct dma_fence **fence);
@@ -404,6 +413,8 @@ void amdgpu_vm_check_compute_bug(struct amdgpu_device *adev);
 
 void amdgpu_vm_get_task_info(struct amdgpu_device *adev, unsigned int pasid,
                             struct amdgpu_task_info *task_info);
+bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, unsigned int pasid,
+                           uint64_t addr);
 
 void amdgpu_vm_set_task_info(struct amdgpu_vm *vm);
 
index 5222d165abfcf1472d10e99bbacd8b110dcbae92..73fec7a0ced57022dac4554e23ec0114328d143e 100644 (file)
@@ -49,13 +49,6 @@ static int amdgpu_vm_cpu_prepare(struct amdgpu_vm_update_params *p, void *owner,
 {
        int r;
 
-       /* Wait for PT BOs to be idle. PTs share the same resv. object
-        * as the root PD BO
-        */
-       r = amdgpu_bo_sync_wait(p->vm->root.base.bo, owner, true);
-       if (unlikely(r))
-               return r;
-
        /* Wait for any BO move to be completed */
        if (exclusive) {
                r = dma_fence_wait(exclusive, true);
@@ -63,7 +56,14 @@ static int amdgpu_vm_cpu_prepare(struct amdgpu_vm_update_params *p, void *owner,
                        return r;
        }
 
-       return 0;
+       /* Don't wait for submissions during page fault */
+       if (p->direct)
+               return 0;
+
+       /* Wait for PT BOs to be idle. PTs share the same resv. object
+        * as the root PD BO
+        */
+       return amdgpu_bo_sync_wait(p->vm->root.base.bo, owner, true);
 }
 
 /**
@@ -89,7 +89,7 @@ static int amdgpu_vm_cpu_update(struct amdgpu_vm_update_params *p,
 
        pe += (unsigned long)amdgpu_bo_kptr(bo);
 
-       trace_amdgpu_vm_set_ptes(pe, addr, count, incr, flags);
+       trace_amdgpu_vm_set_ptes(pe, addr, count, incr, flags, p->direct);
 
        for (i = 0; i < count; i++) {
                value = p->pages_addr ?
index 61fc584cbb1aa26cb6b7e3f5f5847b54eb8b2620..832db59f441ecc8c1b79106307f5bd69ab7ca1ca 100644 (file)
@@ -68,17 +68,19 @@ static int amdgpu_vm_sdma_prepare(struct amdgpu_vm_update_params *p,
        if (r)
                return r;
 
+       p->num_dw_left = ndw;
+
+       /* Wait for moves to be completed */
        r = amdgpu_sync_fence(p->adev, &p->job->sync, exclusive, false);
        if (r)
                return r;
 
-       r = amdgpu_sync_resv(p->adev, &p->job->sync, root->tbo.base.resv,
-                            owner, false);
-       if (r)
-               return r;
+       /* Don't wait for any submissions during page fault handling */
+       if (p->direct)
+               return 0;
 
-       p->num_dw_left = ndw;
-       return 0;
+       return amdgpu_sync_resv(p->adev, &p->job->sync, root->tbo.base.resv,
+                               owner, false);
 }
 
 /**
@@ -95,22 +97,23 @@ static int amdgpu_vm_sdma_commit(struct amdgpu_vm_update_params *p,
 {
        struct amdgpu_bo *root = p->vm->root.base.bo;
        struct amdgpu_ib *ib = p->job->ibs;
+       struct drm_sched_entity *entity;
        struct amdgpu_ring *ring;
        struct dma_fence *f;
        int r;
 
-       ring = container_of(p->vm->entity.rq->sched, struct amdgpu_ring, sched);
+       entity = p->direct ? &p->vm->direct : &p->vm->delayed;
+       ring = container_of(entity->rq->sched, struct amdgpu_ring, sched);
 
        WARN_ON(ib->length_dw == 0);
        amdgpu_ring_pad_ib(ring, ib);
        WARN_ON(ib->length_dw > p->num_dw_left);
-       r = amdgpu_job_submit(p->job, &p->vm->entity,
-                             AMDGPU_FENCE_OWNER_VM, &f);
+       r = amdgpu_job_submit(p->job, entity, AMDGPU_FENCE_OWNER_VM, &f);
        if (r)
                goto error;
 
        amdgpu_bo_fence(root, f, true);
-       if (fence)
+       if (fence && !p->direct)
                swap(*fence, f);
        dma_fence_put(f);
        return 0;
@@ -120,7 +123,6 @@ static int amdgpu_vm_sdma_commit(struct amdgpu_vm_update_params *p,
        return r;
 }
 
-
 /**
  * amdgpu_vm_sdma_copy_ptes - copy the PTEs from mapping
  *
@@ -141,7 +143,7 @@ static void amdgpu_vm_sdma_copy_ptes(struct amdgpu_vm_update_params *p,
        src += p->num_dw_left * 4;
 
        pe += amdgpu_bo_gpu_offset(bo);
-       trace_amdgpu_vm_copy_ptes(pe, src, count);
+       trace_amdgpu_vm_copy_ptes(pe, src, count, p->direct);
 
        amdgpu_vm_copy_pte(p->adev, ib, pe, src, count);
 }
@@ -168,7 +170,7 @@ static void amdgpu_vm_sdma_set_ptes(struct amdgpu_vm_update_params *p,
        struct amdgpu_ib *ib = p->job->ibs;
 
        pe += amdgpu_bo_gpu_offset(bo);
-       trace_amdgpu_vm_set_ptes(pe, addr, count, incr, flags);
+       trace_amdgpu_vm_set_ptes(pe, addr, count, incr, flags, p->direct);
        if (count < 3) {
                amdgpu_vm_write_pte(p->adev, ib, pe, addr | flags,
                                    count, incr);
index 3a9d8c15fe9fc732326c9f59aae0c68495235b14..82a3299e53c042f6c8a5f8e688e0f36a15ca60e4 100644 (file)
@@ -23,6 +23,9 @@
  */
 
 #include "amdgpu.h"
+#include "amdgpu_vm.h"
+#include "amdgpu_atomfirmware.h"
+#include "atom.h"
 
 struct amdgpu_vram_mgr {
        struct drm_mm mm;
@@ -101,6 +104,39 @@ static ssize_t amdgpu_mem_info_vis_vram_used_show(struct device *dev,
                amdgpu_vram_mgr_vis_usage(&adev->mman.bdev.man[TTM_PL_VRAM]));
 }
 
+static ssize_t amdgpu_mem_info_vram_vendor(struct device *dev,
+                                                struct device_attribute *attr,
+                                                char *buf)
+{
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       struct amdgpu_device *adev = ddev->dev_private;
+
+       switch (adev->gmc.vram_vendor) {
+       case SAMSUNG:
+               return snprintf(buf, PAGE_SIZE, "samsung\n");
+       case INFINEON:
+               return snprintf(buf, PAGE_SIZE, "infineon\n");
+       case ELPIDA:
+               return snprintf(buf, PAGE_SIZE, "elpida\n");
+       case ETRON:
+               return snprintf(buf, PAGE_SIZE, "etron\n");
+       case NANYA:
+               return snprintf(buf, PAGE_SIZE, "nanya\n");
+       case HYNIX:
+               return snprintf(buf, PAGE_SIZE, "hynix\n");
+       case MOSEL:
+               return snprintf(buf, PAGE_SIZE, "mosel\n");
+       case WINBOND:
+               return snprintf(buf, PAGE_SIZE, "winbond\n");
+       case ESMT:
+               return snprintf(buf, PAGE_SIZE, "esmt\n");
+       case MICRON:
+               return snprintf(buf, PAGE_SIZE, "micron\n");
+       default:
+               return snprintf(buf, PAGE_SIZE, "unknown\n");
+       }
+}
+
 static DEVICE_ATTR(mem_info_vram_total, S_IRUGO,
                   amdgpu_mem_info_vram_total_show, NULL);
 static DEVICE_ATTR(mem_info_vis_vram_total, S_IRUGO,
@@ -109,6 +145,8 @@ static DEVICE_ATTR(mem_info_vram_used, S_IRUGO,
                   amdgpu_mem_info_vram_used_show, NULL);
 static DEVICE_ATTR(mem_info_vis_vram_used, S_IRUGO,
                   amdgpu_mem_info_vis_vram_used_show, NULL);
+static DEVICE_ATTR(mem_info_vram_vendor, S_IRUGO,
+                  amdgpu_mem_info_vram_vendor, NULL);
 
 /**
  * amdgpu_vram_mgr_init - init VRAM manager and DRM MM
@@ -154,6 +192,11 @@ static int amdgpu_vram_mgr_init(struct ttm_mem_type_manager *man,
                DRM_ERROR("Failed to create device file mem_info_vis_vram_used\n");
                return ret;
        }
+       ret = device_create_file(adev->dev, &dev_attr_mem_info_vram_vendor);
+       if (ret) {
+               DRM_ERROR("Failed to create device file mem_info_vram_vendor\n");
+               return ret;
+       }
 
        return 0;
 }
@@ -180,6 +223,7 @@ static int amdgpu_vram_mgr_fini(struct ttm_mem_type_manager *man)
        device_remove_file(adev->dev, &dev_attr_mem_info_vis_vram_total);
        device_remove_file(adev->dev, &dev_attr_mem_info_vram_used);
        device_remove_file(adev->dev, &dev_attr_mem_info_vis_vram_used);
+       device_remove_file(adev->dev, &dev_attr_mem_info_vram_vendor);
        return 0;
 }
 
@@ -275,7 +319,7 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man,
        struct drm_mm_node *nodes;
        enum drm_mm_insert_mode mode;
        unsigned long lpfn, num_nodes, pages_per_node, pages_left;
-       uint64_t vis_usage = 0, mem_bytes;
+       uint64_t vis_usage = 0, mem_bytes, max_bytes;
        unsigned i;
        int r;
 
@@ -283,9 +327,13 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man,
        if (!lpfn)
                lpfn = man->size;
 
+       max_bytes = adev->gmc.mc_vram_size;
+       if (tbo->type != ttm_bo_type_kernel)
+               max_bytes -= AMDGPU_VM_RESERVED_VRAM;
+
        /* bail out quickly if there's likely not enough VRAM for this BO */
        mem_bytes = (u64)mem->num_pages << PAGE_SHIFT;
-       if (atomic64_add_return(mem_bytes, &mgr->usage) > adev->gmc.mc_vram_size) {
+       if (atomic64_add_return(mem_bytes, &mgr->usage) > max_bytes) {
                atomic64_sub(mem_bytes, &mgr->usage);
                mem->mm_node = NULL;
                return 0;
index 65aae75f80fd5ee4b62b7dc2bdf4cecb24b1b859..00371713c671a531410512afaa5976ddb488e03c 100644 (file)
@@ -25,6 +25,7 @@
 #include "amdgpu.h"
 #include "amdgpu_xgmi.h"
 #include "amdgpu_smu.h"
+#include "amdgpu_ras.h"
 #include "df/df_3_6_offset.h"
 
 static DEFINE_MUTEX(xgmi_mutex);
@@ -437,3 +438,52 @@ void amdgpu_xgmi_remove_device(struct amdgpu_device *adev)
                mutex_unlock(&hive->hive_lock);
        }
 }
+
+int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev)
+{
+       int r;
+       struct ras_ih_if ih_info = {
+               .cb = NULL,
+       };
+       struct ras_fs_if fs_info = {
+               .sysfs_name = "xgmi_wafl_err_count",
+               .debugfs_name = "xgmi_wafl_err_inject",
+       };
+
+       if (!adev->gmc.xgmi.supported ||
+           adev->gmc.xgmi.num_physical_nodes == 0)
+               return 0;
+
+       if (!adev->gmc.xgmi.ras_if) {
+               adev->gmc.xgmi.ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL);
+               if (!adev->gmc.xgmi.ras_if)
+                       return -ENOMEM;
+               adev->gmc.xgmi.ras_if->block = AMDGPU_RAS_BLOCK__XGMI_WAFL;
+               adev->gmc.xgmi.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
+               adev->gmc.xgmi.ras_if->sub_block_index = 0;
+               strcpy(adev->gmc.xgmi.ras_if->name, "xgmi_wafl");
+       }
+       ih_info.head = fs_info.head = *adev->gmc.xgmi.ras_if;
+       r = amdgpu_ras_late_init(adev, adev->gmc.xgmi.ras_if,
+                                &fs_info, &ih_info);
+       if (r || !amdgpu_ras_is_supported(adev, adev->gmc.xgmi.ras_if->block)) {
+               kfree(adev->gmc.xgmi.ras_if);
+               adev->gmc.xgmi.ras_if = NULL;
+       }
+
+       return r;
+}
+
+void amdgpu_xgmi_ras_fini(struct amdgpu_device *adev)
+{
+       if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__XGMI_WAFL) &&
+                       adev->gmc.xgmi.ras_if) {
+               struct ras_common_if *ras_if = adev->gmc.xgmi.ras_if;
+               struct ras_ih_if ih_info = {
+                       .cb = NULL,
+               };
+
+               amdgpu_ras_late_fini(adev, ras_if, &ih_info);
+               kfree(ras_if);
+       }
+}
index fbcee31788c4dc4e30b5fd29739b6232005306ec..bbf504ff7051f1d34eba4c2eaae2704cd5b70c7b 100644 (file)
@@ -42,6 +42,8 @@ void amdgpu_xgmi_remove_device(struct amdgpu_device *adev);
 int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate);
 int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev,
                struct amdgpu_device *peer_adev);
+int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev);
+void amdgpu_xgmi_ras_fini(struct amdgpu_device *adev);
 
 static inline bool amdgpu_xgmi_same_hive(struct amdgpu_device *adev,
                struct amdgpu_device *bo_adev)
index 4853899b1824b37b5e6a2b0bf4a38a6d4e004d9a..fda99c958c3b4622987fa609032b6d8fc8fb558f 100644 (file)
@@ -24,7 +24,6 @@
 #include "soc15.h"
 
 #include "soc15_common.h"
-#include "soc15_hw_ip.h"
 #include "arct_ip_offset.h"
 
 int arct_reg_base_init(struct amdgpu_device *adev)
@@ -52,6 +51,8 @@ int arct_reg_base_init(struct amdgpu_device *adev)
                adev->reg_offset[SDMA7_HWIP][i] = (uint32_t *)(&(SDMA7_BASE.instance[i]));
                adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
                adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i]));
+               adev->reg_offset[UMC_HWIP][i] = (uint32_t *)(&(UMC_BASE.instance[i]));
+               adev->reg_offset[RSMU_HWIP][i] = (uint32_t *)(&(RSMU_BASE.instance[i]));
        }
        return 0;
 }
index b81bb414fcb300a98312fa7d60c5ced4c72d05f7..fc8b34480f66da2acbf91d00df667eeda6255423 100644 (file)
@@ -1270,15 +1270,15 @@ static int cik_gpu_pci_config_reset(struct amdgpu_device *adev)
 }
 
 /**
- * cik_asic_reset - soft reset GPU
+ * cik_asic_pci_config_reset - soft reset GPU
  *
  * @adev: amdgpu_device pointer
  *
- * Look up which blocks are hung and attempt
- * to reset them.
+ * Use PCI Config method to reset the GPU.
+ *
  * Returns 0 for success.
  */
-static int cik_asic_reset(struct amdgpu_device *adev)
+static int cik_asic_pci_config_reset(struct amdgpu_device *adev)
 {
        int r;
 
@@ -1294,7 +1294,45 @@ static int cik_asic_reset(struct amdgpu_device *adev)
 static enum amd_reset_method
 cik_asic_reset_method(struct amdgpu_device *adev)
 {
-       return AMD_RESET_METHOD_LEGACY;
+       bool baco_reset;
+
+       switch (adev->asic_type) {
+       case CHIP_BONAIRE:
+       case CHIP_HAWAII:
+               /* disable baco reset until it works */
+               /* smu7_asic_get_baco_capability(adev, &baco_reset); */
+               baco_reset = false;
+               break;
+       default:
+               baco_reset = false;
+               break;
+       }
+
+       if (baco_reset)
+               return AMD_RESET_METHOD_BACO;
+       else
+               return AMD_RESET_METHOD_LEGACY;
+}
+
+/**
+ * cik_asic_reset - soft reset GPU
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Look up which blocks are hung and attempt
+ * to reset them.
+ * Returns 0 for success.
+ */
+static int cik_asic_reset(struct amdgpu_device *adev)
+{
+       int r;
+
+       if (cik_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)
+               r = smu7_asic_baco_reset(adev);
+       else
+               r = cik_asic_pci_config_reset(adev);
+
+       return r;
 }
 
 static u32 cik_get_config_memsize(struct amdgpu_device *adev)
index 54c625a2e57054568f3498236186822cc55ed2d3..9870bf27870e060dbc5b22ad416782a8bbafd69b 100644 (file)
@@ -31,4 +31,7 @@ void cik_srbm_select(struct amdgpu_device *adev,
 int cik_set_ip_blocks(struct amdgpu_device *adev);
 
 void legacy_doorbell_index_init(struct amdgpu_device *adev);
+int smu7_asic_get_baco_capability(struct amdgpu_device *adev, bool *cap);
+int smu7_asic_baco_reset(struct amdgpu_device *adev);
+
 #endif
index 645550e7caf5183cf193bb4fb8afaf04a7d02405..40d2ac723dd6ce3df09170551ebbcffb4933ab8d 100644 (file)
@@ -330,9 +330,11 @@ static void dce_v10_0_hpd_init(struct amdgpu_device *adev)
 {
        struct drm_device *dev = adev->ddev;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
        u32 tmp;
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
                if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
@@ -368,6 +370,7 @@ static void dce_v10_0_hpd_init(struct amdgpu_device *adev)
                amdgpu_irq_get(adev, &adev->hpd_irq,
                               amdgpu_connector->hpd.hpd);
        }
+       drm_connector_list_iter_end(&iter);
 }
 
 /**
@@ -382,9 +385,11 @@ static void dce_v10_0_hpd_fini(struct amdgpu_device *adev)
 {
        struct drm_device *dev = adev->ddev;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
        u32 tmp;
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
                if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
@@ -397,6 +402,7 @@ static void dce_v10_0_hpd_fini(struct amdgpu_device *adev)
                amdgpu_irq_put(adev, &adev->hpd_irq,
                               amdgpu_connector->hpd.hpd);
        }
+       drm_connector_list_iter_end(&iter);
 }
 
 static u32 dce_v10_0_hpd_get_gpio_reg(struct amdgpu_device *adev)
@@ -1219,10 +1225,12 @@ static void dce_v10_0_afmt_audio_select_pin(struct drm_encoder *encoder)
 static void dce_v10_0_audio_write_latency_fields(struct drm_encoder *encoder,
                                                struct drm_display_mode *mode)
 {
-       struct amdgpu_device *adev = encoder->dev->dev_private;
+       struct drm_device *dev = encoder->dev;
+       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;
+       struct drm_connector_list_iter iter;
        struct amdgpu_connector *amdgpu_connector = NULL;
        u32 tmp;
        int interlace = 0;
@@ -1230,12 +1238,14 @@ static void dce_v10_0_audio_write_latency_fields(struct drm_encoder *encoder,
        if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
-       list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                if (connector->encoder == encoder) {
                        amdgpu_connector = to_amdgpu_connector(connector);
                        break;
                }
        }
+       drm_connector_list_iter_end(&iter);
 
        if (!amdgpu_connector) {
                DRM_ERROR("Couldn't find encoder's connector\n");
@@ -1261,10 +1271,12 @@ static void dce_v10_0_audio_write_latency_fields(struct drm_encoder *encoder,
 
 static void dce_v10_0_audio_write_speaker_allocation(struct drm_encoder *encoder)
 {
-       struct amdgpu_device *adev = encoder->dev->dev_private;
+       struct drm_device *dev = encoder->dev;
+       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;
+       struct drm_connector_list_iter iter;
        struct amdgpu_connector *amdgpu_connector = NULL;
        u32 tmp;
        u8 *sadb = NULL;
@@ -1273,12 +1285,14 @@ static void dce_v10_0_audio_write_speaker_allocation(struct drm_encoder *encoder
        if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
-       list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                if (connector->encoder == encoder) {
                        amdgpu_connector = to_amdgpu_connector(connector);
                        break;
                }
        }
+       drm_connector_list_iter_end(&iter);
 
        if (!amdgpu_connector) {
                DRM_ERROR("Couldn't find encoder's connector\n");
@@ -1313,10 +1327,12 @@ static void dce_v10_0_audio_write_speaker_allocation(struct drm_encoder *encoder
 
 static void dce_v10_0_audio_write_sad_regs(struct drm_encoder *encoder)
 {
-       struct amdgpu_device *adev = encoder->dev->dev_private;
+       struct drm_device *dev = encoder->dev;
+       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;
+       struct drm_connector_list_iter iter;
        struct amdgpu_connector *amdgpu_connector = NULL;
        struct cea_sad *sads;
        int i, sad_count;
@@ -1339,12 +1355,14 @@ static void dce_v10_0_audio_write_sad_regs(struct drm_encoder *encoder)
        if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
-       list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                if (connector->encoder == encoder) {
                        amdgpu_connector = to_amdgpu_connector(connector);
                        break;
                }
        }
+       drm_connector_list_iter_end(&iter);
 
        if (!amdgpu_connector) {
                DRM_ERROR("Couldn't find encoder's connector\n");
@@ -1352,10 +1370,10 @@ static void dce_v10_0_audio_write_sad_regs(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_sad(amdgpu_connector_edid(connector), &sads);
-       if (sad_count <= 0) {
+       if (sad_count < 0)
                DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
+       if (sad_count <= 0)
                return;
-       }
        BUG_ON(!sads);
 
        for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
index d9f470632b2ca1682a7c64c8004e2eb9a33a1849..898ef72d423c213f5c745532c9dacd411556d465 100644 (file)
@@ -348,9 +348,11 @@ static void dce_v11_0_hpd_init(struct amdgpu_device *adev)
 {
        struct drm_device *dev = adev->ddev;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
        u32 tmp;
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
                if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
@@ -385,6 +387,7 @@ static void dce_v11_0_hpd_init(struct amdgpu_device *adev)
                dce_v11_0_hpd_set_polarity(adev, amdgpu_connector->hpd.hpd);
                amdgpu_irq_get(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
        }
+       drm_connector_list_iter_end(&iter);
 }
 
 /**
@@ -399,9 +402,11 @@ static void dce_v11_0_hpd_fini(struct amdgpu_device *adev)
 {
        struct drm_device *dev = adev->ddev;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
        u32 tmp;
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
                if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
@@ -413,6 +418,7 @@ static void dce_v11_0_hpd_fini(struct amdgpu_device *adev)
 
                amdgpu_irq_put(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
        }
+       drm_connector_list_iter_end(&iter);
 }
 
 static u32 dce_v11_0_hpd_get_gpio_reg(struct amdgpu_device *adev)
@@ -1245,10 +1251,12 @@ static void dce_v11_0_afmt_audio_select_pin(struct drm_encoder *encoder)
 static void dce_v11_0_audio_write_latency_fields(struct drm_encoder *encoder,
                                                struct drm_display_mode *mode)
 {
-       struct amdgpu_device *adev = encoder->dev->dev_private;
+       struct drm_device *dev = encoder->dev;
+       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;
+       struct drm_connector_list_iter iter;
        struct amdgpu_connector *amdgpu_connector = NULL;
        u32 tmp;
        int interlace = 0;
@@ -1256,12 +1264,14 @@ static void dce_v11_0_audio_write_latency_fields(struct drm_encoder *encoder,
        if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
-       list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                if (connector->encoder == encoder) {
                        amdgpu_connector = to_amdgpu_connector(connector);
                        break;
                }
        }
+       drm_connector_list_iter_end(&iter);
 
        if (!amdgpu_connector) {
                DRM_ERROR("Couldn't find encoder's connector\n");
@@ -1287,10 +1297,12 @@ static void dce_v11_0_audio_write_latency_fields(struct drm_encoder *encoder,
 
 static void dce_v11_0_audio_write_speaker_allocation(struct drm_encoder *encoder)
 {
-       struct amdgpu_device *adev = encoder->dev->dev_private;
+       struct drm_device *dev = encoder->dev;
+       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;
+       struct drm_connector_list_iter iter;
        struct amdgpu_connector *amdgpu_connector = NULL;
        u32 tmp;
        u8 *sadb = NULL;
@@ -1299,12 +1311,14 @@ static void dce_v11_0_audio_write_speaker_allocation(struct drm_encoder *encoder
        if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
-       list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                if (connector->encoder == encoder) {
                        amdgpu_connector = to_amdgpu_connector(connector);
                        break;
                }
        }
+       drm_connector_list_iter_end(&iter);
 
        if (!amdgpu_connector) {
                DRM_ERROR("Couldn't find encoder's connector\n");
@@ -1339,10 +1353,12 @@ static void dce_v11_0_audio_write_speaker_allocation(struct drm_encoder *encoder
 
 static void dce_v11_0_audio_write_sad_regs(struct drm_encoder *encoder)
 {
-       struct amdgpu_device *adev = encoder->dev->dev_private;
+       struct drm_device *dev = encoder->dev;
+       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;
+       struct drm_connector_list_iter iter;
        struct amdgpu_connector *amdgpu_connector = NULL;
        struct cea_sad *sads;
        int i, sad_count;
@@ -1365,12 +1381,14 @@ static void dce_v11_0_audio_write_sad_regs(struct drm_encoder *encoder)
        if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
-       list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                if (connector->encoder == encoder) {
                        amdgpu_connector = to_amdgpu_connector(connector);
                        break;
                }
        }
+       drm_connector_list_iter_end(&iter);
 
        if (!amdgpu_connector) {
                DRM_ERROR("Couldn't find encoder's connector\n");
@@ -1378,10 +1396,10 @@ static void dce_v11_0_audio_write_sad_regs(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_sad(amdgpu_connector_edid(connector), &sads);
-       if (sad_count <= 0) {
+       if (sad_count < 0)
                DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
+       if (sad_count <= 0)
                return;
-       }
        BUG_ON(!sads);
 
        for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
index 3eb2e74292697325c7539efea0755b2970494115..db15a112beccc97510815c61f0be12f9c098db1a 100644 (file)
@@ -281,9 +281,11 @@ static void dce_v6_0_hpd_init(struct amdgpu_device *adev)
 {
        struct drm_device *dev = adev->ddev;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
        u32 tmp;
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
                if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
@@ -309,7 +311,7 @@ static void dce_v6_0_hpd_init(struct amdgpu_device *adev)
                dce_v6_0_hpd_set_polarity(adev, amdgpu_connector->hpd.hpd);
                amdgpu_irq_get(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
        }
-
+       drm_connector_list_iter_end(&iter);
 }
 
 /**
@@ -324,9 +326,11 @@ static void dce_v6_0_hpd_fini(struct amdgpu_device *adev)
 {
        struct drm_device *dev = adev->ddev;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
        u32 tmp;
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
                if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
@@ -338,6 +342,7 @@ static void dce_v6_0_hpd_fini(struct amdgpu_device *adev)
 
                amdgpu_irq_put(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
        }
+       drm_connector_list_iter_end(&iter);
 }
 
 static u32 dce_v6_0_hpd_get_gpio_reg(struct amdgpu_device *adev)
@@ -1124,20 +1129,24 @@ static void dce_v6_0_audio_select_pin(struct drm_encoder *encoder)
 static void dce_v6_0_audio_write_latency_fields(struct drm_encoder *encoder,
                                                struct drm_display_mode *mode)
 {
-       struct amdgpu_device *adev = encoder->dev->dev_private;
+       struct drm_device *dev = encoder->dev;
+       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;
+       struct drm_connector_list_iter iter;
        struct amdgpu_connector *amdgpu_connector = NULL;
        int interlace = 0;
        u32 tmp;
 
-       list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                if (connector->encoder == encoder) {
                        amdgpu_connector = to_amdgpu_connector(connector);
                        break;
                }
        }
+       drm_connector_list_iter_end(&iter);
 
        if (!amdgpu_connector) {
                DRM_ERROR("Couldn't find encoder's connector\n");
@@ -1164,21 +1173,25 @@ static void dce_v6_0_audio_write_latency_fields(struct drm_encoder *encoder,
 
 static void dce_v6_0_audio_write_speaker_allocation(struct drm_encoder *encoder)
 {
-       struct amdgpu_device *adev = encoder->dev->dev_private;
+       struct drm_device *dev = encoder->dev;
+       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;
+       struct drm_connector_list_iter iter;
        struct amdgpu_connector *amdgpu_connector = NULL;
        u8 *sadb = NULL;
        int sad_count;
        u32 tmp;
 
-       list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                if (connector->encoder == encoder) {
                        amdgpu_connector = to_amdgpu_connector(connector);
                        break;
                }
        }
+       drm_connector_list_iter_end(&iter);
 
        if (!amdgpu_connector) {
                DRM_ERROR("Couldn't find encoder's connector\n");
@@ -1221,10 +1234,12 @@ static void dce_v6_0_audio_write_speaker_allocation(struct drm_encoder *encoder)
 
 static void dce_v6_0_audio_write_sad_regs(struct drm_encoder *encoder)
 {
-       struct amdgpu_device *adev = encoder->dev->dev_private;
+       struct drm_device *dev = encoder->dev;
+       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;
+       struct drm_connector_list_iter iter;
        struct amdgpu_connector *amdgpu_connector = NULL;
        struct cea_sad *sads;
        int i, sad_count;
@@ -1244,12 +1259,14 @@ static void dce_v6_0_audio_write_sad_regs(struct drm_encoder *encoder)
                { ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
        };
 
-       list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                if (connector->encoder == encoder) {
                        amdgpu_connector = to_amdgpu_connector(connector);
                        break;
                }
        }
+       drm_connector_list_iter_end(&iter);
 
        if (!amdgpu_connector) {
                DRM_ERROR("Couldn't find encoder's connector\n");
@@ -1257,10 +1274,10 @@ static void dce_v6_0_audio_write_sad_regs(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_sad(amdgpu_connector_edid(connector), &sads);
-       if (sad_count <= 0) {
+       if (sad_count < 0)
                DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
+       if (sad_count <= 0)
                return;
-       }
 
        for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
                u32 tmp = 0;
@@ -1632,6 +1649,7 @@ static void dce_v6_0_afmt_setmode(struct drm_encoder *encoder,
        struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
        struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
        struct amdgpu_connector *amdgpu_connector = NULL;
        int em = amdgpu_atombios_encoder_get_encoder_mode(encoder);
        int bpc = 8;
@@ -1639,12 +1657,14 @@ static void dce_v6_0_afmt_setmode(struct drm_encoder *encoder,
        if (!dig || !dig->afmt)
                return;
 
-       list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                if (connector->encoder == encoder) {
                        amdgpu_connector = to_amdgpu_connector(connector);
                        break;
                }
        }
+       drm_connector_list_iter_end(&iter);
 
        if (!amdgpu_connector) {
                DRM_ERROR("Couldn't find encoder's connector\n");
index a16c5e9e610e766ebd55c3f90b3ab68df0e96dcf..f06c9022c1fd38b5a3c128cc3d481eab4f04366a 100644 (file)
@@ -275,9 +275,11 @@ static void dce_v8_0_hpd_init(struct amdgpu_device *adev)
 {
        struct drm_device *dev = adev->ddev;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
        u32 tmp;
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
                if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
@@ -303,6 +305,7 @@ static void dce_v8_0_hpd_init(struct amdgpu_device *adev)
                dce_v8_0_hpd_set_polarity(adev, amdgpu_connector->hpd.hpd);
                amdgpu_irq_get(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
        }
+       drm_connector_list_iter_end(&iter);
 }
 
 /**
@@ -317,9 +320,11 @@ static void dce_v8_0_hpd_fini(struct amdgpu_device *adev)
 {
        struct drm_device *dev = adev->ddev;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
        u32 tmp;
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
                if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
@@ -331,6 +336,7 @@ static void dce_v8_0_hpd_fini(struct amdgpu_device *adev)
 
                amdgpu_irq_put(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
        }
+       drm_connector_list_iter_end(&iter);
 }
 
 static u32 dce_v8_0_hpd_get_gpio_reg(struct amdgpu_device *adev)
@@ -1157,10 +1163,12 @@ static void dce_v8_0_afmt_audio_select_pin(struct drm_encoder *encoder)
 static void dce_v8_0_audio_write_latency_fields(struct drm_encoder *encoder,
                                                struct drm_display_mode *mode)
 {
-       struct amdgpu_device *adev = encoder->dev->dev_private;
+       struct drm_device *dev = encoder->dev;
+       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;
+       struct drm_connector_list_iter iter;
        struct amdgpu_connector *amdgpu_connector = NULL;
        u32 tmp = 0, offset;
 
@@ -1169,12 +1177,14 @@ static void dce_v8_0_audio_write_latency_fields(struct drm_encoder *encoder,
 
        offset = dig->afmt->pin->offset;
 
-       list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                if (connector->encoder == encoder) {
                        amdgpu_connector = to_amdgpu_connector(connector);
                        break;
                }
        }
+       drm_connector_list_iter_end(&iter);
 
        if (!amdgpu_connector) {
                DRM_ERROR("Couldn't find encoder's connector\n");
@@ -1214,10 +1224,12 @@ static void dce_v8_0_audio_write_latency_fields(struct drm_encoder *encoder,
 
 static void dce_v8_0_audio_write_speaker_allocation(struct drm_encoder *encoder)
 {
-       struct amdgpu_device *adev = encoder->dev->dev_private;
+       struct drm_device *dev = encoder->dev;
+       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;
+       struct drm_connector_list_iter iter;
        struct amdgpu_connector *amdgpu_connector = NULL;
        u32 offset, tmp;
        u8 *sadb = NULL;
@@ -1228,12 +1240,14 @@ static void dce_v8_0_audio_write_speaker_allocation(struct drm_encoder *encoder)
 
        offset = dig->afmt->pin->offset;
 
-       list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                if (connector->encoder == encoder) {
                        amdgpu_connector = to_amdgpu_connector(connector);
                        break;
                }
        }
+       drm_connector_list_iter_end(&iter);
 
        if (!amdgpu_connector) {
                DRM_ERROR("Couldn't find encoder's connector\n");
@@ -1263,11 +1277,13 @@ static void dce_v8_0_audio_write_speaker_allocation(struct drm_encoder *encoder)
 
 static void dce_v8_0_audio_write_sad_regs(struct drm_encoder *encoder)
 {
-       struct amdgpu_device *adev = encoder->dev->dev_private;
+       struct drm_device *dev = encoder->dev;
+       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;
        u32 offset;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
        struct amdgpu_connector *amdgpu_connector = NULL;
        struct cea_sad *sads;
        int i, sad_count;
@@ -1292,12 +1308,14 @@ static void dce_v8_0_audio_write_sad_regs(struct drm_encoder *encoder)
 
        offset = dig->afmt->pin->offset;
 
-       list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                if (connector->encoder == encoder) {
                        amdgpu_connector = to_amdgpu_connector(connector);
                        break;
                }
        }
+       drm_connector_list_iter_end(&iter);
 
        if (!amdgpu_connector) {
                DRM_ERROR("Couldn't find encoder's connector\n");
@@ -1305,10 +1323,10 @@ static void dce_v8_0_audio_write_sad_regs(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_sad(amdgpu_connector_edid(connector), &sads);
-       if (sad_count <= 0) {
+       if (sad_count < 0)
                DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
+       if (sad_count <= 0)
                return;
-       }
        BUG_ON(!sads);
 
        for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
index 844c038682485bbb629e7ba152b14611f3455f01..d6221298b477fef6340c9086ca97da78ae5720eb 100644 (file)
@@ -33,6 +33,10 @@ static void df_v1_7_sw_init(struct amdgpu_device *adev)
 {
 }
 
+static void df_v1_7_sw_fini(struct amdgpu_device *adev)
+{
+}
+
 static void df_v1_7_enable_broadcast_mode(struct amdgpu_device *adev,
                                           bool enable)
 {
@@ -111,6 +115,7 @@ static void df_v1_7_enable_ecc_force_par_wr_rmw(struct amdgpu_device *adev,
 
 const struct amdgpu_df_funcs df_v1_7_funcs = {
        .sw_init = df_v1_7_sw_init,
+       .sw_fini = df_v1_7_sw_fini,
        .enable_broadcast_mode = df_v1_7_enable_broadcast_mode,
        .get_fb_channel_number = df_v1_7_get_fb_channel_number,
        .get_hbm_channel_number = df_v1_7_get_hbm_channel_number,
index 5850c8e34caacc57e2e44581c5e2892022ab7a3d..16fbd2bc8ad1ea00d3f1c7a6c9e8df996970571e 100644 (file)
@@ -99,8 +99,8 @@ static uint64_t df_v3_6_get_fica(struct amdgpu_device *adev,
        unsigned long flags, address, data;
        uint32_t ficadl_val, ficadh_val;
 
-       address = adev->nbio_funcs->get_pcie_index_offset(adev);
-       data = adev->nbio_funcs->get_pcie_data_offset(adev);
+       address = adev->nbio.funcs->get_pcie_index_offset(adev);
+       data = adev->nbio.funcs->get_pcie_data_offset(adev);
 
        spin_lock_irqsave(&adev->pcie_idx_lock, flags);
        WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessAddress3);
@@ -122,8 +122,8 @@ static void df_v3_6_set_fica(struct amdgpu_device *adev, uint32_t ficaa_val,
 {
        unsigned long flags, address, data;
 
-       address = adev->nbio_funcs->get_pcie_index_offset(adev);
-       data = adev->nbio_funcs->get_pcie_data_offset(adev);
+       address = adev->nbio.funcs->get_pcie_index_offset(adev);
+       data = adev->nbio.funcs->get_pcie_data_offset(adev);
 
        spin_lock_irqsave(&adev->pcie_idx_lock, flags);
        WREG32(address, smnDF_PIE_AON_FabricIndirectConfigAccessAddress3);
@@ -150,8 +150,8 @@ static void df_v3_6_perfmon_rreg(struct amdgpu_device *adev,
 {
        unsigned long flags, address, data;
 
-       address = adev->nbio_funcs->get_pcie_index_offset(adev);
-       data = adev->nbio_funcs->get_pcie_data_offset(adev);
+       address = adev->nbio.funcs->get_pcie_index_offset(adev);
+       data = adev->nbio.funcs->get_pcie_data_offset(adev);
 
        spin_lock_irqsave(&adev->pcie_idx_lock, flags);
        WREG32(address, lo_addr);
@@ -172,8 +172,8 @@ static void df_v3_6_perfmon_wreg(struct amdgpu_device *adev, uint32_t lo_addr,
 {
        unsigned long flags, address, data;
 
-       address = adev->nbio_funcs->get_pcie_index_offset(adev);
-       data = adev->nbio_funcs->get_pcie_data_offset(adev);
+       address = adev->nbio.funcs->get_pcie_index_offset(adev);
+       data = adev->nbio.funcs->get_pcie_data_offset(adev);
 
        spin_lock_irqsave(&adev->pcie_idx_lock, flags);
        WREG32(address, lo_addr);
@@ -220,6 +220,13 @@ static void df_v3_6_sw_init(struct amdgpu_device *adev)
                adev->df_perfmon_config_assign_mask[i] = 0;
 }
 
+static void df_v3_6_sw_fini(struct amdgpu_device *adev)
+{
+
+       device_remove_file(adev->dev, &dev_attr_df_cntr_avail);
+
+}
+
 static void df_v3_6_enable_broadcast_mode(struct amdgpu_device *adev,
                                          bool enable)
 {
@@ -537,6 +544,7 @@ static void df_v3_6_pmc_get_count(struct amdgpu_device *adev,
 
 const struct amdgpu_df_funcs df_v3_6_funcs = {
        .sw_init = df_v3_6_sw_init,
+       .sw_fini = df_v3_6_sw_fini,
        .enable_broadcast_mode = df_v3_6_enable_broadcast_mode,
        .get_fb_channel_number = df_v3_6_get_fb_channel_number,
        .get_hbm_channel_number = df_v3_6_get_hbm_channel_number,
index 957811b73672a988fd92d8985fe7f0f27569bf58..b2ad928f60abd353096f632a4be1f84da5def7fc 100644 (file)
@@ -127,7 +127,7 @@ static const struct soc15_reg_golden golden_settings_gc_10_1[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTA_CNTL_AUX, 0xfff7ffff, 0x01030000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CNTL, 0x60000010, 0x479c0010),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CGTT_CLK_CTRL, 0xfeff0fff, 0x40000100),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0x00800000, 0x00800000)
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0x00c00000, 0x00c00000)
 };
 
 static const struct soc15_reg_golden golden_settings_gc_10_0_nv10[] =
@@ -171,7 +171,7 @@ static const struct soc15_reg_golden golden_settings_gc_10_1_1[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_LDS_CLK_CTRL, 0xffffffff, 0xffffffff),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTA_CNTL_AUX, 0xfff7ffff, 0x01030000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CNTL, 0x60000010, 0x479c0010),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0x00800000, 0x00800000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0x00c00000, 0x00c00000),
 };
 
 static const struct soc15_reg_golden golden_settings_gc_10_1_2[] =
@@ -2443,7 +2443,7 @@ static int gfx_v10_0_cp_gfx_load_pfp_microcode(struct amdgpu_device *adev)
        }
 
        if (amdgpu_emu_mode == 1)
-               adev->nbio_funcs->hdp_flush(adev, NULL);
+               adev->nbio.funcs->hdp_flush(adev, NULL);
 
        tmp = RREG32_SOC15(GC, 0, mmCP_PFP_IC_BASE_CNTL);
        tmp = REG_SET_FIELD(tmp, CP_PFP_IC_BASE_CNTL, VMID, 0);
@@ -2513,7 +2513,7 @@ static int gfx_v10_0_cp_gfx_load_ce_microcode(struct amdgpu_device *adev)
        }
 
        if (amdgpu_emu_mode == 1)
-               adev->nbio_funcs->hdp_flush(adev, NULL);
+               adev->nbio.funcs->hdp_flush(adev, NULL);
 
        tmp = RREG32_SOC15(GC, 0, mmCP_CE_IC_BASE_CNTL);
        tmp = REG_SET_FIELD(tmp, CP_CE_IC_BASE_CNTL, VMID, 0);
@@ -2582,7 +2582,7 @@ static int gfx_v10_0_cp_gfx_load_me_microcode(struct amdgpu_device *adev)
        }
 
        if (amdgpu_emu_mode == 1)
-               adev->nbio_funcs->hdp_flush(adev, NULL);
+               adev->nbio.funcs->hdp_flush(adev, NULL);
 
        tmp = RREG32_SOC15(GC, 0, mmCP_ME_IC_BASE_CNTL);
        tmp = REG_SET_FIELD(tmp, CP_ME_IC_BASE_CNTL, VMID, 0);
@@ -2903,7 +2903,7 @@ static int gfx_v10_0_cp_compute_load_microcode(struct amdgpu_device *adev)
        }
 
        if (amdgpu_emu_mode == 1)
-               adev->nbio_funcs->hdp_flush(adev, NULL);
+               adev->nbio.funcs->hdp_flush(adev, NULL);
 
        tmp = RREG32_SOC15(GC, 0, mmCP_CPC_IC_BASE_CNTL);
        tmp = REG_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0);
@@ -4357,7 +4357,7 @@ static void gfx_v10_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
 {
        struct amdgpu_device *adev = ring->adev;
        u32 ref_and_mask, reg_mem_engine;
-       const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio_funcs->hdp_flush_reg;
+       const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio.hdp_flush_reg;
 
        if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) {
                switch (ring->me) {
@@ -4377,8 +4377,8 @@ static void gfx_v10_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
        }
 
        gfx_v10_0_wait_reg_mem(ring, reg_mem_engine, 0, 1,
-                              adev->nbio_funcs->get_hdp_flush_req_offset(adev),
-                              adev->nbio_funcs->get_hdp_flush_done_offset(adev),
+                              adev->nbio.funcs->get_hdp_flush_req_offset(adev),
+                              adev->nbio.funcs->get_hdp_flush_done_offset(adev),
                               ref_and_mask, ref_and_mask, 0x20);
 }
 
@@ -5283,15 +5283,12 @@ static void gfx_v10_0_set_rlc_funcs(struct amdgpu_device *adev)
 
 static void gfx_v10_0_set_gds_init(struct amdgpu_device *adev)
 {
-       /* init asic gds info */
-       switch (adev->asic_type) {
-       case CHIP_NAVI10:
-       default:
-               adev->gds.gds_size = 0x10000;
-               adev->gds.gds_compute_max_wave_id = 0x4ff;
-               break;
-       }
+       unsigned total_cu = adev->gfx.config.max_cu_per_sh *
+                           adev->gfx.config.max_sh_per_se *
+                           adev->gfx.config.max_shader_engines;
 
+       adev->gds.gds_size = 0x10000;
+       adev->gds.gds_compute_max_wave_id = total_cu * 32 - 1;
        adev->gds.gws_size = 64;
        adev->gds.oa_size = 16;
 }
index dcadc73bffd27b111a64319cd9fe7f0a49509544..47e256b6a0e59673c190bb1d034360b1b79a5780 100644 (file)
@@ -131,6 +131,18 @@ MODULE_FIRMWARE("amdgpu/renoir_rlc.bin");
 #define mmTCP_CHAN_STEER_5_ARCT                                                                0x0b0c
 #define mmTCP_CHAN_STEER_5_ARCT_BASE_IDX                                                       0
 
+struct ras_gfx_subblock_reg {
+       const char *name;
+       uint32_t hwip;
+       uint32_t inst;
+       uint32_t seg;
+       uint32_t reg_offset;
+       uint32_t sec_count_mask;
+       uint32_t sec_count_shift;
+       uint32_t ded_count_mask;
+       uint32_t ded_count_shift;
+};
+
 enum ta_ras_gfx_subblock {
        /*CPC*/
        TA_RAS_BLOCK__GFX_CPC_INDEX_START = 0,
@@ -517,9 +529,9 @@ static const struct soc15_reg_golden golden_settings_gc_9_0[] =
        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, 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, mmCP_MEC1_F32_INT_DIS, 0x00000800, 0x00000800),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000800, 0x00000800),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00008000, 0x00008000)
 };
 
 static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] =
@@ -582,9 +594,9 @@ static const struct soc15_reg_golden golden_settings_gc_9_1[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_CACHE_INVALIDATION, 0x3fff3af3, 0x19200000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000000ff),
        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, mmCP_MEC1_F32_INT_DIS, 0x00000800, 0x00000800),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000800, 0x00000800),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00008000, 0x00008000)
 };
 
 static const struct soc15_reg_golden golden_settings_gc_9_1_rv1[] =
@@ -676,9 +688,9 @@ static const struct soc15_reg_golden golden_settings_gc_9_2_1_vg12[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_HI, 0xffffffff, 0x00000000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_LO, 0xffffffff, 0x76325410),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTD_CNTL, 0x01bd9f33, 0x01000000),
-       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, mmCP_MEC1_F32_INT_DIS, 0x00000800, 0x00000800),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000800, 0x00000800),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00008000, 0x00008000)
 };
 
 static const struct soc15_reg_golden golden_settings_gc_9_4_1_arct[] =
@@ -1324,7 +1336,8 @@ static int gfx_v9_0_init_cp_compute_microcode(struct amdgpu_device *adev,
 
                        /* TODO: Determine if MEC2 JT FW loading can be removed
                                 for all GFX V9 asic and above */
-                       if (adev->asic_type != CHIP_ARCTURUS) {
+                       if (adev->asic_type != CHIP_ARCTURUS &&
+                           adev->asic_type != CHIP_RENOIR) {
                                info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC2_JT];
                                info->ucode_id = AMDGPU_UCODE_ID_CP_MEC2_JT;
                                info->fw = adev->gfx.mec2_fw;
@@ -1956,190 +1969,6 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
        return 0;
 }
 
-static int gfx_v9_0_ngg_create_buf(struct amdgpu_device *adev,
-                                  struct amdgpu_ngg_buf *ngg_buf,
-                                  int size_se,
-                                  int default_size_se)
-{
-       int r;
-
-       if (size_se < 0) {
-               dev_err(adev->dev, "Buffer size is invalid: %d\n", size_se);
-               return -EINVAL;
-       }
-       size_se = size_se ? size_se : default_size_se;
-
-       ngg_buf->size = size_se * adev->gfx.config.max_shader_engines;
-       r = amdgpu_bo_create_kernel(adev, ngg_buf->size,
-                                   PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
-                                   &ngg_buf->bo,
-                                   &ngg_buf->gpu_addr,
-                                   NULL);
-       if (r) {
-               dev_err(adev->dev, "(%d) failed to create NGG buffer\n", r);
-               return r;
-       }
-       ngg_buf->bo_size = amdgpu_bo_size(ngg_buf->bo);
-
-       return r;
-}
-
-static int gfx_v9_0_ngg_fini(struct amdgpu_device *adev)
-{
-       int i;
-
-       for (i = 0; i < NGG_BUF_MAX; i++)
-               amdgpu_bo_free_kernel(&adev->gfx.ngg.buf[i].bo,
-                                     &adev->gfx.ngg.buf[i].gpu_addr,
-                                     NULL);
-
-       memset(&adev->gfx.ngg.buf[0], 0,
-                       sizeof(struct amdgpu_ngg_buf) * NGG_BUF_MAX);
-
-       adev->gfx.ngg.init = false;
-
-       return 0;
-}
-
-static int gfx_v9_0_ngg_init(struct amdgpu_device *adev)
-{
-       int r;
-
-       if (!amdgpu_ngg || adev->gfx.ngg.init == true)
-               return 0;
-
-       /* GDS reserve memory: 64 bytes alignment */
-       adev->gfx.ngg.gds_reserve_size = ALIGN(5 * 4, 0x40);
-       adev->gds.gds_size -= adev->gfx.ngg.gds_reserve_size;
-       adev->gfx.ngg.gds_reserve_addr = RREG32_SOC15(GC, 0, mmGDS_VMID0_BASE);
-       adev->gfx.ngg.gds_reserve_addr += RREG32_SOC15(GC, 0, mmGDS_VMID0_SIZE);
-
-       /* Primitive Buffer */
-       r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[NGG_PRIM],
-                                   amdgpu_prim_buf_per_se,
-                                   64 * 1024);
-       if (r) {
-               dev_err(adev->dev, "Failed to create Primitive Buffer\n");
-               goto err;
-       }
-
-       /* Position Buffer */
-       r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[NGG_POS],
-                                   amdgpu_pos_buf_per_se,
-                                   256 * 1024);
-       if (r) {
-               dev_err(adev->dev, "Failed to create Position Buffer\n");
-               goto err;
-       }
-
-       /* Control Sideband */
-       r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[NGG_CNTL],
-                                   amdgpu_cntl_sb_buf_per_se,
-                                   256);
-       if (r) {
-               dev_err(adev->dev, "Failed to create Control Sideband Buffer\n");
-               goto err;
-       }
-
-       /* Parameter Cache, not created by default */
-       if (amdgpu_param_buf_per_se <= 0)
-               goto out;
-
-       r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[NGG_PARAM],
-                                   amdgpu_param_buf_per_se,
-                                   512 * 1024);
-       if (r) {
-               dev_err(adev->dev, "Failed to create Parameter Cache\n");
-               goto err;
-       }
-
-out:
-       adev->gfx.ngg.init = true;
-       return 0;
-err:
-       gfx_v9_0_ngg_fini(adev);
-       return r;
-}
-
-static int gfx_v9_0_ngg_en(struct amdgpu_device *adev)
-{
-       struct amdgpu_ring *ring = &adev->gfx.gfx_ring[0];
-       int r;
-       u32 data, base;
-
-       if (!amdgpu_ngg)
-               return 0;
-
-       /* Program buffer size */
-       data = REG_SET_FIELD(0, WD_BUF_RESOURCE_1, INDEX_BUF_SIZE,
-                            adev->gfx.ngg.buf[NGG_PRIM].size >> 8);
-       data = REG_SET_FIELD(data, WD_BUF_RESOURCE_1, POS_BUF_SIZE,
-                            adev->gfx.ngg.buf[NGG_POS].size >> 8);
-       WREG32_SOC15(GC, 0, mmWD_BUF_RESOURCE_1, data);
-
-       data = REG_SET_FIELD(0, WD_BUF_RESOURCE_2, CNTL_SB_BUF_SIZE,
-                            adev->gfx.ngg.buf[NGG_CNTL].size >> 8);
-       data = REG_SET_FIELD(data, WD_BUF_RESOURCE_2, PARAM_BUF_SIZE,
-                            adev->gfx.ngg.buf[NGG_PARAM].size >> 10);
-       WREG32_SOC15(GC, 0, mmWD_BUF_RESOURCE_2, data);
-
-       /* Program buffer base address */
-       base = lower_32_bits(adev->gfx.ngg.buf[NGG_PRIM].gpu_addr);
-       data = REG_SET_FIELD(0, WD_INDEX_BUF_BASE, BASE, base);
-       WREG32_SOC15(GC, 0, mmWD_INDEX_BUF_BASE, data);
-
-       base = upper_32_bits(adev->gfx.ngg.buf[NGG_PRIM].gpu_addr);
-       data = REG_SET_FIELD(0, WD_INDEX_BUF_BASE_HI, BASE_HI, base);
-       WREG32_SOC15(GC, 0, mmWD_INDEX_BUF_BASE_HI, data);
-
-       base = lower_32_bits(adev->gfx.ngg.buf[NGG_POS].gpu_addr);
-       data = REG_SET_FIELD(0, WD_POS_BUF_BASE, BASE, base);
-       WREG32_SOC15(GC, 0, mmWD_POS_BUF_BASE, data);
-
-       base = upper_32_bits(adev->gfx.ngg.buf[NGG_POS].gpu_addr);
-       data = REG_SET_FIELD(0, WD_POS_BUF_BASE_HI, BASE_HI, base);
-       WREG32_SOC15(GC, 0, mmWD_POS_BUF_BASE_HI, data);
-
-       base = lower_32_bits(adev->gfx.ngg.buf[NGG_CNTL].gpu_addr);
-       data = REG_SET_FIELD(0, WD_CNTL_SB_BUF_BASE, BASE, base);
-       WREG32_SOC15(GC, 0, mmWD_CNTL_SB_BUF_BASE, data);
-
-       base = upper_32_bits(adev->gfx.ngg.buf[NGG_CNTL].gpu_addr);
-       data = REG_SET_FIELD(0, WD_CNTL_SB_BUF_BASE_HI, BASE_HI, base);
-       WREG32_SOC15(GC, 0, mmWD_CNTL_SB_BUF_BASE_HI, data);
-
-       /* Clear GDS reserved memory */
-       r = amdgpu_ring_alloc(ring, 17);
-       if (r) {
-               DRM_ERROR("amdgpu: NGG failed to lock ring %s (%d).\n",
-                         ring->name, r);
-               return r;
-       }
-
-       gfx_v9_0_write_data_to_reg(ring, 0, false,
-                                  SOC15_REG_OFFSET(GC, 0, mmGDS_VMID0_SIZE),
-                                  (adev->gds.gds_size +
-                                   adev->gfx.ngg.gds_reserve_size));
-
-       amdgpu_ring_write(ring, PACKET3(PACKET3_DMA_DATA, 5));
-       amdgpu_ring_write(ring, (PACKET3_DMA_DATA_CP_SYNC |
-                               PACKET3_DMA_DATA_DST_SEL(1) |
-                               PACKET3_DMA_DATA_SRC_SEL(2)));
-       amdgpu_ring_write(ring, 0);
-       amdgpu_ring_write(ring, 0);
-       amdgpu_ring_write(ring, adev->gfx.ngg.gds_reserve_addr);
-       amdgpu_ring_write(ring, 0);
-       amdgpu_ring_write(ring, PACKET3_DMA_DATA_CMD_RAW_WAIT |
-                               adev->gfx.ngg.gds_reserve_size);
-
-       gfx_v9_0_write_data_to_reg(ring, 0, false,
-                                  SOC15_REG_OFFSET(GC, 0, mmGDS_VMID0_SIZE), 0);
-
-       amdgpu_ring_commit(ring);
-
-       return 0;
-}
-
 static int gfx_v9_0_compute_ring_init(struct amdgpu_device *adev, int ring_id,
                                      int mec, int pipe, int queue)
 {
@@ -2307,10 +2136,6 @@ static int gfx_v9_0_sw_init(void *handle)
        if (r)
                return r;
 
-       r = gfx_v9_0_ngg_init(adev);
-       if (r)
-               return r;
-
        return 0;
 }
 
@@ -2320,19 +2145,7 @@ static int gfx_v9_0_sw_fini(void *handle)
        int i;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX) &&
-                       adev->gfx.ras_if) {
-               struct ras_common_if *ras_if = adev->gfx.ras_if;
-               struct ras_ih_if ih_info = {
-                       .head = *ras_if,
-               };
-
-               amdgpu_ras_debugfs_remove(adev, ras_if);
-               amdgpu_ras_sysfs_remove(adev, ras_if);
-               amdgpu_ras_interrupt_remove_handler(adev,  &ih_info);
-               amdgpu_ras_feature_enable(adev, ras_if, 0);
-               kfree(ras_if);
-       }
+       amdgpu_gfx_ras_fini(adev);
 
        for (i = 0; i < adev->gfx.num_gfx_rings; i++)
                amdgpu_ring_fini(&adev->gfx.gfx_ring[i]);
@@ -2344,7 +2157,6 @@ static int gfx_v9_0_sw_fini(void *handle)
        amdgpu_gfx_kiq_fini(adev);
 
        gfx_v9_0_mec_fini(adev);
-       gfx_v9_0_ngg_fini(adev);
        amdgpu_bo_unref(&adev->gfx.rlc.clear_state_obj);
        if (adev->asic_type == CHIP_RAVEN || adev->asic_type == CHIP_RENOIR) {
                amdgpu_bo_free_kernel(&adev->gfx.rlc.cp_table_obj,
@@ -3883,12 +3695,6 @@ static int gfx_v9_0_hw_init(void *handle)
        if (r)
                return r;
 
-       if (adev->asic_type != CHIP_ARCTURUS) {
-               r = gfx_v9_0_ngg_en(adev);
-               if (r)
-                       return r;
-       }
-
        return r;
 }
 
@@ -4184,6 +3990,7 @@ static const struct soc15_reg_entry sec_ded_counter_registers[] = {
    { SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT), 0, 1, 16},
    { SOC15_REG_ENTRY(GC, 0, mmTCP_ATC_EDC_GATCL1_CNT), 0, 4, 16},
    { SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT), 0, 4, 16},
+   { SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT_NEW), 0, 4, 16},
    { SOC15_REG_ENTRY(GC, 0, mmTD_EDC_CNT), 0, 4, 16},
    { SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2), 0, 4, 6},
    { SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT), 0, 4, 16},
@@ -4203,6 +4010,10 @@ static int gfx_v9_0_do_edc_gds_workarounds(struct amdgpu_device *adev)
        struct amdgpu_ring *ring = &adev->gfx.compute_ring[0];
        int i, r;
 
+       /* only support when RAS is enabled */
+       if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX))
+               return 0;
+
        r = amdgpu_ring_alloc(ring, 7);
        if (r) {
                DRM_ERROR("amdgpu: GDS workarounds failed to lock ring %s (%d).\n",
@@ -4393,33 +4204,14 @@ static int gfx_v9_0_early_init(void *handle)
        return 0;
 }
 
-static int gfx_v9_0_process_ras_data_cb(struct amdgpu_device *adev,
-               struct ras_err_data *err_data,
-               struct amdgpu_iv_entry *entry);
-
 static int gfx_v9_0_ecc_late_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ras_common_if **ras_if = &adev->gfx.ras_if;
-       struct ras_ih_if ih_info = {
-               .cb = gfx_v9_0_process_ras_data_cb,
-       };
-       struct ras_fs_if fs_info = {
-               .sysfs_name = "gfx_err_count",
-               .debugfs_name = "gfx_err_inject",
-       };
-       struct ras_common_if ras_block = {
-               .block = AMDGPU_RAS_BLOCK__GFX,
-               .type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
-               .sub_block_index = 0,
-               .name = "gfx",
-       };
        int r;
 
-       if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX)) {
-               amdgpu_ras_feature_enable_on_boot(adev, &ras_block, 0);
-               return 0;
-       }
+       r = amdgpu_gfx_ras_late_init(adev);
+       if (r)
+               return r;
 
        r = gfx_v9_0_do_edc_gds_workarounds(adev);
        if (r)
@@ -4430,72 +4222,7 @@ static int gfx_v9_0_ecc_late_init(void *handle)
        if (r)
                return r;
 
-       /* handle resume path. */
-       if (*ras_if) {
-               /* resend ras TA enable cmd during resume.
-                * prepare to handle failure.
-                */
-               ih_info.head = **ras_if;
-               r = amdgpu_ras_feature_enable_on_boot(adev, *ras_if, 1);
-               if (r) {
-                       if (r == -EAGAIN) {
-                               /* request a gpu reset. will run again. */
-                               amdgpu_ras_request_reset_on_boot(adev,
-                                               AMDGPU_RAS_BLOCK__GFX);
-                               return 0;
-                       }
-                       /* fail to enable ras, cleanup all. */
-                       goto irq;
-               }
-               /* enable successfully. continue. */
-               goto resume;
-       }
-
-       *ras_if = kmalloc(sizeof(**ras_if), GFP_KERNEL);
-       if (!*ras_if)
-               return -ENOMEM;
-
-       **ras_if = ras_block;
-
-       r = amdgpu_ras_feature_enable_on_boot(adev, *ras_if, 1);
-       if (r) {
-               if (r == -EAGAIN) {
-                       amdgpu_ras_request_reset_on_boot(adev,
-                                       AMDGPU_RAS_BLOCK__GFX);
-                       r = 0;
-               }
-               goto feature;
-       }
-
-       ih_info.head = **ras_if;
-       fs_info.head = **ras_if;
-
-       r = amdgpu_ras_interrupt_add_handler(adev, &ih_info);
-       if (r)
-               goto interrupt;
-
-       amdgpu_ras_debugfs_create(adev, &fs_info);
-
-       r = amdgpu_ras_sysfs_create(adev, &fs_info);
-       if (r)
-               goto sysfs;
-resume:
-       r = amdgpu_irq_get(adev, &adev->gfx.cp_ecc_error_irq, 0);
-       if (r)
-               goto irq;
-
        return 0;
-irq:
-       amdgpu_ras_sysfs_remove(adev, *ras_if);
-sysfs:
-       amdgpu_ras_debugfs_remove(adev, *ras_if);
-       amdgpu_ras_interrupt_remove_handler(adev, &ih_info);
-interrupt:
-       amdgpu_ras_feature_enable(adev, *ras_if, 0);
-feature:
-       kfree(*ras_if);
-       *ras_if = NULL;
-       return r;
 }
 
 static int gfx_v9_0_late_init(void *handle)
@@ -4560,16 +4287,14 @@ static void gfx_v9_0_update_gfx_cg_power_gating(struct amdgpu_device *adev,
 {
        amdgpu_gfx_rlc_enter_safe_mode(adev);
 
-       if (is_support_sw_smu(adev) && !enable)
-               smu_set_gfx_cgpg(&adev->smu, enable);
-
        if ((adev->pg_flags & AMD_PG_SUPPORT_GFX_PG) && enable) {
                gfx_v9_0_enable_gfx_cg_power_gating(adev, true);
                if (adev->pg_flags & AMD_PG_SUPPORT_GFX_PIPELINE)
                        gfx_v9_0_enable_gfx_pipeline_powergating(adev, true);
        } else {
                gfx_v9_0_enable_gfx_cg_power_gating(adev, false);
-               gfx_v9_0_enable_gfx_pipeline_powergating(adev, false);
+               if (adev->pg_flags & AMD_PG_SUPPORT_GFX_PIPELINE)
+                       gfx_v9_0_enable_gfx_pipeline_powergating(adev, false);
        }
 
        amdgpu_gfx_rlc_exit_safe_mode(adev);
@@ -4838,8 +4563,6 @@ static int gfx_v9_0_set_powergating_state(void *handle,
                        gfx_v9_0_enable_cp_power_gating(adev, false);
 
                /* update gfx cgpg state */
-               if (is_support_sw_smu(adev) && enable)
-                       smu_set_gfx_cgpg(&adev->smu, enable);
                gfx_v9_0_update_gfx_cg_power_gating(adev, enable);
 
                /* update mgcg state */
@@ -4970,7 +4693,7 @@ static void gfx_v9_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
 {
        struct amdgpu_device *adev = ring->adev;
        u32 ref_and_mask, reg_mem_engine;
-       const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio_funcs->hdp_flush_reg;
+       const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio.hdp_flush_reg;
 
        if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) {
                switch (ring->me) {
@@ -4990,8 +4713,8 @@ static void gfx_v9_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
        }
 
        gfx_v9_0_wait_reg_mem(ring, reg_mem_engine, 0, 1,
-                             adev->nbio_funcs->get_hdp_flush_req_offset(adev),
-                             adev->nbio_funcs->get_hdp_flush_done_offset(adev),
+                             adev->nbio.funcs->get_hdp_flush_req_offset(adev),
+                             adev->nbio.funcs->get_hdp_flush_done_offset(adev),
                              ref_and_mask, ref_and_mask, 0x20);
 }
 
@@ -5723,313 +5446,446 @@ static int gfx_v9_0_priv_inst_irq(struct amdgpu_device *adev,
        return 0;
 }
 
-static int gfx_v9_0_process_ras_data_cb(struct amdgpu_device *adev,
-               struct ras_err_data *err_data,
-               struct amdgpu_iv_entry *entry)
-{
-       /* TODO ue will trigger an interrupt. */
-       kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
-       if (adev->gfx.funcs->query_ras_error_count)
-               adev->gfx.funcs->query_ras_error_count(adev, err_data);
-       amdgpu_ras_reset_gpu(adev, 0);
-       return AMDGPU_RAS_SUCCESS;
-}
 
-static const struct {
-       const char *name;
-       uint32_t ip;
-       uint32_t inst;
-       uint32_t seg;
-       uint32_t reg_offset;
-       uint32_t per_se_instance;
-       int32_t num_instance;
-       uint32_t sec_count_mask;
-       uint32_t ded_count_mask;
-} gfx_ras_edc_regs[] = {
-       { "CPC_SCRATCH", SOC15_REG_ENTRY(GC, 0, mmCPC_EDC_SCRATCH_CNT), 0, 1,
-         REG_FIELD_MASK(CPC_EDC_SCRATCH_CNT, SEC_COUNT),
-         REG_FIELD_MASK(CPC_EDC_SCRATCH_CNT, DED_COUNT) },
-       { "CPC_UCODE", SOC15_REG_ENTRY(GC, 0, mmCPC_EDC_UCODE_CNT), 0, 1,
-         REG_FIELD_MASK(CPC_EDC_UCODE_CNT, SEC_COUNT),
-         REG_FIELD_MASK(CPC_EDC_UCODE_CNT, DED_COUNT) },
-       { "CPF_ROQ_ME1", SOC15_REG_ENTRY(GC, 0, mmCPF_EDC_ROQ_CNT), 0, 1,
-         REG_FIELD_MASK(CPF_EDC_ROQ_CNT, COUNT_ME1), 0 },
-       { "CPF_ROQ_ME2", SOC15_REG_ENTRY(GC, 0, mmCPF_EDC_ROQ_CNT), 0, 1,
-         REG_FIELD_MASK(CPF_EDC_ROQ_CNT, COUNT_ME2), 0 },
-       { "CPF_TAG", SOC15_REG_ENTRY(GC, 0, mmCPF_EDC_TAG_CNT), 0, 1,
-         REG_FIELD_MASK(CPF_EDC_TAG_CNT, SEC_COUNT),
-         REG_FIELD_MASK(CPF_EDC_TAG_CNT, DED_COUNT) },
-       { "CPG_DMA_ROQ", SOC15_REG_ENTRY(GC, 0, mmCPG_EDC_DMA_CNT), 0, 1,
-         REG_FIELD_MASK(CPG_EDC_DMA_CNT, ROQ_COUNT), 0 },
-       { "CPG_DMA_TAG", SOC15_REG_ENTRY(GC, 0, mmCPG_EDC_DMA_CNT), 0, 1,
-         REG_FIELD_MASK(CPG_EDC_DMA_CNT, TAG_SEC_COUNT),
-         REG_FIELD_MASK(CPG_EDC_DMA_CNT, TAG_DED_COUNT) },
-       { "CPG_TAG", SOC15_REG_ENTRY(GC, 0, mmCPG_EDC_TAG_CNT), 0, 1,
-         REG_FIELD_MASK(CPG_EDC_TAG_CNT, SEC_COUNT),
-         REG_FIELD_MASK(CPG_EDC_TAG_CNT, DED_COUNT) },
-       { "DC_CSINVOC", SOC15_REG_ENTRY(GC, 0, mmDC_EDC_CSINVOC_CNT), 0, 1,
-         REG_FIELD_MASK(DC_EDC_CSINVOC_CNT, COUNT_ME1), 0 },
-       { "DC_RESTORE", SOC15_REG_ENTRY(GC, 0, mmDC_EDC_RESTORE_CNT), 0, 1,
-         REG_FIELD_MASK(DC_EDC_RESTORE_CNT, COUNT_ME1), 0 },
-       { "DC_STATE", SOC15_REG_ENTRY(GC, 0, mmDC_EDC_STATE_CNT), 0, 1,
-         REG_FIELD_MASK(DC_EDC_STATE_CNT, COUNT_ME1), 0 },
-       { "GDS_MEM", SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_CNT), 0, 1,
-         REG_FIELD_MASK(GDS_EDC_CNT, GDS_MEM_SEC),
-         REG_FIELD_MASK(GDS_EDC_CNT, GDS_MEM_DED) },
-       { "GDS_INPUT_QUEUE", SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_CNT), 0, 1,
-         REG_FIELD_MASK(GDS_EDC_CNT, GDS_INPUT_QUEUE_SED), 0 },
+static const struct ras_gfx_subblock_reg ras_subblock_regs[] = {
+       { "CPC_SCRATCH", SOC15_REG_ENTRY(GC, 0, mmCPC_EDC_SCRATCH_CNT),
+         SOC15_REG_FIELD(CPC_EDC_SCRATCH_CNT, SEC_COUNT),
+         SOC15_REG_FIELD(CPC_EDC_SCRATCH_CNT, DED_COUNT)
+       },
+       { "CPC_UCODE", SOC15_REG_ENTRY(GC, 0, mmCPC_EDC_UCODE_CNT),
+         SOC15_REG_FIELD(CPC_EDC_UCODE_CNT, SEC_COUNT),
+         SOC15_REG_FIELD(CPC_EDC_UCODE_CNT, DED_COUNT)
+       },
+       { "CPF_ROQ_ME1", SOC15_REG_ENTRY(GC, 0, mmCPF_EDC_ROQ_CNT),
+         SOC15_REG_FIELD(CPF_EDC_ROQ_CNT, COUNT_ME1),
+         0, 0
+       },
+       { "CPF_ROQ_ME2", SOC15_REG_ENTRY(GC, 0, mmCPF_EDC_ROQ_CNT),
+         SOC15_REG_FIELD(CPF_EDC_ROQ_CNT, COUNT_ME2),
+         0, 0
+       },
+       { "CPF_TAG", SOC15_REG_ENTRY(GC, 0, mmCPF_EDC_TAG_CNT),
+         SOC15_REG_FIELD(CPF_EDC_TAG_CNT, SEC_COUNT),
+         SOC15_REG_FIELD(CPF_EDC_TAG_CNT, DED_COUNT)
+       },
+       { "CPG_DMA_ROQ", SOC15_REG_ENTRY(GC, 0, mmCPG_EDC_DMA_CNT),
+         SOC15_REG_FIELD(CPG_EDC_DMA_CNT, ROQ_COUNT),
+         0, 0
+       },
+       { "CPG_DMA_TAG", SOC15_REG_ENTRY(GC, 0, mmCPG_EDC_DMA_CNT),
+         SOC15_REG_FIELD(CPG_EDC_DMA_CNT, TAG_SEC_COUNT),
+         SOC15_REG_FIELD(CPG_EDC_DMA_CNT, TAG_DED_COUNT)
+       },
+       { "CPG_TAG", SOC15_REG_ENTRY(GC, 0, mmCPG_EDC_TAG_CNT),
+         SOC15_REG_FIELD(CPG_EDC_TAG_CNT, SEC_COUNT),
+         SOC15_REG_FIELD(CPG_EDC_TAG_CNT, DED_COUNT)
+       },
+       { "DC_CSINVOC", SOC15_REG_ENTRY(GC, 0, mmDC_EDC_CSINVOC_CNT),
+         SOC15_REG_FIELD(DC_EDC_CSINVOC_CNT, COUNT_ME1),
+         0, 0
+       },
+       { "DC_RESTORE", SOC15_REG_ENTRY(GC, 0, mmDC_EDC_RESTORE_CNT),
+         SOC15_REG_FIELD(DC_EDC_RESTORE_CNT, COUNT_ME1),
+         0, 0
+       },
+       { "DC_STATE", SOC15_REG_ENTRY(GC, 0, mmDC_EDC_STATE_CNT),
+         SOC15_REG_FIELD(DC_EDC_STATE_CNT, COUNT_ME1),
+         0, 0
+       },
+       { "GDS_MEM", SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_CNT),
+         SOC15_REG_FIELD(GDS_EDC_CNT, GDS_MEM_SEC),
+         SOC15_REG_FIELD(GDS_EDC_CNT, GDS_MEM_DED)
+       },
+       { "GDS_INPUT_QUEUE", SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_CNT),
+         SOC15_REG_FIELD(GDS_EDC_CNT, GDS_INPUT_QUEUE_SED),
+         0, 0
+       },
        { "GDS_ME0_CS_PIPE_MEM", SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_PHY_CNT),
-         0, 1, REG_FIELD_MASK(GDS_EDC_OA_PHY_CNT, ME0_CS_PIPE_MEM_SEC),
-         REG_FIELD_MASK(GDS_EDC_OA_PHY_CNT, ME0_CS_PIPE_MEM_DED) },
+         SOC15_REG_FIELD(GDS_EDC_OA_PHY_CNT, ME0_CS_PIPE_MEM_SEC),
+         SOC15_REG_FIELD(GDS_EDC_OA_PHY_CNT, ME0_CS_PIPE_MEM_DED)
+       },
        { "GDS_OA_PHY_PHY_CMD_RAM_MEM",
-         SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_PHY_CNT), 0, 1,
-         REG_FIELD_MASK(GDS_EDC_OA_PHY_CNT, PHY_CMD_RAM_MEM_SEC),
-         REG_FIELD_MASK(GDS_EDC_OA_PHY_CNT, PHY_CMD_RAM_MEM_DED) },
+         SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_PHY_CNT),
+         SOC15_REG_FIELD(GDS_EDC_OA_PHY_CNT, PHY_CMD_RAM_MEM_SEC),
+         SOC15_REG_FIELD(GDS_EDC_OA_PHY_CNT, PHY_CMD_RAM_MEM_DED)
+       },
        { "GDS_OA_PHY_PHY_DATA_RAM_MEM",
-         SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_PHY_CNT), 0, 1,
-         REG_FIELD_MASK(GDS_EDC_OA_PHY_CNT, PHY_DATA_RAM_MEM_SED), 0 },
+         SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_PHY_CNT),
+         SOC15_REG_FIELD(GDS_EDC_OA_PHY_CNT, PHY_DATA_RAM_MEM_SED),
+         0, 0
+       },
        { "GDS_OA_PIPE_ME1_PIPE0_PIPE_MEM",
-         SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_PIPE_CNT), 0, 1,
-         REG_FIELD_MASK(GDS_EDC_OA_PIPE_CNT, ME1_PIPE0_PIPE_MEM_SEC),
-         REG_FIELD_MASK(GDS_EDC_OA_PIPE_CNT, ME1_PIPE0_PIPE_MEM_DED) },
+         SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_PIPE_CNT),
+         SOC15_REG_FIELD(GDS_EDC_OA_PIPE_CNT, ME1_PIPE0_PIPE_MEM_SEC),
+         SOC15_REG_FIELD(GDS_EDC_OA_PIPE_CNT, ME1_PIPE0_PIPE_MEM_DED)
+       },
        { "GDS_OA_PIPE_ME1_PIPE1_PIPE_MEM",
-         SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_PIPE_CNT), 0, 1,
-         REG_FIELD_MASK(GDS_EDC_OA_PIPE_CNT, ME1_PIPE1_PIPE_MEM_SEC),
-         REG_FIELD_MASK(GDS_EDC_OA_PIPE_CNT, ME1_PIPE1_PIPE_MEM_DED) },
+         SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_PIPE_CNT),
+         SOC15_REG_FIELD(GDS_EDC_OA_PIPE_CNT, ME1_PIPE1_PIPE_MEM_SEC),
+         SOC15_REG_FIELD(GDS_EDC_OA_PIPE_CNT, ME1_PIPE1_PIPE_MEM_DED)
+       },
        { "GDS_OA_PIPE_ME1_PIPE2_PIPE_MEM",
-         SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_PIPE_CNT), 0, 1,
-         REG_FIELD_MASK(GDS_EDC_OA_PIPE_CNT, ME1_PIPE2_PIPE_MEM_SEC),
-         REG_FIELD_MASK(GDS_EDC_OA_PIPE_CNT, ME1_PIPE2_PIPE_MEM_DED) },
+         SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_PIPE_CNT),
+         SOC15_REG_FIELD(GDS_EDC_OA_PIPE_CNT, ME1_PIPE2_PIPE_MEM_SEC),
+         SOC15_REG_FIELD(GDS_EDC_OA_PIPE_CNT, ME1_PIPE2_PIPE_MEM_DED)
+       },
        { "GDS_OA_PIPE_ME1_PIPE3_PIPE_MEM",
-         SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_PIPE_CNT), 0, 1,
-         REG_FIELD_MASK(GDS_EDC_OA_PIPE_CNT, ME1_PIPE3_PIPE_MEM_SEC),
-         REG_FIELD_MASK(GDS_EDC_OA_PIPE_CNT, ME1_PIPE3_PIPE_MEM_DED) },
-       { "SPI_SR_MEM", SOC15_REG_ENTRY(GC, 0, mmSPI_EDC_CNT), 1, 1,
-         REG_FIELD_MASK(SPI_EDC_CNT, SPI_SR_MEM_SED_COUNT), 0 },
-       { "TA_FS_DFIFO", SOC15_REG_ENTRY(GC, 0, mmTA_EDC_CNT), 1, 16,
-         REG_FIELD_MASK(TA_EDC_CNT, TA_FS_DFIFO_SEC_COUNT),
-         REG_FIELD_MASK(TA_EDC_CNT, TA_FS_DFIFO_DED_COUNT) },
-       { "TA_FS_AFIFO", SOC15_REG_ENTRY(GC, 0, mmTA_EDC_CNT), 1, 16,
-         REG_FIELD_MASK(TA_EDC_CNT, TA_FS_AFIFO_SED_COUNT), 0 },
-       { "TA_FL_LFIFO", SOC15_REG_ENTRY(GC, 0, mmTA_EDC_CNT), 1, 16,
-         REG_FIELD_MASK(TA_EDC_CNT, TA_FL_LFIFO_SED_COUNT), 0 },
-       { "TA_FX_LFIFO", SOC15_REG_ENTRY(GC, 0, mmTA_EDC_CNT), 1, 16,
-         REG_FIELD_MASK(TA_EDC_CNT, TA_FX_LFIFO_SED_COUNT), 0 },
-       { "TA_FS_CFIFO", SOC15_REG_ENTRY(GC, 0, mmTA_EDC_CNT), 1, 16,
-         REG_FIELD_MASK(TA_EDC_CNT, TA_FS_CFIFO_SED_COUNT), 0 },
-       { "TCA_HOLE_FIFO", SOC15_REG_ENTRY(GC, 0, mmTCA_EDC_CNT), 0, 2,
-         REG_FIELD_MASK(TCA_EDC_CNT, HOLE_FIFO_SED_COUNT), 0 },
-       { "TCA_REQ_FIFO", SOC15_REG_ENTRY(GC, 0, mmTCA_EDC_CNT), 0, 2,
-         REG_FIELD_MASK(TCA_EDC_CNT, REQ_FIFO_SED_COUNT), 0 },
-       { "TCC_CACHE_DATA", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT), 0, 16,
-         REG_FIELD_MASK(TCC_EDC_CNT, CACHE_DATA_SEC_COUNT),
-         REG_FIELD_MASK(TCC_EDC_CNT, CACHE_DATA_DED_COUNT) },
-       { "TCC_CACHE_DIRTY", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT), 0, 16,
-         REG_FIELD_MASK(TCC_EDC_CNT, CACHE_DIRTY_SEC_COUNT),
-         REG_FIELD_MASK(TCC_EDC_CNT, CACHE_DIRTY_DED_COUNT) },
-       { "TCC_HIGH_RATE_TAG", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT), 0, 16,
-         REG_FIELD_MASK(TCC_EDC_CNT, HIGH_RATE_TAG_SEC_COUNT),
-         REG_FIELD_MASK(TCC_EDC_CNT, HIGH_RATE_TAG_DED_COUNT) },
-       { "TCC_LOW_RATE_TAG", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT), 0, 16,
-         REG_FIELD_MASK(TCC_EDC_CNT, LOW_RATE_TAG_SEC_COUNT),
-         REG_FIELD_MASK(TCC_EDC_CNT, LOW_RATE_TAG_DED_COUNT) },
-       { "TCC_SRC_FIFO", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT), 0, 16,
-         REG_FIELD_MASK(TCC_EDC_CNT, SRC_FIFO_SEC_COUNT),
-         REG_FIELD_MASK(TCC_EDC_CNT, SRC_FIFO_DED_COUNT) },
-       { "TCC_IN_USE_DEC", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT), 0, 16,
-         REG_FIELD_MASK(TCC_EDC_CNT, IN_USE_DEC_SED_COUNT), 0 },
-       { "TCC_IN_USE_TRANSFER", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT), 0, 16,
-         REG_FIELD_MASK(TCC_EDC_CNT, IN_USE_TRANSFER_SED_COUNT), 0 },
-       { "TCC_LATENCY_FIFO", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT), 0, 16,
-         REG_FIELD_MASK(TCC_EDC_CNT, LATENCY_FIFO_SED_COUNT), 0 },
-       { "TCC_RETURN_DATA", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT), 0, 16,
-         REG_FIELD_MASK(TCC_EDC_CNT, RETURN_DATA_SED_COUNT), 0 },
-       { "TCC_RETURN_CONTROL", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT), 0, 16,
-         REG_FIELD_MASK(TCC_EDC_CNT, RETURN_CONTROL_SED_COUNT), 0 },
-       { "TCC_UC_ATOMIC_FIFO", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT), 0, 16,
-         REG_FIELD_MASK(TCC_EDC_CNT, UC_ATOMIC_FIFO_SED_COUNT), 0 },
-       { "TCC_WRITE_RETURN", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT2), 0, 16,
-         REG_FIELD_MASK(TCC_EDC_CNT2, WRITE_RETURN_SED_COUNT), 0 },
-       { "TCC_WRITE_CACHE_READ", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT2), 0, 16,
-         REG_FIELD_MASK(TCC_EDC_CNT2, WRITE_CACHE_READ_SED_COUNT), 0 },
-       { "TCC_SRC_FIFO_NEXT_RAM", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT2), 0,
-         16, REG_FIELD_MASK(TCC_EDC_CNT2, SRC_FIFO_NEXT_RAM_SED_COUNT), 0 },
+         SOC15_REG_ENTRY(GC, 0, mmGDS_EDC_OA_PIPE_CNT),
+         SOC15_REG_FIELD(GDS_EDC_OA_PIPE_CNT, ME1_PIPE3_PIPE_MEM_SEC),
+         SOC15_REG_FIELD(GDS_EDC_OA_PIPE_CNT, ME1_PIPE3_PIPE_MEM_DED)
+       },
+       { "SPI_SR_MEM", SOC15_REG_ENTRY(GC, 0, mmSPI_EDC_CNT),
+         SOC15_REG_FIELD(SPI_EDC_CNT, SPI_SR_MEM_SED_COUNT),
+         0, 0
+       },
+       { "TA_FS_DFIFO", SOC15_REG_ENTRY(GC, 0, mmTA_EDC_CNT),
+         SOC15_REG_FIELD(TA_EDC_CNT, TA_FS_DFIFO_SEC_COUNT),
+         SOC15_REG_FIELD(TA_EDC_CNT, TA_FS_DFIFO_DED_COUNT)
+       },
+       { "TA_FS_AFIFO", SOC15_REG_ENTRY(GC, 0, mmTA_EDC_CNT),
+         SOC15_REG_FIELD(TA_EDC_CNT, TA_FS_AFIFO_SED_COUNT),
+         0, 0
+       },
+       { "TA_FL_LFIFO", SOC15_REG_ENTRY(GC, 0, mmTA_EDC_CNT),
+         SOC15_REG_FIELD(TA_EDC_CNT, TA_FL_LFIFO_SED_COUNT),
+         0, 0
+       },
+       { "TA_FX_LFIFO", SOC15_REG_ENTRY(GC, 0, mmTA_EDC_CNT),
+         SOC15_REG_FIELD(TA_EDC_CNT, TA_FX_LFIFO_SED_COUNT),
+         0, 0
+       },
+       { "TA_FS_CFIFO", SOC15_REG_ENTRY(GC, 0, mmTA_EDC_CNT),
+         SOC15_REG_FIELD(TA_EDC_CNT, TA_FS_CFIFO_SED_COUNT),
+         0, 0
+       },
+       { "TCA_HOLE_FIFO", SOC15_REG_ENTRY(GC, 0, mmTCA_EDC_CNT),
+         SOC15_REG_FIELD(TCA_EDC_CNT, HOLE_FIFO_SED_COUNT),
+         0, 0
+       },
+       { "TCA_REQ_FIFO", SOC15_REG_ENTRY(GC, 0, mmTCA_EDC_CNT),
+         SOC15_REG_FIELD(TCA_EDC_CNT, REQ_FIFO_SED_COUNT),
+         0, 0
+       },
+       { "TCC_CACHE_DATA", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT),
+         SOC15_REG_FIELD(TCC_EDC_CNT, CACHE_DATA_SEC_COUNT),
+         SOC15_REG_FIELD(TCC_EDC_CNT, CACHE_DATA_DED_COUNT)
+       },
+       { "TCC_CACHE_DIRTY", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT),
+         SOC15_REG_FIELD(TCC_EDC_CNT, CACHE_DIRTY_SEC_COUNT),
+         SOC15_REG_FIELD(TCC_EDC_CNT, CACHE_DIRTY_DED_COUNT)
+       },
+       { "TCC_HIGH_RATE_TAG", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT),
+         SOC15_REG_FIELD(TCC_EDC_CNT, HIGH_RATE_TAG_SEC_COUNT),
+         SOC15_REG_FIELD(TCC_EDC_CNT, HIGH_RATE_TAG_DED_COUNT)
+       },
+       { "TCC_LOW_RATE_TAG", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT),
+         SOC15_REG_FIELD(TCC_EDC_CNT, LOW_RATE_TAG_SEC_COUNT),
+         SOC15_REG_FIELD(TCC_EDC_CNT, LOW_RATE_TAG_DED_COUNT)
+       },
+       { "TCC_SRC_FIFO", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT),
+         SOC15_REG_FIELD(TCC_EDC_CNT, SRC_FIFO_SEC_COUNT),
+         SOC15_REG_FIELD(TCC_EDC_CNT, SRC_FIFO_DED_COUNT)
+       },
+       { "TCC_IN_USE_DEC", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT),
+         SOC15_REG_FIELD(TCC_EDC_CNT, IN_USE_DEC_SED_COUNT),
+         0, 0
+       },
+       { "TCC_IN_USE_TRANSFER", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT),
+         SOC15_REG_FIELD(TCC_EDC_CNT, IN_USE_TRANSFER_SED_COUNT),
+         0, 0
+       },
+       { "TCC_LATENCY_FIFO", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT),
+         SOC15_REG_FIELD(TCC_EDC_CNT, LATENCY_FIFO_SED_COUNT),
+         0, 0
+       },
+       { "TCC_RETURN_DATA", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT),
+         SOC15_REG_FIELD(TCC_EDC_CNT, RETURN_DATA_SED_COUNT),
+         0, 0
+       },
+       { "TCC_RETURN_CONTROL", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT),
+         SOC15_REG_FIELD(TCC_EDC_CNT, RETURN_CONTROL_SED_COUNT),
+         0, 0
+       },
+       { "TCC_UC_ATOMIC_FIFO", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT),
+         SOC15_REG_FIELD(TCC_EDC_CNT, UC_ATOMIC_FIFO_SED_COUNT),
+         0, 0
+       },
+       { "TCC_WRITE_RETURN", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT2),
+         SOC15_REG_FIELD(TCC_EDC_CNT2, WRITE_RETURN_SED_COUNT),
+         0, 0
+       },
+       { "TCC_WRITE_CACHE_READ", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT2),
+         SOC15_REG_FIELD(TCC_EDC_CNT2, WRITE_CACHE_READ_SED_COUNT),
+         0, 0
+       },
+       { "TCC_SRC_FIFO_NEXT_RAM", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT2),
+         SOC15_REG_FIELD(TCC_EDC_CNT2, SRC_FIFO_NEXT_RAM_SED_COUNT),
+         0, 0
+       },
        { "TCC_LATENCY_FIFO_NEXT_RAM", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT2),
-         0, 16, REG_FIELD_MASK(TCC_EDC_CNT2, LATENCY_FIFO_NEXT_RAM_SED_COUNT),
-         0 },
-       { "TCC_CACHE_TAG_PROBE_FIFO", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT2), 0,
-         16, REG_FIELD_MASK(TCC_EDC_CNT2, CACHE_TAG_PROBE_FIFO_SED_COUNT), 0 },
+         SOC15_REG_FIELD(TCC_EDC_CNT2, LATENCY_FIFO_NEXT_RAM_SED_COUNT),
+         0, 0
+       },
+       { "TCC_CACHE_TAG_PROBE_FIFO", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT2),
+         SOC15_REG_FIELD(TCC_EDC_CNT2, CACHE_TAG_PROBE_FIFO_SED_COUNT),
+         0, 0
+       },
        { "TCC_WRRET_TAG_WRITE_RETURN", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT2),
-         0, 16, REG_FIELD_MASK(TCC_EDC_CNT2, WRRET_TAG_WRITE_RETURN_SED_COUNT),
-         0 },
-       { "TCC_ATOMIC_RETURN_BUFFER", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT2), 0,
-         16, REG_FIELD_MASK(TCC_EDC_CNT2, ATOMIC_RETURN_BUFFER_SED_COUNT), 0 },
-       { "TCI_WRITE_RAM", SOC15_REG_ENTRY(GC, 0, mmTCI_EDC_CNT), 0, 72,
-         REG_FIELD_MASK(TCI_EDC_CNT, WRITE_RAM_SED_COUNT), 0 },
-       { "TCP_CACHE_RAM", SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT_NEW), 1, 16,
-         REG_FIELD_MASK(TCP_EDC_CNT_NEW, CACHE_RAM_SEC_COUNT),
-         REG_FIELD_MASK(TCP_EDC_CNT_NEW, CACHE_RAM_DED_COUNT) },
-       { "TCP_LFIFO_RAM", SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT_NEW), 1, 16,
-         REG_FIELD_MASK(TCP_EDC_CNT_NEW, LFIFO_RAM_SEC_COUNT),
-         REG_FIELD_MASK(TCP_EDC_CNT_NEW, LFIFO_RAM_DED_COUNT) },
-       { "TCP_CMD_FIFO", SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT_NEW), 1, 16,
-         REG_FIELD_MASK(TCP_EDC_CNT_NEW, CMD_FIFO_SED_COUNT), 0 },
-       { "TCP_VM_FIFO", SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT_NEW), 1, 16,
-         REG_FIELD_MASK(TCP_EDC_CNT_NEW, VM_FIFO_SEC_COUNT), 0 },
-       { "TCP_DB_RAM", SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT_NEW), 1, 16,
-         REG_FIELD_MASK(TCP_EDC_CNT_NEW, DB_RAM_SED_COUNT), 0 },
-       { "TCP_UTCL1_LFIFO0", SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT_NEW), 1, 16,
-         REG_FIELD_MASK(TCP_EDC_CNT_NEW, UTCL1_LFIFO0_SEC_COUNT),
-         REG_FIELD_MASK(TCP_EDC_CNT_NEW, UTCL1_LFIFO0_DED_COUNT) },
-       { "TCP_UTCL1_LFIFO1", SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT_NEW), 1, 16,
-         REG_FIELD_MASK(TCP_EDC_CNT_NEW, UTCL1_LFIFO1_SEC_COUNT),
-         REG_FIELD_MASK(TCP_EDC_CNT_NEW, UTCL1_LFIFO1_DED_COUNT) },
-       { "TD_SS_FIFO_LO", SOC15_REG_ENTRY(GC, 0, mmTD_EDC_CNT), 1, 16,
-         REG_FIELD_MASK(TD_EDC_CNT, SS_FIFO_LO_SEC_COUNT),
-         REG_FIELD_MASK(TD_EDC_CNT, SS_FIFO_LO_DED_COUNT) },
-       { "TD_SS_FIFO_HI", SOC15_REG_ENTRY(GC, 0, mmTD_EDC_CNT), 1, 16,
-         REG_FIELD_MASK(TD_EDC_CNT, SS_FIFO_HI_SEC_COUNT),
-         REG_FIELD_MASK(TD_EDC_CNT, SS_FIFO_HI_DED_COUNT) },
-       { "TD_CS_FIFO", SOC15_REG_ENTRY(GC, 0, mmTD_EDC_CNT), 1, 16,
-         REG_FIELD_MASK(TD_EDC_CNT, CS_FIFO_SED_COUNT), 0 },
-       { "SQ_LDS_D", SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT), 1, 16,
-         REG_FIELD_MASK(SQ_EDC_CNT, LDS_D_SEC_COUNT),
-         REG_FIELD_MASK(SQ_EDC_CNT, LDS_D_DED_COUNT) },
-       { "SQ_LDS_I", SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT), 1, 16,
-         REG_FIELD_MASK(SQ_EDC_CNT, LDS_I_SEC_COUNT),
-         REG_FIELD_MASK(SQ_EDC_CNT, LDS_I_DED_COUNT) },
-       { "SQ_SGPR", SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT), 1, 16,
-         REG_FIELD_MASK(SQ_EDC_CNT, SGPR_SEC_COUNT),
-         REG_FIELD_MASK(SQ_EDC_CNT, SGPR_DED_COUNT) },
-       { "SQ_VGPR0", SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT), 1, 16,
-         REG_FIELD_MASK(SQ_EDC_CNT, VGPR0_SEC_COUNT),
-         REG_FIELD_MASK(SQ_EDC_CNT, VGPR0_DED_COUNT) },
-       { "SQ_VGPR1", SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT), 1, 16,
-         REG_FIELD_MASK(SQ_EDC_CNT, VGPR1_SEC_COUNT),
-         REG_FIELD_MASK(SQ_EDC_CNT, VGPR1_DED_COUNT) },
-       { "SQ_VGPR2", SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT), 1, 16,
-         REG_FIELD_MASK(SQ_EDC_CNT, VGPR2_SEC_COUNT),
-         REG_FIELD_MASK(SQ_EDC_CNT, VGPR2_DED_COUNT) },
-       { "SQ_VGPR3", SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT), 1, 16,
-         REG_FIELD_MASK(SQ_EDC_CNT, VGPR3_SEC_COUNT),
-         REG_FIELD_MASK(SQ_EDC_CNT, VGPR3_DED_COUNT) },
+         SOC15_REG_FIELD(TCC_EDC_CNT2, WRRET_TAG_WRITE_RETURN_SED_COUNT),
+         0, 0
+       },
+       { "TCC_ATOMIC_RETURN_BUFFER", SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT2),
+         SOC15_REG_FIELD(TCC_EDC_CNT2, ATOMIC_RETURN_BUFFER_SED_COUNT),
+         0, 0
+       },
+       { "TCI_WRITE_RAM", SOC15_REG_ENTRY(GC, 0, mmTCI_EDC_CNT),
+         SOC15_REG_FIELD(TCI_EDC_CNT, WRITE_RAM_SED_COUNT),
+         0, 0
+       },
+       { "TCP_CACHE_RAM", SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT_NEW),
+         SOC15_REG_FIELD(TCP_EDC_CNT_NEW, CACHE_RAM_SEC_COUNT),
+         SOC15_REG_FIELD(TCP_EDC_CNT_NEW, CACHE_RAM_DED_COUNT)
+       },
+       { "TCP_LFIFO_RAM", SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT_NEW),
+         SOC15_REG_FIELD(TCP_EDC_CNT_NEW, LFIFO_RAM_SEC_COUNT),
+         SOC15_REG_FIELD(TCP_EDC_CNT_NEW, LFIFO_RAM_DED_COUNT)
+       },
+       { "TCP_CMD_FIFO", SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT_NEW),
+         SOC15_REG_FIELD(TCP_EDC_CNT_NEW, CMD_FIFO_SED_COUNT),
+         0, 0
+       },
+       { "TCP_VM_FIFO", SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT_NEW),
+         SOC15_REG_FIELD(TCP_EDC_CNT_NEW, VM_FIFO_SEC_COUNT),
+         0, 0
+       },
+       { "TCP_DB_RAM", SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT_NEW),
+         SOC15_REG_FIELD(TCP_EDC_CNT_NEW, DB_RAM_SED_COUNT),
+         0, 0
+       },
+       { "TCP_UTCL1_LFIFO0", SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT_NEW),
+         SOC15_REG_FIELD(TCP_EDC_CNT_NEW, UTCL1_LFIFO0_SEC_COUNT),
+         SOC15_REG_FIELD(TCP_EDC_CNT_NEW, UTCL1_LFIFO0_DED_COUNT)
+       },
+       { "TCP_UTCL1_LFIFO1", SOC15_REG_ENTRY(GC, 0, mmTCP_EDC_CNT_NEW),
+         SOC15_REG_FIELD(TCP_EDC_CNT_NEW, UTCL1_LFIFO1_SEC_COUNT),
+         SOC15_REG_FIELD(TCP_EDC_CNT_NEW, UTCL1_LFIFO1_DED_COUNT)
+       },
+       { "TD_SS_FIFO_LO", SOC15_REG_ENTRY(GC, 0, mmTD_EDC_CNT),
+         SOC15_REG_FIELD(TD_EDC_CNT, SS_FIFO_LO_SEC_COUNT),
+         SOC15_REG_FIELD(TD_EDC_CNT, SS_FIFO_LO_DED_COUNT)
+       },
+       { "TD_SS_FIFO_HI", SOC15_REG_ENTRY(GC, 0, mmTD_EDC_CNT),
+         SOC15_REG_FIELD(TD_EDC_CNT, SS_FIFO_HI_SEC_COUNT),
+         SOC15_REG_FIELD(TD_EDC_CNT, SS_FIFO_HI_DED_COUNT)
+       },
+       { "TD_CS_FIFO", SOC15_REG_ENTRY(GC, 0, mmTD_EDC_CNT),
+         SOC15_REG_FIELD(TD_EDC_CNT, CS_FIFO_SED_COUNT),
+         0, 0
+       },
+       { "SQ_LDS_D", SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT),
+         SOC15_REG_FIELD(SQ_EDC_CNT, LDS_D_SEC_COUNT),
+         SOC15_REG_FIELD(SQ_EDC_CNT, LDS_D_DED_COUNT)
+       },
+       { "SQ_LDS_I", SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT),
+         SOC15_REG_FIELD(SQ_EDC_CNT, LDS_I_SEC_COUNT),
+         SOC15_REG_FIELD(SQ_EDC_CNT, LDS_I_DED_COUNT)
+       },
+       { "SQ_SGPR", SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT),
+         SOC15_REG_FIELD(SQ_EDC_CNT, SGPR_SEC_COUNT),
+         SOC15_REG_FIELD(SQ_EDC_CNT, SGPR_DED_COUNT)
+       },
+       { "SQ_VGPR0", SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT),
+         SOC15_REG_FIELD(SQ_EDC_CNT, VGPR0_SEC_COUNT),
+         SOC15_REG_FIELD(SQ_EDC_CNT, VGPR0_DED_COUNT)
+       },
+       { "SQ_VGPR1", SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT),
+         SOC15_REG_FIELD(SQ_EDC_CNT, VGPR1_SEC_COUNT),
+         SOC15_REG_FIELD(SQ_EDC_CNT, VGPR1_DED_COUNT)
+       },
+       { "SQ_VGPR2", SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT),
+         SOC15_REG_FIELD(SQ_EDC_CNT, VGPR2_SEC_COUNT),
+         SOC15_REG_FIELD(SQ_EDC_CNT, VGPR2_DED_COUNT)
+       },
+       { "SQ_VGPR3", SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT),
+         SOC15_REG_FIELD(SQ_EDC_CNT, VGPR3_SEC_COUNT),
+         SOC15_REG_FIELD(SQ_EDC_CNT, VGPR3_DED_COUNT)
+       },
        { "SQC_DATA_CU0_WRITE_DATA_BUF", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT),
-         1, 6, REG_FIELD_MASK(SQC_EDC_CNT, DATA_CU0_WRITE_DATA_BUF_SEC_COUNT),
-         REG_FIELD_MASK(SQC_EDC_CNT, DATA_CU0_WRITE_DATA_BUF_DED_COUNT) },
-       { "SQC_DATA_CU0_UTCL1_LFIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT), 1,
-         6, REG_FIELD_MASK(SQC_EDC_CNT, DATA_CU0_UTCL1_LFIFO_SEC_COUNT),
-         REG_FIELD_MASK(SQC_EDC_CNT, DATA_CU0_UTCL1_LFIFO_DED_COUNT) },
+         SOC15_REG_FIELD(SQC_EDC_CNT, DATA_CU0_WRITE_DATA_BUF_SEC_COUNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT, DATA_CU0_WRITE_DATA_BUF_DED_COUNT)
+       },
+       { "SQC_DATA_CU0_UTCL1_LFIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT, DATA_CU0_UTCL1_LFIFO_SEC_COUNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT, DATA_CU0_UTCL1_LFIFO_DED_COUNT)
+       },
        { "SQC_DATA_CU1_WRITE_DATA_BUF", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT),
-         1, 6, REG_FIELD_MASK(SQC_EDC_CNT, DATA_CU1_WRITE_DATA_BUF_SEC_COUNT),
-         REG_FIELD_MASK(SQC_EDC_CNT, DATA_CU1_WRITE_DATA_BUF_DED_COUNT) },
-       { "SQC_DATA_CU1_UTCL1_LFIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT), 1,
-         6, REG_FIELD_MASK(SQC_EDC_CNT, DATA_CU1_UTCL1_LFIFO_SEC_COUNT),
-         REG_FIELD_MASK(SQC_EDC_CNT, DATA_CU1_UTCL1_LFIFO_DED_COUNT) },
+         SOC15_REG_FIELD(SQC_EDC_CNT, DATA_CU1_WRITE_DATA_BUF_SEC_COUNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT, DATA_CU1_WRITE_DATA_BUF_DED_COUNT)
+       },
+       { "SQC_DATA_CU1_UTCL1_LFIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT, DATA_CU1_UTCL1_LFIFO_SEC_COUNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT, DATA_CU1_UTCL1_LFIFO_DED_COUNT)
+       },
        { "SQC_DATA_CU2_WRITE_DATA_BUF", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT),
-         1, 6, REG_FIELD_MASK(SQC_EDC_CNT, DATA_CU2_WRITE_DATA_BUF_SEC_COUNT),
-         REG_FIELD_MASK(SQC_EDC_CNT, DATA_CU2_WRITE_DATA_BUF_DED_COUNT) },
-       { "SQC_DATA_CU2_UTCL1_LFIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT), 1,
-         6, REG_FIELD_MASK(SQC_EDC_CNT, DATA_CU2_UTCL1_LFIFO_SEC_COUNT),
-         REG_FIELD_MASK(SQC_EDC_CNT, DATA_CU2_UTCL1_LFIFO_DED_COUNT) },
-       { "SQC_INST_BANKA_TAG_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2), 1,
-         6, REG_FIELD_MASK(SQC_EDC_CNT2, INST_BANKA_TAG_RAM_SEC_COUNT),
-         REG_FIELD_MASK(SQC_EDC_CNT2, INST_BANKA_TAG_RAM_DED_COUNT) },
-       { "SQC_INST_BANKA_BANK_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2), 1,
-         6, REG_FIELD_MASK(SQC_EDC_CNT2, INST_BANKA_BANK_RAM_SEC_COUNT),
-         REG_FIELD_MASK(SQC_EDC_CNT2, INST_BANKA_BANK_RAM_DED_COUNT) },
-       { "SQC_DATA_BANKA_TAG_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2), 1,
-         6, REG_FIELD_MASK(SQC_EDC_CNT2, DATA_BANKA_TAG_RAM_SEC_COUNT),
-         REG_FIELD_MASK(SQC_EDC_CNT2, DATA_BANKA_TAG_RAM_DED_COUNT) },
-       { "SQC_DATA_BANKA_BANK_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2), 1,
-         6, REG_FIELD_MASK(SQC_EDC_CNT2, DATA_BANKA_BANK_RAM_SEC_COUNT),
-         REG_FIELD_MASK(SQC_EDC_CNT2, DATA_BANKA_BANK_RAM_DED_COUNT) },
-       { "SQC_INST_BANKA_UTCL1_MISS_FIFO",
-         SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2), 1, 6,
-         REG_FIELD_MASK(SQC_EDC_CNT2, INST_BANKA_UTCL1_MISS_FIFO_SED_COUNT),
-         0 },
-       { "SQC_INST_BANKA_MISS_FIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2), 1,
-         6, REG_FIELD_MASK(SQC_EDC_CNT2, INST_BANKA_MISS_FIFO_SED_COUNT), 0 },
-       { "SQC_DATA_BANKA_HIT_FIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2), 1,
-         6, REG_FIELD_MASK(SQC_EDC_CNT2, DATA_BANKA_HIT_FIFO_SED_COUNT), 0 },
-       { "SQC_DATA_BANKA_MISS_FIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2), 1,
-         6, REG_FIELD_MASK(SQC_EDC_CNT2, DATA_BANKA_MISS_FIFO_SED_COUNT), 0 },
-       { "SQC_DATA_BANKA_DIRTY_BIT_RAM",
-         SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2), 1, 6,
-         REG_FIELD_MASK(SQC_EDC_CNT2, DATA_BANKA_DIRTY_BIT_RAM_SED_COUNT), 0 },
-       { "SQC_INST_UTCL1_LFIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2), 1, 6,
-         REG_FIELD_MASK(SQC_EDC_CNT2, INST_UTCL1_LFIFO_SEC_COUNT),
-         REG_FIELD_MASK(SQC_EDC_CNT2, INST_UTCL1_LFIFO_DED_COUNT) },
-       { "SQC_INST_BANKB_TAG_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3), 1,
-         6, REG_FIELD_MASK(SQC_EDC_CNT3, INST_BANKB_TAG_RAM_SEC_COUNT),
-         REG_FIELD_MASK(SQC_EDC_CNT3, INST_BANKB_TAG_RAM_DED_COUNT) },
-       { "SQC_INST_BANKB_BANK_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3), 1,
-         6, REG_FIELD_MASK(SQC_EDC_CNT3, INST_BANKB_BANK_RAM_SEC_COUNT),
-         REG_FIELD_MASK(SQC_EDC_CNT3, INST_BANKB_BANK_RAM_DED_COUNT) },
-       { "SQC_DATA_BANKB_TAG_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3), 1,
-         6, REG_FIELD_MASK(SQC_EDC_CNT3, DATA_BANKB_TAG_RAM_SEC_COUNT),
-         REG_FIELD_MASK(SQC_EDC_CNT3, DATA_BANKB_TAG_RAM_DED_COUNT) },
-       { "SQC_DATA_BANKB_BANK_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3), 1,
-         6, REG_FIELD_MASK(SQC_EDC_CNT3, DATA_BANKB_BANK_RAM_SEC_COUNT),
-         REG_FIELD_MASK(SQC_EDC_CNT3, DATA_BANKB_BANK_RAM_DED_COUNT) },
-       { "SQC_INST_BANKB_UTCL1_MISS_FIFO",
-         SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3), 1, 6,
-         REG_FIELD_MASK(SQC_EDC_CNT3, INST_BANKB_UTCL1_MISS_FIFO_SED_COUNT),
-         0 },
-       { "SQC_INST_BANKB_MISS_FIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3), 1,
-         6, REG_FIELD_MASK(SQC_EDC_CNT3, INST_BANKB_MISS_FIFO_SED_COUNT), 0 },
-       { "SQC_DATA_BANKB_HIT_FIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3), 1,
-         6, REG_FIELD_MASK(SQC_EDC_CNT3, DATA_BANKB_HIT_FIFO_SED_COUNT), 0 },
-       { "SQC_DATA_BANKB_MISS_FIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3), 1,
-         6, REG_FIELD_MASK(SQC_EDC_CNT3, DATA_BANKB_MISS_FIFO_SED_COUNT), 0 },
-       { "SQC_DATA_BANKB_DIRTY_BIT_RAM",
-         SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3), 1, 6,
-         REG_FIELD_MASK(SQC_EDC_CNT3, DATA_BANKB_DIRTY_BIT_RAM_SED_COUNT), 0 },
-       { "EA_DRAMRD_CMDMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT, DRAMRD_CMDMEM_SEC_COUNT),
-         REG_FIELD_MASK(GCEA_EDC_CNT, DRAMRD_CMDMEM_DED_COUNT) },
-       { "EA_DRAMWR_CMDMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT, DRAMWR_CMDMEM_SEC_COUNT),
-         REG_FIELD_MASK(GCEA_EDC_CNT, DRAMWR_CMDMEM_DED_COUNT) },
-       { "EA_DRAMWR_DATAMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT, DRAMWR_DATAMEM_SEC_COUNT),
-         REG_FIELD_MASK(GCEA_EDC_CNT, DRAMWR_DATAMEM_DED_COUNT) },
-       { "EA_RRET_TAGMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT, RRET_TAGMEM_SEC_COUNT),
-         REG_FIELD_MASK(GCEA_EDC_CNT, RRET_TAGMEM_DED_COUNT) },
-       { "EA_WRET_TAGMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT, WRET_TAGMEM_SEC_COUNT),
-         REG_FIELD_MASK(GCEA_EDC_CNT, WRET_TAGMEM_DED_COUNT) },
-       { "EA_DRAMRD_PAGEMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT, DRAMRD_PAGEMEM_SED_COUNT), 0 },
-       { "EA_DRAMWR_PAGEMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT, DRAMWR_PAGEMEM_SED_COUNT), 0 },
-       { "EA_IORD_CMDMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT, IORD_CMDMEM_SED_COUNT), 0 },
-       { "EA_IOWR_CMDMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT, IOWR_CMDMEM_SED_COUNT), 0 },
-       { "EA_IOWR_DATAMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT, IOWR_DATAMEM_SED_COUNT), 0 },
-       { "GMIRD_CMDMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT2, GMIRD_CMDMEM_SEC_COUNT),
-         REG_FIELD_MASK(GCEA_EDC_CNT2, GMIRD_CMDMEM_DED_COUNT) },
-       { "GMIWR_CMDMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT2, GMIWR_CMDMEM_SEC_COUNT),
-         REG_FIELD_MASK(GCEA_EDC_CNT2, GMIWR_CMDMEM_DED_COUNT) },
-       { "GMIWR_DATAMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT2, GMIWR_DATAMEM_SEC_COUNT),
-         REG_FIELD_MASK(GCEA_EDC_CNT2, GMIWR_DATAMEM_DED_COUNT) },
-       { "GMIRD_PAGEMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT2, GMIRD_PAGEMEM_SED_COUNT), 0 },
-       { "GMIWR_PAGEMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT2, GMIWR_PAGEMEM_SED_COUNT), 0 },
-       { "MAM_D0MEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT2, MAM_D0MEM_SED_COUNT), 0 },
-       { "MAM_D1MEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT2, MAM_D1MEM_SED_COUNT), 0 },
-       { "MAM_D2MEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT2, MAM_D2MEM_SED_COUNT), 0 },
-       { "MAM_D3MEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2), 0, 32,
-         REG_FIELD_MASK(GCEA_EDC_CNT2, MAM_D3MEM_SED_COUNT), 0 },
+         SOC15_REG_FIELD(SQC_EDC_CNT, DATA_CU2_WRITE_DATA_BUF_SEC_COUNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT, DATA_CU2_WRITE_DATA_BUF_DED_COUNT)
+       },
+       { "SQC_DATA_CU2_UTCL1_LFIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT, DATA_CU2_UTCL1_LFIFO_SEC_COUNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT, DATA_CU2_UTCL1_LFIFO_DED_COUNT)
+       },
+       { "SQC_INST_BANKA_TAG_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2),
+         SOC15_REG_FIELD(SQC_EDC_CNT2, INST_BANKA_TAG_RAM_SEC_COUNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT2, INST_BANKA_TAG_RAM_DED_COUNT)
+       },
+       { "SQC_INST_BANKA_BANK_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2),
+         SOC15_REG_FIELD(SQC_EDC_CNT2, INST_BANKA_BANK_RAM_SEC_COUNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT2, INST_BANKA_BANK_RAM_DED_COUNT)
+       },
+       { "SQC_DATA_BANKA_TAG_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2),
+         SOC15_REG_FIELD(SQC_EDC_CNT2, DATA_BANKA_TAG_RAM_SEC_COUNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT2, DATA_BANKA_TAG_RAM_DED_COUNT)
+       },
+       { "SQC_DATA_BANKA_BANK_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2),
+         SOC15_REG_FIELD(SQC_EDC_CNT2, DATA_BANKA_BANK_RAM_SEC_COUNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT2, DATA_BANKA_BANK_RAM_DED_COUNT)
+       },
+       { "SQC_INST_BANKA_UTCL1_MISS_FIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2),
+         SOC15_REG_FIELD(SQC_EDC_CNT2, INST_BANKA_UTCL1_MISS_FIFO_SED_COUNT),
+         0, 0
+       },
+       { "SQC_INST_BANKA_MISS_FIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2),
+         SOC15_REG_FIELD(SQC_EDC_CNT2, INST_BANKA_MISS_FIFO_SED_COUNT),
+         0, 0
+       },
+       { "SQC_DATA_BANKA_HIT_FIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2),
+         SOC15_REG_FIELD(SQC_EDC_CNT2, DATA_BANKA_HIT_FIFO_SED_COUNT),
+         0, 0
+       },
+       { "SQC_DATA_BANKA_MISS_FIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2),
+         SOC15_REG_FIELD(SQC_EDC_CNT2, DATA_BANKA_MISS_FIFO_SED_COUNT),
+         0, 0
+       },
+       { "SQC_DATA_BANKA_DIRTY_BIT_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2),
+         SOC15_REG_FIELD(SQC_EDC_CNT2, DATA_BANKA_DIRTY_BIT_RAM_SED_COUNT),
+         0, 0
+       },
+       { "SQC_INST_UTCL1_LFIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2),
+         SOC15_REG_FIELD(SQC_EDC_CNT2, INST_UTCL1_LFIFO_SEC_COUNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT2, INST_UTCL1_LFIFO_DED_COUNT)
+       },
+       { "SQC_INST_BANKB_TAG_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3),
+         SOC15_REG_FIELD(SQC_EDC_CNT3, INST_BANKB_TAG_RAM_SEC_COUNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT3, INST_BANKB_TAG_RAM_DED_COUNT)
+       },
+       { "SQC_INST_BANKB_BANK_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3),
+         SOC15_REG_FIELD(SQC_EDC_CNT3, INST_BANKB_BANK_RAM_SEC_COUNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT3, INST_BANKB_BANK_RAM_DED_COUNT)
+       },
+       { "SQC_DATA_BANKB_TAG_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3),
+         SOC15_REG_FIELD(SQC_EDC_CNT3, DATA_BANKB_TAG_RAM_SEC_COUNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT3, DATA_BANKB_TAG_RAM_DED_COUNT)
+       },
+       { "SQC_DATA_BANKB_BANK_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3),
+         SOC15_REG_FIELD(SQC_EDC_CNT3, DATA_BANKB_BANK_RAM_SEC_COUNT),
+         SOC15_REG_FIELD(SQC_EDC_CNT3, DATA_BANKB_BANK_RAM_DED_COUNT)
+       },
+       { "SQC_INST_BANKB_UTCL1_MISS_FIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3),
+         SOC15_REG_FIELD(SQC_EDC_CNT3, INST_BANKB_UTCL1_MISS_FIFO_SED_COUNT),
+         0, 0
+       },
+       { "SQC_INST_BANKB_MISS_FIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3),
+         SOC15_REG_FIELD(SQC_EDC_CNT3, INST_BANKB_MISS_FIFO_SED_COUNT),
+         0, 0
+       },
+       { "SQC_DATA_BANKB_HIT_FIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3),
+         SOC15_REG_FIELD(SQC_EDC_CNT3, DATA_BANKB_HIT_FIFO_SED_COUNT),
+         0, 0
+       },
+       { "SQC_DATA_BANKB_MISS_FIFO", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3),
+         SOC15_REG_FIELD(SQC_EDC_CNT3, DATA_BANKB_MISS_FIFO_SED_COUNT),
+         0, 0
+       },
+       { "SQC_DATA_BANKB_DIRTY_BIT_RAM", SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3),
+         SOC15_REG_FIELD(SQC_EDC_CNT3, DATA_BANKB_DIRTY_BIT_RAM_SED_COUNT),
+         0, 0
+       },
+       { "EA_DRAMRD_CMDMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT, DRAMRD_CMDMEM_SEC_COUNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT, DRAMRD_CMDMEM_DED_COUNT)
+       },
+       { "EA_DRAMWR_CMDMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT, DRAMWR_CMDMEM_SEC_COUNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT, DRAMWR_CMDMEM_DED_COUNT)
+       },
+       { "EA_DRAMWR_DATAMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT, DRAMWR_DATAMEM_SEC_COUNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT, DRAMWR_DATAMEM_DED_COUNT)
+       },
+       { "EA_RRET_TAGMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT, RRET_TAGMEM_SEC_COUNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT, RRET_TAGMEM_DED_COUNT)
+       },
+       { "EA_WRET_TAGMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT, WRET_TAGMEM_SEC_COUNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT, WRET_TAGMEM_DED_COUNT)
+       },
+       { "EA_DRAMRD_PAGEMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT, DRAMRD_PAGEMEM_SED_COUNT),
+         0, 0
+       },
+       { "EA_DRAMWR_PAGEMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT, DRAMWR_PAGEMEM_SED_COUNT),
+         0, 0
+       },
+       { "EA_IORD_CMDMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT, IORD_CMDMEM_SED_COUNT),
+         0, 0
+       },
+       { "EA_IOWR_CMDMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT, IOWR_CMDMEM_SED_COUNT),
+         0, 0
+       },
+       { "EA_IOWR_DATAMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT, IOWR_DATAMEM_SED_COUNT),
+         0, 0
+       },
+       { "GMIRD_CMDMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2),
+         SOC15_REG_FIELD(GCEA_EDC_CNT2, GMIRD_CMDMEM_SEC_COUNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT2, GMIRD_CMDMEM_DED_COUNT)
+       },
+       { "GMIWR_CMDMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2),
+         SOC15_REG_FIELD(GCEA_EDC_CNT2, GMIWR_CMDMEM_SEC_COUNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT2, GMIWR_CMDMEM_DED_COUNT)
+       },
+       { "GMIWR_DATAMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2),
+         SOC15_REG_FIELD(GCEA_EDC_CNT2, GMIWR_DATAMEM_SEC_COUNT),
+         SOC15_REG_FIELD(GCEA_EDC_CNT2, GMIWR_DATAMEM_DED_COUNT)
+       },
+       { "GMIRD_PAGEMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2),
+         SOC15_REG_FIELD(GCEA_EDC_CNT2, GMIRD_PAGEMEM_SED_COUNT),
+         0, 0
+       },
+       { "GMIWR_PAGEMEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2),
+         SOC15_REG_FIELD(GCEA_EDC_CNT2, GMIWR_PAGEMEM_SED_COUNT),
+         0, 0
+       },
+       { "MAM_D0MEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2),
+         SOC15_REG_FIELD(GCEA_EDC_CNT2, MAM_D0MEM_SED_COUNT),
+         0, 0
+       },
+       { "MAM_D1MEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2),
+         SOC15_REG_FIELD(GCEA_EDC_CNT2, MAM_D1MEM_SED_COUNT),
+         0, 0
+       },
+       { "MAM_D2MEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2),
+         SOC15_REG_FIELD(GCEA_EDC_CNT2, MAM_D2MEM_SED_COUNT),
+         0, 0
+       },
+       { "MAM_D3MEM", SOC15_REG_ENTRY(GC, 0, mmGCEA_EDC_CNT2),
+         SOC15_REG_FIELD(GCEA_EDC_CNT2, MAM_D3MEM_SED_COUNT),
+         0, 0
+       }
 };
 
 static int gfx_v9_0_ras_error_inject(struct amdgpu_device *adev,
@@ -6078,14 +5934,217 @@ static int gfx_v9_0_ras_error_inject(struct amdgpu_device *adev,
        return ret;
 }
 
+static const char *vml2_mems[] = {
+       "UTC_VML2_BANK_CACHE_0_BIGK_MEM0",
+       "UTC_VML2_BANK_CACHE_0_BIGK_MEM1",
+       "UTC_VML2_BANK_CACHE_0_4K_MEM0",
+       "UTC_VML2_BANK_CACHE_0_4K_MEM1",
+       "UTC_VML2_BANK_CACHE_1_BIGK_MEM0",
+       "UTC_VML2_BANK_CACHE_1_BIGK_MEM1",
+       "UTC_VML2_BANK_CACHE_1_4K_MEM0",
+       "UTC_VML2_BANK_CACHE_1_4K_MEM1",
+       "UTC_VML2_BANK_CACHE_2_BIGK_MEM0",
+       "UTC_VML2_BANK_CACHE_2_BIGK_MEM1",
+       "UTC_VML2_BANK_CACHE_2_4K_MEM0",
+       "UTC_VML2_BANK_CACHE_2_4K_MEM1",
+       "UTC_VML2_BANK_CACHE_3_BIGK_MEM0",
+       "UTC_VML2_BANK_CACHE_3_BIGK_MEM1",
+       "UTC_VML2_BANK_CACHE_3_4K_MEM0",
+       "UTC_VML2_BANK_CACHE_3_4K_MEM1",
+};
+
+static const char *vml2_walker_mems[] = {
+       "UTC_VML2_CACHE_PDE0_MEM0",
+       "UTC_VML2_CACHE_PDE0_MEM1",
+       "UTC_VML2_CACHE_PDE1_MEM0",
+       "UTC_VML2_CACHE_PDE1_MEM1",
+       "UTC_VML2_CACHE_PDE2_MEM0",
+       "UTC_VML2_CACHE_PDE2_MEM1",
+       "UTC_VML2_RDIF_LOG_FIFO",
+};
+
+static const char *atc_l2_cache_2m_mems[] = {
+       "UTC_ATCL2_CACHE_2M_BANK0_WAY0_MEM",
+       "UTC_ATCL2_CACHE_2M_BANK0_WAY1_MEM",
+       "UTC_ATCL2_CACHE_2M_BANK1_WAY0_MEM",
+       "UTC_ATCL2_CACHE_2M_BANK1_WAY1_MEM",
+};
+
+static const char *atc_l2_cache_4k_mems[] = {
+       "UTC_ATCL2_CACHE_4K_BANK0_WAY0_MEM0",
+       "UTC_ATCL2_CACHE_4K_BANK0_WAY0_MEM1",
+       "UTC_ATCL2_CACHE_4K_BANK0_WAY0_MEM2",
+       "UTC_ATCL2_CACHE_4K_BANK0_WAY0_MEM3",
+       "UTC_ATCL2_CACHE_4K_BANK0_WAY0_MEM4",
+       "UTC_ATCL2_CACHE_4K_BANK0_WAY0_MEM5",
+       "UTC_ATCL2_CACHE_4K_BANK0_WAY0_MEM6",
+       "UTC_ATCL2_CACHE_4K_BANK0_WAY0_MEM7",
+       "UTC_ATCL2_CACHE_4K_BANK0_WAY1_MEM0",
+       "UTC_ATCL2_CACHE_4K_BANK0_WAY1_MEM1",
+       "UTC_ATCL2_CACHE_4K_BANK0_WAY1_MEM2",
+       "UTC_ATCL2_CACHE_4K_BANK0_WAY1_MEM3",
+       "UTC_ATCL2_CACHE_4K_BANK0_WAY1_MEM4",
+       "UTC_ATCL2_CACHE_4K_BANK0_WAY1_MEM5",
+       "UTC_ATCL2_CACHE_4K_BANK0_WAY1_MEM6",
+       "UTC_ATCL2_CACHE_4K_BANK0_WAY1_MEM7",
+       "UTC_ATCL2_CACHE_4K_BANK1_WAY0_MEM0",
+       "UTC_ATCL2_CACHE_4K_BANK1_WAY0_MEM1",
+       "UTC_ATCL2_CACHE_4K_BANK1_WAY0_MEM2",
+       "UTC_ATCL2_CACHE_4K_BANK1_WAY0_MEM3",
+       "UTC_ATCL2_CACHE_4K_BANK1_WAY0_MEM4",
+       "UTC_ATCL2_CACHE_4K_BANK1_WAY0_MEM5",
+       "UTC_ATCL2_CACHE_4K_BANK1_WAY0_MEM6",
+       "UTC_ATCL2_CACHE_4K_BANK1_WAY0_MEM7",
+       "UTC_ATCL2_CACHE_4K_BANK1_WAY1_MEM0",
+       "UTC_ATCL2_CACHE_4K_BANK1_WAY1_MEM1",
+       "UTC_ATCL2_CACHE_4K_BANK1_WAY1_MEM2",
+       "UTC_ATCL2_CACHE_4K_BANK1_WAY1_MEM3",
+       "UTC_ATCL2_CACHE_4K_BANK1_WAY1_MEM4",
+       "UTC_ATCL2_CACHE_4K_BANK1_WAY1_MEM5",
+       "UTC_ATCL2_CACHE_4K_BANK1_WAY1_MEM6",
+       "UTC_ATCL2_CACHE_4K_BANK1_WAY1_MEM7",
+};
+
+static int gfx_v9_0_query_utc_edc_status(struct amdgpu_device *adev,
+                                        struct ras_err_data *err_data)
+{
+       uint32_t i, data;
+       uint32_t sec_count, ded_count;
+
+       WREG32_SOC15(GC, 0, mmVM_L2_MEM_ECC_INDEX, 255);
+       WREG32_SOC15(GC, 0, mmVM_L2_MEM_ECC_CNT, 0);
+       WREG32_SOC15(GC, 0, mmVM_L2_WALKER_MEM_ECC_INDEX, 255);
+       WREG32_SOC15(GC, 0, mmVM_L2_WALKER_MEM_ECC_CNT, 0);
+       WREG32_SOC15(GC, 0, mmATC_L2_CACHE_2M_EDC_INDEX, 255);
+       WREG32_SOC15(GC, 0, mmATC_L2_CACHE_2M_EDC_CNT, 0);
+       WREG32_SOC15(GC, 0, mmATC_L2_CACHE_4K_EDC_INDEX, 255);
+       WREG32_SOC15(GC, 0, mmATC_L2_CACHE_4K_EDC_CNT, 0);
+
+       for (i = 0; i < 16; i++) {
+               WREG32_SOC15(GC, 0, mmVM_L2_MEM_ECC_INDEX, i);
+               data = RREG32_SOC15(GC, 0, mmVM_L2_MEM_ECC_CNT);
+
+               sec_count = REG_GET_FIELD(data, VM_L2_MEM_ECC_CNT, SEC_COUNT);
+               if (sec_count) {
+                       DRM_INFO("Instance[%d]: SubBlock %s, SEC %d\n", i,
+                                vml2_mems[i], sec_count);
+                       err_data->ce_count += sec_count;
+               }
+
+               ded_count = REG_GET_FIELD(data, VM_L2_MEM_ECC_CNT, DED_COUNT);
+               if (ded_count) {
+                       DRM_INFO("Instance[%d]: SubBlock %s, DED %d\n", i,
+                                vml2_mems[i], ded_count);
+                       err_data->ue_count += ded_count;
+               }
+       }
+
+       for (i = 0; i < 7; i++) {
+               WREG32_SOC15(GC, 0, mmVM_L2_WALKER_MEM_ECC_INDEX, i);
+               data = RREG32_SOC15(GC, 0, mmVM_L2_WALKER_MEM_ECC_CNT);
+
+               sec_count = REG_GET_FIELD(data, VM_L2_WALKER_MEM_ECC_CNT,
+                                               SEC_COUNT);
+               if (sec_count) {
+                       DRM_INFO("Instance[%d]: SubBlock %s, SEC %d\n", i,
+                                vml2_walker_mems[i], sec_count);
+                       err_data->ce_count += sec_count;
+               }
+
+               ded_count = REG_GET_FIELD(data, VM_L2_WALKER_MEM_ECC_CNT,
+                                               DED_COUNT);
+               if (ded_count) {
+                       DRM_INFO("Instance[%d]: SubBlock %s, DED %d\n", i,
+                                vml2_walker_mems[i], ded_count);
+                       err_data->ue_count += ded_count;
+               }
+       }
+
+       for (i = 0; i < 4; i++) {
+               WREG32_SOC15(GC, 0, mmATC_L2_CACHE_2M_EDC_INDEX, i);
+               data = RREG32_SOC15(GC, 0, mmATC_L2_CACHE_2M_EDC_CNT);
+
+               sec_count = (data & 0x00006000L) >> 0xd;
+               if (sec_count) {
+                       DRM_INFO("Instance[%d]: SubBlock %s, SEC %d\n", i,
+                                atc_l2_cache_2m_mems[i], sec_count);
+                       err_data->ce_count += sec_count;
+               }
+       }
+
+       for (i = 0; i < 32; i++) {
+               WREG32_SOC15(GC, 0, mmATC_L2_CACHE_4K_EDC_INDEX, i);
+               data = RREG32_SOC15(GC, 0, mmATC_L2_CACHE_4K_EDC_CNT);
+
+               sec_count = (data & 0x00006000L) >> 0xd;
+               if (sec_count) {
+                       DRM_INFO("Instance[%d]: SubBlock %s, SEC %d\n", i,
+                                atc_l2_cache_4k_mems[i], sec_count);
+                       err_data->ce_count += sec_count;
+               }
+
+               ded_count = (data & 0x00018000L) >> 0xf;
+               if (ded_count) {
+                       DRM_INFO("Instance[%d]: SubBlock %s, DED %d\n", i,
+                                atc_l2_cache_4k_mems[i], ded_count);
+                       err_data->ue_count += ded_count;
+               }
+       }
+
+       WREG32_SOC15(GC, 0, mmVM_L2_MEM_ECC_INDEX, 255);
+       WREG32_SOC15(GC, 0, mmVM_L2_WALKER_MEM_ECC_INDEX, 255);
+       WREG32_SOC15(GC, 0, mmATC_L2_CACHE_2M_EDC_INDEX, 255);
+       WREG32_SOC15(GC, 0, mmATC_L2_CACHE_4K_EDC_INDEX, 255);
+
+       return 0;
+}
+
+static int __get_ras_error_count(const struct soc15_reg_entry *reg,
+       uint32_t se_id, uint32_t inst_id, uint32_t value,
+       uint32_t *sec_count, uint32_t *ded_count)
+{
+       uint32_t i;
+       uint32_t sec_cnt, ded_cnt;
+
+       for (i = 0; i < ARRAY_SIZE(ras_subblock_regs); i++) {
+               if(ras_subblock_regs[i].reg_offset != reg->reg_offset ||
+                       ras_subblock_regs[i].seg != reg->seg ||
+                       ras_subblock_regs[i].inst != reg->inst)
+                       continue;
+
+               sec_cnt = (value &
+                               ras_subblock_regs[i].sec_count_mask) >>
+                               ras_subblock_regs[i].sec_count_shift;
+               if (sec_cnt) {
+                       DRM_INFO("GFX SubBlock %s, Instance[%d][%d], SEC %d\n",
+                               ras_subblock_regs[i].name,
+                               se_id, inst_id,
+                               sec_cnt);
+                       *sec_count += sec_cnt;
+               }
+
+               ded_cnt = (value &
+                               ras_subblock_regs[i].ded_count_mask) >>
+                               ras_subblock_regs[i].ded_count_shift;
+               if (ded_cnt) {
+                       DRM_INFO("GFX SubBlock %s, Instance[%d][%d], DED %d\n",
+                               ras_subblock_regs[i].name,
+                               se_id, inst_id,
+                               ded_cnt);
+                       *ded_count += ded_cnt;
+               }
+       }
+
+       return 0;
+}
+
 static int gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev,
                                          void *ras_error_status)
 {
        struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
-       uint32_t sec_count, ded_count;
-       uint32_t i;
+       uint32_t sec_count = 0, ded_count = 0;
+       uint32_t i, j, k;
        uint32_t reg_value;
-       uint32_t se_id, instance_id;
 
        if (adev->asic_type != CHIP_VEGA20)
                return -EINVAL;
@@ -6094,71 +6153,29 @@ static int gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev,
        err_data->ce_count = 0;
 
        mutex_lock(&adev->grbm_idx_mutex);
-       for (se_id = 0; se_id < adev->gfx.config.max_shader_engines; se_id++) {
-               for (instance_id = 0; instance_id < 256; instance_id++) {
-                       for (i = 0;
-                            i < sizeof(gfx_ras_edc_regs) / sizeof(gfx_ras_edc_regs[0]);
-                            i++) {
-                               if (se_id != 0 &&
-                                   !gfx_ras_edc_regs[i].per_se_instance)
-                                       continue;
-                               if (instance_id >= gfx_ras_edc_regs[i].num_instance)
-                                       continue;
-
-                               gfx_v9_0_select_se_sh(adev, se_id, 0,
-                                                     instance_id);
-
-                               reg_value = RREG32(
-                                       adev->reg_offset[gfx_ras_edc_regs[i].ip]
-                                                       [gfx_ras_edc_regs[i].inst]
-                                                       [gfx_ras_edc_regs[i].seg] +
-                                       gfx_ras_edc_regs[i].reg_offset);
-                               sec_count = reg_value &
-                                           gfx_ras_edc_regs[i].sec_count_mask;
-                               ded_count = reg_value &
-                                           gfx_ras_edc_regs[i].ded_count_mask;
-                               if (sec_count) {
-                                       DRM_INFO(
-                                               "Instance[%d][%d]: SubBlock %s, SEC %d\n",
-                                               se_id, instance_id,
-                                               gfx_ras_edc_regs[i].name,
-                                               sec_count);
-                                       err_data->ce_count++;
-                               }
 
-                               if (ded_count) {
-                                       DRM_INFO(
-                                               "Instance[%d][%d]: SubBlock %s, DED %d\n",
-                                               se_id, instance_id,
-                                               gfx_ras_edc_regs[i].name,
-                                               ded_count);
-                                       err_data->ue_count++;
-                               }
+       for (i = 0; i < ARRAY_SIZE(sec_ded_counter_registers); i++) {
+               for (j = 0; j < sec_ded_counter_registers[i].se_num; j++) {
+                       for (k = 0; k < sec_ded_counter_registers[i].instance; k++) {
+                               gfx_v9_0_select_se_sh(adev, j, 0, k);
+                               reg_value =
+                                       RREG32(SOC15_REG_ENTRY_OFFSET(sec_ded_counter_registers[i]));
+                               if (reg_value)
+                                       __get_ras_error_count(&sec_ded_counter_registers[i],
+                                                       j, k, reg_value,
+                                                       &sec_count, &ded_count);
                        }
                }
        }
-       gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
-       mutex_unlock(&adev->grbm_idx_mutex);
-
-       return 0;
-}
 
-static int gfx_v9_0_cp_ecc_error_irq(struct amdgpu_device *adev,
-                                 struct amdgpu_irq_src *source,
-                                 struct amdgpu_iv_entry *entry)
-{
-       struct ras_common_if *ras_if = adev->gfx.ras_if;
-       struct ras_dispatch_if ih_data = {
-               .entry = entry,
-       };
+       err_data->ce_count += sec_count;
+       err_data->ue_count += ded_count;
 
-       if (!ras_if)
-               return 0;
+       gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+       mutex_unlock(&adev->grbm_idx_mutex);
 
-       ih_data.head = *ras_if;
+       gfx_v9_0_query_utc_edc_status(adev, err_data);
 
-       DRM_ERROR("CP ECC ERROR IRQ\n");
-       amdgpu_ras_interrupt_dispatch(adev, &ih_data);
        return 0;
 }
 
@@ -6325,7 +6342,7 @@ static const struct amdgpu_irq_src_funcs gfx_v9_0_priv_inst_irq_funcs = {
 
 static const struct amdgpu_irq_src_funcs gfx_v9_0_cp_ecc_error_irq_funcs = {
        .set = gfx_v9_0_set_cp_ecc_error_state,
-       .process = gfx_v9_0_cp_ecc_error_irq,
+       .process = amdgpu_gfx_cp_ecc_error_irq,
 };
 
 
index 6ce37ce77d14ab519eaca87a02886d59aa5be6b7..9ec4297e61e5d46301fc9e22cd70ecf1a5959ae5 100644 (file)
@@ -178,6 +178,8 @@ static void gfxhub_v1_0_enable_system_domain(struct amdgpu_device *adev)
        tmp = RREG32_SOC15(GC, 0, mmVM_CONTEXT0_CNTL);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL, ENABLE_CONTEXT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL, PAGE_TABLE_DEPTH, 0);
+       tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL,
+                           RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0);
        WREG32_SOC15(GC, 0, mmVM_CONTEXT0_CNTL, tmp);
 }
 
index 8b789f750b72b0ecba603bb2982cd4e8ada03d60..b601c6740ef5bd6212998c2df3067ec96196cb74 100644 (file)
@@ -46,21 +46,25 @@ u64 gfxhub_v2_0_get_mc_fb_offset(struct amdgpu_device *adev)
        return (u64)RREG32_SOC15(GC, 0, mmGCMC_VM_FB_OFFSET) << 24;
 }
 
-static void gfxhub_v2_0_init_gart_pt_regs(struct amdgpu_device *adev)
+void gfxhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
+                               uint64_t page_table_base)
 {
-       uint64_t value = amdgpu_gmc_pd_addr(adev->gart.bo);
+       /* two registers distance between mmGCVM_CONTEXT0_* to mmGCVM_CONTEXT1_* */
+       int offset = mmGCVM_CONTEXT1_PAGE_TABLE_BASE_ADDR_LO32
+                       - mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32;
 
+       WREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
+                               offset * vmid, lower_32_bits(page_table_base));
 
-       WREG32_SOC15(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
-                    lower_32_bits(value));
-
-       WREG32_SOC15(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
-                    upper_32_bits(value));
+       WREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
+                               offset * vmid, upper_32_bits(page_table_base));
 }
 
 static void gfxhub_v2_0_init_gart_aperture_regs(struct amdgpu_device *adev)
 {
-       gfxhub_v2_0_init_gart_pt_regs(adev);
+       uint64_t pt_base = amdgpu_gmc_pd_addr(adev->gart.bo);
+
+       gfxhub_v2_0_setup_vm_pt_regs(adev, 0, pt_base);
 
        WREG32_SOC15(GC, 0, mmGCVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
                     (u32)(adev->gmc.gart_start >> 12));
@@ -166,6 +170,8 @@ static void gfxhub_v2_0_enable_system_domain(struct amdgpu_device *adev)
        tmp = RREG32_SOC15(GC, 0, mmGCVM_CONTEXT0_CNTL);
        tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT0_CNTL, ENABLE_CONTEXT, 1);
        tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT0_CNTL, PAGE_TABLE_DEPTH, 0);
+       tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT0_CNTL,
+                           RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0);
        WREG32_SOC15(GC, 0, mmGCVM_CONTEXT0_CNTL, tmp);
 }
 
index 06807940748be4bbcd9e31a24bc3a5e8ac359bf2..392b8cd94fc0f36d797e17c1c4dd21bb9d4920de 100644 (file)
@@ -31,5 +31,7 @@ void gfxhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev,
                                          bool value);
 void gfxhub_v2_0_init(struct amdgpu_device *adev);
 u64 gfxhub_v2_0_get_mc_fb_offset(struct amdgpu_device *adev);
+void gfxhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
+                               uint64_t page_table_base);
 
 #endif
index 241a4e57cf4a993ea1756523c3b69f208f30a9d7..fb48622c2abdb022c4a16837ab5c065061ac25fc 100644 (file)
@@ -278,7 +278,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
        int r;
 
        /* flush hdp cache */
-       adev->nbio_funcs->hdp_flush(adev, NULL);
+       adev->nbio.funcs->hdp_flush(adev, NULL);
 
        mutex_lock(&adev->mman.gtt_window_lock);
 
@@ -397,43 +397,23 @@ static void gmc_v10_0_emit_pasid_mapping(struct amdgpu_ring *ring, unsigned vmid
  * 1 system
  * 0 valid
  */
-static uint64_t gmc_v10_0_get_vm_pte_flags(struct amdgpu_device *adev,
-                                          uint32_t flags)
-{
-       uint64_t pte_flag = 0;
-
-       if (flags & AMDGPU_VM_PAGE_EXECUTABLE)
-               pte_flag |= AMDGPU_PTE_EXECUTABLE;
-       if (flags & AMDGPU_VM_PAGE_READABLE)
-               pte_flag |= AMDGPU_PTE_READABLE;
-       if (flags & AMDGPU_VM_PAGE_WRITEABLE)
-               pte_flag |= AMDGPU_PTE_WRITEABLE;
 
-       switch (flags & AMDGPU_VM_MTYPE_MASK) {
+static uint64_t gmc_v10_0_map_mtype(struct amdgpu_device *adev, uint32_t flags)
+{
+       switch (flags) {
        case AMDGPU_VM_MTYPE_DEFAULT:
-               pte_flag |= AMDGPU_PTE_MTYPE_NV10(MTYPE_NC);
-               break;
+               return AMDGPU_PTE_MTYPE_NV10(MTYPE_NC);
        case AMDGPU_VM_MTYPE_NC:
-               pte_flag |= AMDGPU_PTE_MTYPE_NV10(MTYPE_NC);
-               break;
+               return AMDGPU_PTE_MTYPE_NV10(MTYPE_NC);
        case AMDGPU_VM_MTYPE_WC:
-               pte_flag |= AMDGPU_PTE_MTYPE_NV10(MTYPE_WC);
-               break;
+               return AMDGPU_PTE_MTYPE_NV10(MTYPE_WC);
        case AMDGPU_VM_MTYPE_CC:
-               pte_flag |= AMDGPU_PTE_MTYPE_NV10(MTYPE_CC);
-               break;
+               return AMDGPU_PTE_MTYPE_NV10(MTYPE_CC);
        case AMDGPU_VM_MTYPE_UC:
-               pte_flag |= AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
-               break;
+               return AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
        default:
-               pte_flag |= AMDGPU_PTE_MTYPE_NV10(MTYPE_NC);
-               break;
+               return AMDGPU_PTE_MTYPE_NV10(MTYPE_NC);
        }
-
-       if (flags & AMDGPU_VM_PAGE_PRT)
-               pte_flag |= AMDGPU_PTE_PRT;
-
-       return pte_flag;
 }
 
 static void gmc_v10_0_get_vm_pde(struct amdgpu_device *adev, int level,
@@ -460,12 +440,32 @@ static void gmc_v10_0_get_vm_pde(struct amdgpu_device *adev, int level,
        }
 }
 
+static void gmc_v10_0_get_vm_pte(struct amdgpu_device *adev,
+                                struct amdgpu_bo_va_mapping *mapping,
+                                uint64_t *flags)
+{
+       *flags &= ~AMDGPU_PTE_EXECUTABLE;
+       *flags |= mapping->flags & AMDGPU_PTE_EXECUTABLE;
+
+       *flags &= ~AMDGPU_PTE_MTYPE_NV10_MASK;
+       *flags |= (mapping->flags & AMDGPU_PTE_MTYPE_NV10_MASK);
+
+       if (mapping->flags & AMDGPU_PTE_PRT) {
+               *flags |= AMDGPU_PTE_PRT;
+               *flags |= AMDGPU_PTE_SNOOPED;
+               *flags |= AMDGPU_PTE_LOG;
+               *flags |= AMDGPU_PTE_SYSTEM;
+               *flags &= ~AMDGPU_PTE_VALID;
+       }
+}
+
 static const struct amdgpu_gmc_funcs gmc_v10_0_gmc_funcs = {
        .flush_gpu_tlb = gmc_v10_0_flush_gpu_tlb,
        .emit_flush_gpu_tlb = gmc_v10_0_emit_flush_gpu_tlb,
        .emit_pasid_mapping = gmc_v10_0_emit_pasid_mapping,
-       .get_vm_pte_flags = gmc_v10_0_get_vm_pte_flags,
-       .get_vm_pde = gmc_v10_0_get_vm_pde
+       .map_mtype = gmc_v10_0_map_mtype,
+       .get_vm_pde = gmc_v10_0_get_vm_pde,
+       .get_vm_pte = gmc_v10_0_get_vm_pte
 };
 
 static void gmc_v10_0_set_gmc_funcs(struct amdgpu_device *adev)
@@ -519,8 +519,7 @@ static void gmc_v10_0_vram_gtt_location(struct amdgpu_device *adev,
 {
        u64 base = 0;
 
-       if (!amdgpu_sriov_vf(adev))
-               base = gfxhub_v2_0_get_fb_location(adev);
+       base = gfxhub_v2_0_get_fb_location(adev);
 
        amdgpu_gmc_vram_location(adev, &adev->gmc, base);
        amdgpu_gmc_gart_location(adev, mc);
@@ -540,24 +539,13 @@ static void gmc_v10_0_vram_gtt_location(struct amdgpu_device *adev,
  */
 static int gmc_v10_0_mc_init(struct amdgpu_device *adev)
 {
-       int chansize, numchan;
-
-       if (!amdgpu_emu_mode)
-               adev->gmc.vram_width = amdgpu_atomfirmware_get_vram_width(adev);
-       else {
-               /* hard code vram_width for emulation */
-               chansize = 128;
-               numchan = 1;
-               adev->gmc.vram_width = numchan * chansize;
-       }
-
        /* Could aper size report 0 ? */
        adev->gmc.aper_base = pci_resource_start(adev->pdev, 0);
        adev->gmc.aper_size = pci_resource_len(adev->pdev, 0);
 
        /* size in MB on si */
        adev->gmc.mc_vram_size =
-               adev->nbio_funcs->get_memsize(adev) * 1024ULL * 1024ULL;
+               adev->nbio.funcs->get_memsize(adev) * 1024ULL * 1024ULL;
        adev->gmc.real_vram_size = adev->gmc.mc_vram_size;
        adev->gmc.visible_vram_size = adev->gmc.aper_size;
 
@@ -636,7 +624,7 @@ static unsigned gmc_v10_0_get_vbios_fb_size(struct amdgpu_device *adev)
 
 static int gmc_v10_0_sw_init(void *handle)
 {
-       int r;
+       int r, vram_width = 0, vram_type = 0, vram_vendor = 0;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
        gfxhub_v2_0_init(adev);
@@ -644,7 +632,15 @@ static int gmc_v10_0_sw_init(void *handle)
 
        spin_lock_init(&adev->gmc.invalidate_lock);
 
-       adev->gmc.vram_type = amdgpu_atomfirmware_get_vram_type(adev);
+       r = amdgpu_atomfirmware_get_vram_info(adev,
+               &vram_width, &vram_type, &vram_vendor);
+       if (!amdgpu_emu_mode)
+               adev->gmc.vram_width = vram_width;
+       else
+               adev->gmc.vram_width = 1 * 128; /* numchan * chansize */
+
+       adev->gmc.vram_type = vram_type;
+       adev->gmc.vram_vendor = vram_vendor;
        switch (adev->asic_type) {
        case CHIP_NAVI10:
        case CHIP_NAVI14:
@@ -794,7 +790,7 @@ static int gmc_v10_0_gart_enable(struct amdgpu_device *adev)
        WREG32_SOC15(HDP, 0, mmHDP_HOST_PATH_CNTL, tmp);
 
        /* Flush HDP after it is initialized */
-       adev->nbio_funcs->hdp_flush(adev, NULL);
+       adev->nbio.funcs->hdp_flush(adev, NULL);
 
        value = (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS) ?
                false : true;
index 9fb1765e92d15a8e5183df22b5dd591cf717d7cd..b205039350b6c9d469ecdb3d738a71ea3cb40f17 100644 (file)
@@ -386,27 +386,20 @@ static uint64_t gmc_v6_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
        return pd_addr;
 }
 
-static uint64_t gmc_v6_0_get_vm_pte_flags(struct amdgpu_device *adev,
-                                         uint32_t flags)
-{
-       uint64_t pte_flag = 0;
-
-       if (flags & AMDGPU_VM_PAGE_READABLE)
-               pte_flag |= AMDGPU_PTE_READABLE;
-       if (flags & AMDGPU_VM_PAGE_WRITEABLE)
-               pte_flag |= AMDGPU_PTE_WRITEABLE;
-       if (flags & AMDGPU_VM_PAGE_PRT)
-               pte_flag |= AMDGPU_PTE_PRT;
-
-       return pte_flag;
-}
-
 static void gmc_v6_0_get_vm_pde(struct amdgpu_device *adev, int level,
                                uint64_t *addr, uint64_t *flags)
 {
        BUG_ON(*addr & 0xFFFFFF0000000FFFULL);
 }
 
+static void gmc_v6_0_get_vm_pte(struct amdgpu_device *adev,
+                               struct amdgpu_bo_va_mapping *mapping,
+                               uint64_t *flags)
+{
+       *flags &= ~AMDGPU_PTE_EXECUTABLE;
+       *flags &= ~AMDGPU_PTE_PRT;
+}
+
 static void gmc_v6_0_set_fault_enable_default(struct amdgpu_device *adev,
                                              bool value)
 {
@@ -1153,7 +1146,7 @@ static const struct amdgpu_gmc_funcs gmc_v6_0_gmc_funcs = {
        .emit_flush_gpu_tlb = gmc_v6_0_emit_flush_gpu_tlb,
        .set_prt = gmc_v6_0_set_prt,
        .get_vm_pde = gmc_v6_0_get_vm_pde,
-       .get_vm_pte_flags = gmc_v6_0_get_vm_pte_flags
+       .get_vm_pte = gmc_v6_0_get_vm_pte,
 };
 
 static const struct amdgpu_irq_src_funcs gmc_v6_0_irq_funcs = {
index 0c3d9bc3a64165e2f672077c06c81e9235ee54b3..f08e5330642d6f525cbf65107b7dd5422f84b1ab 100644 (file)
@@ -463,27 +463,20 @@ static void gmc_v7_0_emit_pasid_mapping(struct amdgpu_ring *ring, unsigned vmid,
        amdgpu_ring_emit_wreg(ring, mmIH_VMID_0_LUT + vmid, pasid);
 }
 
-static uint64_t gmc_v7_0_get_vm_pte_flags(struct amdgpu_device *adev,
-                                         uint32_t flags)
-{
-       uint64_t pte_flag = 0;
-
-       if (flags & AMDGPU_VM_PAGE_READABLE)
-               pte_flag |= AMDGPU_PTE_READABLE;
-       if (flags & AMDGPU_VM_PAGE_WRITEABLE)
-               pte_flag |= AMDGPU_PTE_WRITEABLE;
-       if (flags & AMDGPU_VM_PAGE_PRT)
-               pte_flag |= AMDGPU_PTE_PRT;
-
-       return pte_flag;
-}
-
 static void gmc_v7_0_get_vm_pde(struct amdgpu_device *adev, int level,
                                uint64_t *addr, uint64_t *flags)
 {
        BUG_ON(*addr & 0xFFFFFF0000000FFFULL);
 }
 
+static void gmc_v7_0_get_vm_pte(struct amdgpu_device *adev,
+                               struct amdgpu_bo_va_mapping *mapping,
+                               uint64_t *flags)
+{
+       *flags &= ~AMDGPU_PTE_EXECUTABLE;
+       *flags &= ~AMDGPU_PTE_PRT;
+}
+
 /**
  * gmc_v8_0_set_fault_enable_default - update VM fault handling
  *
@@ -1343,8 +1336,8 @@ static const struct amdgpu_gmc_funcs gmc_v7_0_gmc_funcs = {
        .emit_flush_gpu_tlb = gmc_v7_0_emit_flush_gpu_tlb,
        .emit_pasid_mapping = gmc_v7_0_emit_pasid_mapping,
        .set_prt = gmc_v7_0_set_prt,
-       .get_vm_pte_flags = gmc_v7_0_get_vm_pte_flags,
-       .get_vm_pde = gmc_v7_0_get_vm_pde
+       .get_vm_pde = gmc_v7_0_get_vm_pde,
+       .get_vm_pte = gmc_v7_0_get_vm_pte
 };
 
 static const struct amdgpu_irq_src_funcs gmc_v7_0_irq_funcs = {
index ea764dd9245dba23a28bca0d6dd39c49838f43b7..6d96d40fbcb8f8382dd3ab9c4945c05695f9bdf6 100644 (file)
@@ -686,29 +686,21 @@ static void gmc_v8_0_emit_pasid_mapping(struct amdgpu_ring *ring, unsigned vmid,
  * 0 valid
  */
 
-static uint64_t gmc_v8_0_get_vm_pte_flags(struct amdgpu_device *adev,
-                                         uint32_t flags)
-{
-       uint64_t pte_flag = 0;
-
-       if (flags & AMDGPU_VM_PAGE_EXECUTABLE)
-               pte_flag |= AMDGPU_PTE_EXECUTABLE;
-       if (flags & AMDGPU_VM_PAGE_READABLE)
-               pte_flag |= AMDGPU_PTE_READABLE;
-       if (flags & AMDGPU_VM_PAGE_WRITEABLE)
-               pte_flag |= AMDGPU_PTE_WRITEABLE;
-       if (flags & AMDGPU_VM_PAGE_PRT)
-               pte_flag |= AMDGPU_PTE_PRT;
-
-       return pte_flag;
-}
-
 static void gmc_v8_0_get_vm_pde(struct amdgpu_device *adev, int level,
                                uint64_t *addr, uint64_t *flags)
 {
        BUG_ON(*addr & 0xFFFFFF0000000FFFULL);
 }
 
+static void gmc_v8_0_get_vm_pte(struct amdgpu_device *adev,
+                               struct amdgpu_bo_va_mapping *mapping,
+                               uint64_t *flags)
+{
+       *flags &= ~AMDGPU_PTE_EXECUTABLE;
+       *flags |= mapping->flags & AMDGPU_PTE_EXECUTABLE;
+       *flags &= ~AMDGPU_PTE_PRT;
+}
+
 /**
  * gmc_v8_0_set_fault_enable_default - update VM fault handling
  *
@@ -1711,8 +1703,8 @@ static const struct amdgpu_gmc_funcs gmc_v8_0_gmc_funcs = {
        .emit_flush_gpu_tlb = gmc_v8_0_emit_flush_gpu_tlb,
        .emit_pasid_mapping = gmc_v8_0_emit_pasid_mapping,
        .set_prt = gmc_v8_0_set_prt,
-       .get_vm_pte_flags = gmc_v8_0_get_vm_pte_flags,
-       .get_vm_pde = gmc_v8_0_get_vm_pde
+       .get_vm_pde = gmc_v8_0_get_vm_pde,
+       .get_vm_pte = gmc_v8_0_get_vm_pte
 };
 
 static const struct amdgpu_irq_src_funcs gmc_v8_0_irq_funcs = {
index f91337030dc07857987bfc25ea6cabe8185585e3..9f2a893871ecd21a01da46837fb75ff9cd9bebca 100644 (file)
 #include "gfxhub_v1_1.h"
 #include "mmhub_v9_4.h"
 #include "umc_v6_1.h"
+#include "umc_v6_0.h"
 
 #include "ivsrcid/vmc/irqsrcs_vmc_1_0.h"
 
 #include "amdgpu_ras.h"
+#include "amdgpu_xgmi.h"
 
 /* add these here since we already include dce12 headers and these are for DCN */
 #define mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION                                                          0x055d
@@ -243,44 +245,6 @@ static int gmc_v9_0_ecc_interrupt_state(struct amdgpu_device *adev,
        return 0;
 }
 
-static int gmc_v9_0_process_ras_data_cb(struct amdgpu_device *adev,
-               struct ras_err_data *err_data,
-               struct amdgpu_iv_entry *entry)
-{
-       kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
-       if (adev->umc.funcs->query_ras_error_count)
-               adev->umc.funcs->query_ras_error_count(adev, err_data);
-       /* umc query_ras_error_address is also responsible for clearing
-        * error status
-        */
-       if (adev->umc.funcs->query_ras_error_address)
-               adev->umc.funcs->query_ras_error_address(adev, err_data);
-
-       /* only uncorrectable error needs gpu reset */
-       if (err_data->ue_count)
-               amdgpu_ras_reset_gpu(adev, 0);
-
-       return AMDGPU_RAS_SUCCESS;
-}
-
-static int gmc_v9_0_process_ecc_irq(struct amdgpu_device *adev,
-               struct amdgpu_irq_src *source,
-               struct amdgpu_iv_entry *entry)
-{
-       struct ras_common_if *ras_if = adev->gmc.umc_ras_if;
-       struct ras_dispatch_if ih_data = {
-               .entry = entry,
-       };
-
-       if (!ras_if)
-               return 0;
-
-       ih_data.head = *ras_if;
-
-       amdgpu_ras_interrupt_dispatch(adev, &ih_data);
-       return 0;
-}
-
 static int gmc_v9_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
                                        struct amdgpu_irq_src *src,
                                        unsigned type,
@@ -355,6 +319,10 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
        }
 
        /* If it's the first fault for this address, process it normally */
+       if (retry_fault && !in_interrupt() &&
+           amdgpu_vm_handle_fault(adev, entry->pasid, addr))
+               return 1; /* This also prevents sending it to KFD */
+
        if (!amdgpu_sriov_vf(adev)) {
                /*
                 * Issue a dummy read to wait for the status register to
@@ -417,7 +385,7 @@ static const struct amdgpu_irq_src_funcs gmc_v9_0_irq_funcs = {
 
 static const struct amdgpu_irq_src_funcs gmc_v9_0_ecc_funcs = {
        .set = gmc_v9_0_ecc_interrupt_state,
-       .process = gmc_v9_0_process_ecc_irq,
+       .process = amdgpu_umc_process_ecc_irq,
 };
 
 static void gmc_v9_0_set_irq_funcs(struct amdgpu_device *adev)
@@ -584,44 +552,25 @@ static void gmc_v9_0_emit_pasid_mapping(struct amdgpu_ring *ring, unsigned vmid,
  * 0 valid
  */
 
-static uint64_t gmc_v9_0_get_vm_pte_flags(struct amdgpu_device *adev,
-                                               uint32_t flags)
+static uint64_t gmc_v9_0_map_mtype(struct amdgpu_device *adev, uint32_t flags)
 
 {
-       uint64_t pte_flag = 0;
-
-       if (flags & AMDGPU_VM_PAGE_EXECUTABLE)
-               pte_flag |= AMDGPU_PTE_EXECUTABLE;
-       if (flags & AMDGPU_VM_PAGE_READABLE)
-               pte_flag |= AMDGPU_PTE_READABLE;
-       if (flags & AMDGPU_VM_PAGE_WRITEABLE)
-               pte_flag |= AMDGPU_PTE_WRITEABLE;
-
-       switch (flags & AMDGPU_VM_MTYPE_MASK) {
+       switch (flags) {
        case AMDGPU_VM_MTYPE_DEFAULT:
-               pte_flag |= AMDGPU_PTE_MTYPE_VG10(MTYPE_NC);
-               break;
+               return AMDGPU_PTE_MTYPE_VG10(MTYPE_NC);
        case AMDGPU_VM_MTYPE_NC:
-               pte_flag |= AMDGPU_PTE_MTYPE_VG10(MTYPE_NC);
-               break;
+               return AMDGPU_PTE_MTYPE_VG10(MTYPE_NC);
        case AMDGPU_VM_MTYPE_WC:
-               pte_flag |= AMDGPU_PTE_MTYPE_VG10(MTYPE_WC);
-               break;
+               return AMDGPU_PTE_MTYPE_VG10(MTYPE_WC);
+       case AMDGPU_VM_MTYPE_RW:
+               return AMDGPU_PTE_MTYPE_VG10(MTYPE_RW);
        case AMDGPU_VM_MTYPE_CC:
-               pte_flag |= AMDGPU_PTE_MTYPE_VG10(MTYPE_CC);
-               break;
+               return AMDGPU_PTE_MTYPE_VG10(MTYPE_CC);
        case AMDGPU_VM_MTYPE_UC:
-               pte_flag |= AMDGPU_PTE_MTYPE_VG10(MTYPE_UC);
-               break;
+               return AMDGPU_PTE_MTYPE_VG10(MTYPE_UC);
        default:
-               pte_flag |= AMDGPU_PTE_MTYPE_VG10(MTYPE_NC);
-               break;
+               return AMDGPU_PTE_MTYPE_VG10(MTYPE_NC);
        }
-
-       if (flags & AMDGPU_VM_PAGE_PRT)
-               pte_flag |= AMDGPU_PTE_PRT;
-
-       return pte_flag;
 }
 
 static void gmc_v9_0_get_vm_pde(struct amdgpu_device *adev, int level,
@@ -648,12 +597,34 @@ static void gmc_v9_0_get_vm_pde(struct amdgpu_device *adev, int level,
        }
 }
 
+static void gmc_v9_0_get_vm_pte(struct amdgpu_device *adev,
+                               struct amdgpu_bo_va_mapping *mapping,
+                               uint64_t *flags)
+{
+       *flags &= ~AMDGPU_PTE_EXECUTABLE;
+       *flags |= mapping->flags & AMDGPU_PTE_EXECUTABLE;
+
+       *flags &= ~AMDGPU_PTE_MTYPE_VG10_MASK;
+       *flags |= mapping->flags & AMDGPU_PTE_MTYPE_VG10_MASK;
+
+       if (mapping->flags & AMDGPU_PTE_PRT) {
+               *flags |= AMDGPU_PTE_PRT;
+               *flags &= ~AMDGPU_PTE_VALID;
+       }
+
+       if (adev->asic_type == CHIP_ARCTURUS &&
+           !(*flags & AMDGPU_PTE_SYSTEM) &&
+           mapping->bo_va->is_xgmi)
+               *flags |= AMDGPU_PTE_SNOOPED;
+}
+
 static const struct amdgpu_gmc_funcs gmc_v9_0_gmc_funcs = {
        .flush_gpu_tlb = gmc_v9_0_flush_gpu_tlb,
        .emit_flush_gpu_tlb = gmc_v9_0_emit_flush_gpu_tlb,
        .emit_pasid_mapping = gmc_v9_0_emit_pasid_mapping,
-       .get_vm_pte_flags = gmc_v9_0_get_vm_pte_flags,
-       .get_vm_pde = gmc_v9_0_get_vm_pde
+       .map_mtype = gmc_v9_0_map_mtype,
+       .get_vm_pde = gmc_v9_0_get_vm_pde,
+       .get_vm_pte = gmc_v9_0_get_vm_pte
 };
 
 static void gmc_v9_0_set_gmc_funcs(struct amdgpu_device *adev)
@@ -664,6 +635,9 @@ static void gmc_v9_0_set_gmc_funcs(struct amdgpu_device *adev)
 static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
 {
        switch (adev->asic_type) {
+       case CHIP_VEGA10:
+               adev->umc.funcs = &umc_v6_0_funcs;
+               break;
        case CHIP_VEGA20:
                adev->umc.max_ras_err_cnt_per_query = UMC_V6_1_TOTAL_CHANNEL_NUM;
                adev->umc.channel_inst_num = UMC_V6_1_CHANNEL_INSTANCE_NUM;
@@ -681,7 +655,7 @@ static void gmc_v9_0_set_mmhub_funcs(struct amdgpu_device *adev)
 {
        switch (adev->asic_type) {
        case CHIP_VEGA20:
-               adev->mmhub_funcs = &mmhub_v1_0_funcs;
+               adev->mmhub.funcs = &mmhub_v1_0_funcs;
                break;
        default:
                break;
@@ -762,140 +736,10 @@ static int gmc_v9_0_allocate_vm_inv_eng(struct amdgpu_device *adev)
        return 0;
 }
 
-static int gmc_v9_0_ecc_ras_block_late_init(void *handle,
-                       struct ras_fs_if *fs_info, struct ras_common_if *ras_block)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ras_common_if **ras_if = NULL;
-       struct ras_ih_if ih_info = {
-               .cb = gmc_v9_0_process_ras_data_cb,
-       };
-       int r;
-
-       if (ras_block->block == AMDGPU_RAS_BLOCK__UMC)
-               ras_if = &adev->gmc.umc_ras_if;
-       else if (ras_block->block == AMDGPU_RAS_BLOCK__MMHUB)
-               ras_if = &adev->gmc.mmhub_ras_if;
-       else
-               BUG();
-
-       if (!amdgpu_ras_is_supported(adev, ras_block->block)) {
-               amdgpu_ras_feature_enable_on_boot(adev, ras_block, 0);
-               return 0;
-       }
-
-       /* handle resume path. */
-       if (*ras_if) {
-               /* resend ras TA enable cmd during resume.
-                * prepare to handle failure.
-                */
-               ih_info.head = **ras_if;
-               r = amdgpu_ras_feature_enable_on_boot(adev, *ras_if, 1);
-               if (r) {
-                       if (r == -EAGAIN) {
-                               /* request a gpu reset. will run again. */
-                               amdgpu_ras_request_reset_on_boot(adev,
-                                               ras_block->block);
-                               return 0;
-                       }
-                       /* fail to enable ras, cleanup all. */
-                       goto irq;
-               }
-               /* enable successfully. continue. */
-               goto resume;
-       }
-
-       *ras_if = kmalloc(sizeof(**ras_if), GFP_KERNEL);
-       if (!*ras_if)
-               return -ENOMEM;
-
-       **ras_if = *ras_block;
-
-       r = amdgpu_ras_feature_enable_on_boot(adev, *ras_if, 1);
-       if (r) {
-               if (r == -EAGAIN) {
-                       amdgpu_ras_request_reset_on_boot(adev,
-                                       ras_block->block);
-                       r = 0;
-               }
-               goto feature;
-       }
-
-       ih_info.head = **ras_if;
-       fs_info->head = **ras_if;
-
-       if (ras_block->block == AMDGPU_RAS_BLOCK__UMC) {
-               r = amdgpu_ras_interrupt_add_handler(adev, &ih_info);
-               if (r)
-                       goto interrupt;
-       }
-
-       amdgpu_ras_debugfs_create(adev, fs_info);
-
-       r = amdgpu_ras_sysfs_create(adev, fs_info);
-       if (r)
-               goto sysfs;
-resume:
-       if (ras_block->block == AMDGPU_RAS_BLOCK__UMC) {
-               r = amdgpu_irq_get(adev, &adev->gmc.ecc_irq, 0);
-               if (r)
-                       goto irq;
-       }
-
-       return 0;
-irq:
-       amdgpu_ras_sysfs_remove(adev, *ras_if);
-sysfs:
-       amdgpu_ras_debugfs_remove(adev, *ras_if);
-       if (ras_block->block == AMDGPU_RAS_BLOCK__UMC)
-               amdgpu_ras_interrupt_remove_handler(adev, &ih_info);
-interrupt:
-       amdgpu_ras_feature_enable(adev, *ras_if, 0);
-feature:
-       kfree(*ras_if);
-       *ras_if = NULL;
-       return r;
-}
-
-static int gmc_v9_0_ecc_late_init(void *handle)
-{
-       int r;
-
-       struct ras_fs_if umc_fs_info = {
-               .sysfs_name = "umc_err_count",
-               .debugfs_name = "umc_err_inject",
-       };
-       struct ras_common_if umc_ras_block = {
-               .block = AMDGPU_RAS_BLOCK__UMC,
-               .type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
-               .sub_block_index = 0,
-               .name = "umc",
-       };
-       struct ras_fs_if mmhub_fs_info = {
-               .sysfs_name = "mmhub_err_count",
-               .debugfs_name = "mmhub_err_inject",
-       };
-       struct ras_common_if mmhub_ras_block = {
-               .block = AMDGPU_RAS_BLOCK__MMHUB,
-               .type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
-               .sub_block_index = 0,
-               .name = "mmhub",
-       };
-
-       r = gmc_v9_0_ecc_ras_block_late_init(handle,
-                       &umc_fs_info, &umc_ras_block);
-       if (r)
-               return r;
-
-       r = gmc_v9_0_ecc_ras_block_late_init(handle,
-                       &mmhub_fs_info, &mmhub_ras_block);
-       return r;
-}
-
 static int gmc_v9_0_late_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       bool r;
+       int r;
 
        if (!gmc_v9_0_keep_stolen_memory(adev))
                amdgpu_bo_late_init(adev);
@@ -929,7 +773,7 @@ static int gmc_v9_0_late_init(void *handle)
                }
        }
 
-       r = gmc_v9_0_ecc_late_init(handle);
+       r = amdgpu_gmc_ras_late_init(adev);
        if (r)
                return r;
 
@@ -970,33 +814,11 @@ static void gmc_v9_0_vram_gtt_location(struct amdgpu_device *adev,
  */
 static int gmc_v9_0_mc_init(struct amdgpu_device *adev)
 {
-       int chansize, numchan;
        int r;
 
-       if (amdgpu_sriov_vf(adev)) {
-               /* For Vega10 SR-IOV, vram_width can't be read from ATOM as RAVEN,
-                * and DF related registers is not readable, seems hardcord is the
-                * only way to set the correct vram_width
-                */
-               adev->gmc.vram_width = 2048;
-       } else if (amdgpu_emu_mode != 1) {
-               adev->gmc.vram_width = amdgpu_atomfirmware_get_vram_width(adev);
-       }
-
-       if (!adev->gmc.vram_width) {
-               /* hbm memory channel size */
-               if (adev->flags & AMD_IS_APU)
-                       chansize = 64;
-               else
-                       chansize = 128;
-
-               numchan = adev->df_funcs->get_hbm_channel_number(adev);
-               adev->gmc.vram_width = numchan * chansize;
-       }
-
        /* size in MB on si */
        adev->gmc.mc_vram_size =
-               adev->nbio_funcs->get_memsize(adev) * 1024ULL * 1024ULL;
+               adev->nbio.funcs->get_memsize(adev) * 1024ULL * 1024ULL;
        adev->gmc.real_vram_size = adev->gmc.mc_vram_size;
 
        if (!(adev->flags & AMD_IS_APU)) {
@@ -1108,7 +930,7 @@ static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev)
 
 static int gmc_v9_0_sw_init(void *handle)
 {
-       int r;
+       int r, vram_width = 0, vram_type = 0, vram_vendor = 0;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
        gfxhub_v1_0_init(adev);
@@ -1119,7 +941,32 @@ static int gmc_v9_0_sw_init(void *handle)
 
        spin_lock_init(&adev->gmc.invalidate_lock);
 
-       adev->gmc.vram_type = amdgpu_atomfirmware_get_vram_type(adev);
+       r = amdgpu_atomfirmware_get_vram_info(adev,
+               &vram_width, &vram_type, &vram_vendor);
+       if (amdgpu_sriov_vf(adev))
+               /* For Vega10 SR-IOV, vram_width can't be read from ATOM as RAVEN,
+                * and DF related registers is not readable, seems hardcord is the
+                * only way to set the correct vram_width
+                */
+               adev->gmc.vram_width = 2048;
+       else if (amdgpu_emu_mode != 1)
+               adev->gmc.vram_width = vram_width;
+
+       if (!adev->gmc.vram_width) {
+               int chansize, numchan;
+
+               /* hbm memory channel size */
+               if (adev->flags & AMD_IS_APU)
+                       chansize = 64;
+               else
+                       chansize = 128;
+
+               numchan = adev->df_funcs->get_hbm_channel_number(adev);
+               adev->gmc.vram_width = numchan * chansize;
+       }
+
+       adev->gmc.vram_type = vram_type;
+       adev->gmc.vram_vendor = vram_vendor;
        switch (adev->asic_type) {
        case CHIP_RAVEN:
                adev->num_vmhubs = 2;
@@ -1240,33 +1087,7 @@ static int gmc_v9_0_sw_fini(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        void *stolen_vga_buf;
 
-       if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC) &&
-                       adev->gmc.umc_ras_if) {
-               struct ras_common_if *ras_if = adev->gmc.umc_ras_if;
-               struct ras_ih_if ih_info = {
-                       .head = *ras_if,
-               };
-
-               /* remove fs first */
-               amdgpu_ras_debugfs_remove(adev, ras_if);
-               amdgpu_ras_sysfs_remove(adev, ras_if);
-               /* remove the IH */
-               amdgpu_ras_interrupt_remove_handler(adev, &ih_info);
-               amdgpu_ras_feature_enable(adev, ras_if, 0);
-               kfree(ras_if);
-       }
-
-       if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__MMHUB) &&
-                       adev->gmc.mmhub_ras_if) {
-               struct ras_common_if *ras_if = adev->gmc.mmhub_ras_if;
-
-               /* remove fs and disable ras feature */
-               amdgpu_ras_debugfs_remove(adev, ras_if);
-               amdgpu_ras_sysfs_remove(adev, ras_if);
-               amdgpu_ras_feature_enable(adev, ras_if, 0);
-               kfree(ras_if);
-       }
-
+       amdgpu_gmc_ras_fini(adev);
        amdgpu_gem_force_release(adev);
        amdgpu_vm_manager_fini(adev);
 
@@ -1316,13 +1137,7 @@ static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev)
  */
 static int gmc_v9_0_gart_enable(struct amdgpu_device *adev)
 {
-       int r, i;
-       bool value;
-       u32 tmp;
-
-       amdgpu_device_program_register_sequence(adev,
-                                               golden_settings_vega10_hdp,
-                                               ARRAY_SIZE(golden_settings_vega10_hdp));
+       int r;
 
        if (adev->gart.bo == NULL) {
                dev_err(adev->dev, "No VRAM object for PCIE GART.\n");
@@ -1332,15 +1147,6 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev)
        if (r)
                return r;
 
-       switch (adev->asic_type) {
-       case CHIP_RAVEN:
-               /* TODO for renoir */
-               mmhub_v1_0_update_power_gating(adev, true);
-               break;
-       default:
-               break;
-       }
-
        r = gfxhub_v1_0_gart_enable(adev);
        if (r)
                return r;
@@ -1352,6 +1158,49 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev)
        if (r)
                return r;
 
+       DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+                (unsigned)(adev->gmc.gart_size >> 20),
+                (unsigned long long)amdgpu_bo_gpu_offset(adev->gart.bo));
+       adev->gart.ready = true;
+       return 0;
+}
+
+static int gmc_v9_0_hw_init(void *handle)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       bool value;
+       int r, i;
+       u32 tmp;
+
+       /* The sequence of these two function calls matters.*/
+       gmc_v9_0_init_golden_registers(adev);
+
+       if (adev->mode_info.num_crtc) {
+               if (adev->asic_type != CHIP_ARCTURUS) {
+                       /* Lockout access through VGA aperture*/
+                       WREG32_FIELD15(DCE, 0, VGA_HDP_CONTROL, VGA_MEMORY_DISABLE, 1);
+
+                       /* disable VGA render */
+                       WREG32_FIELD15(DCE, 0, VGA_RENDER_CONTROL, VGA_VSTATUS_CNTL, 0);
+               }
+       }
+
+       amdgpu_device_program_register_sequence(adev,
+                                               golden_settings_vega10_hdp,
+                                               ARRAY_SIZE(golden_settings_vega10_hdp));
+
+       switch (adev->asic_type) {
+       case CHIP_RAVEN:
+               /* TODO for renoir */
+               mmhub_v1_0_update_power_gating(adev, true);
+               break;
+       case CHIP_ARCTURUS:
+               WREG32_FIELD15(HDP, 0, HDP_MMHUB_CNTL, HDP_MMHUB_GCC, 1);
+               break;
+       default:
+               break;
+       }
+
        WREG32_FIELD15(HDP, 0, HDP_MISC_CNTL, FLUSH_INVALIDATE_CACHE, 1);
 
        tmp = RREG32_SOC15(HDP, 0, mmHDP_HOST_PATH_CNTL);
@@ -1361,7 +1210,7 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev)
        WREG32_SOC15(HDP, 0, mmHDP_NONSURFACE_BASE_HI, (adev->gmc.vram_start >> 40));
 
        /* After HDP is initialized, flush HDP.*/
-       adev->nbio_funcs->hdp_flush(adev, NULL);
+       adev->nbio.funcs->hdp_flush(adev, NULL);
 
        if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS)
                value = false;
@@ -1377,28 +1226,8 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev)
        for (i = 0; i < adev->num_vmhubs; ++i)
                gmc_v9_0_flush_gpu_tlb(adev, 0, i, 0);
 
-       DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
-                (unsigned)(adev->gmc.gart_size >> 20),
-                (unsigned long long)amdgpu_bo_gpu_offset(adev->gart.bo));
-       adev->gart.ready = true;
-       return 0;
-}
-
-static int gmc_v9_0_hw_init(void *handle)
-{
-       int r;
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       /* The sequence of these two function calls matters.*/
-       gmc_v9_0_init_golden_registers(adev);
-
-       if (adev->mode_info.num_crtc) {
-               /* Lockout access through VGA aperture*/
-               WREG32_FIELD15(DCE, 0, VGA_HDP_CONTROL, VGA_MEMORY_DISABLE, 1);
-
-               /* disable VGA render */
-               WREG32_FIELD15(DCE, 0, VGA_RENDER_CONTROL, VGA_VSTATUS_CNTL, 0);
-       }
+       if (adev->umc.funcs && adev->umc.funcs->init_registers)
+               adev->umc.funcs->init_registers(adev);
 
        r = gmc_v9_0_gart_enable(adev);
 
index 04cd4b6f95d48882bbe1e2289701deeeb88b7578..6965e1e6fa9e627eb57832e52c10146732243f46 100644 (file)
@@ -206,6 +206,8 @@ static void mmhub_v1_0_enable_system_domain(struct amdgpu_device *adev)
        tmp = RREG32_SOC15(MMHUB, 0, mmVM_CONTEXT0_CNTL);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL, ENABLE_CONTEXT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL, PAGE_TABLE_DEPTH, 0);
+       tmp = REG_SET_FIELD(tmp, VM_CONTEXT0_CNTL,
+                           RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0);
        WREG32_SOC15(MMHUB, 0, mmVM_CONTEXT0_CNTL, tmp);
 }
 
@@ -616,5 +618,6 @@ static void mmhub_v1_0_query_ras_error_count(struct amdgpu_device *adev,
 }
 
 const struct amdgpu_mmhub_funcs mmhub_v1_0_funcs = {
+       .ras_late_init = amdgpu_mmhub_ras_late_init,
        .query_ras_error_count = mmhub_v1_0_query_ras_error_count,
 };
index 3542c203c3c8f487a0f4dad537fc5f52cdbdf072..2eea702de8eee42eac2a09bb383c8ea8efcbe275 100644 (file)
 
 #include "soc15_common.h"
 
-static void mmhub_v2_0_init_gart_pt_regs(struct amdgpu_device *adev)
+void mmhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
+                               uint64_t page_table_base)
 {
-       uint64_t value = amdgpu_gmc_pd_addr(adev->gart.bo);
+       /* two registers distance between mmMMVM_CONTEXT0_* to mmMMVM_CONTEXT1_* */
+       int offset = mmMMVM_CONTEXT1_PAGE_TABLE_BASE_ADDR_LO32
+                       - mmMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32;
 
-       WREG32_SOC15(MMHUB, 0, mmMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
-                    lower_32_bits(value));
+       WREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
+                       offset * vmid, lower_32_bits(page_table_base));
 
-       WREG32_SOC15(MMHUB, 0, mmMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
-                    upper_32_bits(value));
+       WREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
+                       offset * vmid, upper_32_bits(page_table_base));
 }
 
 static void mmhub_v2_0_init_gart_aperture_regs(struct amdgpu_device *adev)
 {
-       mmhub_v2_0_init_gart_pt_regs(adev);
+       uint64_t pt_base = amdgpu_gmc_pd_addr(adev->gart.bo);
+
+       mmhub_v2_0_setup_vm_pt_regs(adev, 0, pt_base);
 
        WREG32_SOC15(MMHUB, 0, mmMMVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
                     (u32)(adev->gmc.gart_start >> 12));
@@ -152,6 +157,8 @@ static void mmhub_v2_0_enable_system_domain(struct amdgpu_device *adev)
        tmp = RREG32_SOC15(MMHUB, 0, mmMMVM_CONTEXT0_CNTL);
        tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT0_CNTL, ENABLE_CONTEXT, 1);
        tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT0_CNTL, PAGE_TABLE_DEPTH, 0);
+       tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT0_CNTL,
+                           RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0);
        WREG32_SOC15(MMHUB, 0, mmMMVM_CONTEXT0_CNTL, tmp);
 }
 
index db16f3ece2180991fb64649aa6c86049d4a80963..3ea4344f0315ca92c78c6a252adc7f2aab3bbff6 100644 (file)
@@ -31,5 +31,7 @@ void mmhub_v2_0_init(struct amdgpu_device *adev);
 int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev,
                               enum amd_clockgating_state state);
 void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u32 *flags);
+void mmhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
+                               uint64_t page_table_base);
 
 #endif
index 0cf7ef44b4b5c7015d018612a872fb32596b3a54..657970f9ebfbe8621ad5309f7308a0ab6e426fa5 100644 (file)
@@ -240,6 +240,8 @@ static void mmhub_v9_4_enable_system_domain(struct amdgpu_device *adev,
                                  hubid * MMHUB_INSTANCE_REGISTER_OFFSET);
        tmp = REG_SET_FIELD(tmp, VML2VC0_VM_CONTEXT0_CNTL, ENABLE_CONTEXT, 1);
        tmp = REG_SET_FIELD(tmp, VML2VC0_VM_CONTEXT0_CNTL, PAGE_TABLE_DEPTH, 0);
+       tmp = REG_SET_FIELD(tmp, VML2VC0_VM_CONTEXT0_CNTL,
+                           RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0);
        WREG32_SOC15_OFFSET(MMHUB, 0, mmVML2VC0_VM_CONTEXT0_CNTL,
                            hubid * MMHUB_INSTANCE_REGISTER_OFFSET, tmp);
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c
new file mode 100644 (file)
index 0000000..0d8767e
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "amdgpu.h"
+#include "nbio/nbio_2_3_offset.h"
+#include "nbio/nbio_2_3_sh_mask.h"
+#include "gc/gc_10_1_0_offset.h"
+#include "gc/gc_10_1_0_sh_mask.h"
+#include "soc15.h"
+#include "navi10_ih.h"
+#include "soc15_common.h"
+#include "mxgpu_nv.h"
+#include "mxgpu_ai.h"
+
+static void xgpu_nv_mailbox_send_ack(struct amdgpu_device *adev)
+{
+       WREG8(NV_MAIBOX_CONTROL_RCV_OFFSET_BYTE, 2);
+}
+
+static void xgpu_nv_mailbox_set_valid(struct amdgpu_device *adev, bool val)
+{
+       WREG8(NV_MAIBOX_CONTROL_TRN_OFFSET_BYTE, val ? 1 : 0);
+}
+
+/*
+ * this peek_msg could *only* be called in IRQ routine becuase in IRQ routine
+ * RCV_MSG_VALID filed of BIF_BX_PF_MAILBOX_CONTROL must already be set to 1
+ * by host.
+ *
+ * if called no in IRQ routine, this peek_msg cannot guaranteed to return the
+ * correct value since it doesn't return the RCV_DW0 under the case that
+ * RCV_MSG_VALID is set by host.
+ */
+static enum idh_event xgpu_nv_mailbox_peek_msg(struct amdgpu_device *adev)
+{
+       return RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0,
+                               mmBIF_BX_PF_MAILBOX_MSGBUF_RCV_DW0));
+}
+
+
+static int xgpu_nv_mailbox_rcv_msg(struct amdgpu_device *adev,
+                                  enum idh_event event)
+{
+       u32 reg;
+
+       reg = RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0,
+                                            mmBIF_BX_PF_MAILBOX_MSGBUF_RCV_DW0));
+       if (reg != event)
+               return -ENOENT;
+
+       xgpu_nv_mailbox_send_ack(adev);
+
+       return 0;
+}
+
+static uint8_t xgpu_nv_peek_ack(struct amdgpu_device *adev)
+{
+       return RREG8(NV_MAIBOX_CONTROL_TRN_OFFSET_BYTE) & 2;
+}
+
+static int xgpu_nv_poll_ack(struct amdgpu_device *adev)
+{
+       int timeout  = NV_MAILBOX_POLL_ACK_TIMEDOUT;
+       u8 reg;
+
+       do {
+               reg = RREG8(NV_MAIBOX_CONTROL_TRN_OFFSET_BYTE);
+               if (reg & 2)
+                       return 0;
+
+               mdelay(5);
+               timeout -= 5;
+       } while (timeout > 1);
+
+       pr_err("Doesn't get TRN_MSG_ACK from pf in %d msec\n", NV_MAILBOX_POLL_ACK_TIMEDOUT);
+
+       return -ETIME;
+}
+
+static int xgpu_nv_poll_msg(struct amdgpu_device *adev, enum idh_event event)
+{
+       int r, timeout = NV_MAILBOX_POLL_MSG_TIMEDOUT;
+
+       do {
+               r = xgpu_nv_mailbox_rcv_msg(adev, event);
+               if (!r)
+                       return 0;
+
+               msleep(10);
+               timeout -= 10;
+       } while (timeout > 1);
+
+       pr_err("Doesn't get msg:%d from pf, error=%d\n", event, r);
+
+       return -ETIME;
+}
+
+static void xgpu_nv_mailbox_trans_msg (struct amdgpu_device *adev,
+             enum idh_request req, u32 data1, u32 data2, u32 data3)
+{
+       u32 reg;
+       int r;
+       uint8_t trn;
+
+       /* IMPORTANT:
+        * clear TRN_MSG_VALID valid to clear host's RCV_MSG_ACK
+        * and with host's RCV_MSG_ACK cleared hw automatically clear host's RCV_MSG_ACK
+        * which lead to VF's TRN_MSG_ACK cleared, otherwise below xgpu_nv_poll_ack()
+        * will return immediatly
+        */
+       do {
+               xgpu_nv_mailbox_set_valid(adev, false);
+               trn = xgpu_nv_peek_ack(adev);
+               if (trn) {
+                       pr_err("trn=%x ACK should not assert! wait again !\n", trn);
+                       msleep(1);
+               }
+       } while (trn);
+
+       reg = RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0,
+                                            mmBIF_BX_PF_MAILBOX_MSGBUF_TRN_DW0));
+       reg = REG_SET_FIELD(reg, BIF_BX_PF_MAILBOX_MSGBUF_TRN_DW0,
+                           MSGBUF_DATA, req);
+       WREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_MSGBUF_TRN_DW0),
+                     reg);
+       WREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_MSGBUF_TRN_DW1),
+                               data1);
+       WREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_MSGBUF_TRN_DW2),
+                               data2);
+       WREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_MSGBUF_TRN_DW3),
+                               data3);
+
+       xgpu_nv_mailbox_set_valid(adev, true);
+
+       /* start to poll ack */
+       r = xgpu_nv_poll_ack(adev);
+       if (r)
+               pr_err("Doesn't get ack from pf, continue\n");
+
+       xgpu_nv_mailbox_set_valid(adev, false);
+}
+
+static int xgpu_nv_send_access_requests(struct amdgpu_device *adev,
+                                       enum idh_request req)
+{
+       int r;
+
+       xgpu_nv_mailbox_trans_msg(adev, req, 0, 0, 0);
+
+       /* start to check msg if request is idh_req_gpu_init_access */
+       if (req == IDH_REQ_GPU_INIT_ACCESS ||
+               req == IDH_REQ_GPU_FINI_ACCESS ||
+               req == IDH_REQ_GPU_RESET_ACCESS) {
+               r = xgpu_nv_poll_msg(adev, IDH_READY_TO_ACCESS_GPU);
+               if (r) {
+                       pr_err("Doesn't get READY_TO_ACCESS_GPU from pf, give up\n");
+                       return r;
+               }
+               /* Retrieve checksum from mailbox2 */
+               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_PF_MAILBOX_MSGBUF_RCV_DW2));
+               }
+       }
+
+       return 0;
+}
+
+static int xgpu_nv_request_reset(struct amdgpu_device *adev)
+{
+       return xgpu_nv_send_access_requests(adev, IDH_REQ_GPU_RESET_ACCESS);
+}
+
+static int xgpu_nv_request_full_gpu_access(struct amdgpu_device *adev,
+                                          bool init)
+{
+       enum idh_request req;
+
+       req = init ? IDH_REQ_GPU_INIT_ACCESS : IDH_REQ_GPU_FINI_ACCESS;
+       return xgpu_nv_send_access_requests(adev, req);
+}
+
+static int xgpu_nv_release_full_gpu_access(struct amdgpu_device *adev,
+                                          bool init)
+{
+       enum idh_request req;
+       int r = 0;
+
+       req = init ? IDH_REL_GPU_INIT_ACCESS : IDH_REL_GPU_FINI_ACCESS;
+       r = xgpu_nv_send_access_requests(adev, req);
+
+       return r;
+}
+
+static int xgpu_nv_mailbox_ack_irq(struct amdgpu_device *adev,
+                                       struct amdgpu_irq_src *source,
+                                       struct amdgpu_iv_entry *entry)
+{
+       DRM_DEBUG("get ack intr and do nothing.\n");
+       return 0;
+}
+
+static int xgpu_nv_set_mailbox_ack_irq(struct amdgpu_device *adev,
+                                       struct amdgpu_irq_src *source,
+                                       unsigned type,
+                                       enum amdgpu_interrupt_state state)
+{
+       u32 tmp = RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_INT_CNTL));
+
+       tmp = REG_SET_FIELD(tmp, BIF_BX_PF_MAILBOX_INT_CNTL, ACK_INT_EN,
+                               (state == AMDGPU_IRQ_STATE_ENABLE) ? 1 : 0);
+       WREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_INT_CNTL), tmp);
+
+       return 0;
+}
+
+static void xgpu_nv_mailbox_flr_work(struct work_struct *work)
+{
+       struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work);
+       struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt);
+       int timeout = NV_MAILBOX_POLL_FLR_TIMEDOUT;
+       int locked;
+
+       /* block amdgpu_gpu_recover till msg FLR COMPLETE received,
+        * otherwise the mailbox msg will be ruined/reseted by
+        * the VF FLR.
+        *
+        * we can unlock the lock_reset to allow "amdgpu_job_timedout"
+        * to run gpu_recover() after FLR_NOTIFICATION_CMPL received
+        * which means host side had finished this VF's FLR.
+        */
+       locked = mutex_trylock(&adev->lock_reset);
+       if (locked)
+               adev->in_gpu_reset = 1;
+
+       do {
+               if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL)
+                       goto flr_done;
+
+               msleep(10);
+               timeout -= 10;
+       } while (timeout > 1);
+
+flr_done:
+       if (locked) {
+               adev->in_gpu_reset = 0;
+               mutex_unlock(&adev->lock_reset);
+       }
+
+       /* Trigger recovery for world switch failure if no TDR */
+       if (amdgpu_device_should_recover_gpu(adev))
+               amdgpu_device_gpu_recover(adev, NULL);
+}
+
+static int xgpu_nv_set_mailbox_rcv_irq(struct amdgpu_device *adev,
+                                      struct amdgpu_irq_src *src,
+                                      unsigned type,
+                                      enum amdgpu_interrupt_state state)
+{
+       u32 tmp = RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_INT_CNTL));
+
+       tmp = REG_SET_FIELD(tmp, BIF_BX_PF_MAILBOX_INT_CNTL, VALID_INT_EN,
+                           (state == AMDGPU_IRQ_STATE_ENABLE) ? 1 : 0);
+       WREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_INT_CNTL), tmp);
+
+       return 0;
+}
+
+static int xgpu_nv_mailbox_rcv_irq(struct amdgpu_device *adev,
+                                  struct amdgpu_irq_src *source,
+                                  struct amdgpu_iv_entry *entry)
+{
+       enum idh_event event = xgpu_nv_mailbox_peek_msg(adev);
+
+       switch (event) {
+       case IDH_FLR_NOTIFICATION:
+               if (amdgpu_sriov_runtime(adev))
+                       schedule_work(&adev->virt.flr_work);
+               break;
+               /* READY_TO_ACCESS_GPU is fetched by kernel polling, IRQ can ignore
+                * it byfar since that polling thread will handle it,
+                * other msg like flr complete is not handled here.
+                */
+       case IDH_CLR_MSG_BUF:
+       case IDH_FLR_NOTIFICATION_CMPL:
+       case IDH_READY_TO_ACCESS_GPU:
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static const struct amdgpu_irq_src_funcs xgpu_nv_mailbox_ack_irq_funcs = {
+       .set = xgpu_nv_set_mailbox_ack_irq,
+       .process = xgpu_nv_mailbox_ack_irq,
+};
+
+static const struct amdgpu_irq_src_funcs xgpu_nv_mailbox_rcv_irq_funcs = {
+       .set = xgpu_nv_set_mailbox_rcv_irq,
+       .process = xgpu_nv_mailbox_rcv_irq,
+};
+
+void xgpu_nv_mailbox_set_irq_funcs(struct amdgpu_device *adev)
+{
+       adev->virt.ack_irq.num_types = 1;
+       adev->virt.ack_irq.funcs = &xgpu_nv_mailbox_ack_irq_funcs;
+       adev->virt.rcv_irq.num_types = 1;
+       adev->virt.rcv_irq.funcs = &xgpu_nv_mailbox_rcv_irq_funcs;
+}
+
+int xgpu_nv_mailbox_add_irq_id(struct amdgpu_device *adev)
+{
+       int r;
+
+       r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_BIF, 135, &adev->virt.rcv_irq);
+       if (r)
+               return r;
+
+       r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_BIF, 138, &adev->virt.ack_irq);
+       if (r) {
+               amdgpu_irq_put(adev, &adev->virt.rcv_irq, 0);
+               return r;
+       }
+
+       return 0;
+}
+
+int xgpu_nv_mailbox_get_irq(struct amdgpu_device *adev)
+{
+       int r;
+
+       r = amdgpu_irq_get(adev, &adev->virt.rcv_irq, 0);
+       if (r)
+               return r;
+       r = amdgpu_irq_get(adev, &adev->virt.ack_irq, 0);
+       if (r) {
+               amdgpu_irq_put(adev, &adev->virt.rcv_irq, 0);
+               return r;
+       }
+
+       INIT_WORK(&adev->virt.flr_work, xgpu_nv_mailbox_flr_work);
+
+       return 0;
+}
+
+void xgpu_nv_mailbox_put_irq(struct amdgpu_device *adev)
+{
+       amdgpu_irq_put(adev, &adev->virt.ack_irq, 0);
+       amdgpu_irq_put(adev, &adev->virt.rcv_irq, 0);
+}
+
+const struct amdgpu_virt_ops xgpu_nv_virt_ops = {
+       .req_full_gpu   = xgpu_nv_request_full_gpu_access,
+       .rel_full_gpu   = xgpu_nv_release_full_gpu_access,
+       .reset_gpu = xgpu_nv_request_reset,
+       .wait_reset = NULL,
+       .trans_msg = xgpu_nv_mailbox_trans_msg,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.h
new file mode 100644 (file)
index 0000000..99b15f6
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2014 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 __MXGPU_NV_H__
+#define __MXGPU_NV_H__
+
+#define NV_MAILBOX_POLL_ACK_TIMEDOUT   500
+#define NV_MAILBOX_POLL_MSG_TIMEDOUT   12000
+#define NV_MAILBOX_POLL_FLR_TIMEDOUT   500
+
+extern const struct amdgpu_virt_ops xgpu_nv_virt_ops;
+
+void xgpu_nv_mailbox_set_irq_funcs(struct amdgpu_device *adev);
+int xgpu_nv_mailbox_add_irq_id(struct amdgpu_device *adev);
+int xgpu_nv_mailbox_get_irq(struct amdgpu_device *adev);
+void xgpu_nv_mailbox_put_irq(struct amdgpu_device *adev);
+
+#define NV_MAIBOX_CONTROL_TRN_OFFSET_BYTE (SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_CONTROL) * 4)
+#define NV_MAIBOX_CONTROL_RCV_OFFSET_BYTE (SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF_MAILBOX_CONTROL) * 4 + 1)
+
+#endif
index 9fe08408db588fa6154567d9eba89760f78a7ce8..9af73567e716a62705c4f44b88f2b6a6d4f4f352 100644 (file)
@@ -117,7 +117,7 @@ static int navi10_ih_irq_init(struct amdgpu_device *adev)
        /* disable irqs */
        navi10_ih_disable_interrupts(adev);
 
-       adev->nbio_funcs->ih_control(adev);
+       adev->nbio.funcs->ih_control(adev);
 
        /* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/
        WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, ih->gpu_addr >> 8);
@@ -162,7 +162,7 @@ static int navi10_ih_irq_init(struct amdgpu_device *adev)
        }
        WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR, ih_doorbell_rtpr);
 
-       adev->nbio_funcs->ih_doorbell_range(adev, ih->use_doorbell,
+       adev->nbio.funcs->ih_doorbell_range(adev, ih->use_doorbell,
                                            ih->doorbell_index);
 
        tmp = RREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL);
index a56c93620e78621a1f0408de982bb5a3b7d4c46f..88efaecf9f70f1bfd9177ed22060abc8a75a3f77 100644 (file)
@@ -24,7 +24,6 @@
 #include "nv.h"
 
 #include "soc15_common.h"
-#include "soc15_hw_ip.h"
 #include "navi10_ip_offset.h"
 
 int navi10_reg_base_init(struct amdgpu_device *adev)
index cadc7603ca41aad4828d7975a51c69c58409f652..a786d159e5e99b1832ae2ad3a01061f26ee3c168 100644 (file)
@@ -24,7 +24,6 @@
 #include "nv.h"
 
 #include "soc15_common.h"
-#include "soc15_hw_ip.h"
 #include "navi12_ip_offset.h"
 
 int navi12_reg_base_init(struct amdgpu_device *adev)
index 3b5f0f65e0964ba2260424041053b4a28d19efb4..4ea1e8fbb6010f162b803b51e2d37a4510e683d5 100644 (file)
@@ -24,7 +24,6 @@
 #include "nv.h"
 
 #include "soc15_common.h"
-#include "soc15_hw_ip.h"
 #include "navi14_ip_offset.h"
 
 int navi14_reg_base_init(struct amdgpu_device *adev)
index c05d78d4efc667ce6443f9df6ef86332ed56acef..f3a3fe746222f39ff681212a40a10feb3777facb 100644 (file)
 #include "nbio/nbio_2_3_default.h"
 #include "nbio/nbio_2_3_offset.h"
 #include "nbio/nbio_2_3_sh_mask.h"
+#include <uapi/linux/kfd_ioctl.h>
 
 #define smnPCIE_CONFIG_CNTL    0x11180044
 #define smnCPM_CONTROL         0x11180460
 #define smnPCIE_CNTL2          0x11180070
 
+
+static void nbio_v2_3_remap_hdp_registers(struct amdgpu_device *adev)
+{
+       WREG32_SOC15(NBIO, 0, mmREMAP_HDP_MEM_FLUSH_CNTL,
+               adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL);
+       WREG32_SOC15(NBIO, 0, mmREMAP_HDP_REG_FLUSH_CNTL,
+               adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_REG_FLUSH_CNTL);
+}
+
 static u32 nbio_v2_3_get_rev_id(struct amdgpu_device *adev)
 {
        u32 tmp = RREG32_SOC15(NBIO, 0, mmRCC_DEV0_EPF0_STRAP0);
@@ -56,10 +66,9 @@ static void nbio_v2_3_hdp_flush(struct amdgpu_device *adev,
                                struct amdgpu_ring *ring)
 {
        if (!ring || !ring->funcs->emit_wreg)
-               WREG32_SOC15_NO_KIQ(NBIO, 0, mmBIF_BX_PF_HDP_MEM_COHERENCY_FLUSH_CNTL, 0);
+               WREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
        else
-               amdgpu_ring_emit_wreg(ring, SOC15_REG_OFFSET(
-                       NBIO, 0, mmBIF_BX_PF_HDP_MEM_COHERENCY_FLUSH_CNTL), 0);
+               amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
 }
 
 static u32 nbio_v2_3_get_memsize(struct amdgpu_device *adev)
@@ -311,7 +320,6 @@ static void nbio_v2_3_init_registers(struct amdgpu_device *adev)
 }
 
 const struct amdgpu_nbio_funcs nbio_v2_3_funcs = {
-       .hdp_flush_reg = &nbio_v2_3_hdp_flush_reg,
        .get_hdp_flush_req_offset = nbio_v2_3_get_hdp_flush_req_offset,
        .get_hdp_flush_done_offset = nbio_v2_3_get_hdp_flush_done_offset,
        .get_pcie_index_offset = nbio_v2_3_get_pcie_index_offset,
@@ -331,4 +339,5 @@ const struct amdgpu_nbio_funcs nbio_v2_3_funcs = {
        .ih_control = nbio_v2_3_ih_control,
        .init_registers = nbio_v2_3_init_registers,
        .detect_hw_virt = nbio_v2_3_detect_hw_virt,
+       .remap_hdp_registers = nbio_v2_3_remap_hdp_registers,
 };
index 5ae52085f6b7fde953dc8f36242f10ae5eec15c2..a43b60acf7f63fd396f3dc3987871da65f045d2a 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "soc15_common.h"
 
+extern const struct nbio_hdp_flush_reg nbio_v2_3_hdp_flush_reg;
 extern const struct amdgpu_nbio_funcs nbio_v2_3_funcs;
 
 #endif
index 6590143c3f7516ab1f532f5ad0a111b8005a8073..635d9e1fc0a364db991317bec42e6d6edccc29b1 100644 (file)
@@ -226,7 +226,7 @@ static u32 nbio_v6_1_get_pcie_data_offset(struct amdgpu_device *adev)
        return SOC15_REG_OFFSET(NBIO, 0, mmPCIE_DATA2);
 }
 
-static const struct nbio_hdp_flush_reg nbio_v6_1_hdp_flush_reg = {
+const struct nbio_hdp_flush_reg nbio_v6_1_hdp_flush_reg = {
        .ref_and_mask_cp0 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP0_MASK,
        .ref_and_mask_cp1 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP1_MASK,
        .ref_and_mask_cp2 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP2_MASK,
@@ -277,7 +277,6 @@ static void nbio_v6_1_init_registers(struct amdgpu_device *adev)
 }
 
 const struct amdgpu_nbio_funcs nbio_v6_1_funcs = {
-       .hdp_flush_reg = &nbio_v6_1_hdp_flush_reg,
        .get_hdp_flush_req_offset = nbio_v6_1_get_hdp_flush_req_offset,
        .get_hdp_flush_done_offset = nbio_v6_1_get_hdp_flush_done_offset,
        .get_pcie_index_offset = nbio_v6_1_get_pcie_index_offset,
index 0743a6f016f37cfb793166c54c78050c8d199d67..6dc743b732181dc1d8b05317526c611f0b3e5f89 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "soc15_common.h"
 
+extern const struct nbio_hdp_flush_reg nbio_v6_1_hdp_flush_reg;
 extern const struct amdgpu_nbio_funcs nbio_v6_1_funcs;
 
 #endif
index 74eecb768a82002c140196d80281016319ba3909..d6cbf26074bca475d915d1ac9f1d6b6c13665130 100644 (file)
@@ -292,7 +292,6 @@ static void nbio_v7_0_init_registers(struct amdgpu_device *adev)
 }
 
 const struct amdgpu_nbio_funcs nbio_v7_0_funcs = {
-       .hdp_flush_reg = &nbio_v7_0_hdp_flush_reg,
        .get_hdp_flush_req_offset = nbio_v7_0_get_hdp_flush_req_offset,
        .get_hdp_flush_done_offset = nbio_v7_0_get_hdp_flush_done_offset,
        .get_pcie_index_offset = nbio_v7_0_get_pcie_index_offset,
index 508d549c50291fc89a40539b2a33642275b74a0d..e7aefb252550b7efe6c8aad276699ce1fc2eebaf 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "soc15_common.h"
 
+extern const struct nbio_hdp_flush_reg nbio_v7_0_hdp_flush_reg;
 extern const struct amdgpu_nbio_funcs nbio_v7_0_funcs;
 
 #endif
index 910fffced43bb9ecabf4868b73c0c6b686b83f08..0db458f9fafcc2f3e1b924da2d2909eea03e9739 100644 (file)
 #include "amdgpu.h"
 #include "amdgpu_atombios.h"
 #include "nbio_v7_4.h"
+#include "amdgpu_ras.h"
 
 #include "nbio/nbio_7_4_offset.h"
 #include "nbio/nbio_7_4_sh_mask.h"
 #include "nbio/nbio_7_4_0_smn.h"
+#include "ivsrcid/nbio/irqsrcs_nbif_7_4.h"
 #include <uapi/linux/kfd_ioctl.h>
 
 #define smnNBIF_MGCG_CTRL_LCLK 0x1013a21c
@@ -266,7 +268,7 @@ static u32 nbio_v7_4_get_pcie_data_offset(struct amdgpu_device *adev)
        return SOC15_REG_OFFSET(NBIO, 0, mmPCIE_DATA2);
 }
 
-static const struct nbio_hdp_flush_reg nbio_v7_4_hdp_flush_reg = {
+const struct nbio_hdp_flush_reg nbio_v7_4_hdp_flush_reg = {
        .ref_and_mask_cp0 = GPU_HDP_FLUSH_DONE__CP0_MASK,
        .ref_and_mask_cp1 = GPU_HDP_FLUSH_DONE__CP1_MASK,
        .ref_and_mask_cp2 = GPU_HDP_FLUSH_DONE__CP2_MASK,
@@ -306,17 +308,208 @@ static void nbio_v7_4_detect_hw_virt(struct amdgpu_device *adev)
 
 static void nbio_v7_4_init_registers(struct amdgpu_device *adev)
 {
-       uint32_t def, data;
 
-       def = data = RREG32_PCIE(smnPCIE_CI_CNTL);
-       data = REG_SET_FIELD(data, PCIE_CI_CNTL, CI_SLV_ORDERING_DIS, 1);
+}
 
-       if (def != data)
-               WREG32_PCIE(smnPCIE_CI_CNTL, data);
+static void nbio_v7_4_handle_ras_controller_intr_no_bifring(struct amdgpu_device *adev)
+{
+       uint32_t bif_doorbell_intr_cntl;
+
+       bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL);
+       if (REG_GET_FIELD(bif_doorbell_intr_cntl,
+               BIF_DOORBELL_INT_CNTL, RAS_CNTLR_INTERRUPT_STATUS)) {
+               /* driver has to clear the interrupt status when bif ring is disabled */
+               bif_doorbell_intr_cntl = REG_SET_FIELD(bif_doorbell_intr_cntl,
+                                               BIF_DOORBELL_INT_CNTL,
+                                               RAS_CNTLR_INTERRUPT_CLEAR, 1);
+               WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, bif_doorbell_intr_cntl);
+
+               amdgpu_ras_global_ras_isr(adev);
+       }
+}
+
+static void nbio_v7_4_handle_ras_err_event_athub_intr_no_bifring(struct amdgpu_device *adev)
+{
+       uint32_t bif_doorbell_intr_cntl;
+
+       bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL);
+       if (REG_GET_FIELD(bif_doorbell_intr_cntl,
+               BIF_DOORBELL_INT_CNTL, RAS_ATHUB_ERR_EVENT_INTERRUPT_STATUS)) {
+               /* driver has to clear the interrupt status when bif ring is disabled */
+               bif_doorbell_intr_cntl = REG_SET_FIELD(bif_doorbell_intr_cntl,
+                                               BIF_DOORBELL_INT_CNTL,
+                                               RAS_ATHUB_ERR_EVENT_INTERRUPT_CLEAR, 1);
+               WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, bif_doorbell_intr_cntl);
+
+               amdgpu_ras_global_ras_isr(adev);
+       }
+}
+
+
+static int nbio_v7_4_set_ras_controller_irq_state(struct amdgpu_device *adev,
+                                                 struct amdgpu_irq_src *src,
+                                                 unsigned type,
+                                                 enum amdgpu_interrupt_state state)
+{
+       /* The ras_controller_irq enablement should be done in psp bl when it
+        * tries to enable ras feature. Driver only need to set the correct interrupt
+        * vector for bare-metal and sriov use case respectively
+        */
+       uint32_t bif_intr_cntl;
+
+       bif_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_INTR_CNTL);
+       if (state == AMDGPU_IRQ_STATE_ENABLE) {
+               /* set interrupt vector select bit to 0 to select
+                * vetcor 1 for bare metal case */
+               bif_intr_cntl = REG_SET_FIELD(bif_intr_cntl,
+                                             BIF_INTR_CNTL,
+                                             RAS_INTR_VEC_SEL, 0);
+               WREG32_SOC15(NBIO, 0, mmBIF_INTR_CNTL, bif_intr_cntl);
+       }
+
+       return 0;
+}
+
+static int nbio_v7_4_process_ras_controller_irq(struct amdgpu_device *adev,
+                                               struct amdgpu_irq_src *source,
+                                               struct amdgpu_iv_entry *entry)
+{
+       /* By design, the ih cookie for ras_controller_irq should be written
+        * to BIFring instead of general iv ring. However, due to known bif ring
+        * hw bug, it has to be disabled. There is no chance the process function
+        * will be involked. Just left it as a dummy one.
+        */
+       return 0;
+}
+
+static int nbio_v7_4_set_ras_err_event_athub_irq_state(struct amdgpu_device *adev,
+                                                      struct amdgpu_irq_src *src,
+                                                      unsigned type,
+                                                      enum amdgpu_interrupt_state state)
+{
+       /* The ras_controller_irq enablement should be done in psp bl when it
+        * tries to enable ras feature. Driver only need to set the correct interrupt
+        * vector for bare-metal and sriov use case respectively
+        */
+       uint32_t bif_intr_cntl;
+
+       bif_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_INTR_CNTL);
+       if (state == AMDGPU_IRQ_STATE_ENABLE) {
+               /* set interrupt vector select bit to 0 to select
+                * vetcor 1 for bare metal case */
+               bif_intr_cntl = REG_SET_FIELD(bif_intr_cntl,
+                                             BIF_INTR_CNTL,
+                                             RAS_INTR_VEC_SEL, 0);
+               WREG32_SOC15(NBIO, 0, mmBIF_INTR_CNTL, bif_intr_cntl);
+       }
+
+       return 0;
+}
+
+static int nbio_v7_4_process_err_event_athub_irq(struct amdgpu_device *adev,
+                                                struct amdgpu_irq_src *source,
+                                                struct amdgpu_iv_entry *entry)
+{
+       /* By design, the ih cookie for err_event_athub_irq should be written
+        * to BIFring instead of general iv ring. However, due to known bif ring
+        * hw bug, it has to be disabled. There is no chance the process function
+        * will be involked. Just left it as a dummy one.
+        */
+       return 0;
+}
+
+static const struct amdgpu_irq_src_funcs nbio_v7_4_ras_controller_irq_funcs = {
+       .set = nbio_v7_4_set_ras_controller_irq_state,
+       .process = nbio_v7_4_process_ras_controller_irq,
+};
+
+static const struct amdgpu_irq_src_funcs nbio_v7_4_ras_err_event_athub_irq_funcs = {
+       .set = nbio_v7_4_set_ras_err_event_athub_irq_state,
+       .process = nbio_v7_4_process_err_event_athub_irq,
+};
+
+static int nbio_v7_4_init_ras_controller_interrupt (struct amdgpu_device *adev)
+{
+       int r;
+
+       /* init the irq funcs */
+       adev->nbio.ras_controller_irq.funcs =
+               &nbio_v7_4_ras_controller_irq_funcs;
+       adev->nbio.ras_controller_irq.num_types = 1;
+
+       /* register ras controller interrupt */
+       r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_BIF,
+                             NBIF_7_4__SRCID__RAS_CONTROLLER_INTERRUPT,
+                             &adev->nbio.ras_controller_irq);
+       if (r)
+               return r;
+
+       return 0;
+}
+
+static int nbio_v7_4_init_ras_err_event_athub_interrupt (struct amdgpu_device *adev)
+{
+
+       int r;
+
+       /* init the irq funcs */
+       adev->nbio.ras_err_event_athub_irq.funcs =
+               &nbio_v7_4_ras_err_event_athub_irq_funcs;
+       adev->nbio.ras_err_event_athub_irq.num_types = 1;
+
+       /* register ras err event athub interrupt */
+       r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_BIF,
+                             NBIF_7_4__SRCID__ERREVENT_ATHUB_INTERRUPT,
+                             &adev->nbio.ras_err_event_athub_irq);
+       if (r)
+               return r;
+
+       return 0;
+}
+
+static void nbio_v7_4_query_ras_error_count(struct amdgpu_device *adev,
+                                       void *ras_error_status)
+{
+       uint32_t global_sts, central_sts, int_eoi;
+       uint32_t corr, fatal, non_fatal;
+       struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
+
+       global_sts = RREG32_PCIE(smnRAS_GLOBAL_STATUS_LO);
+       corr = REG_GET_FIELD(global_sts, RAS_GLOBAL_STATUS_LO, ParityErrCorr);
+       fatal = REG_GET_FIELD(global_sts, RAS_GLOBAL_STATUS_LO, ParityErrFatal);
+       non_fatal = REG_GET_FIELD(global_sts, RAS_GLOBAL_STATUS_LO,
+                               ParityErrNonFatal);
+
+       if (corr)
+               err_data->ce_count++;
+       if (fatal)
+               err_data->ue_count++;
+
+       if (corr || fatal || non_fatal) {
+               central_sts = RREG32_PCIE(smnBIFL_RAS_CENTRAL_STATUS);
+               /* clear error status register */
+               WREG32_PCIE(smnRAS_GLOBAL_STATUS_LO, global_sts);
+
+               if (REG_GET_FIELD(central_sts, BIFL_RAS_CENTRAL_STATUS,
+                               BIFL_RasContller_Intr_Recv)) {
+                       /* clear interrupt status register */
+                       WREG32_PCIE(smnBIFL_RAS_CENTRAL_STATUS, central_sts);
+                       int_eoi = RREG32_PCIE(smnIOHC_INTERRUPT_EOI);
+                       int_eoi = REG_SET_FIELD(int_eoi,
+                                       IOHC_INTERRUPT_EOI, SMI_EOI, 1);
+                       WREG32_PCIE(smnIOHC_INTERRUPT_EOI, int_eoi);
+               }
+       }
+}
+
+static void nbio_v7_4_enable_doorbell_interrupt(struct amdgpu_device *adev,
+                                               bool enable)
+{
+       WREG32_FIELD15(NBIO, 0, BIF_DOORBELL_INT_CNTL,
+                      DOORBELL_INTERRUPT_DISABLE, enable ? 0 : 1);
 }
 
 const struct amdgpu_nbio_funcs nbio_v7_4_funcs = {
-       .hdp_flush_reg = &nbio_v7_4_hdp_flush_reg,
        .get_hdp_flush_req_offset = nbio_v7_4_get_hdp_flush_req_offset,
        .get_hdp_flush_done_offset = nbio_v7_4_get_hdp_flush_done_offset,
        .get_pcie_index_offset = nbio_v7_4_get_pcie_index_offset,
@@ -330,6 +523,7 @@ const struct amdgpu_nbio_funcs nbio_v7_4_funcs = {
        .enable_doorbell_aperture = nbio_v7_4_enable_doorbell_aperture,
        .enable_doorbell_selfring_aperture = nbio_v7_4_enable_doorbell_selfring_aperture,
        .ih_doorbell_range = nbio_v7_4_ih_doorbell_range,
+       .enable_doorbell_interrupt = nbio_v7_4_enable_doorbell_interrupt,
        .update_medium_grain_clock_gating = nbio_v7_4_update_medium_grain_clock_gating,
        .update_medium_grain_light_sleep = nbio_v7_4_update_medium_grain_light_sleep,
        .get_clockgating_state = nbio_v7_4_get_clockgating_state,
@@ -337,4 +531,10 @@ const struct amdgpu_nbio_funcs nbio_v7_4_funcs = {
        .init_registers = nbio_v7_4_init_registers,
        .detect_hw_virt = nbio_v7_4_detect_hw_virt,
        .remap_hdp_registers = nbio_v7_4_remap_hdp_registers,
+       .handle_ras_controller_intr_no_bifring = nbio_v7_4_handle_ras_controller_intr_no_bifring,
+       .handle_ras_err_event_athub_intr_no_bifring = nbio_v7_4_handle_ras_err_event_athub_intr_no_bifring,
+       .init_ras_controller_interrupt = nbio_v7_4_init_ras_controller_interrupt,
+       .init_ras_err_event_athub_interrupt = nbio_v7_4_init_ras_err_event_athub_interrupt,
+       .query_ras_error_count = nbio_v7_4_query_ras_error_count,
+       .ras_late_init = amdgpu_nbio_ras_late_init,
 };
index c442865bac4f219d992cab9f62dae9d8ae4c0144..b1ac828727526367bfa3fc2313c1dfb63ec15a49 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "soc15_common.h"
 
+extern const struct nbio_hdp_flush_reg nbio_v7_4_hdp_flush_reg;
 extern const struct amdgpu_nbio_funcs nbio_v7_4_funcs;
 
 #endif
index de9b995b65b1aac85baa62371903d33c3f8c4d74..46206a1a1f4dcb372507897b68395c1e6b611e67 100644 (file)
@@ -46,6 +46,7 @@
 #include "gmc_v10_0.h"
 #include "gfxhub_v2_0.h"
 #include "mmhub_v2_0.h"
+#include "nbio_v2_3.h"
 #include "nv.h"
 #include "navi10_ih.h"
 #include "gfx_v10_0.h"
@@ -53,6 +54,7 @@
 #include "vcn_v2_0.h"
 #include "dce_virtual.h"
 #include "mes_v10_1.h"
+#include "mxgpu_nv.h"
 
 static const struct amd_ip_funcs nv_common_ip_funcs;
 
@@ -63,8 +65,8 @@ static u32 nv_pcie_rreg(struct amdgpu_device *adev, u32 reg)
 {
        unsigned long flags, address, data;
        u32 r;
-       address = adev->nbio_funcs->get_pcie_index_offset(adev);
-       data = adev->nbio_funcs->get_pcie_data_offset(adev);
+       address = adev->nbio.funcs->get_pcie_index_offset(adev);
+       data = adev->nbio.funcs->get_pcie_data_offset(adev);
 
        spin_lock_irqsave(&adev->pcie_idx_lock, flags);
        WREG32(address, reg);
@@ -78,8 +80,8 @@ static void nv_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
 {
        unsigned long flags, address, data;
 
-       address = adev->nbio_funcs->get_pcie_index_offset(adev);
-       data = adev->nbio_funcs->get_pcie_data_offset(adev);
+       address = adev->nbio.funcs->get_pcie_index_offset(adev);
+       data = adev->nbio.funcs->get_pcie_data_offset(adev);
 
        spin_lock_irqsave(&adev->pcie_idx_lock, flags);
        WREG32(address, reg);
@@ -119,7 +121,7 @@ static void nv_didt_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
 
 static u32 nv_get_config_memsize(struct amdgpu_device *adev)
 {
-       return adev->nbio_funcs->get_memsize(adev);
+       return adev->nbio.funcs->get_memsize(adev);
 }
 
 static u32 nv_get_xclk(struct amdgpu_device *adev)
@@ -279,7 +281,7 @@ static int nv_asic_mode1_reset(struct amdgpu_device *adev)
 
        /* wait for asic to come out of reset */
        for (i = 0; i < adev->usec_timeout; i++) {
-               u32 memsize = adev->nbio_funcs->get_memsize(adev);
+               u32 memsize = adev->nbio.funcs->get_memsize(adev);
 
                if (memsize != 0xffffffff)
                        break;
@@ -368,8 +370,8 @@ static void nv_program_aspm(struct amdgpu_device *adev)
 static void nv_enable_doorbell_aperture(struct amdgpu_device *adev,
                                        bool enable)
 {
-       adev->nbio_funcs->enable_doorbell_aperture(adev, enable);
-       adev->nbio_funcs->enable_doorbell_selfring_aperture(adev, enable);
+       adev->nbio.funcs->enable_doorbell_aperture(adev, enable);
+       adev->nbio.funcs->enable_doorbell_selfring_aperture(adev, enable);
 }
 
 static const struct amdgpu_ip_block_version nv_common_ip_block =
@@ -423,9 +425,13 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
        if (r)
                return r;
 
-       adev->nbio_funcs = &nbio_v2_3_funcs;
+       adev->nbio.funcs = &nbio_v2_3_funcs;
+       adev->nbio.hdp_flush_reg = &nbio_v2_3_hdp_flush_reg;
 
-       adev->nbio_funcs->detect_hw_virt(adev);
+       adev->nbio.funcs->detect_hw_virt(adev);
+
+       if (amdgpu_sriov_vf(adev))
+               adev->virt.ops = &xgpu_nv_virt_ops;
 
        switch (adev->asic_type) {
        case CHIP_NAVI10:
@@ -435,7 +441,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
                amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
                amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
                if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP &&
-                   is_support_sw_smu(adev))
+                   is_support_sw_smu(adev) && !amdgpu_sriov_vf(adev))
                        amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
                if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
                        amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
@@ -446,7 +452,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
                amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
                amdgpu_device_ip_block_add(adev, &sdma_v5_0_ip_block);
                if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT &&
-                   is_support_sw_smu(adev))
+                   is_support_sw_smu(adev) && !amdgpu_sriov_vf(adev))
                        amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
                amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
                if (adev->enable_mes)
@@ -458,7 +464,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
                amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
                amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
                if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP &&
-                   is_support_sw_smu(adev))
+                   is_support_sw_smu(adev) && !amdgpu_sriov_vf(adev))
                        amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
                if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
                        amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
@@ -469,7 +475,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
                amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
                amdgpu_device_ip_block_add(adev, &sdma_v5_0_ip_block);
                if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT &&
-                   is_support_sw_smu(adev))
+                   is_support_sw_smu(adev) && !amdgpu_sriov_vf(adev))
                        amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
                amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
                break;
@@ -482,12 +488,12 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 
 static uint32_t nv_get_rev_id(struct amdgpu_device *adev)
 {
-       return adev->nbio_funcs->get_rev_id(adev);
+       return adev->nbio.funcs->get_rev_id(adev);
 }
 
 static void nv_flush_hdp(struct amdgpu_device *adev, struct amdgpu_ring *ring)
 {
-       adev->nbio_funcs->hdp_flush(adev, ring);
+       adev->nbio.funcs->hdp_flush(adev, ring);
 }
 
 static void nv_invalidate_hdp(struct amdgpu_device *adev,
@@ -583,8 +589,11 @@ static const struct amdgpu_asic_funcs nv_asic_funcs =
 
 static int nv_common_early_init(void *handle)
 {
+#define MMIO_REG_HOLE_OFFSET (0x80000 - PAGE_SIZE)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       adev->rmmio_remap.reg_offset = MMIO_REG_HOLE_OFFSET;
+       adev->rmmio_remap.bus_addr = adev->rmmio_base + MMIO_REG_HOLE_OFFSET;
        adev->smc_rreg = NULL;
        adev->smc_wreg = NULL;
        adev->pcie_rreg = &nv_pcie_rreg;
@@ -667,16 +676,31 @@ static int nv_common_early_init(void *handle)
                return -EINVAL;
        }
 
+       if (amdgpu_sriov_vf(adev)) {
+               amdgpu_virt_init_setting(adev);
+               xgpu_nv_mailbox_set_irq_funcs(adev);
+       }
+
        return 0;
 }
 
 static int nv_common_late_init(void *handle)
 {
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       if (amdgpu_sriov_vf(adev))
+               xgpu_nv_mailbox_get_irq(adev);
+
        return 0;
 }
 
 static int nv_common_sw_init(void *handle)
 {
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       if (amdgpu_sriov_vf(adev))
+               xgpu_nv_mailbox_add_irq_id(adev);
+
        return 0;
 }
 
@@ -694,7 +718,13 @@ static int nv_common_hw_init(void *handle)
        /* enable aspm */
        nv_program_aspm(adev);
        /* setup nbio registers */
-       adev->nbio_funcs->init_registers(adev);
+       adev->nbio.funcs->init_registers(adev);
+       /* remap HDP registers to a hole in mmio space,
+        * for the purpose of expose those registers
+        * to process space
+        */
+       if (adev->nbio.funcs->remap_hdp_registers)
+               adev->nbio.funcs->remap_hdp_registers(adev);
        /* enable the doorbell aperture */
        nv_enable_doorbell_aperture(adev, true);
 
@@ -856,9 +886,9 @@ static int nv_common_set_clockgating_state(void *handle,
        case CHIP_NAVI10:
        case CHIP_NAVI14:
        case CHIP_NAVI12:
-               adev->nbio_funcs->update_medium_grain_clock_gating(adev,
+               adev->nbio.funcs->update_medium_grain_clock_gating(adev,
                                state == AMD_CG_STATE_GATE ? true : false);
-               adev->nbio_funcs->update_medium_grain_light_sleep(adev,
+               adev->nbio.funcs->update_medium_grain_light_sleep(adev,
                                state == AMD_CG_STATE_GATE ? true : false);
                nv_update_hdp_mem_power_gating(adev,
                                   state == AMD_CG_STATE_GATE ? true : false);
@@ -886,7 +916,7 @@ static void nv_common_get_clockgating_state(void *handle, u32 *flags)
        if (amdgpu_sriov_vf(adev))
                *flags = 0;
 
-       adev->nbio_funcs->get_clockgating_state(adev, flags);
+       adev->nbio.funcs->get_clockgating_state(adev, flags);
 
        /* AMD_CG_SUPPORT_HDP_MGCG */
        tmp = RREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL);
index 5d95e614369aaf3c3614a52f26c6ec8e94c1439b..b345e69ba2460d5850aadd67701909adcadfe731 100644 (file)
@@ -40,6 +40,9 @@
 MODULE_FIRMWARE("amdgpu/raven_asd.bin");
 MODULE_FIRMWARE("amdgpu/picasso_asd.bin");
 MODULE_FIRMWARE("amdgpu/raven2_asd.bin");
+MODULE_FIRMWARE("amdgpu/picasso_ta.bin");
+MODULE_FIRMWARE("amdgpu/raven2_ta.bin");
+MODULE_FIRMWARE("amdgpu/raven_ta.bin");
 
 static int psp_v10_0_init_microcode(struct psp_context *psp)
 {
@@ -48,7 +51,7 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
        char fw_name[30];
        int err = 0;
        const struct psp_firmware_header_v1_0 *hdr;
-
+       const struct ta_firmware_header_v1_0 *ta_hdr;
        DRM_DEBUG("\n");
 
        switch (adev->asic_type) {
@@ -79,7 +82,45 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
        adev->psp.asd_start_addr = (uint8_t *)hdr +
                                le32_to_cpu(hdr->header.ucode_array_offset_bytes);
 
+       snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
+       err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
+       if (err) {
+               release_firmware(adev->psp.ta_fw);
+               adev->psp.ta_fw = NULL;
+               dev_info(adev->dev,
+                        "psp v10.0: Failed to load firmware \"%s\"\n",
+                        fw_name);
+       } else {
+               err = amdgpu_ucode_validate(adev->psp.ta_fw);
+               if (err)
+                       goto out2;
+
+               ta_hdr = (const struct ta_firmware_header_v1_0 *)
+                                adev->psp.ta_fw->data;
+               adev->psp.ta_hdcp_ucode_version =
+                       le32_to_cpu(ta_hdr->ta_hdcp_ucode_version);
+               adev->psp.ta_hdcp_ucode_size =
+                       le32_to_cpu(ta_hdr->ta_hdcp_size_bytes);
+               adev->psp.ta_hdcp_start_addr =
+                       (uint8_t *)ta_hdr +
+                       le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
+
+               adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
+
+               adev->psp.ta_dtm_ucode_version =
+                       le32_to_cpu(ta_hdr->ta_dtm_ucode_version);
+               adev->psp.ta_dtm_ucode_size =
+                       le32_to_cpu(ta_hdr->ta_dtm_size_bytes);
+               adev->psp.ta_dtm_start_addr =
+                       (uint8_t *)adev->psp.ta_hdcp_start_addr +
+                       le32_to_cpu(ta_hdr->ta_dtm_offset_bytes);
+       }
+
        return 0;
+
+out2:
+       release_firmware(adev->psp.ta_fw);
+       adev->psp.ta_fw = NULL;
 out:
        if (err) {
                dev_err(adev->dev,
@@ -228,6 +269,7 @@ static int psp_v10_0_cmd_submit(struct psp_context *psp,
        write_frame->fence_addr_hi = upper_32_bits(fence_mc_addr);
        write_frame->fence_addr_lo = lower_32_bits(fence_mc_addr);
        write_frame->fence_value = index;
+       amdgpu_asic_flush_hdp(adev, NULL);
 
        /* Update the write Pointer in DWORDs */
        psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw;
index 10166104b8a39a7bd4acd1f0fa295b96c04147cc..ace6e6c5629ccfe3848e601419722c1b5bb7c844 100644 (file)
@@ -49,6 +49,7 @@ MODULE_FIRMWARE("amdgpu/navi12_sos.bin");
 MODULE_FIRMWARE("amdgpu/navi12_asd.bin");
 MODULE_FIRMWARE("amdgpu/arcturus_sos.bin");
 MODULE_FIRMWARE("amdgpu/arcturus_asd.bin");
+MODULE_FIRMWARE("amdgpu/arcturus_ta.bin");
 
 /* address block */
 #define smnMP1_FIRMWARE_FLAGS          0x3010024
@@ -57,6 +58,8 @@ MODULE_FIRMWARE("amdgpu/arcturus_asd.bin");
 #define mmRLC_GPM_UCODE_DATA_NV10      0x5b62
 #define mmSDMA0_UCODE_ADDR_NV10                0x5880
 #define mmSDMA0_UCODE_DATA_NV10                0x5881
+/* memory training timeout define */
+#define MEM_TRAIN_SEND_MSG_TIMEOUT_US  3000000
 
 static int psp_v11_0_init_microcode(struct psp_context *psp)
 {
@@ -155,6 +158,7 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
 
        switch (adev->asic_type) {
        case CHIP_VEGA20:
+       case CHIP_ARCTURUS:
                snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
                err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
                if (err) {
@@ -182,7 +186,6 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
        case CHIP_NAVI10:
        case CHIP_NAVI14:
        case CHIP_NAVI12:
-       case CHIP_ARCTURUS:
                break;
        default:
                BUG();
@@ -205,18 +208,26 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
        return err;
 }
 
+static bool psp_v11_0_is_sos_alive(struct psp_context *psp)
+{
+       struct amdgpu_device *adev = psp->adev;
+       uint32_t sol_reg;
+
+       sol_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81);
+
+       return sol_reg != 0x0;
+}
+
 static int psp_v11_0_bootloader_load_kdb(struct psp_context *psp)
 {
        int ret;
        uint32_t psp_gfxdrv_command_reg = 0;
        struct amdgpu_device *adev = psp->adev;
-       uint32_t sol_reg;
 
        /* Check tOS 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) {
+       if (psp_v11_0_is_sos_alive(psp)) {
                psp->sos_fw_version = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_58);
                dev_info(adev->dev, "sos fw version = 0x%x.\n", psp->sos_fw_version);
                return 0;
@@ -252,13 +263,11 @@ static int psp_v11_0_bootloader_load_sysdrv(struct psp_context *psp)
        int ret;
        uint32_t psp_gfxdrv_command_reg = 0;
        struct amdgpu_device *adev = psp->adev;
-       uint32_t sol_reg;
 
        /* 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) {
+       if (psp_v11_0_is_sos_alive(psp)) {
                psp->sos_fw_version = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_58);
                dev_info(adev->dev, "sos fw version = 0x%x.\n", psp->sos_fw_version);
                return 0;
@@ -296,13 +305,11 @@ static int psp_v11_0_bootloader_load_sos(struct psp_context *psp)
        int ret;
        unsigned int psp_gfxdrv_command_reg = 0;
        struct amdgpu_device *adev = psp->adev;
-       uint32_t sol_reg;
 
        /* 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)
+       if (psp_v11_0_is_sos_alive(psp))
                return 0;
 
        /* Wait for bootloader to signify that is ready having bit 31 of C2PMSG_35 set to 1 */
@@ -398,6 +405,34 @@ static bool psp_v11_0_support_vmr_ring(struct psp_context *psp)
        return false;
 }
 
+static int psp_v11_0_ring_stop(struct psp_context *psp,
+                             enum psp_ring_type ring_type)
+{
+       int ret = 0;
+       struct amdgpu_device *adev = psp->adev;
+
+       /* Write the ring destroy command*/
+       if (psp_v11_0_support_vmr_ring(psp))
+               WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101,
+                                    GFX_CTRL_CMD_ID_DESTROY_GPCOM_RING);
+       else
+               WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64,
+                                    GFX_CTRL_CMD_ID_DESTROY_RINGS);
+
+       /* there might be handshake issue with hardware which needs delay */
+       mdelay(20);
+
+       /* Wait for response flag (bit 31) */
+       if (psp_v11_0_support_vmr_ring(psp))
+               ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
+                                  0x80000000, 0x80000000, false);
+       else
+               ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
+                                  0x80000000, 0x80000000, false);
+
+       return ret;
+}
+
 static int psp_v11_0_ring_create(struct psp_context *psp,
                                enum psp_ring_type ring_type)
 {
@@ -407,6 +442,12 @@ static int psp_v11_0_ring_create(struct psp_context *psp,
        struct amdgpu_device *adev = psp->adev;
 
        if (psp_v11_0_support_vmr_ring(psp)) {
+               ret = psp_v11_0_ring_stop(psp, ring_type);
+               if (ret) {
+                       DRM_ERROR("psp_v11_0_ring_stop_sriov failed!\n");
+                       return ret;
+               }
+
                /* Write low address of the ring to C2PMSG_102 */
                psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr);
                WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, psp_ring_reg);
@@ -451,33 +492,6 @@ static int psp_v11_0_ring_create(struct psp_context *psp,
        return ret;
 }
 
-static int psp_v11_0_ring_stop(struct psp_context *psp,
-                             enum psp_ring_type ring_type)
-{
-       int ret = 0;
-       struct amdgpu_device *adev = psp->adev;
-
-       /* Write the ring destroy command*/
-       if (psp_v11_0_support_vmr_ring(psp))
-               WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101,
-                                    GFX_CTRL_CMD_ID_DESTROY_GPCOM_RING);
-       else
-               WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64,
-                                    GFX_CTRL_CMD_ID_DESTROY_RINGS);
-
-       /* there might be handshake issue with hardware which needs delay */
-       mdelay(20);
-
-       /* Wait for response flag (bit 31) */
-       if (psp_v11_0_support_vmr_ring(psp))
-               ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
-                                  0x80000000, 0x80000000, false);
-       else
-               ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
-                                  0x80000000, 0x80000000, false);
-
-       return ret;
-}
 
 static int psp_v11_0_ring_destroy(struct psp_context *psp,
                                 enum psp_ring_type ring_type)
@@ -541,6 +555,7 @@ static int psp_v11_0_cmd_submit(struct psp_context *psp,
        write_frame->fence_addr_hi = upper_32_bits(fence_mc_addr);
        write_frame->fence_addr_lo = lower_32_bits(fence_mc_addr);
        write_frame->fence_value = index;
+       amdgpu_asic_flush_hdp(adev, NULL);
 
        /* Update the write Pointer in DWORDs */
        psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw;
@@ -889,6 +904,162 @@ static int psp_v11_0_rlc_autoload_start(struct psp_context *psp)
        return psp_rlc_autoload_start(psp);
 }
 
+static int psp_v11_0_memory_training_send_msg(struct psp_context *psp, int msg)
+{
+       int ret;
+       int i;
+       uint32_t data_32;
+       int max_wait;
+       struct amdgpu_device *adev = psp->adev;
+
+       data_32 = (psp->mem_train_ctx.c2p_train_data_offset >> 20);
+       WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, data_32);
+       WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, msg);
+
+       max_wait = MEM_TRAIN_SEND_MSG_TIMEOUT_US / adev->usec_timeout;
+       for (i = 0; i < max_wait; i++) {
+               ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
+                                  0x80000000, 0x80000000, false);
+               if (ret == 0)
+                       break;
+       }
+       if (i < max_wait)
+               ret = 0;
+       else
+               ret = -ETIME;
+
+       DRM_DEBUG("training %s %s, cost %d @ %d ms\n",
+                 (msg == PSP_BL__DRAM_SHORT_TRAIN) ? "short" : "long",
+                 (ret == 0) ? "succeed" : "failed",
+                 i, adev->usec_timeout/1000);
+       return ret;
+}
+
+static void psp_v11_0_memory_training_fini(struct psp_context *psp)
+{
+       struct psp_memory_training_context *ctx = &psp->mem_train_ctx;
+
+       ctx->init = PSP_MEM_TRAIN_NOT_SUPPORT;
+       kfree(ctx->sys_cache);
+       ctx->sys_cache = NULL;
+}
+
+static int psp_v11_0_memory_training_init(struct psp_context *psp)
+{
+       int ret;
+       struct psp_memory_training_context *ctx = &psp->mem_train_ctx;
+
+       if (ctx->init != PSP_MEM_TRAIN_RESERVE_SUCCESS) {
+               DRM_DEBUG("memory training is not supported!\n");
+               return 0;
+       }
+
+       ctx->sys_cache = kzalloc(ctx->train_data_size, GFP_KERNEL);
+       if (ctx->sys_cache == NULL) {
+               DRM_ERROR("alloc mem_train_ctx.sys_cache failed!\n");
+               ret = -ENOMEM;
+               goto Err_out;
+       }
+
+       DRM_DEBUG("train_data_size:%llx,p2c_train_data_offset:%llx,c2p_train_data_offset:%llx.\n",
+                 ctx->train_data_size,
+                 ctx->p2c_train_data_offset,
+                 ctx->c2p_train_data_offset);
+       ctx->init = PSP_MEM_TRAIN_INIT_SUCCESS;
+       return 0;
+
+Err_out:
+       psp_v11_0_memory_training_fini(psp);
+       return ret;
+}
+
+/*
+ * save and restore proces
+ */
+static int psp_v11_0_memory_training(struct psp_context *psp, uint32_t ops)
+{
+       int ret;
+       uint32_t p2c_header[4];
+       struct psp_memory_training_context *ctx = &psp->mem_train_ctx;
+       uint32_t *pcache = (uint32_t*)ctx->sys_cache;
+
+       if (ctx->init == PSP_MEM_TRAIN_NOT_SUPPORT) {
+               DRM_DEBUG("Memory training is not supported.\n");
+               return 0;
+       } else if (ctx->init != PSP_MEM_TRAIN_INIT_SUCCESS) {
+               DRM_ERROR("Memory training initialization failure.\n");
+               return -EINVAL;
+       }
+
+       if (psp_v11_0_is_sos_alive(psp)) {
+               DRM_DEBUG("SOS is alive, skip memory training.\n");
+               return 0;
+       }
+
+       amdgpu_device_vram_access(psp->adev, ctx->p2c_train_data_offset, p2c_header, sizeof(p2c_header), false);
+       DRM_DEBUG("sys_cache[%08x,%08x,%08x,%08x] p2c_header[%08x,%08x,%08x,%08x]\n",
+                 pcache[0], pcache[1], pcache[2], pcache[3],
+                 p2c_header[0], p2c_header[1], p2c_header[2], p2c_header[3]);
+
+       if (ops & PSP_MEM_TRAIN_SEND_SHORT_MSG) {
+               DRM_DEBUG("Short training depends on restore.\n");
+               ops |= PSP_MEM_TRAIN_RESTORE;
+       }
+
+       if ((ops & PSP_MEM_TRAIN_RESTORE) &&
+           pcache[0] != MEM_TRAIN_SYSTEM_SIGNATURE) {
+               DRM_DEBUG("sys_cache[0] is invalid, restore depends on save.\n");
+               ops |= PSP_MEM_TRAIN_SAVE;
+       }
+
+       if (p2c_header[0] == MEM_TRAIN_SYSTEM_SIGNATURE &&
+           !(pcache[0] == MEM_TRAIN_SYSTEM_SIGNATURE &&
+             pcache[3] == p2c_header[3])) {
+               DRM_DEBUG("sys_cache is invalid or out-of-date, need save training data to sys_cache.\n");
+               ops |= PSP_MEM_TRAIN_SAVE;
+       }
+
+       if ((ops & PSP_MEM_TRAIN_SAVE) &&
+           p2c_header[0] != MEM_TRAIN_SYSTEM_SIGNATURE) {
+               DRM_DEBUG("p2c_header[0] is invalid, save depends on long training.\n");
+               ops |= PSP_MEM_TRAIN_SEND_LONG_MSG;
+       }
+
+       if (ops & PSP_MEM_TRAIN_SEND_LONG_MSG) {
+               ops &= ~PSP_MEM_TRAIN_SEND_SHORT_MSG;
+               ops |= PSP_MEM_TRAIN_SAVE;
+       }
+
+       DRM_DEBUG("Memory training ops:%x.\n", ops);
+
+       if (ops & PSP_MEM_TRAIN_SEND_LONG_MSG) {
+               ret = psp_v11_0_memory_training_send_msg(psp, PSP_BL__DRAM_LONG_TRAIN);
+               if (ret) {
+                       DRM_ERROR("Send long training msg failed.\n");
+                       return ret;
+               }
+       }
+
+       if (ops & PSP_MEM_TRAIN_SAVE) {
+               amdgpu_device_vram_access(psp->adev, ctx->p2c_train_data_offset, ctx->sys_cache, ctx->train_data_size, false);
+       }
+
+       if (ops & PSP_MEM_TRAIN_RESTORE) {
+               amdgpu_device_vram_access(psp->adev, ctx->c2p_train_data_offset, ctx->sys_cache, ctx->train_data_size, true);
+       }
+
+       if (ops & PSP_MEM_TRAIN_SEND_SHORT_MSG) {
+               ret = psp_v11_0_memory_training_send_msg(psp, (amdgpu_force_long_training > 0) ?
+                                                        PSP_BL__DRAM_LONG_TRAIN : PSP_BL__DRAM_SHORT_TRAIN);
+               if (ret) {
+                       DRM_ERROR("send training msg failed.\n");
+                       return ret;
+               }
+       }
+       ctx->training_cnt++;
+       return 0;
+}
+
 static const struct psp_funcs psp_v11_0_funcs = {
        .init_microcode = psp_v11_0_init_microcode,
        .bootloader_load_kdb = psp_v11_0_bootloader_load_kdb,
@@ -909,6 +1080,9 @@ static const struct psp_funcs psp_v11_0_funcs = {
        .ras_trigger_error = psp_v11_0_ras_trigger_error,
        .ras_cure_posion = psp_v11_0_ras_cure_posion,
        .rlc_autoload_start = psp_v11_0_rlc_autoload_start,
+       .mem_training_init = psp_v11_0_memory_training_init,
+       .mem_training_fini = psp_v11_0_memory_training_fini,
+       .mem_training = psp_v11_0_memory_training,
 };
 
 void psp_v11_0_set_psp_funcs(struct psp_context *psp)
index c72e43f8e0be3fafc5352207466503b43e132504..8f553f6f92d61b1a117b485e4a667fd0415d5f48 100644 (file)
@@ -378,6 +378,7 @@ static int psp_v12_0_cmd_submit(struct psp_context *psp,
        write_frame->fence_addr_hi = upper_32_bits(fence_mc_addr);
        write_frame->fence_addr_lo = lower_32_bits(fence_mc_addr);
        write_frame->fence_value = index;
+       amdgpu_asic_flush_hdp(adev, NULL);
 
        /* Update the write Pointer in DWORDs */
        psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw;
index d2c727f6a8bd460c7f4baa02425d370535739070..fdc00938327b8b60e73c9e93429862f76dd64cb9 100644 (file)
@@ -454,6 +454,7 @@ static int psp_v3_1_cmd_submit(struct psp_context *psp,
        write_frame->fence_addr_hi = upper_32_bits(fence_mc_addr);
        write_frame->fence_addr_lo = lower_32_bits(fence_mc_addr);
        write_frame->fence_value = index;
+       amdgpu_asic_flush_hdp(adev, NULL);
 
        /* Update the write Pointer in DWORDs */
        psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw;
index 78452cf0115df0dc5ad41d93a167c3c83b40db8c..4fb9f19298096ee4d8809d7290a3c33a87377235 100644 (file)
@@ -746,13 +746,13 @@ static void sdma_v4_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
 {
        struct amdgpu_device *adev = ring->adev;
        u32 ref_and_mask = 0;
-       const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio_funcs->hdp_flush_reg;
+       const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio.hdp_flush_reg;
 
        ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0 << ring->me;
 
        sdma_v4_0_wait_reg_mem(ring, 0, 1,
-                              adev->nbio_funcs->get_hdp_flush_done_offset(adev),
-                              adev->nbio_funcs->get_hdp_flush_req_offset(adev),
+                              adev->nbio.funcs->get_hdp_flush_done_offset(adev),
+                              adev->nbio.funcs->get_hdp_flush_req_offset(adev),
                               ref_and_mask, ref_and_mask, 10);
 }
 
@@ -1690,102 +1690,17 @@ static int sdma_v4_0_early_init(void *handle)
 }
 
 static int sdma_v4_0_process_ras_data_cb(struct amdgpu_device *adev,
-               struct ras_err_data *err_data,
+               void *err_data,
                struct amdgpu_iv_entry *entry);
 
 static int sdma_v4_0_late_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct ras_common_if **ras_if = &adev->sdma.ras_if;
        struct ras_ih_if ih_info = {
                .cb = sdma_v4_0_process_ras_data_cb,
        };
-       struct ras_fs_if fs_info = {
-               .sysfs_name = "sdma_err_count",
-               .debugfs_name = "sdma_err_inject",
-       };
-       struct ras_common_if ras_block = {
-               .block = AMDGPU_RAS_BLOCK__SDMA,
-               .type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
-               .sub_block_index = 0,
-               .name = "sdma",
-       };
-       int r, i;
-
-       if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__SDMA)) {
-               amdgpu_ras_feature_enable_on_boot(adev, &ras_block, 0);
-               return 0;
-       }
-
-       /* handle resume path. */
-       if (*ras_if) {
-               /* resend ras TA enable cmd during resume.
-                * prepare to handle failure.
-                */
-               ih_info.head = **ras_if;
-               r = amdgpu_ras_feature_enable_on_boot(adev, *ras_if, 1);
-               if (r) {
-                       if (r == -EAGAIN) {
-                               /* request a gpu reset. will run again. */
-                               amdgpu_ras_request_reset_on_boot(adev,
-                                               AMDGPU_RAS_BLOCK__SDMA);
-                               return 0;
-                       }
-                       /* fail to enable ras, cleanup all. */
-                       goto irq;
-               }
-               /* enable successfully. continue. */
-               goto resume;
-       }
-
-       *ras_if = kmalloc(sizeof(**ras_if), GFP_KERNEL);
-       if (!*ras_if)
-               return -ENOMEM;
-
-       **ras_if = ras_block;
-
-       r = amdgpu_ras_feature_enable_on_boot(adev, *ras_if, 1);
-       if (r) {
-               if (r == -EAGAIN) {
-                       amdgpu_ras_request_reset_on_boot(adev,
-                                       AMDGPU_RAS_BLOCK__SDMA);
-                       r = 0;
-               }
-               goto feature;
-       }
 
-       ih_info.head = **ras_if;
-       fs_info.head = **ras_if;
-
-       r = amdgpu_ras_interrupt_add_handler(adev, &ih_info);
-       if (r)
-               goto interrupt;
-
-       amdgpu_ras_debugfs_create(adev, &fs_info);
-
-       r = amdgpu_ras_sysfs_create(adev, &fs_info);
-       if (r)
-               goto sysfs;
-resume:
-       for (i = 0; i < adev->sdma.num_instances; i++) {
-               r = amdgpu_irq_get(adev, &adev->sdma.ecc_irq,
-                                  AMDGPU_SDMA_IRQ_INSTANCE0 + i);
-               if (r)
-                       goto irq;
-       }
-
-       return 0;
-irq:
-       amdgpu_ras_sysfs_remove(adev, *ras_if);
-sysfs:
-       amdgpu_ras_debugfs_remove(adev, *ras_if);
-       amdgpu_ras_interrupt_remove_handler(adev, &ih_info);
-interrupt:
-       amdgpu_ras_feature_enable(adev, *ras_if, 0);
-feature:
-       kfree(*ras_if);
-       *ras_if = NULL;
-       return r;
+       return amdgpu_sdma_ras_late_init(adev, &ih_info);
 }
 
 static int sdma_v4_0_sw_init(void *handle)
@@ -1857,21 +1772,7 @@ static int sdma_v4_0_sw_fini(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        int i;
 
-       if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__SDMA) &&
-                       adev->sdma.ras_if) {
-               struct ras_common_if *ras_if = adev->sdma.ras_if;
-               struct ras_ih_if ih_info = {
-                       .head = *ras_if,
-               };
-
-               /*remove fs first*/
-               amdgpu_ras_debugfs_remove(adev, ras_if);
-               amdgpu_ras_sysfs_remove(adev, ras_if);
-               /*remove the IH*/
-               amdgpu_ras_interrupt_remove_handler(adev, &ih_info);
-               amdgpu_ras_feature_enable(adev, ras_if, 0);
-               kfree(ras_if);
-       }
+       amdgpu_sdma_ras_fini(adev);
 
        for (i = 0; i < adev->sdma.num_instances; i++) {
                amdgpu_ring_fini(&adev->sdma.instance[i].ring);
@@ -1891,7 +1792,7 @@ static int sdma_v4_0_hw_init(void *handle)
 
        if ((adev->asic_type == CHIP_RAVEN && adev->powerplay.pp_funcs &&
                        adev->powerplay.pp_funcs->set_powergating_by_smu) ||
-                       adev->asic_type == CHIP_RENOIR)
+                       (adev->asic_type == CHIP_RENOIR && !adev->in_gpu_reset))
                amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_SDMA, false);
 
        if (!amdgpu_sriov_vf(adev))
@@ -2024,52 +1925,28 @@ static int sdma_v4_0_process_trap_irq(struct amdgpu_device *adev,
 }
 
 static int sdma_v4_0_process_ras_data_cb(struct amdgpu_device *adev,
-               struct ras_err_data *err_data,
+               void *err_data,
                struct amdgpu_iv_entry *entry)
 {
-       uint32_t err_source;
        int instance;
 
+       /* When “Full RAS” is enabled, the per-IP interrupt sources should
+        * be disabled and the driver should only look for the aggregated
+        * interrupt via sync flood
+        */
+       if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX))
+               goto out;
+
        instance = sdma_v4_0_irq_id_to_seq(entry->client_id);
        if (instance < 0)
-               return 0;
-
-       switch (entry->src_id) {
-       case SDMA0_4_0__SRCID__SDMA_SRAM_ECC:
-               err_source = 0;
-               break;
-       case SDMA0_4_0__SRCID__SDMA_ECC:
-               err_source = 1;
-               break;
-       default:
-               return 0;
-       }
-
-       kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
+               goto out;
 
-       amdgpu_ras_reset_gpu(adev, 0);
+       amdgpu_sdma_process_ras_data_cb(adev, err_data, entry);
 
+out:
        return AMDGPU_RAS_SUCCESS;
 }
 
-static int sdma_v4_0_process_ecc_irq(struct amdgpu_device *adev,
-                                     struct amdgpu_irq_src *source,
-                                     struct amdgpu_iv_entry *entry)
-{
-       struct ras_common_if *ras_if = adev->sdma.ras_if;
-       struct ras_dispatch_if ih_data = {
-               .entry = entry,
-       };
-
-       if (!ras_if)
-               return 0;
-
-       ih_data.head = *ras_if;
-
-       amdgpu_ras_interrupt_dispatch(adev, &ih_data);
-       return 0;
-}
-
 static int sdma_v4_0_process_illegal_inst_irq(struct amdgpu_device *adev,
                                              struct amdgpu_irq_src *source,
                                              struct amdgpu_iv_entry *entry)
@@ -2417,7 +2294,7 @@ static const struct amdgpu_irq_src_funcs sdma_v4_0_illegal_inst_irq_funcs = {
 
 static const struct amdgpu_irq_src_funcs sdma_v4_0_ecc_irq_funcs = {
        .set = sdma_v4_0_set_ecc_irq_state,
-       .process = sdma_v4_0_process_ecc_irq,
+       .process = amdgpu_sdma_process_ecc_irq,
 };
 
 
index f6e81680dd7e8edd03cc2ada50008db924d93692..b8fdb192f6d6f07b0da3f0a86d0071b190d246a7 100644 (file)
@@ -406,7 +406,7 @@ static void sdma_v5_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
 {
        struct amdgpu_device *adev = ring->adev;
        u32 ref_and_mask = 0;
-       const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio_funcs->hdp_flush_reg;
+       const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio.hdp_flush_reg;
 
        if (ring->me == 0)
                ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0;
@@ -416,8 +416,8 @@ static void sdma_v5_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
        amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
                          SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(1) |
                          SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* == */
-       amdgpu_ring_write(ring, (adev->nbio_funcs->get_hdp_flush_done_offset(adev)) << 2);
-       amdgpu_ring_write(ring, (adev->nbio_funcs->get_hdp_flush_req_offset(adev)) << 2);
+       amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_done_offset(adev)) << 2);
+       amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_req_offset(adev)) << 2);
        amdgpu_ring_write(ring, ref_and_mask); /* reference */
        amdgpu_ring_write(ring, ref_and_mask); /* mask */
        amdgpu_ring_write(ring, SDMA_PKT_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) |
@@ -683,7 +683,7 @@ static int sdma_v5_0_gfx_resume(struct amdgpu_device *adev)
                WREG32(sdma_v5_0_get_reg_offset(adev, i, mmSDMA0_GFX_DOORBELL), doorbell);
                WREG32(sdma_v5_0_get_reg_offset(adev, i, mmSDMA0_GFX_DOORBELL_OFFSET), doorbell_offset);
 
-               adev->nbio_funcs->sdma_doorbell_range(adev, i, ring->use_doorbell,
+               adev->nbio.funcs->sdma_doorbell_range(adev, i, ring->use_doorbell,
                                                      ring->doorbell_index, 20);
 
                if (amdgpu_sriov_vf(adev))
index f8ab80c8801b1bfbce2ec1f1735feb5a857cb21e..9be0168217f55d2fa81060145a7a24c9f172fbc6 100644 (file)
@@ -58,6 +58,9 @@
 #include "mmhub_v1_0.h"
 #include "df_v1_7.h"
 #include "df_v3_6.h"
+#include "nbio_v6_1.h"
+#include "nbio_v7_0.h"
+#include "nbio_v7_4.h"
 #include "vega10_ih.h"
 #include "sdma_v4_0.h"
 #include "uvd_v7_0.h"
@@ -91,8 +94,8 @@ static u32 soc15_pcie_rreg(struct amdgpu_device *adev, u32 reg)
 {
        unsigned long flags, address, data;
        u32 r;
-       address = adev->nbio_funcs->get_pcie_index_offset(adev);
-       data = adev->nbio_funcs->get_pcie_data_offset(adev);
+       address = adev->nbio.funcs->get_pcie_index_offset(adev);
+       data = adev->nbio.funcs->get_pcie_data_offset(adev);
 
        spin_lock_irqsave(&adev->pcie_idx_lock, flags);
        WREG32(address, reg);
@@ -106,8 +109,8 @@ static void soc15_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
 {
        unsigned long flags, address, data;
 
-       address = adev->nbio_funcs->get_pcie_index_offset(adev);
-       data = adev->nbio_funcs->get_pcie_data_offset(adev);
+       address = adev->nbio.funcs->get_pcie_index_offset(adev);
+       data = adev->nbio.funcs->get_pcie_data_offset(adev);
 
        spin_lock_irqsave(&adev->pcie_idx_lock, flags);
        WREG32(address, reg);
@@ -121,8 +124,8 @@ static u64 soc15_pcie_rreg64(struct amdgpu_device *adev, u32 reg)
 {
        unsigned long flags, address, data;
        u64 r;
-       address = adev->nbio_funcs->get_pcie_index_offset(adev);
-       data = adev->nbio_funcs->get_pcie_data_offset(adev);
+       address = adev->nbio.funcs->get_pcie_index_offset(adev);
+       data = adev->nbio.funcs->get_pcie_data_offset(adev);
 
        spin_lock_irqsave(&adev->pcie_idx_lock, flags);
        /* read low 32 bit */
@@ -142,8 +145,8 @@ static void soc15_pcie_wreg64(struct amdgpu_device *adev, u32 reg, u64 v)
 {
        unsigned long flags, address, data;
 
-       address = adev->nbio_funcs->get_pcie_index_offset(adev);
-       data = adev->nbio_funcs->get_pcie_data_offset(adev);
+       address = adev->nbio.funcs->get_pcie_index_offset(adev);
+       data = adev->nbio.funcs->get_pcie_data_offset(adev);
 
        spin_lock_irqsave(&adev->pcie_idx_lock, flags);
        /* write low 32 bit */
@@ -262,7 +265,7 @@ static void soc15_se_cac_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
 
 static u32 soc15_get_config_memsize(struct amdgpu_device *adev)
 {
-       return adev->nbio_funcs->get_memsize(adev);
+       return adev->nbio.funcs->get_memsize(adev);
 }
 
 static u32 soc15_get_xclk(struct amdgpu_device *adev)
@@ -461,7 +464,7 @@ static int soc15_asic_mode1_reset(struct amdgpu_device *adev)
 
        /* wait for asic to come out of reset */
        for (i = 0; i < adev->usec_timeout; i++) {
-               u32 memsize = adev->nbio_funcs->get_memsize(adev);
+               u32 memsize = adev->nbio.funcs->get_memsize(adev);
 
                if (memsize != 0xffffffff)
                        break;
@@ -475,42 +478,66 @@ static int soc15_asic_mode1_reset(struct amdgpu_device *adev)
 
 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 (is_support_sw_smu(adev)) {
+               struct smu_context *smu = &adev->smu;
 
-       if (!pp_funcs || !pp_funcs->get_asic_baco_capability) {
-               *cap = false;
-               return -ENOENT;
-       }
+               *cap = smu_baco_is_support(smu);
+               return 0;
+       } else {
+               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);
+               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;
+       struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
 
-       if (!pp_funcs ||!pp_funcs->get_asic_baco_state ||!pp_funcs->set_asic_baco_state)
-               return -ENOENT;
+       /* avoid NBIF got stuck when do RAS recovery in BACO reset */
+       if (ras && ras->supported)
+               adev->nbio.funcs->enable_doorbell_interrupt(adev, false);
 
-       /* enter BACO state */
-       if (pp_funcs->set_asic_baco_state(pp_handle, 1))
-               return -EIO;
+       dev_info(adev->dev, "GPU BACO reset\n");
 
-       /* exit BACO state */
-       if (pp_funcs->set_asic_baco_state(pp_handle, 0))
-               return -EIO;
+       if (is_support_sw_smu(adev)) {
+               struct smu_context *smu = &adev->smu;
 
-       dev_info(adev->dev, "GPU BACO reset\n");
+               if (smu_baco_reset(smu))
+                       return -EIO;
+       } else {
+               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;
+       }
 
-       adev->in_baco_reset = 1;
+       /* re-enable doorbell interrupt after BACO exit */
+       if (ras && ras->supported)
+               adev->nbio.funcs->enable_doorbell_interrupt(adev, true);
 
        return 0;
 }
 
 static int soc15_mode2_reset(struct amdgpu_device *adev)
 {
+       if (is_support_sw_smu(adev))
+               return smu_mode2_reset(&adev->smu);
        if (!adev->powerplay.pp_funcs ||
            !adev->powerplay.pp_funcs->asic_reset_mode_2)
                return -ENOENT;
@@ -525,6 +552,7 @@ soc15_asic_reset_method(struct amdgpu_device *adev)
 
        switch (adev->asic_type) {
        case CHIP_RAVEN:
+       case CHIP_RENOIR:
                return AMD_RESET_METHOD_MODE2;
        case CHIP_VEGA10:
        case CHIP_VEGA12:
@@ -626,8 +654,8 @@ static void soc15_program_aspm(struct amdgpu_device *adev)
 static void soc15_enable_doorbell_aperture(struct amdgpu_device *adev,
                                           bool enable)
 {
-       adev->nbio_funcs->enable_doorbell_aperture(adev, enable);
-       adev->nbio_funcs->enable_doorbell_selfring_aperture(adev, enable);
+       adev->nbio.funcs->enable_doorbell_aperture(adev, enable);
+       adev->nbio.funcs->enable_doorbell_selfring_aperture(adev, enable);
 }
 
 static const struct amdgpu_ip_block_version vega10_common_ip_block =
@@ -641,7 +669,7 @@ static const struct amdgpu_ip_block_version vega10_common_ip_block =
 
 static uint32_t soc15_get_rev_id(struct amdgpu_device *adev)
 {
-       return adev->nbio_funcs->get_rev_id(adev);
+       return adev->nbio.funcs->get_rev_id(adev);
 }
 
 int soc15_set_ip_blocks(struct amdgpu_device *adev)
@@ -667,13 +695,17 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
        if (adev->asic_type == CHIP_VEGA20 || adev->asic_type == CHIP_ARCTURUS)
                adev->gmc.xgmi.supported = true;
 
-       if (adev->flags & AMD_IS_APU)
-               adev->nbio_funcs = &nbio_v7_0_funcs;
-       else if (adev->asic_type == CHIP_VEGA20 ||
-               adev->asic_type == CHIP_ARCTURUS)
-               adev->nbio_funcs = &nbio_v7_4_funcs;
-       else
-               adev->nbio_funcs = &nbio_v6_1_funcs;
+       if (adev->flags & AMD_IS_APU) {
+               adev->nbio.funcs = &nbio_v7_0_funcs;
+               adev->nbio.hdp_flush_reg = &nbio_v7_0_hdp_flush_reg;
+       } else if (adev->asic_type == CHIP_VEGA20 ||
+                  adev->asic_type == CHIP_ARCTURUS) {
+               adev->nbio.funcs = &nbio_v7_4_funcs;
+               adev->nbio.hdp_flush_reg = &nbio_v7_4_hdp_flush_reg;
+       } else {
+               adev->nbio.funcs = &nbio_v6_1_funcs;
+               adev->nbio.hdp_flush_reg = &nbio_v6_1_hdp_flush_reg;
+       }
 
        if (adev->asic_type == CHIP_VEGA20 || adev->asic_type == CHIP_ARCTURUS)
                adev->df_funcs = &df_v3_6_funcs;
@@ -681,7 +713,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
                adev->df_funcs = &df_v1_7_funcs;
 
        adev->rev_id = soc15_get_rev_id(adev);
-       adev->nbio_funcs->detect_hw_virt(adev);
+       adev->nbio.funcs->detect_hw_virt(adev);
 
        if (amdgpu_sriov_vf(adev))
                adev->virt.ops = &xgpu_ai_virt_ops;
@@ -750,13 +782,26 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
        case CHIP_ARCTURUS:
                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 (amdgpu_sriov_vf(adev)) {
+                       if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
+                               amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
+                       amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
+               } else {
+                       amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
+                       if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
+                               amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
+               }
+
                if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
                        amdgpu_device_ip_block_add(adev, &dce_virtual_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, &smu_v11_0_ip_block);
-               amdgpu_device_ip_block_add(adev, &vcn_v2_5_ip_block);
+               if (!amdgpu_sriov_vf(adev))
+                       amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
+
+               if (unlikely(adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT))
+                       amdgpu_device_ip_block_add(adev, &vcn_v2_5_ip_block);
                break;
        case CHIP_RENOIR:
                amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
@@ -785,7 +830,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
 
 static void soc15_flush_hdp(struct amdgpu_device *adev, struct amdgpu_ring *ring)
 {
-       adev->nbio_funcs->hdp_flush(adev, ring);
+       adev->nbio.funcs->hdp_flush(adev, ring);
 }
 
 static void soc15_invalidate_hdp(struct amdgpu_device *adev,
@@ -1157,7 +1202,8 @@ static int soc15_common_early_init(void *handle)
                        AMD_CG_SUPPORT_SDMA_MGCG |
                        AMD_CG_SUPPORT_SDMA_LS |
                        AMD_CG_SUPPORT_MC_MGCG |
-                       AMD_CG_SUPPORT_MC_LS;
+                       AMD_CG_SUPPORT_MC_LS |
+                       AMD_CG_SUPPORT_IH_CG;
                adev->pg_flags = 0;
                adev->external_rev_id = adev->rev_id + 0x32;
                break;
@@ -1208,11 +1254,15 @@ static int soc15_common_early_init(void *handle)
 static int soc15_common_late_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       int r = 0;
 
        if (amdgpu_sriov_vf(adev))
                xgpu_ai_mailbox_get_irq(adev);
 
-       return 0;
+       if (adev->nbio.funcs->ras_late_init)
+               r = adev->nbio.funcs->ras_late_init(adev);
+
+       return r;
 }
 
 static int soc15_common_sw_init(void *handle)
@@ -1229,6 +1279,10 @@ static int soc15_common_sw_init(void *handle)
 
 static int soc15_common_sw_fini(void *handle)
 {
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       amdgpu_nbio_ras_fini(adev);
+       adev->df_funcs->sw_fini(adev);
        return 0;
 }
 
@@ -1241,12 +1295,12 @@ static void soc15_doorbell_range_init(struct amdgpu_device *adev)
        if (!amdgpu_sriov_vf(adev)) {
                for (i = 0; i < adev->sdma.num_instances; i++) {
                        ring = &adev->sdma.instance[i].ring;
-                       adev->nbio_funcs->sdma_doorbell_range(adev, i,
+                       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->nbio.funcs->ih_doorbell_range(adev, adev->irq.ih.use_doorbell,
                                                adev->irq.ih.doorbell_index);
        }
 }
@@ -1260,13 +1314,13 @@ static int soc15_common_hw_init(void *handle)
        /* enable aspm */
        soc15_program_aspm(adev);
        /* setup nbio registers */
-       adev->nbio_funcs->init_registers(adev);
+       adev->nbio.funcs->init_registers(adev);
        /* remap HDP registers to a hole in mmio space,
         * for the purpose of expose those registers
         * to process space
         */
-       if (adev->nbio_funcs->remap_hdp_registers)
-               adev->nbio_funcs->remap_hdp_registers(adev);
+       if (adev->nbio.funcs->remap_hdp_registers)
+               adev->nbio.funcs->remap_hdp_registers(adev);
 
        /* enable the doorbell aperture */
        soc15_enable_doorbell_aperture(adev, true);
@@ -1289,6 +1343,14 @@ static int soc15_common_hw_fini(void *handle)
        if (amdgpu_sriov_vf(adev))
                xgpu_ai_mailbox_put_irq(adev);
 
+       if (adev->nbio.ras_if &&
+           amdgpu_ras_is_supported(adev, adev->nbio.ras_if->block)) {
+               if (adev->nbio.funcs->init_ras_controller_interrupt)
+                       amdgpu_irq_put(adev, &adev->nbio.ras_controller_irq, 0);
+               if (adev->nbio.funcs->init_ras_err_event_athub_interrupt)
+                       amdgpu_irq_put(adev, &adev->nbio.ras_err_event_athub_irq, 0);
+       }
+
        return 0;
 }
 
@@ -1429,9 +1491,9 @@ static int soc15_common_set_clockgating_state(void *handle,
        case CHIP_VEGA10:
        case CHIP_VEGA12:
        case CHIP_VEGA20:
-               adev->nbio_funcs->update_medium_grain_clock_gating(adev,
+               adev->nbio.funcs->update_medium_grain_clock_gating(adev,
                                state == AMD_CG_STATE_GATE ? true : false);
-               adev->nbio_funcs->update_medium_grain_light_sleep(adev,
+               adev->nbio.funcs->update_medium_grain_light_sleep(adev,
                                state == AMD_CG_STATE_GATE ? true : false);
                soc15_update_hdp_light_sleep(adev,
                                state == AMD_CG_STATE_GATE ? true : false);
@@ -1446,9 +1508,9 @@ static int soc15_common_set_clockgating_state(void *handle,
                break;
        case CHIP_RAVEN:
        case CHIP_RENOIR:
-               adev->nbio_funcs->update_medium_grain_clock_gating(adev,
+               adev->nbio.funcs->update_medium_grain_clock_gating(adev,
                                state == AMD_CG_STATE_GATE ? true : false);
-               adev->nbio_funcs->update_medium_grain_light_sleep(adev,
+               adev->nbio.funcs->update_medium_grain_light_sleep(adev,
                                state == AMD_CG_STATE_GATE ? true : false);
                soc15_update_hdp_light_sleep(adev,
                                state == AMD_CG_STATE_GATE ? true : false);
@@ -1477,7 +1539,7 @@ static void soc15_common_get_clockgating_state(void *handle, u32 *flags)
        if (amdgpu_sriov_vf(adev))
                *flags = 0;
 
-       adev->nbio_funcs->get_clockgating_state(adev, flags);
+       adev->nbio.funcs->get_clockgating_state(adev, flags);
 
        /* AMD_CG_SUPPORT_HDP_LS */
        data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS));
index a3dde0c31f578bbab79dc6ae31bfb547e7ed43c5..9af6c6ffbfa2b8b1c312633f4811c56a7a7ba4b6 100644 (file)
@@ -67,6 +67,8 @@ struct soc15_allowed_register_entry {
 #define SOC15_REG_GOLDEN_VALUE(ip, inst, reg, and_mask, or_mask) \
        { ip##_HWIP, inst, reg##_BASE_IDX, reg, and_mask, or_mask }
 
+#define SOC15_REG_FIELD(reg, field) reg##__##field##_MASK, reg##__##field##__SHIFT
+
 void soc15_grbm_select(struct amdgpu_device *adev,
                    u32 me, u32 pipe, u32 queue, u32 vmid);
 int soc15_set_ip_blocks(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/umc_v6_0.c
new file mode 100644 (file)
index 0000000..0d6b505
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright 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) 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 "umc_v6_0.h"
+#include "amdgpu.h"
+
+static void umc_v6_0_init_registers(struct amdgpu_device *adev)
+{
+       unsigned i,j;
+
+       for (i = 0; i < 4; i++)
+               for (j = 0; j < 4; j++)
+                       WREG32((i*0x100000 + 0x5010c + j*0x2000)/4, 0x1002);
+}
+
+const struct amdgpu_umc_funcs umc_v6_0_funcs = {
+       .init_registers = umc_v6_0_init_registers,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_0.h b/drivers/gpu/drm/amd/amdgpu/umc_v6_0.h
new file mode 100644 (file)
index 0000000..109f1a5
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright 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) 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 __UMC_V6_0_H__
+#define __UMC_V6_0_H__
+
+#include "soc15_common.h"
+#include "amdgpu.h"
+
+extern const struct amdgpu_umc_funcs umc_v6_0_funcs;
+
+#endif
index 8502e736f72107b276ba25789a7588d8c6bc8d84..47c4b96b14d18725eda054756e2eff36acdb7d7c 100644 (file)
@@ -75,6 +75,17 @@ static void umc_v6_1_disable_umc_index_mode(struct amdgpu_device *adev)
                        RSMU_UMC_INDEX_MODE_EN, 0);
 }
 
+static uint32_t umc_v6_1_get_umc_inst(struct amdgpu_device *adev)
+{
+       uint32_t rsmu_umc_index;
+
+       rsmu_umc_index = RREG32_SOC15(RSMU, 0,
+                               mmRSMU_UMC_INDEX_REGISTER_NBIF_VG20_GPU);
+       return REG_GET_FIELD(rsmu_umc_index,
+                               RSMU_UMC_INDEX_REGISTER_NBIF_VG20_GPU,
+                               RSMU_UMC_INDEX_INSTANCE);
+}
+
 static void umc_v6_1_query_correctable_error_count(struct amdgpu_device *adev,
                                                   uint32_t umc_reg_offset,
                                                   unsigned long *error_count)
@@ -165,7 +176,8 @@ static void umc_v6_1_query_error_address(struct amdgpu_device *adev,
                                         uint32_t umc_reg_offset, uint32_t channel_index)
 {
        uint32_t lsb, mc_umc_status_addr;
-       uint64_t mc_umc_status, err_addr;
+       uint64_t mc_umc_status, err_addr, retired_page;
+       struct eeprom_table_record *err_rec;
 
        mc_umc_status_addr =
                SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0);
@@ -177,6 +189,7 @@ static void umc_v6_1_query_error_address(struct amdgpu_device *adev,
                return;
        }
 
+       err_rec = &err_data->err_addr[err_data->err_addr_cnt];
        mc_umc_status = RREG64_UMC(mc_umc_status_addr + umc_reg_offset);
 
        /* calculate error address if ue/ce error is detected */
@@ -191,12 +204,24 @@ static void umc_v6_1_query_error_address(struct amdgpu_device *adev,
                err_addr &= ~((0x1ULL << lsb) - 1);
 
                /* translate umc channel address to soc pa, 3 parts are included */
-               err_data->err_addr[err_data->err_addr_cnt] =
-                                               ADDR_OF_8KB_BLOCK(err_addr) |
-                                               ADDR_OF_256B_BLOCK(channel_index) |
-                                               OFFSET_IN_256B_BLOCK(err_addr);
-
-               err_data->err_addr_cnt++;
+               retired_page = ADDR_OF_8KB_BLOCK(err_addr) |
+                               ADDR_OF_256B_BLOCK(channel_index) |
+                               OFFSET_IN_256B_BLOCK(err_addr);
+
+               /* we only save ue error information currently, ce is skipped */
+               if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC)
+                               == 1) {
+                       err_rec->address = err_addr;
+                       /* page frame address is saved */
+                       err_rec->retired_page = retired_page >> AMDGPU_GPU_PAGE_SHIFT;
+                       err_rec->ts = (uint64_t)ktime_get_real_seconds();
+                       err_rec->err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE;
+                       err_rec->cu = 0;
+                       err_rec->mem_channel = channel_index;
+                       err_rec->mcumc_id = umc_v6_1_get_umc_inst(adev);
+
+                       err_data->err_addr_cnt++;
+               }
        }
 
        /* clear umc status */
@@ -209,7 +234,7 @@ static void umc_v6_1_query_ras_error_address(struct amdgpu_device *adev,
        amdgpu_umc_for_each_channel(umc_v6_1_query_error_address);
 }
 
-static void umc_v6_1_ras_init_per_channel(struct amdgpu_device *adev,
+static void umc_v6_1_err_cnt_init_per_channel(struct amdgpu_device *adev,
                                         struct ras_err_data *err_data,
                                         uint32_t umc_reg_offset, uint32_t channel_index)
 {
@@ -239,15 +264,16 @@ static void umc_v6_1_ras_init_per_channel(struct amdgpu_device *adev,
        WREG32(ecc_err_cnt_addr + umc_reg_offset, UMC_V6_1_CE_CNT_INIT);
 }
 
-static void umc_v6_1_ras_init(struct amdgpu_device *adev)
+static void umc_v6_1_err_cnt_init(struct amdgpu_device *adev)
 {
        void *ras_error_status = NULL;
 
-       amdgpu_umc_for_each_channel(umc_v6_1_ras_init_per_channel);
+       amdgpu_umc_for_each_channel(umc_v6_1_err_cnt_init_per_channel);
 }
 
 const struct amdgpu_umc_funcs umc_v6_1_funcs = {
-       .ras_init = umc_v6_1_ras_init,
+       .err_cnt_init = umc_v6_1_err_cnt_init,
+       .ras_late_init = amdgpu_umc_ras_late_init,
        .query_ras_error_count = umc_v6_1_query_ras_error_count,
        .query_ras_error_address = umc_v6_1_query_ras_error_address,
        .enable_umc_index_mode = umc_v6_1_enable_umc_index_mode,
index 670784a78512b82a7c0f5e484746308ad1fd904d..217084d56ab8c86e6b1b16b335bc4faf13258136 100644 (file)
@@ -206,13 +206,14 @@ static int uvd_v6_0_enc_ring_test_ring(struct amdgpu_ring *ring)
  * Open up a stream for HW test
  */
 static int uvd_v6_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
+                                      struct amdgpu_bo *bo,
                                       struct dma_fence **fence)
 {
        const unsigned ib_size_dw = 16;
        struct amdgpu_job *job;
        struct amdgpu_ib *ib;
        struct dma_fence *f = NULL;
-       uint64_t dummy;
+       uint64_t addr;
        int i, r;
 
        r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
@@ -220,15 +221,15 @@ static int uvd_v6_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle
                return r;
 
        ib = &job->ibs[0];
-       dummy = ib->gpu_addr + 1024;
+       addr = amdgpu_bo_gpu_offset(bo);
 
        ib->length_dw = 0;
        ib->ptr[ib->length_dw++] = 0x00000018;
        ib->ptr[ib->length_dw++] = 0x00000001; /* session info */
        ib->ptr[ib->length_dw++] = handle;
        ib->ptr[ib->length_dw++] = 0x00010000;
-       ib->ptr[ib->length_dw++] = upper_32_bits(dummy);
-       ib->ptr[ib->length_dw++] = dummy;
+       ib->ptr[ib->length_dw++] = upper_32_bits(addr);
+       ib->ptr[ib->length_dw++] = addr;
 
        ib->ptr[ib->length_dw++] = 0x00000014;
        ib->ptr[ib->length_dw++] = 0x00000002; /* task info */
@@ -268,13 +269,14 @@ static int uvd_v6_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle
  */
 static int uvd_v6_0_enc_get_destroy_msg(struct amdgpu_ring *ring,
                                        uint32_t handle,
+                                       struct amdgpu_bo *bo,
                                        struct dma_fence **fence)
 {
        const unsigned ib_size_dw = 16;
        struct amdgpu_job *job;
        struct amdgpu_ib *ib;
        struct dma_fence *f = NULL;
-       uint64_t dummy;
+       uint64_t addr;
        int i, r;
 
        r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
@@ -282,15 +284,15 @@ static int uvd_v6_0_enc_get_destroy_msg(struct amdgpu_ring *ring,
                return r;
 
        ib = &job->ibs[0];
-       dummy = ib->gpu_addr + 1024;
+       addr = amdgpu_bo_gpu_offset(bo);
 
        ib->length_dw = 0;
        ib->ptr[ib->length_dw++] = 0x00000018;
        ib->ptr[ib->length_dw++] = 0x00000001; /* session info */
        ib->ptr[ib->length_dw++] = handle;
        ib->ptr[ib->length_dw++] = 0x00010000;
-       ib->ptr[ib->length_dw++] = upper_32_bits(dummy);
-       ib->ptr[ib->length_dw++] = dummy;
+       ib->ptr[ib->length_dw++] = upper_32_bits(addr);
+       ib->ptr[ib->length_dw++] = addr;
 
        ib->ptr[ib->length_dw++] = 0x00000014;
        ib->ptr[ib->length_dw++] = 0x00000002; /* task info */
@@ -327,13 +329,20 @@ static int uvd_v6_0_enc_get_destroy_msg(struct amdgpu_ring *ring,
 static int uvd_v6_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)
 {
        struct dma_fence *fence = NULL;
+       struct amdgpu_bo *bo = NULL;
        long r;
 
-       r = uvd_v6_0_enc_get_create_msg(ring, 1, NULL);
+       r = amdgpu_bo_create_reserved(ring->adev, 128 * 1024, PAGE_SIZE,
+                                     AMDGPU_GEM_DOMAIN_VRAM,
+                                     &bo, NULL, NULL);
+       if (r)
+               return r;
+
+       r = uvd_v6_0_enc_get_create_msg(ring, 1, bo, NULL);
        if (r)
                goto error;
 
-       r = uvd_v6_0_enc_get_destroy_msg(ring, 1, &fence);
+       r = uvd_v6_0_enc_get_destroy_msg(ring, 1, bo, &fence);
        if (r)
                goto error;
 
@@ -345,6 +354,8 @@ static int uvd_v6_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)
 
 error:
        dma_fence_put(fence);
+       amdgpu_bo_unreserve(bo);
+       amdgpu_bo_unref(&bo);
        return r;
 }
 
index 01f658fa72c68a904d678fcf9f131dd5f2675924..0995378d8263c495799068bee36b95c00874fe1c 100644 (file)
@@ -214,13 +214,14 @@ static int uvd_v7_0_enc_ring_test_ring(struct amdgpu_ring *ring)
  * Open up a stream for HW test
  */
 static int uvd_v7_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
+                                      struct amdgpu_bo *bo,
                                       struct dma_fence **fence)
 {
        const unsigned ib_size_dw = 16;
        struct amdgpu_job *job;
        struct amdgpu_ib *ib;
        struct dma_fence *f = NULL;
-       uint64_t dummy;
+       uint64_t addr;
        int i, r;
 
        r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
@@ -228,15 +229,15 @@ static int uvd_v7_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle
                return r;
 
        ib = &job->ibs[0];
-       dummy = ib->gpu_addr + 1024;
+       addr = amdgpu_bo_gpu_offset(bo);
 
        ib->length_dw = 0;
        ib->ptr[ib->length_dw++] = 0x00000018;
        ib->ptr[ib->length_dw++] = 0x00000001; /* session info */
        ib->ptr[ib->length_dw++] = handle;
        ib->ptr[ib->length_dw++] = 0x00000000;
-       ib->ptr[ib->length_dw++] = upper_32_bits(dummy);
-       ib->ptr[ib->length_dw++] = dummy;
+       ib->ptr[ib->length_dw++] = upper_32_bits(addr);
+       ib->ptr[ib->length_dw++] = addr;
 
        ib->ptr[ib->length_dw++] = 0x00000014;
        ib->ptr[ib->length_dw++] = 0x00000002; /* task info */
@@ -275,13 +276,14 @@ static int uvd_v7_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle
  * Close up a stream for HW test or if userspace failed to do so
  */
 static int uvd_v7_0_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
-                               struct dma_fence **fence)
+                                       struct amdgpu_bo *bo,
+                                       struct dma_fence **fence)
 {
        const unsigned ib_size_dw = 16;
        struct amdgpu_job *job;
        struct amdgpu_ib *ib;
        struct dma_fence *f = NULL;
-       uint64_t dummy;
+       uint64_t addr;
        int i, r;
 
        r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
@@ -289,15 +291,15 @@ static int uvd_v7_0_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handl
                return r;
 
        ib = &job->ibs[0];
-       dummy = ib->gpu_addr + 1024;
+       addr = amdgpu_bo_gpu_offset(bo);
 
        ib->length_dw = 0;
        ib->ptr[ib->length_dw++] = 0x00000018;
        ib->ptr[ib->length_dw++] = 0x00000001;
        ib->ptr[ib->length_dw++] = handle;
        ib->ptr[ib->length_dw++] = 0x00000000;
-       ib->ptr[ib->length_dw++] = upper_32_bits(dummy);
-       ib->ptr[ib->length_dw++] = dummy;
+       ib->ptr[ib->length_dw++] = upper_32_bits(addr);
+       ib->ptr[ib->length_dw++] = addr;
 
        ib->ptr[ib->length_dw++] = 0x00000014;
        ib->ptr[ib->length_dw++] = 0x00000002;
@@ -334,13 +336,20 @@ static int uvd_v7_0_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handl
 static int uvd_v7_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)
 {
        struct dma_fence *fence = NULL;
+       struct amdgpu_bo *bo = NULL;
        long r;
 
-       r = uvd_v7_0_enc_get_create_msg(ring, 1, NULL);
+       r = amdgpu_bo_create_reserved(ring->adev, 128 * 1024, PAGE_SIZE,
+                                     AMDGPU_GEM_DOMAIN_VRAM,
+                                     &bo, NULL, NULL);
+       if (r)
+               return r;
+
+       r = uvd_v7_0_enc_get_create_msg(ring, 1, bo, NULL);
        if (r)
                goto error;
 
-       r = uvd_v7_0_enc_get_destroy_msg(ring, 1, &fence);
+       r = uvd_v7_0_enc_get_destroy_msg(ring, 1, bo, &fence);
        if (r)
                goto error;
 
@@ -352,6 +361,8 @@ static int uvd_v7_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)
 
 error:
        dma_fence_put(fence);
+       amdgpu_bo_unreserve(bo);
+       amdgpu_bo_unref(&bo);
        return r;
 }
 
index 93b3500e522b8be2b3be23419c129c8dc96652c2..b4f84a820a448a847f21447998c39173ecb6fce9 100644 (file)
@@ -202,7 +202,6 @@ static int vcn_v1_0_hw_init(void *handle)
 
        for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
                ring = &adev->vcn.inst->ring_enc[i];
-               ring->sched.ready = true;
                r = amdgpu_ring_test_helper(ring);
                if (r)
                        goto done;
index 36ad0c0e8efbcb714fd0acc3ed3e261bbf0ab51b..38f787a560cb6ebdac85c5f8449f02d674fbe242 100644 (file)
@@ -244,33 +244,24 @@ static int vcn_v2_0_hw_init(void *handle)
        struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec;
        int i, r;
 
-       adev->nbio_funcs->vcn_doorbell_range(adev, ring->use_doorbell,
+       adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
                                             ring->doorbell_index, 0);
 
-       ring->sched.ready = true;
-       r = amdgpu_ring_test_ring(ring);
-       if (r) {
-               ring->sched.ready = false;
+       r = amdgpu_ring_test_helper(ring);
+       if (r)
                goto done;
-       }
 
        for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
                ring = &adev->vcn.inst->ring_enc[i];
-               ring->sched.ready = true;
-               r = amdgpu_ring_test_ring(ring);
-               if (r) {
-                       ring->sched.ready = false;
+               r = amdgpu_ring_test_helper(ring);
+               if (r)
                        goto done;
-               }
        }
 
        ring = &adev->vcn.inst->ring_jpeg;
-       ring->sched.ready = true;
-       r = amdgpu_ring_test_ring(ring);
-       if (r) {
-               ring->sched.ready = false;
+       r = amdgpu_ring_test_helper(ring);
+       if (r)
                goto done;
-       }
 
 done:
        if (!r)
index 395c2259f979bb3c79de6768d00ca1ac52a2edd8..b3623ed3dc42f9f446adb3ce4ef391ce6a9003c7 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "amdgpu.h"
 #include "amdgpu_vcn.h"
+#include "amdgpu_pm.h"
 #include "soc15.h"
 #include "soc15d.h"
 #include "vcn_v2_0.h"
@@ -255,32 +256,27 @@ static int vcn_v2_5_hw_init(void *handle)
                        continue;
                ring = &adev->vcn.inst[j].ring_dec;
 
-               adev->nbio_funcs->vcn_doorbell_range(adev, ring->use_doorbell,
+               adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
                                                     ring->doorbell_index, j);
 
-               r = amdgpu_ring_test_ring(ring);
-               if (r) {
-                       ring->sched.ready = false;
+               r = amdgpu_ring_test_helper(ring);
+               if (r)
                        goto done;
-               }
 
                for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
                        ring = &adev->vcn.inst[j].ring_enc[i];
+                       /* disable encode rings till the robustness of the FW */
                        ring->sched.ready = false;
                        continue;
-                       r = amdgpu_ring_test_ring(ring);
-                       if (r) {
-                               ring->sched.ready = false;
+                       r = amdgpu_ring_test_helper(ring);
+                       if (r)
                                goto done;
-                       }
                }
 
                ring = &adev->vcn.inst[j].ring_jpeg;
-               r = amdgpu_ring_test_ring(ring);
-               if (r) {
-                       ring->sched.ready = false;
+               r = amdgpu_ring_test_helper(ring);
+               if (r)
                        goto done;
-               }
        }
 done:
        if (!r)
@@ -423,7 +419,6 @@ static void vcn_v2_5_mc_resume(struct amdgpu_device *adev)
  * vcn_v2_5_disable_clock_gating - disable VCN clock gating
  *
  * @adev: amdgpu_device pointer
- * @sw: enable SW clock gating
  *
  * Disable clock gating for VCN block
  */
@@ -542,7 +537,6 @@ static void vcn_v2_5_disable_clock_gating(struct amdgpu_device *adev)
  * vcn_v2_5_enable_clock_gating - enable VCN clock gating
  *
  * @adev: amdgpu_device pointer
- * @sw: enable SW clock gating
  *
  * Enable clock gating for VCN block
  */
@@ -716,6 +710,9 @@ static int vcn_v2_5_start(struct amdgpu_device *adev)
        uint32_t rb_bufsz, tmp;
        int i, j, k, r;
 
+       if (adev->pm.dpm_enabled)
+               amdgpu_dpm_enable_uvd(adev, true);
+
        for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
                if (adev->vcn.harvest_config & (1 << i))
                        continue;
@@ -946,6 +943,9 @@ static int vcn_v2_5_stop(struct amdgpu_device *adev)
                        ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
        }
 
+       if (adev->pm.dpm_enabled)
+               amdgpu_dpm_enable_uvd(adev, false);
+
        return 0;
 }
 
index 9eae3536ddad78ffb80931065b71d82446b60ee0..5cb7e231de5f0e10e6095aae47f7c146e49b5cbd 100644 (file)
@@ -226,7 +226,7 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
        /* disable irqs */
        vega10_ih_disable_interrupts(adev);
 
-       adev->nbio_funcs->ih_control(adev);
+       adev->nbio.funcs->ih_control(adev);
 
        ih = &adev->irq.ih;
        /* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/
@@ -675,10 +675,49 @@ static int vega10_ih_soft_reset(void *handle)
        return 0;
 }
 
+static void vega10_ih_update_clockgating_state(struct amdgpu_device *adev,
+                                              bool enable)
+{
+       uint32_t data, def, field_val;
+
+       if (adev->cg_flags & AMD_CG_SUPPORT_IH_CG) {
+               def = data = RREG32_SOC15(OSSSYS, 0, mmIH_CLK_CTRL);
+               field_val = enable ? 0 : 1;
+               /**
+                * Vega10 does not have IH_RETRY_INT_CAM_MEM_CLK_SOFT_OVERRIDE
+                * and IH_BUFFER_MEM_CLK_SOFT_OVERRIDE field.
+                */
+               if (adev->asic_type > CHIP_VEGA10) {
+                       data = REG_SET_FIELD(data, IH_CLK_CTRL,
+                                    IH_RETRY_INT_CAM_MEM_CLK_SOFT_OVERRIDE, field_val);
+                       data = REG_SET_FIELD(data, IH_CLK_CTRL,
+                                    IH_BUFFER_MEM_CLK_SOFT_OVERRIDE, field_val);
+               }
+
+               data = REG_SET_FIELD(data, IH_CLK_CTRL,
+                                    DBUS_MUX_CLK_SOFT_OVERRIDE, field_val);
+               data = REG_SET_FIELD(data, IH_CLK_CTRL,
+                                    OSSSYS_SHARE_CLK_SOFT_OVERRIDE, field_val);
+               data = REG_SET_FIELD(data, IH_CLK_CTRL,
+                                    LIMIT_SMN_CLK_SOFT_OVERRIDE, field_val);
+               data = REG_SET_FIELD(data, IH_CLK_CTRL,
+                                    DYN_CLK_SOFT_OVERRIDE, field_val);
+               data = REG_SET_FIELD(data, IH_CLK_CTRL,
+                                    REG_CLK_SOFT_OVERRIDE, field_val);
+               if (def != data)
+                       WREG32_SOC15(OSSSYS, 0, mmIH_CLK_CTRL, data);
+       }
+}
+
 static int vega10_ih_set_clockgating_state(void *handle,
                                          enum amd_clockgating_state state)
 {
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       vega10_ih_update_clockgating_state(adev,
+                               state == AMD_CG_STATE_GATE ? true : false);
        return 0;
+
 }
 
 static int vega10_ih_set_powergating_state(void *handle,
index bd0580334f834828ee4ad0707a2c01f6c06f02b6..6b52a539d51bd923009c7112b9653c887c25d781 100644 (file)
@@ -24,7 +24,6 @@
 #include "soc15.h"
 
 #include "soc15_common.h"
-#include "soc15_hw_ip.h"
 #include "vega10_ip_offset.h"
 
 int vega10_reg_base_init(struct amdgpu_device *adev)
index 587e33f5dcce713191b313235a438b8410cad250..556f854e35512f97abee5662cae1601ba97f96c3 100644 (file)
@@ -24,7 +24,6 @@
 #include "soc15.h"
 
 #include "soc15_common.h"
-#include "soc15_hw_ip.h"
 #include "vega20_ip_offset.h"
 
 int vega20_reg_base_init(struct amdgpu_device *adev)
index 5f8c8786cac51d22200bfb21a14653b2a67c60a5..78e5cdc0c05887307eb2e5864619207a7b870d92 100644 (file)
@@ -689,16 +689,50 @@ static int vi_gpu_pci_config_reset(struct amdgpu_device *adev)
        return -EINVAL;
 }
 
+int smu7_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);
+}
+
+int smu7_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;
+}
+
 /**
- * vi_asic_reset - soft reset GPU
+ * vi_asic_pci_config_reset - soft reset GPU
  *
  * @adev: amdgpu_device pointer
  *
- * Look up which blocks are hung and attempt
- * to reset them.
+ * Use PCI Config method to reset the GPU.
+ *
  * Returns 0 for success.
  */
-static int vi_asic_reset(struct amdgpu_device *adev)
+static int vi_asic_pci_config_reset(struct amdgpu_device *adev)
 {
        int r;
 
@@ -714,7 +748,47 @@ static int vi_asic_reset(struct amdgpu_device *adev)
 static enum amd_reset_method
 vi_asic_reset_method(struct amdgpu_device *adev)
 {
-       return AMD_RESET_METHOD_LEGACY;
+       bool baco_reset;
+
+       switch (adev->asic_type) {
+       case CHIP_FIJI:
+       case CHIP_TONGA:
+       case CHIP_POLARIS10:
+       case CHIP_POLARIS11:
+       case CHIP_POLARIS12:
+       case CHIP_TOPAZ:
+               smu7_asic_get_baco_capability(adev, &baco_reset);
+               break;
+       default:
+               baco_reset = false;
+               break;
+       }
+
+       if (baco_reset)
+               return AMD_RESET_METHOD_BACO;
+       else
+               return AMD_RESET_METHOD_LEGACY;
+}
+
+/**
+ * vi_asic_reset - soft reset GPU
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Look up which blocks are hung and attempt
+ * to reset them.
+ * Returns 0 for success.
+ */
+static int vi_asic_reset(struct amdgpu_device *adev)
+{
+       int r;
+
+       if (vi_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)
+               r = smu7_asic_baco_reset(adev);
+       else
+               r = vi_asic_pci_config_reset(adev);
+
+       return r;
 }
 
 static u32 vi_get_config_memsize(struct amdgpu_device *adev)
index 8de0772f986c53ea469d2cffe5c4ddb098f9f302..40d4174913a41d12107c626a52e04fa9c07f7bc6 100644 (file)
@@ -31,4 +31,7 @@ void vi_srbm_select(struct amdgpu_device *adev,
 int vi_set_ip_blocks(struct amdgpu_device *adev);
 
 void legacy_doorbell_index_init(struct amdgpu_device *adev);
+int smu7_asic_get_baco_capability(struct amdgpu_device *adev, bool *cap);
+int smu7_asic_baco_reset(struct amdgpu_device *adev);
+
 #endif
index 177d1e5329a5723482c437381253700c224aeb90..9f59ba93cfe03c51041e7cbfad979bc71f6a3361 100644 (file)
@@ -33,7 +33,9 @@ static bool cik_event_interrupt_isr(struct kfd_dev *dev,
        const struct cik_ih_ring_entry *ihre =
                        (const struct cik_ih_ring_entry *)ih_ring_entry;
        const struct kfd2kgd_calls *f2g = dev->kfd2kgd;
-       unsigned int vmid, pasid;
+       unsigned int vmid;
+       uint16_t pasid;
+       bool ret;
 
        /* This workaround is due to HW/FW limitation on Hawaii that
         * VMID and PASID are not written into ih_ring_entry
@@ -48,13 +50,13 @@ static bool cik_event_interrupt_isr(struct kfd_dev *dev,
                *tmp_ihre = *ihre;
 
                vmid = f2g->read_vmid_from_vmfault_reg(dev->kgd);
-               pasid = f2g->get_atc_vmid_pasid_mapping_pasid(dev->kgd, vmid);
+               ret = f2g->get_atc_vmid_pasid_mapping_info(dev->kgd, vmid, &pasid);
 
                tmp_ihre->ring_id &= 0x000000ff;
                tmp_ihre->ring_id |= vmid << 8;
                tmp_ihre->ring_id |= pasid << 16;
 
-               return (pasid != 0) &&
+               return ret && (pasid != 0) &&
                        vmid >= dev->vm_info.first_vmid_kfd &&
                        vmid <= dev->vm_info.last_vmid_kfd;
        }
index 901fe359016564cdfa752c43babcffa1c1a8fb40..d3400da6ab6437532bb4237b30a6cefb63e9a212 100644 (file)
@@ -905,7 +905,7 @@ static const uint32_t cwsr_trap_gfx10_hex[] = {
        0x7a5d0000, 0x807c817c,
        0x807aff7a, 0x00000080,
        0xbf0a717c, 0xbf85fff8,
-       0xbf820141, 0xbef4037e,
+       0xbf820142, 0xbef4037e,
        0x8775ff7f, 0x0000ffff,
        0x8875ff75, 0x00040000,
        0xbef60380, 0xbef703ff,
@@ -967,7 +967,7 @@ static const uint32_t cwsr_trap_gfx10_hex[] = {
        0x725d0000, 0xe0304080,
        0x725d0100, 0xe0304100,
        0x725d0200, 0xe0304180,
-       0x725d0300, 0xbf820031,
+       0x725d0300, 0xbf820032,
        0xbef603ff, 0x01000000,
        0xbef20378, 0x8078ff78,
        0x00000400, 0xbefc0384,
@@ -992,83 +992,84 @@ static const uint32_t cwsr_trap_gfx10_hex[] = {
        0x725d0000, 0xe0304100,
        0x725d0100, 0xe0304200,
        0x725d0200, 0xe0304300,
-       0x725d0300, 0xb9782a05,
-       0x80788178, 0x907c9973,
-       0x877c817c, 0xbf06817c,
-       0xbf850002, 0x8f788978,
-       0xbf820001, 0x8f788a78,
-       0xb9721e06, 0x8f728a72,
-       0x80787278, 0x8078ff78,
-       0x00000200, 0x80f8ff78,
-       0x00000050, 0xbef603ff,
-       0x01000000, 0xbefc03ff,
-       0x0000006c, 0x80f89078,
-       0xf429003a, 0xf0000000,
-       0xbf8cc07f, 0x80fc847c,
-       0xbf800000, 0xbe803100,
-       0xbe823102, 0x80f8a078,
-       0xf42d003a, 0xf0000000,
-       0xbf8cc07f, 0x80fc887c,
-       0xbf800000, 0xbe803100,
-       0xbe823102, 0xbe843104,
-       0xbe863106, 0x80f8c078,
-       0xf431003a, 0xf0000000,
-       0xbf8cc07f, 0x80fc907c,
-       0xbf800000, 0xbe803100,
-       0xbe823102, 0xbe843104,
-       0xbe863106, 0xbe883108,
-       0xbe8a310a, 0xbe8c310c,
-       0xbe8e310e, 0xbf06807c,
-       0xbf84fff0, 0xb9782a05,
-       0x80788178, 0x907c9973,
-       0x877c817c, 0xbf06817c,
-       0xbf850002, 0x8f788978,
-       0xbf820001, 0x8f788a78,
-       0xb9721e06, 0x8f728a72,
-       0x80787278, 0x8078ff78,
-       0x00000200, 0xbef603ff,
-       0x01000000, 0xf4211bfa,
+       0x725d0300, 0xbf8c3f70,
+       0xb9782a05, 0x80788178,
+       0x907c9973, 0x877c817c,
+       0xbf06817c, 0xbf850002,
+       0x8f788978, 0xbf820001,
+       0x8f788a78, 0xb9721e06,
+       0x8f728a72, 0x80787278,
+       0x8078ff78, 0x00000200,
+       0x80f8ff78, 0x00000050,
+       0xbef603ff, 0x01000000,
+       0xbefc03ff, 0x0000006c,
+       0x80f89078, 0xf429003a,
+       0xf0000000, 0xbf8cc07f,
+       0x80fc847c, 0xbf800000,
+       0xbe803100, 0xbe823102,
+       0x80f8a078, 0xf42d003a,
+       0xf0000000, 0xbf8cc07f,
+       0x80fc887c, 0xbf800000,
+       0xbe803100, 0xbe823102,
+       0xbe843104, 0xbe863106,
+       0x80f8c078, 0xf431003a,
+       0xf0000000, 0xbf8cc07f,
+       0x80fc907c, 0xbf800000,
+       0xbe803100, 0xbe823102,
+       0xbe843104, 0xbe863106,
+       0xbe883108, 0xbe8a310a,
+       0xbe8c310c, 0xbe8e310e,
+       0xbf06807c, 0xbf84fff0,
+       0xb9782a05, 0x80788178,
+       0x907c9973, 0x877c817c,
+       0xbf06817c, 0xbf850002,
+       0x8f788978, 0xbf820001,
+       0x8f788a78, 0xb9721e06,
+       0x8f728a72, 0x80787278,
+       0x8078ff78, 0x00000200,
+       0xbef603ff, 0x01000000,
+       0xf4211bfa, 0xf0000000,
+       0x80788478, 0xf4211b3a,
        0xf0000000, 0x80788478,
-       0xf4211b3a, 0xf0000000,
-       0x80788478, 0xf4211b7a,
+       0xf4211b7a, 0xf0000000,
+       0x80788478, 0xf4211eba,
        0xf0000000, 0x80788478,
-       0xf4211eba, 0xf0000000,
-       0x80788478, 0xf4211efa,
+       0xf4211efa, 0xf0000000,
+       0x80788478, 0xf4211c3a,
        0xf0000000, 0x80788478,
-       0xf4211c3a, 0xf0000000,
-       0x80788478, 0xf4211c7a,
+       0xf4211c7a, 0xf0000000,
+       0x80788478, 0xf4211e7a,
        0xf0000000, 0x80788478,
-       0xf4211e7a, 0xf0000000,
-       0x80788478, 0xf4211cfa,
+       0xf4211cfa, 0xf0000000,
+       0x80788478, 0xf4211bba,
        0xf0000000, 0x80788478,
+       0xbf8cc07f, 0xb9eef814,
        0xf4211bba, 0xf0000000,
        0x80788478, 0xbf8cc07f,
-       0xb9eef814, 0xf4211bba,
-       0xf0000000, 0x80788478,
-       0xbf8cc07f, 0xb9eef815,
-       0xbef2036d, 0x876dff72,
-       0x0000ffff, 0xbefc036f,
-       0xbefe037a, 0xbeff037b,
-       0x876f71ff, 0x000003ff,
-       0xb9ef4803, 0xb9f9f816,
-       0x876f71ff, 0xfffff800,
-       0x906f8b6f, 0xb9efa2c3,
-       0xb9f3f801, 0x876fff72,
-       0xfc000000, 0x906f9a6f,
-       0x8f6f906f, 0xbef30380,
+       0xb9eef815, 0xbef2036d,
+       0x876dff72, 0x0000ffff,
+       0xbefc036f, 0xbefe037a,
+       0xbeff037b, 0x876f71ff,
+       0x000003ff, 0xb9ef4803,
+       0xb9f9f816, 0x876f71ff,
+       0xfffff800, 0x906f8b6f,
+       0xb9efa2c3, 0xb9f3f801,
+       0x876fff72, 0xfc000000,
+       0x906f9a6f, 0x8f6f906f,
+       0xbef30380, 0x88736f73,
+       0x876fff72, 0x02000000,
+       0x906f996f, 0x8f6f8f6f,
        0x88736f73, 0x876fff72,
-       0x02000000, 0x906f996f,
-       0x8f6f8f6f, 0x88736f73,
-       0x876fff72, 0x01000000,
-       0x906f986f, 0x8f6f996f,
-       0x88736f73, 0x876fff70,
-       0x00800000, 0x906f976f,
-       0xb9f3f807, 0x87fe7e7e,
-       0x87ea6a6a, 0xb9f0f802,
-       0xbf8a0000, 0xbe80226c,
-       0xbf810000, 0xbf9f0000,
+       0x01000000, 0x906f986f,
+       0x8f6f996f, 0x88736f73,
+       0x876fff70, 0x00800000,
+       0x906f976f, 0xb9f3f807,
+       0x87fe7e7e, 0x87ea6a6a,
+       0xb9f0f802, 0xbf8a0000,
+       0xbe80226c, 0xbf810000,
        0xbf9f0000, 0xbf9f0000,
        0xbf9f0000, 0xbf9f0000,
+       0xbf9f0000, 0x00000000,
 };
 static const uint32_t cwsr_trap_arcturus_hex[] = {
        0xbf820001, 0xbf8202c4,
index cdaa523ce6bee562a00581efa0fad47e25925298..4433bda2ce25eb998c4cb771cd7d16610030aa11 100644 (file)
@@ -758,6 +758,7 @@ L_RESTORE_V0:
        buffer_load_dword       v1, v0, s_restore_buf_rsrc0, s_restore_mem_offset_save slc:1 glc:1 offset:256
        buffer_load_dword       v2, v0, s_restore_buf_rsrc0, s_restore_mem_offset_save slc:1 glc:1 offset:256*2
        buffer_load_dword       v3, v0, s_restore_buf_rsrc0, s_restore_mem_offset_save slc:1 glc:1 offset:256*3
+       s_waitcnt       vmcnt(0)
 
        /* restore SGPRs */
        //will be 2+8+16*6
index 1d3cd5c50d5f2b06191e5bf8ff1fee7bed7a6225..9af45d07515bd8eae17ed15084a59d4eaf0ab6e3 100644 (file)
@@ -282,7 +282,7 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
                goto err_bind_process;
        }
 
-       pr_debug("Creating queue for PASID %d on gpu 0x%x\n",
+       pr_debug("Creating queue for PASID 0x%x on gpu 0x%x\n",
                        p->pasid,
                        dev->id);
 
@@ -332,7 +332,7 @@ static int kfd_ioctl_destroy_queue(struct file *filp, struct kfd_process *p,
        int retval;
        struct kfd_ioctl_destroy_queue_args *args = data;
 
-       pr_debug("Destroying queue id %d for pasid %d\n",
+       pr_debug("Destroying queue id %d for pasid 0x%x\n",
                                args->queue_id,
                                p->pasid);
 
@@ -378,7 +378,7 @@ static int kfd_ioctl_update_queue(struct file *filp, struct kfd_process *p,
        properties.queue_percent = args->queue_percentage;
        properties.priority = args->queue_priority;
 
-       pr_debug("Updating queue id %d for pasid %d\n",
+       pr_debug("Updating queue id %d for pasid 0x%x\n",
                        args->queue_id, p->pasid);
 
        mutex_lock(&p->mutex);
@@ -855,7 +855,7 @@ static int kfd_ioctl_get_process_apertures(struct file *filp,
        struct kfd_process_device_apertures *pAperture;
        struct kfd_process_device *pdd;
 
-       dev_dbg(kfd_device, "get apertures for PASID %d", p->pasid);
+       dev_dbg(kfd_device, "get apertures for PASID 0x%x", p->pasid);
 
        args->num_of_nodes = 0;
 
@@ -913,7 +913,7 @@ static int kfd_ioctl_get_process_apertures_new(struct file *filp,
        uint32_t nodes = 0;
        int ret;
 
-       dev_dbg(kfd_device, "get apertures for PASID %d", p->pasid);
+       dev_dbg(kfd_device, "get apertures for PASID 0x%x", p->pasid);
 
        if (args->num_of_nodes == 0) {
                /* Return number of nodes, so that user space can alloacate
@@ -1128,7 +1128,7 @@ static int kfd_ioctl_set_scratch_backing_va(struct file *filep,
        mutex_unlock(&p->mutex);
 
        if (dev->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS &&
-           pdd->qpd.vmid != 0)
+           pdd->qpd.vmid != 0 && dev->kfd2kgd->set_scratch_backing_va)
                dev->kfd2kgd->set_scratch_backing_va(
                        dev->kgd, args->va_addr, pdd->qpd.vmid);
 
@@ -1801,7 +1801,7 @@ static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
        } else
                goto err_i1;
 
-       dev_dbg(kfd_device, "ioctl cmd 0x%x (#%d), arg 0x%lx\n", cmd, nr, arg);
+       dev_dbg(kfd_device, "ioctl cmd 0x%x (#0x%x), arg 0x%lx\n", cmd, nr, arg);
 
        process = kfd_get_process(current);
        if (IS_ERR(process)) {
@@ -1856,7 +1856,8 @@ static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
                kfree(kdata);
 
        if (retcode)
-               dev_dbg(kfd_device, "ret = %d\n", retcode);
+               dev_dbg(kfd_device, "ioctl cmd (#0x%x), arg 0x%lx, ret = %d\n",
+                               nr, arg, retcode);
 
        return retcode;
 }
@@ -1877,7 +1878,7 @@ static int kfd_mmio_mmap(struct kfd_dev *dev, struct kfd_process *process,
 
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
-       pr_debug("Process %d mapping mmio page\n"
+       pr_debug("pasid 0x%x mapping mmio page\n"
                 "     target user address == 0x%08llX\n"
                 "     physical address    == 0x%08llX\n"
                 "     vm_flags            == 0x%04lX\n"
index 66387caf966e2b01954fde2620af4ac66ab89245..0c327e0fc0f7d80d1543dd4e2b52995692734aeb 100644 (file)
@@ -138,6 +138,7 @@ static struct kfd_gpu_cache_info carrizo_cache_info[] = {
 /* TODO - check & update Vega10 cache details */
 #define vega10_cache_info carrizo_cache_info
 #define raven_cache_info carrizo_cache_info
+#define renoir_cache_info carrizo_cache_info
 /* TODO - check & update Navi10 cache details */
 #define navi10_cache_info carrizo_cache_info
 
@@ -670,7 +671,13 @@ static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev,
                pcache_info = raven_cache_info;
                num_of_cache_types = ARRAY_SIZE(raven_cache_info);
                break;
+       case CHIP_RENOIR:
+               pcache_info = renoir_cache_info;
+               num_of_cache_types = ARRAY_SIZE(renoir_cache_info);
+               break;
        case CHIP_NAVI10:
+       case CHIP_NAVI12:
+       case CHIP_NAVI14:
                pcache_info = navi10_cache_info;
                num_of_cache_types = ARRAY_SIZE(navi10_cache_info);
                break;
index a3441b0e385b7a32edf8a887dbafe2daaed3d109..d59f2cd056c648ee9d64c43c3fadda140b9b4dc1 100644 (file)
@@ -761,6 +761,7 @@ int dbgdev_wave_reset_wavefronts(struct kfd_dev *dev, struct kfd_process *p)
 {
        int status = 0;
        unsigned int vmid;
+       uint16_t queried_pasid;
        union SQ_CMD_BITS reg_sq_cmd;
        union GRBM_GFX_INDEX_BITS reg_gfx_index;
        struct kfd_process_device *pdd;
@@ -782,19 +783,18 @@ int dbgdev_wave_reset_wavefronts(struct kfd_dev *dev, struct kfd_process *p)
         */
 
        for (vmid = first_vmid_to_scan; vmid <= last_vmid_to_scan; vmid++) {
-               if (dev->kfd2kgd->get_atc_vmid_pasid_mapping_valid
-                               (dev->kgd, vmid)) {
-                       if (dev->kfd2kgd->get_atc_vmid_pasid_mapping_pasid
-                                       (dev->kgd, vmid) == p->pasid) {
-                               pr_debug("Killing wave fronts of vmid %d and pasid %d\n",
-                                               vmid, p->pasid);
-                               break;
-                       }
+               status = dev->kfd2kgd->get_atc_vmid_pasid_mapping_info
+                               (dev->kgd, vmid, &queried_pasid);
+
+               if (status && queried_pasid == p->pasid) {
+                       pr_debug("Killing wave fronts of vmid %d and pasid 0x%x\n",
+                                       vmid, p->pasid);
+                       break;
                }
        }
 
        if (vmid > last_vmid_to_scan) {
-               pr_err("Didn't find vmid for pasid %d\n", p->pasid);
+               pr_err("Didn't find vmid for pasid 0x%x\n", p->pasid);
                return -EFAULT;
        }
 
index 9d4af961c5d1f2d1b106585332c257e0d79deacf..9bfa50633654a9ebd6638ff4f60a782abf4cfef4 100644 (file)
@@ -96,7 +96,7 @@ bool kfd_dbgmgr_create(struct kfd_dbgmgr **ppmgr, struct kfd_dev *pdev)
 long kfd_dbgmgr_register(struct kfd_dbgmgr *pmgr, struct kfd_process *p)
 {
        if (pmgr->pasid != 0) {
-               pr_debug("H/W debugger is already active using pasid %d\n",
+               pr_debug("H/W debugger is already active using pasid 0x%x\n",
                                pmgr->pasid);
                return -EBUSY;
        }
@@ -117,7 +117,7 @@ long kfd_dbgmgr_unregister(struct kfd_dbgmgr *pmgr, struct kfd_process *p)
 {
        /* Is the requests coming from the already registered process? */
        if (pmgr->pasid != p->pasid) {
-               pr_debug("H/W debugger is not registered by calling pasid %d\n",
+               pr_debug("H/W debugger is not registered by calling pasid 0x%x\n",
                                p->pasid);
                return -EINVAL;
        }
@@ -134,7 +134,7 @@ long kfd_dbgmgr_wave_control(struct kfd_dbgmgr *pmgr,
 {
        /* Is the requests coming from the already registered process? */
        if (pmgr->pasid != wac_info->process->pasid) {
-               pr_debug("H/W debugger support was not registered for requester pasid %d\n",
+               pr_debug("H/W debugger support was not registered for requester pasid 0x%x\n",
                                wac_info->process->pasid);
                return -EINVAL;
        }
@@ -147,7 +147,7 @@ long kfd_dbgmgr_address_watch(struct kfd_dbgmgr *pmgr,
 {
        /* Is the requests coming from the already registered process? */
        if (pmgr->pasid != adw_info->process->pasid) {
-               pr_debug("H/W debugger support was not registered for requester pasid %d\n",
+               pr_debug("H/W debugger support was not registered for requester pasid 0x%x\n",
                                adw_info->process->pasid);
                return -EINVAL;
        }
index 0dc1084b5e829fe3dd580716d32d3e281f8e839d..8f4b24e84964b7eae692d8e2742b7e1e58730424 100644 (file)
  */
 static atomic_t kfd_locked = ATOMIC_INIT(0);
 
+#ifdef CONFIG_DRM_AMDGPU_CIK
+extern const struct kfd2kgd_calls gfx_v7_kfd2kgd;
+#endif
+extern const struct kfd2kgd_calls gfx_v8_kfd2kgd;
+extern const struct kfd2kgd_calls gfx_v9_kfd2kgd;
+extern const struct kfd2kgd_calls arcturus_kfd2kgd;
+extern const struct kfd2kgd_calls gfx_v10_kfd2kgd;
+
+static const struct kfd2kgd_calls *kfd2kgd_funcs[] = {
+#ifdef KFD_SUPPORT_IOMMU_V2
+#ifdef CONFIG_DRM_AMDGPU_CIK
+       [CHIP_KAVERI] = &gfx_v7_kfd2kgd,
+#endif
+       [CHIP_CARRIZO] = &gfx_v8_kfd2kgd,
+       [CHIP_RAVEN] = &gfx_v9_kfd2kgd,
+#endif
+#ifdef CONFIG_DRM_AMDGPU_CIK
+       [CHIP_HAWAII] = &gfx_v7_kfd2kgd,
+#endif
+       [CHIP_TONGA] = &gfx_v8_kfd2kgd,
+       [CHIP_FIJI] = &gfx_v8_kfd2kgd,
+       [CHIP_POLARIS10] = &gfx_v8_kfd2kgd,
+       [CHIP_POLARIS11] = &gfx_v8_kfd2kgd,
+       [CHIP_POLARIS12] = &gfx_v8_kfd2kgd,
+       [CHIP_VEGAM] = &gfx_v8_kfd2kgd,
+       [CHIP_VEGA10] = &gfx_v9_kfd2kgd,
+       [CHIP_VEGA12] = &gfx_v9_kfd2kgd,
+       [CHIP_VEGA20] = &gfx_v9_kfd2kgd,
+       [CHIP_RENOIR] = &gfx_v9_kfd2kgd,
+       [CHIP_ARCTURUS] = &arcturus_kfd2kgd,
+       [CHIP_NAVI10] = &gfx_v10_kfd2kgd,
+       [CHIP_NAVI12] = &gfx_v10_kfd2kgd,
+       [CHIP_NAVI14] = &gfx_v10_kfd2kgd,
+};
+
 #ifdef KFD_SUPPORT_IOMMU_V2
 static const struct kfd_device_info kaveri_device_info = {
        .asic_family = CHIP_KAVERI,
@@ -351,6 +386,24 @@ static const struct kfd_device_info arcturus_device_info = {
        .num_sdma_queues_per_engine = 8,
 };
 
+static const struct kfd_device_info renoir_device_info = {
+       .asic_family = CHIP_RENOIR,
+       .asic_name = "renoir",
+       .max_pasid_bits = 16,
+       .max_no_of_hqd  = 24,
+       .doorbell_size  = 8,
+       .ih_ring_entry_size = 8 * sizeof(uint32_t),
+       .event_interrupt_class = &event_interrupt_class_v9,
+       .num_of_watch_points = 4,
+       .mqd_size_aligned = MQD_SIZE_ALIGNED,
+       .supports_cwsr = true,
+       .needs_iommu_device = false,
+       .needs_pci_atomics = false,
+       .num_sdma_engines = 1,
+       .num_xgmi_sdma_engines = 0,
+       .num_sdma_queues_per_engine = 2,
+};
+
 static const struct kfd_device_info navi10_device_info = {
        .asic_family = CHIP_NAVI10,
        .asic_name = "navi10",
@@ -369,133 +422,64 @@ static const struct kfd_device_info navi10_device_info = {
        .num_sdma_queues_per_engine = 8,
 };
 
-struct kfd_deviceid {
-       unsigned short did;
-       const struct kfd_device_info *device_info;
+static const struct kfd_device_info navi12_device_info = {
+       .asic_family = CHIP_NAVI12,
+       .asic_name = "navi12",
+       .max_pasid_bits = 16,
+       .max_no_of_hqd  = 24,
+       .doorbell_size  = 8,
+       .ih_ring_entry_size = 8 * sizeof(uint32_t),
+       .event_interrupt_class = &event_interrupt_class_v9,
+       .num_of_watch_points = 4,
+       .mqd_size_aligned = MQD_SIZE_ALIGNED,
+       .needs_iommu_device = false,
+       .supports_cwsr = true,
+       .needs_pci_atomics = false,
+       .num_sdma_engines = 2,
+       .num_xgmi_sdma_engines = 0,
+       .num_sdma_queues_per_engine = 8,
 };
 
-static const struct kfd_deviceid supported_devices[] = {
+static const struct kfd_device_info navi14_device_info = {
+       .asic_family = CHIP_NAVI14,
+       .asic_name = "navi14",
+       .max_pasid_bits = 16,
+       .max_no_of_hqd  = 24,
+       .doorbell_size  = 8,
+       .ih_ring_entry_size = 8 * sizeof(uint32_t),
+       .event_interrupt_class = &event_interrupt_class_v9,
+       .num_of_watch_points = 4,
+       .mqd_size_aligned = MQD_SIZE_ALIGNED,
+       .needs_iommu_device = false,
+       .supports_cwsr = true,
+       .needs_pci_atomics = false,
+       .num_sdma_engines = 2,
+       .num_xgmi_sdma_engines = 0,
+       .num_sdma_queues_per_engine = 8,
+};
+
+/* For each entry, [0] is regular and [1] is virtualisation device. */
+static const struct kfd_device_info *kfd_supported_devices[][2] = {
 #ifdef KFD_SUPPORT_IOMMU_V2
-       { 0x1304, &kaveri_device_info },        /* Kaveri */
-       { 0x1305, &kaveri_device_info },        /* Kaveri */
-       { 0x1306, &kaveri_device_info },        /* Kaveri */
-       { 0x1307, &kaveri_device_info },        /* Kaveri */
-       { 0x1309, &kaveri_device_info },        /* Kaveri */
-       { 0x130A, &kaveri_device_info },        /* Kaveri */
-       { 0x130B, &kaveri_device_info },        /* Kaveri */
-       { 0x130C, &kaveri_device_info },        /* Kaveri */
-       { 0x130D, &kaveri_device_info },        /* Kaveri */
-       { 0x130E, &kaveri_device_info },        /* Kaveri */
-       { 0x130F, &kaveri_device_info },        /* Kaveri */
-       { 0x1310, &kaveri_device_info },        /* Kaveri */
-       { 0x1311, &kaveri_device_info },        /* Kaveri */
-       { 0x1312, &kaveri_device_info },        /* Kaveri */
-       { 0x1313, &kaveri_device_info },        /* Kaveri */
-       { 0x1315, &kaveri_device_info },        /* Kaveri */
-       { 0x1316, &kaveri_device_info },        /* Kaveri */
-       { 0x1317, &kaveri_device_info },        /* Kaveri */
-       { 0x1318, &kaveri_device_info },        /* Kaveri */
-       { 0x131B, &kaveri_device_info },        /* Kaveri */
-       { 0x131C, &kaveri_device_info },        /* Kaveri */
-       { 0x131D, &kaveri_device_info },        /* Kaveri */
-       { 0x9870, &carrizo_device_info },       /* Carrizo */
-       { 0x9874, &carrizo_device_info },       /* Carrizo */
-       { 0x9875, &carrizo_device_info },       /* Carrizo */
-       { 0x9876, &carrizo_device_info },       /* Carrizo */
-       { 0x9877, &carrizo_device_info },       /* Carrizo */
-       { 0x15DD, &raven_device_info },         /* Raven */
-       { 0x15D8, &raven_device_info },         /* Raven */
+       [CHIP_KAVERI] = {&kaveri_device_info, NULL},
+       [CHIP_CARRIZO] = {&carrizo_device_info, NULL},
+       [CHIP_RAVEN] = {&raven_device_info, NULL},
 #endif
-       { 0x67A0, &hawaii_device_info },        /* Hawaii */
-       { 0x67A1, &hawaii_device_info },        /* Hawaii */
-       { 0x67A2, &hawaii_device_info },        /* Hawaii */
-       { 0x67A8, &hawaii_device_info },        /* Hawaii */
-       { 0x67A9, &hawaii_device_info },        /* Hawaii */
-       { 0x67AA, &hawaii_device_info },        /* Hawaii */
-       { 0x67B0, &hawaii_device_info },        /* Hawaii */
-       { 0x67B1, &hawaii_device_info },        /* Hawaii */
-       { 0x67B8, &hawaii_device_info },        /* Hawaii */
-       { 0x67B9, &hawaii_device_info },        /* Hawaii */
-       { 0x67BA, &hawaii_device_info },        /* Hawaii */
-       { 0x67BE, &hawaii_device_info },        /* Hawaii */
-       { 0x6920, &tonga_device_info },         /* Tonga */
-       { 0x6921, &tonga_device_info },         /* Tonga */
-       { 0x6928, &tonga_device_info },         /* Tonga */
-       { 0x6929, &tonga_device_info },         /* Tonga */
-       { 0x692B, &tonga_device_info },         /* Tonga */
-       { 0x6938, &tonga_device_info },         /* Tonga */
-       { 0x6939, &tonga_device_info },         /* Tonga */
-       { 0x7300, &fiji_device_info },          /* Fiji */
-       { 0x730F, &fiji_vf_device_info },       /* Fiji vf*/
-       { 0x67C0, &polaris10_device_info },     /* Polaris10 */
-       { 0x67C1, &polaris10_device_info },     /* Polaris10 */
-       { 0x67C2, &polaris10_device_info },     /* Polaris10 */
-       { 0x67C4, &polaris10_device_info },     /* Polaris10 */
-       { 0x67C7, &polaris10_device_info },     /* Polaris10 */
-       { 0x67C8, &polaris10_device_info },     /* Polaris10 */
-       { 0x67C9, &polaris10_device_info },     /* Polaris10 */
-       { 0x67CA, &polaris10_device_info },     /* Polaris10 */
-       { 0x67CC, &polaris10_device_info },     /* Polaris10 */
-       { 0x67CF, &polaris10_device_info },     /* Polaris10 */
-       { 0x67D0, &polaris10_vf_device_info },  /* Polaris10 vf*/
-       { 0x67DF, &polaris10_device_info },     /* Polaris10 */
-       { 0x6FDF, &polaris10_device_info },     /* Polaris10 */
-       { 0x67E0, &polaris11_device_info },     /* Polaris11 */
-       { 0x67E1, &polaris11_device_info },     /* Polaris11 */
-       { 0x67E3, &polaris11_device_info },     /* Polaris11 */
-       { 0x67E7, &polaris11_device_info },     /* Polaris11 */
-       { 0x67E8, &polaris11_device_info },     /* Polaris11 */
-       { 0x67E9, &polaris11_device_info },     /* Polaris11 */
-       { 0x67EB, &polaris11_device_info },     /* Polaris11 */
-       { 0x67EF, &polaris11_device_info },     /* Polaris11 */
-       { 0x67FF, &polaris11_device_info },     /* Polaris11 */
-       { 0x6980, &polaris12_device_info },     /* Polaris12 */
-       { 0x6981, &polaris12_device_info },     /* Polaris12 */
-       { 0x6985, &polaris12_device_info },     /* Polaris12 */
-       { 0x6986, &polaris12_device_info },     /* Polaris12 */
-       { 0x6987, &polaris12_device_info },     /* Polaris12 */
-       { 0x6995, &polaris12_device_info },     /* Polaris12 */
-       { 0x6997, &polaris12_device_info },     /* Polaris12 */
-       { 0x699F, &polaris12_device_info },     /* Polaris12 */
-       { 0x694C, &vegam_device_info },         /* VegaM */
-       { 0x694E, &vegam_device_info },         /* VegaM */
-       { 0x694F, &vegam_device_info },         /* VegaM */
-       { 0x6860, &vega10_device_info },        /* Vega10 */
-       { 0x6861, &vega10_device_info },        /* Vega10 */
-       { 0x6862, &vega10_device_info },        /* Vega10 */
-       { 0x6863, &vega10_device_info },        /* Vega10 */
-       { 0x6864, &vega10_device_info },        /* Vega10 */
-       { 0x6867, &vega10_device_info },        /* Vega10 */
-       { 0x6868, &vega10_device_info },        /* Vega10 */
-       { 0x6869, &vega10_device_info },        /* Vega10 */
-       { 0x686A, &vega10_device_info },        /* Vega10 */
-       { 0x686B, &vega10_device_info },        /* Vega10 */
-       { 0x686C, &vega10_vf_device_info },     /* Vega10  vf*/
-       { 0x686D, &vega10_device_info },        /* Vega10 */
-       { 0x686E, &vega10_device_info },        /* Vega10 */
-       { 0x686F, &vega10_device_info },        /* Vega10 */
-       { 0x687F, &vega10_device_info },        /* Vega10 */
-       { 0x69A0, &vega12_device_info },        /* Vega12 */
-       { 0x69A1, &vega12_device_info },        /* Vega12 */
-       { 0x69A2, &vega12_device_info },        /* Vega12 */
-       { 0x69A3, &vega12_device_info },        /* Vega12 */
-       { 0x69AF, &vega12_device_info },        /* Vega12 */
-       { 0x66a0, &vega20_device_info },        /* Vega20 */
-       { 0x66a1, &vega20_device_info },        /* Vega20 */
-       { 0x66a2, &vega20_device_info },        /* Vega20 */
-       { 0x66a3, &vega20_device_info },        /* Vega20 */
-       { 0x66a4, &vega20_device_info },        /* Vega20 */
-       { 0x66a7, &vega20_device_info },        /* Vega20 */
-       { 0x66af, &vega20_device_info },        /* Vega20 */
-       { 0x738C, &arcturus_device_info },      /* Arcturus */
-       { 0x7388, &arcturus_device_info },      /* Arcturus */
-       { 0x738E, &arcturus_device_info },      /* Arcturus */
-       { 0x7390, &arcturus_device_info },      /* Arcturus vf */
-       { 0x7310, &navi10_device_info },        /* Navi10 */
-       { 0x7312, &navi10_device_info },        /* Navi10 */
-       { 0x7318, &navi10_device_info },        /* Navi10 */
-       { 0x731a, &navi10_device_info },        /* Navi10 */
-       { 0x731f, &navi10_device_info },        /* Navi10 */
+       [CHIP_HAWAII] = {&hawaii_device_info, NULL},
+       [CHIP_TONGA] = {&tonga_device_info, NULL},
+       [CHIP_FIJI] = {&fiji_device_info, &fiji_vf_device_info},
+       [CHIP_POLARIS10] = {&polaris10_device_info, &polaris10_vf_device_info},
+       [CHIP_POLARIS11] = {&polaris11_device_info, NULL},
+       [CHIP_POLARIS12] = {&polaris12_device_info, NULL},
+       [CHIP_VEGAM] = {&vegam_device_info, NULL},
+       [CHIP_VEGA10] = {&vega10_device_info, &vega10_vf_device_info},
+       [CHIP_VEGA12] = {&vega12_device_info, NULL},
+       [CHIP_VEGA20] = {&vega20_device_info, NULL},
+       [CHIP_RENOIR] = {&renoir_device_info, NULL},
+       [CHIP_ARCTURUS] = {&arcturus_device_info, &arcturus_device_info},
+       [CHIP_NAVI10] = {&navi10_device_info, NULL},
+       [CHIP_NAVI12] = {&navi12_device_info, &navi12_device_info},
+       [CHIP_NAVI14] = {&navi14_device_info, NULL},
 };
 
 static int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size,
@@ -504,32 +488,25 @@ static void kfd_gtt_sa_fini(struct kfd_dev *kfd);
 
 static int kfd_resume(struct kfd_dev *kfd);
 
-static const struct kfd_device_info *lookup_device_info(unsigned short did)
+struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd,
+       struct pci_dev *pdev, unsigned int asic_type, bool vf)
 {
-       size_t i;
+       struct kfd_dev *kfd;
+       const struct kfd_device_info *device_info;
+       const struct kfd2kgd_calls *f2g;
 
-       for (i = 0; i < ARRAY_SIZE(supported_devices); i++) {
-               if (supported_devices[i].did == did) {
-                       WARN_ON(!supported_devices[i].device_info);
-                       return supported_devices[i].device_info;
-               }
+       if (asic_type >= sizeof(kfd_supported_devices) / (sizeof(void *) * 2)
+               || asic_type >= sizeof(kfd2kgd_funcs) / sizeof(void *)) {
+               dev_err(kfd_device, "asic_type %d out of range\n", asic_type);
+               return NULL; /* asic_type out of range */
        }
 
-       dev_warn(kfd_device, "DID %04x is missing in supported_devices\n",
-                did);
-
-       return NULL;
-}
-
-struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd,
-       struct pci_dev *pdev, const struct kfd2kgd_calls *f2g)
-{
-       struct kfd_dev *kfd;
-       const struct kfd_device_info *device_info =
-                                       lookup_device_info(pdev->device);
+       device_info = kfd_supported_devices[asic_type][vf];
+       f2g = kfd2kgd_funcs[asic_type];
 
-       if (!device_info) {
-               dev_err(kfd_device, "kgd2kfd_probe failed\n");
+       if (!device_info || !f2g) {
+               dev_err(kfd_device, "%s %s not supported in kfd\n",
+                       amdgpu_asic_name[asic_type], vf ? "VF" : "");
                return NULL;
        }
 
@@ -593,10 +570,12 @@ static void kfd_cwsr_init(struct kfd_dev *kfd)
 }
 
 bool kgd2kfd_device_init(struct kfd_dev *kfd,
+                        struct drm_device *ddev,
                         const struct kgd2kfd_shared_resources *gpu_resources)
 {
        unsigned int size;
 
+       kfd->ddev = ddev;
        kfd->mec_fw_version = amdgpu_amdkfd_get_fw_version(kfd->kgd,
                        KGD_ENGINE_MEC1);
        kfd->sdma_fw_version = amdgpu_amdkfd_get_fw_version(kfd->kgd,
index d985e31fcc1eb3249857e35732fa835fd94c3aaf..81fb545cf42c6f90e79a374ba2eebde5c7df89ec 100644 (file)
@@ -195,20 +195,30 @@ static int allocate_vmid(struct device_queue_manager *dqm,
                        struct qcm_process_device *qpd,
                        struct queue *q)
 {
-       int bit, allocated_vmid;
+       int allocated_vmid = -1, i;
 
-       if (dqm->vmid_bitmap == 0)
-               return -ENOMEM;
+       for (i = dqm->dev->vm_info.first_vmid_kfd;
+                       i <= dqm->dev->vm_info.last_vmid_kfd; i++) {
+               if (!dqm->vmid_pasid[i]) {
+                       allocated_vmid = i;
+                       break;
+               }
+       }
+
+       if (allocated_vmid < 0) {
+               pr_err("no more vmid to allocate\n");
+               return -ENOSPC;
+       }
 
-       bit = ffs(dqm->vmid_bitmap) - 1;
-       dqm->vmid_bitmap &= ~(1 << bit);
+       pr_debug("vmid allocated: %d\n", allocated_vmid);
+
+       dqm->vmid_pasid[allocated_vmid] = q->process->pasid;
+
+       set_pasid_vmid_mapping(dqm, q->process->pasid, allocated_vmid);
 
-       allocated_vmid = bit + dqm->dev->vm_info.first_vmid_kfd;
-       pr_debug("vmid allocation %d\n", allocated_vmid);
        qpd->vmid = allocated_vmid;
        q->properties.vmid = allocated_vmid;
 
-       set_pasid_vmid_mapping(dqm, q->process->pasid, q->properties.vmid);
        program_sh_mem_settings(dqm, qpd);
 
        /* qpd->page_table_base is set earlier when register_process()
@@ -220,8 +230,9 @@ static int allocate_vmid(struct device_queue_manager *dqm,
        /* invalidate the VM context after pasid and vmid mapping is set up */
        kfd_flush_tlb(qpd_to_pdd(qpd));
 
-       dqm->dev->kfd2kgd->set_scratch_backing_va(
-               dqm->dev->kgd, qpd->sh_hidden_private_base, qpd->vmid);
+       if (dqm->dev->kfd2kgd->set_scratch_backing_va)
+               dqm->dev->kfd2kgd->set_scratch_backing_va(dqm->dev->kgd,
+                               qpd->sh_hidden_private_base, qpd->vmid);
 
        return 0;
 }
@@ -248,8 +259,6 @@ static void deallocate_vmid(struct device_queue_manager *dqm,
                                struct qcm_process_device *qpd,
                                struct queue *q)
 {
-       int bit = qpd->vmid - dqm->dev->vm_info.first_vmid_kfd;
-
        /* On GFX v7, CP doesn't flush TC at dequeue */
        if (q->device->device_info->asic_family == CHIP_HAWAII)
                if (flush_texture_cache_nocpsch(q->device, qpd))
@@ -259,8 +268,8 @@ static void deallocate_vmid(struct device_queue_manager *dqm,
 
        /* Release the vmid mapping */
        set_pasid_vmid_mapping(dqm, 0, qpd->vmid);
+       dqm->vmid_pasid[qpd->vmid] = 0;
 
-       dqm->vmid_bitmap |= (1 << bit);
        qpd->vmid = 0;
        q->properties.vmid = 0;
 }
@@ -579,7 +588,7 @@ static int evict_process_queues_nocpsch(struct device_queue_manager *dqm,
                goto out;
 
        pdd = qpd_to_pdd(qpd);
-       pr_info_ratelimited("Evicting PASID %u queues\n",
+       pr_info_ratelimited("Evicting PASID 0x%x queues\n",
                            pdd->process->pasid);
 
        /* Mark all queues as evicted. Deactivate all active queues on
@@ -621,7 +630,7 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm,
                goto out;
 
        pdd = qpd_to_pdd(qpd);
-       pr_info_ratelimited("Evicting PASID %u queues\n",
+       pr_info_ratelimited("Evicting PASID 0x%x queues\n",
                            pdd->process->pasid);
 
        /* Mark all queues as evicted. Deactivate all active queues on
@@ -667,7 +676,7 @@ static int restore_process_queues_nocpsch(struct device_queue_manager *dqm,
                goto out;
        }
 
-       pr_info_ratelimited("Restoring PASID %u queues\n",
+       pr_info_ratelimited("Restoring PASID 0x%x queues\n",
                            pdd->process->pasid);
 
        /* Update PD Base in QPD */
@@ -739,7 +748,7 @@ static int restore_process_queues_cpsch(struct device_queue_manager *dqm,
                goto out;
        }
 
-       pr_info_ratelimited("Restoring PASID %u queues\n",
+       pr_info_ratelimited("Restoring PASID 0x%x queues\n",
                            pdd->process->pasid);
 
        /* Update PD Base in QPD */
@@ -879,7 +888,8 @@ static int initialize_nocpsch(struct device_queue_manager *dqm)
                                dqm->allocated_queues[pipe] |= 1 << queue;
        }
 
-       dqm->vmid_bitmap = (1 << dqm->dev->vm_info.vmid_num_kfd) - 1;
+       memset(dqm->vmid_pasid, 0, sizeof(dqm->vmid_pasid));
+
        dqm->sdma_bitmap = ~0ULL >> (64 - get_num_sdma_queues(dqm));
        dqm->xgmi_sdma_bitmap = ~0ULL >> (64 - get_num_xgmi_sdma_queues(dqm));
 
@@ -902,12 +912,18 @@ static void uninitialize(struct device_queue_manager *dqm)
 static int start_nocpsch(struct device_queue_manager *dqm)
 {
        init_interrupts(dqm);
-       return pm_init(&dqm->packets, dqm);
+       
+       if (dqm->dev->device_info->asic_family == CHIP_HAWAII)
+               return pm_init(&dqm->packets, dqm);
+       
+       return 0;
 }
 
 static int stop_nocpsch(struct device_queue_manager *dqm)
 {
-       pm_uninit(&dqm->packets);
+       if (dqm->dev->device_info->asic_family == CHIP_HAWAII)
+               pm_uninit(&dqm->packets);
+       
        return 0;
 }
 
@@ -1676,7 +1692,8 @@ static int allocate_hiq_sdma_mqd(struct device_queue_manager *dqm)
        struct kfd_dev *dev = dqm->dev;
        struct kfd_mem_obj *mem_obj = &dqm->hiq_sdma_mqd;
        uint32_t size = dqm->mqd_mgrs[KFD_MQD_TYPE_SDMA]->mqd_size *
-               dev->device_info->num_sdma_engines *
+               (dev->device_info->num_sdma_engines +
+               dev->device_info->num_xgmi_sdma_engines) *
                dev->device_info->num_sdma_queues_per_engine +
                dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ]->mqd_size;
 
@@ -1786,10 +1803,13 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev)
        case CHIP_VEGA12:
        case CHIP_VEGA20:
        case CHIP_RAVEN:
+       case CHIP_RENOIR:
        case CHIP_ARCTURUS:
                device_queue_manager_init_v9(&dqm->asic_ops);
                break;
        case CHIP_NAVI10:
+       case CHIP_NAVI12:
+       case CHIP_NAVI14:
                device_queue_manager_init_v10_navi10(&dqm->asic_ops);
                break;
        default:
@@ -1917,7 +1937,8 @@ int dqm_debugfs_hqds(struct seq_file *m, void *data)
                }
        }
 
-       for (pipe = 0; pipe < get_num_sdma_engines(dqm); pipe++) {
+       for (pipe = 0; pipe < get_num_sdma_engines(dqm) +
+                       get_num_xgmi_sdma_engines(dqm); pipe++) {
                for (queue = 0;
                     queue < dqm->dev->device_info->num_sdma_queues_per_engine;
                     queue++) {
index 90db2c9275f6ccb40fd4839e870905ecf3add09e..2eaea6b04cbe4d655bd0afc5445ba4b700fdc934 100644 (file)
@@ -32,6 +32,8 @@
 #include "kfd_mqd_manager.h"
 
 
+#define VMID_NUM 16
+
 struct device_process_node {
        struct qcm_process_device *qpd;
        struct list_head list;
@@ -185,7 +187,8 @@ struct device_queue_manager {
        unsigned int            *allocated_queues;
        uint64_t                sdma_bitmap;
        uint64_t                xgmi_sdma_bitmap;
-       unsigned int            vmid_bitmap;
+       /* the pasid mapping for each kfd vmid */
+       uint16_t                vmid_pasid[VMID_NUM];
        uint64_t                pipelines_addr;
        struct kfd_mem_obj      *pipeline_mem;
        uint64_t                fence_gpu_addr;
index d674d4b3340faa3437bf798cd73c05fd01d82411..908081c85de1da238c6f0762c9c22817100a0bc1 100644 (file)
@@ -852,8 +852,8 @@ static void lookup_events_by_type_and_signal(struct kfd_process *p,
 
        if (type == KFD_EVENT_TYPE_MEMORY) {
                dev_warn(kfd_device,
-                       "Sending SIGSEGV to HSA Process with PID %d ",
-                               p->lead_thread->pid);
+                       "Sending SIGSEGV to process %d (pasid 0x%x)",
+                               p->lead_thread->pid, p->pasid);
                send_sig(SIGSEGV, p->lead_thread, 0);
        }
 
@@ -861,13 +861,13 @@ static void lookup_events_by_type_and_signal(struct kfd_process *p,
        if (send_signal) {
                if (send_sigterm) {
                        dev_warn(kfd_device,
-                               "Sending SIGTERM to HSA Process with PID %d ",
-                                       p->lead_thread->pid);
+                               "Sending SIGTERM to process %d (pasid 0x%x)",
+                                       p->lead_thread->pid, p->pasid);
                        send_sig(SIGTERM, p->lead_thread, 0);
                } else {
                        dev_err(kfd_device,
-                               "HSA Process (PID %d) got unhandled exception",
-                               p->lead_thread->pid);
+                               "Process %d (pasid 0x%x) got unhandled exception",
+                               p->lead_thread->pid, p->pasid);
                }
        }
 }
@@ -936,7 +936,8 @@ void kfd_signal_iommu_event(struct kfd_dev *dev, unsigned int pasid,
        /* Workaround on Raven to not kill the process when memory is freed
         * before IOMMU is able to finish processing all the excessive PPRs
         */
-       if (dev->device_info->asic_family != CHIP_RAVEN) {
+       if (dev->device_info->asic_family != CHIP_RAVEN &&
+           dev->device_info->asic_family != CHIP_RENOIR) {
                mutex_lock(&p->event_mutex);
 
                /* Lookup events by type and signal them */
index 9dc4bff8085e21e0e6b1b19bf38d263fc4b42eb9..bb77b8890e77f8ebd71d1e7539405f0c5224518c 100644 (file)
@@ -369,8 +369,13 @@ int kfd_init_apertures(struct kfd_process *process)
 
        /*Iterating over all devices*/
        while (kfd_topology_enum_kfd_devices(id, &dev) == 0) {
-               if (!dev) {
-                       id++; /* Skip non GPU devices */
+               if (!dev || kfd_devcgroup_check_permission(dev)) {
+                       /* Skip non GPU devices and devices to which the
+                        * current process have no access to. Access can be
+                        * limited by placing the process in a specific
+                        * cgroup hierarchy
+                        */
+                       id++;
                        continue;
                }
 
@@ -405,8 +410,11 @@ int kfd_init_apertures(struct kfd_process *process)
                        case CHIP_VEGA12:
                        case CHIP_VEGA20:
                        case CHIP_RAVEN:
+                       case CHIP_RENOIR:
                        case CHIP_ARCTURUS:
                        case CHIP_NAVI10:
+                       case CHIP_NAVI12:
+                       case CHIP_NAVI14:
                                kfd_init_apertures_v9(pdd, id);
                                break;
                        default:
index 3ef67d2e0d9f9471ce007d96038435fd50c8d22f..e05d75ecda21839e85a9c7990fed87df84503dd9 100644 (file)
@@ -54,8 +54,7 @@ static bool event_interrupt_isr_v9(struct kfd_dev *dev,
                memcpy(patched_ihre, ih_ring_entry,
                                dev->device_info->ih_ring_entry_size);
 
-               pasid = dev->kfd2kgd->get_atc_vmid_pasid_mapping_pasid(
-                               dev->kgd, vmid);
+               pasid = dev->dqm->vmid_pasid[vmid];
 
                /* Patch the pasid field */
                patched_ihre[3] = cpu_to_le32((le32_to_cpu(patched_ihre[3])
index c56ac47cd3189779333acc9e8da89a8f9ad7c5be..bc47f6a44456440a0d85ad028fe75d5f83b3e8be 100644 (file)
@@ -62,6 +62,11 @@ int kfd_interrupt_init(struct kfd_dev *kfd)
        }
 
        kfd->ih_wq = alloc_workqueue("KFD IH", WQ_HIGHPRI, 1);
+       if (unlikely(!kfd->ih_wq)) {
+               kfifo_free(&kfd->ih_fifo);
+               dev_err(kfd_chardev(), "Failed to allocate KFD IH workqueue\n");
+               return -ENOMEM;
+       }
        spin_lock_init(&kfd->interrupt_lock);
 
        INIT_WORK(&kfd->interrupt_work, interrupt_wq);
index 5f35df23fb18ec365cc079fb9312ea0eb5a0929c..193e2835bd4d26b7709cae4305cd7544c41b2567 100644 (file)
@@ -160,7 +160,7 @@ static void iommu_pasid_shutdown_callback(struct pci_dev *pdev, int pasid)
        if (!p)
                return;
 
-       pr_debug("Unbinding process %d from IOMMU\n", pasid);
+       pr_debug("Unbinding process 0x%x from IOMMU\n", pasid);
 
        mutex_lock(kfd_get_dbgmgr_mutex());
 
@@ -194,7 +194,7 @@ static int iommu_invalid_ppr_cb(struct pci_dev *pdev, int pasid,
        struct kfd_dev *dev;
 
        dev_warn_ratelimited(kfd_device,
-                       "Invalid PPR device %x:%x.%x pasid %d address 0x%lX flags 0x%X",
+                       "Invalid PPR device %x:%x.%x pasid 0x%x address 0x%lX flags 0x%X",
                        PCI_BUS_NUM(pdev->devfn),
                        PCI_SLOT(pdev->devfn),
                        PCI_FUNC(pdev->devfn),
@@ -235,7 +235,7 @@ static int kfd_bind_processes_to_device(struct kfd_dev *kfd)
                err = amd_iommu_bind_pasid(kfd->pdev, p->pasid,
                                p->lead_thread);
                if (err < 0) {
-                       pr_err("Unexpected pasid %d binding failure\n",
+                       pr_err("Unexpected pasid 0x%x binding failure\n",
                                        p->pasid);
                        mutex_unlock(&p->mutex);
                        break;
index 8b4564f71a7a56c11f33d61509b3cb27880c8d69..11d2448913938ddc0f65e3ff56fa87d8f4e3d451 100644 (file)
@@ -330,10 +330,13 @@ struct kernel_queue *kernel_queue_init(struct kfd_dev *dev,
        case CHIP_VEGA12:
        case CHIP_VEGA20:
        case CHIP_RAVEN:
+       case CHIP_RENOIR:
        case CHIP_ARCTURUS:
                kernel_queue_init_v9(&kq->ops_asic_specific);
                break;
        case CHIP_NAVI10:
+       case CHIP_NAVI12:
+       case CHIP_NAVI14:
                kernel_queue_init_v10(&kq->ops_asic_specific);
                break;
        default:
index 986ff52d5750ccf605c563401b1e2aa51392055d..f4b7f7e6c40e490fceca3bd95c447418ff8058b5 100644 (file)
@@ -82,7 +82,7 @@ static void kfd_exit(void)
        kfd_chardev_exit();
 }
 
-int kgd2kfd_init()
+int kgd2kfd_init(void)
 {
        return kfd_init();
 }
index 9cd3eb2d90bd6b54cc47ec698eba07c146bd9c1b..4a236b2c2354effbfb82b9e03ea2e2a5a594aff7 100644 (file)
@@ -69,35 +69,13 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
 static struct kfd_mem_obj *allocate_mqd(struct kfd_dev *kfd,
                struct queue_properties *q)
 {
-       int retval;
-       struct kfd_mem_obj *mqd_mem_obj = NULL;
+       struct kfd_mem_obj *mqd_mem_obj;
 
-       /* From V9,  for CWSR, the control stack is located on the next page
-        * boundary after the mqd, we will use the gtt allocation function
-        * instead of sub-allocation function.
-        */
-       if (kfd->cwsr_enabled && (q->type == KFD_QUEUE_TYPE_COMPUTE)) {
-               mqd_mem_obj = kzalloc(sizeof(struct kfd_mem_obj), GFP_NOIO);
-               if (!mqd_mem_obj)
-                       return NULL;
-               retval = amdgpu_amdkfd_alloc_gtt_mem(kfd->kgd,
-                       ALIGN(q->ctl_stack_size, PAGE_SIZE) +
-                               ALIGN(sizeof(struct v10_compute_mqd), PAGE_SIZE),
-                       &(mqd_mem_obj->gtt_mem),
-                       &(mqd_mem_obj->gpu_addr),
-                       (void *)&(mqd_mem_obj->cpu_ptr), true);
-       } else {
-               retval = kfd_gtt_sa_allocate(kfd, sizeof(struct v10_compute_mqd),
-                               &mqd_mem_obj);
-       }
-
-       if (retval) {
-               kfree(mqd_mem_obj);
+       if (kfd_gtt_sa_allocate(kfd, sizeof(struct v10_compute_mqd),
+                       &mqd_mem_obj))
                return NULL;
-       }
 
        return mqd_mem_obj;
-
 }
 
 static void init_mqd(struct mqd_manager *mm, void **mqd,
@@ -250,14 +228,7 @@ static int destroy_mqd(struct mqd_manager *mm, void *mqd,
 static void free_mqd(struct mqd_manager *mm, void *mqd,
                        struct kfd_mem_obj *mqd_mem_obj)
 {
-       struct kfd_dev *kfd = mm->dev;
-
-       if (mqd_mem_obj->gtt_mem) {
-               amdgpu_amdkfd_free_gtt_mem(kfd->kgd, mqd_mem_obj->gtt_mem);
-               kfree(mqd_mem_obj);
-       } else {
-               kfd_gtt_sa_free(mm->dev, mqd_mem_obj);
-       }
+       kfd_gtt_sa_free(mm->dev, mqd_mem_obj);
 }
 
 static bool is_occupied(struct mqd_manager *mm, void *mqd,
index 2c8624c5b42c136002da2e56f71ba8b9cdc4519d..83ef4b3dd2fbb2ce1393c268c16c33388bc6136d 100644 (file)
@@ -239,10 +239,13 @@ int pm_init(struct packet_manager *pm, struct device_queue_manager *dqm)
        case CHIP_VEGA12:
        case CHIP_VEGA20:
        case CHIP_RAVEN:
+       case CHIP_RENOIR:
        case CHIP_ARCTURUS:
                pm->pmf = &kfd_v9_pm_funcs;
                break;
        case CHIP_NAVI10:
+       case CHIP_NAVI12:
+       case CHIP_NAVI14:
                pm->pmf = &kfd_v10_pm_funcs;
                break;
        default:
index c89326125d71170509531a8ffc434db3101f1908..060a9e8b301e4a0cfc409badc943c10c9567b489 100644 (file)
 #include <linux/seq_file.h>
 #include <linux/kref.h>
 #include <linux/sysfs.h>
+#include <linux/device_cgroup.h>
+#include <drm/drm_file.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_device.h>
 #include <kgd_kfd_interface.h>
 
 #include "amd_shared.h"
@@ -179,10 +183,6 @@ enum cache_policy {
        cache_policy_noncoherent
 };
 
-#define KFD_IS_VI(chip) ((chip) >= CHIP_CARRIZO && (chip) <= CHIP_POLARIS11)
-#define KFD_IS_DGPU(chip) (((chip) >= CHIP_TONGA && \
-                          (chip) <= CHIP_NAVI10) || \
-                          (chip) == CHIP_HAWAII)
 #define KFD_IS_SOC15(chip) ((chip) >= CHIP_VEGA10)
 
 struct kfd_event_interrupt_class {
@@ -230,6 +230,7 @@ struct kfd_dev {
 
        const struct kfd_device_info *device_info;
        struct pci_dev *pdev;
+       struct drm_device *ddev;
 
        unsigned int id;                /* topology stub index */
 
@@ -687,7 +688,7 @@ struct kfd_process {
        /* We want to receive a notification when the mm_struct is destroyed */
        struct mmu_notifier mmu_notifier;
 
-       unsigned int pasid;
+       uint16_t pasid;
        unsigned int doorbell_index;
 
        /*
@@ -1040,6 +1041,21 @@ bool kfd_is_locked(void);
 void kfd_inc_compute_active(struct kfd_dev *dev);
 void kfd_dec_compute_active(struct kfd_dev *dev);
 
+/* Cgroup Support */
+/* Check with device cgroup if @kfd device is accessible */
+static inline int kfd_devcgroup_check_permission(struct kfd_dev *kfd)
+{
+#if defined(CONFIG_CGROUP_DEVICE)
+       struct drm_device *ddev = kfd->ddev;
+
+       return devcgroup_check_permission(DEVCG_DEV_CHAR, ddev->driver->major,
+                                         ddev->render->index,
+                                         DEVCG_ACC_WRITE | DEVCG_ACC_READ);
+#else
+       return 0;
+#endif
+}
+
 /* Debugfs */
 #if defined(CONFIG_DEBUG_FS)
 
index 40e3fc0c6942120b83e724038a537ed11f756e9f..10f9af5784f25b98c25eafe2534a3d64e71d9c1c 100644 (file)
@@ -416,7 +416,7 @@ static void kfd_process_destroy_pdds(struct kfd_process *p)
 
        list_for_each_entry_safe(pdd, temp, &p->per_device_data,
                                 per_device_list) {
-               pr_debug("Releasing pdd (topology id %d) for process (pasid %d)\n",
+               pr_debug("Releasing pdd (topology id %d) for process (pasid 0x%x)\n",
                                pdd->dev->id, p->pasid);
 
                if (pdd->drm_file) {
@@ -687,6 +687,8 @@ static int init_doorbell_bitmap(struct qcm_process_device *qpd,
                        struct kfd_dev *dev)
 {
        unsigned int i;
+       int range_start = dev->shared_resources.non_cp_doorbells_start;
+       int range_end = dev->shared_resources.non_cp_doorbells_end;
 
        if (!KFD_IS_SOC15(dev->device_info->asic_family))
                return 0;
@@ -698,14 +700,16 @@ static int init_doorbell_bitmap(struct qcm_process_device *qpd,
                return -ENOMEM;
 
        /* Mask out doorbells reserved for SDMA, IH, and VCN on SOC15. */
+       pr_debug("reserved doorbell 0x%03x - 0x%03x\n", range_start, range_end);
+       pr_debug("reserved doorbell 0x%03x - 0x%03x\n",
+                       range_start + KFD_QUEUE_DOORBELL_MIRROR_OFFSET,
+                       range_end + KFD_QUEUE_DOORBELL_MIRROR_OFFSET);
+
        for (i = 0; i < KFD_MAX_NUM_OF_QUEUES_PER_PROCESS / 2; i++) {
-               if (i >= dev->shared_resources.non_cp_doorbells_start
-                       && i <= dev->shared_resources.non_cp_doorbells_end) {
+               if (i >= range_start && i <= range_end) {
                        set_bit(i, qpd->doorbell_bitmap);
                        set_bit(i + KFD_QUEUE_DOORBELL_MIRROR_OFFSET,
                                qpd->doorbell_bitmap);
-                       pr_debug("reserved doorbell 0x%03x and 0x%03x\n", i,
-                               i + KFD_QUEUE_DOORBELL_MIRROR_OFFSET);
                }
        }
 
@@ -1020,7 +1024,7 @@ static void evict_process_worker(struct work_struct *work)
         */
        flush_delayed_work(&p->restore_work);
 
-       pr_debug("Started evicting pasid %d\n", p->pasid);
+       pr_debug("Started evicting pasid 0x%x\n", p->pasid);
        ret = kfd_process_evict_queues(p);
        if (!ret) {
                dma_fence_signal(p->ef);
@@ -1029,9 +1033,9 @@ static void evict_process_worker(struct work_struct *work)
                queue_delayed_work(kfd_restore_wq, &p->restore_work,
                                msecs_to_jiffies(PROCESS_RESTORE_TIME_MS));
 
-               pr_debug("Finished evicting pasid %d\n", p->pasid);
+               pr_debug("Finished evicting pasid 0x%x\n", p->pasid);
        } else
-               pr_err("Failed to evict queues of pasid %d\n", p->pasid);
+               pr_err("Failed to evict queues of pasid 0x%x\n", p->pasid);
 }
 
 static void restore_process_worker(struct work_struct *work)
@@ -1046,7 +1050,7 @@ static void restore_process_worker(struct work_struct *work)
         * lifetime of this thread, kfd_process p will be valid
         */
        p = container_of(dwork, struct kfd_process, restore_work);
-       pr_debug("Started restoring pasid %d\n", p->pasid);
+       pr_debug("Started restoring pasid 0x%x\n", p->pasid);
 
        /* Setting last_restore_timestamp before successful restoration.
         * Otherwise this would have to be set by KGD (restore_process_bos)
@@ -1062,7 +1066,7 @@ static void restore_process_worker(struct work_struct *work)
        ret = amdgpu_amdkfd_gpuvm_restore_process_bos(p->kgd_process_info,
                                                     &p->ef);
        if (ret) {
-               pr_debug("Failed to restore BOs of pasid %d, retry after %d ms\n",
+               pr_debug("Failed to restore BOs of pasid 0x%x, retry after %d ms\n",
                         p->pasid, PROCESS_BACK_OFF_TIME_MS);
                ret = queue_delayed_work(kfd_restore_wq, &p->restore_work,
                                msecs_to_jiffies(PROCESS_BACK_OFF_TIME_MS));
@@ -1072,9 +1076,9 @@ static void restore_process_worker(struct work_struct *work)
 
        ret = kfd_process_restore_queues(p);
        if (!ret)
-               pr_debug("Finished restoring pasid %d\n", p->pasid);
+               pr_debug("Finished restoring pasid 0x%x\n", p->pasid);
        else
-               pr_err("Failed to restore queues of pasid %d\n", p->pasid);
+               pr_err("Failed to restore queues of pasid 0x%x\n", p->pasid);
 }
 
 void kfd_suspend_all_processes(void)
@@ -1088,7 +1092,7 @@ void kfd_suspend_all_processes(void)
                cancel_delayed_work_sync(&p->restore_work);
 
                if (kfd_process_evict_queues(p))
-                       pr_err("Failed to suspend process %d\n", p->pasid);
+                       pr_err("Failed to suspend process 0x%x\n", p->pasid);
                dma_fence_signal(p->ef);
                dma_fence_put(p->ef);
                p->ef = NULL;
@@ -1171,7 +1175,7 @@ int kfd_debugfs_mqds_by_process(struct seq_file *m, void *data)
        int idx = srcu_read_lock(&kfd_processes_srcu);
 
        hash_for_each_rcu(kfd_processes_table, temp, p, kfd_processes) {
-               seq_printf(m, "Process %d PASID %d:\n",
+               seq_printf(m, "Process %d PASID 0x%x:\n",
                           p->lead_thread->tgid, p->pasid);
 
                mutex_lock(&p->mutex);
index 7e6c3ee82f5b233ef3730b78896f10e8c2a92166..2659d226c0565ee8594babd3d7f0fdfbdac4bedb 100644 (file)
@@ -53,7 +53,7 @@ static int find_available_queue_slot(struct process_queue_manager *pqm,
        pr_debug("The new slot id %lu\n", found);
 
        if (found >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS) {
-               pr_info("Cannot open more queues for process with pasid %d\n",
+               pr_info("Cannot open more queues for process with pasid 0x%x\n",
                                pqm->process->pasid);
                return -ENOMEM;
        }
@@ -298,7 +298,7 @@ int pqm_create_queue(struct process_queue_manager *pqm,
        }
 
        if (retval != 0) {
-               pr_err("Pasid %d DQM create queue %d failed. ret %d\n",
+               pr_err("Pasid 0x%x DQM create queue %d failed. ret %d\n",
                        pqm->process->pasid, type, retval);
                goto err_create_queue;
        }
@@ -377,7 +377,7 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid)
                dqm = pqn->q->device->dqm;
                retval = dqm->ops.destroy_queue(dqm, &pdd->qpd, pqn->q);
                if (retval) {
-                       pr_err("Pasid %d destroy queue %d failed, ret %d\n",
+                       pr_err("Pasid 0x%x destroy queue %d failed, ret %d\n",
                                pqm->process->pasid,
                                pqn->q->properties.queue_id, retval);
                        if (retval != -ETIME)
index 7551761f2aa9794966fdf7891dfb5808ad3ee849..69bd0628fdc607677890afd11e4b00c74ed0e113 100644 (file)
@@ -269,6 +269,8 @@ static ssize_t iolink_show(struct kobject *kobj, struct attribute *attr,
        buffer[0] = 0;
 
        iolink = container_of(attr, struct kfd_iolink_properties, attr);
+       if (iolink->gpu && kfd_devcgroup_check_permission(iolink->gpu))
+               return -EPERM;
        sysfs_show_32bit_prop(buffer, "type", iolink->iolink_type);
        sysfs_show_32bit_prop(buffer, "version_major", iolink->ver_maj);
        sysfs_show_32bit_prop(buffer, "version_minor", iolink->ver_min);
@@ -305,6 +307,8 @@ static ssize_t mem_show(struct kobject *kobj, struct attribute *attr,
        buffer[0] = 0;
 
        mem = container_of(attr, struct kfd_mem_properties, attr);
+       if (mem->gpu && kfd_devcgroup_check_permission(mem->gpu))
+               return -EPERM;
        sysfs_show_32bit_prop(buffer, "heap_type", mem->heap_type);
        sysfs_show_64bit_prop(buffer, "size_in_bytes", mem->size_in_bytes);
        sysfs_show_32bit_prop(buffer, "flags", mem->flags);
@@ -334,6 +338,8 @@ static ssize_t kfd_cache_show(struct kobject *kobj, struct attribute *attr,
        buffer[0] = 0;
 
        cache = container_of(attr, struct kfd_cache_properties, attr);
+       if (cache->gpu && kfd_devcgroup_check_permission(cache->gpu))
+               return -EPERM;
        sysfs_show_32bit_prop(buffer, "processor_id_low",
                        cache->processor_id_low);
        sysfs_show_32bit_prop(buffer, "level", cache->cache_level);
@@ -414,6 +420,8 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr,
        if (strcmp(attr->name, "gpu_id") == 0) {
                dev = container_of(attr, struct kfd_topology_device,
                                attr_gpuid);
+               if (dev->gpu && kfd_devcgroup_check_permission(dev->gpu))
+                       return -EPERM;
                return sysfs_show_32bit_val(buffer, dev->gpu_id);
        }
 
@@ -421,11 +429,15 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr,
                dev = container_of(attr, struct kfd_topology_device,
                                attr_name);
 
+               if (dev->gpu && kfd_devcgroup_check_permission(dev->gpu))
+                       return -EPERM;
                return sysfs_show_str_val(buffer, dev->node_props.name);
        }
 
        dev = container_of(attr, struct kfd_topology_device,
                        attr_props);
+       if (dev->gpu && kfd_devcgroup_check_permission(dev->gpu))
+               return -EPERM;
        sysfs_show_32bit_prop(buffer, "cpu_cores_count",
                        dev->node_props.cpu_cores_count);
        sysfs_show_32bit_prop(buffer, "simd_count",
@@ -1098,6 +1110,9 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
 {
        struct kfd_topology_device *dev;
        struct kfd_topology_device *out_dev = NULL;
+       struct kfd_mem_properties *mem;
+       struct kfd_cache_properties *cache;
+       struct kfd_iolink_properties *iolink;
 
        down_write(&topology_lock);
        list_for_each_entry(dev, &topology_device_list, list) {
@@ -1111,6 +1126,13 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
                if (!dev->gpu && (dev->node_props.simd_count > 0)) {
                        dev->gpu = gpu;
                        out_dev = dev;
+
+                       list_for_each_entry(mem, &dev->mem_props, list)
+                               mem->gpu = dev->gpu;
+                       list_for_each_entry(cache, &dev->cache_props, list)
+                               cache->gpu = dev->gpu;
+                       list_for_each_entry(iolink, &dev->io_link_props, list)
+                               iolink->gpu = dev->gpu;
                        break;
                }
        }
@@ -1317,8 +1339,11 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
        case CHIP_VEGA12:
        case CHIP_VEGA20:
        case CHIP_RAVEN:
+       case CHIP_RENOIR:
        case CHIP_ARCTURUS:
        case CHIP_NAVI10:
+       case CHIP_NAVI12:
+       case CHIP_NAVI14:
                dev->node_props.capability |= ((HSA_CAP_DOORBELL_TYPE_2_0 <<
                        HSA_CAP_DOORBELL_TYPE_TOTALBITS_SHIFT) &
                        HSA_CAP_DOORBELL_TYPE_TOTALBITS_MASK);
index d4718d58d0f246dde6c0023cef2ade9a4dc85093..15843e0fc7564246be673b04d90ccdde4dbb929e 100644 (file)
@@ -102,6 +102,7 @@ struct kfd_mem_properties {
        uint32_t                flags;
        uint32_t                width;
        uint32_t                mem_clk_max;
+       struct kfd_dev          *gpu;
        struct kobject          *kobj;
        struct attribute        attr;
 };
@@ -123,6 +124,7 @@ struct kfd_cache_properties {
        uint32_t                cache_latency;
        uint32_t                cache_type;
        uint8_t                 sibling_map[CRAT_SIBLINGMAP_SIZE];
+       struct kfd_dev          *gpu;
        struct kobject          *kobj;
        struct attribute        attr;
 };
@@ -141,6 +143,7 @@ struct kfd_iolink_properties {
        uint32_t                max_bandwidth;
        uint32_t                rec_transfer_size;
        uint32_t                flags;
+       struct kfd_dev          *gpu;
        struct kobject          *kobj;
        struct attribute        attr;
 };
index 71991a28a775a13ed0f6c1a4d8e4000dcf77a353..313183b800328c11cb7c5ec8d25a362afbe7037c 100644 (file)
@@ -23,16 +23,16 @@ config DRM_AMD_DC_DCN2_0
        depends on DRM_AMD_DC && X86
        depends on DRM_AMD_DC_DCN1_0
        help
-           Choose this option if you want to have
-           Navi support for display engine
+         Choose this option if you want to have
+         Navi support for display engine
 
 config DRM_AMD_DC_DCN2_1
-        bool "DCN 2.1 family"
-        depends on DRM_AMD_DC && X86
-        depends on DRM_AMD_DC_DCN2_0
-        help
-            Choose this option if you want to have
-            Renoir support for display engine
+       bool "DCN 2.1 family"
+       depends on DRM_AMD_DC && X86
+       depends on DRM_AMD_DC_DCN2_0
+       help
+         Choose this option if you want to have
+         Renoir support for display engine
 
 config DRM_AMD_DC_DSC_SUPPORT
        bool "DSC support"
@@ -41,8 +41,16 @@ config DRM_AMD_DC_DSC_SUPPORT
        depends on DRM_AMD_DC_DCN1_0
        depends on DRM_AMD_DC_DCN2_0
        help
-           Choose this option if you want to have
-           Dynamic Stream Compression support
+         Choose this option if you want to have
+         Dynamic Stream Compression support
+
+config DRM_AMD_DC_HDCP
+       bool "Enable HDCP support in DC"
+       depends on DRM_AMD_DC
+       help
+        Choose this option
+        if you want to support
+        HDCP authentication
 
 config DEBUG_KERNEL_DC
        bool "Enable kgdb break in DC"
index 496cee000f1087a43ec8be956987047aaa94734c..36b3d6a5d04d9fea4cb5d1b5a2969ea6d7f3f91b 100644 (file)
@@ -34,12 +34,19 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/color
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/info_packet
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/power
+ifdef CONFIG_DRM_AMD_DC_HDCP
+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/hdcp
+endif
 
 #TODO: remove when Timing Sync feature is complete
 subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0
 
 DAL_LIBS = amdgpu_dm dc        modules/freesync modules/color modules/info_packet modules/power
 
+ifdef CONFIG_DRM_AMD_DC_HDCP
+DAL_LIBS += modules/hdcp
+endif
+
 AMD_DAL = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/,$(DAL_LIBS)))
 
 include $(AMD_DAL)
index 94911871eb9b5e4218e53f80f570786b865cc700..9a3b7bf8ab0b243c4b692eaeab779282553f4db8 100644 (file)
@@ -31,6 +31,10 @@ ifneq ($(CONFIG_DRM_AMD_DC),)
 AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o amdgpu_dm_pp_smu.o
 endif
 
+ifdef CONFIG_DRM_AMD_DC_HDCP
+AMDGPUDM += amdgpu_dm_hdcp.o
+endif
+
 ifneq ($(CONFIG_DEBUG_FS),)
 AMDGPUDM += amdgpu_dm_crc.o amdgpu_dm_debugfs.o
 endif
index c67d3c41db1985a0ab1b593a05a0d178cc283389..23bdcbcb477a55373f6c34949222e89aab65d850 100644 (file)
@@ -37,6 +37,9 @@
 #include "amdgpu_ucode.h"
 #include "atom.h"
 #include "amdgpu_dm.h"
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+#include "amdgpu_dm_hdcp.h"
+#endif
 #include "amdgpu_pm.h"
 
 #include "amd_shared.h"
@@ -67,6 +70,7 @@
 #include <drm/drm_edid.h>
 #include <drm/drm_vblank.h>
 #include <drm/drm_audio_component.h>
+#include <drm/drm_hdcp.h>
 
 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 #include "ivsrcid/dcn/irqsrcs_dcn_1_0.h"
@@ -263,6 +267,13 @@ static inline bool amdgpu_dm_vrr_active(struct dm_crtc_state *dm_state)
               dm_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED;
 }
 
+/**
+ * dm_pflip_high_irq() - Handle pageflip interrupt
+ * @interrupt_params: ignored
+ *
+ * Handles the pageflip interrupt by notifying all interested parties
+ * that the pageflip has been completed.
+ */
 static void dm_pflip_high_irq(void *interrupt_params)
 {
        struct amdgpu_crtc *amdgpu_crtc;
@@ -407,6 +418,13 @@ static void dm_vupdate_high_irq(void *interrupt_params)
        }
 }
 
+/**
+ * dm_crtc_high_irq() - Handles CRTC interrupt
+ * @interrupt_params: ignored
+ *
+ * Handles the CRTC/VSYNC interrupt by notfying DRM's VBLANK
+ * event handler.
+ */
 static void dm_crtc_high_irq(void *interrupt_params)
 {
        struct common_irq_params *irq_params = interrupt_params;
@@ -646,11 +664,18 @@ void amdgpu_dm_audio_eld_notify(struct amdgpu_device *adev, int pin)
 static int amdgpu_dm_init(struct amdgpu_device *adev)
 {
        struct dc_init_data init_data;
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+       struct dc_callback_init init_params;
+#endif
+
        adev->dm.ddev = adev->ddev;
        adev->dm.adev = adev;
 
        /* Zero all the fields */
        memset(&init_data, 0, sizeof(init_data));
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+       memset(&init_params, 0, sizeof(init_params));
+#endif
 
        mutex_init(&adev->dm.dc_lock);
        mutex_init(&adev->dm.audio_lock);
@@ -713,6 +738,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
                goto error;
        }
 
+       dc_hardware_init(adev->dm.dc);
+
        adev->dm.freesync_module = mod_freesync_create(adev->dm.dc);
        if (!adev->dm.freesync_module) {
                DRM_ERROR(
@@ -723,6 +750,18 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
 
        amdgpu_dm_init_color_mod();
 
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+       if (adev->asic_type >= CHIP_RAVEN) {
+               adev->dm.hdcp_workqueue = hdcp_create_workqueue(&adev->psp, &init_params.cp_psp, adev->dm.dc);
+
+               if (!adev->dm.hdcp_workqueue)
+                       DRM_ERROR("amdgpu: failed to initialize hdcp_workqueue.\n");
+               else
+                       DRM_DEBUG_DRIVER("amdgpu: hdcp_workqueue init done %p.\n", adev->dm.hdcp_workqueue);
+
+               dc_init_callbacks(adev->dm.dc, &init_params);
+       }
+#endif
        if (amdgpu_dm_initialize_drm_device(adev)) {
                DRM_ERROR(
                "amdgpu: failed to initialize sw for display support.\n");
@@ -764,6 +803,16 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
 
        amdgpu_dm_destroy_drm_device(&adev->dm);
 
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+       if (adev->dm.hdcp_workqueue) {
+               hdcp_destroy(adev->dm.hdcp_workqueue);
+               adev->dm.hdcp_workqueue = NULL;
+       }
+
+       if (adev->dm.dc)
+               dc_deinit_callbacks(adev->dm.dc);
+#endif
+
        /* DC Destroy TODO: Replace destroy DAL */
        if (adev->dm.dc)
                dc_destroy(&adev->dm.dc);
@@ -897,27 +946,29 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev)
 {
        struct amdgpu_dm_connector *aconnector;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
        int ret = 0;
 
-       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                aconnector = to_amdgpu_dm_connector(connector);
                if (aconnector->dc_link->type == dc_connection_mst_branch &&
                    aconnector->mst_mgr.aux) {
                        DRM_DEBUG_DRIVER("DM_MST: starting TM on aconnector: %p [id: %d]\n",
-                                       aconnector, aconnector->base.base.id);
+                                        aconnector,
+                                        aconnector->base.base.id);
 
                        ret = drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true);
                        if (ret < 0) {
                                DRM_ERROR("DM_MST: Failed to start MST\n");
-                               ((struct dc_link *)aconnector->dc_link)->type = dc_connection_single;
-                               return ret;
-                               }
+                               aconnector->dc_link->type =
+                                       dc_connection_single;
+                               break;
                        }
+               }
        }
+       drm_connector_list_iter_end(&iter);
 
-       drm_modeset_unlock(&dev->mode_config.connection_mutex);
        return ret;
 }
 
@@ -940,6 +991,11 @@ static int dm_late_init(void *handle)
        params.backlight_lut_array_size = 16;
        params.backlight_lut_array = linear_lut;
 
+       /* Min backlight level after ABM reduction,  Don't allow below 1%
+        * 0xFFFF x 0.01 = 0x28F
+        */
+       params.min_abm_backlight = 0x28F;
+
        /* todo will enable for navi10 */
        if (adev->asic_type <= CHIP_RAVEN) {
                ret = dmcu_load_iram(dmcu, params);
@@ -955,14 +1011,13 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend)
 {
        struct amdgpu_dm_connector *aconnector;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
        struct drm_dp_mst_topology_mgr *mgr;
        int ret;
        bool need_hotplug = false;
 
-       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-
-       list_for_each_entry(connector, &dev->mode_config.connector_list,
-                           head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                aconnector = to_amdgpu_dm_connector(connector);
                if (aconnector->dc_link->type != dc_connection_mst_branch ||
                    aconnector->mst_port)
@@ -980,8 +1035,7 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend)
                        }
                }
        }
-
-       drm_modeset_unlock(&dev->mode_config.connection_mutex);
+       drm_connector_list_iter_end(&iter);
 
        if (need_hotplug)
                drm_kms_helper_hotplug_event(dev);
@@ -989,7 +1043,7 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend)
 
 /**
  * dm_hw_init() - Initialize DC device
- * @handle: The base driver device containing the amdpgu_dm device.
+ * @handle: The base driver device containing the amdgpu_dm device.
  *
  * Initialize the &struct amdgpu_display_manager device. This involves calling
  * the initializers of each DM component, then populating the struct with them.
@@ -1019,7 +1073,7 @@ static int dm_hw_init(void *handle)
 
 /**
  * dm_hw_fini() - Teardown DC device
- * @handle: The base driver device containing the amdpgu_dm device.
+ * @handle: The base driver device containing the amdgpu_dm device.
  *
  * Teardown components within &struct amdgpu_display_manager that require
  * cleanup. This involves cleaning up the DRM device, DC, and any modules that
@@ -1163,6 +1217,7 @@ static int dm_resume(void *handle)
        struct amdgpu_display_manager *dm = &adev->dm;
        struct amdgpu_dm_connector *aconnector;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
        struct drm_crtc *crtc;
        struct drm_crtc_state *new_crtc_state;
        struct dm_crtc_state *dm_new_crtc_state;
@@ -1185,17 +1240,18 @@ static int dm_resume(void *handle)
        /* program HPD filter */
        dc_resume(dm->dc);
 
-       /* On resume we need to  rewrite the MSTM control bits to enamble MST*/
-       s3_handle_mst(ddev, false);
-
        /*
         * early enable HPD Rx IRQ, should be done before set mode as short
         * pulse interrupts are used for MST
         */
        amdgpu_dm_irq_resume_early(adev);
 
+       /* On resume we need to  rewrite the MSTM control bits to enable MST*/
+       s3_handle_mst(ddev, false);
+
        /* Do detection*/
-       list_for_each_entry(connector, &ddev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(ddev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                aconnector = to_amdgpu_dm_connector(connector);
 
                /*
@@ -1223,6 +1279,7 @@ static int dm_resume(void *handle)
                amdgpu_dm_update_connector_after_detect(aconnector);
                mutex_unlock(&aconnector->hpd_lock);
        }
+       drm_connector_list_iter_end(&iter);
 
        /* Force mode set in atomic commit */
        for_each_new_crtc_in_state(dm->cached_state, crtc, new_crtc_state, i)
@@ -1438,6 +1495,11 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector)
                dc_sink_release(aconnector->dc_sink);
                aconnector->dc_sink = NULL;
                aconnector->edid = NULL;
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+               /* Set CP to DESIRED if it was ENABLED, so we can re-enable it again on hotplug */
+               if (connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED)
+                       connector->state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+#endif
        }
 
        mutex_unlock(&dev->mode_config.mutex);
@@ -1452,6 +1514,9 @@ static void handle_hpd_irq(void *param)
        struct drm_connector *connector = &aconnector->base;
        struct drm_device *dev = connector->dev;
        enum dc_connection_type new_connection_type = dc_connection_none;
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+       struct amdgpu_device *adev = dev->dev_private;
+#endif
 
        /*
         * In case of failure or MST no need to update connector status or notify the OS
@@ -1459,6 +1524,10 @@ static void handle_hpd_irq(void *param)
         */
        mutex_lock(&aconnector->hpd_lock);
 
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+       if (adev->asic_type >= CHIP_RAVEN)
+               hdcp_reset_display(adev->dm.hdcp_workqueue, aconnector->dc_link->link_index);
+#endif
        if (aconnector->fake_enable)
                aconnector->fake_enable = false;
 
@@ -1577,6 +1646,12 @@ static void handle_hpd_rx_irq(void *param)
        struct dc_link *dc_link = aconnector->dc_link;
        bool is_mst_root_connector = aconnector->mst_mgr.mst_state;
        enum dc_connection_type new_connection_type = dc_connection_none;
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+       union hpd_irq_data hpd_irq_data;
+       struct amdgpu_device *adev = dev->dev_private;
+
+       memset(&hpd_irq_data, 0, sizeof(hpd_irq_data));
+#endif
 
        /*
         * TODO:Temporary add mutex to protect hpd interrupt not have a gpio
@@ -1586,7 +1661,12 @@ static void handle_hpd_rx_irq(void *param)
        if (dc_link->type != dc_connection_mst_branch)
                mutex_lock(&aconnector->hpd_lock);
 
+
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+       if (dc_link_handle_hpd_rx_irq(dc_link, &hpd_irq_data, NULL) &&
+#else
        if (dc_link_handle_hpd_rx_irq(dc_link, NULL, NULL) &&
+#endif
                        !is_mst_root_connector) {
                /* Downstream Port status changed. */
                if (!dc_link_detect_sink(dc_link, &new_connection_type))
@@ -1621,6 +1701,10 @@ static void handle_hpd_rx_irq(void *param)
                        drm_kms_helper_hotplug_event(dev);
                }
        }
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+       if (hpd_irq_data.bytes.device_service_irq.bits.CP_IRQ)
+               hdcp_handle_cpirq(adev->dm.hdcp_workqueue,  aconnector->base.index);
+#endif
        if ((dc_link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
            (dc_link->type == dc_connection_mst_branch))
                dm_handle_hpd_rx_irq(aconnector);
@@ -3311,8 +3395,9 @@ static void fill_stream_properties_from_drm_display_mode(
 {
        struct dc_crtc_timing *timing_out = &stream->timing;
        const struct drm_display_info *info = &connector->display_info;
-
-       memset(timing_out, 0, sizeof(struct dc_crtc_timing));
+       struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+       struct hdmi_vendor_infoframe hv_frame;
+       struct hdmi_avi_infoframe avi_frame;
 
        timing_out->h_border_left = 0;
        timing_out->h_border_right = 0;
@@ -3322,6 +3407,9 @@ static void fill_stream_properties_from_drm_display_mode(
        if (drm_mode_is_420_only(info, mode_in)
                        && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
                timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
+       else if (drm_mode_is_420_also(info, mode_in)
+                       && aconnector->force_yuv420_output)
+               timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
        else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444)
                        && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
                timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;
@@ -3346,6 +3434,13 @@ static void fill_stream_properties_from_drm_display_mode(
                        timing_out->flags.VSYNC_POSITIVE_POLARITY = 1;
        }
 
+       if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) {
+               drm_hdmi_avi_infoframe_from_display_mode(&avi_frame, (struct drm_connector *)connector, mode_in);
+               timing_out->vic = avi_frame.video_code;
+               drm_hdmi_vendor_infoframe_from_display_mode(&hv_frame, (struct drm_connector *)connector, mode_in);
+               timing_out->hdmi_vic = hv_frame.vic;
+       }
+
        timing_out->h_addressable = mode_in->crtc_hdisplay;
        timing_out->h_total = mode_in->crtc_htotal;
        timing_out->h_sync_width =
@@ -3566,6 +3661,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
 
        stream->dm_stream_context = aconnector;
 
+       stream->timing.flags.LTE_340MCSC_SCRAMBLE =
+               drm_connector->display_info.hdmi.scdc.scrambling.low_rates;
+
        list_for_each_entry(preferred_mode, &aconnector->base.modes, head) {
                /* Search for preferred mode */
                if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) {
@@ -3621,8 +3719,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
                                                             dc_link_get_link_cap(aconnector->dc_link));
 
                if (dsc_caps.is_dsc_supported)
-                       if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc,
+                       if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0],
                                                  &dsc_caps,
+                                                 aconnector->dc_link->ctx->dc->debug.dsc_min_slice_height_override,
                                                  link_bandwidth_kbps,
                                                  &stream->timing,
                                                  &stream->timing.dsc_cfg))
@@ -3639,6 +3738,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
 
        update_stream_signal(stream, sink);
 
+       if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+               mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket, false, false);
+
 finish:
        dc_sink_release(sink);
 
@@ -5088,6 +5190,10 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
 
                drm_connector_attach_vrr_capable_property(
                        &aconnector->base);
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+               if (adev->asic_type >= CHIP_RAVEN)
+                       drm_connector_attach_content_protection_property(&aconnector->base, false);
+#endif
        }
 }
 
@@ -5330,6 +5436,53 @@ is_scaling_state_different(const struct dm_connector_state *dm_state,
        return false;
 }
 
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+static bool is_content_protection_different(struct drm_connector_state *state,
+                                           const struct drm_connector_state *old_state,
+                                           const struct drm_connector *connector, struct hdcp_workqueue *hdcp_w)
+{
+       struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+
+       /* CP is being re enabled, ignore this */
+       if (old_state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED &&
+           state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED) {
+               state->content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+               return false;
+       }
+
+       /* S3 resume case, since old state will always be 0 (UNDESIRED) and the restored state will be ENABLED */
+       if (old_state->content_protection == DRM_MODE_CONTENT_PROTECTION_UNDESIRED &&
+           state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED)
+               state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+
+       /* Check if something is connected/enabled, otherwise we start hdcp but nothing is connected/enabled
+        * hot-plug, headless s3, dpms
+        */
+       if (state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED && connector->dpms == DRM_MODE_DPMS_ON &&
+           aconnector->dc_sink != NULL)
+               return true;
+
+       if (old_state->content_protection == state->content_protection)
+               return false;
+
+       if (state->content_protection == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
+               return true;
+
+       return false;
+}
+
+static void update_content_protection(struct drm_connector_state *state, const struct drm_connector *connector,
+                                     struct hdcp_workqueue *hdcp_w)
+{
+       struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+
+       if (state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED)
+               hdcp_add_display(hdcp_w, aconnector->dc_link->link_index, aconnector);
+       else if (state->content_protection == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
+               hdcp_remove_display(hdcp_w, aconnector->dc_link->link_index, aconnector->base.index);
+
+}
+#endif
 static void remove_stream(struct amdgpu_device *adev,
                          struct amdgpu_crtc *acrtc,
                          struct dc_stream_state *stream)
@@ -5870,6 +6023,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
        /* Update the planes if changed or disable if we don't have any. */
        if ((planes_count || acrtc_state->active_planes == 0) &&
                acrtc_state->stream) {
+               bundle->stream_update.stream = acrtc_state->stream;
                if (new_pcrtc_state->mode_changed) {
                        bundle->stream_update.src = acrtc_state->stream->src;
                        bundle->stream_update.dst = acrtc_state->stream->dst;
@@ -6254,6 +6408,30 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                                acrtc->otg_inst = status->primary_otg_inst;
                }
        }
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+       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 amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc);
+               struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+
+               new_crtc_state = NULL;
+
+               if (acrtc)
+                       new_crtc_state = drm_atomic_get_new_crtc_state(state, &acrtc->base);
+
+               dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
+
+               if (dm_new_crtc_state && dm_new_crtc_state->stream == NULL &&
+                   connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
+                       hdcp_reset_display(adev->dm.hdcp_workqueue, aconnector->dc_link->link_index);
+                       new_con_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+                       continue;
+               }
+
+               if (is_content_protection_different(new_con_state, old_con_state, connector, adev->dm.hdcp_workqueue))
+                       update_content_protection(new_con_state, connector, adev->dm.hdcp_workqueue);
+       }
+#endif
 
        /* Handle connector state changes */
        for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) {
@@ -6293,9 +6471,10 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                if (!scaling_changed && !abm_changed && !hdr_changed)
                        continue;
 
+               stream_update.stream = dm_new_crtc_state->stream;
                if (scaling_changed) {
                        update_stream_scaling_settings(&dm_new_con_state->base.crtc->mode,
-                                       dm_new_con_state, (struct dc_stream_state *)dm_new_crtc_state->stream);
+                                       dm_new_con_state, dm_new_crtc_state->stream);
 
                        stream_update.src = dm_new_crtc_state->stream->src;
                        stream_update.dst = dm_new_crtc_state->stream->dst;
@@ -7164,7 +7343,7 @@ dm_determine_update_type_for_commit(struct amdgpu_display_manager *dm,
 
                status = dc_stream_get_status_from_state(old_dm_state->context,
                                                         new_dm_crtc_state->stream);
-
+               stream_update.stream = new_dm_crtc_state->stream;
                /*
                 * TODO: DC modifies the surface during this call so we need
                 * to lock here - find a way to do this without locking.
index c8c525a2b50529e5ce6413931907ee442590b475..77c5166e6b08263683c48019e230af612e580e32 100644 (file)
@@ -108,6 +108,12 @@ struct amdgpu_dm_backlight_caps {
  * @display_indexes_num: Max number of display streams supported
  * @irq_handler_list_table_lock: Synchronizes access to IRQ tables
  * @backlight_dev: Backlight control device
+ * @backlight_link: Link on which to control backlight
+ * @backlight_caps: Capabilities of the backlight device
+ * @freesync_module: Module handling freesync calculations
+ * @fw_dmcu: Reference to DMCU firmware
+ * @dmcu_fw_version: Version of the DMCU firmware
+ * @soc_bounding_box: SOC bounding box values provided by gpu_info FW
  * @cached_state: Caches device atomic state for suspend/resume
  * @compressor: Frame buffer compression buffer. See &struct dm_comressor_info
  */
@@ -128,7 +134,7 @@ struct amdgpu_display_manager {
        u16 display_indexes_num;
 
        /**
-        * @atomic_obj
+        * @atomic_obj:
         *
         * In combination with &dm_atomic_state it helps manage
         * global atomic state that doesn't map cleanly into existing
@@ -225,6 +231,9 @@ struct amdgpu_display_manager {
        struct amdgpu_dm_backlight_caps backlight_caps;
 
        struct mod_freesync *freesync_module;
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+       struct hdcp_workqueue *hdcp_workqueue;
+#endif
 
        struct drm_atomic_state *cached_state;
 
@@ -234,6 +243,8 @@ struct amdgpu_display_manager {
        uint32_t dmcu_fw_version;
 #ifdef CONFIG_DRM_AMD_DC_DCN2_0
        /**
+        * @soc_bounding_box:
+        *
         * gpu_info FW provided soc bounding box struct or 0 if not
         * available in FW
         */
@@ -287,6 +298,7 @@ struct amdgpu_dm_connector {
        uint32_t debugfs_dpcd_address;
        uint32_t debugfs_dpcd_size;
 #endif
+       bool force_yuv420_output;
 };
 
 #define to_amdgpu_dm_connector(x) container_of(x, struct amdgpu_dm_connector, base)
index a549c7c717ddc10233ffc4974c5ed0dfacbc8861..eaad9099bc0b4bfe91fa56f82d675acd993cdb95 100644 (file)
@@ -122,11 +122,16 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
        }
 
        /* Configure dithering */
-       if (!dm_need_crc_dither(source))
+       if (!dm_need_crc_dither(source)) {
                dc_stream_set_dither_option(stream_state, DITHER_OPTION_TRUN8);
-       else
+               dc_stream_set_dyn_expansion(stream_state->ctx->dc, stream_state,
+                                           DYN_EXPANSION_DISABLE);
+       } else {
                dc_stream_set_dither_option(stream_state,
                                            DITHER_OPTION_DEFAULT);
+               dc_stream_set_dyn_expansion(stream_state->ctx->dc, stream_state,
+                                           DYN_EXPANSION_AUTO);
+       }
 
 unlock:
        mutex_unlock(&adev->dm.dc_lock);
index f3dfb2887ae0b0adf33e12418ead5e4c5c3895c4..e29c6314f98c4b814f44fb6fe5d1b872f113dd51 100644 (file)
@@ -942,6 +942,33 @@ static const struct {
                {"aux_dpcd_data", &dp_dpcd_data_debugfs_fops}
 };
 
+/*
+ * Force YUV420 output if available from the given mode
+ */
+static int force_yuv420_output_set(void *data, u64 val)
+{
+       struct amdgpu_dm_connector *connector = data;
+
+       connector->force_yuv420_output = (bool)val;
+
+       return 0;
+}
+
+/*
+ * Check if YUV420 is forced when available from the given mode
+ */
+static int force_yuv420_output_get(void *data, u64 *val)
+{
+       struct amdgpu_dm_connector *connector = data;
+
+       *val = connector->force_yuv420_output;
+
+       return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(force_yuv420_output_fops, force_yuv420_output_get,
+                        force_yuv420_output_set, "%llu\n");
+
 void connector_debugfs_init(struct amdgpu_dm_connector *connector)
 {
        int i;
@@ -955,6 +982,10 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector)
                                            dp_debugfs_entries[i].fops);
                }
        }
+
+       debugfs_create_file_unsafe("force_yuv420_output", 0644, dir, connector,
+                                  &force_yuv420_output_fops);
+
 }
 
 /*
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
new file mode 100644 (file)
index 0000000..77181dd
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * Copyright 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) 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 "amdgpu_dm_hdcp.h"
+#include "amdgpu.h"
+#include "amdgpu_dm.h"
+#include "dm_helpers.h"
+#include <drm/drm_hdcp.h>
+
+static bool
+lp_write_i2c(void *handle, uint32_t address, const uint8_t *data, uint32_t size)
+{
+
+       struct dc_link *link = handle;
+       struct i2c_payload i2c_payloads[] = {{true, address, size, (void *)data} };
+       struct i2c_command cmd = {i2c_payloads, 1, I2C_COMMAND_ENGINE_HW, link->dc->caps.i2c_speed_in_khz};
+
+       return dm_helpers_submit_i2c(link->ctx, link, &cmd);
+}
+
+static bool
+lp_read_i2c(void *handle, uint32_t address, uint8_t offset, uint8_t *data, uint32_t size)
+{
+       struct dc_link *link = handle;
+
+       struct i2c_payload i2c_payloads[] = {{true, address, 1, &offset}, {false, address, size, data} };
+       struct i2c_command cmd = {i2c_payloads, 2, I2C_COMMAND_ENGINE_HW, link->dc->caps.i2c_speed_in_khz};
+
+       return dm_helpers_submit_i2c(link->ctx, link, &cmd);
+}
+
+static bool
+lp_write_dpcd(void *handle, uint32_t address, const uint8_t *data, uint32_t size)
+{
+       struct dc_link *link = handle;
+
+       return dm_helpers_dp_write_dpcd(link->ctx, link, address, data, size);
+}
+
+static bool
+lp_read_dpcd(void *handle, uint32_t address, uint8_t *data, uint32_t size)
+{
+       struct dc_link *link = handle;
+
+       return dm_helpers_dp_read_dpcd(link->ctx, link, address, data, size);
+}
+
+static void process_output(struct hdcp_workqueue *hdcp_work)
+{
+       struct mod_hdcp_output output = hdcp_work->output;
+
+       if (output.callback_stop)
+               cancel_delayed_work(&hdcp_work->callback_dwork);
+
+       if (output.callback_needed)
+               schedule_delayed_work(&hdcp_work->callback_dwork,
+                                     msecs_to_jiffies(output.callback_delay));
+
+       if (output.watchdog_timer_stop)
+               cancel_delayed_work(&hdcp_work->watchdog_timer_dwork);
+
+       if (output.watchdog_timer_needed)
+               schedule_delayed_work(&hdcp_work->watchdog_timer_dwork,
+                                     msecs_to_jiffies(output.watchdog_timer_delay));
+
+}
+
+void hdcp_add_display(struct hdcp_workqueue *hdcp_work, unsigned int link_index, struct amdgpu_dm_connector *aconnector)
+{
+       struct hdcp_workqueue *hdcp_w = &hdcp_work[link_index];
+       struct mod_hdcp_display *display = &hdcp_work[link_index].display;
+       struct mod_hdcp_link *link = &hdcp_work[link_index].link;
+
+       mutex_lock(&hdcp_w->mutex);
+       hdcp_w->aconnector = aconnector;
+
+       mod_hdcp_add_display(&hdcp_w->hdcp, link, display, &hdcp_w->output);
+
+       schedule_delayed_work(&hdcp_w->property_validate_dwork, msecs_to_jiffies(DRM_HDCP_CHECK_PERIOD_MS));
+
+       process_output(hdcp_w);
+
+       mutex_unlock(&hdcp_w->mutex);
+
+}
+
+void hdcp_remove_display(struct hdcp_workqueue *hdcp_work, unsigned int link_index,  unsigned int display_index)
+{
+       struct hdcp_workqueue *hdcp_w = &hdcp_work[link_index];
+
+       mutex_lock(&hdcp_w->mutex);
+
+       mod_hdcp_remove_display(&hdcp_w->hdcp, display_index, &hdcp_w->output);
+
+       cancel_delayed_work(&hdcp_w->property_validate_dwork);
+       hdcp_w->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
+
+       process_output(hdcp_w);
+
+       mutex_unlock(&hdcp_w->mutex);
+
+}
+
+void hdcp_reset_display(struct hdcp_workqueue *hdcp_work, unsigned int link_index)
+{
+       struct hdcp_workqueue *hdcp_w = &hdcp_work[link_index];
+
+       mutex_lock(&hdcp_w->mutex);
+
+       mod_hdcp_reset_connection(&hdcp_w->hdcp,  &hdcp_w->output);
+
+       cancel_delayed_work(&hdcp_w->property_validate_dwork);
+       hdcp_w->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
+
+       process_output(hdcp_w);
+
+       mutex_unlock(&hdcp_w->mutex);
+}
+
+void hdcp_handle_cpirq(struct hdcp_workqueue *hdcp_work, unsigned int link_index)
+{
+       struct hdcp_workqueue *hdcp_w = &hdcp_work[link_index];
+
+       schedule_work(&hdcp_w->cpirq_work);
+}
+
+
+
+
+static void event_callback(struct work_struct *work)
+{
+       struct hdcp_workqueue *hdcp_work;
+
+       hdcp_work = container_of(to_delayed_work(work), struct hdcp_workqueue,
+                                     callback_dwork);
+
+       mutex_lock(&hdcp_work->mutex);
+
+       cancel_delayed_work(&hdcp_work->watchdog_timer_dwork);
+
+       mod_hdcp_process_event(&hdcp_work->hdcp, MOD_HDCP_EVENT_CALLBACK,
+                              &hdcp_work->output);
+
+       process_output(hdcp_work);
+
+       mutex_unlock(&hdcp_work->mutex);
+
+
+}
+static void event_property_update(struct work_struct *work)
+{
+
+       struct hdcp_workqueue *hdcp_work = container_of(work, struct hdcp_workqueue, property_update_work);
+       struct amdgpu_dm_connector *aconnector = hdcp_work->aconnector;
+       struct drm_device *dev = hdcp_work->aconnector->base.dev;
+       long ret;
+
+       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+       mutex_lock(&hdcp_work->mutex);
+
+
+       if (aconnector->base.state->commit) {
+               ret = wait_for_completion_interruptible_timeout(&aconnector->base.state->commit->hw_done, 10 * HZ);
+
+               if (ret == 0) {
+                       DRM_ERROR("HDCP state unknown! Setting it to DESIRED");
+                       hdcp_work->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
+               }
+       }
+
+       if (hdcp_work->encryption_status == MOD_HDCP_ENCRYPTION_STATUS_HDCP1_ON)
+               drm_hdcp_update_content_protection(&aconnector->base, DRM_MODE_CONTENT_PROTECTION_ENABLED);
+       else
+               drm_hdcp_update_content_protection(&aconnector->base, DRM_MODE_CONTENT_PROTECTION_DESIRED);
+
+
+       mutex_unlock(&hdcp_work->mutex);
+       drm_modeset_unlock(&dev->mode_config.connection_mutex);
+}
+
+static void event_property_validate(struct work_struct *work)
+{
+       struct hdcp_workqueue *hdcp_work =
+               container_of(to_delayed_work(work), struct hdcp_workqueue, property_validate_dwork);
+       struct mod_hdcp_display_query query;
+       struct amdgpu_dm_connector *aconnector = hdcp_work->aconnector;
+
+       mutex_lock(&hdcp_work->mutex);
+
+       query.encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
+       mod_hdcp_query_display(&hdcp_work->hdcp, aconnector->base.index, &query);
+
+       if (query.encryption_status != hdcp_work->encryption_status) {
+               hdcp_work->encryption_status = query.encryption_status;
+               schedule_work(&hdcp_work->property_update_work);
+       }
+
+       schedule_delayed_work(&hdcp_work->property_validate_dwork, msecs_to_jiffies(DRM_HDCP_CHECK_PERIOD_MS));
+
+       mutex_unlock(&hdcp_work->mutex);
+}
+
+static void event_watchdog_timer(struct work_struct *work)
+{
+       struct hdcp_workqueue *hdcp_work;
+
+       hdcp_work = container_of(to_delayed_work(work),
+                                     struct hdcp_workqueue,
+                                     watchdog_timer_dwork);
+
+       mutex_lock(&hdcp_work->mutex);
+
+       mod_hdcp_process_event(&hdcp_work->hdcp,
+                              MOD_HDCP_EVENT_WATCHDOG_TIMEOUT,
+                              &hdcp_work->output);
+
+       process_output(hdcp_work);
+
+       mutex_unlock(&hdcp_work->mutex);
+
+}
+
+static void event_cpirq(struct work_struct *work)
+{
+       struct hdcp_workqueue *hdcp_work;
+
+       hdcp_work = container_of(work, struct hdcp_workqueue, cpirq_work);
+
+       mutex_lock(&hdcp_work->mutex);
+
+       mod_hdcp_process_event(&hdcp_work->hdcp, MOD_HDCP_EVENT_CPIRQ, &hdcp_work->output);
+
+       process_output(hdcp_work);
+
+       mutex_unlock(&hdcp_work->mutex);
+
+}
+
+
+void hdcp_destroy(struct hdcp_workqueue *hdcp_work)
+{
+       int i = 0;
+
+       for (i = 0; i < hdcp_work->max_link; i++) {
+               cancel_delayed_work_sync(&hdcp_work[i].callback_dwork);
+               cancel_delayed_work_sync(&hdcp_work[i].watchdog_timer_dwork);
+       }
+
+       kfree(hdcp_work);
+
+}
+
+static void update_config(void *handle, struct cp_psp_stream_config *config)
+{
+       struct hdcp_workqueue *hdcp_work = handle;
+       struct amdgpu_dm_connector *aconnector = config->dm_stream_ctx;
+       int link_index = aconnector->dc_link->link_index;
+       struct mod_hdcp_display *display = &hdcp_work[link_index].display;
+       struct mod_hdcp_link *link = &hdcp_work[link_index].link;
+
+       memset(display, 0, sizeof(*display));
+       memset(link, 0, sizeof(*link));
+
+       display->index = aconnector->base.index;
+       display->state = MOD_HDCP_DISPLAY_ACTIVE;
+
+       if (aconnector->dc_sink != NULL)
+               link->mode = mod_hdcp_signal_type_to_operation_mode(aconnector->dc_sink->sink_signal);
+
+       display->controller = CONTROLLER_ID_D0 + config->otg_inst;
+       display->dig_fe = config->stream_enc_inst;
+       link->dig_be = config->link_enc_inst;
+       link->ddc_line = aconnector->dc_link->ddc_hw_inst + 1;
+       link->dp.rev = aconnector->dc_link->dpcd_caps.dpcd_rev.raw;
+       link->adjust.hdcp2.disable = 1;
+
+}
+
+struct hdcp_workqueue *hdcp_create_workqueue(void *psp_context, struct cp_psp *cp_psp, struct dc *dc)
+{
+
+       int max_caps = dc->caps.max_links;
+       struct hdcp_workqueue *hdcp_work = kzalloc(max_caps*sizeof(*hdcp_work), GFP_KERNEL);
+       int i = 0;
+
+       if (hdcp_work == NULL)
+               goto fail_alloc_context;
+
+       hdcp_work->max_link = max_caps;
+
+       for (i = 0; i < max_caps; i++) {
+
+               mutex_init(&hdcp_work[i].mutex);
+
+               INIT_WORK(&hdcp_work[i].cpirq_work, event_cpirq);
+               INIT_WORK(&hdcp_work[i].property_update_work, event_property_update);
+               INIT_DELAYED_WORK(&hdcp_work[i].callback_dwork, event_callback);
+               INIT_DELAYED_WORK(&hdcp_work[i].watchdog_timer_dwork, event_watchdog_timer);
+               INIT_DELAYED_WORK(&hdcp_work[i].property_validate_dwork, event_property_validate);
+
+               hdcp_work[i].hdcp.config.psp.handle =  psp_context;
+               hdcp_work[i].hdcp.config.ddc.handle = dc_get_link_at_index(dc, i);
+               hdcp_work[i].hdcp.config.ddc.funcs.write_i2c = lp_write_i2c;
+               hdcp_work[i].hdcp.config.ddc.funcs.read_i2c = lp_read_i2c;
+               hdcp_work[i].hdcp.config.ddc.funcs.write_dpcd = lp_write_dpcd;
+               hdcp_work[i].hdcp.config.ddc.funcs.read_dpcd = lp_read_dpcd;
+       }
+
+       cp_psp->funcs.update_stream_config = update_config;
+       cp_psp->handle = hdcp_work;
+
+       return hdcp_work;
+
+fail_alloc_context:
+       kfree(hdcp_work);
+
+       return NULL;
+
+
+
+}
+
+
+
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h
new file mode 100644 (file)
index 0000000..d3ba505
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright 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) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef AMDGPU_DM_AMDGPU_DM_HDCP_H_
+#define AMDGPU_DM_AMDGPU_DM_HDCP_H_
+
+#include "mod_hdcp.h"
+#include "hdcp.h"
+#include "dc.h"
+#include "dm_cp_psp.h"
+
+struct mod_hdcp;
+struct mod_hdcp_link;
+struct mod_hdcp_display;
+struct cp_psp;
+
+struct hdcp_workqueue {
+       struct work_struct cpirq_work;
+       struct work_struct property_update_work;
+       struct delayed_work callback_dwork;
+       struct delayed_work watchdog_timer_dwork;
+       struct delayed_work property_validate_dwork;
+       struct amdgpu_dm_connector *aconnector;
+       struct mutex mutex;
+
+       struct mod_hdcp hdcp;
+       struct mod_hdcp_output output;
+       struct mod_hdcp_display display;
+       struct mod_hdcp_link link;
+
+       enum mod_hdcp_encryption_status encryption_status;
+       uint8_t max_link;
+};
+
+void hdcp_add_display(struct hdcp_workqueue *hdcp_work, unsigned int link_index,
+                     struct amdgpu_dm_connector *aconnector);
+void hdcp_remove_display(struct hdcp_workqueue *work, unsigned int link_index, unsigned int display_index);
+void hdcp_reset_display(struct hdcp_workqueue *work, unsigned int link_index);
+void hdcp_handle_cpirq(struct hdcp_workqueue *work, unsigned int link_index);
+void hdcp_destroy(struct hdcp_workqueue *work);
+
+struct hdcp_workqueue *hdcp_create_workqueue(void *psp_context, struct cp_psp *cp_psp, struct dc *dc);
+
+#endif /* AMDGPU_DM_AMDGPU_DM_HDCP_H_ */
index ee1dc75f5ddc39ee7128013ffd23d47b286c3c63..11e5784aa62a15cc2d66b0270c9d7dda99e2e2a8 100644 (file)
@@ -97,11 +97,10 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
                        (struct edid *) edid->raw_edid);
 
        sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, &sads);
-       if (sad_count <= 0) {
-               DRM_INFO("SADs count is: %d, don't need to read it\n",
-                               sad_count);
+       if (sad_count < 0)
+               DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
+       if (sad_count <= 0)
                return result;
-       }
 
        edid_caps->audio_mode_count = sad_count < DC_MAX_AUDIO_DESC_COUNT ? sad_count : DC_MAX_AUDIO_DESC_COUNT;
        for (i = 0; i < edid_caps->audio_mode_count; ++i) {
@@ -282,7 +281,7 @@ void dm_helpers_dp_mst_clear_payload_allocation_table(
  * Polls for ACT (allocation change trigger) handled and sends
  * ALLOCATE_PAYLOAD message.
  */
-bool dm_helpers_dp_mst_poll_for_allocation_change_trigger(
+enum act_return_status dm_helpers_dp_mst_poll_for_allocation_change_trigger(
                struct dc_context *ctx,
                const struct dc_stream_state *stream)
 {
@@ -293,19 +292,19 @@ bool dm_helpers_dp_mst_poll_for_allocation_change_trigger(
        aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
        if (!aconnector || !aconnector->mst_port)
-               return false;
+               return ACT_FAILED;
 
        mst_mgr = &aconnector->mst_port->mst_mgr;
 
        if (!mst_mgr->mst_state)
-               return false;
+               return ACT_FAILED;
 
        ret = drm_dp_check_act_status(mst_mgr);
 
        if (ret)
-               return false;
+               return ACT_FAILED;
 
-       return true;
+       return ACT_SUCCESS;
 }
 
 bool dm_helpers_dp_mst_send_payload_allocation(
index fa5d503d379cfbdc9924f5010da8bcef583c9867..64445c4cc4c2e1d3b708553428dad3c2c2f6932a 100644 (file)
@@ -732,8 +732,10 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
 {
        struct drm_device *dev = adev->ddev;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                struct amdgpu_dm_connector *amdgpu_dm_connector =
                                to_amdgpu_dm_connector(connector);
 
@@ -751,6 +753,7 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
                                        true);
                }
        }
+       drm_connector_list_iter_end(&iter);
 }
 
 /**
@@ -765,8 +768,10 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
 {
        struct drm_device *dev = adev->ddev;
        struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
                struct amdgpu_dm_connector *amdgpu_dm_connector =
                                to_amdgpu_dm_connector(connector);
                const struct dc_link *dc_link = amdgpu_dm_connector->dc_link;
@@ -779,4 +784,5 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
                                        false);
                }
        }
+       drm_connector_list_iter_end(&iter);
 }
index 5ec14efd4d8cb5cdb774a675c7d6bf2481ae89e3..d9113ce0be097cfa84b005b8dd143308e2eff0cd 100644 (file)
@@ -144,10 +144,8 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector)
        struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector);
        struct amdgpu_encoder *amdgpu_encoder = amdgpu_dm_connector->mst_encoder;
 
-       if (amdgpu_dm_connector->edid) {
-               kfree(amdgpu_dm_connector->edid);
-               amdgpu_dm_connector->edid = NULL;
-       }
+       kfree(amdgpu_dm_connector->edid);
+       amdgpu_dm_connector->edid = NULL;
 
        drm_encoder_cleanup(&amdgpu_encoder->base);
        kfree(amdgpu_encoder);
@@ -245,17 +243,17 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
        return ret;
 }
 
-static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector)
+static struct drm_encoder *
+dm_mst_atomic_best_encoder(struct drm_connector *connector,
+                          struct drm_connector_state *connector_state)
 {
-       struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector);
-
-       return &amdgpu_dm_connector->mst_encoder->base;
+       return &to_amdgpu_dm_connector(connector)->mst_encoder->base;
 }
 
 static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs = {
        .get_modes = dm_dp_mst_get_modes,
        .mode_valid = amdgpu_dm_connector_mode_valid,
-       .best_encoder = dm_mst_best_encoder,
+       .atomic_best_encoder = dm_mst_atomic_best_encoder,
 };
 
 static void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder)
@@ -417,6 +415,10 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
        drm_dp_aux_register(&aconnector->dm_dp_aux.aux);
        drm_dp_cec_register_connector(&aconnector->dm_dp_aux.aux,
                                      &aconnector->base);
+
+       if (aconnector->base.connector_type == DRM_MODE_CONNECTOR_eDP)
+               return;
+
        aconnector->mst_mgr.cbs = &dm_mst_cbs;
        drm_dp_mst_topology_mgr_init(
                &aconnector->mst_mgr,
index f4cfa0caeba882c8ee01088c0cc526b3142e8aeb..7add40dea9b7e838548b7f51e0f8a74bb37ae92f 100644 (file)
@@ -589,10 +589,9 @@ void pp_rv_set_wm_ranges(struct pp_smu *pp,
        if (pp_funcs && pp_funcs->set_watermarks_for_clocks_ranges)
                pp_funcs->set_watermarks_for_clocks_ranges(pp_handle,
                                                           &wm_with_clock_ranges);
-       else if (adev->smu.funcs &&
-                adev->smu.funcs->set_watermarks_for_clock_ranges)
+       else
                smu_set_watermarks_for_clock_ranges(&adev->smu,
-                                                   &wm_with_clock_ranges);
+                               &wm_with_clock_ranges);
 }
 
 void pp_rv_set_pme_wa_enable(struct pp_smu *pp)
@@ -665,7 +664,6 @@ enum pp_smu_status pp_nv_set_wm_ranges(struct pp_smu *pp,
 {
        const struct dc_context *ctx = pp->dm;
        struct amdgpu_device *adev = ctx->driver_context;
-       struct smu_context *smu = &adev->smu;
        struct dm_pp_wm_sets_with_clock_ranges_soc15 wm_with_clock_ranges;
        struct dm_pp_clock_range_for_dmif_wm_set_soc15 *wm_dce_clocks =
                        wm_with_clock_ranges.wm_dmif_clocks_ranges;
@@ -708,15 +706,7 @@ enum pp_smu_status pp_nv_set_wm_ranges(struct pp_smu *pp,
                        ranges->writer_wm_sets[i].min_drain_clk_mhz * 1000;
        }
 
-       if (!smu->funcs)
-               return PP_SMU_RESULT_UNSUPPORTED;
-
-       /* 0: successful or smu.funcs->set_watermarks_for_clock_ranges = NULL;
-        * 1: fail
-        */
-       if (smu_set_watermarks_for_clock_ranges(&adev->smu,
-                       &wm_with_clock_ranges))
-               return PP_SMU_RESULT_UNSUPPORTED;
+       smu_set_watermarks_for_clock_ranges(&adev->smu, &wm_with_clock_ranges);
 
        return PP_SMU_RESULT_OK;
 }
@@ -901,6 +891,90 @@ enum pp_smu_status pp_nv_get_uclk_dpm_states(struct pp_smu *pp,
        return PP_SMU_RESULT_FAIL;
 }
 
+#ifdef CONFIG_DRM_AMD_DC_DCN2_1
+enum pp_smu_status pp_rn_get_dpm_clock_table(
+               struct pp_smu *pp, struct dpm_clocks *clock_table)
+{
+       const struct dc_context *ctx = pp->dm;
+       struct amdgpu_device *adev = ctx->driver_context;
+       struct smu_context *smu = &adev->smu;
+
+       if (!smu->ppt_funcs)
+               return PP_SMU_RESULT_UNSUPPORTED;
+
+       if (!smu->ppt_funcs->get_dpm_clock_table)
+               return PP_SMU_RESULT_UNSUPPORTED;
+
+       if (!smu->ppt_funcs->get_dpm_clock_table(smu, clock_table))
+               return PP_SMU_RESULT_OK;
+
+       return PP_SMU_RESULT_FAIL;
+}
+
+enum pp_smu_status pp_rn_set_wm_ranges(struct pp_smu *pp,
+               struct pp_smu_wm_range_sets *ranges)
+{
+       const struct dc_context *ctx = pp->dm;
+       struct amdgpu_device *adev = ctx->driver_context;
+       struct smu_context *smu = &adev->smu;
+       struct dm_pp_wm_sets_with_clock_ranges_soc15 wm_with_clock_ranges;
+       struct dm_pp_clock_range_for_dmif_wm_set_soc15 *wm_dce_clocks =
+                       wm_with_clock_ranges.wm_dmif_clocks_ranges;
+       struct dm_pp_clock_range_for_mcif_wm_set_soc15 *wm_soc_clocks =
+                       wm_with_clock_ranges.wm_mcif_clocks_ranges;
+       int32_t i;
+
+       if (!smu->funcs)
+               return PP_SMU_RESULT_UNSUPPORTED;
+
+       wm_with_clock_ranges.num_wm_dmif_sets = ranges->num_reader_wm_sets;
+       wm_with_clock_ranges.num_wm_mcif_sets = ranges->num_writer_wm_sets;
+
+       for (i = 0; i < wm_with_clock_ranges.num_wm_dmif_sets; i++) {
+               if (ranges->reader_wm_sets[i].wm_inst > 3)
+                       wm_dce_clocks[i].wm_set_id = WM_SET_A;
+               else
+                       wm_dce_clocks[i].wm_set_id =
+                                       ranges->reader_wm_sets[i].wm_inst;
+
+               wm_dce_clocks[i].wm_min_dcfclk_clk_in_khz =
+                       ranges->reader_wm_sets[i].min_drain_clk_mhz;
+
+               wm_dce_clocks[i].wm_max_dcfclk_clk_in_khz =
+                       ranges->reader_wm_sets[i].max_drain_clk_mhz;
+
+               wm_dce_clocks[i].wm_min_mem_clk_in_khz =
+                       ranges->reader_wm_sets[i].min_fill_clk_mhz;
+
+               wm_dce_clocks[i].wm_max_mem_clk_in_khz =
+                       ranges->reader_wm_sets[i].max_fill_clk_mhz;
+       }
+
+       for (i = 0; i < wm_with_clock_ranges.num_wm_mcif_sets; i++) {
+               if (ranges->writer_wm_sets[i].wm_inst > 3)
+                       wm_soc_clocks[i].wm_set_id = WM_SET_A;
+               else
+                       wm_soc_clocks[i].wm_set_id =
+                                       ranges->writer_wm_sets[i].wm_inst;
+               wm_soc_clocks[i].wm_min_socclk_clk_in_khz =
+                               ranges->writer_wm_sets[i].min_fill_clk_mhz;
+
+               wm_soc_clocks[i].wm_max_socclk_clk_in_khz =
+                       ranges->writer_wm_sets[i].max_fill_clk_mhz;
+
+               wm_soc_clocks[i].wm_min_mem_clk_in_khz =
+                       ranges->writer_wm_sets[i].min_drain_clk_mhz;
+
+               wm_soc_clocks[i].wm_max_mem_clk_in_khz =
+                       ranges->writer_wm_sets[i].max_drain_clk_mhz;
+       }
+
+       smu_set_watermarks_for_clock_ranges(&adev->smu, &wm_with_clock_ranges);
+
+       return PP_SMU_RESULT_OK;
+}
+#endif
+
 void dm_pp_get_funcs(
                struct dc_context *ctx,
                struct pp_smu_funcs *funcs)
@@ -945,6 +1019,15 @@ void dm_pp_get_funcs(
                funcs->nv_funcs.set_pstate_handshake_support = pp_nv_set_pstate_handshake_support;
                break;
 #endif
+
+#ifdef CONFIG_DRM_AMD_DC_DCN2_1
+       case DCN_VERSION_2_1:
+               funcs->ctx.ver = PP_SMU_VER_RN;
+               funcs->rn_funcs.pp_smu.dm = ctx;
+               funcs->rn_funcs.set_wm_ranges = pp_rn_set_wm_ranges;
+               funcs->rn_funcs.get_dpm_clock_table = pp_rn_get_dpm_clock_table;
+               break;
+#endif
        default:
                DRM_ERROR("smu version is not supported !\n");
                break;
index 627982cb15d29ebca40646c2d32830705b8d24ce..a160512a2f04d59e0140f01c9497e1d6556dde92 100644 (file)
@@ -48,6 +48,10 @@ DC_LIBS += dce110
 DC_LIBS += dce100
 DC_LIBS += dce80
 
+ifdef CONFIG_DRM_AMD_DC_HDCP
+DC_LIBS += hdcp
+endif
+
 AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LIBS)))
 
 include $(AMD_DC)
index 221e0f56389f383740d127e2bc79c34becf58f35..823843cd261339a3d200d5f2884c98c8a7d442ab 100644 (file)
@@ -2543,7 +2543,6 @@ static enum bp_result construct_integrated_info(
 
        /* Sort voltage table from low to high*/
        if (result == BP_RESULT_OK) {
-               struct clock_voltage_caps temp = {0, 0};
                uint32_t i;
                uint32_t j;
 
@@ -2553,10 +2552,8 @@ static enum bp_result construct_integrated_info(
                                                info->disp_clk_voltage[j].max_supported_clk <
                                                info->disp_clk_voltage[j-1].max_supported_clk) {
                                        /* swap j and j - 1*/
-                                       temp = info->disp_clk_voltage[j-1];
-                                       info->disp_clk_voltage[j-1] =
-                                                       info->disp_clk_voltage[j];
-                                       info->disp_clk_voltage[j] = temp;
+                                       swap(info->disp_clk_voltage[j - 1],
+                                            info->disp_clk_voltage[j]);
                                }
                        }
                }
index dff65c0fe82f80847b71c039563de12ca2844b41..7873abea4112b434d0d1def2f5d3634aae0a9f23 100644 (file)
@@ -1613,8 +1613,6 @@ static enum bp_result construct_integrated_info(
 
        struct atom_common_table_header *header;
        struct atom_data_revision revision;
-
-       struct clock_voltage_caps temp = {0, 0};
        uint32_t i;
        uint32_t j;
 
@@ -1644,10 +1642,8 @@ static enum bp_result construct_integrated_info(
                                info->disp_clk_voltage[j-1].max_supported_clk
                                ) {
                                /* swap j and j - 1*/
-                               temp = info->disp_clk_voltage[j-1];
-                               info->disp_clk_voltage[j-1] =
-                                       info->disp_clk_voltage[j];
-                               info->disp_clk_voltage[j] = temp;
+                               swap(info->disp_clk_voltage[j - 1],
+                                    info->disp_clk_voltage[j]);
                        }
                }
        }
index c43797bea4139de97d0b4b8e534ac8f802b01c4e..8828dd9c3783537d95f5e024cbe9b243aaa481eb 100644 (file)
@@ -65,6 +65,31 @@ int clk_mgr_helper_get_active_display_cnt(
        return display_count;
 }
 
+void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr)
+{
+       struct dc_link *edp_link = get_edp_link(dc);
+
+       if (dc->hwss.exit_optimized_pwr_state)
+               dc->hwss.exit_optimized_pwr_state(dc, dc->current_state);
+
+       if (edp_link) {
+               clk_mgr->psr_allow_active_cache = edp_link->psr_allow_active;
+               dc_link_set_psr_allow_active(edp_link, false, false);
+       }
+
+}
+
+void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr)
+{
+       struct dc_link *edp_link = get_edp_link(dc);
+
+       if (edp_link)
+               dc_link_set_psr_allow_active(edp_link, clk_mgr->psr_allow_active_cache, false);
+
+       if (dc->hwss.optimize_pwr_state)
+               dc->hwss.optimize_pwr_state(dc, dc->current_state);
+
+}
 
 struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *pp_smu, struct dccg *dccg)
 {
index 47f529ce280ae19db1ebdddfc50d15eacb1ec3fa..5b3d36d418228cd7fa1d76831e15abe21357f173 100644 (file)
@@ -139,6 +139,9 @@ static void rv1_update_clocks(struct clk_mgr *clk_mgr_base,
 
        ASSERT(clk_mgr->pp_smu);
 
+       if (dc->work_arounds.skip_clock_update)
+               return;
+
        pp_smu = &clk_mgr->pp_smu->rv_funcs;
 
        display_count = clk_mgr_helper_get_active_display_cnt(dc, context);
index 3e8ac303bd526823c978592f3bcf8838669a3a0b..ecd2cb4840e38f36fe0809c0c752b444ab83102f 100644 (file)
@@ -104,6 +104,7 @@ void dcn20_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr,
 {
        int i;
 
+       clk_mgr->dccg->ref_dppclk = clk_mgr->base.clks.dppclk_khz;
        for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
                int dpp_inst, dppclk_khz;
 
@@ -113,75 +114,28 @@ void dcn20_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr,
                dpp_inst = context->res_ctx.pipe_ctx[i].plane_res.dpp->inst;
                dppclk_khz = context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz;
                clk_mgr->dccg->funcs->update_dpp_dto(
-                               clk_mgr->dccg, dpp_inst, dppclk_khz, false);
+                               clk_mgr->dccg, dpp_inst, dppclk_khz);
        }
 }
 
-static void update_global_dpp_clk(struct clk_mgr_internal *clk_mgr, unsigned int khz)
+void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr)
 {
        int dpp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR
-                       * clk_mgr->dentist_vco_freq_khz / khz;
-
-       uint32_t dppclk_wdivider = dentist_get_did_from_divider(dpp_divider);
-
-       REG_UPDATE(DENTIST_DISPCLK_CNTL,
-                       DENTIST_DPPCLK_WDIVIDER, dppclk_wdivider);
-       REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_CHG_DONE, 1, 5, 100);
-}
-
-static void update_display_clk(struct clk_mgr_internal *clk_mgr, unsigned int khz)
-{
+                       * clk_mgr->dentist_vco_freq_khz / clk_mgr->base.clks.dppclk_khz;
        int disp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR
-                       * clk_mgr->dentist_vco_freq_khz / khz;
+                       * clk_mgr->dentist_vco_freq_khz / clk_mgr->base.clks.dispclk_khz;
 
+       uint32_t dppclk_wdivider = dentist_get_did_from_divider(dpp_divider);
        uint32_t dispclk_wdivider = dentist_get_did_from_divider(disp_divider);
 
        REG_UPDATE(DENTIST_DISPCLK_CNTL,
                        DENTIST_DISPCLK_WDIVIDER, dispclk_wdivider);
+//     REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 5, 100);
+       REG_UPDATE(DENTIST_DISPCLK_CNTL,
+                       DENTIST_DPPCLK_WDIVIDER, dppclk_wdivider);
+       REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_CHG_DONE, 1, 5, 100);
 }
 
-static void request_voltage_and_program_disp_clk(struct clk_mgr *clk_mgr_base, unsigned int khz)
-{
-       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
-       struct dc *dc = clk_mgr_base->ctx->dc;
-       struct pp_smu_funcs_nv *pp_smu = NULL;
-       bool going_up = clk_mgr->base.clks.dispclk_khz < khz;
-
-       if (dc->res_pool->pp_smu)
-               pp_smu = &dc->res_pool->pp_smu->nv_funcs;
-
-       clk_mgr->base.clks.dispclk_khz = khz;
-
-       if (going_up && pp_smu && pp_smu->set_voltage_by_freq)
-               pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_DISPCLK, clk_mgr_base->clks.dispclk_khz / 1000);
-
-       update_display_clk(clk_mgr, khz);
-
-       if (!going_up && pp_smu && pp_smu->set_voltage_by_freq)
-               pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_DISPCLK, clk_mgr_base->clks.dispclk_khz / 1000);
-}
-
-static void request_voltage_and_program_global_dpp_clk(struct clk_mgr *clk_mgr_base, unsigned int khz)
-{
-       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
-       struct dc *dc = clk_mgr_base->ctx->dc;
-       struct pp_smu_funcs_nv *pp_smu = NULL;
-       bool going_up = clk_mgr->base.clks.dppclk_khz < khz;
-
-       if (dc->res_pool->pp_smu)
-               pp_smu = &dc->res_pool->pp_smu->nv_funcs;
-
-       clk_mgr->base.clks.dppclk_khz = khz;
-       clk_mgr->dccg->ref_dppclk = khz;
-
-       if (going_up && pp_smu && pp_smu->set_voltage_by_freq)
-               pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_PIXELCLK, clk_mgr_base->clks.dppclk_khz / 1000);
-
-       update_global_dpp_clk(clk_mgr, khz);
-
-       if (!going_up && pp_smu && pp_smu->set_voltage_by_freq)
-               pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_PIXELCLK, clk_mgr_base->clks.dppclk_khz / 1000);
-}
 
 void dcn2_update_clocks(struct clk_mgr *clk_mgr_base,
                        struct dc_state *context,
@@ -192,11 +146,12 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base,
        struct dc *dc = clk_mgr_base->ctx->dc;
        struct pp_smu_funcs_nv *pp_smu = NULL;
        int display_count;
+       bool update_dppclk = false;
        bool update_dispclk = false;
        bool enter_display_off = false;
+       bool dpp_clock_lowered = false;
        struct dmcu *dmcu = clk_mgr_base->ctx->dc->res_pool->dmcu;
        bool force_reset = false;
-       int i;
 
        if (dc->work_arounds.skip_clock_update)
                return;
@@ -251,12 +206,10 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base,
 
        if (should_update_pstate_support(safe_to_lower, new_clocks->p_state_change_support, clk_mgr_base->clks.p_state_change_support)) {
                clk_mgr_base->clks.prev_p_state_change_support = clk_mgr_base->clks.p_state_change_support;
-
                clk_mgr_base->clks.p_state_change_support = new_clocks->p_state_change_support;
                if (pp_smu && pp_smu->set_pstate_handshake_support)
                        pp_smu->set_pstate_handshake_support(&pp_smu->pp_smu, clk_mgr_base->clks.p_state_change_support);
        }
-       clk_mgr_base->clks.prev_p_state_change_support = clk_mgr_base->clks.p_state_change_support;
 
        if (should_set_clock(safe_to_lower, new_clocks->dramclk_khz, clk_mgr_base->clks.dramclk_khz)) {
                clk_mgr_base->clks.dramclk_khz = new_clocks->dramclk_khz;
@@ -264,48 +217,35 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base,
                        pp_smu->set_hard_min_uclk_by_freq(&pp_smu->pp_smu, clk_mgr_base->clks.dramclk_khz / 1000);
        }
 
-       if (dc->config.forced_clocks == false) {
-               // First update display clock
-               if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz))
-                       request_voltage_and_program_disp_clk(clk_mgr_base, new_clocks->dispclk_khz);
-
-               // Updating DPP clock requires some more logic
-               if (!safe_to_lower) {
-                       // For pre-programming, we need to make sure any DPP clock that will go up has to go up
+       if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) {
+               if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz)
+                       dpp_clock_lowered = true;
+               clk_mgr->base.clks.dppclk_khz = new_clocks->dppclk_khz;
 
-                       // First raise the global reference if needed
-                       if (new_clocks->dppclk_khz > clk_mgr_base->clks.dppclk_khz)
-                               request_voltage_and_program_global_dpp_clk(clk_mgr_base, new_clocks->dppclk_khz);
-
-                       // Then raise any dividers that need raising
-                       for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
-                               int dpp_inst, dppclk_khz;
+               if (pp_smu && pp_smu->set_voltage_by_freq)
+                       pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_PIXELCLK, clk_mgr_base->clks.dppclk_khz / 1000);
 
-                               if (!context->res_ctx.pipe_ctx[i].plane_state)
-                                       continue;
+               update_dppclk = true;
+       }
 
-                               dpp_inst = context->res_ctx.pipe_ctx[i].plane_res.dpp->inst;
-                               dppclk_khz = context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz;
+       if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) {
+               clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
+               if (pp_smu && pp_smu->set_voltage_by_freq)
+                       pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_DISPCLK, clk_mgr_base->clks.dispclk_khz / 1000);
 
-                               clk_mgr->dccg->funcs->update_dpp_dto(clk_mgr->dccg, dpp_inst, dppclk_khz, true);
-                       }
+               update_dispclk = true;
+       }
+       if (dc->config.forced_clocks == false || (force_reset && safe_to_lower)) {
+               if (dpp_clock_lowered) {
+                       // if clock is being lowered, increase DTO before lowering refclk
+                       dcn20_update_clocks_update_dpp_dto(clk_mgr, context);
+                       dcn20_update_clocks_update_dentist(clk_mgr);
                } else {
-                       // For post-programming, we can lower ref clk if needed, and unconditionally set all the DTOs
-
-                       if (new_clocks->dppclk_khz < clk_mgr_base->clks.dppclk_khz)
-                               request_voltage_and_program_global_dpp_clk(clk_mgr_base, new_clocks->dppclk_khz);
-
-                       for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
-                               int dpp_inst, dppclk_khz;
-
-                               if (!context->res_ctx.pipe_ctx[i].plane_state)
-                                       continue;
-
-                               dpp_inst = context->res_ctx.pipe_ctx[i].plane_res.dpp->inst;
-                               dppclk_khz = context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz;
-
-                               clk_mgr->dccg->funcs->update_dpp_dto(clk_mgr->dccg, dpp_inst, dppclk_khz, false);
-                       }
+                       // if clock is being raised, increase refclk before lowering DTO
+                       if (update_dppclk || update_dispclk)
+                               dcn20_update_clocks_update_dentist(clk_mgr);
+                       if (update_dppclk)
+                               dcn20_update_clocks_update_dpp_dto(clk_mgr, context);
                }
        }
        if (update_dispclk &&
@@ -409,12 +349,36 @@ void dcn2_get_clock(struct clk_mgr *clk_mgr,
        }
 }
 
+static bool dcn2_are_clock_states_equal(struct dc_clocks *a,
+               struct dc_clocks *b)
+{
+       if (a->dispclk_khz != b->dispclk_khz)
+               return false;
+       else if (a->dppclk_khz != b->dppclk_khz)
+               return false;
+       else if (a->dcfclk_khz != b->dcfclk_khz)
+               return false;
+       else if (a->socclk_khz != b->socclk_khz)
+               return false;
+       else if (a->dcfclk_deep_sleep_khz != b->dcfclk_deep_sleep_khz)
+               return false;
+       else if (a->phyclk_khz != b->phyclk_khz)
+               return false;
+       else if (a->dramclk_khz != b->dramclk_khz)
+               return false;
+       else if (a->p_state_change_support != b->p_state_change_support)
+               return false;
+
+       return true;
+}
+
 static struct clk_mgr_funcs dcn2_funcs = {
        .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
        .update_clocks = dcn2_update_clocks,
        .init_clocks = dcn2_init_clocks,
        .enable_pme_wa = dcn2_enable_pme_wa,
        .get_clock = dcn2_get_clock,
+       .are_clock_states_equal = dcn2_are_clock_states_equal,
 };
 
 
index ac31a9787305b2d8dab55712213279911382536c..c9fd824f3c231c1506a9a39abc653c8156c8e18a 100644 (file)
@@ -50,4 +50,5 @@ void dcn2_get_clock(struct clk_mgr *clk_mgr,
                        enum dc_clock_type clock_type,
                        struct dc_clock_config *clock_cfg);
 
+void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr);
 #endif //__DCN20_CLK_MGR_H__
index 787f94d815f42c86700cf965fee95766b902a966..b647e0320e4bf964c16dce9e0a22b1fde3f6762b 100644 (file)
 #define REG(reg_name) \
        (CLK_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name)
 
+
+/* TODO: evaluate how to lower or disable all dcn clocks in screen off case */
+int rn_get_active_display_cnt_wa(
+               struct dc *dc,
+               struct dc_state *context)
+{
+       int i, display_count;
+       bool hdmi_present = false;
+
+       display_count = 0;
+       for (i = 0; i < context->stream_count; i++) {
+               const struct dc_stream_state *stream = context->streams[i];
+
+               if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+                       hdmi_present = true;
+       }
+
+       for (i = 0; i < dc->link_count; i++) {
+               const struct dc_link *link = dc->links[i];
+
+               /*
+                * Only notify active stream or virtual stream.
+                * Need to notify virtual stream to work around
+                * headless case. HPD does not fire when system is in
+                * S0i2.
+                */
+               /* abusing the fact that the dig and phy are coupled to see if the phy is enabled */
+               if (link->connector_signal == SIGNAL_TYPE_VIRTUAL ||
+                               link->link_enc->funcs->is_dig_enabled(link->link_enc))
+                       display_count++;
+       }
+
+       /* WA for hang on HDMI after display off back back on*/
+       if (display_count == 0 && hdmi_present)
+               display_count = 1;
+
+       return display_count;
+}
+
 void rn_update_clocks(struct clk_mgr *clk_mgr_base,
                        struct dc_state *context,
                        bool safe_to_lower)
@@ -62,17 +101,36 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base,
        int display_count;
        bool update_dppclk = false;
        bool update_dispclk = false;
-       bool enter_display_off = false;
        bool dpp_clock_lowered = false;
-       struct dmcu *dmcu = clk_mgr_base->ctx->dc->res_pool->dmcu;
 
-       display_count = clk_mgr_helper_get_active_display_cnt(dc, context);
+       struct dmcu *dmcu = clk_mgr_base->ctx->dc->res_pool->dmcu;
 
-       if (display_count == 0)
-               enter_display_off = true;
+       if (dc->work_arounds.skip_clock_update)
+               return;
 
-       if (enter_display_off == safe_to_lower) {
-               rn_vbios_smu_set_display_count(clk_mgr, display_count);
+       /*
+        * if it is safe to lower, but we are already in the lower state, we don't have to do anything
+        * also if safe to lower is false, we just go in the higher state
+        */
+       if (safe_to_lower) {
+               /* check that we're not already in lower */
+               if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_OPTIMIZED) {
+
+                       display_count = rn_get_active_display_cnt_wa(dc, context);
+                       /* if we can go lower, go lower */
+                       if (display_count == 0) {
+                               rn_vbios_smu_set_dcn_low_power_state(clk_mgr, DCN_PWR_STATE_OPTIMIZED);
+                               /* update power state */
+                               clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_OPTIMIZED;
+                       }
+               }
+       } else {
+               /* check that we're not already in the normal state */
+               if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_NORMAL) {
+                       rn_vbios_smu_set_dcn_low_power_state(clk_mgr, DCN_PWR_STATE_NORMAL);
+                       /* update power state */
+                       clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_NORMAL;
+               }
        }
 
        if (should_set_clock(safe_to_lower, new_clocks->phyclk_khz, clk_mgr_base->clks.phyclk_khz)) {
@@ -319,7 +377,7 @@ void rn_get_clk_states(struct clk_mgr *clk_mgr_base, struct clk_states *s)
 
        rn_dump_clk_registers(&sb, clk_mgr_base, &log_info);
 
-       s->dprefclk_khz = sb.dprefclk;
+       s->dprefclk_khz = sb.dprefclk * 1000;
 }
 
 void rn_enable_pme_wa(struct clk_mgr *clk_mgr_base)
@@ -329,10 +387,19 @@ void rn_enable_pme_wa(struct clk_mgr *clk_mgr_base)
        rn_vbios_smu_enable_pme_wa(clk_mgr);
 }
 
+void rn_init_clocks(struct clk_mgr *clk_mgr)
+{
+       memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
+       // Assumption is that boot state always supports pstate
+       clk_mgr->clks.p_state_change_support = true;
+       clk_mgr->clks.prev_p_state_change_support = true;
+       clk_mgr->clks.pwr_state = DCN_PWR_STATE_NORMAL;
+}
+
 static struct clk_mgr_funcs dcn21_funcs = {
        .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
        .update_clocks = rn_update_clocks,
-       .init_clocks = dcn2_init_clocks,
+       .init_clocks = rn_init_clocks,
        .enable_pme_wa = rn_enable_pme_wa,
        /* .dump_clk_registers = rn_dump_clk_registers */
 };
@@ -405,7 +472,7 @@ struct clk_bw_params rn_bw_params = {
        }
 };
 
-void build_watermark_ranges(struct clk_bw_params *bw_params, struct pp_smu_wm_range_sets *ranges)
+void rn_build_watermark_ranges(struct clk_bw_params *bw_params, struct pp_smu_wm_range_sets *ranges)
 {
        int i, num_valid_sets;
 
@@ -462,23 +529,50 @@ void build_watermark_ranges(struct clk_bw_params *bw_params, struct pp_smu_wm_ra
 
 }
 
-void clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params, struct dpm_clocks *clock_table, struct hw_asic_id *asic_id)
+static unsigned int find_dcfclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage)
 {
        int i;
 
+       for (i = 0; i < PP_SMU_NUM_DCFCLK_DPM_LEVELS; i++) {
+               if (clock_table->DcfClocks[i].Vol == voltage)
+                       return clock_table->DcfClocks[i].Freq;
+       }
+
+       ASSERT(0);
+       return 0;
+}
+
+void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params, struct dpm_clocks *clock_table, struct hw_asic_id *asic_id)
+{
+       int i, j = 0;
+
+       j = -1;
+
        ASSERT(PP_SMU_NUM_FCLK_DPM_LEVELS <= MAX_NUM_DPM_LVL);
 
-       for (i = 0; i < PP_SMU_NUM_FCLK_DPM_LEVELS; i++) {
-               if (clock_table->FClocks[i].Freq == 0)
+       /* Find lowest DPM, FCLK is filled in reverse order*/
+
+       for (i = PP_SMU_NUM_FCLK_DPM_LEVELS - 1; i >= 0; i--) {
+               if (clock_table->FClocks[i].Freq != 0) {
+                       j = i;
                        break;
+               }
+       }
+
+       if (j == -1) {
+               /* clock table is all 0s, just use our own hardcode */
+               ASSERT(0);
+               return;
+       }
+
+       bw_params->clk_table.num_entries = j + 1;
 
-               bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[i].Freq;
-               bw_params->clk_table.entries[i].fclk_mhz = clock_table->FClocks[i].Freq;
-               bw_params->clk_table.entries[i].memclk_mhz = clock_table->MemClocks[i].Freq;
-               bw_params->clk_table.entries[i].socclk_mhz = clock_table->SocClocks[i].Freq;
-               bw_params->clk_table.entries[i].voltage = clock_table->FClocks[i].Vol;
+       for (i = 0; i < bw_params->clk_table.num_entries; i++, j--) {
+               bw_params->clk_table.entries[i].fclk_mhz = clock_table->FClocks[j].Freq;
+               bw_params->clk_table.entries[i].memclk_mhz = clock_table->MemClocks[j].Freq;
+               bw_params->clk_table.entries[i].voltage = clock_table->FClocks[j].Vol;
+               bw_params->clk_table.entries[i].dcfclk_mhz = find_dcfclk_for_voltage(clock_table, clock_table->FClocks[j].Vol);
        }
-       bw_params->clk_table.num_entries = i;
 
        bw_params->vram_type = asic_id->vram_type;
        bw_params->num_channels = asic_id->vram_width / DDR4_DRAM_WIDTH;
@@ -486,7 +580,7 @@ void clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params, struct d
        for (i = 0; i < WM_SET_COUNT; i++) {
                bw_params->wm_table.entries[i].wm_inst = i;
 
-               if (clock_table->FClocks[i].Freq == 0) {
+               if (i >= bw_params->clk_table.num_entries) {
                        bw_params->wm_table.entries[i].valid = false;
                        continue;
                }
@@ -547,25 +641,24 @@ void rn_clk_mgr_construct(
                        clk_mgr->dentist_vco_freq_khz = 3600000;
 
                rn_dump_clk_registers(&s, &clk_mgr->base, &log_info);
-               clk_mgr->base.dprefclk_khz = s.dprefclk;
-
-               if (clk_mgr->base.dprefclk_khz != 600000) {
-                       clk_mgr->base.dprefclk_khz = 600000;
-                       ASSERT(1); //TODO: Renoir follow up.
-               }
+               /* Convert dprefclk units from MHz to KHz */
+               /* Value already divided by 10, some resolution lost */
+               clk_mgr->base.dprefclk_khz = s.dprefclk * 1000;
 
                /* in case we don't get a value from the register, use default */
-               if (clk_mgr->base.dprefclk_khz == 0)
+               if (clk_mgr->base.dprefclk_khz == 0) {
+                       ASSERT(clk_mgr->base.dprefclk_khz == 600000);
                        clk_mgr->base.dprefclk_khz = 600000;
+               }
        }
 
        dce_clock_read_ss_info(clk_mgr);
 
        clk_mgr->base.bw_params = &rn_bw_params;
 
-       if (pp_smu) {
+       if (pp_smu && pp_smu->rn_funcs.get_dpm_clock_table) {
                pp_smu->rn_funcs.get_dpm_clock_table(&pp_smu->rn_funcs.pp_smu, &clock_table);
-               clk_mgr_helper_populate_bw_params(clk_mgr->base.bw_params, &clock_table, &ctx->asic_id);
+               rn_clk_mgr_helper_populate_bw_params(clk_mgr->base.bw_params, &clock_table, &ctx->asic_id);
        }
 
        /*
@@ -576,15 +669,16 @@ void rn_clk_mgr_construct(
        if (!debug->disable_pplib_wm_range) {
                struct pp_smu_wm_range_sets ranges = {0};
 
-               build_watermark_ranges(clk_mgr->base.bw_params, &ranges);
+               rn_build_watermark_ranges(clk_mgr->base.bw_params, &ranges);
 
                /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */
                if (pp_smu && pp_smu->rn_funcs.set_wm_ranges)
                        pp_smu->rn_funcs.set_wm_ranges(&pp_smu->rn_funcs.pp_smu, &ranges);
        }
 
-       /* enable powerfeatures when displaycount goes to 0 */
-       if (!debug->disable_48mhz_pwrdwn)
-               rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(clk_mgr);
+       if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment) && clk_mgr->smu_ver >= 0x00371500) {
+               /* enable powerfeatures when displaycount goes to 0 */
+               rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(clk_mgr, !debug->disable_48mhz_pwrdwn);
+       }
 }
 
index aadec06fde10ee5d92285e9cb8373dfd8edd866a..761bfda970a5d620881300cb456a2f13ec3eb52a 100644 (file)
 #ifndef __RN_CLK_MGR_H__
 #define __RN_CLK_MGR_H__
 
+#include "clk_mgr.h"
+#include "dm_pp_smu.h"
+
 struct rn_clk_registers {
        uint32_t CLK1_CLK0_CURRENT_CNT; /* DPREFCLK */
 };
 
-
+void rn_build_watermark_ranges(
+               struct clk_bw_params *bw_params,
+               struct pp_smu_wm_range_sets *ranges);
+void rn_clk_mgr_helper_populate_bw_params(
+               struct clk_bw_params *bw_params,
+               struct dpm_clocks *clock_table,
+               struct hw_asic_id *asic_id);
 void rn_clk_mgr_construct(struct dc_context *ctx,
                struct clk_mgr_internal *clk_mgr,
                struct pp_smu_funcs *pp_smu,
index 50984c1811bb2dc001092db096de92c7f5f95bfa..5647fcf10717089054ac79047feec679f372fe10 100644 (file)
@@ -33,7 +33,7 @@
 #include "mp/mp_12_0_0_sh_mask.h"
 
 #define REG(reg_name) \
-       (MP1_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name)
+       (MP0_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name)
 
 #define FN(reg_name, field) \
        FD(reg_name##__##field)
@@ -84,16 +84,12 @@ int rn_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dis
        int actual_dispclk_set_mhz = -1;
        struct dc *core_dc = clk_mgr->base.ctx->dc;
        struct dmcu *dmcu = core_dc->res_pool->dmcu;
-       uint32_t clk = requested_dispclk_khz / 1000;
-
-       if (clk <= 100)
-               clk = 101;
 
        /*  Unit of SMU msg parameter is Mhz */
        actual_dispclk_set_mhz = rn_vbios_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetDispclkFreq,
-                       clk);
+                       requested_dispclk_khz / 1000);
 
        if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) {
                if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
@@ -124,7 +120,7 @@ int rn_vbios_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int reque
 {
        int actual_dcfclk_set_mhz = -1;
 
-       if (clk_mgr->smu_ver < 0xFFFFFFFF)
+       if (clk_mgr->smu_ver < 0x370c00)
                return actual_dcfclk_set_mhz;
 
        actual_dcfclk_set_mhz = rn_vbios_smu_send_msg_with_param(
@@ -139,7 +135,7 @@ int rn_vbios_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int
 {
        int actual_min_ds_dcfclk_mhz = -1;
 
-       if (clk_mgr->smu_ver < 0xFFFFFFFF)
+       if (clk_mgr->smu_ver < 0x370c00)
                return actual_min_ds_dcfclk_mhz;
 
        actual_min_ds_dcfclk_mhz = rn_vbios_smu_send_msg_with_param(
@@ -162,33 +158,35 @@ int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_
 {
        int actual_dppclk_set_mhz = -1;
 
-       uint32_t clk = requested_dpp_khz / 1000;
-
-       if (clk <= 100)
-               clk = 101;
-
        actual_dppclk_set_mhz = rn_vbios_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_SetDppclkFreq,
-                       clk);
+                       requested_dpp_khz / 1000);
 
        return actual_dppclk_set_mhz * 1000;
 }
 
-void rn_vbios_smu_set_display_count(struct clk_mgr_internal *clk_mgr, int display_count)
+void rn_vbios_smu_set_dcn_low_power_state(struct clk_mgr_internal *clk_mgr, enum dcn_pwr_state state)
 {
+       int disp_count;
+
+       if (state == DCN_PWR_STATE_OPTIMIZED)
+               disp_count = 0;
+       else
+               disp_count = 1;
+
        rn_vbios_smu_send_msg_with_param(
-                       clk_mgr,
-                       VBIOSSMC_MSG_SetDisplayCount,
-                       display_count);
+               clk_mgr,
+               VBIOSSMC_MSG_SetDisplayCount,
+               disp_count);
 }
 
-void rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr)
+void rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable)
 {
        rn_vbios_smu_send_msg_with_param(
                        clk_mgr,
                        VBIOSSMC_MSG_EnableTmdp48MHzRefclkPwrDown,
-                       0);
+                       enable);
 }
 
 void rn_vbios_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr)
index da3a49487c6d220b47519af83978cc97a464d5c2..ccc01879c9d4a627b3b7fd24bc866cf0ee73967a 100644 (file)
@@ -33,8 +33,8 @@ int rn_vbios_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int reque
 int rn_vbios_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz);
 void rn_vbios_smu_set_phyclk(struct clk_mgr_internal *clk_mgr, int requested_phyclk_khz);
 int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz);
-void rn_vbios_smu_set_display_count(struct clk_mgr_internal *clk_mgr, int display_count);
-void rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr);
+void rn_vbios_smu_set_dcn_low_power_state(struct clk_mgr_internal *clk_mgr, int display_count);
+void rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable);
 void rn_vbios_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr);
 
 #endif /* DAL_DC_DCN10_RV1_CLK_MGR_VBIOS_SMU_H_ */
index 5d1adeda4d90fa189bfa5dc36bea2bdce30cf72a..41b51f43a64b14311369b45a28c4ab1f2e357592 100644 (file)
@@ -411,6 +411,27 @@ bool dc_stream_get_crc(struct dc *dc, struct dc_stream_state *stream,
        return false;
 }
 
+void dc_stream_set_dyn_expansion(struct dc *dc, struct dc_stream_state *stream,
+               enum dc_dynamic_expansion option)
+{
+       /* OPP FMT dyn expansion updates*/
+       int i = 0;
+       struct pipe_ctx *pipe_ctx;
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               if (dc->current_state->res_ctx.pipe_ctx[i].stream
+                               == stream) {
+                       pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
+                       pipe_ctx->stream_res.opp->dyn_expansion = option;
+                       pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
+                                       pipe_ctx->stream_res.opp,
+                                       COLOR_SPACE_YCBCR601,
+                                       stream->timing.display_color_depth,
+                                       stream->signal);
+               }
+       }
+}
+
 void dc_stream_set_dither_option(struct dc_stream_state *stream,
                enum dc_dither_option option)
 {
@@ -761,8 +782,13 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
                        disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context);
 #endif
-                       dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context);
+                       if (dc->hwss.apply_ctx_for_surface)
+                               dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context);
                }
+#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
+               if (dc->hwss.program_front_end_for_ctx)
+                       dc->hwss.program_front_end_for_ctx(dc, dangling_context);
+#endif
        }
 
        current_ctx = dc->current_state;
@@ -785,9 +811,6 @@ struct dc *dc_create(const struct dc_init_data *init_params)
        if (false == construct(dc, init_params))
                goto construct_fail;
 
-       /*TODO: separate HW and SW initialization*/
-       dc->hwss.init_hw(dc);
-
        full_pipe_count = dc->res_pool->pipe_count;
        if (dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE)
                full_pipe_count--;
@@ -820,9 +843,24 @@ struct dc *dc_create(const struct dc_init_data *init_params)
        return NULL;
 }
 
+void dc_hardware_init(struct dc *dc)
+{
+       dc->hwss.init_hw(dc);
+}
+
 void dc_init_callbacks(struct dc *dc,
                const struct dc_callback_init *init_params)
 {
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+       dc->ctx->cp_psp = init_params->cp_psp;
+#endif
+}
+
+void dc_deinit_callbacks(struct dc *dc)
+{
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+       memset(&dc->ctx->cp_psp, 0, sizeof(dc->ctx->cp_psp));
+#endif
 }
 
 void dc_destroy(struct dc **dc)
@@ -901,15 +939,11 @@ static void program_timing_sync(
 
                /* set first pipe with plane as master */
                for (j = 0; j < group_size; j++) {
-                       struct pipe_ctx *temp;
-
                        if (pipe_set[j]->plane_state) {
                                if (j == 0)
                                        break;
 
-                               temp = pipe_set[0];
-                               pipe_set[0] = pipe_set[j];
-                               pipe_set[j] = temp;
+                               swap(pipe_set[0], pipe_set[j]);
                                break;
                        }
                }
@@ -966,40 +1000,87 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc,
                                struct dc_crtc_timing *crtc_timing)
 {
        struct timing_generator *tg;
+       struct stream_encoder *se = NULL;
+
+       struct dc_crtc_timing hw_crtc_timing = {0};
+
        struct dc_link *link = sink->link;
-       unsigned int enc_inst, tg_inst;
+       unsigned int i, enc_inst, tg_inst = 0;
+
+       // Seamless port only support single DP and EDP so far
+       if (sink->sink_signal != SIGNAL_TYPE_DISPLAY_PORT &&
+               sink->sink_signal != SIGNAL_TYPE_EDP)
+               return false;
 
        /* Check for enabled DIG to identify enabled display */
        if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
                return false;
 
-       /* Check for which front end is used by this encoder.
-        * Note the inst is 1 indexed, where 0 is undefined.
-        * Note that DIG_FE can source from different OTG but our
-        * current implementation always map 1-to-1, so this code makes
-        * the same assumption and doesn't check OTG source.
-        */
        enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
 
-       /* Instance should be within the range of the pool */
-       if (enc_inst >= dc->res_pool->pipe_count)
+       if (enc_inst == ENGINE_ID_UNKNOWN)
                return false;
 
-       if (enc_inst >= dc->res_pool->stream_enc_count)
-               return false;
+       for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
+               if (dc->res_pool->stream_enc[i]->id == enc_inst) {
+
+                       se = dc->res_pool->stream_enc[i];
 
-       tg_inst = dc->res_pool->stream_enc[enc_inst]->funcs->dig_source_otg(
-               dc->res_pool->stream_enc[enc_inst]);
+                       tg_inst = dc->res_pool->stream_enc[i]->funcs->dig_source_otg(
+                               dc->res_pool->stream_enc[i]);
+                       break;
+               }
+       }
+
+       // tg_inst not found
+       if (i == dc->res_pool->stream_enc_count)
+               return false;
 
        if (tg_inst >= dc->res_pool->timing_generator_count)
                return false;
 
        tg = dc->res_pool->timing_generators[tg_inst];
 
-       if (!tg->funcs->is_matching_timing)
+       if (!tg->funcs->get_hw_timing)
+               return false;
+
+       if (!tg->funcs->get_hw_timing(tg, &hw_crtc_timing))
+               return false;
+
+       if (crtc_timing->h_total != hw_crtc_timing.h_total)
+               return false;
+
+       if (crtc_timing->h_border_left != hw_crtc_timing.h_border_left)
+               return false;
+
+       if (crtc_timing->h_addressable != hw_crtc_timing.h_addressable)
+               return false;
+
+       if (crtc_timing->h_border_right != hw_crtc_timing.h_border_right)
+               return false;
+
+       if (crtc_timing->h_front_porch != hw_crtc_timing.h_front_porch)
+               return false;
+
+       if (crtc_timing->h_sync_width != hw_crtc_timing.h_sync_width)
+               return false;
+
+       if (crtc_timing->v_total != hw_crtc_timing.v_total)
+               return false;
+
+       if (crtc_timing->v_border_top != hw_crtc_timing.v_border_top)
+               return false;
+
+       if (crtc_timing->v_addressable != hw_crtc_timing.v_addressable)
+               return false;
+
+       if (crtc_timing->v_border_bottom != hw_crtc_timing.v_border_bottom)
+               return false;
+
+       if (crtc_timing->v_front_porch != hw_crtc_timing.v_front_porch)
                return false;
 
-       if (!tg->funcs->is_matching_timing(tg, crtc_timing))
+       if (crtc_timing->v_sync_width != hw_crtc_timing.v_sync_width)
                return false;
 
        if (dc_is_dp_signal(link->connector_signal)) {
@@ -1012,6 +1093,20 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc,
                if (crtc_timing->pix_clk_100hz != pix_clk_100hz)
                        return false;
 
+               if (!se->funcs->dp_get_pixel_format)
+                       return false;
+
+               if (!se->funcs->dp_get_pixel_format(
+                       se,
+                       &hw_crtc_timing.pixel_encoding,
+                       &hw_crtc_timing.display_color_depth))
+                       return false;
+
+               if (hw_crtc_timing.display_color_depth != crtc_timing->display_color_depth)
+                       return false;
+
+               if (hw_crtc_timing.pixel_encoding != crtc_timing->pixel_encoding)
+                       return false;
        }
 
        return true;
@@ -1073,15 +1168,20 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
        /* re-program planes for existing stream, in case we need to
         * free up plane resource for later use
         */
-       for (i = 0; i < context->stream_count; i++) {
-               if (context->streams[i]->mode_changed)
-                       continue;
+       if (dc->hwss.apply_ctx_for_surface)
+               for (i = 0; i < context->stream_count; i++) {
+                       if (context->streams[i]->mode_changed)
+                               continue;
 
-               dc->hwss.apply_ctx_for_surface(
-                       dc, context->streams[i],
-                       context->stream_status[i].plane_count,
-                       context); /* use new pipe config in new context */
-       }
+                       dc->hwss.apply_ctx_for_surface(
+                               dc, context->streams[i],
+                               context->stream_status[i].plane_count,
+                               context); /* use new pipe config in new context */
+               }
+#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
+       if (dc->hwss.program_front_end_for_ctx)
+               dc->hwss.program_front_end_for_ctx(dc, context);
+#endif
 
        /* Program hardware */
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
@@ -1100,16 +1200,21 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
        }
 
        /* Program all planes within new context*/
+#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
+       if (dc->hwss.program_front_end_for_ctx)
+               dc->hwss.program_front_end_for_ctx(dc, context);
+#endif
        for (i = 0; i < context->stream_count; i++) {
                const struct dc_link *link = context->streams[i]->link;
 
                if (!context->streams[i]->mode_changed)
                        continue;
 
-               dc->hwss.apply_ctx_for_surface(
-                               dc, context->streams[i],
-                               context->stream_status[i].plane_count,
-                               context);
+               if (dc->hwss.apply_ctx_for_surface)
+                       dc->hwss.apply_ctx_for_surface(
+                                       dc, context->streams[i],
+                                       context->stream_status[i].plane_count,
+                                       context);
 
                /*
                 * enable stereo
@@ -1492,20 +1597,15 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
        enum surface_update_type overall_type = UPDATE_TYPE_FAST;
        union surface_update_flags *update_flags = &u->surface->update_flags;
 
-       update_flags->raw = 0; // Reset all flags
-
        if (u->flip_addr)
                update_flags->bits.addr_update = 1;
 
-       if (!is_surface_in_context(context, u->surface)) {
-               update_flags->bits.new_plane = 1;
+       if (!is_surface_in_context(context, u->surface) || u->surface->force_full_update) {
+               update_flags->raw = 0xFFFFFFFF;
                return UPDATE_TYPE_FULL;
        }
 
-       if (u->surface->force_full_update) {
-               update_flags->bits.full_update = 1;
-               return UPDATE_TYPE_FULL;
-       }
+       update_flags->raw = 0; // Reset all flags
 
        type = get_plane_info_update_type(u);
        elevate_update_type(&overall_type, type);
@@ -1563,40 +1663,43 @@ static enum surface_update_type check_update_surfaces_for_stream(
        enum surface_update_type overall_type = UPDATE_TYPE_FAST;
 
        if (stream_status == NULL || stream_status->plane_count != surface_count)
-               return UPDATE_TYPE_FULL;
+               overall_type = UPDATE_TYPE_FULL;
 
        /* some stream updates require passive update */
        if (stream_update) {
-               if ((stream_update->src.height != 0) &&
-                               (stream_update->src.width != 0))
-                       return UPDATE_TYPE_FULL;
+               union stream_update_flags *su_flags = &stream_update->stream->update_flags;
 
-               if ((stream_update->dst.height != 0) &&
-                               (stream_update->dst.width != 0))
-                       return UPDATE_TYPE_FULL;
+               if ((stream_update->src.height != 0 && stream_update->src.width != 0) ||
+                               (stream_update->dst.height != 0 && stream_update->dst.width != 0))
+                       su_flags->bits.scaling = 1;
 
                if (stream_update->out_transfer_func)
-                       return UPDATE_TYPE_FULL;
+                       su_flags->bits.out_tf = 1;
 
                if (stream_update->abm_level)
-                       return UPDATE_TYPE_FULL;
+                       su_flags->bits.abm_level = 1;
 
                if (stream_update->dpms_off)
-                       return UPDATE_TYPE_FULL;
+                       su_flags->bits.dpms_off = 1;
+
+               if (stream_update->gamut_remap)
+                       su_flags->bits.gamut_remap = 1;
 
 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
                if (stream_update->wb_update)
-                       return UPDATE_TYPE_FULL;
+                       su_flags->bits.wb_update = 1;
 #endif
+               if (su_flags->raw != 0)
+                       overall_type = UPDATE_TYPE_FULL;
+
+               if (stream_update->output_csc_transform || stream_update->output_color_space)
+                       su_flags->bits.out_csc = 1;
        }
 
        for (i = 0 ; i < surface_count; i++) {
                enum surface_update_type type =
                                det_surface_update(dc, &updates[i]);
 
-               if (type == UPDATE_TYPE_FULL)
-                       return type;
-
                elevate_update_type(&overall_type, type);
        }
 
@@ -1618,16 +1721,29 @@ enum surface_update_type dc_check_update_surfaces_for_stream(
        int i;
        enum surface_update_type type;
 
+       if (stream_update)
+               stream_update->stream->update_flags.raw = 0;
        for (i = 0; i < surface_count; i++)
                updates[i].surface->update_flags.raw = 0;
 
        type = check_update_surfaces_for_stream(dc, updates, surface_count, stream_update, stream_status);
-       if (type == UPDATE_TYPE_FULL)
+       if (type == UPDATE_TYPE_FULL) {
+               if (stream_update)
+                       stream_update->stream->update_flags.raw = 0xFFFFFFFF;
                for (i = 0; i < surface_count; i++)
                        updates[i].surface->update_flags.raw = 0xFFFFFFFF;
+       }
 
-       if (type == UPDATE_TYPE_FAST && memcmp(&dc->current_state->bw_ctx.bw.dcn.clk, &dc->clk_mgr->clks, offsetof(struct dc_clocks, prev_p_state_change_support)) != 0)
-               dc->optimized_required = true;
+       if (type == UPDATE_TYPE_FAST) {
+               // If there's an available clock comparator, we use that.
+               if (dc->clk_mgr->funcs->are_clock_states_equal) {
+                       if (!dc->clk_mgr->funcs->are_clock_states_equal(&dc->clk_mgr->clks, &dc->current_state->bw_ctx.bw.dcn.clk))
+                               dc->optimized_required = true;
+               // Else we fallback to mem compare.
+               } else if (memcmp(&dc->current_state->bw_ctx.bw.dcn.clk, &dc->clk_mgr->clks, offsetof(struct dc_clocks, prev_p_state_change_support)) != 0) {
+                       dc->optimized_required = true;
+               }
+       }
 
        return type;
 }
@@ -1868,6 +1984,7 @@ static void commit_planes_do_stream_update(struct dc *dc,
                struct dc_state *context)
 {
        int j;
+       bool should_program_abm;
 
        // Stream updates
        for (j = 0; j < dc->res_pool->pipe_count; j++) {
@@ -1948,14 +2065,21 @@ static void commit_planes_do_stream_update(struct dc *dc,
                        }
 
                        if (stream_update->abm_level && pipe_ctx->stream_res.abm) {
-                               if (pipe_ctx->stream_res.tg->funcs->is_blanked) {
-                                       // if otg funcs defined check if blanked before programming
-                                       if (!pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg))
+                               should_program_abm = true;
+
+                               // if otg funcs defined check if blanked before programming
+                               if (pipe_ctx->stream_res.tg->funcs->is_blanked)
+                                       if (pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg))
+                                               should_program_abm = false;
+
+                               if (should_program_abm) {
+                                       if (*stream_update->abm_level == ABM_LEVEL_IMMEDIATE_DISABLE) {
+                                               pipe_ctx->stream_res.abm->funcs->set_abm_immediate_disable(pipe_ctx->stream_res.abm);
+                                       } else {
                                                pipe_ctx->stream_res.abm->funcs->set_abm_level(
                                                        pipe_ctx->stream_res.abm, stream->abm_level);
-                               } else
-                                       pipe_ctx->stream_res.abm->funcs->set_abm_level(
-                                               pipe_ctx->stream_res.abm, stream->abm_level);
+                                       }
+                               }
                        }
                }
        }
@@ -2000,7 +2124,13 @@ static void commit_planes_for_stream(struct dc *dc,
                 * In case of turning off screen, no need to program front end a second time.
                 * just return after program blank.
                 */
-               dc->hwss.apply_ctx_for_surface(dc, stream, 0, context);
+               if (dc->hwss.apply_ctx_for_surface)
+                       dc->hwss.apply_ctx_for_surface(dc, stream, 0, context);
+#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
+               if (dc->hwss.program_front_end_for_ctx)
+                       dc->hwss.program_front_end_for_ctx(dc, context);
+#endif
+
                return;
        }
 
@@ -2060,10 +2190,15 @@ static void commit_planes_for_stream(struct dc *dc,
                        stream_status =
                                stream_get_status(context, pipe_ctx->stream);
 
-                       dc->hwss.apply_ctx_for_surface(
+                       if (dc->hwss.apply_ctx_for_surface)
+                               dc->hwss.apply_ctx_for_surface(
                                        dc, pipe_ctx->stream, stream_status->plane_count, context);
                }
        }
+#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
+       if (dc->hwss.program_front_end_for_ctx && update_type != UPDATE_TYPE_FAST)
+               dc->hwss.program_front_end_for_ctx(dc, context);
+#endif
 
        // Update Type FAST, Surface updates
        if (update_type == UPDATE_TYPE_FAST) {
index ca20b150afcc237ba21f8ad46f4bc3bb3b1d97d4..93505366416019db5f681ed91a229b1263067028 100644 (file)
@@ -79,7 +79,6 @@ static void destruct(struct dc_link *link)
        int i;
 
        if (link->hpd_gpio != NULL) {
-               dal_gpio_close(link->hpd_gpio);
                dal_gpio_destroy_irq(&link->hpd_gpio);
                link->hpd_gpio = NULL;
        }
@@ -520,7 +519,7 @@ static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *lin
 }
 
 
-static void read_edp_current_link_settings_on_detect(struct dc_link *link)
+static void read_current_link_settings_on_detect(struct dc_link *link)
 {
        union lane_count_set lane_count_set = { {0} };
        uint8_t link_bw_set;
@@ -555,17 +554,23 @@ static void read_edp_current_link_settings_on_detect(struct dc_link *link)
                        &link_bw_set, sizeof(link_bw_set));
 
        if (link_bw_set == 0) {
-               /* If standard link rates are not being used,
-                * Read DPCD 00115h to find the link rate set used
-                */
-               core_link_read_dpcd(link, DP_LINK_RATE_SET,
-                               &link_rate_set, sizeof(link_rate_set));
-
-               if (link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
-                       link->cur_link_settings.link_rate =
-                               link->dpcd_caps.edp_supported_link_rates[link_rate_set];
-                       link->cur_link_settings.link_rate_set = link_rate_set;
-                       link->cur_link_settings.use_link_rate_set = true;
+               if (link->connector_signal == SIGNAL_TYPE_EDP) {
+                       /* If standard link rates are not being used,
+                        * Read DPCD 00115h to find the edp link rate set used
+                        */
+                       core_link_read_dpcd(link, DP_LINK_RATE_SET,
+                                       &link_rate_set, sizeof(link_rate_set));
+
+                       // edp_supported_link_rates_count = 0 for DP
+                       if (link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
+                               link->cur_link_settings.link_rate =
+                                               link->dpcd_caps.edp_supported_link_rates[link_rate_set];
+                               link->cur_link_settings.link_rate_set = link_rate_set;
+                               link->cur_link_settings.use_link_rate_set = true;
+                       }
+               } else {
+                       // Link Rate not found. Seamless boot may not work.
+                       ASSERT(false);
                }
        } else {
                link->cur_link_settings.link_rate = link_bw_set;
@@ -680,7 +685,7 @@ static bool is_same_edid(struct dc_edid *old_edid, struct dc_edid *new_edid)
        return (memcmp(old_edid->raw_edid, new_edid->raw_edid, new_edid->length) == 0);
 }
 
-bool wait_for_alt_mode(struct dc_link *link)
+static bool wait_for_alt_mode(struct dc_link *link)
 {
 
        /**
@@ -738,7 +743,8 @@ bool wait_for_alt_mode(struct dc_link *link)
  * This does not create remote sinks but will trigger DM
  * to start MST detection if a branch is detected.
  */
-bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
+static bool dc_link_detect_helper(struct dc_link *link,
+                                 enum dc_detect_reason reason)
 {
        struct dc_sink_init_data sink_init_data = { 0 };
        struct display_sink_capability sink_caps = { 0 };
@@ -753,6 +759,8 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
        struct dpcd_caps prev_dpcd_caps;
        bool same_dpcd = true;
        enum dc_connection_type new_connection_type = dc_connection_none;
+       bool perform_dp_seamless_boot = false;
+
        DC_LOGGER_INIT(link->ctx->logger);
 
        if (dc_is_virtual_signal(link->connector_signal))
@@ -809,15 +817,15 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
                }
 
                case SIGNAL_TYPE_EDP: {
-                       read_edp_current_link_settings_on_detect(link);
+                       read_current_link_settings_on_detect(link);
                        detect_edp_sink_caps(link);
-                       sink_caps.transaction_type =
-                               DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
+                       sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
                        sink_caps.signal = SIGNAL_TYPE_EDP;
                        break;
                }
 
                case SIGNAL_TYPE_DISPLAY_PORT: {
+
                        /* wa HPD high coming too early*/
                        if (link->link_enc->features.flags.bits.DP_IS_USB_C == 1) {
 
@@ -865,12 +873,24 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
                                 * empty which leads to allocate_mst_payload() has "0"
                                 * pbn_per_slot value leading to exception on dc_fixpt_div()
                                 */
-                               link->verified_link_cap = link->reported_link_cap;
+                               dp_verify_mst_link_cap(link);
+
                                if (prev_sink != NULL)
                                        dc_sink_release(prev_sink);
                                return false;
                        }
 
+                       // For seamless boot, to skip verify link cap, we read UEFI settings and set them as verified.
+                       if (reason == DETECT_REASON_BOOT &&
+                                       dc_ctx->dc->config.power_down_display_on_boot == false &&
+                                       link->link_status.link_active == true)
+                               perform_dp_seamless_boot = true;
+
+                       if (perform_dp_seamless_boot) {
+                               read_current_link_settings_on_detect(link);
+                               link->verified_link_cap = link->reported_link_cap;
+                       }
+
                        break;
                }
 
@@ -955,10 +975,11 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
                         *  two link trainings
                         */
 
-                       /* deal with non-mst cases */
-                       dp_verify_link_cap_with_retries(link,
-                                       &link->reported_link_cap,
-                                       LINK_TRAINING_MAX_VERIFY_RETRY);
+                       // verify link cap for SST non-seamless boot
+                       if (!perform_dp_seamless_boot)
+                               dp_verify_link_cap_with_retries(link,
+                                               &link->reported_link_cap,
+                                               LINK_TRAINING_MAX_VERIFY_RETRY);
                } else {
                        // If edid is the same, then discard new sink and revert back to original sink
                        if (same_edid) {
@@ -1047,6 +1068,23 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
                dc_sink_release(prev_sink);
 
        return true;
+
+}
+
+bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
+{
+       const struct dc *dc = link->dc;
+       bool ret;
+
+       /* get out of low power state */
+       clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr);
+
+       ret = dc_link_detect_helper(link, reason);
+
+       /* Go back to power optimized state */
+       clk_mgr_optimize_pwr_state(dc, dc->clk_mgr);
+
+       return ret;
 }
 
 bool dc_link_get_hpd_state(struct dc_link *dc_link)
@@ -1492,7 +1530,7 @@ static enum dc_status enable_link_dp(
 
        pipe_ctx->stream_res.pix_clk_params.requested_sym_clk =
                        link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ;
-       if (!apply_seamless_boot_optimization)
+       if (state->clk_mgr && !apply_seamless_boot_optimization)
                state->clk_mgr->funcs->update_clocks(state->clk_mgr, state, false);
 
        dp_enable_link_phy(
@@ -2169,8 +2207,10 @@ static void disable_link(struct dc_link *link, enum signal_type signal)
                        dp_set_fec_ready(link, false);
                }
 #endif
-       } else
-               link->link_enc->funcs->disable_output(link->link_enc, signal);
+       } else {
+               if (signal != SIGNAL_TYPE_VIRTUAL)
+                       link->link_enc->funcs->disable_output(link->link_enc, signal);
+       }
 
        if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
                /* MST disable link only when no stream use the link */
@@ -2217,7 +2257,7 @@ static bool dp_active_dongle_validate_timing(
                break;
        }
 
-       if (dongle_caps->dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER ||
+       if (dpcd_caps->dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER ||
                dongle_caps->extendedCapValid == false)
                return true;
 
@@ -2381,13 +2421,17 @@ bool dc_link_set_abm_disable(const struct dc_link *link)
        return true;
 }
 
-bool dc_link_set_psr_enable(const struct dc_link *link, bool enable, bool wait)
+bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, bool wait)
 {
        struct dc  *core_dc = link->ctx->dc;
        struct dmcu *dmcu = core_dc->res_pool->dmcu;
 
-       if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_enabled)
-               dmcu->funcs->set_psr_enable(dmcu, enable, wait);
+
+
+       if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_feature_enabled)
+               dmcu->funcs->set_psr_enable(dmcu, allow_active, wait);
+
+       link->psr_allow_active = allow_active;
 
        return true;
 }
@@ -2510,7 +2554,7 @@ static void update_mst_stream_alloc_table(
 /* convert link_mst_stream_alloc_table to dm dp_mst_stream_alloc_table
  * because stream_encoder is not exposed to dm
  */
-static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
+enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx)
 {
        struct dc_stream_state *stream = pipe_ctx->stream;
        struct dc_link *link = stream->link;
@@ -2521,6 +2565,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
        struct fixed31_32 pbn;
        struct fixed31_32 pbn_per_slot;
        uint8_t i;
+       enum act_return_status ret;
        DC_LOGGER_INIT(link->ctx->logger);
 
        /* enable_link_dp_mst already check link->enabled_stream_count
@@ -2568,14 +2613,16 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
                &link->mst_stream_alloc_table);
 
        /* send down message */
-       dm_helpers_dp_mst_poll_for_allocation_change_trigger(
+       ret = dm_helpers_dp_mst_poll_for_allocation_change_trigger(
                        stream->ctx,
                        stream);
 
-       dm_helpers_dp_mst_send_payload_allocation(
-                       stream->ctx,
-                       stream,
-                       true);
+       if (ret != ACT_LINK_LOST) {
+               dm_helpers_dp_mst_send_payload_allocation(
+                               stream->ctx,
+                               stream,
+                               true);
+       }
 
        /* slot X.Y for only current stream */
        pbn_per_slot = get_pbn_per_slot(stream);
@@ -2667,6 +2714,24 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
 
        return DC_OK;
 }
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
+static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
+{
+       struct cp_psp *cp_psp = &pipe_ctx->stream->ctx->cp_psp;
+       if (cp_psp && cp_psp->funcs.update_stream_config) {
+               struct cp_psp_stream_config config;
+
+               memset(&config, 0, sizeof(config));
+
+               config.otg_inst = (uint8_t) pipe_ctx->stream_res.tg->inst;
+               config.stream_enc_inst = (uint8_t) pipe_ctx->stream_res.stream_enc->id;
+               config.link_enc_inst = pipe_ctx->stream->link->link_enc_hw_inst;
+               config.dpms_off = dpms_off;
+               config.dm_stream_ctx = pipe_ctx->stream->dm_stream_context;
+               cp_psp->funcs.update_stream_config(cp_psp->handle, &config);
+       }
+}
+#endif
 
 void core_link_enable_stream(
                struct dc_state *state,
@@ -2677,6 +2742,10 @@ void core_link_enable_stream(
        enum dc_status status;
        DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
 
+       if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment) &&
+                       dc_is_virtual_signal(pipe_ctx->stream->signal))
+               return;
+
        if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) {
                stream->link->link_enc->funcs->setup(
                        stream->link->link_enc,
@@ -2727,6 +2796,9 @@ void core_link_enable_stream(
                /* Do not touch link on seamless boot optimization. */
                if (pipe_ctx->stream->apply_seamless_boot_optimization) {
                        pipe_ctx->stream->dpms_off = false;
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
+                       update_psp_stream_config(pipe_ctx, false);
+#endif
                        return;
                }
 
@@ -2734,6 +2806,9 @@ void core_link_enable_stream(
                if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP &&
                                        apply_edp_fast_boot_optimization) {
                        pipe_ctx->stream->dpms_off = false;
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
+                       update_psp_stream_config(pipe_ctx, false);
+#endif
                        return;
                }
 
@@ -2786,13 +2861,16 @@ void core_link_enable_stream(
 #endif
 
                if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
-                       allocate_mst_payload(pipe_ctx);
+                       dc_link_allocate_mst_payload(pipe_ctx);
 
                core_dc->hwss.unblank_stream(pipe_ctx,
                        &pipe_ctx->stream->link->cur_link_settings);
 
                if (dc_is_dp_signal(pipe_ctx->stream->signal))
                        enable_stream_features(pipe_ctx);
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
+               update_psp_stream_config(pipe_ctx, false);
+#endif
        }
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
        else { // if (IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment))
@@ -2810,6 +2888,14 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx)
        struct dc_stream_state *stream = pipe_ctx->stream;
        struct dc_link *link = stream->sink->link;
 
+       if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment) &&
+                       dc_is_virtual_signal(pipe_ctx->stream->signal))
+               return;
+
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
+       update_psp_stream_config(pipe_ctx, true);
+#endif
+
        core_dc->hwss.blank_stream(pipe_ctx);
 
        if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
index 505967b48e144b7701dc0c70f92299636c6965ad..9a56f110bbd1f3aa0055cf65757c1e29e44c852d 100644 (file)
@@ -496,7 +496,7 @@ bool dal_ddc_service_query_ddc_data(
        uint8_t *read_buf,
        uint32_t read_size)
 {
-       bool ret;
+       bool ret = false;
        uint32_t payload_size =
                dal_ddc_service_is_in_aux_transaction_mode(ddc) ?
                        DEFAULT_AUX_MAX_DATA_SIZE : EDID_SEGMENT_SIZE;
@@ -515,34 +515,32 @@ 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_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),
-               };
-
-               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 = dc_link_aux_transfer_with_retries(ddc, &write_payload);
+               struct aux_payload payload;
+               bool read_available = true;
+
+               payload.i2c_over_aux = true;
+               payload.address = address;
+               payload.reply = NULL;
+               payload.defer_delay = get_defer_delay(ddc);
+
+               if (write_size != 0) {
+                       payload.write = true;
+                       payload.mot = false;
+                       payload.length = write_size;
+                       payload.data = write_buf;
+
+                       ret = dal_ddc_submit_aux_command(ddc, &payload);
+                       read_available = ret;
+               }
 
-               if (!ret)
-                       return false;
+               if (read_size != 0 && read_available) {
+                       payload.write = false;
+                       payload.mot = false;
+                       payload.length = read_size;
+                       payload.data = read_buf;
 
-               ret = dc_link_aux_transfer_with_retries(ddc, &read_payload);
+                       ret = dal_ddc_submit_aux_command(ddc, &payload);
+               }
        } else {
                struct i2c_payloads *payloads =
                        dal_ddc_i2c_payloads_create(ddc->ctx, payloads_num);
@@ -573,6 +571,41 @@ bool dal_ddc_service_query_ddc_data(
        return ret;
 }
 
+bool dal_ddc_submit_aux_command(struct ddc_service *ddc,
+               struct aux_payload *payload)
+{
+       uint8_t retrieved = 0;
+       bool ret = 0;
+
+       if (!ddc)
+               return false;
+
+       if (!payload)
+               return false;
+
+       do {
+               struct aux_payload current_payload;
+               bool is_end_of_payload = (retrieved + DEFAULT_AUX_MAX_DATA_SIZE) >
+                       payload->length ? true : false;
+
+               current_payload.address = payload->address;
+               current_payload.data = &payload->data[retrieved];
+               current_payload.defer_delay = payload->defer_delay;
+               current_payload.i2c_over_aux = payload->i2c_over_aux;
+               current_payload.length = is_end_of_payload ?
+                       payload->length - retrieved : DEFAULT_AUX_MAX_DATA_SIZE;
+               current_payload.mot = !is_end_of_payload;
+               current_payload.reply = payload->reply;
+               current_payload.write = payload->write;
+
+               ret = dc_link_aux_transfer_with_retries(ddc, &current_payload);
+
+               retrieved += current_payload.length;
+       } while (retrieved < payload->length && ret == true);
+
+       return ret;
+}
+
 /* dc_link_aux_transfer_raw() - Attempt to transfer
  * the given aux payload.  This function does not perform
  * retries or handle error states.  The reply is returned
@@ -601,6 +634,20 @@ bool dc_link_aux_transfer_with_retries(struct ddc_service *ddc,
        return dce_aux_transfer_with_retries(ddc, payload);
 }
 
+
+enum dc_status dc_link_aux_configure_timeout(struct ddc_service *ddc,
+               uint32_t timeout)
+{
+       enum dc_status status = DC_OK;
+       struct ddc *ddc_pin = ddc->ddc_pin;
+
+       if (ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout == NULL)
+               return DC_ERROR_UNEXPECTED;
+       if (!ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout(ddc, timeout))
+               status = DC_ERROR_UNEXPECTED;
+       return status;
+}
+
 /*test only function*/
 void dal_ddc_service_set_ddc_pin(
        struct ddc_service *ddc_service,
index f5742719b5d9b6951acc773cd268e56d51fa9d96..0f59b68aa4c245e0d7cc4b18150ddb53c741a663 100644 (file)
@@ -1409,6 +1409,9 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link)
        if (link->link_enc->features.flags.bits.IS_HBR3_CAPABLE)
                max_link_cap.link_rate = LINK_RATE_HIGH3;
 
+       if (link->link_enc->funcs->get_max_link_cap)
+               link->link_enc->funcs->get_max_link_cap(link->link_enc, &max_link_cap);
+
        /* Lower link settings based on sink's link cap */
        if (link->reported_link_cap.lane_count < max_link_cap.lane_count)
                max_link_cap.lane_count =
@@ -1653,11 +1656,14 @@ bool dp_verify_link_cap_with_retries(
 
        for (i = 0; i < attempts; i++) {
                int fail_count = 0;
-               enum dc_connection_type type;
+               enum dc_connection_type type = dc_connection_none;
 
                memset(&link->verified_link_cap, 0,
                                sizeof(struct dc_link_settings));
-               if (!dc_link_detect_sink(link, &type)) {
+               if (!dc_link_detect_sink(link, &type) || type == dc_connection_none) {
+                       link->verified_link_cap.lane_count = LANE_COUNT_ONE;
+                       link->verified_link_cap.link_rate = LINK_RATE_LOW;
+                       link->verified_link_cap.link_spread = LINK_SPREAD_DISABLED;
                        break;
                } else if (dp_verify_link_cap(link,
                                &link->reported_link_cap,
@@ -1670,6 +1676,19 @@ bool dp_verify_link_cap_with_retries(
        return success;
 }
 
+bool dp_verify_mst_link_cap(
+       struct dc_link *link)
+{
+       struct dc_link_settings max_link_cap = {0};
+
+       max_link_cap = get_max_link_cap(link);
+       link->verified_link_cap = get_common_supported_link_settings(
+               link->reported_link_cap,
+               max_link_cap);
+
+       return true;
+}
+
 static struct dc_link_settings get_common_supported_link_settings(
                struct dc_link_settings link_setting_a,
                struct dc_link_settings link_setting_b)
@@ -2057,11 +2076,11 @@ static bool allow_hpd_rx_irq(const struct dc_link *link)
        return false;
 }
 
-static bool handle_hpd_irq_psr_sink(const struct dc_link *link)
+static bool handle_hpd_irq_psr_sink(struct dc_link *link)
 {
        union dpcd_psr_configuration psr_configuration;
 
-       if (!link->psr_enabled)
+       if (!link->psr_feature_enabled)
                return false;
 
        dm_helpers_dp_read_dpcd(
@@ -2100,8 +2119,8 @@ static bool handle_hpd_irq_psr_sink(const struct dc_link *link)
                                sizeof(psr_error_status.raw));
 
                        /* PSR error, disable and re-enable PSR */
-                       dc_link_set_psr_enable(link, false, true);
-                       dc_link_set_psr_enable(link, true, true);
+                       dc_link_set_psr_allow_active(link, false, true);
+                       dc_link_set_psr_allow_active(link, true, true);
 
                        return true;
                } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
@@ -2364,6 +2383,8 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
        enum dc_status result;
 
        bool status = false;
+       struct pipe_ctx *pipe_ctx;
+       int i;
 
        if (out_link_loss)
                *out_link_loss = false;
@@ -2440,6 +2461,15 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
                        &link->cur_link_settings,
                        true, LINK_TRAINING_ATTEMPTS);
 
+               for (i = 0; i < MAX_PIPES; i++) {
+                       pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
+                       if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link &&
+                                       pipe_ctx->stream->dpms_off == false &&
+                                       pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+                               dc_link_allocate_mst_payload(pipe_ctx);
+                       }
+               }
+
                status = false;
                if (out_link_loss)
                        *out_link_loss = true;
@@ -2545,6 +2575,7 @@ static void get_active_converter_info(
        uint8_t data, struct dc_link *link)
 {
        union dp_downstream_port_present ds_port = { .byte = data };
+       memset(&link->dpcd_caps.dongle_caps, 0, sizeof(link->dpcd_caps.dongle_caps));
 
        /* decode converter info*/
        if (!ds_port.fields.PORT_PRESENT) {
@@ -2691,6 +2722,7 @@ static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
                 * keep receiver powered all the time.*/
                case DP_BRANCH_DEVICE_ID_0010FA:
                case DP_BRANCH_DEVICE_ID_0080E1:
+               case DP_BRANCH_DEVICE_ID_00E04C:
                        link->wa_flags.dp_keep_receiver_powered = true;
                        break;
 
index 79438c4f1e20be86f2cadd3a6b7a28c2a577fee9..a519dbc5ecb65317b766ce92023a276303a23403 100644 (file)
@@ -277,7 +277,8 @@ void dp_retrain_link_dp_test(struct dc_link *link,
                if (pipes[i].stream != NULL &&
                        !pipes[i].top_pipe && !pipes[i].prev_odm_pipe &&
                        pipes[i].stream->link != NULL &&
-                       pipes[i].stream_res.stream_enc != NULL) {
+                       pipes[i].stream_res.stream_enc != NULL &&
+                       pipes[i].stream->link == link) {
                        udelay(100);
 
                        pipes[i].stream_res.stream_enc->funcs->dp_blank(
index 8f70295179ffa2aad20982f28d79da8661ff0496..25da0c45d828422bd21771d4d940fa94367e2177 100644 (file)
@@ -1848,28 +1848,28 @@ static int acquire_resource_from_hw_enabled_state(
                struct dc_stream_state *stream)
 {
        struct dc_link *link = stream->link;
-       unsigned int inst, tg_inst;
+       unsigned int i, inst, tg_inst = 0;
 
        /* Check for enabled DIG to identify enabled display */
        if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
                return -1;
 
-       /* Check for which front end is used by this encoder.
-        * Note the inst is 1 indexed, where 0 is undefined.
-        * Note that DIG_FE can source from different OTG but our
-        * current implementation always map 1-to-1, so this code makes
-        * the same assumption and doesn't check OTG source.
-        */
        inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
 
-       /* Instance should be within the range of the pool */
-       if (inst >= pool->pipe_count)
-               return -1;
+       if (inst == ENGINE_ID_UNKNOWN)
+               return false;
 
-       if (inst >= pool->stream_enc_count)
-               return -1;
+       for (i = 0; i < pool->stream_enc_count; i++) {
+               if (pool->stream_enc[i]->id == inst) {
+                       tg_inst = pool->stream_enc[i]->funcs->dig_source_otg(
+                               pool->stream_enc[i]);
+                       break;
+               }
+       }
 
-       tg_inst = pool->stream_enc[inst]->funcs->dig_source_otg(pool->stream_enc[inst]);
+       // tg_inst not found
+       if (i == pool->stream_enc_count)
+               return false;
 
        if (tg_inst >= pool->timing_generator_count)
                return false;
index bf1d7bb90e0f98885f9112b3ff2f32e6c205bb84..bb09243758fe35e0768e2a74994df837112f5b7b 100644 (file)
@@ -423,10 +423,10 @@ bool dc_stream_add_writeback(struct dc *dc,
 
                if (dwb->funcs->is_enabled(dwb)) {
                        /* writeback pipe already enabled, only need to update */
-                       dc->hwss.update_writeback(dc, stream_status, wb_info);
+                       dc->hwss.update_writeback(dc, stream_status, wb_info, dc->current_state);
                } else {
                        /* Enable writeback pipe from scratch*/
-                       dc->hwss.enable_writeback(dc, stream_status, wb_info);
+                       dc->hwss.enable_writeback(dc, stream_status, wb_info, dc->current_state);
                }
        }
 
index a82352a87808b0fbdc81637a7a55d0efbcc32f1b..5967106826ca5e2038d91df08983236688905676 100644 (file)
@@ -39,7 +39,7 @@
 #include "inc/hw/dmcu.h"
 #include "dml/display_mode_lib.h"
 
-#define DC_VER "3.2.48"
+#define DC_VER "3.2.54"
 
 #define MAX_SURFACES 3
 #define MAX_PLANES 6
@@ -111,19 +111,20 @@ struct dc_caps {
        bool force_dp_tps4_for_cp2520;
        bool disable_dp_clk_share;
        bool psp_setup_panel_mode;
+       bool extended_aux_timeout_support;
 #ifdef CONFIG_DRM_AMD_DC_DCN2_0
        bool hw_3d_lut;
 #endif
        struct dc_plane_cap planes[MAX_PLANES];
 };
 
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
 struct dc_bug_wa {
+#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
        bool no_connect_phy_config;
        bool dedcn20_305_wa;
+#endif
        bool skip_clock_update;
 };
-#endif
 
 struct dc_dcc_surface_param {
        struct dc_size surface_size;
@@ -220,6 +221,7 @@ struct dc_config {
        bool power_down_display_on_boot;
        bool edp_not_connected;
        bool forced_clocks;
+       bool disable_extended_timeout_support; // Used to disable extended timeout and lttpr feature as well
        bool multi_mon_pp_mclk_switch;
 };
 
@@ -245,6 +247,18 @@ enum wm_report_mode {
        WM_REPORT_DEFAULT = 0,
        WM_REPORT_OVERRIDE = 1,
 };
+enum dtm_pstate{
+       dtm_level_p0 = 0,/*highest voltage*/
+       dtm_level_p1,
+       dtm_level_p2,
+       dtm_level_p3,
+       dtm_level_p4,/*when active_display_count = 0*/
+};
+
+enum dcn_pwr_state {
+       DCN_PWR_STATE_OPTIMIZED = 0,
+       DCN_PWR_STATE_NORMAL = 1
+};
 
 /*
  * For any clocks that may differ per pipe
@@ -252,11 +266,7 @@ enum wm_report_mode {
  */
 struct dc_clocks {
        int dispclk_khz;
-       int max_supported_dppclk_khz;
-       int max_supported_dispclk_khz;
        int dppclk_khz;
-       int bw_dppclk_khz; /*a copy of dppclk_khz*/
-       int bw_dispclk_khz;
        int dcfclk_khz;
        int socclk_khz;
        int dcfclk_deep_sleep_khz;
@@ -264,12 +274,17 @@ struct dc_clocks {
        int phyclk_khz;
        int dramclk_khz;
        bool p_state_change_support;
-
+       enum dcn_pwr_state pwr_state;
        /*
         * Elements below are not compared for the purposes of
         * optimization required
         */
        bool prev_p_state_change_support;
+       enum dtm_pstate dtm_level;
+       int max_supported_dppclk_khz;
+       int max_supported_dispclk_khz;
+       int bw_dppclk_khz; /*a copy of dppclk_khz*/
+       int bw_dispclk_khz;
 };
 
 struct dc_bw_validation_profile {
@@ -347,6 +362,7 @@ struct dc_debug_options {
        bool disable_hubp_power_gate;
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
        bool disable_dsc_power_gate;
+       int dsc_min_slice_height_override;
 #endif
        bool disable_pplib_wm_range;
        enum wm_report_mode pplib_wm_report_mode;
@@ -462,9 +478,7 @@ struct dc {
        struct dc_config config;
        struct dc_debug_options debug;
        struct dc_bounding_box_overrides bb_overrides;
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
        struct dc_bug_wa work_arounds;
-#endif
        struct dc_context *ctx;
 #ifdef CONFIG_DRM_AMD_DC_DCN2_0
        struct dc_phy_addr_space_config vm_pa_config;
@@ -553,10 +567,16 @@ struct dc_init_data {
 };
 
 struct dc_callback_init {
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+       struct cp_psp cp_psp;
+#else
        uint8_t reserved;
+#endif
 };
 
 struct dc *dc_create(const struct dc_init_data *init_params);
+void dc_hardware_init(struct dc *dc);
+
 int dc_get_vmid_use_vector(struct dc *dc);
 #ifdef CONFIG_DRM_AMD_DC_DCN2_0
 void dc_setup_vm_context(struct dc *dc, struct dc_virtual_addr_space_config *va_config, int vmid);
@@ -565,6 +585,7 @@ int dc_setup_system_context(struct dc *dc, struct dc_phy_addr_space_config *pa_c
 #endif
 void dc_init_callbacks(struct dc *dc,
                const struct dc_callback_init *init_params);
+void dc_deinit_callbacks(struct dc *dc);
 void dc_destroy(struct dc **dc);
 
 /*******************************************************************************
index 6e42209f0e2053618a6f36c4f2e2cd392b0add58..0ed2962add5accf98c54ba8bd50e8d032126fe42 100644 (file)
@@ -30,6 +30,7 @@
 #define DP_DSC_BRANCH_OVERALL_THROUGHPUT_0  0x0a0   /* DP 1.4a SCR */
 #define DP_DSC_BRANCH_OVERALL_THROUGHPUT_1  0x0a1
 #define DP_DSC_BRANCH_MAX_LINE_WIDTH        0x0a2
+#include "dc_types.h"
 
 struct dc_dsc_bw_range {
        uint32_t min_kbps; /* Bandwidth if min_target_bpp_x16 is used */
@@ -39,13 +40,21 @@ struct dc_dsc_bw_range {
        uint32_t stream_kbps; /* Uncompressed stream bandwidth */
 };
 
+struct display_stream_compressor {
+       const struct dsc_funcs *funcs;
+#ifndef AMD_EDID_UTILITY
+       struct dc_context *ctx;
+       int inst;
+#endif
+};
 
 bool dc_dsc_parse_dsc_dpcd(const uint8_t *dpcd_dsc_basic_data,
                const uint8_t *dpcd_dsc_ext_data,
                struct dsc_dec_dpcd_caps *dsc_sink_caps);
 
 bool dc_dsc_compute_bandwidth_range(
-               const struct dc *dc,
+               const struct display_stream_compressor *dsc,
+               const uint32_t dsc_min_slice_height_override,
                const uint32_t min_kbps,
                const uint32_t max_kbps,
                const struct dsc_dec_dpcd_caps *dsc_sink_caps,
@@ -53,8 +62,9 @@ bool dc_dsc_compute_bandwidth_range(
                struct dc_dsc_bw_range *range);
 
 bool dc_dsc_compute_config(
-               const struct dc *dc,
+               const struct display_stream_compressor *dsc,
                const struct dsc_dec_dpcd_caps *dsc_sink_caps,
+               const uint32_t dsc_min_slice_height_override,
                uint32_t target_bandwidth_kbps,
                const struct dc_crtc_timing *timing,
                struct dc_dsc_config *dsc_cfg);
index 0b8700a8a94a684d92fd9d3de062e9235089a06d..e0856bb8511f6d9d7abfd4aecf7c87d18bd00e7a 100644 (file)
@@ -26,6 +26,8 @@
 #ifndef DC_HW_TYPES_H
 #define DC_HW_TYPES_H
 
+#ifndef AMD_EDID_UTILITY
+
 #include "os_types.h"
 #include "fixed31_32.h"
 #include "signal_types.h"
@@ -124,20 +126,6 @@ struct plane_size {
        int chroma_pitch;
        struct rect surface_size;
        struct rect chroma_size;
-
-       union {
-               struct {
-                       struct rect surface_size;
-                       int surface_pitch;
-               } grph;
-
-               struct {
-                       struct rect luma_size;
-                       int luma_pitch;
-                       struct rect chroma_size;
-                       int chroma_pitch;
-               } video;
-       };
 };
 
 struct dc_plane_dcc_param {
@@ -148,21 +136,6 @@ struct dc_plane_dcc_param {
 
        int meta_pitch_c;
        bool independent_64b_blks_c;
-
-       union {
-               struct {
-                       int meta_pitch;
-                       bool independent_64b_blks;
-               } grph;
-
-               struct {
-                       int meta_pitch_l;
-                       bool independent_64b_blks_l;
-
-                       int meta_pitch_c;
-                       bool independent_64b_blks_c;
-               } video;
-       };
 };
 
 /*Displayable pixel format in fb*/
@@ -605,6 +578,11 @@ enum dc_quantization_range {
        QUANTIZATION_RANGE_LIMITED
 };
 
+enum dc_dynamic_expansion {
+       DYN_EXPANSION_AUTO,
+       DYN_EXPANSION_DISABLE
+};
+
 /* XFM */
 
 /* used in  struct dc_plane_state */
@@ -616,6 +594,8 @@ struct scaling_taps {
        bool integer_scaling;
 };
 
+#endif /* AMD_EDID_UTILITY */
+
 enum dc_timing_standard {
        DC_TIMING_STANDARD_UNDEFINED,
        DC_TIMING_STANDARD_DMT,
@@ -737,30 +717,6 @@ enum dc_timing_3d_format {
        TIMING_3D_FORMAT_MAX,
 };
 
-enum trigger_delay {
-       TRIGGER_DELAY_NEXT_PIXEL = 0,
-       TRIGGER_DELAY_NEXT_LINE,
-};
-
-enum crtc_event {
-       CRTC_EVENT_VSYNC_RISING = 0,
-       CRTC_EVENT_VSYNC_FALLING
-};
-
-struct crtc_trigger_info {
-       bool enabled;
-       struct dc_stream_state *event_source;
-       enum crtc_event event;
-       enum trigger_delay delay;
-};
-
-struct dc_crtc_timing_adjust {
-       uint32_t v_total_min;
-       uint32_t v_total_max;
-       uint32_t v_total_mid;
-       uint32_t v_total_mid_frame_num;
-};
-
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
 struct dc_dsc_config {
        uint32_t num_slices_h; /* Number of DSC slices - horizontal */
@@ -804,6 +760,33 @@ struct dc_crtc_timing {
 #endif
 };
 
+#ifndef AMD_EDID_UTILITY
+
+enum trigger_delay {
+       TRIGGER_DELAY_NEXT_PIXEL = 0,
+       TRIGGER_DELAY_NEXT_LINE,
+};
+
+enum crtc_event {
+       CRTC_EVENT_VSYNC_RISING = 0,
+       CRTC_EVENT_VSYNC_FALLING
+};
+
+struct crtc_trigger_info {
+       bool enabled;
+       struct dc_stream_state *event_source;
+       enum crtc_event event;
+       enum trigger_delay delay;
+};
+
+struct dc_crtc_timing_adjust {
+       uint32_t v_total_min;
+       uint32_t v_total_max;
+       uint32_t v_total_mid;
+       uint32_t v_total_mid_frame_num;
+};
+
+
 /* Passed on init */
 enum vram_type {
        VIDEO_MEMORY_TYPE_GDDR5  = 2,
@@ -874,5 +857,7 @@ struct tg_color {
        uint16_t color_b_cb;
 };
 
+#endif /* AMD_EDID_UTILITY */
+
 #endif /* DC_HW_TYPES_H */
 
index 9ea75db3484ea0c825f7f53a37c22ba7058232d5..f24fd19ed93d71389ca8634173cd456f80bcc470 100644 (file)
@@ -126,7 +126,8 @@ struct dc_link {
        unsigned short chip_caps;
        unsigned int dpcd_sink_count;
        enum edp_revision edp_revision;
-       bool psr_enabled;
+       bool psr_feature_enabled;
+       bool psr_allow_active;
 
        /* MST record stream using this link */
        struct link_flags {
@@ -158,6 +159,18 @@ static inline struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_
        return dc->links[link_index];
 }
 
+static inline struct dc_link *get_edp_link(const struct dc *dc)
+{
+       int i;
+
+       // report any eDP links, even unconnected DDI's
+       for (i = 0; i < dc->link_count; i++) {
+               if (dc->links[i]->connector_signal == SIGNAL_TYPE_EDP)
+                       return dc->links[i];
+       }
+       return NULL;
+}
+
 /* Set backlight level of an embedded panel (eDP, LVDS).
  * backlight_pwm_u16_16 is unsigned 32 bit with 16 bit integer
  * and 16 bit fractional, where 1.0 is max backlight value.
@@ -170,7 +183,7 @@ int dc_link_get_backlight_level(const struct dc_link *dc_link);
 
 bool dc_link_set_abm_disable(const struct dc_link *dc_link);
 
-bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable, bool wait);
+bool dc_link_set_psr_allow_active(struct dc_link *dc_link, bool enable, bool wait);
 
 bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state);
 
@@ -192,6 +205,7 @@ enum dc_detect_reason {
 
 bool dc_link_detect(struct dc_link *dc_link, enum dc_detect_reason reason);
 bool dc_link_get_hpd_state(struct dc_link *dc_link);
+enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx);
 
 /* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt).
  * Return:
index 0fa1c26bc20db4faad5a29d4aaf568a8533403fe..fdb6adc37857a1654fbe5e33a95d5bb027a38aa8 100644 (file)
@@ -113,6 +113,21 @@ struct periodic_interrupt_config {
        int lines_offset;
 };
 
+union stream_update_flags {
+       struct {
+               uint32_t scaling:1;
+               uint32_t out_tf:1;
+               uint32_t out_csc:1;
+               uint32_t abm_level:1;
+               uint32_t dpms_off:1;
+               uint32_t gamut_remap:1;
+#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
+               uint32_t wb_update:1;
+#endif
+       } bits;
+
+       uint32_t raw;
+};
 
 struct dc_stream_state {
        // sink is deprecated, new code should not reference
@@ -214,9 +229,14 @@ struct dc_stream_state {
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
        bool is_dsc_enabled;
 #endif
+       union stream_update_flags update_flags;
 };
 
+#define ABM_LEVEL_IMMEDIATE_DISABLE 0xFFFFFFFF
+
 struct dc_stream_update {
+       struct dc_stream_state *stream;
+
        struct rect src;
        struct rect dst;
        struct dc_transfer_func *out_transfer_func;
@@ -431,6 +451,9 @@ void dc_stream_set_static_screen_events(struct dc *dc,
                                        int num_streams,
                                        const struct dc_static_screen_events *events);
 
+void dc_stream_set_dyn_expansion(struct dc *dc, struct dc_stream_state *stream,
+               enum dc_dynamic_expansion option);
+
 void dc_stream_set_dither_option(struct dc_stream_state *stream,
                                 enum dc_dither_option option);
 
index b273735b6a3ece1855484bc745280978391cfe6d..d9be8fc3889f7d9f0a7a1fd3d63f036110f445b0 100644 (file)
 #ifndef DC_TYPES_H_
 #define DC_TYPES_H_
 
+#ifndef AMD_EDID_UTILITY
+/* AND EdidUtility only needs a portion
+ * of this file, including the rest only
+ * causes additional issues.
+ */
 #include "os_types.h"
 #include "fixed31_32.h"
 #include "irq_types.h"
 #include "dal_types.h"
 #include "grph_object_defs.h"
 
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+#include "dm_cp_psp.h"
+#endif
+
 /* forward declarations */
 struct dc_plane_state;
 struct dc_stream_state;
@@ -100,6 +109,9 @@ struct dc_context {
        uint32_t dc_sink_id_count;
        uint32_t dc_stream_id_count;
        uint64_t fbc_gpu_addr;
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+       struct cp_psp cp_psp;
+#endif
 };
 
 
@@ -159,6 +171,12 @@ enum dc_edid_status {
        EDID_THE_SAME,
 };
 
+enum act_return_status {
+       ACT_SUCCESS,
+       ACT_LINK_LOST,
+       ACT_FAILED
+};
+
 /* audio capability from EDID*/
 struct dc_cea_audio_mode {
        uint8_t format_code; /* ucData[0] [6:3]*/
@@ -739,6 +757,9 @@ struct dc_clock_config {
        uint32_t current_clock_khz;/*current clock in use*/
 };
 
+#endif /*AMD_EDID_UTILITY*/
+//AMD EDID UTILITY does not need any of the above structures
+
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
 /* DSC DPCD capabilities */
 union dsc_slice_caps1 {
@@ -810,4 +831,5 @@ struct dsc_dec_dpcd_caps {
        uint32_t branch_max_line_width;
 };
 #endif
+
 #endif /* DC_TYPES_H_ */
index 58bd131d5b4849bc70f0bc29f4448d6d44d38daf..d759fdca7fdbafe2c222c2e5a0c5fd753981773e 100644 (file)
@@ -77,6 +77,9 @@ static bool dce_abm_set_pipe(struct abm *abm, uint32_t controller_id)
        /* notifyDMCUMsg */
        REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
 
+       REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
+                       1, 80000);
+
        return true;
 }
 
@@ -489,9 +492,6 @@ void dce_abm_destroy(struct abm **abm)
 {
        struct dce_abm *abm_dce = TO_DCE_ABM(*abm);
 
-       if (abm_dce->base.dmcu_is_running == true)
-               abm_dce->base.funcs->set_abm_immediate_disable(*abm);
-
        kfree(abm_dce);
        *abm = NULL;
 }
index c3f9f4185ce8dafdcf157c372d0364ddcf126361..976bd4987a28ffc4f7f299fda45cd51e137fa287 100644 (file)
 
 #include "reg_helper.h"
 
+#undef FN
+#define FN(reg_name, field_name) \
+       aux110->shift->field_name, aux110->mask->field_name
+
 #define FROM_AUX_ENGINE(ptr) \
        container_of((ptr), struct aux_engine_dce110, base)
 
@@ -55,6 +59,14 @@ enum {
        AUX_TIMED_OUT_RETRY_COUNTER = 2,
        AUX_DEFER_RETRY_COUNTER = 6
 };
+
+#define TIME_OUT_INCREMENT      1016
+#define TIME_OUT_MULTIPLIER_8  8
+#define TIME_OUT_MULTIPLIER_16  16
+#define TIME_OUT_MULTIPLIER_32  32
+#define TIME_OUT_MULTIPLIER_64  64
+#define MAX_TIMEOUT_LENGTH      127
+
 static void release_engine(
        struct dce_aux *engine)
 {
@@ -198,7 +210,7 @@ static void submit_channel_request(
        REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1);
 
        REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0,
-                               10, aux110->timeout_period/10);
+                               10, aux110->polling_timeout_period/10);
 
        /* set the delay and the number of bytes to write */
 
@@ -327,7 +339,7 @@ static enum aux_channel_operation_result get_channel_status(
 
        /* poll to make sure that SW_DONE is asserted */
        REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1,
-                               10, aux110->timeout_period/10);
+                               10, aux110->polling_timeout_period/10);
 
        value = REG_READ(AUX_SW_STATUS);
        /* in case HPD is LOW, exit AUX transaction */
@@ -414,20 +426,82 @@ void dce110_engine_destroy(struct dce_aux **engine)
        *engine = NULL;
 
 }
+
+static bool dce_aux_configure_timeout(struct ddc_service *ddc,
+               uint32_t timeout_in_us)
+{
+       uint32_t multiplier = 0;
+       uint32_t length = 0;
+       uint32_t timeout = 0;
+       struct ddc *ddc_pin = ddc->ddc_pin;
+       struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
+       struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(aux_engine);
+
+       /* 1-Update polling timeout period */
+       aux110->polling_timeout_period = timeout_in_us * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER;
+
+       /* 2-Update aux timeout period length and multiplier */
+       if (timeout_in_us <= TIME_OUT_INCREMENT) {
+               multiplier = 0;
+               length = timeout_in_us/TIME_OUT_MULTIPLIER_8;
+               if (timeout_in_us % TIME_OUT_MULTIPLIER_8 != 0)
+                       length++;
+               timeout = length * TIME_OUT_MULTIPLIER_8;
+       } else if (timeout_in_us <= 2 * TIME_OUT_INCREMENT) {
+               multiplier = 1;
+               length = timeout_in_us/TIME_OUT_MULTIPLIER_16;
+               if (timeout_in_us % TIME_OUT_MULTIPLIER_16 != 0)
+                       length++;
+               timeout = length * TIME_OUT_MULTIPLIER_16;
+       } else if (timeout_in_us <= 4 * TIME_OUT_INCREMENT) {
+               multiplier = 2;
+               length = timeout_in_us/TIME_OUT_MULTIPLIER_32;
+               if (timeout_in_us % TIME_OUT_MULTIPLIER_32 != 0)
+                       length++;
+               timeout = length * TIME_OUT_MULTIPLIER_32;
+       } else if (timeout_in_us > 4 * TIME_OUT_INCREMENT) {
+               multiplier = 3;
+               length = timeout_in_us/TIME_OUT_MULTIPLIER_64;
+               if (timeout_in_us % TIME_OUT_MULTIPLIER_64 != 0)
+                       length++;
+               timeout = length * TIME_OUT_MULTIPLIER_64;
+       }
+
+       length = (length < MAX_TIMEOUT_LENGTH) ? length : MAX_TIMEOUT_LENGTH;
+
+       REG_UPDATE_SEQ_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, length, AUX_RX_TIMEOUT_LEN_MUL, multiplier);
+
+       return true;
+}
+
+static struct dce_aux_funcs aux_functions = {
+       .configure_timeout = NULL,
+       .destroy = NULL,
+};
+
 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)
+               const struct dce110_aux_registers *regs,
+               const struct dce110_aux_registers_mask *mask,
+               const struct dce110_aux_registers_shift *shift,
+               bool is_ext_aux_timeout_configurable)
 {
        aux_engine110->base.ddc = NULL;
        aux_engine110->base.ctx = ctx;
        aux_engine110->base.delay = 0;
        aux_engine110->base.max_defer_write_retry = 0;
        aux_engine110->base.inst = inst;
-       aux_engine110->timeout_period = timeout_period;
+       aux_engine110->polling_timeout_period = timeout_period;
        aux_engine110->regs = regs;
 
+       aux_engine110->mask = mask;
+       aux_engine110->shift = shift;
+       aux_engine110->base.funcs = &aux_functions;
+       if (is_ext_aux_timeout_configurable)
+               aux_engine110->base.funcs->configure_timeout = &dce_aux_configure_timeout;
+
        return &aux_engine110->base;
 }
 
@@ -475,7 +549,7 @@ int dce_aux_transfer_raw(struct ddc_service *ddc,
        aux_req.action = i2caux_action_from_payload(payload);
 
        aux_req.address = payload->address;
-       aux_req.delay = payload->defer_delay * 10;
+       aux_req.delay = 0;
        aux_req.length = payload->length;
        aux_req.data = payload->data;
 
@@ -544,8 +618,15 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
                        case AUX_TRANSACTION_REPLY_AUX_DEFER:
                        case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK:
                        case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER:
-                               if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES)
+                               if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES) {
                                        goto fail;
+                               } else {
+                                       if ((*payload->reply == AUX_TRANSACTION_REPLY_AUX_DEFER) ||
+                                               (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)) {
+                                               if (payload->defer_delay > 0)
+                                                       msleep(payload->defer_delay);
+                                       }
+                               }
                                break;
 
                        case AUX_TRANSACTION_REPLY_I2C_DEFER:
index ed7fec8fe25389333ffd07b8077b57c123804d05..b4b2c79a80736351b6faac766381316f8d2d913c 100644 (file)
@@ -29,6 +29,7 @@
 #include "i2caux_interface.h"
 #include "inc/hw/aux_engine.h"
 
+
 #ifdef CONFIG_DRM_AMD_DC_DCN2_0
 #define AUX_COMMON_REG_LIST0(id)\
        SRI(AUX_CONTROL, DP_AUX, id), \
@@ -36,6 +37,7 @@
        SRI(AUX_SW_DATA, DP_AUX, id), \
        SRI(AUX_SW_CONTROL, DP_AUX, id), \
        SRI(AUX_INTERRUPT_CONTROL, DP_AUX, id), \
+       SRI(AUX_DPHY_RX_CONTROL1, DP_AUX, id), \
        SRI(AUX_SW_STATUS, DP_AUX, id)
 #endif
 
@@ -55,6 +57,7 @@ struct dce110_aux_registers {
        uint32_t AUX_SW_DATA;
        uint32_t AUX_SW_CONTROL;
        uint32_t AUX_INTERRUPT_CONTROL;
+       uint32_t AUX_DPHY_RX_CONTROL1;
        uint32_t AUX_SW_STATUS;
        uint32_t AUXN_IMPCAL;
        uint32_t AUXP_IMPCAL;
@@ -62,6 +65,156 @@ struct dce110_aux_registers {
        uint32_t AUX_RESET_MASK;
 };
 
+#define DCE_AUX_REG_FIELD_LIST(type)\
+       type AUX_EN;\
+       type AUX_RESET;\
+       type AUX_RESET_DONE;\
+       type AUX_REG_RW_CNTL_STATUS;\
+       type AUX_SW_USE_AUX_REG_REQ;\
+       type AUX_SW_DONE_USING_AUX_REG;\
+       type AUX_SW_AUTOINCREMENT_DISABLE;\
+       type AUX_SW_DATA_RW;\
+       type AUX_SW_INDEX;\
+       type AUX_SW_GO;\
+       type AUX_SW_DATA;\
+       type AUX_SW_REPLY_BYTE_COUNT;\
+       type AUX_SW_DONE;\
+       type AUX_SW_DONE_ACK;\
+       type AUXN_IMPCAL_ENABLE;\
+       type AUXP_IMPCAL_ENABLE;\
+       type AUXN_IMPCAL_OVERRIDE_ENABLE;\
+       type AUXP_IMPCAL_OVERRIDE_ENABLE;\
+       type AUX_RX_TIMEOUT_LEN;\
+       type AUX_RX_TIMEOUT_LEN_MUL;\
+       type AUXN_CALOUT_ERROR_AK;\
+       type AUXP_CALOUT_ERROR_AK;\
+       type AUX_SW_START_DELAY;\
+       type AUX_SW_WR_BYTES
+
+#define DCE10_AUX_MASK_SH_LIST(mask_sh)\
+       AUX_SF(AUX_CONTROL, AUX_EN, mask_sh),\
+       AUX_SF(AUX_ARB_CONTROL, AUX_REG_RW_CNTL_STATUS, mask_sh),\
+       AUX_SF(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, mask_sh),\
+       AUX_SF(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, mask_sh),\
+       AUX_SF(AUX_SW_CONTROL, AUX_SW_START_DELAY, mask_sh),\
+       AUX_SF(AUX_SW_CONTROL, AUX_SW_WR_BYTES, mask_sh),\
+       AUX_SF(AUX_SW_CONTROL, AUX_SW_GO, mask_sh),\
+       AUX_SF(AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
+       AUX_SF(AUX_SW_DATA, AUX_SW_DATA_RW, mask_sh),\
+       AUX_SF(AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
+       AUX_SF(AUX_SW_DATA, AUX_SW_INDEX, mask_sh),\
+       AUX_SF(AUX_SW_DATA, AUX_SW_DATA, mask_sh),\
+       AUX_SF(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, mask_sh),\
+       AUX_SF(AUX_SW_STATUS, AUX_SW_DONE, mask_sh),\
+       AUX_SF(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, mask_sh),\
+       AUX_SF(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK, mask_sh),\
+       AUX_SF(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK, mask_sh),\
+       AUX_SF(AUXN_IMPCAL, AUXN_IMPCAL_ENABLE, mask_sh),\
+       AUX_SF(AUXP_IMPCAL, AUXP_IMPCAL_ENABLE, mask_sh),\
+       AUX_SF(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE, mask_sh),\
+       AUX_SF(AUXN_IMPCAL, AUXN_IMPCAL_OVERRIDE_ENABLE, mask_sh)
+
+#define DCE_AUX_MASK_SH_LIST(mask_sh)\
+       AUX_SF(AUX_CONTROL, AUX_EN, mask_sh),\
+       AUX_SF(AUX_CONTROL, AUX_RESET, mask_sh),\
+       AUX_SF(AUX_CONTROL, AUX_RESET_DONE, mask_sh),\
+       AUX_SF(AUX_ARB_CONTROL, AUX_REG_RW_CNTL_STATUS, mask_sh),\
+       AUX_SF(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, mask_sh),\
+       AUX_SF(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, mask_sh),\
+       AUX_SF(AUX_SW_CONTROL, AUX_SW_START_DELAY, mask_sh),\
+       AUX_SF(AUX_SW_CONTROL, AUX_SW_WR_BYTES, mask_sh),\
+       AUX_SF(AUX_SW_CONTROL, AUX_SW_GO, mask_sh),\
+       AUX_SF(AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
+       AUX_SF(AUX_SW_DATA, AUX_SW_DATA_RW, mask_sh),\
+       AUX_SF(AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
+       AUX_SF(AUX_SW_DATA, AUX_SW_INDEX, mask_sh),\
+       AUX_SF(AUX_SW_DATA, AUX_SW_DATA, mask_sh),\
+       AUX_SF(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, mask_sh),\
+       AUX_SF(AUX_SW_STATUS, AUX_SW_DONE, mask_sh),\
+       AUX_SF(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, mask_sh),\
+       AUX_SF(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK, mask_sh),\
+       AUX_SF(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK, mask_sh),\
+       AUX_SF(AUXN_IMPCAL, AUXN_IMPCAL_ENABLE, mask_sh),\
+       AUX_SF(AUXP_IMPCAL, AUXP_IMPCAL_ENABLE, mask_sh),\
+       AUX_SF(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE, mask_sh),\
+       AUX_SF(AUXN_IMPCAL, AUXN_IMPCAL_OVERRIDE_ENABLE, mask_sh)
+
+#define DCE12_AUX_MASK_SH_LIST(mask_sh)\
+       AUX_SF(DP_AUX0_AUX_CONTROL, AUX_EN, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_CONTROL, AUX_RESET, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_CONTROL, AUX_RESET_DONE, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_REG_RW_CNTL_STATUS, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_START_DELAY, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_WR_BYTES, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_GO, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_DATA_RW, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_INDEX, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_DATA, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_STATUS, AUX_SW_DONE, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, mask_sh),\
+       AUX_SF(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK, mask_sh),\
+       AUX_SF(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK, mask_sh),\
+       AUX_SF(AUXN_IMPCAL, AUXN_IMPCAL_ENABLE, mask_sh),\
+       AUX_SF(AUXP_IMPCAL, AUXP_IMPCAL_ENABLE, mask_sh),\
+       AUX_SF(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE, mask_sh),\
+       AUX_SF(AUXN_IMPCAL, AUXN_IMPCAL_OVERRIDE_ENABLE, mask_sh)
+
+/* DCN10 MASK */
+#define DCN10_AUX_MASK_SH_LIST(mask_sh)\
+       AUX_SF(DP_AUX0_AUX_CONTROL, AUX_EN, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_CONTROL, AUX_RESET, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_CONTROL, AUX_RESET_DONE, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_REG_RW_CNTL_STATUS, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_START_DELAY, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_WR_BYTES, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_GO, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_DATA_RW, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_INDEX, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_DATA, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_STATUS, AUX_SW_DONE, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, mask_sh),\
+       AUX_SF(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK, mask_sh),\
+       AUX_SF(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK, mask_sh),\
+       AUX_SF(AUXN_IMPCAL, AUXN_IMPCAL_ENABLE, mask_sh),\
+       AUX_SF(AUXP_IMPCAL, AUXP_IMPCAL_ENABLE, mask_sh),\
+       AUX_SF(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE, mask_sh),\
+       AUX_SF(AUXN_IMPCAL, AUXN_IMPCAL_OVERRIDE_ENABLE, mask_sh)
+
+/* for all other DCN */
+#define DCN_AUX_MASK_SH_LIST(mask_sh)\
+       AUX_SF(DP_AUX0_AUX_CONTROL, AUX_EN, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_CONTROL, AUX_RESET, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_CONTROL, AUX_RESET_DONE, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_REG_RW_CNTL_STATUS, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_START_DELAY, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_WR_BYTES, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_GO, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_DATA_RW, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_INDEX, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_DATA, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_SW_STATUS, AUX_SW_DONE, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\
+       AUX_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh)
+
+#define AUX_SF(reg_name, field_name, post_fix)\
+       .field_name = reg_name ## __ ## field_name ## post_fix
+
 enum { /* This is the timeout as defined in DP 1.2a,
         * 2.3.4 "Detailed uPacket TX AUX CH State Description".
         */
@@ -97,20 +250,34 @@ struct dce_aux {
        uint32_t max_defer_write_retry;
 
        bool acquire_reset;
+       struct dce_aux_funcs *funcs;
+};
+
+struct dce110_aux_registers_mask {
+       DCE_AUX_REG_FIELD_LIST(uint32_t);
+};
+
+struct dce110_aux_registers_shift {
+       DCE_AUX_REG_FIELD_LIST(uint8_t);
 };
 
+
 struct aux_engine_dce110 {
        struct dce_aux base;
        const struct dce110_aux_registers *regs;
+       const struct dce110_aux_registers_mask *mask;
+       const struct dce110_aux_registers_shift *shift;
        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_dphy_rx_control1;
+               uint32_t aux_dphy_rx_control0;
                uint32_t aux_sw_status;
        } addr;
-       uint32_t timeout_period;
+       uint32_t polling_timeout_period;
 };
 
 struct aux_engine_dce110_init_data {
@@ -120,12 +287,15 @@ struct aux_engine_dce110_init_data {
        const struct dce110_aux_registers *regs;
 };
 
-struct dce_aux *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,
-               const struct dce110_aux_registers *regs);
+               const struct dce110_aux_registers *regs,
+
+               const struct dce110_aux_registers_mask *mask,
+               const struct dce110_aux_registers_shift *shift,
+               bool is_ext_aux_timeout_configurable);
 
 void dce110_engine_destroy(struct dce_aux **engine);
 
@@ -139,4 +309,13 @@ int dce_aux_transfer_raw(struct ddc_service *ddc,
 
 bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
                struct aux_payload *cmd);
+
+struct dce_aux_funcs {
+       bool (*configure_timeout)
+               (struct ddc_service *ddc,
+                uint32_t timeout);
+       void (*destroy)
+               (struct aux_engine **ptr);
+};
+
 #endif
index 0b86cee4876f46986f58bd32c0937d9d956d27ed..ba995d3f23182438b70e4e42a9053ad7698f44b1 100644 (file)
@@ -907,9 +907,6 @@ void dce_dmcu_destroy(struct dmcu **dmcu)
 {
        struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(*dmcu);
 
-       if (dmcu_dce->base.dmcu_state == DMCU_RUNNING)
-               dmcu_dce->base.funcs->set_psr_enable(*dmcu, false, true);
-
        kfree(dmcu_dce);
        *dmcu = NULL;
 }
index ac04d77058f09d84a0f09f6444107ed1de2a9f57..32d145a0d6fce5437b480e97c76970335895c8d4 100644 (file)
@@ -679,6 +679,7 @@ struct dce_hwseq_registers {
        HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN17_PGFSM_PWR_STATUS, mask_sh), \
        HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN18_PGFSM_PWR_STATUS, mask_sh), \
        HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \
+       HWSEQ_LVTMA_MASK_SH_LIST(mask_sh), \
        HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \
        HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh)
 #endif
index 31b698bf9cfc911f54a93205ad0a4a739918c318..8aa937f496c4ffb5e81b222b98c9ce97793eda02 100644 (file)
@@ -606,11 +606,11 @@ static void dce_mi_allocate_dmif(
        }
 
        if (dce_mi->wa.single_head_rdreq_dmif_limit) {
-               uint32_t eanble =  (total_stream_num > 1) ? 0 :
+               uint32_t enable =  (total_stream_num > 1) ? 0 :
                                dce_mi->wa.single_head_rdreq_dmif_limit;
 
                REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
-                               ENABLE, eanble);
+                               ENABLE, enable);
        }
 }
 
@@ -636,11 +636,11 @@ static void dce_mi_free_dmif(
                        10, 3500);
 
        if (dce_mi->wa.single_head_rdreq_dmif_limit) {
-               uint32_t eanble =  (total_stream_num > 1) ? 0 :
+               uint32_t enable =  (total_stream_num > 1) ? 0 :
                                dce_mi->wa.single_head_rdreq_dmif_limit;
 
                REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
-                               ENABLE, eanble);
+                               ENABLE, enable);
        }
 }
 
index 76d54885374abbf08df4b16041004da78d934afd..b5d6dff29c4513ddc6a2596fc47c8d9c3d9f6165 100644 (file)
@@ -506,6 +506,14 @@ static const struct dce_mem_input_mask mi_masks = {
                .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK
 };
 
+static const struct dce110_aux_registers_shift aux_shift = {
+       DCE10_AUX_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dce110_aux_registers_mask aux_mask = {
+       DCE10_AUX_MASK_SH_LIST(_MASK)
+};
+
 static struct mem_input *dce100_mem_input_create(
        struct dc_context *ctx,
        uint32_t inst)
@@ -611,7 +619,10 @@ struct dce_aux *dce100_aux_engine_create(
 
        dce110_aux_engine_construct(aux_engine, ctx, inst,
                                    SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,
-                                   &aux_engine_regs[inst]);
+                                   &aux_engine_regs[inst],
+                                       &aux_mask,
+                                       &aux_shift,
+                                       ctx->dc->caps.extended_aux_timeout_support);
 
        return &aux_engine->base;
 }
@@ -997,6 +1008,8 @@ static bool construct(
        dc->caps.max_cursor_size = 128;
        dc->caps.dual_link_dvi = true;
        dc->caps.disable_dp_clk_share = true;
+       dc->caps.extended_aux_timeout_support = false;
+
        for (i = 0; i < pool->base.pipe_count; i++) {
                pool->base.timing_generators[i] =
                        dce100_timing_generator_create(
index 01a924bf477a6d86a933a02b7316d0f168a8c300..9150e546dcf2dc784b6172a16e747150ac6a46e6 100644 (file)
@@ -944,7 +944,6 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
 {
        /* notify audio driver for audio modes of monitor */
        struct dc *core_dc;
-       struct pp_smu_funcs *pp_smu = NULL;
        struct clk_mgr *clk_mgr;
        unsigned int i, num_audio = 1;
 
@@ -957,9 +956,6 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
        if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == true)
                return;
 
-       if (core_dc->res_pool->pp_smu)
-               pp_smu = core_dc->res_pool->pp_smu;
-
        if (pipe_ctx->stream_res.audio) {
                for (i = 0; i < MAX_PIPES; i++) {
                        /*current_state not updated yet*/
@@ -984,7 +980,6 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
 void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx)
 {
        struct dc *dc;
-       struct pp_smu_funcs *pp_smu = NULL;
        struct clk_mgr *clk_mgr;
 
        if (!pipe_ctx || !pipe_ctx->stream)
@@ -1001,9 +996,6 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx)
        if (pipe_ctx->stream_res.audio) {
                pipe_ctx->stream_res.audio->enabled = false;
 
-               if (dc->res_pool->pp_smu)
-                       pp_smu = dc->res_pool->pp_smu;
-
                if (dc_is_dp_signal(pipe_ctx->stream->signal))
                        pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable(
                                        pipe_ctx->stream_res.stream_enc);
@@ -1169,8 +1161,9 @@ static void build_audio_output(
                }
        }
 
-       if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
-                       pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+       if (state->clk_mgr &&
+               (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
+                       pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)) {
                audio_output->pll_info.dp_dto_source_clock_in_khz =
                                state->clk_mgr->funcs->get_dp_ref_clk_frequency(
                                                state->clk_mgr);
@@ -1418,7 +1411,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->link->psr_enabled = false;
+       pipe_ctx->stream->link->psr_feature_enabled = false;
 
        return DC_OK;
 }
@@ -1529,18 +1522,6 @@ static struct dc_stream_state *get_edp_stream(struct dc_state *context)
        return NULL;
 }
 
-static struct dc_link *get_edp_link(struct dc *dc)
-{
-       int i;
-
-       // report any eDP links, even unconnected DDI's
-       for (i = 0; i < dc->link_count; i++) {
-               if (dc->links[i]->connector_signal == SIGNAL_TYPE_EDP)
-                       return dc->links[i];
-       }
-       return NULL;
-}
-
 static struct dc_link *get_edp_link_with_sink(
                struct dc *dc,
                struct dc_state *context)
@@ -1834,7 +1815,7 @@ static bool should_enable_fbc(struct dc *dc,
                return false;
 
        /* PSR should not be enabled */
-       if (pipe_ctx->stream->link->psr_enabled)
+       if (pipe_ctx->stream->link->psr_feature_enabled)
                return false;
 
        /* Nothing to compress */
@@ -2464,7 +2445,6 @@ static void dce110_program_front_end_for_pipe(
                struct dc *dc, struct pipe_ctx *pipe_ctx)
 {
        struct mem_input *mi = pipe_ctx->plane_res.mi;
-       struct pipe_ctx *old_pipe = NULL;
        struct dc_plane_state *plane_state = pipe_ctx->plane_state;
        struct xfm_grph_csc_adjustment adjust;
        struct out_csc_color_matrix tbl_entry;
@@ -2472,9 +2452,6 @@ static void dce110_program_front_end_for_pipe(
        DC_LOGGER_INIT();
        memset(&tbl_entry, 0, sizeof(tbl_entry));
 
-       if (dc->current_state)
-               old_pipe = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
-
        memset(&adjust, 0, sizeof(adjust));
        adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
 
index 89620adc81d8b338115b07775a1b7f2452188283..c651a38e34a08b7063cff6f412aebe2082bc90b4 100644 (file)
@@ -275,6 +275,14 @@ static const struct dce_stream_encoder_mask se_mask = {
                SE_COMMON_MASK_SH_LIST_DCE110(_MASK)
 };
 
+static const struct dce110_aux_registers_shift aux_shift = {
+       DCE_AUX_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dce110_aux_registers_mask aux_mask = {
+       DCE_AUX_MASK_SH_LIST(_MASK)
+};
+
 #define opp_regs(id)\
 [id] = {\
        OPP_DCE_110_REG_LIST(id),\
@@ -657,7 +665,10 @@ struct dce_aux *dce110_aux_engine_create(
 
        dce110_aux_engine_construct(aux_engine, ctx, inst,
                                    SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,
-                                   &aux_engine_regs[inst]);
+                                   &aux_engine_regs[inst],
+                                       &aux_mask,
+                                       &aux_shift,
+                                       ctx->dc->caps.extended_aux_timeout_support);
 
        return &aux_engine->base;
 }
@@ -1293,6 +1304,7 @@ static bool construct(
        dc->caps.i2c_speed_in_khz = 100;
        dc->caps.max_cursor_size = 128;
        dc->caps.is_apu = true;
+       dc->caps.extended_aux_timeout_support = false;
 
        /*************************************************
         *  Create resources                             *
index 21a657e79306362432bf0f3d7a8723d849716e2f..876ed0607718016f462be9533048612f96b422c1 100644 (file)
@@ -172,6 +172,14 @@ static const struct dce_abm_mask abm_mask = {
                ABM_MASK_SH_LIST_DCE110(_MASK)
 };
 
+static const struct dce110_aux_registers_shift aux_shift = {
+       DCE_AUX_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dce110_aux_registers_mask aux_mask = {
+       DCE_AUX_MASK_SH_LIST(_MASK)
+};
+
 #define ipp_regs(id)\
 [id] = {\
                IPP_DCE110_REG_LIST_DCE_BASE(id)\
@@ -630,7 +638,10 @@ struct dce_aux *dce112_aux_engine_create(
 
        dce110_aux_engine_construct(aux_engine, ctx, inst,
                                    SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,
-                                   &aux_engine_regs[inst]);
+                                   &aux_engine_regs[inst],
+                                       &aux_mask,
+                                       &aux_shift,
+                                       ctx->dc->caps.extended_aux_timeout_support);
 
        return &aux_engine->base;
 }
@@ -1163,7 +1174,7 @@ static bool construct(
        dc->caps.i2c_speed_in_khz = 100;
        dc->caps.max_cursor_size = 128;
        dc->caps.dual_link_dvi = true;
-
+       dc->caps.extended_aux_timeout_support = false;
 
        /*************************************************
         *  Create resources                             *
index 7c52f7f9196c9595d60064d0b05ecbe41a792dad..c30faa05fd27deee7aee51f629cc55f5e4199f32 100644 (file)
@@ -293,6 +293,14 @@ static const struct dce_stream_encoder_mask se_mask = {
                SE_COMMON_MASK_SH_LIST_DCE120(_MASK)
 };
 
+static const struct dce110_aux_registers_shift aux_shift = {
+       DCE12_AUX_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dce110_aux_registers_mask aux_mask = {
+       DCE12_AUX_MASK_SH_LIST(_MASK)
+};
+
 #define opp_regs(id)\
 [id] = {\
        OPP_DCE_120_REG_LIST(id),\
@@ -404,7 +412,10 @@ struct dce_aux *dce120_aux_engine_create(
 
        dce110_aux_engine_construct(aux_engine, ctx, inst,
                                    SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,
-                                   &aux_engine_regs[inst]);
+                                   &aux_engine_regs[inst],
+                                       &aux_mask,
+                                       &aux_shift,
+                                       ctx->dc->caps.extended_aux_timeout_support);
 
        return &aux_engine->base;
 }
@@ -1006,7 +1017,7 @@ static bool construct(
        dc->caps.max_cursor_size = 128;
        dc->caps.dual_link_dvi = true;
        dc->caps.psp_setup_panel_mode = true;
-
+       dc->caps.extended_aux_timeout_support = false;
        dc->debug = debug_defaults;
 
        /*************************************************
index 643ccb0ade006fac359c70aa74e323712771336f..59ebd657462d868536932fe058191e3dfb2c9e99 100644 (file)
@@ -288,6 +288,14 @@ static const struct dce_opp_mask opp_mask = {
        OPP_COMMON_MASK_SH_LIST_DCE_80(_MASK)
 };
 
+static const struct dce110_aux_registers_shift aux_shift = {
+       DCE10_AUX_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dce110_aux_registers_mask aux_mask = {
+       DCE10_AUX_MASK_SH_LIST(_MASK)
+};
+
 #define aux_engine_regs(id)\
 [id] = {\
        AUX_COMMON_REG_LIST(id), \
@@ -491,7 +499,10 @@ struct dce_aux *dce80_aux_engine_create(
 
        dce110_aux_engine_construct(aux_engine, ctx, inst,
                                    SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,
-                                   &aux_engine_regs[inst]);
+                                   &aux_engine_regs[inst],
+                                       &aux_mask,
+                                       &aux_shift,
+                                       ctx->dc->caps.extended_aux_timeout_support);
 
        return &aux_engine->base;
 }
@@ -895,6 +906,7 @@ static bool dce80_construct(
        dc->caps.i2c_speed_in_khz = 40;
        dc->caps.max_cursor_size = 128;
        dc->caps.dual_link_dvi = true;
+       dc->caps.extended_aux_timeout_support = false;
 
        /*************************************************
         *  Create resources                             *
index d8b2da18db396045f2e94db770b2845cef0977ff..997e9582edc7a5174dc7a52fbf5d955aaa3b2235 100644 (file)
@@ -129,7 +129,7 @@ void dpp_set_gamut_remap_bypass(struct dcn10_dpp *dpp)
 
 #define IDENTITY_RATIO(ratio) (dc_fixpt_u2d19(ratio) == (1 << 19))
 
-static bool dpp_get_optimal_number_of_taps(
+bool dpp1_get_optimal_number_of_taps(
                struct dpp *dpp,
                struct scaler_data *scl_data,
                const struct scaling_taps *in_taps)
@@ -521,7 +521,7 @@ static const struct dpp_funcs dcn10_dpp_funcs = {
                .dpp_read_state = dpp_read_state,
                .dpp_reset = dpp_reset,
                .dpp_set_scaler = dpp1_dscl_set_scaler_manual_scale,
-               .dpp_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps,
+               .dpp_get_optimal_number_of_taps = dpp1_get_optimal_number_of_taps,
                .dpp_set_gamut_remap = dpp1_cm_set_gamut_remap,
                .dpp_set_csc_adjustment = dpp1_cm_set_output_csc_adjustment,
                .dpp_set_csc_default = dpp1_cm_set_output_csc_default,
index e2c613611ac95583ce5023f028f78958518ffed2..1d4a7d640334020272f529f9228ac673c54229c3 100644 (file)
@@ -1504,6 +1504,11 @@ void dpp1_set_hdr_multiplier(
                struct dpp *dpp_base,
                uint32_t multiplier);
 
+bool dpp1_get_optimal_number_of_taps(
+               struct dpp *dpp,
+               struct scaler_data *scl_data,
+               const struct scaling_taps *in_taps);
+
 void dpp1_construct(struct dcn10_dpp *dpp1,
        struct dc_context *ctx,
        uint32_t inst,
index 001db49e4bb237deb6f9c7fc6cd807a62853b048..14d1be6c66e631d57583954189b3e74838b3764b 100644 (file)
@@ -841,6 +841,14 @@ void min_set_viewport(
        REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0,
                  PRI_VIEWPORT_X_START_C, viewport_c->x,
                  PRI_VIEWPORT_Y_START_C, viewport_c->y);
+
+       REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION_C, 0,
+                 SEC_VIEWPORT_WIDTH_C, viewport_c->width,
+                 SEC_VIEWPORT_HEIGHT_C, viewport_c->height);
+
+       REG_SET_2(DCSURF_SEC_VIEWPORT_START_C, 0,
+                 SEC_VIEWPORT_X_START_C, viewport_c->x,
+                 SEC_VIEWPORT_Y_START_C, viewport_c->y);
 }
 
 void hubp1_read_state_common(struct hubp *hubp)
index cb20d10288c0be8ce915b7684e490917e007e701..ae70d9c0aa1d467bc4514c3351ee38934119298b 100644 (file)
@@ -47,6 +47,8 @@
        SRI(DCSURF_SEC_VIEWPORT_START, HUBP, id), \
        SRI(DCSURF_PRI_VIEWPORT_DIMENSION_C, HUBP, id), \
        SRI(DCSURF_PRI_VIEWPORT_START_C, HUBP, id), \
+       SRI(DCSURF_SEC_VIEWPORT_DIMENSION_C, HUBP, id), \
+       SRI(DCSURF_SEC_VIEWPORT_START_C, HUBP, id), \
        SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\
        SRI(DCSURF_PRIMARY_SURFACE_ADDRESS, HUBPREQ, id),\
        SRI(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\
        SRI(DCSURF_SECONDARY_META_SURFACE_ADDRESS, HUBPREQ, id),\
        SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id),\
        SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_C, HUBPREQ, id),\
+       SRI(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id),\
+       SRI(DCSURF_SECONDARY_SURFACE_ADDRESS_C, HUBPREQ, id),\
        SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id),\
        SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, HUBPREQ, id),\
+       SRI(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id),\
+       SRI(DCSURF_SECONDARY_META_SURFACE_ADDRESS_C, HUBPREQ, id),\
        SRI(DCSURF_SURFACE_INUSE, HUBPREQ, id),\
        SRI(DCSURF_SURFACE_INUSE_HIGH, HUBPREQ, id),\
        SRI(DCSURF_SURFACE_INUSE_C, HUBPREQ, id),\
        uint32_t DCSURF_SEC_VIEWPORT_START; \
        uint32_t DCSURF_PRI_VIEWPORT_DIMENSION_C; \
        uint32_t DCSURF_PRI_VIEWPORT_START_C; \
+       uint32_t DCSURF_SEC_VIEWPORT_DIMENSION_C; \
+       uint32_t DCSURF_SEC_VIEWPORT_START_C; \
        uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH; \
        uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS; \
        uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH; \
        uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS; \
        uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C; \
        uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_C; \
+       uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH_C; \
+       uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS_C; \
        uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C; \
        uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_C; \
+       uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH_C; \
+       uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS_C; \
        uint32_t DCSURF_SURFACE_INUSE; \
        uint32_t DCSURF_SURFACE_INUSE_HIGH; \
        uint32_t DCSURF_SURFACE_INUSE_C; \
        HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_HEIGHT_C, mask_sh),\
        HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_X_START_C, mask_sh),\
        HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_Y_START_C, mask_sh),\
+       HUBP_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION_C, SEC_VIEWPORT_WIDTH_C, mask_sh),\
+       HUBP_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION_C, SEC_VIEWPORT_HEIGHT_C, mask_sh),\
+       HUBP_SF(HUBP0_DCSURF_SEC_VIEWPORT_START_C, SEC_VIEWPORT_X_START_C, mask_sh),\
+       HUBP_SF(HUBP0_DCSURF_SEC_VIEWPORT_START_C, SEC_VIEWPORT_Y_START_C, mask_sh),\
        HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\
        HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS, PRIMARY_SURFACE_ADDRESS, mask_sh),\
        HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, SECONDARY_SURFACE_ADDRESS_HIGH, mask_sh),\
        HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS, SECONDARY_META_SURFACE_ADDRESS, mask_sh),\
        HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, PRIMARY_SURFACE_ADDRESS_HIGH_C, mask_sh),\
        HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_C, PRIMARY_SURFACE_ADDRESS_C, mask_sh),\
+       HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH_C, SECONDARY_SURFACE_ADDRESS_HIGH_C, mask_sh),\
+       HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS_C, SECONDARY_SURFACE_ADDRESS_C, mask_sh),\
        HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, PRIMARY_META_SURFACE_ADDRESS_HIGH_C, mask_sh),\
        HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, PRIMARY_META_SURFACE_ADDRESS_C, mask_sh),\
+       HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH_C, SECONDARY_META_SURFACE_ADDRESS_HIGH_C, mask_sh),\
+       HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS_C, SECONDARY_META_SURFACE_ADDRESS_C, mask_sh),\
        HUBP_SF(HUBPREQ0_DCSURF_SURFACE_INUSE, SURFACE_INUSE_ADDRESS, mask_sh),\
        HUBP_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_HIGH, SURFACE_INUSE_ADDRESS_HIGH, mask_sh),\
        HUBP_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_C, SURFACE_INUSE_ADDRESS_C, mask_sh),\
        type PRI_VIEWPORT_HEIGHT_C; \
        type PRI_VIEWPORT_X_START_C; \
        type PRI_VIEWPORT_Y_START_C; \
+       type SEC_VIEWPORT_WIDTH_C; \
+       type SEC_VIEWPORT_HEIGHT_C; \
+       type SEC_VIEWPORT_X_START_C; \
+       type SEC_VIEWPORT_Y_START_C; \
        type PRIMARY_SURFACE_ADDRESS_HIGH;\
        type PRIMARY_SURFACE_ADDRESS;\
        type SECONDARY_SURFACE_ADDRESS_HIGH;\
        type SECONDARY_META_SURFACE_ADDRESS;\
        type PRIMARY_SURFACE_ADDRESS_HIGH_C;\
        type PRIMARY_SURFACE_ADDRESS_C;\
+       type SECONDARY_SURFACE_ADDRESS_HIGH_C;\
+       type SECONDARY_SURFACE_ADDRESS_C;\
        type PRIMARY_META_SURFACE_ADDRESS_HIGH_C;\
        type PRIMARY_META_SURFACE_ADDRESS_C;\
+       type SECONDARY_META_SURFACE_ADDRESS_HIGH_C;\
+       type SECONDARY_META_SURFACE_ADDRESS_C;\
        type SURFACE_INUSE_ADDRESS;\
        type SURFACE_INUSE_ADDRESS_HIGH;\
        type SURFACE_INUSE_ADDRESS_C;\
index 60123db7ba02ff2fc4fba0461023dc29c6e312bd..df1be8ada66de0742b30a9f2b97d4ebcb3480ef1 100644 (file)
@@ -670,6 +670,10 @@ static void dcn10_bios_golden_init(struct dc *dc)
        int i;
        bool allow_self_fresh_force_enable = true;
 
+#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
+       if (dc->hwss.s0i3_golden_init_wa && dc->hwss.s0i3_golden_init_wa(dc))
+               return;
+#endif
        if (dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled)
                allow_self_fresh_force_enable =
                                dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub);
@@ -1452,15 +1456,15 @@ static void log_tf(struct dc_context *ctx,
        DC_LOG_ALL_TF_CHANNELS("Logging all channels...");
 
        for (i = 0; i < hw_points_num; i++) {
-               DC_LOG_GAMMA("R\t%d\t%llu\n", i, tf->tf_pts.red[i].value);
-               DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu\n", i, tf->tf_pts.green[i].value);
-               DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu\n", i, tf->tf_pts.blue[i].value);
+               DC_LOG_GAMMA("R\t%d\t%llu", i, tf->tf_pts.red[i].value);
+               DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu", i, tf->tf_pts.green[i].value);
+               DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu", i, tf->tf_pts.blue[i].value);
        }
 
        for (i = hw_points_num; i < MAX_NUM_HW_POINTS; i++) {
-               DC_LOG_ALL_GAMMA("R\t%d\t%llu\n", i, tf->tf_pts.red[i].value);
-               DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu\n", i, tf->tf_pts.green[i].value);
-               DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu\n", i, tf->tf_pts.blue[i].value);
+               DC_LOG_ALL_GAMMA("R\t%d\t%llu", i, tf->tf_pts.red[i].value);
+               DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu", i, tf->tf_pts.green[i].value);
+               DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu", i, tf->tf_pts.blue[i].value);
        }
 }
 
@@ -2304,8 +2308,7 @@ void update_dchubp_dpp(
                        dc->res_pool->dccg->funcs->update_dpp_dto(
                                        dc->res_pool->dccg,
                                        dpp->inst,
-                                       pipe_ctx->plane_res.bw.dppclk_khz,
-                                       false);
+                                       pipe_ctx->plane_res.bw.dppclk_khz);
                else
                        dc->clk_mgr->clks.dppclk_khz = should_divided_by_2 ?
                                                dc->clk_mgr->clks.dispclk_khz / 2 :
@@ -2512,8 +2515,10 @@ static void program_all_pipe_in_tree(
                pipe_ctx->stream_res.tg->funcs->set_vtg_params(
                                pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
 
-               dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
+               if (dc->hwss.setup_vupdate_interrupt)
+                       dc->hwss.setup_vupdate_interrupt(pipe_ctx);
 
+               dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
        }
 
        if (pipe_ctx->plane_state != NULL)
index 8bf5f0f2301d2a7f579e70ebab60d4526e5dfe90..88fcc395adf52475672479147d6a1075e84db052 100644 (file)
@@ -113,6 +113,20 @@ struct dcn10_link_enc_registers {
        uint32_t DIG_LANE_ENABLE;
        /* UNIPHY */
        uint32_t CHANNEL_XBAR_CNTL;
+       /* DPCS */
+       uint32_t RDPCSTX_PHY_CNTL3;
+       uint32_t RDPCSTX_PHY_CNTL4;
+       uint32_t RDPCSTX_PHY_CNTL5;
+       uint32_t RDPCSTX_PHY_CNTL6;
+       uint32_t RDPCSTX_PHY_CNTL7;
+       uint32_t RDPCSTX_PHY_CNTL8;
+       uint32_t RDPCSTX_PHY_CNTL9;
+       uint32_t RDPCSTX_PHY_CNTL10;
+       uint32_t RDPCSTX_PHY_CNTL11;
+       uint32_t RDPCSTX_PHY_CNTL12;
+       uint32_t RDPCSTX_PHY_CNTL13;
+       uint32_t RDPCSTX_PHY_CNTL14;
+       uint32_t RDPCSTX_PHY_CNTL15;
        /* indirect registers */
        uint32_t RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_2;
        uint32_t RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_3;
@@ -250,6 +264,10 @@ struct dcn10_link_enc_registers {
                type RDPCS_EXT_REFCLK_EN;\
                type RDPCS_TX_FIFO_EN;\
                type UNIPHY_LINK_ENABLE;\
+               type UNIPHY_CHANNEL0_XBAR_SOURCE;\
+               type UNIPHY_CHANNEL1_XBAR_SOURCE;\
+               type UNIPHY_CHANNEL2_XBAR_SOURCE;\
+               type UNIPHY_CHANNEL3_XBAR_SOURCE;\
                type UNIPHY_CHANNEL0_INVERT;\
                type UNIPHY_CHANNEL1_INVERT;\
                type UNIPHY_CHANNEL2_INVERT;\
@@ -337,16 +355,46 @@ struct dcn10_link_enc_registers {
                type RDPCS_TX_FIFO_ERROR_MASK;\
                type RDPCS_DPALT_DISABLE_TOGGLE_MASK;\
                type RDPCS_DPALT_4LANE_TOGGLE_MASK;\
+               type RDPCS_PHY_DPALT_DP4;\
                type RDPCS_PHY_DPALT_DISABLE;\
                type RDPCS_PHY_DPALT_DISABLE_ACK;\
                type RDPCS_PHY_DP_MPLLB_V2I;\
                type RDPCS_PHY_DP_MPLLB_FREQ_VCO;\
+               type RDPCS_PHY_DP_MPLLB_CP_INT_GS;\
+               type RDPCS_PHY_RX_VREF_CTRL;\
                type RDPCS_PHY_DP_MPLLB_CP_INT;\
                type RDPCS_PHY_DP_MPLLB_CP_PROP;\
                type RDPCS_PHY_RX_REF_LD_VAL;\
                type RDPCS_PHY_RX_VCO_LD_VAL;\
                type DPCSTX_DEBUG_CONFIG; \
-               type RDPCSTX_DEBUG_CONFIG
+               type RDPCSTX_DEBUG_CONFIG; \
+               type RDPCS_PHY_DP_TX0_EQ_MAIN;\
+               type RDPCS_PHY_DP_TX0_EQ_PRE;\
+               type RDPCS_PHY_DP_TX0_EQ_POST;\
+               type RDPCS_PHY_DP_TX1_EQ_MAIN;\
+               type RDPCS_PHY_DP_TX1_EQ_PRE;\
+               type RDPCS_PHY_DP_TX1_EQ_POST;\
+               type RDPCS_PHY_DP_TX2_EQ_MAIN;\
+               type RDPCS_PHY_DP_MPLLB_CP_PROP_GS;\
+               type RDPCS_PHY_DP_TX2_EQ_PRE;\
+               type RDPCS_PHY_DP_TX2_EQ_POST;\
+               type RDPCS_PHY_DP_TX3_EQ_MAIN;\
+               type RDPCS_PHY_DCO_RANGE;\
+               type RDPCS_PHY_DCO_FINETUNE;\
+               type RDPCS_PHY_DP_TX3_EQ_PRE;\
+               type RDPCS_PHY_DP_TX3_EQ_POST;\
+               type RDPCS_PHY_SUP_PRE_HP;\
+               type RDPCS_PHY_DP_TX0_VREGDRV_BYP;\
+               type RDPCS_PHY_DP_TX1_VREGDRV_BYP;\
+               type RDPCS_PHY_DP_TX2_VREGDRV_BYP;\
+               type RDPCS_PHY_DP_TX3_VREGDRV_BYP;\
+               type RDPCS_DMCU_DPALT_DIS_BLOCK_REG;\
+               type UNIPHYA_SOFT_RESET;\
+               type UNIPHYB_SOFT_RESET;\
+               type UNIPHYC_SOFT_RESET;\
+               type UNIPHYD_SOFT_RESET;\
+               type UNIPHYE_SOFT_RESET;\
+               type UNIPHYF_SOFT_RESET
 
 #define DCN20_LINK_ENCODER_REG_FIELD_LIST(type) \
        type DIG_LANE0EN;\
index e9ebbbe256b455c81944e42cebabc8eda1dfd110..0a9ad692f541af3c821abdb5cb9c92d74c518832 100644 (file)
@@ -168,7 +168,10 @@ static void opp1_set_pixel_encoding(
                REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 0);
                break;
        case PIXEL_ENCODING_YCBCR422:
-               REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 1);
+               REG_UPDATE_3(FMT_CONTROL,
+                               FMT_PIXEL_ENCODING, 1,
+                               FMT_SUBSAMPLING_MODE, 2,
+                               FMT_CBCR_BIT_REDUCTION_BYPASS, 0);
                break;
        case PIXEL_ENCODING_YCBCR420:
                REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 2);
@@ -237,6 +240,9 @@ void opp1_set_dyn_expansion(
                        FMT_DYNAMIC_EXP_EN, 0,
                        FMT_DYNAMIC_EXP_MODE, 0);
 
+       if (opp->dyn_expansion == DYN_EXPANSION_DISABLE)
+               return;
+
        /*00 - 10-bit -> 12-bit dynamic expansion*/
        /*01 - 8-bit  -> 12-bit dynamic expansion*/
        if (signal == SIGNAL_TYPE_HDMI_TYPE_A ||
index 0f10adea000cc29f844abe4767c1b7f59099086a..2c0ecfa5a643affe7f190de7adb1fe0dc865b22f 100644 (file)
        type FMT_RAND_G_SEED; \
        type FMT_RAND_B_SEED; \
        type FMT_PIXEL_ENCODING; \
+       type FMT_SUBSAMPLING_MODE; \
+       type FMT_CBCR_BIT_REDUCTION_BYPASS; \
        type FMT_CLAMP_DATA_EN; \
        type FMT_CLAMP_COLOR_FORMAT; \
        type FMT_DYNAMIC_EXP_EN; \
index e74a07d03fde913e5aa8d9b5b475f6033f5e7f4a..dabccbd49ad4aa53239075c7f2ec5a33365b51cd 100644 (file)
@@ -1230,59 +1230,25 @@ bool optc1_is_stereo_left_eye(struct timing_generator *optc)
        return ret;
 }
 
-bool optc1_is_matching_timing(struct timing_generator *tg,
-               const struct dc_crtc_timing *otg_timing)
+bool optc1_get_hw_timing(struct timing_generator *tg,
+               struct dc_crtc_timing *hw_crtc_timing)
 {
-       struct dc_crtc_timing hw_crtc_timing = {0};
        struct dcn_otg_state s = {0};
 
-       if (tg == NULL || otg_timing == NULL)
+       if (tg == NULL || hw_crtc_timing == NULL)
                return false;
 
        optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s);
 
-       hw_crtc_timing.h_total = s.h_total + 1;
-       hw_crtc_timing.h_addressable = s.h_total - ((s.h_total - s.h_blank_start) + s.h_blank_end);
-       hw_crtc_timing.h_front_porch = s.h_total + 1 - s.h_blank_start;
-       hw_crtc_timing.h_sync_width = s.h_sync_a_end - s.h_sync_a_start;
+       hw_crtc_timing->h_total = s.h_total + 1;
+       hw_crtc_timing->h_addressable = s.h_total - ((s.h_total - s.h_blank_start) + s.h_blank_end);
+       hw_crtc_timing->h_front_porch = s.h_total + 1 - s.h_blank_start;
+       hw_crtc_timing->h_sync_width = s.h_sync_a_end - s.h_sync_a_start;
 
-       hw_crtc_timing.v_total = s.v_total + 1;
-       hw_crtc_timing.v_addressable = s.v_total - ((s.v_total - s.v_blank_start) + s.v_blank_end);
-       hw_crtc_timing.v_front_porch = s.v_total + 1 - s.v_blank_start;
-       hw_crtc_timing.v_sync_width = s.v_sync_a_end - s.v_sync_a_start;
-
-       if (otg_timing->h_total != hw_crtc_timing.h_total)
-               return false;
-
-       if (otg_timing->h_border_left != hw_crtc_timing.h_border_left)
-               return false;
-
-       if (otg_timing->h_addressable != hw_crtc_timing.h_addressable)
-               return false;
-
-       if (otg_timing->h_border_right != hw_crtc_timing.h_border_right)
-               return false;
-
-       if (otg_timing->h_front_porch != hw_crtc_timing.h_front_porch)
-               return false;
-
-       if (otg_timing->h_sync_width != hw_crtc_timing.h_sync_width)
-               return false;
-
-       if (otg_timing->v_total != hw_crtc_timing.v_total)
-               return false;
-
-       if (otg_timing->v_border_top != hw_crtc_timing.v_border_top)
-               return false;
-
-       if (otg_timing->v_addressable != hw_crtc_timing.v_addressable)
-               return false;
-
-       if (otg_timing->v_border_bottom != hw_crtc_timing.v_border_bottom)
-               return false;
-
-       if (otg_timing->v_sync_width != hw_crtc_timing.v_sync_width)
-               return false;
+       hw_crtc_timing->v_total = s.v_total + 1;
+       hw_crtc_timing->v_addressable = s.v_total - ((s.v_total - s.v_blank_start) + s.v_blank_end);
+       hw_crtc_timing->v_front_porch = s.v_total + 1 - s.v_blank_start;
+       hw_crtc_timing->v_sync_width = s.v_sync_a_end - s.v_sync_a_start;
 
        return true;
 }
@@ -1486,7 +1452,6 @@ static const struct timing_generator_funcs dcn10_tg_funcs = {
                .get_frame_count = optc1_get_vblank_counter,
                .get_scanoutpos = optc1_get_crtc_scanoutpos,
                .get_otg_active_size = optc1_get_otg_active_size,
-               .is_matching_timing = optc1_is_matching_timing,
                .set_early_control = optc1_set_early_control,
                /* used by enable_timing_synchronization. Not need for FPGA */
                .wait_for_state = optc1_wait_for_state,
@@ -1514,7 +1479,8 @@ static const struct timing_generator_funcs dcn10_tg_funcs = {
                .configure_crc = optc1_configure_crc,
                .set_vtg_params = optc1_set_vtg_params,
                .program_manual_trigger = optc1_program_manual_trigger,
-               .setup_manual_trigger = optc1_setup_manual_trigger
+               .setup_manual_trigger = optc1_setup_manual_trigger,
+               .get_hw_timing = optc1_get_hw_timing,
 };
 
 void dcn10_timing_generator_init(struct optc *optc1)
index 83575599672e8b67c346a1c273c7e6dca88d6e01..c8d795b335baff92c3add378e1ead404dcea0cb4 100644 (file)
@@ -547,9 +547,8 @@ struct dcn_otg_state {
 void optc1_read_otg_state(struct optc *optc1,
                struct dcn_otg_state *s);
 
-bool optc1_is_matching_timing(
-       struct timing_generator *tg,
-       const struct dc_crtc_timing *otg_timing);
+bool optc1_get_hw_timing(struct timing_generator *tg,
+               struct dc_crtc_timing *hw_crtc_timing);
 
 bool optc1_validate_timing(
        struct timing_generator *optc,
index 1599bb97111114dc2eec402f7fdb99e377799830..e3b279ff0d2167851d94df49a37e4f25922458fd 100644 (file)
@@ -319,6 +319,14 @@ static const struct dcn10_link_enc_mask le_mask = {
                LINK_ENCODER_MASK_SH_LIST_DCN10(_MASK)
 };
 
+static const struct dce110_aux_registers_shift aux_shift = {
+       DCN10_AUX_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dce110_aux_registers_mask aux_mask = {
+       DCN10_AUX_MASK_SH_LIST(_MASK)
+};
+
 #define ipp_regs(id)\
 [id] = {\
        IPP_REG_LIST_DCN10(id),\
@@ -642,7 +650,10 @@ struct dce_aux *dcn10_aux_engine_create(
 
        dce110_aux_engine_construct(aux_engine, ctx, inst,
                                    SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,
-                                   &aux_engine_regs[inst]);
+                                   &aux_engine_regs[inst],
+                                       &aux_mask,
+                                       &aux_shift,
+                                       ctx->dc->caps.extended_aux_timeout_support);
 
        return &aux_engine->base;
 }
@@ -1308,6 +1319,8 @@ static bool construct(
        dc->caps.max_slave_planes = 1;
        dc->caps.is_apu = true;
        dc->caps.post_blend_color_processing = false;
+       dc->caps.extended_aux_timeout_support = false;
+
        /* Raven DP PHY HBR2 eye diagram pattern is not stable. Use TP4 */
        dc->caps.force_dp_tps4_for_cp2520 = true;
 
index 9aa258f3550b6edc0ae7f796d93c76e2af76e9da..06e5bbb4545cd5512baa310c12dcc42bc2d4b80e 100644 (file)
@@ -1553,6 +1553,66 @@ unsigned int enc1_dig_source_otg(
        return tg_inst;
 }
 
+bool enc1_stream_encoder_dp_get_pixel_format(
+       struct stream_encoder *enc,
+       enum dc_pixel_encoding *encoding,
+       enum dc_color_depth *depth)
+{
+       uint32_t hw_encoding = 0;
+       uint32_t hw_depth = 0;
+       struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+       if (enc == NULL ||
+               encoding == NULL ||
+               depth == NULL)
+               return false;
+
+       REG_GET_2(DP_PIXEL_FORMAT,
+               DP_PIXEL_ENCODING, &hw_encoding,
+               DP_COMPONENT_DEPTH, &hw_depth);
+
+       switch (hw_depth) {
+       case DP_COMPONENT_PIXEL_DEPTH_6BPC:
+               *depth = COLOR_DEPTH_666;
+               break;
+       case DP_COMPONENT_PIXEL_DEPTH_8BPC:
+               *depth = COLOR_DEPTH_888;
+               break;
+       case DP_COMPONENT_PIXEL_DEPTH_10BPC:
+               *depth = COLOR_DEPTH_101010;
+               break;
+       case DP_COMPONENT_PIXEL_DEPTH_12BPC:
+               *depth = COLOR_DEPTH_121212;
+               break;
+       case DP_COMPONENT_PIXEL_DEPTH_16BPC:
+               *depth = COLOR_DEPTH_161616;
+               break;
+       default:
+               *depth = COLOR_DEPTH_UNDEFINED;
+               break;
+       }
+
+       switch (hw_encoding) {
+       case DP_PIXEL_ENCODING_TYPE_RGB444:
+               *encoding = PIXEL_ENCODING_RGB;
+               break;
+       case DP_PIXEL_ENCODING_TYPE_YCBCR422:
+               *encoding = PIXEL_ENCODING_YCBCR422;
+               break;
+       case DP_PIXEL_ENCODING_TYPE_YCBCR444:
+       case DP_PIXEL_ENCODING_TYPE_Y_ONLY:
+               *encoding = PIXEL_ENCODING_YCBCR444;
+               break;
+       case DP_PIXEL_ENCODING_TYPE_YCBCR420:
+               *encoding = PIXEL_ENCODING_YCBCR420;
+               break;
+       default:
+               *encoding = PIXEL_ENCODING_UNDEFINED;
+               break;
+       }
+       return true;
+}
+
 static const struct stream_encoder_funcs dcn10_str_enc_funcs = {
        .dp_set_stream_attribute =
                enc1_stream_encoder_dp_set_stream_attribute,
@@ -1589,6 +1649,8 @@ static const struct stream_encoder_funcs dcn10_str_enc_funcs = {
        .dig_connect_to_otg  = enc1_dig_connect_to_otg,
        .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute,
        .dig_source_otg = enc1_dig_source_otg,
+
+       .dp_get_pixel_format  = enc1_stream_encoder_dp_get_pixel_format,
 };
 
 void dcn10_stream_encoder_construct(
index a512cbea00d17c2db49fb4d76bf24b9a908956c7..c9cbc21d121e8a519a4a813aa5809732f0d67867 100644 (file)
@@ -621,4 +621,9 @@ void get_audio_clock_info(
 void enc1_reset_hdmi_stream_attribute(
        struct stream_encoder *enc);
 
+bool enc1_stream_encoder_dp_get_pixel_format(
+       struct stream_encoder *enc,
+       enum dc_pixel_encoding *encoding,
+       enum dc_color_depth *depth);
+
 #endif /* __DC_STREAM_ENCODER_DCN10_H__ */
index 16476ed255363d88cfdb37aa1405c03140125bf3..1e1151356e6063089fffac01ed08fffe81c4cb02 100644 (file)
 #define DC_LOGGER \
        dccg->ctx->logger
 
-void dccg2_update_dpp_dto(struct dccg *dccg,
-               int dpp_inst,
-               int req_dppclk,
-               bool reduce_divider_only)
+void dccg2_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk)
 {
        struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
 
        if (dccg->ref_dppclk && req_dppclk) {
                int ref_dppclk = dccg->ref_dppclk;
-               int current_phase, current_modulo;
 
                ASSERT(req_dppclk <= ref_dppclk);
                /* need to clamp to 8 bits */
@@ -65,28 +61,9 @@ void dccg2_update_dpp_dto(struct dccg *dccg,
                        if (req_dppclk > ref_dppclk)
                                req_dppclk = ref_dppclk;
                }
-
-               REG_GET_2(DPPCLK_DTO_PARAM[dpp_inst],
-                               DPPCLK0_DTO_PHASE, &current_phase,
-                               DPPCLK0_DTO_MODULO, &current_modulo);
-
-               if (reduce_divider_only) {
-                       // requested phase/modulo greater than current
-                       if (req_dppclk * current_modulo >= current_phase * ref_dppclk) {
-                               REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
-                                               DPPCLK0_DTO_PHASE, req_dppclk,
-                                               DPPCLK0_DTO_MODULO, ref_dppclk);
-                       } else {
-                               REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
-                                               DPPCLK0_DTO_PHASE, current_phase,
-                                               DPPCLK0_DTO_MODULO, current_modulo);
-                       }
-               } else {
-                       REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
-                                       DPPCLK0_DTO_PHASE, req_dppclk,
-                                       DPPCLK0_DTO_MODULO, ref_dppclk);
-               }
-
+               REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
+                               DPPCLK0_DTO_PHASE, req_dppclk,
+                               DPPCLK0_DTO_MODULO, ref_dppclk);
                REG_UPDATE(DPPCLK_DTO_CTRL,
                                DPPCLK_DTO_ENABLE[dpp_inst], 1);
        } else {
@@ -119,32 +96,6 @@ void dccg2_get_dccg_ref_freq(struct dccg *dccg,
 
 void dccg2_init(struct dccg *dccg)
 {
-       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
-
-       // Fallthrough intentional to program all available dpp_dto's
-       switch (dccg_dcn->base.ctx->dc->res_pool->pipe_count) {
-       case 6:
-               REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[5], 1);
-               /* Fall through */
-       case 5:
-               REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[4], 1);
-               /* Fall through */
-       case 4:
-               REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[3], 1);
-               /* Fall through */
-       case 3:
-               REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[2], 1);
-               /* Fall through */
-       case 2:
-               REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[1], 1);
-               /* Fall through */
-       case 1:
-               REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[0], 1);
-               break;
-       default:
-               ASSERT(false);
-               break;
-       }
 }
 
 static const struct dccg_funcs dccg2_funcs = {
index 74a074a873cd4126ec6b26494e259fc512f32933..2205cb0204e7980960fc530bc0fe4d409683e5fd 100644 (file)
@@ -97,7 +97,7 @@ struct dcn_dccg {
        const struct dccg_mask *dccg_mask;
 };
 
-void dccg2_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk, bool raise_divider_only);
+void dccg2_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk);
 
 void dccg2_get_dccg_ref_freq(struct dccg *dccg,
                unsigned int xtalin_freq_inKhz,
index 2f5aade1e8829651a71c11193b90ecdbc7c14987..4d7e45892f087ac81db26a2aaff99de449201b99 100644 (file)
@@ -376,13 +376,6 @@ bool dpp2_get_optimal_number_of_taps(
                struct scaler_data *scl_data,
                const struct scaling_taps *in_taps)
 {
-       uint32_t pixel_width;
-
-       if (scl_data->viewport.width > scl_data->recout.width)
-               pixel_width = scl_data->recout.width;
-       else
-               pixel_width = scl_data->viewport.width;
-
        /* Some ASICs does not support  FP16 scaling, so we reject modes require this*/
        if (scl_data->viewport.width  != scl_data->h_active &&
                scl_data->viewport.height != scl_data->v_active &&
@@ -464,7 +457,7 @@ static struct dpp_funcs dcn20_dpp_funcs = {
        .dpp_read_state = dpp20_read_state,
        .dpp_reset = dpp_reset,
        .dpp_set_scaler = dpp1_dscl_set_scaler_manual_scale,
-       .dpp_get_optimal_number_of_taps = dpp2_get_optimal_number_of_taps,
+       .dpp_get_optimal_number_of_taps = dpp1_get_optimal_number_of_taps,
        .dpp_set_gamut_remap = dpp1_cm_set_gamut_remap,
        .dpp_set_csc_adjustment = NULL,
        .dpp_set_csc_default = NULL,
index 290b2854bd2cdf5698fb616a224ab82563dafe98..5b03b737b1d6104f2e95ea6e9780f6e940ce77dc 100644 (file)
 #define TO_DCN20_DPP(dpp)\
        container_of(dpp, struct dcn20_dpp, base)
 
-#define TF_REG_LIST_DCN20(id) \
-       TF_REG_LIST_DCN(id), \
+#define TF_REG_LIST_DCN20_COMMON_UPDATED(id) \
        SRI(CM_BLNDGAM_LUT_WRITE_EN_MASK, CM, id), \
+       SRI(CM_BLNDGAM_RAMB_SLOPE_CNTL_B, CM, id), \
+       SRI(CM_BLNDGAM_RAMB_SLOPE_CNTL_G, CM, id), \
+       SRI(CM_BLNDGAM_RAMB_SLOPE_CNTL_R, CM, id), \
+       SRI(CM_BLNDGAM_RAMA_SLOPE_CNTL_B, CM, id), \
+       SRI(CM_BLNDGAM_RAMA_SLOPE_CNTL_G, CM, id), \
+       SRI(CM_BLNDGAM_RAMA_SLOPE_CNTL_R, CM, id)
+
+#define TF_REG_LIST_DCN20_COMMON(id) \
        SRI(CM_BLNDGAM_CONTROL, CM, id), \
        SRI(CM_BLNDGAM_RAMB_START_CNTL_B, CM, id), \
        SRI(CM_BLNDGAM_RAMB_START_CNTL_G, CM, id), \
        SRI(CM_BLNDGAM_RAMB_START_CNTL_R, CM, id), \
-       SRI(CM_BLNDGAM_RAMB_SLOPE_CNTL_B, CM, id), \
-       SRI(CM_BLNDGAM_RAMB_SLOPE_CNTL_G, CM, id), \
-       SRI(CM_BLNDGAM_RAMB_SLOPE_CNTL_R, CM, id), \
        SRI(CM_BLNDGAM_RAMB_END_CNTL1_B, CM, id), \
        SRI(CM_BLNDGAM_RAMB_END_CNTL2_B, CM, id), \
        SRI(CM_BLNDGAM_RAMB_END_CNTL1_G, CM, id), \
@@ -66,9 +70,6 @@
        SRI(CM_BLNDGAM_RAMA_START_CNTL_B, CM, id), \
        SRI(CM_BLNDGAM_RAMA_START_CNTL_G, CM, id), \
        SRI(CM_BLNDGAM_RAMA_START_CNTL_R, CM, id), \
-       SRI(CM_BLNDGAM_RAMA_SLOPE_CNTL_B, CM, id), \
-       SRI(CM_BLNDGAM_RAMA_SLOPE_CNTL_G, CM, id), \
-       SRI(CM_BLNDGAM_RAMA_SLOPE_CNTL_R, CM, id), \
        SRI(CM_BLNDGAM_RAMA_END_CNTL1_B, CM, id), \
        SRI(CM_BLNDGAM_RAMA_END_CNTL2_B, CM, id), \
        SRI(CM_BLNDGAM_RAMA_END_CNTL1_G, CM, id), \
        SRI(CM_SHAPER_RAMA_REGION_28_29, CM, id), \
        SRI(CM_SHAPER_RAMA_REGION_30_31, CM, id), \
        SRI(CM_SHAPER_RAMA_REGION_32_33, CM, id), \
-       SRI(CM_SHAPER_LUT_INDEX, CM, id), \
+       SRI(CM_SHAPER_LUT_INDEX, CM, id)
+
+#define TF_REG_LIST_DCN20(id) \
+       TF_REG_LIST_DCN(id), \
+       TF_REG_LIST_DCN20_COMMON(id), \
+       TF_REG_LIST_DCN20_COMMON_UPDATED(id), \
        SRI(CURSOR_CONTROL, CURSOR0_, id), \
        SRI(ALPHA_2BIT_LUT, CNVC_CFG, id), \
        SRI(FCNV_FP_BIAS_R, CNVC_CFG, id), \
        SRI(OBUF_MEM_PWR_CTRL, DSCL, id),\
        SRI(DSCL_MEM_PWR_CTRL, DSCL, id)
 
-#define TF_REG_LIST_SH_MASK_DCN20(mask_sh)\
-       TF_REG_LIST_SH_MASK_DCN(mask_sh), \
+
+#define TF_REG_LIST_SH_MASK_DCN20_UPDATED(mask_sh)\
+       TF_SF(CM0_CM_BLNDGAM_RAMB_SLOPE_CNTL_B, CM_BLNDGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \
+       TF_SF(CM0_CM_BLNDGAM_RAMB_SLOPE_CNTL_G, CM_BLNDGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \
+       TF_SF(CM0_CM_BLNDGAM_RAMB_SLOPE_CNTL_R, CM_BLNDGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \
+       TF_SF(CM0_CM_BLNDGAM_RAMB_END_CNTL1_B, CM_BLNDGAM_RAMB_EXP_REGION_END_B, mask_sh), \
+       TF_SF(CM0_CM_BLNDGAM_RAMB_END_CNTL1_G, CM_BLNDGAM_RAMB_EXP_REGION_END_G, mask_sh), \
+       TF_SF(CM0_CM_BLNDGAM_RAMB_END_CNTL1_R, CM_BLNDGAM_RAMB_EXP_REGION_END_R, mask_sh), \
+       TF_SF(CM0_CM_BLNDGAM_RAMA_SLOPE_CNTL_B, CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \
+       TF_SF(CM0_CM_BLNDGAM_RAMA_SLOPE_CNTL_G, CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \
+       TF_SF(CM0_CM_BLNDGAM_RAMA_SLOPE_CNTL_R, CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \
+       TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL1_B, CM_BLNDGAM_RAMA_EXP_REGION_END_B, mask_sh), \
+       TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL1_G, CM_BLNDGAM_RAMA_EXP_REGION_END_G, mask_sh), \
+       TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL1_R, CM_BLNDGAM_RAMA_EXP_REGION_END_R, mask_sh), \
+       TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL2_B, CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh), \
+       TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL2_G, CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_G, mask_sh), \
+       TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL2_R, CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_R, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_CONTROL, CM_BLNDGAM_LUT_MODE, mask_sh), \
+       TF_SF(CM0_CM_BLNDGAM_LUT_WRITE_EN_MASK, CM_BLNDGAM_LUT_WRITE_EN_MASK, mask_sh), \
+       TF_SF(CM0_CM_BLNDGAM_LUT_WRITE_EN_MASK, CM_BLNDGAM_LUT_WRITE_SEL, mask_sh), \
+       TF_SF(CM0_CM_BLNDGAM_LUT_WRITE_EN_MASK, CM_BLNDGAM_CONFIG_STATUS, mask_sh), \
+       TF_SF(CM0_CM_SHAPER_CONTROL, CM_SHAPER_LUT_MODE, mask_sh)
+
+
+#define TF_REG_LIST_SH_MASK_DCN20_COMMON(mask_sh)\
+       TF_SF(CM0_CM_3DLUT_MODE, CM_3DLUT_MODE, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMB_START_CNTL_B, CM_BLNDGAM_RAMB_EXP_REGION_START_B, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMB_START_CNTL_B, CM_BLNDGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMB_START_CNTL_G, CM_BLNDGAM_RAMB_EXP_REGION_START_G, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMB_START_CNTL_G, CM_BLNDGAM_RAMB_EXP_REGION_START_SEGMENT_G, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMB_START_CNTL_R, CM_BLNDGAM_RAMB_EXP_REGION_START_R, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMB_START_CNTL_R, CM_BLNDGAM_RAMB_EXP_REGION_START_SEGMENT_R, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMB_SLOPE_CNTL_B, CM_BLNDGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMB_SLOPE_CNTL_G, CM_BLNDGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMB_SLOPE_CNTL_R, CM_BLNDGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMB_END_CNTL1_B, CM_BLNDGAM_RAMB_EXP_REGION_END_B, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMB_END_CNTL2_B, CM_BLNDGAM_RAMB_EXP_REGION_END_SLOPE_B, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMB_END_CNTL2_B, CM_BLNDGAM_RAMB_EXP_REGION_END_BASE_B, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMB_END_CNTL1_G, CM_BLNDGAM_RAMB_EXP_REGION_END_G, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMB_END_CNTL2_G, CM_BLNDGAM_RAMB_EXP_REGION_END_SLOPE_G, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMB_END_CNTL2_G, CM_BLNDGAM_RAMB_EXP_REGION_END_BASE_G, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMB_END_CNTL1_R, CM_BLNDGAM_RAMB_EXP_REGION_END_R, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMB_END_CNTL2_R, CM_BLNDGAM_RAMB_EXP_REGION_END_SLOPE_R, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMB_END_CNTL2_R, CM_BLNDGAM_RAMB_EXP_REGION_END_BASE_R, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMB_REGION_0_1, CM_BLNDGAM_RAMB_EXP_REGION0_LUT_OFFSET, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMB_REGION_0_1, CM_BLNDGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMB_REGION_0_1, CM_BLNDGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMA_START_CNTL_G, CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_G, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMA_START_CNTL_R, CM_BLNDGAM_RAMA_EXP_REGION_START_R, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMA_START_CNTL_R, CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_R, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMA_SLOPE_CNTL_B, CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMA_SLOPE_CNTL_G, CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMA_SLOPE_CNTL_R, CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL1_B, CM_BLNDGAM_RAMA_EXP_REGION_END_B, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL2_B, CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL2_B, CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL1_G, CM_BLNDGAM_RAMA_EXP_REGION_END_G, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL2_G, CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_G, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL2_G, CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_G, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL1_R, CM_BLNDGAM_RAMA_EXP_REGION_END_R, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL2_R, CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_R, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL2_R, CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_R, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMA_REGION_0_1, CM_BLNDGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMA_REGION_0_1, CM_BLNDGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMA_REGION_0_1, CM_BLNDGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMA_REGION_32_33, CM_BLNDGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMA_REGION_32_33, CM_BLNDGAM_RAMA_EXP_REGION33_LUT_OFFSET, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_RAMA_REGION_32_33, CM_BLNDGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_LUT_WRITE_EN_MASK, CM_BLNDGAM_LUT_WRITE_EN_MASK, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_LUT_WRITE_EN_MASK, CM_BLNDGAM_LUT_WRITE_SEL, mask_sh), \
-       TF_SF(CM0_CM_BLNDGAM_LUT_WRITE_EN_MASK, CM_BLNDGAM_CONFIG_STATUS, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_LUT_INDEX, CM_BLNDGAM_LUT_INDEX, mask_sh), \
        TF_SF(CM0_CM_BLNDGAM_LUT_DATA, CM_BLNDGAM_LUT_DATA, mask_sh), \
        TF_SF(CM0_CM_MEM_PWR_CTRL, BLNDGAM_MEM_PWR_FORCE, mask_sh), \
        TF_SF(CM0_CM_3DLUT_READ_WRITE_CONTROL, CM_3DLUT_WRITE_EN_MASK, mask_sh), \
        TF_SF(CM0_CM_3DLUT_READ_WRITE_CONTROL, CM_3DLUT_RAM_SEL, mask_sh), \
        TF_SF(CM0_CM_3DLUT_READ_WRITE_CONTROL, CM_3DLUT_30BIT_EN, mask_sh), \
-       TF_SF(CM0_CM_3DLUT_READ_WRITE_CONTROL, CM_3DLUT_CONFIG_STATUS, mask_sh), \
        TF_SF(CM0_CM_3DLUT_READ_WRITE_CONTROL, CM_3DLUT_READ_SEL, mask_sh), \
        TF_SF(CM0_CM_SHAPER_CONTROL, CM_SHAPER_LUT_MODE, mask_sh), \
        TF_SF(CM0_CM_SHAPER_RAMB_START_CNTL_B, CM_SHAPER_RAMB_EXP_REGION_START_B, mask_sh), \
        TF_SF(CM0_CM_SHAPER_RAMA_REGION_32_33, CM_SHAPER_RAMA_EXP_REGION33_NUM_SEGMENTS, mask_sh), \
        TF_SF(CM0_CM_SHAPER_LUT_WRITE_EN_MASK, CM_SHAPER_LUT_WRITE_EN_MASK, mask_sh), \
        TF_SF(CM0_CM_SHAPER_LUT_WRITE_EN_MASK, CM_SHAPER_LUT_WRITE_SEL, mask_sh), \
-       TF_SF(CM0_CM_SHAPER_LUT_WRITE_EN_MASK, CM_SHAPER_CONFIG_STATUS, mask_sh), \
        TF_SF(CM0_CM_SHAPER_LUT_INDEX, CM_SHAPER_LUT_INDEX, mask_sh), \
-       TF_SF(CM0_CM_SHAPER_LUT_DATA, CM_SHAPER_LUT_DATA, mask_sh), \
+       TF_SF(CM0_CM_SHAPER_LUT_DATA, CM_SHAPER_LUT_DATA, mask_sh)
+
+
+#define TF_REG_LIST_SH_MASK_DCN20(mask_sh)\
+       TF_REG_LIST_SH_MASK_DCN(mask_sh), \
+       TF_REG_LIST_SH_MASK_DCN20_COMMON(mask_sh), \
+       TF_REG_LIST_SH_MASK_DCN20_UPDATED(mask_sh), \
        TF_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_CONFIG_STATUS, mask_sh), \
        TF_SF(CM0_CM_CONTROL, CM_BYPASS, mask_sh), \
        TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \
        TF_SF(DSCL0_OBUF_MEM_PWR_CTRL, OBUF_MEM_PWR_FORCE, mask_sh),\
        TF_SF(DSCL0_DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, mask_sh)
 
+
 #define TF_REG_FIELD_LIST_DCN2_0(type) \
        TF_REG_FIELD_LIST(type) \
        type CM_BLNDGAM_LUT_DATA; \
        type OBUF_MEM_PWR_FORCE;\
        type LUT_MEM_PWR_FORCE
 
+
 struct dcn2_dpp_shift {
        TF_REG_FIELD_LIST_DCN2_0(uint8_t);
 };
@@ -691,11 +705,6 @@ void dpp2_set_hdr_multiplier(
                struct dpp *dpp_base,
                uint32_t multiplier);
 
-bool dpp2_get_optimal_number_of_taps(
-               struct dpp *dpp,
-               struct scaler_data *scl_data,
-               const struct scaling_taps *in_taps);
-
 bool dpp2_construct(struct dcn20_dpp *dpp2,
        struct dc_context *ctx,
        uint32_t inst,
index 1b419407af942b57aa9e0f2b0b05f2b3597a86db..63eb377ed9c03fcc9e0dfbafd09977394147f65a 100644 (file)
@@ -118,7 +118,7 @@ static void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock
 
        dsc_enc_caps->color_formats.bits.RGB = 1;
        dsc_enc_caps->color_formats.bits.YCBCR_444 = 1;
-       dsc_enc_caps->color_formats.bits.YCBCR_SIMPLE_422 = 0;
+       dsc_enc_caps->color_formats.bits.YCBCR_SIMPLE_422 = 1;
        dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_422 = 0;
        dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_420 = 1;
 
index cd8bc92ce3ba9e4b88fee7f28a28c5c6c8eac778..880954ac0b02748e58e2b3548adf0d880f74f22c 100644 (file)
@@ -722,7 +722,6 @@ bool dwb_program_horz_scalar(struct dcn20_dwbc *dwbc20,
                struct scaling_taps num_taps)
 {
        uint32_t h_ratio_luma = 1;
-       uint32_t h_ratio_chroma = 1;
        uint32_t h_taps_luma = num_taps.h_taps;
        uint32_t h_taps_chroma = num_taps.h_taps_c;
        int32_t h_init_phase_luma = 0;
@@ -747,7 +746,6 @@ bool dwb_program_horz_scalar(struct dcn20_dwbc *dwbc20,
                h_ratio_luma = -1;
        else
                h_ratio_luma = dc_fixpt_u3d19(tmp_h_ratio_luma) << 5;
-       h_ratio_chroma = h_ratio_luma * 2;
 
        /*Program ratio*/
        REG_UPDATE(WBSCL_HORZ_FILTER_SCALE_RATIO, WBSCL_H_SCALE_RATIO, h_ratio_luma);
@@ -803,7 +801,6 @@ bool dwb_program_vert_scalar(struct dcn20_dwbc *dwbc20,
                enum dwb_subsample_position subsample_position)
 {
        uint32_t v_ratio_luma = 1;
-       uint32_t v_ratio_chroma = 1;
        uint32_t v_taps_luma = num_taps.v_taps;
        uint32_t v_taps_chroma = num_taps.v_taps_c;
        int32_t v_init_phase_luma = 0;
@@ -827,7 +824,6 @@ bool dwb_program_vert_scalar(struct dcn20_dwbc *dwbc20,
                v_ratio_luma = -1;
        else
                v_ratio_luma = dc_fixpt_u3d19(tmp_v_ratio_luma) << 5;
-       v_ratio_chroma = v_ratio_luma * 2;
 
        /*Program ratio*/
        REG_UPDATE(WBSCL_VERT_FILTER_SCALE_RATIO, WBSCL_V_SCALE_RATIO, v_ratio_luma);
index b83c022e2c6f80c5d7d06cc3b80208083b199290..8b84385661019e3212b8c0b272938462ccfac719 100644 (file)
@@ -186,14 +186,13 @@ static void hubbub2_get_blk256_size(unsigned int *blk256_width, unsigned int *bl
 }
 
 static void hubbub2_det_request_size(
+               unsigned int detile_buf_size,
                unsigned int height,
                unsigned int width,
                unsigned int bpe,
                bool *req128_horz_wc,
                bool *req128_vert_wc)
 {
-       unsigned int detile_buf_size = 164 * 1024;  /* 164KB for DCN1.0 */
-
        unsigned int blk256_height = 0;
        unsigned int blk256_width = 0;
        unsigned int swath_bytes_horz_wc, swath_bytes_vert_wc;
@@ -236,7 +235,8 @@ bool hubbub2_get_dcc_compression_cap(struct hubbub *hubbub,
                        &segment_order_horz, &segment_order_vert))
                return false;
 
-       hubbub2_det_request_size(input->surface_size.height,  input->surface_size.width,
+       hubbub2_det_request_size(TO_DCN20_HUBBUB(hubbub)->detile_buf_size,
+                       input->surface_size.height,  input->surface_size.width,
                        bpe, &req128_horz_wc, &req128_vert_wc);
 
        if (!req128_horz_wc && !req128_vert_wc) {
@@ -588,7 +588,7 @@ static void hubbub2_program_watermarks(
                        DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
        REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 180);
 
-       hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
+       hubbub->funcs->allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
 }
 
 static const struct hubbub_funcs hubbub2_funcs = {
@@ -600,7 +600,8 @@ static const struct hubbub_funcs hubbub2_funcs = {
        .get_dcc_compression_cap = hubbub2_get_dcc_compression_cap,
        .wm_read_state = hubbub2_wm_read_state,
        .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,
-       .program_watermarks = hubbub2_program_watermarks
+       .program_watermarks = hubbub2_program_watermarks,
+       .allow_self_refresh_control = hubbub1_allow_self_refresh_control
 };
 
 void hubbub2_construct(struct dcn20_hubbub *hubbub,
@@ -618,4 +619,5 @@ void hubbub2_construct(struct dcn20_hubbub *hubbub,
        hubbub->masks = hubbub_mask;
 
        hubbub->debug_test_index_pstate = 0xB;
+       hubbub->detile_buf_size = 164 * 1024; /* 164KB for DCN2.0 */
 }
index 626117d3b4e97a0fe52657de2ae3f68cac64c3b5..501532dd523ade2ee033e3e01c23a15b36e74502 100644 (file)
@@ -81,6 +81,7 @@ struct dcn20_hubbub {
        unsigned int debug_test_index_pstate;
        struct dcn_watermark_set watermarks;
        struct dcn20_vmid vmid[16];
+       unsigned int detile_buf_size;
 };
 
 void hubbub2_construct(struct dcn20_hubbub *hubbub,
index 1212da12c4144d6ab8956307c551cf8d6d372a26..6229a8ca001333bf61838fa01082ac9bef1f193d 100644 (file)
@@ -688,7 +688,7 @@ bool dcn20_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
        return true;
 }
 
-static bool dcn20_set_blend_lut(
+bool dcn20_set_blend_lut(
        struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state)
 {
        struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
@@ -710,7 +710,7 @@ static bool dcn20_set_blend_lut(
        return result;
 }
 
-static bool dcn20_set_shaper_3dlut(
+bool dcn20_set_shaper_3dlut(
        struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state)
 {
        struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
@@ -999,72 +999,6 @@ void dcn20_enable_plane(
 }
 
 
-static void dcn20_program_pipe(
-               struct dc *dc,
-               struct pipe_ctx *pipe_ctx,
-               struct dc_state *context)
-{
-       pipe_ctx->plane_state->update_flags.bits.full_update =
-                       context->commit_hints.full_update_needed ? 1 : pipe_ctx->plane_state->update_flags.bits.full_update;
-
-       if (pipe_ctx->plane_state->update_flags.bits.full_update)
-               dcn20_enable_plane(dc, pipe_ctx, context);
-
-       update_dchubp_dpp(dc, pipe_ctx, context);
-
-       set_hdr_multiplier(pipe_ctx);
-
-       if (pipe_ctx->plane_state->update_flags.bits.full_update ||
-                       pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
-                       pipe_ctx->plane_state->update_flags.bits.gamma_change)
-               dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state);
-
-       /* dcn10_translate_regamma_to_hw_format takes 750us to finish
-        * only do gamma programming for full update.
-        * TODO: This can be further optimized/cleaned up
-        * Always call this for now since it does memcmp inside before
-        * doing heavy calculation and programming
-        */
-       if (pipe_ctx->plane_state->update_flags.bits.full_update)
-               dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream);
-}
-
-static void dcn20_program_all_pipe_in_tree(
-               struct dc *dc,
-               struct pipe_ctx *pipe_ctx,
-               struct dc_state *context)
-{
-       if (pipe_ctx->top_pipe == NULL && !pipe_ctx->prev_odm_pipe) {
-               bool blank = !is_pipe_tree_visible(pipe_ctx);
-
-               pipe_ctx->stream_res.tg->funcs->program_global_sync(
-                               pipe_ctx->stream_res.tg,
-                               pipe_ctx->pipe_dlg_param.vready_offset,
-                               pipe_ctx->pipe_dlg_param.vstartup_start,
-                               pipe_ctx->pipe_dlg_param.vupdate_offset,
-                               pipe_ctx->pipe_dlg_param.vupdate_width);
-
-               pipe_ctx->stream_res.tg->funcs->set_vtg_params(
-                               pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
-
-               dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
-
-               if (dc->hwss.update_odm)
-                       dc->hwss.update_odm(dc, context, pipe_ctx);
-       }
-
-       if (pipe_ctx->plane_state != NULL)
-               dcn20_program_pipe(dc, pipe_ctx, context);
-
-       if (pipe_ctx->bottom_pipe != NULL) {
-               ASSERT(pipe_ctx->bottom_pipe != pipe_ctx);
-               dcn20_program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context);
-       } else if (pipe_ctx->next_odm_pipe != NULL) {
-               ASSERT(pipe_ctx->next_odm_pipe != pipe_ctx);
-               dcn20_program_all_pipe_in_tree(dc, pipe_ctx->next_odm_pipe, context);
-       }
-}
-
 void dcn20_pipe_control_lock_global(
                struct dc *dc,
                struct pipe_ctx *pipe,
@@ -1124,114 +1058,462 @@ void dcn20_pipe_control_lock(
        }
 }
 
-static void dcn20_apply_ctx_for_surface(
-               struct dc *dc,
-               const struct dc_stream_state *stream,
-               int num_planes,
-               struct dc_state *context)
+static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx *new_pipe)
 {
-       const unsigned int TIMEOUT_FOR_PIPE_ENABLE_MS = 100;
-       int i;
-       struct timing_generator *tg;
-       bool removed_pipe[6] = { false };
-       bool interdependent_update = false;
-       struct pipe_ctx *top_pipe_to_program =
-                       find_top_pipe_for_stream(dc, context, stream);
-       struct pipe_ctx *prev_top_pipe_to_program =
-                       find_top_pipe_for_stream(dc, dc->current_state, stream);
-       DC_LOGGER_INIT(dc->ctx->logger);
+       new_pipe->update_flags.raw = 0;
 
-       if (!top_pipe_to_program)
+       /* Exit on unchanged, unused pipe */
+       if (!old_pipe->plane_state && !new_pipe->plane_state)
                return;
+       /* Detect pipe enable/disable */
+       if (!old_pipe->plane_state && new_pipe->plane_state) {
+               new_pipe->update_flags.bits.enable = 1;
+               new_pipe->update_flags.bits.mpcc = 1;
+               new_pipe->update_flags.bits.dppclk = 1;
+               new_pipe->update_flags.bits.hubp_interdependent = 1;
+               new_pipe->update_flags.bits.hubp_rq_dlg_ttu = 1;
+               new_pipe->update_flags.bits.gamut_remap = 1;
+               new_pipe->update_flags.bits.scaler = 1;
+               new_pipe->update_flags.bits.viewport = 1;
+               if (!new_pipe->top_pipe && !new_pipe->prev_odm_pipe) {
+                       new_pipe->update_flags.bits.odm = 1;
+                       new_pipe->update_flags.bits.global_sync = 1;
+               }
+               return;
+       }
+       if (old_pipe->plane_state && !new_pipe->plane_state) {
+               new_pipe->update_flags.bits.disable = 1;
+               return;
+       }
 
-       /* Carry over GSL groups in case the context is changing. */
-       for (i = 0; i < dc->res_pool->pipe_count; i++) {
-               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-               struct pipe_ctx *old_pipe_ctx =
-                       &dc->current_state->res_ctx.pipe_ctx[i];
+       /* Detect top pipe only changes */
+       if (!new_pipe->top_pipe && !new_pipe->prev_odm_pipe) {
+               /* Detect odm changes */
+               if ((old_pipe->next_odm_pipe && new_pipe->next_odm_pipe
+                       && old_pipe->next_odm_pipe->pipe_idx != new_pipe->next_odm_pipe->pipe_idx)
+                               || (!old_pipe->next_odm_pipe && new_pipe->next_odm_pipe)
+                               || (old_pipe->next_odm_pipe && !new_pipe->next_odm_pipe)
+                               || old_pipe->stream_res.opp != new_pipe->stream_res.opp)
+                       new_pipe->update_flags.bits.odm = 1;
+
+               /* Detect global sync changes */
+               if (old_pipe->pipe_dlg_param.vready_offset != new_pipe->pipe_dlg_param.vready_offset
+                               || old_pipe->pipe_dlg_param.vstartup_start != new_pipe->pipe_dlg_param.vstartup_start
+                               || old_pipe->pipe_dlg_param.vupdate_offset != new_pipe->pipe_dlg_param.vupdate_offset
+                               || old_pipe->pipe_dlg_param.vupdate_width != new_pipe->pipe_dlg_param.vupdate_width)
+                       new_pipe->update_flags.bits.global_sync = 1;
+       }
 
-               if (pipe_ctx->stream == stream &&
-                   pipe_ctx->stream == old_pipe_ctx->stream)
-                       pipe_ctx->stream_res.gsl_group =
-                               old_pipe_ctx->stream_res.gsl_group;
+       /*
+        * Detect opp / tg change, only set on change, not on enable
+        * Assume mpcc inst = pipe index, if not this code needs to be updated
+        * since mpcc is what is affected by these. In fact all of our sequence
+        * makes this assumption at the moment with how hubp reset is matched to
+        * same index mpcc reset.
+        */
+       if (old_pipe->stream_res.opp != new_pipe->stream_res.opp)
+               new_pipe->update_flags.bits.opp_changed = 1;
+       if (old_pipe->stream_res.tg != new_pipe->stream_res.tg)
+               new_pipe->update_flags.bits.tg_changed = 1;
+
+       /* Detect mpcc blending changes, only dpp inst and bot matter here */
+       if (old_pipe->plane_res.dpp != new_pipe->plane_res.dpp
+                       || old_pipe->stream_res.opp != new_pipe->stream_res.opp
+                       || (!old_pipe->bottom_pipe && new_pipe->bottom_pipe)
+                       || (old_pipe->bottom_pipe && !new_pipe->bottom_pipe)
+                       || (old_pipe->bottom_pipe && new_pipe->bottom_pipe
+                               && old_pipe->bottom_pipe->plane_res.mpcc_inst
+                                       != new_pipe->bottom_pipe->plane_res.mpcc_inst))
+               new_pipe->update_flags.bits.mpcc = 1;
+
+       /* Detect dppclk change */
+       if (old_pipe->plane_res.bw.dppclk_khz != new_pipe->plane_res.bw.dppclk_khz)
+               new_pipe->update_flags.bits.dppclk = 1;
+
+       /* Check for scl update */
+       if (memcmp(&old_pipe->plane_res.scl_data, &new_pipe->plane_res.scl_data, sizeof(struct scaler_data)))
+                       new_pipe->update_flags.bits.scaler = 1;
+       /* Check for vp update */
+       if (memcmp(&old_pipe->plane_res.scl_data.viewport, &new_pipe->plane_res.scl_data.viewport, sizeof(struct rect))
+                       || memcmp(&old_pipe->plane_res.scl_data.viewport_c,
+                               &new_pipe->plane_res.scl_data.viewport_c, sizeof(struct rect)))
+               new_pipe->update_flags.bits.viewport = 1;
+
+       /* Detect dlg/ttu/rq updates */
+       {
+               struct _vcs_dpi_display_dlg_regs_st old_dlg_attr = old_pipe->dlg_regs;
+               struct _vcs_dpi_display_ttu_regs_st old_ttu_attr = old_pipe->ttu_regs;
+               struct _vcs_dpi_display_dlg_regs_st *new_dlg_attr = &new_pipe->dlg_regs;
+               struct _vcs_dpi_display_ttu_regs_st *new_ttu_attr = &new_pipe->ttu_regs;
+
+               /* Detect pipe interdependent updates */
+               if (old_dlg_attr.dst_y_prefetch != new_dlg_attr->dst_y_prefetch ||
+                               old_dlg_attr.vratio_prefetch != new_dlg_attr->vratio_prefetch ||
+                               old_dlg_attr.vratio_prefetch_c != new_dlg_attr->vratio_prefetch_c ||
+                               old_dlg_attr.dst_y_per_vm_vblank != new_dlg_attr->dst_y_per_vm_vblank ||
+                               old_dlg_attr.dst_y_per_row_vblank != new_dlg_attr->dst_y_per_row_vblank ||
+                               old_dlg_attr.dst_y_per_vm_flip != new_dlg_attr->dst_y_per_vm_flip ||
+                               old_dlg_attr.dst_y_per_row_flip != new_dlg_attr->dst_y_per_row_flip ||
+                               old_dlg_attr.refcyc_per_meta_chunk_vblank_l != new_dlg_attr->refcyc_per_meta_chunk_vblank_l ||
+                               old_dlg_attr.refcyc_per_meta_chunk_vblank_c != new_dlg_attr->refcyc_per_meta_chunk_vblank_c ||
+                               old_dlg_attr.refcyc_per_meta_chunk_flip_l != new_dlg_attr->refcyc_per_meta_chunk_flip_l ||
+                               old_dlg_attr.refcyc_per_line_delivery_pre_l != new_dlg_attr->refcyc_per_line_delivery_pre_l ||
+                               old_dlg_attr.refcyc_per_line_delivery_pre_c != new_dlg_attr->refcyc_per_line_delivery_pre_c ||
+                               old_ttu_attr.refcyc_per_req_delivery_pre_l != new_ttu_attr->refcyc_per_req_delivery_pre_l ||
+                               old_ttu_attr.refcyc_per_req_delivery_pre_c != new_ttu_attr->refcyc_per_req_delivery_pre_c ||
+                               old_ttu_attr.refcyc_per_req_delivery_pre_cur0 != new_ttu_attr->refcyc_per_req_delivery_pre_cur0 ||
+                               old_ttu_attr.refcyc_per_req_delivery_pre_cur1 != new_ttu_attr->refcyc_per_req_delivery_pre_cur1 ||
+                               old_ttu_attr.min_ttu_vblank != new_ttu_attr->min_ttu_vblank ||
+                               old_ttu_attr.qos_level_flip != new_ttu_attr->qos_level_flip) {
+                       old_dlg_attr.dst_y_prefetch = new_dlg_attr->dst_y_prefetch;
+                       old_dlg_attr.vratio_prefetch = new_dlg_attr->vratio_prefetch;
+                       old_dlg_attr.vratio_prefetch_c = new_dlg_attr->vratio_prefetch_c;
+                       old_dlg_attr.dst_y_per_vm_vblank = new_dlg_attr->dst_y_per_vm_vblank;
+                       old_dlg_attr.dst_y_per_row_vblank = new_dlg_attr->dst_y_per_row_vblank;
+                       old_dlg_attr.dst_y_per_vm_flip = new_dlg_attr->dst_y_per_vm_flip;
+                       old_dlg_attr.dst_y_per_row_flip = new_dlg_attr->dst_y_per_row_flip;
+                       old_dlg_attr.refcyc_per_meta_chunk_vblank_l = new_dlg_attr->refcyc_per_meta_chunk_vblank_l;
+                       old_dlg_attr.refcyc_per_meta_chunk_vblank_c = new_dlg_attr->refcyc_per_meta_chunk_vblank_c;
+                       old_dlg_attr.refcyc_per_meta_chunk_flip_l = new_dlg_attr->refcyc_per_meta_chunk_flip_l;
+                       old_dlg_attr.refcyc_per_line_delivery_pre_l = new_dlg_attr->refcyc_per_line_delivery_pre_l;
+                       old_dlg_attr.refcyc_per_line_delivery_pre_c = new_dlg_attr->refcyc_per_line_delivery_pre_c;
+                       old_ttu_attr.refcyc_per_req_delivery_pre_l = new_ttu_attr->refcyc_per_req_delivery_pre_l;
+                       old_ttu_attr.refcyc_per_req_delivery_pre_c = new_ttu_attr->refcyc_per_req_delivery_pre_c;
+                       old_ttu_attr.refcyc_per_req_delivery_pre_cur0 = new_ttu_attr->refcyc_per_req_delivery_pre_cur0;
+                       old_ttu_attr.refcyc_per_req_delivery_pre_cur1 = new_ttu_attr->refcyc_per_req_delivery_pre_cur1;
+                       old_ttu_attr.min_ttu_vblank = new_ttu_attr->min_ttu_vblank;
+                       old_ttu_attr.qos_level_flip = new_ttu_attr->qos_level_flip;
+                       new_pipe->update_flags.bits.hubp_interdependent = 1;
+               }
+               /* Detect any other updates to ttu/rq/dlg */
+               if (memcmp(&old_dlg_attr, &new_pipe->dlg_regs, sizeof(old_dlg_attr)) ||
+                               memcmp(&old_ttu_attr, &new_pipe->ttu_regs, sizeof(old_ttu_attr)) ||
+                               memcmp(&old_pipe->rq_regs, &new_pipe->rq_regs, sizeof(old_pipe->rq_regs)))
+                       new_pipe->update_flags.bits.hubp_rq_dlg_ttu = 1;
        }
+}
 
-       tg = top_pipe_to_program->stream_res.tg;
+static void dcn20_update_dchubp_dpp(
+       struct dc *dc,
+       struct pipe_ctx *pipe_ctx,
+       struct dc_state *context)
+{
+       struct hubp *hubp = pipe_ctx->plane_res.hubp;
+       struct dpp *dpp = pipe_ctx->plane_res.dpp;
+       struct dc_plane_state *plane_state = pipe_ctx->plane_state;
 
-       interdependent_update = top_pipe_to_program->plane_state &&
-               top_pipe_to_program->plane_state->update_flags.bits.full_update;
+       if (pipe_ctx->update_flags.bits.dppclk) {
+               dpp->funcs->dpp_dppclk_control(dpp, false, true);
 
-       if (interdependent_update)
-               lock_all_pipes(dc, context, true);
-       else
-               dcn20_pipe_control_lock(dc, top_pipe_to_program, true);
+               dc->res_pool->dccg->funcs->update_dpp_dto(
+                               dc->res_pool->dccg,
+                               dpp->inst,
+                               pipe_ctx->plane_res.bw.dppclk_khz);
+       }
 
-       if (num_planes == 0) {
-               /* OTG blank before remove all front end */
-               dc->hwss.blank_pixel_data(dc, top_pipe_to_program, true);
+       /* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG
+        * VTG is within DCHUBBUB which is commond block share by each pipe HUBP.
+        * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG
+        */
+       if (pipe_ctx->update_flags.bits.hubp_rq_dlg_ttu) {
+               hubp->funcs->hubp_vtg_sel(hubp, pipe_ctx->stream_res.tg->inst);
+
+               hubp->funcs->hubp_setup(
+                       hubp,
+                       &pipe_ctx->dlg_regs,
+                       &pipe_ctx->ttu_regs,
+                       &pipe_ctx->rq_regs,
+                       &pipe_ctx->pipe_dlg_param);
+       }
+       if (pipe_ctx->update_flags.bits.hubp_interdependent)
+               hubp->funcs->hubp_setup_interdependent(
+                       hubp,
+                       &pipe_ctx->dlg_regs,
+                       &pipe_ctx->ttu_regs);
+
+       if (pipe_ctx->update_flags.bits.enable ||
+                       plane_state->update_flags.bits.bpp_change ||
+                       plane_state->update_flags.bits.input_csc_change ||
+                       plane_state->update_flags.bits.color_space_change ||
+                       plane_state->update_flags.bits.coeff_reduction_change) {
+               struct dc_bias_and_scale bns_params = {0};
+
+               // program the input csc
+               dpp->funcs->dpp_setup(dpp,
+                               plane_state->format,
+                               EXPANSION_MODE_ZERO,
+                               plane_state->input_csc_color_matrix,
+                               plane_state->color_space,
+                               NULL);
+
+               if (dpp->funcs->dpp_program_bias_and_scale) {
+                       //TODO :for CNVC set scale and bias registers if necessary
+                       dcn10_build_prescale_params(&bns_params, plane_state);
+                       dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params);
+               }
        }
 
-       /* Disconnect unused mpcc */
-       for (i = 0; i < dc->res_pool->pipe_count; i++) {
-               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-               struct pipe_ctx *old_pipe_ctx =
-                               &dc->current_state->res_ctx.pipe_ctx[i];
-               /*
-                * Powergate reused pipes that are not powergated
-                * fairly hacky right now, using opp_id as indicator
-                * TODO: After move dc_post to dc_update, this will
-                * be removed.
-                */
-               if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) {
-                       if (old_pipe_ctx->stream_res.tg == tg &&
-                           old_pipe_ctx->plane_res.hubp &&
-                           old_pipe_ctx->plane_res.hubp->opp_id != OPP_ID_INVALID)
-                               dc->hwss.disable_plane(dc, old_pipe_ctx);
+       if (pipe_ctx->update_flags.bits.mpcc
+                       || plane_state->update_flags.bits.global_alpha_change
+                       || plane_state->update_flags.bits.per_pixel_alpha_change) {
+               /* Need mpcc to be idle if changing opp */
+               if (pipe_ctx->update_flags.bits.opp_changed) {
+                       struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
+                       int mpcc_inst;
+
+                       for (mpcc_inst = 0; mpcc_inst < MAX_PIPES; mpcc_inst++) {
+                               if (!old_pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst])
+                                       continue;
+                               dc->res_pool->mpc->funcs->wait_for_idle(dc->res_pool->mpc, mpcc_inst);
+                               old_pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false;
+                       }
                }
+               dc->hwss.update_mpcc(dc, pipe_ctx);
+       }
+
+       if (pipe_ctx->update_flags.bits.scaler ||
+                       plane_state->update_flags.bits.scaling_change ||
+                       plane_state->update_flags.bits.position_change ||
+                       plane_state->update_flags.bits.per_pixel_alpha_change ||
+                       pipe_ctx->stream->update_flags.bits.scaling) {
+               pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->plane_state->per_pixel_alpha;
+               ASSERT(pipe_ctx->plane_res.scl_data.lb_params.depth == LB_PIXEL_DEPTH_30BPP);
+               /* scaler configuration */
+               pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler(
+                               pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data);
+       }
 
-               if ((!pipe_ctx->plane_state ||
-                    pipe_ctx->stream_res.tg != old_pipe_ctx->stream_res.tg) &&
-                    old_pipe_ctx->plane_state &&
-                    old_pipe_ctx->stream_res.tg == tg) {
+       if (pipe_ctx->update_flags.bits.viewport ||
+                       (context == dc->current_state && plane_state->update_flags.bits.scaling_change) ||
+                       (context == dc->current_state && pipe_ctx->stream->update_flags.bits.scaling))
+               hubp->funcs->mem_program_viewport(
+                       hubp,
+                       &pipe_ctx->plane_res.scl_data.viewport,
+                       &pipe_ctx->plane_res.scl_data.viewport_c);
+
+       /* Any updates are handled in dc interface, just need to apply existing for plane enable */
+       if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed)
+                       && pipe_ctx->stream->cursor_attributes.address.quad_part != 0) {
+               dc->hwss.set_cursor_position(pipe_ctx);
+               dc->hwss.set_cursor_attribute(pipe_ctx);
+
+               if (dc->hwss.set_cursor_sdr_white_level)
+                       dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
+       }
 
-                       dc->hwss.plane_atomic_disconnect(dc, old_pipe_ctx);
-                       removed_pipe[i] = true;
+       /* Any updates are handled in dc interface, just need
+        * to apply existing for plane enable / opp change */
+       if (pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed
+                       || pipe_ctx->stream->update_flags.bits.gamut_remap
+                       || pipe_ctx->stream->update_flags.bits.out_csc) {
+                       /* dpp/cm gamut remap*/
+                       dc->hwss.program_gamut_remap(pipe_ctx);
+
+               /*call the dcn2 method which uses mpc csc*/
+               dc->hwss.program_output_csc(dc,
+                               pipe_ctx,
+                               pipe_ctx->stream->output_color_space,
+                               pipe_ctx->stream->csc_color_matrix.matrix,
+                               hubp->opp_id);
+       }
 
-                       DC_LOG_DC("Reset mpcc for pipe %d\n",
-                                       old_pipe_ctx->pipe_idx);
-               }
+       if (pipe_ctx->update_flags.bits.enable ||
+                       pipe_ctx->update_flags.bits.opp_changed ||
+                       plane_state->update_flags.bits.pixel_format_change ||
+                       plane_state->update_flags.bits.horizontal_mirror_change ||
+                       plane_state->update_flags.bits.rotation_change ||
+                       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.plane_size_change) {
+               struct plane_size size = plane_state->plane_size;
+
+               size.surface_size = pipe_ctx->plane_res.scl_data.viewport;
+               hubp->funcs->hubp_program_surface_config(
+                       hubp,
+                       plane_state->format,
+                       &plane_state->tiling_info,
+                       &size,
+                       plane_state->rotation,
+                       &plane_state->dcc,
+                       plane_state->horizontal_mirror,
+                       0);
+               hubp->power_gated = false;
        }
 
-       if (num_planes > 0)
-               dcn20_program_all_pipe_in_tree(dc, top_pipe_to_program, context);
+       if (pipe_ctx->update_flags.bits.enable || plane_state->update_flags.bits.addr_update)
+               dc->hwss.update_plane_addr(dc, pipe_ctx);
 
-       /* Program secondary blending tree and writeback pipes */
-       if ((stream->num_wb_info > 0) && (dc->hwss.program_all_writeback_pipes_in_tree))
-               dc->hwss.program_all_writeback_pipes_in_tree(dc, stream, context);
+       if (pipe_ctx->update_flags.bits.enable)
+               hubp->funcs->set_blank(hubp, false);
+}
+
+
+static void dcn20_program_pipe(
+               struct dc *dc,
+               struct pipe_ctx *pipe_ctx,
+               struct dc_state *context)
+{
+       /* Only need to unblank on top pipe */
+       if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->stream->update_flags.bits.abm_level)
+                       && !pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe)
+               dc->hwss.blank_pixel_data(dc, pipe_ctx, !pipe_ctx->plane_state->visible);
+
+       if (pipe_ctx->update_flags.bits.global_sync) {
+               pipe_ctx->stream_res.tg->funcs->program_global_sync(
+                               pipe_ctx->stream_res.tg,
+                               pipe_ctx->pipe_dlg_param.vready_offset,
+                               pipe_ctx->pipe_dlg_param.vstartup_start,
+                               pipe_ctx->pipe_dlg_param.vupdate_offset,
+                               pipe_ctx->pipe_dlg_param.vupdate_width);
 
-       if (interdependent_update)
-               for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               pipe_ctx->stream_res.tg->funcs->set_vtg_params(
+                               pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
+
+               if (dc->hwss.setup_vupdate_interrupt)
+                       dc->hwss.setup_vupdate_interrupt(pipe_ctx);
+       }
+
+       if (pipe_ctx->update_flags.bits.odm)
+               dc->hwss.update_odm(dc, context, pipe_ctx);
+
+       if (pipe_ctx->update_flags.bits.enable)
+               dcn20_enable_plane(dc, pipe_ctx, context);
+
+       if (pipe_ctx->update_flags.raw || pipe_ctx->plane_state->update_flags.raw || pipe_ctx->stream->update_flags.raw)
+               dcn20_update_dchubp_dpp(dc, pipe_ctx, context);
+
+       if (pipe_ctx->update_flags.bits.enable
+                       || pipe_ctx->plane_state->update_flags.bits.sdr_white_level)
+               set_hdr_multiplier(pipe_ctx);
+
+       if (pipe_ctx->update_flags.bits.enable ||
+                       pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
+                       pipe_ctx->plane_state->update_flags.bits.gamma_change)
+               dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state);
+
+       /* dcn10_translate_regamma_to_hw_format takes 750us to finish
+        * only do gamma programming for powering on, internal memcmp to avoid
+        * updating on slave planes
+        */
+       if (pipe_ctx->update_flags.bits.enable || pipe_ctx->stream->update_flags.bits.out_tf)
+               dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream);
+
+       /* If the pipe has been enabled or has a different opp, we
+        * should reprogram the fmt. This deals with cases where
+        * interation between mpc and odm combine on different streams
+        * causes a different pipe to be chosen to odm combine with.
+        */
+       if (pipe_ctx->update_flags.bits.enable
+           || pipe_ctx->update_flags.bits.opp_changed) {
+
+               pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
+                       pipe_ctx->stream_res.opp,
+                       COLOR_SPACE_YCBCR601,
+                       pipe_ctx->stream->timing.display_color_depth,
+                       pipe_ctx->stream->signal);
+
+               pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
+                       pipe_ctx->stream_res.opp,
+                       &pipe_ctx->stream->bit_depth_params,
+                       &pipe_ctx->stream->clamping);
+       }
+}
+
+static bool does_pipe_need_lock(struct pipe_ctx *pipe)
+{
+       if ((pipe->plane_state && pipe->plane_state->update_flags.raw)
+                       || pipe->update_flags.raw)
+               return true;
+       if (pipe->bottom_pipe)
+               return does_pipe_need_lock(pipe->bottom_pipe);
+
+       return false;
+}
+
+static void dcn20_program_front_end_for_ctx(
+               struct dc *dc,
+               struct dc_state *context)
+{
+       const unsigned int TIMEOUT_FOR_PIPE_ENABLE_MS = 100;
+       int i;
+       bool pipe_locked[MAX_PIPES] = {false};
+       DC_LOGGER_INIT(dc->ctx->logger);
+
+       /* Carry over GSL groups in case the context is changing. */
+       for (i = 0; i < dc->res_pool->pipe_count; i++)
+               if (context->res_ctx.pipe_ctx[i].stream == dc->current_state->res_ctx.pipe_ctx[i].stream)
+                       context->res_ctx.pipe_ctx[i].stream_res.gsl_group =
+                               dc->current_state->res_ctx.pipe_ctx[i].stream_res.gsl_group;
+
+       /* Set pipe update flags and lock pipes */
+       for (i = 0; i < dc->res_pool->pipe_count; i++)
+               dcn20_detect_pipe_changes(&dc->current_state->res_ctx.pipe_ctx[i],
+                               &context->res_ctx.pipe_ctx[i]);
+       for (i = 0; i < dc->res_pool->pipe_count; i++)
+               if (!context->res_ctx.pipe_ctx[i].top_pipe &&
+                               does_pipe_need_lock(&context->res_ctx.pipe_ctx[i])) {
                        struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
 
-                       /* Skip inactive pipes and ones already updated */
-                       if (!pipe_ctx->stream || pipe_ctx->stream == stream ||
-                           !pipe_ctx->plane_state || !tg->funcs->is_tg_enabled(tg))
-                               continue;
+                       if (pipe_ctx->update_flags.bits.tg_changed || pipe_ctx->update_flags.bits.enable)
+                               dc->hwss.pipe_control_lock(dc, pipe_ctx, true);
+                       if (!pipe_ctx->update_flags.bits.enable)
+                               dc->hwss.pipe_control_lock(dc, &dc->current_state->res_ctx.pipe_ctx[i], true);
+                       pipe_locked[i] = true;
+               }
 
-                       pipe_ctx->plane_res.hubp->funcs->hubp_setup_interdependent(
-                               pipe_ctx->plane_res.hubp,
-                               &pipe_ctx->dlg_regs,
-                               &pipe_ctx->ttu_regs);
+       /* OTG blank before disabling all front ends */
+       for (i = 0; i < dc->res_pool->pipe_count; i++)
+               if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable
+                               && !context->res_ctx.pipe_ctx[i].top_pipe
+                               && !context->res_ctx.pipe_ctx[i].prev_odm_pipe
+                               && context->res_ctx.pipe_ctx[i].stream)
+                       dc->hwss.blank_pixel_data(dc, &context->res_ctx.pipe_ctx[i], true);
+
+       /* Disconnect mpcc */
+       for (i = 0; i < dc->res_pool->pipe_count; i++)
+               if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable
+                               || context->res_ctx.pipe_ctx[i].update_flags.bits.opp_changed) {
+                       dc->hwss.plane_atomic_disconnect(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
+                       DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx);
                }
 
-       if (interdependent_update)
-               lock_all_pipes(dc, context, false);
-       else
-               dcn20_pipe_control_lock(dc, top_pipe_to_program, false);
+       /*
+        * Program all updated pipes, order matters for mpcc setup. Start with
+        * top pipe and program all pipes that follow in order
+        */
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
 
+               if (pipe->plane_state && !pipe->top_pipe) {
+                       while (pipe) {
+                               dcn20_program_pipe(dc, pipe, context);
+                               pipe = pipe->bottom_pipe;
+                       }
+                       /* Program secondary blending tree and writeback pipes */
+                       pipe = &context->res_ctx.pipe_ctx[i];
+                       if (!pipe->prev_odm_pipe && pipe->stream->num_wb_info > 0
+                                       && (pipe->update_flags.raw || pipe->plane_state->update_flags.raw || pipe->stream->update_flags.raw)
+                                       && dc->hwss.program_all_writeback_pipes_in_tree)
+                               dc->hwss.program_all_writeback_pipes_in_tree(dc, pipe->stream, context);
+               }
+       }
+
+       /* Unlock all locked pipes */
        for (i = 0; i < dc->res_pool->pipe_count; i++)
-               if (removed_pipe[i])
-                       dcn20_disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
+               if (pipe_locked[i]) {
+                       struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+                       if (pipe_ctx->update_flags.bits.tg_changed || pipe_ctx->update_flags.bits.enable)
+                               dc->hwss.pipe_control_lock(dc, pipe_ctx, false);
+                       if (!pipe_ctx->update_flags.bits.enable)
+                               dc->hwss.pipe_control_lock(dc, &dc->current_state->res_ctx.pipe_ctx[i], false);
+               }
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++)
+               if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable)
+                       dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
 
        /*
         * If we are enabling a pipe, we need to wait for pending clear as this is a critical
@@ -1239,15 +1521,22 @@ static void dcn20_apply_ctx_for_surface(
         * will cause HW to perform an "immediate enable" (as opposed to "vsync enable") which
         * is unsupported on DCN.
         */
-       i = 0;
-       if (num_planes > 0 && top_pipe_to_program &&
-                       (prev_top_pipe_to_program == NULL || prev_top_pipe_to_program->plane_state == NULL)) {
-               while (i < TIMEOUT_FOR_PIPE_ENABLE_MS &&
-                               top_pipe_to_program->plane_res.hubp->funcs->hubp_is_flip_pending(top_pipe_to_program->plane_res.hubp)) {
-                       i += 1;
-                       msleep(1);
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+               if (pipe->plane_state && !pipe->top_pipe && pipe->update_flags.bits.enable) {
+                       struct hubp *hubp = pipe->plane_res.hubp;
+                       int j = 0;
+
+                       for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_MS
+                                       && hubp->funcs->hubp_is_flip_pending(hubp); j++)
+                               msleep(1);
                }
        }
+
+       /* WA to apply WM setting*/
+       if (dc->hwseq->wa.DEGVIDCN21)
+               dc->res_pool->hubbub->funcs->apply_DEDCN21_147_wa(dc->res_pool->hubbub);
 }
 
 
@@ -1319,8 +1608,12 @@ bool dcn20_update_bandwidth(
 
                        pipe_ctx->stream_res.tg->funcs->set_vtg_params(
                                        pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
+
                        if (pipe_ctx->prev_odm_pipe == NULL)
                                dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
+
+                       if (dc->hwss.setup_vupdate_interrupt)
+                               dc->hwss.setup_vupdate_interrupt(pipe_ctx);
                }
 
                pipe_ctx->plane_res.hubp->funcs->hubp_setup(
@@ -1337,7 +1630,8 @@ bool dcn20_update_bandwidth(
 static void dcn20_enable_writeback(
                struct dc *dc,
                const struct dc_stream_status *stream_status,
-               struct dc_writeback_info *wb_info)
+               struct dc_writeback_info *wb_info,
+               struct dc_state *context)
 {
        struct dwbc *dwb;
        struct mcif_wb *mcif_wb;
@@ -1354,7 +1648,7 @@ static void dcn20_enable_writeback(
        optc->funcs->set_dwb_source(optc, wb_info->dwb_pipe_inst);
        /* set MCIF_WB buffer and arbitration configuration */
        mcif_wb->funcs->config_mcif_buf(mcif_wb, &wb_info->mcif_buf_params, wb_info->dwb_params.dest_height);
-       mcif_wb->funcs->config_mcif_arb(mcif_wb, &dc->current_state->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[wb_info->dwb_pipe_inst]);
+       mcif_wb->funcs->config_mcif_arb(mcif_wb, &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[wb_info->dwb_pipe_inst]);
        /* Enable MCIF_WB */
        mcif_wb->funcs->enable_mcif(mcif_wb);
        /* Enable DWB */
@@ -1919,8 +2213,10 @@ static void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
        link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
                                                    pipe_ctx->stream_res.stream_enc->id, true);
 
-       if (link->dc->hwss.program_dmdata_engine)
-               link->dc->hwss.program_dmdata_engine(pipe_ctx);
+       if (pipe_ctx->plane_state && pipe_ctx->plane_state->flip_immediate != 1) {
+               if (link->dc->hwss.program_dmdata_engine)
+                       link->dc->hwss.program_dmdata_engine(pipe_ctx);
+       }
 
        link->dc->hwss.update_info_frame(pipe_ctx);
 
@@ -2095,7 +2391,8 @@ void dcn20_hw_sequencer_construct(struct dc *dc)
        dc->hwss.program_triplebuffer = dcn20_program_tripleBuffer;
        dc->hwss.set_input_transfer_func = dcn20_set_input_transfer_func;
        dc->hwss.set_output_transfer_func = dcn20_set_output_transfer_func;
-       dc->hwss.apply_ctx_for_surface = dcn20_apply_ctx_for_surface;
+       dc->hwss.apply_ctx_for_surface = NULL;
+       dc->hwss.program_front_end_for_ctx = dcn20_program_front_end_for_ctx;
        dc->hwss.pipe_control_lock = dcn20_pipe_control_lock;
        dc->hwss.pipe_control_lock_global = dcn20_pipe_control_lock_global;
        dc->hwss.optimize_bandwidth = dcn20_optimize_bandwidth;
index 92ab3dd91814ff8bccb90c235023047ff82c7504..9dbc2effa4ea7dd6e83301549ed161cb53275072 100644 (file)
@@ -96,4 +96,18 @@ void dcn20_init_blank(
           struct dc *dc,
           struct timing_generator *tg);
 void dcn20_display_init(struct dc *dc);
+void dcn20_pipe_control_lock(
+       struct dc *dc,
+       struct pipe_ctx *pipe,
+       bool lock);
+void dcn20_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx);
+void dcn20_enable_plane(
+       struct dc *dc,
+       struct pipe_ctx *pipe_ctx,
+       struct dc_state *context);
+bool dcn20_set_blend_lut(
+       struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state);
+bool dcn20_set_shaper_3dlut(
+       struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state);
+
 #endif /* __DC_HWSS_DCN20_H__ */
index 3736b5548a2511362b29bc8852b029fe1e806f2a..0c98a0bbbd14f0cea11cbbd9ebeda7e0396333f1 100644 (file)
@@ -91,6 +91,13 @@ struct mpll_cfg {
        uint32_t ref_range;
        uint32_t ref_clk;
        bool hdmimode_enable;
+       bool sup_pre_hp;
+       bool dp_tx0_vergdrv_byp;
+       bool dp_tx1_vergdrv_byp;
+       bool dp_tx2_vergdrv_byp;
+       bool dp_tx3_vergdrv_byp;
+
+
 };
 
 struct dpcssys_phy_seq_cfg {
index 2137e2be2140405997f6c6a75d2b1f651ae4eb8d..3b613fb93ef8041dd4f5846ad072ea4887684ad5 100644 (file)
@@ -287,6 +287,10 @@ void optc2_get_optc_source(struct timing_generator *optc,
                *num_of_src_opp = 2;
        else
                *num_of_src_opp = 1;
+
+       /* Work around VBIOS not updating OPTC_NUM_OF_INPUT_SEGMENT */
+       if (*src_opp_id_1 == 0xf)
+               *num_of_src_opp = 1;
 }
 
 void optc2_set_dwb_source(struct timing_generator *optc,
@@ -456,7 +460,7 @@ static struct timing_generator_funcs dcn20_tg_funcs = {
                .set_vtg_params = optc1_set_vtg_params,
                .program_manual_trigger = optc2_program_manual_trigger,
                .setup_manual_trigger = optc2_setup_manual_trigger,
-               .is_matching_timing = optc1_is_matching_timing
+               .get_hw_timing = optc1_get_hw_timing,
 };
 
 void dcn20_timing_generator_init(struct optc *optc1)
index 5a2763daff4d65980733292d652ad9770c3615ca..ee9157b673aba520e6ae6d85540d9d85d8f5b69d 100644 (file)
@@ -581,11 +581,13 @@ static const struct dcn2_dpp_registers tf_regs[] = {
 };
 
 static const struct dcn2_dpp_shift tf_shift = {
-               TF_REG_LIST_SH_MASK_DCN20(__SHIFT)
+               TF_REG_LIST_SH_MASK_DCN20(__SHIFT),
+               TF_DEBUG_REG_LIST_SH_DCN10
 };
 
 static const struct dcn2_dpp_mask tf_mask = {
-               TF_REG_LIST_SH_MASK_DCN20(_MASK)
+               TF_REG_LIST_SH_MASK_DCN20(_MASK),
+               TF_DEBUG_REG_LIST_MASK_DCN10
 };
 
 #define dwbc_regs_dcn2(id)\
@@ -732,6 +734,15 @@ static const struct dcn20_vmid_mask vmid_masks = {
                DCN20_VMID_MASK_SH_LIST(_MASK)
 };
 
+static const struct dce110_aux_registers_shift aux_shift = {
+               DCN_AUX_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dce110_aux_registers_mask aux_mask = {
+               DCN_AUX_MASK_SH_LIST(_MASK)
+};
+
+
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
 #define dsc_regsDCN20(id)\
 [id] = {\
@@ -922,7 +933,10 @@ struct dce_aux *dcn20_aux_engine_create(
 
        dce110_aux_engine_construct(aux_engine, ctx, inst,
                                    SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,
-                                   &aux_engine_regs[inst]);
+                                   &aux_engine_regs[inst],
+                                       &aux_mask,
+                                       &aux_shift,
+                                       ctx->dc->caps.extended_aux_timeout_support);
 
        return &aux_engine->base;
 }
@@ -1154,6 +1168,8 @@ static const struct resource_create_funcs res_create_maximus_funcs = {
        .create_hwseq = dcn20_hwseq_create,
 };
 
+static void dcn20_pp_smu_destroy(struct pp_smu_funcs **pp_smu);
+
 void dcn20_clock_source_destroy(struct clock_source **clk_src)
 {
        kfree(TO_DCE110_CLK_SRC(*clk_src));
@@ -1760,7 +1776,7 @@ int dcn20_populate_dml_pipes_from_context(
                        pipe_cnt = i;
                        continue;
                }
-               if (!resource_are_streams_timing_synchronizable(
+               if (dc->debug.disable_timing_sync || !resource_are_streams_timing_synchronizable(
                                res_ctx->pipe_ctx[pipe_cnt].stream,
                                res_ctx->pipe_ctx[i].stream)) {
                        synchronized_vblank = false;
@@ -1892,7 +1908,7 @@ int dcn20_populate_dml_pipes_from_context(
                        break;
                case PIXEL_ENCODING_YCBCR420:
                        pipes[pipe_cnt].dout.output_format = dm_420;
-                       pipes[pipe_cnt].dout.output_bpp = (output_bpc * 3) / 2;
+                       pipes[pipe_cnt].dout.output_bpp = (output_bpc * 3.0) / 2;
                        break;
                case PIXEL_ENCODING_YCBCR422:
                        if (true) /* todo */
@@ -1906,6 +1922,11 @@ int dcn20_populate_dml_pipes_from_context(
                        pipes[pipe_cnt].dout.output_bpp = output_bpc * 3;
                }
 
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+               if (res_ctx->pipe_ctx[i].stream->timing.flags.DSC)
+                       pipes[pipe_cnt].dout.output_bpp = res_ctx->pipe_ctx[i].stream->timing.dsc_cfg.bits_per_pixel / 16.0;
+#endif
+
                /* todo: default max for now, until there is logic reflecting this in dc*/
                pipes[pipe_cnt].dout.output_bpc = 12;
                /*
@@ -2202,7 +2223,8 @@ static struct pipe_ctx *dcn20_find_secondary_pipe(struct dc *dc,
                 */
                if (secondary_pipe == NULL) {
                        for (j = dc->res_pool->pipe_count - 1; j >= 0; j--) {
-                               if (dc->current_state->res_ctx.pipe_ctx[j].top_pipe == NULL) {
+                               if (dc->current_state->res_ctx.pipe_ctx[j].top_pipe == NULL
+                                               && dc->current_state->res_ctx.pipe_ctx[j].prev_odm_pipe == NULL) {
                                        preferred_pipe_idx = j;
 
                                        if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
@@ -2249,11 +2271,7 @@ bool dcn20_fast_validate_bw(
        bool out = false;
 
        int pipe_cnt, i, pipe_idx, vlevel, vlevel_unsplit;
-       bool odm_capable = context->bw_ctx.dml.ip.odm_capable;
        bool force_split = false;
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
-       bool failed_non_odm_dsc = false;
-#endif
        int split_threshold = dc->res_pool->pipe_count / 2;
        bool avoid_split = dc->debug.pipe_split_policy != MPC_SPLIT_DYNAMIC;
 
@@ -2330,24 +2348,8 @@ bool dcn20_fast_validate_bw(
                goto validate_out;
        }
 
-       context->bw_ctx.dml.ip.odm_capable = 0;
-
        vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
 
-       context->bw_ctx.dml.ip.odm_capable = odm_capable;
-
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
-       /* 1 dsc per stream dsc validation */
-       if (vlevel <= context->bw_ctx.dml.soc.num_states)
-               if (!dcn20_validate_dsc(dc, context)) {
-                       failed_non_odm_dsc = true;
-                       vlevel = context->bw_ctx.dml.soc.num_states + 1;
-               }
-#endif
-
-       if (vlevel > context->bw_ctx.dml.soc.num_states && odm_capable)
-               vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
-
        if (vlevel > context->bw_ctx.dml.soc.num_states)
                goto validate_fail;
 
@@ -2469,6 +2471,7 @@ bool dcn20_fast_validate_bw(
                                                        &context->res_ctx, dc->res_pool,
                                                        pipe, hsplit_pipe))
                                                goto validate_fail;
+                                       dcn20_build_mapped_resource(dc, context, pipe->stream);
                                } else
                                        dcn20_split_stream_for_mpc(
                                                &context->res_ctx, dc->res_pool,
@@ -2482,7 +2485,7 @@ bool dcn20_fast_validate_bw(
        }
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
        /* Actual dsc count per stream dsc validation*/
-       if (failed_non_odm_dsc && !dcn20_validate_dsc(dc, context)) {
+       if (!dcn20_validate_dsc(dc, context)) {
                context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states] =
                                DML_FAIL_DSC_VALIDATION_FAILURE;
                goto validate_fail;
@@ -2574,6 +2577,10 @@ void dcn20_calculate_wm(
        context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
        context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
        context->bw_ctx.bw.dcn.watermarks.b.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
+#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
+       context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
+       context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
+#endif
 
        if (vlevel < 2) {
                pipes[0].clks_cfg.voltage = 2;
@@ -2585,6 +2592,10 @@ void dcn20_calculate_wm(
        context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
        context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
        context->bw_ctx.bw.dcn.watermarks.c.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
+#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
+       context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
+       context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
+#endif
 
        if (vlevel < 3) {
                pipes[0].clks_cfg.voltage = 3;
@@ -2596,6 +2607,10 @@ void dcn20_calculate_wm(
        context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
        context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
        context->bw_ctx.bw.dcn.watermarks.d.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
+#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
+       context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
+       context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
+#endif
 
        pipes[0].clks_cfg.voltage = vlevel;
        pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].dcfclk_mhz;
@@ -2605,6 +2620,10 @@ void dcn20_calculate_wm(
        context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
        context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
        context->bw_ctx.bw.dcn.watermarks.a.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
+#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
+       context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
+       context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
+#endif
 }
 
 void dcn20_calculate_dlg_params(
@@ -2624,7 +2643,7 @@ void dcn20_calculate_dlg_params(
        context->bw_ctx.bw.dcn.clk.socclk_khz = context->bw_ctx.dml.vba.SOCCLK * 1000;
        context->bw_ctx.bw.dcn.clk.dramclk_khz = context->bw_ctx.dml.vba.DRAMSpeed * 1000 / 16;
        context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = context->bw_ctx.dml.vba.DCFCLKDeepSleep * 1000;
-       context->bw_ctx.bw.dcn.clk.fclk_khz = 0;
+       context->bw_ctx.bw.dcn.clk.fclk_khz = context->bw_ctx.dml.vba.FabricClock * 1000;
        context->bw_ctx.bw.dcn.clk.p_state_change_support =
                context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb]
                                                        != dm_dram_clock_change_unsupported;
@@ -2640,8 +2659,8 @@ void dcn20_calculate_dlg_params(
                        continue;
 
                if (!visited[pipe_idx]) {
-                       display_pipe_source_params_st *src = &pipes[pipe_idx_unsplit].pipe.src;
-                       display_pipe_dest_params_st *dst = &pipes[pipe_idx_unsplit].pipe.dest;
+                       display_pipe_source_params_st *src = &pipes[pipe_idx].pipe.src;
+                       display_pipe_dest_params_st *dst = &pipes[pipe_idx].pipe.dest;
 
                        dst->vstartup_start = context->bw_ctx.dml.vba.VStartup[pipe_idx_unsplit];
                        dst->vupdate_offset = context->bw_ctx.dml.vba.VUpdateOffsetPix[pipe_idx_unsplit];
@@ -2801,7 +2820,6 @@ bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
        ASSERT(false);
 
 restore_dml_state:
-       memcpy(&context->bw_ctx.dml, &dc->dml, sizeof(struct display_mode_lib));
        context->bw_ctx.dml.soc.dram_clock_change_latency_us = p_state_latency_us;
 
        return voltage_supported;
@@ -2942,7 +2960,7 @@ bool dcn20_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool)
        return true;
 }
 
-struct pp_smu_funcs *dcn20_pp_smu_create(struct dc_context *ctx)
+static struct pp_smu_funcs *dcn20_pp_smu_create(struct dc_context *ctx)
 {
        struct pp_smu_funcs *pp_smu = kzalloc(sizeof(*pp_smu), GFP_KERNEL);
 
@@ -2957,7 +2975,7 @@ struct pp_smu_funcs *dcn20_pp_smu_create(struct dc_context *ctx)
        return pp_smu;
 }
 
-void dcn20_pp_smu_destroy(struct pp_smu_funcs **pp_smu)
+static void dcn20_pp_smu_destroy(struct pp_smu_funcs **pp_smu)
 {
        if (pp_smu && *pp_smu) {
                kfree(*pp_smu);
@@ -3035,7 +3053,7 @@ static void cap_soc_clocks(
 static void update_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb,
                struct pp_smu_nv_clock_table *max_clocks, unsigned int *uclk_states, unsigned int num_states)
 {
-       struct _vcs_dpi_voltage_scaling_st calculated_states[MAX_CLOCK_LIMIT_STATES] = {0};
+       struct _vcs_dpi_voltage_scaling_st calculated_states[MAX_CLOCK_LIMIT_STATES];
        int i;
        int num_calculated_states = 0;
        int min_dcfclk = 0;
@@ -3043,6 +3061,8 @@ static void update_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_
        if (num_states == 0)
                return;
 
+       memset(calculated_states, 0, sizeof(calculated_states));
+
        if (dc->bb_overrides.min_dcfclk_mhz > 0)
                min_dcfclk = dc->bb_overrides.min_dcfclk_mhz;
        else
@@ -3340,6 +3360,7 @@ static bool construct(
        dc->caps.post_blend_color_processing = true;
        dc->caps.force_dp_tps4_for_cp2520 = true;
        dc->caps.hw_3d_lut = true;
+       dc->caps.extended_aux_timeout_support = true;
 
        if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) {
                dc->debug = debug_defaults_drv;
index 44f95aa0d61e09ddde99baa8c318ffa743e0f431..55006462f4812c1789485778dd15c3d2006dc768 100644 (file)
@@ -95,9 +95,6 @@ struct display_stream_compressor *dcn20_dsc_create(
        struct dc_context *ctx, uint32_t inst);
 void dcn20_dsc_destroy(struct display_stream_compressor **dsc);
 
-struct pp_smu_funcs *dcn20_pp_smu_create(struct dc_context *ctx);
-void dcn20_pp_smu_destroy(struct pp_smu_funcs **pp_smu);
-
 struct hubp *dcn20_hubp_create(
        struct dc_context *ctx,
        uint32_t inst);
index 5ab9d6240498113e8f7d0e530e1f054c6380427a..4b34016164348706e8be44aca42ef24d0aa89b13 100644 (file)
@@ -578,6 +578,10 @@ static const struct stream_encoder_funcs dcn20_str_enc_funcs = {
        .set_avmute = enc1_stream_encoder_set_avmute,
        .dig_connect_to_otg  = enc1_dig_connect_to_otg,
        .dig_source_otg = enc1_dig_source_otg,
+
+       .dp_get_pixel_format =
+               enc1_stream_encoder_dp_get_pixel_format,
+
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
        .enc_read_state = enc2_read_state,
        .dp_set_dsc_config = enc2_dp_set_dsc_config,
index ef673bffc241ef0bff3cafb24a7f05ade7ed6ff1..19fabac13c65311b15c571d56a5e434a54cd11f8 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Makefile for DCN21.
 
-DCN21 = dcn21_hubp.o dcn21_hubbub.o dcn21_resource.o
+DCN21 = dcn21_hubp.o dcn21_hubbub.o dcn21_resource.o dcn21_hwseq.o dcn21_link_encoder.o
 
 ifneq ($(call cc-option, -mpreferred-stack-boundary=4),)
        cc_stack_align := -mpreferred-stack-boundary=4
index d1266741763b92f3d6ad7ed4d0d9a2f31dc71248..f546260c15b72c7db5ee416946d6b5760267f94f 100644 (file)
@@ -22,6 +22,7 @@
  * Authors: AMD
  *
  */
+#include <linux/delay.h>
 #include "dm_services.h"
 #include "dcn20/dcn20_hubbub.h"
 #include "dcn21_hubbub.h"
@@ -51,7 +52,7 @@
 #ifdef NUM_VMID
 #undef NUM_VMID
 #endif
-#define NUM_VMID 1
+#define NUM_VMID 16
 
 static uint32_t convert_and_clamp(
        uint32_t wm_ns,
@@ -71,56 +72,76 @@ static uint32_t convert_and_clamp(
 void dcn21_dchvm_init(struct hubbub *hubbub)
 {
        struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
+       uint32_t riommu_active;
+       int i;
 
        //Init DCHVM block
        REG_UPDATE(DCHVM_CTRL0, HOSTVM_INIT_REQ, 1);
 
        //Poll until RIOMMU_ACTIVE = 1
-       //TODO: Figure out interval us and retry count
-       REG_WAIT(DCHVM_RIOMMU_STAT0, RIOMMU_ACTIVE, 1, 5, 100);
+       for (i = 0; i < 100; i++) {
+               REG_GET(DCHVM_RIOMMU_STAT0, RIOMMU_ACTIVE, &riommu_active);
 
-       //Reflect the power status of DCHUBBUB
-       REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, 1);
+               if (riommu_active)
+                       break;
+               else
+                       udelay(5);
+       }
+
+       if (riommu_active) {
+               //Reflect the power status of DCHUBBUB
+               REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, 1);
 
-       //Start rIOMMU prefetching
-       REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, 1);
+               //Start rIOMMU prefetching
+               REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, 1);
 
-       // Enable dynamic clock gating
-       REG_UPDATE_4(DCHVM_CLK_CTRL,
-                                       HVM_DISPCLK_R_GATE_DIS, 0,
-                                       HVM_DISPCLK_G_GATE_DIS, 0,
-                                       HVM_DCFCLK_R_GATE_DIS, 0,
-                                       HVM_DCFCLK_G_GATE_DIS, 0);
+               // Enable dynamic clock gating
+               REG_UPDATE_4(DCHVM_CLK_CTRL,
+                                               HVM_DISPCLK_R_GATE_DIS, 0,
+                                               HVM_DISPCLK_G_GATE_DIS, 0,
+                                               HVM_DCFCLK_R_GATE_DIS, 0,
+                                               HVM_DCFCLK_G_GATE_DIS, 0);
 
-       //Poll until HOSTVM_PREFETCH_DONE = 1
-       //TODO: Figure out interval us and retry count
-       REG_WAIT(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, 1, 5, 100);
+               //Poll until HOSTVM_PREFETCH_DONE = 1
+               REG_WAIT(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, 1, 5, 100);
+       }
 }
 
-static int hubbub21_init_dchub(struct hubbub *hubbub,
+int hubbub21_init_dchub(struct hubbub *hubbub,
                struct dcn_hubbub_phys_addr_config *pa_config)
 {
        struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
+       struct dcn_vmid_page_table_config phys_config;
 
        REG_SET(DCN_VM_FB_LOCATION_BASE, 0,
-               FB_BASE, pa_config->system_aperture.fb_base);
+                       FB_BASE, pa_config->system_aperture.fb_base >> 24);
        REG_SET(DCN_VM_FB_LOCATION_TOP, 0,
-                       FB_TOP, pa_config->system_aperture.fb_top);
+                       FB_TOP, pa_config->system_aperture.fb_top >> 24);
        REG_SET(DCN_VM_FB_OFFSET, 0,
-                       FB_OFFSET, pa_config->system_aperture.fb_offset);
+                       FB_OFFSET, pa_config->system_aperture.fb_offset >> 24);
        REG_SET(DCN_VM_AGP_BOT, 0,
-                       AGP_BOT, pa_config->system_aperture.agp_bot);
+                       AGP_BOT, pa_config->system_aperture.agp_bot >> 24);
        REG_SET(DCN_VM_AGP_TOP, 0,
-                       AGP_TOP, pa_config->system_aperture.agp_top);
+                       AGP_TOP, pa_config->system_aperture.agp_top >> 24);
        REG_SET(DCN_VM_AGP_BASE, 0,
-                       AGP_BASE, pa_config->system_aperture.agp_base);
+                       AGP_BASE, pa_config->system_aperture.agp_base >> 24);
+
+       if (pa_config->gart_config.page_table_start_addr != pa_config->gart_config.page_table_end_addr) {
+               phys_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr >> 12;
+               phys_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr >> 12;
+               phys_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr | 1; //Note: hack
+               phys_config.depth = 0;
+               phys_config.block_size = 0;
+               // Init VMID 0 based on PA config
+               dcn20_vmid_setup(&hubbub1->vmid[0], &phys_config);
+       }
 
        dcn21_dchvm_init(hubbub);
 
        return NUM_VMID;
 }
 
-static void hubbub21_program_urgent_watermarks(
+void hubbub21_program_urgent_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
@@ -160,6 +181,13 @@ static void hubbub21_program_urgent_watermarks(
                REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0,
                                DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->a.frac_urg_bw_nom);
        }
+       if (safe_to_lower || watermarks->a.urgent_latency_ns > hubbub1->watermarks.a.urgent_latency_ns) {
+               hubbub1->watermarks.a.urgent_latency_ns = watermarks->a.urgent_latency_ns;
+               prog_wm_value = convert_and_clamp(watermarks->a.urgent_latency_ns,
+                               refclk_mhz, 0x1fffff);
+               REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0,
+                               DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, prog_wm_value);
+       }
 
        /* clock state B */
        if (safe_to_lower || watermarks->b.urgent_ns > hubbub1->watermarks.b.urgent_ns) {
@@ -192,6 +220,14 @@ static void hubbub21_program_urgent_watermarks(
                                DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->a.frac_urg_bw_nom);
        }
 
+       if (safe_to_lower || watermarks->b.urgent_latency_ns > hubbub1->watermarks.b.urgent_latency_ns) {
+               hubbub1->watermarks.b.urgent_latency_ns = watermarks->b.urgent_latency_ns;
+               prog_wm_value = convert_and_clamp(watermarks->b.urgent_latency_ns,
+                               refclk_mhz, 0x1fffff);
+               REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0,
+                               DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, prog_wm_value);
+       }
+
        /* clock state C */
        if (safe_to_lower || watermarks->c.urgent_ns > hubbub1->watermarks.c.urgent_ns) {
                hubbub1->watermarks.c.urgent_ns = watermarks->c.urgent_ns;
@@ -223,6 +259,14 @@ static void hubbub21_program_urgent_watermarks(
                                DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, watermarks->a.frac_urg_bw_nom);
        }
 
+       if (safe_to_lower || watermarks->c.urgent_latency_ns > hubbub1->watermarks.c.urgent_latency_ns) {
+               hubbub1->watermarks.c.urgent_latency_ns = watermarks->c.urgent_latency_ns;
+               prog_wm_value = convert_and_clamp(watermarks->c.urgent_latency_ns,
+                               refclk_mhz, 0x1fffff);
+               REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 0,
+                               DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, prog_wm_value);
+       }
+
        /* clock state D */
        if (safe_to_lower || watermarks->d.urgent_ns > hubbub1->watermarks.d.urgent_ns) {
                hubbub1->watermarks.d.urgent_ns = watermarks->d.urgent_ns;
@@ -253,9 +297,17 @@ static void hubbub21_program_urgent_watermarks(
                REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 0,
                                DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, watermarks->a.frac_urg_bw_nom);
        }
+
+       if (safe_to_lower || watermarks->d.urgent_latency_ns > hubbub1->watermarks.d.urgent_latency_ns) {
+               hubbub1->watermarks.d.urgent_latency_ns = watermarks->d.urgent_latency_ns;
+               prog_wm_value = convert_and_clamp(watermarks->d.urgent_latency_ns,
+                               refclk_mhz, 0x1fffff);
+               REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0,
+                               DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, prog_wm_value);
+       }
 }
 
-static void hubbub21_program_stutter_watermarks(
+void hubbub21_program_stutter_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
@@ -389,7 +441,7 @@ static void hubbub21_program_stutter_watermarks(
        }
 }
 
-static void hubbub21_program_pstate_watermarks(
+void hubbub21_program_pstate_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
@@ -564,17 +616,26 @@ void hubbub21_wm_read_state(struct hubbub *hubbub,
                        DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, &s->dram_clk_chanage);
 }
 
+void hubbub21_apply_DEDCN21_147_wa(struct hubbub *hubbub)
+{
+       struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
+       uint32_t prog_wm_value;
+
+       prog_wm_value = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A);
+       REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value);
+}
 
 static const struct hubbub_funcs hubbub21_funcs = {
        .update_dchub = hubbub2_update_dchub,
        .init_dchub_sys_ctx = hubbub21_init_dchub,
-       .init_vm_ctx = NULL,
+       .init_vm_ctx = hubbub2_init_vm_ctx,
        .dcc_support_swizzle = hubbub2_dcc_support_swizzle,
        .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format,
        .get_dcc_compression_cap = hubbub2_get_dcc_compression_cap,
        .wm_read_state = hubbub21_wm_read_state,
        .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,
        .program_watermarks = hubbub21_program_watermarks,
+       .apply_DEDCN21_147_wa = hubbub21_apply_DEDCN21_147_wa,
 };
 
 void hubbub21_construct(struct dcn20_hubbub *hubbub,
@@ -592,4 +653,5 @@ void hubbub21_construct(struct dcn20_hubbub *hubbub,
        hubbub->masks = hubbub_mask;
 
        hubbub->debug_test_index_pstate = 0xB;
+       hubbub->detile_buf_size = 164 * 1024; /* 164KB for DCN2.0 */
 }
index 6ff3cdb89178e24e381c29d3cd71142526756891..c4840dfb1fa51f3f8517692c5de4a787294fc66b 100644 (file)
        SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B),\
        SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C),\
        SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D),\
+       SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A),\
+       SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B),\
+       SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C),\
+       SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D),\
        SR(DCHUBBUB_ARB_HOSTVM_CNTL), \
        SR(DCHVM_CTRL0), \
        SR(DCHVM_MEM_CTRL), \
        SR(DCHVM_RIOMMU_STAT0)
 
 #define HUBBUB_REG_LIST_DCN21()\
-       HUBBUB_REG_LIST_DCN_COMMON(), \
+       HUBBUB_REG_LIST_DCN20_COMMON(), \
        HUBBUB_SR_WATERMARK_REG_LIST(), \
-       HUBBUB_HVM_REG_LIST(), \
-       SR(DCHUBBUB_CRC_CTRL), \
-       SR(DCN_VM_FB_LOCATION_BASE),\
-       SR(DCN_VM_FB_LOCATION_TOP),\
-       SR(DCN_VM_FB_OFFSET),\
-       SR(DCN_VM_AGP_BOT),\
-       SR(DCN_VM_AGP_TOP),\
-       SR(DCN_VM_AGP_BASE)
+       HUBBUB_HVM_REG_LIST()
 
 #define HUBBUB_MASK_SH_LIST_HVM(mask_sh) \
        HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, mask_sh), \
        HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, mask_sh)
 
 #define HUBBUB_MASK_SH_LIST_DCN21(mask_sh)\
-       HUBBUB_MASK_SH_LIST_HVM(mask_sh),\
+       HUBBUB_MASK_SH_LIST_HVM(mask_sh), \
        HUBBUB_MASK_SH_LIST_DCN_COMMON(mask_sh), \
        HUBBUB_MASK_SH_LIST_STUTTER(mask_sh), \
        HUBBUB_SF(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \
        HUBBUB_SF(DCN_VM_AGP_BASE, AGP_BASE, mask_sh)
 
 void dcn21_dchvm_init(struct hubbub *hubbub);
+int hubbub21_init_dchub(struct hubbub *hubbub,
+               struct dcn_hubbub_phys_addr_config *pa_config);
 void hubbub21_program_watermarks(
                struct hubbub *hubbub,
                struct dcn_watermark_set *watermarks,
                unsigned int refclk_mhz,
                bool safe_to_lower);
+void hubbub21_program_urgent_watermarks(
+               struct hubbub *hubbub,
+               struct dcn_watermark_set *watermarks,
+               unsigned int refclk_mhz,
+               bool safe_to_lower);
+void hubbub21_program_stutter_watermarks(
+               struct hubbub *hubbub,
+               struct dcn_watermark_set *watermarks,
+               unsigned int refclk_mhz,
+               bool safe_to_lower);
+void hubbub21_program_pstate_watermarks(
+               struct hubbub *hubbub,
+               struct dcn_watermark_set *watermarks,
+               unsigned int refclk_mhz,
+               bool safe_to_lower);
 
 void hubbub21_wm_read_state(struct hubbub *hubbub,
                struct dcn_hubbub_wm *wm);
index a00af513aa2b01226ef286bed224176d854ac7a6..2f5a5867e6749318b65f30a8f80b3b8983659484 100644 (file)
@@ -22,6 +22,8 @@
  * Authors: AMD
  *
  */
+
+#include "dcn10/dcn10_hubp.h"
 #include "dcn21_hubp.h"
 
 #include "dm_services.h"
@@ -202,7 +204,7 @@ static struct hubp_funcs dcn21_hubp_funcs = {
        .hubp_enable_tripleBuffer = hubp2_enable_triplebuffer,
        .hubp_is_triplebuffer_enabled = hubp2_is_triplebuffer_enabled,
        .hubp_program_surface_flip_and_addr = hubp2_program_surface_flip_and_addr,
-       .hubp_program_surface_config = hubp2_program_surface_config,
+       .hubp_program_surface_config = hubp1_program_surface_config,
        .hubp_is_flip_pending = hubp1_is_flip_pending,
        .hubp_setup = hubp21_setup,
        .hubp_setup_interdependent = hubp2_setup_interdependent,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c
new file mode 100644 (file)
index 0000000..b25215c
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2016 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_helpers.h"
+#include "core_types.h"
+#include "resource.h"
+#include "dce/dce_hwseq.h"
+#include "dcn20/dcn20_hwseq.h"
+#include "vmid.h"
+#include "reg_helper.h"
+#include "hw/clk_mgr.h"
+
+
+#define DC_LOGGER_INIT(logger)
+
+#define CTX \
+       hws->ctx
+#define REG(reg)\
+       hws->regs->reg
+
+#undef FN
+#define FN(reg_name, field_name) \
+       hws->shifts->field_name, hws->masks->field_name
+
+/* Temporary read settings, future will get values from kmd directly */
+static void mmhub_update_page_table_config(struct dcn_hubbub_phys_addr_config *config,
+               struct dce_hwseq *hws)
+{
+       uint32_t page_table_base_hi;
+       uint32_t page_table_base_lo;
+
+       REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
+                       PAGE_DIRECTORY_ENTRY_HI32, &page_table_base_hi);
+       REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
+                       PAGE_DIRECTORY_ENTRY_LO32, &page_table_base_lo);
+
+       config->gart_config.page_table_base_addr = ((uint64_t)page_table_base_hi << 32) | page_table_base_lo;
+
+}
+
+static int dcn21_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config)
+{
+       struct dcn_hubbub_phys_addr_config config;
+
+       config.system_aperture.fb_top = pa_config->system_aperture.fb_top;
+       config.system_aperture.fb_offset = pa_config->system_aperture.fb_offset;
+       config.system_aperture.fb_base = pa_config->system_aperture.fb_base;
+       config.system_aperture.agp_top = pa_config->system_aperture.agp_top;
+       config.system_aperture.agp_bot = pa_config->system_aperture.agp_bot;
+       config.system_aperture.agp_base = pa_config->system_aperture.agp_base;
+       config.gart_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr;
+       config.gart_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr;
+       config.gart_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr;
+
+       mmhub_update_page_table_config(&config, hws);
+
+       return dc->res_pool->hubbub->funcs->init_dchub_sys_ctx(dc->res_pool->hubbub, &config);
+}
+
+// work around for Renoir s0i3, if register is programmed, bypass golden init.
+
+static bool dcn21_s0i3_golden_init_wa(struct dc *dc)
+{
+       struct dce_hwseq *hws = dc->hwseq;
+       uint32_t value = 0;
+
+       value = REG_READ(MICROSECOND_TIME_BASE_DIV);
+
+       return value != 0x00120464;
+}
+
+void dcn21_exit_optimized_pwr_state(
+               const struct dc *dc,
+               struct dc_state *context)
+{
+       dc->clk_mgr->funcs->update_clocks(
+                       dc->clk_mgr,
+                       context,
+                       false);
+}
+
+void dcn21_optimize_pwr_state(
+               const struct dc *dc,
+               struct dc_state *context)
+{
+       dc->clk_mgr->funcs->update_clocks(
+                       dc->clk_mgr,
+                       context,
+                       true);
+}
+
+void dcn21_hw_sequencer_construct(struct dc *dc)
+{
+       dcn20_hw_sequencer_construct(dc);
+       dc->hwss.init_sys_ctx = dcn21_init_sys_ctx;
+       dc->hwss.s0i3_golden_init_wa = dcn21_s0i3_golden_init_wa;
+       dc->hwss.optimize_pwr_state = dcn21_optimize_pwr_state;
+       dc->hwss.exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.h
new file mode 100644 (file)
index 0000000..be67b62
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+* Copyright 2016 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 __DC_HWSS_DCN21_H__
+#define __DC_HWSS_DCN21_H__
+
+struct dc;
+
+void dcn21_hw_sequencer_construct(struct dc *dc);
+
+#endif /* __DC_HWSS_DCN21_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_link_encoder.c
new file mode 100644 (file)
index 0000000..e8a504c
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ * 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 "reg_helper.h"
+
+#include <linux/delay.h>
+#include "core_types.h"
+#include "link_encoder.h"
+#include "dcn21_link_encoder.h"
+#include "stream_encoder.h"
+
+#include "i2caux_interface.h"
+#include "dc_bios_types.h"
+
+#include "gpio_service_interface.h"
+
+#define CTX \
+       enc10->base.ctx
+#define DC_LOGGER \
+       enc10->base.ctx->logger
+
+#define REG(reg)\
+       (enc10->link_regs->reg)
+
+#undef FN
+#define FN(reg_name, field_name) \
+       enc10->link_shift->field_name, enc10->link_mask->field_name
+
+#define IND_REG(index) \
+       (enc10->link_regs->index)
+
+static struct mpll_cfg dcn21_mpll_cfg_ref[] = {
+       // RBR
+       {
+               .hdmimode_enable = 0,
+               .ref_range = 1,
+               .ref_clk_mpllb_div = 1,
+               .mpllb_ssc_en = 1,
+               .mpllb_div5_clk_en = 1,
+               .mpllb_multiplier = 238,
+               .mpllb_fracn_en = 0,
+               .mpllb_fracn_quot = 0,
+               .mpllb_fracn_rem = 0,
+               .mpllb_fracn_den = 1,
+               .mpllb_ssc_up_spread = 0,
+               .mpllb_ssc_peak = 44237,
+               .mpllb_ssc_stepsize = 59454,
+               .mpllb_div_clk_en = 0,
+               .mpllb_div_multiplier = 0,
+               .mpllb_hdmi_div = 0,
+               .mpllb_tx_clk_div = 2,
+               .tx_vboost_lvl = 5,
+               .mpllb_pmix_en = 1,
+               .mpllb_word_div2_en = 0,
+               .mpllb_ana_v2i = 2,
+               .mpllb_ana_freq_vco = 2,
+               .mpllb_ana_cp_int = 9,
+               .mpllb_ana_cp_prop = 15,
+               .hdmi_pixel_clk_div = 0,
+       },
+       // HBR
+       {
+               .hdmimode_enable = 0,
+               .ref_range = 1,
+               .ref_clk_mpllb_div = 1,
+               .mpllb_ssc_en = 1,
+               .mpllb_div5_clk_en = 1,
+               .mpllb_multiplier = 192,
+               .mpllb_fracn_en = 1,
+               .mpllb_fracn_quot = 32768,
+               .mpllb_fracn_rem = 0,
+               .mpllb_fracn_den = 1,
+               .mpllb_ssc_up_spread = 0,
+               .mpllb_ssc_peak = 36864,
+               .mpllb_ssc_stepsize = 49545,
+               .mpllb_div_clk_en = 0,
+               .mpllb_div_multiplier = 0,
+               .mpllb_hdmi_div = 0,
+               .mpllb_tx_clk_div = 1,
+               .tx_vboost_lvl = 5,
+               .mpllb_pmix_en = 1,
+               .mpllb_word_div2_en = 0,
+               .mpllb_ana_v2i = 2,
+               .mpllb_ana_freq_vco = 3,
+               .mpllb_ana_cp_int = 9,
+               .mpllb_ana_cp_prop = 15,
+               .hdmi_pixel_clk_div = 0,
+       },
+       //HBR2
+       {
+               .hdmimode_enable = 0,
+               .ref_range = 1,
+               .ref_clk_mpllb_div = 1,
+               .mpllb_ssc_en = 1,
+               .mpllb_div5_clk_en = 1,
+               .mpllb_multiplier = 192,
+               .mpllb_fracn_en = 1,
+               .mpllb_fracn_quot = 32768,
+               .mpllb_fracn_rem = 0,
+               .mpllb_fracn_den = 1,
+               .mpllb_ssc_up_spread = 0,
+               .mpllb_ssc_peak = 36864,
+               .mpllb_ssc_stepsize = 49545,
+               .mpllb_div_clk_en = 0,
+               .mpllb_div_multiplier = 0,
+               .mpllb_hdmi_div = 0,
+               .mpllb_tx_clk_div = 0,
+               .tx_vboost_lvl = 5,
+               .mpllb_pmix_en = 1,
+               .mpllb_word_div2_en = 0,
+               .mpllb_ana_v2i = 2,
+               .mpllb_ana_freq_vco = 3,
+               .mpllb_ana_cp_int = 9,
+               .mpllb_ana_cp_prop = 15,
+               .hdmi_pixel_clk_div = 0,
+       },
+       //HBR3
+       {
+               .hdmimode_enable = 0,
+               .ref_range = 1,
+               .ref_clk_mpllb_div = 1,
+               .mpllb_ssc_en = 1,
+               .mpllb_div5_clk_en = 1,
+               .mpllb_multiplier = 304,
+               .mpllb_fracn_en = 1,
+               .mpllb_fracn_quot = 49152,
+               .mpllb_fracn_rem = 0,
+               .mpllb_fracn_den = 1,
+               .mpllb_ssc_up_spread = 0,
+               .mpllb_ssc_peak = 55296,
+               .mpllb_ssc_stepsize = 74318,
+               .mpllb_div_clk_en = 0,
+               .mpllb_div_multiplier = 0,
+               .mpllb_hdmi_div = 0,
+               .mpllb_tx_clk_div = 0,
+               .tx_vboost_lvl = 5,
+               .mpllb_pmix_en = 1,
+               .mpllb_word_div2_en = 0,
+               .mpllb_ana_v2i = 2,
+               .mpllb_ana_freq_vco = 1,
+               .mpllb_ana_cp_int = 7,
+               .mpllb_ana_cp_prop = 16,
+               .hdmi_pixel_clk_div = 0,
+       },
+};
+
+
+static bool update_cfg_data(
+               struct dcn10_link_encoder *enc10,
+               const struct dc_link_settings *link_settings,
+               struct dpcssys_phy_seq_cfg *cfg)
+{
+       int i;
+
+       cfg->load_sram_fw = false;
+       cfg->use_calibration_setting = true;
+
+       //TODO: need to implement a proper lane mapping for Renoir.
+       for (i = 0; i < 4; i++)
+               cfg->lane_en[i] = true;
+
+       switch (link_settings->link_rate) {
+       case LINK_RATE_LOW:
+               cfg->mpll_cfg = dcn21_mpll_cfg_ref[0];
+               break;
+       case LINK_RATE_HIGH:
+               cfg->mpll_cfg = dcn21_mpll_cfg_ref[1];
+               break;
+       case LINK_RATE_HIGH2:
+               cfg->mpll_cfg = dcn21_mpll_cfg_ref[2];
+               break;
+       case LINK_RATE_HIGH3:
+               cfg->mpll_cfg = dcn21_mpll_cfg_ref[3];
+               break;
+       default:
+               DC_LOG_ERROR("%s: No supported link rate found %X!\n",
+                               __func__, link_settings->link_rate);
+               return false;
+       }
+
+       return true;
+}
+
+void dcn21_link_encoder_get_max_link_cap(struct link_encoder *enc,
+       struct dc_link_settings *link_settings)
+{
+       struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+       uint32_t value;
+
+       REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, &value);
+
+       if (!value && link_settings->lane_count > LANE_COUNT_TWO)
+               link_settings->lane_count = LANE_COUNT_TWO;
+}
+
+bool dcn21_link_encoder_is_in_alt_mode(struct link_encoder *enc)
+{
+       struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+       uint32_t value;
+
+       REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, &value);
+
+       // if value == 1 alt mode is disabled, otherwise it is enabled
+       return !value;
+}
+
+bool dcn21_link_encoder_acquire_phy(struct link_encoder *enc)
+{
+       struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+       int value;
+
+       if (enc->features.flags.bits.DP_IS_USB_C) {
+               REG_GET(RDPCSTX_PHY_CNTL6,
+                               RDPCS_PHY_DPALT_DISABLE, &value);
+
+               if (value == 1) {
+                       ASSERT(0);
+                       return false;
+               }
+               REG_UPDATE(RDPCSTX_PHY_CNTL6,
+                               RDPCS_PHY_DPALT_DISABLE_ACK, 0);
+
+               udelay(40);
+
+               REG_GET(RDPCSTX_PHY_CNTL6,
+                                               RDPCS_PHY_DPALT_DISABLE, &value);
+               if (value == 1) {
+                       ASSERT(0);
+                       REG_UPDATE(RDPCSTX_PHY_CNTL6,
+                                       RDPCS_PHY_DPALT_DISABLE_ACK, 1);
+                       return false;
+               }
+       }
+
+       REG_UPDATE(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_REF_CLK_EN, 1);
+
+       return true;
+}
+
+
+
+static void dcn21_link_encoder_release_phy(struct link_encoder *enc)
+{
+       struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+
+       if (enc->features.flags.bits.DP_IS_USB_C) {
+               REG_UPDATE(RDPCSTX_PHY_CNTL6,
+                               RDPCS_PHY_DPALT_DISABLE_ACK, 1);
+       }
+
+       REG_UPDATE(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_REF_CLK_EN, 0);
+
+}
+
+void dcn21_link_encoder_enable_dp_output(
+       struct link_encoder *enc,
+       const struct dc_link_settings *link_settings,
+       enum clock_source_id clock_source)
+{
+       struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+       struct dcn21_link_encoder *enc21 = (struct dcn21_link_encoder *) enc10;
+       struct dpcssys_phy_seq_cfg *cfg = &enc21->phy_seq_cfg;
+
+       if (!dcn21_link_encoder_acquire_phy(enc))
+               return;
+
+       if (!enc->ctx->dc->debug.avoid_vbios_exec_table) {
+               dcn10_link_encoder_enable_dp_output(enc, link_settings, clock_source);
+               return;
+       }
+
+       if (!update_cfg_data(enc10, link_settings, cfg))
+               return;
+
+       enc1_configure_encoder(enc10, link_settings);
+
+       dcn10_link_encoder_setup(enc, SIGNAL_TYPE_DISPLAY_PORT);
+
+}
+
+void dcn21_link_encoder_enable_dp_mst_output(
+       struct link_encoder *enc,
+       const struct dc_link_settings *link_settings,
+       enum clock_source_id clock_source)
+{
+       if (!dcn21_link_encoder_acquire_phy(enc))
+               return;
+
+       dcn10_link_encoder_enable_dp_mst_output(enc, link_settings, clock_source);
+}
+
+void dcn21_link_encoder_disable_output(
+       struct link_encoder *enc,
+       enum signal_type signal)
+{
+       dcn10_link_encoder_disable_output(enc, signal);
+
+       if (dc_is_dp_signal(signal))
+               dcn21_link_encoder_release_phy(enc);
+}
+
+
+static const struct link_encoder_funcs dcn21_link_enc_funcs = {
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+       .read_state = link_enc2_read_state,
+#endif
+       .validate_output_with_stream =
+               dcn10_link_encoder_validate_output_with_stream,
+       .hw_init = enc2_hw_init,
+       .setup = dcn10_link_encoder_setup,
+       .enable_tmds_output = dcn10_link_encoder_enable_tmds_output,
+       .enable_dp_output = dcn21_link_encoder_enable_dp_output,
+       .enable_dp_mst_output = dcn21_link_encoder_enable_dp_mst_output,
+       .disable_output = dcn21_link_encoder_disable_output,
+       .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings,
+       .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern,
+       .update_mst_stream_allocation_table =
+               dcn10_link_encoder_update_mst_stream_allocation_table,
+       .psr_program_dp_dphy_fast_training =
+                       dcn10_psr_program_dp_dphy_fast_training,
+       .psr_program_secondary_packet = dcn10_psr_program_secondary_packet,
+       .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe,
+       .enable_hpd = dcn10_link_encoder_enable_hpd,
+       .disable_hpd = dcn10_link_encoder_disable_hpd,
+       .is_dig_enabled = dcn10_is_dig_enabled,
+       .destroy = dcn10_link_encoder_destroy,
+       .fec_set_enable = enc2_fec_set_enable,
+       .fec_set_ready = enc2_fec_set_ready,
+       .fec_is_active = enc2_fec_is_active,
+       .get_dig_frontend = dcn10_get_dig_frontend,
+       .is_in_alt_mode = dcn21_link_encoder_is_in_alt_mode,
+       .get_max_link_cap = dcn21_link_encoder_get_max_link_cap,
+};
+
+void dcn21_link_encoder_construct(
+       struct dcn21_link_encoder *enc21,
+       const struct encoder_init_data *init_data,
+       const struct encoder_feature_support *enc_features,
+       const struct dcn10_link_enc_registers *link_regs,
+       const struct dcn10_link_enc_aux_registers *aux_regs,
+       const struct dcn10_link_enc_hpd_registers *hpd_regs,
+       const struct dcn10_link_enc_shift *link_shift,
+       const struct dcn10_link_enc_mask *link_mask)
+{
+       struct bp_encoder_cap_info bp_cap_info = {0};
+       const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs;
+       enum bp_result result = BP_RESULT_OK;
+       struct dcn10_link_encoder *enc10 = &enc21->enc10;
+
+       enc10->base.funcs = &dcn21_link_enc_funcs;
+       enc10->base.ctx = init_data->ctx;
+       enc10->base.id = init_data->encoder;
+
+       enc10->base.hpd_source = init_data->hpd_source;
+       enc10->base.connector = init_data->connector;
+
+       enc10->base.preferred_engine = ENGINE_ID_UNKNOWN;
+
+       enc10->base.features = *enc_features;
+
+       enc10->base.transmitter = init_data->transmitter;
+
+       /* set the flag to indicate whether driver poll the I2C data pin
+        * while doing the DP sink detect
+        */
+
+/*     if (dal_adapter_service_is_feature_supported(as,
+               FEATURE_DP_SINK_DETECT_POLL_DATA_PIN))
+               enc10->base.features.flags.bits.
+                       DP_SINK_DETECT_POLL_DATA_PIN = true;*/
+
+       enc10->base.output_signals =
+               SIGNAL_TYPE_DVI_SINGLE_LINK |
+               SIGNAL_TYPE_DVI_DUAL_LINK |
+               SIGNAL_TYPE_LVDS |
+               SIGNAL_TYPE_DISPLAY_PORT |
+               SIGNAL_TYPE_DISPLAY_PORT_MST |
+               SIGNAL_TYPE_EDP |
+               SIGNAL_TYPE_HDMI_TYPE_A;
+
+       /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE.
+        * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY.
+        * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer
+        * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS.
+        * Prefer DIG assignment is decided by board design.
+        * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design
+        * and VBIOS will filter out 7 UNIPHY for DCE 8.0.
+        * By this, adding DIGG should not hurt DCE 8.0.
+        * This will let DCE 8.1 share DCE 8.0 as much as possible
+        */
+
+       enc10->link_regs = link_regs;
+       enc10->aux_regs = aux_regs;
+       enc10->hpd_regs = hpd_regs;
+       enc10->link_shift = link_shift;
+       enc10->link_mask = link_mask;
+
+       switch (enc10->base.transmitter) {
+       case TRANSMITTER_UNIPHY_A:
+               enc10->base.preferred_engine = ENGINE_ID_DIGA;
+       break;
+       case TRANSMITTER_UNIPHY_B:
+               enc10->base.preferred_engine = ENGINE_ID_DIGB;
+       break;
+       case TRANSMITTER_UNIPHY_C:
+               enc10->base.preferred_engine = ENGINE_ID_DIGC;
+       break;
+       case TRANSMITTER_UNIPHY_D:
+               enc10->base.preferred_engine = ENGINE_ID_DIGD;
+       break;
+       case TRANSMITTER_UNIPHY_E:
+               enc10->base.preferred_engine = ENGINE_ID_DIGE;
+       break;
+       case TRANSMITTER_UNIPHY_F:
+               enc10->base.preferred_engine = ENGINE_ID_DIGF;
+       break;
+       case TRANSMITTER_UNIPHY_G:
+               enc10->base.preferred_engine = ENGINE_ID_DIGG;
+       break;
+       default:
+               ASSERT_CRITICAL(false);
+               enc10->base.preferred_engine = ENGINE_ID_UNKNOWN;
+       }
+
+       /* default to one to mirror Windows behavior */
+       enc10->base.features.flags.bits.HDMI_6GB_EN = 1;
+
+       result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios,
+                                               enc10->base.id, &bp_cap_info);
+
+       /* Override features with DCE-specific values */
+       if (result == BP_RESULT_OK) {
+               enc10->base.features.flags.bits.IS_HBR2_CAPABLE =
+                               bp_cap_info.DP_HBR2_EN;
+               enc10->base.features.flags.bits.IS_HBR3_CAPABLE =
+                               bp_cap_info.DP_HBR3_EN;
+               enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN;
+               enc10->base.features.flags.bits.DP_IS_USB_C =
+                               bp_cap_info.DP_IS_USB_C;
+       } else {
+               DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
+                               __func__,
+                               result);
+       }
+       if (enc10->base.ctx->dc->debug.hdmi20_disable) {
+               enc10->base.features.flags.bits.HDMI_6GB_EN = 0;
+       }
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_link_encoder.h
new file mode 100644 (file)
index 0000000..1d7a1a5
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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 __DC_LINK_ENCODER__DCN21_H__
+#define __DC_LINK_ENCODER__DCN21_H__
+
+#include "dcn20/dcn20_link_encoder.h"
+
+struct dcn21_link_encoder {
+       struct dcn10_link_encoder enc10;
+       struct dpcssys_phy_seq_cfg phy_seq_cfg;
+};
+
+#define LINK_ENCODER_MASK_SH_LIST_DCN21(mask_sh)\
+       LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh),\
+       LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL0_XBAR_SOURCE, mask_sh),\
+       LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL1_XBAR_SOURCE, mask_sh),\
+       LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL2_XBAR_SOURCE, mask_sh),\
+       LE_SF(UNIPHYA_CHANNEL_XBAR_CNTL, UNIPHY_CHANNEL3_XBAR_SOURCE, mask_sh), \
+       SRI(RDPCSTX_PHY_FUSE2, RDPCSTX, id), \
+       SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \
+       SR(RDPCSTX0_RDPCSTX_SCRATCH)
+
+void dcn21_link_encoder_enable_dp_output(
+       struct link_encoder *enc,
+       const struct dc_link_settings *link_settings,
+       enum clock_source_id clock_source);
+
+void dcn21_link_encoder_construct(
+       struct dcn21_link_encoder *enc21,
+       const struct encoder_init_data *init_data,
+       const struct encoder_feature_support *enc_features,
+       const struct dcn10_link_enc_registers *link_regs,
+       const struct dcn10_link_enc_aux_registers *aux_regs,
+       const struct dcn10_link_enc_hpd_registers *hpd_regs,
+       const struct dcn10_link_enc_shift *link_shift,
+       const struct dcn10_link_enc_mask *link_mask);
+
+#endif
index de182185fe1f558ff83f00b6b2c7e917941525bb..bd16a8bfc951226c321fdc5b38a5aed21be4020b 100644 (file)
@@ -23,8 +23,6 @@
  *
  */
 
-#include <linux/slab.h>
-
 #include "dm_services.h"
 #include "dc.h"
 
 #include "irq/dcn21/irq_service_dcn21.h"
 #include "dcn20/dcn20_dpp.h"
 #include "dcn20/dcn20_optc.h"
-#include "dcn20/dcn20_hwseq.h"
+#include "dcn21/dcn21_hwseq.h"
 #include "dce110/dce110_hw_sequencer.h"
 #include "dcn20/dcn20_opp.h"
 #include "dcn20/dcn20_dsc.h"
-#include "dcn20/dcn20_link_encoder.h"
+#include "dcn21/dcn21_link_encoder.h"
 #include "dcn20/dcn20_stream_encoder.h"
 #include "dce/dce_clock_source.h"
 #include "dce/dce_audio.h"
@@ -84,6 +82,7 @@
 
 
 struct _vcs_dpi_ip_params_st dcn2_1_ip = {
+       .odm_capable = 1,
        .gpuvm_enable = 0,
        .hostvm_enable = 0,
        .gpuvm_max_page_table_levels = 1,
@@ -205,11 +204,11 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = {
                                .state = 4,
                                .dcfclk_mhz = 810.0,
                                .fabricclk_mhz = 1600.0,
-                               .dispclk_mhz = 1015.0,
-                               .dppclk_mhz = 1015.0,
-                               .phyclk_mhz = 810.0,
+                               .dispclk_mhz = 1395.0,
+                               .dppclk_mhz = 1285.0,
+                               .phyclk_mhz = 1325.0,
                                .socclk_mhz = 953.0,
-                               .dscclk_mhz = 318.334,
+                               .dscclk_mhz = 489.0,
                                .dram_speed_mts = 4266.0,
                        },
                        /*Extra state, no dispclk ramping*/
@@ -217,18 +216,18 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = {
                                .state = 5,
                                .dcfclk_mhz = 810.0,
                                .fabricclk_mhz = 1600.0,
-                               .dispclk_mhz = 1015.0,
-                               .dppclk_mhz = 1015.0,
-                               .phyclk_mhz = 810.0,
+                               .dispclk_mhz = 1395.0,
+                               .dppclk_mhz = 1285.0,
+                               .phyclk_mhz = 1325.0,
                                .socclk_mhz = 953.0,
-                               .dscclk_mhz = 318.334,
+                               .dscclk_mhz = 489.0,
                                .dram_speed_mts = 4266.0,
                        },
 
                },
 
-       .sr_exit_time_us = 9.0,
-       .sr_enter_plus_exit_time_us = 11.0,
+       .sr_exit_time_us = 12.5,
+       .sr_enter_plus_exit_time_us = 17.0,
        .urgent_latency_us = 4.0,
        .urgent_latency_pixel_data_only_us = 4.0,
        .urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
@@ -350,6 +349,30 @@ static const struct bios_registers bios_regs = {
                NBIO_SR(BIOS_SCRATCH_6)
 };
 
+static const struct dce_dmcu_registers dmcu_regs = {
+               DMCU_DCN10_REG_LIST()
+};
+
+static const struct dce_dmcu_shift dmcu_shift = {
+               DMCU_MASK_SH_LIST_DCN10(__SHIFT)
+};
+
+static const struct dce_dmcu_mask dmcu_mask = {
+               DMCU_MASK_SH_LIST_DCN10(_MASK)
+};
+
+static const struct dce_abm_registers abm_regs = {
+               ABM_DCN20_REG_LIST()
+};
+
+static const struct dce_abm_shift abm_shift = {
+               ABM_MASK_SH_LIST_DCN20(__SHIFT)
+};
+
+static const struct dce_abm_mask abm_mask = {
+               ABM_MASK_SH_LIST_DCN20(_MASK)
+};
+
 #ifdef CONFIG_DRM_AMD_DC_DMUB
 static const struct dcn21_dmcub_registers dmcub_regs = {
                DMCUB_REG_LIST_DCN()
@@ -628,6 +651,14 @@ static const struct dcn10_stream_enc_registers stream_enc_regs[] = {
        stream_enc_regs(4),
 };
 
+static const struct dce110_aux_registers_shift aux_shift = {
+       DCN_AUX_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dce110_aux_registers_mask aux_mask = {
+       DCN_AUX_MASK_SH_LIST(_MASK)
+};
+
 static const struct dcn10_stream_encoder_shift se_shift = {
                SE_COMMON_MASK_SH_LIST_DCN20(__SHIFT)
 };
@@ -636,6 +667,8 @@ static const struct dcn10_stream_encoder_mask se_mask = {
                SE_COMMON_MASK_SH_LIST_DCN20(_MASK)
 };
 
+static void dcn21_pp_smu_destroy(struct pp_smu_funcs **pp_smu);
+
 static struct input_pixel_processor *dcn21_ipp_create(
        struct dc_context *ctx, uint32_t inst)
 {
@@ -683,7 +716,10 @@ static struct dce_aux *dcn21_aux_engine_create(
 
        dce110_aux_engine_construct(aux_engine, ctx, inst,
                                    SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,
-                                   &aux_engine_regs[inst]);
+                                   &aux_engine_regs[inst],
+                                       &aux_mask,
+                                       &aux_shift,
+                                       ctx->dc->caps.extended_aux_timeout_support);
 
        return &aux_engine->base;
 }
@@ -726,11 +762,12 @@ static const struct resource_caps res_cap_rn = {
                .num_timing_generator = 4,
                .num_opp = 4,
                .num_video_plane = 4,
-               .num_audio = 6, // 6 audio endpoints.  4 audio streams
+               .num_audio = 4, // 4 audio endpoints.  4 audio streams
                .num_stream_encoder = 5,
                .num_pll = 5,  // maybe 3 because the last two used for USB-c
                .num_dwb = 1,
                .num_ddc = 5,
+               .num_vmid = 1,
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
                .num_dsc = 3,
 #endif
@@ -800,11 +837,11 @@ static const struct dc_debug_options debug_defaults_drv = {
                .disable_dcc = DCC_ENABLE,
                .vsr_support = true,
                .performance_trace = false,
-               .max_downscale_src_width = 5120,/*upto 5K*/
+               .max_downscale_src_width = 3840,
                .disable_pplib_wm_range = false,
                .scl_reset_length10 = true,
                .sanity_checks = true,
-               .disable_48mhz_pwrdwn = true,
+               .disable_48mhz_pwrdwn = false,
 };
 
 static const struct dc_debug_options debug_defaults_diags = {
@@ -939,7 +976,7 @@ static void destruct(struct dcn21_resource_pool *pool)
                dcn_dccg_destroy(&pool->base.dccg);
 
        if (pool->base.pp_smu != NULL)
-               dcn20_pp_smu_destroy(&pool->base.pp_smu);
+               dcn21_pp_smu_destroy(&pool->base.pp_smu);
 }
 
 
@@ -974,6 +1011,29 @@ static void calculate_wm_set_for_vlevel(
 
 }
 
+static void patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb)
+{
+       kernel_fpu_begin();
+       if (dc->bb_overrides.sr_exit_time_ns) {
+               bb->sr_exit_time_us = dc->bb_overrides.sr_exit_time_ns / 1000.0;
+       }
+
+       if (dc->bb_overrides.sr_enter_plus_exit_time_ns) {
+               bb->sr_enter_plus_exit_time_us =
+                               dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
+       }
+
+       if (dc->bb_overrides.urgent_latency_ns) {
+               bb->urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
+       }
+
+       if (dc->bb_overrides.dram_clock_change_latency_ns) {
+               bb->dram_clock_change_latency_us =
+                               dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
+       }
+       kernel_fpu_end();
+}
+
 void dcn21_calculate_wm(
                struct dc *dc, struct dc_state *context,
                display_e2e_pipe_params_st *pipes,
@@ -988,6 +1048,8 @@ void dcn21_calculate_wm(
 
        ASSERT(bw_params);
 
+       patch_bounding_box(dc, &context->bw_ctx.dml.soc);
+
        for (i = 0, pipe_idx = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
                        if (!context->res_ctx.pipe_ctx[i].stream)
                                continue;
@@ -1278,7 +1340,6 @@ static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
        dcn2_1_ip.max_num_otg = pool->base.res_cap->num_timing_generator;
        dcn2_1_ip.max_num_dpp = pool->base.pipe_count;
        dcn2_1_soc.num_chans = bw_params->num_channels;
-       dcn2_1_soc.num_states = 0;
 
        for (i = 0; i < clk_table->num_entries; i++) {
 
@@ -1288,8 +1349,9 @@ static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
                dcn2_1_soc.clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz;
                /* This is probably wrong, TODO: find correct calculation */
                dcn2_1_soc.clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 16 / 1000;
-               dcn2_1_soc.num_states++;
        }
+       dcn2_1_soc.clock_limits[i] = dcn2_1_soc.clock_limits[i - i];
+       dcn2_1_soc.num_states = i;
 }
 
 /* Temporary Place holder until we can get them from fuse */
@@ -1317,32 +1379,42 @@ static struct dpm_clocks dummy_clocks = {
 
 };
 
-enum pp_smu_status dummy_set_wm_ranges(struct pp_smu *pp,
+static enum pp_smu_status dummy_set_wm_ranges(struct pp_smu *pp,
                struct pp_smu_wm_range_sets *ranges)
 {
        return PP_SMU_RESULT_OK;
 }
 
-enum pp_smu_status dummy_get_dpm_clock_table(struct pp_smu *pp,
+static enum pp_smu_status dummy_get_dpm_clock_table(struct pp_smu *pp,
                struct dpm_clocks *clock_table)
 {
        *clock_table = dummy_clocks;
        return PP_SMU_RESULT_OK;
 }
 
-struct pp_smu_funcs *dcn21_pp_smu_create(struct dc_context *ctx)
+static struct pp_smu_funcs *dcn21_pp_smu_create(struct dc_context *ctx)
 {
        struct pp_smu_funcs *pp_smu = kzalloc(sizeof(*pp_smu), GFP_KERNEL);
 
-       pp_smu->ctx.ver = PP_SMU_VER_RN;
+       if (!pp_smu)
+               return pp_smu;
+
+       if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment) || IS_DIAG_DC(ctx->dce_environment)) {
+               pp_smu->ctx.ver = PP_SMU_VER_RN;
+               pp_smu->rn_funcs.get_dpm_clock_table = dummy_get_dpm_clock_table;
+               pp_smu->rn_funcs.set_wm_ranges = dummy_set_wm_ranges;
+       } else {
 
-       pp_smu->rn_funcs.get_dpm_clock_table = dummy_get_dpm_clock_table;
-       pp_smu->rn_funcs.set_wm_ranges = dummy_set_wm_ranges;
+               dm_pp_get_funcs(ctx, pp_smu);
+
+               if (pp_smu->ctx.ver != PP_SMU_VER_RN)
+                       pp_smu = memset(pp_smu, 0, sizeof(struct pp_smu_funcs));
+       }
 
        return pp_smu;
 }
 
-void dcn21_pp_smu_destroy(struct pp_smu_funcs **pp_smu)
+static void dcn21_pp_smu_destroy(struct pp_smu_funcs **pp_smu)
 {
        if (pp_smu && *pp_smu) {
                kfree(*pp_smu);
@@ -1400,6 +1472,7 @@ static struct dce_hwseq *dcn21_hwseq_create(
                hws->regs = &hwseq_reg;
                hws->shifts = &hwseq_shift;
                hws->masks = &hwseq_mask;
+               hws->wa.DEGVIDCN21 = true;
        }
        return hws;
 }
@@ -1418,9 +1491,103 @@ static const struct resource_create_funcs res_create_maximus_funcs = {
        .create_hwseq = dcn21_hwseq_create,
 };
 
+static const struct encoder_feature_support link_enc_feature = {
+               .max_hdmi_deep_color = COLOR_DEPTH_121212,
+               .max_hdmi_pixel_clock = 600000,
+               .hdmi_ycbcr420_supported = true,
+               .dp_ycbcr420_supported = true,
+               .flags.bits.IS_HBR2_CAPABLE = true,
+               .flags.bits.IS_HBR3_CAPABLE = true,
+               .flags.bits.IS_TPS3_CAPABLE = true,
+               .flags.bits.IS_TPS4_CAPABLE = true
+};
+
+
+#define link_regs(id, phyid)\
+[id] = {\
+       LE_DCN10_REG_LIST(id), \
+       UNIPHY_DCN2_REG_LIST(phyid), \
+       SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \
+}
+
+static const struct dcn10_link_enc_registers link_enc_regs[] = {
+       link_regs(0, A),
+       link_regs(1, B),
+       link_regs(2, C),
+       link_regs(3, D),
+       link_regs(4, E),
+};
+
+#define aux_regs(id)\
+[id] = {\
+       DCN2_AUX_REG_LIST(id)\
+}
+
+static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = {
+               aux_regs(0),
+               aux_regs(1),
+               aux_regs(2),
+               aux_regs(3),
+               aux_regs(4)
+};
+
+#define hpd_regs(id)\
+[id] = {\
+       HPD_REG_LIST(id)\
+}
+
+static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = {
+               hpd_regs(0),
+               hpd_regs(1),
+               hpd_regs(2),
+               hpd_regs(3),
+               hpd_regs(4)
+};
+
+static const struct dcn10_link_enc_shift le_shift = {
+       LINK_ENCODER_MASK_SH_LIST_DCN20(__SHIFT)
+};
+
+static const struct dcn10_link_enc_mask le_mask = {
+       LINK_ENCODER_MASK_SH_LIST_DCN20(_MASK)
+};
+
+static struct link_encoder *dcn21_link_encoder_create(
+       const struct encoder_init_data *enc_init_data)
+{
+       struct dcn21_link_encoder *enc21 =
+               kzalloc(sizeof(struct dcn21_link_encoder), GFP_KERNEL);
+
+       if (!enc21)
+               return NULL;
+
+       dcn21_link_encoder_construct(enc21,
+                                     enc_init_data,
+                                     &link_enc_feature,
+                                     &link_enc_regs[enc_init_data->transmitter],
+                                     &link_enc_aux_regs[enc_init_data->channel - 1],
+                                     &link_enc_hpd_regs[enc_init_data->hpd_source],
+                                     &le_shift,
+                                     &le_mask);
+
+       return &enc21->enc10.base;
+}
+#define CTX ctx
+
+#define REG(reg_name) \
+       (DCN_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name)
+
+static uint32_t read_pipe_fuses(struct dc_context *ctx)
+{
+       uint32_t value = REG_READ(CC_DC_PIPE_DIS);
+       /* RV1 support max 4 pipes */
+       value = value & 0xf;
+       return value;
+}
+
 static struct resource_funcs dcn21_res_pool_funcs = {
        .destroy = dcn21_destroy_resource_pool,
-       .link_enc_create = dcn20_link_encoder_create,
+       .link_enc_create = dcn21_link_encoder_create,
        .validate_bandwidth = dcn21_validate_bandwidth,
        .add_stream_to_ctx = dcn20_add_stream_to_ctx,
        .remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
@@ -1437,9 +1604,10 @@ static bool construct(
        struct dc *dc,
        struct dcn21_resource_pool *pool)
 {
-       int i;
+       int i, j;
        struct dc_context *ctx = dc->ctx;
        struct irq_service_init_data init_data;
+       uint32_t pipe_fuses = read_pipe_fuses(ctx);
 
        ctx->dc_bios->regs = &bios_regs;
 
@@ -1457,7 +1625,9 @@ static bool construct(
         *************************************************/
        pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
 
-       pool->base.pipe_count = 4;
+       /* max pipe num for ASIC before check pipe fuses */
+       pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
+
        dc->caps.max_downscale_ratio = 200;
        dc->caps.i2c_speed_in_khz = 100;
        dc->caps.max_cursor_size = 256;
@@ -1467,6 +1637,7 @@ static bool construct(
        dc->caps.max_slave_planes = 1;
        dc->caps.post_blend_color_processing = true;
        dc->caps.force_dp_tps4_for_cp2520 = true;
+       dc->caps.extended_aux_timeout_support = true;
 
        if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
                dc->debug = debug_defaults_drv;
@@ -1516,6 +1687,26 @@ static bool construct(
                goto create_fail;
        }
 
+       pool->base.dmcu = dcn20_dmcu_create(ctx,
+                       &dmcu_regs,
+                       &dmcu_shift,
+                       &dmcu_mask);
+       if (pool->base.dmcu == NULL) {
+               dm_error("DC: failed to create dmcu!\n");
+               BREAK_TO_DEBUGGER();
+               goto create_fail;
+       }
+
+       pool->base.abm = dce_abm_create(ctx,
+                       &abm_regs,
+                       &abm_shift,
+                       &abm_mask);
+       if (pool->base.abm == NULL) {
+               dm_error("DC: failed to create abm!\n");
+               BREAK_TO_DEBUGGER();
+               goto create_fail;
+       }
+
 #ifdef CONFIG_DRM_AMD_DC_DMUB
        pool->base.dmcub = dcn21_dmcub_create(ctx,
                        &dmcub_regs,
@@ -1537,8 +1728,15 @@ static bool construct(
        if (!pool->base.irqs)
                goto create_fail;
 
+       j = 0;
        /* mem input -> ipp -> dpp -> opp -> TG */
        for (i = 0; i < pool->base.pipe_count; i++) {
+               /* if pipe is disabled, skip instance of HW pipe,
+                * i.e, skip ASIC register instance
+                */
+               if ((pipe_fuses & (1 << i)) != 0)
+                       continue;
+
                pool->base.hubps[i] = dcn21_hubp_create(ctx, i);
                if (pool->base.hubps[i] == NULL) {
                        BREAK_TO_DEBUGGER();
@@ -1562,6 +1760,23 @@ static bool construct(
                                "DC: failed to create dpps!\n");
                        goto create_fail;
                }
+
+               pool->base.opps[i] = dcn21_opp_create(ctx, i);
+               if (pool->base.opps[i] == NULL) {
+                       BREAK_TO_DEBUGGER();
+                       dm_error(
+                               "DC: failed to create output pixel processor!\n");
+                       goto create_fail;
+               }
+
+               pool->base.timing_generators[i] = dcn21_timing_generator_create(
+                               ctx, i);
+               if (pool->base.timing_generators[i] == NULL) {
+                       BREAK_TO_DEBUGGER();
+                       dm_error("DC: failed to create tg!\n");
+                       goto create_fail;
+               }
+               j++;
        }
 
        for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
@@ -1582,27 +1797,9 @@ static bool construct(
                pool->base.sw_i2cs[i] = NULL;
        }
 
-       for (i = 0; i < pool->base.res_cap->num_opp; i++) {
-               pool->base.opps[i] = dcn21_opp_create(ctx, i);
-               if (pool->base.opps[i] == NULL) {
-                       BREAK_TO_DEBUGGER();
-                       dm_error(
-                               "DC: failed to create output pixel processor!\n");
-                       goto create_fail;
-               }
-       }
-
-       for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
-               pool->base.timing_generators[i] = dcn21_timing_generator_create(
-                               ctx, i);
-               if (pool->base.timing_generators[i] == NULL) {
-                       BREAK_TO_DEBUGGER();
-                       dm_error("DC: failed to create tg!\n");
-                       goto create_fail;
-               }
-       }
-
-       pool->base.timing_generator_count = i;
+       pool->base.timing_generator_count = j;
+       pool->base.pipe_count = j;
+       pool->base.mpcc_count = j;
 
        pool->base.mpc = dcn21_mpc_create(ctx);
        if (pool->base.mpc == NULL) {
@@ -1645,7 +1842,7 @@ static bool construct(
                        &res_create_funcs : &res_create_maximus_funcs)))
                        goto create_fail;
 
-       dcn20_hw_sequencer_construct(dc);
+       dcn21_hw_sequencer_construct(dc);
 
        dc->caps.max_planes =  pool->base.pipe_count;
 
diff --git a/drivers/gpu/drm/amd/display/dc/dm_cp_psp.h b/drivers/gpu/drm/amd/display/dc/dm_cp_psp.h
new file mode 100644 (file)
index 0000000..626d22d
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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
+ *
+ */
+
+#ifndef DM_CP_PSP_IF__H
+#define DM_CP_PSP_IF__H
+
+struct dc_link;
+
+struct cp_psp_stream_config {
+       uint8_t otg_inst;
+       uint8_t link_enc_inst;
+       uint8_t stream_enc_inst;
+       void *dm_stream_ctx;
+       bool dpms_off;
+};
+
+struct cp_psp_funcs {
+       void (*update_stream_config)(void *handle, struct cp_psp_stream_config *config);
+};
+
+struct cp_psp {
+       void *handle;
+       struct cp_psp_funcs funcs;
+};
+
+
+#endif /* DM_CP_PSP_IF__H */
index b6b4333737f21828ae1382226c504d2fe392ff99..94b75e9426074ebd345b702161de4e7e2ac0b930 100644 (file)
@@ -74,7 +74,7 @@ void dm_helpers_dp_mst_clear_payload_allocation_table(
 /*
  * Polls for ACT (allocation change trigger) handled and
  */
-bool dm_helpers_dp_mst_poll_for_allocation_change_trigger(
+enum act_return_status dm_helpers_dp_mst_poll_for_allocation_change_trigger(
                struct dc_context *ctx,
                const struct dc_stream_state *stream);
 /*
index c03a441ee638a0175dfc5dcadf8a2a6b16d64c17..b01db61b6181ce1d35a13db6f4bfa996cae2d55e 100644 (file)
@@ -249,12 +249,10 @@ struct pp_smu_funcs_nv {
 };
 #endif
 
-#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
-
 #define PP_SMU_NUM_SOCCLK_DPM_LEVELS  8
-#define PP_SMU_NUM_DCFCLK_DPM_LEVELS  4
-#define PP_SMU_NUM_FCLK_DPM_LEVELS    4
-#define PP_SMU_NUM_MEMCLK_DPM_LEVELS  4
+#define PP_SMU_NUM_DCFCLK_DPM_LEVELS  8
+#define PP_SMU_NUM_FCLK_DPM_LEVELS    8
+#define PP_SMU_NUM_MEMCLK_DPM_LEVELS  8
 
 struct dpm_clock {
   uint32_t  Freq;    // In MHz
@@ -288,7 +286,6 @@ struct pp_smu_funcs_rn {
        enum pp_smu_status (*get_dpm_clock_table) (struct pp_smu *pp,
                        struct dpm_clocks *clock_table);
 };
-#endif
 
 struct pp_smu_funcs {
        struct pp_smu ctx;
index 0fafd693ffb41efb29d718e9ef986eef23aac253..841ed6c23f93ad41bb62157d5aa12fe0ecfd72ce 100644 (file)
@@ -38,6 +38,7 @@
 
 #define BPP_INVALID 0
 #define BPP_BLENDED_PIPE 0xffffffff
+#define DCN20_MAX_DSC_IMAGE_WIDTH 5184
 
 static double adjust_ReturnBW(
                struct display_mode_lib *mode_lib,
@@ -3901,6 +3902,10 @@ void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode
                                mode_lib->vba.MaximumSwathWidthInLineBuffer);
        }
        for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
+               double MaxMaxDispclkRoundedDown = RoundToDFSGranularityDown(
+                       mode_lib->vba.MaxDispclk[mode_lib->vba.soc.num_states],
+                       mode_lib->vba.DISPCLKDPPCLKVCOSpeed);
+
                for (j = 0; j < 2; j++) {
                        mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity = RoundToDFSGranularityDown(
                                mode_lib->vba.MaxDispclk[i],
@@ -3925,7 +3930,9 @@ void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode
                                                && i == mode_lib->vba.soc.num_states)
                                        mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine = mode_lib->vba.PixelClock[k] / 2
                                                        * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0);
-                               if (mode_lib->vba.ODMCapability == false || mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine <= mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity) {
+                               if (mode_lib->vba.ODMCapability == false ||
+                                               (locals->PlaneRequiredDISPCLKWithoutODMCombine <= MaxMaxDispclkRoundedDown
+                                                       && (!locals->DSCEnabled[k] || locals->HActive[k] <= DCN20_MAX_DSC_IMAGE_WIDTH))) {
                                        locals->ODMCombineEnablePerState[i][k] = false;
                                        mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine;
                                } else {
index 878bf4782ce611703e05eeb0ef1d1af300c2e39d..2c7455e22a65569884f8c86740f49c17e0293508 100644 (file)
@@ -207,7 +207,7 @@ static void extract_rq_regs(struct display_mode_lib *mode_lib,
        rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height);
        rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height);
 
-       // FIXME: take the max between luma, chroma chunk size?
+       // TODO: take the max between luma, chroma chunk size?
        // okay for now, as we are setting chunk_bytes to 8kb anyways
        if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { //32kb
                rq_regs->drq_expansion_mode = 0;
@@ -677,7 +677,7 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib,
        unsigned int meta_pitch = 0;
        unsigned int ppe = mode_422 ? 2 : 1;
 
-       // FIXME check if ppe apply for both luma and chroma in 422 case
+       // TODO check if ppe apply for both luma and chroma in 422 case
        if (is_chroma) {
                vp_width = pipe_src_param.viewport_width_c / ppe;
                vp_height = pipe_src_param.viewport_height_c;
@@ -959,7 +959,7 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
        // Source
 //             dcc_en              = src.dcc;
        dual_plane = is_dual_plane((enum source_format_class)(src->source_format));
-       mode_422 = 0; // FIXME
+       mode_422 = 0; // TODO
        access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed
 //      bytes_per_element_l = get_bytes_per_element(source_format_class(src.source_format), 0);
 //      bytes_per_element_c = get_bytes_per_element(source_format_class(src.source_format), 1);
@@ -1655,7 +1655,7 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib,
                cur_width_ub = dml_ceil((double) cur_src_width / (double) cur_req_width, 1)
                                * (double) cur_req_width;
                cur_req_per_width = cur_width_ub / (double) cur_req_width;
-               hactive_cur = (double) cur_src_width / hscl_ratio; // FIXME: oswin to think about what to do for cursor
+               hactive_cur = (double) cur_src_width / hscl_ratio; // TODO: oswin to think about what to do for cursor
 
                if (vratio_pre_l <= 1.0) {
                        *refcyc_per_req_delivery_pre_cur = hactive_cur * ref_freq_to_pix_freq
index ed8bf5f723c93b38621558ad5c1f27f4a8335087..1e6aeb1bd2bf6f0a910b3884aa538ac1714b8b09 100644 (file)
@@ -207,7 +207,7 @@ static void extract_rq_regs(struct display_mode_lib *mode_lib,
        rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height);
        rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height);
 
-       // FIXME: take the max between luma, chroma chunk size?
+       // TODO: take the max between luma, chroma chunk size?
        // okay for now, as we are setting chunk_bytes to 8kb anyways
        if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { //32kb
                rq_regs->drq_expansion_mode = 0;
@@ -677,7 +677,7 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib,
        unsigned int meta_pitch = 0;
        unsigned int ppe = mode_422 ? 2 : 1;
 
-       // FIXME check if ppe apply for both luma and chroma in 422 case
+       // TODO check if ppe apply for both luma and chroma in 422 case
        if (is_chroma) {
                vp_width = pipe_src_param.viewport_width_c / ppe;
                vp_height = pipe_src_param.viewport_height_c;
@@ -959,7 +959,7 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
        // Source
 //             dcc_en              = src.dcc;
        dual_plane = is_dual_plane((enum source_format_class)(src->source_format));
-       mode_422 = 0; // FIXME
+       mode_422 = 0; // TODO
        access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed
 //      bytes_per_element_l = get_bytes_per_element(source_format_class(src.source_format), 0);
 //      bytes_per_element_c = get_bytes_per_element(source_format_class(src.source_format), 1);
@@ -1655,7 +1655,7 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib,
                cur_width_ub = dml_ceil((double) cur_src_width / (double) cur_req_width, 1)
                                * (double) cur_req_width;
                cur_req_per_width = cur_width_ub / (double) cur_req_width;
-               hactive_cur = (double) cur_src_width / hscl_ratio; // FIXME: oswin to think about what to do for cursor
+               hactive_cur = (double) cur_src_width / hscl_ratio; // TODO: oswin to think about what to do for cursor
 
                if (vratio_pre_l <= 1.0) {
                        *refcyc_per_req_delivery_pre_cur = hactive_cur * ref_freq_to_pix_freq
index 3b6ed60dcd3510115833bb418d1ccef3d614998b..ba77957aefe38361c4d19fb0bfcd4453a16d8b56 100644 (file)
@@ -65,6 +65,7 @@ typedef struct {
 
 #define BPP_INVALID 0
 #define BPP_BLENDED_PIPE 0xffffffff
+#define DCN21_MAX_DSC_IMAGE_WIDTH 5184
 
 static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib);
 static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation(
@@ -3379,6 +3380,8 @@ static unsigned int TruncToValidBPP(
                                return 30;
                        else if (DecimalBPP >= 24 && (DesiredBPP == 0 || DesiredBPP == 24))
                                return 24;
+                       else if (DecimalBPP >= 18 && (DesiredBPP == 0 || DesiredBPP == 18))
+                               return 18;
                        else
                                return BPP_INVALID;
                }
@@ -3936,6 +3939,10 @@ void dml21_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                mode_lib->vba.MaximumSwathWidthInLineBuffer);
        }
        for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
+               double MaxMaxDispclkRoundedDown = RoundToDFSGranularityDown(
+                       mode_lib->vba.MaxDispclk[mode_lib->vba.soc.num_states],
+                       mode_lib->vba.DISPCLKDPPCLKVCOSpeed);
+
                for (j = 0; j < 2; j++) {
                        mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity = RoundToDFSGranularityDown(
                                mode_lib->vba.MaxDispclk[i],
@@ -3965,7 +3972,9 @@ void dml21_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                                && i == mode_lib->vba.soc.num_states)
                                        mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine = mode_lib->vba.PixelClock[k] / 2
                                                        * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0);
-                               if (mode_lib->vba.ODMCapability == false || mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine <= mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity) {
+                               if (mode_lib->vba.ODMCapability == false ||
+                                               (locals->PlaneRequiredDISPCLKWithoutODMCombine <= MaxMaxDispclkRoundedDown
+                                                       && (!locals->DSCEnabled[k] || locals->HActive[k] <= DCN21_MAX_DSC_IMAGE_WIDTH))) {
                                        locals->ODMCombineEnablePerState[i][k] = false;
                                        mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine;
                                } else {
index f4c1ef9046bf1dcabbf11b503b4a06e47036ed6e..83f84cdd4055cf07140a1a045d42f5f261a4d855 100644 (file)
@@ -269,7 +269,7 @@ struct writeback_st {
 
 struct _vcs_dpi_display_output_params_st {
        int dp_lanes;
-       int output_bpp;
+       double output_bpp;
        int dsc_enable;
        int wb_enable;
        int num_active_wb;
index 65cf4edddaff7e97743a1981506fede748a33e99..362dc6ea98ae5b0b054d27a8c543996a201ab4ca 100644 (file)
@@ -434,6 +434,8 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib)
                                dst->odm_combine;
                mode_lib->vba.OutputFormat[mode_lib->vba.NumberOfActivePlanes] =
                                (enum output_format_class) (dout->output_format);
+               mode_lib->vba.OutputBpp[mode_lib->vba.NumberOfActivePlanes] =
+                               dout->output_bpp;
                mode_lib->vba.Output[mode_lib->vba.NumberOfActivePlanes] =
                                (enum output_encoder_class) (dout->output_type);
 
index ad8571f5a142fb3405d78dd165119f4a2a4a4d3e..4c3e9cc30167953a1b29f38d100589d4e65ef6ec 100644 (file)
@@ -243,7 +243,7 @@ void dml1_extract_rq_regs(
        rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height);
        rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height);
 
-       /* FIXME: take the max between luma, chroma chunk size?
+       /* TODO: take the max between luma, chroma chunk size?
         * okay for now, as we are setting chunk_bytes to 8kb anyways
         */
        if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { /*32kb */
@@ -602,7 +602,7 @@ static void get_surf_rq_param(
        unsigned int log2_dpte_group_length;
        unsigned int func_meta_row_height, func_dpte_row_height;
 
-       /* FIXME check if ppe apply for both luma and chroma in 422 case */
+       /* TODO check if ppe apply for both luma and chroma in 422 case */
        if (is_chroma) {
                vp_width = pipe_src_param.viewport_width_c / ppe;
                vp_height = pipe_src_param.viewport_height_c;
@@ -1141,7 +1141,7 @@ void dml1_rq_dlg_get_dlg_params(
        ASSERT(disp_dlg_regs->refcyc_h_blank_end < (unsigned int) dml_pow(2, 13));
        disp_dlg_regs->dlg_vblank_end = interlaced ? (vblank_end / 2) : vblank_end; /* 15 bits */
 
-       prefetch_xy_calc_in_dcfclk = 24.0; /* FIXME: ip_param */
+       prefetch_xy_calc_in_dcfclk = 24.0; /* TODO: ip_param */
        min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz;
        t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz;
        min_ttu_vblank = dlg_sys_param.t_urg_wm_us;
@@ -1182,7 +1182,7 @@ void dml1_rq_dlg_get_dlg_params(
        dcc_en = e2e_pipe_param.pipe.src.dcc;
        dual_plane = is_dual_plane(
                        (enum source_format_class) e2e_pipe_param.pipe.src.source_format);
-       mode_422 = 0; /* FIXME */
+       mode_422 = 0; /* TODO */
        access_dir = (e2e_pipe_param.pipe.src.source_scan == dm_vert); /* vp access direction: horizontal or vertical accessed */
        bytes_per_element_l = get_bytes_per_element(
                        (enum source_format_class) e2e_pipe_param.pipe.src.source_format,
@@ -1837,7 +1837,7 @@ void dml1_rq_dlg_get_dlg_params(
                cur0_width_ub = dml_ceil((double) cur0_src_width / (double) cur0_req_width, 1)
                                * (double) cur0_req_width;
                cur0_req_per_width = cur0_width_ub / (double) cur0_req_width;
-               hactive_cur0 = (double) cur0_src_width / hratios_cur0; /* FIXME: oswin to think about what to do for cursor */
+               hactive_cur0 = (double) cur0_src_width / hratios_cur0; /* TODO: oswin to think about what to do for cursor */
 
                if (vratio_pre_l <= 1.0) {
                        refcyc_per_req_delivery_pre_cur0 = hactive_cur0 * ref_freq_to_pix_freq
index 5995bcdfed542bc10d9a49014c40fd5f042e9dbf..e60f760585e460ff0f4d5c1cc40473cd13463d1c 100644 (file)
@@ -23,8 +23,7 @@
  */
 
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
-#include "dc.h"
-#include "core_types.h"
+#include "dc_hw_types.h"
 #include "dsc.h"
 #include <drm/drm_dp_helper.h>
 
@@ -47,6 +46,59 @@ const struct dc_dsc_policy dsc_policy = {
 
 /* This module's internal functions */
 
+static uint32_t dc_dsc_bandwidth_in_kbps_from_timing(
+       const struct dc_crtc_timing *timing)
+{
+       uint32_t bits_per_channel = 0;
+       uint32_t kbps;
+
+       if (timing->flags.DSC) {
+               kbps = (timing->pix_clk_100hz * timing->dsc_cfg.bits_per_pixel);
+               kbps = kbps / 160 + ((kbps % 160) ? 1 : 0);
+               return kbps;
+       }
+
+       switch (timing->display_color_depth) {
+       case COLOR_DEPTH_666:
+               bits_per_channel = 6;
+               break;
+       case COLOR_DEPTH_888:
+               bits_per_channel = 8;
+               break;
+       case COLOR_DEPTH_101010:
+               bits_per_channel = 10;
+               break;
+       case COLOR_DEPTH_121212:
+               bits_per_channel = 12;
+               break;
+       case COLOR_DEPTH_141414:
+               bits_per_channel = 14;
+               break;
+       case COLOR_DEPTH_161616:
+               bits_per_channel = 16;
+               break;
+       default:
+               break;
+       }
+
+       ASSERT(bits_per_channel != 0);
+
+       kbps = timing->pix_clk_100hz / 10;
+       kbps *= bits_per_channel;
+
+       if (timing->flags.Y_ONLY != 1) {
+               /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/
+               kbps *= 3;
+               if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
+                       kbps /= 2;
+               else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
+                       kbps = kbps * 2 / 3;
+       }
+
+       return kbps;
+
+}
+
 static bool dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size, int *buff_block_size)
 {
 
@@ -178,12 +230,11 @@ static bool dsc_bpp_increment_div_from_dpcd(int bpp_increment_dpcd, uint32_t *bp
 }
 
 static void get_dsc_enc_caps(
-       const struct dc *dc,
+       const struct display_stream_compressor *dsc,
        struct dsc_enc_caps *dsc_enc_caps,
        int pixel_clock_100Hz)
 {
        // This is a static HW query, so we can use any DSC
-       struct display_stream_compressor *dsc = dc->res_pool->dscs[0];
 
        memset(dsc_enc_caps, 0, sizeof(struct dsc_enc_caps));
        if (dsc)
@@ -290,7 +341,7 @@ static void get_dsc_bandwidth_range(
                struct dc_dsc_bw_range *range)
 {
        /* native stream bandwidth */
-       range->stream_kbps = dc_bandwidth_in_kbps_from_timing(timing);
+       range->stream_kbps = dc_dsc_bandwidth_in_kbps_from_timing(timing);
 
        /* max dsc target bpp */
        range->max_kbps = dsc_div_by_10_round_up(max_bpp * timing->pix_clk_100hz);
@@ -512,6 +563,7 @@ static bool setup_dsc_config(
                const struct dsc_enc_caps *dsc_enc_caps,
                int target_bandwidth_kbps,
                const struct dc_crtc_timing *timing,
+               int min_slice_height_override,
                struct dc_dsc_config *dsc_cfg)
 {
        struct dsc_enc_caps dsc_common_caps;
@@ -680,7 +732,10 @@ static bool setup_dsc_config(
 
        // Slice height (i.e. number of slices per column): start with policy and pick the first one that height is divisible by.
        // For 4:2:0 make sure the slice height is divisible by 2 as well.
-       slice_height = min(dsc_policy.min_sice_height, pic_height);
+       if (min_slice_height_override == 0)
+               slice_height = min(dsc_policy.min_sice_height, pic_height);
+       else
+               slice_height = min(min_slice_height_override, pic_height);
 
        while (slice_height < pic_height && (pic_height % slice_height != 0 ||
                (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 && slice_height % 2 != 0)))
@@ -802,7 +857,8 @@ bool dc_dsc_parse_dsc_dpcd(const uint8_t *dpcd_dsc_basic_data, const uint8_t *dp
  * If DSC is not possible, leave '*range' untouched.
  */
 bool dc_dsc_compute_bandwidth_range(
-               const struct dc *dc,
+               const struct display_stream_compressor *dsc,
+               const uint32_t dsc_min_slice_height_override,
                const uint32_t min_bpp,
                const uint32_t max_bpp,
                const struct dsc_dec_dpcd_caps *dsc_sink_caps,
@@ -814,16 +870,14 @@ bool dc_dsc_compute_bandwidth_range(
        struct dsc_enc_caps dsc_common_caps;
        struct dc_dsc_config config;
 
-       get_dsc_enc_caps(dc, &dsc_enc_caps, timing->pix_clk_100hz);
+       get_dsc_enc_caps(dsc, &dsc_enc_caps, timing->pix_clk_100hz);
 
        is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, &dsc_enc_caps,
                        timing->pixel_encoding, &dsc_common_caps);
 
        if (is_dsc_possible)
-               is_dsc_possible = setup_dsc_config(dsc_sink_caps,
-                               &dsc_enc_caps,
-                               0,
-                               timing, &config);
+               is_dsc_possible = setup_dsc_config(dsc_sink_caps, &dsc_enc_caps, 0, timing,
+                               dsc_min_slice_height_override, &config);
 
        if (is_dsc_possible)
                get_dsc_bandwidth_range(min_bpp, max_bpp, &dsc_common_caps, timing, range);
@@ -832,8 +886,9 @@ bool dc_dsc_compute_bandwidth_range(
 }
 
 bool dc_dsc_compute_config(
-               const struct dc *dc,
+               const struct display_stream_compressor *dsc,
                const struct dsc_dec_dpcd_caps *dsc_sink_caps,
+               const uint32_t dsc_min_slice_height_override,
                uint32_t target_bandwidth_kbps,
                const struct dc_crtc_timing *timing,
                struct dc_dsc_config *dsc_cfg)
@@ -841,11 +896,11 @@ bool dc_dsc_compute_config(
        bool is_dsc_possible = false;
        struct dsc_enc_caps dsc_enc_caps;
 
-       get_dsc_enc_caps(dc, &dsc_enc_caps, timing->pix_clk_100hz);
+       get_dsc_enc_caps(dsc, &dsc_enc_caps, timing->pix_clk_100hz);
        is_dsc_possible = setup_dsc_config(dsc_sink_caps,
                        &dsc_enc_caps,
                        target_bandwidth_kbps,
-                       timing, dsc_cfg);
+                       timing, dsc_min_slice_height_override, dsc_cfg);
        return is_dsc_possible;
 }
 #endif /* CONFIG_DRM_AMD_DC_DSC_SUPPORT */
index ca51e83f8764dba6ca5c4133d3753b85f65cee64..76c4b12d6824b0d5b4db1a3ef6de27605b03d9d3 100644 (file)
@@ -177,7 +177,6 @@ void calc_rc_params(struct rc_params *rc, enum colour_mode cm, enum bits_per_com
 {
        float bpp_group;
        float initial_xmit_delay_factor;
-       int source_bpp;
        int padding_pixels;
        int i;
 
@@ -217,8 +216,6 @@ void calc_rc_params(struct rc_params *rc, enum colour_mode cm, enum bits_per_com
                        rc->initial_xmit_delay++;
        }
 
-       source_bpp = MODE_SELECT(bpc * 3, bpc * 2, bpc * 1.5);
-
        rc->flatness_min_qp     = ((bpc == BPC_8) ?  (3) : ((bpc == BPC_10) ? (7)  : (11))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
        rc->flatness_max_qp     = ((bpc == BPC_8) ? (12) : ((bpc == BPC_10) ? (16) : (20))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
        rc->flatness_det_thresh = 2 << (bpc - 8);
index f8f85490e77e20d8494e9356a6e4133cbaedf7ca..f67c18375bfdb7ae63adce970a42cfebf969a19a 100644 (file)
@@ -321,8 +321,6 @@ void dal_gpio_destroy(
                return;
        }
 
-       dal_gpio_close(*gpio);
-
        switch ((*gpio)->id) {
        case GPIO_ID_DDC_DATA:
                kfree((*gpio)->hw_container.ddc);
index d03165e71dc651764e37ff1dcfbef441bda33670..92280cc05e2dbe083a2165ae8042db0771146730 100644 (file)
@@ -169,7 +169,6 @@ void dal_gpio_destroy_generic_mux(
                return;
        }
 
-       dal_gpio_close(*mux);
        dal_gpio_destroy(mux);
        kfree(*mux);
 
@@ -460,7 +459,6 @@ void dal_gpio_destroy_irq(
                return;
        }
 
-       dal_gpio_close(*irq);
        dal_gpio_destroy(irq);
        kfree(*irq);
 
diff --git a/drivers/gpu/drm/amd/display/dc/hdcp/Makefile b/drivers/gpu/drm/amd/display/dc/hdcp/Makefile
new file mode 100644 (file)
index 0000000..4170b6e
--- /dev/null
@@ -0,0 +1,28 @@
+# Copyright 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) 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 'hdcp' sub-component of DAL.
+#
+
+HDCP_MSG = hdcp_msg.o
+
+AMD_DAL_HDCP_MSG = $(addprefix $(AMDDALPATH)/dc/hdcp/,$(HDCP_MSG))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_HDCP_MSG)
diff --git a/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c b/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c
new file mode 100644 (file)
index 0000000..cf6ef38
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * Copyright 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) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <linux/slab.h>
+
+#include "dm_services.h"
+#include "dm_helpers.h"
+#include "include/hdcp_types.h"
+#include "include/i2caux_interface.h"
+#include "include/signal_types.h"
+#include "core_types.h"
+#include "dc_link_ddc.h"
+#include "link_hwss.h"
+
+#define DC_LOGGER \
+       link->ctx->logger
+#define HDCP14_KSV_SIZE 5
+#define HDCP14_MAX_KSV_FIFO_SIZE 127*HDCP14_KSV_SIZE
+
+static const bool hdcp_cmd_is_read[] = {
+       [HDCP_MESSAGE_ID_READ_BKSV] = true,
+       [HDCP_MESSAGE_ID_READ_RI_R0] = true,
+       [HDCP_MESSAGE_ID_READ_PJ] = true,
+       [HDCP_MESSAGE_ID_WRITE_AKSV] = false,
+       [HDCP_MESSAGE_ID_WRITE_AINFO] = false,
+       [HDCP_MESSAGE_ID_WRITE_AN] = false,
+       [HDCP_MESSAGE_ID_READ_VH_X] = true,
+       [HDCP_MESSAGE_ID_READ_VH_0] = true,
+       [HDCP_MESSAGE_ID_READ_VH_1] = true,
+       [HDCP_MESSAGE_ID_READ_VH_2] = true,
+       [HDCP_MESSAGE_ID_READ_VH_3] = true,
+       [HDCP_MESSAGE_ID_READ_VH_4] = true,
+       [HDCP_MESSAGE_ID_READ_BCAPS] = true,
+       [HDCP_MESSAGE_ID_READ_BSTATUS] = true,
+       [HDCP_MESSAGE_ID_READ_KSV_FIFO] = true,
+       [HDCP_MESSAGE_ID_READ_BINFO] = true,
+       [HDCP_MESSAGE_ID_HDCP2VERSION] = true,
+       [HDCP_MESSAGE_ID_RX_CAPS] = true,
+       [HDCP_MESSAGE_ID_WRITE_AKE_INIT] = false,
+       [HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = true,
+       [HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = false,
+       [HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = false,
+       [HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = true,
+       [HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = true,
+       [HDCP_MESSAGE_ID_WRITE_LC_INIT] = false,
+       [HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = true,
+       [HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = false,
+       [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = true,
+       [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = false,
+       [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = false,
+       [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = true,
+       [HDCP_MESSAGE_ID_READ_RXSTATUS] = true,
+       [HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = false
+};
+
+static const uint8_t hdcp_i2c_offsets[] = {
+       [HDCP_MESSAGE_ID_READ_BKSV] = 0x0,
+       [HDCP_MESSAGE_ID_READ_RI_R0] = 0x8,
+       [HDCP_MESSAGE_ID_READ_PJ] = 0xA,
+       [HDCP_MESSAGE_ID_WRITE_AKSV] = 0x10,
+       [HDCP_MESSAGE_ID_WRITE_AINFO] = 0x15,
+       [HDCP_MESSAGE_ID_WRITE_AN] = 0x18,
+       [HDCP_MESSAGE_ID_READ_VH_X] = 0x20,
+       [HDCP_MESSAGE_ID_READ_VH_0] = 0x20,
+       [HDCP_MESSAGE_ID_READ_VH_1] = 0x24,
+       [HDCP_MESSAGE_ID_READ_VH_2] = 0x28,
+       [HDCP_MESSAGE_ID_READ_VH_3] = 0x2C,
+       [HDCP_MESSAGE_ID_READ_VH_4] = 0x30,
+       [HDCP_MESSAGE_ID_READ_BCAPS] = 0x40,
+       [HDCP_MESSAGE_ID_READ_BSTATUS] = 0x41,
+       [HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x43,
+       [HDCP_MESSAGE_ID_READ_BINFO] = 0xFF,
+       [HDCP_MESSAGE_ID_HDCP2VERSION] = 0x50,
+       [HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x60,
+       [HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x80,
+       [HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x60,
+       [HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x60,
+       [HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x80,
+       [HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x80,
+       [HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x60,
+       [HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x80,
+       [HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x60,
+       [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x80,
+       [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x60,
+       [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x60,
+       [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x80,
+       [HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x70
+};
+
+struct protection_properties {
+       bool supported;
+       bool (*process_transaction)(
+               struct dc_link *link,
+               struct hdcp_protection_message *message_info);
+};
+
+static const struct protection_properties non_supported_protection = {
+       .supported = false
+};
+
+static bool hdmi_14_process_transaction(
+       struct dc_link *link,
+       struct hdcp_protection_message *message_info)
+{
+       uint8_t *buff = NULL;
+       bool result;
+       const uint8_t hdcp_i2c_addr_link_primary = 0x3a; /* 0x74 >> 1*/
+       const uint8_t hdcp_i2c_addr_link_secondary = 0x3b; /* 0x76 >> 1*/
+       struct i2c_command i2c_command;
+       uint8_t offset = hdcp_i2c_offsets[message_info->msg_id];
+       struct i2c_payload i2c_payloads[] = {
+               { true, 0, 1, &offset },
+               /* actual hdcp payload, will be filled later, zeroed for now*/
+               { 0 }
+       };
+
+       switch (message_info->link) {
+       case HDCP_LINK_SECONDARY:
+               i2c_payloads[0].address = hdcp_i2c_addr_link_secondary;
+               i2c_payloads[1].address = hdcp_i2c_addr_link_secondary;
+               break;
+       case HDCP_LINK_PRIMARY:
+       default:
+               i2c_payloads[0].address = hdcp_i2c_addr_link_primary;
+               i2c_payloads[1].address = hdcp_i2c_addr_link_primary;
+               break;
+       }
+
+       if (hdcp_cmd_is_read[message_info->msg_id]) {
+               i2c_payloads[1].write = false;
+               i2c_command.number_of_payloads = ARRAY_SIZE(i2c_payloads);
+               i2c_payloads[1].length = message_info->length;
+               i2c_payloads[1].data = message_info->data;
+       } else {
+               i2c_command.number_of_payloads = 1;
+               buff = kzalloc(message_info->length + 1, GFP_KERNEL);
+
+               if (!buff)
+                       return false;
+
+               buff[0] = offset;
+               memmove(&buff[1], message_info->data, message_info->length);
+               i2c_payloads[0].length = message_info->length + 1;
+               i2c_payloads[0].data = buff;
+       }
+
+       i2c_command.payloads = i2c_payloads;
+       i2c_command.engine = I2C_COMMAND_ENGINE_HW;//only HW
+       i2c_command.speed = link->ddc->ctx->dc->caps.i2c_speed_in_khz;
+
+       result = dm_helpers_submit_i2c(
+                       link->ctx,
+                       link,
+                       &i2c_command);
+
+       if (buff)
+               kfree(buff);
+
+       return result;
+}
+
+static const struct protection_properties hdmi_14_protection = {
+       .supported = true,
+       .process_transaction = hdmi_14_process_transaction
+};
+
+static const uint32_t hdcp_dpcd_addrs[] = {
+       [HDCP_MESSAGE_ID_READ_BKSV] = 0x68000,
+       [HDCP_MESSAGE_ID_READ_RI_R0] = 0x68005,
+       [HDCP_MESSAGE_ID_READ_PJ] = 0xFFFFFFFF,
+       [HDCP_MESSAGE_ID_WRITE_AKSV] = 0x68007,
+       [HDCP_MESSAGE_ID_WRITE_AINFO] = 0x6803B,
+       [HDCP_MESSAGE_ID_WRITE_AN] = 0x6800c,
+       [HDCP_MESSAGE_ID_READ_VH_X] = 0x68014,
+       [HDCP_MESSAGE_ID_READ_VH_0] = 0x68014,
+       [HDCP_MESSAGE_ID_READ_VH_1] = 0x68018,
+       [HDCP_MESSAGE_ID_READ_VH_2] = 0x6801c,
+       [HDCP_MESSAGE_ID_READ_VH_3] = 0x68020,
+       [HDCP_MESSAGE_ID_READ_VH_4] = 0x68024,
+       [HDCP_MESSAGE_ID_READ_BCAPS] = 0x68028,
+       [HDCP_MESSAGE_ID_READ_BSTATUS] = 0x68029,
+       [HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x6802c,
+       [HDCP_MESSAGE_ID_READ_BINFO] = 0x6802a,
+       [HDCP_MESSAGE_ID_RX_CAPS] = 0x6921d,
+       [HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x69000,
+       [HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x6900b,
+       [HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x69220,
+       [HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x692a0,
+       [HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x692c0,
+       [HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x692e0,
+       [HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x692f0,
+       [HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x692f8,
+       [HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x69318,
+       [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x69330,
+       [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x693e0,
+       [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x693f0,
+       [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x69473,
+       [HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x69493,
+       [HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x69494
+};
+
+static bool dpcd_access_helper(
+       struct dc_link *link,
+       uint32_t length,
+       uint8_t *data,
+       uint32_t dpcd_addr,
+       bool is_read)
+{
+       enum dc_status status;
+       uint32_t cur_length = 0;
+       uint32_t offset = 0;
+       uint32_t ksv_read_size = 0x6803b - 0x6802c;
+
+       /* Read KSV, need repeatedly handle */
+       if (dpcd_addr == 0x6802c) {
+               if (length % HDCP14_KSV_SIZE) {
+                       DC_LOG_ERROR("%s: KsvFifo Size(%d) is not a multiple of HDCP14_KSV_SIZE(%d)\n",
+                               __func__,
+                               length,
+                               HDCP14_KSV_SIZE);
+               }
+               if (length > HDCP14_MAX_KSV_FIFO_SIZE) {
+                       DC_LOG_ERROR("%s: KsvFifo Size(%d) is greater than HDCP14_MAX_KSV_FIFO_SIZE(%d)\n",
+                               __func__,
+                               length,
+                               HDCP14_MAX_KSV_FIFO_SIZE);
+               }
+
+               DC_LOG_ERROR("%s: Reading %d Ksv(s) from KsvFifo\n",
+                       __func__,
+                       length / HDCP14_KSV_SIZE);
+
+               while (length > 0) {
+                       if (length > ksv_read_size) {
+                               status = core_link_read_dpcd(
+                                       link,
+                                       dpcd_addr + offset,
+                                       data + offset,
+                                       ksv_read_size);
+
+                               data += ksv_read_size;
+                               length -= ksv_read_size;
+                       } else {
+                               status = core_link_read_dpcd(
+                                       link,
+                                       dpcd_addr + offset,
+                                       data + offset,
+                                       length);
+
+                               data += length;
+                               length = 0;
+                       }
+
+                       if (status != DC_OK)
+                               return false;
+               }
+       } else {
+               while (length > 0) {
+                       if (length > DEFAULT_AUX_MAX_DATA_SIZE)
+                               cur_length = DEFAULT_AUX_MAX_DATA_SIZE;
+                       else
+                               cur_length = length;
+
+                       if (is_read) {
+                               status = core_link_read_dpcd(
+                                       link,
+                                       dpcd_addr + offset,
+                                       data + offset,
+                                       cur_length);
+                       } else {
+                               status = core_link_write_dpcd(
+                                       link,
+                                       dpcd_addr + offset,
+                                       data + offset,
+                                       cur_length);
+                       }
+
+                       if (status != DC_OK)
+                               return false;
+
+                       length -= cur_length;
+                       offset += cur_length;
+               }
+       }
+       return true;
+}
+
+static bool dp_11_process_transaction(
+       struct dc_link *link,
+       struct hdcp_protection_message *message_info)
+{
+       return dpcd_access_helper(
+               link,
+               message_info->length,
+               message_info->data,
+               hdcp_dpcd_addrs[message_info->msg_id],
+               hdcp_cmd_is_read[message_info->msg_id]);
+}
+
+static const struct protection_properties dp_11_protection = {
+       .supported = true,
+       .process_transaction = dp_11_process_transaction
+};
+
index f189307750ab3544679b132a904f8ff1ee4320eb..eee78a73d88c5b0aff2c9edfe20fa399c4d114a8 100644 (file)
@@ -52,7 +52,9 @@ void enable_surface_flip_reporting(struct dc_plane_state *plane_state,
 #include "clock_source.h"
 #include "audio.h"
 #include "dm_pp_smu.h"
-
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+#include "dm_cp_psp.h"
+#endif
 
 /************ link *****************/
 struct link_init_data {
@@ -231,6 +233,7 @@ struct resource_pool {
 
 struct dcn_fe_bandwidth {
        int dppclk_khz;
+
 };
 
 struct stream_resource {
index b1fab251c09bede95ca2783110d94c056e6cfb11..14716ba3566257458767a2b41349f3c4ac4060f1 100644 (file)
@@ -95,6 +95,9 @@ bool dal_ddc_service_query_ddc_data(
                uint8_t *read_buf,
                uint32_t read_size);
 
+bool dal_ddc_submit_aux_command(struct ddc_service *ddc,
+               struct aux_payload *payload);
+
 int dc_link_aux_transfer_raw(struct ddc_service *ddc,
                struct aux_payload *payload,
                enum aux_channel_operation_result *operation_result);
@@ -102,6 +105,9 @@ int dc_link_aux_transfer_raw(struct ddc_service *ddc,
 bool dc_link_aux_transfer_with_retries(struct ddc_service *ddc,
                struct aux_payload *payload);
 
+enum dc_status dc_link_aux_configure_timeout(struct ddc_service *ddc,
+               uint32_t timeout);
+
 void dal_ddc_service_write_scdc_data(
                struct ddc_service *ddc_service,
                uint32_t pix_clk,
index 08a4df2c61a8cb8685d395775e269d805c08a7a5..045138dbdccb471989f8215defcabe18829b376a 100644 (file)
@@ -28,6 +28,8 @@
 
 #define LINK_TRAINING_ATTEMPTS 4
 #define LINK_TRAINING_RETRY_DELAY 50 /* ms */
+#define LINK_AUX_DEFAULT_EXTENDED_TIMEOUT_PERIOD 32000 /*us*/
+#define LINK_AUX_DEFAULT_TIMEOUT_PERIOD 400 /*us*/
 
 struct dc_link;
 struct dc_stream_state;
@@ -43,6 +45,9 @@ bool dp_verify_link_cap_with_retries(
        struct dc_link_settings *known_limit_link_setting,
        int attempts);
 
+bool dp_verify_mst_link_cap(
+       struct dc_link *link);
+
 bool dp_validate_mode_timing(
        struct dc_link *link,
        const struct dc_crtc_timing *timing);
index e79cd4e92919405c4f551e5461aa840c878484a3..e77b3a76766d12cdfd331235af217fd129d148a6 100644 (file)
@@ -140,6 +140,9 @@ struct write_command_context {
 
 
 struct aux_engine_funcs {
+       bool (*configure_timeout)(
+               struct ddc_service *ddc,
+               uint32_t timeout);
        void (*destroy)(
                struct aux_engine **ptr);
        bool (*acquire_engine)(
index 76f9ad1b23df17875dcc9e8daf78c1622d87a1db..f2e21cb9fbd507af4b5337e5af128e39ce9504e8 100644 (file)
@@ -47,7 +47,7 @@
 #ifdef CONFIG_DRM_AMD_DC_DCN2_1
 /* Will these bw structures be ASIC specific? */
 
-#define MAX_NUM_DPM_LVL                4
+#define MAX_NUM_DPM_LVL                8
 #define WM_SET_COUNT           4
 
 
@@ -149,6 +149,7 @@ struct wm_table {
 struct clk_bw_params {
        unsigned int vram_type;
        unsigned int num_channels;
+       unsigned int dispclk_vco_khz;
        struct clk_limit_table clk_table;
        struct wm_table wm_table;
 };
@@ -180,12 +181,16 @@ struct clk_mgr_funcs {
                        struct dc_state *context,
                        enum dc_clock_type clock_type,
                        struct dc_clock_config *clock_cfg);
+
+       bool (*are_clock_states_equal) (struct dc_clocks *a,
+                       struct dc_clocks *b);
 };
 
 struct clk_mgr {
        struct dc_context *ctx;
        struct clk_mgr_funcs *funcs;
        struct dc_clocks clks;
+       bool psr_allow_active_cache;
        int dprefclk_khz; // Used by program pixel clock in clock source funcs, need to figureout where this goes
 #ifdef CONFIG_DRM_AMD_DC_DCN2_1
        struct clk_bw_params *bw_params;
@@ -199,4 +204,8 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
 
 void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr);
 
+void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr);
+
+void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr);
+
 #endif /* __DAL_CLK_MGR_H__ */
index 7dd46eb96d67d58adb0031e0914ac42ef1edf7d2..2e8cd7956a174bfe13edc75b53b72a1c27f1bb7a 100644 (file)
@@ -184,6 +184,21 @@ struct clk_mgr_registers {
        uint32_t MP1_SMN_C2PMSG_91;
 };
 
+enum clock_type {
+       clock_type_dispclk = 1,
+       clock_type_dcfclk,
+       clock_type_socclk,
+       clock_type_pixelclk,
+       clock_type_phyclk,
+       clock_type_dppclk,
+       clock_type_fclk,
+       clock_type_dcfdsclk,
+       clock_type_dscclk,
+       clock_type_uclk,
+       clock_type_dramclk,
+};
+
+
 struct state_dependent_clocks {
        int display_clk_khz;
        int pixel_clk_khz;
index d8e744f366e5e8a06637175a31f15f728c8bfedc..05ee5295d2c15935f2cef0f9f3cb292c98db2445 100644 (file)
@@ -38,8 +38,7 @@ struct dccg {
 struct dccg_funcs {
        void (*update_dpp_dto)(struct dccg *dccg,
                        int dpp_inst,
-                       int req_dppclk,
-                       bool reduce_divider_only);
+                       int req_dppclk);
        void (*get_dccg_ref_freq)(struct dccg *dccg,
                        unsigned int xtalin_freq_inKhz,
                        unsigned int *dccg_ref_freq_inKhz);
index a6297219d7fcead6765fbedd2390a77bb4610cbe..c81a17aeaa25c5a7988268d1580f41b6ca06a90e 100644 (file)
@@ -147,6 +147,7 @@ struct hubbub_funcs {
        bool (*is_allow_self_refresh_enabled)(struct hubbub *hubbub);
        void (*allow_self_refresh_control)(struct hubbub *hubbub, bool allow);
 
+       void (*apply_DEDCN21_147_wa)(struct hubbub *hubbub);
 };
 
 struct hubbub {
index 1ddb1c6fa1493c1ece0cdda16ef93d2c123be7f1..c6ff3d78b43502b6d4bf7b1d9a291ecad36c4e10 100644 (file)
 
 #include "dc_dsc.h"
 #include "dc_hw_types.h"
-#include "dc_dp_types.h"
+#include "dc_types.h"
+/* do not include any other headers
+ * or else it might break Edid Utility functionality.
+ */
+
 
 /* Input parameters for configuring DSC from the outside of DSC */
 struct dsc_config {
@@ -81,12 +85,6 @@ struct dsc_enc_caps {
        uint32_t bpp_increment_div; /* bpp increment divisor, e.g. if 16, it's 1/16th of a bit */
 };
 
-struct display_stream_compressor {
-       const struct dsc_funcs *funcs;
-       struct dc_context *ctx;
-       int inst;
-};
-
 struct dsc_funcs {
        void (*dsc_get_enc_caps)(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz);
        void (*dsc_read_state)(struct display_stream_compressor *dsc, struct dcn_dsc_state *s);
index abb4e4237fb6a731013514a3887d37eb791ed026..b21909216fb671f28b034d02599fb769fd0e9879 100644 (file)
@@ -184,6 +184,10 @@ struct link_encoder_funcs {
        bool (*fec_is_active)(struct link_encoder *enc);
 #endif
        bool (*is_in_alt_mode) (struct link_encoder *enc);
+
+       void (*get_max_link_cap)(struct link_encoder *enc,
+               struct dc_link_settings *link_settings);
+
        enum signal_type (*get_dig_mode)(
                struct link_encoder *enc);
 };
index e8668388581b2568d6da9f4ef1698bd96ac28c00..67b610d6d91f0efe503b08f7a075c3c03a057729 100644 (file)
@@ -43,6 +43,7 @@ struct dcn_watermarks {
 #if defined(CONFIG_DRM_AMD_DC_DCN2_1)
        uint32_t frac_urg_bw_nom;
        uint32_t frac_urg_bw_flip;
+       int32_t urgent_latency_ns;
 #endif
        struct cstate_pstate_watermarks_st cstate_pstate;
 };
index 957e9047381aa84a2210fa9300fd6ad897fffaa1..18def2b6fafe02ca79f2adb42f93636805012c7a 100644 (file)
@@ -208,6 +208,7 @@ struct output_pixel_processor {
        struct mpc_tree mpc_tree_params;
        bool mpcc_disconnect_pending[MAX_PIPES];
        const struct opp_funcs *funcs;
+       uint32_t dyn_expansion;
 };
 
 enum fmt_stereo_action {
index fe9b7a10a1c34ab344b16be8f60eef797e97a63e..6305e388612a22fb2bc0261ebcd8ba85a5a00a6c 100644 (file)
@@ -214,6 +214,11 @@ struct stream_encoder_funcs {
        unsigned int (*dig_source_otg)(
                struct stream_encoder *enc);
 
+       bool (*dp_get_pixel_format)(
+               struct stream_encoder *enc,
+               enum dc_pixel_encoding *encoding,
+               enum dc_color_depth *depth);
+
 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
        void (*enc_read_state)(struct stream_encoder *enc, struct enc_state *s);
index 6196cc32356e6685697333b0c0f0e2f94ee38ba9..27c73caf74ee68687da06bc71203d992372f45ef 100644 (file)
@@ -261,6 +261,8 @@ struct timing_generator_funcs {
 
        void (*program_manual_trigger)(struct timing_generator *optc);
        void (*setup_manual_trigger)(struct timing_generator *optc);
+       bool (*get_hw_timing)(struct timing_generator *optc,
+                       struct dc_crtc_timing *hw_crtc_timing);
 
        void (*set_vtg_params)(struct timing_generator *optc,
                        const struct dc_crtc_timing *dc_crtc_timing);
index 3a938cd414ea4cced48bdc15098e56a8229416fe..d39c1e11def56004d6b4cbcf8e6638eebed8593f 100644 (file)
@@ -114,6 +114,9 @@ struct hw_sequencer_funcs {
                        int opp_id);
 
 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
+       void (*program_front_end_for_ctx)(
+                       struct dc *dc,
+                       struct dc_state *context);
        void (*program_triplebuffer)(
                const struct dc *dc,
                struct pipe_ctx *pipe_ctx,
@@ -229,6 +232,13 @@ struct hw_sequencer_funcs {
                        struct dc *dc,
                        struct dc_state *context);
 
+       void (*exit_optimized_pwr_state)(
+                       const struct dc *dc,
+                       struct dc_state *context);
+       void (*optimize_pwr_state)(
+                       const struct dc *dc,
+                       struct dc_state *context);
+
 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
        bool (*update_bandwidth)(
                        struct dc *dc,
@@ -321,10 +331,12 @@ struct hw_sequencer_funcs {
                        struct dc_state *context);
        void (*update_writeback)(struct dc *dc,
                        const struct dc_stream_status *stream_status,
-                       struct dc_writeback_info *wb_info);
+                       struct dc_writeback_info *wb_info,
+                       struct dc_state *context);
        void (*enable_writeback)(struct dc *dc,
                        const struct dc_stream_status *stream_status,
-                       struct dc_writeback_info *wb_info);
+                       struct dc_writeback_info *wb_info,
+                       struct dc_state *context);
        void (*disable_writeback)(struct dc *dc,
                        unsigned int dwb_pipe_inst);
 #endif
@@ -337,6 +349,9 @@ struct hw_sequencer_funcs {
                        enum dc_clock_type clock_type,
                        struct dc_clock_config *clock_cfg);
 
+#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
+       bool (*s0i3_golden_init_wa)(struct dc *dc);
+#endif
 };
 
 void color_space_to_black_color(
index 18961707db23741d99a45e117846647e98834a2c..9ad49da50a17dacdcf9e2058224169b0054c76c4 100644 (file)
@@ -31,6 +31,8 @@
 #define DP_BRANCH_DEVICE_ID_0022B9 0x0022B9
 #define DP_BRANCH_DEVICE_ID_00001A 0x00001A
 #define DP_BRANCH_DEVICE_ID_0080E1 0x0080e1
+#define DP_BRANCH_DEVICE_ID_90CC24 0x90CC24
+#define DP_BRANCH_DEVICE_ID_00E04C 0x00E04C
 
 enum ddc_result {
        DDC_RESULT_UNKNOWN = 0,
diff --git a/drivers/gpu/drm/amd/display/include/hdcp_types.h b/drivers/gpu/drm/amd/display/include/hdcp_types.h
new file mode 100644 (file)
index 0000000..f31e6be
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+* Copyright 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) 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 __DC_HDCP_TYPES_H__
+#define __DC_HDCP_TYPES_H__
+
+enum hdcp_message_id {
+       HDCP_MESSAGE_ID_INVALID = -1,
+
+       /* HDCP 1.4 */
+
+       HDCP_MESSAGE_ID_READ_BKSV = 0,
+       /* HDMI is called Ri', DP is called R0' */
+       HDCP_MESSAGE_ID_READ_RI_R0,
+       HDCP_MESSAGE_ID_READ_PJ,
+       HDCP_MESSAGE_ID_WRITE_AKSV,
+       HDCP_MESSAGE_ID_WRITE_AINFO,
+       HDCP_MESSAGE_ID_WRITE_AN,
+       HDCP_MESSAGE_ID_READ_VH_X,
+       HDCP_MESSAGE_ID_READ_VH_0,
+       HDCP_MESSAGE_ID_READ_VH_1,
+       HDCP_MESSAGE_ID_READ_VH_2,
+       HDCP_MESSAGE_ID_READ_VH_3,
+       HDCP_MESSAGE_ID_READ_VH_4,
+       HDCP_MESSAGE_ID_READ_BCAPS,
+       HDCP_MESSAGE_ID_READ_BSTATUS,
+       HDCP_MESSAGE_ID_READ_KSV_FIFO,
+       HDCP_MESSAGE_ID_READ_BINFO,
+
+       /* HDCP 2.2 */
+
+       HDCP_MESSAGE_ID_HDCP2VERSION,
+       HDCP_MESSAGE_ID_RX_CAPS,
+       HDCP_MESSAGE_ID_WRITE_AKE_INIT,
+       HDCP_MESSAGE_ID_READ_AKE_SEND_CERT,
+       HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM,
+       HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM,
+       HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME,
+       HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO,
+       HDCP_MESSAGE_ID_WRITE_LC_INIT,
+       HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME,
+       HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS,
+       HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST,
+       HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK,
+       HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE,
+       HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY,
+       HDCP_MESSAGE_ID_READ_RXSTATUS,
+       HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE,
+
+       HDCP_MESSAGE_ID_MAX
+};
+
+enum hdcp_version {
+       HDCP_Unknown = 0,
+       HDCP_VERSION_14,
+       HDCP_VERSION_22,
+};
+
+enum hdcp_link {
+       HDCP_LINK_PRIMARY,
+       HDCP_LINK_SECONDARY
+};
+
+struct hdcp_protection_message {
+       enum hdcp_version version;
+       /* relevant only for DVI */
+       enum hdcp_link link;
+       enum hdcp_message_id msg_id;
+       uint32_t length;
+       uint8_t max_retries;
+       uint8_t *data;
+};
+
+#endif
index ec70c9b12e1aae849acc38787addc206e3df15d5..16e69bbc69aaa7b04a458880199962199abdf824 100644 (file)
@@ -37,8 +37,8 @@
 #define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65)
 /* Number of elements in the render times cache array */
 #define RENDER_TIMES_MAX_COUNT 10
-/* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */
-#define BTR_EXIT_MARGIN 2000
+/* Threshold to exit/exit BTR (to avoid frequent enter-exits at the lower limit) */
+#define BTR_MAX_MARGIN 2500
 /* Threshold to change BTR multiplier (to avoid frequent changes) */
 #define BTR_DRIFT_MARGIN 2000
 /*Threshold to exit fixed refresh rate*/
@@ -234,6 +234,10 @@ static void update_v_total_for_static_ramp(
                        current_duration_in_us) * (stream->timing.pix_clk_100hz / 10)),
                                stream->timing.h_total), 1000);
 
+       /* v_total cannot be less than nominal */
+       if (v_total < stream->timing.v_total)
+               v_total = stream->timing.v_total;
+
        in_out_vrr->adjust.v_total_min = v_total;
        in_out_vrr->adjust.v_total_max = v_total;
 }
@@ -250,24 +254,22 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
        unsigned int delta_from_mid_point_in_us_1 = 0xFFFFFFFF;
        unsigned int delta_from_mid_point_in_us_2 = 0xFFFFFFFF;
        unsigned int frames_to_insert = 0;
-       unsigned int min_frame_duration_in_ns = 0;
-       unsigned int max_render_time_in_us = in_out_vrr->max_duration_in_us;
        unsigned int delta_from_mid_point_delta_in_us;
-
-       min_frame_duration_in_ns = ((unsigned int) (div64_u64(
-               (1000000000ULL * 1000000),
-               in_out_vrr->max_refresh_in_uhz)));
+       unsigned int max_render_time_in_us =
+                       in_out_vrr->max_duration_in_us - in_out_vrr->btr.margin_in_us;
 
        /* Program BTR */
-       if (last_render_time_in_us + BTR_EXIT_MARGIN < max_render_time_in_us) {
+       if ((last_render_time_in_us + in_out_vrr->btr.margin_in_us / 2) < max_render_time_in_us) {
                /* Exit Below the Range */
                if (in_out_vrr->btr.btr_active) {
                        in_out_vrr->btr.frame_counter = 0;
                        in_out_vrr->btr.btr_active = false;
                }
-       } else if (last_render_time_in_us > max_render_time_in_us) {
+       } else if (last_render_time_in_us > (max_render_time_in_us + in_out_vrr->btr.margin_in_us / 2)) {
                /* Enter Below the Range */
-               in_out_vrr->btr.btr_active = true;
+               if (!in_out_vrr->btr.btr_active) {
+                       in_out_vrr->btr.btr_active = true;
+               }
        }
 
        /* BTR set to "not active" so disengage */
@@ -323,7 +325,9 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
                /* Choose number of frames to insert based on how close it
                 * can get to the mid point of the variable range.
                 */
-               if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) {
+               if ((frame_time_in_us / mid_point_frames_ceil) > in_out_vrr->min_duration_in_us &&
+                               (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2 ||
+                                               mid_point_frames_floor < 2)) {
                        frames_to_insert = mid_point_frames_ceil;
                        delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 -
                                        delta_from_mid_point_in_us_1;
@@ -339,7 +343,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
                if (in_out_vrr->btr.frames_to_insert != 0 &&
                                delta_from_mid_point_delta_in_us < BTR_DRIFT_MARGIN) {
                        if (((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) <
-                                       in_out_vrr->max_duration_in_us) &&
+                                       max_render_time_in_us) &&
                                ((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) >
                                        in_out_vrr->min_duration_in_us))
                                frames_to_insert = in_out_vrr->btr.frames_to_insert;
@@ -743,6 +747,10 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
        nominal_field_rate_in_uhz =
                        mod_freesync_calc_nominal_field_rate(stream);
 
+       /* Rounded to the nearest Hz */
+       nominal_field_rate_in_uhz = 1000000ULL *
+                       div_u64(nominal_field_rate_in_uhz + 500000, 1000000);
+
        min_refresh_in_uhz = in_config->min_refresh_in_uhz;
        max_refresh_in_uhz = in_config->max_refresh_in_uhz;
 
@@ -788,6 +796,11 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
                refresh_range = in_out_vrr->max_refresh_in_uhz -
                                in_out_vrr->min_refresh_in_uhz;
 
+               in_out_vrr->btr.margin_in_us = in_out_vrr->max_duration_in_us -
+                               2 * in_out_vrr->min_duration_in_us;
+               if (in_out_vrr->btr.margin_in_us > BTR_MAX_MARGIN)
+                       in_out_vrr->btr.margin_in_us = BTR_MAX_MARGIN;
+
                in_out_vrr->supported = true;
        }
 
@@ -803,6 +816,7 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
        in_out_vrr->btr.inserted_duration_in_us = 0;
        in_out_vrr->btr.frames_to_insert = 0;
        in_out_vrr->btr.frame_counter = 0;
+
        in_out_vrr->btr.mid_point_in_us =
                                (in_out_vrr->min_duration_in_us +
                                 in_out_vrr->max_duration_in_us) / 2;
@@ -975,13 +989,9 @@ void mod_freesync_get_settings(struct mod_freesync *mod_freesync,
                unsigned int *inserted_frames,
                unsigned int *inserted_duration_in_us)
 {
-       struct core_freesync *core_freesync = NULL;
-
        if (mod_freesync == NULL)
                return;
 
-       core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
-
        if (vrr->supported) {
                *v_total_min = vrr->adjust.v_total_min;
                *v_total_max = vrr->adjust.v_total_max;
@@ -996,14 +1006,13 @@ unsigned long long mod_freesync_calc_nominal_field_rate(
                        const struct dc_stream_state *stream)
 {
        unsigned long long nominal_field_rate_in_uhz = 0;
+       unsigned int total = stream->timing.h_total * stream->timing.v_total;
 
-       /* Calculate nominal field rate for stream */
+       /* Calculate nominal field rate for stream, rounded up to nearest integer */
        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);
-       nominal_field_rate_in_uhz = div_u64(nominal_field_rate_in_uhz,
-                                               stream->timing.v_total);
+
+       nominal_field_rate_in_uhz =     div_u64(nominal_field_rate_in_uhz, total);
 
        return nominal_field_rate_in_uhz;
 }
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/Makefile b/drivers/gpu/drm/amd/display/modules/hdcp/Makefile
new file mode 100644 (file)
index 0000000..1c3c6d4
--- /dev/null
@@ -0,0 +1,32 @@
+#
+# Copyright 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) 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 'hdcp' sub-module of DAL.
+#
+
+HDCP = hdcp_ddc.o hdcp_log.o hdcp_psp.o hdcp.o \
+               hdcp1_execution.o hdcp1_transition.o
+
+AMD_DAL_HDCP = $(addprefix $(AMDDALPATH)/modules/hdcp/,$(HDCP))
+#$(info ************  DAL-HDCP_MAKEFILE ************)
+
+AMD_DISPLAY_FILES += $(AMD_DAL_HDCP)
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c
new file mode 100644 (file)
index 0000000..d7ac445
--- /dev/null
@@ -0,0 +1,426 @@
+/*
+ * Copyright 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) 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 "hdcp.h"
+
+static void push_error_status(struct mod_hdcp *hdcp,
+               enum mod_hdcp_status status)
+{
+       struct mod_hdcp_trace *trace = &hdcp->connection.trace;
+
+       if (trace->error_count < MAX_NUM_OF_ERROR_TRACE) {
+               trace->errors[trace->error_count].status = status;
+               trace->errors[trace->error_count].state_id = hdcp->state.id;
+               trace->error_count++;
+               HDCP_ERROR_TRACE(hdcp, status);
+       }
+
+       hdcp->connection.hdcp1_retry_count++;
+}
+
+static uint8_t is_cp_desired_hdcp1(struct mod_hdcp *hdcp)
+{
+       int i, display_enabled = 0;
+
+       /* if all displays on the link are disabled, hdcp is not desired */
+       for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) {
+               if (hdcp->connection.displays[i].state != MOD_HDCP_DISPLAY_INACTIVE &&
+                               !hdcp->connection.displays[i].adjust.disable) {
+                       display_enabled = 1;
+                       break;
+               }
+       }
+
+       return (hdcp->connection.hdcp1_retry_count < MAX_NUM_OF_ATTEMPTS) &&
+                       display_enabled && !hdcp->connection.link.adjust.hdcp1.disable;
+}
+
+static enum mod_hdcp_status execution(struct mod_hdcp *hdcp,
+               struct mod_hdcp_event_context *event_ctx,
+               union mod_hdcp_transition_input *input)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+
+       if (is_in_initialized_state(hdcp)) {
+               if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
+                       event_ctx->unexpected_event = 1;
+                       goto out;
+               }
+               /* initialize transition input */
+               memset(input, 0, sizeof(union mod_hdcp_transition_input));
+       } else if (is_in_cp_not_desired_state(hdcp)) {
+               if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
+                       event_ctx->unexpected_event = 1;
+                       goto out;
+               }
+               /* update topology event if hdcp is not desired */
+               status = mod_hdcp_add_display_topology(hdcp);
+       } else if (is_in_hdcp1_states(hdcp)) {
+               status = mod_hdcp_hdcp1_execution(hdcp, event_ctx, &input->hdcp1);
+       } else if (is_in_hdcp1_dp_states(hdcp)) {
+               status = mod_hdcp_hdcp1_dp_execution(hdcp,
+                               event_ctx, &input->hdcp1);
+       }
+out:
+       return status;
+}
+
+static enum mod_hdcp_status transition(struct mod_hdcp *hdcp,
+               struct mod_hdcp_event_context *event_ctx,
+               union mod_hdcp_transition_input *input,
+               struct mod_hdcp_output *output)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+
+       if (event_ctx->unexpected_event)
+               goto out;
+
+       if (is_in_initialized_state(hdcp)) {
+               if (is_dp_hdcp(hdcp))
+                       if (is_cp_desired_hdcp1(hdcp)) {
+                               callback_in_ms(0, output);
+                               set_state_id(hdcp, output, D1_A0_DETERMINE_RX_HDCP_CAPABLE);
+                       } else {
+                               callback_in_ms(0, output);
+                               set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED);
+                       }
+               else if (is_hdmi_dvi_sl_hdcp(hdcp))
+                       if (is_cp_desired_hdcp1(hdcp)) {
+                               callback_in_ms(0, output);
+                               set_state_id(hdcp, output, H1_A0_WAIT_FOR_ACTIVE_RX);
+                       } else {
+                               callback_in_ms(0, output);
+                               set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED);
+                       }
+               else {
+                       callback_in_ms(0, output);
+                       set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED);
+               }
+       } else if (is_in_cp_not_desired_state(hdcp)) {
+               increment_stay_counter(hdcp);
+       } else if (is_in_hdcp1_states(hdcp)) {
+               status = mod_hdcp_hdcp1_transition(hdcp,
+                               event_ctx, &input->hdcp1, output);
+       } else if (is_in_hdcp1_dp_states(hdcp)) {
+               status = mod_hdcp_hdcp1_dp_transition(hdcp,
+                               event_ctx, &input->hdcp1, output);
+       } else {
+               status = MOD_HDCP_STATUS_INVALID_STATE;
+       }
+out:
+       return status;
+}
+
+static enum mod_hdcp_status reset_authentication(struct mod_hdcp *hdcp,
+               struct mod_hdcp_output *output)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+
+       if (is_hdcp1(hdcp)) {
+               if (hdcp->auth.trans_input.hdcp1.create_session != UNKNOWN)
+                       mod_hdcp_hdcp1_destroy_session(hdcp);
+
+               if (hdcp->auth.trans_input.hdcp1.add_topology == PASS) {
+                       status = mod_hdcp_remove_display_topology(hdcp);
+                       if (status != MOD_HDCP_STATUS_SUCCESS) {
+                               output->callback_needed = 0;
+                               output->watchdog_timer_needed = 0;
+                               goto out;
+                       }
+               }
+               HDCP_TOP_RESET_AUTH_TRACE(hdcp);
+               memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication));
+               memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state));
+               set_state_id(hdcp, output, HDCP_INITIALIZED);
+       } else if (is_in_cp_not_desired_state(hdcp)) {
+               status = mod_hdcp_remove_display_topology(hdcp);
+               if (status != MOD_HDCP_STATUS_SUCCESS) {
+                       output->callback_needed = 0;
+                       output->watchdog_timer_needed = 0;
+                       goto out;
+               }
+               HDCP_TOP_RESET_AUTH_TRACE(hdcp);
+               memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication));
+               memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state));
+               set_state_id(hdcp, output, HDCP_INITIALIZED);
+       }
+
+out:
+       /* stop callback and watchdog requests from previous authentication*/
+       output->watchdog_timer_stop = 1;
+       output->callback_stop = 1;
+       return status;
+}
+
+static enum mod_hdcp_status reset_connection(struct mod_hdcp *hdcp,
+               struct mod_hdcp_output *output)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+
+       memset(output, 0, sizeof(struct mod_hdcp_output));
+
+       status = reset_authentication(hdcp, output);
+       if (status != MOD_HDCP_STATUS_SUCCESS)
+               goto out;
+
+       if (current_state(hdcp) != HDCP_UNINITIALIZED) {
+               HDCP_TOP_RESET_CONN_TRACE(hdcp);
+               set_state_id(hdcp, output, HDCP_UNINITIALIZED);
+       }
+       memset(&hdcp->connection, 0, sizeof(hdcp->connection));
+out:
+       return status;
+}
+
+/*
+ * Implementation of functions in mod_hdcp.h
+ */
+size_t mod_hdcp_get_memory_size(void)
+{
+       return sizeof(struct mod_hdcp);
+}
+
+enum mod_hdcp_status mod_hdcp_setup(struct mod_hdcp *hdcp,
+               struct mod_hdcp_config *config)
+{
+       struct mod_hdcp_output output;
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+
+       memset(hdcp, 0, sizeof(struct mod_hdcp));
+       memset(&output, 0, sizeof(output));
+       hdcp->config = *config;
+       HDCP_TOP_INTERFACE_TRACE(hdcp);
+       status = reset_connection(hdcp, &output);
+       if (status != MOD_HDCP_STATUS_SUCCESS)
+               push_error_status(hdcp, status);
+       return status;
+}
+
+enum mod_hdcp_status mod_hdcp_teardown(struct mod_hdcp *hdcp)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+       struct mod_hdcp_output output;
+
+       HDCP_TOP_INTERFACE_TRACE(hdcp);
+       memset(&output, 0,  sizeof(output));
+       status = reset_connection(hdcp, &output);
+       if (status == MOD_HDCP_STATUS_SUCCESS)
+               memset(hdcp, 0, sizeof(struct mod_hdcp));
+       else
+               push_error_status(hdcp, status);
+       return status;
+}
+
+enum mod_hdcp_status mod_hdcp_add_display(struct mod_hdcp *hdcp,
+               struct mod_hdcp_link *link, struct mod_hdcp_display *display,
+               struct mod_hdcp_output *output)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+       struct mod_hdcp_display *display_container = NULL;
+
+       HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, display->index);
+       memset(output, 0, sizeof(struct mod_hdcp_output));
+
+       /* skip inactive display */
+       if (display->state != MOD_HDCP_DISPLAY_ACTIVE) {
+               status = MOD_HDCP_STATUS_SUCCESS;
+               goto out;
+       }
+
+       /* check existing display container */
+       if (get_active_display_at_index(hdcp, display->index)) {
+               status = MOD_HDCP_STATUS_SUCCESS;
+               goto out;
+       }
+
+       /* find an empty display container */
+       display_container = get_empty_display_container(hdcp);
+       if (!display_container) {
+               status = MOD_HDCP_STATUS_DISPLAY_OUT_OF_BOUND;
+               goto out;
+       }
+
+       /* reset existing authentication status */
+       status = reset_authentication(hdcp, output);
+       if (status != MOD_HDCP_STATUS_SUCCESS)
+               goto out;
+
+       /* add display to connection */
+       hdcp->connection.link = *link;
+       *display_container = *display;
+
+       /* reset retry counters */
+       reset_retry_counts(hdcp);
+
+       /* reset error trace */
+       memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace));
+
+       /* request authentication */
+       if (current_state(hdcp) != HDCP_INITIALIZED)
+               set_state_id(hdcp, output, HDCP_INITIALIZED);
+       callback_in_ms(hdcp->connection.link.adjust.auth_delay * 1000, output);
+out:
+       if (status != MOD_HDCP_STATUS_SUCCESS)
+               push_error_status(hdcp, status);
+
+       return status;
+}
+
+enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp,
+               uint8_t index, struct mod_hdcp_output *output)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+       struct mod_hdcp_display *display = NULL;
+
+       HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, index);
+       memset(output, 0, sizeof(struct mod_hdcp_output));
+
+       /* find display in connection */
+       display = get_active_display_at_index(hdcp, index);
+       if (!display) {
+               status = MOD_HDCP_STATUS_SUCCESS;
+               goto out;
+       }
+
+       /* stop current authentication */
+       status = reset_authentication(hdcp, output);
+       if (status != MOD_HDCP_STATUS_SUCCESS)
+               goto out;
+
+       /* remove display */
+       display->state = MOD_HDCP_DISPLAY_INACTIVE;
+
+       /* clear retry counters */
+       reset_retry_counts(hdcp);
+
+       /* reset error trace */
+       memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace));
+
+       /* request authentication for remaining displays*/
+       if (get_active_display_count(hdcp) > 0)
+               callback_in_ms(hdcp->connection.link.adjust.auth_delay * 1000,
+                               output);
+out:
+       if (status != MOD_HDCP_STATUS_SUCCESS)
+               push_error_status(hdcp, status);
+       return status;
+}
+
+enum mod_hdcp_status mod_hdcp_query_display(struct mod_hdcp *hdcp,
+               uint8_t index, struct mod_hdcp_display_query *query)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+       struct mod_hdcp_display *display = NULL;
+
+       /* find display in connection */
+       display = get_active_display_at_index(hdcp, index);
+       if (!display) {
+               status = MOD_HDCP_STATUS_DISPLAY_NOT_FOUND;
+               goto out;
+       }
+
+       /* populate query */
+       query->link = &hdcp->connection.link;
+       query->display = display;
+       query->trace = &hdcp->connection.trace;
+       query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
+
+       mod_hdcp_hdcp1_get_link_encryption_status(hdcp, &query->encryption_status);
+
+out:
+       return status;
+}
+
+enum mod_hdcp_status mod_hdcp_reset_connection(struct mod_hdcp *hdcp,
+               struct mod_hdcp_output *output)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+
+       HDCP_TOP_INTERFACE_TRACE(hdcp);
+       status = reset_connection(hdcp, output);
+       if (status != MOD_HDCP_STATUS_SUCCESS)
+               push_error_status(hdcp, status);
+
+       return status;
+}
+
+enum mod_hdcp_status mod_hdcp_process_event(struct mod_hdcp *hdcp,
+               enum mod_hdcp_event event, struct mod_hdcp_output *output)
+{
+       enum mod_hdcp_status exec_status, trans_status, reset_status, status;
+       struct mod_hdcp_event_context event_ctx;
+
+       HDCP_EVENT_TRACE(hdcp, event);
+       memset(output, 0, sizeof(struct mod_hdcp_output));
+       memset(&event_ctx, 0, sizeof(struct mod_hdcp_event_context));
+       event_ctx.event = event;
+
+       /* execute and transition */
+       exec_status = execution(hdcp, &event_ctx, &hdcp->auth.trans_input);
+       trans_status = transition(
+                       hdcp, &event_ctx, &hdcp->auth.trans_input, output);
+       if (trans_status == MOD_HDCP_STATUS_SUCCESS) {
+               status = MOD_HDCP_STATUS_SUCCESS;
+       } else if (exec_status == MOD_HDCP_STATUS_SUCCESS) {
+               status = MOD_HDCP_STATUS_INTERNAL_POLICY_FAILURE;
+               push_error_status(hdcp, status);
+       } else {
+               status = exec_status;
+               push_error_status(hdcp, status);
+       }
+
+       /* reset authentication if needed */
+       if (trans_status == MOD_HDCP_STATUS_RESET_NEEDED) {
+               HDCP_FULL_DDC_TRACE(hdcp);
+               reset_status = reset_authentication(hdcp, output);
+               if (reset_status != MOD_HDCP_STATUS_SUCCESS)
+                       push_error_status(hdcp, reset_status);
+       }
+       return status;
+}
+
+enum mod_hdcp_operation_mode mod_hdcp_signal_type_to_operation_mode(
+               enum signal_type signal)
+{
+       enum mod_hdcp_operation_mode mode = MOD_HDCP_MODE_OFF;
+
+       switch (signal) {
+       case SIGNAL_TYPE_DVI_SINGLE_LINK:
+       case SIGNAL_TYPE_HDMI_TYPE_A:
+               mode = MOD_HDCP_MODE_DEFAULT;
+               break;
+       case SIGNAL_TYPE_EDP:
+       case SIGNAL_TYPE_DISPLAY_PORT:
+               mode = MOD_HDCP_MODE_DP;
+               break;
+       case SIGNAL_TYPE_DISPLAY_PORT_MST:
+               mode = MOD_HDCP_MODE_DP_MST;
+               break;
+       default:
+               break;
+       };
+
+       return mode;
+}
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h
new file mode 100644 (file)
index 0000000..5664bc0
--- /dev/null
@@ -0,0 +1,442 @@
+/*
+ * Copyright 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) 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 HDCP_H_
+#define HDCP_H_
+
+#include "mod_hdcp.h"
+#include "hdcp_log.h"
+
+#define BCAPS_READY_MASK                               0x20
+#define BCAPS_REPEATER_MASK                            0x40
+#define BSTATUS_DEVICE_COUNT_MASK                      0X007F
+#define BSTATUS_MAX_DEVS_EXCEEDED_MASK                 0x0080
+#define BSTATUS_MAX_CASCADE_EXCEEDED_MASK              0x0800
+#define BCAPS_HDCP_CAPABLE_MASK_DP                     0x01
+#define BCAPS_REPEATER_MASK_DP                         0x02
+#define BSTATUS_READY_MASK_DP                          0x01
+#define BSTATUS_R0_P_AVAILABLE_MASK_DP                 0x02
+#define BSTATUS_LINK_INTEGRITY_FAILURE_MASK_DP         0x04
+#define BSTATUS_REAUTH_REQUEST_MASK_DP                 0x08
+#define BINFO_DEVICE_COUNT_MASK_DP                     0X007F
+#define BINFO_MAX_DEVS_EXCEEDED_MASK_DP                        0x0080
+#define BINFO_MAX_CASCADE_EXCEEDED_MASK_DP             0x0800
+
+#define RXSTATUS_MSG_SIZE_MASK                         0x03FF
+#define RXSTATUS_READY_MASK                            0x0400
+#define RXSTATUS_REAUTH_REQUEST_MASK                   0x0800
+#define RXIDLIST_DEVICE_COUNT_LOWER_MASK               0xf0
+#define RXIDLIST_DEVICE_COUNT_UPPER_MASK               0x01
+#define RXCAPS_BYTE0_HDCP_CAPABLE_MASK_DP              0x02
+#define RXSTATUS_READY_MASK_DP                         0x0001
+#define RXSTATUS_H_P_AVAILABLE_MASK_DP                 0x0002
+#define RXSTATUS_PAIRING_AVAILABLE_MASK_DP             0x0004
+#define RXSTATUS_REAUTH_REQUEST_MASK_DP                        0x0008
+#define RXSTATUS_LINK_INTEGRITY_FAILURE_MASK_DP                0x0010
+
+enum mod_hdcp_trans_input_result {
+       UNKNOWN = 0,
+       PASS,
+       FAIL
+};
+
+struct mod_hdcp_transition_input_hdcp1 {
+       uint8_t bksv_read;
+       uint8_t bksv_validation;
+       uint8_t add_topology;
+       uint8_t create_session;
+       uint8_t an_write;
+       uint8_t aksv_write;
+       uint8_t ainfo_write;
+       uint8_t bcaps_read;
+       uint8_t r0p_read;
+       uint8_t rx_validation;
+       uint8_t encryption;
+       uint8_t link_maintenance;
+       uint8_t ready_check;
+       uint8_t bstatus_read;
+       uint8_t max_cascade_check;
+       uint8_t max_devs_check;
+       uint8_t device_count_check;
+       uint8_t ksvlist_read;
+       uint8_t vp_read;
+       uint8_t ksvlist_vp_validation;
+
+       uint8_t hdcp_capable_dp;
+       uint8_t binfo_read_dp;
+       uint8_t r0p_available_dp;
+       uint8_t link_integiry_check;
+       uint8_t reauth_request_check;
+       uint8_t stream_encryption_dp;
+};
+
+union mod_hdcp_transition_input {
+       struct mod_hdcp_transition_input_hdcp1 hdcp1;
+};
+
+struct mod_hdcp_message_hdcp1 {
+       uint8_t         an[8];
+       uint8_t         aksv[5];
+       uint8_t         ainfo;
+       uint8_t         bksv[5];
+       uint16_t        r0p;
+       uint8_t         bcaps;
+       uint16_t        bstatus;
+       uint8_t         ksvlist[635];
+       uint16_t        ksvlist_size;
+       uint8_t         vp[20];
+
+       uint16_t        binfo_dp;
+};
+
+union mod_hdcp_message {
+       struct mod_hdcp_message_hdcp1 hdcp1;
+};
+
+struct mod_hdcp_auth_counters {
+       uint8_t stream_management_retry_count;
+};
+
+/* contains values per connection */
+struct mod_hdcp_connection {
+       struct mod_hdcp_link link;
+       struct mod_hdcp_display displays[MAX_NUM_OF_DISPLAYS];
+       uint8_t is_repeater;
+       uint8_t is_km_stored;
+       struct mod_hdcp_trace trace;
+       uint8_t hdcp1_retry_count;
+};
+
+/* contains values per authentication cycle */
+struct mod_hdcp_authentication {
+       uint32_t id;
+       union mod_hdcp_message msg;
+       union mod_hdcp_transition_input trans_input;
+       struct mod_hdcp_auth_counters count;
+};
+
+/* contains values per state change */
+struct mod_hdcp_state {
+       uint8_t id;
+       uint32_t stay_count;
+};
+
+/* per event in a state */
+struct mod_hdcp_event_context {
+       enum mod_hdcp_event event;
+       uint8_t rx_id_list_ready;
+       uint8_t unexpected_event;
+};
+
+struct mod_hdcp {
+       /* per link */
+       struct mod_hdcp_config config;
+       /* per connection */
+       struct mod_hdcp_connection connection;
+       /* per authentication attempt */
+       struct mod_hdcp_authentication auth;
+       /* per state in an authentication */
+       struct mod_hdcp_state state;
+       /* reserved memory buffer */
+       uint8_t buf[2025];
+};
+
+enum mod_hdcp_initial_state_id {
+       HDCP_UNINITIALIZED = 0x0,
+       HDCP_INITIAL_STATE_START = HDCP_UNINITIALIZED,
+       HDCP_INITIALIZED,
+       HDCP_CP_NOT_DESIRED,
+       HDCP_INITIAL_STATE_END = HDCP_CP_NOT_DESIRED
+};
+
+enum mod_hdcp_hdcp1_state_id {
+       HDCP1_STATE_START = HDCP_INITIAL_STATE_END,
+       H1_A0_WAIT_FOR_ACTIVE_RX,
+       H1_A1_EXCHANGE_KSVS,
+       H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER,
+       H1_A45_AUTHENTICATED,
+       H1_A8_WAIT_FOR_READY,
+       H1_A9_READ_KSV_LIST,
+       HDCP1_STATE_END = H1_A9_READ_KSV_LIST
+};
+
+enum mod_hdcp_hdcp1_dp_state_id {
+       HDCP1_DP_STATE_START = HDCP1_STATE_END,
+       D1_A0_DETERMINE_RX_HDCP_CAPABLE,
+       D1_A1_EXCHANGE_KSVS,
+       D1_A23_WAIT_FOR_R0_PRIME,
+       D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER,
+       D1_A4_AUTHENTICATED,
+       D1_A6_WAIT_FOR_READY,
+       D1_A7_READ_KSV_LIST,
+       HDCP1_DP_STATE_END = D1_A7_READ_KSV_LIST,
+};
+
+/* hdcp1 executions and transitions */
+typedef enum mod_hdcp_status (*mod_hdcp_action)(struct mod_hdcp *hdcp);
+uint8_t mod_hdcp_execute_and_set(
+               mod_hdcp_action func, uint8_t *flag,
+               enum mod_hdcp_status *status, struct mod_hdcp *hdcp, char *str);
+enum mod_hdcp_status mod_hdcp_hdcp1_execution(struct mod_hdcp *hdcp,
+       struct mod_hdcp_event_context *event_ctx,
+       struct mod_hdcp_transition_input_hdcp1 *input);
+enum mod_hdcp_status mod_hdcp_hdcp1_dp_execution(struct mod_hdcp *hdcp,
+       struct mod_hdcp_event_context *event_ctx,
+       struct mod_hdcp_transition_input_hdcp1 *input);
+enum mod_hdcp_status mod_hdcp_hdcp1_transition(struct mod_hdcp *hdcp,
+       struct mod_hdcp_event_context *event_ctx,
+       struct mod_hdcp_transition_input_hdcp1 *input,
+       struct mod_hdcp_output *output);
+enum mod_hdcp_status mod_hdcp_hdcp1_dp_transition(struct mod_hdcp *hdcp,
+       struct mod_hdcp_event_context *event_ctx,
+       struct mod_hdcp_transition_input_hdcp1 *input,
+       struct mod_hdcp_output *output);
+
+/* log functions */
+void mod_hdcp_dump_binary_message(uint8_t *msg, uint32_t msg_size,
+               uint8_t *buf, uint32_t buf_size);
+/* TODO: add adjustment log */
+
+/* psp functions */
+enum mod_hdcp_status mod_hdcp_add_display_topology(
+               struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_remove_display_topology(
+               struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_hdcp1_destroy_session(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_hdcp1_validate_rx(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_hdcp1_enable_encryption(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_hdcp1_validate_ksvlist_vp(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_hdcp1_enable_dp_stream_encryption(
+       struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_hdcp1_link_maintenance(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_hdcp1_get_link_encryption_status(struct mod_hdcp *hdcp,
+                                                              enum mod_hdcp_encryption_status *encryption_status);
+/* ddc functions */
+enum mod_hdcp_status mod_hdcp_read_bksv(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_read_bcaps(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_read_bstatus(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_read_r0p(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_read_ksvlist(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_read_vp(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_read_binfo(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_write_aksv(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_write_ainfo(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_write_an(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_read_rxcaps(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_read_rxstatus(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_read_ake_cert(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_read_h_prime(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_read_pairing_info(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_read_l_prime(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_read_rx_id_list(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_read_stream_ready(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_write_ake_init(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_write_no_stored_km(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_write_stored_km(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_write_lc_init(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_write_eks(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_write_repeater_auth_ack(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_write_stream_manage(struct mod_hdcp *hdcp);
+enum mod_hdcp_status mod_hdcp_write_content_type(struct mod_hdcp *hdcp);
+
+/* hdcp version helpers */
+static inline uint8_t is_dp_hdcp(struct mod_hdcp *hdcp)
+{
+       return (hdcp->connection.link.mode == MOD_HDCP_MODE_DP ||
+                       hdcp->connection.link.mode == MOD_HDCP_MODE_DP_MST);
+}
+
+static inline uint8_t is_dp_mst_hdcp(struct mod_hdcp *hdcp)
+{
+       return (hdcp->connection.link.mode == MOD_HDCP_MODE_DP_MST);
+}
+
+static inline uint8_t is_hdmi_dvi_sl_hdcp(struct mod_hdcp *hdcp)
+{
+       return (hdcp->connection.link.mode == MOD_HDCP_MODE_DEFAULT);
+}
+
+/* hdcp state helpers */
+static inline uint8_t current_state(struct mod_hdcp *hdcp)
+{
+       return hdcp->state.id;
+}
+
+static inline void set_state_id(struct mod_hdcp *hdcp,
+               struct mod_hdcp_output *output, uint8_t id)
+{
+       memset(&hdcp->state, 0, sizeof(hdcp->state));
+       hdcp->state.id = id;
+       /* callback timer should be reset per state */
+       output->callback_stop = 1;
+       output->watchdog_timer_stop = 1;
+       HDCP_NEXT_STATE_TRACE(hdcp, id, output);
+}
+
+static inline uint8_t is_in_hdcp1_states(struct mod_hdcp *hdcp)
+{
+       return (current_state(hdcp) > HDCP1_STATE_START &&
+                       current_state(hdcp) <= HDCP1_STATE_END);
+}
+
+static inline uint8_t is_in_hdcp1_dp_states(struct mod_hdcp *hdcp)
+{
+       return (current_state(hdcp) > HDCP1_DP_STATE_START &&
+                       current_state(hdcp) <= HDCP1_DP_STATE_END);
+}
+
+static inline uint8_t is_hdcp1(struct mod_hdcp *hdcp)
+{
+       return (is_in_hdcp1_states(hdcp) || is_in_hdcp1_dp_states(hdcp));
+}
+
+static inline uint8_t is_in_cp_not_desired_state(struct mod_hdcp *hdcp)
+{
+       return current_state(hdcp) == HDCP_CP_NOT_DESIRED;
+}
+
+static inline uint8_t is_in_initialized_state(struct mod_hdcp *hdcp)
+{
+       return current_state(hdcp) == HDCP_INITIALIZED;
+}
+
+/* transition operation helpers */
+static inline void increment_stay_counter(struct mod_hdcp *hdcp)
+{
+       hdcp->state.stay_count++;
+}
+
+static inline void fail_and_restart_in_ms(uint16_t time,
+               enum mod_hdcp_status *status,
+               struct mod_hdcp_output *output)
+{
+       output->callback_needed = 1;
+       output->callback_delay = time;
+       output->watchdog_timer_needed = 0;
+       output->watchdog_timer_delay = 0;
+       *status = MOD_HDCP_STATUS_RESET_NEEDED;
+}
+
+static inline void callback_in_ms(uint16_t time, struct mod_hdcp_output *output)
+{
+       output->callback_needed = 1;
+       output->callback_delay = time;
+}
+
+static inline void set_watchdog_in_ms(struct mod_hdcp *hdcp, uint16_t time,
+               struct mod_hdcp_output *output)
+{
+       output->watchdog_timer_needed = 1;
+       output->watchdog_timer_delay = time;
+}
+
+/* connection topology helpers */
+static inline uint8_t is_display_active(struct mod_hdcp_display *display)
+{
+       return display->state >= MOD_HDCP_DISPLAY_ACTIVE;
+}
+
+static inline uint8_t is_display_added(struct mod_hdcp_display *display)
+{
+       return display->state >= MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED;
+}
+
+static inline uint8_t is_display_encryption_enabled(struct mod_hdcp_display *display)
+{
+       return display->state >= MOD_HDCP_DISPLAY_ENCRYPTION_ENABLED;
+}
+
+static inline uint8_t get_active_display_count(struct mod_hdcp *hdcp)
+{
+       uint8_t added_count = 0;
+       uint8_t i;
+
+       for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++)
+               if (is_display_active(&hdcp->connection.displays[i]))
+                       added_count++;
+       return added_count;
+}
+
+static inline uint8_t get_added_display_count(struct mod_hdcp *hdcp)
+{
+       uint8_t added_count = 0;
+       uint8_t i;
+
+       for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++)
+               if (is_display_added(&hdcp->connection.displays[i]))
+                       added_count++;
+       return added_count;
+}
+
+static inline struct mod_hdcp_display *get_first_added_display(
+               struct mod_hdcp *hdcp)
+{
+       uint8_t i;
+       struct mod_hdcp_display *display = NULL;
+
+       for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++)
+               if (is_display_added(&hdcp->connection.displays[i])) {
+                       display = &hdcp->connection.displays[i];
+                       break;
+               }
+       return display;
+}
+
+static inline struct mod_hdcp_display *get_active_display_at_index(
+               struct mod_hdcp *hdcp, uint8_t index)
+{
+       uint8_t i;
+       struct mod_hdcp_display *display = NULL;
+
+       for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++)
+               if (hdcp->connection.displays[i].index == index &&
+                               is_display_active(&hdcp->connection.displays[i])) {
+                       display = &hdcp->connection.displays[i];
+                       break;
+               }
+       return display;
+}
+
+static inline struct mod_hdcp_display *get_empty_display_container(
+               struct mod_hdcp *hdcp)
+{
+       uint8_t i;
+       struct mod_hdcp_display *display = NULL;
+
+       for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++)
+               if (!is_display_active(&hdcp->connection.displays[i])) {
+                       display = &hdcp->connection.displays[i];
+                       break;
+               }
+       return display;
+}
+
+static inline void reset_retry_counts(struct mod_hdcp *hdcp)
+{
+       hdcp->connection.hdcp1_retry_count = 0;
+}
+
+#endif /* HDCP_H_ */
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c
new file mode 100644 (file)
index 0000000..3db4a7d
--- /dev/null
@@ -0,0 +1,531 @@
+/*
+ * Copyright 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) 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 "hdcp.h"
+
+static inline enum mod_hdcp_status validate_bksv(struct mod_hdcp *hdcp)
+{
+       uint64_t n = *(uint64_t *)hdcp->auth.msg.hdcp1.bksv;
+       uint8_t count = 0;
+
+       while (n) {
+               count++;
+               n &= (n - 1);
+       }
+       return (count == 20) ? MOD_HDCP_STATUS_SUCCESS :
+                       MOD_HDCP_STATUS_HDCP1_INVALID_BKSV;
+}
+
+static inline enum mod_hdcp_status check_ksv_ready(struct mod_hdcp *hdcp)
+{
+       if (is_dp_hdcp(hdcp))
+               return (hdcp->auth.msg.hdcp1.bstatus & BSTATUS_READY_MASK_DP) ?
+                               MOD_HDCP_STATUS_SUCCESS :
+                               MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY;
+       return (hdcp->auth.msg.hdcp1.bcaps & BCAPS_READY_MASK) ?
+                       MOD_HDCP_STATUS_SUCCESS :
+                       MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY;
+}
+
+static inline enum mod_hdcp_status check_hdcp_capable_dp(struct mod_hdcp *hdcp)
+{
+       return (hdcp->auth.msg.hdcp1.bcaps & BCAPS_HDCP_CAPABLE_MASK_DP) ?
+                       MOD_HDCP_STATUS_SUCCESS :
+                       MOD_HDCP_STATUS_HDCP1_NOT_CAPABLE;
+}
+
+static inline enum mod_hdcp_status check_r0p_available_dp(struct mod_hdcp *hdcp)
+{
+       enum mod_hdcp_status status;
+       if (is_dp_hdcp(hdcp)) {
+               status = (hdcp->auth.msg.hdcp1.bstatus &
+                               BSTATUS_R0_P_AVAILABLE_MASK_DP) ?
+                       MOD_HDCP_STATUS_SUCCESS :
+                       MOD_HDCP_STATUS_HDCP1_R0_PRIME_PENDING;
+       } else {
+               status = MOD_HDCP_STATUS_INVALID_OPERATION;
+       }
+       return status;
+}
+
+static inline enum mod_hdcp_status check_link_integrity_dp(
+               struct mod_hdcp *hdcp)
+{
+       return (hdcp->auth.msg.hdcp1.bstatus &
+                       BSTATUS_LINK_INTEGRITY_FAILURE_MASK_DP) ?
+                       MOD_HDCP_STATUS_HDCP1_LINK_INTEGRITY_FAILURE :
+                       MOD_HDCP_STATUS_SUCCESS;
+}
+
+static inline enum mod_hdcp_status check_no_reauthentication_request_dp(
+               struct mod_hdcp *hdcp)
+{
+       return (hdcp->auth.msg.hdcp1.bstatus & BSTATUS_REAUTH_REQUEST_MASK_DP) ?
+                       MOD_HDCP_STATUS_HDCP1_REAUTH_REQUEST_ISSUED :
+                       MOD_HDCP_STATUS_SUCCESS;
+}
+
+static inline enum mod_hdcp_status check_no_max_cascade(struct mod_hdcp *hdcp)
+{
+       enum mod_hdcp_status status;
+
+       if (is_dp_hdcp(hdcp))
+               status = (hdcp->auth.msg.hdcp1.binfo_dp &
+                               BINFO_MAX_CASCADE_EXCEEDED_MASK_DP) ?
+                       MOD_HDCP_STATUS_HDCP1_MAX_CASCADE_EXCEEDED_FAILURE :
+                       MOD_HDCP_STATUS_SUCCESS;
+       else
+               status = (hdcp->auth.msg.hdcp1.bstatus &
+                               BSTATUS_MAX_CASCADE_EXCEEDED_MASK) ?
+                               MOD_HDCP_STATUS_HDCP1_MAX_CASCADE_EXCEEDED_FAILURE :
+                               MOD_HDCP_STATUS_SUCCESS;
+       return status;
+}
+
+static inline enum mod_hdcp_status check_no_max_devs(struct mod_hdcp *hdcp)
+{
+       enum mod_hdcp_status status;
+
+       if (is_dp_hdcp(hdcp))
+               status = (hdcp->auth.msg.hdcp1.binfo_dp &
+                               BINFO_MAX_DEVS_EXCEEDED_MASK_DP) ?
+                               MOD_HDCP_STATUS_HDCP1_MAX_DEVS_EXCEEDED_FAILURE :
+                               MOD_HDCP_STATUS_SUCCESS;
+       else
+               status = (hdcp->auth.msg.hdcp1.bstatus &
+                               BSTATUS_MAX_DEVS_EXCEEDED_MASK) ?
+                               MOD_HDCP_STATUS_HDCP1_MAX_DEVS_EXCEEDED_FAILURE :
+                               MOD_HDCP_STATUS_SUCCESS;
+       return status;
+}
+
+static inline uint8_t get_device_count(struct mod_hdcp *hdcp)
+{
+       return is_dp_hdcp(hdcp) ?
+                       (hdcp->auth.msg.hdcp1.binfo_dp & BINFO_DEVICE_COUNT_MASK_DP) :
+                       (hdcp->auth.msg.hdcp1.bstatus & BSTATUS_DEVICE_COUNT_MASK);
+}
+
+static inline enum mod_hdcp_status check_device_count(struct mod_hdcp *hdcp)
+{
+       /* device count must be greater than or equal to tracked hdcp displays */
+       return (get_device_count(hdcp) < get_added_display_count(hdcp)) ?
+                       MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE :
+                       MOD_HDCP_STATUS_SUCCESS;
+}
+
+static enum mod_hdcp_status wait_for_active_rx(struct mod_hdcp *hdcp,
+               struct mod_hdcp_event_context *event_ctx,
+               struct mod_hdcp_transition_input_hdcp1 *input)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+
+       if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
+               event_ctx->unexpected_event = 1;
+               goto out;
+       }
+
+       if (!mod_hdcp_execute_and_set(mod_hdcp_read_bksv,
+                       &input->bksv_read, &status,
+                       hdcp, "bksv_read"))
+               goto out;
+       if (!mod_hdcp_execute_and_set(mod_hdcp_read_bcaps,
+                       &input->bcaps_read, &status,
+                       hdcp, "bcaps_read"))
+               goto out;
+out:
+       return status;
+}
+
+static enum mod_hdcp_status exchange_ksvs(struct mod_hdcp *hdcp,
+               struct mod_hdcp_event_context *event_ctx,
+               struct mod_hdcp_transition_input_hdcp1 *input)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+
+       if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
+               event_ctx->unexpected_event = 1;
+               goto out;
+       }
+
+       if (!mod_hdcp_execute_and_set(mod_hdcp_add_display_topology,
+                       &input->add_topology, &status,
+                       hdcp, "add_topology"))
+               goto out;
+       if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_create_session,
+                       &input->create_session, &status,
+                       hdcp, "create_session"))
+               goto out;
+       if (!mod_hdcp_execute_and_set(mod_hdcp_write_an,
+                       &input->an_write, &status,
+                       hdcp, "an_write"))
+               goto out;
+       if (!mod_hdcp_execute_and_set(mod_hdcp_write_aksv,
+                       &input->aksv_write, &status,
+                       hdcp, "aksv_write"))
+               goto out;
+       if (!mod_hdcp_execute_and_set(mod_hdcp_read_bksv,
+                       &input->bksv_read, &status,
+                       hdcp, "bksv_read"))
+               goto out;
+       if (!mod_hdcp_execute_and_set(validate_bksv,
+                       &input->bksv_validation, &status,
+                       hdcp, "bksv_validation"))
+               goto out;
+       if (hdcp->auth.msg.hdcp1.ainfo) {
+               if (!mod_hdcp_execute_and_set(mod_hdcp_write_ainfo,
+                               &input->ainfo_write, &status,
+                               hdcp, "ainfo_write"))
+                       goto out;
+       }
+out:
+       return status;
+}
+
+static enum mod_hdcp_status computations_validate_rx_test_for_repeater(
+               struct mod_hdcp *hdcp,
+               struct mod_hdcp_event_context *event_ctx,
+               struct mod_hdcp_transition_input_hdcp1 *input)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+
+       if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
+               event_ctx->unexpected_event = 1;
+               goto out;
+       }
+
+       if (!mod_hdcp_execute_and_set(mod_hdcp_read_r0p,
+                       &input->r0p_read, &status,
+                       hdcp, "r0p_read"))
+               goto out;
+       if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_validate_rx,
+                       &input->rx_validation, &status,
+                       hdcp, "rx_validation"))
+               goto out;
+       if (hdcp->connection.is_repeater) {
+               if (!hdcp->connection.link.adjust.hdcp1.postpone_encryption)
+                       if (!mod_hdcp_execute_and_set(
+                                       mod_hdcp_hdcp1_enable_encryption,
+                                       &input->encryption, &status,
+                                       hdcp, "encryption"))
+                               goto out;
+       } else {
+               if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_enable_encryption,
+                               &input->encryption, &status,
+                               hdcp, "encryption"))
+                       goto out;
+               if (is_dp_mst_hdcp(hdcp))
+                       if (!mod_hdcp_execute_and_set(
+                                       mod_hdcp_hdcp1_enable_dp_stream_encryption,
+                                       &input->stream_encryption_dp, &status,
+                                       hdcp, "stream_encryption_dp"))
+                               goto out;
+       }
+out:
+       return status;
+}
+
+static enum mod_hdcp_status authenticated(struct mod_hdcp *hdcp,
+               struct mod_hdcp_event_context *event_ctx,
+               struct mod_hdcp_transition_input_hdcp1 *input)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+
+       if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
+               event_ctx->unexpected_event = 1;
+               goto out;
+       }
+
+       if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_link_maintenance,
+                       &input->link_maintenance, &status,
+                       hdcp, "link_maintenance"))
+               goto out;
+out:
+       return status;
+}
+
+static enum mod_hdcp_status wait_for_ready(struct mod_hdcp *hdcp,
+               struct mod_hdcp_event_context *event_ctx,
+               struct mod_hdcp_transition_input_hdcp1 *input)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+
+       if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
+                       event_ctx->event != MOD_HDCP_EVENT_CPIRQ &&
+                       event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
+               event_ctx->unexpected_event = 1;
+               goto out;
+       }
+
+       if (is_dp_hdcp(hdcp)) {
+               if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus,
+                               &input->bstatus_read, &status,
+                               hdcp, "bstatus_read"))
+                       goto out;
+               if (!mod_hdcp_execute_and_set(check_link_integrity_dp,
+                               &input->link_integiry_check, &status,
+                               hdcp, "link_integiry_check"))
+                       goto out;
+               if (!mod_hdcp_execute_and_set(check_no_reauthentication_request_dp,
+                               &input->reauth_request_check, &status,
+                               hdcp, "reauth_request_check"))
+                       goto out;
+       } else {
+               if (!mod_hdcp_execute_and_set(mod_hdcp_read_bcaps,
+                               &input->bcaps_read, &status,
+                               hdcp, "bcaps_read"))
+                       goto out;
+       }
+       if (!mod_hdcp_execute_and_set(check_ksv_ready,
+                       &input->ready_check, &status,
+                       hdcp, "ready_check"))
+               goto out;
+out:
+       return status;
+}
+
+static enum mod_hdcp_status read_ksv_list(struct mod_hdcp *hdcp,
+               struct mod_hdcp_event_context *event_ctx,
+               struct mod_hdcp_transition_input_hdcp1 *input)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+       uint8_t device_count;
+
+       if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
+               event_ctx->unexpected_event = 1;
+               goto out;
+       }
+
+       if (is_dp_hdcp(hdcp)) {
+               if (!mod_hdcp_execute_and_set(mod_hdcp_read_binfo,
+                               &input->binfo_read_dp, &status,
+                               hdcp, "binfo_read_dp"))
+                       goto out;
+       } else {
+               if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus,
+                               &input->bstatus_read, &status,
+                               hdcp, "bstatus_read"))
+                       goto out;
+       }
+       if (!mod_hdcp_execute_and_set(check_no_max_cascade,
+                       &input->max_cascade_check, &status,
+                       hdcp, "max_cascade_check"))
+               goto out;
+       if (!mod_hdcp_execute_and_set(check_no_max_devs,
+                       &input->max_devs_check, &status,
+                       hdcp, "max_devs_check"))
+               goto out;
+       if (!mod_hdcp_execute_and_set(check_device_count,
+                       &input->device_count_check, &status,
+                       hdcp, "device_count_check"))
+               goto out;
+       device_count = get_device_count(hdcp);
+       hdcp->auth.msg.hdcp1.ksvlist_size = device_count*5;
+       if (!mod_hdcp_execute_and_set(mod_hdcp_read_ksvlist,
+                       &input->ksvlist_read, &status,
+                       hdcp, "ksvlist_read"))
+               goto out;
+       if (!mod_hdcp_execute_and_set(mod_hdcp_read_vp,
+                       &input->vp_read, &status,
+                       hdcp, "vp_read"))
+               goto out;
+       if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_validate_ksvlist_vp,
+                       &input->ksvlist_vp_validation, &status,
+                       hdcp, "ksvlist_vp_validation"))
+               goto out;
+       if (input->encryption != PASS)
+               if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_enable_encryption,
+                               &input->encryption, &status,
+                               hdcp, "encryption"))
+                       goto out;
+       if (is_dp_mst_hdcp(hdcp))
+               if (!mod_hdcp_execute_and_set(
+                               mod_hdcp_hdcp1_enable_dp_stream_encryption,
+                               &input->stream_encryption_dp, &status,
+                               hdcp, "stream_encryption_dp"))
+                       goto out;
+out:
+       return status;
+}
+
+static enum mod_hdcp_status determine_rx_hdcp_capable_dp(struct mod_hdcp *hdcp,
+               struct mod_hdcp_event_context *event_ctx,
+               struct mod_hdcp_transition_input_hdcp1 *input)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+
+       if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
+               event_ctx->unexpected_event = 1;
+               goto out;
+       }
+
+       if (!mod_hdcp_execute_and_set(mod_hdcp_read_bcaps,
+                       &input->bcaps_read, &status,
+                       hdcp, "bcaps_read"))
+               goto out;
+       if (!mod_hdcp_execute_and_set(check_hdcp_capable_dp,
+                       &input->hdcp_capable_dp, &status,
+                       hdcp, "hdcp_capable_dp"))
+               goto out;
+out:
+       return status;
+}
+
+static enum mod_hdcp_status wait_for_r0_prime_dp(struct mod_hdcp *hdcp,
+               struct mod_hdcp_event_context *event_ctx,
+               struct mod_hdcp_transition_input_hdcp1 *input)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+
+       if (event_ctx->event != MOD_HDCP_EVENT_CPIRQ &&
+                       event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
+               event_ctx->unexpected_event = 1;
+               goto out;
+       }
+
+       if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus,
+                       &input->bstatus_read, &status,
+                       hdcp, "bstatus_read"))
+               goto out;
+       if (!mod_hdcp_execute_and_set(check_r0p_available_dp,
+                       &input->r0p_available_dp, &status,
+                       hdcp, "r0p_available_dp"))
+               goto out;
+out:
+       return status;
+}
+
+static enum mod_hdcp_status authenticated_dp(struct mod_hdcp *hdcp,
+               struct mod_hdcp_event_context *event_ctx,
+               struct mod_hdcp_transition_input_hdcp1 *input)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+
+       if (event_ctx->event != MOD_HDCP_EVENT_CPIRQ) {
+               event_ctx->unexpected_event = 1;
+               goto out;
+       }
+
+       if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus,
+                       &input->bstatus_read, &status,
+                       hdcp, "bstatus_read"))
+               goto out;
+       if (!mod_hdcp_execute_and_set(check_link_integrity_dp,
+                       &input->link_integiry_check, &status,
+                       hdcp, "link_integiry_check"))
+               goto out;
+       if (!mod_hdcp_execute_and_set(check_no_reauthentication_request_dp,
+                       &input->reauth_request_check, &status,
+                       hdcp, "reauth_request_check"))
+               goto out;
+out:
+       return status;
+}
+
+uint8_t mod_hdcp_execute_and_set(
+               mod_hdcp_action func, uint8_t *flag,
+               enum mod_hdcp_status *status, struct mod_hdcp *hdcp, char *str)
+{
+       *status = func(hdcp);
+       if (*status == MOD_HDCP_STATUS_SUCCESS && *flag != PASS) {
+               HDCP_INPUT_PASS_TRACE(hdcp, str);
+               *flag = PASS;
+       } else if (*status != MOD_HDCP_STATUS_SUCCESS && *flag != FAIL) {
+               HDCP_INPUT_FAIL_TRACE(hdcp, str);
+               *flag = FAIL;
+       }
+       return (*status == MOD_HDCP_STATUS_SUCCESS);
+}
+
+enum mod_hdcp_status mod_hdcp_hdcp1_execution(struct mod_hdcp *hdcp,
+               struct mod_hdcp_event_context *event_ctx,
+               struct mod_hdcp_transition_input_hdcp1 *input)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+
+       switch (current_state(hdcp)) {
+       case H1_A0_WAIT_FOR_ACTIVE_RX:
+               status = wait_for_active_rx(hdcp, event_ctx, input);
+               break;
+       case H1_A1_EXCHANGE_KSVS:
+               status = exchange_ksvs(hdcp, event_ctx, input);
+               break;
+       case H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER:
+               status = computations_validate_rx_test_for_repeater(hdcp,
+                               event_ctx, input);
+               break;
+       case H1_A45_AUTHENTICATED:
+               status = authenticated(hdcp, event_ctx, input);
+               break;
+       case H1_A8_WAIT_FOR_READY:
+               status = wait_for_ready(hdcp, event_ctx, input);
+               break;
+       case H1_A9_READ_KSV_LIST:
+               status = read_ksv_list(hdcp, event_ctx, input);
+               break;
+       default:
+               status = MOD_HDCP_STATUS_INVALID_STATE;
+               break;
+       }
+
+       return status;
+}
+
+extern enum mod_hdcp_status mod_hdcp_hdcp1_dp_execution(struct mod_hdcp *hdcp,
+               struct mod_hdcp_event_context *event_ctx,
+               struct mod_hdcp_transition_input_hdcp1 *input)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+
+       switch (current_state(hdcp)) {
+       case D1_A0_DETERMINE_RX_HDCP_CAPABLE:
+               status = determine_rx_hdcp_capable_dp(hdcp, event_ctx, input);
+               break;
+       case D1_A1_EXCHANGE_KSVS:
+               status = exchange_ksvs(hdcp, event_ctx, input);
+               break;
+       case D1_A23_WAIT_FOR_R0_PRIME:
+               status = wait_for_r0_prime_dp(hdcp, event_ctx, input);
+               break;
+       case D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER:
+               status = computations_validate_rx_test_for_repeater(
+                               hdcp, event_ctx, input);
+               break;
+       case D1_A4_AUTHENTICATED:
+               status = authenticated_dp(hdcp, event_ctx, input);
+               break;
+       case D1_A6_WAIT_FOR_READY:
+               status = wait_for_ready(hdcp, event_ctx, input);
+               break;
+       case D1_A7_READ_KSV_LIST:
+               status = read_ksv_list(hdcp, event_ctx, input);
+               break;
+       default:
+               status = MOD_HDCP_STATUS_INVALID_STATE;
+               break;
+       }
+
+       return status;
+}
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_transition.c
new file mode 100644 (file)
index 0000000..136b801
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Copyright 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) 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 "hdcp.h"
+
+enum mod_hdcp_status mod_hdcp_hdcp1_transition(struct mod_hdcp *hdcp,
+               struct mod_hdcp_event_context *event_ctx,
+               struct mod_hdcp_transition_input_hdcp1 *input,
+               struct mod_hdcp_output *output)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+       struct mod_hdcp_connection *conn = &hdcp->connection;
+       struct mod_hdcp_link_adjustment *adjust = &hdcp->connection.link.adjust;
+
+       switch (current_state(hdcp)) {
+       case H1_A0_WAIT_FOR_ACTIVE_RX:
+               if (input->bksv_read != PASS || input->bcaps_read != PASS) {
+                       /* 1A-04: repeatedly attempts on port access failure */
+                       callback_in_ms(500, output);
+                       increment_stay_counter(hdcp);
+                       break;
+               }
+               callback_in_ms(0, output);
+               set_state_id(hdcp, output, H1_A1_EXCHANGE_KSVS);
+               break;
+       case H1_A1_EXCHANGE_KSVS:
+               if (input->add_topology != PASS ||
+                               input->create_session != PASS) {
+                       /* out of sync with psp state */
+                       adjust->hdcp1.disable = 1;
+                       fail_and_restart_in_ms(0, &status, output);
+                       break;
+               } else if (input->an_write != PASS ||
+                               input->aksv_write != PASS ||
+                               input->bksv_read != PASS ||
+                               input->bksv_validation != PASS ||
+                               input->ainfo_write == FAIL) {
+                       /* 1A-05: consider invalid bksv a failure */
+                       fail_and_restart_in_ms(0, &status, output);
+                       break;
+               }
+               callback_in_ms(300, output);
+               set_state_id(hdcp, output,
+                       H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER);
+               break;
+       case H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER:
+               if (input->bcaps_read != PASS ||
+                               input->r0p_read != PASS ||
+                               input->rx_validation != PASS ||
+                               (!conn->is_repeater && input->encryption != PASS)) {
+                       /* 1A-06: consider invalid r0' a failure */
+                       /* 1A-08: consider bksv listed in SRM a failure */
+                       fail_and_restart_in_ms(0, &status, output);
+                       break;
+               }
+               if (conn->is_repeater) {
+                       callback_in_ms(0, output);
+                       set_watchdog_in_ms(hdcp, 5000, output);
+                       set_state_id(hdcp, output, H1_A8_WAIT_FOR_READY);
+               } else {
+                       callback_in_ms(0, output);
+                       set_state_id(hdcp, output, H1_A45_AUTHENTICATED);
+                       HDCP_FULL_DDC_TRACE(hdcp);
+               }
+               break;
+       case H1_A45_AUTHENTICATED:
+               if (input->link_maintenance != PASS) {
+                       /* 1A-07: consider invalid ri' a failure */
+                       /* 1A-07a: consider read ri' not returned a failure */
+                       fail_and_restart_in_ms(0, &status, output);
+                       break;
+               }
+               callback_in_ms(500, output);
+               increment_stay_counter(hdcp);
+               break;
+       case H1_A8_WAIT_FOR_READY:
+               if (input->ready_check != PASS) {
+                       if (event_ctx->event ==
+                                       MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
+                               /* 1B-03: fail hdcp on ksv list READY timeout */
+                               /* prevent black screen in next attempt */
+                               adjust->hdcp1.postpone_encryption = 1;
+                               fail_and_restart_in_ms(0, &status, output);
+                       } else {
+                               /* continue ksv list READY polling*/
+                               callback_in_ms(500, output);
+                               increment_stay_counter(hdcp);
+                       }
+                       break;
+               }
+               callback_in_ms(0, output);
+               set_state_id(hdcp, output, H1_A9_READ_KSV_LIST);
+               break;
+       case H1_A9_READ_KSV_LIST:
+               if (input->bstatus_read != PASS ||
+                               input->max_cascade_check != PASS ||
+                               input->max_devs_check != PASS ||
+                               input->device_count_check != PASS ||
+                               input->ksvlist_read != PASS ||
+                               input->vp_read != PASS ||
+                               input->ksvlist_vp_validation != PASS ||
+                               input->encryption != PASS) {
+                       /* 1B-06: consider MAX_CASCADE_EXCEEDED a failure */
+                       /* 1B-05: consider MAX_DEVS_EXCEEDED a failure */
+                       /* 1B-04: consider invalid v' a failure */
+                       fail_and_restart_in_ms(0, &status, output);
+                       break;
+               }
+               callback_in_ms(0, output);
+               set_state_id(hdcp, output, H1_A45_AUTHENTICATED);
+               HDCP_FULL_DDC_TRACE(hdcp);
+               break;
+       default:
+               status = MOD_HDCP_STATUS_INVALID_STATE;
+               fail_and_restart_in_ms(0, &status, output);
+               break;
+       }
+
+       return status;
+}
+
+enum mod_hdcp_status mod_hdcp_hdcp1_dp_transition(struct mod_hdcp *hdcp,
+               struct mod_hdcp_event_context *event_ctx,
+               struct mod_hdcp_transition_input_hdcp1 *input,
+               struct mod_hdcp_output *output)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
+       struct mod_hdcp_connection *conn = &hdcp->connection;
+       struct mod_hdcp_link_adjustment *adjust = &hdcp->connection.link.adjust;
+
+       switch (current_state(hdcp)) {
+       case D1_A0_DETERMINE_RX_HDCP_CAPABLE:
+               if (input->bcaps_read != PASS) {
+                       /* 1A-04: no authentication on bcaps read failure */
+                       fail_and_restart_in_ms(0, &status, output);
+                       break;
+               } else if (input->hdcp_capable_dp != PASS) {
+                       adjust->hdcp1.disable = 1;
+                       fail_and_restart_in_ms(0, &status, output);
+                       break;
+               }
+               callback_in_ms(0, output);
+               set_state_id(hdcp, output, D1_A1_EXCHANGE_KSVS);
+               break;
+       case D1_A1_EXCHANGE_KSVS:
+               if (input->add_topology != PASS ||
+                               input->create_session != PASS) {
+                       /* out of sync with psp state */
+                       adjust->hdcp1.disable = 1;
+                       fail_and_restart_in_ms(0, &status, output);
+                       break;
+               } else if (input->an_write != PASS ||
+                               input->aksv_write != PASS ||
+                               input->bksv_read != PASS ||
+                               input->bksv_validation != PASS ||
+                               input->ainfo_write == FAIL) {
+                       /* 1A-05: consider invalid bksv a failure */
+                       fail_and_restart_in_ms(0, &status, output);
+                       break;
+               }
+               set_watchdog_in_ms(hdcp, 100, output);
+               set_state_id(hdcp, output, D1_A23_WAIT_FOR_R0_PRIME);
+               break;
+       case D1_A23_WAIT_FOR_R0_PRIME:
+               if (input->bstatus_read != PASS) {
+                       fail_and_restart_in_ms(0, &status, output);
+                       break;
+               } else if (input->r0p_available_dp != PASS) {
+                       if (event_ctx->event == MOD_HDCP_EVENT_WATCHDOG_TIMEOUT)
+                               fail_and_restart_in_ms(0, &status, output);
+                       else
+                               increment_stay_counter(hdcp);
+                       break;
+               }
+               callback_in_ms(0, output);
+               set_state_id(hdcp, output, D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER);
+               break;
+       case D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER:
+               if (input->r0p_read != PASS) {
+                       fail_and_restart_in_ms(0, &status, output);
+                       break;
+               } else if (input->rx_validation != PASS) {
+                       if (hdcp->state.stay_count < 2) {
+                               /* allow 2 additional retries */
+                               callback_in_ms(0, output);
+                               increment_stay_counter(hdcp);
+                       } else {
+                               /*
+                                * 1A-06: consider invalid r0' a failure
+                                * after 3 attempts.
+                                * 1A-08: consider bksv listed in SRM a failure
+                                */
+                               fail_and_restart_in_ms(0, &status, output);
+                       }
+                       break;
+               } else if ((!conn->is_repeater && input->encryption != PASS) ||
+                               (!conn->is_repeater && is_dp_mst_hdcp(hdcp) && input->stream_encryption_dp != PASS)) {
+                       fail_and_restart_in_ms(0, &status, output);
+                       break;
+               }
+               if (conn->is_repeater) {
+                       set_watchdog_in_ms(hdcp, 5000, output);
+                       set_state_id(hdcp, output, D1_A6_WAIT_FOR_READY);
+               } else {
+                       set_state_id(hdcp, output, D1_A4_AUTHENTICATED);
+                       HDCP_FULL_DDC_TRACE(hdcp);
+               }
+               break;
+       case D1_A4_AUTHENTICATED:
+               if (input->link_integiry_check != PASS ||
+                               input->reauth_request_check != PASS) {
+                       /* 1A-07: restart hdcp on a link integrity failure */
+                       fail_and_restart_in_ms(0, &status, output);
+                       break;
+               }
+               break;
+       case D1_A6_WAIT_FOR_READY:
+               if (input->link_integiry_check == FAIL ||
+                               input->reauth_request_check == FAIL) {
+                       fail_and_restart_in_ms(0, &status, output);
+                       break;
+               } else if (input->ready_check != PASS) {
+                       if (event_ctx->event ==
+                                       MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
+                               /* 1B-04: fail hdcp on ksv list READY timeout */
+                               /* prevent black screen in next attempt */
+                               adjust->hdcp1.postpone_encryption = 1;
+                               fail_and_restart_in_ms(0, &status, output);
+                       } else {
+                               increment_stay_counter(hdcp);
+                       }
+                       break;
+               }
+               callback_in_ms(0, output);
+               set_state_id(hdcp, output, D1_A7_READ_KSV_LIST);
+               break;
+       case D1_A7_READ_KSV_LIST:
+               if (input->binfo_read_dp != PASS ||
+                               input->max_cascade_check != PASS ||
+                               input->max_devs_check != PASS) {
+                       /* 1B-06: consider MAX_DEVS_EXCEEDED a failure */
+                       /* 1B-07: consider MAX_CASCADE_EXCEEDED a failure */
+                       fail_and_restart_in_ms(0, &status, output);
+                       break;
+               } else if (input->device_count_check != PASS) {
+                       /*
+                        * some slow dongle doesn't update
+                        * device count as soon as downstream is connected.
+                        * give it more time to react.
+                        */
+                       adjust->hdcp1.postpone_encryption = 1;
+                       fail_and_restart_in_ms(1000, &status, output);
+                       break;
+               } else if (input->ksvlist_read != PASS ||
+                               input->vp_read != PASS) {
+                       fail_and_restart_in_ms(0, &status, output);
+                       break;
+               } else if (input->ksvlist_vp_validation != PASS) {
+                       if (hdcp->state.stay_count < 2) {
+                               /* allow 2 additional retries */
+                               callback_in_ms(0, output);
+                               increment_stay_counter(hdcp);
+                       } else {
+                               /*
+                                * 1B-05: consider invalid v' a failure
+                                * after 3 attempts.
+                                */
+                               fail_and_restart_in_ms(0, &status, output);
+                       }
+                       break;
+               } else if (input->encryption != PASS ||
+                               (is_dp_mst_hdcp(hdcp) && input->stream_encryption_dp != PASS)) {
+                       fail_and_restart_in_ms(0, &status, output);
+                       break;
+               }
+               set_state_id(hdcp, output, D1_A4_AUTHENTICATED);
+               HDCP_FULL_DDC_TRACE(hdcp);
+               break;
+       default:
+               fail_and_restart_in_ms(0, &status, output);
+               break;
+       }
+
+       return status;
+}
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c
new file mode 100644 (file)
index 0000000..e7baae0
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * Copyright 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) 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 "hdcp.h"
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define HDCP_I2C_ADDR 0x3a     /* 0x74 >> 1*/
+#define KSV_READ_SIZE 0xf      /* 0x6803b - 0x6802c */
+#define HDCP_MAX_AUX_TRANSACTION_SIZE 16
+
+enum mod_hdcp_ddc_message_id {
+       MOD_HDCP_MESSAGE_ID_INVALID = -1,
+
+       /* HDCP 1.4 */
+
+       MOD_HDCP_MESSAGE_ID_READ_BKSV = 0,
+       MOD_HDCP_MESSAGE_ID_READ_RI_R0,
+       MOD_HDCP_MESSAGE_ID_WRITE_AKSV,
+       MOD_HDCP_MESSAGE_ID_WRITE_AINFO,
+       MOD_HDCP_MESSAGE_ID_WRITE_AN,
+       MOD_HDCP_MESSAGE_ID_READ_VH_X,
+       MOD_HDCP_MESSAGE_ID_READ_VH_0,
+       MOD_HDCP_MESSAGE_ID_READ_VH_1,
+       MOD_HDCP_MESSAGE_ID_READ_VH_2,
+       MOD_HDCP_MESSAGE_ID_READ_VH_3,
+       MOD_HDCP_MESSAGE_ID_READ_VH_4,
+       MOD_HDCP_MESSAGE_ID_READ_BCAPS,
+       MOD_HDCP_MESSAGE_ID_READ_BSTATUS,
+       MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO,
+       MOD_HDCP_MESSAGE_ID_READ_BINFO,
+
+       MOD_HDCP_MESSAGE_ID_MAX
+};
+
+static const uint8_t hdcp_i2c_offsets[] = {
+       [MOD_HDCP_MESSAGE_ID_READ_BKSV] = 0x0,
+       [MOD_HDCP_MESSAGE_ID_READ_RI_R0] = 0x8,
+       [MOD_HDCP_MESSAGE_ID_WRITE_AKSV] = 0x10,
+       [MOD_HDCP_MESSAGE_ID_WRITE_AINFO] = 0x15,
+       [MOD_HDCP_MESSAGE_ID_WRITE_AN] = 0x18,
+       [MOD_HDCP_MESSAGE_ID_READ_VH_X] = 0x20,
+       [MOD_HDCP_MESSAGE_ID_READ_VH_0] = 0x20,
+       [MOD_HDCP_MESSAGE_ID_READ_VH_1] = 0x24,
+       [MOD_HDCP_MESSAGE_ID_READ_VH_2] = 0x28,
+       [MOD_HDCP_MESSAGE_ID_READ_VH_3] = 0x2C,
+       [MOD_HDCP_MESSAGE_ID_READ_VH_4] = 0x30,
+       [MOD_HDCP_MESSAGE_ID_READ_BCAPS] = 0x40,
+       [MOD_HDCP_MESSAGE_ID_READ_BSTATUS] = 0x41,
+       [MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x43,
+       [MOD_HDCP_MESSAGE_ID_READ_BINFO] = 0xFF,
+};
+
+static const uint32_t hdcp_dpcd_addrs[] = {
+       [MOD_HDCP_MESSAGE_ID_READ_BKSV] = 0x68000,
+       [MOD_HDCP_MESSAGE_ID_READ_RI_R0] = 0x68005,
+       [MOD_HDCP_MESSAGE_ID_WRITE_AKSV] = 0x68007,
+       [MOD_HDCP_MESSAGE_ID_WRITE_AINFO] = 0x6803B,
+       [MOD_HDCP_MESSAGE_ID_WRITE_AN] = 0x6800c,
+       [MOD_HDCP_MESSAGE_ID_READ_VH_X] = 0x68014,
+       [MOD_HDCP_MESSAGE_ID_READ_VH_0] = 0x68014,
+       [MOD_HDCP_MESSAGE_ID_READ_VH_1] = 0x68018,
+       [MOD_HDCP_MESSAGE_ID_READ_VH_2] = 0x6801c,
+       [MOD_HDCP_MESSAGE_ID_READ_VH_3] = 0x68020,
+       [MOD_HDCP_MESSAGE_ID_READ_VH_4] = 0x68024,
+       [MOD_HDCP_MESSAGE_ID_READ_BCAPS] = 0x68028,
+       [MOD_HDCP_MESSAGE_ID_READ_BSTATUS] = 0x68029,
+       [MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x6802c,
+       [MOD_HDCP_MESSAGE_ID_READ_BINFO] = 0x6802a,
+};
+
+static enum mod_hdcp_status read(struct mod_hdcp *hdcp,
+               enum mod_hdcp_ddc_message_id msg_id,
+               uint8_t *buf,
+               uint32_t buf_len)
+{
+       bool success = true;
+       uint32_t cur_size = 0;
+       uint32_t data_offset = 0;
+
+       if (is_dp_hdcp(hdcp)) {
+               while (buf_len > 0) {
+                       cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE);
+                       success = hdcp->config.ddc.funcs.read_dpcd(hdcp->config.ddc.handle,
+                                       hdcp_dpcd_addrs[msg_id] + data_offset,
+                                       buf + data_offset,
+                                       cur_size);
+
+                       if (!success)
+                               break;
+
+                       buf_len -= cur_size;
+                       data_offset += cur_size;
+               }
+       } else {
+               success = hdcp->config.ddc.funcs.read_i2c(
+                               hdcp->config.ddc.handle,
+                               HDCP_I2C_ADDR,
+                               hdcp_i2c_offsets[msg_id],
+                               buf,
+                               (uint32_t)buf_len);
+       }
+
+       return success ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE;
+}
+
+static enum mod_hdcp_status read_repeatedly(struct mod_hdcp *hdcp,
+               enum mod_hdcp_ddc_message_id msg_id,
+               uint8_t *buf,
+               uint32_t buf_len,
+               uint8_t read_size)
+{
+       enum mod_hdcp_status status = MOD_HDCP_STATUS_DDC_FAILURE;
+       uint32_t cur_size = 0;
+       uint32_t data_offset = 0;
+
+       while (buf_len > 0) {
+               cur_size = MIN(buf_len, read_size);
+               status = read(hdcp, msg_id, buf + data_offset, cur_size);
+
+               if (status != MOD_HDCP_STATUS_SUCCESS)
+                       break;
+
+               buf_len -= cur_size;
+               data_offset += cur_size;
+       }
+
+       return status;
+}
+
+static enum mod_hdcp_status write(struct mod_hdcp *hdcp,
+               enum mod_hdcp_ddc_message_id msg_id,
+               uint8_t *buf,
+               uint32_t buf_len)
+{
+       bool success = true;
+       uint32_t cur_size = 0;
+       uint32_t data_offset = 0;
+
+       if (is_dp_hdcp(hdcp)) {
+               while (buf_len > 0) {
+                       cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE);
+                       success = hdcp->config.ddc.funcs.write_dpcd(
+                                       hdcp->config.ddc.handle,
+                                       hdcp_dpcd_addrs[msg_id] + data_offset,
+                                       buf + data_offset,
+                                       cur_size);
+
+                       if (!success)
+                               break;
+
+                       buf_len -= cur_size;
+                       data_offset += cur_size;
+               }
+       } else {
+               hdcp->buf[0] = hdcp_i2c_offsets[msg_id];
+               memmove(&hdcp->buf[1], buf, buf_len);
+               success = hdcp->config.ddc.funcs.write_i2c(
+                               hdcp->config.ddc.handle,
+                               HDCP_I2C_ADDR,
+                               hdcp->buf,
+                               (uint32_t)(buf_len+1));
+       }
+
+       return success ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE;
+}
+
+enum mod_hdcp_status mod_hdcp_read_bksv(struct mod_hdcp *hdcp)
+{
+       return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BKSV,
+                       hdcp->auth.msg.hdcp1.bksv,
+                       sizeof(hdcp->auth.msg.hdcp1.bksv));
+}
+
+enum mod_hdcp_status mod_hdcp_read_bcaps(struct mod_hdcp *hdcp)
+{
+       return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BCAPS,
+                       &hdcp->auth.msg.hdcp1.bcaps,
+                       sizeof(hdcp->auth.msg.hdcp1.bcaps));
+}
+
+enum mod_hdcp_status mod_hdcp_read_bstatus(struct mod_hdcp *hdcp)
+{
+       enum mod_hdcp_status status;
+
+       if (is_dp_hdcp(hdcp))
+               status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BSTATUS,
+                                       (uint8_t *)&hdcp->auth.msg.hdcp1.bstatus,
+                                       1);
+       else
+               status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BSTATUS,
+                               (uint8_t *)&hdcp->auth.msg.hdcp1.bstatus,
+                               sizeof(hdcp->auth.msg.hdcp1.bstatus));
+       return status;
+}
+
+enum mod_hdcp_status mod_hdcp_read_r0p(struct mod_hdcp *hdcp)
+{
+       return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_RI_R0,
+                       (uint8_t *)&hdcp->auth.msg.hdcp1.r0p,
+                       sizeof(hdcp->auth.msg.hdcp1.r0p));
+}
+
+/* special case, reading repeatedly at the same address, don't use read() */
+enum mod_hdcp_status mod_hdcp_read_ksvlist(struct mod_hdcp *hdcp)
+{
+       enum mod_hdcp_status status;
+
+       if (is_dp_hdcp(hdcp))
+               status = read_repeatedly(hdcp, MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO,
+                               hdcp->auth.msg.hdcp1.ksvlist,
+                               hdcp->auth.msg.hdcp1.ksvlist_size,
+                               KSV_READ_SIZE);
+       else
+               status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO,
+                               (uint8_t *)&hdcp->auth.msg.hdcp1.ksvlist,
+                               hdcp->auth.msg.hdcp1.ksvlist_size);
+       return status;
+}
+
+enum mod_hdcp_status mod_hdcp_read_vp(struct mod_hdcp *hdcp)
+{
+       enum mod_hdcp_status status;
+
+       status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_0,
+                       &hdcp->auth.msg.hdcp1.vp[0], 4);
+       if (status != MOD_HDCP_STATUS_SUCCESS)
+               goto out;
+
+       status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_1,
+                       &hdcp->auth.msg.hdcp1.vp[4], 4);
+       if (status != MOD_HDCP_STATUS_SUCCESS)
+               goto out;
+
+       status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_2,
+                       &hdcp->auth.msg.hdcp1.vp[8], 4);
+       if (status != MOD_HDCP_STATUS_SUCCESS)
+               goto out;
+
+       status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_3,
+                       &hdcp->auth.msg.hdcp1.vp[12], 4);
+       if (status != MOD_HDCP_STATUS_SUCCESS)
+               goto out;
+
+       status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_4,
+                       &hdcp->auth.msg.hdcp1.vp[16], 4);
+out:
+       return status;
+}
+
+enum mod_hdcp_status mod_hdcp_read_binfo(struct mod_hdcp *hdcp)
+{
+       enum mod_hdcp_status status;
+
+       if (is_dp_hdcp(hdcp))
+               status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BINFO,
+                               (uint8_t *)&hdcp->auth.msg.hdcp1.binfo_dp,
+                               sizeof(hdcp->auth.msg.hdcp1.binfo_dp));
+       else
+               status = MOD_HDCP_STATUS_INVALID_OPERATION;
+
+       return status;
+}
+
+enum mod_hdcp_status mod_hdcp_write_aksv(struct mod_hdcp *hdcp)
+{
+       return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKSV,
+                       hdcp->auth.msg.hdcp1.aksv,
+                       sizeof(hdcp->auth.msg.hdcp1.aksv));
+}
+
+enum mod_hdcp_status mod_hdcp_write_ainfo(struct mod_hdcp *hdcp)
+{
+       return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AINFO,
+                       &hdcp->auth.msg.hdcp1.ainfo,
+                       sizeof(hdcp->auth.msg.hdcp1.ainfo));
+}
+
+enum mod_hdcp_status mod_hdcp_write_an(struct mod_hdcp *hdcp)
+{
+       return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AN,
+                       hdcp->auth.msg.hdcp1.an,
+                       sizeof(hdcp->auth.msg.hdcp1.an));
+}
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.c
new file mode 100644 (file)
index 0000000..3982ced
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright 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) 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 "hdcp.h"
+
+void mod_hdcp_dump_binary_message(uint8_t *msg, uint32_t msg_size,
+               uint8_t *buf, uint32_t buf_size)
+{
+       const uint8_t bytes_per_line = 16,
+                       byte_size = 3,
+                       newline_size = 1,
+                       terminator_size = 1;
+       uint32_t line_count = msg_size / bytes_per_line,
+                       trailing_bytes = msg_size % bytes_per_line;
+       uint32_t target_size = (byte_size * bytes_per_line + newline_size) * line_count +
+                       byte_size * trailing_bytes + newline_size + terminator_size;
+       uint32_t buf_pos = 0;
+       uint32_t i = 0;
+
+       if (buf_size >= target_size) {
+               for (i = 0; i < msg_size; i++) {
+                       if (i % bytes_per_line == 0)
+                               buf[buf_pos++] = '\n';
+                       sprintf(&buf[buf_pos], "%02X ", msg[i]);
+                       buf_pos += byte_size;
+               }
+               buf[buf_pos++] = '\0';
+       }
+}
+
+char *mod_hdcp_status_to_str(int32_t status)
+{
+       switch (status) {
+       case MOD_HDCP_STATUS_SUCCESS:
+               return "MOD_HDCP_STATUS_SUCCESS";
+       case MOD_HDCP_STATUS_FAILURE:
+               return "MOD_HDCP_STATUS_FAILURE";
+       case MOD_HDCP_STATUS_RESET_NEEDED:
+               return "MOD_HDCP_STATUS_RESET_NEEDED";
+       case MOD_HDCP_STATUS_DISPLAY_OUT_OF_BOUND:
+               return "MOD_HDCP_STATUS_DISPLAY_OUT_OF_BOUND";
+       case MOD_HDCP_STATUS_DISPLAY_NOT_FOUND:
+               return "MOD_HDCP_STATUS_DISPLAY_NOT_FOUND";
+       case MOD_HDCP_STATUS_INVALID_STATE:
+               return "MOD_HDCP_STATUS_INVALID_STATE";
+       case MOD_HDCP_STATUS_NOT_IMPLEMENTED:
+               return "MOD_HDCP_STATUS_NOT_IMPLEMENTED";
+       case MOD_HDCP_STATUS_INTERNAL_POLICY_FAILURE:
+               return "MOD_HDCP_STATUS_INTERNAL_POLICY_FAILURE";
+       case MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE:
+               return "MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE";
+       case MOD_HDCP_STATUS_CREATE_PSP_SERVICE_FAILURE:
+               return "MOD_HDCP_STATUS_CREATE_PSP_SERVICE_FAILURE";
+       case MOD_HDCP_STATUS_DESTROY_PSP_SERVICE_FAILURE:
+               return "MOD_HDCP_STATUS_DESTROY_PSP_SERVICE_FAILURE";
+       case MOD_HDCP_STATUS_HDCP1_CREATE_SESSION_FAILURE:
+               return "MOD_HDCP_STATUS_HDCP1_CREATE_SESSION_FAILURE";
+       case MOD_HDCP_STATUS_HDCP1_DESTROY_SESSION_FAILURE:
+               return "MOD_HDCP_STATUS_HDCP1_DESTROY_SESSION_FAILURE";
+       case MOD_HDCP_STATUS_HDCP1_VALIDATE_ENCRYPTION_FAILURE:
+               return "MOD_HDCP_STATUS_HDCP1_VALIDATE_ENCRYPTION_FAILURE";
+       case MOD_HDCP_STATUS_HDCP1_NOT_HDCP_REPEATER:
+               return "MOD_HDCP_STATUS_HDCP1_NOT_HDCP_REPEATER";
+       case MOD_HDCP_STATUS_HDCP1_NOT_CAPABLE:
+               return "MOD_HDCP_STATUS_HDCP1_NOT_CAPABLE";
+       case MOD_HDCP_STATUS_HDCP1_R0_PRIME_PENDING:
+               return "MOD_HDCP_STATUS_HDCP1_R0_PRIME_PENDING";
+       case MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE:
+               return "MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE";
+       case MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY:
+               return "MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY";
+       case MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE:
+               return "MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE";
+       case MOD_HDCP_STATUS_HDCP1_ENABLE_ENCRYPTION:
+               return "MOD_HDCP_STATUS_HDCP1_ENABLE_ENCRYPTION";
+       case MOD_HDCP_STATUS_HDCP1_ENABLE_STREAM_ENCRYPTION_FAILURE:
+               return "MOD_HDCP_STATUS_HDCP1_ENABLE_STREAM_ENCRYPTION_FAILURE";
+       case MOD_HDCP_STATUS_HDCP1_MAX_CASCADE_EXCEEDED_FAILURE:
+               return "MOD_HDCP_STATUS_HDCP1_MAX_CASCADE_EXCEEDED_FAILURE";
+       case MOD_HDCP_STATUS_HDCP1_MAX_DEVS_EXCEEDED_FAILURE:
+               return "MOD_HDCP_STATUS_HDCP1_MAX_DEVS_EXCEEDED_FAILURE";
+       case MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE:
+               return "MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE";
+       case MOD_HDCP_STATUS_HDCP1_LINK_INTEGRITY_FAILURE:
+               return "MOD_HDCP_STATUS_HDCP1_LINK_INTEGRITY_FAILURE";
+       case MOD_HDCP_STATUS_HDCP1_REAUTH_REQUEST_ISSUED:
+               return "MOD_HDCP_STATUS_HDCP1_REAUTH_REQUEST_ISSUED";
+       case MOD_HDCP_STATUS_HDCP1_LINK_MAINTENANCE_FAILURE:
+               return "MOD_HDCP_STATUS_HDCP1_LINK_MAINTENANCE_FAILURE";
+       case MOD_HDCP_STATUS_HDCP1_INVALID_BKSV:
+               return "MOD_HDCP_STATUS_HDCP1_INVALID_BKSV";
+       case MOD_HDCP_STATUS_DDC_FAILURE:
+               return "MOD_HDCP_STATUS_DDC_FAILURE";
+       case MOD_HDCP_STATUS_INVALID_OPERATION:
+               return "MOD_HDCP_STATUS_INVALID_OPERATION";
+       default:
+               return "MOD_HDCP_STATUS_UNKNOWN";
+       }
+}
+
+char *mod_hdcp_state_id_to_str(int32_t id)
+{
+       switch (id) {
+       case HDCP_UNINITIALIZED:
+               return "HDCP_UNINITIALIZED";
+       case HDCP_INITIALIZED:
+               return "HDCP_INITIALIZED";
+       case HDCP_CP_NOT_DESIRED:
+               return "HDCP_CP_NOT_DESIRED";
+       case H1_A0_WAIT_FOR_ACTIVE_RX:
+               return "H1_A0_WAIT_FOR_ACTIVE_RX";
+       case H1_A1_EXCHANGE_KSVS:
+               return "H1_A1_EXCHANGE_KSVS";
+       case H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER:
+               return "H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER";
+       case H1_A45_AUTHENTICATED:
+               return "H1_A45_AUTHENTICATED";
+       case H1_A8_WAIT_FOR_READY:
+               return "H1_A8_WAIT_FOR_READY";
+       case H1_A9_READ_KSV_LIST:
+               return "H1_A9_READ_KSV_LIST";
+       case D1_A0_DETERMINE_RX_HDCP_CAPABLE:
+               return "D1_A0_DETERMINE_RX_HDCP_CAPABLE";
+       case D1_A1_EXCHANGE_KSVS:
+               return "D1_A1_EXCHANGE_KSVS";
+       case D1_A23_WAIT_FOR_R0_PRIME:
+               return "D1_A23_WAIT_FOR_R0_PRIME";
+       case D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER:
+               return "D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER";
+       case D1_A4_AUTHENTICATED:
+               return "D1_A4_AUTHENTICATED";
+       case D1_A6_WAIT_FOR_READY:
+               return "D1_A6_WAIT_FOR_READY";
+       case D1_A7_READ_KSV_LIST:
+               return "D1_A7_READ_KSV_LIST";
+       default:
+               return "UNKNOWN_STATE_ID";
+       };
+}
+
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h
new file mode 100644 (file)
index 0000000..2fd0e0a
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright 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) 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 MOD_HDCP_LOG_H_
+#define MOD_HDCP_LOG_H_
+
+#ifdef CONFIG_DRM_AMD_DC_HDCP
+#define HDCP_LOG_ERR(hdcp, ...) DRM_ERROR(__VA_ARGS__)
+#define HDCP_LOG_VER(hdcp, ...) DRM_DEBUG_KMS(__VA_ARGS__)
+#define HDCP_LOG_FSM(hdcp, ...) DRM_DEBUG_KMS(__VA_ARGS__)
+#define HDCP_LOG_TOP(hdcp, ...) pr_debug("[HDCP_TOP]:"__VA_ARGS__)
+#define HDCP_LOG_DDC(hdcp, ...) pr_debug("[HDCP_DDC]:"__VA_ARGS__)
+#endif
+
+/* default logs */
+#define HDCP_ERROR_TRACE(hdcp, status) \
+               HDCP_LOG_ERR(hdcp, \
+                       "[Link %d] ERROR %s IN STATE %s", \
+                       hdcp->config.index, \
+                       mod_hdcp_status_to_str(status), \
+                       mod_hdcp_state_id_to_str(hdcp->state.id))
+#define HDCP_HDCP1_ENABLED_TRACE(hdcp, displayIndex) \
+               HDCP_LOG_VER(hdcp, \
+                       "[Link %d] HDCP 1.4 enabled on display %d", \
+                       hdcp->config.index, displayIndex)
+/* state machine logs */
+#define HDCP_REMOVE_DISPLAY_TRACE(hdcp, displayIndex) \
+               HDCP_LOG_FSM(hdcp, \
+                       "[Link %d] HDCP_REMOVE_DISPLAY index %d", \
+                       hdcp->config.index, displayIndex)
+#define HDCP_INPUT_PASS_TRACE(hdcp, str) \
+               HDCP_LOG_FSM(hdcp, \
+                       "[Link %d]\tPASS %s", \
+                       hdcp->config.index, str)
+#define HDCP_INPUT_FAIL_TRACE(hdcp, str) \
+               HDCP_LOG_FSM(hdcp, \
+                       "[Link %d]\tFAIL %s", \
+                       hdcp->config.index, str)
+#define HDCP_NEXT_STATE_TRACE(hdcp, id, output) do { \
+               if (output->watchdog_timer_needed) \
+                       HDCP_LOG_FSM(hdcp, \
+                               "[Link %d] > %s with %d ms watchdog", \
+                               hdcp->config.index, \
+                               mod_hdcp_state_id_to_str(id), output->watchdog_timer_delay); \
+               else \
+                       HDCP_LOG_FSM(hdcp, \
+                               "[Link %d] > %s", hdcp->config.index, \
+                               mod_hdcp_state_id_to_str(id)); \
+} while (0)
+#define HDCP_TIMEOUT_TRACE(hdcp) \
+               HDCP_LOG_FSM(hdcp, "[Link %d] --> TIMEOUT", hdcp->config.index)
+#define HDCP_CPIRQ_TRACE(hdcp) \
+               HDCP_LOG_FSM(hdcp, "[Link %d] --> CPIRQ", hdcp->config.index)
+#define HDCP_EVENT_TRACE(hdcp, event) \
+               if (event == MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) \
+                       HDCP_TIMEOUT_TRACE(hdcp); \
+               else if (event == MOD_HDCP_EVENT_CPIRQ) \
+                       HDCP_CPIRQ_TRACE(hdcp)
+/* TODO: find some way to tell if logging is off to save time */
+#define HDCP_DDC_READ_TRACE(hdcp, msg_name, msg, msg_size) do { \
+               mod_hdcp_dump_binary_message(msg, msg_size, hdcp->buf, \
+                               sizeof(hdcp->buf)); \
+               HDCP_LOG_DDC(hdcp, "[Link %d] Read %s%s", hdcp->config.index, \
+                               msg_name, hdcp->buf); \
+} while (0)
+#define HDCP_DDC_WRITE_TRACE(hdcp, msg_name, msg, msg_size) do { \
+               mod_hdcp_dump_binary_message(msg, msg_size, hdcp->buf, \
+                               sizeof(hdcp->buf)); \
+               HDCP_LOG_DDC(hdcp, "[Link %d] Write %s%s", \
+                               hdcp->config.index, msg_name,\
+                               hdcp->buf); \
+} while (0)
+#define HDCP_FULL_DDC_TRACE(hdcp) do { \
+       HDCP_DDC_READ_TRACE(hdcp, "BKSV", hdcp->auth.msg.hdcp1.bksv, \
+                       sizeof(hdcp->auth.msg.hdcp1.bksv)); \
+       HDCP_DDC_READ_TRACE(hdcp, "BCAPS", &hdcp->auth.msg.hdcp1.bcaps, \
+                       sizeof(hdcp->auth.msg.hdcp1.bcaps)); \
+       HDCP_DDC_WRITE_TRACE(hdcp, "AN", hdcp->auth.msg.hdcp1.an, \
+                       sizeof(hdcp->auth.msg.hdcp1.an)); \
+       HDCP_DDC_WRITE_TRACE(hdcp, "AKSV", hdcp->auth.msg.hdcp1.aksv, \
+                       sizeof(hdcp->auth.msg.hdcp1.aksv)); \
+       HDCP_DDC_WRITE_TRACE(hdcp, "AINFO", &hdcp->auth.msg.hdcp1.ainfo, \
+                       sizeof(hdcp->auth.msg.hdcp1.ainfo)); \
+       HDCP_DDC_READ_TRACE(hdcp, "RI' / R0'", \
+                       (uint8_t *)&hdcp->auth.msg.hdcp1.r0p, \
+                       sizeof(hdcp->auth.msg.hdcp1.r0p)); \
+       HDCP_DDC_READ_TRACE(hdcp, "BINFO", \
+                       (uint8_t *)&hdcp->auth.msg.hdcp1.binfo_dp, \
+                       sizeof(hdcp->auth.msg.hdcp1.binfo_dp)); \
+       HDCP_DDC_READ_TRACE(hdcp, "KSVLIST", hdcp->auth.msg.hdcp1.ksvlist, \
+                       hdcp->auth.msg.hdcp1.ksvlist_size); \
+       HDCP_DDC_READ_TRACE(hdcp, "V'", hdcp->auth.msg.hdcp1.vp, \
+                       sizeof(hdcp->auth.msg.hdcp1.vp)); \
+} while (0)
+#define HDCP_TOP_ADD_DISPLAY_TRACE(hdcp, i) \
+               HDCP_LOG_TOP(hdcp, "[Link %d]\tadd display %d", \
+                               hdcp->config.index, i)
+#define HDCP_TOP_REMOVE_DISPLAY_TRACE(hdcp, i) \
+               HDCP_LOG_TOP(hdcp, "[Link %d]\tremove display %d", \
+                               hdcp->config.index, i)
+#define HDCP_TOP_HDCP1_DESTROY_SESSION_TRACE(hdcp) \
+               HDCP_LOG_TOP(hdcp, "[Link %d]\tdestroy hdcp1 session", \
+                               hdcp->config.index)
+#define HDCP_TOP_RESET_AUTH_TRACE(hdcp) \
+               HDCP_LOG_TOP(hdcp, "[Link %d]\treset authentication", hdcp->config.index)
+#define HDCP_TOP_RESET_CONN_TRACE(hdcp) \
+               HDCP_LOG_TOP(hdcp, "[Link %d]\treset connection", hdcp->config.index)
+#define HDCP_TOP_INTERFACE_TRACE(hdcp) do { \
+               HDCP_LOG_TOP(hdcp, "\n"); \
+               HDCP_LOG_TOP(hdcp, "[Link %d] %s", hdcp->config.index, __func__); \
+} while (0)
+#define HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, i) do { \
+               HDCP_LOG_TOP(hdcp, "\n"); \
+               HDCP_LOG_TOP(hdcp, "[Link %d] %s display %d", hdcp->config.index, __func__, i); \
+} while (0)
+
+#endif // MOD_HDCP_LOG_H_
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
new file mode 100644 (file)
index 0000000..646d909
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * 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
+ *
+ */
+
+#define MAX_NUM_DISPLAYS 24
+
+
+#include "hdcp.h"
+
+#include "amdgpu.h"
+#include "hdcp_psp.h"
+
+enum mod_hdcp_status mod_hdcp_remove_display_topology(struct mod_hdcp *hdcp)
+{
+
+       struct psp_context *psp = hdcp->config.psp.handle;
+       struct ta_dtm_shared_memory *dtm_cmd;
+       struct mod_hdcp_display *display = NULL;
+       uint8_t i;
+
+       dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.dtm_shared_buf;
+
+       for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) {
+               if (hdcp->connection.displays[i].state == MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED) {
+
+                       memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory));
+
+                       display = &hdcp->connection.displays[i];
+
+                       dtm_cmd->cmd_id = TA_DTM_COMMAND__TOPOLOGY_UPDATE_V2;
+                       dtm_cmd->dtm_in_message.topology_update_v2.display_handle = display->index;
+                       dtm_cmd->dtm_in_message.topology_update_v2.is_active = 0;
+                       dtm_cmd->dtm_status = TA_DTM_STATUS__GENERIC_FAILURE;
+
+                       psp_dtm_invoke(psp, dtm_cmd->cmd_id);
+
+                       if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS)
+                               return MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE;
+
+                       display->state = MOD_HDCP_DISPLAY_ACTIVE;
+                       HDCP_TOP_REMOVE_DISPLAY_TRACE(hdcp, display->index);
+               }
+       }
+
+       return MOD_HDCP_STATUS_SUCCESS;
+}
+
+enum mod_hdcp_status mod_hdcp_add_display_topology(struct mod_hdcp *hdcp)
+{
+       struct psp_context *psp = hdcp->config.psp.handle;
+       struct ta_dtm_shared_memory *dtm_cmd;
+       struct mod_hdcp_display *display = NULL;
+       struct mod_hdcp_link *link = &hdcp->connection.link;
+       uint8_t i;
+
+       if (!psp->dtm_context.dtm_initialized) {
+               DRM_ERROR("Failed to add display topology, DTM TA is not initialized.");
+               return MOD_HDCP_STATUS_FAILURE;
+       }
+
+       dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.dtm_shared_buf;
+
+       for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) {
+               if (hdcp->connection.displays[i].state == MOD_HDCP_DISPLAY_ACTIVE) {
+                       display = &hdcp->connection.displays[i];
+
+                       memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory));
+
+                       dtm_cmd->cmd_id = TA_DTM_COMMAND__TOPOLOGY_UPDATE_V2;
+                       dtm_cmd->dtm_in_message.topology_update_v2.display_handle = display->index;
+                       dtm_cmd->dtm_in_message.topology_update_v2.is_active = 1;
+                       dtm_cmd->dtm_in_message.topology_update_v2.controller = display->controller;
+                       dtm_cmd->dtm_in_message.topology_update_v2.ddc_line = link->ddc_line;
+                       dtm_cmd->dtm_in_message.topology_update_v2.dig_be = link->dig_be;
+                       dtm_cmd->dtm_in_message.topology_update_v2.dig_fe = display->dig_fe;
+                       dtm_cmd->dtm_in_message.topology_update_v2.dp_mst_vcid = display->vc_id;
+                       dtm_cmd->dtm_in_message.topology_update_v2.max_hdcp_supported_version =
+                               TA_DTM_HDCP_VERSION_MAX_SUPPORTED__1_x;
+                       dtm_cmd->dtm_status = TA_DTM_STATUS__GENERIC_FAILURE;
+
+                       psp_dtm_invoke(psp, dtm_cmd->cmd_id);
+
+                       if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS)
+                               return MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE;
+
+                       display->state = MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED;
+                       HDCP_TOP_ADD_DISPLAY_TRACE(hdcp, display->index);
+               }
+       }
+
+       return MOD_HDCP_STATUS_SUCCESS;
+}
+
+enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp)
+{
+
+       struct psp_context *psp = hdcp->config.psp.handle;
+       struct mod_hdcp_display *display = get_first_added_display(hdcp);
+       struct ta_hdcp_shared_memory *hdcp_cmd;
+
+       if (!psp->hdcp_context.hdcp_initialized) {
+               DRM_ERROR("Failed to create hdcp session. HDCP TA is not initialized.");
+               return MOD_HDCP_STATUS_FAILURE;
+       }
+
+       hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+       memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
+
+       hdcp_cmd->in_msg.hdcp1_create_session.display_handle = display->index;
+       hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP1_CREATE_SESSION;
+
+       psp_hdcp_invoke(psp, hdcp_cmd->cmd_id);
+
+       if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS)
+               return MOD_HDCP_STATUS_HDCP1_CREATE_SESSION_FAILURE;
+
+       hdcp->auth.id = hdcp_cmd->out_msg.hdcp1_create_session.session_handle;
+       hdcp->auth.msg.hdcp1.ainfo = hdcp_cmd->out_msg.hdcp1_create_session.ainfo_primary;
+       memcpy(hdcp->auth.msg.hdcp1.aksv, hdcp_cmd->out_msg.hdcp1_create_session.aksv_primary,
+               sizeof(hdcp->auth.msg.hdcp1.aksv));
+       memcpy(hdcp->auth.msg.hdcp1.an, hdcp_cmd->out_msg.hdcp1_create_session.an_primary,
+               sizeof(hdcp->auth.msg.hdcp1.an));
+
+       return MOD_HDCP_STATUS_SUCCESS;
+}
+
+enum mod_hdcp_status mod_hdcp_hdcp1_destroy_session(struct mod_hdcp *hdcp)
+{
+
+       struct psp_context *psp = hdcp->config.psp.handle;
+       struct ta_hdcp_shared_memory *hdcp_cmd;
+
+       hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+       memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
+
+       hdcp_cmd->in_msg.hdcp1_destroy_session.session_handle = hdcp->auth.id;
+       hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP1_DESTROY_SESSION;
+
+       psp_hdcp_invoke(psp, hdcp_cmd->cmd_id);
+
+       if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS)
+               return MOD_HDCP_STATUS_HDCP1_DESTROY_SESSION_FAILURE;
+
+       HDCP_TOP_HDCP1_DESTROY_SESSION_TRACE(hdcp);
+
+       return MOD_HDCP_STATUS_SUCCESS;
+}
+
+enum mod_hdcp_status mod_hdcp_hdcp1_validate_rx(struct mod_hdcp *hdcp)
+{
+       struct psp_context *psp = hdcp->config.psp.handle;
+       struct ta_hdcp_shared_memory *hdcp_cmd;
+
+       hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+       memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
+
+       hdcp_cmd->in_msg.hdcp1_first_part_authentication.session_handle = hdcp->auth.id;
+
+       memcpy(hdcp_cmd->in_msg.hdcp1_first_part_authentication.bksv_primary, hdcp->auth.msg.hdcp1.bksv,
+               TA_HDCP__HDCP1_KSV_SIZE);
+
+       hdcp_cmd->in_msg.hdcp1_first_part_authentication.r0_prime_primary = hdcp->auth.msg.hdcp1.r0p;
+       hdcp_cmd->in_msg.hdcp1_first_part_authentication.bcaps = hdcp->auth.msg.hdcp1.bcaps;
+       hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP1_FIRST_PART_AUTHENTICATION;
+
+       psp_hdcp_invoke(psp, hdcp_cmd->cmd_id);
+
+       if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS)
+               return MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE;
+
+       if (hdcp_cmd->out_msg.hdcp1_first_part_authentication.authentication_status ==
+           TA_HDCP_AUTHENTICATION_STATUS__HDCP1_FIRST_PART_COMPLETE) {
+               /* needs second part of authentication */
+               hdcp->connection.is_repeater = 1;
+       } else if (hdcp_cmd->out_msg.hdcp1_first_part_authentication.authentication_status ==
+                  TA_HDCP_AUTHENTICATION_STATUS__HDCP1_AUTHENTICATED) {
+               hdcp->connection.is_repeater = 0;
+       } else
+               return MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE;
+
+
+       return MOD_HDCP_STATUS_SUCCESS;
+}
+
+enum mod_hdcp_status mod_hdcp_hdcp1_enable_encryption(struct mod_hdcp *hdcp)
+{
+       struct psp_context *psp = hdcp->config.psp.handle;
+       struct ta_hdcp_shared_memory *hdcp_cmd;
+       struct mod_hdcp_display *display = get_first_added_display(hdcp);
+
+       hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+       memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
+
+       hdcp_cmd->in_msg.hdcp1_enable_encryption.session_handle = hdcp->auth.id;
+       hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP1_ENABLE_ENCRYPTION;
+
+       psp_hdcp_invoke(psp, hdcp_cmd->cmd_id);
+
+       if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS)
+               return MOD_HDCP_STATUS_HDCP1_ENABLE_ENCRYPTION;
+
+       if (!is_dp_mst_hdcp(hdcp)) {
+               display->state = MOD_HDCP_DISPLAY_ENCRYPTION_ENABLED;
+               HDCP_HDCP1_ENABLED_TRACE(hdcp, display->index);
+       }
+       return MOD_HDCP_STATUS_SUCCESS;
+}
+
+enum mod_hdcp_status mod_hdcp_hdcp1_validate_ksvlist_vp(struct mod_hdcp *hdcp)
+{
+       struct psp_context *psp = hdcp->config.psp.handle;
+       struct ta_hdcp_shared_memory *hdcp_cmd;
+
+       hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+       memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
+
+       hdcp_cmd->in_msg.hdcp1_second_part_authentication.session_handle = hdcp->auth.id;
+
+       hdcp_cmd->in_msg.hdcp1_second_part_authentication.ksv_list_size = hdcp->auth.msg.hdcp1.ksvlist_size;
+       memcpy(hdcp_cmd->in_msg.hdcp1_second_part_authentication.ksv_list, hdcp->auth.msg.hdcp1.ksvlist,
+              hdcp->auth.msg.hdcp1.ksvlist_size);
+
+       memcpy(hdcp_cmd->in_msg.hdcp1_second_part_authentication.v_prime, hdcp->auth.msg.hdcp1.vp,
+              sizeof(hdcp->auth.msg.hdcp1.vp));
+
+       hdcp_cmd->in_msg.hdcp1_second_part_authentication.bstatus_binfo =
+               is_dp_hdcp(hdcp) ? hdcp->auth.msg.hdcp1.binfo_dp : hdcp->auth.msg.hdcp1.bstatus;
+       hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP1_SECOND_PART_AUTHENTICATION;
+
+       psp_hdcp_invoke(psp, hdcp_cmd->cmd_id);
+
+       if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS)
+               return MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE;
+
+       return MOD_HDCP_STATUS_SUCCESS;
+}
+
+enum mod_hdcp_status mod_hdcp_hdcp1_enable_dp_stream_encryption(struct mod_hdcp *hdcp)
+{
+
+       struct psp_context *psp = hdcp->config.psp.handle;
+       struct ta_hdcp_shared_memory *hdcp_cmd;
+       int i = 0;
+
+       hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+
+       for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) {
+
+               if (hdcp->connection.displays[i].state != MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED ||
+                   hdcp->connection.displays[i].adjust.disable)
+                       continue;
+
+               memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
+
+               hdcp_cmd->in_msg.hdcp1_enable_dp_stream_encryption.session_handle = hdcp->auth.id;
+               hdcp_cmd->in_msg.hdcp1_enable_dp_stream_encryption.display_handle = hdcp->connection.displays[i].index;
+               hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP1_ENABLE_DP_STREAM_ENCRYPTION;
+
+               psp_hdcp_invoke(psp, hdcp_cmd->cmd_id);
+
+               if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS)
+                       return MOD_HDCP_STATUS_HDCP1_ENABLE_STREAM_ENCRYPTION_FAILURE;
+
+               hdcp->connection.displays[i].state = MOD_HDCP_DISPLAY_ENCRYPTION_ENABLED;
+               HDCP_HDCP1_ENABLED_TRACE(hdcp, hdcp->connection.displays[i].index);
+       }
+
+       return MOD_HDCP_STATUS_SUCCESS;
+}
+
+enum mod_hdcp_status mod_hdcp_hdcp1_link_maintenance(struct mod_hdcp *hdcp)
+{
+       struct psp_context *psp = hdcp->config.psp.handle;
+       struct ta_hdcp_shared_memory *hdcp_cmd;
+
+       hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
+
+       memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
+
+       hdcp_cmd->in_msg.hdcp1_get_encryption_status.session_handle = hdcp->auth.id;
+
+       hdcp_cmd->out_msg.hdcp1_get_encryption_status.protection_level = 0;
+       hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP1_GET_ENCRYPTION_STATUS;
+
+       psp_hdcp_invoke(psp, hdcp_cmd->cmd_id);
+
+       if (hdcp_cmd->hdcp_status != TA_HDCP_STATUS__SUCCESS)
+               return MOD_HDCP_STATUS_HDCP1_LINK_MAINTENANCE_FAILURE;
+
+       return (hdcp_cmd->out_msg.hdcp1_get_encryption_status.protection_level == 1)
+                      ? MOD_HDCP_STATUS_SUCCESS
+                      : MOD_HDCP_STATUS_HDCP1_LINK_MAINTENANCE_FAILURE;
+}
+
+enum mod_hdcp_status mod_hdcp_hdcp1_get_link_encryption_status(struct mod_hdcp *hdcp,
+                                                              enum mod_hdcp_encryption_status *encryption_status)
+{
+       *encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
+
+       if (mod_hdcp_hdcp1_link_maintenance(hdcp) != MOD_HDCP_STATUS_SUCCESS)
+               return MOD_HDCP_STATUS_FAILURE;
+
+       *encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP1_ON;
+
+       return MOD_HDCP_STATUS_SUCCESS;
+}
+
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.h
new file mode 100644 (file)
index 0000000..986fc07
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright 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) 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 MODULES_HDCP_HDCP_PSP_H_
+#define MODULES_HDCP_HDCP_PSP_H_
+
+/*
+ * NOTE: These parameters are a one-to-one copy of the
+ * parameters required by PSP
+ */
+enum bgd_security_hdcp_encryption_level {
+       HDCP_ENCRYPTION_LEVEL__INVALID = 0,
+       HDCP_ENCRYPTION_LEVEL__OFF,
+       HDCP_ENCRYPTION_LEVEL__ON
+};
+
+enum ta_dtm_command {
+       TA_DTM_COMMAND__UNUSED_1 = 1,
+       TA_DTM_COMMAND__TOPOLOGY_UPDATE_V2,
+       TA_DTM_COMMAND__TOPOLOGY_ASSR_ENABLE
+};
+
+/* DTM related enumerations */
+/**********************************************************/
+
+enum ta_dtm_status {
+       TA_DTM_STATUS__SUCCESS = 0x00,
+       TA_DTM_STATUS__GENERIC_FAILURE = 0x01,
+       TA_DTM_STATUS__INVALID_PARAMETER = 0x02,
+       TA_DTM_STATUS__NULL_POINTER = 0x3
+};
+
+/* input/output structures for DTM commands */
+/**********************************************************/
+/**
+ * Input structures
+ */
+enum ta_dtm_hdcp_version_max_supported {
+       TA_DTM_HDCP_VERSION_MAX_SUPPORTED__NONE = 0,
+       TA_DTM_HDCP_VERSION_MAX_SUPPORTED__1_x = 10,
+       TA_DTM_HDCP_VERSION_MAX_SUPPORTED__2_0 = 20,
+       TA_DTM_HDCP_VERSION_MAX_SUPPORTED__2_1 = 21,
+       TA_DTM_HDCP_VERSION_MAX_SUPPORTED__2_2 = 22,
+       TA_DTM_HDCP_VERSION_MAX_SUPPORTED__2_3 = 23
+};
+
+struct ta_dtm_topology_update_input_v2 {
+       /* display handle is unique across the driver and is used to identify a display */
+       /* for all security interfaces which reference displays such as HDCP */
+       uint32_t display_handle;
+       uint32_t is_active;
+       uint32_t is_miracast;
+       uint32_t controller;
+       uint32_t ddc_line;
+       uint32_t dig_be;
+       uint32_t dig_fe;
+       uint32_t dp_mst_vcid;
+       uint32_t is_assr;
+       uint32_t max_hdcp_supported_version;
+};
+
+struct ta_dtm_topology_assr_enable {
+       uint32_t display_topology_dig_be_index;
+};
+
+/**
+ * Output structures
+ */
+
+/* No output structures yet */
+
+union ta_dtm_cmd_input {
+       struct ta_dtm_topology_update_input_v2 topology_update_v2;
+       struct ta_dtm_topology_assr_enable topology_assr_enable;
+};
+
+union ta_dtm_cmd_output {
+       uint32_t reserved;
+};
+
+struct ta_dtm_shared_memory {
+       uint32_t cmd_id;
+       uint32_t resp_id;
+       enum ta_dtm_status dtm_status;
+       uint32_t reserved;
+       union ta_dtm_cmd_input dtm_in_message;
+       union ta_dtm_cmd_output dtm_out_message;
+};
+
+int psp_cmd_submit_buf(struct psp_context *psp, struct amdgpu_firmware_info *ucode, struct psp_gfx_cmd_resp *cmd,
+               uint64_t fence_mc_addr);
+
+enum ta_hdcp_command {
+       TA_HDCP_COMMAND__INITIALIZE,
+       TA_HDCP_COMMAND__HDCP1_CREATE_SESSION,
+       TA_HDCP_COMMAND__HDCP1_DESTROY_SESSION,
+       TA_HDCP_COMMAND__HDCP1_FIRST_PART_AUTHENTICATION,
+       TA_HDCP_COMMAND__HDCP1_SECOND_PART_AUTHENTICATION,
+       TA_HDCP_COMMAND__HDCP1_ENABLE_ENCRYPTION,
+       TA_HDCP_COMMAND__HDCP1_ENABLE_DP_STREAM_ENCRYPTION,
+       TA_HDCP_COMMAND__HDCP1_GET_ENCRYPTION_STATUS,
+};
+
+
+/* HDCP related enumerations */
+/**********************************************************/
+#define TA_HDCP__INVALID_SESSION 0xFFFF
+#define TA_HDCP__HDCP1_AN_SIZE 8
+#define TA_HDCP__HDCP1_KSV_SIZE 5
+#define TA_HDCP__HDCP1_KSV_LIST_MAX_ENTRIES 127
+#define TA_HDCP__HDCP1_V_PRIME_SIZE 20
+
+enum ta_hdcp_status {
+       TA_HDCP_STATUS__SUCCESS = 0x00,
+       TA_HDCP_STATUS__GENERIC_FAILURE = 0x01,
+       TA_HDCP_STATUS__NULL_POINTER = 0x02,
+       TA_HDCP_STATUS__FAILED_ALLOCATING_SESSION = 0x03,
+       TA_HDCP_STATUS__FAILED_SETUP_TX = 0x04,
+       TA_HDCP_STATUS__INVALID_PARAMETER = 0x05,
+       TA_HDCP_STATUS__VHX_ERROR = 0x06,
+       TA_HDCP_STATUS__SESSION_NOT_CLOSED_PROPERLY = 0x07,
+       TA_HDCP_STATUS__SRM_FAILURE = 0x08,
+       TA_HDCP_STATUS__MST_AUTHENTICATED_ALREADY_STARTED = 0x09,
+       TA_HDCP_STATUS__AKE_SEND_CERT_FAILURE = 0x0A,
+       TA_HDCP_STATUS__AKE_NO_STORED_KM_FAILURE = 0x0B,
+       TA_HDCP_STATUS__AKE_SEND_HPRIME_FAILURE = 0x0C,
+       TA_HDCP_STATUS__LC_SEND_LPRIME_FAILURE = 0x0D,
+       TA_HDCP_STATUS__SKE_SEND_EKS_FAILURE = 0x0E,
+       TA_HDCP_STATUS__REPAUTH_SEND_RXIDLIST_FAILURE = 0x0F,
+       TA_HDCP_STATUS__REPAUTH_STREAM_READY_FAILURE = 0x10,
+       TA_HDCP_STATUS__ASD_GENERIC_FAILURE = 0x11,
+       TA_HDCP_STATUS__UNWRAP_SECRET_FAILURE = 0x12,
+       TA_HDCP_STATUS__ENABLE_ENCR_FAILURE = 0x13,
+       TA_HDCP_STATUS__DISABLE_ENCR_FAILURE = 0x14,
+       TA_HDCP_STATUS__NOT_ENOUGH_MEMORY_FAILURE = 0x15,
+       TA_HDCP_STATUS__UNKNOWN_MESSAGE = 0x16,
+       TA_HDCP_STATUS__TOO_MANY_STREAM = 0x17
+};
+
+enum ta_hdcp_authentication_status {
+       TA_HDCP_AUTHENTICATION_STATUS__NOT_STARTED = 0x00,
+       TA_HDCP_AUTHENTICATION_STATUS__HDCP1_FIRST_PART_FAILED = 0x01,
+       TA_HDCP_AUTHENTICATION_STATUS__HDCP1_FIRST_PART_COMPLETE = 0x02,
+       TA_HDCP_AUTHENTICATION_STATUS__HDCP1_SECOND_PART_FAILED = 0x03,
+       TA_HDCP_AUTHENTICATION_STATUS__HDCP1_AUTHENTICATED = 0x04,
+       TA_HDCP_AUTHENTICATION_STATUS__HDCP1_KSV_VALIDATION_FAILED = 0x09
+};
+
+
+/* input/output structures for HDCP commands */
+/**********************************************************/
+struct ta_hdcp_cmd_hdcp1_create_session_input {
+       uint8_t display_handle;
+};
+
+struct ta_hdcp_cmd_hdcp1_create_session_output {
+       uint32_t session_handle;
+       uint8_t an_primary[TA_HDCP__HDCP1_AN_SIZE];
+       uint8_t aksv_primary[TA_HDCP__HDCP1_KSV_SIZE];
+       uint8_t ainfo_primary;
+       uint8_t an_secondary[TA_HDCP__HDCP1_AN_SIZE];
+       uint8_t aksv_secondary[TA_HDCP__HDCP1_KSV_SIZE];
+       uint8_t ainfo_secondary;
+};
+
+struct ta_hdcp_cmd_hdcp1_destroy_session_input {
+       uint32_t session_handle;
+};
+
+struct ta_hdcp_cmd_hdcp1_first_part_authentication_input {
+       uint32_t session_handle;
+       uint8_t bksv_primary[TA_HDCP__HDCP1_KSV_SIZE];
+       uint8_t bksv_secondary[TA_HDCP__HDCP1_KSV_SIZE];
+       uint8_t bcaps;
+       uint16_t r0_prime_primary;
+       uint16_t r0_prime_secondary;
+};
+
+struct ta_hdcp_cmd_hdcp1_first_part_authentication_output {
+       enum ta_hdcp_authentication_status authentication_status;
+};
+
+struct ta_hdcp_cmd_hdcp1_second_part_authentication_input {
+       uint32_t session_handle;
+       uint16_t bstatus_binfo;
+       uint8_t ksv_list[TA_HDCP__HDCP1_KSV_LIST_MAX_ENTRIES][TA_HDCP__HDCP1_KSV_SIZE];
+       uint32_t ksv_list_size;
+       uint8_t pj_prime;
+       uint8_t v_prime[TA_HDCP__HDCP1_V_PRIME_SIZE];
+};
+
+struct ta_hdcp_cmd_hdcp1_second_part_authentication_output {
+       enum ta_hdcp_authentication_status authentication_status;
+};
+
+struct ta_hdcp_cmd_hdcp1_enable_encryption_input {
+       uint32_t session_handle;
+};
+
+struct ta_hdcp_cmd_hdcp1_enable_dp_stream_encryption_input {
+       uint32_t session_handle;
+       uint32_t display_handle;
+};
+
+struct ta_hdcp_cmd_hdcp1_get_encryption_status_input {
+       uint32_t session_handle;
+};
+
+struct ta_hdcp_cmd_hdcp1_get_encryption_status_output {
+       uint32_t protection_level;
+};
+
+/**********************************************************/
+/* Common input structure for HDCP callbacks */
+union ta_hdcp_cmd_input {
+       struct ta_hdcp_cmd_hdcp1_create_session_input hdcp1_create_session;
+       struct ta_hdcp_cmd_hdcp1_destroy_session_input hdcp1_destroy_session;
+       struct ta_hdcp_cmd_hdcp1_first_part_authentication_input hdcp1_first_part_authentication;
+       struct ta_hdcp_cmd_hdcp1_second_part_authentication_input hdcp1_second_part_authentication;
+       struct ta_hdcp_cmd_hdcp1_enable_encryption_input hdcp1_enable_encryption;
+       struct ta_hdcp_cmd_hdcp1_enable_dp_stream_encryption_input hdcp1_enable_dp_stream_encryption;
+       struct ta_hdcp_cmd_hdcp1_get_encryption_status_input hdcp1_get_encryption_status;
+};
+
+/* Common output structure for HDCP callbacks */
+union ta_hdcp_cmd_output {
+       struct ta_hdcp_cmd_hdcp1_create_session_output hdcp1_create_session;
+       struct ta_hdcp_cmd_hdcp1_first_part_authentication_output hdcp1_first_part_authentication;
+       struct ta_hdcp_cmd_hdcp1_second_part_authentication_output hdcp1_second_part_authentication;
+       struct ta_hdcp_cmd_hdcp1_get_encryption_status_output hdcp1_get_encryption_status;
+};
+/**********************************************************/
+
+struct ta_hdcp_shared_memory {
+       uint32_t cmd_id;
+       enum ta_hdcp_status hdcp_status;
+       uint32_t reserved;
+       union ta_hdcp_cmd_input in_msg;
+       union ta_hdcp_cmd_output out_msg;
+};
+
+enum psp_status {
+       PSP_STATUS__SUCCESS = 0,
+       PSP_STATUS__ERROR_INVALID_PARAMS,
+       PSP_STATUS__ERROR_GENERIC,
+       PSP_STATUS__ERROR_OUT_OF_MEMORY,
+       PSP_STATUS__ERROR_UNSUPPORTED_FEATURE
+};
+
+#endif /* MODULES_HDCP_HDCP_PSP_H_ */
index dc187844d10b1f5e99e4423f15cadb6b422643d5..dbe7835aabcf747c25825e76dac9d2e047bb9025 100644 (file)
@@ -92,6 +92,7 @@ struct mod_vrr_params_btr {
        uint32_t inserted_duration_in_us;
        uint32_t frames_to_insert;
        uint32_t frame_counter;
+       uint32_t margin_in_us;
 };
 
 struct mod_vrr_params_fixed_refresh {
diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h b/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h
new file mode 100644 (file)
index 0000000..dea2170
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * Copyright 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) 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 MOD_HDCP_H_
+#define MOD_HDCP_H_
+
+#include "os_types.h"
+#include "signal_types.h"
+
+/* Forward Declarations */
+struct mod_hdcp;
+
+#define MAX_NUM_OF_DISPLAYS 6
+#define MAX_NUM_OF_ATTEMPTS 4
+#define MAX_NUM_OF_ERROR_TRACE 10
+
+/* detailed return status */
+enum mod_hdcp_status {
+       MOD_HDCP_STATUS_SUCCESS = 0,
+       MOD_HDCP_STATUS_FAILURE,
+       MOD_HDCP_STATUS_RESET_NEEDED,
+       MOD_HDCP_STATUS_DISPLAY_OUT_OF_BOUND,
+       MOD_HDCP_STATUS_DISPLAY_NOT_FOUND,
+       MOD_HDCP_STATUS_INVALID_STATE,
+       MOD_HDCP_STATUS_NOT_IMPLEMENTED,
+       MOD_HDCP_STATUS_INTERNAL_POLICY_FAILURE,
+       MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE,
+       MOD_HDCP_STATUS_CREATE_PSP_SERVICE_FAILURE,
+       MOD_HDCP_STATUS_DESTROY_PSP_SERVICE_FAILURE,
+       MOD_HDCP_STATUS_HDCP1_CREATE_SESSION_FAILURE,
+       MOD_HDCP_STATUS_HDCP1_DESTROY_SESSION_FAILURE,
+       MOD_HDCP_STATUS_HDCP1_VALIDATE_ENCRYPTION_FAILURE,
+       MOD_HDCP_STATUS_HDCP1_NOT_HDCP_REPEATER,
+       MOD_HDCP_STATUS_HDCP1_NOT_CAPABLE,
+       MOD_HDCP_STATUS_HDCP1_R0_PRIME_PENDING,
+       MOD_HDCP_STATUS_HDCP1_VALIDATE_RX_FAILURE,
+       MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY,
+       MOD_HDCP_STATUS_HDCP1_VALIDATE_KSV_LIST_FAILURE,
+       MOD_HDCP_STATUS_HDCP1_ENABLE_ENCRYPTION,
+       MOD_HDCP_STATUS_HDCP1_ENABLE_STREAM_ENCRYPTION_FAILURE,
+       MOD_HDCP_STATUS_HDCP1_MAX_CASCADE_EXCEEDED_FAILURE,
+       MOD_HDCP_STATUS_HDCP1_MAX_DEVS_EXCEEDED_FAILURE,
+       MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE,
+       MOD_HDCP_STATUS_HDCP1_LINK_INTEGRITY_FAILURE,
+       MOD_HDCP_STATUS_HDCP1_REAUTH_REQUEST_ISSUED,
+       MOD_HDCP_STATUS_HDCP1_LINK_MAINTENANCE_FAILURE,
+       MOD_HDCP_STATUS_HDCP1_INVALID_BKSV,
+       MOD_HDCP_STATUS_DDC_FAILURE, /* TODO: specific errors */
+       MOD_HDCP_STATUS_INVALID_OPERATION,
+       MOD_HDCP_STATUS_HDCP2_NOT_CAPABLE,
+       MOD_HDCP_STATUS_HDCP2_CREATE_SESSION_FAILURE,
+       MOD_HDCP_STATUS_HDCP2_DESTROY_SESSION_FAILURE,
+       MOD_HDCP_STATUS_HDCP2_PREP_AKE_INIT_FAILURE,
+       MOD_HDCP_STATUS_HDCP2_AKE_CERT_PENDING,
+       MOD_HDCP_STATUS_HDCP2_H_PRIME_PENDING,
+       MOD_HDCP_STATUS_HDCP2_PAIRING_INFO_PENDING,
+       MOD_HDCP_STATUS_HDCP2_VALIDATE_AKE_CERT_FAILURE,
+       MOD_HDCP_STATUS_HDCP2_VALIDATE_H_PRIME_FAILURE,
+       MOD_HDCP_STATUS_HDCP2_VALIDATE_PAIRING_INFO_FAILURE,
+       MOD_HDCP_STATUS_HDCP2_PREP_LC_INIT_FAILURE,
+       MOD_HDCP_STATUS_HDCP2_L_PRIME_PENDING,
+       MOD_HDCP_STATUS_HDCP2_VALIDATE_L_PRIME_FAILURE,
+       MOD_HDCP_STATUS_HDCP2_PREP_EKS_FAILURE,
+       MOD_HDCP_STATUS_HDCP2_ENABLE_ENCRYPTION_FAILURE,
+       MOD_HDCP_STATUS_HDCP2_RX_ID_LIST_NOT_READY,
+       MOD_HDCP_STATUS_HDCP2_VALIDATE_RX_ID_LIST_FAILURE,
+       MOD_HDCP_STATUS_HDCP2_ENABLE_STREAM_ENCRYPTION,
+       MOD_HDCP_STATUS_HDCP2_STREAM_READY_PENDING,
+       MOD_HDCP_STATUS_HDCP2_VALIDATE_STREAM_READY_FAILURE,
+       MOD_HDCP_STATUS_HDCP2_PREPARE_STREAM_MANAGEMENT_FAILURE,
+       MOD_HDCP_STATUS_HDCP2_REAUTH_REQUEST,
+       MOD_HDCP_STATUS_HDCP2_REAUTH_LINK_INTEGRITY_FAILURE,
+       MOD_HDCP_STATUS_HDCP2_DEVICE_COUNT_MISMATCH_FAILURE,
+};
+
+struct mod_hdcp_displayport {
+       uint8_t rev;
+       uint8_t assr_supported;
+};
+
+struct mod_hdcp_hdmi {
+       uint8_t reserved;
+};
+enum mod_hdcp_operation_mode {
+       MOD_HDCP_MODE_OFF,
+       MOD_HDCP_MODE_DEFAULT,
+       MOD_HDCP_MODE_DP,
+       MOD_HDCP_MODE_DP_MST
+};
+
+enum mod_hdcp_display_state {
+       MOD_HDCP_DISPLAY_INACTIVE = 0,
+       MOD_HDCP_DISPLAY_ACTIVE,
+       MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED,
+       MOD_HDCP_DISPLAY_ENCRYPTION_ENABLED
+};
+
+struct mod_hdcp_ddc {
+       void *handle;
+       struct {
+               bool (*read_i2c)(void *handle,
+                               uint32_t address,
+                               uint8_t offset,
+                               uint8_t *data,
+                               uint32_t size);
+               bool (*write_i2c)(void *handle,
+                               uint32_t address,
+                               const uint8_t *data,
+                               uint32_t size);
+               bool (*read_dpcd)(void *handle,
+                               uint32_t address,
+                               uint8_t *data,
+                               uint32_t size);
+               bool (*write_dpcd)(void *handle,
+                               uint32_t address,
+                               const uint8_t *data,
+                               uint32_t size);
+       } funcs;
+};
+
+struct mod_hdcp_psp {
+       void *handle;
+       void *funcs;
+};
+
+struct mod_hdcp_display_adjustment {
+       uint8_t disable                 : 1;
+       uint8_t reserved                : 7;
+};
+
+struct mod_hdcp_link_adjustment_hdcp1 {
+       uint8_t disable                 : 1;
+       uint8_t postpone_encryption     : 1;
+       uint8_t reserved                : 6;
+};
+
+struct mod_hdcp_link_adjustment_hdcp2 {
+       uint8_t disable                 : 1;
+       uint8_t disable_type1           : 1;
+       uint8_t force_no_stored_km      : 1;
+       uint8_t increase_h_prime_timeout: 1;
+       uint8_t reserved                : 4;
+};
+
+struct mod_hdcp_link_adjustment {
+       uint8_t auth_delay;
+       struct mod_hdcp_link_adjustment_hdcp1 hdcp1;
+       struct mod_hdcp_link_adjustment_hdcp2 hdcp2;
+};
+
+struct mod_hdcp_error {
+       enum mod_hdcp_status status;
+       uint8_t state_id;
+};
+
+struct mod_hdcp_trace {
+       struct mod_hdcp_error errors[MAX_NUM_OF_ERROR_TRACE];
+       uint8_t error_count;
+};
+
+enum mod_hdcp_encryption_status {
+       MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF = 0,
+       MOD_HDCP_ENCRYPTION_STATUS_HDCP1_ON,
+       MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE0_ON,
+       MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE1_ON
+};
+
+/* per link events dm has to notify to hdcp module */
+enum mod_hdcp_event {
+       MOD_HDCP_EVENT_CALLBACK = 0,
+       MOD_HDCP_EVENT_WATCHDOG_TIMEOUT,
+       MOD_HDCP_EVENT_CPIRQ
+};
+
+/* output flags from module requesting timer operations */
+struct mod_hdcp_output {
+       uint8_t callback_needed;
+       uint8_t callback_stop;
+       uint8_t watchdog_timer_needed;
+       uint8_t watchdog_timer_stop;
+       uint16_t callback_delay;
+       uint16_t watchdog_timer_delay;
+};
+
+/* used to represent per display info */
+struct mod_hdcp_display {
+       enum mod_hdcp_display_state state;
+       uint8_t index;
+       uint8_t controller;
+       uint8_t dig_fe;
+       union {
+               uint8_t vc_id;
+       };
+       struct mod_hdcp_display_adjustment adjust;
+};
+
+/* used to represent per link info */
+/* in case a link has multiple displays, they share the same link info */
+struct mod_hdcp_link {
+       enum mod_hdcp_operation_mode mode;
+       uint8_t dig_be;
+       uint8_t ddc_line;
+       union {
+               struct mod_hdcp_displayport dp;
+               struct mod_hdcp_hdmi hdmi;
+       };
+       struct mod_hdcp_link_adjustment adjust;
+};
+
+/* a query structure for a display's hdcp information */
+struct mod_hdcp_display_query {
+       const struct mod_hdcp_display *display;
+       const struct mod_hdcp_link *link;
+       const struct mod_hdcp_trace *trace;
+       enum mod_hdcp_encryption_status encryption_status;
+};
+
+/* contains values per on external display configuration change */
+struct mod_hdcp_config {
+       struct mod_hdcp_psp psp;
+       struct mod_hdcp_ddc ddc;
+       uint8_t index;
+};
+
+struct mod_hdcp;
+
+/* dm allocates memory of mod_hdcp per dc_link on dm init based on memory size*/
+size_t mod_hdcp_get_memory_size(void);
+
+/* called per link on link creation */
+enum mod_hdcp_status mod_hdcp_setup(struct mod_hdcp *hdcp,
+               struct mod_hdcp_config *config);
+
+/* called per link on link destroy */
+enum mod_hdcp_status mod_hdcp_teardown(struct mod_hdcp *hdcp);
+
+/* called per display on cp_desired set to true */
+enum mod_hdcp_status mod_hdcp_add_display(struct mod_hdcp *hdcp,
+               struct mod_hdcp_link *link, struct mod_hdcp_display *display,
+               struct mod_hdcp_output *output);
+
+/* called per display on cp_desired set to false */
+enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp,
+               uint8_t index, struct mod_hdcp_output *output);
+
+/* called to query hdcp information on a specific index */
+enum mod_hdcp_status mod_hdcp_query_display(struct mod_hdcp *hdcp,
+               uint8_t index, struct mod_hdcp_display_query *query);
+
+/* called per link on connectivity change */
+enum mod_hdcp_status mod_hdcp_reset_connection(struct mod_hdcp *hdcp,
+               struct mod_hdcp_output *output);
+
+/* called per link on events (i.e. callback, watchdog, CP_IRQ) */
+enum mod_hdcp_status mod_hdcp_process_event(struct mod_hdcp *hdcp,
+               enum mod_hdcp_event event, struct mod_hdcp_output *output);
+
+/* called to convert enum mod_hdcp_status to c string */
+char *mod_hdcp_status_to_str(int32_t status);
+
+/* called to convert state id to c string */
+char *mod_hdcp_state_id_to_str(int32_t id);
+
+/* called to convert signal type to operation mode */
+enum mod_hdcp_operation_mode mod_hdcp_signal_type_to_operation_mode(
+               enum signal_type signal);
+#endif /* MOD_HDCP_H_ */
index d930bdecb1174f1e8b0445c0e544ef04221e9bdf..ca8ce3c55337bf968c0d4d76c58ea51f04e76ad5 100644 (file)
@@ -35,4 +35,7 @@ struct mod_vrr_params;
 void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
                struct dc_info_packet *info_packet);
 
+void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream,
+               struct dc_info_packet *info_packet, int ALLMEnabled, int ALLMValue);
+
 #endif
index d885d642ed7fc9fccbb9cec310099d4c99377a35..db6b08f6d0931876ea504bb2d96af3b90367889b 100644 (file)
@@ -31,6 +31,7 @@
 #include "dc.h"
 
 #define HDMI_INFOFRAME_TYPE_VENDOR 0x81
+#define HF_VSIF_VERSION 1
 
 // VTEM Byte Offset
 #define VTEM_PB0               0
@@ -395,3 +396,100 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
 
 }
 
+/**
+ *****************************************************************************
+ *  Function: mod_build_hf_vsif_infopacket
+ *
+ *  @brief
+ *     Prepare HDMI Vendor Specific info frame.
+ *     Follows HDMI Spec to build up Vendor Specific info frame
+ *
+ *  @param [in] stream: contains data we may need to construct VSIF (i.e. timing_3d_format, etc.)
+ *  @param [out] info_packet:   output structure where to store VSIF
+ *****************************************************************************
+ */
+void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream,
+               struct dc_info_packet *info_packet, int ALLMEnabled, int ALLMValue)
+{
+               unsigned int length = 5;
+               bool hdmi_vic_mode = false;
+               uint8_t checksum = 0;
+               uint32_t i = 0;
+               enum dc_timing_3d_format format;
+               bool bALLM = (bool)ALLMEnabled;
+               bool bALLMVal = (bool)ALLMValue;
+
+               info_packet->valid = false;
+               format = stream->timing.timing_3d_format;
+               if (stream->view_format == VIEW_3D_FORMAT_NONE)
+                       format = TIMING_3D_FORMAT_NONE;
+
+               if (stream->timing.hdmi_vic != 0
+                               && stream->timing.h_total >= 3840
+                               && stream->timing.v_total >= 2160
+                               && format == TIMING_3D_FORMAT_NONE)
+                       hdmi_vic_mode = true;
+
+               if ((format == TIMING_3D_FORMAT_NONE) && !hdmi_vic_mode && !bALLM)
+                       return;
+
+               info_packet->sb[1] = 0x03;
+               info_packet->sb[2] = 0x0C;
+               info_packet->sb[3] = 0x00;
+
+               if (bALLM) {
+                       info_packet->sb[1] = 0xD8;
+                       info_packet->sb[2] = 0x5D;
+                       info_packet->sb[3] = 0xC4;
+                       info_packet->sb[4] = HF_VSIF_VERSION;
+               }
+
+               if (format != TIMING_3D_FORMAT_NONE)
+                       info_packet->sb[4] = (2 << 5);
+
+               else if (hdmi_vic_mode)
+                       info_packet->sb[4] = (1 << 5);
+
+               switch (format) {
+               case TIMING_3D_FORMAT_HW_FRAME_PACKING:
+               case TIMING_3D_FORMAT_SW_FRAME_PACKING:
+                       info_packet->sb[5] = (0x0 << 4);
+                       break;
+
+               case TIMING_3D_FORMAT_SIDE_BY_SIDE:
+               case TIMING_3D_FORMAT_SBS_SW_PACKED:
+                       info_packet->sb[5] = (0x8 << 4);
+                       length = 6;
+                       break;
+
+               case TIMING_3D_FORMAT_TOP_AND_BOTTOM:
+               case TIMING_3D_FORMAT_TB_SW_PACKED:
+                       info_packet->sb[5] = (0x6 << 4);
+                       break;
+
+               default:
+                       break;
+               }
+
+               if (hdmi_vic_mode)
+                       info_packet->sb[5] = stream->timing.hdmi_vic;
+
+               info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR;
+               info_packet->hb1 = 0x01;
+               info_packet->hb2 = (uint8_t) (length);
+
+               if (bALLM)
+                       info_packet->sb[5] = (info_packet->sb[5] & ~0x02) | (bALLMVal << 1);
+
+               checksum += info_packet->hb0;
+               checksum += info_packet->hb1;
+               checksum += info_packet->hb2;
+
+               for (i = 1; i <= length; i++)
+                       checksum += info_packet->sb[i];
+
+               info_packet->sb[0] = (uint8_t) (0x100 - checksum);
+
+               info_packet->valid = true;
+}
+
index 05e2be856037ead17f7ede33a4369917cad2df00..4e2f615c3566c2ba76ecea1698336b24dc712bb3 100644 (file)
@@ -80,18 +80,18 @@ struct abm_parameters {
 
 static const struct abm_parameters abm_settings_config0[abm_defines_max_level] = {
 //  min_red  max_red  bright_pos  dark_pos  brightness_gain  contrast  deviation  min_knee  max_knee
-       {0xff,   0xbf,    0x20,       0x00,     0xff,            0x99,     0xb3,      0x40,     0xE0},
-       {0xff,   0x85,    0x20,       0x00,     0xff,            0x90,     0xa8,      0x40,     0xE0},
-       {0xff,   0x40,    0x20,       0x00,     0xff,            0x90,     0x68,      0x40,     0xE0},
-       {0x82,   0x4d,    0x20,       0x00,     0x00,            0x90,     0xb3,      0x70,     0x70},
+       {0xff,   0xbf,    0x20,       0x00,     0xff,            0x99,     0xb3,      0x40,     0xe0},
+       {0xde,   0x85,    0x20,       0x00,     0xff,            0x90,     0xa8,      0x40,     0xdf},
+       {0xb0,   0x50,    0x20,       0x00,     0xc0,            0x88,     0x78,      0x70,     0xa0},
+       {0x82,   0x40,    0x20,       0x00,     0x00,            0xff,     0xb3,      0x70,     0x70},
 };
 
 static const struct abm_parameters abm_settings_config1[abm_defines_max_level] = {
 //  min_red  max_red  bright_pos  dark_pos  brightness_gain  contrast  deviation  min_knee  max_knee
-       {0xf0,   0xd9,    0x20,       0x00,     0x00,            0xa8,     0xb3,      0x70,     0x70},
-       {0xcd,   0xa5,    0x20,       0x00,     0x00,            0xa8,     0xb3,      0x70,     0x70},
-       {0x99,   0x65,    0x20,       0x00,     0x00,            0xa8,     0xb3,      0x70,     0x70},
-       {0x82,   0x4d,    0x20,       0x00,     0x00,            0xa8,     0xb3,      0x70,     0x70},
+       {0xf0,   0xd9,    0x20,       0x00,     0x00,            0xff,     0xb3,      0x70,     0x70},
+       {0xcd,   0xa5,    0x20,       0x00,     0x00,            0xff,     0xb3,      0x70,     0x70},
+       {0x99,   0x65,    0x20,       0x00,     0x00,            0xff,     0xb3,      0x70,     0x70},
+       {0x82,   0x4d,    0x20,       0x00,     0x00,            0xff,     0xb3,      0x70,     0x70},
 };
 
 static const struct abm_parameters * const abm_settings[] = {
@@ -115,7 +115,7 @@ static const struct abm_parameters * const abm_settings[] = {
 /* NOTE: iRAM is 256B in size */
 struct iram_table_v_2 {
        /* flags                      */
-       uint16_t flags;                                                 /* 0x00 U16  */
+       uint16_t min_abm_backlight;                                     /* 0x00 U16  */
 
        /* parameters for ABM2.0 algorithm */
        uint8_t min_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];          /* 0x02 U0.8 */
@@ -140,10 +140,10 @@ struct iram_table_v_2 {
 
        /* 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_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       */
@@ -164,42 +164,43 @@ struct iram_table_v_2_2 {
        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 hybrid_factor[NUM_AGGR_LEVEL];                                          /* 0x52 U0.8 */
-       uint8_t contrast_factor[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 min_knee[NUM_AGGR_LEVEL];                                                       /* 0x63 U0.8 */
-       uint8_t max_knee[NUM_AGGR_LEVEL];                                                       /* 0x67 U0.8 */
-       uint8_t pad[21];                                                                                        /* 0x6b U0.8 */
+       uint8_t hybrid_factor[NUM_AGGR_LEVEL];                          /* 0x52 U0.8 */
+       uint8_t contrast_factor[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 min_knee[NUM_AGGR_LEVEL];                               /* 0x63 U0.8 */
+       uint8_t max_knee[NUM_AGGR_LEVEL];                               /* 0x67 U0.8 */
+       uint16_t min_abm_backlight;                                     /* 0x6b U16  */
+       uint8_t pad[19];                                                /* 0x6d 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 */
+       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 */
+       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 */
+       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       */
-
-       uint8_t dummy1;                                                                                         /* 0xf7       */
-       uint8_t dummy2;                                                                                         /* 0xf8       */
-       uint8_t dummy3;                                                                                         /* 0xf9       */
-       uint8_t dummy4;                                                                                         /* 0xfa       */
-       uint8_t dummy5;                                                                                         /* 0xfb       */
-       uint8_t dummy6;                                                                                         /* 0xfc       */
-       uint8_t dummy7;                                                                                         /* 0xfd       */
-       uint8_t dummy8;                                                                                         /* 0xfe       */
-       uint8_t dummy9;                                                                                         /* 0xff       */
+       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       */
+
+       uint8_t dummy1;                                                 /* 0xf7       */
+       uint8_t dummy2;                                                 /* 0xf8       */
+       uint8_t dummy3;                                                 /* 0xf9       */
+       uint8_t dummy4;                                                 /* 0xfa       */
+       uint8_t dummy5;                                                 /* 0xfb       */
+       uint8_t dummy6;                                                 /* 0xfc       */
+       uint8_t dummy7;                                                 /* 0xfd       */
+       uint8_t dummy8;                                                 /* 0xfe       */
+       uint8_t dummy9;                                                 /* 0xff       */
 };
 #pragma pack(pop)
 
@@ -271,7 +272,8 @@ void fill_iram_v_2(struct iram_table_v_2 *ram_table, struct dmcu_iram_parameters
 {
        unsigned int set = params.set;
 
-       ram_table->flags = 0x0;
+       ram_table->min_abm_backlight =
+                       cpu_to_be16(params.min_abm_backlight);
        ram_table->deviation_gain = 0xb3;
 
        ram_table->blRampReduction =
@@ -445,6 +447,9 @@ void fill_iram_v_2_2(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parame
 
        ram_table->flags = 0x0;
 
+       ram_table->min_abm_backlight =
+                       cpu_to_be16(params.min_abm_backlight);
+
        ram_table->deviation_gain[0] = 0xb3;
        ram_table->deviation_gain[1] = 0xa8;
        ram_table->deviation_gain[2] = 0x98;
@@ -588,6 +593,10 @@ void fill_iram_v_2_3(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parame
        unsigned int set = params.set;
 
        ram_table->flags = 0x0;
+
+       ram_table->min_abm_backlight =
+                       cpu_to_be16(params.min_abm_backlight);
+
        for (i = 0; i < NUM_AGGR_LEVEL; i++) {
                ram_table->hybrid_factor[i] = abm_settings[set][i].brightness_gain;
                ram_table->contrast_factor[i] = abm_settings[set][i].contrast_factor;
index da5df00fedcedafb03a4f5a642524efe019b4be3..e541570263308af5c504748db2f401e7106c6919 100644 (file)
@@ -38,6 +38,7 @@ struct dmcu_iram_parameters {
        unsigned int backlight_lut_array_size;
        unsigned int backlight_ramping_reduction;
        unsigned int backlight_ramping_start;
+       unsigned int min_abm_backlight;
        unsigned int set;
 };
 
index a761ba07f937333f7207de92726ec6e25a1a7172..fce965984e760cf532abe70cf34c93a906386d39 100644 (file)
@@ -27,6 +27,7 @@
 #define mmMM_INDEX                                                              0x0
 #define mmMM_INDEX_HI                                                           0x6
 #define mmMM_DATA                                                               0x1
+#define mmCC_BIF_BX_FUSESTRAP0                                                 0x14D7
 #define mmBUS_CNTL                                                              0x1508
 #define mmCONFIG_CNTL                                                           0x1509
 #define mmCONFIG_MEMSIZE                                                        0x150a
index 8fbfd0261d276e667dad30291e986d6f917bc26f..39cc4880beb47e7c5349b457088c375f1e5fa4b9 100644 (file)
@@ -32,6 +32,8 @@
 #define MM_INDEX_HI__MM_OFFSET_HI__SHIFT 0x0
 #define MM_DATA__MM_DATA_MASK 0xffffffff
 #define MM_DATA__MM_DATA__SHIFT 0x0
+#define CC_BIF_BX_FUSESTRAP0__STRAP_BIF_PX_CAPABLE_MASK    0x2
+#define CC_BIF_BX_FUSESTRAP0__STRAP_BIF_PX_CAPABLE__SHIFT  0x1
 #define BUS_CNTL__BIOS_ROM_WRT_EN_MASK 0x1
 #define BUS_CNTL__BIOS_ROM_WRT_EN__SHIFT 0x0
 #define BUS_CNTL__BIOS_ROM_DIS_MASK 0x2
index 809759f7bb8189ffbc68095a1583b947c42e6e2c..8d05d6ca1c8d0c9408676ebe3724a52733cc33bf 100644 (file)
@@ -27,6 +27,7 @@
 #define mmMM_INDEX                                                              0x0
 #define mmMM_INDEX_HI                                                           0x6
 #define mmMM_DATA                                                               0x1
+#define mmCC_BIF_BX_FUSESTRAP0                                                 0x14D7
 #define mmCC_BIF_BX_STRAP2                                                     0x152A
 #define mmBIF_MM_INDACCESS_CNTL                                                 0x1500
 #define mmBIF_DOORBELL_APER_EN                                                  0x1501
index adc71b01f793ba583f33d063f702cdf482eecfab..73435687d049a49957dcb30891fa399101c238a4 100644 (file)
@@ -32,6 +32,8 @@
 #define MM_INDEX_HI__MM_OFFSET_HI__SHIFT 0x0
 #define MM_DATA__MM_DATA_MASK 0xffffffff
 #define MM_DATA__MM_DATA__SHIFT 0x0
+#define CC_BIF_BX_FUSESTRAP0__STRAP_BIF_PX_CAPABLE_MASK    0x2
+#define CC_BIF_BX_FUSESTRAP0__STRAP_BIF_PX_CAPABLE__SHIFT  0x1
 #define BIF_MM_INDACCESS_CNTL__MM_INDACCESS_DIS_MASK 0x2
 #define BIF_MM_INDACCESS_CNTL__MM_INDACCESS_DIS__SHIFT 0x1
 #define BIF_DOORBELL_APER_EN__BIF_DOORBELL_APER_EN_MASK 0x1
index be4249adb3562add2e33ff1754dca666862c1b84..eddf83ec1c39605d1000e1f7c2e3bf01265a9a45 100644 (file)
 #define mmDP0_DP_STEER_FIFO_BASE_IDX                                                                   2
 #define mmDP0_DP_MSA_MISC                                                                              0x210e
 #define mmDP0_DP_MSA_MISC_BASE_IDX                                                                     2
+#define mmDP0_DP_DPHY_INTERNAL_CTRL                                                                    0x210f
+#define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX                                                           2
 #define mmDP0_DP_VID_TIMING                                                                            0x2110
 #define mmDP0_DP_VID_TIMING_BASE_IDX                                                                   2
 #define mmDP0_DP_VID_N                                                                                 0x2111
 #define mmDP1_DP_STEER_FIFO_BASE_IDX                                                                   2
 #define mmDP1_DP_MSA_MISC                                                                              0x220e
 #define mmDP1_DP_MSA_MISC_BASE_IDX                                                                     2
+#define mmDP1_DP_DPHY_INTERNAL_CTRL                                                                    0x220f
+#define mmDP1_DP_DPHY_INTERNAL_CTRL_BASE_IDX                                                           2
 #define mmDP1_DP_VID_TIMING                                                                            0x2210
 #define mmDP1_DP_VID_TIMING_BASE_IDX                                                                   2
 #define mmDP1_DP_VID_N                                                                                 0x2211
 #define mmDP2_DP_STEER_FIFO_BASE_IDX                                                                   2
 #define mmDP2_DP_MSA_MISC                                                                              0x230e
 #define mmDP2_DP_MSA_MISC_BASE_IDX                                                                     2
+#define mmDP2_DP_DPHY_INTERNAL_CTRL                                                                    0x230f
+#define mmDP2_DP_DPHY_INTERNAL_CTRL_BASE_IDX                                                           2
 #define mmDP2_DP_VID_TIMING                                                                            0x2310
 #define mmDP2_DP_VID_TIMING_BASE_IDX                                                                   2
 #define mmDP2_DP_VID_N                                                                                 0x2311
 #define mmDP3_DP_STEER_FIFO_BASE_IDX                                                                   2
 #define mmDP3_DP_MSA_MISC                                                                              0x240e
 #define mmDP3_DP_MSA_MISC_BASE_IDX                                                                     2
+#define mmDP3_DP_DPHY_INTERNAL_CTRL                                                                    0x240f
+#define mmDP3_DP_DPHY_INTERNAL_CTRL_BASE_IDX                                                           2
 #define mmDP3_DP_VID_TIMING                                                                            0x2410
 #define mmDP3_DP_VID_TIMING_BASE_IDX                                                                   2
 #define mmDP3_DP_VID_N                                                                                 0x2411
 #define mmDP4_DP_STEER_FIFO_BASE_IDX                                                                   2
 #define mmDP4_DP_MSA_MISC                                                                              0x250e
 #define mmDP4_DP_MSA_MISC_BASE_IDX                                                                     2
+#define mmDP4_DP_DPHY_INTERNAL_CTRL                                                                    0x250f
+#define mmDP4_DP_DPHY_INTERNAL_CTRL_BASE_IDX                                                           2
 #define mmDP4_DP_VID_TIMING                                                                            0x2510
 #define mmDP4_DP_VID_TIMING_BASE_IDX                                                                   2
 #define mmDP4_DP_VID_N                                                                                 0x2511
index ca16d9125fbcc249e5ad85249503a64f4feada3b..2bfaaa8157d083625b2ce1221cc9bd09ef02c555 100644 (file)
 #define mmATC_L2_MEM_POWER_LS_BASE_IDX                                                                 0
 #define mmATC_L2_CGTT_CLK_CTRL                                                                         0x080c
 #define mmATC_L2_CGTT_CLK_CTRL_BASE_IDX                                                                0
-
+#define mmATC_L2_CACHE_4K_EDC_INDEX                                                                    0x080e
+#define mmATC_L2_CACHE_4K_EDC_INDEX_BASE_IDX                                                           0
+#define mmATC_L2_CACHE_2M_EDC_INDEX                                                                    0x080f
+#define mmATC_L2_CACHE_2M_EDC_INDEX_BASE_IDX                                                           0
+#define mmATC_L2_CACHE_4K_EDC_CNT                                                                      0x0810
+#define mmATC_L2_CACHE_4K_EDC_CNT_BASE_IDX                                                             0
+#define mmATC_L2_CACHE_2M_EDC_CNT                                                                      0x0811
+#define mmATC_L2_CACHE_2M_EDC_CNT_BASE_IDX                                                             0
 
 // addressBlock: gc_utcl2_vml2pfdec
 // base address: 0xa100
 #define mmVM_L2_CACHE_PARITY_CNTL_BASE_IDX                                                             0
 #define mmVM_L2_CGTT_CLK_CTRL                                                                          0x085e
 #define mmVM_L2_CGTT_CLK_CTRL_BASE_IDX                                                                 0
-
+#define mmVM_L2_MEM_ECC_INDEX                                                                          0x0860
+#define mmVM_L2_MEM_ECC_INDEX_BASE_IDX                                                                 0
+#define mmVM_L2_WALKER_MEM_ECC_INDEX                                                                   0x0861
+#define mmVM_L2_WALKER_MEM_ECC_INDEX_BASE_IDX                                                          0
+#define mmVM_L2_MEM_ECC_CNT                                                                            0x0862
+#define mmVM_L2_MEM_ECC_CNT_BASE_IDX                                                                   0
+#define mmVM_L2_WALKER_MEM_ECC_CNT                                                                     0x0863
+#define mmVM_L2_WALKER_MEM_ECC_CNT_BASE_IDX                                                            0
 
 // addressBlock: gc_utcl2_vml2vcdec
 // base address: 0xa200
index 064c4bb1dc6231a31fce66cc40185004c4418386..d4c613a8535278b7275be83cc4fee332ae77292d 100644 (file)
 #define ATC_L2_CGTT_CLK_CTRL__SOFT_STALL_OVERRIDE_MASK                                                        0x00FF0000L
 #define ATC_L2_CGTT_CLK_CTRL__SOFT_OVERRIDE_MASK                                                              0xFF000000L
 
-
 // addressBlock: gc_utcl2_vml2pfdec
 //VM_L2_CNTL
 #define VM_L2_CNTL__ENABLE_L2_CACHE__SHIFT                                                                    0x0
 #define VM_L2_CGTT_CLK_CTRL__MGLS_OVERRIDE_MASK                                                               0x00008000L
 #define VM_L2_CGTT_CLK_CTRL__SOFT_STALL_OVERRIDE_MASK                                                         0x00FF0000L
 #define VM_L2_CGTT_CLK_CTRL__SOFT_OVERRIDE_MASK                                                               0xFF000000L
-
+//VM_L2_MEM_ECC_INDEX
+#define VM_L2_MEM_ECC_INDEX__INDEX__SHIFT                                                                     0x0
+#define VM_L2_MEM_ECC_INDEX__INDEX_MASK                                                                       0x000000FFL
+//VM_L2_WALKER_MEM_ECC_INDEX
+#define VM_L2_WALKER_MEM_ECC_INDEX__INDEX__SHIFT                                                              0x0
+#define VM_L2_WALKER_MEM_ECC_INDEX__INDEX_MASK                                                                0x000000FFL
+//VM_L2_MEM_ECC_CNT
+#define VM_L2_MEM_ECC_CNT__SEC_COUNT__SHIFT                                                                   0xc
+#define VM_L2_MEM_ECC_CNT__DED_COUNT__SHIFT                                                                   0xe
+#define VM_L2_MEM_ECC_CNT__SEC_COUNT_MASK                                                                     0x00003000L
+#define VM_L2_MEM_ECC_CNT__DED_COUNT_MASK                                                                     0x0000C000L
+//VM_L2_WALKER_MEM_ECC_CNT
+#define VM_L2_WALKER_MEM_ECC_CNT__SEC_COUNT__SHIFT                                                            0xc
+#define VM_L2_WALKER_MEM_ECC_CNT__DED_COUNT__SHIFT                                                            0xe
+#define VM_L2_WALKER_MEM_ECC_CNT__SEC_COUNT_MASK                                                              0x00003000L
+#define VM_L2_WALKER_MEM_ECC_CNT__DED_COUNT_MASK                                                              0x0000C000L
 
 // addressBlock: gc_utcl2_vml2vcdec
 //VM_CONTEXT0_CNTL
index 4bcacf5298528c5139ba789ff646d40c3959fe2c..991128bb947611aa786064b66cc1013496ccd454 100644 (file)
@@ -22,6 +22,9 @@
 #ifndef _nbio_7_4_0_SMN_HEADER
 #define _nbio_7_4_0_SMN_HEADER
 
+// addressBlock: nbio_nbif0_bif_ras_bif_ras_regblk
+// base address: 0x10100000
+#define smnBIFL_RAS_CENTRAL_STATUS                     0x10139040
 
 #define smnNBIF_MGCG_CTRL_LCLK                         0x1013a21c
 #define smnCPM_CONTROL                                 0x11180460
 #define smnPCIE_RX_NUM_NAK                             0x11180038
 #define smnPCIE_RX_NUM_NAK_GENERATED                   0x1118003c
 
+// addressBlock: nbio_iohub_nb_misc_misc_cfgdec
+// base address: 0x13a10000
+#define smnIOHC_INTERRUPT_EOI                          0x13a10120
+
+// addressBlock: nbio_iohub_nb_rascfg_ras_cfgdec
+// base address: 0x13a20000
+#define smnRAS_GLOBAL_STATUS_LO                                0x13a20020
+#define smnRAS_GLOBAL_STATUS_HI                                0x13a20024
+
 #endif // _nbio_7_4_0_SMN_HEADER
index 994e796a28d78fa5a20ccc88c120ce651c867cae..ce5830ebe095ab6635971041fcc16e8ca4fbe4ba 100644 (file)
 #define mmBIF_DOORBELL_INT_CNTL_BASE_IDX                                                               2
 #define mmBIF_FB_EN                                                                                    0x00ff
 #define mmBIF_FB_EN_BASE_IDX                                                                           2
-#define mmBIF_BUSY_DELAY_CNTR                                                                          0x0100
-#define mmBIF_BUSY_DELAY_CNTR_BASE_IDX                                                                 2
+#define mmBIF_INTR_CNTL                                                                                0x0100
+#define mmBIF_INTR_CNTL_BASE_IDX                                                                       2
 #define mmBIF_MST_TRANS_PENDING_VF                                                                     0x0109
 #define mmBIF_MST_TRANS_PENDING_VF_BASE_IDX                                                            2
 #define mmBIF_SLV_TRANS_PENDING_VF                                                                     0x010a
index d467b939c97133789a357a9841e5560ec9cd7e48..07f04b2b5bdd3d53964a894b5775dc56b3ab8d3b 100644 (file)
 #define BIF_FB_EN__FB_WRITE_EN__SHIFT                                                                         0x1
 #define BIF_FB_EN__FB_READ_EN_MASK                                                                            0x00000001L
 #define BIF_FB_EN__FB_WRITE_EN_MASK                                                                           0x00000002L
-//BIF_BUSY_DELAY_CNTR
-#define BIF_BUSY_DELAY_CNTR__DELAY_CNT__SHIFT                                                                 0x0
-#define BIF_BUSY_DELAY_CNTR__DELAY_CNT_MASK                                                                   0x0000003FL
+//BIF_INTR_CNTL
+#define BIF_INTR_CNTL__RAS_INTR_VEC_SEL__SHIFT                                                                0x0
+#define BIF_INTR_CNTL__RAS_INTR_VEC_SEL_MASK                                                                  0x00000001L
 //BIF_MST_TRANS_PENDING_VF
 #define BIF_MST_TRANS_PENDING_VF__BIF_MST_TRANS_PENDING__SHIFT                                                0x0
 #define BIF_MST_TRANS_PENDING_VF__BIF_MST_TRANS_PENDING_MASK                                                  0x7FFFFFFFL
 #define RCC_DEV0_EPF0_VF15_GFXMSIX_PBA__MSIX_PENDING_BITS_1_MASK                                              0x00000002L
 #define RCC_DEV0_EPF0_VF15_GFXMSIX_PBA__MSIX_PENDING_BITS_2_MASK                                              0x00000004L
 
+//IOHC_INTERRUPT_EOI
+#define IOHC_INTERRUPT_EOI__SMI_EOI__SHIFT                                                                    0x0
+#define IOHC_INTERRUPT_EOI__SCI_EOI__SHIFT                                                                    0x1
+#define IOHC_INTERRUPT_EOI__NMI_EOI__SHIFT                                                                    0x2
+#define IOHC_INTERRUPT_EOI__SMI_EOI_MASK                                                                      0x00000001L
+#define IOHC_INTERRUPT_EOI__SCI_EOI_MASK                                                                      0x00000002L
+#define IOHC_INTERRUPT_EOI__NMI_EOI_MASK                                                                      0x00000004L
+
+//RAS_GLOBAL_STATUS_LO
+#define RAS_GLOBAL_STATUS_LO__ParityErrCorr__SHIFT                                                            0x0
+#define RAS_GLOBAL_STATUS_LO__ParityErrNonFatal__SHIFT                                                        0x1
+#define RAS_GLOBAL_STATUS_LO__ParityErrFatal__SHIFT                                                           0x2
+#define RAS_GLOBAL_STATUS_LO__ParityErrSerr__SHIFT                                                            0x3
+#define RAS_GLOBAL_STATUS_LO__HPLGWA_NMI__SHIFT                                                               0x6
+#define RAS_GLOBAL_STATUS_LO__HPLGWA_SCI__SHIFT                                                               0x7
+#define RAS_GLOBAL_STATUS_LO__HPLGWA_SMI__SHIFT                                                               0x8
+#define RAS_GLOBAL_STATUS_LO__SW_SMI__SHIFT                                                                   0x9
+#define RAS_GLOBAL_STATUS_LO__SW_SCI__SHIFT                                                                   0xa
+#define RAS_GLOBAL_STATUS_LO__SW_NMI__SHIFT                                                                   0xb
+#define RAS_GLOBAL_STATUS_LO__APML_NMI__SHIFT                                                                 0xc
+#define RAS_GLOBAL_STATUS_LO__APML_SyncFld__SHIFT                                                             0xd
+#define RAS_GLOBAL_STATUS_LO__PIN_SyncFld_NMI__SHIFT                                                          0xe
+#define RAS_GLOBAL_STATUS_LO__APML_SyncFld_Private__SHIFT                                                     0xf
+#define RAS_GLOBAL_STATUS_LO__ParityErrCorr_MASK                                                              0x00000001L
+#define RAS_GLOBAL_STATUS_LO__ParityErrNonFatal_MASK                                                          0x00000002L
+#define RAS_GLOBAL_STATUS_LO__ParityErrFatal_MASK                                                             0x00000004L
+#define RAS_GLOBAL_STATUS_LO__ParityErrSerr_MASK                                                              0x00000008L
+#define RAS_GLOBAL_STATUS_LO__HPLGWA_NMI_MASK                                                                 0x00000040L
+#define RAS_GLOBAL_STATUS_LO__HPLGWA_SCI_MASK                                                                 0x00000080L
+#define RAS_GLOBAL_STATUS_LO__HPLGWA_SMI_MASK                                                                 0x00000100L
+#define RAS_GLOBAL_STATUS_LO__SW_SMI_MASK                                                                     0x00000200L
+#define RAS_GLOBAL_STATUS_LO__SW_SCI_MASK                                                                     0x00000400L
+#define RAS_GLOBAL_STATUS_LO__SW_NMI_MASK                                                                     0x00000800L
+#define RAS_GLOBAL_STATUS_LO__APML_NMI_MASK                                                                   0x00001000L
+#define RAS_GLOBAL_STATUS_LO__APML_SyncFld_MASK                                                               0x00002000L
+#define RAS_GLOBAL_STATUS_LO__PIN_SyncFld_NMI_MASK                                                            0x00004000L
+#define RAS_GLOBAL_STATUS_LO__APML_SyncFld_Private_MASK                                                       0x00008000L
+//RAS_GLOBAL_STATUS_HI
+#define RAS_GLOBAL_STATUS_HI__PCIE0PortAErr__SHIFT                                                            0x0
+#define RAS_GLOBAL_STATUS_HI__NBIF0PortAErr__SHIFT                                                            0x1
+#define RAS_GLOBAL_STATUS_HI__PCIE0PortAErr_MASK                                                              0x00000001L
+#define RAS_GLOBAL_STATUS_HI__NBIF0PortAErr_MASK                                                              0x00000002L
+
 #endif
index dc9895a684fe160798afa32cbc7bc7c9d302d74f..096d878eb1de5fcac2030f21ae528f7481ebe86c 100644 (file)
 #define IH_STORM_CLIENT_LIST_CNTL__CLIENT30_IS_STORM_CLIENT_MASK                                              0x40000000L
 #define IH_STORM_CLIENT_LIST_CNTL__CLIENT31_IS_STORM_CLIENT_MASK                                              0x80000000L
 //IH_CLK_CTRL
+#define IH_CLK_CTRL__IH_RETRY_INT_CAM_MEM_CLK_SOFT_OVERRIDE__SHIFT                                             0x19
+#define IH_CLK_CTRL__IH_BUFFER_MEM_CLK_SOFT_OVERRIDE__SHIFT                                                              0x1a
 #define IH_CLK_CTRL__DBUS_MUX_CLK_SOFT_OVERRIDE__SHIFT                                                        0x1b
 #define IH_CLK_CTRL__OSSSYS_SHARE_CLK_SOFT_OVERRIDE__SHIFT                                                    0x1c
 #define IH_CLK_CTRL__LIMIT_SMN_CLK_SOFT_OVERRIDE__SHIFT                                                       0x1d
 #define IH_CLK_CTRL__DYN_CLK_SOFT_OVERRIDE__SHIFT                                                             0x1e
 #define IH_CLK_CTRL__REG_CLK_SOFT_OVERRIDE__SHIFT                                                             0x1f
+#define IH_CLK_CTRL__IH_RETRY_INT_CAM_MEM_CLK_SOFT_OVERRIDE_MASK                                              0x02000000L
+#define IH_CLK_CTRL__IH_BUFFER_MEM_CLK_SOFT_OVERRIDE_MASK                                                        0x04000000L
 #define IH_CLK_CTRL__DBUS_MUX_CLK_SOFT_OVERRIDE_MASK                                                          0x08000000L
 #define IH_CLK_CTRL__OSSSYS_SHARE_CLK_SOFT_OVERRIDE_MASK                                                      0x10000000L
 #define IH_CLK_CTRL__LIMIT_SMN_CLK_SOFT_OVERRIDE_MASK                                                         0x20000000L
index dbc2e723f6592b064c4db880216a5c18ccb10419..71169daa701a127c6d33d721956f431c1daf8e2b 100644 (file)
@@ -49,6 +49,7 @@
 #define ixCG_SPLL_FUNC_CNTL_5                                                   0xc0500150
 #define ixCG_SPLL_FUNC_CNTL_6                                                   0xc0500154
 #define ixCG_SPLL_FUNC_CNTL_7                                                   0xc0500158
+#define ixCG_SPLL_STATUS                                                        0xC050015C
 #define ixSPLL_CNTL_MODE                                                        0xc0500160
 #define ixCG_SPLL_SPREAD_SPECTRUM                                               0xc0500164
 #define ixCG_SPLL_SPREAD_SPECTRUM_2                                             0xc0500168
index 6af9f0217b349b161fb00b14e40a4e1f54945e9b..61a9a84e0c3a18107941131f435373dd912c3ce7 100644 (file)
 #define CG_SPLL_FUNC_CNTL_6__SPLL_LF_CNTR__SHIFT 0x19
 #define CG_SPLL_FUNC_CNTL_7__SPLL_BW_CNTRL_MASK 0xfff
 #define CG_SPLL_FUNC_CNTL_7__SPLL_BW_CNTRL__SHIFT 0x0
+#define CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK 0x2
+#define CG_SPLL_STATUS__SPLL_CHG_STATUS__SHIFT 0x1
 #define SPLL_CNTL_MODE__SPLL_SW_DIR_CONTROL_MASK 0x1
 #define SPLL_CNTL_MODE__SPLL_SW_DIR_CONTROL__SHIFT 0x0
 #define SPLL_CNTL_MODE__SPLL_LEGACY_PDIV_MASK 0x2
index bd3685166779e898d3b1729e8088c654ab8d97fc..351446754c72f65aada7d2e3262dca5092ed7207 100644 (file)
@@ -49,6 +49,7 @@
 #define ixCG_SPLL_FUNC_CNTL_5                                                   0xc0500150
 #define ixCG_SPLL_FUNC_CNTL_6                                                   0xc0500154
 #define ixCG_SPLL_FUNC_CNTL_7                                                   0xc0500158
+#define ixCG_SPLL_STATUS                                                        0xC050015C
 #define ixSPLL_CNTL_MODE                                                        0xc0500160
 #define ixCG_SPLL_SPREAD_SPECTRUM                                               0xc0500164
 #define ixCG_SPLL_SPREAD_SPECTRUM_2                                             0xc0500168
index 627906674fe81f064c99511e40fcc58a222f741d..4bfd5f8ba66c8f2b4fe5668cede7c9b90b219e9a 100644 (file)
 #define CG_SPLL_FUNC_CNTL_6__SPLL_LF_CNTR__SHIFT 0x19
 #define CG_SPLL_FUNC_CNTL_7__SPLL_BW_CNTRL_MASK 0xfff
 #define CG_SPLL_FUNC_CNTL_7__SPLL_BW_CNTRL__SHIFT 0x0
+#define CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK 0x2
+#define CG_SPLL_STATUS__SPLL_CHG_STATUS__SHIFT 0x1
 #define SPLL_CNTL_MODE__SPLL_SW_DIR_CONTROL_MASK 0x1
 #define SPLL_CNTL_MODE__SPLL_SW_DIR_CONTROL__SHIFT 0x0
 #define SPLL_CNTL_MODE__SPLL_LEGACY_PDIV_MASK 0x2
index f35aba72e64005b074d6bbe9a8f561f0e05a7361..21da61c398f58e28e632dc9191ec95b10199f46e 100644 (file)
@@ -52,6 +52,7 @@
 #define ixCG_SPLL_FUNC_CNTL_5                                                   0xc0500150
 #define ixCG_SPLL_FUNC_CNTL_6                                                   0xc0500154
 #define ixCG_SPLL_FUNC_CNTL_7                                                   0xc0500158
+#define ixCG_SPLL_STATUS                                                        0xC050015C
 #define ixSPLL_CNTL_MODE                                                        0xc0500160
 #define ixCG_SPLL_SPREAD_SPECTRUM                                               0xc0500164
 #define ixCG_SPLL_SPREAD_SPECTRUM_2                                             0xc0500168
index 481ee6560aa9c7738bcaff8bb0428bdae55fe50b..f64fe0fbcb32ad728dce5ee51c9a3d6feb85df31 100644 (file)
 #define CG_SPLL_FUNC_CNTL_6__SPLL_LF_CNTR__SHIFT 0x19
 #define CG_SPLL_FUNC_CNTL_7__SPLL_BW_CNTRL_MASK 0xfff
 #define CG_SPLL_FUNC_CNTL_7__SPLL_BW_CNTRL__SHIFT 0x0
+#define CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK 0x2
+#define CG_SPLL_STATUS__SPLL_CHG_STATUS__SHIFT 0x1
 #define SPLL_CNTL_MODE__SPLL_SW_DIR_CONTROL_MASK 0x1
 #define SPLL_CNTL_MODE__SPLL_SW_DIR_CONTROL__SHIFT 0x0
 #define SPLL_CNTL_MODE__SPLL_LEGACY_PDIV_MASK 0x2
index d3876052562bcadce44c3f9636c00935f7c63657..687d6843c258f016b08f9a58fb9451724f18b56d 100644 (file)
 #define mmCKSVII2C_IC_COMP_VERSION_BASE_IDX                                                            0
 #define mmCKSVII2C_IC_COMP_TYPE                                                                        0x006d
 #define mmCKSVII2C_IC_COMP_TYPE_BASE_IDX                                                               0
+#define mmCKSVII2C1_IC_CON                                                                             0x0080
+#define mmCKSVII2C1_IC_CON_BASE_IDX                                                                    0
+#define mmCKSVII2C1_IC_TAR                                                                             0x0081
+#define mmCKSVII2C1_IC_TAR_BASE_IDX                                                                    0
+#define mmCKSVII2C1_IC_SAR                                                                             0x0082
+#define mmCKSVII2C1_IC_SAR_BASE_IDX                                                                    0
+#define mmCKSVII2C1_IC_HS_MADDR                                                                        0x0083
+#define mmCKSVII2C1_IC_HS_MADDR_BASE_IDX                                                               0
+#define mmCKSVII2C1_IC_DATA_CMD                                                                        0x0084
+#define mmCKSVII2C1_IC_DATA_CMD_BASE_IDX                                                               0
+#define mmCKSVII2C1_IC_SS_SCL_HCNT                                                                     0x0085
+#define mmCKSVII2C1_IC_SS_SCL_HCNT_BASE_IDX                                                            0
+#define mmCKSVII2C1_IC_SS_SCL_LCNT                                                                     0x0086
+#define mmCKSVII2C1_IC_SS_SCL_LCNT_BASE_IDX                                                            0
+#define mmCKSVII2C1_IC_FS_SCL_HCNT                                                                     0x0087
+#define mmCKSVII2C1_IC_FS_SCL_HCNT_BASE_IDX                                                            0
+#define mmCKSVII2C1_IC_FS_SCL_LCNT                                                                     0x0088
+#define mmCKSVII2C1_IC_FS_SCL_LCNT_BASE_IDX                                                            0
+#define mmCKSVII2C1_IC_HS_SCL_HCNT                                                                     0x0089
+#define mmCKSVII2C1_IC_HS_SCL_HCNT_BASE_IDX                                                            0
+#define mmCKSVII2C1_IC_HS_SCL_LCNT                                                                     0x008a
+#define mmCKSVII2C1_IC_HS_SCL_LCNT_BASE_IDX                                                            0
+#define mmCKSVII2C1_IC_INTR_STAT                                                                       0x008b
+#define mmCKSVII2C1_IC_INTR_STAT_BASE_IDX                                                              0
+#define mmCKSVII2C1_IC_INTR_MASK                                                                       0x008c
+#define mmCKSVII2C1_IC_INTR_MASK_BASE_IDX                                                              0
+#define mmCKSVII2C1_IC_RAW_INTR_STAT                                                                   0x008d
+#define mmCKSVII2C1_IC_RAW_INTR_STAT_BASE_IDX                                                          0
+#define mmCKSVII2C1_IC_RX_TL                                                                           0x008e
+#define mmCKSVII2C1_IC_RX_TL_BASE_IDX                                                                  0
+#define mmCKSVII2C1_IC_TX_TL                                                                           0x008f
+#define mmCKSVII2C1_IC_TX_TL_BASE_IDX                                                                  0
+#define mmCKSVII2C1_IC_CLR_INTR                                                                        0x0090
+#define mmCKSVII2C1_IC_CLR_INTR_BASE_IDX                                                               0
+#define mmCKSVII2C1_IC_CLR_RX_UNDER                                                                    0x0091
+#define mmCKSVII2C1_IC_CLR_RX_UNDER_BASE_IDX                                                           0
+#define mmCKSVII2C1_IC_CLR_RX_OVER                                                                     0x0092
+#define mmCKSVII2C1_IC_CLR_RX_OVER_BASE_IDX                                                            0
+#define mmCKSVII2C1_IC_CLR_TX_OVER                                                                     0x0093
+#define mmCKSVII2C1_IC_CLR_TX_OVER_BASE_IDX                                                            0
+#define mmCKSVII2C1_IC_CLR_RD_REQ                                                                      0x0094
+#define mmCKSVII2C1_IC_CLR_RD_REQ_BASE_IDX                                                             0
+#define mmCKSVII2C1_IC_CLR_TX_ABRT                                                                     0x0095
+#define mmCKSVII2C1_IC_CLR_TX_ABRT_BASE_IDX                                                            0
+#define mmCKSVII2C1_IC_CLR_RX_DONE                                                                     0x0096
+#define mmCKSVII2C1_IC_CLR_RX_DONE_BASE_IDX                                                            0
+#define mmCKSVII2C1_IC_CLR_ACTIVITY                                                                    0x0097
+#define mmCKSVII2C1_IC_CLR_ACTIVITY_BASE_IDX                                                           0
+#define mmCKSVII2C1_IC_CLR_STOP_DET                                                                    0x0098
+#define mmCKSVII2C1_IC_CLR_STOP_DET_BASE_IDX                                                           0
+#define mmCKSVII2C1_IC_CLR_START_DET                                                                   0x0099
+#define mmCKSVII2C1_IC_CLR_START_DET_BASE_IDX                                                          0
+#define mmCKSVII2C1_IC_CLR_GEN_CALL                                                                    0x009a
+#define mmCKSVII2C1_IC_CLR_GEN_CALL_BASE_IDX                                                           0
+#define mmCKSVII2C1_IC_ENABLE                                                                          0x009b
+#define mmCKSVII2C1_IC_ENABLE_BASE_IDX                                                                 0
+#define mmCKSVII2C1_IC_STATUS                                                                          0x009c
+#define mmCKSVII2C1_IC_STATUS_BASE_IDX                                                                 0
+#define mmCKSVII2C1_IC_TXFLR                                                                           0x009d
+#define mmCKSVII2C1_IC_TXFLR_BASE_IDX                                                                  0
+#define mmCKSVII2C1_IC_RXFLR                                                                           0x009e
+#define mmCKSVII2C1_IC_RXFLR_BASE_IDX                                                                  0
+#define mmCKSVII2C1_IC_SDA_HOLD                                                                        0x009f
+#define mmCKSVII2C1_IC_SDA_HOLD_BASE_IDX                                                               0
+#define mmCKSVII2C1_IC_TX_ABRT_SOURCE                                                                  0x00a0
+#define mmCKSVII2C1_IC_TX_ABRT_SOURCE_BASE_IDX                                                         0
+#define mmCKSVII2C1_IC_SLV_DATA_NACK_ONLY                                                              0x00a1
+#define mmCKSVII2C1_IC_SLV_DATA_NACK_ONLY_BASE_IDX                                                     0
+#define mmCKSVII2C1_IC_DMA_CR                                                                          0x00a2
+#define mmCKSVII2C1_IC_DMA_CR_BASE_IDX                                                                 0
+#define mmCKSVII2C1_IC_DMA_TDLR                                                                        0x00a3
+#define mmCKSVII2C1_IC_DMA_TDLR_BASE_IDX                                                               0
+#define mmCKSVII2C1_IC_DMA_RDLR                                                                        0x00a4
+#define mmCKSVII2C1_IC_DMA_RDLR_BASE_IDX                                                               0
+#define mmCKSVII2C1_IC_SDA_SETUP                                                                       0x00a5
+#define mmCKSVII2C1_IC_SDA_SETUP_BASE_IDX                                                              0
+#define mmCKSVII2C1_IC_ACK_GENERAL_CALL                                                                0x00a6
+#define mmCKSVII2C1_IC_ACK_GENERAL_CALL_BASE_IDX                                                       0
+#define mmCKSVII2C1_IC_ENABLE_STATUS                                                                   0x00a7
+#define mmCKSVII2C1_IC_ENABLE_STATUS_BASE_IDX                                                          0
+#define mmCKSVII2C1_IC_FS_SPKLEN                                                                       0x00a8
+#define mmCKSVII2C1_IC_FS_SPKLEN_BASE_IDX                                                              0
+#define mmCKSVII2C1_IC_HS_SPKLEN                                                                       0x00a9
+#define mmCKSVII2C1_IC_HS_SPKLEN_BASE_IDX                                                              0
+#define mmCKSVII2C1_IC_CLR_RESTART_DET                                                                 0x00aa
+#define mmCKSVII2C1_IC_CLR_RESTART_DET_BASE_IDX                                                        0
+#define mmCKSVII2C1_IC_COMP_PARAM_1                                                                    0x00ab
+#define mmCKSVII2C1_IC_COMP_PARAM_1_BASE_IDX                                                           0
+#define mmCKSVII2C1_IC_COMP_VERSION                                                                    0x00ac
+#define mmCKSVII2C1_IC_COMP_VERSION_BASE_IDX                                                           0
+#define mmCKSVII2C1_IC_COMP_TYPE                                                                       0x00ad
+#define mmCKSVII2C1_IC_COMP_TYPE_BASE_IDX                                                              0
 #define mmSMUIO_MP_RESET_INTR                                                                          0x00c1
 #define mmSMUIO_MP_RESET_INTR_BASE_IDX                                                                 0
 #define mmSMUIO_SOC_HALT                                                                               0x00c2
index f8afa3518bf264445e033fcc143a8d3f219249ff..6905a96181275287cb08a62c66d3626f9cc4c9f0 100644 (file)
 //CKSVII2C_IC_COMP_TYPE
 #define CKSVII2C_IC_COMP_TYPE__COMP_TYPE__SHIFT                                                               0x0
 #define CKSVII2C_IC_COMP_TYPE__COMP_TYPE_MASK                                                                 0xFFFFFFFFL
+//CKSVII2C1_IC_CON
+#define CKSVII2C1_IC_CON__IC1_MASTER_MODE__SHIFT                                                              0x0
+#define CKSVII2C1_IC_CON__IC1_MAX_SPEED_MODE__SHIFT                                                           0x1
+#define CKSVII2C1_IC_CON__IC1_10BITADDR_SLAVE__SHIFT                                                          0x3
+#define CKSVII2C1_IC_CON__IC1_10BITADDR_MASTER__SHIFT                                                         0x4
+#define CKSVII2C1_IC_CON__IC1_RESTART_EN__SHIFT                                                               0x5
+#define CKSVII2C1_IC_CON__IC1_SLAVE_DISABLE__SHIFT                                                            0x6
+#define CKSVII2C1_IC_CON__STOP1_DET_IFADDRESSED__SHIFT                                                        0x7
+#define CKSVII2C1_IC_CON__TX1_EMPTY_CTRL__SHIFT                                                               0x8
+#define CKSVII2C1_IC_CON__RX1_FIFO_FULL_HLD_CTRL__SHIFT                                                       0x9
+#define CKSVII2C1_IC_CON__IC1_MASTER_MODE_MASK                                                                0x00000001L
+#define CKSVII2C1_IC_CON__IC1_MAX_SPEED_MODE_MASK                                                             0x00000006L
+#define CKSVII2C1_IC_CON__IC1_10BITADDR_SLAVE_MASK                                                            0x00000008L
+#define CKSVII2C1_IC_CON__IC1_10BITADDR_MASTER_MASK                                                           0x00000010L
+#define CKSVII2C1_IC_CON__IC1_RESTART_EN_MASK                                                                 0x00000020L
+#define CKSVII2C1_IC_CON__IC1_SLAVE_DISABLE_MASK                                                              0x00000040L
+#define CKSVII2C1_IC_CON__STOP1_DET_IFADDRESSED_MASK                                                          0x00000080L
+#define CKSVII2C1_IC_CON__TX1_EMPTY_CTRL_MASK                                                                 0x00000100L
+#define CKSVII2C1_IC_CON__RX1_FIFO_FULL_HLD_CTRL_MASK                                                         0x00000200L
+//CKSVII2C1_IC_TAR
+#define CKSVII2C1_IC_TAR__IC1_TAR__SHIFT                                                                      0x0
+#define CKSVII2C1_IC_TAR__GC1_OR_START__SHIFT                                                                 0xa
+#define CKSVII2C1_IC_TAR__SPECIAL1__SHIFT                                                                     0xb
+#define CKSVII2C1_IC_TAR__IC1_10BITADDR_MASTER__SHIFT                                                         0xc
+#define CKSVII2C1_IC_TAR__IC1_TAR_MASK                                                                        0x000003FFL
+#define CKSVII2C1_IC_TAR__GC1_OR_START_MASK                                                                   0x00000400L
+#define CKSVII2C1_IC_TAR__SPECIAL1_MASK                                                                       0x00000800L
+#define CKSVII2C1_IC_TAR__IC1_10BITADDR_MASTER_MASK                                                           0x00001000L
+//CKSVII2C1_IC_SAR
+#define CKSVII2C1_IC_SAR__IC1_SAR__SHIFT                                                                      0x0
+#define CKSVII2C1_IC_SAR__IC1_SAR_MASK                                                                        0x000003FFL
+//CKSVII2C1_IC_HS_MADDR
+#define CKSVII2C1_IC_HS_MADDR__IC1_HS_MADDR__SHIFT                                                            0x0
+#define CKSVII2C1_IC_HS_MADDR__IC1_HS_MADDR_MASK                                                              0x00000007L
+//CKSVII2C1_IC_DATA_CMD
+#define CKSVII2C1_IC_DATA_CMD__DAT1__SHIFT                                                                    0x0
+#define CKSVII2C1_IC_DATA_CMD__CMD1__SHIFT                                                                    0x8
+#define CKSVII2C1_IC_DATA_CMD__STOP1__SHIFT                                                                   0x9
+#define CKSVII2C1_IC_DATA_CMD__RESTART1__SHIFT                                                                0xa
+#define CKSVII2C1_IC_DATA_CMD__DAT1_MASK                                                                      0x000000FFL
+#define CKSVII2C1_IC_DATA_CMD__CMD1_MASK                                                                      0x00000100L
+#define CKSVII2C1_IC_DATA_CMD__STOP1_MASK                                                                     0x00000200L
+#define CKSVII2C1_IC_DATA_CMD__RESTART1_MASK                                                                  0x00000400L
+//CKSVII2C1_IC_SS_SCL_HCNT
+#define CKSVII2C1_IC_SS_SCL_HCNT__IC1_SS_SCL_HCNT__SHIFT                                                      0x0
+#define CKSVII2C1_IC_SS_SCL_HCNT__IC1_SS_SCL_HCNT_MASK                                                        0x0000FFFFL
+//CKSVII2C1_IC_SS_SCL_LCNT
+#define CKSVII2C1_IC_SS_SCL_LCNT__IC1_SS_SCL_LCNT__SHIFT                                                      0x0
+#define CKSVII2C1_IC_SS_SCL_LCNT__IC1_SS_SCL_LCNT_MASK                                                        0x0000FFFFL
+//CKSVII2C1_IC_FS_SCL_HCNT
+#define CKSVII2C1_IC_FS_SCL_HCNT__IC1_FS_SCL_HCNT__SHIFT                                                      0x0
+#define CKSVII2C1_IC_FS_SCL_HCNT__IC1_FS_SCL_HCNT_MASK                                                        0x0000FFFFL
+//CKSVII2C1_IC_FS_SCL_LCNT
+#define CKSVII2C1_IC_FS_SCL_LCNT__IC1_FS_SCL_LCNT__SHIFT                                                      0x0
+#define CKSVII2C1_IC_FS_SCL_LCNT__IC1_FS_SCL_LCNT_MASK                                                        0x0000FFFFL
+//CKSVII2C1_IC_HS_SCL_HCNT
+#define CKSVII2C1_IC_HS_SCL_HCNT__IC1_HS_SCL_HCNT__SHIFT                                                      0x0
+#define CKSVII2C1_IC_HS_SCL_HCNT__IC1_HS_SCL_HCNT_MASK                                                        0x0000FFFFL
+//CKSVII2C1_IC_HS_SCL_LCNT
+#define CKSVII2C1_IC_HS_SCL_LCNT__IC1_HS_SCL_LCNT__SHIFT                                                      0x0
+#define CKSVII2C1_IC_HS_SCL_LCNT__IC1_HS_SCL_LCNT_MASK                                                        0x0000FFFFL
+//CKSVII2C1_IC_INTR_STAT
+#define CKSVII2C1_IC_INTR_STAT__R1_RX_UNDER__SHIFT                                                            0x0
+#define CKSVII2C1_IC_INTR_STAT__R1_RX_OVER__SHIFT                                                             0x1
+#define CKSVII2C1_IC_INTR_STAT__R1_RX_FULL__SHIFT                                                             0x2
+#define CKSVII2C1_IC_INTR_STAT__R1_TX_OVER__SHIFT                                                             0x3
+#define CKSVII2C1_IC_INTR_STAT__R1_TX_EMPTY__SHIFT                                                            0x4
+#define CKSVII2C1_IC_INTR_STAT__R1_RD_REQ__SHIFT                                                              0x5
+#define CKSVII2C1_IC_INTR_STAT__R1_TX_ABRT__SHIFT                                                             0x6
+#define CKSVII2C1_IC_INTR_STAT__R1_RX_DONE__SHIFT                                                             0x7
+#define CKSVII2C1_IC_INTR_STAT__R1_ACTIVITY__SHIFT                                                            0x8
+#define CKSVII2C1_IC_INTR_STAT__R1_STOP_DET__SHIFT                                                            0x9
+#define CKSVII2C1_IC_INTR_STAT__R1_START_DET__SHIFT                                                           0xa
+#define CKSVII2C1_IC_INTR_STAT__R1_GEN_CALL__SHIFT                                                            0xb
+#define CKSVII2C1_IC_INTR_STAT__R1_RESTART_DET__SHIFT                                                         0xc
+#define CKSVII2C1_IC_INTR_STAT__R1_MST_ON_HOLD__SHIFT                                                         0xd
+#define CKSVII2C1_IC_INTR_STAT__R1_RX_UNDER_MASK                                                              0x00000001L
+#define CKSVII2C1_IC_INTR_STAT__R1_RX_OVER_MASK                                                               0x00000002L
+#define CKSVII2C1_IC_INTR_STAT__R1_RX_FULL_MASK                                                               0x00000004L
+#define CKSVII2C1_IC_INTR_STAT__R1_TX_OVER_MASK                                                               0x00000008L
+#define CKSVII2C1_IC_INTR_STAT__R1_TX_EMPTY_MASK                                                              0x00000010L
+#define CKSVII2C1_IC_INTR_STAT__R1_RD_REQ_MASK                                                                0x00000020L
+#define CKSVII2C1_IC_INTR_STAT__R1_TX_ABRT_MASK                                                               0x00000040L
+#define CKSVII2C1_IC_INTR_STAT__R1_RX_DONE_MASK                                                               0x00000080L
+#define CKSVII2C1_IC_INTR_STAT__R1_ACTIVITY_MASK                                                              0x00000100L
+#define CKSVII2C1_IC_INTR_STAT__R1_STOP_DET_MASK                                                              0x00000200L
+#define CKSVII2C1_IC_INTR_STAT__R1_START_DET_MASK                                                             0x00000400L
+#define CKSVII2C1_IC_INTR_STAT__R1_GEN_CALL_MASK                                                              0x00000800L
+#define CKSVII2C1_IC_INTR_STAT__R1_RESTART_DET_MASK                                                           0x00001000L
+#define CKSVII2C1_IC_INTR_STAT__R1_MST_ON_HOLD_MASK                                                           0x00002000L
+//CKSVII2C1_IC_INTR_MASK
+#define CKSVII2C1_IC_INTR_MASK__M1_RX_UNDER__SHIFT                                                            0x0
+#define CKSVII2C1_IC_INTR_MASK__M1_RX_OVER__SHIFT                                                             0x1
+#define CKSVII2C1_IC_INTR_MASK__M1_RX_FULL__SHIFT                                                             0x2
+#define CKSVII2C1_IC_INTR_MASK__M1_TX_OVER__SHIFT                                                             0x3
+#define CKSVII2C1_IC_INTR_MASK__M1_TX_EMPTY__SHIFT                                                            0x4
+#define CKSVII2C1_IC_INTR_MASK__M1_RD_REQ__SHIFT                                                              0x5
+#define CKSVII2C1_IC_INTR_MASK__M1_TX_ABRT__SHIFT                                                             0x6
+#define CKSVII2C1_IC_INTR_MASK__M1_RX_DONE__SHIFT                                                             0x7
+#define CKSVII2C1_IC_INTR_MASK__M1_ACTIVITY__SHIFT                                                            0x8
+#define CKSVII2C1_IC_INTR_MASK__M1_STOP_DET__SHIFT                                                            0x9
+#define CKSVII2C1_IC_INTR_MASK__M1_START_DET__SHIFT                                                           0xa
+#define CKSVII2C1_IC_INTR_MASK__M1_GEN_CALL__SHIFT                                                            0xb
+#define CKSVII2C1_IC_INTR_MASK__M1_RESTART_DET__SHIFT                                                         0xc
+#define CKSVII2C1_IC_INTR_MASK__M1_MST_ON_HOLD__SHIFT                                                         0xd
+#define CKSVII2C1_IC_INTR_MASK__M1_RX_UNDER_MASK                                                              0x00000001L
+#define CKSVII2C1_IC_INTR_MASK__M1_RX_OVER_MASK                                                               0x00000002L
+#define CKSVII2C1_IC_INTR_MASK__M1_RX_FULL_MASK                                                               0x00000004L
+#define CKSVII2C1_IC_INTR_MASK__M1_TX_OVER_MASK                                                               0x00000008L
+#define CKSVII2C1_IC_INTR_MASK__M1_TX_EMPTY_MASK                                                              0x00000010L
+#define CKSVII2C1_IC_INTR_MASK__M1_RD_REQ_MASK                                                                0x00000020L
+#define CKSVII2C1_IC_INTR_MASK__M1_TX_ABRT_MASK                                                               0x00000040L
+#define CKSVII2C1_IC_INTR_MASK__M1_RX_DONE_MASK                                                               0x00000080L
+#define CKSVII2C1_IC_INTR_MASK__M1_ACTIVITY_MASK                                                              0x00000100L
+#define CKSVII2C1_IC_INTR_MASK__M1_STOP_DET_MASK                                                              0x00000200L
+#define CKSVII2C1_IC_INTR_MASK__M1_START_DET_MASK                                                             0x00000400L
+#define CKSVII2C1_IC_INTR_MASK__M1_GEN_CALL_MASK                                                              0x00000800L
+#define CKSVII2C1_IC_INTR_MASK__M1_RESTART_DET_MASK                                                           0x00001000L
+#define CKSVII2C1_IC_INTR_MASK__M1_MST_ON_HOLD_MASK                                                           0x00002000L
+//CKSVII2C1_IC_RAW_INTR_STAT
+//CKSVII2C1_IC_RX_TL
+//CKSVII2C1_IC_TX_TL
+//CKSVII2C1_IC_CLR_INTR
+//CKSVII2C1_IC_CLR_RX_UNDER
+//CKSVII2C1_IC_CLR_RX_OVER
+//CKSVII2C1_IC_CLR_TX_OVER
+//CKSVII2C1_IC_CLR_RD_REQ
+//CKSVII2C1_IC_CLR_TX_ABRT
+//CKSVII2C1_IC_CLR_RX_DONE
+//CKSVII2C1_IC_CLR_ACTIVITY
+//CKSVII2C1_IC_CLR_STOP_DET
+//CKSVII2C1_IC_CLR_START_DET
+//CKSVII2C1_IC_CLR_GEN_CALL
+//CKSVII2C1_IC_ENABLE
+#define CKSVII2C1_IC_ENABLE__ENABLE1__SHIFT                                                                   0x0
+#define CKSVII2C1_IC_ENABLE__ABORT1__SHIFT                                                                    0x1
+#define CKSVII2C1_IC_ENABLE__ENABLE1_MASK                                                                     0x00000001L
+#define CKSVII2C1_IC_ENABLE__ABORT1_MASK                                                                      0x00000002L
+//CKSVII2C1_IC_STATUS
+#define CKSVII2C1_IC_STATUS__ACTIVITY1__SHIFT                                                                 0x0
+#define CKSVII2C1_IC_STATUS__TFNF1__SHIFT                                                                     0x1
+#define CKSVII2C1_IC_STATUS__TFE1__SHIFT                                                                      0x2
+#define CKSVII2C1_IC_STATUS__RFNE1__SHIFT                                                                     0x3
+#define CKSVII2C1_IC_STATUS__RFF1__SHIFT                                                                      0x4
+#define CKSVII2C1_IC_STATUS__MST1_ACTIVITY__SHIFT                                                             0x5
+#define CKSVII2C1_IC_STATUS__SLV1_ACTIVITY__SHIFT                                                             0x6
+#define CKSVII2C1_IC_STATUS__ACTIVITY1_MASK                                                                   0x00000001L
+#define CKSVII2C1_IC_STATUS__TFNF1_MASK                                                                       0x00000002L
+#define CKSVII2C1_IC_STATUS__TFE1_MASK                                                                        0x00000004L
+#define CKSVII2C1_IC_STATUS__RFNE1_MASK                                                                       0x00000008L
+#define CKSVII2C1_IC_STATUS__RFF1_MASK                                                                        0x00000010L
+#define CKSVII2C1_IC_STATUS__MST1_ACTIVITY_MASK                                                               0x00000020L
+#define CKSVII2C1_IC_STATUS__SLV1_ACTIVITY_MASK                                                               0x00000040L
+//CKSVII2C1_IC_TXFLR
+//CKSVII2C1_IC_RXFLR
+//CKSVII2C1_IC_SDA_HOLD
+#define CKSVII2C1_IC_SDA_HOLD__IC1_SDA_HOLD__SHIFT                                                            0x0
+#define CKSVII2C1_IC_SDA_HOLD__IC1_SDA_HOLD_MASK                                                              0x00FFFFFFL
+//CKSVII2C1_IC_TX_ABRT_SOURCE
+//CKSVII2C1_IC_SLV_DATA_NACK_ONLY
+//CKSVII2C1_IC_DMA_CR
+//CKSVII2C1_IC_DMA_TDLR
+//CKSVII2C1_IC_DMA_RDLR
+//CKSVII2C1_IC_SDA_SETUP
+#define CKSVII2C1_IC_SDA_SETUP__SDA1_SETUP__SHIFT                                                             0x0
+#define CKSVII2C1_IC_SDA_SETUP__SDA1_SETUP_MASK                                                               0x000000FFL
+//CKSVII2C1_IC_ACK_GENERAL_CALL
+#define CKSVII2C1_IC_ACK_GENERAL_CALL__ACK1_GENERAL_CALL__SHIFT                                               0x0
+#define CKSVII2C1_IC_ACK_GENERAL_CALL__ACK1_GENERAL_CALL_MASK                                                 0x00000001L
+//CKSVII2C1_IC_ENABLE_STATUS
+#define CKSVII2C1_IC_ENABLE_STATUS__IC1_EN__SHIFT                                                             0x0
+#define CKSVII2C1_IC_ENABLE_STATUS__SLV1_RX_ABORTED__SHIFT                                                    0x1
+#define CKSVII2C1_IC_ENABLE_STATUS__SLV1_FIFO_FILLED_AND_FLUSHED__SHIFT                                       0x2
+#define CKSVII2C1_IC_ENABLE_STATUS__IC1_EN_MASK                                                               0x00000001L
+#define CKSVII2C1_IC_ENABLE_STATUS__SLV1_RX_ABORTED_MASK                                                      0x00000002L
+#define CKSVII2C1_IC_ENABLE_STATUS__SLV1_FIFO_FILLED_AND_FLUSHED_MASK                                         0x00000004L
 //SMUIO_MP_RESET_INTR
 #define SMUIO_MP_RESET_INTR__SMUIO_MP_RESET_INTR__SHIFT                                                       0x0
 #define SMUIO_MP_RESET_INTR__SMUIO_MP_RESET_INTR_MASK                                                         0x00000001L
index e88541d67aa0040e6a60896f9a16dc945ddaf6de..dd7cbc00a0aa2ac3a61d1f16fe5cb04825e16656 100644 (file)
@@ -492,12 +492,13 @@ struct atom_firmware_info_v3_1
 /* Total 32bit cap indication */
 enum atombios_firmware_capability
 {
-  ATOM_FIRMWARE_CAP_FIRMWARE_POSTED = 0x00000001,
-  ATOM_FIRMWARE_CAP_GPU_VIRTUALIZATION  = 0x00000002,
-  ATOM_FIRMWARE_CAP_WMI_SUPPORT  = 0x00000040,
-  ATOM_FIRMWARE_CAP_HWEMU_ENABLE  = 0x00000080,
-  ATOM_FIRMWARE_CAP_HWEMU_UMC_CFG = 0x00000100,
-  ATOM_FIRMWARE_CAP_SRAM_ECC      = 0x00000200,
+       ATOM_FIRMWARE_CAP_FIRMWARE_POSTED = 0x00000001,
+       ATOM_FIRMWARE_CAP_GPU_VIRTUALIZATION  = 0x00000002,
+       ATOM_FIRMWARE_CAP_WMI_SUPPORT  = 0x00000040,
+       ATOM_FIRMWARE_CAP_HWEMU_ENABLE  = 0x00000080,
+       ATOM_FIRMWARE_CAP_HWEMU_UMC_CFG = 0x00000100,
+       ATOM_FIRMWARE_CAP_SRAM_ECC      = 0x00000200,
+       ATOM_FIRMWARE_CAP_ENABLE_2STAGE_BIST_TRAINING  = 0x00000400,
 };
 
 enum atom_cooling_solution_id{
@@ -671,6 +672,20 @@ struct vram_usagebyfirmware_v2_1
   uint16_t  used_by_driver_in_kb; 
 };
 
+/* This is part of vram_usagebyfirmware_v2_1 */
+struct vram_reserve_block
+{
+       uint32_t start_address_in_kb;
+       uint16_t used_by_firmware_in_kb;
+       uint16_t used_by_driver_in_kb;
+};
+
+/* Definitions for constance */
+enum atomfirmware_internal_constants
+{
+       ONE_KiB = 0x400,
+       ONE_MiB = 0x100000,
+};
 
 /* 
   ***************************************************************************
index 5dcb776548d8974f50acc75d5da11f3be9c1f14f..7ec4331e67f26e5860268637c2e5f77b28a9fe25 100644 (file)
@@ -25,7 +25,6 @@
 #define _DISCOVERY_H_
 
 #define PSP_HEADER_SIZE                 256
-#define BINARY_MAX_SIZE                 (64 << 10)
 #define BINARY_SIGNATURE                0x28211407
 #define DISCOVERY_TABLE_SIGNATURE       0x53445049
 
diff --git a/drivers/gpu/drm/amd/include/ivsrcid/nbio/irqsrcs_nbif_7_4.h b/drivers/gpu/drm/amd/include/ivsrcid/nbio/irqsrcs_nbif_7_4.h
new file mode 100644 (file)
index 0000000..79af425
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright 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) 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 __IRQSRCS_NBIF_7_4_H__
+#define __IRQSRCS_NBIF_7_4_H__
+
+#define NBIF_7_4__SRCID__CHIP_ERR_INT_EVENT            0x5E        // Error generated
+#define NBIF_7_4__SRCID__DOORBELL_INTERRUPT            0x5F        // Interrupt for doorbell event during VDDGFX off
+#define NBIF_7_4__SRCID__RAS_CONTROLLER_INTERRUPT      0x60        // Interrupt for ras_intr_valid from RAS controller
+#define NBIF_7_4__SRCID__ERREVENT_ATHUB_INTERRUPT      0x61        // Interrupt for SDP ErrEvent received from ATHUB
+#define NBIF_7_4__SRCID__PF_VF_MSGBUF_VALID            0x87        // Valid message in PF->VF mailbox message buffer (The interrupt is sent on behalf of PF)
+#define NBIF_7_4__SRCID__PF_VF_MSGBUF_ACK              0x88        // Acknowledge message in PF->VF mailbox message buffer (The interrupt is sent on behalf of VF)
+#define NBIF_7_4__SRCID__VF_PF_MSGBUF_VALID            0x89        // Valid message in VF->PF mailbox message buffer (The interrupt is sent on behalf of VF)
+#define NBIF_7_4__SRCID__VF_PF_MSGBUF_ACK              0x8A        // Acknowledge message in VF->PF mailbox message buffer (The interrupt is sent on behalf of PF)
+#define NBIF_7_4__SRCID__CHIP_DPA_INT_EVENT            0xA0        // BIF_CHIP_DPA_INT_EVENT
+#define NBIF_7_4__SRCID__CHIP_SLOT_POWER_CHG_INT_EVENT 0xA1        // BIF_CHIP_SLOT_POWER_CHG_INT_EVENT
+#define NBIF_7_4__SRCID__ATOMIC_UR_OPCODE              0xCE        // BIF receives unsupported atomic opcode from MC
+#define NBIF_7_4__SRCID__ATOMIC_REQESTEREN_LOW         0xCF        // BIF receive atomic request from MC while AtomicOp Requester is not enabled in PCIE config space
+
+#endif // __IRQSRCS_NBIF_7_4_H__
index 98b9533e672ba9a3e876fe4cbe11e8f9d23d4c0a..2cd217e60125d2993b149f1d45454869ec48be88 100644 (file)
@@ -291,15 +291,18 @@ struct kfd2kgd_calls {
        uint32_t (*address_watch_get_offset)(struct kgd_dev *kgd,
                                        unsigned int watch_point_id,
                                        unsigned int reg_offset);
-       bool (*get_atc_vmid_pasid_mapping_valid)(
+       bool (*get_atc_vmid_pasid_mapping_info)(
                                        struct kgd_dev *kgd,
-                                       uint8_t vmid);
-       uint16_t (*get_atc_vmid_pasid_mapping_pasid)(
-                                       struct kgd_dev *kgd,
-                                       uint8_t vmid);
+                                       uint8_t vmid,
+                                       uint16_t *p_pasid);
 
+       /* No longer needed from GFXv9 onward. The scratch base address is
+        * passed to the shader by the CP. It's the user mode driver's
+        * responsibility.
+        */
        void (*set_scratch_backing_va)(struct kgd_dev *kgd,
                                uint64_t va, uint32_t vmid);
+
        int (*get_tile_config)(struct kgd_dev *kgd, struct tile_config *config);
 
        void (*set_vm_context_page_table_base)(struct kgd_dev *kgd,
index 27cf0afaa0b4e63a90c65c0d81ba92fe53fdde95..5902f80d1fce66906536c20a94e4ea4859e70aa4 100644 (file)
@@ -179,6 +179,11 @@ enum pp_mp1_state {
        PP_MP1_STATE_RESET,
 };
 
+enum pp_df_cstate {
+       DF_CSTATE_DISALLOW = 0,
+       DF_CSTATE_ALLOW,
+};
+
 #define PP_GROUP_MASK        0xF0000000
 #define PP_GROUP_SHIFT       28
 
@@ -312,6 +317,7 @@ struct amd_pm_funcs {
        int (*get_ppfeature_status)(void *handle, char *buf);
        int (*set_ppfeature_status)(void *handle, uint64_t ppfeature_masks);
        int (*asic_reset_mode_2)(void *handle);
+       int (*set_df_cstate)(void *handle, enum pp_df_cstate state);
 };
 
 #endif
index 094648cac3925f4ab00ad0e3f4fde5d2996d1bbf..07633e22e99a15c15debf61b0b79a2ba3b82f266 100644 (file)
@@ -169,6 +169,11 @@ static const struct IP_BASE NBIF0_BASE ={ { { { 0x00000000, 0x00000014, 0x00000D
                                         { { 0, 0, 0, 0, 0 } },
                                         { { 0, 0, 0, 0, 0 } },
                                         { { 0, 0, 0, 0, 0 } } } };
+static const struct IP_BASE DCN_BASE   ={ { { { 0x00000012, 0x000000C0, 0x000034C0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } },
+                                        { { 0, 0, 0, 0, 0 } } } };
 static const struct IP_BASE OSSSYS_BASE ={ { { { 0x000010A0, 0x0240A000, 0, 0, 0 } },
                                         { { 0, 0, 0, 0, 0 } },
                                         { { 0, 0, 0, 0, 0 } },
@@ -1361,4 +1366,33 @@ static const struct IP_BASE UVD0_BASE ={ { { { 0x00007800, 0x00007E00, 0x0240300
 #define UVD0_BASE__INST6_SEG3                      0
 #define UVD0_BASE__INST6_SEG4                      0
 
+#define DCN_BASE__INST0_SEG0                      0x00000012
+#define DCN_BASE__INST0_SEG1                      0x000000C0
+#define DCN_BASE__INST0_SEG2                      0x000034C0
+#define DCN_BASE__INST0_SEG3                      0
+#define DCN_BASE__INST0_SEG4                      0
+
+#define DCN_BASE__INST1_SEG0                      0
+#define DCN_BASE__INST1_SEG1                      0
+#define DCN_BASE__INST1_SEG2                      0
+#define DCN_BASE__INST1_SEG3                      0
+#define DCN_BASE__INST1_SEG4                      0
+
+#define DCN_BASE__INST2_SEG0                      0
+#define DCN_BASE__INST2_SEG1                      0
+#define DCN_BASE__INST2_SEG2                      0
+#define DCN_BASE__INST2_SEG3                      0
+#define DCN_BASE__INST2_SEG4                      0
+
+#define DCN_BASE__INST3_SEG0                      0
+#define DCN_BASE__INST3_SEG1                      0
+#define DCN_BASE__INST3_SEG2                      0
+#define DCN_BASE__INST3_SEG3                      0
+#define DCN_BASE__INST3_SEG4                      0
+
+#define DCN_BASE__INST4_SEG0                      0
+#define DCN_BASE__INST4_SEG1                      0
+#define DCN_BASE__INST4_SEG2                      0
+#define DCN_BASE__INST4_SEG3                      0
+#define DCN_BASE__INST4_SEG4                      0
 #endif
index c14ba65a24157f133f8d5bf37f5424c2d70d2ad1..adf1b754666e3d616378084f0c80760b87b6d961 100644 (file)
@@ -1037,6 +1037,7 @@ TCC_CACHE_POLICY_STREAM                  = 0x00000001,
 typedef enum MTYPE {
 MTYPE_NC                                 = 0x00000000,
 MTYPE_WC                                 = 0x00000001,
+MTYPE_RW                                 = 0x00000001,
 MTYPE_CC                                 = 0x00000002,
 MTYPE_UC                                 = 0x00000003,
 } MTYPE;
index fa8ad7db2b3a1f933ea698646dc0a537acffdbfb..f4ff15378e61b478987f552124e7cebe24ad4b60 100644 (file)
@@ -1421,6 +1421,7 @@ static int pp_get_asic_baco_capability(void *handle, bool *cap)
 {
        struct pp_hwmgr *hwmgr = handle;
 
+       *cap = false;
        if (!hwmgr)
                return -EINVAL;
 
@@ -1548,6 +1549,23 @@ static int pp_smu_i2c_bus_access(void *handle, bool acquire)
        return ret;
 }
 
+static int pp_set_df_cstate(void *handle, enum pp_df_cstate state)
+{
+       struct pp_hwmgr *hwmgr = handle;
+
+       if (!hwmgr)
+               return -EINVAL;
+
+       if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_df_cstate)
+               return 0;
+
+       mutex_lock(&hwmgr->smu_lock);
+       hwmgr->hwmgr_func->set_df_cstate(hwmgr, state);
+       mutex_unlock(&hwmgr->smu_lock);
+
+       return 0;
+}
+
 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,
@@ -1606,4 +1624,5 @@ static const struct amd_pm_funcs pp_dpm_funcs = {
        .set_ppfeature_status = pp_set_ppfeature_status,
        .asic_reset_mode_2 = pp_asic_reset_mode_2,
        .smu_i2c_bus_access = pp_smu_i2c_bus_access,
+       .set_df_cstate = pp_set_df_cstate,
 };
index 4acf139ea014099beb2616344a462e119203eedb..ee374df32b199e1398e729f8df954040540775a2 100644 (file)
@@ -95,6 +95,52 @@ size_t smu_sys_get_pp_feature_mask(struct smu_context *smu, char *buf)
        return size;
 }
 
+static int smu_feature_update_enable_state(struct smu_context *smu,
+                                          uint64_t feature_mask,
+                                          bool enabled)
+{
+       struct smu_feature *feature = &smu->smu_feature;
+       uint32_t feature_low = 0, feature_high = 0;
+       int ret = 0;
+
+       if (!smu->pm_enabled)
+               return ret;
+
+       feature_low = (feature_mask >> 0 ) & 0xffffffff;
+       feature_high = (feature_mask >> 32) & 0xffffffff;
+
+       if (enabled) {
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesLow,
+                                                 feature_low);
+               if (ret)
+                       return ret;
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesHigh,
+                                                 feature_high);
+               if (ret)
+                       return ret;
+       } else {
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesLow,
+                                                 feature_low);
+               if (ret)
+                       return ret;
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesHigh,
+                                                 feature_high);
+               if (ret)
+                       return ret;
+       }
+
+       mutex_lock(&feature->mutex);
+       if (enabled)
+               bitmap_or(feature->enabled, feature->enabled,
+                               (unsigned long *)(&feature_mask), SMU_FEATURE_MAX);
+       else
+               bitmap_andnot(feature->enabled, feature->enabled,
+                               (unsigned long *)(&feature_mask), SMU_FEATURE_MAX);
+       mutex_unlock(&feature->mutex);
+
+       return ret;
+}
+
 int smu_sys_set_pp_feature_mask(struct smu_context *smu, uint64_t new_mask)
 {
        int ret = 0;
@@ -159,8 +205,7 @@ int smu_get_smc_version(struct smu_context *smu, uint32_t *if_version, uint32_t
 int smu_set_soft_freq_range(struct smu_context *smu, enum smu_clk_type clk_type,
                            uint32_t min, uint32_t max)
 {
-       int ret = 0, clk_id = 0;
-       uint32_t param;
+       int ret = 0;
 
        if (min <= 0 && max <= 0)
                return -EINVAL;
@@ -168,27 +213,7 @@ int smu_set_soft_freq_range(struct smu_context *smu, enum smu_clk_type clk_type,
        if (!smu_clk_dpm_is_enabled(smu, clk_type))
                return 0;
 
-       clk_id = smu_clk_get_index(smu, clk_type);
-       if (clk_id < 0)
-               return clk_id;
-
-       if (max > 0) {
-               param = (uint32_t)((clk_id << 16) | (max & 0xffff));
-               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxByFreq,
-                                                 param);
-               if (ret)
-                       return ret;
-       }
-
-       if (min > 0) {
-               param = (uint32_t)((clk_id << 16) | (min & 0xffff));
-               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinByFreq,
-                                                 param);
-               if (ret)
-                       return ret;
-       }
-
-
+       ret = smu_set_soft_freq_limited_range(smu, clk_type, min, max);
        return ret;
 }
 
@@ -439,7 +464,7 @@ int smu_update_table(struct smu_context *smu, enum smu_table_id table_index, int
        int ret = 0;
        int table_id = smu_table_get_index(smu, table_index);
 
-       if (!table_data || table_id >= smu_table->table_count || table_id < 0)
+       if (!table_data || table_id >= SMU_TABLE_COUNT || table_id < 0)
                return -EINVAL;
 
        table = &smu_table->tables[table_index];
@@ -463,7 +488,7 @@ int smu_update_table(struct smu_context *smu, enum smu_table_id table_index, int
                return ret;
 
        /* flush hdp cache */
-       adev->nbio_funcs->hdp_flush(adev, NULL);
+       adev->nbio.funcs->hdp_flush(adev, NULL);
 
        if (!drv2smu)
                memcpy(table_data, table->cpu_addr, table->size);
@@ -569,41 +594,7 @@ int smu_feature_init_dpm(struct smu_context *smu)
 
        return ret;
 }
-int smu_feature_update_enable_state(struct smu_context *smu, uint64_t feature_mask, bool enabled)
-{
-       uint32_t feature_low = 0, feature_high = 0;
-       int ret = 0;
-
-       if (!smu->pm_enabled)
-               return ret;
-
-       feature_low = (feature_mask >> 0 ) & 0xffffffff;
-       feature_high = (feature_mask >> 32) & 0xffffffff;
-
-       if (enabled) {
-               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesLow,
-                                                 feature_low);
-               if (ret)
-                       return ret;
-               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesHigh,
-                                                 feature_high);
-               if (ret)
-                       return ret;
-
-       } else {
-               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesLow,
-                                                 feature_low);
-               if (ret)
-                       return ret;
-               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesHigh,
-                                                 feature_high);
-               if (ret)
-                       return ret;
 
-       }
-
-       return ret;
-}
 
 int smu_feature_is_enabled(struct smu_context *smu, enum smu_feature_mask mask)
 {
@@ -633,8 +624,6 @@ int smu_feature_set_enabled(struct smu_context *smu, enum smu_feature_mask mask,
 {
        struct smu_feature *feature = &smu->smu_feature;
        int feature_id;
-       uint64_t feature_mask = 0;
-       int ret = 0;
 
        feature_id = smu_feature_get_index(smu, mask);
        if (feature_id < 0)
@@ -642,22 +631,9 @@ int smu_feature_set_enabled(struct smu_context *smu, enum smu_feature_mask mask,
 
        WARN_ON(feature_id > feature->feature_num);
 
-       feature_mask = 1ULL << feature_id;
-
-       mutex_lock(&feature->mutex);
-       ret = smu_feature_update_enable_state(smu, feature_mask, enable);
-       if (ret)
-               goto failed;
-
-       if (enable)
-               test_and_set_bit(feature_id, feature->enabled);
-       else
-               test_and_clear_bit(feature_id, feature->enabled);
-
-failed:
-       mutex_unlock(&feature->mutex);
-
-       return ret;
+       return smu_feature_update_enable_state(smu,
+                                              1ULL << feature_id,
+                                              enable);
 }
 
 int smu_feature_is_supported(struct smu_context *smu, enum smu_feature_mask mask)
@@ -736,6 +712,7 @@ static int smu_early_init(void *handle)
 
        smu->adev = adev;
        smu->pm_enabled = !!amdgpu_dpm;
+       smu->is_apu = false;
        mutex_init(&smu->mutex);
 
        return smu_set_funcs(adev);
@@ -919,14 +896,9 @@ static int smu_init_fb_allocations(struct smu_context *smu)
        struct amdgpu_device *adev = smu->adev;
        struct smu_table_context *smu_table = &smu->smu_table;
        struct smu_table *tables = smu_table->tables;
-       uint32_t table_count = smu_table->table_count;
-       uint32_t i = 0;
-       int32_t ret = 0;
-
-       if (table_count <= 0)
-               return -EINVAL;
+       int ret, i;
 
-       for (i = 0 ; i < table_count; i++) {
+       for (i = 0; i < SMU_TABLE_COUNT; i++) {
                if (tables[i].size == 0)
                        continue;
                ret = amdgpu_bo_create_kernel(adev,
@@ -942,7 +914,7 @@ static int smu_init_fb_allocations(struct smu_context *smu)
 
        return 0;
 failed:
-       for (; i > 0; i--) {
+       while (--i >= 0) {
                if (tables[i].size == 0)
                        continue;
                amdgpu_bo_free_kernel(&tables[i].bo,
@@ -957,13 +929,12 @@ static int smu_fini_fb_allocations(struct smu_context *smu)
 {
        struct smu_table_context *smu_table = &smu->smu_table;
        struct smu_table *tables = smu_table->tables;
-       uint32_t table_count = smu_table->table_count;
        uint32_t i = 0;
 
-       if (table_count == 0 || tables == NULL)
+       if (!tables)
                return 0;
 
-       for (i = 0 ; i < table_count; i++) {
+       for (i = 0; i < SMU_TABLE_COUNT; i++) {
                if (tables[i].size == 0)
                        continue;
                amdgpu_bo_free_kernel(&tables[i].bo,
@@ -974,50 +945,6 @@ static int smu_fini_fb_allocations(struct smu_context *smu)
        return 0;
 }
 
-static int smu_override_pcie_parameters(struct smu_context *smu)
-{
-       struct amdgpu_device *adev = smu->adev;
-       uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg;
-       int ret;
-
-       if (adev->flags & AMD_IS_APU)
-               return 0;
-
-       if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
-               pcie_gen = 3;
-       else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
-               pcie_gen = 2;
-       else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
-               pcie_gen = 1;
-       else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1)
-               pcie_gen = 0;
-
-       /* Bit 31:16: LCLK DPM level. 0 is DPM0, and 1 is DPM1
-        * Bit 15:8:  PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4
-        * Bit 7:0:   PCIE lane width, 1 to 7 corresponds is x1 to x32
-        */
-       if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
-               pcie_width = 6;
-       else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12)
-               pcie_width = 5;
-       else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8)
-               pcie_width = 4;
-       else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4)
-               pcie_width = 3;
-       else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2)
-               pcie_width = 2;
-       else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1)
-               pcie_width = 1;
-
-       smu_pcie_arg = (1 << 16) | (pcie_gen << 8) | pcie_width;
-       ret = smu_send_smc_msg_with_param(smu,
-                                         SMU_MSG_OverridePcieParameters,
-                                         smu_pcie_arg);
-       if (ret)
-               pr_err("[%s] Attempt to override pcie params failed!\n", __func__);
-       return ret;
-}
-
 static int smu_smc_table_hw_init(struct smu_context *smu,
                                 bool initialize)
 {
@@ -1092,8 +1019,8 @@ static int smu_smc_table_hw_init(struct smu_context *smu,
        if (ret)
                return ret;
 
-       /* issue RunAfllBtc msg */
-       ret = smu_run_afll_btc(smu);
+       /* issue Run*Btc msg */
+       ret = smu_run_btc(smu);
        if (ret)
                return ret;
 
@@ -1226,11 +1153,10 @@ static int smu_free_memory_pool(struct smu_context *smu)
        return ret;
 }
 
-static int smu_hw_init(void *handle)
+static int smu_start_smc_engine(struct smu_context *smu)
 {
-       int ret;
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct smu_context *smu = &adev->smu;
+       struct amdgpu_device *adev = smu->adev;
+       int ret = 0;
 
        if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
                if (adev->asic_type < CHIP_NAVI10) {
@@ -1241,14 +1167,28 @@ static int smu_hw_init(void *handle)
        }
 
        ret = smu_check_fw_status(smu);
+       if (ret)
+               pr_err("SMC is not ready\n");
+
+       return ret;
+}
+
+static int smu_hw_init(void *handle)
+{
+       int ret;
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       struct smu_context *smu = &adev->smu;
+
+       ret = smu_start_smc_engine(smu);
        if (ret) {
-               pr_err("SMC firmware status is not correct\n");
+               pr_err("SMU is not ready yet!\n");
                return ret;
        }
 
        if (adev->flags & AMD_IS_APU) {
                smu_powergate_sdma(&adev->smu, false);
                smu_powergate_vcn(&adev->smu, false);
+               smu_set_gfx_cgpg(&adev->smu, true);
        }
 
        if (!smu->pm_enabled)
@@ -1291,6 +1231,11 @@ static int smu_hw_init(void *handle)
        return ret;
 }
 
+static int smu_stop_dpms(struct smu_context *smu)
+{
+       return smu_send_smc_msg(smu, SMU_MSG_DisableAllSmuFeatures);
+}
+
 static int smu_hw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -1303,6 +1248,18 @@ static int smu_hw_fini(void *handle)
                smu_powergate_vcn(&adev->smu, true);
        }
 
+       ret = smu_stop_thermal_control(smu);
+       if (ret) {
+               pr_warn("Fail to stop thermal control!\n");
+               return ret;
+       }
+
+       ret = smu_stop_dpms(smu);
+       if (ret) {
+               pr_warn("Fail to stop Dpms!\n");
+               return ret;
+       }
+
        kfree(table_context->driver_pptable);
        table_context->driver_pptable = NULL;
 
@@ -1344,7 +1301,10 @@ static int smu_suspend(void *handle)
        int ret;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        struct smu_context *smu = &adev->smu;
-       bool baco_feature_is_enabled = smu_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT);
+       bool baco_feature_is_enabled = false;
+
+       if(!(adev->flags & AMD_IS_APU))
+               baco_feature_is_enabled = smu_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT);
 
        ret = smu_system_features_control(smu, false);
        if (ret)
@@ -1377,6 +1337,12 @@ static int smu_resume(void *handle)
 
        mutex_lock(&smu->mutex);
 
+       ret = smu_start_smc_engine(smu);
+       if (ret) {
+               pr_err("SMU is not ready yet!\n");
+               goto failed;
+       }
+
        ret = smu_smc_table_hw_init(smu, false);
        if (ret)
                goto failed;
@@ -1385,6 +1351,11 @@ static int smu_resume(void *handle)
        if (ret)
                goto failed;
 
+       if (smu->is_apu)
+               smu_set_gfx_cgpg(&adev->smu, true);
+
+       smu->disable_uclk_switch = 0;
+
        mutex_unlock(&smu->mutex);
 
        pr_info("SMU is resumed successfully!\n");
@@ -1529,7 +1500,8 @@ static int smu_enable_umd_pstate(void *handle,
 
        struct smu_context *smu = (struct smu_context*)(handle);
        struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
-       if (!smu->pm_enabled || !smu_dpm_ctx->dpm_context)
+
+       if (!smu->is_apu && (!smu->pm_enabled || !smu_dpm_ctx->dpm_context))
                return -EINVAL;
 
        if (!(smu_dpm_ctx->dpm_level & profile_mode_mask)) {
@@ -1727,7 +1699,7 @@ enum amd_dpm_forced_level smu_get_performance_level(struct smu_context *smu)
        struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
        enum amd_dpm_forced_level level;
 
-       if (!smu_dpm_ctx->dpm_context)
+       if (!smu->is_apu && !smu_dpm_ctx->dpm_context)
                return -EINVAL;
 
        mutex_lock(&(smu->mutex));
@@ -1742,7 +1714,7 @@ int smu_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_lev
        struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
        int ret = 0;
 
-       if (!smu_dpm_ctx->dpm_context)
+       if (!smu->is_apu && !smu_dpm_ctx->dpm_context)
                return -EINVAL;
 
        ret = smu_enable_umd_pstate(smu, &level);
@@ -1766,6 +1738,122 @@ int smu_set_display_count(struct smu_context *smu, uint32_t count)
        return ret;
 }
 
+int smu_force_clk_levels(struct smu_context *smu,
+                        enum smu_clk_type clk_type,
+                        uint32_t mask)
+{
+       struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
+       int ret = 0;
+
+       if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
+               pr_debug("force clock level is for dpm manual mode only.\n");
+               return -EINVAL;
+       }
+
+       if (smu->ppt_funcs && smu->ppt_funcs->force_clk_levels)
+               ret = smu->ppt_funcs->force_clk_levels(smu, clk_type, mask);
+
+       return ret;
+}
+
+int smu_set_mp1_state(struct smu_context *smu,
+                     enum pp_mp1_state mp1_state)
+{
+       uint16_t msg;
+       int ret;
+
+       /*
+        * The SMC is not fully ready. That may be
+        * expected as the IP may be masked.
+        * So, just return without error.
+        */
+       if (!smu->pm_enabled)
+               return 0;
+
+       switch (mp1_state) {
+       case PP_MP1_STATE_SHUTDOWN:
+               msg = SMU_MSG_PrepareMp1ForShutdown;
+               break;
+       case PP_MP1_STATE_UNLOAD:
+               msg = SMU_MSG_PrepareMp1ForUnload;
+               break;
+       case PP_MP1_STATE_RESET:
+               msg = SMU_MSG_PrepareMp1ForReset;
+               break;
+       case PP_MP1_STATE_NONE:
+       default:
+               return 0;
+       }
+
+       /* some asics may not support those messages */
+       if (smu_msg_get_index(smu, msg) < 0)
+               return 0;
+
+       ret = smu_send_smc_msg(smu, msg);
+       if (ret)
+               pr_err("[PrepareMp1] Failed!\n");
+
+       return ret;
+}
+
+int smu_set_df_cstate(struct smu_context *smu,
+                     enum pp_df_cstate state)
+{
+       int ret = 0;
+
+       /*
+        * The SMC is not fully ready. That may be
+        * expected as the IP may be masked.
+        * So, just return without error.
+        */
+       if (!smu->pm_enabled)
+               return 0;
+
+       if (!smu->ppt_funcs || !smu->ppt_funcs->set_df_cstate)
+               return 0;
+
+       ret = smu->ppt_funcs->set_df_cstate(smu, state);
+       if (ret)
+               pr_err("[SetDfCstate] failed!\n");
+
+       return ret;
+}
+
+int smu_write_watermarks_table(struct smu_context *smu)
+{
+       int ret = 0;
+       struct smu_table_context *smu_table = &smu->smu_table;
+       struct smu_table *table = NULL;
+
+       table = &smu_table->tables[SMU_TABLE_WATERMARKS];
+
+       if (!table->cpu_addr)
+               return -EINVAL;
+
+       ret = smu_update_table(smu, SMU_TABLE_WATERMARKS, 0, table->cpu_addr,
+                               true);
+
+       return ret;
+}
+
+int smu_set_watermarks_for_clock_ranges(struct smu_context *smu,
+               struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges)
+{
+       int ret = 0;
+       struct smu_table *watermarks = &smu->smu_table.tables[SMU_TABLE_WATERMARKS];
+       void *table = watermarks->cpu_addr;
+
+       if (!smu->disable_watermark &&
+                       smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
+                       smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
+               smu_set_watermarks_table(smu, table, clock_ranges);
+               smu->watermarks_bitmap |= WATERMARKS_EXIST;
+               smu->watermarks_bitmap &= ~WATERMARKS_LOADED;
+       }
+
+       return ret;
+}
+
 const struct amd_ip_funcs smu_ip_funcs = {
        .name = "smu",
        .early_init = smu_early_init,
index d493a3f8c07a63bd570b25905e965f854bf74e90..90d871af8e58c8b2b7213fc091437ea7a4d0b365 100644 (file)
@@ -112,8 +112,7 @@ static struct smu_11_0_cmn2aisc_mapping arcturus_message_map[SMU_MSG_MAX_COUNT]
        MSG_MAP(PrepareMp1ForShutdown,               PPSMC_MSG_PrepareMp1ForShutdown),
        MSG_MAP(SoftReset,                           PPSMC_MSG_SoftReset),
        MSG_MAP(RunAfllBtc,                          PPSMC_MSG_RunAfllBtc),
-       MSG_MAP(RunGfxDcBtc,                         PPSMC_MSG_RunGfxDcBtc),
-       MSG_MAP(RunSocDcBtc,                         PPSMC_MSG_RunSocDcBtc),
+       MSG_MAP(RunDcBtc,                            PPSMC_MSG_RunDcBtc),
        MSG_MAP(DramLogSetDramAddrHigh,              PPSMC_MSG_DramLogSetDramAddrHigh),
        MSG_MAP(DramLogSetDramAddrLow,               PPSMC_MSG_DramLogSetDramAddrLow),
        MSG_MAP(DramLogSetDramSize,                  PPSMC_MSG_DramLogSetDramSize),
@@ -528,9 +527,17 @@ static int arcturus_append_powerplay_table(struct smu_context *smu)
        return 0;
 }
 
-static int arcturus_run_btc_afll(struct smu_context *smu)
+static int arcturus_run_btc(struct smu_context *smu)
 {
-       return smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc);
+       int ret = 0;
+
+       ret = smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc);
+       if (ret) {
+               pr_err("RunAfllBtc failed!\n");
+               return ret;
+       }
+
+       return smu_send_smc_msg(smu, SMU_MSG_RunDcBtc);
 }
 
 static int arcturus_populate_umd_state_clk(struct smu_context *smu)
@@ -1891,6 +1898,35 @@ static bool arcturus_is_dpm_running(struct smu_context *smu)
        return !!(feature_enabled & SMC_DPM_FEATURE);
 }
 
+static int arcturus_dpm_set_uvd_enable(struct smu_context *smu, bool enable)
+{
+       struct smu_power_context *smu_power = &smu->smu_power;
+       struct smu_power_gate *power_gate = &smu_power->power_gate;
+       int ret = 0;
+
+       if (enable) {
+               if (!smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
+                       ret = smu_feature_set_enabled(smu, SMU_FEATURE_VCN_PG_BIT, 1);
+                       if (ret) {
+                               pr_err("[EnableVCNDPM] failed!\n");
+                               return ret;
+                       }
+               }
+               power_gate->vcn_gated = false;
+       } else {
+               if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
+                       ret = smu_feature_set_enabled(smu, SMU_FEATURE_VCN_PG_BIT, 0);
+                       if (ret) {
+                               pr_err("[DisableVCNDPM] failed!\n");
+                               return ret;
+                       }
+               }
+               power_gate->vcn_gated = true;
+       }
+
+       return ret;
+}
+
 static const struct pptable_funcs arcturus_ppt_funcs = {
        /* translate smu index into arcturus specific index */
        .get_smu_msg_index = arcturus_get_smu_msg_index,
@@ -1909,7 +1945,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
        /* init dpm */
        .get_allowed_feature_mask = arcturus_get_allowed_feature_mask,
        /* btc */
-       .run_afll_btc = arcturus_run_btc_afll,
+       .run_btc = arcturus_run_btc,
        /* dpm/clk tables */
        .set_default_dpm_table = arcturus_set_default_dpm_table,
        .populate_umd_state_clk = arcturus_populate_umd_state_clk,
@@ -1929,12 +1965,10 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
        .dump_pptable = arcturus_dump_pptable,
        .get_power_limit = arcturus_get_power_limit,
        .is_dpm_running = arcturus_is_dpm_running,
+       .dpm_set_uvd_enable = arcturus_dpm_set_uvd_enable,
 };
 
 void arcturus_set_ppt_funcs(struct smu_context *smu)
 {
-       struct smu_table_context *smu_table = &smu->smu_table;
-
        smu->ppt_funcs = &arcturus_ppt_funcs;
-       smu_table->table_count = TABLE_COUNT;
 }
index cc63705920dcd34d5e8ecf79ff15ef5c9d73eed0..2773966ae4342e90bf84a5b371b5812c2922e03e 100644 (file)
@@ -36,7 +36,8 @@ HARDWARE_MGR = hwmgr.o processpptables.o \
                pp_overdriver.o smu_helper.o \
                vega20_processpptables.o vega20_hwmgr.o vega20_powertune.o \
                vega20_thermal.o common_baco.o vega10_baco.o  vega20_baco.o \
-               vega12_baco.o smu9_baco.o
+               vega12_baco.o smu9_baco.o tonga_baco.o polaris_baco.o fiji_baco.o \
+               ci_baco.o smu7_baco.o
 
 AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR))
 
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.c b/drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.c
new file mode 100644 (file)
index 0000000..3be4011
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright 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) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "amdgpu.h"
+#include "ci_baco.h"
+
+#include "gmc/gmc_7_1_d.h"
+#include "gmc/gmc_7_1_sh_mask.h"
+
+#include "bif/bif_4_1_d.h"
+#include "bif/bif_4_1_sh_mask.h"
+
+#include "dce/dce_8_0_d.h"
+#include "dce/dce_8_0_sh_mask.h"
+
+#include "smu/smu_7_0_1_d.h"
+#include "smu/smu_7_0_1_sh_mask.h"
+
+#include "gca/gfx_7_2_d.h"
+#include "gca/gfx_7_2_sh_mask.h"
+
+static const struct baco_cmd_entry gpio_tbl[] =
+{
+       { CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff },
+       { CMD_WRITE, mmDC_GPIO_DVODATA_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmDC_GPIO_DVODATA_MASK, 0, 0, 0, 0xffffffff },
+       { CMD_WRITE, mmDC_GPIO_GENERIC_EN, 0, 0, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmDC_GPIO_GENERIC_MASK, 0, 0, 0, 0x03333333 },
+       { CMD_WRITE, mmDC_GPIO_SYNCA_EN, 0, 0, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmDC_GPIO_SYNCA_MASK, 0, 0, 0, 0x00001111 }
+};
+
+static const struct baco_cmd_entry enable_fb_req_rej_tbl[] =
+{
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0300024 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 },
+       { CMD_WRITE, mmBIF_FB_EN, 0, 0, 0, 0x0 }
+};
+
+static const struct baco_cmd_entry use_bclk_tbl[] =
+{
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS },
+       { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS },
+       { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 },
+       { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL_MASK, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL__SHIFT, 0, 0x1 },
+       { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_MCLK_SEL_MASK, MPLL_CNTL_MODE__MPLL_MCLK_SEL__SHIFT, 0, 0x0 }
+};
+
+static const struct baco_cmd_entry turn_off_plls_tbl[] =
+{
+       { CMD_READMODIFYWRITE, mmDISPPLL_BG_CNTL, DISPPLL_BG_CNTL__DISPPLL_BG_PDN_MASK, DISPPLL_BG_CNTL__DISPPLL_BG_PDN__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_DC },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_DC__OSC_EN_MASK, CG_CLKPIN_CNTL_DC__OSC_EN__SHIFT, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_DC__XTALIN_SEL_MASK, CG_CLKPIN_CNTL_DC__XTALIN_SEL__SHIFT, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmPLL_CNTL, PLL_CNTL__PLL_RESET_MASK, PLL_CNTL__PLL_RESET__SHIFT, 0, 0x1 },
+       { CMD_READMODIFYWRITE, mmPLL_CNTL, PLL_CNTL__PLL_POWER_DOWN_MASK, PLL_CNTL__PLL_POWER_DOWN__SHIFT, 0, 0x1 },
+       { CMD_READMODIFYWRITE, mmPLL_CNTL, PLL_CNTL__PLL_BYPASS_CAL_MASK, PLL_CNTL__PLL_BYPASS_CAL__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_RESET_MASK, CG_SPLL_FUNC_CNTL__SPLL_RESET__SHIFT, 0, 0x1 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_PWRON_MASK, CG_SPLL_FUNC_CNTL__SPLL_PWRON__SHIFT, 0, 0x0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x2000000, 0x19, 0, 0x1 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x8000000, 0x1b, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__GLOBAL_MPLL_RESET_MASK, MPLL_CNTL_MODE__GLOBAL_MPLL_RESET__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmMPLL_CONTROL, 0, 0, 0, 0x00000006 },
+       { CMD_WRITE, mmMC_IO_RXCNTL_DPHY0_D0, 0, 0, 0, 0x00007740 },
+       { CMD_WRITE, mmMC_IO_RXCNTL_DPHY0_D1, 0, 0, 0, 0x00007740 },
+       { CMD_WRITE, mmMC_IO_RXCNTL_DPHY1_D0, 0, 0, 0, 0x00007740 },
+       { CMD_WRITE, mmMC_IO_RXCNTL_DPHY1_D1, 0, 0, 0, 0x00007740 },
+       { CMD_READMODIFYWRITE, mmMCLK_PWRMGT_CNTL, MCLK_PWRMGT_CNTL__MRDCK0_PDNB_MASK, MCLK_PWRMGT_CNTL__MRDCK0_PDNB__SHIFT, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmMCLK_PWRMGT_CNTL, MCLK_PWRMGT_CNTL__MRDCK1_PDNB_MASK, MCLK_PWRMGT_CNTL__MRDCK1_PDNB__SHIFT, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmMC_SEQ_CNTL_2, MC_SEQ_CNTL_2__DRST_PU_MASK, MC_SEQ_CNTL_2__DRST_PU__SHIFT, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmMC_SEQ_CNTL_2, MC_SEQ_CNTL_2__DRST_PD_MASK, MC_SEQ_CNTL_2__DRST_PD__SHIFT, 0, 0x0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_2 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN_MASK, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN__SHIFT, 0, 0x0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x4 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMISC_CLK_CTRL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL_MASK, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL__SHIFT, 0, 0x2 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__ZCLK_SEL_MASK, MISC_CLK_CTRL__ZCLK_SEL__SHIFT, 0, 0x2 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DFT_SMS_PG_CLK_SEL_MASK, MISC_CLK_CTRL__DFT_SMS_PG_CLK_SEL__SHIFT, 0, 0x2 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixTHM_CLK_CNTL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__CMON_CLK_SEL_MASK, THM_CLK_CNTL__CMON_CLK_SEL__SHIFT, 0, 0x2 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__TMON_CLK_SEL_MASK, THM_CLK_CNTL__TMON_CLK_SEL__SHIFT, 0, 0x2 }
+};
+
+static const struct baco_cmd_entry enter_baco_tbl[] =
+{
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x01 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x01 },
+       { CMD_WAITFOR,         mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, 0, 5, 0x02 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR,         mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, 0, 5,  0x00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR,         mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, 0, 5, 0x00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x01 },
+       { CMD_WAITFOR,         mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, 0, 5, 0x08 },
+       { CMD_WAITFOR,         mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x40 }
+};
+
+#define BACO_CNTL__PWRGOOD_MASK  BACO_CNTL__PWRGOOD_GPIO_MASK+BACO_CNTL__PWRGOOD_MEM_MASK+BACO_CNTL__PWRGOOD_DVO_MASK
+
+static const struct baco_cmd_entry exit_baco_tbl[] =
+{
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK,           BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK,          BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 },
+       { CMD_DELAY_MS, 0, 0, 0, 20, 0 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x20 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x10 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 }
+};
+
+static const struct baco_cmd_entry clean_baco_tbl[] =
+{
+       { CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 },
+       { CMD_WRITE, mmCP_PFP_UCODE_ADDR, 0, 0, 0, 0 }
+};
+
+int ci_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state)
+{
+       enum BACO_STATE cur_state;
+
+       smu7_baco_get_state(hwmgr, &cur_state);
+
+       if (cur_state == state)
+               /* aisc already in the target state */
+               return 0;
+
+       if (state == BACO_STATE_IN) {
+               baco_program_registers(hwmgr, gpio_tbl, ARRAY_SIZE(gpio_tbl));
+               baco_program_registers(hwmgr, enable_fb_req_rej_tbl,
+                                      ARRAY_SIZE(enable_fb_req_rej_tbl));
+               baco_program_registers(hwmgr, use_bclk_tbl, ARRAY_SIZE(use_bclk_tbl));
+               baco_program_registers(hwmgr, turn_off_plls_tbl,
+                                      ARRAY_SIZE(turn_off_plls_tbl));
+               if (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 (baco_program_registers(hwmgr, exit_baco_tbl,
+                                          ARRAY_SIZE(exit_baco_tbl))) {
+                       if (baco_program_registers(hwmgr, clean_baco_tbl,
+                                                  ARRAY_SIZE(clean_baco_tbl)))
+                               return 0;
+               }
+       }
+
+       return -EINVAL;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.h
new file mode 100644 (file)
index 0000000..17041f1
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright 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) 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_BACO_H__
+#define __CI_BACO_H__
+#include "smu7_baco.h"
+
+extern int ci_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
+
+#endif
index 9c57c1f6774917a73971096d04ec56ca0fca9ced..1c73776bd606fdb3412925a49348c365e52f1dc6 100644 (file)
@@ -79,6 +79,25 @@ static bool baco_cmd_handler(struct pp_hwmgr *hwmgr, u32 command, u32 reg, u32 m
        return ret;
 }
 
+bool baco_program_registers(struct pp_hwmgr *hwmgr,
+                           const struct baco_cmd_entry *entry,
+                           const u32 array_size)
+{
+       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 = 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;
+}
+
 bool soc15_baco_program_registers(struct pp_hwmgr *hwmgr,
                                 const struct soc15_baco_cmd_entry *entry,
                                 const u32 array_size)
index 95296c916f4e9c1fd9bd86067a287424b0888e1a..8393eb62706d5bed21a6bfd0e503bd60e7b0a93f 100644 (file)
@@ -33,6 +33,15 @@ enum baco_cmd_type {
        CMD_DELAY_US,
 };
 
+struct baco_cmd_entry {
+       enum baco_cmd_type cmd;
+       uint32_t        reg_offset;
+       uint32_t        mask;
+       uint32_t        shift;
+       uint32_t        timeout;
+       uint32_t        val;
+};
+
 struct soc15_baco_cmd_entry {
        enum baco_cmd_type cmd;
        uint32_t        hwip;
@@ -44,6 +53,10 @@ struct soc15_baco_cmd_entry {
        uint32_t        timeout;
        uint32_t        val;
 };
+
+extern bool baco_program_registers(struct pp_hwmgr *hwmgr,
+                                  const struct baco_cmd_entry *entry,
+                                  const u32 array_size);
 extern bool soc15_baco_program_registers(struct pp_hwmgr *hwmgr,
                                        const struct soc15_baco_cmd_entry *entry,
                                        const u32 array_size);
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.c
new file mode 100644 (file)
index 0000000..c0368f2
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright 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) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "amdgpu.h"
+#include "fiji_baco.h"
+
+#include "gmc/gmc_8_1_d.h"
+#include "gmc/gmc_8_1_sh_mask.h"
+
+#include "bif/bif_5_0_d.h"
+#include "bif/bif_5_0_sh_mask.h"
+
+#include "dce/dce_10_0_d.h"
+#include "dce/dce_10_0_sh_mask.h"
+
+#include "smu/smu_7_1_3_d.h"
+#include "smu/smu_7_1_3_sh_mask.h"
+
+
+static const struct baco_cmd_entry gpio_tbl[] =
+{
+       { CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff },
+       { CMD_WRITE, mmDC_GPIO_DVODATA_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmDC_GPIO_DVODATA_MASK, 0, 0, 0, 0xffffffff },
+       { CMD_WRITE, mmDC_GPIO_GENERIC_EN, 0, 0, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmDC_GPIO_GENERIC_MASK, 0, 0, 0, 0x03333333 },
+       { CMD_WRITE, mmDC_GPIO_SYNCA_EN, 0, 0, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmDC_GPIO_SYNCA_MASK, 0, 0, 0, 0x00001111 }
+};
+
+static const struct baco_cmd_entry enable_fb_req_rej_tbl[] =
+{
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0300024 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 },
+       { CMD_WRITE, mmBIF_FB_EN, 0, 0, 0, 0x0 }
+};
+
+static const struct baco_cmd_entry use_bclk_tbl[] =
+{
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS },
+       { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0,  0x0 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0,  0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS },
+       { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 }
+};
+
+static const struct baco_cmd_entry turn_off_plls_tbl[] =
+{
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_RESET_MASK, CG_SPLL_FUNC_CNTL__SPLL_RESET__SHIFT, 0,     0x1 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_PWRON_MASK, CG_SPLL_FUNC_CNTL__SPLL_PWRON__SHIFT, 0,     0x0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x2000000, 0x19, 0, 0x1 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x8000000, 0x1b, 0, 0x0 }
+};
+
+static const struct baco_cmd_entry clk_req_b_tbl[] =
+{
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_2 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN_MASK, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN__SHIFT, 0, 0x0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x4 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMISC_CLK_CTRL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL_MASK, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL__SHIFT, 0, 0x1 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__ZCLK_SEL_MASK, MISC_CLK_CTRL__ZCLK_SEL__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL__BCLK_AS_XCLK_MASK, CG_CLKPIN_CNTL__BCLK_AS_XCLK__SHIFT, 0, 0x0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixTHM_CLK_CNTL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__CMON_CLK_SEL_MASK, THM_CLK_CNTL__CMON_CLK_SEL__SHIFT, 0, 0x1 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__TMON_CLK_SEL_MASK, THM_CLK_CNTL__TMON_CLK_SEL__SHIFT, 0, 0x1 }
+};
+
+static const struct baco_cmd_entry enter_baco_tbl[] =
+{
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x01 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x01 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, 0, 5, 0x40000 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x01 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, 0, 5, 0x02 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, 0, 5, 0x00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, 0, 5, 0x00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x01 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, 0, 5, 0x08 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x40 }
+};
+
+#define BACO_CNTL__PWRGOOD_MASK  BACO_CNTL__PWRGOOD_GPIO_MASK+BACO_CNTL__PWRGOOD_MEM_MASK+BACO_CNTL__PWRGOOD_DVO_MASK
+
+static const struct baco_cmd_entry exit_baco_tbl[] =
+{
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 }
+};
+
+static const struct baco_cmd_entry clean_baco_tbl[] =
+{
+       { CMD_WRITE, mmBIOS_SCRATCH_0, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_1, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_2, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_3, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_4, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_5, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_8, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_9, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_10, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_11, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_12, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_13, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_14, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_15, 0, 0, 0, 0 }
+};
+
+int fiji_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state)
+{
+       enum BACO_STATE cur_state;
+
+       smu7_baco_get_state(hwmgr, &cur_state);
+
+       if (cur_state == state)
+               /* aisc already in the target state */
+               return 0;
+
+       if (state == BACO_STATE_IN) {
+               baco_program_registers(hwmgr, gpio_tbl, ARRAY_SIZE(gpio_tbl));
+               baco_program_registers(hwmgr, enable_fb_req_rej_tbl,
+                                      ARRAY_SIZE(enable_fb_req_rej_tbl));
+               baco_program_registers(hwmgr, use_bclk_tbl, ARRAY_SIZE(use_bclk_tbl));
+               baco_program_registers(hwmgr, turn_off_plls_tbl,
+                                      ARRAY_SIZE(turn_off_plls_tbl));
+               baco_program_registers(hwmgr, clk_req_b_tbl, ARRAY_SIZE(clk_req_b_tbl));
+               if (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 (baco_program_registers(hwmgr, exit_baco_tbl,
+                                          ARRAY_SIZE(exit_baco_tbl))) {
+                       if (baco_program_registers(hwmgr, clean_baco_tbl,
+                                                  ARRAY_SIZE(clean_baco_tbl)))
+                               return 0;
+               }
+       }
+
+       return -EINVAL;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.h b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.h
new file mode 100644 (file)
index 0000000..47f4029
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright 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) 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 __FIJI_BACO_H__
+#define __FIJI_BACO_H__
+#include "smu7_baco.h"
+
+extern int fiji_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
+
+#endif
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.c b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.c
new file mode 100644 (file)
index 0000000..8f8e296
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * Copyright 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) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "amdgpu.h"
+#include "polaris_baco.h"
+
+#include "gmc/gmc_8_1_d.h"
+#include "gmc/gmc_8_1_sh_mask.h"
+
+#include "bif/bif_5_0_d.h"
+#include "bif/bif_5_0_sh_mask.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "smu/smu_7_1_3_d.h"
+#include "smu/smu_7_1_3_sh_mask.h"
+
+static const struct baco_cmd_entry gpio_tbl[] =
+{
+       { CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff },
+       { CMD_WRITE, mmDC_GPIO_DVODATA_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmDC_GPIO_DVODATA_MASK, 0, 0, 0, 0xffffffff },
+       { CMD_WRITE, mmDC_GPIO_GENERIC_EN, 0, 0, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmDC_GPIO_GENERIC_MASK, 0, 0, 0, 0x03333333 },
+       { CMD_WRITE, mmDC_GPIO_SYNCA_EN, 0, 0, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmDC_GPIO_SYNCA_MASK, 0, 0, 0, 0x00001111 }
+};
+
+static const struct baco_cmd_entry enable_fb_req_rej_tbl[] =
+{
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0300024 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 },
+       { CMD_WRITE, mmBIF_FB_EN, 0, 0, 0, 0x0 }
+};
+
+static const struct baco_cmd_entry use_bclk_tbl[] =
+{
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixGCK_DFS_BYPASS_CNTL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, GCK_DFS_BYPASS_CNTL__BYPASSACLK_MASK, GCK_DFS_BYPASS_CNTL__BYPASSACLK__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 },
+       { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL_MASK, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL__SHIFT, 0, 0x1 },
+       { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_MCLK_SEL_MASK, MPLL_CNTL_MODE__MPLL_MCLK_SEL__SHIFT, 0, 0x0 }
+};
+
+static const struct baco_cmd_entry turn_off_plls_tbl[] =
+{
+       { CMD_READMODIFYWRITE, mmDC_GPIO_PAD_STRENGTH_1, DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP_MASK, DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP__SHIFT, 0, 0x1 },
+       { CMD_DELAY_US, 0, 0, 0, 1, 0x0 },
+       { CMD_READMODIFYWRITE, mmMC_SEQ_DRAM, MC_SEQ_DRAM__RST_CTL_MASK, MC_SEQ_DRAM__RST_CTL__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC05002B0 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x10, 0x4, 0, 0x1 },
+       { CMD_WAITFOR, mmGCK_SMC_IND_DATA, 0x10, 0, 1, 0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC050032C },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x10, 0x4, 0, 0x1 },
+       { CMD_WAITFOR, mmGCK_SMC_IND_DATA, 0x10, 0, 1, 0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500080 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 },
+       { CMD_READMODIFYWRITE, 0xda2, 0x40, 0x6, 0, 0x0 },
+       { CMD_DELAY_US, 0, 0, 0, 3, 0x0 },
+       { CMD_READMODIFYWRITE, 0xda2, 0x8, 0x3, 0, 0x0 },
+       { CMD_READMODIFYWRITE, 0xda2, 0x3fff00, 0x8, 0, 0x32 },
+       { CMD_DELAY_US, 0, 0, 0, 3, 0x0 },
+       { CMD_READMODIFYWRITE, mmMPLL_FUNC_CNTL_2, MPLL_FUNC_CNTL_2__ISO_DIS_P_MASK, MPLL_FUNC_CNTL_2__ISO_DIS_P__SHIFT, 0, 0x0 },
+       { CMD_DELAY_US, 0, 0, 0, 5, 0x0 }
+};
+
+static const struct baco_cmd_entry clk_req_b_tbl[] =
+{
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixTHM_CLK_CNTL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__CMON_CLK_SEL_MASK, THM_CLK_CNTL__CMON_CLK_SEL__SHIFT, 0, 0x1 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__TMON_CLK_SEL_MASK, THM_CLK_CNTL__TMON_CLK_SEL__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMISC_CLK_CTRL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL_MASK, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL__SHIFT, 0, 0x1 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__ZCLK_SEL_MASK, MISC_CLK_CTRL__ZCLK_SEL__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL__BCLK_AS_XCLK_MASK, CG_CLKPIN_CNTL__BCLK_AS_XCLK__SHIFT, 0, 0x0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_2 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN_MASK, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN__SHIFT, 0, 0x0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0,     0x4 }
+};
+
+static const struct baco_cmd_entry enter_baco_tbl[] =
+{
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x01 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x01 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, 0, 5, 0x40000 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x01 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, 0, 5, 0x02 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, 0, 5, 0x00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, 0, 5, 0x00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x01 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, 0, 5, 0x08 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x40 }
+};
+
+#define BACO_CNTL__PWRGOOD_MASK  BACO_CNTL__PWRGOOD_GPIO_MASK+BACO_CNTL__PWRGOOD_MEM_MASK+BACO_CNTL__PWRGOOD_DVO_MASK
+
+static const struct baco_cmd_entry exit_baco_tbl[] =
+{
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 }
+};
+
+static const struct baco_cmd_entry clean_baco_tbl[] =
+{
+       { CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 }
+};
+
+static const struct baco_cmd_entry use_bclk_tbl_vg[] =
+{
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixGCK_DFS_BYPASS_CNTL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, GCK_DFS_BYPASS_CNTL__BYPASSACLK_MASK, GCK_DFS_BYPASS_CNTL__BYPASSACLK__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 }
+};
+
+static const struct baco_cmd_entry turn_off_plls_tbl_vg[] =
+{
+       { CMD_READMODIFYWRITE, mmDC_GPIO_PAD_STRENGTH_1, DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP_MASK, DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP__SHIFT, 0, 0x1 },
+       { CMD_DELAY_US, 0, 0, 0, 1, 0x0 },
+       { CMD_READMODIFYWRITE, mmMC_SEQ_DRAM, MC_SEQ_DRAM__RST_CTL_MASK, MC_SEQ_DRAM__RST_CTL__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC05002B0 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x10, 0x4, 0, 0x1 },
+       { CMD_WAITFOR, mmGCK_SMC_IND_DATA, 0x10, 0, 1, 0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC050032C },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x10, 0x4, 0, 0x1 },
+       { CMD_WAITFOR, mmGCK_SMC_IND_DATA, 0x10, 0, 1, 0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500080 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 },
+       { CMD_DELAY_US, 0, 0, 0, 3, 0x0 },
+       { CMD_DELAY_US, 0, 0, 0, 3, 0x0 },
+       { CMD_DELAY_US, 0, 0, 0, 5, 0x0 }
+};
+
+int polaris_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state)
+{
+       enum BACO_STATE cur_state;
+
+       smu7_baco_get_state(hwmgr, &cur_state);
+
+       if (cur_state == state)
+               /* aisc already in the target state */
+               return 0;
+
+       if (state == BACO_STATE_IN) {
+               baco_program_registers(hwmgr, gpio_tbl, ARRAY_SIZE(gpio_tbl));
+               baco_program_registers(hwmgr, enable_fb_req_rej_tbl,
+                                      ARRAY_SIZE(enable_fb_req_rej_tbl));
+               if (hwmgr->chip_id == CHIP_VEGAM) {
+                       baco_program_registers(hwmgr, use_bclk_tbl_vg, ARRAY_SIZE(use_bclk_tbl_vg));
+                       baco_program_registers(hwmgr, turn_off_plls_tbl_vg,
+                                              ARRAY_SIZE(turn_off_plls_tbl_vg));
+               } else {
+                       baco_program_registers(hwmgr, use_bclk_tbl, ARRAY_SIZE(use_bclk_tbl));
+                       baco_program_registers(hwmgr, turn_off_plls_tbl,
+                                              ARRAY_SIZE(turn_off_plls_tbl));
+               }
+               baco_program_registers(hwmgr, clk_req_b_tbl, ARRAY_SIZE(clk_req_b_tbl));
+               if (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 (baco_program_registers(hwmgr, exit_baco_tbl,
+                                          ARRAY_SIZE(exit_baco_tbl))) {
+                       if (baco_program_registers(hwmgr, clean_baco_tbl,
+                                                  ARRAY_SIZE(clean_baco_tbl)))
+                               return 0;
+               }
+       }
+
+       return -EINVAL;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.h b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.h
new file mode 100644 (file)
index 0000000..87a5fa0
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright 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) 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 __POLARIS_BACO_H__
+#define __POLARIS_BACO_H__
+#include "smu7_baco.h"
+
+extern int polaris_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
+
+#endif
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.c
new file mode 100644 (file)
index 0000000..044cda0
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright 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) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "amdgpu.h"
+#include "smu7_baco.h"
+#include "tonga_baco.h"
+#include "fiji_baco.h"
+#include "polaris_baco.h"
+#include "ci_baco.h"
+
+#include "bif/bif_5_0_d.h"
+#include "bif/bif_5_0_sh_mask.h"
+
+#include "smu/smu_7_1_2_d.h"
+#include "smu/smu_7_1_2_sh_mask.h"
+
+int smu7_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;
+
+       reg = RREG32(mmCC_BIF_BX_FUSESTRAP0);
+
+       if (reg & CC_BIF_BX_FUSESTRAP0__STRAP_BIF_PX_CAPABLE_MASK)
+               *cap = true;
+
+       return 0;
+}
+
+int smu7_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(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 smu7_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
+
+       switch (adev->asic_type) {
+       case CHIP_TOPAZ:
+       case CHIP_TONGA:
+               return tonga_baco_set_state(hwmgr, state);
+       case CHIP_FIJI:
+               return fiji_baco_set_state(hwmgr, state);
+       case CHIP_POLARIS10:
+       case CHIP_POLARIS11:
+       case CHIP_POLARIS12:
+       case CHIP_VEGAM:
+               return polaris_baco_set_state(hwmgr, state);
+#ifdef CONFIG_DRM_AMDGPU_CIK
+       case CHIP_BONAIRE:
+       case CHIP_HAWAII:
+               return ci_baco_set_state(hwmgr, state);
+#endif
+       default:
+               return -EINVAL;
+       }
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.h
new file mode 100644 (file)
index 0000000..be0d98a
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright 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) 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 __SMU7_BACO_H__
+#define __SMU7_BACO_H__
+#include "hwmgr.h"
+#include "common_baco.h"
+
+extern int smu7_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap);
+extern int smu7_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state);
+extern int smu7_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
+
+#endif
index 34f95e0e3ea45a32a89fe55b343d5c49fdedeed7..c805c6fcdba202f8dc14acd1420a059d2dbc1253 100644 (file)
@@ -48,6 +48,7 @@
 #include "smu7_clockpowergating.h"
 #include "processpptables.h"
 #include "pp_thermal.h"
+#include "smu7_baco.h"
 
 #include "ivsrcid/ivsrcid_vislands30.h"
 
@@ -1994,7 +1995,6 @@ static int smu7_sort_lookup_table(struct pp_hwmgr *hwmgr,
                struct phm_ppt_v1_voltage_lookup_table *lookup_table)
 {
        uint32_t table_size, i, j;
-       struct phm_ppt_v1_voltage_lookup_record tmp_voltage_lookup_record;
        table_size = lookup_table->count;
 
        PP_ASSERT_WITH_CODE(0 != lookup_table->count,
@@ -2005,9 +2005,8 @@ static int smu7_sort_lookup_table(struct pp_hwmgr *hwmgr,
                for (j = i + 1; j > 0; j--) {
                        if (lookup_table->entries[j].us_vdd <
                                        lookup_table->entries[j - 1].us_vdd) {
-                               tmp_voltage_lookup_record = lookup_table->entries[j - 1];
-                               lookup_table->entries[j - 1] = lookup_table->entries[j];
-                               lookup_table->entries[j] = tmp_voltage_lookup_record;
+                               swap(lookup_table->entries[j - 1],
+                                    lookup_table->entries[j]);
                        }
                }
        }
@@ -5145,6 +5144,9 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = {
        .get_power_profile_mode = smu7_get_power_profile_mode,
        .set_power_profile_mode = smu7_set_power_profile_mode,
        .get_performance_level = smu7_get_performance_level,
+       .get_asic_baco_capability = smu7_baco_get_capability,
+       .get_asic_baco_state = smu7_baco_get_state,
+       .set_asic_baco_state = smu7_baco_set_state,
        .power_off_asic = smu7_power_off_asic,
 };
 
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.c
new file mode 100644 (file)
index 0000000..ea743be
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright 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) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "amdgpu.h"
+#include "tonga_baco.h"
+
+#include "gmc/gmc_8_1_d.h"
+#include "gmc/gmc_8_1_sh_mask.h"
+
+#include "bif/bif_5_0_d.h"
+#include "bif/bif_5_0_sh_mask.h"
+
+#include "dce/dce_10_0_d.h"
+#include "dce/dce_10_0_sh_mask.h"
+
+#include "smu/smu_7_1_2_d.h"
+#include "smu/smu_7_1_2_sh_mask.h"
+
+
+static const struct baco_cmd_entry gpio_tbl[] =
+{
+       { CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff },
+       { CMD_WRITE, mmDC_GPIO_DVODATA_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmDC_GPIO_DVODATA_MASK, 0, 0, 0, 0xffffffff },
+       { CMD_WRITE, mmDC_GPIO_GENERIC_EN, 0, 0, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmDC_GPIO_GENERIC_MASK, 0, 0, 0, 0x03333333 },
+       { CMD_WRITE, mmDC_GPIO_SYNCA_EN, 0, 0, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmDC_GPIO_SYNCA_MASK, 0, 0, 0, 0x00001111 }
+};
+
+static const struct baco_cmd_entry enable_fb_req_rej_tbl[] =
+{
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0300024 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 },
+       { CMD_WRITE, mmBIF_FB_EN, 0, 0, 0, 0x0 }
+};
+
+static const struct baco_cmd_entry use_bclk_tbl[] =
+{
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS },
+       { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS },
+       { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 },
+       { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL_MASK, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL__SHIFT, 0, 0x1 },
+       { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_MCLK_SEL_MASK, MPLL_CNTL_MODE__MPLL_MCLK_SEL__SHIFT, 0, 0x0 }
+};
+
+static const struct baco_cmd_entry turn_off_plls_tbl[] =
+{
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_RESET_MASK, CG_SPLL_FUNC_CNTL__SPLL_RESET__SHIFT, 0, 0x1 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_PWRON_MASK, CG_SPLL_FUNC_CNTL__SPLL_PWRON__SHIFT, 0, 0x0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x2000000, 0x19, 0, 0x1 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x8000000, 0x1b, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__GLOBAL_MPLL_RESET_MASK, MPLL_CNTL_MODE__GLOBAL_MPLL_RESET__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmMPLL_CONTROL, 0, 0, 0, 0x00000006 },
+       { CMD_WRITE, mmMC_IO_RXCNTL_DPHY0_D0, 0, 0, 0, 0x00007740 },
+       { CMD_WRITE, mmMC_IO_RXCNTL_DPHY0_D1, 0, 0, 0, 0x00007740 },
+       { CMD_WRITE, mmMC_IO_RXCNTL_DPHY1_D0, 0, 0, 0, 0x00007740 },
+       { CMD_WRITE, mmMC_IO_RXCNTL_DPHY1_D1, 0, 0, 0, 0x00007740 },
+       { CMD_READMODIFYWRITE, mmMCLK_PWRMGT_CNTL, MCLK_PWRMGT_CNTL__MRDCK0_PDNB_MASK, MCLK_PWRMGT_CNTL__MRDCK0_PDNB__SHIFT, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmMCLK_PWRMGT_CNTL, MCLK_PWRMGT_CNTL__MRDCK1_PDNB_MASK, MCLK_PWRMGT_CNTL__MRDCK1_PDNB__SHIFT, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmMC_SEQ_CNTL_2, MC_SEQ_CNTL_2__DRST_PU_MASK, MC_SEQ_CNTL_2__DRST_PU__SHIFT, 0, 0x0 },
+       { CMD_READMODIFYWRITE, mmMC_SEQ_CNTL_2, MC_SEQ_CNTL_2__DRST_PD_MASK, MC_SEQ_CNTL_2__DRST_PD__SHIFT, 0, 0x0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_2 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN_MASK, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN__SHIFT, 0, 0x0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x4 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMISC_CLK_CTRL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL_MASK, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL__SHIFT, 0, 0x1 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__ZCLK_SEL_MASK, MISC_CLK_CTRL__ZCLK_SEL__SHIFT, 0, 0x1 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL__BCLK_AS_XCLK_MASK, CG_CLKPIN_CNTL__BCLK_AS_XCLK__SHIFT, 0, 0x0 },
+       { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixTHM_CLK_CNTL },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__CMON_CLK_SEL_MASK,  THM_CLK_CNTL__CMON_CLK_SEL__SHIFT, 0, 0x1 },
+       { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__TMON_CLK_SEL_MASK,  THM_CLK_CNTL__TMON_CLK_SEL__SHIFT, 0, 0x1 }
+};
+
+static const struct baco_cmd_entry enter_baco_tbl[] =
+{
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x01 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x01 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, 0, 5, 0x40000 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x01 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, 0, 5, 0x02 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, 0, 5, 0x00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, 0, 5, 0x00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x01 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, 0, 5, 0x08 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x40 }
+};
+
+#define BACO_CNTL__PWRGOOD_MASK  BACO_CNTL__PWRGOOD_GPIO_MASK+BACO_CNTL__PWRGOOD_MEM_MASK+BACO_CNTL__PWRGOOD_DVO_MASK
+
+static const struct baco_cmd_entry exit_baco_tbl[] =
+{
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 }
+};
+
+static const struct baco_cmd_entry clean_baco_tbl[] =
+{
+       { CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 },
+       { CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 }
+};
+
+static const struct baco_cmd_entry gpio_tbl_iceland[] =
+{
+       { CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 },
+       { CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff }
+};
+
+static const struct baco_cmd_entry exit_baco_tbl_iceland[] =
+{
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 },
+       { CMD_DELAY_MS, 0, 0, 0, 20, 0 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x00 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 },
+       { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 },
+       { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 }
+};
+
+static const struct baco_cmd_entry clean_baco_tbl_iceland[] =
+{
+       { CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 }
+};
+
+int tonga_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state)
+{
+       enum BACO_STATE cur_state;
+
+       smu7_baco_get_state(hwmgr, &cur_state);
+
+       if (cur_state == state)
+               /* aisc already in the target state */
+               return 0;
+
+       if (state == BACO_STATE_IN) {
+               if (hwmgr->chip_id == CHIP_TOPAZ)
+                       baco_program_registers(hwmgr, gpio_tbl_iceland, ARRAY_SIZE(gpio_tbl_iceland));
+               else
+                       baco_program_registers(hwmgr, gpio_tbl, ARRAY_SIZE(gpio_tbl));
+               baco_program_registers(hwmgr, enable_fb_req_rej_tbl,
+                                      ARRAY_SIZE(enable_fb_req_rej_tbl));
+               baco_program_registers(hwmgr, use_bclk_tbl, ARRAY_SIZE(use_bclk_tbl));
+               baco_program_registers(hwmgr, turn_off_plls_tbl,
+                                      ARRAY_SIZE(turn_off_plls_tbl));
+               if (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 (hwmgr->chip_id == CHIP_TOPAZ) {
+                       if (baco_program_registers(hwmgr, exit_baco_tbl_iceland,
+                                                  ARRAY_SIZE(exit_baco_tbl_iceland))) {
+                               if (baco_program_registers(hwmgr, clean_baco_tbl_iceland,
+                                                          ARRAY_SIZE(clean_baco_tbl_iceland)))
+                                       return 0;
+                       }
+               } else {
+                       if (baco_program_registers(hwmgr, exit_baco_tbl,
+                                                  ARRAY_SIZE(exit_baco_tbl))) {
+                               if (baco_program_registers(hwmgr, clean_baco_tbl,
+                                                          ARRAY_SIZE(clean_baco_tbl)))
+                                       return 0;
+                       }
+               }
+       }
+
+       return -EINVAL;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.h
new file mode 100644 (file)
index 0000000..5dc16cc
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright 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) 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 __TONGA_BACO_H__
+#define __TONGA_BACO_H__
+#include "smu7_baco.h"
+
+extern int tonga_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
+
+#endif
index d08493b67b67d1d2d67985777ea7003c29593fb6..f5dcba44f74a0168fa48110fc2ad9f13cf0eaa7b 100644 (file)
@@ -712,7 +712,6 @@ static int vega10_sort_lookup_table(struct pp_hwmgr *hwmgr,
                struct phm_ppt_v1_voltage_lookup_table *lookup_table)
 {
        uint32_t table_size, i, j;
-       struct phm_ppt_v1_voltage_lookup_record tmp_voltage_lookup_record;
 
        PP_ASSERT_WITH_CODE(lookup_table && lookup_table->count,
                "Lookup table is empty", return -EINVAL);
@@ -724,9 +723,8 @@ static int vega10_sort_lookup_table(struct pp_hwmgr *hwmgr,
                for (j = i + 1; j > 0; j--) {
                        if (lookup_table->entries[j].us_vdd <
                                        lookup_table->entries[j - 1].us_vdd) {
-                               tmp_voltage_lookup_record = lookup_table->entries[j - 1];
-                               lookup_table->entries[j - 1] = lookup_table->entries[j];
-                               lookup_table->entries[j] = tmp_voltage_lookup_record;
+                               swap(lookup_table->entries[j - 1],
+                                    lookup_table->entries[j]);
                        }
                }
        }
index df6ff92524011d9480149c26c4466f9bd69a9374..9b5e72bdceca5ad1c8dd10285128bc00d811af31 100644 (file)
@@ -29,7 +29,7 @@
 #include "vega20_baco.h"
 #include "vega20_smumgr.h"
 
-
+#include "amdgpu_ras.h"
 
 static const struct soc15_baco_cmd_entry clean_baco_tbl[] =
 {
@@ -74,6 +74,7 @@ int vega20_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state)
 int vega20_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
+       struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
        enum BACO_STATE cur_state;
        uint32_t data;
 
@@ -84,13 +85,19 @@ int vega20_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE 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 -EINVAL;
+               if (!ras || !ras->supported) {
+                       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 -EINVAL;
+               } else {
+                       if(smum_send_msg_to_smc_with_parameter(hwmgr,
+                                       PPSMC_MSG_EnterBaco, 1))
+                               return -EINVAL;
+               }
 
        } else if (state == BACO_STATE_OUT) {
                if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ExitBaco))
index f5915308e643a896233e8cb60783d52afb3e82a7..9295bd90b792271e14e38bf3e86312486eeacaf5 100644 (file)
@@ -182,6 +182,9 @@ static int vega20_set_features_platform_caps(struct pp_hwmgr *hwmgr)
        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
                        PHM_PlatformCaps_TablelessHardwareInterface);
 
+       phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+                       PHM_PlatformCaps_BACO);
+
        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
                        PHM_PlatformCaps_EnableSMU7ThermalManagement);
 
@@ -490,8 +493,8 @@ static int vega20_setup_asic_task(struct pp_hwmgr *hwmgr)
                        "Failed to init sclk threshold!",
                        return ret);
 
-       if (adev->in_baco_reset) {
-               adev->in_baco_reset = 0;
+       if (adev->in_gpu_reset &&
+           (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) {
 
                ret = vega20_baco_apply_vdci_flush_workaround(hwmgr);
                if (ret)
@@ -4155,6 +4158,24 @@ static int vega20_smu_i2c_bus_access(struct pp_hwmgr *hwmgr, bool acquire)
        return res;
 }
 
+static int vega20_set_df_cstate(struct pp_hwmgr *hwmgr,
+                               enum pp_df_cstate state)
+{
+       int ret;
+
+       /* PPSMC_MSG_DFCstateControl is supported with 40.50 and later fws */
+       if (hwmgr->smu_version < 0x283200) {
+               pr_err("Df cstate control is supported with 40.50 and later SMC fw!\n");
+               return -EINVAL;
+       }
+
+       ret = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DFCstateControl, state);
+       if (ret)
+               pr_err("SetDfCstate failed!\n");
+
+       return ret;
+}
+
 static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
        /* init/fini related */
        .backend_init = vega20_hwmgr_backend_init,
@@ -4223,6 +4244,7 @@ static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
        .set_asic_baco_state = vega20_baco_set_state,
        .set_mp1_state = vega20_set_mp1_state,
        .smu_i2c_bus_access = vega20_smu_i2c_bus_access,
+       .set_df_cstate = vega20_set_df_cstate,
 };
 
 int vega20_hwmgr_init(struct pp_hwmgr *hwmgr)
index 23171a4d9a31cfed921873f504f629580bb3ac38..49f1caa7b1c5c5d74c11aeb8d25ee906fe1975e4 100644 (file)
@@ -259,7 +259,6 @@ struct smu_table_context
        struct smu_bios_boot_up_values  boot_values;
        void                            *driver_pptable;
        struct smu_table                *tables;
-       uint32_t                        table_count;
        struct smu_table                memory_pool;
        uint8_t                         thermal_controller_type;
        uint16_t                        TDPODLimit;
@@ -322,6 +321,13 @@ struct mclock_latency_table {
        struct mclk_latency_entries  entries[MAX_REGULAR_DPM_NUM];
 };
 
+enum smu_reset_mode
+{
+    SMU_RESET_MODE_0,
+    SMU_RESET_MODE_1,
+    SMU_RESET_MODE_2,
+};
+
 enum smu_baco_state
 {
        SMU_BACO_STATE_ENTER = 0,
@@ -382,6 +388,7 @@ struct smu_context
        uint32_t power_profile_mode;
        uint32_t default_power_profile_mode;
        bool pm_enabled;
+       bool is_apu;
 
        uint32_t smc_if_version;
 
@@ -398,7 +405,7 @@ struct pptable_funcs {
        int (*get_smu_table_index)(struct smu_context *smu, uint32_t index);
        int (*get_smu_power_index)(struct smu_context *smu, uint32_t index);
        int (*get_workload_type)(struct smu_context *smu, enum PP_SMC_POWER_PROFILE profile);
-       int (*run_afll_btc)(struct smu_context *smu);
+       int (*run_btc)(struct smu_context *smu);
        int (*get_allowed_feature_mask)(struct smu_context *smu, uint32_t *feature_mask, uint32_t num);
        enum amd_pm_state_type (*get_current_power_state)(struct smu_context *smu);
        int (*set_default_dpm_table)(struct smu_context *smu);
@@ -459,7 +466,11 @@ struct pptable_funcs {
        int (*display_disable_memory_clock_switch)(struct smu_context *smu, bool disable_memory_clock_switch);
        void (*dump_pptable)(struct smu_context *smu);
        int (*get_power_limit)(struct smu_context *smu, uint32_t *limit, bool asic_default);
-       int (*get_dpm_uclk_limited)(struct smu_context *smu, uint32_t *clock, bool max);
+       int (*get_dpm_clk_limited)(struct smu_context *smu, enum smu_clk_type clk_type,
+                                  uint32_t dpm_level, uint32_t *freq);
+       int (*set_df_cstate)(struct smu_context *smu, enum pp_df_cstate state);
+       int (*update_pcie_parameters)(struct smu_context *smu, uint32_t pcie_gen_cap, uint32_t pcie_width_cap);
+       int (*get_dpm_clock_table)(struct smu_context *smu, struct dpm_clocks *clock_table);
 };
 
 struct smu_funcs
@@ -485,7 +496,6 @@ struct smu_funcs
        int (*set_min_dcef_deep_sleep)(struct smu_context *smu);
        int (*set_tool_table_location)(struct smu_context *smu);
        int (*notify_memory_pool_location)(struct smu_context *smu);
-       int (*write_watermarks_table)(struct smu_context *smu);
        int (*set_last_dcef_min_deep_sleep_clk)(struct smu_context *smu);
        int (*system_features_control)(struct smu_context *smu, bool en);
        int (*send_smc_msg)(struct smu_context *smu, uint16_t msg);
@@ -499,6 +509,7 @@ struct smu_funcs
        int (*get_current_clk_freq)(struct smu_context *smu, enum smu_clk_type clk_id, uint32_t *value);
        int (*init_max_sustainable_clocks)(struct smu_context *smu);
        int (*start_thermal_control)(struct smu_context *smu);
+       int (*stop_thermal_control)(struct smu_context *smu);
        int (*read_sensor)(struct smu_context *smu, enum amd_pp_sensors sensor,
                           void *data, uint32_t *size);
        int (*set_deep_sleep_dcefclk)(struct smu_context *smu, uint32_t clk);
@@ -522,8 +533,6 @@ struct smu_funcs
        int (*get_current_shallow_sleep_clocks)(struct smu_context *smu,
                                                struct smu_clock_info *clocks);
        int (*notify_smu_enable_pwe)(struct smu_context *smu);
-       int (*set_watermarks_for_clock_ranges)(struct smu_context *smu,
-                                              struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges);
        int (*conv_power_profile_to_pplib_workload)(int power_profile);
        uint32_t (*get_fan_control_mode)(struct smu_context *smu);
        int (*set_fan_control_mode)(struct smu_context *smu, uint32_t mode);
@@ -538,7 +547,10 @@ struct smu_funcs
        enum smu_baco_state (*baco_get_state)(struct smu_context *smu);
        int (*baco_set_state)(struct smu_context *smu, enum smu_baco_state state);
        int (*baco_reset)(struct smu_context *smu);
+       int (*mode2_reset)(struct smu_context *smu);
        int (*get_dpm_ultimate_freq)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t *min, uint32_t *max);
+       int (*set_soft_freq_limited_range)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t min, uint32_t max);
+       int (*override_pcie_parameters)(struct smu_context *smu);
 };
 
 #define smu_init_microcode(smu) \
@@ -585,9 +597,6 @@ struct smu_funcs
        ((smu)->funcs->notify_memory_pool_location ? (smu)->funcs->notify_memory_pool_location((smu)) : 0)
 #define smu_gfx_off_control(smu, enable) \
        ((smu)->funcs->gfx_off_control ? (smu)->funcs->gfx_off_control((smu), (enable)) : 0)
-
-#define smu_write_watermarks_table(smu) \
-       ((smu)->funcs->write_watermarks_table ? (smu)->funcs->write_watermarks_table((smu)) : 0)
 #define smu_set_last_dcef_min_deep_sleep_clk(smu) \
        ((smu)->funcs->set_last_dcef_min_deep_sleep_clk ? (smu)->funcs->set_last_dcef_min_deep_sleep_clk((smu)) : 0)
 #define smu_system_features_control(smu, en) \
@@ -636,8 +645,6 @@ struct smu_funcs
        ((smu)->funcs->get_current_clk_freq? (smu)->funcs->get_current_clk_freq((smu), (clk_id), (value)) : 0)
 #define smu_print_clk_levels(smu, clk_type, buf) \
        ((smu)->ppt_funcs->print_clk_levels ? (smu)->ppt_funcs->print_clk_levels((smu), (clk_type), (buf)) : 0)
-#define smu_force_clk_levels(smu, clk_type, level) \
-       ((smu)->ppt_funcs->force_clk_levels ? (smu)->ppt_funcs->force_clk_levels((smu), (clk_type), (level)) : 0)
 #define smu_get_od_percentage(smu, type) \
        ((smu)->ppt_funcs->get_od_percentage ? (smu)->ppt_funcs->get_od_percentage((smu), (type)) : 0)
 #define smu_set_od_percentage(smu, type, value) \
@@ -650,6 +657,8 @@ struct smu_funcs
        ((smu)->ppt_funcs->set_thermal_fan_table ? (smu)->ppt_funcs->set_thermal_fan_table((smu)) : 0)
 #define smu_start_thermal_control(smu) \
        ((smu)->funcs->start_thermal_control? (smu)->funcs->start_thermal_control((smu)) : 0)
+#define smu_stop_thermal_control(smu) \
+       ((smu)->funcs->stop_thermal_control? (smu)->funcs->stop_thermal_control((smu)) : 0)
 #define smu_read_sensor(smu, sensor, data, size) \
        ((smu)->ppt_funcs->read_sensor? (smu)->ppt_funcs->read_sensor((smu), (sensor), (data), (size)) : 0)
 #define smu_smc_read_sensor(smu, sensor, data, size) \
@@ -697,8 +706,8 @@ struct smu_funcs
        ((smu)->ppt_funcs? ((smu)->ppt_funcs->get_smu_power_index? (smu)->ppt_funcs->get_smu_power_index((smu), (src)) : -EINVAL) : -EINVAL)
 #define smu_workload_get_type(smu, profile) \
        ((smu)->ppt_funcs? ((smu)->ppt_funcs->get_workload_type? (smu)->ppt_funcs->get_workload_type((smu), (profile)) : -EINVAL) : -EINVAL)
-#define smu_run_afll_btc(smu) \
-       ((smu)->ppt_funcs? ((smu)->ppt_funcs->run_afll_btc? (smu)->ppt_funcs->run_afll_btc((smu)) : 0) : 0)
+#define smu_run_btc(smu) \
+       ((smu)->ppt_funcs? ((smu)->ppt_funcs->run_btc? (smu)->ppt_funcs->run_btc((smu)) : 0) : 0)
 #define smu_get_allowed_feature_mask(smu, feature_mask, num) \
        ((smu)->ppt_funcs? ((smu)->ppt_funcs->get_allowed_feature_mask? (smu)->ppt_funcs->get_allowed_feature_mask((smu), (feature_mask), (num)) : 0) : 0)
 #define smu_set_deep_sleep_dcefclk(smu, clk) \
@@ -727,8 +736,6 @@ struct smu_funcs
        ((smu)->funcs->get_current_shallow_sleep_clocks ? (smu)->funcs->get_current_shallow_sleep_clocks((smu), (clocks)) : 0)
 #define smu_notify_smu_enable_pwe(smu) \
        ((smu)->funcs->notify_smu_enable_pwe ? (smu)->funcs->notify_smu_enable_pwe((smu)) : 0)
-#define smu_set_watermarks_for_clock_ranges(smu, clock_ranges) \
-       ((smu)->funcs->set_watermarks_for_clock_ranges ? (smu)->funcs->set_watermarks_for_clock_ranges((smu), (clock_ranges)) : 0)
 #define smu_dpm_set_uvd_enable(smu, enable) \
        ((smu)->ppt_funcs->dpm_set_uvd_enable ? (smu)->ppt_funcs->dpm_set_uvd_enable((smu), (enable)) : 0)
 #define smu_dpm_set_vce_enable(smu, enable) \
@@ -751,21 +758,30 @@ struct smu_funcs
                ((smu)->funcs->get_dpm_ultimate_freq ? (smu)->funcs->get_dpm_ultimate_freq((smu), (param), (min), (max)) : 0)
 #define smu_get_max_sustainable_clocks_by_dc(smu, max_clocks) \
        ((smu)->funcs->get_max_sustainable_clocks_by_dc ? (smu)->funcs->get_max_sustainable_clocks_by_dc((smu), (max_clocks)) : 0)
-#define smu_get_uclk_dpm_states(smu, clocks_in_khz, num_states) \
-       ((smu)->ppt_funcs->get_uclk_dpm_states ? (smu)->ppt_funcs->get_uclk_dpm_states((smu), (clocks_in_khz), (num_states)) : 0)
 #define smu_baco_is_support(smu) \
        ((smu)->funcs->baco_is_support? (smu)->funcs->baco_is_support((smu)) : false)
 #define smu_baco_get_state(smu, state) \
        ((smu)->funcs->baco_get_state? (smu)->funcs->baco_get_state((smu), (state)) : 0)
 #define smu_baco_reset(smu) \
        ((smu)->funcs->baco_reset? (smu)->funcs->baco_reset((smu)) : 0)
+#define smu_mode2_reset(smu) \
+       ((smu)->funcs->mode2_reset? (smu)->funcs->mode2_reset((smu)) : 0)
 #define smu_asic_set_performance_level(smu, level) \
        ((smu)->ppt_funcs->set_performance_level? (smu)->ppt_funcs->set_performance_level((smu), (level)) : -EINVAL);
 #define smu_dump_pptable(smu) \
        ((smu)->ppt_funcs->dump_pptable ? (smu)->ppt_funcs->dump_pptable((smu)) : 0)
-#define smu_get_dpm_uclk_limited(smu, clock, max) \
-               ((smu)->ppt_funcs->get_dpm_uclk_limited ? (smu)->ppt_funcs->get_dpm_uclk_limited((smu), (clock), (max)) : -EINVAL)
+#define smu_get_dpm_clk_limited(smu, clk_type, dpm_level, freq) \
+               ((smu)->ppt_funcs->get_dpm_clk_limited ? (smu)->ppt_funcs->get_dpm_clk_limited((smu), (clk_type), (dpm_level), (freq)) : -EINVAL)
+#define smu_set_soft_freq_limited_range(smu, clk_type, min, max) \
+               ((smu)->funcs->set_soft_freq_limited_range ? (smu)->funcs->set_soft_freq_limited_range((smu), (clk_type), (min), (max)) : -EINVAL)
+#define smu_get_dpm_clock_table(smu, clock_table) \
+               ((smu)->ppt_funcs->get_dpm_clock_table ? (smu)->ppt_funcs->get_dpm_clock_table((smu), (clock_table)) : -EINVAL)
+
+#define smu_override_pcie_parameters(smu) \
+               ((smu)->funcs->override_pcie_parameters ? (smu)->funcs->override_pcie_parameters((smu)) : 0)
 
+#define smu_update_pcie_parameters(smu, pcie_gen_cap, pcie_width_cap) \
+               ((smu)->ppt_funcs->update_pcie_parameters ? (smu)->ppt_funcs->update_pcie_parameters((smu), (pcie_gen_cap), (pcie_width_cap)) : 0)
 
 extern int smu_get_atom_data_table(struct smu_context *smu, uint32_t table,
                                   uint16_t *size, uint8_t *frev, uint8_t *crev,
@@ -799,6 +815,10 @@ int smu_sys_get_pp_table(struct smu_context *smu, void **table);
 int smu_sys_set_pp_table(struct smu_context *smu,  void *buf, size_t size);
 int smu_get_power_num_states(struct smu_context *smu, struct pp_states_info *state_info);
 enum amd_pm_state_type smu_get_current_power_state(struct smu_context *smu);
+int smu_write_watermarks_table(struct smu_context *smu);
+int smu_set_watermarks_for_clock_ranges(
+               struct smu_context *smu,
+               struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges);
 
 /* smu to display interface */
 extern int smu_display_configuration_change(struct smu_context *smu, const
@@ -828,10 +848,16 @@ enum amd_dpm_forced_level smu_get_performance_level(struct smu_context *smu);
 int smu_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level);
 int smu_set_display_count(struct smu_context *smu, uint32_t count);
 bool smu_clk_dpm_is_enabled(struct smu_context *smu, enum smu_clk_type clk_type);
-int smu_feature_update_enable_state(struct smu_context *smu, uint64_t feature_mask, bool enabled);
 const char *smu_get_message_name(struct smu_context *smu, enum smu_message_type type);
 const char *smu_get_feature_name(struct smu_context *smu, enum smu_feature_mask feature);
 size_t smu_sys_get_pp_feature_mask(struct smu_context *smu, char *buf);
 int smu_sys_set_pp_feature_mask(struct smu_context *smu, uint64_t new_mask);
+int smu_force_clk_levels(struct smu_context *smu,
+                        enum smu_clk_type clk_type,
+                        uint32_t mask);
+int smu_set_mp1_state(struct smu_context *smu,
+                     enum pp_mp1_state mp1_state);
+int smu_set_df_cstate(struct smu_context *smu,
+                     enum pp_df_cstate state);
 
 #endif
index 78e5927b7711f8e5879ae26de108b450ab579cd5..e3291259b249bff823b346ac919d87f74fd76d1c 100644 (file)
@@ -95,8 +95,7 @@
 
 //BTC
 #define PPSMC_MSG_RunAfllBtc                     0x30
-#define PPSMC_MSG_RunGfxDcBtc                    0x31
-#define PPSMC_MSG_RunSocDcBtc                    0x32
+#define PPSMC_MSG_RunDcBtc                       0x31
 
 //Debug
 #define PPSMC_MSG_DramLogSetDramAddrHigh         0x33
index 7bf9a14bfa0becba79a6e9e97a1120bfd637f413..bd8c922dfd3ece5a00772fa7df618573ab6d1c8e 100644 (file)
@@ -355,6 +355,7 @@ struct pp_hwmgr_func {
        int (*set_mp1_state)(struct pp_hwmgr *hwmgr, enum pp_mp1_state mp1_state);
        int (*asic_reset)(struct pp_hwmgr *hwmgr, enum SMU_ASIC_RESET_MODE mode);
        int (*smu_i2c_bus_access)(struct pp_hwmgr *hwmgr, bool aquire);
+       int (*set_df_cstate)(struct pp_hwmgr *hwmgr, enum pp_df_cstate state);
 };
 
 struct pp_table_func {
index e02950b505fa5333e001112e12ebef73fd1dc719..2248d682c462bf4429df5dc0a2e97608091d2ef7 100644 (file)
 #define FEATURE_DS_SOCCLK_MASK            (1 << FEATURE_DS_SOCCLK_BIT            )
 #define FEATURE_DS_LCLK_MASK              (1 << FEATURE_DS_LCLK_BIT              )
 #define FEATURE_DS_FCLK_MASK              (1 << FEATURE_DS_FCLK_BIT              )
-#define FEATURE_DS_LCLK_MASK              (1 << FEATURE_DS_LCLK_BIT              )
+#define FEATURE_DS_UCLK_MASK              (1 << FEATURE_DS_UCLK_BIT              )
 #define FEATURE_GFX_ULV_MASK              (1 << FEATURE_GFX_ULV_BIT              )
-#define FEATURE_VCN_PG_MASK               (1 << FEATURE_VCN_PG_BIT               )
+#define FEATURE_DPM_VCN_MASK              (1 << FEATURE_DPM_VCN_BIT              )
 #define FEATURE_RSMU_SMN_CG_MASK          (1 << FEATURE_RSMU_SMN_CG_BIT          )
 #define FEATURE_WAFL_CG_MASK              (1 << FEATURE_WAFL_CG_BIT              )
 
 #define FEATURE_PPT_MASK                  (1 << FEATURE_PPT_BIT                  )
 #define FEATURE_TDC_MASK                  (1 << FEATURE_TDC_BIT                  )
-#define FEATURE_APCC_MASK                 (1 << FEATURE_APCC_BIT                 )
+#define FEATURE_APCC_PLUS_MASK            (1 << FEATURE_APCC_PLUS_BIT            )
 #define FEATURE_VR0HOT_MASK               (1 << FEATURE_VR0HOT_BIT               )
 #define FEATURE_VR1HOT_MASK               (1 << FEATURE_VR1HOT_BIT               )
 #define FEATURE_FW_CTF_MASK               (1 << FEATURE_FW_CTF_BIT               )
 #define FEATURE_FAN_CONTROL_MASK          (1 << FEATURE_FAN_CONTROL_BIT          )
 #define FEATURE_THERMAL_MASK              (1 << FEATURE_THERMAL_BIT              )
 
-#define FEATURE_OUT_OF_BAND_MONITOR_MASK  (1 << EATURE_OUT_OF_BAND_MONITOR_BIT   )
-#define FEATURE_TEMP_DEPENDENT_VMIN_MASK  (1 << FEATURE_TEMP_DEPENDENT_VMIN_MASK )
+#define FEATURE_OUT_OF_BAND_MONITOR_MASK  (1 << FEATURE_OUT_OF_BAND_MONITOR_BIT   )
+#define FEATURE_TEMP_DEPENDENT_VMIN_MASK  (1 << FEATURE_TEMP_DEPENDENT_VMIN_BIT )
 
 
 //FIXME need updating
@@ -696,7 +696,11 @@ typedef struct {
   uint8_t      GpioI2cSda;          // Serial Data
   uint16_t     GpioPadding;
 
-  uint32_t     BoardReserved[9];
+  // Platform input telemetry voltage coefficient
+  uint32_t     BoardVoltageCoeffA;    // decode by /1000
+  uint32_t     BoardVoltageCoeffB;    // decode by /1000
+
+  uint32_t     BoardReserved[7];
 
   // Padding for MMHUB - do not modify this
   uint32_t     MmHubPadding[8]; // SMU internal use
@@ -802,7 +806,7 @@ typedef struct {
 
   uint32_t P2VCharzFreq[AVFS_VOLTAGE_COUNT]; // in 10KHz units
 
-  uint32_t EnabledAvfsModules[2];
+  uint32_t EnabledAvfsModules[3];
 
   uint32_t MmHubPadding[8]; // SMU internal use
 } AvfsFuseOverride_t;
@@ -865,7 +869,8 @@ typedef struct {
 //#define TABLE_ACTIVITY_MONITOR_COEFF  7
 #define TABLE_OVERDRIVE               7
 #define TABLE_WAFL_XGMI_TOPOLOGY      8
-#define TABLE_COUNT                   9
+#define TABLE_I2C_COMMANDS            9
+#define TABLE_COUNT                   10
 
 // These defines are used with the SMC_MSG_SetUclkFastSwitch message.
 typedef enum {
index b0dd05d431dd403b0ff54baa423f24a2b0ed0d77..d8c9b7f91fcc2825459eabc99ed7388ee9fa00b1 100644 (file)
        __SMU_DUMMY_MAP(PowerDownJpeg),                \
        __SMU_DUMMY_MAP(BacoAudioD3PME),               \
        __SMU_DUMMY_MAP(ArmD3),                        \
+       __SMU_DUMMY_MAP(RunDcBtc),                     \
        __SMU_DUMMY_MAP(RunGfxDcBtc),                  \
        __SMU_DUMMY_MAP(RunSocDcBtc),                  \
        __SMU_DUMMY_MAP(SetMemoryChannelEnable),       \
        __SMU_DUMMY_MAP(PowerGateAtHub),              \
        __SMU_DUMMY_MAP(SetSoftMinJpeg),              \
        __SMU_DUMMY_MAP(SetHardMinFclkByFreq),        \
+       __SMU_DUMMY_MAP(DFCstateControl), \
 
 #undef __SMU_DUMMY_MAP
 #define __SMU_DUMMY_MAP(type)  SMU_MSG_##type
@@ -251,6 +253,7 @@ enum smu_clk_type {
        __SMU_DUMMY_MAP(TEMP_DEPENDENT_VMIN),                   \
        __SMU_DUMMY_MAP(MMHUB_PG),                              \
        __SMU_DUMMY_MAP(ATHUB_PG),                              \
+       __SMU_DUMMY_MAP(APCC_DFLL),                             \
        __SMU_DUMMY_MAP(WAFL_CG),
 
 #undef __SMU_DUMMY_MAP
index 5bda8539447acfddf0c3451180cff45ed10ca3b4..9b856a6c5dfb6a63e566270e79877bdd2e27c2b6 100644 (file)
@@ -27,7 +27,7 @@
 
 #define SMU11_DRIVER_IF_VERSION_INV 0xFFFFFFFF
 #define SMU11_DRIVER_IF_VERSION_VG20 0x13
-#define SMU11_DRIVER_IF_VERSION_ARCT 0x09
+#define SMU11_DRIVER_IF_VERSION_ARCT 0x0D
 #define SMU11_DRIVER_IF_VERSION_NV10 0x33
 #define SMU11_DRIVER_IF_VERSION_NV14 0x34
 
index a0883038f3c3fabdada19def4571591a3ea97c22..0c66f0fe1aaf04e4081768ca7591c93f106e8ec6 100644 (file)
 #define PPSMC_MSG_SetMGpuFanBoostLimitRpm        0x5D
 #define PPSMC_MSG_GetAVFSVoltageByDpm            0x5F
 #define PPSMC_MSG_BacoWorkAroundFlushVDCI        0x60
-#define PPSMC_Message_Count                      0x61
+#define PPSMC_MSG_DFCstateControl                0x63
+#define PPSMC_Message_Count                      0x64
 
 typedef uint32_t PPSMC_Result;
 typedef uint32_t PPSMC_Msg;
index 0b461404af6b489972fd62dca5217c8bc32191cc..d59ec114f824ab14650250bbb5636a838bb318cb 100644 (file)
@@ -177,6 +177,7 @@ static struct smu_11_0_cmn2aisc_mapping navi10_feature_mask_map[SMU_FEATURE_COUN
        FEA_MAP(TEMP_DEPENDENT_VMIN),
        FEA_MAP(MMHUB_PG),
        FEA_MAP(ATHUB_PG),
+       FEA_MAP(APCC_DFLL),
 };
 
 static struct smu_11_0_cmn2aisc_mapping navi10_table_map[SMU_TABLE_COUNT] = {
@@ -327,40 +328,52 @@ navi10_get_allowed_feature_mask(struct smu_context *smu,
        memset(feature_mask, 0, sizeof(uint32_t) * num);
 
        *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT)
-                               | FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)
-                               | FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT)
                                | FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)
-                               | FEATURE_MASK(FEATURE_DPM_LINK_BIT)
-                               | FEATURE_MASK(FEATURE_GFX_ULV_BIT)
                                | FEATURE_MASK(FEATURE_RSMU_SMN_CG_BIT)
                                | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT)
                                | FEATURE_MASK(FEATURE_PPT_BIT)
                                | FEATURE_MASK(FEATURE_TDC_BIT)
                                | FEATURE_MASK(FEATURE_GFX_EDC_BIT)
+                               | FEATURE_MASK(FEATURE_APCC_PLUS_BIT)
                                | FEATURE_MASK(FEATURE_VR0HOT_BIT)
                                | FEATURE_MASK(FEATURE_FAN_CONTROL_BIT)
                                | FEATURE_MASK(FEATURE_THERMAL_BIT)
                                | FEATURE_MASK(FEATURE_LED_DISPLAY_BIT)
-                               | FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT)
-                               | FEATURE_MASK(FEATURE_DS_GFXCLK_BIT)
+                               | FEATURE_MASK(FEATURE_DS_LCLK_BIT)
                                | FEATURE_MASK(FEATURE_DS_DCEFCLK_BIT)
                                | FEATURE_MASK(FEATURE_FW_DSTATE_BIT)
                                | FEATURE_MASK(FEATURE_BACO_BIT)
                                | FEATURE_MASK(FEATURE_ACDC_BIT)
                                | FEATURE_MASK(FEATURE_GFX_SS_BIT)
                                | FEATURE_MASK(FEATURE_APCC_DFLL_BIT)
-                               | FEATURE_MASK(FEATURE_FW_CTF_BIT);
+                               | FEATURE_MASK(FEATURE_FW_CTF_BIT)
+                               | FEATURE_MASK(FEATURE_OUT_OF_BAND_MONITOR_BIT);
+
+       if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK)
+               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT);
+
+       if (adev->pm.pp_feature & PP_SCLK_DPM_MASK)
+               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT);
+
+       if (adev->pm.pp_feature & PP_PCIE_DPM_MASK)
+               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_LINK_BIT);
+
+       if (adev->pm.pp_feature & PP_DCEFCLK_DPM_MASK)
+               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT);
 
        if (adev->pm.pp_feature & PP_MCLK_DPM_MASK)
                *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT)
                                | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT)
                                | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT);
 
-       if (adev->pm.pp_feature & PP_GFXOFF_MASK) {
+       if (adev->pm.pp_feature & PP_ULV_MASK)
+               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_ULV_BIT);
+
+       if (adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK)
+               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_GFXCLK_BIT);
+
+       if (adev->pm.pp_feature & PP_GFXOFF_MASK)
                *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXOFF_BIT);
-               /* TODO: remove it once fw fix the bug */
-               *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_FW_DSTATE_BIT);
-       }
 
        if (smu->adev->pg_flags & AMD_PG_SUPPORT_MMHUB)
                *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MMHUB_PG_BIT);
@@ -1451,18 +1464,47 @@ static int navi10_set_peak_clock_by_device(struct smu_context *smu)
        uint32_t sclk_freq = 0, uclk_freq = 0;
        uint32_t uclk_level = 0;
 
-       switch (adev->pdev->revision) {
-       case 0xf0: /* XTX */
-       case 0xc0:
-               sclk_freq = NAVI10_PEAK_SCLK_XTX;
-               break;
-       case 0xf1: /* XT */
-       case 0xc1:
-               sclk_freq = NAVI10_PEAK_SCLK_XT;
+       switch (adev->asic_type) {
+       case CHIP_NAVI10:
+               switch (adev->pdev->revision) {
+               case 0xf0: /* XTX */
+               case 0xc0:
+                       sclk_freq = NAVI10_PEAK_SCLK_XTX;
+                       break;
+               case 0xf1: /* XT */
+               case 0xc1:
+                       sclk_freq = NAVI10_PEAK_SCLK_XT;
+                       break;
+               default: /* XL */
+                       sclk_freq = NAVI10_PEAK_SCLK_XL;
+                       break;
+               }
                break;
-       default: /* XL */
-               sclk_freq = NAVI10_PEAK_SCLK_XL;
+       case CHIP_NAVI14:
+               switch (adev->pdev->revision) {
+               case 0xc7: /* XT */
+               case 0xf4:
+                       sclk_freq = NAVI14_UMD_PSTATE_PEAK_XT_GFXCLK;
+                       break;
+               case 0xc1: /* XTM */
+               case 0xf2:
+                       sclk_freq = NAVI14_UMD_PSTATE_PEAK_XTM_GFXCLK;
+                       break;
+               case 0xc3: /* XLM */
+               case 0xf3:
+                       sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK;
+                       break;
+               case 0xc5: /* XTX */
+               case 0xf6:
+                       sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK;
+                       break;
+               default: /* XL */
+                       sclk_freq = NAVI14_UMD_PSTATE_PEAK_XL_GFXCLK;
+                       break;
+               }
                break;
+       default:
+               return -EINVAL;
        }
 
        ret = smu_get_dpm_level_count(smu, SMU_UCLK, &uclk_level);
@@ -1485,10 +1527,6 @@ static int navi10_set_peak_clock_by_device(struct smu_context *smu)
 static int navi10_set_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
 {
        int ret = 0;
-       struct amdgpu_device *adev = smu->adev;
-
-       if (adev->asic_type != CHIP_NAVI10)
-               return -EINVAL;
 
        switch (level) {
        case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
@@ -1591,6 +1629,28 @@ static int navi10_get_power_limit(struct smu_context *smu,
        return 0;
 }
 
+static int navi10_update_pcie_parameters(struct smu_context *smu,
+                                    uint32_t pcie_gen_cap,
+                                    uint32_t pcie_width_cap)
+{
+       PPTable_t *pptable = smu->smu_table.driver_pptable;
+       int ret, i;
+       uint32_t smu_pcie_arg;
+
+       for (i = 0; i < NUM_LINK_LEVELS; i++) {
+               smu_pcie_arg = (i << 16) |
+                       ((pptable->PcieGenSpeed[i] <= pcie_gen_cap) ? (pptable->PcieGenSpeed[i] << 8) :
+                               (pcie_gen_cap << 8)) | ((pptable->PcieLaneCount[i] <= pcie_width_cap) ?
+                                       pptable->PcieLaneCount[i] : pcie_width_cap);
+               ret = smu_send_smc_msg_with_param(smu,
+                                         SMU_MSG_OverridePcieParameters,
+                                         smu_pcie_arg);
+       }
+
+       return ret;
+}
+
+
 static const struct pptable_funcs navi10_ppt_funcs = {
        .tables_init = navi10_tables_init,
        .alloc_dpm_context = navi10_allocate_dpm_context,
@@ -1629,12 +1689,10 @@ static const struct pptable_funcs navi10_ppt_funcs = {
        .get_thermal_temperature_range = navi10_get_thermal_temperature_range,
        .display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch,
        .get_power_limit = navi10_get_power_limit,
+       .update_pcie_parameters = navi10_update_pcie_parameters,
 };
 
 void navi10_set_ppt_funcs(struct smu_context *smu)
 {
-       struct smu_table_context *smu_table = &smu->smu_table;
-
        smu->ppt_funcs = &navi10_ppt_funcs;
-       smu_table->table_count = TABLE_COUNT;
 }
index 620ff17c2fef8ff54e70bbd13bcb2a9a8c52f368..a37e37c5f1058ba52e814e7acac7835105c4cb87 100644 (file)
 #define NAVI10_PEAK_SCLK_XT            (1755)
 #define NAVI10_PEAK_SCLK_XL            (1625)
 
+#define NAVI14_UMD_PSTATE_PEAK_XT_GFXCLK      (1670)
+#define NAVI14_UMD_PSTATE_PEAK_XTM_GFXCLK     (1448)
+#define NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK     (1181)
+#define NAVI14_UMD_PSTATE_PEAK_XTX_GFXCLK     (1717)
+#define NAVI14_UMD_PSTATE_PEAK_XL_GFXCLK      (1448)
+
 extern void navi10_set_ppt_funcs(struct smu_context *smu);
 
 #endif
index e62bfba51562da92b347bf06ec57bb03f9332938..57930c9e22ff25bd90956bc5bc79f2884e508ff1 100644 (file)
@@ -160,21 +160,17 @@ static int renoir_tables_init(struct smu_context *smu, struct smu_table *tables)
  * This interface just for getting uclk ultimate freq and should't introduce
  * other likewise function result in overmuch callback.
  */
-static int renoir_get_dpm_uclk_limited(struct smu_context *smu, uint32_t *clock, bool max)
+static int renoir_get_dpm_clk_limited(struct smu_context *smu, enum smu_clk_type clk_type,
+                                               uint32_t dpm_level, uint32_t *freq)
 {
+       DpmClocks_t *clk_table = smu->smu_table.clocks_table;
 
-       DpmClocks_t *table = smu->smu_table.clocks_table;
-
-       if (!clock || !table)
+       if (!clk_table || clk_type >= SMU_CLK_COUNT)
                return -EINVAL;
 
-       if (max)
-               *clock = table->FClocks[NUM_FCLK_DPM_LEVELS-1].Freq;
-       else
-               *clock = table->FClocks[0].Freq;
+       GET_DPM_CUR_FREQ(clk_table, clk_type, dpm_level, *freq);
 
        return 0;
-
 }
 
 static int renoir_print_clk_levels(struct smu_context *smu,
@@ -246,20 +242,461 @@ static int renoir_print_clk_levels(struct smu_context *smu,
        return size;
 }
 
+static enum amd_pm_state_type renoir_get_current_power_state(struct smu_context *smu)
+{
+       enum amd_pm_state_type pm_type;
+       struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
+
+       if (!smu_dpm_ctx->dpm_context ||
+           !smu_dpm_ctx->dpm_current_power_state)
+               return -EINVAL;
+
+       mutex_lock(&(smu->mutex));
+       switch (smu_dpm_ctx->dpm_current_power_state->classification.ui_label) {
+       case SMU_STATE_UI_LABEL_BATTERY:
+               pm_type = POWER_STATE_TYPE_BATTERY;
+               break;
+       case SMU_STATE_UI_LABEL_BALLANCED:
+               pm_type = POWER_STATE_TYPE_BALANCED;
+               break;
+       case SMU_STATE_UI_LABEL_PERFORMANCE:
+               pm_type = POWER_STATE_TYPE_PERFORMANCE;
+               break;
+       default:
+               if (smu_dpm_ctx->dpm_current_power_state->classification.flags & SMU_STATE_CLASSIFICATION_FLAG_BOOT)
+                       pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
+               else
+                       pm_type = POWER_STATE_TYPE_DEFAULT;
+               break;
+       }
+       mutex_unlock(&(smu->mutex));
+
+       return pm_type;
+}
+
+static int renoir_dpm_set_uvd_enable(struct smu_context *smu, bool enable)
+{
+       struct smu_power_context *smu_power = &smu->smu_power;
+       struct smu_power_gate *power_gate = &smu_power->power_gate;
+       int ret = 0;
+
+       if (enable) {
+               /* vcn dpm on is a prerequisite for vcn power gate messages */
+               if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
+                       ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1);
+                       if (ret)
+                               return ret;
+               }
+               power_gate->vcn_gated = false;
+       } else {
+               if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
+                       ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn);
+                       if (ret)
+                               return ret;
+               }
+               power_gate->vcn_gated = true;
+       }
+
+       return ret;
+}
+
+static int renoir_force_dpm_limit_value(struct smu_context *smu, bool highest)
+{
+       int ret = 0, i = 0;
+       uint32_t min_freq, max_freq, force_freq;
+       enum smu_clk_type clk_type;
+
+       enum smu_clk_type clks[] = {
+               SMU_GFXCLK,
+               SMU_MCLK,
+               SMU_SOCCLK,
+       };
+
+       for (i = 0; i < ARRAY_SIZE(clks); i++) {
+               clk_type = clks[i];
+               ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq);
+               if (ret)
+                       return ret;
+
+               force_freq = highest ? max_freq : min_freq;
+               ret = smu_set_soft_freq_range(smu, clk_type, force_freq, force_freq);
+               if (ret)
+                       return ret;
+       }
+
+       return ret;
+}
+
+static int renoir_unforce_dpm_levels(struct smu_context *smu) {
+
+       int ret = 0, i = 0;
+       uint32_t min_freq, max_freq;
+       enum smu_clk_type clk_type;
+
+       struct clk_feature_map {
+               enum smu_clk_type clk_type;
+               uint32_t        feature;
+       } clk_feature_map[] = {
+               {SMU_GFXCLK, SMU_FEATURE_DPM_GFXCLK_BIT},
+               {SMU_MCLK,   SMU_FEATURE_DPM_UCLK_BIT},
+               {SMU_SOCCLK, SMU_FEATURE_DPM_SOCCLK_BIT},
+       };
+
+       for (i = 0; i < ARRAY_SIZE(clk_feature_map); i++) {
+               if (!smu_feature_is_enabled(smu, clk_feature_map[i].feature))
+                   continue;
+
+               clk_type = clk_feature_map[i].clk_type;
+
+               ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq);
+               if (ret)
+                       return ret;
+
+               ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq);
+               if (ret)
+                       return ret;
+       }
+
+       return ret;
+}
+
+static int renoir_get_workload_type(struct smu_context *smu, uint32_t profile)
+{
+
+       uint32_t  pplib_workload = 0;
+
+       switch (profile) {
+       case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
+               pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;
+               break;
+       case PP_SMC_POWER_PROFILE_CUSTOM:
+               pplib_workload = WORKLOAD_PPLIB_COUNT;
+               break;
+       case PP_SMC_POWER_PROFILE_VIDEO:
+               pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT;
+               break;
+       case PP_SMC_POWER_PROFILE_VR:
+               pplib_workload = WORKLOAD_PPLIB_VR_BIT;
+               break;
+       case PP_SMC_POWER_PROFILE_COMPUTE:
+               pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return pplib_workload;
+}
+
+static int renoir_get_profiling_clk_mask(struct smu_context *smu,
+                                        enum amd_dpm_forced_level level,
+                                        uint32_t *sclk_mask,
+                                        uint32_t *mclk_mask,
+                                        uint32_t *soc_mask)
+{
+
+       if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
+               if (sclk_mask)
+                       *sclk_mask = 0;
+       } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
+               if (mclk_mask)
+                       *mclk_mask = 0;
+       } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
+               if(sclk_mask)
+                       /* The sclk as gfxclk and has three level about max/min/current */
+                       *sclk_mask = 3 - 1;
+
+               if(mclk_mask)
+                       *mclk_mask = NUM_MEMCLK_DPM_LEVELS - 1;
+
+               if(soc_mask)
+                       *soc_mask = NUM_SOCCLK_DPM_LEVELS - 1;
+       }
+
+       return 0;
+}
+
+/**
+ * This interface get dpm clock table for dc
+ */
+static int renoir_get_dpm_clock_table(struct smu_context *smu, struct dpm_clocks *clock_table)
+{
+       DpmClocks_t *table = smu->smu_table.clocks_table;
+       int i;
+
+       if (!clock_table || !table)
+               return -EINVAL;
+
+       for (i = 0; i < NUM_DCFCLK_DPM_LEVELS; i++) {
+               clock_table->DcfClocks[i].Freq = table->DcfClocks[i].Freq;
+               clock_table->DcfClocks[i].Vol = table->DcfClocks[i].Vol;
+       }
+
+       for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) {
+               clock_table->SocClocks[i].Freq = table->SocClocks[i].Freq;
+               clock_table->SocClocks[i].Vol = table->SocClocks[i].Vol;
+       }
+
+       for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) {
+               clock_table->FClocks[i].Freq = table->FClocks[i].Freq;
+               clock_table->FClocks[i].Vol = table->FClocks[i].Vol;
+       }
+
+       for (i = 0; i<  NUM_MEMCLK_DPM_LEVELS; i++) {
+               clock_table->MemClocks[i].Freq = table->MemClocks[i].Freq;
+               clock_table->MemClocks[i].Vol = table->MemClocks[i].Vol;
+       }
+
+       return 0;
+}
+
+static int renoir_force_clk_levels(struct smu_context *smu,
+                                  enum smu_clk_type clk_type, uint32_t mask)
+{
+
+       int ret = 0 ;
+       uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0;
+       DpmClocks_t *clk_table = smu->smu_table.clocks_table;
+
+       soft_min_level = mask ? (ffs(mask) - 1) : 0;
+       soft_max_level = mask ? (fls(mask) - 1) : 0;
+
+       switch (clk_type) {
+       case SMU_GFXCLK:
+       case SMU_SCLK:
+               if (soft_min_level > 2 || soft_max_level > 2) {
+                       pr_info("Currently sclk only support 3 levels on APU\n");
+                       return -EINVAL;
+               }
+
+               ret = smu_get_dpm_freq_range(smu, SMU_GFXCLK, &min_freq, &max_freq);
+               if (ret)
+                       return ret;
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
+                                       soft_max_level == 0 ? min_freq :
+                                       soft_max_level == 1 ? RENOIR_UMD_PSTATE_GFXCLK : max_freq);
+               if (ret)
+                       return ret;
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
+                                       soft_min_level == 2 ? max_freq :
+                                       soft_min_level == 1 ? RENOIR_UMD_PSTATE_GFXCLK : min_freq);
+               if (ret)
+                       return ret;
+               break;
+       case SMU_SOCCLK:
+               GET_DPM_CUR_FREQ(clk_table, clk_type, soft_min_level, min_freq);
+               GET_DPM_CUR_FREQ(clk_table, clk_type, soft_max_level, max_freq);
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxSocclkByFreq, max_freq);
+               if (ret)
+                       return ret;
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinSocclkByFreq, min_freq);
+               if (ret)
+                       return ret;
+               break;
+       case SMU_MCLK:
+       case SMU_FCLK:
+               GET_DPM_CUR_FREQ(clk_table, clk_type, soft_min_level, min_freq);
+               GET_DPM_CUR_FREQ(clk_table, clk_type, soft_max_level, max_freq);
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxFclkByFreq, max_freq);
+               if (ret)
+                       return ret;
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinFclkByFreq, min_freq);
+               if (ret)
+                       return ret;
+               break;
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
+{
+       int workload_type, ret;
+       uint32_t profile_mode = input[size];
+
+       if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
+               pr_err("Invalid power profile mode %d\n", smu->power_profile_mode);
+               return -EINVAL;
+       }
+
+       /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
+       workload_type = smu_workload_get_type(smu, smu->power_profile_mode);
+       if (workload_type < 0) {
+               pr_err("Unsupported power profile mode %d on RENOIR\n",smu->power_profile_mode);
+               return -EINVAL;
+       }
+
+       ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
+                                   1 << workload_type);
+       if (ret) {
+               pr_err("Fail to set workload type %d\n", workload_type);
+               return ret;
+       }
+
+       smu->power_profile_mode = profile_mode;
+
+       return 0;
+}
+
+static int renoir_set_peak_clock_by_device(struct smu_context *smu)
+{
+       int ret = 0;
+       uint32_t sclk_freq = 0, uclk_freq = 0;
+
+       ret = smu_get_dpm_freq_range(smu, SMU_SCLK, NULL, &sclk_freq);
+       if (ret)
+               return ret;
+
+       ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq);
+       if (ret)
+               return ret;
+
+       ret = smu_get_dpm_freq_range(smu, SMU_UCLK, NULL, &uclk_freq);
+       if (ret)
+               return ret;
+
+       ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq);
+       if (ret)
+               return ret;
+
+       return ret;
+}
+
+static int renoir_set_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
+{
+       int ret = 0;
+
+       switch (level) {
+       case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
+               ret = renoir_set_peak_clock_by_device(smu);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+/* save watermark settings into pplib smu structure,
+ * also pass data to smu controller
+ */
+static int renoir_set_watermarks_table(
+               struct smu_context *smu,
+               void *watermarks,
+               struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges)
+{
+       int i;
+       int ret = 0;
+       Watermarks_t *table = watermarks;
+
+       if (!table || !clock_ranges)
+               return -EINVAL;
+
+       if (clock_ranges->num_wm_dmif_sets > 4 ||
+                       clock_ranges->num_wm_mcif_sets > 4)
+               return -EINVAL;
+
+       /* save into smu->smu_table.tables[SMU_TABLE_WATERMARKS]->cpu_addr*/
+       for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) {
+               table->WatermarkRow[WM_DCFCLK][i].MinClock =
+                       cpu_to_le16((uint16_t)
+                       (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz));
+               table->WatermarkRow[WM_DCFCLK][i].MaxClock =
+                       cpu_to_le16((uint16_t)
+                       (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz));
+               table->WatermarkRow[WM_DCFCLK][i].MinMclk =
+                       cpu_to_le16((uint16_t)
+                       (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz));
+               table->WatermarkRow[WM_DCFCLK][i].MaxMclk =
+                       cpu_to_le16((uint16_t)
+                       (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz));
+               table->WatermarkRow[WM_DCFCLK][i].WmSetting = (uint8_t)
+                               clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id;
+       }
+
+       for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) {
+               table->WatermarkRow[WM_SOCCLK][i].MinClock =
+                       cpu_to_le16((uint16_t)
+                       (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz));
+               table->WatermarkRow[WM_SOCCLK][i].MaxClock =
+                       cpu_to_le16((uint16_t)
+                       (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz));
+               table->WatermarkRow[WM_SOCCLK][i].MinMclk =
+                       cpu_to_le16((uint16_t)
+                       (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz));
+               table->WatermarkRow[WM_SOCCLK][i].MaxMclk =
+                       cpu_to_le16((uint16_t)
+                       (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz));
+               table->WatermarkRow[WM_SOCCLK][i].WmSetting = (uint8_t)
+                               clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;
+       }
+
+       /* pass data to smu controller */
+       ret = smu_write_watermarks_table(smu);
+
+       return ret;
+}
+
+static int renoir_get_power_profile_mode(struct smu_context *smu,
+                                          char *buf)
+{
+       static const char *profile_name[] = {
+                                       "BOOTUP_DEFAULT",
+                                       "3D_FULL_SCREEN",
+                                       "POWER_SAVING",
+                                       "VIDEO",
+                                       "VR",
+                                       "COMPUTE",
+                                       "CUSTOM"};
+       uint32_t i, size = 0;
+       int16_t workload_type = 0;
+
+       if (!smu->pm_enabled || !buf)
+               return -EINVAL;
+
+       for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
+               /*
+                * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT
+                * Not all profile modes are supported on arcturus.
+                */
+               workload_type = smu_workload_get_type(smu, i);
+               if (workload_type < 0)
+                       continue;
+
+               size += sprintf(buf + size, "%2d %14s%s\n",
+                       i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
+       }
+
+       return size;
+}
+
 static const struct pptable_funcs renoir_ppt_funcs = {
        .get_smu_msg_index = renoir_get_smu_msg_index,
        .get_smu_table_index = renoir_get_smu_table_index,
        .tables_init = renoir_tables_init,
        .set_power_state = NULL,
-       .get_dpm_uclk_limited = renoir_get_dpm_uclk_limited,
+       .get_dpm_clk_limited = renoir_get_dpm_clk_limited,
        .print_clk_levels = renoir_print_clk_levels,
+       .get_current_power_state = renoir_get_current_power_state,
+       .dpm_set_uvd_enable = renoir_dpm_set_uvd_enable,
+       .force_dpm_limit_value = renoir_force_dpm_limit_value,
+       .unforce_dpm_levels = renoir_unforce_dpm_levels,
+       .get_workload_type = renoir_get_workload_type,
+       .get_profiling_clk_mask = renoir_get_profiling_clk_mask,
+       .force_clk_levels = renoir_force_clk_levels,
+       .set_power_profile_mode = renoir_set_power_profile_mode,
+       .set_performance_level = renoir_set_performance_level,
+       .get_dpm_clock_table = renoir_get_dpm_clock_table,
+       .set_watermarks_table = renoir_set_watermarks_table,
+       .get_power_profile_mode = renoir_get_power_profile_mode,
 };
 
 void renoir_set_ppt_funcs(struct smu_context *smu)
 {
-       struct smu_table_context *smu_table = &smu->smu_table;
-
        smu->ppt_funcs = &renoir_ppt_funcs;
        smu->smc_if_version = SMU12_DRIVER_IF_VERSION;
-       smu_table->table_count = TABLE_COUNT;
+       smu->is_apu = true;
 }
index c5257ae3188a3fe3c2cf7e4fe51961a190ca9372..96200011f9bca960ba4cf365fa67674a3943cb25 100644 (file)
@@ -35,6 +35,7 @@
 #include "vega20_ppt.h"
 #include "arcturus_ppt.h"
 #include "navi10_ppt.h"
+#include "amd_pcie.h"
 
 #include "asic_reg/thm/thm_11_0_2_offset.h"
 #include "asic_reg/thm/thm_11_0_2_sh_mask.h"
@@ -439,7 +440,7 @@ static int smu_v11_0_init_smc_tables(struct smu_context *smu)
        struct smu_table *tables = NULL;
        int ret = 0;
 
-       if (smu_table->tables || smu_table->table_count == 0)
+       if (smu_table->tables)
                return -EINVAL;
 
        tables = kcalloc(SMU_TABLE_COUNT, sizeof(struct smu_table),
@@ -465,13 +466,12 @@ static int smu_v11_0_fini_smc_tables(struct smu_context *smu)
        struct smu_table_context *smu_table = &smu->smu_table;
        int ret = 0;
 
-       if (!smu_table->tables || smu_table->table_count == 0)
+       if (!smu_table->tables)
                return -EINVAL;
 
        kfree(smu_table->tables);
        kfree(smu_table->metrics_table);
        smu_table->tables = NULL;
-       smu_table->table_count = 0;
        smu_table->metrics_table = NULL;
        smu_table->metrics_time = 0;
 
@@ -771,23 +771,6 @@ static int smu_v11_0_write_pptable(struct smu_context *smu)
        return ret;
 }
 
-static int smu_v11_0_write_watermarks_table(struct smu_context *smu)
-{
-       int ret = 0;
-       struct smu_table_context *smu_table = &smu->smu_table;
-       struct smu_table *table = NULL;
-
-       table = &smu_table->tables[SMU_TABLE_WATERMARKS];
-
-       if (!table->cpu_addr)
-               return -EINVAL;
-
-       ret = smu_update_table(smu, SMU_TABLE_WATERMARKS, 0, table->cpu_addr,
-                               true);
-
-       return ret;
-}
-
 static int smu_v11_0_set_deep_sleep_dcefclk(struct smu_context *smu, uint32_t clk)
 {
        int ret;
@@ -1212,6 +1195,15 @@ static int smu_v11_0_start_thermal_control(struct smu_context *smu)
        return ret;
 }
 
+static int smu_v11_0_stop_thermal_control(struct smu_context *smu)
+{
+       struct amdgpu_device *adev = smu->adev;
+
+       WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0);
+
+       return 0;
+}
+
 static uint16_t convert_to_vddc(uint8_t vid)
 {
        return (uint16_t) ((6200 - (vid * 25)) / SMU11_VOLTAGE_SCALE);
@@ -1328,26 +1320,6 @@ smu_v11_0_display_clock_voltage_request(struct smu_context *smu,
        return ret;
 }
 
-static int
-smu_v11_0_set_watermarks_for_clock_ranges(struct smu_context *smu, struct
-                                         dm_pp_wm_sets_with_clock_ranges_soc15
-                                         *clock_ranges)
-{
-       int ret = 0;
-       struct smu_table *watermarks = &smu->smu_table.tables[SMU_TABLE_WATERMARKS];
-       void *table = watermarks->cpu_addr;
-
-       if (!smu->disable_watermark &&
-           smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
-           smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
-               smu_set_watermarks_table(smu, table, clock_ranges);
-               smu->watermarks_bitmap |= WATERMARKS_EXIST;
-               smu->watermarks_bitmap &= ~WATERMARKS_LOADED;
-       }
-
-       return ret;
-}
-
 static int smu_v11_0_gfx_off_control(struct smu_context *smu, bool enable)
 {
        int ret = 0;
@@ -1755,6 +1727,77 @@ static int smu_v11_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk
        return ret;
 }
 
+static int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_type clk_type,
+                           uint32_t min, uint32_t max)
+{
+       int ret = 0, clk_id = 0;
+       uint32_t param;
+
+       clk_id = smu_clk_get_index(smu, clk_type);
+       if (clk_id < 0)
+               return clk_id;
+
+       if (max > 0) {
+               param = (uint32_t)((clk_id << 16) | (max & 0xffff));
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxByFreq,
+                                                 param);
+               if (ret)
+                       return ret;
+       }
+
+       if (min > 0) {
+               param = (uint32_t)((clk_id << 16) | (min & 0xffff));
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinByFreq,
+                                                 param);
+               if (ret)
+                       return ret;
+       }
+
+       return ret;
+}
+
+static int smu_v11_0_override_pcie_parameters(struct smu_context *smu)
+{
+       struct amdgpu_device *adev = smu->adev;
+       uint32_t pcie_gen = 0, pcie_width = 0;
+       int ret;
+
+       if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
+               pcie_gen = 3;
+       else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
+               pcie_gen = 2;
+       else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
+               pcie_gen = 1;
+       else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1)
+               pcie_gen = 0;
+
+       /* Bit 31:16: LCLK DPM level. 0 is DPM0, and 1 is DPM1
+        * Bit 15:8:  PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4
+        * Bit 7:0:   PCIE lane width, 1 to 7 corresponds is x1 to x32
+        */
+       if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
+               pcie_width = 6;
+       else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12)
+               pcie_width = 5;
+       else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8)
+               pcie_width = 4;
+       else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4)
+               pcie_width = 3;
+       else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2)
+               pcie_width = 2;
+       else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1)
+               pcie_width = 1;
+
+       ret = smu_update_pcie_parameters(smu, pcie_gen, pcie_width);
+
+       if (ret)
+               pr_err("[%s] Attempt to override pcie params failed!\n", __func__);
+
+       return ret;
+
+}
+
+
 static const struct smu_funcs smu_v11_0_funcs = {
        .init_microcode = smu_v11_0_init_microcode,
        .load_microcode = smu_v11_0_load_microcode,
@@ -1775,7 +1818,6 @@ static const struct smu_funcs smu_v11_0_funcs = {
        .parse_pptable = smu_v11_0_parse_pptable,
        .populate_smc_tables = smu_v11_0_populate_smc_pptable,
        .write_pptable = smu_v11_0_write_pptable,
-       .write_watermarks_table = smu_v11_0_write_watermarks_table,
        .set_min_dcef_deep_sleep = smu_v11_0_set_min_dcef_deep_sleep,
        .set_tool_table_location = smu_v11_0_set_tool_table_location,
        .init_display_count = smu_v11_0_init_display_count,
@@ -1787,10 +1829,10 @@ static const struct smu_funcs smu_v11_0_funcs = {
        .get_current_clk_freq = smu_v11_0_get_current_clk_freq,
        .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks,
        .start_thermal_control = smu_v11_0_start_thermal_control,
+       .stop_thermal_control = smu_v11_0_stop_thermal_control,
        .read_sensor = smu_v11_0_read_sensor,
        .set_deep_sleep_dcefclk = smu_v11_0_set_deep_sleep_dcefclk,
        .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request,
-       .set_watermarks_for_clock_ranges = smu_v11_0_set_watermarks_for_clock_ranges,
        .get_fan_control_mode = smu_v11_0_get_fan_control_mode,
        .set_fan_control_mode = smu_v11_0_set_fan_control_mode,
        .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
@@ -1805,6 +1847,8 @@ static const struct smu_funcs smu_v11_0_funcs = {
        .baco_set_state = smu_v11_0_baco_set_state,
        .baco_reset = smu_v11_0_baco_reset,
        .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq,
+       .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
+       .override_pcie_parameters = smu_v11_0_override_pcie_parameters,
 };
 
 void smu_v11_0_set_smu_funcs(struct smu_context *smu)
index 9d2280ca1f4b8d0ec439ced7ad14857a477d77d5..cac4269cf1d1efdae18ed5a3f9ae559010df93b8 100644 (file)
@@ -244,15 +244,6 @@ static int smu_v12_0_gfx_off_control(struct smu_context *smu, bool enable)
        if (enable) {
                ret = smu_send_smc_msg(smu, SMU_MSG_AllowGfxOff);
 
-               /* confirm gfx is back to "off" state, timeout is 5 seconds */
-               while (!(smu_v12_0_get_gfxoff_status(smu) == 0)) {
-                       msleep(10);
-                       timeout--;
-                       if (timeout == 0) {
-                               DRM_ERROR("enable gfxoff timeout and failed!\n");
-                               break;
-                       }
-               }
        } else {
                ret = smu_send_smc_msg(smu, SMU_MSG_DisallowGfxOff);
 
@@ -275,7 +266,7 @@ static int smu_v12_0_init_smc_tables(struct smu_context *smu)
        struct smu_table_context *smu_table = &smu->smu_table;
        struct smu_table *tables = NULL;
 
-       if (smu_table->tables || smu_table->table_count == 0)
+       if (smu_table->tables)
                return -EINVAL;
 
        tables = kcalloc(SMU_TABLE_COUNT, sizeof(struct smu_table),
@@ -292,7 +283,7 @@ static int smu_v12_0_fini_smc_tables(struct smu_context *smu)
 {
        struct smu_table_context *smu_table = &smu->smu_table;
 
-       if (!smu_table->tables || smu_table->table_count == 0)
+       if (!smu_table->tables)
                return -EINVAL;
 
        kfree(smu_table->clocks_table);
@@ -323,10 +314,18 @@ static int smu_v12_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk
                                                 uint32_t *min, uint32_t *max)
 {
        int ret = 0;
+       uint32_t mclk_mask, soc_mask;
 
        mutex_lock(&smu->mutex);
 
        if (max) {
+               ret = smu_get_profiling_clk_mask(smu, AMD_DPM_FORCED_LEVEL_PROFILE_PEAK,
+                                                NULL,
+                                                &mclk_mask,
+                                                &soc_mask);
+               if (ret)
+                       goto failed;
+
                switch (clk_type) {
                case SMU_GFXCLK:
                case SMU_SCLK:
@@ -340,14 +339,20 @@ static int smu_v12_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk
                                goto failed;
                        break;
                case SMU_UCLK:
-                       ret = smu_get_dpm_uclk_limited(smu, max, true);
+               case SMU_FCLK:
+               case SMU_MCLK:
+                       ret = smu_get_dpm_clk_limited(smu, clk_type, mclk_mask, max);
+                       if (ret)
+                               goto failed;
+                       break;
+               case SMU_SOCCLK:
+                       ret = smu_get_dpm_clk_limited(smu, clk_type, soc_mask, max);
                        if (ret)
                                goto failed;
                        break;
                default:
                        ret = -EINVAL;
                        goto failed;
-
                }
        }
 
@@ -365,7 +370,14 @@ static int smu_v12_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk
                                goto failed;
                        break;
                case SMU_UCLK:
-                       ret = smu_get_dpm_uclk_limited(smu, min, false);
+               case SMU_FCLK:
+               case SMU_MCLK:
+                       ret = smu_get_dpm_clk_limited(smu, clk_type, 0, min);
+                       if (ret)
+                               goto failed;
+                       break;
+               case SMU_SOCCLK:
+                       ret = smu_get_dpm_clk_limited(smu, clk_type, 0, min);
                        if (ret)
                                goto failed;
                        break;
@@ -373,13 +385,70 @@ static int smu_v12_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk
                        ret = -EINVAL;
                        goto failed;
                }
-
        }
 failed:
        mutex_unlock(&smu->mutex);
        return ret;
 }
 
+static int smu_v12_0_mode2_reset(struct smu_context *smu){
+       return smu_v12_0_send_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset, SMU_RESET_MODE_2);
+}
+
+static int smu_v12_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_type clk_type,
+                           uint32_t min, uint32_t max)
+{
+       int ret = 0;
+
+       if (max < min)
+               return -EINVAL;
+
+       switch (clk_type) {
+       case SMU_GFXCLK:
+       case SMU_SCLK:
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, min);
+               if (ret)
+                       return ret;
+
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, max);
+               if (ret)
+                       return ret;
+       break;
+       case SMU_FCLK:
+       case SMU_MCLK:
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinFclkByFreq, min);
+               if (ret)
+                       return ret;
+
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxFclkByFreq, max);
+               if (ret)
+                       return ret;
+       break;
+       case SMU_SOCCLK:
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinSocclkByFreq, min);
+               if (ret)
+                       return ret;
+
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxSocclkByFreq, max);
+               if (ret)
+                       return ret;
+       break;
+       case SMU_VCLK:
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinVcn, min);
+               if (ret)
+                       return ret;
+
+               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxVcn, max);
+               if (ret)
+                       return ret;
+       break;
+       default:
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
 static const struct smu_funcs smu_v12_0_funcs = {
        .check_fw_status = smu_v12_0_check_fw_status,
        .check_fw_version = smu_v12_0_check_fw_version,
@@ -394,6 +463,8 @@ static const struct smu_funcs smu_v12_0_funcs = {
        .fini_smc_tables = smu_v12_0_fini_smc_tables,
        .populate_smc_tables = smu_v12_0_populate_smc_tables,
        .get_dpm_ultimate_freq = smu_v12_0_get_dpm_ultimate_freq,
+       .mode2_reset = smu_v12_0_mode2_reset,
+       .set_soft_freq_limited_range = smu_v12_0_set_soft_freq_limited_range,
 };
 
 void smu_v12_0_set_smu_funcs(struct smu_context *smu)
index 3f12cf341511e72f09c22e5d9a1c63aa425cf986..aa0ee2b46135421477deb36d6f65a810b33ebc37 100644 (file)
@@ -137,7 +137,7 @@ static int smu10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
                        priv->smu_tables.entry[table_id].table_id);
 
        /* flush hdp cache */
-       adev->nbio_funcs->hdp_flush(adev, NULL);
+       adev->nbio.funcs->hdp_flush(adev, NULL);
 
        memcpy(table, (uint8_t *)priv->smu_tables.entry[table_id].table,
                        priv->smu_tables.entry[table_id].size);
index 4728aa23a818005534fe0a3672c662d37338d3f7..7dca04a8921730a3eb046275253f9464322f7bbe 100644 (file)
@@ -177,12 +177,10 @@ static int smu8_load_mec_firmware(struct pp_hwmgr *hwmgr)
        uint32_t tmp;
        int ret = 0;
        struct cgs_firmware_info info = {0};
-       struct smu8_smumgr *smu8_smu;
 
        if (hwmgr == NULL || hwmgr->device == NULL)
                return -EINVAL;
 
-       smu8_smu = hwmgr->smu_backend;
        ret = cgs_get_firmware_info(hwmgr->device,
                                                CGS_UCODE_ID_CP_MEC, &info);
 
index 0dbdde69f2d90ce29fb7f772f712c02b6b52b19a..0f3836fd9666f4d2745bbf0d29b0cab36a686245 100644 (file)
@@ -58,7 +58,7 @@ static int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
                        priv->smu_tables.entry[table_id].table_id);
 
        /* flush hdp cache */
-       adev->nbio_funcs->hdp_flush(adev, NULL);
+       adev->nbio.funcs->hdp_flush(adev, NULL);
 
        memcpy(table, priv->smu_tables.entry[table_id].table,
                        priv->smu_tables.entry[table_id].size);
index f9589806bf8340acf464d48ff0a1f38e174ad896..90c782c132d255a96426cf303f8eb4c09eef3f0b 100644 (file)
@@ -66,7 +66,7 @@ static int vega12_copy_table_from_smc(struct pp_hwmgr *hwmgr,
                        return -EINVAL);
 
        /* flush hdp cache */
-       adev->nbio_funcs->hdp_flush(adev, NULL);
+       adev->nbio.funcs->hdp_flush(adev, NULL);
 
        memcpy(table, priv->smu_tables.entry[table_id].table,
                        priv->smu_tables.entry[table_id].size);
index b9089c6bea850463fc3cb04901f80dc27e52916b..f604612f411f3a1f2c2e52eebc4ef3698a0a55f7 100644 (file)
@@ -189,7 +189,7 @@ static int vega20_copy_table_from_smc(struct pp_hwmgr *hwmgr,
                        return ret);
 
        /* flush hdp cache */
-       adev->nbio_funcs->hdp_flush(adev, NULL);
+       adev->nbio.funcs->hdp_flush(adev, NULL);
 
        memcpy(table, priv->smu_tables.entry[table_id].table,
                        priv->smu_tables.entry[table_id].size);
@@ -290,7 +290,7 @@ int vega20_get_activity_monitor_coeff(struct pp_hwmgr *hwmgr,
                        return ret);
 
        /* flush hdp cache */
-       adev->nbio_funcs->hdp_flush(adev, NULL);
+       adev->nbio.funcs->hdp_flush(adev, NULL);
 
        memcpy(table, priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].table,
                        priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].size);
index bbd8ebd58434bd2b00316a5d71bbbfd05d456fce..bebf38ca4be7e6d5576feccea2340c97962989d7 100644 (file)
@@ -143,6 +143,7 @@ static struct smu_11_0_cmn2aisc_mapping vega20_message_map[SMU_MSG_MAX_COUNT] =
        MSG_MAP(PrepareMp1ForShutdown),
        MSG_MAP(SetMGpuFanBoostLimitRpm),
        MSG_MAP(GetAVFSVoltageByDpm),
+       MSG_MAP(DFCstateControl),
 };
 
 static struct smu_11_0_cmn2aisc_mapping vega20_clk_map[SMU_CLK_COUNT] = {
@@ -1274,14 +1275,8 @@ static int vega20_force_clk_levels(struct smu_context *smu,
        struct vega20_dpm_table *dpm_table;
        struct vega20_single_dpm_table *single_dpm_table;
        uint32_t soft_min_level, soft_max_level, hard_min_level;
-       struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
        int ret = 0;
 
-       if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
-               pr_info("force clock level is for dpm manual mode only.\n");
-               return -EINVAL;
-       }
-
        mutex_lock(&(smu->mutex));
 
        soft_min_level = mask ? (ffs(mask) - 1) : 0;
@@ -3141,6 +3136,49 @@ static int vega20_get_thermal_temperature_range(struct smu_context *smu,
        return 0;
 }
 
+static int vega20_set_df_cstate(struct smu_context *smu,
+                               enum pp_df_cstate state)
+{
+       uint32_t smu_version;
+       int ret;
+
+       ret = smu_get_smc_version(smu, NULL, &smu_version);
+       if (ret) {
+               pr_err("Failed to get smu version!\n");
+               return ret;
+       }
+
+       /* PPSMC_MSG_DFCstateControl is supported with 40.50 and later fws */
+       if (smu_version < 0x283200) {
+               pr_err("Df cstate control is supported with 40.50 and later SMC fw!\n");
+               return -EINVAL;
+       }
+
+       return smu_send_smc_msg_with_param(smu, SMU_MSG_DFCstateControl, state);
+}
+
+static int vega20_update_pcie_parameters(struct smu_context *smu,
+                                    uint32_t pcie_gen_cap,
+                                    uint32_t pcie_width_cap)
+{
+       PPTable_t *pptable = smu->smu_table.driver_pptable;
+       int ret, i;
+       uint32_t smu_pcie_arg;
+
+       for (i = 0; i < NUM_LINK_LEVELS; i++) {
+               smu_pcie_arg = (i << 16) |
+                       ((pptable->PcieGenSpeed[i] <= pcie_gen_cap) ? (pptable->PcieGenSpeed[i] << 8) :
+                               (pcie_gen_cap << 8)) | ((pptable->PcieLaneCount[i] <= pcie_width_cap) ?
+                                       pptable->PcieLaneCount[i] : pcie_width_cap);
+               ret = smu_send_smc_msg_with_param(smu,
+                                         SMU_MSG_OverridePcieParameters,
+                                         smu_pcie_arg);
+       }
+
+       return ret;
+}
+
+
 static const struct pptable_funcs vega20_ppt_funcs = {
        .tables_init = vega20_tables_init,
        .alloc_dpm_context = vega20_allocate_dpm_context,
@@ -3153,7 +3191,7 @@ static const struct pptable_funcs vega20_ppt_funcs = {
        .get_smu_table_index = vega20_get_smu_table_index,
        .get_smu_power_index = vega20_get_pwr_src_index,
        .get_workload_type = vega20_get_workload_type,
-       .run_afll_btc = vega20_run_btc_afll,
+       .run_btc = vega20_run_btc_afll,
        .get_allowed_feature_mask = vega20_get_allowed_feature_mask,
        .get_current_power_state = vega20_get_current_power_state,
        .set_default_dpm_table = vega20_set_default_dpm_table,
@@ -3183,13 +3221,12 @@ static const struct pptable_funcs vega20_ppt_funcs = {
        .get_fan_speed_percent = vega20_get_fan_speed_percent,
        .get_fan_speed_rpm = vega20_get_fan_speed_rpm,
        .set_watermarks_table = vega20_set_watermarks_table,
-       .get_thermal_temperature_range = vega20_get_thermal_temperature_range
+       .get_thermal_temperature_range = vega20_get_thermal_temperature_range,
+       .set_df_cstate = vega20_set_df_cstate,
+       .update_pcie_parameters = vega20_update_pcie_parameters
 };
 
 void vega20_set_ppt_funcs(struct smu_context *smu)
 {
-       struct smu_table_context *smu_table = &smu->smu_table;
-
        smu->ppt_funcs = &vega20_ppt_funcs;
-       smu_table->table_count = TABLE_COUNT;
 }
index b9aea5776d3d14bb33834317f07d6d8f954aa879..72db2b41e96d91618c5c5f9d706160e962162f23 100644 (file)
@@ -367,10 +367,10 @@ static void radeon_audio_write_sad_regs(struct drm_encoder *encoder)
                return;
 
        sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads);
-       if (sad_count <= 0) {
+       if (sad_count < 0)
                DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
+       if (sad_count <= 0)
                return;
-       }
        BUG_ON(!sads);
 
        if (radeon_encoder->audio && radeon_encoder->audio->write_sad_regs)
index f00b2e79882f885619be835ea98bebd312695a5f..dc3f7d69969737433b43fdefedb8be6a72508a5c 100644 (file)
@@ -926,7 +926,8 @@ EXPORT_SYMBOL(ttm_bo_mem_put);
  */
 static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo,
                                 struct ttm_mem_type_manager *man,
-                                struct ttm_mem_reg *mem)
+                                struct ttm_mem_reg *mem,
+                                bool no_wait_gpu)
 {
        struct dma_fence *fence;
        int ret;
@@ -935,19 +936,22 @@ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo,
        fence = dma_fence_get(man->move);
        spin_unlock(&man->move_lock);
 
-       if (fence) {
-               dma_resv_add_shared_fence(bo->base.resv, fence);
+       if (!fence)
+               return 0;
 
-               ret = dma_resv_reserve_shared(bo->base.resv, 1);
-               if (unlikely(ret)) {
-                       dma_fence_put(fence);
-                       return ret;
-               }
+       if (no_wait_gpu)
+               return -EBUSY;
+
+       dma_resv_add_shared_fence(bo->base.resv, fence);
 
-               dma_fence_put(bo->moving);
-               bo->moving = fence;
+       ret = dma_resv_reserve_shared(bo->base.resv, 1);
+       if (unlikely(ret)) {
+               dma_fence_put(fence);
+               return ret;
        }
 
+       dma_fence_put(bo->moving);
+       bo->moving = fence;
        return 0;
 }
 
@@ -978,7 +982,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo,
                        return ret;
        } while (1);
 
-       return ttm_bo_add_move_fence(bo, man, mem);
+       return ttm_bo_add_move_fence(bo, man, mem, ctx->no_wait_gpu);
 }
 
 static uint32_t ttm_bo_select_caching(struct ttm_mem_type_manager *man,
@@ -1120,14 +1124,18 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
                if (unlikely(ret))
                        goto error;
 
-               if (mem->mm_node) {
-                       ret = ttm_bo_add_move_fence(bo, man, mem);
-                       if (unlikely(ret)) {
-                               (*man->func->put_node)(man, mem);
-                               goto error;
-                       }
-                       return 0;
+               if (!mem->mm_node)
+                       continue;
+
+               ret = ttm_bo_add_move_fence(bo, man, mem, ctx->no_wait_gpu);
+               if (unlikely(ret)) {
+                       (*man->func->put_node)(man, mem);
+                       if (ret == -EBUSY)
+                               continue;
+
+                       goto error;
                }
+               return 0;
        }
 
        for (i = 0; i < placement->num_busy_placement; ++i) {
index 296aab72467743ffb57ae2b4b4db2b11764e0b54..b1230e33d5065ac68151eed6e655cc7444f24de1 100644 (file)
  */
 enum amd_asic_type {
        CHIP_TAHITI = 0,
-       CHIP_PITCAIRN,
-       CHIP_VERDE,
-       CHIP_OLAND,
-       CHIP_HAINAN,
-       CHIP_BONAIRE,
-       CHIP_KAVERI,
-       CHIP_KABINI,
-       CHIP_HAWAII,
-       CHIP_MULLINS,
-       CHIP_TOPAZ,
-       CHIP_TONGA,
-       CHIP_FIJI,
-       CHIP_CARRIZO,
-       CHIP_STONEY,
-       CHIP_POLARIS10,
-       CHIP_POLARIS11,
-       CHIP_POLARIS12,
-       CHIP_VEGAM,
-       CHIP_VEGA10,
-       CHIP_VEGA12,
-       CHIP_VEGA20,
-       CHIP_RAVEN,
-       CHIP_ARCTURUS,
-       CHIP_RENOIR,
-       CHIP_NAVI10,
-       CHIP_NAVI14,
-       CHIP_NAVI12,
+       CHIP_PITCAIRN,  /* 1 */
+       CHIP_VERDE,     /* 2 */
+       CHIP_OLAND,     /* 3 */
+       CHIP_HAINAN,    /* 4 */
+       CHIP_BONAIRE,   /* 5 */
+       CHIP_KAVERI,    /* 6 */
+       CHIP_KABINI,    /* 7 */
+       CHIP_HAWAII,    /* 8 */
+       CHIP_MULLINS,   /* 9 */
+       CHIP_TOPAZ,     /* 10 */
+       CHIP_TONGA,     /* 11 */
+       CHIP_FIJI,      /* 12 */
+       CHIP_CARRIZO,   /* 13 */
+       CHIP_STONEY,    /* 14 */
+       CHIP_POLARIS10, /* 15 */
+       CHIP_POLARIS11, /* 16 */
+       CHIP_POLARIS12, /* 17 */
+       CHIP_VEGAM,     /* 18 */
+       CHIP_VEGA10,    /* 19 */
+       CHIP_VEGA12,    /* 20 */
+       CHIP_VEGA20,    /* 21 */
+       CHIP_RAVEN,     /* 22 */
+       CHIP_ARCTURUS,  /* 23 */
+       CHIP_RENOIR,    /* 24 */
+       CHIP_NAVI10,    /* 25 */
+       CHIP_NAVI14,    /* 26 */
+       CHIP_NAVI12,    /* 27 */
        CHIP_LAST,
 };
 
+extern const char *amdgpu_asic_name[];
+
 #endif /*__AMD_ASIC_TYPE_H__ */
index 8557efe096dc96018525b8ba62790a104a21b888..fa35b52e0002e03a4a2476f2f854daade6e6742d 100644 (file)
 #define DEVCG_DEV_ALL   4  /* this represents all devices */
 
 #ifdef CONFIG_CGROUP_DEVICE
-extern int __devcgroup_check_permission(short type, u32 major, u32 minor,
-                                       short access);
+int devcgroup_check_permission(short type, u32 major, u32 minor,
+                              short access);
 #else
-static inline int __devcgroup_check_permission(short type, u32 major, u32 minor,
-                                              short access)
+static inline int devcgroup_check_permission(short type, u32 major, u32 minor,
+                                            short access)
 { return 0; }
 #endif
 
 #if defined(CONFIG_CGROUP_DEVICE) || defined(CONFIG_CGROUP_BPF)
-static inline int devcgroup_check_permission(short type, u32 major, u32 minor,
-                                            short access)
-{
-       int rc = BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type, major, minor, access);
-
-       if (rc)
-               return -EPERM;
-
-       return __devcgroup_check_permission(type, major, minor, access);
-}
-
 static inline int devcgroup_inode_permission(struct inode *inode, int mask)
 {
        short type, access = 0;
index 4fe35d600ab880092c99cdb5fff82cff7a96a89e..bbdad866e3fe1d5d8310b9119422480e3bd487c1 100644 (file)
@@ -500,6 +500,8 @@ struct drm_amdgpu_gem_op {
 #define AMDGPU_VM_MTYPE_CC             (3 << 5)
 /* Use UC MTYPE instead of default MTYPE */
 #define AMDGPU_VM_MTYPE_UC             (4 << 5)
+/* Use RW MTYPE instead of default MTYPE */
+#define AMDGPU_VM_MTYPE_RW             (5 << 5)
 
 struct drm_amdgpu_gem_va {
        /** GEM object handle */
index 725674f3276d3bccdce851bbb77944ab5a36b5fd..7d0f8f7431ff5466af18e6105b4ed5c2b9136047 100644 (file)
@@ -801,8 +801,8 @@ struct cgroup_subsys devices_cgrp_subsys = {
  *
  * returns 0 on success, -EPERM case the operation is not permitted
  */
-int __devcgroup_check_permission(short type, u32 major, u32 minor,
-                                short access)
+static int __devcgroup_check_permission(short type, u32 major, u32 minor,
+                                       short access)
 {
        struct dev_cgroup *dev_cgroup;
        bool rc;
@@ -824,3 +824,14 @@ int __devcgroup_check_permission(short type, u32 major, u32 minor,
 
        return 0;
 }
+
+int devcgroup_check_permission(short type, u32 major, u32 minor, short access)
+{
+       int rc = BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type, major, minor, access);
+
+       if (rc)
+               return -EPERM;
+
+       return __devcgroup_check_permission(type, major, minor, access);
+}
+EXPORT_SYMBOL(devcgroup_check_permission);