summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-02-23 18:58:18 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-23 18:58:18 -0800
commitef96152e6a36e0510387cb174178b7982c1ae879 (patch)
treef2b881feb97893dd6e73380fe206bbfd5110559e
parentd5500a074741b78b7f778b4ab3415d5ecdcda0a7 (diff)
parent64a577196d66b44e37384bc5c4d78c61f59d5b2a (diff)
downloadlinux-ef96152e6a36e0510387cb174178b7982c1ae879.tar.gz
Merge tag 'drm-for-v4.11-less-shouty' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie: "This is the main drm pull request for v4.11. Nothing too major, the tinydrm and mmu-less support should make writing smaller drivers easier for some of the simpler platforms, and there are a bunch of documentation updates. Intel grew displayport MST audio support which is hopefully useful to people, and FBC is on by default for GEN9+ (so people know where to look for regressions). AMDGPU has a lot of fixes that would like new firmware files installed for some GPUs. Other than that it's pretty scattered all over. I may have a follow up pull request as I know BenH has a bunch of AST rework and fixes and I'd like to get those in once they've been tested by AST, and I've got at least one pull request I'm just trying to get the author to fix up. Core: - drm_mm reworked - Connector list locking and iterators - Documentation updates - Format handling rework - MMU-less support for fbdev helpers - drm_crtc_from_index helper - Core CRC API - Remove drm_framebuffer_unregister_private - Debugfs cleanup - EDID/Infoframe fixes - Release callback - Tinydrm support (smaller drivers for simple hw) panel: - Add support for some new simple panels i915: - FBC by default for gen9+ - Shared dpll cleanups and docs - GEN8 powerdomain cleanup - DMC support on GLK - DP MST audio support - HuC loading support - GVT init ordering fixes - GVT IOMMU workaround fix amdgpu/radeon: - Power/clockgating improvements - Preliminary SR-IOV support - TTM buffer priority and eviction fixes - SI DPM quirks removed due to firmware fixes - Powerplay improvements - VCE/UVD powergating fixes - Cleanup SI GFX code to match CI/VI - Support for > 2 displays on 3/5 crtc asics - SI headless fixes nouveau: - Rework securre boot code in prep for GP10x secure boot - Channel recovery improvements - Initial power budget code - MMU rework preperation vmwgfx: - Bunch of fixes and cleanups exynos: - Runtime PM support for MIC driver - Cleanups to use atomic helpers - UHD Support for TM2/TM2E boards - Trigger mode fix for Rinato board etnaviv: - Shader performance fix - Command stream validator fixes - Command buffer suballocator rockchip: - CDN DisplayPort support - IOMMU support for arm64 platform imx-drm: - Fix i.MX5 TV encoder probing - Remove lower fb size limits msm: - Support for HW cursor on MDP5 devices - DSI encoder cleanup - GPU DT bindings cleanup sti: - stih410 cleanups - Create fbdev at binding - HQVDP fixes - Remove stih416 chip functionality - DVI/HDMI mode selection fixes - FPS statistic reporting omapdrm: - IRQ code cleanup dwi-hdmi bridge: - Cleanups and fixes adv-bridge: - Updates for nexus sii8520 bridge: - Add interlace mode support - Rework HDMI and lots of fixes qxl: - probing/teardown cleanups ZTE drm: - HDMI audio via SPDIF interface - Video Layer overlay plane support - Add TV encoder output device atmel-hlcdc: - Rework fbdev creation logic tegra: - OF node fix fsl-dcu: - Minor fixes mali-dp: - Assorted fixes sunxi: - Minor fix" [ This was the "fixed" pull, that still had build warnings due to people not even having build tested the result. I'm not a happy camper I've fixed the things I noticed up in this merge. - Linus ] * tag 'drm-for-v4.11-less-shouty' of git://people.freedesktop.org/~airlied/linux: (1177 commits) lib/Kconfig: make PRIME_NUMBERS not user selectable drm/tinydrm: helpers: Properly fix backlight dependency drm/tinydrm: mipi-dbi: Fix field width specifier warning drm/tinydrm: mipi-dbi: Silence: ‘cmd’ may be used uninitialized drm/sti: fix build warnings in sti_drv.c and sti_vtg.c files drm/amd/powerplay: fix PSI feature on Polars12 drm/amdgpu: refuse to reserve io mem for split VRAM buffers drm/ttm: fix use-after-free races in vm fault handling drm/tinydrm: Add support for Multi-Inno MI0283QT display dt-bindings: Add Multi-Inno MI0283QT binding dt-bindings: display/panel: Add common rotation property of: Add vendor prefix for Multi-Inno drm/tinydrm: Add MIPI DBI support drm/tinydrm: Add helper functions drm: Add DRM support for tiny LCD displays drm/amd/amdgpu: post card if there is real hw resetting performed drm/nouveau/tmr: provide backtrace when a timeout is hit drm/nouveau/pci/g92: Fix rearm drm/nouveau/drm/therm/fan: add a fallback if no fan control is specified in the vbios drm/nouveau/hwmon: expose power_max and power_crit ..
-rw-r--r--Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt35
-rw-r--r--Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt12
-rw-r--r--Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt85
-rw-r--r--Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt46
-rw-r--r--Documentation/devicetree/bindings/display/hisilicon/hisi-ade.txt2
-rw-r--r--Documentation/devicetree/bindings/display/imx/hdmi.txt51
-rw-r--r--Documentation/devicetree/bindings/display/msm/gpu.txt38
-rw-r--r--Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt27
-rw-r--r--Documentation/devicetree/bindings/display/panel/boe,nv101wxmn51.txt7
-rw-r--r--Documentation/devicetree/bindings/display/panel/netron-dy,e231732.txt7
-rw-r--r--Documentation/devicetree/bindings/display/panel/panel.txt4
-rw-r--r--Documentation/devicetree/bindings/display/panel/tianma,tm070jdhg30.txt7
-rw-r--r--Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt43
-rw-r--r--Documentation/devicetree/bindings/display/zte,vou.txt15
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt3
-rw-r--r--Documentation/dma-buf-sharing.txt482
-rw-r--r--Documentation/driver-api/dma-buf.rst92
-rw-r--r--Documentation/gpu/drm-kms.rst8
-rw-r--r--Documentation/gpu/drm-mm.rst61
-rw-r--r--Documentation/gpu/drm-uapi.rst25
-rw-r--r--Documentation/gpu/i915.rst103
-rw-r--r--Documentation/gpu/index.rst1
-rw-r--r--Documentation/gpu/introduction.rst15
-rw-r--r--Documentation/gpu/tinydrm.rst42
-rw-r--r--Documentation/sound/hd-audio/dp-mst.rst17
-rw-r--r--MAINTAINERS9
-rw-r--r--arch/blackfin/include/asm/vga.h1
-rw-r--r--drivers/char/agp/intel-gtt.c6
-rw-r--r--drivers/dma-buf/dma-buf.c207
-rw-r--r--drivers/dma-buf/dma-fence.c27
-rw-r--r--drivers/dma-buf/sync_debug.c17
-rw-r--r--drivers/dma-buf/sync_file.c21
-rw-r--r--drivers/gpu/drm/Kconfig36
-rw-r--r--drivers/gpu/drm/Makefile6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/Makefile7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h72
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c229
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c151
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c118
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_display.c149
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h19
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c72
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c29
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_job.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c46
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.c55
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.h12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c114
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c116
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c84
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c36
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c221
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h50
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c23
-rw-r--r--drivers/gpu/drm/amd/amdgpu/atombios_encoders.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ci_dpm.c64
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik_sdma.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/clearstate_si.h (renamed from drivers/gpu/drm/amd/include/asic_reg/si/clearstate_si.h)0
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cz_dpm.c2320
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cz_dpm.h239
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cz_smc.c995
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cz_smumgr.h94
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v10_0.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v11_0.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v6_0.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v8_0.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c227
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c898
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c25
-rw-r--r--drivers/gpu/drm/amd/amdgpu/kv_dpm.c132
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c592
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mxgpu_vi.h55
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c19
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si.c1072
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_dma.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_dpm.c67
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_enums.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_ih.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_smc.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sid.h (renamed from drivers/gpu/drm/amd/include/asic_reg/si/sid.h)0
-rw-r--r--drivers/gpu/drm/amd/amdgpu/smu_ucode_xfer_vi.h101
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c133
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c56
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c53
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v2_0.c451
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v3_0.c69
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vi.c157
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vi.h112
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vi_dpm.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vid.h2
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_chardev.c6
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_events.c4
-rw-r--r--drivers/gpu/drm/amd/include/amd_shared.h14
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dce/dce_10_0_d.h8
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dce/dce_10_0_sh_mask.h4
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_0_d.h9
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_0_sh_mask.h6
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_d.h9
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_sh_mask.h6
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dce/dce_8_0_d.h8
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dce/dce_8_0_sh_mask.h4
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/si/si_reg.h105
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_0_1_d.h1
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_0_1_sh_mask.h2
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_1_d.h1
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_1_sh_mask.h2
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_d.h1
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_sh_mask.h2
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_d.h2
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_sh_mask.h3
-rw-r--r--drivers/gpu/drm/amd/include/cgs_common.h8
-rw-r--r--drivers/gpu/drm/amd/powerplay/amd_powerplay.c741
-rw-r--r--drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.c2
-rw-r--r--drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c9
-rw-r--r--drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c5
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c86
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c99
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.h1
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c14
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c2
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c175
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c30
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h3
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c6
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c2
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c23
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.h2
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c241
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h2
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c378
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c28
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.h1
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h20
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/eventmgr.h3
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/hwmgr.h21
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/pp_debug.h10
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/pp_instance.h5
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/smu7_ppsmc.h3
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/smumgr.h20
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c181
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.h4
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c6
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c44
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c10
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c32
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c12
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c36
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c16
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c43
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c16
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c32
-rw-r--r--drivers/gpu/drm/arc/arcpgu_crtc.c3
-rw-r--r--drivers/gpu/drm/arc/arcpgu_drv.c3
-rw-r--r--drivers/gpu/drm/arc/arcpgu_hdmi.c5
-rw-r--r--drivers/gpu/drm/arm/hdlcd_crtc.c18
-rw-r--r--drivers/gpu/drm/arm/hdlcd_drv.c9
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.c76
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.h2
-rw-r--r--drivers/gpu/drm/arm/malidp_hw.c41
-rw-r--r--drivers/gpu/drm/arm/malidp_hw.h13
-rw-r--r--drivers/gpu/drm/arm/malidp_planes.c102
-rw-r--r--drivers/gpu/drm/arm/malidp_regs.h8
-rw-r--r--drivers/gpu/drm/armada/Kconfig2
-rw-r--r--drivers/gpu/drm/armada/Makefile2
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.c9
-rw-r--r--drivers/gpu/drm/armada/armada_debugfs.c6
-rw-r--r--drivers/gpu/drm/armada/armada_drv.c6
-rw-r--r--drivers/gpu/drm/armada/armada_fb.c2
-rw-r--r--drivers/gpu/drm/armada/armada_fbdev.c7
-rw-r--r--drivers/gpu/drm/armada/armada_gem.c4
-rw-r--r--drivers/gpu/drm/armada/armada_overlay.c4
-rw-r--r--drivers/gpu/drm/ast/Kconfig2
-rw-r--r--drivers/gpu/drm/ast/ast_drv.h3
-rw-r--r--drivers/gpu/drm/ast/ast_fb.c7
-rw-r--r--drivers/gpu/drm/ast/ast_main.c5
-rw-r--r--drivers/gpu/drm/ast/ast_mode.c16
-rw-r--r--drivers/gpu/drm/ast/ast_ttm.c2
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c17
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_layer.c2
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c4
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c22
-rw-r--r--drivers/gpu/drm/bochs/Kconfig2
-rw-r--r--drivers/gpu/drm/bochs/bochs.h1
-rw-r--r--drivers/gpu/drm/bochs/bochs_drv.c13
-rw-r--r--drivers/gpu/drm/bochs/bochs_fbdev.c5
-rw-r--r--drivers/gpu/drm/bochs/bochs_mm.c4
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511.h6
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_drv.c153
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_core.c9
-rw-r--r--drivers/gpu/drm/bridge/dumb-vga-dac.c1
-rw-r--r--drivers/gpu/drm/bridge/dw-hdmi.c441
-rw-r--r--drivers/gpu/drm/bridge/dw-hdmi.h85
-rw-r--r--drivers/gpu/drm/bridge/sil-sii8620.c949
-rw-r--r--drivers/gpu/drm/bridge/sil-sii8620.h50
-rw-r--r--drivers/gpu/drm/cirrus/Kconfig2
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_drv.h3
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_fbdev.c8
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_main.c7
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_mode.c9
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_ttm.c2
-rw-r--r--drivers/gpu/drm/drm_agpsupport.c2
-rw-r--r--drivers/gpu/drm/drm_atomic.c141
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c362
-rw-r--r--drivers/gpu/drm/drm_auth.c12
-rw-r--r--drivers/gpu/drm/drm_blend.c11
-rw-r--r--drivers/gpu/drm/drm_bridge.c88
-rw-r--r--drivers/gpu/drm/drm_cache.c27
-rw-r--r--drivers/gpu/drm/drm_color_mgmt.c28
-rw-r--r--drivers/gpu/drm/drm_connector.c228
-rw-r--r--drivers/gpu/drm/drm_crtc.c83
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c85
-rw-r--r--drivers/gpu/drm/drm_crtc_internal.h11
-rw-r--r--drivers/gpu/drm/drm_debugfs.c30
-rw-r--r--drivers/gpu/drm/drm_debugfs_crc.c34
-rw-r--r--drivers/gpu/drm/drm_dp_helper.c2
-rw-r--r--drivers/gpu/drm/drm_dp_mst_topology.c6
-rw-r--r--drivers/gpu/drm/drm_drv.c98
-rw-r--r--drivers/gpu/drm/drm_dumb_buffers.c4
-rw-r--r--drivers/gpu/drm/drm_edid.c80
-rw-r--r--drivers/gpu/drm/drm_encoder.c23
-rw-r--r--drivers/gpu/drm/drm_encoder_slave.c2
-rw-r--r--drivers/gpu/drm/drm_fb_cma_helper.c135
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c96
-rw-r--r--drivers/gpu/drm/drm_fops.c15
-rw-r--r--drivers/gpu/drm/drm_framebuffer.c71
-rw-r--r--drivers/gpu/drm/drm_gem.c24
-rw-r--r--drivers/gpu/drm/drm_gem_cma_helper.c93
-rw-r--r--drivers/gpu/drm/drm_global.c23
-rw-r--r--drivers/gpu/drm/drm_internal.h9
-rw-r--r--drivers/gpu/drm/drm_ioctl.c34
-rw-r--r--drivers/gpu/drm/drm_irq.c75
-rw-r--r--drivers/gpu/drm/drm_legacy.h7
-rw-r--r--drivers/gpu/drm/drm_mm.c1023
-rw-r--r--drivers/gpu/drm/drm_mode_config.c150
-rw-r--r--drivers/gpu/drm/drm_mode_object.c3
-rw-r--r--drivers/gpu/drm/drm_modes.c28
-rw-r--r--drivers/gpu/drm/drm_modeset_helper.c25
-rw-r--r--drivers/gpu/drm/drm_modeset_lock.c10
-rw-r--r--drivers/gpu/drm/drm_of.c1
-rw-r--r--drivers/gpu/drm/drm_panel.c2
-rw-r--r--drivers/gpu/drm/drm_pci.c8
-rw-r--r--drivers/gpu/drm/drm_plane.c20
-rw-r--r--drivers/gpu/drm/drm_plane_helper.c17
-rw-r--r--drivers/gpu/drm/drm_platform.c6
-rw-r--r--drivers/gpu/drm/drm_prime.c19
-rw-r--r--drivers/gpu/drm/drm_print.c6
-rw-r--r--drivers/gpu/drm/drm_probe_helper.c85
-rw-r--r--drivers/gpu/drm/drm_property.c6
-rw-r--r--drivers/gpu/drm/drm_rect.c6
-rw-r--r--drivers/gpu/drm/drm_simple_kms_helper.c23
-rw-r--r--drivers/gpu/drm/drm_sysfs.c2
-rw-r--r--drivers/gpu/drm/drm_vma_manager.c3
-rw-r--r--drivers/gpu/drm/etnaviv/Kconfig3
-rw-r--r--drivers/gpu/drm/etnaviv/Makefile1
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_buffer.c14
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c6
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c153
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.h58
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_drv.c24
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_dump.c6
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c8
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.c95
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.h28
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_iommu.c2
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c6
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_mmu.c76
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_mmu.h10
-rw-r--r--drivers/gpu/drm/exynos/Kconfig2
-rw-r--r--drivers/gpu/drm/exynos/exynos5433_drm_decon.c100
-rw-r--r--drivers/gpu/drm/exynos/exynos7_drm_decon.c8
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp.c5
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c34
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.h4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c118
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h10
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c6
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c34
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c15
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c6
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_g2d.c19
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_mic.c126
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c80
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c14
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c13
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h2
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c4
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c5
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_tcon.c12
-rw-r--r--drivers/gpu/drm/gma500/Kconfig2
-rw-r--r--drivers/gpu/drm/gma500/accel_2d.c2
-rw-r--r--drivers/gpu/drm/gma500/framebuffer.c8
-rw-r--r--drivers/gpu/drm/gma500/gma_display.c13
-rw-r--r--drivers/gpu/drm/gma500/mdfld_intel_display.c17
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_crtc.c13
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.c9
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_drv.h1
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/Kconfig2
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c6
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c7
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c4
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c5
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c27
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c15
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h5
-rw-r--r--drivers/gpu/drm/i810/i810_dma.c24
-rw-r--r--drivers/gpu/drm/i810/i810_drv.c1
-rw-r--r--drivers/gpu/drm/i810/i810_drv.h1
-rw-r--r--drivers/gpu/drm/i915/Kconfig.debug15
-rw-r--r--drivers/gpu/drm/i915/Makefile11
-rw-r--r--drivers/gpu/drm/i915/gvt/aperture_gm.c43
-rw-r--r--drivers/gpu/drm/i915/gvt/cmd_parser.c25
-rw-r--r--drivers/gpu/drm/i915/gvt/display.c31
-rw-r--r--drivers/gpu/drm/i915/gvt/display.h1
-rw-r--r--drivers/gpu/drm/i915/gvt/execlist.c2
-rw-r--r--drivers/gpu/drm/i915/gvt/firmware.c47
-rw-r--r--drivers/gpu/drm/i915/gvt/gtt.c70
-rw-r--r--drivers/gpu/drm/i915/gvt/gvt.c7
-rw-r--r--drivers/gpu/drm/i915/gvt/handlers.c2
-rw-r--r--drivers/gpu/drm/i915/gvt/hypercall.h1
-rw-r--r--drivers/gpu/drm/i915/gvt/interrupt.c57
-rw-r--r--drivers/gpu/drm/i915/gvt/kvmgt.c108
-rw-r--r--drivers/gpu/drm/i915/gvt/mpt.h12
-rw-r--r--drivers/gpu/drm/i915/gvt/render.c17
-rw-r--r--drivers/gpu/drm/i915/gvt/sched_policy.c1
-rw-r--r--drivers/gpu/drm/i915/gvt/scheduler.c15
-rw-r--r--drivers/gpu/drm/i915/gvt/vgpu.c14
-rw-r--r--drivers/gpu/drm/i915/i915_cmd_parser.c174
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c1150
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c218
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h925
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c525
-rw-r--r--drivers/gpu/drm/i915/i915_gem.h4
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.c297
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.h277
-rw-r--r--drivers/gpu/drm/i915/i915_gem_dmabuf.c2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_evict.c172
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c20
-rw-r--r--drivers/gpu/drm/i915/i915_gem_fence_reg.c100
-rw-r--r--drivers/gpu/drm/i915/i915_gem_fence_reg.h2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c617
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.h95
-rw-r--r--drivers/gpu/drm/i915/i915_gem_internal.c49
-rw-r--r--drivers/gpu/drm/i915/i915_gem_object.h23
-rw-r--r--drivers/gpu/drm/i915/i915_gem_render_state.c6
-rw-r--r--drivers/gpu/drm/i915/i915_gem_request.c113
-rw-r--r--drivers/gpu/drm/i915/i915_gem_request.h11
-rw-r--r--drivers/gpu/drm/i915/i915_gem_stolen.c146
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c347
-rw-r--r--drivers/gpu/drm/i915/i915_gem_timeline.c16
-rw-r--r--drivers/gpu/drm/i915/i915_gem_timeline.h2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_userptr.c2
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c116
-rw-r--r--drivers/gpu/drm/i915/i915_guc_reg.h13
-rw-r--r--drivers/gpu/drm/i915/i915_guc_submission.c959
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c169
-rw-r--r--drivers/gpu/drm/i915/i915_oa_hsw.c752
-rw-r--r--drivers/gpu/drm/i915/i915_oa_hsw.h38
-rw-r--r--drivers/gpu/drm/i915/i915_params.c6
-rw-r--r--drivers/gpu/drm/i915/i915_params.h2
-rw-r--r--drivers/gpu/drm/i915/i915_pci.c183
-rw-r--r--drivers/gpu/drm/i915/i915_perf.c2096
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h488
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c16
-rw-r--r--drivers/gpu/drm/i915/i915_sw_fence.c141
-rw-r--r--drivers/gpu/drm/i915/i915_sw_fence.h6
-rw-r--r--drivers/gpu/drm/i915/i915_sysfs.c6
-rw-r--r--drivers/gpu/drm/i915/i915_trace.h34
-rw-r--r--drivers/gpu/drm/i915/i915_utils.h64
-rw-r--r--drivers/gpu/drm/i915/i915_vgpu.c33
-rw-r--r--drivers/gpu/drm/i915/i915_vma.c266
-rw-r--r--drivers/gpu/drm/i915/i915_vma.h59
-rw-r--r--drivers/gpu/drm/i915/intel_atomic.c31
-rw-r--r--drivers/gpu/drm/i915/intel_atomic_plane.c51
-rw-r--r--drivers/gpu/drm/i915/intel_audio.c39
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c27
-rw-r--r--drivers/gpu/drm/i915/intel_breadcrumbs.c10
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c7
-rw-r--r--drivers/gpu/drm/i915/intel_csr.c16
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c70
-rw-r--r--drivers/gpu/drm/i915/intel_device_info.c55
-rw-r--r--drivers/gpu/drm/i915/intel_display.c827
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c366
-rw-r--r--drivers/gpu/drm/i915/intel_dp_mst.c31
-rw-r--r--drivers/gpu/drm/i915/intel_dpio_phy.c130
-rw-r--r--drivers/gpu/drm/i915/intel_dpll_mgr.c351
-rw-r--r--drivers/gpu/drm/i915/intel_dpll_mgr.h178
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h111
-rw-r--r--drivers/gpu/drm/i915/intel_dsi.c46
-rw-r--r--drivers/gpu/drm/i915/intel_dsi_panel_vbt.c38
-rw-r--r--drivers/gpu/drm/i915/intel_dsi_pll.c18
-rw-r--r--drivers/gpu/drm/i915/intel_dvo.c9
-rw-r--r--drivers/gpu/drm/i915/intel_engine_cs.c30
-rw-r--r--drivers/gpu/drm/i915/intel_fbc.c20
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c19
-rw-r--r--drivers/gpu/drm/i915/intel_guc_fwif.h79
-rw-r--r--drivers/gpu/drm/i915/intel_guc_loader.c255
-rw-r--r--drivers/gpu/drm/i915/intel_guc_log.c658
-rw-r--r--drivers/gpu/drm/i915/intel_gvt.c5
-rw-r--r--drivers/gpu/drm/i915/intel_hangcheck.c256
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c198
-rw-r--r--drivers/gpu/drm/i915/intel_hotplug.c4
-rw-r--r--drivers/gpu/drm/i915/intel_huc.c338
-rw-r--r--drivers/gpu/drm/i915/intel_i2c.c22
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.c259
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.h11
-rw-r--r--drivers/gpu/drm/i915/intel_lspcon.c99
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c8
-rw-r--r--drivers/gpu/drm/i915/intel_mocs.c7
-rw-r--r--drivers/gpu/drm/i915/intel_mocs.h2
-rw-r--r--drivers/gpu/drm/i915/intel_opregion.c13
-rw-r--r--drivers/gpu/drm/i915/intel_overlay.c289
-rw-r--r--drivers/gpu/drm/i915/intel_panel.c32
-rw-r--r--drivers/gpu/drm/i915/intel_pipe_crc.c1011
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c843
-rw-r--r--drivers/gpu/drm/i915/intel_psr.c209
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c155
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h66
-rw-r--r--drivers/gpu/drm/i915/intel_runtime_pm.c163
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c21
-rw-r--r--drivers/gpu/drm/i915/intel_sprite.c131
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c4
-rw-r--r--drivers/gpu/drm/i915/intel_uc.c116
-rw-r--r--drivers/gpu/drm/i915/intel_uc.h (renamed from drivers/gpu/drm/i915/intel_guc.h)108
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c14
-rw-r--r--drivers/gpu/drm/i915/intel_vbt_defs.h12
-rw-r--r--drivers/gpu/drm/imx/dw_hdmi-imx.c14
-rw-r--r--drivers/gpu/drm/imx/imx-drm-core.c7
-rw-r--r--drivers/gpu/drm/imx/imx-ldb.c8
-rw-r--r--drivers/gpu/drm/imx/imx-tve.c18
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.c40
-rw-r--r--drivers/gpu/drm/imx/parallel-display.c6
-rw-r--r--drivers/gpu/drm/lib/drm_random.c41
-rw-r--r--drivers/gpu/drm/lib/drm_random.h25
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dpi.c8
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_crtc.c9
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.c3
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.h1
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_fb.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_plane.c4
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dsi.c24
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi.c11
-rw-r--r--drivers/gpu/drm/meson/Makefile6
-rw-r--r--drivers/gpu/drm/meson/meson_drv.c4
-rw-r--r--drivers/gpu/drm/meson/meson_plane.c2
-rw-r--r--drivers/gpu/drm/mga/mga_dma.c24
-rw-r--r--drivers/gpu/drm/mga/mga_drv.c37
-rw-r--r--drivers/gpu/drm/mga/mga_drv.h2
-rw-r--r--drivers/gpu/drm/mgag200/Kconfig2
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.c1
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.h4
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_fb.c6
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_i2c.c1
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_main.c9
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c100
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_ttm.c2
-rw-r--r--drivers/gpu/drm/msm/Kconfig8
-rw-r--r--drivers/gpu/drm/msm/Makefile2
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c21
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c62
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c1
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h4
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.c18
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.h51
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.xml.h269
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_cfg.c25
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_cfg.h1
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c97
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c257
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.c239
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.h20
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c169
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c5
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c6
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c5
-rw-r--r--drivers/gpu/drm/msm/dsi/pll/dsi_pll.c12
-rw-r--r--drivers/gpu/drm/msm/dsi/pll/dsi_pll.h11
-rw-r--r--drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c1104
-rw-r--r--drivers/gpu/drm/msm/edp/edp_bridge.c2
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_bridge.c2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c28
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h48
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c10
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h3
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c135
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c73
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c14
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h4
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c77
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c123
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h45
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c8
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c183
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_kms.h1
-rw-r--r--drivers/gpu/drm/msm/msm_atomic.c26
-rw-r--r--drivers/gpu/drm/msm/msm_debugfs.c6
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c20
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h12
-rw-r--r--drivers/gpu/drm/msm/msm_fb.c12
-rw-r--r--drivers/gpu/drm/msm/msm_fbdev.c10
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c3
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c13
-rw-r--r--drivers/gpu/drm/msm/msm_gem_vma.c3
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c7
-rw-r--r--drivers/gpu/drm/msm/msm_iommu.c7
-rw-r--r--drivers/gpu/drm/msm/msm_kms.h3
-rw-r--r--drivers/gpu/drm/msm/msm_mmu.h9
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_crtc.c2
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_drv.c6
-rw-r--r--drivers/gpu/drm/nouveau/Kconfig3
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/arb.c6
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/crtc.c60
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/cursor.c2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/dac.c18
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/dfp.c15
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/disp.c6
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/disp.h6
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/hw.c80
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/hw.h42
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/overlay.c24
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvnv04.c4
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvnv17.c16
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvnv17.h4
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl826e.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl826f.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl906f.h3
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cla06f.h3
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/class.h30
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/client.h3
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/driver.h6
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if0000.h11
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/client.h20
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/device.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/engine.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/memory.h7
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/mm.h8
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/object.h5
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h6
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h76
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/power_budget.h26
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/iccsense.h3
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h3
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/secboot.h17
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h6
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_abi16.c8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_backlight.c24
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c18
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c358
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.h4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.c30
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.h5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c25
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_debugfs.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c60
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c177
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c30
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c20
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_hwmon.c110
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_led.c7
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_nvif.c24
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_prime.c3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_sgdma.c14
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_ttm.c104
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_usif.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vga.c8
-rw-r--r--drivers/gpu/drm/nouveau/nv04_fbcon.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv17_fence.c8
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c50
-rw-r--r--drivers/gpu/drm/nouveau/nv50_fence.c8
-rw-r--r--drivers/gpu/drm/nouveau/nv84_fence.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvif/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvif/client.c49
-rw-r--r--drivers/gpu/drm/nouveau/nvif/driver.c58
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/client.c170
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/engine.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/ioctl.c78
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/mm.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/object.c64
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/base.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/dma/base.c42
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/dma/user.c19
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c75
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c266
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c19
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c20
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/g84.c12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c307
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gt200.c12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gt215.c14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/mcp79.c12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/mcp89.c14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/base.c191
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/priv.h8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/v1.c266
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/power_budget.c126
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c23
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c20
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c19
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/g92.c57
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/g94.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf106.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c19
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c94
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c34
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/Kbuild4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.c54
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h69
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c936
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.h250
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c138
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c254
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c1391
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h43
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c126
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode.h151
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_gr.c158
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h199
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c22
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/top/base.c14
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c2
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c1
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dispc.c46
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dsi.c18
-rw-r--r--drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c3
-rw-r--r--drivers/gpu/drm/omapdrm/dss/omapdss.h1
-rw-r--r--drivers/gpu/drm/omapdrm/omap_connector.c6
-rw-r--r--drivers/gpu/drm/omapdrm/omap_crtc.c148
-rw-r--r--drivers/gpu/drm/omapdrm/omap_debugfs.c15
-rw-r--r--drivers/gpu/drm/omapdrm/omap_dmm_tiler.c4
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c232
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.h52
-rw-r--r--drivers/gpu/drm/omapdrm/omap_encoder.c2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fb.c176
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fbdev.c13
-rw-r--r--drivers/gpu/drm/omapdrm/omap_irq.c242
-rw-r--r--drivers/gpu/drm/omapdrm/omap_plane.c24
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c102
-rw-r--r--drivers/gpu/drm/qxl/Kconfig2
-rw-r--r--drivers/gpu/drm/qxl/qxl_debugfs.c16
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c35
-rw-r--r--drivers/gpu/drm/qxl/qxl_draw.c2
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.c57
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.h11
-rw-r--r--drivers/gpu/drm/qxl/qxl_fb.c16
-rw-r--r--drivers/gpu/drm/qxl/qxl_ioctl.c4
-rw-r--r--drivers/gpu/drm/qxl/qxl_irq.c2
-rw-r--r--drivers/gpu/drm/qxl/qxl_kms.c70
-rw-r--r--drivers/gpu/drm/qxl/qxl_object.c18
-rw-r--r--drivers/gpu/drm/qxl/qxl_object.h8
-rw-r--r--drivers/gpu/drm/qxl/qxl_ttm.c19
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c19
-rw-r--r--drivers/gpu/drm/radeon/r100.c10
-rw-r--r--drivers/gpu/drm/radeon/radeon_bios.c64
-rw-r--r--drivers/gpu/drm/radeon/radeon_cs.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c16
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c8
-rw-r--r--drivers/gpu/drm/radeon/radeon_dp_mst.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c5
-rw-r--r--drivers/gpu/drm/radeon/radeon_irq_kms.c12
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c7
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_crtc.c16
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_ttm.c10
-rw-r--r--drivers/gpu/drm/radeon/si_dpm.c47
-rw-r--r--drivers/gpu/drm/radeon/vce_v1_0.c2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_encoder.h1
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c5
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_kms.c2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_plane.c4
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_vsp.c4
-rw-r--r--drivers/gpu/drm/rockchip/Kconfig10
-rw-r--r--drivers/gpu/drm/rockchip/Makefile2
-rw-r--r--drivers/gpu/drm/rockchip/cdn-dp-core.c1260
-rw-r--r--drivers/gpu/drm/rockchip/cdn-dp-core.h112
-rw-r--r--drivers/gpu/drm/rockchip/cdn-dp-reg.c979
-rw-r--r--drivers/gpu/drm/rockchip/cdn-dp-reg.h483
-rw-r--r--drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c14
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c118
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.h6
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_fb.c4
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c10
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_gem.c244
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_gem.h8
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c39
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.h9
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_vop_reg.c2
-rw-r--r--drivers/gpu/drm/savage/savage_bci.c4
-rw-r--r--drivers/gpu/drm/savage/savage_drv.h2
-rw-r--r--drivers/gpu/drm/selftests/Makefile1
-rw-r--r--drivers/gpu/drm/selftests/drm_mm_selftests.h24
-rw-r--r--drivers/gpu/drm/selftests/drm_selftest.c109
-rw-r--r--drivers/gpu/drm/selftests/drm_selftest.h41
-rw-r--r--drivers/gpu/drm/selftests/test-drm_mm.c2276
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_crtc.c6
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_crtc.h1
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_drv.c4
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_plane.c4
-rw-r--r--drivers/gpu/drm/sis/sis_drv.c4
-rw-r--r--drivers/gpu/drm/sis/sis_mm.c6
-rw-r--r--drivers/gpu/drm/sti/Makefile1
-rw-r--r--drivers/gpu/drm/sti/sti_crtc.c46
-rw-r--r--drivers/gpu/drm/sti/sti_drv.c162
-rw-r--r--drivers/gpu/drm/sti/sti_drv.h7
-rw-r--r--drivers/gpu/drm/sti/sti_dvo.c13
-rw-r--r--drivers/gpu/drm/sti/sti_gdp.c95
-rw-r--r--drivers/gpu/drm/sti/sti_hda.c14
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi.c257
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi.h17
-rw-r--r--drivers/gpu/drm/sti/sti_hqvdp.c31
-rw-r--r--drivers/gpu/drm/sti/sti_mixer.h2
-rw-r--r--drivers/gpu/drm/sti/sti_plane.c17
-rw-r--r--drivers/gpu/drm/sti/sti_plane.h2
-rw-r--r--drivers/gpu/drm/sti/sti_tvout.c8
-rw-r--r--drivers/gpu/drm/sti/sti_vtac.c223
-rw-r--r--drivers/gpu/drm/sti/sti_vtg.c63
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.c7
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_framebuffer.c4
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_rgb.c13
-rw-r--r--drivers/gpu/drm/tegra/dc.c8
-rw-r--r--drivers/gpu/drm/tegra/drm.c46
-rw-r--r--drivers/gpu/drm/tegra/drm.h1
-rw-r--r--drivers/gpu/drm/tegra/fb.c15
-rw-r--r--drivers/gpu/drm/tegra/gem.c4
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_crtc.c4
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c19
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.h2
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_external.c4
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_plane.c4
-rw-r--r--drivers/gpu/drm/tinydrm/Kconfig21
-rw-r--r--drivers/gpu/drm/tinydrm/Makefile7
-rw-r--r--drivers/gpu/drm/tinydrm/core/Makefile3
-rw-r--r--drivers/gpu/drm/tinydrm/core/tinydrm-core.c376
-rw-r--r--drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c460
-rw-r--r--drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c234
-rw-r--r--drivers/gpu/drm/tinydrm/mi0283qt.c279
-rw-r--r--drivers/gpu/drm/tinydrm/mipi-dbi.c1005
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c129
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_manager.c31
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_vm.c12
-rw-r--r--drivers/gpu/drm/udl/udl_drv.h2
-rw-r--r--drivers/gpu/drm/udl/udl_fb.c9
-rw-r--r--drivers/gpu/drm/udl/udl_main.c3
-rw-r--r--drivers/gpu/drm/vc4/Kconfig2
-rw-r--r--drivers/gpu/drm/vc4/Makefile1
-rw-r--r--drivers/gpu/drm/vc4/vc4_crtc.c52
-rw-r--r--drivers/gpu/drm/vc4/vc4_debugfs.c7
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.h9
-rw-r--r--drivers/gpu/drm/vc4/vc4_dsi.c1725
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c18
-rw-r--r--drivers/gpu/drm/vc4/vc4_hvs.c17
-rw-r--r--drivers/gpu/drm/vc4/vc4_kms.c1
-rw-r--r--drivers/gpu/drm/vc4/vc4_plane.c14
-rw-r--r--drivers/gpu/drm/vc4/vc4_regs.h5
-rw-r--r--drivers/gpu/drm/vgem/vgem_drv.h1
-rw-r--r--drivers/gpu/drm/vgem/vgem_fence.c4
-rw-r--r--drivers/gpu/drm/via/via_drv.h2
-rw-r--r--drivers/gpu/drm/via/via_map.c4
-rw-r--r--drivers/gpu/drm/via/via_mm.c4
-rw-r--r--drivers/gpu/drm/virtio/Kconfig2
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_display.c3
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drm_bus.c4
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h3
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_fb.c5
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_kms.c9
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_ttm.c13
-rw-r--r--drivers/gpu/drm/vmwgfx/Kconfig2
-rw-r--r--drivers/gpu/drm/vmwgfx/device_include/svga3d_surfacedefs.h2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c5
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c10
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c6
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fb.c11
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c10
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c8
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.h1
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c5
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_mob.c7
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource.c4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c2
-rw-r--r--drivers/gpu/drm/zte/Kconfig2
-rw-r--r--drivers/gpu/drm/zte/Makefile1
-rw-r--r--drivers/gpu/drm/zte/zx_drm_drv.c3
-rw-r--r--drivers/gpu/drm/zte/zx_drm_drv.h1
-rw-r--r--drivers/gpu/drm/zte/zx_hdmi.c160
-rw-r--r--drivers/gpu/drm/zte/zx_hdmi_regs.h14
-rw-r--r--drivers/gpu/drm/zte/zx_plane.c332
-rw-r--r--drivers/gpu/drm/zte/zx_plane.h12
-rw-r--r--drivers/gpu/drm/zte/zx_plane_regs.h51
-rw-r--r--drivers/gpu/drm/zte/zx_tvenc.c407
-rw-r--r--drivers/gpu/drm/zte/zx_tvenc_regs.h31
-rw-r--r--drivers/gpu/drm/zte/zx_vou.c371
-rw-r--r--drivers/gpu/drm/zte/zx_vou.h48
-rw-r--r--drivers/gpu/drm/zte/zx_vou_regs.h51
-rw-r--r--drivers/gpu/host1x/bus.c1
-rw-r--r--drivers/gpu/ipu-v3/ipu-common.c6
-rw-r--r--drivers/gpu/ipu-v3/ipu-csi.c1
-rw-r--r--drivers/video/fbdev/Kconfig8
-rw-r--r--drivers/video/fbdev/core/fbmem.c18
-rw-r--r--include/drm/bridge/dw_hdmi.h19
-rw-r--r--include/drm/bridge/mhl.h85
-rw-r--r--include/drm/drmP.h34
-rw-r--r--include/drm/drm_atomic.h37
-rw-r--r--include/drm/drm_atomic_helper.h22
-rw-r--r--include/drm/drm_auth.h17
-rw-r--r--include/drm/drm_bridge.h46
-rw-r--r--include/drm/drm_cache.h4
-rw-r--r--include/drm/drm_color_mgmt.h27
-rw-r--r--include/drm/drm_connector.h107
-rw-r--r--include/drm/drm_crtc.h98
-rw-r--r--include/drm/drm_crtc_helper.h1
-rw-r--r--include/drm/drm_dp_helper.h13
-rw-r--r--include/drm/drm_dp_mst_helper.h14
-rw-r--r--include/drm/drm_drv.h79
-rw-r--r--include/drm/drm_edid.h10
-rw-r--r--include/drm/drm_encoder.h9
-rw-r--r--include/drm/drm_encoder_slave.h1
-rw-r--r--include/drm/drm_fb_cma_helper.h12
-rw-r--r--include/drm/drm_fb_helper.h10
-rw-r--r--include/drm/drm_flip_work.h2
-rw-r--r--include/drm/drm_framebuffer.h46
-rw-r--r--include/drm/drm_gem.h16
-rw-r--r--include/drm/drm_gem_cma_helper.h17
-rw-r--r--include/drm/drm_irq.h8
-rw-r--r--include/drm/drm_mm.h443
-rw-r--r--include/drm/drm_mode_config.h30
-rw-r--r--include/drm/drm_mode_object.h13
-rw-r--r--include/drm/drm_modes.h2
-rw-r--r--include/drm/drm_modeset_helper.h3
-rw-r--r--include/drm/drm_modeset_helper_vtables.h147
-rw-r--r--include/drm/drm_modeset_lock.h2
-rw-r--r--include/drm/drm_panel.h4
-rw-r--r--include/drm/drm_plane.h28
-rw-r--r--include/drm/drm_print.h24
-rw-r--r--include/drm/drm_property.h8
-rw-r--r--include/drm/drm_simple_kms_helper.h18
-rw-r--r--include/drm/i915_pciids.h21
-rw-r--r--include/drm/intel-gtt.h6
-rw-r--r--include/drm/tinydrm/ili9341.h54
-rw-r--r--include/drm/tinydrm/mipi-dbi.h107
-rw-r--r--include/drm/tinydrm/tinydrm-helpers.h81
-rw-r--r--include/drm/tinydrm/tinydrm.h115
-rw-r--r--include/drm/ttm/ttm_bo_api.h2
-rw-r--r--include/drm/ttm/ttm_bo_driver.h31
-rw-r--r--include/linux/dma-buf.h224
-rw-r--r--include/linux/dma-fence.h52
-rw-r--r--include/linux/prime_numbers.h37
-rw-r--r--include/linux/reservation.h34
-rw-r--r--include/uapi/drm/Kbuild1
-rw-r--r--include/uapi/drm/amdgpu_drm.h9
-rw-r--r--include/uapi/drm/drm_fourcc.h59
-rw-r--r--include/uapi/drm/i915_drm.h136
-rw-r--r--include/uapi/linux/Kbuild1
-rw-r--r--include/video/exynos5433_decon.h2
-rw-r--r--lib/Kconfig3
-rw-r--r--lib/Makefile2
-rw-r--r--lib/prime_numbers.c315
-rw-r--r--sound/pci/hda/hda_codec.c76
-rw-r--r--sound/pci/hda/hda_codec.h3
-rw-r--r--sound/pci/hda/patch_hdmi.c245
-rwxr-xr-xtools/testing/selftests/drivers/gpu/drm_mm.sh15
-rwxr-xr-xtools/testing/selftests/lib/prime_numbers.sh15
923 files changed, 46348 insertions, 22490 deletions
diff --git a/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt b/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt
index e276870..34c7fdd 100644
--- a/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt
+++ b/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt
@@ -56,6 +56,18 @@ Required properties for V3D:
- interrupts: The interrupt number
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
+Required properties for DSI:
+- compatible: Should be "brcm,bcm2835-dsi0" or "brcm,bcm2835-dsi1"
+- reg: Physical base address and length of the DSI block's registers
+- interrupts: The interrupt number
+ See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
+- clocks: a) phy: The DSI PLL clock feeding the DSI analog PHY
+ b) escape: The DSI ESC clock from CPRMAN
+ c) pixel: The DSI pixel clock from CPRMAN
+- clock-output-names:
+ The 3 clocks output from the DSI analog PHY: dsi[01]_byte,
+ dsi[01]_ddr2, and dsi[01]_ddr
+
[1] Documentation/devicetree/bindings/media/video-interfaces.txt
Example:
@@ -99,6 +111,29 @@ dpi: dpi@7e208000 {
};
};
+dsi1: dsi@7e700000 {
+ compatible = "brcm,bcm2835-dsi1";
+ reg = <0x7e700000 0x8c>;
+ interrupts = <2 12>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #clock-cells = <1>;
+
+ clocks = <&clocks BCM2835_PLLD_DSI1>,
+ <&clocks BCM2835_CLOCK_DSI1E>,
+ <&clocks BCM2835_CLOCK_DSI1P>;
+ clock-names = "phy", "escape", "pixel";
+
+ clock-output-names = "dsi1_byte", "dsi1_ddr2", "dsi1_ddr";
+
+ pitouchscreen: panel@0 {
+ compatible = "raspberrypi,touchscreen";
+ reg = <0>;
+
+ <...>
+ };
+};
+
vec: vec@7e806000 {
compatible = "brcm,bcm2835-vec";
reg = <0x7e806000 0x1000>;
diff --git a/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt b/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt
index 6532a59..00ea670 100644
--- a/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt
+++ b/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt
@@ -38,10 +38,22 @@ The following input format properties are required except in "rgb 1x" and
- adi,input-justification: The input bit justification ("left", "evenly",
"right").
+- avdd-supply: A 1.8V supply that powers up the AVDD pin on the chip.
+- dvdd-supply: A 1.8V supply that powers up the DVDD pin on the chip.
+- pvdd-supply: A 1.8V supply that powers up the PVDD pin on the chip.
+- dvdd-3v-supply: A 3.3V supply that powers up the pin called DVDD_3V
+ on the chip.
+- bgvdd-supply: A 1.8V supply that powers up the BGVDD pin. This is
+ needed only for ADV7511.
+
The following properties are required for ADV7533:
- adi,dsi-lanes: Number of DSI data lanes connected to the DSI host. It should
be one of 1, 2, 3 or 4.
+- a2vdd-supply: 1.8V supply that powers up the A2VDD pin on the chip.
+- v3p3-supply: A 3.3V supply that powers up the V3P3 pin on the chip.
+- v1p2-supply: A supply that powers up the V1P2 pin on the chip. It can be
+ either 1.2V or 1.8V.
Optional properties:
diff --git a/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt b/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt
index 5e9a84d..33bf981 100644
--- a/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt
+++ b/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt
@@ -1,52 +1,33 @@
-DesignWare HDMI bridge bindings
-
-Required properties:
-- compatible: platform specific such as:
- * "snps,dw-hdmi-tx"
- * "fsl,imx6q-hdmi"
- * "fsl,imx6dl-hdmi"
- * "rockchip,rk3288-dw-hdmi"
-- reg: Physical base address and length of the controller's registers.
-- interrupts: The HDMI interrupt number
-- clocks, clock-names : must have the phandles to the HDMI iahb and isfr clocks,
- as described in Documentation/devicetree/bindings/clock/clock-bindings.txt,
- the clocks are soc specific, the clock-names should be "iahb", "isfr"
--port@[X]: SoC specific port nodes with endpoint definitions as defined
- in Documentation/devicetree/bindings/media/video-interfaces.txt,
- please refer to the SoC specific binding document:
- * Documentation/devicetree/bindings/display/imx/hdmi.txt
- * Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
-
-Optional properties
-- reg-io-width: the width of the reg:1,4, default set to 1 if not present
-- ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing,
- if the property is omitted, a functionally reduced I2C bus
- controller on DW HDMI is probed
-- clocks, clock-names: phandle to the HDMI CEC clock, name should be "cec"
-
-Example:
- hdmi: hdmi@0120000 {
- compatible = "fsl,imx6q-hdmi";
- reg = <0x00120000 0x9000>;
- interrupts = <0 115 0x04>;
- gpr = <&gpr>;
- clocks = <&clks 123>, <&clks 124>;
- clock-names = "iahb", "isfr";
- ddc-i2c-bus = <&i2c2>;
-
- port@0 {
- reg = <0>;
-
- hdmi_mux_0: endpoint {
- remote-endpoint = <&ipu1_di0_hdmi>;
- };
- };
-
- port@1 {
- reg = <1>;
-
- hdmi_mux_1: endpoint {
- remote-endpoint = <&ipu1_di1_hdmi>;
- };
- };
- };
+Synopsys DesignWare HDMI TX Encoder
+===================================
+
+This document defines device tree properties for the Synopsys DesignWare HDMI
+TX Encoder (DWC HDMI TX). It doesn't constitue a device tree binding
+specification by itself but is meant to be referenced by platform-specific
+device tree bindings.
+
+When referenced from platform device tree bindings the properties defined in
+this document are defined as follows. The platform device tree bindings are
+responsible for defining whether each property is required or optional.
+
+- reg: Memory mapped base address and length of the DWC HDMI TX registers.
+
+- reg-io-width: Width of the registers specified by the reg property. The
+ value is expressed in bytes and must be equal to 1 or 4 if specified. The
+ register width defaults to 1 if the property is not present.
+
+- interrupts: Reference to the DWC HDMI TX interrupt.
+
+- clocks: References to all the clocks specified in the clock-names property
+ as specified in Documentation/devicetree/bindings/clock/clock-bindings.txt.
+
+- clock-names: The DWC HDMI TX uses the following clocks.
+
+ - "iahb" is the bus clock for either AHB and APB (mandatory).
+ - "isfr" is the internal register configuration clock (mandatory).
+ - "cec" is the HDMI CEC controller main clock (optional).
+
+- ports: The connectivity of the DWC HDMI TX with the rest of the system is
+ expressed in using ports as specified in the device graph bindings defined
+ in Documentation/devicetree/bindings/graph.txt. The numbering of the ports
+ is platform-specific.
diff --git a/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt b/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt
new file mode 100644
index 0000000..6ec1a88
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt
@@ -0,0 +1,46 @@
+THS8135 Video DAC
+-----------------
+
+This is the binding for Texas Instruments THS8135 Video DAC bridge.
+
+Required properties:
+
+- compatible: Must be "ti,ths8135"
+
+Required nodes:
+
+This device has two video ports. Their connections are modelled using the OF
+graph bindings specified in Documentation/devicetree/bindings/graph.txt.
+
+- Video port 0 for RGB input
+- Video port 1 for VGA output
+
+Example
+-------
+
+vga-bridge {
+ compatible = "ti,ths8135";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ vga_bridge_in: endpoint {
+ remote-endpoint = <&lcdc_out_vga>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ vga_bridge_out: endpoint {
+ remote-endpoint = <&vga_con_in>;
+ };
+ };
+ };
+};
diff --git a/Documentation/devicetree/bindings/display/hisilicon/hisi-ade.txt b/Documentation/devicetree/bindings/display/hisilicon/hisi-ade.txt
index 38dc9d6..305a0e7 100644
--- a/Documentation/devicetree/bindings/display/hisilicon/hisi-ade.txt
+++ b/Documentation/devicetree/bindings/display/hisilicon/hisi-ade.txt
@@ -16,7 +16,7 @@ Required properties:
"clk_ade_core" for the ADE core clock.
"clk_codec_jpeg" for the media NOC QoS clock, which use the same clock with
jpeg codec.
- "clk_ade_pix" for the ADE pixel clok.
+ "clk_ade_pix" for the ADE pixel clock.
- assigned-clocks: Should contain "clk_ade_core" and "clk_codec_jpeg" clocks'
phandle + clock-specifier pairs.
- assigned-clock-rates: clock rates, one for each entry in assigned-clocks.
diff --git a/Documentation/devicetree/bindings/display/imx/hdmi.txt b/Documentation/devicetree/bindings/display/imx/hdmi.txt
index 1b756cf..66a8f86 100644
--- a/Documentation/devicetree/bindings/display/imx/hdmi.txt
+++ b/Documentation/devicetree/bindings/display/imx/hdmi.txt
@@ -1,29 +1,36 @@
-Device-Tree bindings for HDMI Transmitter
+Freescale i.MX6 DWC HDMI TX Encoder
+===================================
-HDMI Transmitter
-================
+The HDMI transmitter is a Synopsys DesignWare HDMI 1.4 TX controller IP
+with a companion PHY IP.
+
+These DT bindings follow the Synopsys DWC HDMI TX bindings defined in
+Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt with the
+following device-specific properties.
-The HDMI Transmitter is a Synopsys DesignWare HDMI 1.4 TX controller IP
-with accompanying PHY IP.
Required properties:
- - #address-cells : should be <1>
- - #size-cells : should be <0>
- - compatible : should be "fsl,imx6q-hdmi" or "fsl,imx6dl-hdmi".
- - gpr : should be <&gpr>.
- The phandle points to the iomuxc-gpr region containing the HDMI
- multiplexer control register.
- - clocks, clock-names : phandles to the HDMI iahb and isrf clocks, as described
- in Documentation/devicetree/bindings/clock/clock-bindings.txt and
- Documentation/devicetree/bindings/clock/imx6q-clock.txt.
- - port@[0-4]: Up to four port nodes with endpoint definitions as defined in
- Documentation/devicetree/bindings/media/video-interfaces.txt,
- corresponding to the four inputs to the HDMI multiplexer.
-
-Optional properties:
- - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
-
-example:
+
+- compatible : Shall be one of "fsl,imx6q-hdmi" or "fsl,imx6dl-hdmi".
+- reg: See dw_hdmi.txt.
+- interrupts: HDMI interrupt number
+- clocks: See dw_hdmi.txt.
+- clock-names: Shall contain "iahb" and "isfr" as defined in dw_hdmi.txt.
+- ports: See dw_hdmi.txt. The DWC HDMI shall have between one and four ports,
+ numbered 0 to 3, corresponding to the four inputs of the HDMI multiplexer.
+ Each port shall have a single endpoint.
+- gpr : Shall contain a phandle to the iomuxc-gpr region containing the HDMI
+ multiplexer control register.
+
+Optional properties
+
+- ddc-i2c-bus: The HDMI DDC bus can be connected to either a system I2C master
+ or the functionally-reduced I2C master contained in the DWC HDMI. When
+ connected to a system I2C master this property contains a phandle to that
+ I2C master controller.
+
+
+Example:
gpr: iomuxc-gpr@020e0000 {
/* ... */
diff --git a/Documentation/devicetree/bindings/display/msm/gpu.txt b/Documentation/devicetree/bindings/display/msm/gpu.txt
index 67d0a58..43fac0f 100644
--- a/Documentation/devicetree/bindings/display/msm/gpu.txt
+++ b/Documentation/devicetree/bindings/display/msm/gpu.txt
@@ -1,23 +1,19 @@
Qualcomm adreno/snapdragon GPU
Required properties:
-- compatible: "qcom,adreno-3xx"
+- compatible: "qcom,adreno-XYZ.W", "qcom,adreno"
+ for example: "qcom,adreno-306.0", "qcom,adreno"
+ Note that you need to list the less specific "qcom,adreno" (since this
+ is what the device is matched on), in addition to the more specific
+ with the chip-id.
- reg: Physical base address and length of the controller's registers.
- interrupts: The interrupt signal from the gpu.
- clocks: device clocks
See ../clocks/clock-bindings.txt for details.
- clock-names: the following clocks are required:
- * "core_clk"
- * "iface_clk"
- * "mem_iface_clk"
-- qcom,chipid: gpu chip-id. Note this may become optional for future
- devices if we can reliably read the chipid from hw
-- qcom,gpu-pwrlevels: list of operating points
- - compatible: "qcom,gpu-pwrlevels"
- - for each qcom,gpu-pwrlevel:
- - qcom,gpu-freq: requested gpu clock speed
- - NOTE: downstream android driver defines additional parameters to
- configure memory bandwidth scaling per OPP.
+ * "core"
+ * "iface"
+ * "mem_iface"
Example:
@@ -25,28 +21,18 @@ Example:
...
gpu: qcom,kgsl-3d0@4300000 {
- compatible = "qcom,adreno-3xx";
+ compatible = "qcom,adreno-320.2", "qcom,adreno";
reg = <0x04300000 0x20000>;
reg-names = "kgsl_3d0_reg_memory";
interrupts = <GIC_SPI 80 0>;
interrupt-names = "kgsl_3d0_irq";
clock-names =
- "core_clk",
- "iface_clk",
- "mem_iface_clk";
+ "core",
+ "iface",
+ "mem_iface";
clocks =
<&mmcc GFX3D_CLK>,
<&mmcc GFX3D_AHB_CLK>,
<&mmcc MMSS_IMEM_AHB_CLK>;
- qcom,chipid = <0x03020100>;
- qcom,gpu-pwrlevels {
- compatible = "qcom,gpu-pwrlevels";
- qcom,gpu-pwrlevel@0 {
- qcom,gpu-freq = <450000000>;
- };
- qcom,gpu-pwrlevel@1 {
- qcom,gpu-freq = <27000000>;
- };
- };
};
};
diff --git a/Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt b/Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt
new file mode 100644
index 0000000..eed48c3
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt
@@ -0,0 +1,27 @@
+Multi-Inno MI0283QT display panel
+
+Required properties:
+- compatible: "multi-inno,mi0283qt".
+
+The node for this driver must be a child node of a SPI controller, hence
+all mandatory properties described in ../spi/spi-bus.txt must be specified.
+
+Optional properties:
+- dc-gpios: D/C pin. The presence/absence of this GPIO determines
+ the panel interface mode (IM[3:0] pins):
+ - present: IM=x110 4-wire 8-bit data serial interface
+ - absent: IM=x101 3-wire 9-bit data serial interface
+- reset-gpios: Reset pin
+- power-supply: A regulator node for the supply voltage.
+- backlight: phandle of the backlight device attached to the panel
+- rotation: panel rotation in degrees counter clockwise (0,90,180,270)
+
+Example:
+ mi0283qt@0{
+ compatible = "multi-inno,mi0283qt";
+ reg = <0>;
+ spi-max-frequency = <32000000>;
+ rotation = <90>;
+ dc-gpios = <&gpio 25 0>;
+ backlight = <&backlight>;
+ };
diff --git a/Documentation/devicetree/bindings/display/panel/boe,nv101wxmn51.txt b/Documentation/devicetree/bindings/display/panel/boe,nv101wxmn51.txt
new file mode 100644
index 0000000..b258d6a
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/boe,nv101wxmn51.txt
@@ -0,0 +1,7 @@
+BOE OPTOELECTRONICS TECHNOLOGY 10.1" WXGA TFT LCD panel
+
+Required properties:
+- compatible: should be "boe,nv101wxmn51"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/display/panel/netron-dy,e231732.txt b/Documentation/devicetree/bindings/display/panel/netron-dy,e231732.txt
new file mode 100644
index 0000000..c6d06b5
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/netron-dy,e231732.txt
@@ -0,0 +1,7 @@
+Netron-DY E231732 7.0" WSVGA TFT LCD panel
+
+Required properties:
+- compatible: should be "netron-dy,e231732"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/display/panel/panel.txt b/Documentation/devicetree/bindings/display/panel/panel.txt
new file mode 100644
index 0000000..e2e6867
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/panel.txt
@@ -0,0 +1,4 @@
+Common display properties
+-------------------------
+
+- rotation: Display rotation in degrees counter clockwise (0,90,180,270)
diff --git a/Documentation/devicetree/bindings/display/panel/tianma,tm070jdhg30.txt b/Documentation/devicetree/bindings/display/panel/tianma,tm070jdhg30.txt
new file mode 100644
index 0000000..eb9501a
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/tianma,tm070jdhg30.txt
@@ -0,0 +1,7 @@
+Tianma Micro-electronics TM070JDHG30 7.0" WXGA TFT LCD panel
+
+Required properties:
+- compatible: should be "tianma,tm070jdhg30"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
index 668091f..046076c 100644
--- a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
+++ b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
@@ -1,24 +1,39 @@
-Rockchip specific extensions to the Synopsys Designware HDMI
-================================
+Rockchip DWC HDMI TX Encoder
+============================
+
+The HDMI transmitter is a Synopsys DesignWare HDMI 1.4 TX controller IP
+with a companion PHY IP.
+
+These DT bindings follow the Synopsys DWC HDMI TX bindings defined in
+Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt with the
+following device-specific properties.
+
Required properties:
-- compatible: "rockchip,rk3288-dw-hdmi";
-- reg: Physical base address and length of the controller's registers.
-- clocks: phandle to hdmi iahb and isfr clocks.
-- clock-names: should be "iahb" "isfr"
-- rockchip,grf: this soc should set GRF regs to mux vopl/vopb.
+
+- compatible: Shall contain "rockchip,rk3288-dw-hdmi".
+- reg: See dw_hdmi.txt.
+- reg-io-width: See dw_hdmi.txt. Shall be 4.
- interrupts: HDMI interrupt number
-- ports: contain a port node with endpoint definitions as defined in
- Documentation/devicetree/bindings/media/video-interfaces.txt. For
- vopb,set the reg = <0> and set the reg = <1> for vopl.
-- reg-io-width: the width of the reg:1,4, the value should be 4 on
- rk3288 platform
+- clocks: See dw_hdmi.txt.
+- clock-names: Shall contain "iahb" and "isfr" as defined in dw_hdmi.txt.
+- ports: See dw_hdmi.txt. The DWC HDMI shall have a single port numbered 0
+ corresponding to the video input of the controller. The port shall have two
+ endpoints, numbered 0 and 1, connected respectively to the vopb and vopl.
+- rockchip,grf: Shall reference the GRF to mux vopl/vopb.
Optional properties
-- ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
-- clocks, clock-names: phandle to the HDMI CEC clock, name should be "cec"
+
+- ddc-i2c-bus: The HDMI DDC bus can be connected to either a system I2C master
+ or the functionally-reduced I2C master contained in the DWC HDMI. When
+ connected to a system I2C master this property contains a phandle to that
+ I2C master controller.
+- clock-names: See dw_hdmi.txt. The "cec" clock is optional.
+- clock-names: May contain "cec" as defined in dw_hdmi.txt.
+
Example:
+
hdmi: hdmi@ff980000 {
compatible = "rockchip,rk3288-dw-hdmi";
reg = <0xff980000 0x20000>;
diff --git a/Documentation/devicetree/bindings/display/zte,vou.txt b/Documentation/devicetree/bindings/display/zte,vou.txt
index 740e5bd..9c35628 100644
--- a/Documentation/devicetree/bindings/display/zte,vou.txt
+++ b/Documentation/devicetree/bindings/display/zte,vou.txt
@@ -49,6 +49,15 @@ Required properties:
"osc_clk"
"xclk"
+* TV Encoder output device
+
+Required properties:
+ - compatible: should be "zte,zx296718-tvenc"
+ - reg: Physical base address and length of the TVENC device IO region
+ - zte,tvenc-power-control: the phandle to SYSCTRL block followed by two
+ integer cells. The first cell is the offset of SYSCTRL register used
+ to control TV Encoder DAC power, and the second cell is the bit mask.
+
Example:
vou: vou@1440000 {
@@ -81,4 +90,10 @@ vou: vou@1440000 {
<&topcrm HDMI_XCLK>;
clock-names = "osc_cec", "osc_clk", "xclk";
};
+
+ tvenc: tvenc@2000 {
+ compatible = "zte,zx296718-tvenc";
+ reg = <0x2000 0x1000>;
+ zte,tvenc-power-control = <&sysctrl 0x170 0x10>;
+ };
};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index f6824fd..bd0ed3c 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -195,6 +195,7 @@ mpl MPL AG
mqmaker mqmaker Inc.
msi Micro-Star International Co. Ltd.
mti Imagination Technologies Ltd. (formerly MIPS Technologies Inc.)
+multi-inno Multi-Inno Technology Co.,Ltd
mundoreader Mundo Reader S.L.
murata Murata Manufacturing Co., Ltd.
mxicy Macronix International Co., Ltd.
@@ -204,6 +205,7 @@ nec NEC LCD Technologies, Ltd.
neonode Neonode Inc.
netgear NETGEAR
netlogic Broadcom Corporation (formerly NetLogic Microsystems)
+netron-dy Netron DY
netxeon Shenzhen Netxeon Technology CO., LTD
nexbox Nexbox
newhaven Newhaven Display International
@@ -305,6 +307,7 @@ technologic Technologic Systems
terasic Terasic Inc.
thine THine Electronics, Inc.
ti Texas Instruments
+tianma Tianma Micro-electronics Co., Ltd.
tlm Trusted Logic Mobility
topeet Topeet
toradex Toradex AG
diff --git a/Documentation/dma-buf-sharing.txt b/Documentation/dma-buf-sharing.txt
deleted file mode 100644
index ca44c58..0000000
--- a/Documentation/dma-buf-sharing.txt
+++ /dev/null
@@ -1,482 +0,0 @@
- DMA Buffer Sharing API Guide
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Sumit Semwal
- <sumit dot semwal at linaro dot org>
- <sumit dot semwal at ti dot com>
-
-This document serves as a guide to device-driver writers on what is the dma-buf
-buffer sharing API, how to use it for exporting and using shared buffers.
-
-Any device driver which wishes to be a part of DMA buffer sharing, can do so as
-either the 'exporter' of buffers, or the 'user' of buffers.
-
-Say a driver A wants to use buffers created by driver B, then we call B as the
-exporter, and A as buffer-user.
-
-The exporter
-- implements and manages operations[1] for the buffer
-- allows other users to share the buffer by using dma_buf sharing APIs,
-- manages the details of buffer allocation,
-- decides about the actual backing storage where this allocation happens,
-- takes care of any migration of scatterlist - for all (shared) users of this
- buffer,
-
-The buffer-user
-- is one of (many) sharing users of the buffer.
-- doesn't need to worry about how the buffer is allocated, or where.
-- needs a mechanism to get access to the scatterlist that makes up this buffer
- in memory, mapped into its own address space, so it can access the same area
- of memory.
-
-dma-buf operations for device dma only
---------------------------------------
-
-The dma_buf buffer sharing API usage contains the following steps:
-
-1. Exporter announces that it wishes to export a buffer
-2. Userspace gets the file descriptor associated with the exported buffer, and
- passes it around to potential buffer-users based on use case
-3. Each buffer-user 'connects' itself to the buffer
-4. When needed, buffer-user requests access to the buffer from exporter
-5. When finished with its use, the buffer-user notifies end-of-DMA to exporter
-6. when buffer-user is done using this buffer completely, it 'disconnects'
- itself from the buffer.
-
-
-1. Exporter's announcement of buffer export
-
- The buffer exporter announces its wish to export a buffer. In this, it
- connects its own private buffer data, provides implementation for operations
- that can be performed on the exported dma_buf, and flags for the file
- associated with this buffer. All these fields are filled in struct
- dma_buf_export_info, defined via the DEFINE_DMA_BUF_EXPORT_INFO macro.
-
- Interface:
- DEFINE_DMA_BUF_EXPORT_INFO(exp_info)
- struct dma_buf *dma_buf_export(struct dma_buf_export_info *exp_info)
-
- If this succeeds, dma_buf_export allocates a dma_buf structure, and
- returns a pointer to the same. It also associates an anonymous file with this
- buffer, so it can be exported. On failure to allocate the dma_buf object,
- it returns NULL.
-
- 'exp_name' in struct dma_buf_export_info is the name of exporter - to
- facilitate information while debugging. It is set to KBUILD_MODNAME by
- default, so exporters don't have to provide a specific name, if they don't
- wish to.
-
- DEFINE_DMA_BUF_EXPORT_INFO macro defines the struct dma_buf_export_info,
- zeroes it out and pre-populates exp_name in it.
-
-
-2. Userspace gets a handle to pass around to potential buffer-users
-
- Userspace entity requests for a file-descriptor (fd) which is a handle to the
- anonymous file associated with the buffer. It can then share the fd with other
- drivers and/or processes.
-
- Interface:
- int dma_buf_fd(struct dma_buf *dmabuf, int flags)
-
- This API installs an fd for the anonymous file associated with this buffer;
- returns either 'fd', or error.
-
-3. Each buffer-user 'connects' itself to the buffer
-
- Each buffer-user now gets a reference to the buffer, using the fd passed to
- it.
-
- Interface:
- struct dma_buf *dma_buf_get(int fd)
-
- This API will return a reference to the dma_buf, and increment refcount for
- it.
-
- After this, the buffer-user needs to attach its device with the buffer, which
- helps the exporter to know of device buffer constraints.
-
- Interface:
- struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
- struct device *dev)
-
- This API returns reference to an attachment structure, which is then used
- for scatterlist operations. It will optionally call the 'attach' dma_buf
- operation, if provided by the exporter.
-
- The dma-buf sharing framework does the bookkeeping bits related to managing
- the list of all attachments to a buffer.
-
-Until this stage, the buffer-exporter has the option to choose not to actually
-allocate the backing storage for this buffer, but wait for the first buffer-user
-to request use of buffer for allocation.
-
-
-4. When needed, buffer-user requests access to the buffer
-
- Whenever a buffer-user wants to use the buffer for any DMA, it asks for
- access to the buffer using dma_buf_map_attachment API. At least one attach to
- the buffer must have happened before map_dma_buf can be called.
-
- Interface:
- struct sg_table * dma_buf_map_attachment(struct dma_buf_attachment *,
- enum dma_data_direction);
-
- This is a wrapper to dma_buf->ops->map_dma_buf operation, which hides the
- "dma_buf->ops->" indirection from the users of this interface.
-
- In struct dma_buf_ops, map_dma_buf is defined as
- struct sg_table * (*map_dma_buf)(struct dma_buf_attachment *,
- enum dma_data_direction);
-
- It is one of the buffer operations that must be implemented by the exporter.
- It should return the sg_table containing scatterlist for this buffer, mapped
- into caller's address space.
-
- If this is being called for the first time, the exporter can now choose to
- scan through the list of attachments for this buffer, collate the requirements
- of the attached devices, and choose an appropriate backing storage for the
- buffer.
-
- Based on enum dma_data_direction, it might be possible to have multiple users
- accessing at the same time (for reading, maybe), or any other kind of sharing
- that the exporter might wish to make available to buffer-users.
-
- map_dma_buf() operation can return -EINTR if it is interrupted by a signal.
-
-
-5. When finished, the buffer-user notifies end-of-DMA to exporter
-
- Once the DMA for the current buffer-user is over, it signals 'end-of-DMA' to
- the exporter using the dma_buf_unmap_attachment API.
-
- Interface:
- void dma_buf_unmap_attachment(struct dma_buf_attachment *,
- struct sg_table *);
-
- This is a wrapper to dma_buf->ops->unmap_dma_buf() operation, which hides the
- "dma_buf->ops->" indirection from the users of this interface.
-
- In struct dma_buf_ops, unmap_dma_buf is defined as
- void (*unmap_dma_buf)(struct dma_buf_attachment *,
- struct sg_table *,
- enum dma_data_direction);
-
- unmap_dma_buf signifies the end-of-DMA for the attachment provided. Like
- map_dma_buf, this API also must be implemented by the exporter.
-
-
-6. when buffer-user is done using this buffer, it 'disconnects' itself from the
- buffer.
-
- After the buffer-user has no more interest in using this buffer, it should
- disconnect itself from the buffer:
-
- - it first detaches itself from the buffer.
-
- Interface:
- void dma_buf_detach(struct dma_buf *dmabuf,
- struct dma_buf_attachment *dmabuf_attach);
-
- This API removes the attachment from the list in dmabuf, and optionally calls
- dma_buf->ops->detach(), if provided by exporter, for any housekeeping bits.
-
- - Then, the buffer-user returns the buffer reference to exporter.
-
- Interface:
- void dma_buf_put(struct dma_buf *dmabuf);
-
- This API then reduces the refcount for this buffer.
-
- If, as a result of this call, the refcount becomes 0, the 'release' file
- operation related to this fd is called. It calls the dmabuf->ops->release()
- operation in turn, and frees the memory allocated for dmabuf when exported.
-
-NOTES:
-- Importance of attach-detach and {map,unmap}_dma_buf operation pairs
- The attach-detach calls allow the exporter to figure out backing-storage
- constraints for the currently-interested devices. This allows preferential
- allocation, and/or migration of pages across different types of storage
- available, if possible.
-
- Bracketing of DMA access with {map,unmap}_dma_buf operations is essential
- to allow just-in-time backing of storage, and migration mid-way through a
- use-case.
-
-- Migration of backing storage if needed
- If after
- - at least one map_dma_buf has happened,
- - and the backing storage has been allocated for this buffer,
- another new buffer-user intends to attach itself to this buffer, it might
- be allowed, if possible for the exporter.
-
- In case it is allowed by the exporter:
- if the new buffer-user has stricter 'backing-storage constraints', and the
- exporter can handle these constraints, the exporter can just stall on the
- map_dma_buf until all outstanding access is completed (as signalled by
- unmap_dma_buf).
- Once all users have finished accessing and have unmapped this buffer, the
- exporter could potentially move the buffer to the stricter backing-storage,
- and then allow further {map,unmap}_dma_buf operations from any buffer-user
- from the migrated backing-storage.
-
- If the exporter cannot fulfill the backing-storage constraints of the new
- buffer-user device as requested, dma_buf_attach() would return an error to
- denote non-compatibility of the new buffer-sharing request with the current
- buffer.
-
- If the exporter chooses not to allow an attach() operation once a
- map_dma_buf() API has been called, it simply returns an error.
-
-Kernel cpu access to a dma-buf buffer object
---------------------------------------------
-
-The motivation to allow cpu access from the kernel to a dma-buf object from the
-importers side are:
-- fallback operations, e.g. if the devices is connected to a usb bus and the
- kernel needs to shuffle the data around first before sending it away.
-- full transparency for existing users on the importer side, i.e. userspace
- should not notice the difference between a normal object from that subsystem
- and an imported one backed by a dma-buf. This is really important for drm
- opengl drivers that expect to still use all the existing upload/download
- paths.
-
-Access to a dma_buf from the kernel context involves three steps:
-
-1. Prepare access, which invalidate any necessary caches and make the object
- available for cpu access.
-2. Access the object page-by-page with the dma_buf map apis
-3. Finish access, which will flush any necessary cpu caches and free reserved
- resources.
-
-1. Prepare access
-
- Before an importer can access a dma_buf object with the cpu from the kernel
- context, it needs to notify the exporter of the access that is about to
- happen.
-
- Interface:
- int dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
- enum dma_data_direction direction)
-
- This allows the exporter to ensure that the memory is actually available for
- cpu access - the exporter might need to allocate or swap-in and pin the
- backing storage. The exporter also needs to ensure that cpu access is
- coherent for the access direction. The direction can be used by the exporter
- to optimize the cache flushing, i.e. access with a different direction (read
- instead of write) might return stale or even bogus data (e.g. when the
- exporter needs to copy the data to temporary storage).
-
- This step might fail, e.g. in oom conditions.
-
-2. Accessing the buffer
-
- To support dma_buf objects residing in highmem cpu access is page-based using
- an api similar to kmap. Accessing a dma_buf is done in aligned chunks of
- PAGE_SIZE size. Before accessing a chunk it needs to be mapped, which returns
- a pointer in kernel virtual address space. Afterwards the chunk needs to be
- unmapped again. There is no limit on how often a given chunk can be mapped
- and unmapped, i.e. the importer does not need to call begin_cpu_access again
- before mapping the same chunk again.
-
- Interfaces:
- void *dma_buf_kmap(struct dma_buf *, unsigned long);
- void dma_buf_kunmap(struct dma_buf *, unsigned long, void *);
-
- There are also atomic variants of these interfaces. Like for kmap they
- facilitate non-blocking fast-paths. Neither the importer nor the exporter (in
- the callback) is allowed to block when using these.
-
- Interfaces:
- void *dma_buf_kmap_atomic(struct dma_buf *, unsigned long);
- void dma_buf_kunmap_atomic(struct dma_buf *, unsigned long, void *);
-
- For importers all the restrictions of using kmap apply, like the limited
- supply of kmap_atomic slots. Hence an importer shall only hold onto at most 2
- atomic dma_buf kmaps at the same time (in any given process context).
-
- dma_buf kmap calls outside of the range specified in begin_cpu_access are
- undefined. If the range is not PAGE_SIZE aligned, kmap needs to succeed on
- the partial chunks at the beginning and end but may return stale or bogus
- data outside of the range (in these partial chunks).
-
- Note that these calls need to always succeed. The exporter needs to complete
- any preparations that might fail in begin_cpu_access.
-
- For some cases the overhead of kmap can be too high, a vmap interface
- is introduced. This interface should be used very carefully, as vmalloc
- space is a limited resources on many architectures.
-
- Interfaces:
- void *dma_buf_vmap(struct dma_buf *dmabuf)
- void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
-
- The vmap call can fail if there is no vmap support in the exporter, or if it
- runs out of vmalloc space. Fallback to kmap should be implemented. Note that
- the dma-buf layer keeps a reference count for all vmap access and calls down
- into the exporter's vmap function only when no vmapping exists, and only
- unmaps it once. Protection against concurrent vmap/vunmap calls is provided
- by taking the dma_buf->lock mutex.
-
-3. Finish access
-
- When the importer is done accessing the CPU, it needs to announce this to
- the exporter (to facilitate cache flushing and unpinning of any pinned
- resources). The result of any dma_buf kmap calls after end_cpu_access is
- undefined.
-
- Interface:
- void dma_buf_end_cpu_access(struct dma_buf *dma_buf,
- enum dma_data_direction dir);
-
-
-Direct Userspace Access/mmap Support
-------------------------------------
-
-Being able to mmap an export dma-buf buffer object has 2 main use-cases:
-- CPU fallback processing in a pipeline and
-- supporting existing mmap interfaces in importers.
-
-1. CPU fallback processing in a pipeline
-
- In many processing pipelines it is sometimes required that the cpu can access
- the data in a dma-buf (e.g. for thumbnail creation, snapshots, ...). To avoid
- the need to handle this specially in userspace frameworks for buffer sharing
- it's ideal if the dma_buf fd itself can be used to access the backing storage
- from userspace using mmap.
-
- Furthermore Android's ION framework already supports this (and is otherwise
- rather similar to dma-buf from a userspace consumer side with using fds as
- handles, too). So it's beneficial to support this in a similar fashion on
- dma-buf to have a good transition path for existing Android userspace.
-
- No special interfaces, userspace simply calls mmap on the dma-buf fd, making
- sure that the cache synchronization ioctl (DMA_BUF_IOCTL_SYNC) is *always*
- used when the access happens. Note that DMA_BUF_IOCTL_SYNC can fail with
- -EAGAIN or -EINTR, in which case it must be restarted.
-
- Some systems might need some sort of cache coherency management e.g. when
- CPU and GPU domains are being accessed through dma-buf at the same time. To
- circumvent this problem there are begin/end coherency markers, that forward
- directly to existing dma-buf device drivers vfunc hooks. Userspace can make
- use of those markers through the DMA_BUF_IOCTL_SYNC ioctl. The sequence
- would be used like following:
- - mmap dma-buf fd
- - for each drawing/upload cycle in CPU 1. SYNC_START ioctl, 2. read/write
- to mmap area 3. SYNC_END ioctl. This can be repeated as often as you
- want (with the new data being consumed by the GPU or say scanout device)
- - munmap once you don't need the buffer any more
-
- For correctness and optimal performance, it is always required to use
- SYNC_START and SYNC_END before and after, respectively, when accessing the
- mapped address. Userspace cannot rely on coherent access, even when there
- are systems where it just works without calling these ioctls.
-
-2. Supporting existing mmap interfaces in importers
-
- Similar to the motivation for kernel cpu access it is again important that
- the userspace code of a given importing subsystem can use the same interfaces
- with a imported dma-buf buffer object as with a native buffer object. This is
- especially important for drm where the userspace part of contemporary OpenGL,
- X, and other drivers is huge, and reworking them to use a different way to
- mmap a buffer rather invasive.
-
- The assumption in the current dma-buf interfaces is that redirecting the
- initial mmap is all that's needed. A survey of some of the existing
- subsystems shows that no driver seems to do any nefarious thing like syncing
- up with outstanding asynchronous processing on the device or allocating
- special resources at fault time. So hopefully this is good enough, since
- adding interfaces to intercept pagefaults and allow pte shootdowns would
- increase the complexity quite a bit.
-
- Interface:
- int dma_buf_mmap(struct dma_buf *, struct vm_area_struct *,
- unsigned long);
-
- If the importing subsystem simply provides a special-purpose mmap call to set
- up a mapping in userspace, calling do_mmap with dma_buf->file will equally
- achieve that for a dma-buf object.
-
-3. Implementation notes for exporters
-
- Because dma-buf buffers have invariant size over their lifetime, the dma-buf
- core checks whether a vma is too large and rejects such mappings. The
- exporter hence does not need to duplicate this check.
-
- Because existing importing subsystems might presume coherent mappings for
- userspace, the exporter needs to set up a coherent mapping. If that's not
- possible, it needs to fake coherency by manually shooting down ptes when
- leaving the cpu domain and flushing caches at fault time. Note that all the
- dma_buf files share the same anon inode, hence the exporter needs to replace
- the dma_buf file stored in vma->vm_file with it's own if pte shootdown is
- required. This is because the kernel uses the underlying inode's address_space
- for vma tracking (and hence pte tracking at shootdown time with
- unmap_mapping_range).
-
- If the above shootdown dance turns out to be too expensive in certain
- scenarios, we can extend dma-buf with a more explicit cache tracking scheme
- for userspace mappings. But the current assumption is that using mmap is
- always a slower path, so some inefficiencies should be acceptable.
-
- Exporters that shoot down mappings (for any reasons) shall not do any
- synchronization at fault time with outstanding device operations.
- Synchronization is an orthogonal issue to sharing the backing storage of a
- buffer and hence should not be handled by dma-buf itself. This is explicitly
- mentioned here because many people seem to want something like this, but if
- different exporters handle this differently, buffer sharing can fail in
- interesting ways depending upong the exporter (if userspace starts depending
- upon this implicit synchronization).
-
-Other Interfaces Exposed to Userspace on the dma-buf FD
-------------------------------------------------------
-
-- Since kernel 3.12 the dma-buf FD supports the llseek system call, but only
- with offset=0 and whence=SEEK_END|SEEK_SET. SEEK_SET is supported to allow
- the usual size discover pattern size = SEEK_END(0); SEEK_SET(0). Every other
- llseek operation will report -EINVAL.
-
- If llseek on dma-buf FDs isn't support the kernel will report -ESPIPE for all
- cases. Userspace can use this to detect support for discovering the dma-buf
- size using llseek.
-
-Miscellaneous notes
--------------------
-
-- Any exporters or users of the dma-buf buffer sharing framework must have
- a 'select DMA_SHARED_BUFFER' in their respective Kconfigs.
-
-- In order to avoid fd leaks on exec, the FD_CLOEXEC flag must be set
- on the file descriptor. This is not just a resource leak, but a
- potential security hole. It could give the newly exec'd application
- access to buffers, via the leaked fd, to which it should otherwise
- not be permitted access.
-
- The problem with doing this via a separate fcntl() call, versus doing it
- atomically when the fd is created, is that this is inherently racy in a
- multi-threaded app[3]. The issue is made worse when it is library code
- opening/creating the file descriptor, as the application may not even be
- aware of the fd's.
-
- To avoid this problem, userspace must have a way to request O_CLOEXEC
- flag be set when the dma-buf fd is created. So any API provided by
- the exporting driver to create a dmabuf fd must provide a way to let
- userspace control setting of O_CLOEXEC flag passed in to dma_buf_fd().
-
-- If an exporter needs to manually flush caches and hence needs to fake
- coherency for mmap support, it needs to be able to zap all the ptes pointing
- at the backing storage. Now linux mm needs a struct address_space associated
- with the struct file stored in vma->vm_file to do that with the function
- unmap_mapping_range. But the dma_buf framework only backs every dma_buf fd
- with the anon_file struct file, i.e. all dma_bufs share the same file.
-
- Hence exporters need to setup their own file (and address_space) association
- by setting vma->vm_file and adjusting vma->vm_pgoff in the dma_buf mmap
- callback. In the specific case of a gem driver the exporter could use the
- shmem file already provided by gem (and set vm_pgoff = 0). Exporters can then
- zap ptes by unmapping the corresponding range of the struct address_space
- associated with their own file.
-
-References:
-[1] struct dma_buf_ops in include/linux/dma-buf.h
-[2] All interfaces mentioned above defined in include/linux/dma-buf.h
-[3] https://lwn.net/Articles/236486/
diff --git a/Documentation/driver-api/dma-buf.rst b/Documentation/driver-api/dma-buf.rst
index a9b457a..31671b4 100644
--- a/Documentation/driver-api/dma-buf.rst
+++ b/Documentation/driver-api/dma-buf.rst
@@ -17,6 +17,98 @@ shared or exclusive fence(s) associated with the buffer.
Shared DMA Buffers
------------------
+This document serves as a guide to device-driver writers on what is the dma-buf
+buffer sharing API, how to use it for exporting and using shared buffers.
+
+Any device driver which wishes to be a part of DMA buffer sharing, can do so as
+either the 'exporter' of buffers, or the 'user' or 'importer' of buffers.
+
+Say a driver A wants to use buffers created by driver B, then we call B as the
+exporter, and A as buffer-user/importer.
+
+The exporter
+
+ - implements and manages operations in :c:type:`struct dma_buf_ops
+ <dma_buf_ops>` for the buffer,
+ - allows other users to share the buffer by using dma_buf sharing APIs,
+ - manages the details of buffer allocation, wrapped int a :c:type:`struct
+ dma_buf <dma_buf>`,
+ - decides about the actual backing storage where this allocation happens,
+ - and takes care of any migration of scatterlist - for all (shared) users of
+ this buffer.
+
+The buffer-user
+
+ - is one of (many) sharing users of the buffer.
+ - doesn't need to worry about how the buffer is allocated, or where.
+ - and needs a mechanism to get access to the scatterlist that makes up this
+ buffer in memory, mapped into its own address space, so it can access the
+ same area of memory. This interface is provided by :c:type:`struct
+ dma_buf_attachment <dma_buf_attachment>`.
+
+Any exporters or users of the dma-buf buffer sharing framework must have a
+'select DMA_SHARED_BUFFER' in their respective Kconfigs.
+
+Userspace Interface Notes
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Mostly a DMA buffer file descriptor is simply an opaque object for userspace,
+and hence the generic interface exposed is very minimal. There's a few things to
+consider though:
+
+- Since kernel 3.12 the dma-buf FD supports the llseek system call, but only
+ with offset=0 and whence=SEEK_END|SEEK_SET. SEEK_SET is supported to allow
+ the usual size discover pattern size = SEEK_END(0); SEEK_SET(0). Every other
+ llseek operation will report -EINVAL.
+
+ If llseek on dma-buf FDs isn't support the kernel will report -ESPIPE for all
+ cases. Userspace can use this to detect support for discovering the dma-buf
+ size using llseek.
+
+- In order to avoid fd leaks on exec, the FD_CLOEXEC flag must be set
+ on the file descriptor. This is not just a resource leak, but a
+ potential security hole. It could give the newly exec'd application
+ access to buffers, via the leaked fd, to which it should otherwise
+ not be permitted access.
+
+ The problem with doing this via a separate fcntl() call, versus doing it
+ atomically when the fd is created, is that this is inherently racy in a
+ multi-threaded app[3]. The issue is made worse when it is library code
+ opening/creating the file descriptor, as the application may not even be
+ aware of the fd's.
+
+ To avoid this problem, userspace must have a way to request O_CLOEXEC
+ flag be set when the dma-buf fd is created. So any API provided by
+ the exporting driver to create a dmabuf fd must provide a way to let
+ userspace control setting of O_CLOEXEC flag passed in to dma_buf_fd().
+
+- Memory mapping the contents of the DMA buffer is also supported. See the
+ discussion below on `CPU Access to DMA Buffer Objects`_ for the full details.
+
+- The DMA buffer FD is also pollable, see `Fence Poll Support`_ below for
+ details.
+
+Basic Operation and Device DMA Access
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/dma-buf/dma-buf.c
+ :doc: dma buf device access
+
+CPU Access to DMA Buffer Objects
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/dma-buf/dma-buf.c
+ :doc: cpu access
+
+Fence Poll Support
+~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/dma-buf/dma-buf.c
+ :doc: fence polling
+
+Kernel Functions and Structures Reference
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
.. kernel-doc:: drivers/dma-buf/dma-buf.c
:export:
diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 0c9abdc..4d40688 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -48,11 +48,17 @@ CRTC Abstraction
================
.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
- :export:
+ :doc: overview
+
+CRTC Functions Reference
+--------------------------------
.. kernel-doc:: include/drm/drm_crtc.h
:internal:
+.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
+ :export:
+
Frame Buffer Abstraction
========================
diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst
index cb5daff..f5760b1 100644
--- a/Documentation/gpu/drm-mm.rst
+++ b/Documentation/gpu/drm-mm.rst
@@ -34,25 +34,26 @@ TTM initialization
------------------
**Warning**
-
This section is outdated.
-Drivers wishing to support TTM must fill out a drm_bo_driver
-structure. The structure contains several fields with function pointers
-for initializing the TTM, allocating and freeing memory, waiting for
-command completion and fence synchronization, and memory migration. See
-the radeon_ttm.c file for an example of usage.
+Drivers wishing to support TTM must pass a filled :c:type:`ttm_bo_driver
+<ttm_bo_driver>` structure to ttm_bo_device_init, together with an
+initialized global reference to the memory manager. The ttm_bo_driver
+structure contains several fields with function pointers for
+initializing the TTM, allocating and freeing memory, waiting for command
+completion and fence synchronization, and memory migration.
-The ttm_global_reference structure is made up of several fields:
+The :c:type:`struct drm_global_reference <drm_global_reference>` is made
+up of several fields:
.. code-block:: c
- struct ttm_global_reference {
+ struct drm_global_reference {
enum ttm_global_types global_type;
size_t size;
void *object;
- int (*init) (struct ttm_global_reference *);
- void (*release) (struct ttm_global_reference *);
+ int (*init) (struct drm_global_reference *);
+ void (*release) (struct drm_global_reference *);
};
@@ -76,6 +77,12 @@ ttm_bo_global_release(), respectively. Also, like the previous
object, ttm_global_item_ref() is used to create an initial reference
count for the TTM, which will call your initialization function.
+See the radeon_ttm.c file for an example of usage.
+
+.. kernel-doc:: drivers/gpu/drm/drm_global.c
+ :export:
+
+
The Graphics Execution Manager (GEM)
====================================
@@ -284,10 +291,17 @@ To use :c:func:`drm_gem_mmap()`, drivers must fill the struct
:c:type:`struct drm_driver <drm_driver>` gem_vm_ops field
with a pointer to VM operations.
-struct vm_operations_struct \*gem_vm_ops struct
-vm_operations_struct { void (\*open)(struct vm_area_struct \* area);
-void (\*close)(struct vm_area_struct \* area); int (\*fault)(struct
-vm_area_struct \*vma, struct vm_fault \*vmf); };
+The VM operations is a :c:type:`struct vm_operations_struct <vm_operations_struct>`
+made up of several fields, the more interesting ones being:
+
+.. code-block:: c
+
+ struct vm_operations_struct {
+ void (*open)(struct vm_area_struct * area);
+ void (*close)(struct vm_area_struct * area);
+ int (*fault)(struct vm_fault *vmf);
+ };
+
The open and close operations must update the GEM object reference
count. Drivers can use the :c:func:`drm_gem_vm_open()` and
@@ -303,6 +317,17 @@ created.
Drivers that want to map the GEM object upfront instead of handling page
faults can implement their own mmap file operation handler.
+For platforms without MMU the GEM core provides a helper method
+:c:func:`drm_gem_cma_get_unmapped_area`. The mmap() routines will call
+this to get a proposed address for the mapping.
+
+To use :c:func:`drm_gem_cma_get_unmapped_area`, drivers must fill the
+struct :c:type:`struct file_operations <file_operations>` get_unmapped_area
+field with a pointer on :c:func:`drm_gem_cma_get_unmapped_area`.
+
+More detailed information about get_unmapped_area can be found in
+Documentation/nommu-mmap.txt
+
Memory Coherency
----------------
@@ -442,7 +467,7 @@ LRU Scan/Eviction Support
-------------------------
.. kernel-doc:: drivers/gpu/drm/drm_mm.c
- :doc: lru scan roaster
+ :doc: lru scan roster
DRM MM Range Allocator Function References
------------------------------------------
@@ -452,3 +477,9 @@ DRM MM Range Allocator Function References
.. kernel-doc:: include/drm/drm_mm.h
:internal:
+
+DRM Cache Handling
+==================
+
+.. kernel-doc:: drivers/gpu/drm/drm_cache.c
+ :export:
diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst
index de3ac9f..fcc228e 100644
--- a/Documentation/gpu/drm-uapi.rst
+++ b/Documentation/gpu/drm-uapi.rst
@@ -156,8 +156,12 @@ other hand, a driver requires shared state between clients which is
visible to user-space and accessible beyond open-file boundaries, they
cannot support render nodes.
+
+Testing and validation
+======================
+
Validating changes with IGT
-===========================
+---------------------------
There's a collection of tests that aims to cover the whole functionality of
DRM drivers and that can be used to check that changes to DRM drivers or the
@@ -193,6 +197,12 @@ run-tests.sh is a wrapper around piglit that will execute the tests matching
the -t options. A report in HTML format will be available in
./results/html/index.html. Results can be compared with piglit.
+Display CRC Support
+-------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_debugfs_crc.c
+ :doc: CRC ABI
+
VBlank event handling
=====================
@@ -209,16 +219,3 @@ DRM_IOCTL_MODESET_CTL
mode setting, since on many devices the vertical blank counter is
reset to 0 at some point during modeset. Modern drivers should not
call this any more since with kernel mode setting it is a no-op.
-
-This second part of the GPU Driver Developer's Guide documents driver
-code, implementation details and also all the driver-specific userspace
-interfaces. Especially since all hardware-acceleration interfaces to
-userspace are driver specific for efficiency and other reasons these
-interfaces can be rather substantial. Hence every driver has its own
-chapter.
-
-Testing and validation
-======================
-
-.. kernel-doc:: drivers/gpu/drm/drm_debugfs_crc.c
- :doc: CRC ABI
diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst
index 7fb605a..b0d6709 100644
--- a/Documentation/gpu/i915.rst
+++ b/Documentation/gpu/i915.rst
@@ -222,6 +222,18 @@ Video BIOS Table (VBT)
.. kernel-doc:: drivers/gpu/drm/i915/intel_vbt_defs.h
:internal:
+Display PLLs
+------------
+
+.. kernel-doc:: drivers/gpu/drm/i915/intel_dpll_mgr.c
+ :doc: Display PLLs
+
+.. kernel-doc:: drivers/gpu/drm/i915/intel_dpll_mgr.c
+ :internal:
+
+.. kernel-doc:: drivers/gpu/drm/i915/intel_dpll_mgr.h
+ :internal:
+
Memory Management and Command Submission
========================================
@@ -365,4 +377,95 @@ switch_mm
.. kernel-doc:: drivers/gpu/drm/i915/i915_trace.h
:doc: switch_mm tracepoint
+Perf
+====
+
+Overview
+--------
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :doc: i915 Perf Overview
+
+Comparison with Core Perf
+-------------------------
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :doc: i915 Perf History and Comparison with Core Perf
+
+i915 Driver Entry Points
+------------------------
+
+This section covers the entrypoints exported outside of i915_perf.c to
+integrate with drm/i915 and to handle the `DRM_I915_PERF_OPEN` ioctl.
+
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_perf_init
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_perf_fini
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_perf_register
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_perf_unregister
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_perf_open_ioctl
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_perf_release
+
+i915 Perf Stream
+----------------
+
+This section covers the stream-semantics-agnostic structures and functions
+for representing an i915 perf stream FD and associated file operations.
+
+.. kernel-doc:: drivers/gpu/drm/i915/i915_drv.h
+ :functions: i915_perf_stream
+.. kernel-doc:: drivers/gpu/drm/i915/i915_drv.h
+ :functions: i915_perf_stream_ops
+
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: read_properties_unlocked
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_perf_open_ioctl_locked
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_perf_destroy_locked
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_perf_read
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_perf_ioctl
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_perf_enable_locked
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_perf_disable_locked
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_perf_poll
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_perf_poll_locked
+
+i915 Perf Observation Architecture Stream
+-----------------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/i915/i915_drv.h
+ :functions: i915_oa_ops
+
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_oa_stream_init
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_oa_read
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_oa_stream_enable
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_oa_stream_disable
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_oa_wait_unlocked
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :functions: i915_oa_poll_wait
+
+All i915 Perf Internals
+-----------------------
+
+This section simply includes all currently documented i915 perf internals, in
+no particular order, but may include some more minor utilities or platform
+specific details than found in the more high-level sections.
+
+.. kernel-doc:: drivers/gpu/drm/i915/i915_perf.c
+ :internal:
+
.. WARNING: DOCPROC directive not supported: !Cdrivers/gpu/drm/i915/i915_irq.c
diff --git a/Documentation/gpu/index.rst b/Documentation/gpu/index.rst
index 367d7c3..f81278a 100644
--- a/Documentation/gpu/index.rst
+++ b/Documentation/gpu/index.rst
@@ -11,6 +11,7 @@ Linux GPU Driver Developer's Guide
drm-kms-helpers
drm-uapi
i915
+ tinydrm
vga-switcheroo
vgaarbiter
diff --git a/Documentation/gpu/introduction.rst b/Documentation/gpu/introduction.rst
index 1903595..eb284eb 100644
--- a/Documentation/gpu/introduction.rst
+++ b/Documentation/gpu/introduction.rst
@@ -23,13 +23,12 @@ For consistency this documentation uses American English. Abbreviations
are written as all-uppercase, for example: DRM, KMS, IOCTL, CRTC, and so
on. To aid in reading, documentations make full use of the markup
characters kerneldoc provides: @parameter for function parameters,
-@member for structure members, &structure to reference structures and
-function() for functions. These all get automatically hyperlinked if
-kerneldoc for the referenced objects exists. When referencing entries in
-function vtables please use ->vfunc(). Note that kerneldoc does not
-support referencing struct members directly, so please add a reference
-to the vtable struct somewhere in the same paragraph or at least
-section.
+@member for structure members (within the same structure), &struct structure to
+reference structures and function() for functions. These all get automatically
+hyperlinked if kerneldoc for the referenced objects exists. When referencing
+entries in function vtables (and structure members in general) please use
+&vtable_name.vfunc. Unfortunately this does not yet yield a direct link to the
+member, only the structure.
Except in special situations (to separate locked from unlocked variants)
locking requirements for functions aren't documented in the kerneldoc.
@@ -49,3 +48,5 @@ section name should be all upper-case or not, and whether it should end
in a colon or not. Go with the file-local style. Other common section
names are "Notes" with information for dangerous or tricky corner cases,
and "FIXME" where the interface could be cleaned up.
+
+Also read the :ref:`guidelines for the kernel documentation at large <doc_guide>`.
diff --git a/Documentation/gpu/tinydrm.rst b/Documentation/gpu/tinydrm.rst
new file mode 100644
index 0000000..a913644
--- /dev/null
+++ b/Documentation/gpu/tinydrm.rst
@@ -0,0 +1,42 @@
+==========================
+drm/tinydrm Driver library
+==========================
+
+.. kernel-doc:: drivers/gpu/drm/tinydrm/core/tinydrm-core.c
+ :doc: overview
+
+Core functionality
+==================
+
+.. kernel-doc:: drivers/gpu/drm/tinydrm/core/tinydrm-core.c
+ :doc: core
+
+.. kernel-doc:: include/drm/tinydrm/tinydrm.h
+ :internal:
+
+.. kernel-doc:: drivers/gpu/drm/tinydrm/core/tinydrm-core.c
+ :export:
+
+.. kernel-doc:: drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c
+ :export:
+
+Additional helpers
+==================
+
+.. kernel-doc:: include/drm/tinydrm/tinydrm-helpers.h
+ :internal:
+
+.. kernel-doc:: drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
+ :export:
+
+MIPI DBI Compatible Controllers
+===============================
+
+.. kernel-doc:: drivers/gpu/drm/tinydrm/mipi-dbi.c
+ :doc: overview
+
+.. kernel-doc:: include/drm/tinydrm/mipi-dbi.h
+ :internal:
+
+.. kernel-doc:: drivers/gpu/drm/tinydrm/mipi-dbi.c
+ :export:
diff --git a/Documentation/sound/hd-audio/dp-mst.rst b/Documentation/sound/hd-audio/dp-mst.rst
index 58b7243..1617459 100644
--- a/Documentation/sound/hd-audio/dp-mst.rst
+++ b/Documentation/sound/hd-audio/dp-mst.rst
@@ -19,6 +19,23 @@ PCM
===
To be added
+Pin Initialization
+==================
+Each pin may have several device entries (virtual pins). On Intel platform,
+the device entries number is dynamically changed. If DP MST hub is connected,
+it is in DP MST mode, and the device entries number is 3. Otherwise, the
+device entries number is 1.
+
+To simplify the implementation, all the device entries will be initialized
+when bootup no matter whether it is in DP MST mode or not.
+
+Connection list
+===============
+DP MST reuses connection list code. The code can be reused because
+device entries on the same pin have the same connection list.
+
+This means DP MST gets the device entry connection list without the
+device entry setting.
Jack
====
diff --git a/MAINTAINERS b/MAINTAINERS
index 1b3a9cb..4b03c47 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4031,7 +4031,7 @@ F: drivers/dma-buf/
F: include/linux/dma-buf*
F: include/linux/reservation.h
F: include/linux/*fence.h
-F: Documentation/dma-buf-sharing.txt
+F: Documentation/driver-api/dma-buf.rst
T: git git://anongit.freedesktop.org/drm/drm-misc
SYNC FILE FRAMEWORK
@@ -4041,6 +4041,7 @@ S: Maintained
L: linux-media@vger.kernel.org
L: dri-devel@lists.freedesktop.org
F: drivers/dma-buf/sync_*
+F: drivers/dma-buf/dma-fence*
F: drivers/dma-buf/sw_sync.c
F: include/linux/sync_file.h
F: include/uapi/linux/sync_file.h
@@ -4315,6 +4316,12 @@ S: Supported
F: drivers/gpu/drm/mediatek/
F: Documentation/devicetree/bindings/display/mediatek/
+DRM DRIVER FOR MI0283QT
+M: Noralf Trønnes <noralf@tronnes.org>
+S: Maintained
+F: drivers/gpu/drm/tinydrm/mi0283qt.c
+F: Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt
+
DRM DRIVER FOR MSM ADRENO GPU
M: Rob Clark <robdclark@gmail.com>
L: linux-arm-msm@vger.kernel.org
diff --git a/arch/blackfin/include/asm/vga.h b/arch/blackfin/include/asm/vga.h
new file mode 100644
index 0000000..89d82fd
--- /dev/null
+++ b/arch/blackfin/include/asm/vga.h
@@ -0,0 +1 @@
+#include <asm-generic/vga.h>
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index 0f7d28a..9702c78 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -1420,8 +1420,10 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
}
EXPORT_SYMBOL(intel_gmch_probe);
-void intel_gtt_get(u64 *gtt_total, size_t *stolen_size,
- phys_addr_t *mappable_base, u64 *mappable_end)
+void intel_gtt_get(u64 *gtt_total,
+ u32 *stolen_size,
+ phys_addr_t *mappable_base,
+ u64 *mappable_end)
{
*gtt_total = intel_private.gtt_total_entries << PAGE_SHIFT;
*stolen_size = intel_private.stolen_size;
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index e72e644..718f832 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -124,6 +124,28 @@ static loff_t dma_buf_llseek(struct file *file, loff_t offset, int whence)
return base + offset;
}
+/**
+ * DOC: fence polling
+ *
+ * To support cross-device and cross-driver synchronization of buffer access
+ * implicit fences (represented internally in the kernel with &struct fence) can
+ * be attached to a &dma_buf. The glue for that and a few related things are
+ * provided in the &reservation_object structure.
+ *
+ * Userspace can query the state of these implicitly tracked fences using poll()
+ * and related system calls:
+ *
+ * - Checking for POLLIN, i.e. read access, can be use to query the state of the
+ * most recent write or exclusive fence.
+ *
+ * - Checking for POLLOUT, i.e. write access, can be used to query the state of
+ * all attached fences, shared and exclusive ones.
+ *
+ * Note that this only signals the completion of the respective fences, i.e. the
+ * DMA transfers are complete. Cache flushing and any other necessary
+ * preparations before CPU access can begin still need to happen.
+ */
+
static void dma_buf_poll_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
{
struct dma_buf_poll_cb_t *dcb = (struct dma_buf_poll_cb_t *)cb;
@@ -314,19 +336,52 @@ static inline int is_dma_buf_file(struct file *file)
}
/**
+ * DOC: dma buf device access
+ *
+ * For device DMA access to a shared DMA buffer the usual sequence of operations
+ * is fairly simple:
+ *
+ * 1. The exporter defines his exporter instance using
+ * DEFINE_DMA_BUF_EXPORT_INFO() and calls dma_buf_export() to wrap a private
+ * buffer object into a &dma_buf. It then exports that &dma_buf to userspace
+ * as a file descriptor by calling dma_buf_fd().
+ *
+ * 2. Userspace passes this file-descriptors to all drivers it wants this buffer
+ * to share with: First the filedescriptor is converted to a &dma_buf using
+ * dma_buf_get(). The the buffer is attached to the device using
+ * dma_buf_attach().
+ *
+ * Up to this stage the exporter is still free to migrate or reallocate the
+ * backing storage.
+ *
+ * 3. Once the buffer is attached to all devices userspace can inniate DMA
+ * access to the shared buffer. In the kernel this is done by calling
+ * dma_buf_map_attachment() and dma_buf_unmap_attachment().
+ *
+ * 4. Once a driver is done with a shared buffer it needs to call
+ * dma_buf_detach() (after cleaning up any mappings) and then release the
+ * reference acquired with dma_buf_get by calling dma_buf_put().
+ *
+ * For the detailed semantics exporters are expected to implement see
+ * &dma_buf_ops.
+ */
+
+/**
* dma_buf_export - Creates a new dma_buf, and associates an anon file
* with this buffer, so it can be exported.
* Also connect the allocator specific data and ops to the buffer.
* Additionally, provide a name string for exporter; useful in debugging.
*
* @exp_info: [in] holds all the export related information provided
- * by the exporter. see struct dma_buf_export_info
+ * by the exporter. see &struct dma_buf_export_info
* for further details.
*
* Returns, on success, a newly created dma_buf object, which wraps the
* supplied private data and operations for dma_buf_ops. On either missing
* ops, or error in allocating struct dma_buf, will return negative error.
*
+ * For most cases the easiest way to create @exp_info is through the
+ * %DEFINE_DMA_BUF_EXPORT_INFO macro.
*/
struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
{
@@ -458,7 +513,11 @@ EXPORT_SYMBOL_GPL(dma_buf_get);
* dma_buf_put - decreases refcount of the buffer
* @dmabuf: [in] buffer to reduce refcount of
*
- * Uses file's refcounting done implicitly by fput()
+ * Uses file's refcounting done implicitly by fput().
+ *
+ * If, as a result of this call, the refcount becomes 0, the 'release' file
+ * operation related to this fd is called. It calls &dma_buf_ops.release vfunc
+ * in turn, and frees the memory allocated for dmabuf when exported.
*/
void dma_buf_put(struct dma_buf *dmabuf)
{
@@ -475,8 +534,17 @@ EXPORT_SYMBOL_GPL(dma_buf_put);
* @dmabuf: [in] buffer to attach device to.
* @dev: [in] device to be attached.
*
- * Returns struct dma_buf_attachment * for this attachment; returns ERR_PTR on
- * error.
+ * Returns struct dma_buf_attachment pointer for this attachment. Attachments
+ * must be cleaned up by calling dma_buf_detach().
+ *
+ * Returns:
+ *
+ * A pointer to newly created &dma_buf_attachment on success, or a negative
+ * error code wrapped into a pointer on failure.
+ *
+ * Note that this can fail if the backing storage of @dmabuf is in a place not
+ * accessible to @dev, and cannot be moved to a more suitable place. This is
+ * indicated with the error code -EBUSY.
*/
struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
struct device *dev)
@@ -519,6 +587,7 @@ EXPORT_SYMBOL_GPL(dma_buf_attach);
* @dmabuf: [in] buffer to detach from.
* @attach: [in] attachment to be detached; is free'd after this call.
*
+ * Clean up a device attachment obtained by calling dma_buf_attach().
*/
void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
{
@@ -543,7 +612,12 @@ EXPORT_SYMBOL_GPL(dma_buf_detach);
* @direction: [in] direction of DMA transfer
*
* Returns sg_table containing the scatterlist to be returned; returns ERR_PTR
- * on error.
+ * on error. May return -EINTR if it is interrupted by a signal.
+ *
+ * A mapping must be unmapped again using dma_buf_map_attachment(). Note that
+ * the underlying backing storage is pinned for as long as a mapping exists,
+ * therefore users/importers should not hold onto a mapping for undue amounts of
+ * time.
*/
struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
enum dma_data_direction direction)
@@ -571,6 +645,7 @@ EXPORT_SYMBOL_GPL(dma_buf_map_attachment);
* @sg_table: [in] scatterlist info of the buffer to unmap
* @direction: [in] direction of DMA transfer
*
+ * This unmaps a DMA mapping for @attached obtained by dma_buf_map_attachment().
*/
void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
struct sg_table *sg_table,
@@ -586,6 +661,122 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
}
EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
+/**
+ * DOC: cpu access
+ *
+ * There are mutliple reasons for supporting CPU access to a dma buffer object:
+ *
+ * - Fallback operations in the kernel, for example when a device is connected
+ * over USB and the kernel needs to shuffle the data around first before
+ * sending it away. Cache coherency is handled by braketing any transactions
+ * with calls to dma_buf_begin_cpu_access() and dma_buf_end_cpu_access()
+ * access.
+ *
+ * To support dma_buf objects residing in highmem cpu access is page-based
+ * using an api similar to kmap. Accessing a dma_buf is done in aligned chunks
+ * of PAGE_SIZE size. Before accessing a chunk it needs to be mapped, which
+ * returns a pointer in kernel virtual address space. Afterwards the chunk
+ * needs to be unmapped again. There is no limit on how often a given chunk
+ * can be mapped and unmapped, i.e. the importer does not need to call
+ * begin_cpu_access again before mapping the same chunk again.
+ *
+ * Interfaces::
+ * void \*dma_buf_kmap(struct dma_buf \*, unsigned long);
+ * void dma_buf_kunmap(struct dma_buf \*, unsigned long, void \*);
+ *
+ * There are also atomic variants of these interfaces. Like for kmap they
+ * facilitate non-blocking fast-paths. Neither the importer nor the exporter
+ * (in the callback) is allowed to block when using these.
+ *
+ * Interfaces::
+ * void \*dma_buf_kmap_atomic(struct dma_buf \*, unsigned long);
+ * void dma_buf_kunmap_atomic(struct dma_buf \*, unsigned long, void \*);
+ *
+ * For importers all the restrictions of using kmap apply, like the limited
+ * supply of kmap_atomic slots. Hence an importer shall only hold onto at
+ * max 2 atomic dma_buf kmaps at the same time (in any given process context).
+ *
+ * dma_buf kmap calls outside of the range specified in begin_cpu_access are
+ * undefined. If the range is not PAGE_SIZE aligned, kmap needs to succeed on
+ * the partial chunks at the beginning and end but may return stale or bogus
+ * data outside of the range (in these partial chunks).
+ *
+ * Note that these calls need to always succeed. The exporter needs to
+ * complete any preparations that might fail in begin_cpu_access.
+ *
+ * For some cases the overhead of kmap can be too high, a vmap interface
+ * is introduced. This interface should be used very carefully, as vmalloc
+ * space is a limited resources on many architectures.
+ *
+ * Interfaces::
+ * void \*dma_buf_vmap(struct dma_buf \*dmabuf)
+ * void dma_buf_vunmap(struct dma_buf \*dmabuf, void \*vaddr)
+ *
+ * The vmap call can fail if there is no vmap support in the exporter, or if
+ * it runs out of vmalloc space. Fallback to kmap should be implemented. Note
+ * that the dma-buf layer keeps a reference count for all vmap access and
+ * calls down into the exporter's vmap function only when no vmapping exists,
+ * and only unmaps it once. Protection against concurrent vmap/vunmap calls is
+ * provided by taking the dma_buf->lock mutex.
+ *
+ * - For full compatibility on the importer side with existing userspace
+ * interfaces, which might already support mmap'ing buffers. This is needed in
+ * many processing pipelines (e.g. feeding a software rendered image into a
+ * hardware pipeline, thumbnail creation, snapshots, ...). Also, Android's ION
+ * framework already supported this and for DMA buffer file descriptors to
+ * replace ION buffers mmap support was needed.
+ *
+ * There is no special interfaces, userspace simply calls mmap on the dma-buf
+ * fd. But like for CPU access there's a need to braket the actual access,
+ * which is handled by the ioctl (DMA_BUF_IOCTL_SYNC). Note that
+ * DMA_BUF_IOCTL_SYNC can fail with -EAGAIN or -EINTR, in which case it must
+ * be restarted.
+ *
+ * Some systems might need some sort of cache coherency management e.g. when
+ * CPU and GPU domains are being accessed through dma-buf at the same time.
+ * To circumvent this problem there are begin/end coherency markers, that
+ * forward directly to existing dma-buf device drivers vfunc hooks. Userspace
+ * can make use of those markers through the DMA_BUF_IOCTL_SYNC ioctl. The
+ * sequence would be used like following:
+ *
+ * - mmap dma-buf fd
+ * - for each drawing/upload cycle in CPU 1. SYNC_START ioctl, 2. read/write
+ * to mmap area 3. SYNC_END ioctl. This can be repeated as often as you
+ * want (with the new data being consumed by say the GPU or the scanout
+ * device)
+ * - munmap once you don't need the buffer any more
+ *
+ * For correctness and optimal performance, it is always required to use
+ * SYNC_START and SYNC_END before and after, respectively, when accessing the
+ * mapped address. Userspace cannot rely on coherent access, even when there
+ * are systems where it just works without calling these ioctls.
+ *
+ * - And as a CPU fallback in userspace processing pipelines.
+ *
+ * Similar to the motivation for kernel cpu access it is again important that
+ * the userspace code of a given importing subsystem can use the same
+ * interfaces with a imported dma-buf buffer object as with a native buffer
+ * object. This is especially important for drm where the userspace part of
+ * contemporary OpenGL, X, and other drivers is huge, and reworking them to
+ * use a different way to mmap a buffer rather invasive.
+ *
+ * The assumption in the current dma-buf interfaces is that redirecting the
+ * initial mmap is all that's needed. A survey of some of the existing
+ * subsystems shows that no driver seems to do any nefarious thing like
+ * syncing up with outstanding asynchronous processing on the device or
+ * allocating special resources at fault time. So hopefully this is good
+ * enough, since adding interfaces to intercept pagefaults and allow pte
+ * shootdowns would increase the complexity quite a bit.
+ *
+ * Interface::
+ * int dma_buf_mmap(struct dma_buf \*, struct vm_area_struct \*,
+ * unsigned long);
+ *
+ * If the importing subsystem simply provides a special-purpose mmap call to
+ * set up a mapping in userspace, calling do_mmap with dma_buf->file will
+ * equally achieve that for a dma-buf object.
+ */
+
static int __dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
enum dma_data_direction direction)
{
@@ -611,6 +802,10 @@ static int __dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
* @dmabuf: [in] buffer to prepare cpu access for.
* @direction: [in] length of range for cpu access.
*
+ * After the cpu access is complete the caller should call
+ * dma_buf_end_cpu_access(). Only when cpu access is braketed by both calls is
+ * it guaranteed to be coherent with other DMA access.
+ *
* Can return negative error values, returns 0 on success.
*/
int dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
@@ -643,6 +838,8 @@ EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access);
* @dmabuf: [in] buffer to complete cpu access for.
* @direction: [in] length of range for cpu access.
*
+ * This terminates CPU access started with dma_buf_begin_cpu_access().
+ *
* Can return negative error values, returns 0 on success.
*/
int dma_buf_end_cpu_access(struct dma_buf *dmabuf,
diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c
index 0212af7..d1f1f45 100644
--- a/drivers/dma-buf/dma-fence.c
+++ b/drivers/dma-buf/dma-fence.c
@@ -28,6 +28,7 @@
EXPORT_TRACEPOINT_SYMBOL(dma_fence_annotate_wait_on);
EXPORT_TRACEPOINT_SYMBOL(dma_fence_emit);
+EXPORT_TRACEPOINT_SYMBOL(dma_fence_enable_signal);
/*
* fence context counter: each execution context should have its own
@@ -282,6 +283,31 @@ int dma_fence_add_callback(struct dma_fence *fence, struct dma_fence_cb *cb,
EXPORT_SYMBOL(dma_fence_add_callback);
/**
+ * dma_fence_get_status - returns the status upon completion
+ * @fence: [in] the dma_fence to query
+ *
+ * This wraps dma_fence_get_status_locked() to return the error status
+ * condition on a signaled fence. See dma_fence_get_status_locked() for more
+ * details.
+ *
+ * Returns 0 if the fence has not yet been signaled, 1 if the fence has
+ * been signaled without an error condition, or a negative error code
+ * if the fence has been completed in err.
+ */
+int dma_fence_get_status(struct dma_fence *fence)
+{
+ unsigned long flags;
+ int status;
+
+ spin_lock_irqsave(fence->lock, flags);
+ status = dma_fence_get_status_locked(fence);
+ spin_unlock_irqrestore(fence->lock, flags);
+
+ return status;
+}
+EXPORT_SYMBOL(dma_fence_get_status);
+
+/**
* dma_fence_remove_callback - remove a callback from the signaling list
* @fence: [in] the fence to wait on
* @cb: [in] the callback to remove
@@ -541,6 +567,7 @@ dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops,
fence->context = context;
fence->seqno = seqno;
fence->flags = 0UL;
+ fence->error = 0;
trace_dma_fence_init(fence);
}
diff --git a/drivers/dma-buf/sync_debug.c b/drivers/dma-buf/sync_debug.c
index 48b20e3..c769dc6 100644
--- a/drivers/dma-buf/sync_debug.c
+++ b/drivers/dma-buf/sync_debug.c
@@ -62,30 +62,29 @@ void sync_file_debug_remove(struct sync_file *sync_file)
static const char *sync_status_str(int status)
{
- if (status == 0)
- return "signaled";
+ if (status < 0)
+ return "error";
if (status > 0)
- return "active";
+ return "signaled";
- return "error";
+ return "active";
}
static void sync_print_fence(struct seq_file *s,
struct dma_fence *fence, bool show)
{
- int status = 1;
struct sync_timeline *parent = dma_fence_parent(fence);
+ int status;
- if (dma_fence_is_signaled_locked(fence))
- status = fence->status;
+ status = dma_fence_get_status_locked(fence);
seq_printf(s, " %s%sfence %s",
show ? parent->name : "",
show ? "_" : "",
sync_status_str(status));
- if (status <= 0) {
+ if (status) {
struct timespec64 ts64 =
ktime_to_timespec64(fence->timestamp);
@@ -136,7 +135,7 @@ static void sync_print_sync_file(struct seq_file *s,
int i;
seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name,
- sync_status_str(!dma_fence_is_signaled(sync_file->fence)));
+ sync_status_str(dma_fence_get_status(sync_file->fence)));
if (dma_fence_is_array(sync_file->fence)) {
struct dma_fence_array *array = to_dma_fence_array(sync_file->fence);
diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c
index 6d802f2..2321035 100644
--- a/drivers/dma-buf/sync_file.c
+++ b/drivers/dma-buf/sync_file.c
@@ -67,9 +67,10 @@ static void fence_check_cb_func(struct dma_fence *f, struct dma_fence_cb *cb)
* sync_file_create() - creates a sync file
* @fence: fence to add to the sync_fence
*
- * Creates a sync_file containg @fence. Once this is called, the sync_file
- * takes ownership of @fence. The sync_file can be released with
- * fput(sync_file->file). Returns the sync_file or NULL in case of error.
+ * Creates a sync_file containg @fence. This function acquires and additional
+ * reference of @fence for the newly-created &sync_file, if it succeeds. The
+ * sync_file can be released with fput(sync_file->file). Returns the
+ * sync_file or NULL in case of error.
*/
struct sync_file *sync_file_create(struct dma_fence *fence)
{
@@ -90,13 +91,6 @@ struct sync_file *sync_file_create(struct dma_fence *fence)
}
EXPORT_SYMBOL(sync_file_create);
-/**
- * sync_file_fdget() - get a sync_file from an fd
- * @fd: fd referencing a fence
- *
- * Ensures @fd references a valid sync_file, increments the refcount of the
- * backing file. Returns the sync_file or NULL in case of error.
- */
static struct sync_file *sync_file_fdget(int fd)
{
struct file *file = fget(fd);
@@ -379,10 +373,8 @@ static void sync_fill_fence_info(struct dma_fence *fence,
sizeof(info->obj_name));
strlcpy(info->driver_name, fence->ops->get_driver_name(fence),
sizeof(info->driver_name));
- if (dma_fence_is_signaled(fence))
- info->status = fence->status >= 0 ? 1 : fence->status;
- else
- info->status = 0;
+
+ info->status = dma_fence_get_status(fence);
info->timestamp_ns = ktime_to_ns(fence->timestamp);
}
@@ -468,4 +460,3 @@ static const struct file_operations sync_file_fops = {
.unlocked_ioctl = sync_file_ioctl,
.compat_ioctl = sync_file_ioctl,
};
-
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index ebfe840..88e01e08e 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -6,7 +6,7 @@
#
menuconfig DRM
tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
- depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU && HAS_DMA
+ depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && HAS_DMA
select HDMI
select FB_CMDLINE
select I2C
@@ -48,6 +48,21 @@ config DRM_DEBUG_MM
If in doubt, say "N".
+config DRM_DEBUG_MM_SELFTEST
+ tristate "kselftests for DRM range manager (struct drm_mm)"
+ depends on DRM
+ depends on DEBUG_KERNEL
+ select PRIME_NUMBERS
+ select DRM_LIB_RANDOM
+ default n
+ help
+ This option provides a kernel module that can be used to test
+ the DRM range manager (drm_mm) and its API. This option is not
+ useful for distributions or general kernels, but only for kernel
+ developers working on DRM and associated drivers.
+
+ If in doubt, say "N".
+
config DRM_KMS_HELPER
tristate
depends on DRM
@@ -98,7 +113,7 @@ config DRM_LOAD_EDID_FIRMWARE
config DRM_TTM
tristate
- depends on DRM
+ depends on DRM && MMU
help
GPU memory management subsystem for devices with multiple
GPU memory types. Will be enabled automatically if a device driver
@@ -121,13 +136,17 @@ config DRM_KMS_CMA_HELPER
help
Choose this if you need the KMS CMA helper functions
+config DRM_VM
+ bool
+ depends on DRM && MMU
+
source "drivers/gpu/drm/i2c/Kconfig"
source "drivers/gpu/drm/arm/Kconfig"
config DRM_RADEON
tristate "ATI Radeon"
- depends on DRM && PCI
+ depends on DRM && PCI && MMU
select FW_LOADER
select DRM_KMS_HELPER
select DRM_TTM
@@ -147,7 +166,7 @@ source "drivers/gpu/drm/radeon/Kconfig"
config DRM_AMDGPU
tristate "AMD GPU"
- depends on DRM && PCI
+ depends on DRM && PCI && MMU
select FW_LOADER
select DRM_KMS_HELPER
select DRM_TTM
@@ -244,11 +263,14 @@ source "drivers/gpu/drm/mxsfb/Kconfig"
source "drivers/gpu/drm/meson/Kconfig"
+source "drivers/gpu/drm/tinydrm/Kconfig"
+
# Keep legacy drivers last
menuconfig DRM_LEGACY
bool "Enable legacy drivers (DANGEROUS)"
- depends on DRM
+ depends on DRM && MMU
+ select DRM_VM
help
Enable legacy DRI1 drivers. Those drivers expose unsafe and dangerous
APIs to user-space, which can be used to circumvent access
@@ -321,3 +343,7 @@ config DRM_SAVAGE
chipset. If M is selected the module will be called savage.
endif # DRM_LEGACY
+
+config DRM_LIB_RANDOM
+ bool
+ default n
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index b9ae428..3ee9579 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -5,7 +5,7 @@
drm-y := drm_auth.o drm_bufs.o drm_cache.o \
drm_context.o drm_dma.o \
drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
- drm_lock.o drm_memory.o drm_drv.o drm_vm.o \
+ drm_lock.o drm_memory.o drm_drv.o \
drm_scatter.o drm_pci.o \
drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \
@@ -18,6 +18,8 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
drm_plane.o drm_color_mgmt.o drm_print.o \
drm_dumb_buffers.o drm_mode_config.o
+drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
+drm-$(CONFIG_DRM_VM) += drm_vm.o
drm-$(CONFIG_COMPAT) += drm_ioc32.o
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
drm-$(CONFIG_PCI) += ati_pcigart.o
@@ -37,6 +39,7 @@ drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
+obj-$(CONFIG_DRM_DEBUG_MM_SELFTEST) += selftests/
CFLAGS_drm_trace_points.o := -I$(src)
@@ -91,3 +94,4 @@ obj-$(CONFIG_DRM_ARCPGU)+= arc/
obj-y += hisilicon/
obj-$(CONFIG_DRM_ZTE) += zte/
obj-$(CONFIG_DRM_MXSFB) += mxsfb/
+obj-$(CONFIG_DRM_TINYDRM) += tinydrm/
diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index 41bd2bf..2814aad 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -24,7 +24,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
atombios_encoders.o amdgpu_sa.o atombios_i2c.o \
amdgpu_prime.o amdgpu_vm.o amdgpu_ib.o amdgpu_pll.o \
amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \
- amdgpu_gtt_mgr.o amdgpu_vram_mgr.o
+ amdgpu_gtt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o
# add asic specific block
amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \
@@ -34,7 +34,7 @@ amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \
amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce_v6_0.o si_dpm.o si_smc.o
amdgpu-y += \
- vi.o
+ vi.o mxgpu_vi.o
# add GMC block
amdgpu-y += \
@@ -52,8 +52,7 @@ amdgpu-y += \
# add SMC block
amdgpu-y += \
amdgpu_dpm.o \
- amdgpu_powerplay.o \
- cz_smc.o cz_dpm.o
+ amdgpu_powerplay.o
# add DCE block
amdgpu-y += \
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 63208e5..c1b9135 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -91,7 +91,6 @@ extern int amdgpu_vm_fault_stop;
extern int amdgpu_vm_debug;
extern int amdgpu_sched_jobs;
extern int amdgpu_sched_hw_submission;
-extern int amdgpu_powerplay;
extern int amdgpu_no_evict;
extern int amdgpu_direct_gma_size;
extern unsigned amdgpu_pcie_gen_cap;
@@ -184,12 +183,18 @@ enum amdgpu_thermal_irq {
AMDGPU_THERMAL_IRQ_LAST
};
+enum amdgpu_kiq_irq {
+ AMDGPU_CP_KIQ_IRQ_DRIVER0 = 0,
+ AMDGPU_CP_KIQ_IRQ_LAST
+};
+
int amdgpu_set_clockgating_state(struct amdgpu_device *adev,
enum amd_ip_block_type block_type,
enum amd_clockgating_state state);
int amdgpu_set_powergating_state(struct amdgpu_device *adev,
enum amd_ip_block_type block_type,
enum amd_powergating_state state);
+void amdgpu_get_clockgating_state(struct amdgpu_device *adev, u32 *flags);
int amdgpu_wait_for_idle(struct amdgpu_device *adev,
enum amd_ip_block_type block_type);
bool amdgpu_is_idle(struct amdgpu_device *adev,
@@ -352,7 +357,7 @@ struct amdgpu_bo_va_mapping {
struct list_head list;
struct interval_tree_node it;
uint64_t offset;
- uint32_t flags;
+ uint64_t flags;
};
/* bo virtual addresses in a specific vm */
@@ -776,14 +781,20 @@ struct amdgpu_mec {
u32 num_queue;
};
+struct amdgpu_kiq {
+ u64 eop_gpu_addr;
+ struct amdgpu_bo *eop_obj;
+ struct amdgpu_ring ring;
+ struct amdgpu_irq_src irq;
+};
+
/*
* GPU scratch registers structures, functions & helpers
*/
struct amdgpu_scratch {
unsigned num_reg;
uint32_t reg_base;
- bool free[32];
- uint32_t reg[32];
+ uint32_t free_mask;
};
/*
@@ -851,6 +862,7 @@ struct amdgpu_gfx {
struct amdgpu_gca_config config;
struct amdgpu_rlc rlc;
struct amdgpu_mec mec;
+ struct amdgpu_kiq kiq;
struct amdgpu_scratch scratch;
const struct firmware *me_fw; /* ME firmware */
uint32_t me_fw_version;
@@ -894,8 +906,8 @@ int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm,
void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib,
struct dma_fence *f);
int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
- struct amdgpu_ib *ib, struct dma_fence *last_vm_update,
- struct amdgpu_job *job, struct dma_fence **f);
+ struct amdgpu_ib *ibs, struct amdgpu_job *job,
+ struct dma_fence **f);
int amdgpu_ib_pool_init(struct amdgpu_device *adev);
void amdgpu_ib_pool_fini(struct amdgpu_device *adev);
int amdgpu_ib_ring_tests(struct amdgpu_device *adev);
@@ -938,6 +950,7 @@ struct amdgpu_cs_parser {
#define AMDGPU_PREAMBLE_IB_PRESENT (1 << 0) /* bit set means command submit involves a preamble IB */
#define AMDGPU_PREAMBLE_IB_PRESENT_FIRST (1 << 1) /* bit set means preamble IB is first presented in belonging context */
#define AMDGPU_HAVE_CTX_SWITCH (1 << 2) /* bit set means context switch occured */
+#define AMDGPU_VM_DOMAIN (1 << 3) /* bit set means in virtual memory context */
struct amdgpu_job {
struct amd_sched_job base;
@@ -1133,7 +1146,6 @@ int amdgpu_debugfs_fence_init(struct amdgpu_device *adev);
#if defined(CONFIG_DEBUG_FS)
int amdgpu_debugfs_init(struct drm_minor *minor);
-void amdgpu_debugfs_cleanup(struct drm_minor *minor);
#endif
int amdgpu_debugfs_firmware_init(struct amdgpu_device *adev);
@@ -1178,7 +1190,6 @@ struct amdgpu_asic_funcs {
bool (*read_disabled_bios)(struct amdgpu_device *adev);
bool (*read_bios_from_rom)(struct amdgpu_device *adev,
u8 *bios, u32 length_bytes);
- void (*detect_hw_virtualization) (struct amdgpu_device *adev);
int (*read_register)(struct amdgpu_device *adev, u32 se_num,
u32 sh_num, u32 reg_offset, u32 *value);
void (*set_vga_state)(struct amdgpu_device *adev, bool state);
@@ -1333,7 +1344,6 @@ struct amdgpu_device {
/* BIOS */
uint8_t *bios;
uint32_t bios_size;
- bool is_atom_bios;
struct amdgpu_bo *stollen_vga_memory;
uint32_t bios_scratch[AMDGPU_BIOS_NUM_SCRATCH];
@@ -1463,7 +1473,7 @@ struct amdgpu_device {
/* amdkfd interface */
struct kfd_dev *kfd;
- struct amdgpu_virtualization virtualization;
+ struct amdgpu_virt virt;
/* link all shadow bo */
struct list_head shadow_list;
@@ -1472,6 +1482,9 @@ struct amdgpu_device {
spinlock_t gtt_list_lock;
struct list_head gtt_list;
+ /* record hw reset is performed */
+ bool has_hw_reset;
+
};
static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev)
@@ -1576,6 +1589,37 @@ static inline void amdgpu_ring_write(struct amdgpu_ring *ring, uint32_t v)
ring->count_dw--;
}
+static inline void amdgpu_ring_write_multiple(struct amdgpu_ring *ring, void *src, int count_dw)
+{
+ unsigned occupied, chunk1, chunk2;
+ void *dst;
+
+ if (ring->count_dw < count_dw) {
+ DRM_ERROR("amdgpu: writing more dwords to the ring than expected!\n");
+ } else {
+ occupied = ring->wptr & ring->ptr_mask;
+ dst = (void *)&ring->ring[occupied];
+ chunk1 = ring->ptr_mask + 1 - occupied;
+ chunk1 = (chunk1 >= count_dw) ? count_dw: chunk1;
+ chunk2 = count_dw - chunk1;
+ chunk1 <<= 2;
+ chunk2 <<= 2;
+
+ if (chunk1)
+ memcpy(dst, src, chunk1);
+
+ if (chunk2) {
+ src += chunk1;
+ dst = (void *)ring->ring;
+ memcpy(dst, src, chunk2);
+ }
+
+ ring->wptr += count_dw;
+ ring->wptr &= ring->ptr_mask;
+ ring->count_dw -= count_dw;
+ }
+}
+
static inline struct amdgpu_sdma_instance *
amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
{
@@ -1605,7 +1649,6 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
#define amdgpu_asic_get_gpu_clock_counter(adev) (adev)->asic_funcs->get_gpu_clock_counter((adev))
#define amdgpu_asic_read_disabled_bios(adev) (adev)->asic_funcs->read_disabled_bios((adev))
#define amdgpu_asic_read_bios_from_rom(adev, b, l) (adev)->asic_funcs->read_bios_from_rom((adev), (b), (l))
-#define amdgpu_asic_detect_hw_virtualization(adev) (adev)->asic_funcs->detect_hw_virtualization((adev))
#define amdgpu_asic_read_register(adev, se, sh, offset, v)((adev)->asic_funcs->read_register((adev), (se), (sh), (offset), (v)))
#define amdgpu_gart_flush_gpu_tlb(adev, vmid) (adev)->gart.gart_funcs->flush_gpu_tlb((adev), (vmid))
#define amdgpu_gart_set_pte_pde(adev, pt, idx, addr, flags) (adev)->gart.gart_funcs->set_pte_pde((adev), (pt), (idx), (addr), (flags))
@@ -1627,6 +1670,8 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
#define amdgpu_ring_emit_hdp_invalidate(r) (r)->funcs->emit_hdp_invalidate((r))
#define amdgpu_ring_emit_switch_buffer(r) (r)->funcs->emit_switch_buffer((r))
#define amdgpu_ring_emit_cntxcntl(r, d) (r)->funcs->emit_cntxcntl((r), (d))
+#define amdgpu_ring_emit_rreg(r, d) (r)->funcs->emit_rreg((r), (d))
+#define amdgpu_ring_emit_wreg(r, d, v) (r)->funcs->emit_wreg((r), (d), (v))
#define amdgpu_ring_pad_ib(r, ib) ((r)->funcs->pad_ib((r), (ib)))
#define amdgpu_ring_init_cond_exec(r) (r)->funcs->init_cond_exec((r))
#define amdgpu_ring_patch_cond_exec(r,o) (r)->funcs->patch_cond_exec((r),(o))
@@ -1658,13 +1703,14 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
int amdgpu_gpu_reset(struct amdgpu_device *adev);
bool amdgpu_need_backup(struct amdgpu_device *adev);
void amdgpu_pci_config_reset(struct amdgpu_device *adev);
-bool amdgpu_card_posted(struct amdgpu_device *adev);
+bool amdgpu_need_post(struct amdgpu_device *adev);
void amdgpu_update_display_priority(struct amdgpu_device *adev);
int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data);
int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,
u32 ip_instance, u32 ring,
struct amdgpu_ring **out_ring);
+void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, u64 num_bytes);
void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *abo, u32 domain);
bool amdgpu_ttm_bo_is_amdgpu_bo(struct ttm_buffer_object *bo);
int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages);
@@ -1711,7 +1757,7 @@ extern const struct drm_ioctl_desc amdgpu_ioctls_kms[];
extern const int amdgpu_max_kms_ioctl;
int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags);
-int amdgpu_driver_unload_kms(struct drm_device *dev);
+void amdgpu_driver_unload_kms(struct drm_device *dev);
void amdgpu_driver_lastclose_kms(struct drm_device *dev);
int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv);
void amdgpu_driver_postclose_kms(struct drm_device *dev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index 5796539..ef79551 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -672,12 +672,10 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
if ((enc->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
enc->enc_priv) {
- if (adev->is_atom_bios) {
- struct amdgpu_encoder_atom_dig *dig = enc->enc_priv;
- if (dig->bl_dev) {
- atif->encoder_for_bl = enc;
- break;
- }
+ struct amdgpu_encoder_atom_dig *dig = enc->enc_priv;
+ if (dig->bl_dev) {
+ atif->encoder_for_bl = enc;
+ break;
}
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
index 8ec1967..821f7cc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -42,6 +42,51 @@
#define AMD_IS_VALID_VBIOS(p) ((p)[0] == 0x55 && (p)[1] == 0xAA)
#define AMD_VBIOS_LENGTH(p) ((p)[2] << 9)
+/* Check if current bios is an ATOM BIOS.
+ * Return true if it is ATOM BIOS. Otherwise, return false.
+ */
+static bool check_atom_bios(uint8_t *bios, size_t size)
+{
+ uint16_t tmp, bios_header_start;
+
+ if (!bios || size < 0x49) {
+ DRM_INFO("vbios mem is null or mem size is wrong\n");
+ return false;
+ }
+
+ if (!AMD_IS_VALID_VBIOS(bios)) {
+ DRM_INFO("BIOS signature incorrect %x %x\n", bios[0], bios[1]);
+ return false;
+ }
+
+ tmp = bios[0x18] | (bios[0x19] << 8);
+ if (bios[tmp + 0x14] != 0x0) {
+ DRM_INFO("Not an x86 BIOS ROM\n");
+ return false;
+ }
+
+ bios_header_start = bios[0x48] | (bios[0x49] << 8);
+ if (!bios_header_start) {
+ DRM_INFO("Can't locate bios header\n");
+ return false;
+ }
+
+ tmp = bios_header_start + 4;
+ if (size < tmp) {
+ DRM_INFO("BIOS header is broken\n");
+ return false;
+ }
+
+ if (!memcmp(bios + tmp, "ATOM", 4) ||
+ !memcmp(bios + tmp, "MOTA", 4)) {
+ DRM_DEBUG("ATOMBIOS detected\n");
+ return true;
+ }
+
+ return false;
+}
+
+
/* If you boot an IGP board with a discrete card as the primary,
* the IGP rom is not accessible via the rom bar as the IGP rom is
* part of the system bios. On boot, the system bios puts a
@@ -55,7 +100,7 @@ static bool igp_read_bios_from_vram(struct amdgpu_device *adev)
resource_size_t size = 256 * 1024; /* ??? */
if (!(adev->flags & AMD_IS_APU))
- if (!amdgpu_card_posted(adev))
+ if (amdgpu_need_post(adev))
return false;
adev->bios = NULL;
@@ -65,10 +110,6 @@ static bool igp_read_bios_from_vram(struct amdgpu_device *adev)
return false;
}
- if (size == 0 || !AMD_IS_VALID_VBIOS(bios)) {
- iounmap(bios);
- return false;
- }
adev->bios = kmalloc(size, GFP_KERNEL);
if (!adev->bios) {
iounmap(bios);
@@ -77,12 +118,18 @@ static bool igp_read_bios_from_vram(struct amdgpu_device *adev)
adev->bios_size = size;
memcpy_fromio(adev->bios, bios, size);
iounmap(bios);
+
+ if (!check_atom_bios(adev->bios, size)) {
+ kfree(adev->bios);
+ return false;
+ }
+
return true;
}
bool amdgpu_read_bios(struct amdgpu_device *adev)
{
- uint8_t __iomem *bios, val[2];
+ uint8_t __iomem *bios;
size_t size;
adev->bios = NULL;
@@ -92,13 +139,6 @@ bool amdgpu_read_bios(struct amdgpu_device *adev)
return false;
}
- val[0] = readb(&bios[0]);
- val[1] = readb(&bios[1]);
-
- if (size == 0 || !AMD_IS_VALID_VBIOS(val)) {
- pci_unmap_rom(adev->pdev, bios);
- return false;
- }
adev->bios = kzalloc(size, GFP_KERNEL);
if (adev->bios == NULL) {
pci_unmap_rom(adev->pdev, bios);
@@ -107,6 +147,12 @@ bool amdgpu_read_bios(struct amdgpu_device *adev)
adev->bios_size = size;
memcpy_fromio(adev->bios, bios, size);
pci_unmap_rom(adev->pdev, bios);
+
+ if (!check_atom_bios(adev->bios, size)) {
+ kfree(adev->bios);
+ return false;
+ }
+
return true;
}
@@ -140,7 +186,14 @@ static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev)
adev->bios_size = len;
/* read complete BIOS */
- return amdgpu_asic_read_bios_from_rom(adev, adev->bios, len);
+ amdgpu_asic_read_bios_from_rom(adev, adev->bios, len);
+
+ if (!check_atom_bios(adev->bios, len)) {
+ kfree(adev->bios);
+ return false;
+ }
+
+ return true;
}
static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
@@ -155,13 +208,17 @@ static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
return false;
}
- if (size == 0 || !AMD_IS_VALID_VBIOS(bios)) {
+ adev->bios = kzalloc(size, GFP_KERNEL);
+ if (adev->bios == NULL)
return false;
- }
- adev->bios = kmemdup(bios, size, GFP_KERNEL);
- if (adev->bios == NULL) {
+
+ memcpy_fromio(adev->bios, bios, size);
+
+ if (!check_atom_bios(adev->bios, size)) {
+ kfree(adev->bios);
return false;
}
+
adev->bios_size = size;
return true;
@@ -273,7 +330,7 @@ static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
break;
}
- if (i == 0 || !AMD_IS_VALID_VBIOS(adev->bios)) {
+ if (!check_atom_bios(adev->bios, size)) {
kfree(adev->bios);
return false;
}
@@ -298,53 +355,59 @@ static bool amdgpu_read_disabled_bios(struct amdgpu_device *adev)
#ifdef CONFIG_ACPI
static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
{
- bool ret = false;
struct acpi_table_header *hdr;
acpi_size tbl_size;
UEFI_ACPI_VFCT *vfct;
- GOP_VBIOS_CONTENT *vbios;
- VFCT_IMAGE_HEADER *vhdr;
+ unsigned offset;
if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
return false;
tbl_size = hdr->length;
if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n");
- goto out_unmap;
+ return false;
}
vfct = (UEFI_ACPI_VFCT *)hdr;
- if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) {
- DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n");
- goto out_unmap;
- }
+ offset = vfct->VBIOSImageOffset;
- vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset);
- vhdr = &vbios->VbiosHeader;
- DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n",
- vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction,
- vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength);
-
- if (vhdr->PCIBus != adev->pdev->bus->number ||
- vhdr->PCIDevice != PCI_SLOT(adev->pdev->devfn) ||
- vhdr->PCIFunction != PCI_FUNC(adev->pdev->devfn) ||
- vhdr->VendorID != adev->pdev->vendor ||
- vhdr->DeviceID != adev->pdev->device) {
- DRM_INFO("ACPI VFCT table is not for this card\n");
- goto out_unmap;
- }
+ while (offset < tbl_size) {
+ GOP_VBIOS_CONTENT *vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + offset);
+ VFCT_IMAGE_HEADER *vhdr = &vbios->VbiosHeader;
- if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) {
- DRM_ERROR("ACPI VFCT image truncated\n");
- goto out_unmap;
- }
+ offset += sizeof(VFCT_IMAGE_HEADER);
+ if (offset > tbl_size) {
+ DRM_ERROR("ACPI VFCT image header truncated\n");
+ return false;
+ }
+
+ offset += vhdr->ImageLength;
+ if (offset > tbl_size) {
+ DRM_ERROR("ACPI VFCT image truncated\n");
+ return false;
+ }
- adev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL);
- adev->bios_size = vhdr->ImageLength;
- ret = !!adev->bios;
+ if (vhdr->ImageLength &&
+ vhdr->PCIBus == adev->pdev->bus->number &&
+ vhdr->PCIDevice == PCI_SLOT(adev->pdev->devfn) &&
+ vhdr->PCIFunction == PCI_FUNC(adev->pdev->devfn) &&
+ vhdr->VendorID == adev->pdev->vendor &&
+ vhdr->DeviceID == adev->pdev->device) {
+ adev->bios = kmemdup(&vbios->VbiosContent,
+ vhdr->ImageLength,
+ GFP_KERNEL);
+
+ if (!check_atom_bios(adev->bios, vhdr->ImageLength)) {
+ kfree(adev->bios);
+ return false;
+ }
+ adev->bios_size = vhdr->ImageLength;
+ return true;
+ }
+ }
-out_unmap:
- return ret;
+ DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n");
+ return false;
}
#else
static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
@@ -355,57 +418,27 @@ static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
bool amdgpu_get_bios(struct amdgpu_device *adev)
{
- bool r;
- uint16_t tmp, bios_header_start;
+ if (amdgpu_atrm_get_bios(adev))
+ return true;
- r = amdgpu_atrm_get_bios(adev);
- if (!r)
- r = amdgpu_acpi_vfct_bios(adev);
- if (!r)
- r = igp_read_bios_from_vram(adev);
- if (!r)
- r = amdgpu_read_bios(adev);
- if (!r) {
- r = amdgpu_read_bios_from_rom(adev);
- }
- if (!r) {
- r = amdgpu_read_disabled_bios(adev);
- }
- if (!r) {
- r = amdgpu_read_platform_bios(adev);
- }
- if (!r || adev->bios == NULL) {
- DRM_ERROR("Unable to locate a BIOS ROM\n");
- adev->bios = NULL;
- return false;
- }
- if (!AMD_IS_VALID_VBIOS(adev->bios)) {
- printk("BIOS signature incorrect %x %x\n", adev->bios[0], adev->bios[1]);
- goto free_bios;
- }
+ if (amdgpu_acpi_vfct_bios(adev))
+ return true;
- tmp = RBIOS16(0x18);
- if (RBIOS8(tmp + 0x14) != 0x0) {
- DRM_INFO("Not an x86 BIOS ROM, not using.\n");
- goto free_bios;
- }
+ if (igp_read_bios_from_vram(adev))
+ return true;
- bios_header_start = RBIOS16(0x48);
- if (!bios_header_start) {
- goto free_bios;
- }
- tmp = bios_header_start + 4;
- if (!memcmp(adev->bios + tmp, "ATOM", 4) ||
- !memcmp(adev->bios + tmp, "MOTA", 4)) {
- adev->is_atom_bios = true;
- } else {
- adev->is_atom_bios = false;
- }
+ if (amdgpu_read_bios(adev))
+ return true;
- DRM_DEBUG("%sBIOS detected\n", adev->is_atom_bios ? "ATOM" : "COM");
- return true;
-free_bios:
- kfree(adev->bios);
- adev->bios = NULL;
+ if (amdgpu_read_bios_from_rom(adev))
+ return true;
+
+ if (amdgpu_read_disabled_bios(adev))
+ return true;
+
+ if (amdgpu_read_platform_bios(adev))
+ return true;
+
+ DRM_ERROR("Unable to locate a BIOS ROM\n");
return false;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
index 4c851fde..d9e5aa4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
@@ -713,6 +713,7 @@ static int amdgpu_cgs_rel_firmware(struct cgs_device *cgs_device, enum cgs_ucode
CGS_FUNC_ADEV;
if ((CGS_UCODE_ID_SMU == type) || (CGS_UCODE_ID_SMU_SK == type)) {
release_firmware(adev->pm.fw);
+ adev->pm.fw = NULL;
return 0;
}
/* cannot release other firmware because they are not created by cgs */
@@ -762,6 +763,23 @@ static uint16_t amdgpu_get_firmware_version(struct cgs_device *cgs_device,
return fw_version;
}
+static int amdgpu_cgs_enter_safe_mode(struct cgs_device *cgs_device,
+ bool en)
+{
+ CGS_FUNC_ADEV;
+
+ if (adev->gfx.rlc.funcs->enter_safe_mode == NULL ||
+ adev->gfx.rlc.funcs->exit_safe_mode == NULL)
+ return 0;
+
+ if (en)
+ adev->gfx.rlc.funcs->enter_safe_mode(adev);
+ else
+ adev->gfx.rlc.funcs->exit_safe_mode(adev);
+
+ return 0;
+}
+
static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
enum cgs_ucode_id type,
struct cgs_firmware_info *info)
@@ -808,37 +826,65 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
const uint8_t *src;
const struct smc_firmware_header_v1_0 *hdr;
+ if (CGS_UCODE_ID_SMU_SK == type)
+ amdgpu_cgs_rel_firmware(cgs_device, CGS_UCODE_ID_SMU);
+
if (!adev->pm.fw) {
switch (adev->asic_type) {
case CHIP_TOPAZ:
if (((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x81)) ||
((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x83)) ||
- ((adev->pdev->device == 0x6907) && (adev->pdev->revision == 0x87)))
+ ((adev->pdev->device == 0x6907) && (adev->pdev->revision == 0x87))) {
+ info->is_kicker = true;
strcpy(fw_name, "amdgpu/topaz_k_smc.bin");
- else
+ } else
strcpy(fw_name, "amdgpu/topaz_smc.bin");
break;
case CHIP_TONGA:
if (((adev->pdev->device == 0x6939) && (adev->pdev->revision == 0xf1)) ||
- ((adev->pdev->device == 0x6938) && (adev->pdev->revision == 0xf1)))
+ ((adev->pdev->device == 0x6938) && (adev->pdev->revision == 0xf1))) {
+ info->is_kicker = true;
strcpy(fw_name, "amdgpu/tonga_k_smc.bin");
- else
+ } else
strcpy(fw_name, "amdgpu/tonga_smc.bin");
break;
case CHIP_FIJI:
strcpy(fw_name, "amdgpu/fiji_smc.bin");
break;
case CHIP_POLARIS11:
- if (type == CGS_UCODE_ID_SMU)
- strcpy(fw_name, "amdgpu/polaris11_smc.bin");
- else if (type == CGS_UCODE_ID_SMU_SK)
+ if (type == CGS_UCODE_ID_SMU) {
+ if (((adev->pdev->device == 0x67ef) &&
+ ((adev->pdev->revision == 0xe0) ||
+ (adev->pdev->revision == 0xe2) ||
+ (adev->pdev->revision == 0xe5))) ||
+ ((adev->pdev->device == 0x67ff) &&
+ ((adev->pdev->revision == 0xcf) ||
+ (adev->pdev->revision == 0xef) ||
+ (adev->pdev->revision == 0xff)))) {
+ info->is_kicker = true;
+ strcpy(fw_name, "amdgpu/polaris11_k_smc.bin");
+ } else
+ strcpy(fw_name, "amdgpu/polaris11_smc.bin");
+ } else if (type == CGS_UCODE_ID_SMU_SK) {
strcpy(fw_name, "amdgpu/polaris11_smc_sk.bin");
+ }
break;
case CHIP_POLARIS10:
- if (type == CGS_UCODE_ID_SMU)
- strcpy(fw_name, "amdgpu/polaris10_smc.bin");
- else if (type == CGS_UCODE_ID_SMU_SK)
+ if (type == CGS_UCODE_ID_SMU) {
+ if ((adev->pdev->device == 0x67df) &&
+ ((adev->pdev->revision == 0xe0) ||
+ (adev->pdev->revision == 0xe3) ||
+ (adev->pdev->revision == 0xe4) ||
+ (adev->pdev->revision == 0xe5) ||
+ (adev->pdev->revision == 0xe7) ||
+ (adev->pdev->revision == 0xef))) {
+ info->is_kicker = true;
+ strcpy(fw_name, "amdgpu/polaris10_k_smc.bin");
+ } else
+ strcpy(fw_name, "amdgpu/polaris10_smc.bin");
+ } else if (type == CGS_UCODE_ID_SMU_SK) {
strcpy(fw_name, "amdgpu/polaris10_smc_sk.bin");
+ }
break;
case CHIP_POLARIS12:
strcpy(fw_name, "amdgpu/polaris12_smc.bin");
@@ -1200,51 +1246,52 @@ static int amdgpu_cgs_call_acpi_method(struct cgs_device *cgs_device,
}
static const struct cgs_ops amdgpu_cgs_ops = {
- amdgpu_cgs_gpu_mem_info,
- amdgpu_cgs_gmap_kmem,
- amdgpu_cgs_gunmap_kmem,
- amdgpu_cgs_alloc_gpu_mem,
- amdgpu_cgs_free_gpu_mem,
- amdgpu_cgs_gmap_gpu_mem,
- amdgpu_cgs_gunmap_gpu_mem,
- amdgpu_cgs_kmap_gpu_mem,
- amdgpu_cgs_kunmap_gpu_mem,
- amdgpu_cgs_read_register,
- amdgpu_cgs_write_register,
- amdgpu_cgs_read_ind_register,
- amdgpu_cgs_write_ind_register,
- amdgpu_cgs_read_pci_config_byte,
- amdgpu_cgs_read_pci_config_word,
- amdgpu_cgs_read_pci_config_dword,
- amdgpu_cgs_write_pci_config_byte,
- amdgpu_cgs_write_pci_config_word,
- amdgpu_cgs_write_pci_config_dword,
- amdgpu_cgs_get_pci_resource,
- amdgpu_cgs_atom_get_data_table,
- amdgpu_cgs_atom_get_cmd_table_revs,
- amdgpu_cgs_atom_exec_cmd_table,
- amdgpu_cgs_create_pm_request,
- amdgpu_cgs_destroy_pm_request,
- amdgpu_cgs_set_pm_request,
- amdgpu_cgs_pm_request_clock,
- amdgpu_cgs_pm_request_engine,
- amdgpu_cgs_pm_query_clock_limits,
- amdgpu_cgs_set_camera_voltages,
- amdgpu_cgs_get_firmware_info,
- amdgpu_cgs_rel_firmware,
- amdgpu_cgs_set_powergating_state,
- amdgpu_cgs_set_clockgating_state,
- amdgpu_cgs_get_active_displays_info,
- amdgpu_cgs_notify_dpm_enabled,
- amdgpu_cgs_call_acpi_method,
- amdgpu_cgs_query_system_info,
- amdgpu_cgs_is_virtualization_enabled
+ .gpu_mem_info = amdgpu_cgs_gpu_mem_info,
+ .gmap_kmem = amdgpu_cgs_gmap_kmem,
+ .gunmap_kmem = amdgpu_cgs_gunmap_kmem,
+ .alloc_gpu_mem = amdgpu_cgs_alloc_gpu_mem,
+ .free_gpu_mem = amdgpu_cgs_free_gpu_mem,
+ .gmap_gpu_mem = amdgpu_cgs_gmap_gpu_mem,
+ .gunmap_gpu_mem = amdgpu_cgs_gunmap_gpu_mem,
+ .kmap_gpu_mem = amdgpu_cgs_kmap_gpu_mem,
+ .kunmap_gpu_mem = amdgpu_cgs_kunmap_gpu_mem,
+ .read_register = amdgpu_cgs_read_register,
+ .write_register = amdgpu_cgs_write_register,
+ .read_ind_register = amdgpu_cgs_read_ind_register,
+ .write_ind_register = amdgpu_cgs_write_ind_register,
+ .read_pci_config_byte = amdgpu_cgs_read_pci_config_byte,
+ .read_pci_config_word = amdgpu_cgs_read_pci_config_word,
+ .read_pci_config_dword = amdgpu_cgs_read_pci_config_dword,
+ .write_pci_config_byte = amdgpu_cgs_write_pci_config_byte,
+ .write_pci_config_word = amdgpu_cgs_write_pci_config_word,
+ .write_pci_config_dword = amdgpu_cgs_write_pci_config_dword,
+ .get_pci_resource = amdgpu_cgs_get_pci_resource,
+ .atom_get_data_table = amdgpu_cgs_atom_get_data_table,
+ .atom_get_cmd_table_revs = amdgpu_cgs_atom_get_cmd_table_revs,
+ .atom_exec_cmd_table = amdgpu_cgs_atom_exec_cmd_table,
+ .create_pm_request = amdgpu_cgs_create_pm_request,
+ .destroy_pm_request = amdgpu_cgs_destroy_pm_request,
+ .set_pm_request = amdgpu_cgs_set_pm_request,
+ .pm_request_clock = amdgpu_cgs_pm_request_clock,
+ .pm_request_engine = amdgpu_cgs_pm_request_engine,
+ .pm_query_clock_limits = amdgpu_cgs_pm_query_clock_limits,
+ .set_camera_voltages = amdgpu_cgs_set_camera_voltages,
+ .get_firmware_info = amdgpu_cgs_get_firmware_info,
+ .rel_firmware = amdgpu_cgs_rel_firmware,
+ .set_powergating_state = amdgpu_cgs_set_powergating_state,
+ .set_clockgating_state = amdgpu_cgs_set_clockgating_state,
+ .get_active_displays_info = amdgpu_cgs_get_active_displays_info,
+ .notify_dpm_enabled = amdgpu_cgs_notify_dpm_enabled,
+ .call_acpi_method = amdgpu_cgs_call_acpi_method,
+ .query_system_info = amdgpu_cgs_query_system_info,
+ .is_virtualization_enabled = amdgpu_cgs_is_virtualization_enabled,
+ .enter_safe_mode = amdgpu_cgs_enter_safe_mode,
};
static const struct cgs_os_ops amdgpu_cgs_os_ops = {
- amdgpu_cgs_add_irq_source,
- amdgpu_cgs_irq_get,
- amdgpu_cgs_irq_put
+ .add_irq_source = amdgpu_cgs_add_irq_source,
+ .irq_get = amdgpu_cgs_irq_get,
+ .irq_put = amdgpu_cgs_irq_put
};
struct cgs_device *amdgpu_cgs_create_device(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 41e41f9..d2d0f60 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -75,10 +75,10 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,
*out_ring = &adev->uvd.ring;
break;
case AMDGPU_HW_IP_VCE:
- if (ring < 2){
+ if (ring < adev->vce.num_rings){
*out_ring = &adev->vce.ring[ring];
} else {
- DRM_ERROR("only two VCE rings are supported\n");
+ DRM_ERROR("only %d VCE rings are supported\n", adev->vce.num_rings);
return -EINVAL;
}
break;
@@ -351,8 +351,7 @@ static u64 amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev)
* submission. This can result in a debt that can stop buffer migrations
* temporarily.
*/
-static void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev,
- u64 num_bytes)
+void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, u64 num_bytes)
{
spin_lock(&adev->mm_stats.lock);
adev->mm_stats.accum_us -= bytes_to_us(adev, num_bytes);
@@ -778,6 +777,20 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p,
if (r)
return r;
+ if (amdgpu_sriov_vf(adev)) {
+ struct dma_fence *f;
+ bo_va = vm->csa_bo_va;
+ BUG_ON(!bo_va);
+ r = amdgpu_vm_bo_update(adev, bo_va, false);
+ if (r)
+ return r;
+
+ f = bo_va->last_pt_update;
+ r = amdgpu_sync_fence(adev, &p->job->sync, f);
+ if (r)
+ return r;
+ }
+
if (p->bo_list) {
for (i = 0; i < p->bo_list->num_entries; i++) {
struct dma_fence *f;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index fe3bb94..6abb238 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -94,6 +94,11 @@ uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg,
{
uint32_t ret;
+ if (amdgpu_sriov_runtime(adev)) {
+ BUG_ON(in_interrupt());
+ return amdgpu_virt_kiq_rreg(adev, reg);
+ }
+
if ((reg * 4) < adev->rmmio_size && !always_indirect)
ret = readl(((void __iomem *)adev->rmmio) + (reg * 4));
else {
@@ -113,6 +118,11 @@ void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v,
{
trace_amdgpu_mm_wreg(adev->pdev->device, reg, v);
+ if (amdgpu_sriov_runtime(adev)) {
+ BUG_ON(in_interrupt());
+ return amdgpu_virt_kiq_wreg(adev, reg, v);
+ }
+
if ((reg * 4) < adev->rmmio_size && !always_indirect)
writel(v, ((void __iomem *)adev->rmmio) + (reg * 4));
else {
@@ -609,25 +619,29 @@ void amdgpu_gtt_location(struct amdgpu_device *adev, struct amdgpu_mc *mc)
* GPU helpers function.
*/
/**
- * amdgpu_card_posted - check if the hw has already been initialized
+ * amdgpu_need_post - check if the hw need post or not
*
* @adev: amdgpu_device pointer
*
- * Check if the asic has been initialized (all asics).
- * Used at driver startup.
- * Returns true if initialized or false if not.
+ * Check if the asic has been initialized (all asics) at driver startup
+ * or post is needed if hw reset is performed.
+ * Returns true if need or false if not.
*/
-bool amdgpu_card_posted(struct amdgpu_device *adev)
+bool amdgpu_need_post(struct amdgpu_device *adev)
{
uint32_t reg;
+ if (adev->has_hw_reset) {
+ adev->has_hw_reset = false;
+ return true;
+ }
/* then check MEM_SIZE, in case the crtcs are off */
reg = RREG32(mmCONFIG_MEMSIZE);
if (reg)
- return true;
+ return false;
- return false;
+ return true;
}
@@ -655,7 +669,7 @@ static bool amdgpu_vpost_needed(struct amdgpu_device *adev)
return true;
}
}
- return !amdgpu_card_posted(adev);
+ return amdgpu_need_post(adev);
}
/**
@@ -885,7 +899,7 @@ static int amdgpu_atombios_init(struct amdgpu_device *adev)
atom_card_info->ioreg_read = cail_ioreg_read;
atom_card_info->ioreg_write = cail_ioreg_write;
} else {
- DRM_ERROR("Unable to find PCI I/O BAR; using MMIO for ATOM IIO\n");
+ DRM_INFO("PCI I/O BAR is not found. Using MMIO to access ATOM BIOS\n");
atom_card_info->ioreg_read = cail_reg_read;
atom_card_info->ioreg_write = cail_reg_write;
}
@@ -1131,6 +1145,18 @@ int amdgpu_set_powergating_state(struct amdgpu_device *adev,
return r;
}
+void amdgpu_get_clockgating_state(struct amdgpu_device *adev, u32 *flags)
+{
+ int i;
+
+ for (i = 0; i < adev->num_ip_blocks; i++) {
+ if (!adev->ip_blocks[i].status.valid)
+ continue;
+ if (adev->ip_blocks[i].version->funcs->get_clockgating_state)
+ adev->ip_blocks[i].version->funcs->get_clockgating_state((void *)adev, flags);
+ }
+}
+
int amdgpu_wait_for_idle(struct amdgpu_device *adev,
enum amd_ip_block_type block_type)
{
@@ -1235,7 +1261,8 @@ static void amdgpu_device_enable_virtual_display(struct amdgpu_device *adev)
pciaddstr_tmp = pciaddstr;
while ((pciaddname_tmp = strsep(&pciaddstr_tmp, ";"))) {
pciaddname = strsep(&pciaddname_tmp, ",");
- if (!strcmp(pci_address_name, pciaddname)) {
+ if (!strcmp("all", pciaddname)
+ || !strcmp(pci_address_name, pciaddname)) {
long num_crtc;
int res = -1;
@@ -1323,6 +1350,12 @@ static int amdgpu_early_init(struct amdgpu_device *adev)
return -EINVAL;
}
+ if (amdgpu_sriov_vf(adev)) {
+ r = amdgpu_virt_request_full_gpu(adev, true);
+ if (r)
+ return r;
+ }
+
for (i = 0; i < adev->num_ip_blocks; i++) {
if ((amdgpu_ip_block_mask & (1 << i)) == 0) {
DRM_ERROR("disabled ip block: %d\n", i);
@@ -1383,6 +1416,15 @@ static int amdgpu_init(struct amdgpu_device *adev)
return r;
}
adev->ip_blocks[i].status.hw = true;
+
+ /* right after GMC hw init, we create CSA */
+ if (amdgpu_sriov_vf(adev)) {
+ r = amdgpu_allocate_static_csa(adev);
+ if (r) {
+ DRM_ERROR("allocate CSA failed %d\n", r);
+ return r;
+ }
+ }
}
}
@@ -1516,6 +1558,11 @@ static int amdgpu_fini(struct amdgpu_device *adev)
adev->ip_blocks[i].status.late_initialized = false;
}
+ if (amdgpu_sriov_vf(adev)) {
+ amdgpu_bo_free_kernel(&adev->virt.csa_obj, &adev->virt.csa_vmid0_addr, NULL);
+ amdgpu_virt_release_full_gpu(adev, false);
+ }
+
return 0;
}
@@ -1523,6 +1570,9 @@ int amdgpu_suspend(struct amdgpu_device *adev)
{
int i, r;
+ if (amdgpu_sriov_vf(adev))
+ amdgpu_virt_request_full_gpu(adev, false);
+
/* ungate SMC block first */
r = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_SMC,
AMD_CG_STATE_UNGATE);
@@ -1551,6 +1601,9 @@ int amdgpu_suspend(struct amdgpu_device *adev)
}
}
+ if (amdgpu_sriov_vf(adev))
+ amdgpu_virt_release_full_gpu(adev, false);
+
return 0;
}
@@ -1575,7 +1628,7 @@ static int amdgpu_resume(struct amdgpu_device *adev)
static void amdgpu_device_detect_sriov_bios(struct amdgpu_device *adev)
{
if (amdgpu_atombios_has_gpu_virtualization_table(adev))
- adev->virtualization.virtual_caps |= AMDGPU_SRIOV_CAPS_SRIOV_VBIOS;
+ adev->virt.caps |= AMDGPU_SRIOV_CAPS_SRIOV_VBIOS;
}
/**
@@ -1605,7 +1658,6 @@ int amdgpu_device_init(struct amdgpu_device *adev,
adev->pdev = pdev;
adev->flags = flags;
adev->asic_type = flags & AMD_ASIC_MASK;
- adev->is_atom_bios = false;
adev->usec_timeout = AMDGPU_MAX_USEC_TIMEOUT;
adev->mc.gtt_size = 512 * 1024 * 1024;
adev->accel_working = false;
@@ -1695,7 +1747,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
}
}
if (adev->rio_mem == NULL)
- DRM_ERROR("Unable to find PCI I/O BAR\n");
+ DRM_INFO("PCI I/O BAR is not found.\n");
/* early init functions */
r = amdgpu_early_init(adev);
@@ -1720,12 +1772,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
r = -EINVAL;
goto failed;
}
- /* Must be an ATOMBIOS */
- if (!adev->is_atom_bios) {
- dev_err(adev->dev, "Expecting atombios for GPU\n");
- r = -EINVAL;
- goto failed;
- }
+
r = amdgpu_atombios_init(adev);
if (r) {
dev_err(adev->dev, "amdgpu_atombios_init failed\n");
@@ -1852,8 +1899,6 @@ failed:
return r;
}
-static void amdgpu_debugfs_remove_files(struct amdgpu_device *adev);
-
/**
* amdgpu_device_fini - tear down the driver
*
@@ -1893,7 +1938,6 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
if (adev->asic_type >= CHIP_BONAIRE)
amdgpu_doorbell_fini(adev);
amdgpu_debugfs_regs_cleanup(adev);
- amdgpu_debugfs_remove_files(adev);
}
@@ -2031,7 +2075,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
amdgpu_atombios_scratch_regs_restore(adev);
/* post card */
- if (!amdgpu_card_posted(adev) || !resume) {
+ if (amdgpu_need_post(adev)) {
r = amdgpu_atom_asic_init(adev->mode_info.atom_context);
if (r)
DRM_ERROR("amdgpu asic init failed\n");
@@ -2252,6 +2296,9 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)
int resched;
bool need_full_reset;
+ if (amdgpu_sriov_vf(adev))
+ return 0;
+
if (!amdgpu_check_soft_reset(adev)) {
DRM_INFO("No hardware hang detected. Did some blocks stall?\n");
return 0;
@@ -2507,19 +2554,6 @@ int amdgpu_debugfs_add_files(struct amdgpu_device *adev,
return 0;
}
-static void amdgpu_debugfs_remove_files(struct amdgpu_device *adev)
-{
-#if defined(CONFIG_DEBUG_FS)
- unsigned i;
-
- for (i = 0; i < adev->debugfs_count; i++) {
- drm_debugfs_remove_files(adev->debugfs[i].files,
- adev->debugfs[i].num_files,
- adev->ddev->primary);
- }
-#endif
-}
-
#if defined(CONFIG_DEBUG_FS)
static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf,
@@ -2853,7 +2887,7 @@ static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf,
return -ENOMEM;
/* version, increment each time something is added */
- config[no_regs++] = 2;
+ config[no_regs++] = 3;
config[no_regs++] = adev->gfx.config.max_shader_engines;
config[no_regs++] = adev->gfx.config.max_tile_pipes;
config[no_regs++] = adev->gfx.config.max_cu_per_sh;
@@ -2887,6 +2921,12 @@ static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf,
config[no_regs++] = adev->family;
config[no_regs++] = adev->external_rev_id;
+ /* rev==3 */
+ config[no_regs++] = adev->pdev->device;
+ config[no_regs++] = adev->pdev->revision;
+ config[no_regs++] = adev->pdev->subsystem_device;
+ config[no_regs++] = adev->pdev->subsystem_vendor;
+
while (size && (*pos < no_regs * 4)) {
uint32_t value;
@@ -3153,10 +3193,6 @@ int amdgpu_debugfs_init(struct drm_minor *minor)
{
return 0;
}
-
-void amdgpu_debugfs_cleanup(struct drm_minor *minor)
-{
-}
#else
static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev)
{
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 581601c..39fc388 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -138,10 +138,52 @@ static void amdgpu_unpin_work_func(struct work_struct *__work)
kfree(work);
}
-int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- struct drm_pending_vblank_event *event,
- uint32_t page_flip_flags, uint32_t target)
+
+static void amdgpu_flip_work_cleanup(struct amdgpu_flip_work *work)
+{
+ int i;
+
+ amdgpu_bo_unref(&work->old_abo);
+ dma_fence_put(work->excl);
+ for (i = 0; i < work->shared_count; ++i)
+ dma_fence_put(work->shared[i]);
+ kfree(work->shared);
+ kfree(work);
+}
+
+static void amdgpu_flip_cleanup_unreserve(struct amdgpu_flip_work *work,
+ struct amdgpu_bo *new_abo)
+{
+ amdgpu_bo_unreserve(new_abo);
+ amdgpu_flip_work_cleanup(work);
+}
+
+static void amdgpu_flip_cleanup_unpin(struct amdgpu_flip_work *work,
+ struct amdgpu_bo *new_abo)
+{
+ if (unlikely(amdgpu_bo_unpin(new_abo) != 0))
+ DRM_ERROR("failed to unpin new abo in error path\n");
+ amdgpu_flip_cleanup_unreserve(work, new_abo);
+}
+
+void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work,
+ struct amdgpu_bo *new_abo)
+{
+ if (unlikely(amdgpu_bo_reserve(new_abo, false) != 0)) {
+ DRM_ERROR("failed to reserve new abo in error path\n");
+ amdgpu_flip_work_cleanup(work);
+ return;
+ }
+ amdgpu_flip_cleanup_unpin(work, new_abo);
+}
+
+int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event,
+ uint32_t page_flip_flags,
+ uint32_t target,
+ struct amdgpu_flip_work **work_p,
+ struct amdgpu_bo **new_abo_p)
{
struct drm_device *dev = crtc->dev;
struct amdgpu_device *adev = dev->dev_private;
@@ -154,7 +196,7 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
unsigned long flags;
u64 tiling_flags;
u64 base;
- int i, r;
+ int r;
work = kzalloc(sizeof *work, GFP_KERNEL);
if (work == NULL)
@@ -189,7 +231,6 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
r = amdgpu_bo_pin(new_abo, AMDGPU_GEM_DOMAIN_VRAM, &base);
if (unlikely(r != 0)) {
- r = -EINVAL;
DRM_ERROR("failed to pin new abo buffer before flip\n");
goto unreserve;
}
@@ -216,41 +257,79 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
r = -EBUSY;
goto pflip_cleanup;
+
}
+ spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+
+ *work_p = work;
+ *new_abo_p = new_abo;
+
+ return 0;
+
+pflip_cleanup:
+ amdgpu_crtc_cleanup_flip_ctx(work, new_abo);
+ return r;
+unpin:
+ amdgpu_flip_cleanup_unpin(work, new_abo);
+ return r;
+
+unreserve:
+ amdgpu_flip_cleanup_unreserve(work, new_abo);
+ return r;
+
+cleanup:
+ amdgpu_flip_work_cleanup(work);
+ return r;
+
+}
+
+void amdgpu_crtc_submit_flip(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct amdgpu_flip_work *work,
+ struct amdgpu_bo *new_abo)
+{
+ unsigned long flags;
+ struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+
+ spin_lock_irqsave(&crtc->dev->event_lock, flags);
amdgpu_crtc->pflip_status = AMDGPU_FLIP_PENDING;
amdgpu_crtc->pflip_works = work;
-
- DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n",
- amdgpu_crtc->crtc_id, amdgpu_crtc, work);
/* update crtc fb */
crtc->primary->fb = fb;
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+
+ DRM_DEBUG_DRIVER(
+ "crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n",
+ amdgpu_crtc->crtc_id, amdgpu_crtc, work);
+
amdgpu_flip_work_func(&work->flip_work.work);
- return 0;
+}
-pflip_cleanup:
- if (unlikely(amdgpu_bo_reserve(new_abo, false) != 0)) {
- DRM_ERROR("failed to reserve new abo in error path\n");
- goto cleanup;
- }
-unpin:
- if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) {
- DRM_ERROR("failed to unpin new abo in error path\n");
- }
-unreserve:
- amdgpu_bo_unreserve(new_abo);
+int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event,
+ uint32_t page_flip_flags,
+ uint32_t target)
+{
+ struct amdgpu_bo *new_abo;
+ struct amdgpu_flip_work *work;
+ int r;
-cleanup:
- amdgpu_bo_unref(&work->old_abo);
- dma_fence_put(work->excl);
- for (i = 0; i < work->shared_count; ++i)
- dma_fence_put(work->shared[i]);
- kfree(work->shared);
- kfree(work);
+ r = amdgpu_crtc_prepare_flip(crtc,
+ fb,
+ event,
+ page_flip_flags,
+ target,
+ &work,
+ &new_abo);
+ if (r)
+ return r;
- return r;
+ amdgpu_crtc_submit_flip(crtc, fb, work, new_abo);
+
+ return 0;
}
int amdgpu_crtc_set_config(struct drm_mode_set *set)
@@ -508,7 +587,7 @@ amdgpu_framebuffer_init(struct drm_device *dev,
{
int ret;
rfb->obj = obj;
- drm_helper_mode_fill_fb_struct(&rfb->base, mode_cmd);
+ drm_helper_mode_fill_fb_struct(dev, &rfb->base, mode_cmd);
ret = drm_framebuffer_init(dev, &rfb->base, &amdgpu_fb_funcs);
if (ret) {
rfb->obj = NULL;
@@ -582,12 +661,10 @@ int amdgpu_modeset_create_props(struct amdgpu_device *adev)
{
int sz;
- if (adev->is_atom_bios) {
- adev->mode_info.coherent_mode_property =
- drm_property_create_range(adev->ddev, 0 , "coherent", 0, 1);
- if (!adev->mode_info.coherent_mode_property)
- return -ENOMEM;
- }
+ adev->mode_info.coherent_mode_property =
+ drm_property_create_range(adev->ddev, 0 , "coherent", 0, 1);
+ if (!adev->mode_info.coherent_mode_property)
+ return -ENOMEM;
adev->mode_info.load_detect_property =
drm_property_create_range(adev->ddev, 0, "load detection", 0, 1);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
index 955d6f2..fa2b556 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
@@ -241,13 +241,6 @@ enum amdgpu_pcie_gen {
AMDGPU_PCIE_GEN_INVALID = 0xffff
};
-enum amdgpu_dpm_forced_level {
- AMDGPU_DPM_FORCED_LEVEL_AUTO = 0,
- AMDGPU_DPM_FORCED_LEVEL_LOW = 1,
- AMDGPU_DPM_FORCED_LEVEL_HIGH = 2,
- AMDGPU_DPM_FORCED_LEVEL_MANUAL = 3,
-};
-
struct amdgpu_dpm_funcs {
int (*get_temperature)(struct amdgpu_device *adev);
int (*pre_set_power_state)(struct amdgpu_device *adev);
@@ -258,7 +251,7 @@ struct amdgpu_dpm_funcs {
u32 (*get_mclk)(struct amdgpu_device *adev, bool low);
void (*print_power_state)(struct amdgpu_device *adev, struct amdgpu_ps *ps);
void (*debugfs_print_current_performance_level)(struct amdgpu_device *adev, struct seq_file *m);
- int (*force_performance_level)(struct amdgpu_device *adev, enum amdgpu_dpm_forced_level level);
+ int (*force_performance_level)(struct amdgpu_device *adev, enum amd_dpm_forced_level level);
bool (*vblank_too_short)(struct amdgpu_device *adev);
void (*powergate_uvd)(struct amdgpu_device *adev, bool gate);
void (*powergate_vce)(struct amdgpu_device *adev, bool gate);
@@ -353,9 +346,6 @@ struct amdgpu_dpm_funcs {
#define amdgpu_dpm_get_current_power_state(adev) \
(adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle)
-#define amdgpu_dpm_get_performance_level(adev) \
- (adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle)
-
#define amdgpu_dpm_get_pp_num_states(adev, data) \
(adev)->powerplay.pp_funcs->get_pp_num_states((adev)->powerplay.pp_handle, data)
@@ -393,6 +383,11 @@ struct amdgpu_dpm_funcs {
(adev)->powerplay.pp_funcs->get_vce_clock_state((adev)->powerplay.pp_handle, (i)) : \
(adev)->pm.funcs->get_vce_clock_state((adev), (i)))
+#define amdgpu_dpm_get_performance_level(adev) \
+ ((adev)->pp_enabled ? \
+ (adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle) : \
+ (adev)->pm.dpm.forced_level)
+
struct amdgpu_dpm {
struct amdgpu_ps *ps;
/* number of valid power states */
@@ -440,7 +435,7 @@ struct amdgpu_dpm {
/* thermal handling */
struct amdgpu_dpm_thermal thermal;
/* forced levels */
- enum amdgpu_dpm_forced_level forced_level;
+ enum amd_dpm_forced_level forced_level;
};
struct amdgpu_pm {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 2534ada..75fc376 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -90,7 +90,6 @@ int amdgpu_vram_page_split = 1024;
int amdgpu_exp_hw_support = 0;
int amdgpu_sched_jobs = 32;
int amdgpu_sched_hw_submission = 2;
-int amdgpu_powerplay = -1;
int amdgpu_no_evict = 0;
int amdgpu_direct_gma_size = 0;
unsigned amdgpu_pcie_gen_cap = 0;
@@ -179,9 +178,6 @@ module_param_named(sched_jobs, amdgpu_sched_jobs, int, 0444);
MODULE_PARM_DESC(sched_hw_submission, "the max number of HW submissions (default 2)");
module_param_named(sched_hw_submission, amdgpu_sched_hw_submission, int, 0444);
-MODULE_PARM_DESC(powerplay, "Powerplay component (1 = enable, 0 = disable, -1 = auto (default))");
-module_param_named(powerplay, amdgpu_powerplay, int, 0444);
-
MODULE_PARM_DESC(ppfeaturemask, "all power features enabled (default))");
module_param_named(ppfeaturemask, amdgpu_pp_feature_mask, int, 0444);
@@ -686,7 +682,6 @@ static struct drm_driver kms_driver = {
DRIVER_USE_AGP |
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM |
DRIVER_PRIME | DRIVER_RENDER | DRIVER_MODESET,
- .dev_priv_size = 0,
.load = amdgpu_driver_load_kms,
.open = amdgpu_driver_open_kms,
.preclose = amdgpu_driver_preclose_kms,
@@ -701,7 +696,6 @@ static struct drm_driver kms_driver = {
.get_scanout_position = amdgpu_get_crtc_scanoutpos,
#if defined(CONFIG_DEBUG_FS)
.debugfs_init = amdgpu_debugfs_init,
- .debugfs_cleanup = amdgpu_debugfs_cleanup,
#endif
.irq_preinstall = amdgpu_irq_preinstall,
.irq_postinstall = amdgpu_irq_postinstall,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
index 24629be..36ce3ca 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -245,7 +245,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
strcpy(info->fix.id, "amdgpudrmfb");
- drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
+ drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
info->fbops = &amdgpufb_ops;
@@ -272,7 +272,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start);
DRM_INFO("vram apper at 0x%lX\n", (unsigned long)adev->mc.aper_base);
DRM_INFO("size %lu\n", (unsigned long)amdgpu_bo_size(abo));
- DRM_INFO("fb depth is %d\n", fb->depth);
+ DRM_INFO("fb depth is %d\n", fb->format->depth);
DRM_INFO(" pitch is %d\n", fb->pitches[0]);
vga_switcheroo_client_fb_set(adev->ddev->pdev, info);
@@ -374,7 +374,6 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
&amdgpu_fb_helper_funcs);
ret = drm_fb_helper_init(adev->ddev, &rfbdev->helper,
- adev->mode_info.num_crtc,
AMDGPUFB_CONN_LIMIT);
if (ret) {
kfree(rfbdev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index cd62f6f..51d7594 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -471,12 +471,15 @@ out:
static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo)
{
- unsigned domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
-
/* if anything is swapped out don't swap it in here,
just abort and wait for the next CS */
+ if (!amdgpu_bo_gpu_accessible(bo))
+ return -ERESTARTSYS;
+
+ if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow))
+ return -ERESTARTSYS;
- return domain == AMDGPU_GEM_DOMAIN_CPU ? -ERESTARTSYS : 0;
+ return 0;
}
/**
@@ -484,62 +487,44 @@ static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo)
*
* @adev: amdgpu_device pointer
* @bo_va: bo_va to update
+ * @list: validation list
+ * @operation: map or unmap
*
- * Update the bo_va directly after setting it's address. Errors are not
+ * Update the bo_va directly after setting its address. Errors are not
* vital here, so they are not reported back to userspace.
*/
static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
struct amdgpu_bo_va *bo_va,
+ struct list_head *list,
uint32_t operation)
{
- struct ttm_validate_buffer tv, *entry;
- struct amdgpu_bo_list_entry vm_pd;
- struct ww_acquire_ctx ticket;
- struct list_head list, duplicates;
- unsigned domain;
- int r;
-
- INIT_LIST_HEAD(&list);
- INIT_LIST_HEAD(&duplicates);
-
- tv.bo = &bo_va->bo->tbo;
- tv.shared = true;
- list_add(&tv.head, &list);
-
- amdgpu_vm_get_pd_bo(bo_va->vm, &list, &vm_pd);
-
- /* Provide duplicates to avoid -EALREADY */
- r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates);
- if (r)
- goto error_print;
-
- list_for_each_entry(entry, &list, head) {
- domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type);
- /* if anything is swapped out don't swap it in here,
- just abort and wait for the next CS */
- if (domain == AMDGPU_GEM_DOMAIN_CPU)
- goto error_unreserve;
+ struct ttm_validate_buffer *entry;
+ int r = -ERESTARTSYS;
+
+ list_for_each_entry(entry, list, head) {
+ struct amdgpu_bo *bo =
+ container_of(entry->bo, struct amdgpu_bo, tbo);
+ if (amdgpu_gem_va_check(NULL, bo))
+ goto error;
}
+
r = amdgpu_vm_validate_pt_bos(adev, bo_va->vm, amdgpu_gem_va_check,
NULL);
if (r)
- goto error_unreserve;
+ goto error;
r = amdgpu_vm_update_page_directory(adev, bo_va->vm);
if (r)
- goto error_unreserve;
+ goto error;
r = amdgpu_vm_clear_freed(adev, bo_va->vm);
if (r)
- goto error_unreserve;
+ goto error;
if (operation == AMDGPU_VA_OP_MAP)
r = amdgpu_vm_bo_update(adev, bo_va, false);
-error_unreserve:
- ttm_eu_backoff_reservation(&ticket, &list);
-
-error_print:
+error:
if (r && r != -ERESTARTSYS)
DRM_ERROR("Couldn't update BO_VA (%d)\n", r);
}
@@ -556,7 +541,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
struct amdgpu_bo_list_entry vm_pd;
struct ttm_validate_buffer tv;
struct ww_acquire_ctx ticket;
- struct list_head list, duplicates;
+ struct list_head list;
uint32_t invalid_flags, va_flags = 0;
int r = 0;
@@ -594,14 +579,13 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
return -ENOENT;
abo = gem_to_amdgpu_bo(gobj);
INIT_LIST_HEAD(&list);
- INIT_LIST_HEAD(&duplicates);
tv.bo = &abo->tbo;
- tv.shared = true;
+ tv.shared = false;
list_add(&tv.head, &list);
amdgpu_vm_get_pd_bo(&fpriv->vm, &list, &vm_pd);
- r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates);
+ r = ttm_eu_reserve_buffers(&ticket, &list, true, NULL);
if (r) {
drm_gem_object_unreference_unlocked(gobj);
return r;
@@ -632,10 +616,10 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
default:
break;
}
- ttm_eu_backoff_reservation(&ticket, &list);
if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE) &&
!amdgpu_vm_debug)
- amdgpu_gem_va_update_vm(adev, bo_va, args->operation);
+ amdgpu_gem_va_update_vm(adev, bo_va, &list, args->operation);
+ ttm_eu_backoff_reservation(&ticket, &list);
drm_gem_object_unreference_unlocked(gobj);
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index 01a42b6..1994335 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -42,12 +42,12 @@ int amdgpu_gfx_scratch_get(struct amdgpu_device *adev, uint32_t *reg)
{
int i;
- for (i = 0; i < adev->gfx.scratch.num_reg; i++) {
- if (adev->gfx.scratch.free[i]) {
- adev->gfx.scratch.free[i] = false;
- *reg = adev->gfx.scratch.reg[i];
- return 0;
- }
+ i = ffs(adev->gfx.scratch.free_mask);
+ if (i != 0 && i <= adev->gfx.scratch.num_reg) {
+ i--;
+ adev->gfx.scratch.free_mask &= ~(1u << i);
+ *reg = adev->gfx.scratch.reg_base + i;
+ return 0;
}
return -EINVAL;
}
@@ -62,14 +62,7 @@ int amdgpu_gfx_scratch_get(struct amdgpu_device *adev, uint32_t *reg)
*/
void amdgpu_gfx_scratch_free(struct amdgpu_device *adev, uint32_t reg)
{
- int i;
-
- for (i = 0; i < adev->gfx.scratch.num_reg; i++) {
- if (adev->gfx.scratch.reg[i] == reg) {
- adev->gfx.scratch.free[i] = true;
- return;
- }
- }
+ adev->gfx.scratch.free_mask |= 1u << (reg - adev->gfx.scratch.reg_base);
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
index 00f46b0..0335c2f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
@@ -97,8 +97,7 @@ int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man,
{
struct amdgpu_gtt_mgr *mgr = man->priv;
struct drm_mm_node *node = mem->mm_node;
- enum drm_mm_search_flags sflags = DRM_MM_SEARCH_BEST;
- enum drm_mm_allocator_flags aflags = DRM_MM_CREATE_DEFAULT;
+ enum drm_mm_insert_mode mode;
unsigned long fpfn, lpfn;
int r;
@@ -115,15 +114,14 @@ int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man,
else
lpfn = man->size;
- if (place && place->flags & TTM_PL_FLAG_TOPDOWN) {
- sflags = DRM_MM_SEARCH_BELOW;
- aflags = DRM_MM_CREATE_TOP;
- }
+ mode = DRM_MM_INSERT_BEST;
+ if (place && place->flags & TTM_PL_FLAG_TOPDOWN)
+ mode = DRM_MM_INSERT_HIGH;
spin_lock(&mgr->lock);
- r = drm_mm_insert_node_in_range_generic(&mgr->mm, node, mem->num_pages,
- mem->page_alignment, 0,
- fpfn, lpfn, sflags, aflags);
+ r = drm_mm_insert_node_in_range(&mgr->mm, node,
+ mem->num_pages, mem->page_alignment, 0,
+ fpfn, lpfn, mode);
spin_unlock(&mgr->lock);
if (!r) {
@@ -235,16 +233,17 @@ static void amdgpu_gtt_mgr_debug(struct ttm_mem_type_manager *man,
const char *prefix)
{
struct amdgpu_gtt_mgr *mgr = man->priv;
+ struct drm_printer p = drm_debug_printer(prefix);
spin_lock(&mgr->lock);
- drm_mm_debug_table(&mgr->mm, prefix);
+ drm_mm_print(&mgr->mm, &p);
spin_unlock(&mgr->lock);
}
const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func = {
- amdgpu_gtt_mgr_init,
- amdgpu_gtt_mgr_fini,
- amdgpu_gtt_mgr_new,
- amdgpu_gtt_mgr_del,
- amdgpu_gtt_mgr_debug
+ .init = amdgpu_gtt_mgr_init,
+ .takedown = amdgpu_gtt_mgr_fini,
+ .get_node = amdgpu_gtt_mgr_new,
+ .put_node = amdgpu_gtt_mgr_del,
+ .debug = amdgpu_gtt_mgr_debug
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c
index 91d3673..f273999 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c
@@ -231,8 +231,7 @@ void amdgpu_i2c_init(struct amdgpu_device *adev)
if (amdgpu_hw_i2c)
DRM_INFO("hw_i2c forced on, you may experience display detection problems!\n");
- if (adev->is_atom_bios)
- amdgpu_atombios_i2c_init(adev);
+ amdgpu_atombios_i2c_init(adev);
}
/* remove all the buses */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index 216a957..e02a70d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -116,8 +116,8 @@ void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib,
* to SI there was just a DE IB.
*/
int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
- struct amdgpu_ib *ibs, struct dma_fence *last_vm_update,
- struct amdgpu_job *job, struct dma_fence **f)
+ struct amdgpu_ib *ibs, struct amdgpu_job *job,
+ struct dma_fence **f)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_ib *ib = &ibs[0];
@@ -175,15 +175,15 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
if (ring->funcs->emit_hdp_flush)
amdgpu_ring_emit_hdp_flush(ring);
- /* always set cond_exec_polling to CONTINUE */
- *ring->cond_exe_cpu_addr = 1;
-
skip_preamble = ring->current_ctx == fence_ctx;
need_ctx_switch = ring->current_ctx != fence_ctx;
if (job && ring->funcs->emit_cntxcntl) {
if (need_ctx_switch)
status |= AMDGPU_HAVE_CTX_SWITCH;
status |= job->preamble_status;
+
+ if (vm)
+ status |= AMDGPU_VM_DOMAIN;
amdgpu_ring_emit_cntxcntl(ring, status);
}
@@ -193,7 +193,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
/* drop preamble IBs if we don't have a context switch */
if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) &&
skip_preamble &&
- !(status & AMDGPU_PREAMBLE_IB_PRESENT_FIRST))
+ !(status & AMDGPU_PREAMBLE_IB_PRESENT_FIRST) &&
+ !amdgpu_sriov_vf(adev)) /* for SRIOV preemption, Preamble CE ib must be inserted anyway */
continue;
amdgpu_ring_emit_ib(ring, ib, job ? job->vm_id : 0,
@@ -223,7 +224,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
amdgpu_ring_patch_cond_exec(ring, patch_offset);
ring->current_ctx = fence_ctx;
- if (ring->funcs->emit_switch_buffer)
+ if (vm && ring->funcs->emit_switch_buffer)
amdgpu_ring_emit_switch_buffer(ring);
amdgpu_ring_commit(ring);
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
index fb90293..e63ece0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -61,10 +61,8 @@ static void amdgpu_hotplug_work_func(struct work_struct *work)
struct drm_connector *connector;
mutex_lock(&mode_config->mutex);
- if (mode_config->num_connector) {
- list_for_each_entry(connector, &mode_config->connector_list, head)
- amdgpu_connector_hotplug(connector);
- }
+ list_for_each_entry(connector, &mode_config->connector_list, head)
+ amdgpu_connector_hotplug(connector);
mutex_unlock(&mode_config->mutex);
/* Just fire off a uevent and let userspace tell us what to do */
drm_helper_hpd_irq_event(dev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index a0de628..86a1242 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -170,8 +170,7 @@ static struct dma_fence *amdgpu_job_run(struct amd_sched_job *sched_job)
BUG_ON(amdgpu_sync_peek_fence(&job->sync, NULL));
trace_amdgpu_sched_run_job(job);
- r = amdgpu_ib_schedule(job->ring, job->num_ibs, job->ibs,
- job->sync.last_vm_update, job, &fence);
+ r = amdgpu_ib_schedule(job->ring, job->num_ibs, job->ibs, job, &fence);
if (r)
DRM_ERROR("Error scheduling IBs (%d)\n", r);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 9af87ea..61d94c7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -50,16 +50,19 @@ static inline bool amdgpu_has_atpx(void) { return false; }
* This is the main unload function for KMS (all asics).
* Returns 0 on success.
*/
-int amdgpu_driver_unload_kms(struct drm_device *dev)
+void amdgpu_driver_unload_kms(struct drm_device *dev)
{
struct amdgpu_device *adev = dev->dev_private;
if (adev == NULL)
- return 0;
+ return;
if (adev->rmmio == NULL)
goto done_free;
+ if (amdgpu_sriov_vf(adev))
+ amdgpu_virt_request_full_gpu(adev, false);
+
if (amdgpu_device_is_px(dev)) {
pm_runtime_get_sync(dev->dev);
pm_runtime_forbid(dev->dev);
@@ -74,7 +77,6 @@ int amdgpu_driver_unload_kms(struct drm_device *dev)
done_free:
kfree(adev);
dev->dev_private = NULL;
- return 0;
}
/**
@@ -139,6 +141,9 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags)
pm_runtime_put_autosuspend(dev->dev);
}
+ if (amdgpu_sriov_vf(adev))
+ amdgpu_virt_release_full_gpu(adev, true);
+
out:
if (r) {
/* balance pm_runtime_get_sync in amdgpu_driver_unload_kms */
@@ -570,6 +575,27 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
return -EINVAL;
}
}
+ case AMDGPU_INFO_NUM_HANDLES: {
+ struct drm_amdgpu_info_num_handles handle;
+
+ switch (info->query_hw_ip.type) {
+ case AMDGPU_HW_IP_UVD:
+ /* Starting Polaris, we support unlimited UVD handles */
+ if (adev->asic_type < CHIP_POLARIS10) {
+ handle.uvd_max_handles = adev->uvd.max_handles;
+ handle.uvd_used_handles = amdgpu_uvd_used_handles(adev);
+
+ return copy_to_user(out, &handle,
+ min((size_t)size, sizeof(handle))) ? -EFAULT : 0;
+ } else {
+ return -ENODATA;
+ }
+
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
default:
DRM_DEBUG_KMS("Invalid request %d\n", info->query);
return -EINVAL;
@@ -629,6 +655,12 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
goto out_suspend;
}
+ if (amdgpu_sriov_vf(adev)) {
+ r = amdgpu_map_static_csa(adev, &fpriv->vm);
+ if (r)
+ goto out_suspend;
+ }
+
mutex_init(&fpriv->bo_list_lock);
idr_init(&fpriv->bo_list_handles);
@@ -667,6 +699,14 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
amdgpu_uvd_free_handles(adev, file_priv);
amdgpu_vce_free_handles(adev, file_priv);
+ if (amdgpu_sriov_vf(adev)) {
+ /* TODO: how to handle reserve failure */
+ BUG_ON(amdgpu_bo_reserve(adev->virt.csa_obj, false));
+ amdgpu_vm_bo_rmv(adev, fpriv->vm.csa_bo_va);
+ fpriv->vm.csa_bo_va = NULL;
+ amdgpu_bo_unreserve(adev->virt.csa_obj);
+ }
+
amdgpu_vm_fini(adev, &fpriv->vm);
idr_for_each_entry(&fpriv->bo_list_handles, list, handle)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 202b417..c12497b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -32,6 +32,7 @@
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_dp_helper.h>
#include <drm/drm_fixed.h>
#include <drm/drm_crtc_helper.h>
@@ -594,6 +595,21 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
uint32_t page_flip_flags, uint32_t target);
+void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work,
+ struct amdgpu_bo *new_abo);
+int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event,
+ uint32_t page_flip_flags,
+ uint32_t target,
+ struct amdgpu_flip_work **work,
+ struct amdgpu_bo **new_abo);
+
+void amdgpu_crtc_submit_flip(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct amdgpu_flip_work *work,
+ struct amdgpu_bo *new_abo);
+
extern const struct drm_mode_config_funcs amdgpu_mode_funcs;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index bf79b73..be80a4a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -323,6 +323,7 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
struct amdgpu_bo *bo;
enum ttm_bo_type type;
unsigned long page_align;
+ u64 initial_bytes_moved;
size_t acc_size;
int r;
@@ -363,11 +364,33 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
bo->flags = flags;
+#ifdef CONFIG_X86_32
+ /* XXX: Write-combined CPU mappings of GTT seem broken on 32-bit
+ * See https://bugs.freedesktop.org/show_bug.cgi?id=84627
+ */
+ bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC;
+#elif defined(CONFIG_X86) && !defined(CONFIG_X86_PAT)
+ /* Don't try to enable write-combining when it can't work, or things
+ * may be slow
+ * See https://bugs.freedesktop.org/show_bug.cgi?id=88758
+ */
+
+#ifndef CONFIG_COMPILE_TEST
+#warning Please enable CONFIG_MTRR and CONFIG_X86_PAT for better performance \
+ thanks to write-combining
+#endif
+
+ if (bo->flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC)
+ DRM_INFO_ONCE("Please enable CONFIG_MTRR and CONFIG_X86_PAT for "
+ "better performance thanks to write-combining\n");
+ bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC;
+#else
/* For architectures that don't support WC memory,
* mask out the WC flag from the BO
*/
if (!drm_arch_can_wc_memory())
bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC;
+#endif
amdgpu_fill_placement_to_bo(bo, placement);
/* Kernel allocation are uninterruptible */
@@ -379,12 +402,25 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
locked = ww_mutex_trylock(&bo->tbo.ttm_resv.lock);
WARN_ON(!locked);
}
+
+ initial_bytes_moved = atomic64_read(&adev->num_bytes_moved);
r = ttm_bo_init(&adev->mman.bdev, &bo->tbo, size, type,
&bo->placement, page_align, !kernel, NULL,
acc_size, sg, resv ? resv : &bo->tbo.ttm_resv,
&amdgpu_ttm_bo_destroy);
- if (unlikely(r != 0))
+ amdgpu_cs_report_moved_bytes(adev,
+ atomic64_read(&adev->num_bytes_moved) - initial_bytes_moved);
+
+ if (unlikely(r != 0)) {
+ if (!resv)
+ ww_mutex_unlock(&bo->tbo.resv->lock);
return r;
+ }
+
+ bo->tbo.priority = ilog2(bo->tbo.num_pages);
+ if (kernel)
+ bo->tbo.priority *= 2;
+ bo->tbo.priority = min(bo->tbo.priority, (unsigned)(TTM_MAX_BO_PRIORITY - 1));
if (flags & AMDGPU_GEM_CREATE_VRAM_CLEARED &&
bo->tbo.mem.placement & TTM_PL_FLAG_VRAM) {
@@ -408,7 +444,8 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
return 0;
fail_unreserve:
- ww_mutex_unlock(&bo->tbo.resv->lock);
+ if (!resv)
+ ww_mutex_unlock(&bo->tbo.resv->lock);
amdgpu_bo_unref(&bo);
return r;
}
@@ -472,7 +509,16 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
return r;
if (amdgpu_need_backup(adev) && (flags & AMDGPU_GEM_CREATE_SHADOW)) {
+ if (!resv) {
+ r = ww_mutex_lock(&(*bo_ptr)->tbo.resv->lock, NULL);
+ WARN_ON(r != 0);
+ }
+
r = amdgpu_bo_create_shadow(adev, size, byte_align, (*bo_ptr));
+
+ if (!resv)
+ ww_mutex_unlock(&(*bo_ptr)->tbo.resv->lock);
+
if (r)
amdgpu_bo_unref(bo_ptr);
}
@@ -849,6 +895,7 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
}
void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
+ bool evict,
struct ttm_mem_reg *new_mem)
{
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
@@ -861,6 +908,10 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
abo = container_of(bo, struct amdgpu_bo, tbo);
amdgpu_vm_bo_invalidate(adev, abo);
+ /* remember the eviction */
+ if (evict)
+ atomic64_inc(&adev->num_evictions);
+
/* update statistics */
if (!new_mem)
return;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
index 5cbf59e..15a723a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
@@ -114,6 +114,15 @@ static inline u64 amdgpu_bo_mmap_offset(struct amdgpu_bo *bo)
return drm_vma_node_offset_addr(&bo->tbo.vma_node);
}
+/**
+ * amdgpu_bo_gpu_accessible - return whether the bo is currently in memory that
+ * is accessible to the GPU.
+ */
+static inline bool amdgpu_bo_gpu_accessible(struct amdgpu_bo *bo)
+{
+ return bo->tbo.mem.mem_type != TTM_PL_SYSTEM;
+}
+
int amdgpu_bo_create(struct amdgpu_device *adev,
unsigned long size, int byte_align,
bool kernel, u32 domain, u64 flags,
@@ -155,7 +164,8 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
size_t buffer_size, uint32_t *metadata_size,
uint64_t *flags);
void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
- struct ttm_mem_reg *new_mem);
+ bool evict,
+ struct ttm_mem_reg *new_mem);
int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence,
bool shared);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index 723ae68..346e80a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -34,6 +34,28 @@
static int amdgpu_debugfs_pm_init(struct amdgpu_device *adev);
+static const struct cg_flag_name clocks[] = {
+ {AMD_CG_SUPPORT_GFX_MGCG, "Graphics Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_GFX_MGLS, "Graphics Medium Grain memory Light Sleep"},
+ {AMD_CG_SUPPORT_GFX_CGCG, "Graphics Coarse Grain Clock Gating"},
+ {AMD_CG_SUPPORT_GFX_CGLS, "Graphics Coarse Grain memory Light Sleep"},
+ {AMD_CG_SUPPORT_GFX_CGTS, "Graphics Coarse Grain Tree Shader Clock Gating"},
+ {AMD_CG_SUPPORT_GFX_CGTS_LS, "Graphics Coarse Grain Tree Shader Light Sleep"},
+ {AMD_CG_SUPPORT_GFX_CP_LS, "Graphics Command Processor Light Sleep"},
+ {AMD_CG_SUPPORT_GFX_RLC_LS, "Graphics Run List Controller Light Sleep"},
+ {AMD_CG_SUPPORT_MC_LS, "Memory Controller Light Sleep"},
+ {AMD_CG_SUPPORT_MC_MGCG, "Memory Controller Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_SDMA_LS, "System Direct Memory Access Light Sleep"},
+ {AMD_CG_SUPPORT_SDMA_MGCG, "System Direct Memory Access Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_BIF_LS, "Bus Interface Light Sleep"},
+ {AMD_CG_SUPPORT_UVD_MGCG, "Unified Video Decoder Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_VCE_MGCG, "Video Compression Engine Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_HDP_LS, "Host Data Path Light Sleep"},
+ {AMD_CG_SUPPORT_HDP_MGCG, "Host Data Path Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_ROM_MGCG, "Rom Medium Grain Clock Gating"},
+ {0, NULL},
+};
+
void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev)
{
if (adev->pp_enabled)
@@ -112,28 +134,23 @@ static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev,
{
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = ddev->dev_private;
+ enum amd_dpm_forced_level level;
if ((adev->flags & AMD_IS_PX) &&
(ddev->switch_power_state != DRM_SWITCH_POWER_ON))
return snprintf(buf, PAGE_SIZE, "off\n");
- if (adev->pp_enabled) {
- enum amd_dpm_forced_level level;
-
- level = amdgpu_dpm_get_performance_level(adev);
- return snprintf(buf, PAGE_SIZE, "%s\n",
- (level == AMD_DPM_FORCED_LEVEL_AUTO) ? "auto" :
- (level == AMD_DPM_FORCED_LEVEL_LOW) ? "low" :
- (level == AMD_DPM_FORCED_LEVEL_HIGH) ? "high" :
- (level == AMD_DPM_FORCED_LEVEL_MANUAL) ? "manual" : "unknown");
- } else {
- enum amdgpu_dpm_forced_level level;
-
- level = adev->pm.dpm.forced_level;
- return snprintf(buf, PAGE_SIZE, "%s\n",
- (level == AMDGPU_DPM_FORCED_LEVEL_AUTO) ? "auto" :
- (level == AMDGPU_DPM_FORCED_LEVEL_LOW) ? "low" : "high");
- }
+ level = amdgpu_dpm_get_performance_level(adev);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ (level == AMD_DPM_FORCED_LEVEL_AUTO) ? "auto" :
+ (level == AMD_DPM_FORCED_LEVEL_LOW) ? "low" :
+ (level == AMD_DPM_FORCED_LEVEL_HIGH) ? "high" :
+ (level == AMD_DPM_FORCED_LEVEL_MANUAL) ? "manual" :
+ (level == AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD) ? "profile_standard" :
+ (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) ? "profile_min_sclk" :
+ (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) ? "profile_min_mclk" :
+ (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) ? "profile_peak" :
+ "unknown");
}
static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
@@ -143,7 +160,8 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
{
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = ddev->dev_private;
- enum amdgpu_dpm_forced_level level;
+ enum amd_dpm_forced_level level;
+ enum amd_dpm_forced_level current_level;
int ret = 0;
/* Can't force performance level when the card is off */
@@ -151,19 +169,34 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
(ddev->switch_power_state != DRM_SWITCH_POWER_ON))
return -EINVAL;
+ current_level = amdgpu_dpm_get_performance_level(adev);
+
if (strncmp("low", buf, strlen("low")) == 0) {
- level = AMDGPU_DPM_FORCED_LEVEL_LOW;
+ level = AMD_DPM_FORCED_LEVEL_LOW;
} else if (strncmp("high", buf, strlen("high")) == 0) {
- level = AMDGPU_DPM_FORCED_LEVEL_HIGH;
+ level = AMD_DPM_FORCED_LEVEL_HIGH;
} else if (strncmp("auto", buf, strlen("auto")) == 0) {
- level = AMDGPU_DPM_FORCED_LEVEL_AUTO;
+ level = AMD_DPM_FORCED_LEVEL_AUTO;
} else if (strncmp("manual", buf, strlen("manual")) == 0) {
- level = AMDGPU_DPM_FORCED_LEVEL_MANUAL;
- } else {
+ level = AMD_DPM_FORCED_LEVEL_MANUAL;
+ } else if (strncmp("profile_exit", buf, strlen("profile_exit")) == 0) {
+ level = AMD_DPM_FORCED_LEVEL_PROFILE_EXIT;
+ } else if (strncmp("profile_standard", buf, strlen("profile_standard")) == 0) {
+ level = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD;
+ } else if (strncmp("profile_min_sclk", buf, strlen("profile_min_sclk")) == 0) {
+ level = AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK;
+ } else if (strncmp("profile_min_mclk", buf, strlen("profile_min_mclk")) == 0) {
+ level = AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK;
+ } else if (strncmp("profile_peak", buf, strlen("profile_peak")) == 0) {
+ level = AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
+ } else {
count = -EINVAL;
goto fail;
}
+ if (current_level == level)
+ return count;
+
if (adev->pp_enabled)
amdgpu_dpm_force_performance_level(adev, level);
else {
@@ -180,6 +213,7 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
adev->pm.dpm.forced_level = level;
mutex_unlock(&adev->pm.mutex);
}
+
fail:
return count;
}
@@ -1060,9 +1094,9 @@ static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev)
if (adev->pm.funcs->force_performance_level) {
if (adev->pm.dpm.thermal_active) {
- enum amdgpu_dpm_forced_level level = adev->pm.dpm.forced_level;
+ enum amd_dpm_forced_level level = adev->pm.dpm.forced_level;
/* force low perf level for thermal */
- amdgpu_dpm_force_performance_level(adev, AMDGPU_DPM_FORCED_LEVEL_LOW);
+ amdgpu_dpm_force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW);
/* save the user's level */
adev->pm.dpm.forced_level = level;
} else {
@@ -1108,12 +1142,22 @@ void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable)
/* XXX select vce level based on ring/task */
adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL;
mutex_unlock(&adev->pm.mutex);
+ amdgpu_pm_compute_clocks(adev);
+ amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+ AMD_PG_STATE_UNGATE);
+ amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+ AMD_CG_STATE_UNGATE);
} else {
+ amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+ AMD_PG_STATE_GATE);
+ amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+ AMD_CG_STATE_GATE);
mutex_lock(&adev->pm.mutex);
adev->pm.dpm.vce_active = false;
mutex_unlock(&adev->pm.mutex);
+ amdgpu_pm_compute_clocks(adev);
}
- amdgpu_pm_compute_clocks(adev);
+
}
}
@@ -1252,7 +1296,8 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev)
if (!adev->pm.dpm_enabled)
return;
- amdgpu_display_bandwidth_update(adev);
+ if (adev->mode_info.num_crtc)
+ amdgpu_display_bandwidth_update(adev);
for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
struct amdgpu_ring *ring = adev->rings[i];
@@ -1351,12 +1396,27 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a
return 0;
}
+static void amdgpu_parse_cg_state(struct seq_file *m, u32 flags)
+{
+ int i;
+
+ for (i = 0; clocks[i].flag; i++)
+ seq_printf(m, "\t%s: %s\n", clocks[i].name,
+ (flags & clocks[i].flag) ? "On" : "Off");
+}
+
static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data)
{
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
struct amdgpu_device *adev = dev->dev_private;
struct drm_device *ddev = adev->ddev;
+ u32 flags = 0;
+
+ amdgpu_get_clockgating_state(adev, &flags);
+ seq_printf(m, "Clock Gating Flags Mask: 0x%x\n", flags);
+ amdgpu_parse_cg_state(m, flags);
+ seq_printf(m, "\n");
if (!adev->pm.dpm_enabled) {
seq_printf(m, "dpm not enabled\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h
index 5fd7734..c19c4d1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h
@@ -24,6 +24,12 @@
#ifndef __AMDGPU_PM_H__
#define __AMDGPU_PM_H__
+struct cg_flag_name
+{
+ u32 flag;
+ const char *name;
+};
+
int amdgpu_pm_sysfs_init(struct amdgpu_device *adev);
void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev);
void amdgpu_pm_print_power_states(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
index 95a568d..8856ecc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
@@ -34,67 +34,34 @@
#include "cik_dpm.h"
#include "vi_dpm.h"
-static int amdgpu_powerplay_init(struct amdgpu_device *adev)
+static int amdgpu_create_pp_handle(struct amdgpu_device *adev)
{
- int ret = 0;
+ struct amd_pp_init pp_init;
struct amd_powerplay *amd_pp;
+ int ret;
amd_pp = &(adev->powerplay);
-
- if (adev->pp_enabled) {
- struct amd_pp_init *pp_init;
-
- pp_init = kzalloc(sizeof(struct amd_pp_init), GFP_KERNEL);
-
- if (pp_init == NULL)
- return -ENOMEM;
-
- pp_init->chip_family = adev->family;
- pp_init->chip_id = adev->asic_type;
- pp_init->device = amdgpu_cgs_create_device(adev);
- ret = amd_powerplay_init(pp_init, amd_pp);
- kfree(pp_init);
- } else {
- amd_pp->pp_handle = (void *)adev;
-
- switch (adev->asic_type) {
-#ifdef CONFIG_DRM_AMDGPU_SI
- case CHIP_TAHITI:
- case CHIP_PITCAIRN:
- case CHIP_VERDE:
- case CHIP_OLAND:
- case CHIP_HAINAN:
- amd_pp->ip_funcs = &si_dpm_ip_funcs;
- break;
-#endif
-#ifdef CONFIG_DRM_AMDGPU_CIK
- case CHIP_BONAIRE:
- case CHIP_HAWAII:
- amd_pp->ip_funcs = &ci_dpm_ip_funcs;
- break;
- case CHIP_KABINI:
- case CHIP_MULLINS:
- case CHIP_KAVERI:
- amd_pp->ip_funcs = &kv_dpm_ip_funcs;
- break;
-#endif
- case CHIP_CARRIZO:
- case CHIP_STONEY:
- amd_pp->ip_funcs = &cz_dpm_ip_funcs;
- break;
- default:
- ret = -EINVAL;
- break;
- }
- }
- return ret;
+ pp_init.chip_family = adev->family;
+ pp_init.chip_id = adev->asic_type;
+ pp_init.pm_en = amdgpu_dpm != 0 ? true : false;
+ pp_init.feature_mask = amdgpu_pp_feature_mask;
+ pp_init.device = amdgpu_cgs_create_device(adev);
+ ret = amd_powerplay_create(&pp_init, &(amd_pp->pp_handle));
+ if (ret)
+ return -EINVAL;
+ return 0;
}
static int amdgpu_pp_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct amd_powerplay *amd_pp;
int ret = 0;
+ amd_pp = &(adev->powerplay);
+ adev->pp_enabled = false;
+ amd_pp->pp_handle = (void *)adev;
+
switch (adev->asic_type) {
case CHIP_POLARIS11:
case CHIP_POLARIS10:
@@ -102,30 +69,48 @@ static int amdgpu_pp_early_init(void *handle)
case CHIP_TONGA:
case CHIP_FIJI:
case CHIP_TOPAZ:
- adev->pp_enabled = true;
- break;
case CHIP_CARRIZO:
case CHIP_STONEY:
- adev->pp_enabled = (amdgpu_powerplay == 0) ? false : true;
+ adev->pp_enabled = true;
+ if (amdgpu_create_pp_handle(adev))
+ return -EINVAL;
+ amd_pp->ip_funcs = &pp_ip_funcs;
+ amd_pp->pp_funcs = &pp_dpm_funcs;
break;
/* These chips don't have powerplay implemenations */
+#ifdef CONFIG_DRM_AMDGPU_SI
+ case CHIP_TAHITI:
+ case CHIP_PITCAIRN:
+ case CHIP_VERDE:
+ case CHIP_OLAND:
+ case CHIP_HAINAN:
+ amd_pp->ip_funcs = &si_dpm_ip_funcs;
+ break;
+#endif
+#ifdef CONFIG_DRM_AMDGPU_CIK
case CHIP_BONAIRE:
case CHIP_HAWAII:
+ amd_pp->ip_funcs = &ci_dpm_ip_funcs;
+ break;
case CHIP_KABINI:
case CHIP_MULLINS:
case CHIP_KAVERI:
+ amd_pp->ip_funcs = &kv_dpm_ip_funcs;
+ break;
+#endif
default:
- adev->pp_enabled = false;
+ ret = -EINVAL;
break;
}
- ret = amdgpu_powerplay_init(adev);
- if (ret)
- return ret;
-
if (adev->powerplay.ip_funcs->early_init)
ret = adev->powerplay.ip_funcs->early_init(
adev->powerplay.pp_handle);
+
+ if (ret == PP_DPM_DISABLED) {
+ adev->pm.dpm_enabled = false;
+ return 0;
+ }
return ret;
}
@@ -185,6 +170,11 @@ static int amdgpu_pp_hw_init(void *handle)
ret = adev->powerplay.ip_funcs->hw_init(
adev->powerplay.pp_handle);
+ if (ret == PP_DPM_DISABLED) {
+ adev->pm.dpm_enabled = false;
+ return 0;
+ }
+
if ((amdgpu_dpm != 0) && !amdgpu_sriov_vf(adev))
adev->pm.dpm_enabled = true;
@@ -210,14 +200,14 @@ static void amdgpu_pp_late_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- if (adev->pp_enabled) {
- amdgpu_pm_sysfs_fini(adev);
- amd_powerplay_fini(adev->powerplay.pp_handle);
- }
-
if (adev->powerplay.ip_funcs->late_fini)
adev->powerplay.ip_funcs->late_fini(
adev->powerplay.pp_handle);
+
+ if (adev->pp_enabled && adev->pm.dpm_enabled)
+ amdgpu_pm_sysfs_fini(adev);
+
+ amd_powerplay_destroy(adev->powerplay.pp_handle);
}
static int amdgpu_pp_suspend(void *handle)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
index a476283..7c842b7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
@@ -207,6 +207,8 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
}
ring->cond_exe_gpu_addr = adev->wb.gpu_addr + (ring->cond_exe_offs * 4);
ring->cond_exe_cpu_addr = &adev->wb.wb[ring->cond_exe_offs];
+ /* always set cond_exec_polling to CONTINUE */
+ *ring->cond_exe_cpu_addr = 1;
r = amdgpu_fence_driver_start_ring(ring, irq_src, irq_type);
if (r) {
@@ -307,7 +309,7 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,
while (size) {
if (*pos >= (ring->ring_size + 12))
return result;
-
+
value = ring->ring[(*pos - 12)/4];
r = put_user(value, (uint32_t*)buf);
if (r)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
index 574f0b7..2345b398 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
@@ -135,6 +135,8 @@ struct amdgpu_ring_funcs {
void (*end_use)(struct amdgpu_ring *ring);
void (*emit_switch_buffer) (struct amdgpu_ring *ring);
void (*emit_cntxcntl) (struct amdgpu_ring *ring, uint32_t flags);
+ void (*emit_rreg)(struct amdgpu_ring *ring, uint32_t reg);
+ void (*emit_wreg)(struct amdgpu_ring *ring, uint32_t reg, uint32_t val);
};
struct amdgpu_ring {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
index bb964a8..a18ae1e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
@@ -24,7 +24,7 @@ TRACE_EVENT(amdgpu_mm_rreg,
__entry->reg = reg;
__entry->value = value;
),
- TP_printk("0x%04lx, 0x%04lx, 0x%08lx",
+ TP_printk("0x%04lx, 0x%08lx, 0x%08lx",
(unsigned long)__entry->did,
(unsigned long)__entry->reg,
(unsigned long)__entry->value)
@@ -43,7 +43,7 @@ TRACE_EVENT(amdgpu_mm_wreg,
__entry->reg = reg;
__entry->value = value;
),
- TP_printk("0x%04lx, 0x%04lx, 0x%08lx",
+ TP_printk("0x%04lx, 0x%08lx, 0x%08lx",
(unsigned long)__entry->did,
(unsigned long)__entry->reg,
(unsigned long)__entry->value)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 8e35c1f..4c6094e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -466,10 +466,6 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo,
adev = amdgpu_ttm_adev(bo->bdev);
- /* remember the eviction */
- if (evict)
- atomic64_inc(&adev->num_evictions);
-
if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) {
amdgpu_move_null(bo, new_mem);
return 0;
@@ -533,6 +529,9 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_
case TTM_PL_TT:
break;
case TTM_PL_VRAM:
+ if (mem->start == AMDGPU_BO_INVALID_OFFSET)
+ return -EINVAL;
+
mem->bus.offset = mem->start << PAGE_SHIFT;
/* check if it's visible */
if ((mem->bus.offset + mem->bus.size) > adev->mc.visible_vram_size)
@@ -552,6 +551,8 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_
mem->bus.addr =
ioremap_nocache(mem->bus.base + mem->bus.offset,
mem->bus.size);
+ if (!mem->bus.addr)
+ return -ENOMEM;
/*
* Alpha: Use just the bus offset plus
@@ -1052,56 +1053,6 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm,
return flags;
}
-static void amdgpu_ttm_lru_removal(struct ttm_buffer_object *tbo)
-{
- struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev);
- unsigned i, j;
-
- for (i = 0; i < AMDGPU_TTM_LRU_SIZE; ++i) {
- struct amdgpu_mman_lru *lru = &adev->mman.log2_size[i];
-
- for (j = 0; j < TTM_NUM_MEM_TYPES; ++j)
- if (&tbo->lru == lru->lru[j])
- lru->lru[j] = tbo->lru.prev;
-
- if (&tbo->swap == lru->swap_lru)
- lru->swap_lru = tbo->swap.prev;
- }
-}
-
-static struct amdgpu_mman_lru *amdgpu_ttm_lru(struct ttm_buffer_object *tbo)
-{
- struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev);
- unsigned log2_size = min(ilog2(tbo->num_pages),
- AMDGPU_TTM_LRU_SIZE - 1);
-
- return &adev->mman.log2_size[log2_size];
-}
-
-static struct list_head *amdgpu_ttm_lru_tail(struct ttm_buffer_object *tbo)
-{
- struct amdgpu_mman_lru *lru = amdgpu_ttm_lru(tbo);
- struct list_head *res = lru->lru[tbo->mem.mem_type];
-
- lru->lru[tbo->mem.mem_type] = &tbo->lru;
- while ((++lru)->lru[tbo->mem.mem_type] == res)
- lru->lru[tbo->mem.mem_type] = &tbo->lru;
-
- return res;
-}
-
-static struct list_head *amdgpu_ttm_swap_lru_tail(struct ttm_buffer_object *tbo)
-{
- struct amdgpu_mman_lru *lru = amdgpu_ttm_lru(tbo);
- struct list_head *res = lru->swap_lru;
-
- lru->swap_lru = &tbo->swap;
- while ((++lru)->swap_lru == res)
- lru->swap_lru = &tbo->swap;
-
- return res;
-}
-
static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
const struct ttm_place *place)
{
@@ -1140,14 +1091,10 @@ static struct ttm_bo_driver amdgpu_bo_driver = {
.fault_reserve_notify = &amdgpu_bo_fault_reserve_notify,
.io_mem_reserve = &amdgpu_ttm_io_mem_reserve,
.io_mem_free = &amdgpu_ttm_io_mem_free,
- .lru_removal = &amdgpu_ttm_lru_removal,
- .lru_tail = &amdgpu_ttm_lru_tail,
- .swap_lru_tail = &amdgpu_ttm_swap_lru_tail,
};
int amdgpu_ttm_init(struct amdgpu_device *adev)
{
- unsigned i, j;
int r;
r = amdgpu_ttm_global_init(adev);
@@ -1165,19 +1112,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
DRM_ERROR("failed initializing buffer object driver(%d).\n", r);
return r;
}
-
- for (i = 0; i < AMDGPU_TTM_LRU_SIZE; ++i) {
- struct amdgpu_mman_lru *lru = &adev->mman.log2_size[i];
-
- for (j = 0; j < TTM_NUM_MEM_TYPES; ++j)
- lru->lru[j] = &adev->mman.bdev.man[j].lru;
- lru->swap_lru = &adev->mman.bdev.glob->swap_lru;
- }
-
- for (j = 0; j < TTM_NUM_MEM_TYPES; ++j)
- adev->mman.guard.lru[j] = NULL;
- adev->mman.guard.swap_lru = NULL;
-
adev->mman.initialized = true;
r = ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_VRAM,
adev->mc.real_vram_size >> PAGE_SHIFT);
@@ -1365,7 +1299,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring,
WARN_ON(job->ibs[0].length_dw > num_dw);
if (direct_submit) {
r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs,
- NULL, NULL, fence);
+ NULL, fence);
job->fence = dma_fence_get(*fence);
if (r)
DRM_ERROR("Error scheduling IBs (%d)\n", r);
@@ -1482,18 +1416,18 @@ static int amdgpu_mm_dump_table(struct seq_file *m, void *data)
struct drm_device *dev = node->minor->dev;
struct amdgpu_device *adev = dev->dev_private;
struct drm_mm *mm = (struct drm_mm *)adev->mman.bdev.man[ttm_pl].priv;
- int ret;
struct ttm_bo_global *glob = adev->mman.bdev.glob;
+ struct drm_printer p = drm_seq_file_printer(m);
spin_lock(&glob->lru_lock);
- ret = drm_mm_dump_table(m, mm);
+ drm_mm_print(mm, &p);
spin_unlock(&glob->lru_lock);
if (ttm_pl == TTM_PL_VRAM)
seq_printf(m, "man size:%llu pages, ram usage:%lluMB, vis usage:%lluMB\n",
adev->mman.bdev.man[ttm_pl].size,
(u64)atomic64_read(&adev->vram_usage) >> 20,
(u64)atomic64_read(&adev->vram_vis_usage) >> 20);
- return ret;
+ return 0;
}
static int ttm_pl_vram = TTM_PL_VRAM;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
index 98ee384..6bdede8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
@@ -34,13 +34,6 @@
#define AMDGPU_PL_FLAG_GWS (TTM_PL_FLAG_PRIV << 1)
#define AMDGPU_PL_FLAG_OA (TTM_PL_FLAG_PRIV << 2)
-#define AMDGPU_TTM_LRU_SIZE 20
-
-struct amdgpu_mman_lru {
- struct list_head *lru[TTM_NUM_MEM_TYPES];
- struct list_head *swap_lru;
-};
-
struct amdgpu_mman {
struct ttm_bo_global_ref bo_global_ref;
struct drm_global_reference mem_global_ref;
@@ -58,11 +51,6 @@ struct amdgpu_mman {
struct amdgpu_ring *buffer_funcs_ring;
/* Scheduler entity for buffer moves */
struct amd_sched_entity entity;
-
- /* custom LRU management */
- struct amdgpu_mman_lru log2_size[AMDGPU_TTM_LRU_SIZE];
- /* guard for log2_size array, don't add anything in between */
- struct amdgpu_mman_lru guard;
};
extern const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index 1d564be..6d6ab7f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -976,7 +976,7 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
ib->length_dw = 16;
if (direct) {
- r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f);
+ r = amdgpu_ib_schedule(ring, 1, ib, NULL, &f);
job->fence = dma_fence_get(f);
if (r)
goto err_free;
@@ -1113,6 +1113,11 @@ static void amdgpu_uvd_idle_work_handler(struct work_struct *work)
amdgpu_dpm_enable_uvd(adev, false);
} else {
amdgpu_asic_set_uvd_clocks(adev, 0, 0);
+ /* shutdown the UVD block */
+ amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ AMD_PG_STATE_GATE);
+ amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ AMD_CG_STATE_GATE);
}
} else {
schedule_delayed_work(&adev->uvd.idle_work, UVD_IDLE_TIMEOUT);
@@ -1129,6 +1134,10 @@ void amdgpu_uvd_ring_begin_use(struct amdgpu_ring *ring)
amdgpu_dpm_enable_uvd(adev, true);
} else {
amdgpu_asic_set_uvd_clocks(adev, 53300, 40000);
+ amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ AMD_CG_STATE_UNGATE);
+ amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ AMD_PG_STATE_UNGATE);
}
}
}
@@ -1178,3 +1187,28 @@ int amdgpu_uvd_ring_test_ib(struct amdgpu_ring *ring, long timeout)
error:
return r;
}
+
+/**
+ * amdgpu_uvd_used_handles - returns used UVD handles
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Returns the number of UVD handles in use
+ */
+uint32_t amdgpu_uvd_used_handles(struct amdgpu_device *adev)
+{
+ unsigned i;
+ uint32_t used_handles = 0;
+
+ for (i = 0; i < adev->uvd.max_handles; ++i) {
+ /*
+ * Handles can be freed in any order, and not
+ * necessarily linear. So we need to count
+ * all non-zero handles.
+ */
+ if (atomic_read(&adev->uvd.handles[i]))
+ used_handles++;
+ }
+
+ return used_handles;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
index 6249ba1..c10682b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
@@ -38,5 +38,6 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx);
void amdgpu_uvd_ring_begin_use(struct amdgpu_ring *ring);
void amdgpu_uvd_ring_end_use(struct amdgpu_ring *ring);
int amdgpu_uvd_ring_test_ib(struct amdgpu_ring *ring, long timeout);
+uint32_t amdgpu_uvd_used_handles(struct amdgpu_device *adev);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index 8fec802..e2c0678 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -321,6 +321,10 @@ static void amdgpu_vce_idle_work_handler(struct work_struct *work)
amdgpu_dpm_enable_vce(adev, false);
} else {
amdgpu_asic_set_vce_clocks(adev, 0, 0);
+ amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+ AMD_PG_STATE_GATE);
+ amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+ AMD_CG_STATE_GATE);
}
} else {
schedule_delayed_work(&adev->vce.idle_work, VCE_IDLE_TIMEOUT);
@@ -346,6 +350,11 @@ void amdgpu_vce_ring_begin_use(struct amdgpu_ring *ring)
amdgpu_dpm_enable_vce(adev, true);
} else {
amdgpu_asic_set_vce_clocks(adev, 53300, 40000);
+ amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+ AMD_CG_STATE_UNGATE);
+ amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+ AMD_PG_STATE_UNGATE);
+
}
}
mutex_unlock(&adev->vce.idle_mutex);
@@ -455,7 +464,7 @@ int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
for (i = ib->length_dw; i < ib_size_dw; ++i)
ib->ptr[i] = 0x0;
- r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f);
+ r = amdgpu_ib_schedule(ring, 1, ib, NULL, &f);
job->fence = dma_fence_get(f);
if (r)
goto err;
@@ -518,7 +527,7 @@ int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
ib->ptr[i] = 0x0;
if (direct) {
- r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f);
+ r = amdgpu_ib_schedule(ring, 1, ib, NULL, &f);
job->fence = dma_fence_get(f);
if (r)
goto err;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
new file mode 100644
index 0000000..dcfb7df
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
@@ -0,0 +1,221 @@
+/*
+ * 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.
+ *
+ */
+
+#include "amdgpu.h"
+
+int amdgpu_allocate_static_csa(struct amdgpu_device *adev)
+{
+ int r;
+ void *ptr;
+
+ r = amdgpu_bo_create_kernel(adev, AMDGPU_CSA_SIZE, PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM, &adev->virt.csa_obj,
+ &adev->virt.csa_vmid0_addr, &ptr);
+ if (r)
+ return r;
+
+ memset(ptr, 0, AMDGPU_CSA_SIZE);
+ return 0;
+}
+
+/*
+ * amdgpu_map_static_csa should be called during amdgpu_vm_init
+ * it maps virtual address "AMDGPU_VA_RESERVED_SIZE - AMDGPU_CSA_SIZE"
+ * to this VM, and each command submission of GFX should use this virtual
+ * address within META_DATA init package to support SRIOV gfx preemption.
+ */
+
+int amdgpu_map_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm)
+{
+ int r;
+ struct amdgpu_bo_va *bo_va;
+ struct ww_acquire_ctx ticket;
+ struct list_head list;
+ struct amdgpu_bo_list_entry pd;
+ struct ttm_validate_buffer csa_tv;
+
+ INIT_LIST_HEAD(&list);
+ INIT_LIST_HEAD(&csa_tv.head);
+ csa_tv.bo = &adev->virt.csa_obj->tbo;
+ csa_tv.shared = true;
+
+ list_add(&csa_tv.head, &list);
+ amdgpu_vm_get_pd_bo(vm, &list, &pd);
+
+ r = ttm_eu_reserve_buffers(&ticket, &list, true, NULL);
+ if (r) {
+ DRM_ERROR("failed to reserve CSA,PD BOs: err=%d\n", r);
+ return r;
+ }
+
+ bo_va = amdgpu_vm_bo_add(adev, vm, adev->virt.csa_obj);
+ if (!bo_va) {
+ ttm_eu_backoff_reservation(&ticket, &list);
+ DRM_ERROR("failed to create bo_va for static CSA\n");
+ return -ENOMEM;
+ }
+
+ r = amdgpu_vm_bo_map(adev, bo_va, AMDGPU_CSA_VADDR, 0,AMDGPU_CSA_SIZE,
+ AMDGPU_PTE_READABLE | AMDGPU_PTE_WRITEABLE |
+ AMDGPU_PTE_EXECUTABLE);
+
+ if (r) {
+ DRM_ERROR("failed to do bo_map on static CSA, err=%d\n", r);
+ amdgpu_vm_bo_rmv(adev, bo_va);
+ ttm_eu_backoff_reservation(&ticket, &list);
+ return r;
+ }
+
+ vm->csa_bo_va = bo_va;
+ ttm_eu_backoff_reservation(&ticket, &list);
+ return 0;
+}
+
+void amdgpu_virt_init_setting(struct amdgpu_device *adev)
+{
+ /* enable virtual display */
+ adev->mode_info.num_crtc = 1;
+ adev->enable_virtual_display = true;
+
+ mutex_init(&adev->virt.lock);
+}
+
+uint32_t amdgpu_virt_kiq_rreg(struct amdgpu_device *adev, uint32_t reg)
+{
+ signed long r;
+ uint32_t val;
+ struct dma_fence *f;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+ struct amdgpu_ring *ring = &kiq->ring;
+
+ BUG_ON(!ring->funcs->emit_rreg);
+
+ mutex_lock(&adev->virt.lock);
+ amdgpu_ring_alloc(ring, 32);
+ amdgpu_ring_emit_hdp_flush(ring);
+ amdgpu_ring_emit_rreg(ring, reg);
+ amdgpu_ring_emit_hdp_invalidate(ring);
+ amdgpu_fence_emit(ring, &f);
+ amdgpu_ring_commit(ring);
+ mutex_unlock(&adev->virt.lock);
+
+ r = dma_fence_wait(f, false);
+ if (r)
+ DRM_ERROR("wait for kiq fence error: %ld.\n", r);
+ dma_fence_put(f);
+
+ val = adev->wb.wb[adev->virt.reg_val_offs];
+
+ return val;
+}
+
+void amdgpu_virt_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v)
+{
+ signed long r;
+ struct dma_fence *f;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+ struct amdgpu_ring *ring = &kiq->ring;
+
+ BUG_ON(!ring->funcs->emit_wreg);
+
+ mutex_lock(&adev->virt.lock);
+ amdgpu_ring_alloc(ring, 32);
+ amdgpu_ring_emit_hdp_flush(ring);
+ amdgpu_ring_emit_wreg(ring, reg, v);
+ amdgpu_ring_emit_hdp_invalidate(ring);
+ amdgpu_fence_emit(ring, &f);
+ amdgpu_ring_commit(ring);
+ mutex_unlock(&adev->virt.lock);
+
+ r = dma_fence_wait(f, false);
+ if (r)
+ DRM_ERROR("wait for kiq fence error: %ld.\n", r);
+ dma_fence_put(f);
+}
+
+/**
+ * amdgpu_virt_request_full_gpu() - request full gpu access
+ * @amdgpu: amdgpu device.
+ * @init: is driver init time.
+ * When start to init/fini driver, first need to request full gpu access.
+ * Return: Zero if request success, otherwise will return error.
+ */
+int amdgpu_virt_request_full_gpu(struct amdgpu_device *adev, bool init)
+{
+ struct amdgpu_virt *virt = &adev->virt;
+ int r;
+
+ if (virt->ops && virt->ops->req_full_gpu) {
+ r = virt->ops->req_full_gpu(adev, init);
+ if (r)
+ return r;
+
+ adev->virt.caps &= ~AMDGPU_SRIOV_CAPS_RUNTIME;
+ }
+
+ return 0;
+}
+
+/**
+ * amdgpu_virt_release_full_gpu() - release full gpu access
+ * @amdgpu: amdgpu device.
+ * @init: is driver init time.
+ * When finishing driver init/fini, need to release full gpu access.
+ * Return: Zero if release success, otherwise will returen error.
+ */
+int amdgpu_virt_release_full_gpu(struct amdgpu_device *adev, bool init)
+{
+ struct amdgpu_virt *virt = &adev->virt;
+ int r;
+
+ if (virt->ops && virt->ops->rel_full_gpu) {
+ r = virt->ops->rel_full_gpu(adev, init);
+ if (r)
+ return r;
+
+ adev->virt.caps |= AMDGPU_SRIOV_CAPS_RUNTIME;
+ }
+ return 0;
+}
+
+/**
+ * amdgpu_virt_reset_gpu() - reset gpu
+ * @amdgpu: amdgpu device.
+ * Send reset command to GPU hypervisor to reset GPU that VM is using
+ * Return: Zero if reset success, otherwise will return error.
+ */
+int amdgpu_virt_reset_gpu(struct amdgpu_device *adev)
+{
+ struct amdgpu_virt *virt = &adev->virt;
+ int r;
+
+ if (virt->ops && virt->ops->reset_gpu) {
+ r = virt->ops->reset_gpu(adev);
+ if (r)
+ return r;
+
+ adev->virt.caps &= ~AMDGPU_SRIOV_CAPS_RUNTIME;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
index 2c37a37..675e12c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
@@ -28,22 +28,48 @@
#define AMDGPU_SRIOV_CAPS_ENABLE_IOV (1 << 1) /* sr-iov is enabled on this GPU */
#define AMDGPU_SRIOV_CAPS_IS_VF (1 << 2) /* this GPU is a virtual function */
#define AMDGPU_PASSTHROUGH_MODE (1 << 3) /* thw whole GPU is pass through for VM */
+#define AMDGPU_SRIOV_CAPS_RUNTIME (1 << 4) /* is out of full access mode */
+
+/**
+ * struct amdgpu_virt_ops - amdgpu device virt operations
+ */
+struct amdgpu_virt_ops {
+ int (*req_full_gpu)(struct amdgpu_device *adev, bool init);
+ int (*rel_full_gpu)(struct amdgpu_device *adev, bool init);
+ int (*reset_gpu)(struct amdgpu_device *adev);
+};
+
/* GPU virtualization */
-struct amdgpu_virtualization {
- uint32_t virtual_caps;
+struct amdgpu_virt {
+ uint32_t caps;
+ struct amdgpu_bo *csa_obj;
+ uint64_t csa_vmid0_addr;
+ bool chained_ib_support;
+ uint32_t reg_val_offs;
+ struct mutex lock;
+ struct amdgpu_irq_src ack_irq;
+ struct amdgpu_irq_src rcv_irq;
+ struct delayed_work flr_work;
+ const struct amdgpu_virt_ops *ops;
};
+#define AMDGPU_CSA_SIZE (8 * 1024)
+#define AMDGPU_CSA_VADDR (AMDGPU_VA_RESERVED_SIZE - AMDGPU_CSA_SIZE)
+
#define amdgpu_sriov_enabled(adev) \
-((adev)->virtualization.virtual_caps & AMDGPU_SRIOV_CAPS_ENABLE_IOV)
+((adev)->virt.caps & AMDGPU_SRIOV_CAPS_ENABLE_IOV)
#define amdgpu_sriov_vf(adev) \
-((adev)->virtualization.virtual_caps & AMDGPU_SRIOV_CAPS_IS_VF)
+((adev)->virt.caps & AMDGPU_SRIOV_CAPS_IS_VF)
#define amdgpu_sriov_bios(adev) \
-((adev)->virtualization.virtual_caps & AMDGPU_SRIOV_CAPS_SRIOV_VBIOS)
+((adev)->virt.caps & AMDGPU_SRIOV_CAPS_SRIOV_VBIOS)
+
+#define amdgpu_sriov_runtime(adev) \
+((adev)->virt.caps & AMDGPU_SRIOV_CAPS_RUNTIME)
#define amdgpu_passthrough(adev) \
-((adev)->virtualization.virtual_caps & AMDGPU_PASSTHROUGH_MODE)
+((adev)->virt.caps & AMDGPU_PASSTHROUGH_MODE)
static inline bool is_virtual_machine(void)
{
@@ -54,4 +80,14 @@ static inline bool is_virtual_machine(void)
#endif
}
-#endif \ No newline at end of file
+struct amdgpu_vm;
+int amdgpu_allocate_static_csa(struct amdgpu_device *adev);
+int amdgpu_map_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm);
+void amdgpu_virt_init_setting(struct amdgpu_device *adev);
+uint32_t amdgpu_virt_kiq_rreg(struct amdgpu_device *adev, uint32_t reg);
+void amdgpu_virt_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v);
+int amdgpu_virt_request_full_gpu(struct amdgpu_device *adev, bool init);
+int amdgpu_virt_release_full_gpu(struct amdgpu_device *adev, bool init);
+int amdgpu_virt_reset_gpu(struct amdgpu_device *adev);
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 1dda932..bd0d331 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -1293,7 +1293,7 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
int amdgpu_vm_bo_map(struct amdgpu_device *adev,
struct amdgpu_bo_va *bo_va,
uint64_t saddr, uint64_t offset,
- uint64_t size, uint32_t flags)
+ uint64_t size, uint64_t flags)
{
struct amdgpu_bo_va_mapping *mapping;
struct amdgpu_vm *vm = bo_va->vm;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index adbc2f5..18c72c0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -111,6 +111,8 @@ struct amdgpu_vm {
/* client id */
u64 client_id;
+ /* each VM will map on CSA */
+ struct amdgpu_bo_va *csa_bo_va;
};
struct amdgpu_vm_id {
@@ -195,7 +197,7 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
int amdgpu_vm_bo_map(struct amdgpu_device *adev,
struct amdgpu_bo_va *bo_va,
uint64_t addr, uint64_t offset,
- uint64_t size, uint32_t flags);
+ uint64_t size, uint64_t flags);
int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
struct amdgpu_bo_va *bo_va,
uint64_t addr);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
index d710226..9e577e3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
@@ -97,8 +97,7 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man,
struct amdgpu_vram_mgr *mgr = man->priv;
struct drm_mm *mm = &mgr->mm;
struct drm_mm_node *nodes;
- enum drm_mm_search_flags sflags = DRM_MM_SEARCH_DEFAULT;
- enum drm_mm_allocator_flags aflags = DRM_MM_CREATE_DEFAULT;
+ enum drm_mm_insert_mode mode;
unsigned long lpfn, num_nodes, pages_per_node, pages_left;
unsigned i;
int r;
@@ -121,10 +120,9 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man,
if (!nodes)
return -ENOMEM;
- if (place->flags & TTM_PL_FLAG_TOPDOWN) {
- sflags = DRM_MM_SEARCH_BELOW;
- aflags = DRM_MM_CREATE_TOP;
- }
+ mode = DRM_MM_INSERT_BEST;
+ if (place->flags & TTM_PL_FLAG_TOPDOWN)
+ mode = DRM_MM_INSERT_HIGH;
pages_left = mem->num_pages;
@@ -135,13 +133,11 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man,
if (pages == pages_per_node)
alignment = pages_per_node;
- else
- sflags |= DRM_MM_SEARCH_BEST;
- r = drm_mm_insert_node_in_range_generic(mm, &nodes[i], pages,
- alignment, 0,
- place->fpfn, lpfn,
- sflags, aflags);
+ r = drm_mm_insert_node_in_range(mm, &nodes[i],
+ pages, alignment, 0,
+ place->fpfn, lpfn,
+ mode);
if (unlikely(r))
goto error;
@@ -207,9 +203,10 @@ static void amdgpu_vram_mgr_debug(struct ttm_mem_type_manager *man,
const char *prefix)
{
struct amdgpu_vram_mgr *mgr = man->priv;
+ struct drm_printer p = drm_debug_printer(prefix);
spin_lock(&mgr->lock);
- drm_mm_debug_table(&mgr->mm, prefix);
+ drm_mm_print(&mgr->mm, &p);
spin_unlock(&mgr->lock);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
index c32eca2..2af26d2 100644
--- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
+++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
@@ -181,9 +181,6 @@ void amdgpu_atombios_encoder_init_backlight(struct amdgpu_encoder *amdgpu_encode
if (!amdgpu_encoder->enc_priv)
return;
- if (!adev->is_atom_bios)
- return;
-
if (!(adev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
return;
@@ -236,9 +233,6 @@ amdgpu_atombios_encoder_fini_backlight(struct amdgpu_encoder *amdgpu_encoder)
if (!amdgpu_encoder->enc_priv)
return;
- if (!adev->is_atom_bios)
- return;
-
if (!(adev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
return;
diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
index bda9e3d..f97ecb4 100644
--- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
@@ -889,7 +889,16 @@ static void ci_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate)
pi->uvd_power_gated = gate;
- ci_update_uvd_dpm(adev, gate);
+ if (gate) {
+ /* stop the UVD block */
+ amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ AMD_PG_STATE_GATE);
+ ci_update_uvd_dpm(adev, gate);
+ } else {
+ amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
+ AMD_PG_STATE_UNGATE);
+ ci_update_uvd_dpm(adev, gate);
+ }
}
static bool ci_dpm_vblank_too_short(struct amdgpu_device *adev)
@@ -2201,7 +2210,6 @@ static void ci_clear_vc(struct amdgpu_device *adev)
static int ci_upload_firmware(struct amdgpu_device *adev)
{
- struct ci_power_info *pi = ci_get_pi(adev);
int i, ret;
if (amdgpu_ci_is_smc_running(adev)) {
@@ -2218,7 +2226,7 @@ static int ci_upload_firmware(struct amdgpu_device *adev)
amdgpu_ci_stop_smc_clock(adev);
amdgpu_ci_reset_smc(adev);
- ret = amdgpu_ci_load_smc_ucode(adev, pi->sram_end);
+ ret = amdgpu_ci_load_smc_ucode(adev, SMC_RAM_END);
return ret;
@@ -4248,12 +4256,6 @@ static int ci_update_vce_dpm(struct amdgpu_device *adev,
if (amdgpu_current_state->evclk != amdgpu_new_state->evclk) {
if (amdgpu_new_state->evclk) {
- /* turn the clocks on when encoding */
- ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
- AMD_CG_STATE_UNGATE);
- if (ret)
- return ret;
-
pi->smc_state_table.VceBootLevel = ci_get_vce_boot_level(adev);
tmp = RREG32_SMC(ixDPM_TABLE_475);
tmp &= ~DPM_TABLE_475__VceBootLevel_MASK;
@@ -4265,9 +4267,6 @@ static int ci_update_vce_dpm(struct amdgpu_device *adev,
ret = ci_enable_vce_dpm(adev, false);
if (ret)
return ret;
- /* turn the clocks off when not encoding */
- ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
- AMD_CG_STATE_GATE);
}
}
return ret;
@@ -4336,13 +4335,13 @@ static u32 ci_get_lowest_enabled_level(struct amdgpu_device *adev,
static int ci_dpm_force_performance_level(struct amdgpu_device *adev,
- enum amdgpu_dpm_forced_level level)
+ enum amd_dpm_forced_level level)
{
struct ci_power_info *pi = ci_get_pi(adev);
u32 tmp, levels, i;
int ret;
- if (level == AMDGPU_DPM_FORCED_LEVEL_HIGH) {
+ if (level == AMD_DPM_FORCED_LEVEL_HIGH) {
if ((!pi->pcie_dpm_key_disabled) &&
pi->dpm_level_enable_mask.pcie_dpm_enable_mask) {
levels = 0;
@@ -4403,7 +4402,7 @@ static int ci_dpm_force_performance_level(struct amdgpu_device *adev,
}
}
}
- } else if (level == AMDGPU_DPM_FORCED_LEVEL_LOW) {
+ } else if (level == AMD_DPM_FORCED_LEVEL_LOW) {
if ((!pi->sclk_dpm_key_disabled) &&
pi->dpm_level_enable_mask.sclk_dpm_enable_mask) {
levels = ci_get_lowest_enabled_level(adev,
@@ -4452,7 +4451,7 @@ static int ci_dpm_force_performance_level(struct amdgpu_device *adev,
udelay(1);
}
}
- } else if (level == AMDGPU_DPM_FORCED_LEVEL_AUTO) {
+ } else if (level == AMD_DPM_FORCED_LEVEL_AUTO) {
if (!pi->pcie_dpm_key_disabled) {
PPSMC_Result smc_result;
@@ -6262,20 +6261,20 @@ static int ci_dpm_sw_init(void *handle)
/* default to balanced state */
adev->pm.dpm.state = POWER_STATE_TYPE_BALANCED;
adev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED;
- adev->pm.dpm.forced_level = AMDGPU_DPM_FORCED_LEVEL_AUTO;
+ adev->pm.dpm.forced_level = AMD_DPM_FORCED_LEVEL_AUTO;
adev->pm.default_sclk = adev->clock.default_sclk;
adev->pm.default_mclk = adev->clock.default_mclk;
adev->pm.current_sclk = adev->clock.default_sclk;
adev->pm.current_mclk = adev->clock.default_mclk;
adev->pm.int_thermal_type = THERMAL_TYPE_NONE;
- if (amdgpu_dpm == 0)
- return 0;
-
ret = ci_dpm_init_microcode(adev);
if (ret)
return ret;
+ if (amdgpu_dpm == 0)
+ return 0;
+
INIT_WORK(&adev->pm.dpm.thermal.work, amdgpu_dpm_thermal_work_handler);
mutex_lock(&adev->pm.mutex);
ret = ci_dpm_init(adev);
@@ -6319,8 +6318,15 @@ static int ci_dpm_hw_init(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- if (!amdgpu_dpm)
+ if (!amdgpu_dpm) {
+ ret = ci_upload_firmware(adev);
+ if (ret) {
+ DRM_ERROR("ci_upload_firmware failed\n");
+ return ret;
+ }
+ ci_dpm_start_smc(adev);
return 0;
+ }
mutex_lock(&adev->pm.mutex);
ci_dpm_setup_asic(adev);
@@ -6342,6 +6348,8 @@ static int ci_dpm_hw_fini(void *handle)
mutex_lock(&adev->pm.mutex);
ci_dpm_disable(adev);
mutex_unlock(&adev->pm.mutex);
+ } else {
+ ci_dpm_stop_smc(adev);
}
return 0;
@@ -6571,8 +6579,9 @@ static int ci_dpm_force_clock_level(struct amdgpu_device *adev,
{
struct ci_power_info *pi = ci_get_pi(adev);
- if (adev->pm.dpm.forced_level
- != AMDGPU_DPM_FORCED_LEVEL_MANUAL)
+ if (adev->pm.dpm.forced_level & (AMD_DPM_FORCED_LEVEL_AUTO |
+ AMD_DPM_FORCED_LEVEL_LOW |
+ AMD_DPM_FORCED_LEVEL_HIGH))
return -EINVAL;
switch (type) {
@@ -6739,12 +6748,3 @@ static void ci_dpm_set_irq_funcs(struct amdgpu_device *adev)
adev->pm.dpm.thermal.irq.num_types = AMDGPU_THERMAL_IRQ_LAST;
adev->pm.dpm.thermal.irq.funcs = &ci_dpm_irq_funcs;
}
-
-const struct amdgpu_ip_block_version ci_dpm_ip_block =
-{
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 7,
- .minor = 0,
- .rev = 0,
- .funcs = &ci_dpm_ip_funcs,
-};
diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index 302df85..c4d4b35 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1176,6 +1176,7 @@ static int cik_gpu_pci_config_reset(struct amdgpu_device *adev)
if (RREG32(mmCONFIG_MEMSIZE) != 0xffffffff) {
/* enable BM */
pci_set_master(adev->pdev);
+ adev->has_hw_reset = true;
r = 0;
break;
}
@@ -1627,14 +1628,13 @@ static uint32_t cik_get_rev_id(struct amdgpu_device *adev)
static void cik_detect_hw_virtualization(struct amdgpu_device *adev)
{
if (is_virtual_machine()) /* passthrough mode */
- adev->virtualization.virtual_caps |= AMDGPU_PASSTHROUGH_MODE;
+ adev->virt.caps |= AMDGPU_PASSTHROUGH_MODE;
}
static const struct amdgpu_asic_funcs cik_asic_funcs =
{
.read_disabled_bios = &cik_read_disabled_bios,
.read_bios_from_rom = &cik_read_bios_from_rom,
- .detect_hw_virtualization = cik_detect_hw_virtualization,
.read_register = &cik_read_register,
.reset = &cik_asic_reset,
.set_vga_state = &cik_vga_set_state,
@@ -1723,8 +1723,8 @@ static int cik_common_early_init(void *handle)
AMD_PG_SUPPORT_GFX_SMG |
AMD_PG_SUPPORT_GFX_DMG |*/
AMD_PG_SUPPORT_UVD |
- /*AMD_PG_SUPPORT_VCE |
- AMD_PG_SUPPORT_CP |
+ AMD_PG_SUPPORT_VCE |
+ /* AMD_PG_SUPPORT_CP |
AMD_PG_SUPPORT_GDS |
AMD_PG_SUPPORT_RLC_SMU_HS |
AMD_PG_SUPPORT_ACP |
@@ -1890,6 +1890,8 @@ static const struct amdgpu_ip_block_version cik_common_ip_block =
int cik_set_ip_blocks(struct amdgpu_device *adev)
{
+ cik_detect_hw_virtualization(adev);
+
switch (adev->asic_type) {
case CHIP_BONAIRE:
amdgpu_ip_block_add(adev, &cik_common_ip_block);
diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
index 4c34dbc..810bba5 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
@@ -651,7 +651,7 @@ static int cik_sdma_ring_test_ib(struct amdgpu_ring *ring, long timeout)
ib.ptr[3] = 1;
ib.ptr[4] = 0xDEADBEEF;
ib.length_dw = 5;
- r = amdgpu_ib_schedule(ring, 1, &ib, NULL, NULL, &f);
+ r = amdgpu_ib_schedule(ring, 1, &ib, NULL, &f);
if (r)
goto err1;
diff --git a/drivers/gpu/drm/amd/include/asic_reg/si/clearstate_si.h b/drivers/gpu/drm/amd/amdgpu/clearstate_si.h
index 66e39cd..66e39cd 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/si/clearstate_si.h
+++ b/drivers/gpu/drm/amd/amdgpu/clearstate_si.h
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
deleted file mode 100644
index ba2b66b..0000000
--- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
+++ /dev/null
@@ -1,2320 +0,0 @@
-/*
- * 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 <linux/firmware.h>
-#include <linux/seq_file.h>
-#include "drmP.h"
-#include "amdgpu.h"
-#include "amdgpu_pm.h"
-#include "amdgpu_atombios.h"
-#include "vid.h"
-#include "vi_dpm.h"
-#include "amdgpu_dpm.h"
-#include "cz_dpm.h"
-#include "cz_ppsmc.h"
-#include "atom.h"
-
-#include "smu/smu_8_0_d.h"
-#include "smu/smu_8_0_sh_mask.h"
-#include "gca/gfx_8_0_d.h"
-#include "gca/gfx_8_0_sh_mask.h"
-#include "gmc/gmc_8_1_d.h"
-#include "bif/bif_5_1_d.h"
-#include "gfx_v8_0.h"
-
-static void cz_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate);
-static void cz_dpm_powergate_vce(struct amdgpu_device *adev, bool gate);
-static void cz_dpm_fini(struct amdgpu_device *adev);
-
-static struct cz_ps *cz_get_ps(struct amdgpu_ps *rps)
-{
- struct cz_ps *ps = rps->ps_priv;
-
- return ps;
-}
-
-static struct cz_power_info *cz_get_pi(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = adev->pm.dpm.priv;
-
- return pi;
-}
-
-static uint16_t cz_convert_8bit_index_to_voltage(struct amdgpu_device *adev,
- uint16_t voltage)
-{
- uint16_t tmp = 6200 - voltage * 25;
-
- return tmp;
-}
-
-static void cz_construct_max_power_limits_table(struct amdgpu_device *adev,
- struct amdgpu_clock_and_voltage_limits *table)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct amdgpu_clock_voltage_dependency_table *dep_table =
- &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk;
-
- if (dep_table->count > 0) {
- table->sclk = dep_table->entries[dep_table->count - 1].clk;
- table->vddc = cz_convert_8bit_index_to_voltage(adev,
- dep_table->entries[dep_table->count - 1].v);
- }
-
- table->mclk = pi->sys_info.nbp_memory_clock[0];
-
-}
-
-union igp_info {
- struct _ATOM_INTEGRATED_SYSTEM_INFO info;
- struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
- struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8 info_8;
- struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_9 info_9;
-};
-
-static int cz_parse_sys_info_table(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct amdgpu_mode_info *mode_info = &adev->mode_info;
- int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
- union igp_info *igp_info;
- u8 frev, crev;
- u16 data_offset;
- int i = 0;
-
- if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
- &frev, &crev, &data_offset)) {
- igp_info = (union igp_info *)(mode_info->atom_context->bios +
- data_offset);
-
- if (crev != 9) {
- DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
- return -EINVAL;
- }
- pi->sys_info.bootup_sclk =
- le32_to_cpu(igp_info->info_9.ulBootUpEngineClock);
- pi->sys_info.bootup_uma_clk =
- le32_to_cpu(igp_info->info_9.ulBootUpUMAClock);
- pi->sys_info.dentist_vco_freq =
- le32_to_cpu(igp_info->info_9.ulDentistVCOFreq);
- pi->sys_info.bootup_nb_voltage_index =
- le16_to_cpu(igp_info->info_9.usBootUpNBVoltage);
-
- if (igp_info->info_9.ucHtcTmpLmt == 0)
- pi->sys_info.htc_tmp_lmt = 203;
- else
- pi->sys_info.htc_tmp_lmt = igp_info->info_9.ucHtcTmpLmt;
-
- if (igp_info->info_9.ucHtcHystLmt == 0)
- pi->sys_info.htc_hyst_lmt = 5;
- else
- pi->sys_info.htc_hyst_lmt = igp_info->info_9.ucHtcHystLmt;
-
- if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) {
- DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n");
- return -EINVAL;
- }
-
- if (le32_to_cpu(igp_info->info_9.ulSystemConfig) & (1 << 3) &&
- pi->enable_nb_ps_policy)
- pi->sys_info.nb_dpm_enable = true;
- else
- pi->sys_info.nb_dpm_enable = false;
-
- for (i = 0; i < CZ_NUM_NBPSTATES; i++) {
- if (i < CZ_NUM_NBPMEMORY_CLOCK)
- pi->sys_info.nbp_memory_clock[i] =
- le32_to_cpu(igp_info->info_9.ulNbpStateMemclkFreq[i]);
- pi->sys_info.nbp_n_clock[i] =
- le32_to_cpu(igp_info->info_9.ulNbpStateNClkFreq[i]);
- }
-
- for (i = 0; i < CZ_MAX_DISPLAY_CLOCK_LEVEL; i++)
- pi->sys_info.display_clock[i] =
- le32_to_cpu(igp_info->info_9.sDispClkVoltageMapping[i].ulMaximumSupportedCLK);
-
- for (i = 0; i < CZ_NUM_NBPSTATES; i++)
- pi->sys_info.nbp_voltage_index[i] =
- le32_to_cpu(igp_info->info_9.usNBPStateVoltage[i]);
-
- if (le32_to_cpu(igp_info->info_9.ulGPUCapInfo) &
- SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS)
- pi->caps_enable_dfs_bypass = true;
-
- pi->sys_info.uma_channel_number =
- igp_info->info_9.ucUMAChannelNumber;
-
- cz_construct_max_power_limits_table(adev,
- &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac);
- }
-
- return 0;
-}
-
-static void cz_patch_voltage_values(struct amdgpu_device *adev)
-{
- int i;
- struct amdgpu_uvd_clock_voltage_dependency_table *uvd_table =
- &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table;
- struct amdgpu_vce_clock_voltage_dependency_table *vce_table =
- &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
- struct amdgpu_clock_voltage_dependency_table *acp_table =
- &adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table;
-
- if (uvd_table->count) {
- for (i = 0; i < uvd_table->count; i++)
- uvd_table->entries[i].v =
- cz_convert_8bit_index_to_voltage(adev,
- uvd_table->entries[i].v);
- }
-
- if (vce_table->count) {
- for (i = 0; i < vce_table->count; i++)
- vce_table->entries[i].v =
- cz_convert_8bit_index_to_voltage(adev,
- vce_table->entries[i].v);
- }
-
- if (acp_table->count) {
- for (i = 0; i < acp_table->count; i++)
- acp_table->entries[i].v =
- cz_convert_8bit_index_to_voltage(adev,
- acp_table->entries[i].v);
- }
-
-}
-
-static void cz_construct_boot_state(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
-
- pi->boot_pl.sclk = pi->sys_info.bootup_sclk;
- pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index;
- pi->boot_pl.ds_divider_index = 0;
- pi->boot_pl.ss_divider_index = 0;
- pi->boot_pl.allow_gnb_slow = 1;
- pi->boot_pl.force_nbp_state = 0;
- pi->boot_pl.display_wm = 0;
- pi->boot_pl.vce_wm = 0;
-
-}
-
-static void cz_patch_boot_state(struct amdgpu_device *adev,
- struct cz_ps *ps)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
-
- ps->num_levels = 1;
- ps->levels[0] = pi->boot_pl;
-}
-
-union pplib_clock_info {
- struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
- struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
- struct _ATOM_PPLIB_CZ_CLOCK_INFO carrizo;
-};
-
-static void cz_parse_pplib_clock_info(struct amdgpu_device *adev,
- struct amdgpu_ps *rps, int index,
- union pplib_clock_info *clock_info)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct cz_ps *ps = cz_get_ps(rps);
- struct cz_pl *pl = &ps->levels[index];
- struct amdgpu_clock_voltage_dependency_table *table =
- &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk;
-
- pl->sclk = table->entries[clock_info->carrizo.index].clk;
- pl->vddc_index = table->entries[clock_info->carrizo.index].v;
-
- ps->num_levels = index + 1;
-
- if (pi->caps_sclk_ds) {
- pl->ds_divider_index = 5;
- pl->ss_divider_index = 5;
- }
-
-}
-
-static void cz_parse_pplib_non_clock_info(struct amdgpu_device *adev,
- struct amdgpu_ps *rps,
- struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
- u8 table_rev)
-{
- struct cz_ps *ps = cz_get_ps(rps);
-
- rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
- rps->class = le16_to_cpu(non_clock_info->usClassification);
- rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
-
- if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
- rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
- rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
- } else {
- rps->vclk = 0;
- rps->dclk = 0;
- }
-
- if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
- adev->pm.dpm.boot_ps = rps;
- cz_patch_boot_state(adev, ps);
- }
- if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
- adev->pm.dpm.uvd_ps = rps;
-
-}
-
-union power_info {
- struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
- struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
- struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
- struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4;
- struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5;
-};
-
-union pplib_power_state {
- struct _ATOM_PPLIB_STATE v1;
- struct _ATOM_PPLIB_STATE_V2 v2;
-};
-
-static int cz_parse_power_table(struct amdgpu_device *adev)
-{
- struct amdgpu_mode_info *mode_info = &adev->mode_info;
- struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
- union pplib_power_state *power_state;
- int i, j, k, non_clock_array_index, clock_array_index;
- union pplib_clock_info *clock_info;
- struct _StateArray *state_array;
- struct _ClockInfoArray *clock_info_array;
- struct _NonClockInfoArray *non_clock_info_array;
- union power_info *power_info;
- int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
- u16 data_offset;
- u8 frev, crev;
- u8 *power_state_offset;
- struct cz_ps *ps;
-
- if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
- &frev, &crev, &data_offset))
- return -EINVAL;
- power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
-
- state_array = (struct _StateArray *)
- (mode_info->atom_context->bios + data_offset +
- le16_to_cpu(power_info->pplib.usStateArrayOffset));
- clock_info_array = (struct _ClockInfoArray *)
- (mode_info->atom_context->bios + data_offset +
- le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
- non_clock_info_array = (struct _NonClockInfoArray *)
- (mode_info->atom_context->bios + data_offset +
- le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
-
- adev->pm.dpm.ps = kzalloc(sizeof(struct amdgpu_ps) *
- state_array->ucNumEntries, GFP_KERNEL);
-
- if (!adev->pm.dpm.ps)
- return -ENOMEM;
-
- power_state_offset = (u8 *)state_array->states;
- adev->pm.dpm.platform_caps =
- le32_to_cpu(power_info->pplib.ulPlatformCaps);
- adev->pm.dpm.backbias_response_time =
- le16_to_cpu(power_info->pplib.usBackbiasTime);
- adev->pm.dpm.voltage_response_time =
- le16_to_cpu(power_info->pplib.usVoltageTime);
-
- for (i = 0; i < state_array->ucNumEntries; i++) {
- power_state = (union pplib_power_state *)power_state_offset;
- non_clock_array_index = power_state->v2.nonClockInfoIndex;
- non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
- &non_clock_info_array->nonClockInfo[non_clock_array_index];
-
- ps = kzalloc(sizeof(struct cz_ps), GFP_KERNEL);
- if (ps == NULL) {
- for (j = 0; j < i; j++)
- kfree(adev->pm.dpm.ps[j].ps_priv);
- kfree(adev->pm.dpm.ps);
- return -ENOMEM;
- }
-
- adev->pm.dpm.ps[i].ps_priv = ps;
- k = 0;
- for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
- clock_array_index = power_state->v2.clockInfoIndex[j];
- if (clock_array_index >= clock_info_array->ucNumEntries)
- continue;
- if (k >= CZ_MAX_HARDWARE_POWERLEVELS)
- break;
- clock_info = (union pplib_clock_info *)
- &clock_info_array->clockInfo[clock_array_index *
- clock_info_array->ucEntrySize];
- cz_parse_pplib_clock_info(adev, &adev->pm.dpm.ps[i],
- k, clock_info);
- k++;
- }
- cz_parse_pplib_non_clock_info(adev, &adev->pm.dpm.ps[i],
- non_clock_info,
- non_clock_info_array->ucEntrySize);
- power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
- }
- adev->pm.dpm.num_ps = state_array->ucNumEntries;
-
- return 0;
-}
-
-static int cz_process_firmware_header(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- u32 tmp;
- int ret;
-
- ret = cz_read_smc_sram_dword(adev, SMU8_FIRMWARE_HEADER_LOCATION +
- offsetof(struct SMU8_Firmware_Header,
- DpmTable),
- &tmp, pi->sram_end);
-
- if (ret == 0)
- pi->dpm_table_start = tmp;
-
- return ret;
-}
-
-static int cz_dpm_init(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi;
- int ret, i;
-
- pi = kzalloc(sizeof(struct cz_power_info), GFP_KERNEL);
- if (NULL == pi)
- return -ENOMEM;
-
- adev->pm.dpm.priv = pi;
-
- ret = amdgpu_get_platform_caps(adev);
- if (ret)
- goto err;
-
- ret = amdgpu_parse_extended_power_table(adev);
- if (ret)
- goto err;
-
- pi->sram_end = SMC_RAM_END;
-
- /* set up DPM defaults */
- for (i = 0; i < CZ_MAX_HARDWARE_POWERLEVELS; i++)
- pi->active_target[i] = CZ_AT_DFLT;
-
- pi->mgcg_cgtt_local0 = 0x0;
- pi->mgcg_cgtt_local1 = 0x0;
- pi->clock_slow_down_step = 25000;
- pi->skip_clock_slow_down = 1;
- pi->enable_nb_ps_policy = false;
- pi->caps_power_containment = true;
- pi->caps_cac = true;
- pi->didt_enabled = false;
- if (pi->didt_enabled) {
- pi->caps_sq_ramping = true;
- pi->caps_db_ramping = true;
- pi->caps_td_ramping = true;
- pi->caps_tcp_ramping = true;
- }
- if (amdgpu_pp_feature_mask & SCLK_DEEP_SLEEP_MASK)
- pi->caps_sclk_ds = true;
- else
- pi->caps_sclk_ds = false;
-
- pi->voting_clients = 0x00c00033;
- pi->auto_thermal_throttling_enabled = true;
- pi->bapm_enabled = false;
- pi->disable_nb_ps3_in_battery = false;
- pi->voltage_drop_threshold = 0;
- pi->caps_sclk_throttle_low_notification = false;
- pi->gfx_pg_threshold = 500;
- pi->caps_fps = true;
- /* uvd */
- pi->caps_uvd_pg = (adev->pg_flags & AMD_PG_SUPPORT_UVD) ? true : false;
- pi->caps_uvd_dpm = true;
- /* vce */
- pi->caps_vce_pg = (adev->pg_flags & AMD_PG_SUPPORT_VCE) ? true : false;
- pi->caps_vce_dpm = true;
- /* acp */
- pi->caps_acp_pg = (adev->pg_flags & AMD_PG_SUPPORT_ACP) ? true : false;
- pi->caps_acp_dpm = true;
-
- pi->caps_stable_power_state = false;
- pi->nb_dpm_enabled_by_driver = true;
- pi->nb_dpm_enabled = false;
- pi->caps_voltage_island = false;
- /* flags which indicate need to upload pptable */
- pi->need_pptable_upload = true;
-
- ret = cz_parse_sys_info_table(adev);
- if (ret)
- goto err;
-
- cz_patch_voltage_values(adev);
- cz_construct_boot_state(adev);
-
- ret = cz_parse_power_table(adev);
- if (ret)
- goto err;
-
- ret = cz_process_firmware_header(adev);
- if (ret)
- goto err;
-
- pi->dpm_enabled = true;
- pi->uvd_dynamic_pg = false;
-
- return 0;
-err:
- cz_dpm_fini(adev);
- return ret;
-}
-
-static void cz_dpm_fini(struct amdgpu_device *adev)
-{
- int i;
-
- for (i = 0; i < adev->pm.dpm.num_ps; i++)
- kfree(adev->pm.dpm.ps[i].ps_priv);
-
- kfree(adev->pm.dpm.ps);
- kfree(adev->pm.dpm.priv);
- amdgpu_free_extended_power_table(adev);
-}
-
-#define ixSMUSVI_NB_CURRENTVID 0xD8230044
-#define CURRENT_NB_VID_MASK 0xff000000
-#define CURRENT_NB_VID__SHIFT 24
-#define ixSMUSVI_GFX_CURRENTVID 0xD8230048
-#define CURRENT_GFX_VID_MASK 0xff000000
-#define CURRENT_GFX_VID__SHIFT 24
-
-static void
-cz_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev,
- struct seq_file *m)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct amdgpu_clock_voltage_dependency_table *table =
- &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk;
- struct amdgpu_uvd_clock_voltage_dependency_table *uvd_table =
- &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table;
- struct amdgpu_vce_clock_voltage_dependency_table *vce_table =
- &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
- u32 sclk_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX),
- TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX);
- u32 uvd_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX_2),
- TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_UVD_INDEX);
- u32 vce_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX_2),
- TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX);
- u32 sclk, vclk, dclk, ecclk, tmp;
- u16 vddnb, vddgfx;
-
- if (sclk_index >= NUM_SCLK_LEVELS) {
- seq_printf(m, "invalid sclk dpm profile %d\n", sclk_index);
- } else {
- sclk = table->entries[sclk_index].clk;
- seq_printf(m, "%u sclk: %u\n", sclk_index, sclk);
- }
-
- tmp = (RREG32_SMC(ixSMUSVI_NB_CURRENTVID) &
- CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT;
- vddnb = cz_convert_8bit_index_to_voltage(adev, (u16)tmp);
- tmp = (RREG32_SMC(ixSMUSVI_GFX_CURRENTVID) &
- CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT;
- vddgfx = cz_convert_8bit_index_to_voltage(adev, (u16)tmp);
- seq_printf(m, "vddnb: %u vddgfx: %u\n", vddnb, vddgfx);
-
- seq_printf(m, "uvd %sabled\n", pi->uvd_power_gated ? "dis" : "en");
- if (!pi->uvd_power_gated) {
- if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) {
- seq_printf(m, "invalid uvd dpm level %d\n", uvd_index);
- } else {
- vclk = uvd_table->entries[uvd_index].vclk;
- dclk = uvd_table->entries[uvd_index].dclk;
- seq_printf(m, "%u uvd vclk: %u dclk: %u\n", uvd_index, vclk, dclk);
- }
- }
-
- seq_printf(m, "vce %sabled\n", pi->vce_power_gated ? "dis" : "en");
- if (!pi->vce_power_gated) {
- if (vce_index >= CZ_MAX_HARDWARE_POWERLEVELS) {
- seq_printf(m, "invalid vce dpm level %d\n", vce_index);
- } else {
- ecclk = vce_table->entries[vce_index].ecclk;
- seq_printf(m, "%u vce ecclk: %u\n", vce_index, ecclk);
- }
- }
-}
-
-static void cz_dpm_print_power_state(struct amdgpu_device *adev,
- struct amdgpu_ps *rps)
-{
- int i;
- struct cz_ps *ps = cz_get_ps(rps);
-
- amdgpu_dpm_print_class_info(rps->class, rps->class2);
- amdgpu_dpm_print_cap_info(rps->caps);
-
- DRM_INFO("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
- for (i = 0; i < ps->num_levels; i++) {
- struct cz_pl *pl = &ps->levels[i];
-
- DRM_INFO("\t\tpower level %d sclk: %u vddc: %u\n",
- i, pl->sclk,
- cz_convert_8bit_index_to_voltage(adev, pl->vddc_index));
- }
-
- amdgpu_dpm_print_ps_status(adev, rps);
-}
-
-static void cz_dpm_set_funcs(struct amdgpu_device *adev);
-
-static int cz_dpm_early_init(void *handle)
-{
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
- cz_dpm_set_funcs(adev);
-
- return 0;
-}
-
-
-static int cz_dpm_late_init(void *handle)
-{
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
- if (amdgpu_dpm) {
- int ret;
- /* init the sysfs and debugfs files late */
- ret = amdgpu_pm_sysfs_init(adev);
- if (ret)
- return ret;
-
- /* powerdown unused blocks for now */
- cz_dpm_powergate_uvd(adev, true);
- cz_dpm_powergate_vce(adev, true);
- }
-
- return 0;
-}
-
-static int cz_dpm_sw_init(void *handle)
-{
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- int ret = 0;
- /* fix me to add thermal support TODO */
-
- /* default to balanced state */
- adev->pm.dpm.state = POWER_STATE_TYPE_BALANCED;
- adev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED;
- adev->pm.dpm.forced_level = AMDGPU_DPM_FORCED_LEVEL_AUTO;
- adev->pm.default_sclk = adev->clock.default_sclk;
- adev->pm.default_mclk = adev->clock.default_mclk;
- adev->pm.current_sclk = adev->clock.default_sclk;
- adev->pm.current_mclk = adev->clock.default_mclk;
- adev->pm.int_thermal_type = THERMAL_TYPE_NONE;
-
- if (amdgpu_dpm == 0)
- return 0;
-
- mutex_lock(&adev->pm.mutex);
- ret = cz_dpm_init(adev);
- if (ret)
- goto dpm_init_failed;
-
- adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
- if (amdgpu_dpm == 1)
- amdgpu_pm_print_power_states(adev);
-
- mutex_unlock(&adev->pm.mutex);
- DRM_INFO("amdgpu: dpm initialized\n");
-
- return 0;
-
-dpm_init_failed:
- cz_dpm_fini(adev);
- mutex_unlock(&adev->pm.mutex);
- DRM_ERROR("amdgpu: dpm initialization failed\n");
-
- return ret;
-}
-
-static int cz_dpm_sw_fini(void *handle)
-{
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
- mutex_lock(&adev->pm.mutex);
- amdgpu_pm_sysfs_fini(adev);
- cz_dpm_fini(adev);
- mutex_unlock(&adev->pm.mutex);
-
- return 0;
-}
-
-static void cz_reset_ap_mask(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
-
- pi->active_process_mask = 0;
-}
-
-static int cz_dpm_download_pptable_from_smu(struct amdgpu_device *adev,
- void **table)
-{
- return cz_smu_download_pptable(adev, table);
-}
-
-static int cz_dpm_upload_pptable_to_smu(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct SMU8_Fusion_ClkTable *clock_table;
- struct atom_clock_dividers dividers;
- void *table = NULL;
- uint8_t i = 0;
- int ret = 0;
-
- struct amdgpu_clock_voltage_dependency_table *vddc_table =
- &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk;
- struct amdgpu_clock_voltage_dependency_table *vddgfx_table =
- &adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk;
- struct amdgpu_uvd_clock_voltage_dependency_table *uvd_table =
- &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table;
- struct amdgpu_vce_clock_voltage_dependency_table *vce_table =
- &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
- struct amdgpu_clock_voltage_dependency_table *acp_table =
- &adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table;
-
- if (!pi->need_pptable_upload)
- return 0;
-
- ret = cz_dpm_download_pptable_from_smu(adev, &table);
- if (ret) {
- DRM_ERROR("amdgpu: Failed to get power play table from SMU!\n");
- return -EINVAL;
- }
-
- clock_table = (struct SMU8_Fusion_ClkTable *)table;
- /* patch clock table */
- if (vddc_table->count > CZ_MAX_HARDWARE_POWERLEVELS ||
- vddgfx_table->count > CZ_MAX_HARDWARE_POWERLEVELS ||
- uvd_table->count > CZ_MAX_HARDWARE_POWERLEVELS ||
- vce_table->count > CZ_MAX_HARDWARE_POWERLEVELS ||
- acp_table->count > CZ_MAX_HARDWARE_POWERLEVELS) {
- DRM_ERROR("amdgpu: Invalid Clock Voltage Dependency Table!\n");
- return -EINVAL;
- }
-
- for (i = 0; i < CZ_MAX_HARDWARE_POWERLEVELS; i++) {
-
- /* vddc sclk */
- clock_table->SclkBreakdownTable.ClkLevel[i].GnbVid =
- (i < vddc_table->count) ? (uint8_t)vddc_table->entries[i].v : 0;
- clock_table->SclkBreakdownTable.ClkLevel[i].Frequency =
- (i < vddc_table->count) ? vddc_table->entries[i].clk : 0;
- ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
- clock_table->SclkBreakdownTable.ClkLevel[i].Frequency,
- false, &dividers);
- if (ret)
- return ret;
- clock_table->SclkBreakdownTable.ClkLevel[i].DfsDid =
- (uint8_t)dividers.post_divider;
-
- /* vddgfx sclk */
- clock_table->SclkBreakdownTable.ClkLevel[i].GfxVid =
- (i < vddgfx_table->count) ? (uint8_t)vddgfx_table->entries[i].v : 0;
-
- /* acp breakdown */
- clock_table->AclkBreakdownTable.ClkLevel[i].GfxVid =
- (i < acp_table->count) ? (uint8_t)acp_table->entries[i].v : 0;
- clock_table->AclkBreakdownTable.ClkLevel[i].Frequency =
- (i < acp_table->count) ? acp_table->entries[i].clk : 0;
- ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
- clock_table->SclkBreakdownTable.ClkLevel[i].Frequency,
- false, &dividers);
- if (ret)
- return ret;
- clock_table->AclkBreakdownTable.ClkLevel[i].DfsDid =
- (uint8_t)dividers.post_divider;
-
- /* uvd breakdown */
- clock_table->VclkBreakdownTable.ClkLevel[i].GfxVid =
- (i < uvd_table->count) ? (uint8_t)uvd_table->entries[i].v : 0;
- clock_table->VclkBreakdownTable.ClkLevel[i].Frequency =
- (i < uvd_table->count) ? uvd_table->entries[i].vclk : 0;
- ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
- clock_table->VclkBreakdownTable.ClkLevel[i].Frequency,
- false, &dividers);
- if (ret)
- return ret;
- clock_table->VclkBreakdownTable.ClkLevel[i].DfsDid =
- (uint8_t)dividers.post_divider;
-
- clock_table->DclkBreakdownTable.ClkLevel[i].GfxVid =
- (i < uvd_table->count) ? (uint8_t)uvd_table->entries[i].v : 0;
- clock_table->DclkBreakdownTable.ClkLevel[i].Frequency =
- (i < uvd_table->count) ? uvd_table->entries[i].dclk : 0;
- ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
- clock_table->DclkBreakdownTable.ClkLevel[i].Frequency,
- false, &dividers);
- if (ret)
- return ret;
- clock_table->DclkBreakdownTable.ClkLevel[i].DfsDid =
- (uint8_t)dividers.post_divider;
-
- /* vce breakdown */
- clock_table->EclkBreakdownTable.ClkLevel[i].GfxVid =
- (i < vce_table->count) ? (uint8_t)vce_table->entries[i].v : 0;
- clock_table->EclkBreakdownTable.ClkLevel[i].Frequency =
- (i < vce_table->count) ? vce_table->entries[i].ecclk : 0;
- ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
- clock_table->EclkBreakdownTable.ClkLevel[i].Frequency,
- false, &dividers);
- if (ret)
- return ret;
- clock_table->EclkBreakdownTable.ClkLevel[i].DfsDid =
- (uint8_t)dividers.post_divider;
- }
-
- /* its time to upload to SMU */
- ret = cz_smu_upload_pptable(adev);
- if (ret) {
- DRM_ERROR("amdgpu: Failed to put power play table to SMU!\n");
- return ret;
- }
-
- return 0;
-}
-
-static void cz_init_sclk_limit(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct amdgpu_clock_voltage_dependency_table *table =
- &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk;
- uint32_t clock = 0, level;
-
- if (!table || !table->count) {
- DRM_ERROR("Invalid Voltage Dependency table.\n");
- return;
- }
-
- pi->sclk_dpm.soft_min_clk = 0;
- pi->sclk_dpm.hard_min_clk = 0;
- cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxSclkLevel);
- level = cz_get_argument(adev);
- if (level < table->count) {
- clock = table->entries[level].clk;
- } else {
- DRM_ERROR("Invalid SLCK Voltage Dependency table entry.\n");
- clock = table->entries[table->count - 1].clk;
- }
-
- pi->sclk_dpm.soft_max_clk = clock;
- pi->sclk_dpm.hard_max_clk = clock;
-
-}
-
-static void cz_init_uvd_limit(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct amdgpu_uvd_clock_voltage_dependency_table *table =
- &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table;
- uint32_t clock = 0, level;
-
- if (!table || !table->count) {
- DRM_ERROR("Invalid Voltage Dependency table.\n");
- return;
- }
-
- pi->uvd_dpm.soft_min_clk = 0;
- pi->uvd_dpm.hard_min_clk = 0;
- cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxUvdLevel);
- level = cz_get_argument(adev);
- if (level < table->count) {
- clock = table->entries[level].vclk;
- } else {
- DRM_ERROR("Invalid UVD Voltage Dependency table entry.\n");
- clock = table->entries[table->count - 1].vclk;
- }
-
- pi->uvd_dpm.soft_max_clk = clock;
- pi->uvd_dpm.hard_max_clk = clock;
-
-}
-
-static void cz_init_vce_limit(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct amdgpu_vce_clock_voltage_dependency_table *table =
- &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
- uint32_t clock = 0, level;
-
- if (!table || !table->count) {
- DRM_ERROR("Invalid Voltage Dependency table.\n");
- return;
- }
-
- pi->vce_dpm.soft_min_clk = table->entries[0].ecclk;
- pi->vce_dpm.hard_min_clk = table->entries[0].ecclk;
- cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxEclkLevel);
- level = cz_get_argument(adev);
- if (level < table->count) {
- clock = table->entries[level].ecclk;
- } else {
- /* future BIOS would fix this error */
- DRM_ERROR("Invalid VCE Voltage Dependency table entry.\n");
- clock = table->entries[table->count - 1].ecclk;
- }
-
- pi->vce_dpm.soft_max_clk = clock;
- pi->vce_dpm.hard_max_clk = clock;
-
-}
-
-static void cz_init_acp_limit(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct amdgpu_clock_voltage_dependency_table *table =
- &adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table;
- uint32_t clock = 0, level;
-
- if (!table || !table->count) {
- DRM_ERROR("Invalid Voltage Dependency table.\n");
- return;
- }
-
- pi->acp_dpm.soft_min_clk = 0;
- pi->acp_dpm.hard_min_clk = 0;
- cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxAclkLevel);
- level = cz_get_argument(adev);
- if (level < table->count) {
- clock = table->entries[level].clk;
- } else {
- DRM_ERROR("Invalid ACP Voltage Dependency table entry.\n");
- clock = table->entries[table->count - 1].clk;
- }
-
- pi->acp_dpm.soft_max_clk = clock;
- pi->acp_dpm.hard_max_clk = clock;
-
-}
-
-static void cz_init_pg_state(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
-
- pi->uvd_power_gated = false;
- pi->vce_power_gated = false;
- pi->acp_power_gated = false;
-
-}
-
-static void cz_init_sclk_threshold(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
-
- pi->low_sclk_interrupt_threshold = 0;
-}
-
-static void cz_dpm_setup_asic(struct amdgpu_device *adev)
-{
- cz_reset_ap_mask(adev);
- cz_dpm_upload_pptable_to_smu(adev);
- cz_init_sclk_limit(adev);
- cz_init_uvd_limit(adev);
- cz_init_vce_limit(adev);
- cz_init_acp_limit(adev);
- cz_init_pg_state(adev);
- cz_init_sclk_threshold(adev);
-
-}
-
-static bool cz_check_smu_feature(struct amdgpu_device *adev,
- uint32_t feature)
-{
- uint32_t smu_feature = 0;
- int ret;
-
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_GetFeatureStatus, 0);
- if (ret) {
- DRM_ERROR("Failed to get SMU features from SMC.\n");
- return false;
- } else {
- smu_feature = cz_get_argument(adev);
- if (feature & smu_feature)
- return true;
- }
-
- return false;
-}
-
-static bool cz_check_for_dpm_enabled(struct amdgpu_device *adev)
-{
- if (cz_check_smu_feature(adev,
- SMU_EnabledFeatureScoreboard_SclkDpmOn))
- return true;
-
- return false;
-}
-
-static void cz_program_voting_clients(struct amdgpu_device *adev)
-{
- WREG32_SMC(ixCG_FREQ_TRAN_VOTING_0, PPCZ_VOTINGRIGHTSCLIENTS_DFLT0);
-}
-
-static void cz_clear_voting_clients(struct amdgpu_device *adev)
-{
- WREG32_SMC(ixCG_FREQ_TRAN_VOTING_0, 0);
-}
-
-static int cz_start_dpm(struct amdgpu_device *adev)
-{
- int ret = 0;
-
- if (amdgpu_dpm) {
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_EnableAllSmuFeatures, SCLK_DPM_MASK);
- if (ret) {
- DRM_ERROR("SMU feature: SCLK_DPM enable failed\n");
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-static int cz_stop_dpm(struct amdgpu_device *adev)
-{
- int ret = 0;
-
- if (amdgpu_dpm && adev->pm.dpm_enabled) {
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_DisableAllSmuFeatures, SCLK_DPM_MASK);
- if (ret) {
- DRM_ERROR("SMU feature: SCLK_DPM disable failed\n");
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-static uint32_t cz_get_sclk_level(struct amdgpu_device *adev,
- uint32_t clock, uint16_t msg)
-{
- int i = 0;
- struct amdgpu_clock_voltage_dependency_table *table =
- &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk;
-
- switch (msg) {
- case PPSMC_MSG_SetSclkSoftMin:
- case PPSMC_MSG_SetSclkHardMin:
- for (i = 0; i < table->count; i++)
- if (clock <= table->entries[i].clk)
- break;
- if (i == table->count)
- i = table->count - 1;
- break;
- case PPSMC_MSG_SetSclkSoftMax:
- case PPSMC_MSG_SetSclkHardMax:
- for (i = table->count - 1; i >= 0; i--)
- if (clock >= table->entries[i].clk)
- break;
- if (i < 0)
- i = 0;
- break;
- default:
- break;
- }
-
- return i;
-}
-
-static uint32_t cz_get_eclk_level(struct amdgpu_device *adev,
- uint32_t clock, uint16_t msg)
-{
- int i = 0;
- struct amdgpu_vce_clock_voltage_dependency_table *table =
- &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
-
- if (table->count == 0)
- return 0;
-
- switch (msg) {
- case PPSMC_MSG_SetEclkSoftMin:
- case PPSMC_MSG_SetEclkHardMin:
- for (i = 0; i < table->count-1; i++)
- if (clock <= table->entries[i].ecclk)
- break;
- break;
- case PPSMC_MSG_SetEclkSoftMax:
- case PPSMC_MSG_SetEclkHardMax:
- for (i = table->count - 1; i > 0; i--)
- if (clock >= table->entries[i].ecclk)
- break;
- break;
- default:
- break;
- }
-
- return i;
-}
-
-static uint32_t cz_get_uvd_level(struct amdgpu_device *adev,
- uint32_t clock, uint16_t msg)
-{
- int i = 0;
- struct amdgpu_uvd_clock_voltage_dependency_table *table =
- &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table;
-
- switch (msg) {
- case PPSMC_MSG_SetUvdSoftMin:
- case PPSMC_MSG_SetUvdHardMin:
- for (i = 0; i < table->count; i++)
- if (clock <= table->entries[i].vclk)
- break;
- if (i == table->count)
- i = table->count - 1;
- break;
- case PPSMC_MSG_SetUvdSoftMax:
- case PPSMC_MSG_SetUvdHardMax:
- for (i = table->count - 1; i >= 0; i--)
- if (clock >= table->entries[i].vclk)
- break;
- if (i < 0)
- i = 0;
- break;
- default:
- break;
- }
-
- return i;
-}
-
-static int cz_program_bootup_state(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- uint32_t soft_min_clk = 0;
- uint32_t soft_max_clk = 0;
- int ret = 0;
-
- pi->sclk_dpm.soft_min_clk = pi->sys_info.bootup_sclk;
- pi->sclk_dpm.soft_max_clk = pi->sys_info.bootup_sclk;
-
- soft_min_clk = cz_get_sclk_level(adev,
- pi->sclk_dpm.soft_min_clk,
- PPSMC_MSG_SetSclkSoftMin);
- soft_max_clk = cz_get_sclk_level(adev,
- pi->sclk_dpm.soft_max_clk,
- PPSMC_MSG_SetSclkSoftMax);
-
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetSclkSoftMin, soft_min_clk);
- if (ret)
- return -EINVAL;
-
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetSclkSoftMax, soft_max_clk);
- if (ret)
- return -EINVAL;
-
- return 0;
-}
-
-/* TODO */
-static int cz_disable_cgpg(struct amdgpu_device *adev)
-{
- return 0;
-}
-
-/* TODO */
-static int cz_enable_cgpg(struct amdgpu_device *adev)
-{
- return 0;
-}
-
-/* TODO */
-static int cz_program_pt_config_registers(struct amdgpu_device *adev)
-{
- return 0;
-}
-
-static void cz_do_enable_didt(struct amdgpu_device *adev, bool enable)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- uint32_t reg = 0;
-
- if (pi->caps_sq_ramping) {
- reg = RREG32_DIDT(ixDIDT_SQ_CTRL0);
- if (enable)
- reg = REG_SET_FIELD(reg, DIDT_SQ_CTRL0, DIDT_CTRL_EN, 1);
- else
- reg = REG_SET_FIELD(reg, DIDT_SQ_CTRL0, DIDT_CTRL_EN, 0);
- WREG32_DIDT(ixDIDT_SQ_CTRL0, reg);
- }
- if (pi->caps_db_ramping) {
- reg = RREG32_DIDT(ixDIDT_DB_CTRL0);
- if (enable)
- reg = REG_SET_FIELD(reg, DIDT_DB_CTRL0, DIDT_CTRL_EN, 1);
- else
- reg = REG_SET_FIELD(reg, DIDT_DB_CTRL0, DIDT_CTRL_EN, 0);
- WREG32_DIDT(ixDIDT_DB_CTRL0, reg);
- }
- if (pi->caps_td_ramping) {
- reg = RREG32_DIDT(ixDIDT_TD_CTRL0);
- if (enable)
- reg = REG_SET_FIELD(reg, DIDT_TD_CTRL0, DIDT_CTRL_EN, 1);
- else
- reg = REG_SET_FIELD(reg, DIDT_TD_CTRL0, DIDT_CTRL_EN, 0);
- WREG32_DIDT(ixDIDT_TD_CTRL0, reg);
- }
- if (pi->caps_tcp_ramping) {
- reg = RREG32_DIDT(ixDIDT_TCP_CTRL0);
- if (enable)
- reg = REG_SET_FIELD(reg, DIDT_SQ_CTRL0, DIDT_CTRL_EN, 1);
- else
- reg = REG_SET_FIELD(reg, DIDT_SQ_CTRL0, DIDT_CTRL_EN, 0);
- WREG32_DIDT(ixDIDT_TCP_CTRL0, reg);
- }
-
-}
-
-static int cz_enable_didt(struct amdgpu_device *adev, bool enable)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- int ret;
-
- if (pi->caps_sq_ramping || pi->caps_db_ramping ||
- pi->caps_td_ramping || pi->caps_tcp_ramping) {
- if (adev->gfx.gfx_current_status != AMDGPU_GFX_SAFE_MODE) {
- ret = cz_disable_cgpg(adev);
- if (ret) {
- DRM_ERROR("Pre Di/Dt disable cg/pg failed\n");
- return -EINVAL;
- }
- adev->gfx.gfx_current_status = AMDGPU_GFX_SAFE_MODE;
- }
-
- ret = cz_program_pt_config_registers(adev);
- if (ret) {
- DRM_ERROR("Di/Dt config failed\n");
- return -EINVAL;
- }
- cz_do_enable_didt(adev, enable);
-
- if (adev->gfx.gfx_current_status == AMDGPU_GFX_SAFE_MODE) {
- ret = cz_enable_cgpg(adev);
- if (ret) {
- DRM_ERROR("Post Di/Dt enable cg/pg failed\n");
- return -EINVAL;
- }
- adev->gfx.gfx_current_status = AMDGPU_GFX_NORMAL_MODE;
- }
- }
-
- return 0;
-}
-
-/* TODO */
-static void cz_reset_acp_boot_level(struct amdgpu_device *adev)
-{
-}
-
-static void cz_update_current_ps(struct amdgpu_device *adev,
- struct amdgpu_ps *rps)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct cz_ps *ps = cz_get_ps(rps);
-
- pi->current_ps = *ps;
- pi->current_rps = *rps;
- pi->current_rps.ps_priv = &pi->current_ps;
- adev->pm.dpm.current_ps = &pi->current_rps;
-
-}
-
-static void cz_update_requested_ps(struct amdgpu_device *adev,
- struct amdgpu_ps *rps)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct cz_ps *ps = cz_get_ps(rps);
-
- pi->requested_ps = *ps;
- pi->requested_rps = *rps;
- pi->requested_rps.ps_priv = &pi->requested_ps;
- adev->pm.dpm.requested_ps = &pi->requested_rps;
-
-}
-
-/* PP arbiter support needed TODO */
-static void cz_apply_state_adjust_rules(struct amdgpu_device *adev,
- struct amdgpu_ps *new_rps,
- struct amdgpu_ps *old_rps)
-{
- struct cz_ps *ps = cz_get_ps(new_rps);
- struct cz_power_info *pi = cz_get_pi(adev);
- struct amdgpu_clock_and_voltage_limits *limits =
- &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
- /* 10kHz memory clock */
- uint32_t mclk = 0;
-
- ps->force_high = false;
- ps->need_dfs_bypass = true;
- pi->video_start = new_rps->dclk || new_rps->vclk ||
- new_rps->evclk || new_rps->ecclk;
-
- if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) ==
- ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)
- pi->battery_state = true;
- else
- pi->battery_state = false;
-
- if (pi->caps_stable_power_state)
- mclk = limits->mclk;
-
- if (mclk > pi->sys_info.nbp_memory_clock[CZ_NUM_NBPMEMORY_CLOCK - 1])
- ps->force_high = true;
-
-}
-
-static int cz_dpm_enable(struct amdgpu_device *adev)
-{
- const char *chip_name;
- int ret = 0;
-
- /* renable will hang up SMU, so check first */
- if (cz_check_for_dpm_enabled(adev))
- return -EINVAL;
-
- cz_program_voting_clients(adev);
-
- switch (adev->asic_type) {
- case CHIP_CARRIZO:
- chip_name = "carrizo";
- break;
- case CHIP_STONEY:
- chip_name = "stoney";
- break;
- default:
- BUG();
- }
-
-
- ret = cz_start_dpm(adev);
- if (ret) {
- DRM_ERROR("%s DPM enable failed\n", chip_name);
- return -EINVAL;
- }
-
- ret = cz_program_bootup_state(adev);
- if (ret) {
- DRM_ERROR("%s bootup state program failed\n", chip_name);
- return -EINVAL;
- }
-
- ret = cz_enable_didt(adev, true);
- if (ret) {
- DRM_ERROR("%s enable di/dt failed\n", chip_name);
- return -EINVAL;
- }
-
- cz_reset_acp_boot_level(adev);
- cz_update_current_ps(adev, adev->pm.dpm.boot_ps);
-
- return 0;
-}
-
-static int cz_dpm_hw_init(void *handle)
-{
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- int ret = 0;
-
- mutex_lock(&adev->pm.mutex);
-
- /* smu init only needs to be called at startup, not resume.
- * It should be in sw_init, but requires the fw info gathered
- * in sw_init from other IP modules.
- */
- ret = cz_smu_init(adev);
- if (ret) {
- DRM_ERROR("amdgpu: smc initialization failed\n");
- mutex_unlock(&adev->pm.mutex);
- return ret;
- }
-
- /* do the actual fw loading */
- ret = cz_smu_start(adev);
- if (ret) {
- DRM_ERROR("amdgpu: smc start failed\n");
- mutex_unlock(&adev->pm.mutex);
- return ret;
- }
-
- if (!amdgpu_dpm) {
- adev->pm.dpm_enabled = false;
- mutex_unlock(&adev->pm.mutex);
- return ret;
- }
-
- /* cz dpm setup asic */
- cz_dpm_setup_asic(adev);
-
- /* cz dpm enable */
- ret = cz_dpm_enable(adev);
- if (ret)
- adev->pm.dpm_enabled = false;
- else
- adev->pm.dpm_enabled = true;
-
- mutex_unlock(&adev->pm.mutex);
-
- return 0;
-}
-
-static int cz_dpm_disable(struct amdgpu_device *adev)
-{
- int ret = 0;
-
- if (!cz_check_for_dpm_enabled(adev))
- return -EINVAL;
-
- ret = cz_enable_didt(adev, false);
- if (ret) {
- DRM_ERROR("disable di/dt failed\n");
- return -EINVAL;
- }
-
- /* powerup blocks */
- cz_dpm_powergate_uvd(adev, false);
- cz_dpm_powergate_vce(adev, false);
-
- cz_clear_voting_clients(adev);
- cz_stop_dpm(adev);
- cz_update_current_ps(adev, adev->pm.dpm.boot_ps);
-
- return 0;
-}
-
-static int cz_dpm_hw_fini(void *handle)
-{
- int ret = 0;
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
- mutex_lock(&adev->pm.mutex);
-
- /* smu fini only needs to be called at teardown, not suspend.
- * It should be in sw_fini, but we put it here for symmetry
- * with smu init.
- */
- cz_smu_fini(adev);
-
- if (adev->pm.dpm_enabled) {
- ret = cz_dpm_disable(adev);
-
- adev->pm.dpm.current_ps =
- adev->pm.dpm.requested_ps =
- adev->pm.dpm.boot_ps;
- }
-
- adev->pm.dpm_enabled = false;
-
- mutex_unlock(&adev->pm.mutex);
-
- return ret;
-}
-
-static int cz_dpm_suspend(void *handle)
-{
- int ret = 0;
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
- if (adev->pm.dpm_enabled) {
- mutex_lock(&adev->pm.mutex);
-
- ret = cz_dpm_disable(adev);
-
- adev->pm.dpm.current_ps =
- adev->pm.dpm.requested_ps =
- adev->pm.dpm.boot_ps;
-
- mutex_unlock(&adev->pm.mutex);
- }
-
- return ret;
-}
-
-static int cz_dpm_resume(void *handle)
-{
- int ret = 0;
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
- mutex_lock(&adev->pm.mutex);
-
- /* do the actual fw loading */
- ret = cz_smu_start(adev);
- if (ret) {
- DRM_ERROR("amdgpu: smc start failed\n");
- mutex_unlock(&adev->pm.mutex);
- return ret;
- }
-
- if (!amdgpu_dpm) {
- adev->pm.dpm_enabled = false;
- mutex_unlock(&adev->pm.mutex);
- return ret;
- }
-
- /* cz dpm setup asic */
- cz_dpm_setup_asic(adev);
-
- /* cz dpm enable */
- ret = cz_dpm_enable(adev);
- if (ret)
- adev->pm.dpm_enabled = false;
- else
- adev->pm.dpm_enabled = true;
-
- mutex_unlock(&adev->pm.mutex);
- /* upon resume, re-compute the clocks */
- if (adev->pm.dpm_enabled)
- amdgpu_pm_compute_clocks(adev);
-
- return 0;
-}
-
-static int cz_dpm_set_clockgating_state(void *handle,
- enum amd_clockgating_state state)
-{
- return 0;
-}
-
-static int cz_dpm_set_powergating_state(void *handle,
- enum amd_powergating_state state)
-{
- return 0;
-}
-
-static int cz_dpm_get_temperature(struct amdgpu_device *adev)
-{
- int actual_temp = 0;
- uint32_t val = RREG32_SMC(ixTHM_TCON_CUR_TMP);
- uint32_t temp = REG_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP);
-
- if (REG_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP_RANGE_SEL))
- actual_temp = 1000 * ((temp / 8) - 49);
- else
- actual_temp = 1000 * (temp / 8);
-
- return actual_temp;
-}
-
-static int cz_dpm_pre_set_power_state(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct amdgpu_ps requested_ps = *adev->pm.dpm.requested_ps;
- struct amdgpu_ps *new_ps = &requested_ps;
-
- cz_update_requested_ps(adev, new_ps);
- cz_apply_state_adjust_rules(adev, &pi->requested_rps,
- &pi->current_rps);
-
- return 0;
-}
-
-static int cz_dpm_update_sclk_limit(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct amdgpu_clock_and_voltage_limits *limits =
- &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
- uint32_t clock, stable_ps_clock = 0;
-
- clock = pi->sclk_dpm.soft_min_clk;
-
- if (pi->caps_stable_power_state) {
- stable_ps_clock = limits->sclk * 75 / 100;
- if (clock < stable_ps_clock)
- clock = stable_ps_clock;
- }
-
- if (clock != pi->sclk_dpm.soft_min_clk) {
- pi->sclk_dpm.soft_min_clk = clock;
- cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetSclkSoftMin,
- cz_get_sclk_level(adev, clock,
- PPSMC_MSG_SetSclkSoftMin));
- }
-
- if (pi->caps_stable_power_state &&
- pi->sclk_dpm.soft_max_clk != clock) {
- pi->sclk_dpm.soft_max_clk = clock;
- cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetSclkSoftMax,
- cz_get_sclk_level(adev, clock,
- PPSMC_MSG_SetSclkSoftMax));
- } else {
- cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetSclkSoftMax,
- cz_get_sclk_level(adev,
- pi->sclk_dpm.soft_max_clk,
- PPSMC_MSG_SetSclkSoftMax));
- }
-
- return 0;
-}
-
-static int cz_dpm_set_deep_sleep_sclk_threshold(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
-
- if (pi->caps_sclk_ds) {
- cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetMinDeepSleepSclk,
- CZ_MIN_DEEP_SLEEP_SCLK);
- }
-
- return 0;
-}
-
-/* ?? without dal support, is this still needed in setpowerstate list*/
-static int cz_dpm_set_watermark_threshold(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
-
- cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetWatermarkFrequency,
- pi->sclk_dpm.soft_max_clk);
-
- return 0;
-}
-
-static int cz_dpm_enable_nbdpm(struct amdgpu_device *adev)
-{
- int ret = 0;
- struct cz_power_info *pi = cz_get_pi(adev);
-
- /* also depend on dal NBPStateDisableRequired */
- if (pi->nb_dpm_enabled_by_driver && !pi->nb_dpm_enabled) {
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_EnableAllSmuFeatures,
- NB_DPM_MASK);
- if (ret) {
- DRM_ERROR("amdgpu: nb dpm enable failed\n");
- return ret;
- }
- pi->nb_dpm_enabled = true;
- }
-
- return ret;
-}
-
-static void cz_dpm_nbdpm_lm_pstate_enable(struct amdgpu_device *adev,
- bool enable)
-{
- if (enable)
- cz_send_msg_to_smc(adev, PPSMC_MSG_EnableLowMemoryPstate);
- else
- cz_send_msg_to_smc(adev, PPSMC_MSG_DisableLowMemoryPstate);
-
-}
-
-static int cz_dpm_update_low_memory_pstate(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct cz_ps *ps = &pi->requested_ps;
-
- if (pi->sys_info.nb_dpm_enable) {
- if (ps->force_high)
- cz_dpm_nbdpm_lm_pstate_enable(adev, false);
- else
- cz_dpm_nbdpm_lm_pstate_enable(adev, true);
- }
-
- return 0;
-}
-
-/* with dpm enabled */
-static int cz_dpm_set_power_state(struct amdgpu_device *adev)
-{
- cz_dpm_update_sclk_limit(adev);
- cz_dpm_set_deep_sleep_sclk_threshold(adev);
- cz_dpm_set_watermark_threshold(adev);
- cz_dpm_enable_nbdpm(adev);
- cz_dpm_update_low_memory_pstate(adev);
-
- return 0;
-}
-
-static void cz_dpm_post_set_power_state(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct amdgpu_ps *ps = &pi->requested_rps;
-
- cz_update_current_ps(adev, ps);
-}
-
-static int cz_dpm_force_highest(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- int ret = 0;
-
- if (pi->sclk_dpm.soft_min_clk != pi->sclk_dpm.soft_max_clk) {
- pi->sclk_dpm.soft_min_clk =
- pi->sclk_dpm.soft_max_clk;
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetSclkSoftMin,
- cz_get_sclk_level(adev,
- pi->sclk_dpm.soft_min_clk,
- PPSMC_MSG_SetSclkSoftMin));
- if (ret)
- return ret;
- }
-
- return ret;
-}
-
-static int cz_dpm_force_lowest(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- int ret = 0;
-
- if (pi->sclk_dpm.soft_max_clk != pi->sclk_dpm.soft_min_clk) {
- pi->sclk_dpm.soft_max_clk = pi->sclk_dpm.soft_min_clk;
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetSclkSoftMax,
- cz_get_sclk_level(adev,
- pi->sclk_dpm.soft_max_clk,
- PPSMC_MSG_SetSclkSoftMax));
- if (ret)
- return ret;
- }
-
- return ret;
-}
-
-static uint32_t cz_dpm_get_max_sclk_level(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
-
- if (!pi->max_sclk_level) {
- cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxSclkLevel);
- pi->max_sclk_level = cz_get_argument(adev) + 1;
- }
-
- if (pi->max_sclk_level > CZ_MAX_HARDWARE_POWERLEVELS) {
- DRM_ERROR("Invalid max sclk level!\n");
- return -EINVAL;
- }
-
- return pi->max_sclk_level;
-}
-
-static int cz_dpm_unforce_dpm_levels(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct amdgpu_clock_voltage_dependency_table *dep_table =
- &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk;
- uint32_t level = 0;
- int ret = 0;
-
- pi->sclk_dpm.soft_min_clk = dep_table->entries[0].clk;
- level = cz_dpm_get_max_sclk_level(adev) - 1;
- if (level < dep_table->count)
- pi->sclk_dpm.soft_max_clk = dep_table->entries[level].clk;
- else
- pi->sclk_dpm.soft_max_clk =
- dep_table->entries[dep_table->count - 1].clk;
-
- /* get min/max sclk soft value
- * notify SMU to execute */
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetSclkSoftMin,
- cz_get_sclk_level(adev,
- pi->sclk_dpm.soft_min_clk,
- PPSMC_MSG_SetSclkSoftMin));
- if (ret)
- return ret;
-
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetSclkSoftMax,
- cz_get_sclk_level(adev,
- pi->sclk_dpm.soft_max_clk,
- PPSMC_MSG_SetSclkSoftMax));
- if (ret)
- return ret;
-
- DRM_DEBUG("DPM unforce state min=%d, max=%d.\n",
- pi->sclk_dpm.soft_min_clk,
- pi->sclk_dpm.soft_max_clk);
-
- return 0;
-}
-
-static int cz_dpm_uvd_force_highest(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- int ret = 0;
-
- if (pi->uvd_dpm.soft_min_clk != pi->uvd_dpm.soft_max_clk) {
- pi->uvd_dpm.soft_min_clk =
- pi->uvd_dpm.soft_max_clk;
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetUvdSoftMin,
- cz_get_uvd_level(adev,
- pi->uvd_dpm.soft_min_clk,
- PPSMC_MSG_SetUvdSoftMin));
- if (ret)
- return ret;
- }
-
- return ret;
-}
-
-static int cz_dpm_uvd_force_lowest(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- int ret = 0;
-
- if (pi->uvd_dpm.soft_max_clk != pi->uvd_dpm.soft_min_clk) {
- pi->uvd_dpm.soft_max_clk = pi->uvd_dpm.soft_min_clk;
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetUvdSoftMax,
- cz_get_uvd_level(adev,
- pi->uvd_dpm.soft_max_clk,
- PPSMC_MSG_SetUvdSoftMax));
- if (ret)
- return ret;
- }
-
- return ret;
-}
-
-static uint32_t cz_dpm_get_max_uvd_level(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
-
- if (!pi->max_uvd_level) {
- cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxUvdLevel);
- pi->max_uvd_level = cz_get_argument(adev) + 1;
- }
-
- if (pi->max_uvd_level > CZ_MAX_HARDWARE_POWERLEVELS) {
- DRM_ERROR("Invalid max uvd level!\n");
- return -EINVAL;
- }
-
- return pi->max_uvd_level;
-}
-
-static int cz_dpm_unforce_uvd_dpm_levels(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct amdgpu_uvd_clock_voltage_dependency_table *dep_table =
- &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table;
- uint32_t level = 0;
- int ret = 0;
-
- pi->uvd_dpm.soft_min_clk = dep_table->entries[0].vclk;
- level = cz_dpm_get_max_uvd_level(adev) - 1;
- if (level < dep_table->count)
- pi->uvd_dpm.soft_max_clk = dep_table->entries[level].vclk;
- else
- pi->uvd_dpm.soft_max_clk =
- dep_table->entries[dep_table->count - 1].vclk;
-
- /* get min/max sclk soft value
- * notify SMU to execute */
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetUvdSoftMin,
- cz_get_uvd_level(adev,
- pi->uvd_dpm.soft_min_clk,
- PPSMC_MSG_SetUvdSoftMin));
- if (ret)
- return ret;
-
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetUvdSoftMax,
- cz_get_uvd_level(adev,
- pi->uvd_dpm.soft_max_clk,
- PPSMC_MSG_SetUvdSoftMax));
- if (ret)
- return ret;
-
- DRM_DEBUG("DPM uvd unforce state min=%d, max=%d.\n",
- pi->uvd_dpm.soft_min_clk,
- pi->uvd_dpm.soft_max_clk);
-
- return 0;
-}
-
-static int cz_dpm_vce_force_highest(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- int ret = 0;
-
- if (pi->vce_dpm.soft_min_clk != pi->vce_dpm.soft_max_clk) {
- pi->vce_dpm.soft_min_clk =
- pi->vce_dpm.soft_max_clk;
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetEclkSoftMin,
- cz_get_eclk_level(adev,
- pi->vce_dpm.soft_min_clk,
- PPSMC_MSG_SetEclkSoftMin));
- if (ret)
- return ret;
- }
-
- return ret;
-}
-
-static int cz_dpm_vce_force_lowest(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- int ret = 0;
-
- if (pi->vce_dpm.soft_max_clk != pi->vce_dpm.soft_min_clk) {
- pi->vce_dpm.soft_max_clk = pi->vce_dpm.soft_min_clk;
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetEclkSoftMax,
- cz_get_uvd_level(adev,
- pi->vce_dpm.soft_max_clk,
- PPSMC_MSG_SetEclkSoftMax));
- if (ret)
- return ret;
- }
-
- return ret;
-}
-
-static uint32_t cz_dpm_get_max_vce_level(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
-
- if (!pi->max_vce_level) {
- cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxEclkLevel);
- pi->max_vce_level = cz_get_argument(adev) + 1;
- }
-
- if (pi->max_vce_level > CZ_MAX_HARDWARE_POWERLEVELS) {
- DRM_ERROR("Invalid max vce level!\n");
- return -EINVAL;
- }
-
- return pi->max_vce_level;
-}
-
-static int cz_dpm_unforce_vce_dpm_levels(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct amdgpu_vce_clock_voltage_dependency_table *dep_table =
- &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
- uint32_t level = 0;
- int ret = 0;
-
- pi->vce_dpm.soft_min_clk = dep_table->entries[0].ecclk;
- level = cz_dpm_get_max_vce_level(adev) - 1;
- if (level < dep_table->count)
- pi->vce_dpm.soft_max_clk = dep_table->entries[level].ecclk;
- else
- pi->vce_dpm.soft_max_clk =
- dep_table->entries[dep_table->count - 1].ecclk;
-
- /* get min/max sclk soft value
- * notify SMU to execute */
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetEclkSoftMin,
- cz_get_eclk_level(adev,
- pi->vce_dpm.soft_min_clk,
- PPSMC_MSG_SetEclkSoftMin));
- if (ret)
- return ret;
-
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetEclkSoftMax,
- cz_get_eclk_level(adev,
- pi->vce_dpm.soft_max_clk,
- PPSMC_MSG_SetEclkSoftMax));
- if (ret)
- return ret;
-
- DRM_DEBUG("DPM vce unforce state min=%d, max=%d.\n",
- pi->vce_dpm.soft_min_clk,
- pi->vce_dpm.soft_max_clk);
-
- return 0;
-}
-
-static int cz_dpm_force_dpm_level(struct amdgpu_device *adev,
- enum amdgpu_dpm_forced_level level)
-{
- int ret = 0;
-
- switch (level) {
- case AMDGPU_DPM_FORCED_LEVEL_HIGH:
- /* sclk */
- ret = cz_dpm_unforce_dpm_levels(adev);
- if (ret)
- return ret;
- ret = cz_dpm_force_highest(adev);
- if (ret)
- return ret;
-
- /* uvd */
- ret = cz_dpm_unforce_uvd_dpm_levels(adev);
- if (ret)
- return ret;
- ret = cz_dpm_uvd_force_highest(adev);
- if (ret)
- return ret;
-
- /* vce */
- ret = cz_dpm_unforce_vce_dpm_levels(adev);
- if (ret)
- return ret;
- ret = cz_dpm_vce_force_highest(adev);
- if (ret)
- return ret;
- break;
- case AMDGPU_DPM_FORCED_LEVEL_LOW:
- /* sclk */
- ret = cz_dpm_unforce_dpm_levels(adev);
- if (ret)
- return ret;
- ret = cz_dpm_force_lowest(adev);
- if (ret)
- return ret;
-
- /* uvd */
- ret = cz_dpm_unforce_uvd_dpm_levels(adev);
- if (ret)
- return ret;
- ret = cz_dpm_uvd_force_lowest(adev);
- if (ret)
- return ret;
-
- /* vce */
- ret = cz_dpm_unforce_vce_dpm_levels(adev);
- if (ret)
- return ret;
- ret = cz_dpm_vce_force_lowest(adev);
- if (ret)
- return ret;
- break;
- case AMDGPU_DPM_FORCED_LEVEL_AUTO:
- /* sclk */
- ret = cz_dpm_unforce_dpm_levels(adev);
- if (ret)
- return ret;
-
- /* uvd */
- ret = cz_dpm_unforce_uvd_dpm_levels(adev);
- if (ret)
- return ret;
-
- /* vce */
- ret = cz_dpm_unforce_vce_dpm_levels(adev);
- if (ret)
- return ret;
- break;
- default:
- break;
- }
-
- adev->pm.dpm.forced_level = level;
-
- return ret;
-}
-
-/* fix me, display configuration change lists here
- * mostly dal related*/
-static void cz_dpm_display_configuration_changed(struct amdgpu_device *adev)
-{
-}
-
-static uint32_t cz_dpm_get_sclk(struct amdgpu_device *adev, bool low)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct cz_ps *requested_state = cz_get_ps(&pi->requested_rps);
-
- if (low)
- return requested_state->levels[0].sclk;
- else
- return requested_state->levels[requested_state->num_levels - 1].sclk;
-
-}
-
-static uint32_t cz_dpm_get_mclk(struct amdgpu_device *adev, bool low)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
-
- return pi->sys_info.bootup_uma_clk;
-}
-
-static int cz_enable_uvd_dpm(struct amdgpu_device *adev, bool enable)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- int ret = 0;
-
- if (enable && pi->caps_uvd_dpm ) {
- pi->dpm_flags |= DPMFlags_UVD_Enabled;
- DRM_DEBUG("UVD DPM Enabled.\n");
-
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_EnableAllSmuFeatures, UVD_DPM_MASK);
- } else {
- pi->dpm_flags &= ~DPMFlags_UVD_Enabled;
- DRM_DEBUG("UVD DPM Stopped\n");
-
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_DisableAllSmuFeatures, UVD_DPM_MASK);
- }
-
- return ret;
-}
-
-static int cz_update_uvd_dpm(struct amdgpu_device *adev, bool gate)
-{
- return cz_enable_uvd_dpm(adev, !gate);
-}
-
-
-static void cz_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- int ret;
-
- if (pi->uvd_power_gated == gate)
- return;
-
- pi->uvd_power_gated = gate;
-
- if (gate) {
- if (pi->caps_uvd_pg) {
- ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
- AMD_CG_STATE_GATE);
- if (ret) {
- DRM_ERROR("UVD DPM Power Gating failed to set clockgating state\n");
- return;
- }
-
- /* shutdown the UVD block */
- ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
- AMD_PG_STATE_GATE);
-
- if (ret) {
- DRM_ERROR("UVD DPM Power Gating failed to set powergating state\n");
- return;
- }
- }
- cz_update_uvd_dpm(adev, gate);
- if (pi->caps_uvd_pg) {
- /* power off the UVD block */
- ret = cz_send_msg_to_smc(adev, PPSMC_MSG_UVDPowerOFF);
- if (ret) {
- DRM_ERROR("UVD DPM Power Gating failed to send SMU PowerOFF message\n");
- return;
- }
- }
- } else {
- if (pi->caps_uvd_pg) {
- /* power on the UVD block */
- if (pi->uvd_dynamic_pg)
- ret = cz_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_UVDPowerON, 1);
- else
- ret = cz_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_UVDPowerON, 0);
-
- if (ret) {
- DRM_ERROR("UVD DPM Power Gating Failed to send SMU PowerON message\n");
- return;
- }
-
- /* re-init the UVD block */
- ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
- AMD_PG_STATE_UNGATE);
-
- if (ret) {
- DRM_ERROR("UVD DPM Power Gating Failed to set powergating state\n");
- return;
- }
-
- ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
- AMD_CG_STATE_UNGATE);
- if (ret) {
- DRM_ERROR("UVD DPM Power Gating Failed to set clockgating state\n");
- return;
- }
- }
- cz_update_uvd_dpm(adev, gate);
- }
-}
-
-static int cz_enable_vce_dpm(struct amdgpu_device *adev, bool enable)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- int ret = 0;
-
- if (enable && pi->caps_vce_dpm) {
- pi->dpm_flags |= DPMFlags_VCE_Enabled;
- DRM_DEBUG("VCE DPM Enabled.\n");
-
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_EnableAllSmuFeatures, VCE_DPM_MASK);
-
- } else {
- pi->dpm_flags &= ~DPMFlags_VCE_Enabled;
- DRM_DEBUG("VCE DPM Stopped\n");
-
- ret = cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_DisableAllSmuFeatures, VCE_DPM_MASK);
- }
-
- return ret;
-}
-
-static int cz_update_vce_dpm(struct amdgpu_device *adev)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
- struct amdgpu_vce_clock_voltage_dependency_table *table =
- &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
-
- /* Stable Pstate is enabled and we need to set the VCE DPM to highest level */
- if (pi->caps_stable_power_state) {
- pi->vce_dpm.hard_min_clk = table->entries[table->count-1].ecclk;
- } else { /* non-stable p-state cases. without vce.Arbiter.EcclkHardMin */
- /* leave it as set by user */
- /*pi->vce_dpm.hard_min_clk = table->entries[0].ecclk;*/
- }
-
- cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetEclkHardMin,
- cz_get_eclk_level(adev,
- pi->vce_dpm.hard_min_clk,
- PPSMC_MSG_SetEclkHardMin));
- return 0;
-}
-
-static void cz_dpm_powergate_vce(struct amdgpu_device *adev, bool gate)
-{
- struct cz_power_info *pi = cz_get_pi(adev);
-
- if (pi->caps_vce_pg) {
- if (pi->vce_power_gated != gate) {
- if (gate) {
- /* disable clockgating so we can properly shut down the block */
- amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
- AMD_CG_STATE_UNGATE);
- /* shutdown the VCE block */
- amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
- AMD_PG_STATE_GATE);
-
- cz_enable_vce_dpm(adev, false);
- cz_send_msg_to_smc(adev, PPSMC_MSG_VCEPowerOFF);
- pi->vce_power_gated = true;
- } else {
- cz_send_msg_to_smc(adev, PPSMC_MSG_VCEPowerON);
- pi->vce_power_gated = false;
-
- /* re-init the VCE block */
- amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
- AMD_PG_STATE_UNGATE);
- /* enable clockgating. hw will dynamically gate/ungate clocks on the fly */
- amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
- AMD_CG_STATE_GATE);
-
- cz_update_vce_dpm(adev);
- cz_enable_vce_dpm(adev, true);
- }
- } else {
- if (! pi->vce_power_gated) {
- cz_update_vce_dpm(adev);
- }
- }
- } else { /*pi->caps_vce_pg*/
- pi->vce_power_gated = gate;
- cz_update_vce_dpm(adev);
- cz_enable_vce_dpm(adev, !gate);
- }
-}
-
-static int cz_check_state_equal(struct amdgpu_device *adev,
- struct amdgpu_ps *cps,
- struct amdgpu_ps *rps,
- bool *equal)
-{
- if (equal == NULL)
- return -EINVAL;
-
- *equal = false;
- return 0;
-}
-
-const struct amd_ip_funcs cz_dpm_ip_funcs = {
- .name = "cz_dpm",
- .early_init = cz_dpm_early_init,
- .late_init = cz_dpm_late_init,
- .sw_init = cz_dpm_sw_init,
- .sw_fini = cz_dpm_sw_fini,
- .hw_init = cz_dpm_hw_init,
- .hw_fini = cz_dpm_hw_fini,
- .suspend = cz_dpm_suspend,
- .resume = cz_dpm_resume,
- .is_idle = NULL,
- .wait_for_idle = NULL,
- .soft_reset = NULL,
- .set_clockgating_state = cz_dpm_set_clockgating_state,
- .set_powergating_state = cz_dpm_set_powergating_state,
-};
-
-static const struct amdgpu_dpm_funcs cz_dpm_funcs = {
- .get_temperature = cz_dpm_get_temperature,
- .pre_set_power_state = cz_dpm_pre_set_power_state,
- .set_power_state = cz_dpm_set_power_state,
- .post_set_power_state = cz_dpm_post_set_power_state,
- .display_configuration_changed = cz_dpm_display_configuration_changed,
- .get_sclk = cz_dpm_get_sclk,
- .get_mclk = cz_dpm_get_mclk,
- .print_power_state = cz_dpm_print_power_state,
- .debugfs_print_current_performance_level =
- cz_dpm_debugfs_print_current_performance_level,
- .force_performance_level = cz_dpm_force_dpm_level,
- .vblank_too_short = NULL,
- .powergate_uvd = cz_dpm_powergate_uvd,
- .powergate_vce = cz_dpm_powergate_vce,
- .check_state_equal = cz_check_state_equal,
-};
-
-static void cz_dpm_set_funcs(struct amdgpu_device *adev)
-{
- if (NULL == adev->pm.funcs)
- adev->pm.funcs = &cz_dpm_funcs;
-}
-
-const struct amdgpu_ip_block_version cz_dpm_ip_block =
-{
- .type = AMD_IP_BLOCK_TYPE_SMC,
- .major = 8,
- .minor = 0,
- .rev = 0,
- .funcs = &cz_dpm_ip_funcs,
-};
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.h b/drivers/gpu/drm/amd/amdgpu/cz_dpm.h
deleted file mode 100644
index 5df8c1f..0000000
--- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.h
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * 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 __CZ_DPM_H__
-#define __CZ_DPM_H__
-
-#include "smu8_fusion.h"
-
-#define CZ_AT_DFLT 30
-#define CZ_NUM_NBPSTATES 4
-#define CZ_NUM_NBPMEMORY_CLOCK 2
-#define CZ_MAX_HARDWARE_POWERLEVELS 8
-#define CZ_MAX_DISPLAY_CLOCK_LEVEL 8
-#define CZ_MAX_DISPLAYPHY_IDS 10
-
-#define PPCZ_VOTINGRIGHTSCLIENTS_DFLT0 0x3FFFC102
-
-#define SMC_RAM_END 0x40000
-
-#define DPMFlags_SCLK_Enabled 0x00000001
-#define DPMFlags_UVD_Enabled 0x00000002
-#define DPMFlags_VCE_Enabled 0x00000004
-#define DPMFlags_ACP_Enabled 0x00000008
-#define DPMFlags_ForceHighestValid 0x40000000
-#define DPMFlags_Debug 0x80000000
-
-/* Do not change the following, it is also defined in SMU8.h */
-#define SMU_EnabledFeatureScoreboard_AcpDpmOn 0x00000001
-#define SMU_EnabledFeatureScoreboard_SclkDpmOn 0x00200000
-#define SMU_EnabledFeatureScoreboard_UvdDpmOn 0x00800000
-#define SMU_EnabledFeatureScoreboard_VceDpmOn 0x01000000
-
-/* temporary solution to SetMinDeepSleepSclk
- * should indicate by display adaptor
- * 10k Hz unit*/
-#define CZ_MIN_DEEP_SLEEP_SCLK 800
-
-enum cz_pt_config_reg_type {
- CZ_CONFIGREG_MMR = 0,
- CZ_CONFIGREG_SMC_IND,
- CZ_CONFIGREG_DIDT_IND,
- CZ_CONFIGREG_CACHE,
- CZ_CONFIGREG_MAX
-};
-
-struct cz_pt_config_reg {
- uint32_t offset;
- uint32_t mask;
- uint32_t shift;
- uint32_t value;
- enum cz_pt_config_reg_type type;
-};
-
-struct cz_dpm_entry {
- uint32_t soft_min_clk;
- uint32_t hard_min_clk;
- uint32_t soft_max_clk;
- uint32_t hard_max_clk;
-};
-
-struct cz_pl {
- uint32_t sclk;
- uint8_t vddc_index;
- uint8_t ds_divider_index;
- uint8_t ss_divider_index;
- uint8_t allow_gnb_slow;
- uint8_t force_nbp_state;
- uint8_t display_wm;
- uint8_t vce_wm;
-};
-
-struct cz_ps {
- struct cz_pl levels[CZ_MAX_HARDWARE_POWERLEVELS];
- uint32_t num_levels;
- bool need_dfs_bypass;
- uint8_t dpm0_pg_nb_ps_lo;
- uint8_t dpm0_pg_nb_ps_hi;
- uint8_t dpmx_nb_ps_lo;
- uint8_t dpmx_nb_ps_hi;
- bool force_high;
-};
-
-struct cz_displayphy_entry {
- uint8_t phy_present;
- uint8_t active_lane_mapping;
- uint8_t display_conf_type;
- uint8_t num_active_lanes;
-};
-
-struct cz_displayphy_info {
- bool phy_access_initialized;
- struct cz_displayphy_entry entries[CZ_MAX_DISPLAYPHY_IDS];
-};
-
-struct cz_sys_info {
- uint32_t bootup_uma_clk;
- uint32_t bootup_sclk;
- uint32_t dentist_vco_freq;
- uint32_t nb_dpm_enable;
- uint32_t nbp_memory_clock[CZ_NUM_NBPMEMORY_CLOCK];
- uint32_t nbp_n_clock[CZ_NUM_NBPSTATES];
- uint8_t nbp_voltage_index[CZ_NUM_NBPSTATES];
- uint32_t display_clock[CZ_MAX_DISPLAY_CLOCK_LEVEL];
- uint16_t bootup_nb_voltage_index;
- uint8_t htc_tmp_lmt;
- uint8_t htc_hyst_lmt;
- uint32_t uma_channel_number;
-};
-
-struct cz_power_info {
- uint32_t active_target[CZ_MAX_HARDWARE_POWERLEVELS];
- struct cz_sys_info sys_info;
- struct cz_pl boot_pl;
- bool disable_nb_ps3_in_battery;
- bool battery_state;
- uint32_t lowest_valid;
- uint32_t highest_valid;
- uint16_t high_voltage_threshold;
- /* smc offsets */
- uint32_t sram_end;
- uint32_t dpm_table_start;
- uint32_t soft_regs_start;
- /* dpm SMU tables */
- uint8_t uvd_level_count;
- uint8_t vce_level_count;
- uint8_t acp_level_count;
- uint32_t fps_high_threshold;
- uint32_t fps_low_threshold;
- /* dpm table */
- uint32_t dpm_flags;
- struct cz_dpm_entry sclk_dpm;
- struct cz_dpm_entry uvd_dpm;
- struct cz_dpm_entry vce_dpm;
- struct cz_dpm_entry acp_dpm;
-
- uint8_t uvd_boot_level;
- uint8_t uvd_interval;
- uint8_t vce_boot_level;
- uint8_t vce_interval;
- uint8_t acp_boot_level;
- uint8_t acp_interval;
-
- uint8_t graphics_boot_level;
- uint8_t graphics_interval;
- uint8_t graphics_therm_throttle_enable;
- uint8_t graphics_voltage_change_enable;
- uint8_t graphics_clk_slow_enable;
- uint8_t graphics_clk_slow_divider;
-
- uint32_t low_sclk_interrupt_threshold;
- bool uvd_power_gated;
- bool vce_power_gated;
- bool acp_power_gated;
-
- uint32_t active_process_mask;
-
- uint32_t mgcg_cgtt_local0;
- uint32_t mgcg_cgtt_local1;
- uint32_t clock_slow_down_step;
- uint32_t skip_clock_slow_down;
- bool enable_nb_ps_policy;
- uint32_t voting_clients;
- uint32_t voltage_drop_threshold;
- uint32_t gfx_pg_threshold;
- uint32_t max_sclk_level;
- uint32_t max_uvd_level;
- uint32_t max_vce_level;
- /* flags */
- bool didt_enabled;
- bool video_start;
- bool cac_enabled;
- bool bapm_enabled;
- bool nb_dpm_enabled_by_driver;
- bool nb_dpm_enabled;
- bool auto_thermal_throttling_enabled;
- bool dpm_enabled;
- bool need_pptable_upload;
- /* caps */
- bool caps_cac;
- bool caps_power_containment;
- bool caps_sq_ramping;
- bool caps_db_ramping;
- bool caps_td_ramping;
- bool caps_tcp_ramping;
- bool caps_sclk_throttle_low_notification;
- bool caps_fps;
- bool caps_uvd_dpm;
- bool caps_uvd_pg;
- bool caps_vce_dpm;
- bool caps_vce_pg;
- bool caps_acp_dpm;
- bool caps_acp_pg;
- bool caps_stable_power_state;
- bool caps_enable_dfs_bypass;
- bool caps_sclk_ds;
- bool caps_voltage_island;
- /* power state */
- struct amdgpu_ps current_rps;
- struct cz_ps current_ps;
- struct amdgpu_ps requested_rps;
- struct cz_ps requested_ps;
-
- bool uvd_power_down;
- bool vce_power_down;
- bool acp_power_down;
-
- bool uvd_dynamic_pg;
-};
-
-/* cz_smc.c */
-uint32_t cz_get_argument(struct amdgpu_device *adev);
-int cz_send_msg_to_smc(struct amdgpu_device *adev, uint16_t msg);
-int cz_send_msg_to_smc_with_parameter(struct amdgpu_device *adev,
- uint16_t msg, uint32_t parameter);
-int cz_read_smc_sram_dword(struct amdgpu_device *adev,
- uint32_t smc_address, uint32_t *value, uint32_t limit);
-int cz_smu_upload_pptable(struct amdgpu_device *adev);
-int cz_smu_download_pptable(struct amdgpu_device *adev, void **table);
-#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_smc.c b/drivers/gpu/drm/amd/amdgpu/cz_smc.c
deleted file mode 100644
index aed7033..0000000
--- a/drivers/gpu/drm/amd/amdgpu/cz_smc.c
+++ /dev/null
@@ -1,995 +0,0 @@
-/*
- * 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 <linux/firmware.h>
-#include "drmP.h"
-#include "amdgpu.h"
-#include "smu8.h"
-#include "smu8_fusion.h"
-#include "cz_ppsmc.h"
-#include "cz_smumgr.h"
-#include "smu_ucode_xfer_cz.h"
-#include "amdgpu_ucode.h"
-#include "cz_dpm.h"
-#include "vi_dpm.h"
-
-#include "smu/smu_8_0_d.h"
-#include "smu/smu_8_0_sh_mask.h"
-#include "gca/gfx_8_0_d.h"
-#include "gca/gfx_8_0_sh_mask.h"
-
-uint32_t cz_get_argument(struct amdgpu_device *adev)
-{
- return RREG32(mmSMU_MP1_SRBM2P_ARG_0);
-}
-
-static struct cz_smu_private_data *cz_smu_get_priv(struct amdgpu_device *adev)
-{
- struct cz_smu_private_data *priv =
- (struct cz_smu_private_data *)(adev->smu.priv);
-
- return priv;
-}
-
-static int cz_send_msg_to_smc_async(struct amdgpu_device *adev, u16 msg)
-{
- int i;
- u32 content = 0, tmp;
-
- for (i = 0; i < adev->usec_timeout; i++) {
- tmp = REG_GET_FIELD(RREG32(mmSMU_MP1_SRBM2P_RESP_0),
- SMU_MP1_SRBM2P_RESP_0, CONTENT);
- if (content != tmp)
- break;
- udelay(1);
- }
-
- /* timeout means wrong logic*/
- if (i == adev->usec_timeout)
- return -EINVAL;
-
- WREG32(mmSMU_MP1_SRBM2P_RESP_0, 0);
- WREG32(mmSMU_MP1_SRBM2P_MSG_0, msg);
-
- return 0;
-}
-
-int cz_send_msg_to_smc(struct amdgpu_device *adev, u16 msg)
-{
- int i;
- u32 content = 0, tmp = 0;
-
- if (cz_send_msg_to_smc_async(adev, msg))
- return -EINVAL;
-
- for (i = 0; i < adev->usec_timeout; i++) {
- tmp = REG_GET_FIELD(RREG32(mmSMU_MP1_SRBM2P_RESP_0),
- SMU_MP1_SRBM2P_RESP_0, CONTENT);
- if (content != tmp)
- break;
- udelay(1);
- }
-
- /* timeout means wrong logic*/
- if (i == adev->usec_timeout)
- return -EINVAL;
-
- if (PPSMC_Result_OK != tmp) {
- dev_err(adev->dev, "SMC Failed to send Message.\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-int cz_send_msg_to_smc_with_parameter(struct amdgpu_device *adev,
- u16 msg, u32 parameter)
-{
- WREG32(mmSMU_MP1_SRBM2P_ARG_0, parameter);
- return cz_send_msg_to_smc(adev, msg);
-}
-
-static int cz_set_smc_sram_address(struct amdgpu_device *adev,
- u32 smc_address, u32 limit)
-{
- if (smc_address & 3)
- return -EINVAL;
- if ((smc_address + 3) > limit)
- return -EINVAL;
-
- WREG32(mmMP0PUB_IND_INDEX_0, SMN_MP1_SRAM_START_ADDR + smc_address);
-
- return 0;
-}
-
-int cz_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address,
- u32 *value, u32 limit)
-{
- int ret;
-
- ret = cz_set_smc_sram_address(adev, smc_address, limit);
- if (ret)
- return ret;
-
- *value = RREG32(mmMP0PUB_IND_DATA_0);
-
- return 0;
-}
-
-static int cz_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address,
- u32 value, u32 limit)
-{
- int ret;
-
- ret = cz_set_smc_sram_address(adev, smc_address, limit);
- if (ret)
- return ret;
-
- WREG32(mmMP0PUB_IND_DATA_0, value);
-
- return 0;
-}
-
-static int cz_smu_request_load_fw(struct amdgpu_device *adev)
-{
- struct cz_smu_private_data *priv = cz_smu_get_priv(adev);
-
- uint32_t smc_addr = SMU8_FIRMWARE_HEADER_LOCATION +
- offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus);
-
- cz_write_smc_sram_dword(adev, smc_addr, 0, smc_addr + 4);
-
- /*prepare toc buffers*/
- cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_DriverDramAddrHi,
- priv->toc_buffer.mc_addr_high);
- cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_DriverDramAddrLo,
- priv->toc_buffer.mc_addr_low);
- cz_send_msg_to_smc(adev, PPSMC_MSG_InitJobs);
-
- /*execute jobs*/
- cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_ExecuteJob,
- priv->toc_entry_aram);
-
- cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_ExecuteJob,
- priv->toc_entry_power_profiling_index);
-
- cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_ExecuteJob,
- priv->toc_entry_initialize_index);
-
- return 0;
-}
-
-/*
- *Check if the FW has been loaded, SMU will not return if loading
- *has not finished.
- */
-static int cz_smu_check_fw_load_finish(struct amdgpu_device *adev,
- uint32_t fw_mask)
-{
- int i;
- uint32_t index = SMN_MP1_SRAM_START_ADDR +
- SMU8_FIRMWARE_HEADER_LOCATION +
- offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus);
-
- WREG32(mmMP0PUB_IND_INDEX, index);
-
- for (i = 0; i < adev->usec_timeout; i++) {
- if (fw_mask == (RREG32(mmMP0PUB_IND_DATA) & fw_mask))
- break;
- udelay(1);
- }
-
- if (i >= adev->usec_timeout) {
- dev_err(adev->dev,
- "SMU check loaded firmware failed, expecting 0x%x, getting 0x%x",
- fw_mask, RREG32(mmMP0PUB_IND_DATA));
- return -EINVAL;
- }
-
- return 0;
-}
-
-/*
- * interfaces for different ip blocks to check firmware loading status
- * 0 for success otherwise failed
- */
-static int cz_smu_check_finished(struct amdgpu_device *adev,
- enum AMDGPU_UCODE_ID id)
-{
- switch (id) {
- case AMDGPU_UCODE_ID_SDMA0:
- if (adev->smu.fw_flags & AMDGPU_SDMA0_UCODE_LOADED)
- return 0;
- break;
- case AMDGPU_UCODE_ID_SDMA1:
- if (adev->smu.fw_flags & AMDGPU_SDMA1_UCODE_LOADED)
- return 0;
- break;
- case AMDGPU_UCODE_ID_CP_CE:
- if (adev->smu.fw_flags & AMDGPU_CPCE_UCODE_LOADED)
- return 0;
- break;
- case AMDGPU_UCODE_ID_CP_PFP:
- if (adev->smu.fw_flags & AMDGPU_CPPFP_UCODE_LOADED)
- return 0;
- case AMDGPU_UCODE_ID_CP_ME:
- if (adev->smu.fw_flags & AMDGPU_CPME_UCODE_LOADED)
- return 0;
- break;
- case AMDGPU_UCODE_ID_CP_MEC1:
- if (adev->smu.fw_flags & AMDGPU_CPMEC1_UCODE_LOADED)
- return 0;
- break;
- case AMDGPU_UCODE_ID_CP_MEC2:
- if (adev->smu.fw_flags & AMDGPU_CPMEC2_UCODE_LOADED)
- return 0;
- break;
- case AMDGPU_UCODE_ID_RLC_G:
- if (adev->smu.fw_flags & AMDGPU_CPRLC_UCODE_LOADED)
- return 0;
- break;
- case AMDGPU_UCODE_ID_MAXIMUM:
- default:
- break;
- }
-
- return 1;
-}
-
-static int cz_load_mec_firmware(struct amdgpu_device *adev)
-{
- struct amdgpu_firmware_info *ucode =
- &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC1];
- uint32_t reg_data;
- uint32_t tmp;
-
- if (ucode->fw == NULL)
- return -EINVAL;
-
- /* Disable MEC parsing/prefetching */
- tmp = RREG32(mmCP_MEC_CNTL);
- tmp = REG_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME1_HALT, 1);
- tmp = REG_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME2_HALT, 1);
- WREG32(mmCP_MEC_CNTL, tmp);
-
- tmp = RREG32(mmCP_CPC_IC_BASE_CNTL);
- tmp = REG_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, VMID, 0);
- tmp = REG_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, ATC, 0);
- tmp = REG_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0);
- tmp = REG_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, MTYPE, 1);
- WREG32(mmCP_CPC_IC_BASE_CNTL, tmp);
-
- reg_data = lower_32_bits(ucode->mc_addr) &
- REG_FIELD_MASK(CP_CPC_IC_BASE_LO, IC_BASE_LO);
- WREG32(mmCP_CPC_IC_BASE_LO, reg_data);
-
- reg_data = upper_32_bits(ucode->mc_addr) &
- REG_FIELD_MASK(CP_CPC_IC_BASE_HI, IC_BASE_HI);
- WREG32(mmCP_CPC_IC_BASE_HI, reg_data);
-
- return 0;
-}
-
-int cz_smu_start(struct amdgpu_device *adev)
-{
- int ret = 0;
-
- uint32_t fw_to_check = UCODE_ID_RLC_G_MASK |
- UCODE_ID_SDMA0_MASK |
- UCODE_ID_SDMA1_MASK |
- UCODE_ID_CP_CE_MASK |
- UCODE_ID_CP_ME_MASK |
- UCODE_ID_CP_PFP_MASK |
- UCODE_ID_CP_MEC_JT1_MASK |
- UCODE_ID_CP_MEC_JT2_MASK;
-
- if (adev->asic_type == CHIP_STONEY)
- fw_to_check &= ~(UCODE_ID_SDMA1_MASK | UCODE_ID_CP_MEC_JT2_MASK);
-
- cz_smu_request_load_fw(adev);
- ret = cz_smu_check_fw_load_finish(adev, fw_to_check);
- if (ret)
- return ret;
-
- /* manually load MEC firmware for CZ */
- if (adev->asic_type == CHIP_CARRIZO || adev->asic_type == CHIP_STONEY) {
- ret = cz_load_mec_firmware(adev);
- if (ret) {
- dev_err(adev->dev, "(%d) Mec Firmware load failed\n", ret);
- return ret;
- }
- }
-
- /* setup fw load flag */
- adev->smu.fw_flags = AMDGPU_SDMA0_UCODE_LOADED |
- AMDGPU_SDMA1_UCODE_LOADED |
- AMDGPU_CPCE_UCODE_LOADED |
- AMDGPU_CPPFP_UCODE_LOADED |
- AMDGPU_CPME_UCODE_LOADED |
- AMDGPU_CPMEC1_UCODE_LOADED |
- AMDGPU_CPMEC2_UCODE_LOADED |
- AMDGPU_CPRLC_UCODE_LOADED;
-
- if (adev->asic_type == CHIP_STONEY)
- adev->smu.fw_flags &= ~(AMDGPU_SDMA1_UCODE_LOADED | AMDGPU_CPMEC2_UCODE_LOADED);
-
- return ret;
-}
-
-static uint32_t cz_convert_fw_type(uint32_t fw_type)
-{
- enum AMDGPU_UCODE_ID result = AMDGPU_UCODE_ID_MAXIMUM;
-
- switch (fw_type) {
- case UCODE_ID_SDMA0:
- result = AMDGPU_UCODE_ID_SDMA0;
- break;
- case UCODE_ID_SDMA1:
- result = AMDGPU_UCODE_ID_SDMA1;
- break;
- case UCODE_ID_CP_CE:
- result = AMDGPU_UCODE_ID_CP_CE;
- break;
- case UCODE_ID_CP_PFP:
- result = AMDGPU_UCODE_ID_CP_PFP;
- break;
- case UCODE_ID_CP_ME:
- result = AMDGPU_UCODE_ID_CP_ME;
- break;
- case UCODE_ID_CP_MEC_JT1:
- case UCODE_ID_CP_MEC_JT2:
- result = AMDGPU_UCODE_ID_CP_MEC1;
- break;
- case UCODE_ID_RLC_G:
- result = AMDGPU_UCODE_ID_RLC_G;
- break;
- default:
- DRM_ERROR("UCode type is out of range!");
- }
-
- return result;
-}
-
-static uint8_t cz_smu_translate_firmware_enum_to_arg(
- enum cz_scratch_entry firmware_enum)
-{
- uint8_t ret = 0;
-
- switch (firmware_enum) {
- case CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0:
- ret = UCODE_ID_SDMA0;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1:
- ret = UCODE_ID_SDMA1;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE:
- ret = UCODE_ID_CP_CE;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP:
- ret = UCODE_ID_CP_PFP;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME:
- ret = UCODE_ID_CP_ME;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1:
- ret = UCODE_ID_CP_MEC_JT1;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2:
- ret = UCODE_ID_CP_MEC_JT2;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG:
- ret = UCODE_ID_GMCON_RENG;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G:
- ret = UCODE_ID_RLC_G;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH:
- ret = UCODE_ID_RLC_SCRATCH;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM:
- ret = UCODE_ID_RLC_SRM_ARAM;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM:
- ret = UCODE_ID_RLC_SRM_DRAM;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM:
- ret = UCODE_ID_DMCU_ERAM;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM:
- ret = UCODE_ID_DMCU_IRAM;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING:
- ret = TASK_ARG_INIT_MM_PWR_LOG;
- break;
- case CZ_SCRATCH_ENTRY_DATA_ID_SDMA_HALT:
- case CZ_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING:
- case CZ_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS:
- case CZ_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT:
- case CZ_SCRATCH_ENTRY_DATA_ID_SDMA_START:
- case CZ_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS:
- ret = TASK_ARG_REG_MMIO;
- break;
- case CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE:
- ret = TASK_ARG_INIT_CLK_TABLE;
- break;
- }
-
- return ret;
-}
-
-static int cz_smu_populate_single_firmware_entry(struct amdgpu_device *adev,
- enum cz_scratch_entry firmware_enum,
- struct cz_buffer_entry *entry)
-{
- uint64_t gpu_addr;
- uint32_t data_size;
- uint8_t ucode_id = cz_smu_translate_firmware_enum_to_arg(firmware_enum);
- enum AMDGPU_UCODE_ID id = cz_convert_fw_type(ucode_id);
- struct amdgpu_firmware_info *ucode = &adev->firmware.ucode[id];
- const struct gfx_firmware_header_v1_0 *header;
-
- if (ucode->fw == NULL)
- return -EINVAL;
-
- gpu_addr = ucode->mc_addr;
- header = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
- data_size = le32_to_cpu(header->header.ucode_size_bytes);
-
- if ((firmware_enum == CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1) ||
- (firmware_enum == CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2)) {
- gpu_addr += le32_to_cpu(header->jt_offset) << 2;
- data_size = le32_to_cpu(header->jt_size) << 2;
- }
-
- entry->mc_addr_low = lower_32_bits(gpu_addr);
- entry->mc_addr_high = upper_32_bits(gpu_addr);
- entry->data_size = data_size;
- entry->firmware_ID = firmware_enum;
-
- return 0;
-}
-
-static int cz_smu_populate_single_scratch_entry(struct amdgpu_device *adev,
- enum cz_scratch_entry scratch_type,
- uint32_t size_in_byte,
- struct cz_buffer_entry *entry)
-{
- struct cz_smu_private_data *priv = cz_smu_get_priv(adev);
- uint64_t mc_addr = (((uint64_t) priv->smu_buffer.mc_addr_high) << 32) |
- priv->smu_buffer.mc_addr_low;
- mc_addr += size_in_byte;
-
- priv->smu_buffer_used_bytes += size_in_byte;
- entry->data_size = size_in_byte;
- entry->kaddr = priv->smu_buffer.kaddr + priv->smu_buffer_used_bytes;
- entry->mc_addr_low = lower_32_bits(mc_addr);
- entry->mc_addr_high = upper_32_bits(mc_addr);
- entry->firmware_ID = scratch_type;
-
- return 0;
-}
-
-static int cz_smu_populate_single_ucode_load_task(struct amdgpu_device *adev,
- enum cz_scratch_entry firmware_enum,
- bool is_last)
-{
- uint8_t i;
- struct cz_smu_private_data *priv = cz_smu_get_priv(adev);
- struct TOC *toc = (struct TOC *)priv->toc_buffer.kaddr;
- struct SMU_Task *task = &toc->tasks[priv->toc_entry_used_count++];
-
- task->type = TASK_TYPE_UCODE_LOAD;
- task->arg = cz_smu_translate_firmware_enum_to_arg(firmware_enum);
- task->next = is_last ? END_OF_TASK_LIST : priv->toc_entry_used_count;
-
- for (i = 0; i < priv->driver_buffer_length; i++)
- if (priv->driver_buffer[i].firmware_ID == firmware_enum)
- break;
-
- if (i >= priv->driver_buffer_length) {
- dev_err(adev->dev, "Invalid Firmware Type\n");
- return -EINVAL;
- }
-
- task->addr.low = priv->driver_buffer[i].mc_addr_low;
- task->addr.high = priv->driver_buffer[i].mc_addr_high;
- task->size_bytes = priv->driver_buffer[i].data_size;
-
- return 0;
-}
-
-static int cz_smu_populate_single_scratch_task(struct amdgpu_device *adev,
- enum cz_scratch_entry firmware_enum,
- uint8_t type, bool is_last)
-{
- uint8_t i;
- struct cz_smu_private_data *priv = cz_smu_get_priv(adev);
- struct TOC *toc = (struct TOC *)priv->toc_buffer.kaddr;
- struct SMU_Task *task = &toc->tasks[priv->toc_entry_used_count++];
-
- task->type = type;
- task->arg = cz_smu_translate_firmware_enum_to_arg(firmware_enum);
- task->next = is_last ? END_OF_TASK_LIST : priv->toc_entry_used_count;
-
- for (i = 0; i < priv->scratch_buffer_length; i++)
- if (priv->scratch_buffer[i].firmware_ID == firmware_enum)
- break;
-
- if (i >= priv->scratch_buffer_length) {
- dev_err(adev->dev, "Invalid Firmware Type\n");
- return -EINVAL;
- }
-
- task->addr.low = priv->scratch_buffer[i].mc_addr_low;
- task->addr.high = priv->scratch_buffer[i].mc_addr_high;
- task->size_bytes = priv->scratch_buffer[i].data_size;
-
- if (CZ_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS == firmware_enum) {
- struct cz_ih_meta_data *pIHReg_restore =
- (struct cz_ih_meta_data *)priv->scratch_buffer[i].kaddr;
- pIHReg_restore->command =
- METADATA_CMD_MODE0 | METADATA_PERFORM_ON_LOAD;
- }
-
- return 0;
-}
-
-static int cz_smu_construct_toc_for_rlc_aram_save(struct amdgpu_device *adev)
-{
- struct cz_smu_private_data *priv = cz_smu_get_priv(adev);
- priv->toc_entry_aram = priv->toc_entry_used_count;
- cz_smu_populate_single_scratch_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
- TASK_TYPE_UCODE_SAVE, true);
-
- return 0;
-}
-
-static int cz_smu_construct_toc_for_vddgfx_enter(struct amdgpu_device *adev)
-{
- struct cz_smu_private_data *priv = cz_smu_get_priv(adev);
- struct TOC *toc = (struct TOC *)priv->toc_buffer.kaddr;
-
- toc->JobList[JOB_GFX_SAVE] = (uint8_t)priv->toc_entry_used_count;
- cz_smu_populate_single_scratch_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
- TASK_TYPE_UCODE_SAVE, false);
- cz_smu_populate_single_scratch_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
- TASK_TYPE_UCODE_SAVE, true);
-
- return 0;
-}
-
-static int cz_smu_construct_toc_for_vddgfx_exit(struct amdgpu_device *adev)
-{
- struct cz_smu_private_data *priv = cz_smu_get_priv(adev);
- struct TOC *toc = (struct TOC *)priv->toc_buffer.kaddr;
-
- toc->JobList[JOB_GFX_RESTORE] = (uint8_t)priv->toc_entry_used_count;
-
- /* populate ucode */
- if (adev->firmware.smu_load) {
- cz_smu_populate_single_ucode_load_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, false);
- cz_smu_populate_single_ucode_load_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false);
- cz_smu_populate_single_ucode_load_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false);
- cz_smu_populate_single_ucode_load_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
- if (adev->asic_type == CHIP_STONEY) {
- cz_smu_populate_single_ucode_load_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
- } else {
- cz_smu_populate_single_ucode_load_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false);
- }
- cz_smu_populate_single_ucode_load_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, false);
- }
-
- /* populate scratch */
- cz_smu_populate_single_scratch_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
- TASK_TYPE_UCODE_LOAD, false);
- cz_smu_populate_single_scratch_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
- TASK_TYPE_UCODE_LOAD, false);
- cz_smu_populate_single_scratch_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
- TASK_TYPE_UCODE_LOAD, true);
-
- return 0;
-}
-
-static int cz_smu_construct_toc_for_power_profiling(struct amdgpu_device *adev)
-{
- struct cz_smu_private_data *priv = cz_smu_get_priv(adev);
-
- priv->toc_entry_power_profiling_index = priv->toc_entry_used_count;
-
- cz_smu_populate_single_scratch_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING,
- TASK_TYPE_INITIALIZE, true);
- return 0;
-}
-
-static int cz_smu_construct_toc_for_bootup(struct amdgpu_device *adev)
-{
- struct cz_smu_private_data *priv = cz_smu_get_priv(adev);
-
- priv->toc_entry_initialize_index = priv->toc_entry_used_count;
-
- if (adev->firmware.smu_load) {
- cz_smu_populate_single_ucode_load_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0, false);
- if (adev->asic_type == CHIP_STONEY) {
- cz_smu_populate_single_ucode_load_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0, false);
- } else {
- cz_smu_populate_single_ucode_load_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1, false);
- }
- cz_smu_populate_single_ucode_load_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, false);
- cz_smu_populate_single_ucode_load_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false);
- cz_smu_populate_single_ucode_load_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false);
- cz_smu_populate_single_ucode_load_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
- if (adev->asic_type == CHIP_STONEY) {
- cz_smu_populate_single_ucode_load_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
- } else {
- cz_smu_populate_single_ucode_load_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false);
- }
- cz_smu_populate_single_ucode_load_task(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, true);
- }
-
- return 0;
-}
-
-static int cz_smu_construct_toc_for_clock_table(struct amdgpu_device *adev)
-{
- struct cz_smu_private_data *priv = cz_smu_get_priv(adev);
-
- priv->toc_entry_clock_table = priv->toc_entry_used_count;
-
- cz_smu_populate_single_scratch_task(adev,
- CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE,
- TASK_TYPE_INITIALIZE, true);
-
- return 0;
-}
-
-static int cz_smu_initialize_toc_empty_job_list(struct amdgpu_device *adev)
-{
- int i;
- struct cz_smu_private_data *priv = cz_smu_get_priv(adev);
- struct TOC *toc = (struct TOC *)priv->toc_buffer.kaddr;
-
- for (i = 0; i < NUM_JOBLIST_ENTRIES; i++)
- toc->JobList[i] = (uint8_t)IGNORE_JOB;
-
- return 0;
-}
-
-/*
- * cz smu uninitialization
- */
-int cz_smu_fini(struct amdgpu_device *adev)
-{
- amdgpu_bo_unref(&adev->smu.toc_buf);
- amdgpu_bo_unref(&adev->smu.smu_buf);
- kfree(adev->smu.priv);
- adev->smu.priv = NULL;
- if (adev->firmware.smu_load)
- amdgpu_ucode_fini_bo(adev);
-
- return 0;
-}
-
-int cz_smu_download_pptable(struct amdgpu_device *adev, void **table)
-{
- uint8_t i;
- struct cz_smu_private_data *priv = cz_smu_get_priv(adev);
-
- for (i = 0; i < priv->scratch_buffer_length; i++)
- if (priv->scratch_buffer[i].firmware_ID ==
- CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE)
- break;
-
- if (i >= priv->scratch_buffer_length) {
- dev_err(adev->dev, "Invalid Scratch Type\n");
- return -EINVAL;
- }
-
- *table = (struct SMU8_Fusion_ClkTable *)priv->scratch_buffer[i].kaddr;
-
- /* prepare buffer for pptable */
- cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetClkTableAddrHi,
- priv->scratch_buffer[i].mc_addr_high);
- cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetClkTableAddrLo,
- priv->scratch_buffer[i].mc_addr_low);
- cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_ExecuteJob,
- priv->toc_entry_clock_table);
-
- /* actual downloading */
- cz_send_msg_to_smc(adev, PPSMC_MSG_ClkTableXferToDram);
-
- return 0;
-}
-
-int cz_smu_upload_pptable(struct amdgpu_device *adev)
-{
- uint8_t i;
- struct cz_smu_private_data *priv = cz_smu_get_priv(adev);
-
- for (i = 0; i < priv->scratch_buffer_length; i++)
- if (priv->scratch_buffer[i].firmware_ID ==
- CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE)
- break;
-
- if (i >= priv->scratch_buffer_length) {
- dev_err(adev->dev, "Invalid Scratch Type\n");
- return -EINVAL;
- }
-
- /* prepare SMU */
- cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetClkTableAddrHi,
- priv->scratch_buffer[i].mc_addr_high);
- cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_SetClkTableAddrLo,
- priv->scratch_buffer[i].mc_addr_low);
- cz_send_msg_to_smc_with_parameter(adev,
- PPSMC_MSG_ExecuteJob,
- priv->toc_entry_clock_table);
-
- /* actual uploading */
- cz_send_msg_to_smc(adev, PPSMC_MSG_ClkTableXferToSmu);
-
- return 0;
-}
-
-/*
- * cz smumgr functions initialization
- */
-static const struct amdgpu_smumgr_funcs cz_smumgr_funcs = {
- .check_fw_load_finish = cz_smu_check_finished,
- .request_smu_load_fw = NULL,
- .request_smu_specific_fw = NULL,
-};
-
-/*
- * cz smu initialization
- */
-int cz_smu_init(struct amdgpu_device *adev)
-{
- int ret = -EINVAL;
- uint64_t mc_addr = 0;
- struct amdgpu_bo **toc_buf = &adev->smu.toc_buf;
- struct amdgpu_bo **smu_buf = &adev->smu.smu_buf;
- void *toc_buf_ptr = NULL;
- void *smu_buf_ptr = NULL;
-
- struct cz_smu_private_data *priv =
- kzalloc(sizeof(struct cz_smu_private_data), GFP_KERNEL);
- if (priv == NULL)
- return -ENOMEM;
-
- /* allocate firmware buffers */
- if (adev->firmware.smu_load)
- amdgpu_ucode_init_bo(adev);
-
- adev->smu.priv = priv;
- adev->smu.fw_flags = 0;
- priv->toc_buffer.data_size = 4096;
-
- priv->smu_buffer.data_size =
- ALIGN(UCODE_ID_RLC_SCRATCH_SIZE_BYTE, 32) +
- ALIGN(UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE, 32) +
- ALIGN(UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE, 32) +
- ALIGN(sizeof(struct SMU8_MultimediaPowerLogData), 32) +
- ALIGN(sizeof(struct SMU8_Fusion_ClkTable), 32);
-
- /* prepare toc buffer and smu buffer:
- * 1. create amdgpu_bo for toc buffer and smu buffer
- * 2. pin mc address
- * 3. map kernel virtual address
- */
- ret = amdgpu_bo_create(adev, priv->toc_buffer.data_size, PAGE_SIZE,
- true, AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL,
- toc_buf);
-
- if (ret) {
- dev_err(adev->dev, "(%d) SMC TOC buffer allocation failed\n", ret);
- return ret;
- }
-
- ret = amdgpu_bo_create(adev, priv->smu_buffer.data_size, PAGE_SIZE,
- true, AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL,
- smu_buf);
-
- if (ret) {
- dev_err(adev->dev, "(%d) SMC Internal buffer allocation failed\n", ret);
- return ret;
- }
-
- /* toc buffer reserve/pin/map */
- ret = amdgpu_bo_reserve(adev->smu.toc_buf, false);
- if (ret) {
- amdgpu_bo_unref(&adev->smu.toc_buf);
- dev_err(adev->dev, "(%d) SMC TOC buffer reserve failed\n", ret);
- return ret;
- }
-
- ret = amdgpu_bo_pin(adev->smu.toc_buf, AMDGPU_GEM_DOMAIN_GTT, &mc_addr);
- if (ret) {
- amdgpu_bo_unreserve(adev->smu.toc_buf);
- amdgpu_bo_unref(&adev->smu.toc_buf);
- dev_err(adev->dev, "(%d) SMC TOC buffer pin failed\n", ret);
- return ret;
- }
-
- ret = amdgpu_bo_kmap(*toc_buf, &toc_buf_ptr);
- if (ret)
- goto smu_init_failed;
-
- amdgpu_bo_unreserve(adev->smu.toc_buf);
-
- priv->toc_buffer.mc_addr_low = lower_32_bits(mc_addr);
- priv->toc_buffer.mc_addr_high = upper_32_bits(mc_addr);
- priv->toc_buffer.kaddr = toc_buf_ptr;
-
- /* smu buffer reserve/pin/map */
- ret = amdgpu_bo_reserve(adev->smu.smu_buf, false);
- if (ret) {
- amdgpu_bo_unref(&adev->smu.smu_buf);
- dev_err(adev->dev, "(%d) SMC Internal buffer reserve failed\n", ret);
- return ret;
- }
-
- ret = amdgpu_bo_pin(adev->smu.smu_buf, AMDGPU_GEM_DOMAIN_GTT, &mc_addr);
- if (ret) {
- amdgpu_bo_unreserve(adev->smu.smu_buf);
- amdgpu_bo_unref(&adev->smu.smu_buf);
- dev_err(adev->dev, "(%d) SMC Internal buffer pin failed\n", ret);
- return ret;
- }
-
- ret = amdgpu_bo_kmap(*smu_buf, &smu_buf_ptr);
- if (ret)
- goto smu_init_failed;
-
- amdgpu_bo_unreserve(adev->smu.smu_buf);
-
- priv->smu_buffer.mc_addr_low = lower_32_bits(mc_addr);
- priv->smu_buffer.mc_addr_high = upper_32_bits(mc_addr);
- priv->smu_buffer.kaddr = smu_buf_ptr;
-
- if (adev->firmware.smu_load) {
- if (cz_smu_populate_single_firmware_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0,
- &priv->driver_buffer[priv->driver_buffer_length++]))
- goto smu_init_failed;
-
- if (adev->asic_type == CHIP_STONEY) {
- if (cz_smu_populate_single_firmware_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0,
- &priv->driver_buffer[priv->driver_buffer_length++]))
- goto smu_init_failed;
- } else {
- if (cz_smu_populate_single_firmware_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1,
- &priv->driver_buffer[priv->driver_buffer_length++]))
- goto smu_init_failed;
- }
- if (cz_smu_populate_single_firmware_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE,
- &priv->driver_buffer[priv->driver_buffer_length++]))
- goto smu_init_failed;
- if (cz_smu_populate_single_firmware_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP,
- &priv->driver_buffer[priv->driver_buffer_length++]))
- goto smu_init_failed;
- if (cz_smu_populate_single_firmware_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME,
- &priv->driver_buffer[priv->driver_buffer_length++]))
- goto smu_init_failed;
- if (cz_smu_populate_single_firmware_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1,
- &priv->driver_buffer[priv->driver_buffer_length++]))
- goto smu_init_failed;
- if (adev->asic_type == CHIP_STONEY) {
- if (cz_smu_populate_single_firmware_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1,
- &priv->driver_buffer[priv->driver_buffer_length++]))
- goto smu_init_failed;
- } else {
- if (cz_smu_populate_single_firmware_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2,
- &priv->driver_buffer[priv->driver_buffer_length++]))
- goto smu_init_failed;
- }
- if (cz_smu_populate_single_firmware_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G,
- &priv->driver_buffer[priv->driver_buffer_length++]))
- goto smu_init_failed;
- }
-
- if (cz_smu_populate_single_scratch_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
- UCODE_ID_RLC_SCRATCH_SIZE_BYTE,
- &priv->scratch_buffer[priv->scratch_buffer_length++]))
- goto smu_init_failed;
- if (cz_smu_populate_single_scratch_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
- UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE,
- &priv->scratch_buffer[priv->scratch_buffer_length++]))
- goto smu_init_failed;
- if (cz_smu_populate_single_scratch_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
- UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE,
- &priv->scratch_buffer[priv->scratch_buffer_length++]))
- goto smu_init_failed;
- if (cz_smu_populate_single_scratch_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING,
- sizeof(struct SMU8_MultimediaPowerLogData),
- &priv->scratch_buffer[priv->scratch_buffer_length++]))
- goto smu_init_failed;
- if (cz_smu_populate_single_scratch_entry(adev,
- CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE,
- sizeof(struct SMU8_Fusion_ClkTable),
- &priv->scratch_buffer[priv->scratch_buffer_length++]))
- goto smu_init_failed;
-
- cz_smu_initialize_toc_empty_job_list(adev);
- cz_smu_construct_toc_for_rlc_aram_save(adev);
- cz_smu_construct_toc_for_vddgfx_enter(adev);
- cz_smu_construct_toc_for_vddgfx_exit(adev);
- cz_smu_construct_toc_for_power_profiling(adev);
- cz_smu_construct_toc_for_bootup(adev);
- cz_smu_construct_toc_for_clock_table(adev);
- /* init the smumgr functions */
- adev->smu.smumgr_funcs = &cz_smumgr_funcs;
-
- return 0;
-
-smu_init_failed:
- amdgpu_bo_unref(toc_buf);
- amdgpu_bo_unref(smu_buf);
-
- return ret;
-}
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_smumgr.h b/drivers/gpu/drm/amd/amdgpu/cz_smumgr.h
deleted file mode 100644
index 026342f..0000000
--- a/drivers/gpu/drm/amd/amdgpu/cz_smumgr.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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 __CZ_SMC_H__
-#define __CZ_SMC_H__
-
-#define MAX_NUM_FIRMWARE 8
-#define MAX_NUM_SCRATCH 11
-#define CZ_SCRATCH_SIZE_NONGFX_CLOCKGATING 1024
-#define CZ_SCRATCH_SIZE_NONGFX_GOLDENSETTING 2048
-#define CZ_SCRATCH_SIZE_SDMA_METADATA 1024
-#define CZ_SCRATCH_SIZE_IH ((2*256+1)*4)
-
-enum cz_scratch_entry {
- CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0 = 0,
- CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2,
- CZ_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
- CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM,
- CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM,
- CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING,
- CZ_SCRATCH_ENTRY_DATA_ID_SDMA_HALT,
- CZ_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING,
- CZ_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS,
- CZ_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT,
- CZ_SCRATCH_ENTRY_DATA_ID_SDMA_START,
- CZ_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS,
- CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE
-};
-
-struct cz_buffer_entry {
- uint32_t data_size;
- uint32_t mc_addr_low;
- uint32_t mc_addr_high;
- void *kaddr;
- enum cz_scratch_entry firmware_ID;
-};
-
-struct cz_register_index_data_pair {
- uint32_t offset;
- uint32_t value;
-};
-
-struct cz_ih_meta_data {
- uint32_t command;
- struct cz_register_index_data_pair register_index_value_pair[1];
-};
-
-struct cz_smu_private_data {
- uint8_t driver_buffer_length;
- uint8_t scratch_buffer_length;
- uint16_t toc_entry_used_count;
- uint16_t toc_entry_initialize_index;
- uint16_t toc_entry_power_profiling_index;
- uint16_t toc_entry_aram;
- uint16_t toc_entry_ih_register_restore_task_index;
- uint16_t toc_entry_clock_table;
- uint16_t ih_register_restore_task_size;
- uint16_t smu_buffer_used_bytes;
-
- struct cz_buffer_entry toc_buffer;
- struct cz_buffer_entry smu_buffer;
- struct cz_buffer_entry driver_buffer[MAX_NUM_FIRMWARE];
- struct cz_buffer_entry scratch_buffer[MAX_NUM_SCRATCH];
-};
-
-#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
index ccb5e02..d4452d8 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
@@ -2072,7 +2072,7 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
- switch (target_fb->pixel_format) {
+ switch (target_fb->format->format) {
case DRM_FORMAT_C8:
fb_format = REG_SET_FIELD(0, GRPH_CONTROL, GRPH_DEPTH, 0);
fb_format = REG_SET_FIELD(fb_format, GRPH_CONTROL, GRPH_FORMAT, 0);
@@ -2145,7 +2145,7 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
break;
default:
DRM_ERROR("Unsupported screen format %s\n",
- drm_get_format_name(target_fb->pixel_format, &format_name));
+ drm_get_format_name(target_fb->format->format, &format_name));
return -EINVAL;
}
@@ -2220,7 +2220,7 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(mmGRPH_X_END + amdgpu_crtc->crtc_offset, target_fb->width);
WREG32(mmGRPH_Y_END + amdgpu_crtc->crtc_offset, target_fb->height);
- fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8);
+ fb_pitch_pixels = target_fb->pitches[0] / target_fb->format->cpp[0];
WREG32(mmGRPH_PITCH + amdgpu_crtc->crtc_offset, fb_pitch_pixels);
dce_v10_0_grph_enable(crtc, true);
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
index a7af5b3..5b24e89 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -2056,7 +2056,7 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc,
pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
- switch (target_fb->pixel_format) {
+ switch (target_fb->format->format) {
case DRM_FORMAT_C8:
fb_format = REG_SET_FIELD(0, GRPH_CONTROL, GRPH_DEPTH, 0);
fb_format = REG_SET_FIELD(fb_format, GRPH_CONTROL, GRPH_FORMAT, 0);
@@ -2129,7 +2129,7 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc,
break;
default:
DRM_ERROR("Unsupported screen format %s\n",
- drm_get_format_name(target_fb->pixel_format, &format_name));
+ drm_get_format_name(target_fb->format->format, &format_name));
return -EINVAL;
}
@@ -2204,7 +2204,7 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(mmGRPH_X_END + amdgpu_crtc->crtc_offset, target_fb->width);
WREG32(mmGRPH_Y_END + amdgpu_crtc->crtc_offset, target_fb->height);
- fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8);
+ fb_pitch_pixels = target_fb->pitches[0] / target_fb->format->cpp[0];
WREG32(mmGRPH_PITCH + amdgpu_crtc->crtc_offset, fb_pitch_pixels);
dce_v11_0_grph_enable(crtc, true);
@@ -3737,9 +3737,15 @@ static void dce_v11_0_encoder_add(struct amdgpu_device *adev,
default:
encoder->possible_crtcs = 0x3;
break;
+ case 3:
+ encoder->possible_crtcs = 0x7;
+ break;
case 4:
encoder->possible_crtcs = 0xf;
break;
+ case 5:
+ encoder->possible_crtcs = 0x1f;
+ break;
case 6:
encoder->possible_crtcs = 0x3f;
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
index 39df6a5..809aa94 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
@@ -1501,7 +1501,7 @@ static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc,
amdgpu_bo_get_tiling_flags(abo, &tiling_flags);
amdgpu_bo_unreserve(abo);
- switch (target_fb->pixel_format) {
+ switch (target_fb->format->format) {
case DRM_FORMAT_C8:
fb_format = (GRPH_DEPTH(GRPH_DEPTH_8BPP) |
GRPH_FORMAT(GRPH_FORMAT_INDEXED));
@@ -1567,7 +1567,7 @@ static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc,
break;
default:
DRM_ERROR("Unsupported screen format %s\n",
- drm_get_format_name(target_fb->pixel_format, &format_name));
+ drm_get_format_name(target_fb->format->format, &format_name));
return -EINVAL;
}
@@ -1630,7 +1630,7 @@ static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(mmGRPH_X_END + amdgpu_crtc->crtc_offset, target_fb->width);
WREG32(mmGRPH_Y_END + amdgpu_crtc->crtc_offset, target_fb->height);
- fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8);
+ fb_pitch_pixels = target_fb->pitches[0] / target_fb->format->cpp[0];
WREG32(mmGRPH_PITCH + amdgpu_crtc->crtc_offset, fb_pitch_pixels);
dce_v6_0_grph_enable(crtc, true);
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
index 28102bb..d2590d7 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -1950,7 +1950,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc,
pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
- switch (target_fb->pixel_format) {
+ switch (target_fb->format->format) {
case DRM_FORMAT_C8:
fb_format = ((GRPH_DEPTH_8BPP << GRPH_CONTROL__GRPH_DEPTH__SHIFT) |
(GRPH_FORMAT_INDEXED << GRPH_CONTROL__GRPH_FORMAT__SHIFT));
@@ -2016,7 +2016,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc,
break;
default:
DRM_ERROR("Unsupported screen format %s\n",
- drm_get_format_name(target_fb->pixel_format, &format_name));
+ drm_get_format_name(target_fb->format->format, &format_name));
return -EINVAL;
}
@@ -2079,7 +2079,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(mmGRPH_X_END + amdgpu_crtc->crtc_offset, target_fb->width);
WREG32(mmGRPH_Y_END + amdgpu_crtc->crtc_offset, target_fb->height);
- fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8);
+ fb_pitch_pixels = target_fb->pitches[0] / target_fb->format->cpp[0];
WREG32(mmGRPH_PITCH + amdgpu_crtc->crtc_offset, fb_pitch_pixels);
dce_v8_0_grph_enable(crtc, true);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index b323f5e..2086e7e 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -25,7 +25,7 @@
#include "amdgpu_ih.h"
#include "amdgpu_gfx.h"
#include "amdgpu_ucode.h"
-#include "si/clearstate_si.h"
+#include "clearstate_si.h"
#include "bif/bif_3_0_d.h"
#include "bif/bif_3_0_sh_mask.h"
#include "oss/oss_1_0_d.h"
@@ -1325,21 +1325,19 @@ static u32 gfx_v6_0_create_bitmask(u32 bit_width)
return (u32)(((u64)1 << bit_width) - 1);
}
-static u32 gfx_v6_0_get_rb_disabled(struct amdgpu_device *adev,
- u32 max_rb_num_per_se,
- u32 sh_per_se)
+static u32 gfx_v6_0_get_rb_active_bitmap(struct amdgpu_device *adev)
{
u32 data, mask;
- data = RREG32(mmCC_RB_BACKEND_DISABLE);
- data &= CC_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK;
- data |= RREG32(mmGC_USER_RB_BACKEND_DISABLE);
+ data = RREG32(mmCC_RB_BACKEND_DISABLE) |
+ RREG32(mmGC_USER_RB_BACKEND_DISABLE);
- data >>= CC_RB_BACKEND_DISABLE__BACKEND_DISABLE__SHIFT;
+ data = REG_GET_FIELD(data, GC_USER_RB_BACKEND_DISABLE, BACKEND_DISABLE);
- mask = gfx_v6_0_create_bitmask(max_rb_num_per_se / sh_per_se);
+ mask = gfx_v6_0_create_bitmask(adev->gfx.config.max_backends_per_se/
+ adev->gfx.config.max_sh_per_se);
- return data & mask;
+ return ~data & mask;
}
static void gfx_v6_0_raster_config(struct amdgpu_device *adev, u32 *rconf)
@@ -1468,68 +1466,55 @@ static void gfx_v6_0_write_harvested_raster_configs(struct amdgpu_device *adev,
gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
}
-static void gfx_v6_0_setup_rb(struct amdgpu_device *adev,
- u32 se_num, u32 sh_per_se,
- u32 max_rb_num_per_se)
+static void gfx_v6_0_setup_rb(struct amdgpu_device *adev)
{
int i, j;
- u32 data, mask;
- u32 disabled_rbs = 0;
- u32 enabled_rbs = 0;
+ u32 data;
+ u32 raster_config = 0;
+ u32 active_rbs = 0;
+ u32 rb_bitmap_width_per_sh = adev->gfx.config.max_backends_per_se /
+ adev->gfx.config.max_sh_per_se;
unsigned num_rb_pipes;
mutex_lock(&adev->grbm_idx_mutex);
- for (i = 0; i < se_num; i++) {
- for (j = 0; j < sh_per_se; j++) {
+ for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
+ for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff);
- data = gfx_v6_0_get_rb_disabled(adev, max_rb_num_per_se, sh_per_se);
- disabled_rbs |= data << ((i * sh_per_se + j) * 2);
+ data = gfx_v6_0_get_rb_active_bitmap(adev);
+ active_rbs |= data << ((i * adev->gfx.config.max_sh_per_se + j) *
+ rb_bitmap_width_per_sh);
}
}
gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
- mutex_unlock(&adev->grbm_idx_mutex);
-
- mask = 1;
- for (i = 0; i < max_rb_num_per_se * se_num; i++) {
- if (!(disabled_rbs & mask))
- enabled_rbs |= mask;
- mask <<= 1;
- }
- adev->gfx.config.backend_enable_mask = enabled_rbs;
- adev->gfx.config.num_rbs = hweight32(enabled_rbs);
+ adev->gfx.config.backend_enable_mask = active_rbs;
+ adev->gfx.config.num_rbs = hweight32(active_rbs);
num_rb_pipes = min_t(unsigned, adev->gfx.config.max_backends_per_se *
adev->gfx.config.max_shader_engines, 16);
- mutex_lock(&adev->grbm_idx_mutex);
- for (i = 0; i < se_num; i++) {
- gfx_v6_0_select_se_sh(adev, i, 0xffffffff, 0xffffffff);
- data = 0;
- for (j = 0; j < sh_per_se; j++) {
- switch (enabled_rbs & 3) {
- case 1:
- data |= (RASTER_CONFIG_RB_MAP_0 << (i * sh_per_se + j) * 2);
- break;
- case 2:
- data |= (RASTER_CONFIG_RB_MAP_3 << (i * sh_per_se + j) * 2);
- break;
- case 3:
- default:
- data |= (RASTER_CONFIG_RB_MAP_2 << (i * sh_per_se + j) * 2);
- break;
- }
- enabled_rbs >>= 2;
- }
- gfx_v6_0_raster_config(adev, &data);
+ gfx_v6_0_raster_config(adev, &raster_config);
- if (!adev->gfx.config.backend_enable_mask ||
- adev->gfx.config.num_rbs >= num_rb_pipes)
- WREG32(mmPA_SC_RASTER_CONFIG, data);
- else
- gfx_v6_0_write_harvested_raster_configs(adev, data,
- adev->gfx.config.backend_enable_mask,
- num_rb_pipes);
+ if (!adev->gfx.config.backend_enable_mask ||
+ adev->gfx.config.num_rbs >= num_rb_pipes) {
+ WREG32(mmPA_SC_RASTER_CONFIG, raster_config);
+ } else {
+ gfx_v6_0_write_harvested_raster_configs(adev, raster_config,
+ adev->gfx.config.backend_enable_mask,
+ num_rb_pipes);
+ }
+
+ /* cache the values for userspace */
+ for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
+ for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
+ gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff);
+ adev->gfx.config.rb_config[i][j].rb_backend_disable =
+ RREG32(mmCC_RB_BACKEND_DISABLE);
+ adev->gfx.config.rb_config[i][j].user_rb_backend_disable =
+ RREG32(mmGC_USER_RB_BACKEND_DISABLE);
+ adev->gfx.config.rb_config[i][j].raster_config =
+ RREG32(mmPA_SC_RASTER_CONFIG);
+ }
}
gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex);
@@ -1540,36 +1525,44 @@ static void gmc_v6_0_init_compute_vmid(struct amdgpu_device *adev)
}
*/
-static u32 gfx_v6_0_get_cu_enabled(struct amdgpu_device *adev, u32 cu_per_sh)
+static void gfx_v6_0_set_user_cu_inactive_bitmap(struct amdgpu_device *adev,
+ u32 bitmap)
{
- u32 data, mask;
+ u32 data;
+
+ if (!bitmap)
+ return;
- data = RREG32(mmCC_GC_SHADER_ARRAY_CONFIG);
- data &= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS_MASK;
- data |= RREG32(mmGC_USER_SHADER_ARRAY_CONFIG);
+ data = bitmap << GC_USER_SHADER_ARRAY_CONFIG__INACTIVE_CUS__SHIFT;
+ data &= GC_USER_SHADER_ARRAY_CONFIG__INACTIVE_CUS_MASK;
- data >>= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS__SHIFT;
+ WREG32(mmGC_USER_SHADER_ARRAY_CONFIG, data);
+}
- mask = gfx_v6_0_create_bitmask(cu_per_sh);
+static u32 gfx_v6_0_get_cu_enabled(struct amdgpu_device *adev)
+{
+ u32 data, mask;
- return ~data & mask;
+ data = RREG32(mmCC_GC_SHADER_ARRAY_CONFIG) |
+ RREG32(mmGC_USER_SHADER_ARRAY_CONFIG);
+
+ mask = gfx_v6_0_create_bitmask(adev->gfx.config.max_cu_per_sh);
+ return ~REG_GET_FIELD(data, CC_GC_SHADER_ARRAY_CONFIG, INACTIVE_CUS) & mask;
}
-static void gfx_v6_0_setup_spi(struct amdgpu_device *adev,
- u32 se_num, u32 sh_per_se,
- u32 cu_per_sh)
+static void gfx_v6_0_setup_spi(struct amdgpu_device *adev)
{
int i, j, k;
u32 data, mask;
u32 active_cu = 0;
mutex_lock(&adev->grbm_idx_mutex);
- for (i = 0; i < se_num; i++) {
- for (j = 0; j < sh_per_se; j++) {
+ for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
+ for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff);
data = RREG32(mmSPI_STATIC_THREAD_MGMT_3);
- active_cu = gfx_v6_0_get_cu_enabled(adev, cu_per_sh);
+ active_cu = gfx_v6_0_get_cu_enabled(adev);
mask = 1;
for (k = 0; k < 16; k++) {
@@ -1717,6 +1710,9 @@ static void gfx_v6_0_gpu_init(struct amdgpu_device *adev)
gb_addr_config |= 2 << GB_ADDR_CONFIG__ROW_SIZE__SHIFT;
break;
}
+ gb_addr_config &= ~GB_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK;
+ if (adev->gfx.config.max_shader_engines == 2)
+ gb_addr_config |= 1 << GB_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT;
adev->gfx.config.gb_addr_config = gb_addr_config;
WREG32(mmGB_ADDR_CONFIG, gb_addr_config);
@@ -1735,13 +1731,9 @@ static void gfx_v6_0_gpu_init(struct amdgpu_device *adev)
#endif
gfx_v6_0_tiling_mode_table_init(adev);
- gfx_v6_0_setup_rb(adev, adev->gfx.config.max_shader_engines,
- adev->gfx.config.max_sh_per_se,
- adev->gfx.config.max_backends_per_se);
+ gfx_v6_0_setup_rb(adev);
- gfx_v6_0_setup_spi(adev, adev->gfx.config.max_shader_engines,
- adev->gfx.config.max_sh_per_se,
- adev->gfx.config.max_cu_per_sh);
+ gfx_v6_0_setup_spi(adev);
gfx_v6_0_get_cu_info(adev);
@@ -1794,14 +1786,9 @@ static void gfx_v6_0_gpu_init(struct amdgpu_device *adev)
static void gfx_v6_0_scratch_init(struct amdgpu_device *adev)
{
- int i;
-
adev->gfx.scratch.num_reg = 7;
adev->gfx.scratch.reg_base = mmSCRATCH_REG0;
- for (i = 0; i < adev->gfx.scratch.num_reg; i++) {
- adev->gfx.scratch.free[i] = true;
- adev->gfx.scratch.reg[i] = adev->gfx.scratch.reg_base + i;
- }
+ adev->gfx.scratch.free_mask = (1u << adev->gfx.scratch.num_reg) - 1;
}
static int gfx_v6_0_ring_test_ring(struct amdgpu_ring *ring)
@@ -1975,7 +1962,7 @@ static int gfx_v6_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
ib.ptr[2] = 0xDEADBEEF;
ib.length_dw = 3;
- r = amdgpu_ib_schedule(ring, 1, &ib, NULL, NULL, &f);
+ r = amdgpu_ib_schedule(ring, 1, &ib, NULL, &f);
if (r)
goto err2;
@@ -2946,61 +2933,16 @@ static void gfx_v6_0_enable_gfx_cgpg(struct amdgpu_device *adev,
}
}
-static u32 gfx_v6_0_get_cu_active_bitmap(struct amdgpu_device *adev,
- u32 se, u32 sh)
-{
-
- u32 mask = 0, tmp, tmp1;
- int i;
-
- mutex_lock(&adev->grbm_idx_mutex);
- gfx_v6_0_select_se_sh(adev, se, sh, 0xffffffff);
- tmp = RREG32(mmCC_GC_SHADER_ARRAY_CONFIG);
- tmp1 = RREG32(mmGC_USER_SHADER_ARRAY_CONFIG);
- gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
- mutex_unlock(&adev->grbm_idx_mutex);
-
- tmp &= 0xffff0000;
-
- tmp |= tmp1;
- tmp >>= 16;
-
- for (i = 0; i < adev->gfx.config.max_cu_per_sh; i ++) {
- mask <<= 1;
- mask |= 1;
- }
-
- return (~tmp) & mask;
-}
-
static void gfx_v6_0_init_ao_cu_mask(struct amdgpu_device *adev)
{
- u32 i, j, k, active_cu_number = 0;
-
- u32 mask, counter, cu_bitmap;
- u32 tmp = 0;
-
- for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
- for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
- mask = 1;
- cu_bitmap = 0;
- counter = 0;
- for (k = 0; k < adev->gfx.config.max_cu_per_sh; k++) {
- if (gfx_v6_0_get_cu_active_bitmap(adev, i, j) & mask) {
- if (counter < 2)
- cu_bitmap |= mask;
- counter++;
- }
- mask <<= 1;
- }
+ u32 tmp;
- active_cu_number += counter;
- tmp |= (cu_bitmap << (i * 16 + j * 8));
- }
- }
+ WREG32(mmRLC_PG_ALWAYS_ON_CU_MASK, adev->gfx.cu_info.ao_cu_mask);
- WREG32(mmRLC_PG_AO_CU_MASK, tmp);
- WREG32_FIELD(RLC_MAX_PG_CU, MAX_POWERED_UP_CU, active_cu_number);
+ tmp = RREG32(mmRLC_MAX_PG_CU);
+ tmp &= ~RLC_MAX_PG_CU__MAX_POWERED_UP_CU_MASK;
+ tmp |= (adev->gfx.cu_info.number << RLC_MAX_PG_CU__MAX_POWERED_UP_CU__SHIFT);
+ WREG32(mmRLC_MAX_PG_CU, tmp);
}
static void gfx_v6_0_enable_gfx_static_mgpg(struct amdgpu_device *adev,
@@ -3775,18 +3717,26 @@ static void gfx_v6_0_get_cu_info(struct amdgpu_device *adev)
int i, j, k, counter, active_cu_number = 0;
u32 mask, bitmap, ao_bitmap, ao_cu_mask = 0;
struct amdgpu_cu_info *cu_info = &adev->gfx.cu_info;
+ unsigned disable_masks[4 * 2];
memset(cu_info, 0, sizeof(*cu_info));
+ amdgpu_gfx_parse_disable_cu(disable_masks, 4, 2);
+
+ mutex_lock(&adev->grbm_idx_mutex);
for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
mask = 1;
ao_bitmap = 0;
counter = 0;
- bitmap = gfx_v6_0_get_cu_active_bitmap(adev, i, j);
+ gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff);
+ if (i < 4 && j < 2)
+ gfx_v6_0_set_user_cu_inactive_bitmap(
+ adev, disable_masks[i * 2 + j]);
+ bitmap = gfx_v6_0_get_cu_enabled(adev);
cu_info->bitmap[i][j] = bitmap;
- for (k = 0; k < adev->gfx.config.max_cu_per_sh; k ++) {
+ for (k = 0; k < 16; k++) {
if (bitmap & mask) {
if (counter < 2)
ao_bitmap |= mask;
@@ -3799,6 +3749,9 @@ static void gfx_v6_0_get_cu_info(struct amdgpu_device *adev)
}
}
+ gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ mutex_unlock(&adev->grbm_idx_mutex);
+
cu_info->number = active_cu_number;
cu_info->ao_cu_mask = ao_cu_mask;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
index c4e1401..1f93545 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
@@ -1983,6 +1983,14 @@ static void gfx_v7_0_gpu_init(struct amdgpu_device *adev)
WREG32(mmPA_CL_ENHANCE, PA_CL_ENHANCE__CLIP_VTX_REORDER_ENA_MASK |
(3 << PA_CL_ENHANCE__NUM_CLIP_SEQ__SHIFT));
WREG32(mmPA_SC_ENHANCE, PA_SC_ENHANCE__ENABLE_PA_SC_OUT_OF_ORDER_MASK);
+
+ tmp = RREG32(mmSPI_ARB_PRIORITY);
+ tmp = REG_SET_FIELD(tmp, SPI_ARB_PRIORITY, PIPE_ORDER_TS0, 2);
+ tmp = REG_SET_FIELD(tmp, SPI_ARB_PRIORITY, PIPE_ORDER_TS1, 2);
+ tmp = REG_SET_FIELD(tmp, SPI_ARB_PRIORITY, PIPE_ORDER_TS2, 2);
+ tmp = REG_SET_FIELD(tmp, SPI_ARB_PRIORITY, PIPE_ORDER_TS3, 2);
+ WREG32(mmSPI_ARB_PRIORITY, tmp);
+
mutex_unlock(&adev->grbm_idx_mutex);
udelay(50);
@@ -2003,14 +2011,9 @@ static void gfx_v7_0_gpu_init(struct amdgpu_device *adev)
*/
static void gfx_v7_0_scratch_init(struct amdgpu_device *adev)
{
- int i;
-
adev->gfx.scratch.num_reg = 7;
adev->gfx.scratch.reg_base = mmSCRATCH_REG0;
- for (i = 0; i < adev->gfx.scratch.num_reg; i++) {
- adev->gfx.scratch.free[i] = true;
- adev->gfx.scratch.reg[i] = adev->gfx.scratch.reg_base + i;
- }
+ adev->gfx.scratch.free_mask = (1u << adev->gfx.scratch.num_reg) - 1;
}
/**
@@ -2321,7 +2324,7 @@ static int gfx_v7_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
ib.ptr[2] = 0xDEADBEEF;
ib.length_dw = 3;
- r = amdgpu_ib_schedule(ring, 1, &ib, NULL, NULL, &f);
+ r = amdgpu_ib_schedule(ring, 1, &ib, NULL, &f);
if (r)
goto err2;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index 3733741..67afc90 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -657,6 +657,8 @@ static void gfx_v8_0_set_gds_init(struct amdgpu_device *adev);
static void gfx_v8_0_set_rlc_funcs(struct amdgpu_device *adev);
static u32 gfx_v8_0_get_csb_size(struct amdgpu_device *adev);
static void gfx_v8_0_get_cu_info(struct amdgpu_device *adev);
+static void gfx_v8_0_ring_emit_ce_meta_init(struct amdgpu_ring *ring, uint64_t addr);
+static void gfx_v8_0_ring_emit_de_meta_init(struct amdgpu_ring *ring, uint64_t addr);
static void gfx_v8_0_init_golden_registers(struct amdgpu_device *adev)
{
@@ -749,14 +751,9 @@ static void gfx_v8_0_init_golden_registers(struct amdgpu_device *adev)
static void gfx_v8_0_scratch_init(struct amdgpu_device *adev)
{
- int i;
-
adev->gfx.scratch.num_reg = 7;
adev->gfx.scratch.reg_base = mmSCRATCH_REG0;
- for (i = 0; i < adev->gfx.scratch.num_reg; i++) {
- adev->gfx.scratch.free[i] = true;
- adev->gfx.scratch.reg[i] = adev->gfx.scratch.reg_base + i;
- }
+ adev->gfx.scratch.free_mask = (1u << adev->gfx.scratch.num_reg) - 1;
}
static int gfx_v8_0_ring_test_ring(struct amdgpu_ring *ring)
@@ -829,7 +826,7 @@ static int gfx_v8_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
ib.ptr[2] = 0xDEADBEEF;
ib.length_dw = 3;
- r = amdgpu_ib_schedule(ring, 1, &ib, NULL, NULL, &f);
+ r = amdgpu_ib_schedule(ring, 1, &ib, NULL, &f);
if (r)
goto err2;
@@ -941,6 +938,13 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.me_fw->data;
adev->gfx.me_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
+
+ /* chain ib ucode isn't formal released, just disable it by far
+ * TODO: when ucod ready we should use ucode version to judge if
+ * chain-ib support or not.
+ */
+ adev->virt.chained_ib_support = false;
+
adev->gfx.me_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
@@ -1367,6 +1371,51 @@ static void gfx_v8_0_mec_fini(struct amdgpu_device *adev)
}
}
+static int gfx_v8_0_kiq_init_ring(struct amdgpu_device *adev,
+ struct amdgpu_ring *ring,
+ struct amdgpu_irq_src *irq)
+{
+ int r = 0;
+
+ if (amdgpu_sriov_vf(adev)) {
+ r = amdgpu_wb_get(adev, &adev->virt.reg_val_offs);
+ if (r)
+ return r;
+ }
+
+ ring->adev = NULL;
+ ring->ring_obj = NULL;
+ ring->use_doorbell = true;
+ ring->doorbell_index = AMDGPU_DOORBELL_KIQ;
+ if (adev->gfx.mec2_fw) {
+ ring->me = 2;
+ ring->pipe = 0;
+ } else {
+ ring->me = 1;
+ ring->pipe = 1;
+ }
+
+ irq->data = ring;
+ ring->queue = 0;
+ sprintf(ring->name, "kiq %d.%d.%d", ring->me, ring->pipe, ring->queue);
+ r = amdgpu_ring_init(adev, ring, 1024,
+ irq, AMDGPU_CP_KIQ_IRQ_DRIVER0);
+ if (r)
+ dev_warn(adev->dev, "(%d) failed to init kiq ring\n", r);
+
+ return r;
+}
+
+static void gfx_v8_0_kiq_free_ring(struct amdgpu_ring *ring,
+ struct amdgpu_irq_src *irq)
+{
+ if (amdgpu_sriov_vf(ring->adev))
+ amdgpu_wb_free(ring->adev, ring->adev->virt.reg_val_offs);
+
+ amdgpu_ring_fini(ring);
+ irq->data = NULL;
+}
+
#define MEC_HPD_SIZE 2048
static int gfx_v8_0_mec_init(struct amdgpu_device *adev)
@@ -1421,6 +1470,35 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev)
return 0;
}
+static void gfx_v8_0_kiq_fini(struct amdgpu_device *adev)
+{
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+
+ amdgpu_bo_free_kernel(&kiq->eop_obj, &kiq->eop_gpu_addr, NULL);
+ kiq->eop_obj = NULL;
+}
+
+static int gfx_v8_0_kiq_init(struct amdgpu_device *adev)
+{
+ int r;
+ u32 *hpd;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+
+ r = amdgpu_bo_create_kernel(adev, MEC_HPD_SIZE, PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_GTT, &kiq->eop_obj,
+ &kiq->eop_gpu_addr, (void **)&hpd);
+ if (r) {
+ dev_warn(adev->dev, "failed to create KIQ bo (%d).\n", r);
+ return r;
+ }
+
+ memset(hpd, 0, MEC_HPD_SIZE);
+
+ amdgpu_bo_kunmap(kiq->eop_obj);
+
+ return 0;
+}
+
static const u32 vgpr_init_compute_shader[] =
{
0x7e000209, 0x7e020208,
@@ -1702,7 +1780,7 @@ static int gfx_v8_0_do_edc_gpr_workarounds(struct amdgpu_device *adev)
ib.ptr[ib.length_dw++] = EVENT_TYPE(7) | EVENT_INDEX(4);
/* shedule the ib on the ring */
- r = amdgpu_ib_schedule(ring, 1, &ib, NULL, NULL, &f);
+ r = amdgpu_ib_schedule(ring, 1, &ib, NULL, &f);
if (r) {
DRM_ERROR("amdgpu: ib submit failed (%d).\n", r);
goto fail;
@@ -1997,8 +2075,14 @@ static int gfx_v8_0_sw_init(void *handle)
{
int i, r;
struct amdgpu_ring *ring;
+ struct amdgpu_kiq *kiq;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ /* KIQ event */
+ r = amdgpu_irq_add_id(adev, 178, &adev->gfx.kiq.irq);
+ if (r)
+ return r;
+
/* EOP Event */
r = amdgpu_irq_add_id(adev, 181, &adev->gfx.eop_irq);
if (r)
@@ -2036,6 +2120,17 @@ static int gfx_v8_0_sw_init(void *handle)
return r;
}
+ r = gfx_v8_0_kiq_init(adev);
+ if (r) {
+ DRM_ERROR("Failed to init KIQ BOs!\n");
+ return r;
+ }
+
+ kiq = &adev->gfx.kiq;
+ r = gfx_v8_0_kiq_init_ring(adev, &kiq->ring, &kiq->irq);
+ if (r)
+ return r;
+
/* set up the gfx ring */
for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
ring = &adev->gfx.gfx_ring[i];
@@ -2119,7 +2214,9 @@ static int gfx_v8_0_sw_fini(void *handle)
amdgpu_ring_fini(&adev->gfx.gfx_ring[i]);
for (i = 0; i < adev->gfx.num_compute_rings; i++)
amdgpu_ring_fini(&adev->gfx.compute_ring[i]);
+ gfx_v8_0_kiq_free_ring(&adev->gfx.kiq.ring, &adev->gfx.kiq.irq);
+ gfx_v8_0_kiq_fini(adev);
gfx_v8_0_mec_fini(adev);
gfx_v8_0_rlc_fini(adev);
gfx_v8_0_free_microcode(adev);
@@ -3801,6 +3898,14 @@ static void gfx_v8_0_gpu_init(struct amdgpu_device *adev)
PA_SC_FIFO_SIZE__SC_HIZ_TILE_FIFO_SIZE__SHIFT) |
(adev->gfx.config.sc_earlyz_tile_fifo_size <<
PA_SC_FIFO_SIZE__SC_EARLYZ_TILE_FIFO_SIZE__SHIFT));
+
+ tmp = RREG32(mmSPI_ARB_PRIORITY);
+ tmp = REG_SET_FIELD(tmp, SPI_ARB_PRIORITY, PIPE_ORDER_TS0, 2);
+ tmp = REG_SET_FIELD(tmp, SPI_ARB_PRIORITY, PIPE_ORDER_TS1, 2);
+ tmp = REG_SET_FIELD(tmp, SPI_ARB_PRIORITY, PIPE_ORDER_TS2, 2);
+ tmp = REG_SET_FIELD(tmp, SPI_ARB_PRIORITY, PIPE_ORDER_TS3, 2);
+ WREG32(mmSPI_ARB_PRIORITY, tmp);
+
mutex_unlock(&adev->grbm_idx_mutex);
}
@@ -4024,17 +4129,6 @@ static void gfx_v8_0_init_pg(struct amdgpu_device *adev)
WREG32(mmRLC_JUMP_TABLE_RESTORE, adev->gfx.rlc.cp_table_gpu_addr >> 8);
gfx_v8_0_init_power_gating(adev);
WREG32(mmRLC_PG_ALWAYS_ON_CU_MASK, adev->gfx.cu_info.ao_cu_mask);
- if (adev->pg_flags & AMD_PG_SUPPORT_RLC_SMU_HS) {
- cz_enable_sck_slow_down_on_power_up(adev, true);
- cz_enable_sck_slow_down_on_power_down(adev, true);
- } else {
- cz_enable_sck_slow_down_on_power_up(adev, false);
- cz_enable_sck_slow_down_on_power_down(adev, false);
- }
- if (adev->pg_flags & AMD_PG_SUPPORT_CP)
- cz_enable_cp_power_gating(adev, true);
- else
- cz_enable_cp_power_gating(adev, false);
} else if ((adev->asic_type == CHIP_POLARIS11) ||
(adev->asic_type == CHIP_POLARIS12)) {
gfx_v8_0_init_csb(adev);
@@ -4506,6 +4600,393 @@ static void gfx_v8_0_cp_compute_fini(struct amdgpu_device *adev)
}
}
+/* KIQ functions */
+static void gfx_v8_0_kiq_setting(struct amdgpu_ring *ring)
+{
+ uint32_t tmp;
+ struct amdgpu_device *adev = ring->adev;
+
+ /* tell RLC which is KIQ queue */
+ tmp = RREG32(mmRLC_CP_SCHEDULERS);
+ tmp &= 0xffffff00;
+ tmp |= (ring->me << 5) | (ring->pipe << 3) | (ring->queue);
+ WREG32(mmRLC_CP_SCHEDULERS, tmp);
+ tmp |= 0x80;
+ WREG32(mmRLC_CP_SCHEDULERS, tmp);
+}
+
+static void gfx_v8_0_kiq_enable(struct amdgpu_ring *ring)
+{
+ amdgpu_ring_alloc(ring, 8);
+ /* set resources */
+ amdgpu_ring_write(ring, PACKET3(PACKET3_SET_RESOURCES, 6));
+ amdgpu_ring_write(ring, 0); /* vmid_mask:0 queue_type:0 (KIQ) */
+ amdgpu_ring_write(ring, 0x000000FF); /* queue mask lo */
+ amdgpu_ring_write(ring, 0); /* queue mask hi */
+ amdgpu_ring_write(ring, 0); /* gws mask lo */
+ amdgpu_ring_write(ring, 0); /* gws mask hi */
+ amdgpu_ring_write(ring, 0); /* oac mask */
+ amdgpu_ring_write(ring, 0); /* gds heap base:0, gds heap size:0 */
+ amdgpu_ring_commit(ring);
+ udelay(50);
+}
+
+static void gfx_v8_0_map_queue_enable(struct amdgpu_ring *kiq_ring,
+ struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = kiq_ring->adev;
+ uint64_t mqd_addr, wptr_addr;
+
+ mqd_addr = amdgpu_bo_gpu_offset(ring->mqd_obj);
+ wptr_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
+ amdgpu_ring_alloc(kiq_ring, 8);
+
+ amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_MAP_QUEUES, 5));
+ /* Q_sel:0, vmid:0, vidmem: 1, engine:0, num_Q:1*/
+ amdgpu_ring_write(kiq_ring, 0x21010000);
+ amdgpu_ring_write(kiq_ring, (ring->doorbell_index << 2) |
+ (ring->queue << 26) |
+ (ring->pipe << 29) |
+ ((ring->me == 1 ? 0 : 1) << 31)); /* doorbell */
+ amdgpu_ring_write(kiq_ring, lower_32_bits(mqd_addr));
+ amdgpu_ring_write(kiq_ring, upper_32_bits(mqd_addr));
+ amdgpu_ring_write(kiq_ring, lower_32_bits(wptr_addr));
+ amdgpu_ring_write(kiq_ring, upper_32_bits(wptr_addr));
+ amdgpu_ring_commit(kiq_ring);
+ udelay(50);
+}
+
+static int gfx_v8_0_mqd_init(struct amdgpu_device *adev,
+ struct vi_mqd *mqd,
+ uint64_t mqd_gpu_addr,
+ uint64_t eop_gpu_addr,
+ struct amdgpu_ring *ring)
+{
+ uint64_t hqd_gpu_addr, wb_gpu_addr, eop_base_addr;
+ uint32_t tmp;
+
+ mqd->header = 0xC0310800;
+ mqd->compute_pipelinestat_enable = 0x00000001;
+ mqd->compute_static_thread_mgmt_se0 = 0xffffffff;
+ mqd->compute_static_thread_mgmt_se1 = 0xffffffff;
+ mqd->compute_static_thread_mgmt_se2 = 0xffffffff;
+ mqd->compute_static_thread_mgmt_se3 = 0xffffffff;
+ mqd->compute_misc_reserved = 0x00000003;
+
+ eop_base_addr = eop_gpu_addr >> 8;
+ mqd->cp_hqd_eop_base_addr_lo = eop_base_addr;
+ mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr);
+
+ /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
+ tmp = RREG32(mmCP_HQD_EOP_CONTROL);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE,
+ (order_base_2(MEC_HPD_SIZE / 4) - 1));
+
+ mqd->cp_hqd_eop_control = tmp;
+
+ /* enable doorbell? */
+ tmp = RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL);
+
+ if (ring->use_doorbell)
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+ DOORBELL_EN, 1);
+ else
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+ DOORBELL_EN, 0);
+
+ mqd->cp_hqd_pq_doorbell_control = tmp;
+
+ /* disable the queue if it's active */
+ mqd->cp_hqd_dequeue_request = 0;
+ mqd->cp_hqd_pq_rptr = 0;
+ mqd->cp_hqd_pq_wptr = 0;
+
+ /* set the pointer to the MQD */
+ mqd->cp_mqd_base_addr_lo = mqd_gpu_addr & 0xfffffffc;
+ mqd->cp_mqd_base_addr_hi = upper_32_bits(mqd_gpu_addr);
+
+ /* set MQD vmid to 0 */
+ tmp = RREG32(mmCP_MQD_CONTROL);
+ tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0);
+ mqd->cp_mqd_control = tmp;
+
+ /* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */
+ hqd_gpu_addr = ring->gpu_addr >> 8;
+ mqd->cp_hqd_pq_base_lo = hqd_gpu_addr;
+ mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr);
+
+ /* set up the HQD, this is similar to CP_RB0_CNTL */
+ tmp = RREG32(mmCP_HQD_PQ_CONTROL);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE,
+ (order_base_2(ring->ring_size / 4) - 1));
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE,
+ ((order_base_2(AMDGPU_GPU_PAGE_SIZE / 4) - 1) << 8));
+#ifdef __BIG_ENDIAN
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ENDIAN_SWAP, 1);
+#endif
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ROQ_PQ_IB_FLIP, 0);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1);
+ mqd->cp_hqd_pq_control = tmp;
+
+ /* set the wb address whether it's enabled or not */
+ wb_gpu_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
+ mqd->cp_hqd_pq_rptr_report_addr_lo = wb_gpu_addr & 0xfffffffc;
+ mqd->cp_hqd_pq_rptr_report_addr_hi =
+ upper_32_bits(wb_gpu_addr) & 0xffff;
+
+ /* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */
+ wb_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
+ mqd->cp_hqd_pq_wptr_poll_addr_lo = wb_gpu_addr & 0xfffffffc;
+ mqd->cp_hqd_pq_wptr_poll_addr_hi = upper_32_bits(wb_gpu_addr) & 0xffff;
+
+ tmp = 0;
+ /* enable the doorbell if requested */
+ if (ring->use_doorbell) {
+ tmp = RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+ DOORBELL_OFFSET, ring->doorbell_index);
+
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+ DOORBELL_EN, 1);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+ DOORBELL_SOURCE, 0);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
+ DOORBELL_HIT, 0);
+ }
+
+ mqd->cp_hqd_pq_doorbell_control = tmp;
+
+ /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
+ ring->wptr = 0;
+ mqd->cp_hqd_pq_wptr = ring->wptr;
+ mqd->cp_hqd_pq_rptr = RREG32(mmCP_HQD_PQ_RPTR);
+
+ /* set the vmid for the queue */
+ mqd->cp_hqd_vmid = 0;
+
+ tmp = RREG32(mmCP_HQD_PERSISTENT_STATE);
+ tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x53);
+ mqd->cp_hqd_persistent_state = tmp;
+
+ /* activate the queue */
+ mqd->cp_hqd_active = 1;
+
+ return 0;
+}
+
+static int gfx_v8_0_kiq_init_register(struct amdgpu_device *adev,
+ struct vi_mqd *mqd,
+ struct amdgpu_ring *ring)
+{
+ uint32_t tmp;
+ int j;
+
+ /* disable wptr polling */
+ tmp = RREG32(mmCP_PQ_WPTR_POLL_CNTL);
+ tmp = REG_SET_FIELD(tmp, CP_PQ_WPTR_POLL_CNTL, EN, 0);
+ WREG32(mmCP_PQ_WPTR_POLL_CNTL, tmp);
+
+ WREG32(mmCP_HQD_EOP_BASE_ADDR, mqd->cp_hqd_eop_base_addr_lo);
+ WREG32(mmCP_HQD_EOP_BASE_ADDR_HI, mqd->cp_hqd_eop_base_addr_hi);
+
+ /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
+ WREG32(mmCP_HQD_EOP_CONTROL, mqd->cp_hqd_eop_control);
+
+ /* enable doorbell? */
+ WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, mqd->cp_hqd_pq_doorbell_control);
+
+ /* disable the queue if it's active */
+ if (RREG32(mmCP_HQD_ACTIVE) & 1) {
+ WREG32(mmCP_HQD_DEQUEUE_REQUEST, 1);
+ for (j = 0; j < adev->usec_timeout; j++) {
+ if (!(RREG32(mmCP_HQD_ACTIVE) & 1))
+ break;
+ udelay(1);
+ }
+ WREG32(mmCP_HQD_DEQUEUE_REQUEST, mqd->cp_hqd_dequeue_request);
+ WREG32(mmCP_HQD_PQ_RPTR, mqd->cp_hqd_pq_rptr);
+ WREG32(mmCP_HQD_PQ_WPTR, mqd->cp_hqd_pq_wptr);
+ }
+
+ /* set the pointer to the MQD */
+ WREG32(mmCP_MQD_BASE_ADDR, mqd->cp_mqd_base_addr_lo);
+ WREG32(mmCP_MQD_BASE_ADDR_HI, mqd->cp_mqd_base_addr_hi);
+
+ /* set MQD vmid to 0 */
+ WREG32(mmCP_MQD_CONTROL, mqd->cp_mqd_control);
+
+ /* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */
+ WREG32(mmCP_HQD_PQ_BASE, mqd->cp_hqd_pq_base_lo);
+ WREG32(mmCP_HQD_PQ_BASE_HI, mqd->cp_hqd_pq_base_hi);
+
+ /* set up the HQD, this is similar to CP_RB0_CNTL */
+ WREG32(mmCP_HQD_PQ_CONTROL, mqd->cp_hqd_pq_control);
+
+ /* set the wb address whether it's enabled or not */
+ WREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR,
+ mqd->cp_hqd_pq_rptr_report_addr_lo);
+ WREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI,
+ mqd->cp_hqd_pq_rptr_report_addr_hi);
+
+ /* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */
+ WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd->cp_hqd_pq_wptr_poll_addr_lo);
+ WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR_HI, mqd->cp_hqd_pq_wptr_poll_addr_hi);
+
+ /* enable the doorbell if requested */
+ if (ring->use_doorbell) {
+ if ((adev->asic_type == CHIP_CARRIZO) ||
+ (adev->asic_type == CHIP_FIJI) ||
+ (adev->asic_type == CHIP_STONEY)) {
+ WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER,
+ AMDGPU_DOORBELL_KIQ << 2);
+ WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER,
+ AMDGPU_DOORBELL_MEC_RING7 << 2);
+ }
+ }
+ WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, mqd->cp_hqd_pq_doorbell_control);
+
+ /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
+ WREG32(mmCP_HQD_PQ_WPTR, mqd->cp_hqd_pq_wptr);
+
+ /* set the vmid for the queue */
+ WREG32(mmCP_HQD_VMID, mqd->cp_hqd_vmid);
+
+ WREG32(mmCP_HQD_PERSISTENT_STATE, mqd->cp_hqd_persistent_state);
+
+ /* activate the queue */
+ WREG32(mmCP_HQD_ACTIVE, mqd->cp_hqd_active);
+
+ if (ring->use_doorbell) {
+ tmp = RREG32(mmCP_PQ_STATUS);
+ tmp = REG_SET_FIELD(tmp, CP_PQ_STATUS, DOORBELL_ENABLE, 1);
+ WREG32(mmCP_PQ_STATUS, tmp);
+ }
+
+ return 0;
+}
+
+static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring,
+ struct vi_mqd *mqd,
+ u64 mqd_gpu_addr)
+{
+ struct amdgpu_device *adev = ring->adev;
+ struct amdgpu_kiq *kiq = &adev->gfx.kiq;
+ uint64_t eop_gpu_addr;
+ bool is_kiq = false;
+
+ if (ring->funcs->type == AMDGPU_RING_TYPE_KIQ)
+ is_kiq = true;
+
+ if (is_kiq) {
+ eop_gpu_addr = kiq->eop_gpu_addr;
+ gfx_v8_0_kiq_setting(&kiq->ring);
+ } else
+ eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr +
+ ring->queue * MEC_HPD_SIZE;
+
+ mutex_lock(&adev->srbm_mutex);
+ vi_srbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
+
+ gfx_v8_0_mqd_init(adev, mqd, mqd_gpu_addr, eop_gpu_addr, ring);
+
+ if (is_kiq)
+ gfx_v8_0_kiq_init_register(adev, mqd, ring);
+
+ vi_srbm_select(adev, 0, 0, 0, 0);
+ mutex_unlock(&adev->srbm_mutex);
+
+ if (is_kiq)
+ gfx_v8_0_kiq_enable(ring);
+ else
+ gfx_v8_0_map_queue_enable(&kiq->ring, ring);
+
+ return 0;
+}
+
+static void gfx_v8_0_kiq_free_queue(struct amdgpu_device *adev)
+{
+ struct amdgpu_ring *ring = NULL;
+ int i;
+
+ for (i = 0; i < adev->gfx.num_compute_rings; i++) {
+ ring = &adev->gfx.compute_ring[i];
+ amdgpu_bo_free_kernel(&ring->mqd_obj, NULL, NULL);
+ ring->mqd_obj = NULL;
+ }
+
+ ring = &adev->gfx.kiq.ring;
+ amdgpu_bo_free_kernel(&ring->mqd_obj, NULL, NULL);
+ ring->mqd_obj = NULL;
+}
+
+static int gfx_v8_0_kiq_setup_queue(struct amdgpu_device *adev,
+ struct amdgpu_ring *ring)
+{
+ struct vi_mqd *mqd;
+ u64 mqd_gpu_addr;
+ u32 *buf;
+ int r = 0;
+
+ r = amdgpu_bo_create_kernel(adev, sizeof(struct vi_mqd), PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_GTT, &ring->mqd_obj,
+ &mqd_gpu_addr, (void **)&buf);
+ if (r) {
+ dev_warn(adev->dev, "failed to create ring mqd ob (%d)", r);
+ return r;
+ }
+
+ /* init the mqd struct */
+ memset(buf, 0, sizeof(struct vi_mqd));
+ mqd = (struct vi_mqd *)buf;
+
+ r = gfx_v8_0_kiq_init_queue(ring, mqd, mqd_gpu_addr);
+ if (r)
+ return r;
+
+ amdgpu_bo_kunmap(ring->mqd_obj);
+
+ return 0;
+}
+
+static int gfx_v8_0_kiq_resume(struct amdgpu_device *adev)
+{
+ struct amdgpu_ring *ring = NULL;
+ int r, i;
+
+ ring = &adev->gfx.kiq.ring;
+ r = gfx_v8_0_kiq_setup_queue(adev, ring);
+ if (r)
+ return r;
+
+ for (i = 0; i < adev->gfx.num_compute_rings; i++) {
+ ring = &adev->gfx.compute_ring[i];
+ r = gfx_v8_0_kiq_setup_queue(adev, ring);
+ if (r)
+ return r;
+ }
+
+ gfx_v8_0_cp_compute_enable(adev, true);
+
+ for (i = 0; i < adev->gfx.num_compute_rings; i++) {
+ ring = &adev->gfx.compute_ring[i];
+
+ ring->ready = true;
+ r = amdgpu_ring_test_ring(ring);
+ if (r)
+ ring->ready = false;
+ }
+
+ ring = &adev->gfx.kiq.ring;
+ ring->ready = true;
+ r = amdgpu_ring_test_ring(ring);
+ if (r)
+ ring->ready = false;
+
+ return 0;
+}
+
static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev)
{
int r, i, j;
@@ -4806,7 +5287,10 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev)
if (r)
return r;
- r = gfx_v8_0_cp_compute_resume(adev);
+ if (amdgpu_sriov_vf(adev))
+ r = gfx_v8_0_kiq_resume(adev);
+ else
+ r = gfx_v8_0_cp_compute_resume(adev);
if (r)
return r;
@@ -4845,6 +5329,7 @@ static int gfx_v8_0_hw_fini(void *handle)
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
if (amdgpu_sriov_vf(adev)) {
+ gfx_v8_0_kiq_free_queue(adev);
pr_debug("For SRIOV client, shouldn't do anything.\n");
return 0;
}
@@ -5360,6 +5845,18 @@ static int gfx_v8_0_set_powergating_state(void *handle,
case CHIP_CARRIZO:
case CHIP_STONEY:
+ if (adev->pg_flags & AMD_PG_SUPPORT_RLC_SMU_HS) {
+ cz_enable_sck_slow_down_on_power_up(adev, true);
+ cz_enable_sck_slow_down_on_power_down(adev, true);
+ } else {
+ cz_enable_sck_slow_down_on_power_up(adev, false);
+ cz_enable_sck_slow_down_on_power_down(adev, false);
+ }
+ if (adev->pg_flags & AMD_PG_SUPPORT_CP)
+ cz_enable_cp_power_gating(adev, true);
+ else
+ cz_enable_cp_power_gating(adev, false);
+
cz_update_gfx_cg_power_gating(adev, enable);
if ((adev->pg_flags & AMD_PG_SUPPORT_GFX_SMG) && enable)
@@ -5396,6 +5893,45 @@ static int gfx_v8_0_set_powergating_state(void *handle,
return 0;
}
+static void gfx_v8_0_get_clockgating_state(void *handle, u32 *flags)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int data;
+
+ /* AMD_CG_SUPPORT_GFX_MGCG */
+ data = RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
+ if (!(data & RLC_CGTT_MGCG_OVERRIDE__CPF_MASK))
+ *flags |= AMD_CG_SUPPORT_GFX_MGCG;
+
+ /* AMD_CG_SUPPORT_GFX_CGLG */
+ data = RREG32(mmRLC_CGCG_CGLS_CTRL);
+ if (data & RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK)
+ *flags |= AMD_CG_SUPPORT_GFX_CGCG;
+
+ /* AMD_CG_SUPPORT_GFX_CGLS */
+ if (data & RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK)
+ *flags |= AMD_CG_SUPPORT_GFX_CGLS;
+
+ /* AMD_CG_SUPPORT_GFX_CGTS */
+ data = RREG32(mmCGTS_SM_CTRL_REG);
+ if (!(data & CGTS_SM_CTRL_REG__OVERRIDE_MASK))
+ *flags |= AMD_CG_SUPPORT_GFX_CGTS;
+
+ /* AMD_CG_SUPPORT_GFX_CGTS_LS */
+ if (!(data & CGTS_SM_CTRL_REG__LS_OVERRIDE_MASK))
+ *flags |= AMD_CG_SUPPORT_GFX_CGTS_LS;
+
+ /* AMD_CG_SUPPORT_GFX_RLC_LS */
+ data = RREG32(mmRLC_MEM_SLP_CNTL);
+ if (data & RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK)
+ *flags |= AMD_CG_SUPPORT_GFX_RLC_LS | AMD_CG_SUPPORT_GFX_MGLS;
+
+ /* AMD_CG_SUPPORT_GFX_CP_LS */
+ data = RREG32(mmCP_MEM_SLP_CNTL);
+ if (data & CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK)
+ *flags |= AMD_CG_SUPPORT_GFX_CP_LS | AMD_CG_SUPPORT_GFX_MGLS;
+}
+
static void gfx_v8_0_send_serdes_cmd(struct amdgpu_device *adev,
uint32_t reg_addr, uint32_t cmd)
{
@@ -5444,68 +5980,6 @@ static void gfx_v8_0_send_serdes_cmd(struct amdgpu_device *adev,
#define RLC_GPR_REG2__MESSAGE__SHIFT 0x00000001
#define RLC_GPR_REG2__MESSAGE_MASK 0x0000001e
-static void cz_enter_rlc_safe_mode(struct amdgpu_device *adev)
-{
- u32 data = 0;
- unsigned i;
-
- data = RREG32(mmRLC_CNTL);
- if ((data & RLC_CNTL__RLC_ENABLE_F32_MASK) == 0)
- return;
-
- if ((adev->cg_flags & (AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_MGCG)) ||
- (adev->pg_flags & (AMD_PG_SUPPORT_GFX_PG | AMD_PG_SUPPORT_GFX_SMG |
- AMD_PG_SUPPORT_GFX_DMG))) {
- data |= RLC_GPR_REG2__REQ_MASK;
- data &= ~RLC_GPR_REG2__MESSAGE_MASK;
- data |= (MSG_ENTER_RLC_SAFE_MODE << RLC_GPR_REG2__MESSAGE__SHIFT);
- WREG32(mmRLC_GPR_REG2, data);
-
- for (i = 0; i < adev->usec_timeout; i++) {
- if ((RREG32(mmRLC_GPM_STAT) &
- (RLC_GPM_STAT__GFX_CLOCK_STATUS_MASK |
- RLC_GPM_STAT__GFX_POWER_STATUS_MASK)) ==
- (RLC_GPM_STAT__GFX_CLOCK_STATUS_MASK |
- RLC_GPM_STAT__GFX_POWER_STATUS_MASK))
- break;
- udelay(1);
- }
-
- for (i = 0; i < adev->usec_timeout; i++) {
- if (!REG_GET_FIELD(RREG32(mmRLC_GPR_REG2), RLC_GPR_REG2, REQ))
- break;
- udelay(1);
- }
- adev->gfx.rlc.in_safe_mode = true;
- }
-}
-
-static void cz_exit_rlc_safe_mode(struct amdgpu_device *adev)
-{
- u32 data;
- unsigned i;
-
- data = RREG32(mmRLC_CNTL);
- if ((data & RLC_CNTL__RLC_ENABLE_F32_MASK) == 0)
- return;
-
- if ((adev->cg_flags & (AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_MGCG)) ||
- (adev->pg_flags & (AMD_PG_SUPPORT_GFX_PG | AMD_PG_SUPPORT_GFX_SMG |
- AMD_PG_SUPPORT_GFX_DMG))) {
- data |= RLC_GPR_REG2__REQ_MASK;
- data &= ~RLC_GPR_REG2__MESSAGE_MASK;
- data |= (MSG_EXIT_RLC_SAFE_MODE << RLC_GPR_REG2__MESSAGE__SHIFT);
- WREG32(mmRLC_GPR_REG2, data);
- adev->gfx.rlc.in_safe_mode = false;
- }
-
- for (i = 0; i < adev->usec_timeout; i++) {
- if (!REG_GET_FIELD(RREG32(mmRLC_GPR_REG2), RLC_GPR_REG2, REQ))
- break;
- udelay(1);
- }
-}
-
static void iceland_enter_rlc_safe_mode(struct amdgpu_device *adev)
{
u32 data;
@@ -5565,31 +6039,11 @@ static void iceland_exit_rlc_safe_mode(struct amdgpu_device *adev)
}
}
-static void gfx_v8_0_nop_enter_rlc_safe_mode(struct amdgpu_device *adev)
-{
- adev->gfx.rlc.in_safe_mode = true;
-}
-
-static void gfx_v8_0_nop_exit_rlc_safe_mode(struct amdgpu_device *adev)
-{
- adev->gfx.rlc.in_safe_mode = false;
-}
-
-static const struct amdgpu_rlc_funcs cz_rlc_funcs = {
- .enter_safe_mode = cz_enter_rlc_safe_mode,
- .exit_safe_mode = cz_exit_rlc_safe_mode
-};
-
static const struct amdgpu_rlc_funcs iceland_rlc_funcs = {
.enter_safe_mode = iceland_enter_rlc_safe_mode,
.exit_safe_mode = iceland_exit_rlc_safe_mode
};
-static const struct amdgpu_rlc_funcs gfx_v8_0_nop_rlc_funcs = {
- .enter_safe_mode = gfx_v8_0_nop_enter_rlc_safe_mode,
- .exit_safe_mode = gfx_v8_0_nop_exit_rlc_safe_mode
-};
-
static void gfx_v8_0_update_medium_grain_clock_gating(struct amdgpu_device *adev,
bool enable)
{
@@ -6011,7 +6465,8 @@ static void gfx_v8_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
{
u32 ref_and_mask, reg_mem_engine;
- if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) {
+ if ((ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) ||
+ (ring->funcs->type == AMDGPU_RING_TYPE_KIQ)) {
switch (ring->me) {
case 1:
ref_and_mask = GPU_HDP_FLUSH_DONE__CP2_MASK << ring->pipe;
@@ -6224,6 +6679,31 @@ static void gfx_v8_0_ring_emit_fence_compute(struct amdgpu_ring *ring,
amdgpu_ring_write(ring, upper_32_bits(seq));
}
+static void gfx_v8_0_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
+ u64 seq, unsigned int flags)
+{
+ /* we only allocate 32bit for each seq wb address */
+ BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
+
+ /* write fence seq to the "addr" */
+ amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
+ amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+ WRITE_DATA_DST_SEL(5) | WR_CONFIRM));
+ amdgpu_ring_write(ring, lower_32_bits(addr));
+ amdgpu_ring_write(ring, upper_32_bits(addr));
+ amdgpu_ring_write(ring, lower_32_bits(seq));
+
+ if (flags & AMDGPU_FENCE_FLAG_INT) {
+ /* set register to trigger INT */
+ amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
+ amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+ WRITE_DATA_DST_SEL(0) | WR_CONFIRM));
+ amdgpu_ring_write(ring, mmCPC_INT_STATUS);
+ amdgpu_ring_write(ring, 0);
+ amdgpu_ring_write(ring, 0x20000000); /* src_id is 178 */
+ }
+}
+
static void gfx_v8_ring_emit_sb(struct amdgpu_ring *ring)
{
amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
@@ -6234,6 +6714,10 @@ static void gfx_v8_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags)
{
uint32_t dw2 = 0;
+ if (amdgpu_sriov_vf(ring->adev))
+ gfx_v8_0_ring_emit_ce_meta_init(ring,
+ (flags & AMDGPU_VM_DOMAIN) ? AMDGPU_CSA_VADDR : ring->adev->virt.csa_vmid0_addr);
+
dw2 |= 0x80000000; /* set load_enable otherwise this package is just NOPs */
if (flags & AMDGPU_HAVE_CTX_SWITCH) {
gfx_v8_0_ring_emit_vgt_flush(ring);
@@ -6258,6 +6742,36 @@ static void gfx_v8_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags)
amdgpu_ring_write(ring, PACKET3(PACKET3_CONTEXT_CONTROL, 1));
amdgpu_ring_write(ring, dw2);
amdgpu_ring_write(ring, 0);
+
+ if (amdgpu_sriov_vf(ring->adev))
+ gfx_v8_0_ring_emit_de_meta_init(ring,
+ (flags & AMDGPU_VM_DOMAIN) ? AMDGPU_CSA_VADDR : ring->adev->virt.csa_vmid0_addr);
+}
+
+static void gfx_v8_0_ring_emit_rreg(struct amdgpu_ring *ring, uint32_t reg)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ amdgpu_ring_write(ring, PACKET3(PACKET3_COPY_DATA, 4));
+ amdgpu_ring_write(ring, 0 | /* src: register*/
+ (5 << 8) | /* dst: memory */
+ (1 << 20)); /* write confirm */
+ amdgpu_ring_write(ring, reg);
+ amdgpu_ring_write(ring, 0);
+ amdgpu_ring_write(ring, lower_32_bits(adev->wb.gpu_addr +
+ adev->virt.reg_val_offs * 4));
+ amdgpu_ring_write(ring, upper_32_bits(adev->wb.gpu_addr +
+ adev->virt.reg_val_offs * 4));
+}
+
+static void gfx_v8_0_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg,
+ uint32_t val)
+{
+ amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
+ amdgpu_ring_write(ring, (1 << 16)); /* no inc addr */
+ amdgpu_ring_write(ring, reg);
+ amdgpu_ring_write(ring, 0);
+ amdgpu_ring_write(ring, val);
}
static void gfx_v8_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
@@ -6405,6 +6919,72 @@ static int gfx_v8_0_priv_inst_irq(struct amdgpu_device *adev,
return 0;
}
+static int gfx_v8_0_kiq_set_interrupt_state(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *src,
+ unsigned int type,
+ enum amdgpu_interrupt_state state)
+{
+ uint32_t tmp, target;
+ struct amdgpu_ring *ring = (struct amdgpu_ring *)src->data;
+
+ BUG_ON(!ring || (ring->funcs->type != AMDGPU_RING_TYPE_KIQ));
+
+ if (ring->me == 1)
+ target = mmCP_ME1_PIPE0_INT_CNTL;
+ else
+ target = mmCP_ME2_PIPE0_INT_CNTL;
+ target += ring->pipe;
+
+ switch (type) {
+ case AMDGPU_CP_KIQ_IRQ_DRIVER0:
+ if (state == AMDGPU_IRQ_STATE_DISABLE) {
+ tmp = RREG32(mmCPC_INT_CNTL);
+ tmp = REG_SET_FIELD(tmp, CPC_INT_CNTL,
+ GENERIC2_INT_ENABLE, 0);
+ WREG32(mmCPC_INT_CNTL, tmp);
+
+ tmp = RREG32(target);
+ tmp = REG_SET_FIELD(tmp, CP_ME2_PIPE0_INT_CNTL,
+ GENERIC2_INT_ENABLE, 0);
+ WREG32(target, tmp);
+ } else {
+ tmp = RREG32(mmCPC_INT_CNTL);
+ tmp = REG_SET_FIELD(tmp, CPC_INT_CNTL,
+ GENERIC2_INT_ENABLE, 1);
+ WREG32(mmCPC_INT_CNTL, tmp);
+
+ tmp = RREG32(target);
+ tmp = REG_SET_FIELD(tmp, CP_ME2_PIPE0_INT_CNTL,
+ GENERIC2_INT_ENABLE, 1);
+ WREG32(target, tmp);
+ }
+ break;
+ default:
+ BUG(); /* kiq only support GENERIC2_INT now */
+ break;
+ }
+ return 0;
+}
+
+static int gfx_v8_0_kiq_irq(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ struct amdgpu_iv_entry *entry)
+{
+ u8 me_id, pipe_id, queue_id;
+ struct amdgpu_ring *ring = (struct amdgpu_ring *)source->data;
+
+ BUG_ON(!ring || (ring->funcs->type != AMDGPU_RING_TYPE_KIQ));
+
+ me_id = (entry->ring_id & 0x0c) >> 2;
+ pipe_id = (entry->ring_id & 0x03) >> 0;
+ queue_id = (entry->ring_id & 0x70) >> 4;
+ DRM_DEBUG("IH: CPC GENERIC2_INT, me:%d, pipe:%d, queue:%d\n",
+ me_id, pipe_id, queue_id);
+
+ amdgpu_fence_process(ring);
+ return 0;
+}
+
static const struct amd_ip_funcs gfx_v8_0_ip_funcs = {
.name = "gfx_v8_0",
.early_init = gfx_v8_0_early_init,
@@ -6423,6 +7003,7 @@ static const struct amd_ip_funcs gfx_v8_0_ip_funcs = {
.post_soft_reset = gfx_v8_0_post_soft_reset,
.set_clockgating_state = gfx_v8_0_set_clockgating_state,
.set_powergating_state = gfx_v8_0_set_powergating_state,
+ .get_clockgating_state = gfx_v8_0_get_clockgating_state,
};
static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
@@ -6440,7 +7021,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
7 + /* gfx_v8_0_ring_emit_pipeline_sync */
128 + 19 + /* gfx_v8_0_ring_emit_vm_flush */
2 + /* gfx_v8_ring_emit_sb */
- 3 + 4, /* gfx_v8_ring_emit_cntxcntl including vgt flush */
+ 3 + 4 + 29, /* gfx_v8_ring_emit_cntxcntl including vgt flush/meta-data */
.emit_ib_size = 4, /* gfx_v8_0_ring_emit_ib_gfx */
.emit_ib = gfx_v8_0_ring_emit_ib_gfx,
.emit_fence = gfx_v8_0_ring_emit_fence_gfx,
@@ -6485,10 +7066,39 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = {
.pad_ib = amdgpu_ring_generic_pad_ib,
};
+static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_kiq = {
+ .type = AMDGPU_RING_TYPE_KIQ,
+ .align_mask = 0xff,
+ .nop = PACKET3(PACKET3_NOP, 0x3FFF),
+ .get_rptr = gfx_v8_0_ring_get_rptr,
+ .get_wptr = gfx_v8_0_ring_get_wptr_compute,
+ .set_wptr = gfx_v8_0_ring_set_wptr_compute,
+ .emit_frame_size =
+ 20 + /* gfx_v8_0_ring_emit_gds_switch */
+ 7 + /* gfx_v8_0_ring_emit_hdp_flush */
+ 5 + /* gfx_v8_0_ring_emit_hdp_invalidate */
+ 7 + /* gfx_v8_0_ring_emit_pipeline_sync */
+ 17 + /* gfx_v8_0_ring_emit_vm_flush */
+ 7 + 7 + 7, /* gfx_v8_0_ring_emit_fence_kiq x3 for user fence, vm fence */
+ .emit_ib_size = 4, /* gfx_v8_0_ring_emit_ib_compute */
+ .emit_ib = gfx_v8_0_ring_emit_ib_compute,
+ .emit_fence = gfx_v8_0_ring_emit_fence_kiq,
+ .emit_hdp_flush = gfx_v8_0_ring_emit_hdp_flush,
+ .emit_hdp_invalidate = gfx_v8_0_ring_emit_hdp_invalidate,
+ .test_ring = gfx_v8_0_ring_test_ring,
+ .test_ib = gfx_v8_0_ring_test_ib,
+ .insert_nop = amdgpu_ring_insert_nop,
+ .pad_ib = amdgpu_ring_generic_pad_ib,
+ .emit_rreg = gfx_v8_0_ring_emit_rreg,
+ .emit_wreg = gfx_v8_0_ring_emit_wreg,
+};
+
static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev)
{
int i;
+ adev->gfx.kiq.ring.funcs = &gfx_v8_0_ring_funcs_kiq;
+
for (i = 0; i < adev->gfx.num_gfx_rings; i++)
adev->gfx.gfx_ring[i].funcs = &gfx_v8_0_ring_funcs_gfx;
@@ -6511,6 +7121,11 @@ static const struct amdgpu_irq_src_funcs gfx_v8_0_priv_inst_irq_funcs = {
.process = gfx_v8_0_priv_inst_irq,
};
+static const struct amdgpu_irq_src_funcs gfx_v8_0_kiq_irq_funcs = {
+ .set = gfx_v8_0_kiq_set_interrupt_state,
+ .process = gfx_v8_0_kiq_irq,
+};
+
static void gfx_v8_0_set_irq_funcs(struct amdgpu_device *adev)
{
adev->gfx.eop_irq.num_types = AMDGPU_CP_IRQ_LAST;
@@ -6521,22 +7136,14 @@ static void gfx_v8_0_set_irq_funcs(struct amdgpu_device *adev)
adev->gfx.priv_inst_irq.num_types = 1;
adev->gfx.priv_inst_irq.funcs = &gfx_v8_0_priv_inst_irq_funcs;
+
+ adev->gfx.kiq.irq.num_types = AMDGPU_CP_KIQ_IRQ_LAST;
+ adev->gfx.kiq.irq.funcs = &gfx_v8_0_kiq_irq_funcs;
}
static void gfx_v8_0_set_rlc_funcs(struct amdgpu_device *adev)
{
- switch (adev->asic_type) {
- case CHIP_TOPAZ:
- adev->gfx.rlc.funcs = &