diff options
Diffstat (limited to 'drivers/gpu/drm')
7411 files changed, 4763475 insertions, 519558 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 43594978958e..7e6bc0b3a589 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -10,11 +10,13 @@ menuconfig DRM depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && HAS_DMA select DRM_PANEL_ORIENTATION_QUIRKS select HDMI - select FB_CMDLINE select I2C - select I2C_ALGOBIT select DMA_SHARED_BUFFER select SYNC_FILE +# gallium uses SYS_kcmp for os_same_file_description() to de-duplicate +# device and dmabuf fd. Let's make sure that is available for our userspace. + select KCMP + select VIDEO help Kernel-level support for the Direct Rendering Infrastructure (DRI) introduced in XFree86 4.0. If you say Y here, you need to select @@ -24,81 +26,115 @@ menuconfig DRM details. You should also select and configure AGP (/dev/agpgart) support if it is available for your platform. +menu "DRM debugging options" +depends on DRM +source "drivers/gpu/drm/Kconfig.debug" +endmenu + +if DRM + config DRM_MIPI_DBI tristate depends on DRM + select DRM_KMS_HELPER config DRM_MIPI_DSI bool depends on DRM -config DRM_DP_AUX_CHARDEV - bool "DRM DP AUX Interface" +config DRM_KMS_HELPER + tristate depends on DRM + select FB_CORE if DRM_FBDEV_EMULATION help - Choose this option to enable a /dev/drm_dp_auxN node that allows to - read and write values to arbitrary DPCD registers on the DP aux - channel. - -config DRM_DEBUG_MM - bool "Insert extra checks and debug info into the DRM range managers" - default n - depends on DRM=y - depends on STACKTRACE_SUPPORT - select STACKDEPOT - help - Enable allocation tracking of memory manager and leak detection on - shutdown. - - Recommended for driver developers only. + CRTC helpers for KMS drivers. - If in doubt, say "N". +config DRM_DRAW + bool + depends on DRM -config DRM_DEBUG_SELFTEST - tristate "kselftests for DRM" +config DRM_PANIC + bool "Display a user-friendly message when a kernel panic occurs" depends on DRM - depends on DEBUG_KERNEL - select PRIME_NUMBERS - select DRM_LIB_RANDOM - select DRM_KMS_HELPER - select DRM_EXPORT_FOR_TESTS if m - default n + select FONT_SUPPORT + select DRM_DRAW help - This option provides kernel modules that can be used to run - various selftests on parts of the DRM api. This option is not - useful for distributions or general kernels, but only for kernel - developers working on DRM and associated drivers. - + Enable a drm panic handler, which will display a user-friendly message + when a kernel panic occurs. It's useful when using a user-space + console instead of fbcon. + It will only work if your graphic driver supports this feature. + To support Hi-DPI Display, you can enable bigger fonts like + FONT_TER16x32 + +config DRM_PANIC_FOREGROUND_COLOR + hex "Drm panic screen foreground color, in RGB" + depends on DRM_PANIC + default 0xffffff + +config DRM_PANIC_BACKGROUND_COLOR + hex "Drm panic screen background color, in RGB" + depends on DRM_PANIC + default 0x000000 + +config DRM_PANIC_DEBUG + bool "Add a debug fs entry to trigger drm_panic" + depends on DRM_PANIC && DEBUG_FS + help + Add dri/[device]/drm_panic_plane_x in the kernel debugfs, to force the + panic handler to write the panic message to this plane scanout buffer. + This is unsafe and should not be enabled on a production build. If in doubt, say "N". -config DRM_KMS_HELPER - tristate - depends on DRM +config DRM_PANIC_SCREEN + string "Panic screen formatter" + default "user" + depends on DRM_PANIC help - CRTC helpers for KMS drivers. - -config DRM_KMS_FB_HELPER - bool - depends on DRM_KMS_HELPER - select FB - select FRAMEBUFFER_CONSOLE if !EXPERT - select FRAMEBUFFER_CONSOLE_DETECT_PRIMARY if FRAMEBUFFER_CONSOLE - select FB_SYS_FOPS - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_DEFERRED_IO + This option enable to choose what will be displayed when a kernel + panic occurs. You can choose between "user", a short message telling + the user to reboot the system, or "kmsg" which will display the last + lines of kmsg. + This can also be overridden by drm.panic_screen=xxxx kernel parameter + or by writing to /sys/module/drm/parameters/panic_screen sysfs entry + Default is "user" + +config DRM_PANIC_SCREEN_QR_CODE + bool "Add a panic screen with a QR code" + depends on DRM_PANIC && RUST + select ZLIB_DEFLATE + help + This option adds a QR code generator, and a panic screen with a QR + code. The QR code will contain the last lines of kmsg and other debug + information. This should be easier for the user to report a kernel + panic, with all debug information available. + To use this panic screen, also set DRM_PANIC_SCREEN to "qr_code" + +config DRM_PANIC_SCREEN_QR_CODE_URL + string "Base URL of the QR code in the panic screen" + depends on DRM_PANIC_SCREEN_QR_CODE help - FBDEV helpers for KMS drivers. + This option sets the base URL to report the kernel panic. If it's set + the QR code will contain the URL and the kmsg compressed with zlib as + a URL parameter. If it's empty, the QR code will contain the kmsg as + uncompressed text only. + There is a demo code in javascript, to decode and uncompress the kmsg + data from the URL parameter at https://github.com/kdj0c/panic_report + +config DRM_PANIC_SCREEN_QR_VERSION + int "Maximum version (size) of the QR code." + depends on DRM_PANIC_SCREEN_QR_CODE + default 40 + help + This option limits the version (or size) of the QR code. QR code + version ranges from Version 1 (21x21) to Version 40 (177x177). + Smaller QR code are easier to read, but will contain less debugging + data. Default is 40. config DRM_DEBUG_DP_MST_TOPOLOGY_REFS bool "Enable refcount backtrace history in the DP MST helpers" depends on STACKTRACE_SUPPORT select STACKDEPOT - depends on DRM_KMS_HELPER + select DRM_KMS_HELPER depends on DEBUG_KERNEL depends on EXPERT help @@ -109,47 +145,31 @@ config DRM_DEBUG_DP_MST_TOPOLOGY_REFS This has the potential to use a lot of memory and print some very large kernel messages. If in doubt, say "N". -config DRM_FBDEV_EMULATION - bool "Enable legacy fbdev support for your modesetting driver" - depends on DRM - select DRM_KMS_HELPER - select DRM_KMS_FB_HELPER - default y +config DRM_DEBUG_MODESET_LOCK + bool "Enable backtrace history for lock contention" + depends on STACKTRACE_SUPPORT + depends on DEBUG_KERNEL + depends on EXPERT + select STACKDEPOT + default y if DEBUG_WW_MUTEX_SLOWPATH help - Choose this option if you have a need for the legacy fbdev - support. Note that this support also provides the linux console - support on top of your modesetting driver. + Enable debug tracing of failures to gracefully handle drm modeset lock + contention. A history of each drm modeset lock path hitting -EDEADLK + will be saved until gracefully handled, and the backtrace will be + printed when attempting to lock a contended lock. - If in doubt, say "Y". - -config DRM_FBDEV_OVERALLOC - int "Overallocation of the fbdev buffer" - depends on DRM_FBDEV_EMULATION - default 100 - help - Defines the fbdev buffer overallocation in percent. Default - is 100. Typical values for double buffering will be 200, - triple buffering 300. + If in doubt, say "N". -config DRM_FBDEV_LEAK_PHYS_SMEM - bool "Shamelessly allow leaking of fbdev physical address (DANGEROUS)" - depends on DRM_FBDEV_EMULATION && EXPERT - default n +config DRM_CLIENT + bool + depends on DRM help - In order to keep user-space compatibility, we want in certain - use-cases to keep leaking the fbdev physical address to the - user-space program handling the fbdev buffer. - This affects, not only, Amlogic, Allwinner or Rockchip devices - with ARM Mali GPUs using an userspace Blob. - This option is not supported by upstream developers and should be - removed as soon as possible and be considered as a broken and - legacy behaviour from a modern fbdev device driver. + Enables support for DRM clients. DRM drivers that need + struct drm_client_dev and its interfaces should select this + option. Drivers that support the default clients should + select DRM_CLIENT_SELECTION instead. - Please send any bug reports when using this to your proprietary - software vendor that requires this. - - If in doubt, say "N" or spread the word to your closed source - library vendor. +source "drivers/gpu/drm/clients/Kconfig" config DRM_LOAD_EDID_FIRMWARE bool "Allow to specify an EDID data set instead of probing for it" @@ -161,33 +181,47 @@ config DRM_LOAD_EDID_FIRMWARE monitor are unable to provide appropriate EDID data. Since this feature is provided as a workaround for broken hardware, the default case is N. Details and instructions how to build your own - EDID data are given in Documentation/driver-api/edid.rst. + EDID data are given in Documentation/admin-guide/edid.rst. -config DRM_DP_CEC - bool "Enable DisplayPort CEC-Tunneling-over-AUX HDMI support" - depends on DRM - select CEC_CORE - help - Choose this option if you want to enable HDMI CEC support for - DisplayPort/USB-C to HDMI adapters. - - Note: not all adapters support this feature, and even for those - that do support this they often do not hook up the CEC pin. +source "drivers/gpu/drm/display/Kconfig" config DRM_TTM tristate depends on DRM && MMU + select SHMEM help GPU memory management subsystem for devices with multiple GPU memory types. Will be enabled automatically if a device driver uses it. -config DRM_TTM_DMA_PAGE_POOL - bool - depends on DRM_TTM && (SWIOTLB || INTEL_IOMMU) - default y +config DRM_EXEC + tristate + depends on DRM + help + Execution context for command submissions + +config DRM_GPUVM + tristate + depends on DRM + select DRM_EXEC help - Choose this if you need the TTM dma page pool + GPU-VM representation providing helpers to manage a GPUs virtual + address space + +config DRM_GPUSVM + tristate + depends on DRM && DEVICE_PRIVATE + select HMM_MIRROR + select MMU_NOTIFIER + help + GPU-SVM representation providing helpers to manage a GPUs shared + virtual memory + +config DRM_BUDDY + tristate + depends on DRM + help + A page based buddy allocator config DRM_VRAM_HELPER tristate @@ -199,102 +233,66 @@ config DRM_TTM_HELPER tristate depends on DRM select DRM_TTM + select DRM_KMS_HELPER if DRM_FBDEV_EMULATION + select FB_CORE if DRM_FBDEV_EMULATION + select FB_SYSMEM_HELPERS_DEFERRED if DRM_FBDEV_EMULATION help Helpers for ttm-based gem objects -config DRM_GEM_CMA_HELPER - bool - depends on DRM - help - Choose this if you need the GEM CMA helper functions - -config DRM_KMS_CMA_HELPER - bool +config DRM_GEM_DMA_HELPER + tristate depends on DRM - select DRM_GEM_CMA_HELPER + select DRM_KMS_HELPER if DRM_FBDEV_EMULATION + select FB_CORE if DRM_FBDEV_EMULATION + select FB_DMAMEM_HELPERS_DEFERRED if DRM_FBDEV_EMULATION help - Choose this if you need the KMS CMA helper functions + Choose this if you need the GEM DMA helper functions config DRM_GEM_SHMEM_HELPER - bool - depends on DRM + tristate + depends on DRM && MMU + select DRM_KMS_HELPER if DRM_FBDEV_EMULATION + select FB_CORE if DRM_FBDEV_EMULATION + select FB_SYSMEM_HELPERS_DEFERRED if DRM_FBDEV_EMULATION help Choose this if you need the GEM shmem helper functions -config DRM_VM - bool - depends on DRM && MMU +config DRM_SUBALLOC_HELPER + tristate + depends on DRM config DRM_SCHED tristate depends on DRM -source "drivers/gpu/drm/i2c/Kconfig" +source "drivers/gpu/drm/sysfb/Kconfig" source "drivers/gpu/drm/arm/Kconfig" -config DRM_RADEON - tristate "ATI Radeon" - depends on DRM && PCI && MMU - select FW_LOADER - select DRM_KMS_HELPER - select DRM_TTM - select POWER_SUPPLY - select HWMON - select BACKLIGHT_CLASS_DEVICE - select INTERVAL_TREE - help - Choose this option if you have an ATI Radeon graphics card. There - are both PCI and AGP versions. You don't need to choose this to - run the Radeon in plain VGA mode. - - If M is selected, the module will be called radeon. - source "drivers/gpu/drm/radeon/Kconfig" -config DRM_AMDGPU - tristate "AMD GPU" - depends on DRM && PCI && MMU - select FW_LOADER - select DRM_KMS_HELPER - select DRM_SCHED - select DRM_TTM - select POWER_SUPPLY - select HWMON - select BACKLIGHT_CLASS_DEVICE - select INTERVAL_TREE - select CHASH - help - Choose this option if you have a recent AMD Radeon graphics card. - - If M is selected, the module will be called amdgpu. - source "drivers/gpu/drm/amd/amdgpu/Kconfig" source "drivers/gpu/drm/nouveau/Kconfig" +source "drivers/gpu/drm/nova/Kconfig" + source "drivers/gpu/drm/i915/Kconfig" +source "drivers/gpu/drm/xe/Kconfig" + +source "drivers/gpu/drm/kmb/Kconfig" + config DRM_VGEM tristate "Virtual GEM provider" - depends on DRM + depends on DRM && MMU + select DRM_GEM_SHMEM_HELPER help Choose this option to get a virtual graphics memory manager, as used by Mesa's software renderer for enhanced performance. If M is selected the module will be called vgem. -config DRM_VKMS - tristate "Virtual KMS (EXPERIMENTAL)" - depends on DRM - select DRM_KMS_HELPER - select CRC32 - default n - help - Virtual Kernel Mode-Setting (VKMS) is used for testing or for - running GPU in a headless machines. Choose this option to get - a VKMS. - - If M is selected the module will be called vkms. +source "drivers/gpu/drm/vkms/Kconfig" source "drivers/gpu/drm/exynos/Kconfig" @@ -310,15 +308,11 @@ source "drivers/gpu/drm/ast/Kconfig" source "drivers/gpu/drm/mgag200/Kconfig" -source "drivers/gpu/drm/cirrus/Kconfig" - source "drivers/gpu/drm/armada/Kconfig" source "drivers/gpu/drm/atmel-hlcdc/Kconfig" -source "drivers/gpu/drm/rcar-du/Kconfig" - -source "drivers/gpu/drm/shmobile/Kconfig" +source "drivers/gpu/drm/renesas/Kconfig" source "drivers/gpu/drm/sun4i/Kconfig" @@ -328,8 +322,6 @@ source "drivers/gpu/drm/tilcdc/Kconfig" source "drivers/gpu/drm/qxl/Kconfig" -source "drivers/gpu/drm/bochs/Kconfig" - source "drivers/gpu/drm/virtio/Kconfig" source "drivers/gpu/drm/msm/Kconfig" @@ -354,15 +346,15 @@ source "drivers/gpu/drm/v3d/Kconfig" source "drivers/gpu/drm/vc4/Kconfig" -source "drivers/gpu/drm/etnaviv/Kconfig" +source "drivers/gpu/drm/loongson/Kconfig" -source "drivers/gpu/drm/arc/Kconfig" +source "drivers/gpu/drm/etnaviv/Kconfig" source "drivers/gpu/drm/hisilicon/Kconfig" -source "drivers/gpu/drm/mediatek/Kconfig" +source "drivers/gpu/drm/logicvc/Kconfig" -source "drivers/gpu/drm/zte/Kconfig" +source "drivers/gpu/drm/mediatek/Kconfig" source "drivers/gpu/drm/mxsfb/Kconfig" @@ -382,98 +374,58 @@ source "drivers/gpu/drm/lima/Kconfig" source "drivers/gpu/drm/panfrost/Kconfig" +source "drivers/gpu/drm/panthor/Kconfig" + source "drivers/gpu/drm/aspeed/Kconfig" source "drivers/gpu/drm/mcde/Kconfig" source "drivers/gpu/drm/tidss/Kconfig" -# Keep legacy drivers last +source "drivers/gpu/drm/adp/Kconfig" -menuconfig DRM_LEGACY - bool "Enable legacy drivers (DANGEROUS)" - 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 - restrictions and other security measures. For backwards compatibility - those drivers are still available, but their use is highly - inadvisable and might harm your system. +source "drivers/gpu/drm/xlnx/Kconfig" - You are recommended to use the safe modeset-only drivers instead, and - perform 3D emulation in user-space. +source "drivers/gpu/drm/gud/Kconfig" - Unless you have strong reasons to go rogue, say "N". +source "drivers/gpu/drm/sitronix/Kconfig" -if DRM_LEGACY +source "drivers/gpu/drm/solomon/Kconfig" -config DRM_TDFX - tristate "3dfx Banshee/Voodoo3+" - depends on DRM && PCI - help - Choose this option if you have a 3dfx Banshee or Voodoo3 (or later), - graphics card. If M is selected, the module will be called tdfx. +source "drivers/gpu/drm/sprd/Kconfig" -config DRM_R128 - tristate "ATI Rage 128" - depends on DRM && PCI - select FW_LOADER - help - Choose this option if you have an ATI Rage 128 graphics card. If M - is selected, the module will be called r128. AGP support for - this card is strongly suggested (unless you have a PCI version). - -config DRM_I810 - tristate "Intel I810" - # !PREEMPTION because of missing ioctl locking - depends on DRM && AGP && AGP_INTEL && (!PREEMPTION || BROKEN) - help - Choose this option if you have an Intel I810 graphics card. If M is - selected, the module will be called i810. AGP support is required - for this driver to work. - -config DRM_MGA - tristate "Matrox g200/g400" - depends on DRM && PCI - select FW_LOADER - help - Choose this option if you have a Matrox G200, G400 or G450 graphics - card. If M is selected, the module will be called mga. AGP - support is required for this driver to work. - -config DRM_SIS - tristate "SiS video cards" - depends on DRM && AGP - depends on FB_SIS || FB_SIS=n - help - Choose this option if you have a SiS 630 or compatible video - chipset. If M is selected the module will be called sis. AGP - support is required for this driver to work. +source "drivers/gpu/drm/imagination/Kconfig" -config DRM_VIA - tristate "Via unichrome video cards" - depends on DRM && PCI - help - Choose this option if you have a Via unichrome or compatible video - chipset. If M is selected the module will be called via. +source "drivers/gpu/drm/tyr/Kconfig" -config DRM_SAVAGE - tristate "Savage video cards" - depends on DRM && PCI +config DRM_HYPERV + tristate "DRM Support for Hyper-V synthetic video device" + depends on DRM && PCI && HYPERV_VMBUS + select DRM_CLIENT_SELECTION + select DRM_KMS_HELPER + select DRM_GEM_SHMEM_HELPER help - Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister - chipset. If M is selected the module will be called savage. - -endif # DRM_LEGACY + This is a KMS driver for Hyper-V synthetic video device. Choose this + option if you would like to enable drm driver for Hyper-V virtual + machine. Unselect Hyper-V framebuffer driver (CONFIG_FB_HYPERV) so + that DRM driver is used by default. -config DRM_EXPORT_FOR_TESTS - bool + If M is selected the module will be called hyperv_drm. -# Separate option because drm_panel_orientation_quirks.c is shared with fbdev -config DRM_PANEL_ORIENTATION_QUIRKS +# Separate option as not all DRM drivers use it +config DRM_PANEL_BACKLIGHT_QUIRKS tristate config DRM_LIB_RANDOM bool default n + +config DRM_PRIVACY_SCREEN + bool + default n + +endif + +# Separate option because drm_panel_orientation_quirks.c is shared with fbdev +config DRM_PANEL_ORIENTATION_QUIRKS + tristate diff --git a/drivers/gpu/drm/Kconfig.debug b/drivers/gpu/drm/Kconfig.debug new file mode 100644 index 000000000000..05dc43c0b8c5 --- /dev/null +++ b/drivers/gpu/drm/Kconfig.debug @@ -0,0 +1,117 @@ +config DRM_USE_DYNAMIC_DEBUG + bool "use dynamic debug to implement drm.debug" + default n + depends on BROKEN + depends on DRM + depends on DYNAMIC_DEBUG || DYNAMIC_DEBUG_CORE + depends on JUMP_LABEL + help + Use dynamic-debug to avoid drm_debug_enabled() runtime overheads. + Due to callsite counts in DRM drivers (~4k in amdgpu) and 56 + bytes per callsite, the .data costs can be substantial, and + are therefore configurable. + +config DRM_WERROR + bool "Compile the drm subsystem with warnings as errors" + depends on DRM && EXPERT + depends on !WERROR + default n + help + A kernel build should not cause any compiler warnings, and this + enables the '-Werror' flag to enforce that rule in the drm subsystem. + + The drm subsystem enables more warnings than the kernel default, so + this config option is disabled by default. + + If in doubt, say N. + +config DRM_HEADER_TEST + bool "Ensure DRM headers are self-contained and pass kernel-doc" + depends on DRM && EXPERT && BROKEN + default n + help + Ensure the DRM subsystem headers both under drivers/gpu/drm and + include/drm compile, are self-contained, have header guards, and have + no kernel-doc warnings. + + If in doubt, say N. + +config DRM_DEBUG_MM + bool "Insert extra checks and debug info into the DRM range managers" + default n + depends on DRM + depends on STACKTRACE_SUPPORT + select STACKDEPOT + help + Enable allocation tracking of memory manager and leak detection on + shutdown. + + Recommended for driver developers only. + + If in doubt, say "N". + +config DRM_KUNIT_TEST_HELPERS + tristate + depends on DRM && KUNIT + select DRM_KMS_HELPER + help + KUnit Helpers for KMS drivers. + +config DRM_KUNIT_TEST + tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS + depends on DRM && KUNIT && MMU + select DRM_BRIDGE_CONNECTOR + select DRM_BUDDY + select DRM_DISPLAY_DP_HELPER + select DRM_DISPLAY_HDMI_STATE_HELPER + select DRM_DISPLAY_HELPER + select DRM_EXEC + select DRM_EXPORT_FOR_TESTS if m + select DRM_GEM_SHMEM_HELPER + select DRM_KUNIT_TEST_HELPERS + select DRM_LIB_RANDOM + select DRM_SYSFB_HELPER + select PRIME_NUMBERS + default KUNIT_ALL_TESTS + help + This builds unit tests for DRM. This option is not useful for + distributions or general kernels, but only for kernel + developers working on DRM and associated drivers. + + For more information on KUnit and unit tests in general, + please refer to the KUnit documentation in + Documentation/dev-tools/kunit/. + + If in doubt, say "N". + +config DRM_TTM_KUNIT_TEST + tristate "KUnit tests for TTM" if !KUNIT_ALL_TESTS + default n + depends on DRM && KUNIT && MMU && (UML || COMPILE_TEST) + select DRM_TTM + select DRM_BUDDY + select DRM_EXPORT_FOR_TESTS if m + select DRM_KUNIT_TEST_HELPERS + default KUNIT_ALL_TESTS + help + Enables unit tests for TTM, a GPU memory manager subsystem used + to manage memory buffers. This option is mostly useful for kernel + developers. It depends on (UML || COMPILE_TEST) since no other driver + which uses TTM can be loaded while running the tests. + + If in doubt, say "N". + +config DRM_SCHED_KUNIT_TEST + tristate "KUnit tests for the DRM scheduler" if !KUNIT_ALL_TESTS + select DRM_SCHED + depends on DRM && KUNIT + default KUNIT_ALL_TESTS + help + Choose this option to build unit tests for the DRM scheduler. + + Recommended for driver developers only. + + If in doubt, say "N". + +config DRM_EXPORT_FOR_TESTS + bool diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 7f72ef5e7811..0e1c668b46d2 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -3,85 +3,188 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -drm-y := drm_auth.o drm_cache.o \ - drm_file.o drm_gem.o drm_ioctl.o drm_irq.o \ - drm_memory.o drm_drv.o \ - drm_sysfs.o drm_hashtab.o drm_mm.o \ - drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \ - drm_encoder_slave.o \ - drm_trace_points.o drm_prime.o \ - drm_rect.o drm_vma_manager.o drm_flip_work.o \ - drm_modeset_lock.o drm_atomic.o drm_bridge.o \ - drm_framebuffer.o drm_connector.o drm_blend.o \ - drm_encoder.o drm_mode_object.o drm_property.o \ - drm_plane.o drm_color_mgmt.o drm_print.o \ - drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \ - drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \ - drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o - -drm-$(CONFIG_DRM_LEGACY) += drm_legacy_misc.o drm_bufs.o drm_context.o drm_dma.o drm_scatter.o drm_lock.o +CFLAGS-$(CONFIG_DRM_USE_DYNAMIC_DEBUG) += -DDYNAMIC_DEBUG_MODULE + +# Unconditionally enable W=1 warnings locally +# --- begin copy-paste W=1 warnings from scripts/Makefile.warn +subdir-ccflags-y += -Wextra -Wunused -Wno-unused-parameter +subdir-ccflags-y += $(call cc-option, -Wrestrict) +subdir-ccflags-y += -Wmissing-format-attribute +subdir-ccflags-y += -Wold-style-definition +subdir-ccflags-y += -Wmissing-include-dirs +subdir-ccflags-y += $(call cc-option, -Wunused-but-set-variable) +subdir-ccflags-y += $(call cc-option, -Wunused-const-variable) +subdir-ccflags-y += $(call cc-option, -Wpacked-not-aligned) +subdir-ccflags-y += $(call cc-option, -Wformat-overflow) +# FIXME: fix -Wformat-truncation warnings and uncomment +#subdir-ccflags-y += $(call cc-option, -Wformat-truncation) +subdir-ccflags-y += $(call cc-option, -Wstringop-truncation) +# The following turn off the warnings enabled by -Wextra +ifeq ($(findstring 2, $(KBUILD_EXTRA_WARN)),) +subdir-ccflags-y += -Wno-missing-field-initializers +subdir-ccflags-y += -Wno-type-limits +subdir-ccflags-y += -Wno-shift-negative-value +endif +ifeq ($(findstring 3, $(KBUILD_EXTRA_WARN)),) +subdir-ccflags-y += -Wno-sign-compare +endif +# --- end copy-paste + +# Enable -Werror in CI and development +subdir-ccflags-$(CONFIG_DRM_WERROR) += -Werror + +drm-y := \ + drm_atomic.o \ + drm_atomic_uapi.o \ + drm_auth.o \ + drm_blend.o \ + drm_bridge.o \ + drm_cache.o \ + drm_color_mgmt.o \ + drm_colorop.o \ + drm_connector.o \ + drm_crtc.o \ + drm_displayid.o \ + drm_drv.o \ + drm_dumb_buffers.o \ + drm_edid.o \ + drm_eld.o \ + drm_encoder.o \ + drm_file.o \ + drm_fourcc.o \ + drm_framebuffer.o \ + drm_gem.o \ + drm_ioctl.o \ + drm_lease.o \ + drm_managed.o \ + drm_mm.o \ + drm_mode_config.o \ + drm_mode_object.o \ + drm_modes.o \ + drm_modeset_lock.o \ + drm_plane.o \ + drm_prime.o \ + drm_print.o \ + drm_property.o \ + drm_rect.o \ + drm_syncobj.o \ + drm_sysfs.o \ + drm_trace_points.o \ + drm_vblank.o \ + drm_vblank_work.o \ + drm_vma_manager.o \ + drm_writeback.o +drm-$(CONFIG_DRM_CLIENT) += \ + drm_client.o \ + drm_client_event.o \ + drm_client_modeset.o \ + drm_client_sysrq.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_DRM_GEM_SHMEM_HELPER) += drm_gem_shmem_helper.o drm-$(CONFIG_DRM_PANEL) += drm_panel.o drm-$(CONFIG_OF) += drm_of.o -drm-$(CONFIG_AGP) += drm_agpsupport.o drm-$(CONFIG_PCI) += drm_pci.o -drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o +drm-$(CONFIG_DEBUG_FS) += \ + drm_debugfs.o \ + drm_debugfs_crc.o drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o +drm-$(CONFIG_DRM_PRIVACY_SCREEN) += \ + drm_privacy_screen.o \ + drm_privacy_screen_x86.o +drm-$(CONFIG_DRM_ACCEL) += ../../accel/drm_accel.o +drm-$(CONFIG_DRM_PANIC) += drm_panic.o +drm-$(CONFIG_DRM_DRAW) += drm_draw.o +drm-$(CONFIG_DRM_PANIC_SCREEN_QR_CODE) += drm_panic_qr.o +obj-$(CONFIG_DRM) += drm.o + +obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o +obj-$(CONFIG_DRM_PANEL_BACKLIGHT_QUIRKS) += drm_panel_backlight_quirks.o + +# +# Memory-management helpers +# +# +obj-$(CONFIG_DRM_EXEC) += drm_exec.o +obj-$(CONFIG_DRM_GPUVM) += drm_gpuvm.o + +drm_gpusvm_helper-y := \ + drm_gpusvm.o\ + drm_pagemap.o +obj-$(CONFIG_DRM_GPUSVM) += drm_gpusvm_helper.o + +obj-$(CONFIG_DRM_BUDDY) += drm_buddy.o + +drm_dma_helper-y := drm_gem_dma_helper.o +drm_dma_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fbdev_dma.o +drm_dma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_dma_helper.o +obj-$(CONFIG_DRM_GEM_DMA_HELPER) += drm_dma_helper.o + +drm_shmem_helper-y := drm_gem_shmem_helper.o +drm_shmem_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fbdev_shmem.o +obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o -drm_vram_helper-y := drm_gem_vram_helper.o \ - drm_vram_helper_common.o +drm_suballoc_helper-y := drm_suballoc.o +obj-$(CONFIG_DRM_SUBALLOC_HELPER) += drm_suballoc_helper.o + +drm_vram_helper-y := drm_gem_vram_helper.o obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o drm_ttm_helper-y := drm_gem_ttm_helper.o +drm_ttm_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fbdev_ttm.o obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o -drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o drm_dp_helper.o \ - drm_dsc.o drm_probe_helper.o \ - drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ - drm_kms_helper_common.o drm_dp_dual_mode_helper.o \ - drm_simple_kms_helper.o drm_modeset_helper.o \ - drm_scdc_helper.o drm_gem_framebuffer_helper.o \ - drm_atomic_state_helper.o drm_damage_helper.o \ - drm_format_helper.o drm_self_refresh_helper.o +# +# Modesetting helpers +# +drm_kms_helper-y := \ + drm_atomic_helper.o \ + drm_atomic_state_helper.o \ + drm_bridge_helper.o \ + drm_crtc_helper.o \ + drm_damage_helper.o \ + drm_flip_work.o \ + drm_format_helper.o \ + drm_gem_atomic_helper.o \ + drm_gem_framebuffer_helper.o \ + drm_kms_helper_common.o \ + drm_modeset_helper.o \ + drm_plane_helper.o \ + drm_probe_helper.o \ + drm_self_refresh_helper.o \ + drm_simple_kms_helper.o \ + drm_vblank_helper.o drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o -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 -drm_kms_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o - obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/ -obj-$(CONFIG_DRM) += drm.o +# +# Drivers and the rest +# + +obj-y += tests/ + obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o -obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o obj-y += arm/ +obj-y += clients/ +obj-y += display/ obj-$(CONFIG_DRM_TTM) += ttm/ obj-$(CONFIG_DRM_SCHED) += scheduler/ -obj-$(CONFIG_DRM_TDFX) += tdfx/ -obj-$(CONFIG_DRM_R128) += r128/ obj-$(CONFIG_DRM_RADEON)+= radeon/ obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/ -obj-$(CONFIG_DRM_MGA) += mga/ -obj-$(CONFIG_DRM_I810) += i810/ +obj-$(CONFIG_DRM_AMDGPU)+= amd/amdxcp/ obj-$(CONFIG_DRM_I915) += i915/ +obj-$(CONFIG_DRM_XE) += xe/ +obj-$(CONFIG_DRM_KMB_DISPLAY) += kmb/ obj-$(CONFIG_DRM_MGAG200) += mgag200/ obj-$(CONFIG_DRM_V3D) += v3d/ obj-$(CONFIG_DRM_VC4) += vc4/ -obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus/ -obj-$(CONFIG_DRM_SIS) += sis/ -obj-$(CONFIG_DRM_SAVAGE)+= savage/ obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/ -obj-$(CONFIG_DRM_VIA) +=via/ obj-$(CONFIG_DRM_VGEM) += vgem/ obj-$(CONFIG_DRM_VKMS) += vkms/ obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/ +obj-$(CONFIG_DRM_NOVA) += nova/ obj-$(CONFIG_DRM_EXYNOS) +=exynos/ obj-$(CONFIG_DRM_ROCKCHIP) +=rockchip/ obj-$(CONFIG_DRM_GMA500) += gma500/ @@ -89,38 +192,64 @@ obj-$(CONFIG_DRM_UDL) += udl/ obj-$(CONFIG_DRM_AST) += ast/ obj-$(CONFIG_DRM_ARMADA) += armada/ obj-$(CONFIG_DRM_ATMEL_HLCDC) += atmel-hlcdc/ -obj-y += rcar-du/ -obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/ +obj-y += renesas/ obj-y += omapdrm/ obj-$(CONFIG_DRM_SUN4I) += sun4i/ obj-y += tilcdc/ obj-$(CONFIG_DRM_QXL) += qxl/ -obj-$(CONFIG_DRM_BOCHS) += bochs/ obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio/ obj-$(CONFIG_DRM_MSM) += msm/ obj-$(CONFIG_DRM_TEGRA) += tegra/ obj-$(CONFIG_DRM_STM) += stm/ obj-$(CONFIG_DRM_STI) += sti/ -obj-$(CONFIG_DRM_IMX) += imx/ +obj-y += imx/ obj-$(CONFIG_DRM_INGENIC) += ingenic/ +obj-$(CONFIG_DRM_LOGICVC) += logicvc/ obj-$(CONFIG_DRM_MEDIATEK) += mediatek/ obj-$(CONFIG_DRM_MESON) += meson/ -obj-y += i2c/ obj-y += panel/ obj-y += bridge/ obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/ obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/ -obj-$(CONFIG_DRM_ARCPGU)+= arc/ obj-y += hisilicon/ -obj-$(CONFIG_DRM_ZTE) += zte/ -obj-$(CONFIG_DRM_MXSFB) += mxsfb/ +obj-y += mxsfb/ +obj-y += sysfb/ obj-y += tiny/ obj-$(CONFIG_DRM_PL111) += pl111/ obj-$(CONFIG_DRM_TVE200) += tve200/ +obj-$(CONFIG_DRM_ADP) += adp/ obj-$(CONFIG_DRM_XEN) += xen/ obj-$(CONFIG_DRM_VBOXVIDEO) += vboxvideo/ obj-$(CONFIG_DRM_LIMA) += lima/ obj-$(CONFIG_DRM_PANFROST) += panfrost/ +obj-$(CONFIG_DRM_PANTHOR) += panthor/ +obj-$(CONFIG_DRM_TYR) += tyr/ obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/ obj-$(CONFIG_DRM_MCDE) += mcde/ obj-$(CONFIG_DRM_TIDSS) += tidss/ +obj-y += xlnx/ +obj-y += gud/ +obj-$(CONFIG_DRM_HYPERV) += hyperv/ +obj-y += sitronix/ +obj-y += solomon/ +obj-$(CONFIG_DRM_SPRD) += sprd/ +obj-$(CONFIG_DRM_LOONGSON) += loongson/ +obj-$(CONFIG_DRM_POWERVR) += imagination/ + +# Ensure drm headers are self-contained and pass kernel-doc +hdrtest-files := \ + $(shell cd $(src) && find . -maxdepth 1 -name 'drm_*.h') \ + $(shell cd $(src) && find display lib -name '*.h') + +always-$(CONFIG_DRM_HEADER_TEST) += \ + $(patsubst %.h,%.hdrtest, $(hdrtest-files)) + +# Include the header twice to detect missing include guard. +quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@) + cmd_hdrtest = \ + $(CC) $(c_flags) -fsyntax-only -x c /dev/null -include $< -include $<; \ + PYTHONDONTWRITEBYTECODE=1 $(PYTHON3) $(KERNELDOC) -none $(if $(CONFIG_WERROR)$(CONFIG_DRM_WERROR),-Werror) $<; \ + touch $@ + +$(obj)/%.hdrtest: $(src)/%.h FORCE + $(call if_changed_dep,hdrtest) diff --git a/drivers/gpu/drm/adp/Kconfig b/drivers/gpu/drm/adp/Kconfig new file mode 100644 index 000000000000..9fcc27eb200d --- /dev/null +++ b/drivers/gpu/drm/adp/Kconfig @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-only OR MIT +config DRM_ADP + tristate "DRM Support for pre-DCP Apple display controllers" + depends on DRM && OF && ARM64 + depends on ARCH_APPLE || COMPILE_TEST + select DRM_KMS_HELPER + select DRM_BRIDGE_CONNECTOR + select DRM_DISPLAY_HELPER + select DRM_KMS_DMA_HELPER + select DRM_GEM_DMA_HELPER + select DRM_PANEL_BRIDGE + select VIDEOMODE_HELPERS + select DRM_MIPI_DSI + help + Chose this option if you have an Apple Arm laptop with a touchbar. + + If M is selected, this module will be called adpdrm. diff --git a/drivers/gpu/drm/adp/Makefile b/drivers/gpu/drm/adp/Makefile new file mode 100644 index 000000000000..8e7b618edd35 --- /dev/null +++ b/drivers/gpu/drm/adp/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only OR MIT + +adpdrm-y := adp_drv.o +adpdrm-mipi-y := adp-mipi.o +obj-$(CONFIG_DRM_ADP) += adpdrm.o adpdrm-mipi.o diff --git a/drivers/gpu/drm/adp/adp-mipi.c b/drivers/gpu/drm/adp/adp-mipi.c new file mode 100644 index 000000000000..cba7d32150a9 --- /dev/null +++ b/drivers/gpu/drm/adp/adp-mipi.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <linux/component.h> +#include <linux/iopoll.h> +#include <linux/of.h> +#include <linux/platform_device.h> + +#include <drm/drm_bridge.h> +#include <drm/drm_mipi_dsi.h> + +#define DSI_GEN_HDR 0x6c +#define DSI_GEN_PLD_DATA 0x70 + +#define DSI_CMD_PKT_STATUS 0x74 + +#define GEN_PLD_R_EMPTY BIT(4) +#define GEN_PLD_W_FULL BIT(3) +#define GEN_PLD_W_EMPTY BIT(2) +#define GEN_CMD_FULL BIT(1) +#define GEN_CMD_EMPTY BIT(0) +#define GEN_RD_CMD_BUSY BIT(6) +#define CMD_PKT_STATUS_TIMEOUT_US 20000 + +struct adp_mipi_drv_private { + struct mipi_dsi_host dsi; + struct drm_bridge bridge; + struct drm_bridge *next_bridge; + void __iomem *mipi; +}; + +#define mipi_to_adp(x) container_of(x, struct adp_mipi_drv_private, dsi) + +static int adp_dsi_gen_pkt_hdr_write(struct adp_mipi_drv_private *adp, u32 hdr_val) +{ + int ret; + u32 val, mask; + + ret = readl_poll_timeout(adp->mipi + DSI_CMD_PKT_STATUS, + val, !(val & GEN_CMD_FULL), 1000, + CMD_PKT_STATUS_TIMEOUT_US); + if (ret) { + dev_err(adp->dsi.dev, "failed to get available command FIFO\n"); + return ret; + } + + writel(hdr_val, adp->mipi + DSI_GEN_HDR); + + mask = GEN_CMD_EMPTY | GEN_PLD_W_EMPTY; + ret = readl_poll_timeout(adp->mipi + DSI_CMD_PKT_STATUS, + val, (val & mask) == mask, + 1000, CMD_PKT_STATUS_TIMEOUT_US); + if (ret) { + dev_err(adp->dsi.dev, "failed to write command FIFO\n"); + return ret; + } + + return 0; +} + +static int adp_dsi_write(struct adp_mipi_drv_private *adp, + const struct mipi_dsi_packet *packet) +{ + const u8 *tx_buf = packet->payload; + int len = packet->payload_length, pld_data_bytes = sizeof(u32), ret; + __le32 word; + u32 val; + + while (len) { + if (len < pld_data_bytes) { + word = 0; + memcpy(&word, tx_buf, len); + writel(le32_to_cpu(word), adp->mipi + DSI_GEN_PLD_DATA); + len = 0; + } else { + memcpy(&word, tx_buf, pld_data_bytes); + writel(le32_to_cpu(word), adp->mipi + DSI_GEN_PLD_DATA); + tx_buf += pld_data_bytes; + len -= pld_data_bytes; + } + + ret = readl_poll_timeout(adp->mipi + DSI_CMD_PKT_STATUS, + val, !(val & GEN_PLD_W_FULL), 1000, + CMD_PKT_STATUS_TIMEOUT_US); + if (ret) { + dev_err(adp->dsi.dev, + "failed to get available write payload FIFO\n"); + return ret; + } + } + + word = 0; + memcpy(&word, packet->header, sizeof(packet->header)); + return adp_dsi_gen_pkt_hdr_write(adp, le32_to_cpu(word)); +} + +static int adp_dsi_read(struct adp_mipi_drv_private *adp, + const struct mipi_dsi_msg *msg) +{ + int i, j, ret, len = msg->rx_len; + u8 *buf = msg->rx_buf; + u32 val; + + /* Wait end of the read operation */ + ret = readl_poll_timeout(adp->mipi + DSI_CMD_PKT_STATUS, + val, !(val & GEN_RD_CMD_BUSY), + 1000, CMD_PKT_STATUS_TIMEOUT_US); + if (ret) { + dev_err(adp->dsi.dev, "Timeout during read operation\n"); + return ret; + } + + for (i = 0; i < len; i += 4) { + /* Read fifo must not be empty before all bytes are read */ + ret = readl_poll_timeout(adp->mipi + DSI_CMD_PKT_STATUS, + val, !(val & GEN_PLD_R_EMPTY), + 1000, CMD_PKT_STATUS_TIMEOUT_US); + if (ret) { + dev_err(adp->dsi.dev, "Read payload FIFO is empty\n"); + return ret; + } + + val = readl(adp->mipi + DSI_GEN_PLD_DATA); + for (j = 0; j < 4 && j + i < len; j++) + buf[i + j] = val >> (8 * j); + } + + return ret; +} + +static ssize_t adp_dsi_host_transfer(struct mipi_dsi_host *host, + const struct mipi_dsi_msg *msg) +{ + struct adp_mipi_drv_private *adp = mipi_to_adp(host); + struct mipi_dsi_packet packet; + int ret, nb_bytes; + + ret = mipi_dsi_create_packet(&packet, msg); + if (ret) { + dev_err(adp->dsi.dev, "failed to create packet: %d\n", ret); + return ret; + } + + ret = adp_dsi_write(adp, &packet); + if (ret) + return ret; + + if (msg->rx_buf && msg->rx_len) { + ret = adp_dsi_read(adp, msg); + if (ret) + return ret; + nb_bytes = msg->rx_len; + } else { + nb_bytes = packet.size; + } + + return nb_bytes; +} + +static int adp_dsi_bind(struct device *dev, struct device *master, void *data) +{ + return 0; +} + +static void adp_dsi_unbind(struct device *dev, struct device *master, void *data) +{ +} + +static const struct component_ops adp_dsi_component_ops = { + .bind = adp_dsi_bind, + .unbind = adp_dsi_unbind, +}; + +static int adp_dsi_host_attach(struct mipi_dsi_host *host, + struct mipi_dsi_device *dev) +{ + struct adp_mipi_drv_private *adp = mipi_to_adp(host); + struct drm_bridge *next; + int ret; + + next = devm_drm_of_get_bridge(adp->dsi.dev, adp->dsi.dev->of_node, 1, 0); + if (IS_ERR(next)) + return PTR_ERR(next); + + adp->next_bridge = next; + + drm_bridge_add(&adp->bridge); + + ret = component_add(host->dev, &adp_dsi_component_ops); + if (ret) { + pr_err("failed to add dsi_host component: %d\n", ret); + drm_bridge_remove(&adp->bridge); + return ret; + } + + return 0; +} + +static int adp_dsi_host_detach(struct mipi_dsi_host *host, + struct mipi_dsi_device *dev) +{ + struct adp_mipi_drv_private *adp = mipi_to_adp(host); + + component_del(host->dev, &adp_dsi_component_ops); + drm_bridge_remove(&adp->bridge); + return 0; +} + +static const struct mipi_dsi_host_ops adp_dsi_host_ops = { + .transfer = adp_dsi_host_transfer, + .attach = adp_dsi_host_attach, + .detach = adp_dsi_host_detach, +}; + +static int adp_dsi_bridge_attach(struct drm_bridge *bridge, + struct drm_encoder *encoder, + enum drm_bridge_attach_flags flags) +{ + struct adp_mipi_drv_private *adp = + container_of(bridge, struct adp_mipi_drv_private, bridge); + + return drm_bridge_attach(encoder, adp->next_bridge, bridge, flags); +} + +static const struct drm_bridge_funcs adp_dsi_bridge_funcs = { + .attach = adp_dsi_bridge_attach, +}; + +static int adp_mipi_probe(struct platform_device *pdev) +{ + struct adp_mipi_drv_private *adp; + + adp = devm_drm_bridge_alloc(&pdev->dev, struct adp_mipi_drv_private, + bridge, &adp_dsi_bridge_funcs); + if (IS_ERR(adp)) + return PTR_ERR(adp); + + adp->mipi = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(adp->mipi)) { + dev_err(&pdev->dev, "failed to map mipi mmio"); + return PTR_ERR(adp->mipi); + } + + adp->dsi.dev = &pdev->dev; + adp->dsi.ops = &adp_dsi_host_ops; + adp->bridge.of_node = pdev->dev.of_node; + adp->bridge.type = DRM_MODE_CONNECTOR_DSI; + dev_set_drvdata(&pdev->dev, adp); + return mipi_dsi_host_register(&adp->dsi); +} + +static void adp_mipi_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct adp_mipi_drv_private *adp = dev_get_drvdata(dev); + + mipi_dsi_host_unregister(&adp->dsi); +} + +static const struct of_device_id adp_mipi_of_match[] = { + { .compatible = "apple,h7-display-pipe-mipi", }, + { }, +}; +MODULE_DEVICE_TABLE(of, adp_mipi_of_match); + +static struct platform_driver adp_mipi_platform_driver = { + .driver = { + .name = "adp-mipi", + .of_match_table = adp_mipi_of_match, + }, + .probe = adp_mipi_probe, + .remove = adp_mipi_remove, +}; + +module_platform_driver(adp_mipi_platform_driver); + +MODULE_DESCRIPTION("Apple Display Pipe MIPI driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/adp/adp_drv.c b/drivers/gpu/drm/adp/adp_drv.c new file mode 100644 index 000000000000..4554cf75565e --- /dev/null +++ b/drivers/gpu/drm/adp/adp_drv.c @@ -0,0 +1,614 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <linux/component.h> +#include <linux/iopoll.h> +#include <linux/of.h> +#include <linux/platform_device.h> + +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_bridge.h> +#include <drm/drm_bridge_connector.h> +#include <drm/drm_drv.h> +#include <drm/drm_fb_dma_helper.h> +#include <drm/drm_framebuffer.h> +#include <drm/drm_gem_atomic_helper.h> +#include <drm/drm_gem_dma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_of.h> +#include <drm/drm_print.h> +#include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> + +#define ADP_INT_STATUS 0x34 +#define ADP_INT_STATUS_INT_MASK 0x7 +#define ADP_INT_STATUS_VBLANK 0x1 +#define ADP_CTRL 0x100 +#define ADP_CTRL_VBLANK_ON 0x12 +#define ADP_CTRL_FIFO_ON 0x601 +#define ADP_SCREEN_SIZE 0x0c +#define ADP_SCREEN_HSIZE GENMASK(15, 0) +#define ADP_SCREEN_VSIZE GENMASK(31, 16) + +#define ADBE_FIFO 0x10c0 +#define ADBE_FIFO_SYNC 0xc0000000 + +#define ADBE_BLEND_BYPASS 0x2020 +#define ADBE_BLEND_EN1 0x2028 +#define ADBE_BLEND_EN2 0x2074 +#define ADBE_BLEND_EN3 0x202c +#define ADBE_BLEND_EN4 0x2034 +#define ADBE_MASK_BUF 0x2200 + +#define ADBE_SRC_START 0x4040 +#define ADBE_SRC_SIZE 0x4048 +#define ADBE_DST_START 0x4050 +#define ADBE_DST_SIZE 0x4054 +#define ADBE_STRIDE 0x4038 +#define ADBE_FB_BASE 0x4030 + +#define ADBE_LAYER_EN1 0x4020 +#define ADBE_LAYER_EN2 0x4068 +#define ADBE_LAYER_EN3 0x40b4 +#define ADBE_LAYER_EN4 0x40f4 +#define ADBE_SCALE_CTL 0x40ac +#define ADBE_SCALE_CTL_BYPASS 0x100000 + +#define ADBE_LAYER_CTL 0x1038 +#define ADBE_LAYER_CTL_ENABLE 0x10000 + +#define ADBE_PIX_FMT 0x402c +#define ADBE_PIX_FMT_XRGB32 0x53e4001 + +static int adp_open(struct inode *inode, struct file *filp) +{ + /* + * The modesetting driver does not check the non-desktop connector + * property and keeps the device open and locked. If the touchbar daemon + * opens the device first, modesetting breaks the whole X session. + * Simply refuse to open the device for X11 server processes as + * workaround. + */ + if (current->comm[0] == 'X') + return -EBUSY; + + return drm_open(inode, filp); +} + +static const struct file_operations adp_fops = { + .owner = THIS_MODULE, + .open = adp_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, + .compat_ioctl = drm_compat_ioctl, + .poll = drm_poll, + .read = drm_read, + .llseek = noop_llseek, + .mmap = drm_gem_mmap, + .fop_flags = FOP_UNSIGNED_OFFSET, + DRM_GEM_DMA_UNMAPPED_AREA_FOPS +}; + +static int adp_drm_gem_dumb_create(struct drm_file *file_priv, + struct drm_device *drm, + struct drm_mode_create_dumb *args) +{ + args->height = ALIGN(args->height, 64); + args->size = args->pitch * args->height; + + return drm_gem_dma_dumb_create_internal(file_priv, drm, args); +} + +static const struct drm_driver adp_driver = { + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, + .fops = &adp_fops, + DRM_GEM_DMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE(adp_drm_gem_dumb_create), + .name = "adp", + .desc = "Apple Display Pipe DRM Driver", + .major = 0, + .minor = 1, +}; + +struct adp_drv_private { + struct drm_device drm; + struct drm_crtc crtc; + struct drm_encoder *encoder; + struct drm_connector *connector; + struct drm_bridge *next_bridge; + void __iomem *be; + void __iomem *fe; + u32 *mask_buf; + u64 mask_buf_size; + dma_addr_t mask_iova; + int be_irq; + int fe_irq; + struct drm_pending_vblank_event *event; +}; + +#define to_adp(x) container_of(x, struct adp_drv_private, drm) +#define crtc_to_adp(x) container_of(x, struct adp_drv_private, crtc) + +static int adp_plane_atomic_check(struct drm_plane *plane, + struct drm_atomic_state *state) +{ + struct drm_plane_state *new_plane_state; + struct drm_crtc_state *crtc_state; + + new_plane_state = drm_atomic_get_new_plane_state(state, plane); + + if (!new_plane_state->crtc) + return 0; + + crtc_state = drm_atomic_get_crtc_state(state, new_plane_state->crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + return drm_atomic_helper_check_plane_state(new_plane_state, + crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + true, true); +} + +static void adp_plane_atomic_update(struct drm_plane *plane, + struct drm_atomic_state *state) +{ + struct adp_drv_private *adp; + struct drm_rect src_rect; + struct drm_gem_dma_object *obj; + struct drm_framebuffer *fb; + struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane); + u32 src_pos, src_size, dst_pos, dst_size; + + if (!plane || !new_state) + return; + + fb = new_state->fb; + if (!fb) + return; + adp = to_adp(plane->dev); + + drm_rect_fp_to_int(&src_rect, &new_state->src); + src_pos = src_rect.x1 << 16 | src_rect.y1; + dst_pos = new_state->dst.x1 << 16 | new_state->dst.y1; + src_size = drm_rect_width(&src_rect) << 16 | drm_rect_height(&src_rect); + dst_size = drm_rect_width(&new_state->dst) << 16 | + drm_rect_height(&new_state->dst); + writel(src_pos, adp->be + ADBE_SRC_START); + writel(src_size, adp->be + ADBE_SRC_SIZE); + writel(dst_pos, adp->be + ADBE_DST_START); + writel(dst_size, adp->be + ADBE_DST_SIZE); + writel(fb->pitches[0], adp->be + ADBE_STRIDE); + obj = drm_fb_dma_get_gem_obj(fb, 0); + if (obj) + writel(obj->dma_addr + fb->offsets[0], adp->be + ADBE_FB_BASE); + + writel(BIT(0), adp->be + ADBE_LAYER_EN1); + writel(BIT(0), adp->be + ADBE_LAYER_EN2); + writel(BIT(0), adp->be + ADBE_LAYER_EN3); + writel(BIT(0), adp->be + ADBE_LAYER_EN4); + writel(ADBE_SCALE_CTL_BYPASS, adp->be + ADBE_SCALE_CTL); + writel(ADBE_LAYER_CTL_ENABLE | BIT(0), adp->be + ADBE_LAYER_CTL); + writel(ADBE_PIX_FMT_XRGB32, adp->be + ADBE_PIX_FMT); +} + +static void adp_plane_atomic_disable(struct drm_plane *plane, + struct drm_atomic_state *state) +{ + struct adp_drv_private *adp = to_adp(plane->dev); + + writel(0x0, adp->be + ADBE_LAYER_EN1); + writel(0x0, adp->be + ADBE_LAYER_EN2); + writel(0x0, adp->be + ADBE_LAYER_EN3); + writel(0x0, adp->be + ADBE_LAYER_EN4); + writel(ADBE_LAYER_CTL_ENABLE, adp->be + ADBE_LAYER_CTL); +} + +static const struct drm_plane_helper_funcs adp_plane_helper_funcs = { + .atomic_check = adp_plane_atomic_check, + .atomic_update = adp_plane_atomic_update, + .atomic_disable = adp_plane_atomic_disable, + DRM_GEM_SHADOW_PLANE_HELPER_FUNCS +}; + +static const struct drm_plane_funcs adp_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + DRM_GEM_SHADOW_PLANE_FUNCS +}; + +static const u32 plane_formats[] = { + DRM_FORMAT_XRGB8888, +}; + +#define ALL_CRTCS 1 + +static struct drm_plane *adp_plane_new(struct adp_drv_private *adp) +{ + struct drm_device *drm = &adp->drm; + struct drm_plane *plane; + + plane = __drmm_universal_plane_alloc(drm, sizeof(struct drm_plane), 0, + ALL_CRTCS, &adp_plane_funcs, + plane_formats, ARRAY_SIZE(plane_formats), + NULL, DRM_PLANE_TYPE_PRIMARY, "plane"); + if (IS_ERR(plane)) { + drm_err(drm, "failed to allocate plane"); + return plane; + } + + drm_plane_helper_add(plane, &adp_plane_helper_funcs); + return plane; +} + +static void adp_enable_vblank(struct adp_drv_private *adp) +{ + u32 cur_ctrl; + + writel(ADP_INT_STATUS_INT_MASK, adp->fe + ADP_INT_STATUS); + + cur_ctrl = readl(adp->fe + ADP_CTRL); + writel(cur_ctrl | ADP_CTRL_VBLANK_ON, adp->fe + ADP_CTRL); +} + +static int adp_crtc_enable_vblank(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct adp_drv_private *adp = to_adp(dev); + + adp_enable_vblank(adp); + + return 0; +} + +static void adp_disable_vblank(struct adp_drv_private *adp) +{ + u32 cur_ctrl; + + cur_ctrl = readl(adp->fe + ADP_CTRL); + writel(cur_ctrl & ~ADP_CTRL_VBLANK_ON, adp->fe + ADP_CTRL); + writel(ADP_INT_STATUS_INT_MASK, adp->fe + ADP_INT_STATUS); +} + +static void adp_crtc_disable_vblank(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct adp_drv_private *adp = to_adp(dev); + + adp_disable_vblank(adp); +} + +static void adp_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_state *state) +{ + struct adp_drv_private *adp = crtc_to_adp(crtc); + + writel(BIT(0), adp->be + ADBE_BLEND_EN2); + writel(BIT(4), adp->be + ADBE_BLEND_EN1); + writel(BIT(0), adp->be + ADBE_BLEND_EN3); + writel(BIT(0), adp->be + ADBE_BLEND_BYPASS); + writel(BIT(0), adp->be + ADBE_BLEND_EN4); + drm_crtc_vblank_on(crtc); +} + +static void adp_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_state *state) +{ + struct adp_drv_private *adp = crtc_to_adp(crtc); + struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state, crtc); + + drm_atomic_helper_disable_planes_on_crtc(old_state, false); + + writel(0x0, adp->be + ADBE_BLEND_EN2); + writel(0x0, adp->be + ADBE_BLEND_EN1); + writel(0x0, adp->be + ADBE_BLEND_EN3); + writel(0x0, adp->be + ADBE_BLEND_BYPASS); + writel(0x0, adp->be + ADBE_BLEND_EN4); + drm_crtc_vblank_off(crtc); +} + +static void adp_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_atomic_state *state) +{ + u32 frame_num = 1; + unsigned long flags; + struct adp_drv_private *adp = crtc_to_adp(crtc); + struct drm_crtc_state *new_state = drm_atomic_get_new_crtc_state(state, crtc); + u64 new_size = ALIGN(new_state->mode.hdisplay * + new_state->mode.vdisplay * 4, PAGE_SIZE); + + if (new_size != adp->mask_buf_size) { + if (adp->mask_buf) + dma_free_coherent(crtc->dev->dev, adp->mask_buf_size, + adp->mask_buf, adp->mask_iova); + adp->mask_buf = NULL; + if (new_size != 0) { + adp->mask_buf = dma_alloc_coherent(crtc->dev->dev, new_size, + &adp->mask_iova, GFP_KERNEL); + memset(adp->mask_buf, 0xFF, new_size); + writel(adp->mask_iova, adp->be + ADBE_MASK_BUF); + } + adp->mask_buf_size = new_size; + } + writel(ADBE_FIFO_SYNC | frame_num, adp->be + ADBE_FIFO); + //FIXME: use adbe flush interrupt + if (crtc->state->event) { + struct drm_pending_vblank_event *event = crtc->state->event; + + crtc->state->event = NULL; + spin_lock_irqsave(&crtc->dev->event_lock, flags); + + if (drm_crtc_vblank_get(crtc) != 0) + drm_crtc_send_vblank_event(crtc, event); + else + adp->event = event; + + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + } +} + +static const struct drm_crtc_funcs adp_crtc_funcs = { + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .reset = drm_atomic_helper_crtc_reset, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .enable_vblank = adp_crtc_enable_vblank, + .disable_vblank = adp_crtc_disable_vblank, +}; + + +static const struct drm_crtc_helper_funcs adp_crtc_helper_funcs = { + .atomic_enable = adp_crtc_atomic_enable, + .atomic_disable = adp_crtc_atomic_disable, + .atomic_flush = adp_crtc_atomic_flush, +}; + +static int adp_setup_crtc(struct adp_drv_private *adp) +{ + struct drm_device *drm = &adp->drm; + struct drm_plane *primary; + int ret; + + primary = adp_plane_new(adp); + if (IS_ERR(primary)) + return PTR_ERR(primary); + + ret = drm_crtc_init_with_planes(drm, &adp->crtc, primary, + NULL, &adp_crtc_funcs, NULL); + if (ret) + return ret; + + drm_crtc_helper_add(&adp->crtc, &adp_crtc_helper_funcs); + return 0; +} + +static const struct drm_mode_config_funcs adp_mode_config_funcs = { + .fb_create = drm_gem_fb_create_with_dirty, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static int adp_setup_mode_config(struct adp_drv_private *adp) +{ + struct drm_device *drm = &adp->drm; + int ret; + u32 size; + + ret = drmm_mode_config_init(drm); + if (ret) + return ret; + + /* + * Query screen size restrict the frame buffer size to the screen size + * aligned to the next multiple of 64. This is not necessary but can be + * used as simple check for non-desktop devices. + * Xorg's modesetting driver does not care about the connector + * "non-desktop" property. The max frame buffer width or height can be + * easily checked and a device can be reject if the max width/height is + * smaller than 120 for example. + * Any touchbar daemon is not limited by this small framebuffer size. + */ + size = readl(adp->fe + ADP_SCREEN_SIZE); + + drm->mode_config.min_width = 32; + drm->mode_config.min_height = 32; + drm->mode_config.max_width = ALIGN(FIELD_GET(ADP_SCREEN_HSIZE, size), 64); + drm->mode_config.max_height = ALIGN(FIELD_GET(ADP_SCREEN_VSIZE, size), 64); + drm->mode_config.preferred_depth = 24; + drm->mode_config.prefer_shadow = 0; + drm->mode_config.funcs = &adp_mode_config_funcs; + + ret = adp_setup_crtc(adp); + if (ret) { + drm_err(drm, "failed to create crtc"); + return ret; + } + + adp->encoder = drmm_plain_encoder_alloc(drm, NULL, DRM_MODE_ENCODER_DSI, NULL); + if (IS_ERR(adp->encoder)) { + drm_err(drm, "failed to init encoder"); + return PTR_ERR(adp->encoder); + } + adp->encoder->possible_crtcs = ALL_CRTCS; + + ret = drm_bridge_attach(adp->encoder, adp->next_bridge, NULL, + DRM_BRIDGE_ATTACH_NO_CONNECTOR); + if (ret) { + drm_err(drm, "failed to init bridge chain"); + return ret; + } + + adp->connector = drm_bridge_connector_init(drm, adp->encoder); + if (IS_ERR(adp->connector)) + return PTR_ERR(adp->connector); + + drm_connector_attach_encoder(adp->connector, adp->encoder); + + ret = drm_vblank_init(drm, drm->mode_config.num_crtc); + if (ret < 0) { + drm_err(drm, "failed to initialize vblank"); + return ret; + } + + drm_mode_config_reset(drm); + + return 0; +} + +static int adp_parse_of(struct platform_device *pdev, struct adp_drv_private *adp) +{ + struct device *dev = &pdev->dev; + + adp->be = devm_platform_ioremap_resource_byname(pdev, "be"); + if (IS_ERR(adp->be)) { + dev_err(dev, "failed to map display backend mmio"); + return PTR_ERR(adp->be); + } + + adp->fe = devm_platform_ioremap_resource_byname(pdev, "fe"); + if (IS_ERR(adp->fe)) { + dev_err(dev, "failed to map display pipe mmio"); + return PTR_ERR(adp->fe); + } + + adp->be_irq = platform_get_irq_byname(pdev, "be"); + if (adp->be_irq < 0) + return adp->be_irq; + + adp->fe_irq = platform_get_irq_byname(pdev, "fe"); + if (adp->fe_irq < 0) + return adp->fe_irq; + + return 0; +} + +static irqreturn_t adp_fe_irq(int irq, void *arg) +{ + struct adp_drv_private *adp = (struct adp_drv_private *)arg; + u32 int_status; + u32 int_ctl; + + int_status = readl(adp->fe + ADP_INT_STATUS); + if (int_status & ADP_INT_STATUS_VBLANK) { + drm_crtc_handle_vblank(&adp->crtc); + spin_lock(&adp->crtc.dev->event_lock); + if (adp->event) { + int_ctl = readl(adp->fe + ADP_CTRL); + if ((int_ctl & 0xF00) == 0x600) { + drm_crtc_send_vblank_event(&adp->crtc, adp->event); + adp->event = NULL; + drm_crtc_vblank_put(&adp->crtc); + } + } + spin_unlock(&adp->crtc.dev->event_lock); + } + + writel(int_status, adp->fe + ADP_INT_STATUS); + + + return IRQ_HANDLED; +} + +static int adp_drm_bind(struct device *dev) +{ + struct drm_device *drm = dev_get_drvdata(dev); + struct adp_drv_private *adp = to_adp(drm); + int err; + + writel(ADP_CTRL_FIFO_ON, adp->fe + ADP_CTRL); + + adp->next_bridge = drmm_of_get_bridge(&adp->drm, dev->of_node, 0, 0); + if (IS_ERR(adp->next_bridge)) { + dev_err(dev, "failed to find next bridge"); + return PTR_ERR(adp->next_bridge); + } + + err = adp_setup_mode_config(adp); + if (err < 0) + return err; + + err = request_irq(adp->fe_irq, adp_fe_irq, 0, "adp-fe", adp); + if (err) + return err; + + err = drm_dev_register(&adp->drm, 0); + if (err) + return err; + + return 0; +} + +static void adp_drm_unbind(struct device *dev) +{ + struct drm_device *drm = dev_get_drvdata(dev); + struct adp_drv_private *adp = to_adp(drm); + + drm_dev_unregister(drm); + drm_atomic_helper_shutdown(drm); + free_irq(adp->fe_irq, adp); +} + +static const struct component_master_ops adp_master_ops = { + .bind = adp_drm_bind, + .unbind = adp_drm_unbind, +}; + +static int compare_dev(struct device *dev, void *data) +{ + return dev->of_node == data; +} + +static int adp_probe(struct platform_device *pdev) +{ + struct device_node *port; + struct component_match *match = NULL; + struct adp_drv_private *adp; + int err; + + adp = devm_drm_dev_alloc(&pdev->dev, &adp_driver, struct adp_drv_private, drm); + if (IS_ERR(adp)) + return PTR_ERR(adp); + + dev_set_drvdata(&pdev->dev, &adp->drm); + + err = adp_parse_of(pdev, adp); + if (err < 0) + return err; + + port = of_graph_get_remote_node(pdev->dev.of_node, 0, 0); + if (!port) + return -ENODEV; + + drm_of_component_match_add(&pdev->dev, &match, compare_dev, port); + of_node_put(port); + + return component_master_add_with_match(&pdev->dev, &adp_master_ops, match); +} + +static void adp_remove(struct platform_device *pdev) +{ + component_master_del(&pdev->dev, &adp_master_ops); + dev_set_drvdata(&pdev->dev, NULL); +} + +static const struct of_device_id adp_of_match[] = { + { .compatible = "apple,h7-display-pipe", }, + { }, +}; +MODULE_DEVICE_TABLE(of, adp_of_match); + +static struct platform_driver adp_platform_driver = { + .driver = { + .name = "adp", + .of_match_table = adp_of_match, + }, + .probe = adp_probe, + .remove = adp_remove, +}; + +module_platform_driver(adp_platform_driver); + +MODULE_DESCRIPTION("Apple Display Pipe DRM driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/amd/acp/Kconfig b/drivers/gpu/drm/amd/acp/Kconfig index 13340f353ea8..216d932a7831 100644 --- a/drivers/gpu/drm/amd/acp/Kconfig +++ b/drivers/gpu/drm/amd/acp/Kconfig @@ -1,5 +1,6 @@ # SPDX-License-Identifier: MIT menu "ACP (Audio CoProcessor) Configuration" + depends on DRM_AMDGPU config DRM_AMD_ACP bool "Enable AMD Audio CoProcessor IP support" diff --git a/drivers/gpu/drm/amd/acp/include/acp_gfx_if.h b/drivers/gpu/drm/amd/acp/include/acp_gfx_if.h index feab8eb7f2a8..b26710cae801 100644 --- a/drivers/gpu/drm/amd/acp/include/acp_gfx_if.h +++ b/drivers/gpu/drm/amd/acp/include/acp_gfx_if.h @@ -19,7 +19,7 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * -*/ + */ #ifndef _ACP_GFX_IF_H #define _ACP_GFX_IF_H diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig index 9375e7f12420..7f515be5185d 100644 --- a/drivers/gpu/drm/amd/amdgpu/Kconfig +++ b/drivers/gpu/drm/amd/amdgpu/Kconfig @@ -1,47 +1,107 @@ # SPDX-License-Identifier: MIT + +config DRM_AMDGPU + tristate "AMD GPU" + depends on DRM && PCI + depends on !UML + select FW_LOADER + select DRM_CLIENT + select DRM_CLIENT_SELECTION + select DRM_DISPLAY_DP_HELPER + select DRM_DISPLAY_DSC_HELPER + select DRM_DISPLAY_HDMI_HELPER + select DRM_DISPLAY_HDCP_HELPER + select DRM_DISPLAY_HELPER + select DRM_KMS_HELPER + select DRM_SCHED + select DRM_TTM + select DRM_TTM_HELPER + select POWER_SUPPLY + select HWMON + select I2C + select I2C_ALGOBIT + select CRC16 + select BACKLIGHT_CLASS_DEVICE + select INTERVAL_TREE + select DRM_BUDDY + select DRM_SUBALLOC_HELPER + select DRM_EXEC + select DRM_PANEL_BACKLIGHT_QUIRKS + # amdgpu depends on ACPI_VIDEO when ACPI is enabled, for select to work + # ACPI_VIDEO's dependencies must also be selected. + select INPUT if ACPI + select ACPI_VIDEO if ACPI + # On x86 ACPI_VIDEO also needs ACPI_WMI + select X86_PLATFORM_DEVICES if ACPI && X86 + select ACPI_WMI if ACPI && X86 + help + Choose this option if you have a recent AMD Radeon graphics card. + + If M is selected, the module will be called amdgpu. + config DRM_AMDGPU_SI bool "Enable amdgpu support for SI parts" depends on DRM_AMDGPU help - Choose this option if you want to enable experimental support - for SI asics. + Choose this option if you want to enable support + for SI (Southern Islands) asics. - SI is already supported in radeon. Experimental support for SI - in amdgpu will be disabled by default and is still provided by - radeon. Use module options to override this: + SI (Southern Islands) are first generation GCN GPUs, + supported by both drivers: radeon (old) and amdgpu (new). + By default, SI dedicated GPUs are supported by amdgpu. - radeon.si_support=0 amdgpu.si_support=1 + Use module options to override this: + To use radeon for SI, + radeon.si_support=1 amdgpu.si_support=0 config DRM_AMDGPU_CIK bool "Enable amdgpu support for CIK parts" depends on DRM_AMDGPU help - Choose this option if you want to enable support for CIK asics. + Choose this option if you want to enable support for CIK (Sea + Islands) asics. - CIK is already supported in radeon. Support for CIK in amdgpu - will be disabled by default and is still provided by radeon. - Use module options to override this: + CIK (Sea Islands) are second generation GCN GPUs, + supported by both drivers: radeon (old) and amdgpu (new). + By default, + CIK dedicated GPUs are supported by amdgpu + CIK APUs are supported by radeon + Use module options to override this: + To use amdgpu for CIK, radeon.cik_support=0 amdgpu.cik_support=1 + To use radeon for CIK, + radeon.cik_support=1 amdgpu.cik_support=0 config DRM_AMDGPU_USERPTR bool "Always enable userptr write support" depends on DRM_AMDGPU - depends on MMU select HMM_MIRROR select MMU_NOTIFIER help This option selects CONFIG_HMM and CONFIG_HMM_MIRROR if it isn't already selected to enabled full userptr support. -config DRM_AMDGPU_GART_DEBUGFS - bool "Allow GART access through debugfs" +config DRM_AMD_ISP + bool "Enable AMD Image Signal Processor IP support" + depends on DRM_AMDGPU && ACPI + select MFD_CORE + select PM_GENERIC_DOMAINS if PM + help + Choose this option to enable ISP IP support for AMD SOCs. + This adds the ISP (Image Signal Processor) IP driver and wires + it up into the amdgpu driver. It is required for cameras + on APUs which utilize mipi cameras. + +config DRM_AMDGPU_WERROR + bool "Force the compiler to throw an error instead of a warning when compiling" depends on DRM_AMDGPU - depends on DEBUG_FS + depends on EXPERT + depends on !COMPILE_TEST default n help - Selecting this option creates a debugfs file to inspect the mapped - pages. Uses more memory for housekeeping, enable only for debugging. + Add -Werror to the build flags for amdgpu.ko. + Only enable this if you are warning code for amdgpu.ko. source "drivers/gpu/drm/amd/acp/Kconfig" source "drivers/gpu/drm/amd/display/Kconfig" diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index c2bbcdd9c875..c88760fb52ea 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -1,5 +1,5 @@ # -# Copyright 2017 Advanced Micro Devices, Inc. +# Copyright 2017-2024 Advanced Micro Devices, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -23,68 +23,92 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -FULL_AMD_PATH=$(srctree)/$(src)/.. +FULL_AMD_PATH=$(src)/.. DISPLAY_FOLDER_NAME=display FULL_AMD_DISPLAY_PATH = $(FULL_AMD_PATH)/$(DISPLAY_FOLDER_NAME) ccflags-y := -I$(FULL_AMD_PATH)/include/asic_reg \ -I$(FULL_AMD_PATH)/include \ -I$(FULL_AMD_PATH)/amdgpu \ - -I$(FULL_AMD_PATH)/powerplay/inc \ + -I$(FULL_AMD_PATH)/pm/inc \ -I$(FULL_AMD_PATH)/acp/include \ -I$(FULL_AMD_DISPLAY_PATH) \ -I$(FULL_AMD_DISPLAY_PATH)/include \ + -I$(FULL_AMD_DISPLAY_PATH)/modules/inc \ -I$(FULL_AMD_DISPLAY_PATH)/dc \ -I$(FULL_AMD_DISPLAY_PATH)/amdgpu_dm \ - -I$(FULL_AMD_PATH)/amdkfd + -I$(FULL_AMD_PATH)/amdkfd \ + -I$(FULL_AMD_PATH)/ras/ras_mgr + +# Locally disable W=1 warnings enabled in drm subsystem Makefile +subdir-ccflags-y += -Wno-override-init +subdir-ccflags-$(CONFIG_DRM_AMDGPU_WERROR) += -Werror amdgpu-y := amdgpu_drv.o # add KMS driver -amdgpu-y += amdgpu_device.o amdgpu_kms.o \ +amdgpu-y += amdgpu_device.o amdgpu_doorbell_mgr.o amdgpu_kms.o \ amdgpu_atombios.o atombios_crtc.o amdgpu_connectors.o \ atom.o amdgpu_fence.o amdgpu_ttm.o amdgpu_object.o amdgpu_gart.o \ amdgpu_encoders.o amdgpu_display.o amdgpu_i2c.o \ - amdgpu_fb.o amdgpu_gem.o amdgpu_ring.o \ - amdgpu_cs.o amdgpu_bios.o amdgpu_benchmark.o amdgpu_test.o \ - amdgpu_pm.o atombios_dp.o amdgpu_afmt.o amdgpu_trace_points.o \ + amdgpu_gem.o amdgpu_ring.o \ + amdgpu_cs.o amdgpu_bios.o amdgpu_benchmark.o \ + atombios_dp.o amdgpu_afmt.o amdgpu_trace_points.o \ atombios_encoders.o amdgpu_sa.o atombios_i2c.o \ - amdgpu_dma_buf.o amdgpu_vm.o amdgpu_ib.o amdgpu_pll.o \ + amdgpu_dma_buf.o amdgpu_vm.o amdgpu_vm_pt.o amdgpu_vm_tlb_fence.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_virt.o amdgpu_atomfirmware.o \ - amdgpu_vf_error.o amdgpu_sched.o amdgpu_debugfs.o amdgpu_ids.o \ - amdgpu_gmc.o amdgpu_mmhub.o amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \ + amdgpu_gtt_mgr.o amdgpu_preempt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o \ + amdgpu_atomfirmware.o amdgpu_vf_error.o amdgpu_sched.o \ + amdgpu_debugfs.o amdgpu_ids.o amdgpu_gmc.o amdgpu_mmhub.o amdgpu_hdp.o \ + amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \ amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.o \ - amdgpu_umc.o smu_v11_0_i2c.o + amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \ + amdgpu_fw_attestation.o amdgpu_securedisplay.o \ + amdgpu_eeprom.o amdgpu_mca.o amdgpu_psp_ta.o amdgpu_lsdma.o \ + amdgpu_ring_mux.o amdgpu_xcp.o amdgpu_seq64.o amdgpu_aca.o amdgpu_dev_coredump.o \ + amdgpu_cper.o amdgpu_userq_fence.o amdgpu_eviction_fence.o amdgpu_ip.o + +amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o amdgpu-$(CONFIG_PERF_EVENTS) += amdgpu_pmu.o # add asic specific block -amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \ +amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o \ dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o -amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce_v6_0.o si_dpm.o si_smc.o +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 \ + uvd_v3_1.o vce_v1_0.o amdgpu-y += \ vi.o mxgpu_vi.o nbio_v6_1.o soc15.o emu_soc.o mxgpu_ai.o nbio_v7_0.o vega10_reg_init.o \ - vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o navi10_reg_init.o navi14_reg_init.o \ - arct_reg_init.o navi12_reg_init.o mxgpu_nv.o + vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o arct_reg_init.o mxgpu_nv.o \ + nbio_v7_2.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o aldebaran.o soc21.o soc24.o \ + sienna_cichlid.o smu_v13_0_10.o nbio_v4_3.o hdp_v6_0.o nbio_v7_7.o hdp_v5_2.o lsdma_v6_0.o \ + nbio_v7_9.o aqua_vanjaram.o nbio_v7_11.o lsdma_v7_0.o hdp_v7_0.o nbif_v6_3_1.o \ + cyan_skillfish_reg_init.o # add DF block amdgpu-y += \ df_v1_7.o \ - df_v3_6.o + df_v3_6.o \ + df_v4_3.o \ + df_v4_6_2.o \ + df_v4_15.o # add GMC block amdgpu-y += \ gmc_v7_0.o \ gmc_v8_0.o \ gfxhub_v1_0.o mmhub_v1_0.o gmc_v9_0.o gfxhub_v1_1.o mmhub_v9_4.o \ - gfxhub_v2_0.o mmhub_v2_0.o gmc_v10_0.o + gfxhub_v2_0.o mmhub_v2_0.o gmc_v10_0.o gfxhub_v2_1.o mmhub_v2_3.o \ + mmhub_v1_7.o gfxhub_v3_0.o mmhub_v3_0.o mmhub_v3_0_2.o gmc_v11_0.o \ + mmhub_v3_0_1.o gfxhub_v3_0_3.o gfxhub_v1_2.o mmhub_v1_8.o mmhub_v3_3.o \ + gfxhub_v11_5_0.o mmhub_v4_1_0.o gfxhub_v12_0.o gmc_v12_0.o # add UMC block amdgpu-y += \ - umc_v6_1.o umc_v6_0.o + umc_v6_0.o umc_v6_1.o umc_v6_7.o umc_v8_7.o umc_v8_10.o umc_v12_0.o umc_v8_14.o # add IH block amdgpu-y += \ @@ -94,7 +118,11 @@ amdgpu-y += \ tonga_ih.o \ cz_ih.o \ vega10_ih.o \ - navi10_ih.o + vega20_ih.o \ + navi10_ih.o \ + ih_v6_0.o \ + ih_v6_1.o \ + ih_v7_0.o # add PSP block amdgpu-y += \ @@ -102,17 +130,16 @@ amdgpu-y += \ psp_v3_1.o \ psp_v10_0.o \ psp_v11_0.o \ - psp_v12_0.o - -# add SMC block -amdgpu-y += \ - amdgpu_dpm.o + psp_v11_0_8.o \ + psp_v12_0.o \ + psp_v13_0.o \ + psp_v13_0_4.o \ + psp_v14_0.o # add DCE block amdgpu-y += \ dce_v10_0.o \ - dce_v11_0.o \ - dce_virtual.o + amdgpu_vkms.o # add GFX block amdgpu-y += \ @@ -121,7 +148,15 @@ amdgpu-y += \ gfx_v8_0.o \ gfx_v9_0.o \ gfx_v9_4.o \ - gfx_v10_0.o + gfx_v9_4_2.o \ + gfx_v9_4_3.o \ + gfx_v10_0.o \ + imu_v11_0.o \ + gfx_v11_0.o \ + gfx_v11_0_3.o \ + imu_v11_0_3.o \ + gfx_v12_0.o \ + imu_v12_0.o # add async DMA block amdgpu-y += \ @@ -129,11 +164,21 @@ amdgpu-y += \ sdma_v2_4.o \ sdma_v3_0.o \ sdma_v4_0.o \ - sdma_v5_0.o + sdma_v4_4.o \ + sdma_v4_4_2.o \ + sdma_v5_0.o \ + sdma_v5_2.o \ + sdma_v6_0.o \ + sdma_v7_0.o # add MES block amdgpu-y += \ - mes_v10_1.o + amdgpu_mes.o \ + mes_v11_0.o \ + mes_v12_0.o \ + +# add GFX userqueue support +amdgpu-y += mes_userqueue.o # add UVD block amdgpu-y += \ @@ -151,33 +196,86 @@ amdgpu-y += \ # add VCN and JPEG block amdgpu-y += \ amdgpu_vcn.o \ + vcn_sw_ring.o \ vcn_v1_0.o \ vcn_v2_0.o \ vcn_v2_5.o \ + vcn_v3_0.o \ + vcn_v4_0.o \ + vcn_v4_0_3.o \ + vcn_v4_0_5.o \ + vcn_v5_0_0.o \ + vcn_v5_0_1.o \ amdgpu_jpeg.o \ jpeg_v1_0.o \ jpeg_v2_0.o \ - jpeg_v2_5.o + jpeg_v2_5.o \ + jpeg_v3_0.o \ + jpeg_v4_0.o \ + jpeg_v4_0_3.o \ + jpeg_v4_0_5.o \ + jpeg_v5_0_0.o \ + jpeg_v5_0_1.o + +# add VPE block +amdgpu-y += \ + amdgpu_vpe.o \ + vpe_v6_1.o + +# add UMSCH block +amdgpu-y += \ + amdgpu_umsch_mm.o \ + umsch_mm_v4_0.o +# # add ATHUB block amdgpu-y += \ athub_v1_0.o \ - athub_v2_0.o + athub_v2_0.o \ + athub_v2_1.o \ + athub_v3_0.o \ + athub_v4_1_0.o + +# add SMUIO block +amdgpu-y += \ + smuio_v9_0.o \ + smuio_v11_0.o \ + smuio_v11_0_6.o \ + smuio_v13_0.o \ + smuio_v13_0_3.o \ + smuio_v13_0_6.o \ + smuio_v14_0_2.o + +# add reset block +amdgpu-y += \ + amdgpu_reset.o + +# add MCA block +amdgpu-y += \ + mca_v3_0.o # add amdkfd interfaces amdgpu-y += amdgpu_amdkfd.o +# add gfx usermode queue +amdgpu-y += amdgpu_userq.o + ifneq ($(CONFIG_HSA_AMD),) AMDKFD_PATH := ../amdkfd include $(FULL_AMD_PATH)/amdkfd/Makefile amdgpu-y += $(AMDKFD_FILES) amdgpu-y += \ - amdgpu_amdkfd_fence.o \ - amdgpu_amdkfd_gpuvm.o \ - amdgpu_amdkfd_gfx_v8.o \ - amdgpu_amdkfd_gfx_v9.o \ - amdgpu_amdkfd_arcturus.o \ - amdgpu_amdkfd_gfx_v10.o + amdgpu_amdkfd_fence.o \ + amdgpu_amdkfd_gpuvm.o \ + amdgpu_amdkfd_gfx_v8.o \ + amdgpu_amdkfd_gfx_v9.o \ + amdgpu_amdkfd_arcturus.o \ + amdgpu_amdkfd_aldebaran.o \ + amdgpu_amdkfd_gc_9_4_3.o \ + amdgpu_amdkfd_gfx_v10.o \ + amdgpu_amdkfd_gfx_v10_3.o \ + amdgpu_amdkfd_gfx_v11.o \ + amdgpu_amdkfd_gfx_v12.o ifneq ($(CONFIG_DRM_AMDGPU_CIK),) amdgpu-y += amdgpu_amdkfd_gfx_v7.o @@ -204,9 +302,9 @@ endif amdgpu-$(CONFIG_COMPAT) += amdgpu_ioc32.o amdgpu-$(CONFIG_VGA_SWITCHEROO) += amdgpu_atpx_handler.o amdgpu-$(CONFIG_ACPI) += amdgpu_acpi.o -amdgpu-$(CONFIG_HMM_MIRROR) += amdgpu_mn.o +amdgpu-$(CONFIG_HMM_MIRROR) += amdgpu_hmm.o -include $(FULL_AMD_PATH)/powerplay/Makefile +include $(FULL_AMD_PATH)/pm/Makefile amdgpu-y += $(AMD_POWERPLAY_FILES) @@ -219,4 +317,17 @@ amdgpu-y += $(AMD_DISPLAY_FILES) endif +# add isp block +ifneq ($(CONFIG_DRM_AMD_ISP),) +amdgpu-y += \ + amdgpu_isp.o \ + isp_v4_1_0.o \ + isp_v4_1_1.o +endif + +AMD_GPU_RAS_PATH := ../ras +AMD_GPU_RAS_FULL_PATH := $(FULL_AMD_PATH)/ras +include $(AMD_GPU_RAS_FULL_PATH)/Makefile +amdgpu-y += $(AMD_GPU_RAS_FILES) + obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o diff --git a/drivers/gpu/drm/amd/amdgpu/ObjectID.h b/drivers/gpu/drm/amd/amdgpu/ObjectID.h index 5b393622f592..a0f0a17e224f 100644 --- a/drivers/gpu/drm/amd/amdgpu/ObjectID.h +++ b/drivers/gpu/drm/amd/amdgpu/ObjectID.h @@ -119,6 +119,7 @@ #define CONNECTOR_OBJECT_ID_eDP 0x14 #define CONNECTOR_OBJECT_ID_MXM 0x15 #define CONNECTOR_OBJECT_ID_LVDS_eDP 0x16 +#define CONNECTOR_OBJECT_ID_USBC 0x17 /* deleted */ diff --git a/drivers/gpu/drm/amd/amdgpu/aldebaran.c b/drivers/gpu/drm/amd/amdgpu/aldebaran.c new file mode 100644 index 000000000000..daa7b23bc775 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/aldebaran.c @@ -0,0 +1,473 @@ +/* + * Copyright 2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "aldebaran.h" +#include "amdgpu_reset.h" +#include "amdgpu_amdkfd.h" +#include "amdgpu_dpm.h" +#include "amdgpu_job.h" +#include "amdgpu_ring.h" +#include "amdgpu_ras.h" +#include "amdgpu_psp.h" +#include "amdgpu_xgmi.h" + +static bool aldebaran_is_mode2_default(struct amdgpu_reset_control *reset_ctl) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle; + + if ((amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 2) && + adev->gmc.xgmi.connected_to_cpu)) + return true; + + return false; +} + +static struct amdgpu_reset_handler * +aldebaran_get_reset_handler(struct amdgpu_reset_control *reset_ctl, + struct amdgpu_reset_context *reset_context) +{ + struct amdgpu_reset_handler *handler; + struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle; + int i; + + if (reset_context->method == AMD_RESET_METHOD_NONE) { + if (aldebaran_is_mode2_default(reset_ctl)) + reset_context->method = AMD_RESET_METHOD_MODE2; + else + reset_context->method = amdgpu_asic_reset_method(adev); + } + + if (reset_context->method != AMD_RESET_METHOD_NONE) { + dev_dbg(adev->dev, "Getting reset handler for method %d\n", + reset_context->method); + for_each_handler(i, handler, reset_ctl) { + if (handler->reset_method == reset_context->method) + return handler; + } + } + + dev_dbg(adev->dev, "Reset handler not found!\n"); + + return NULL; +} + +static inline uint32_t aldebaran_get_ip_block_mask(struct amdgpu_device *adev) +{ + uint32_t ip_block_mask = BIT(AMD_IP_BLOCK_TYPE_GFX) | + BIT(AMD_IP_BLOCK_TYPE_SDMA); + + if (adev->aid_mask) + ip_block_mask |= BIT(AMD_IP_BLOCK_TYPE_IH); + + return ip_block_mask; +} + +static int aldebaran_mode2_suspend_ip(struct amdgpu_device *adev) +{ + uint32_t ip_block_mask = aldebaran_get_ip_block_mask(adev); + uint32_t ip_block; + int r, i; + + /* Skip suspend of SDMA IP versions >= 4.4.2. They are multi-aid */ + if (adev->aid_mask) + ip_block_mask &= ~BIT(AMD_IP_BLOCK_TYPE_SDMA); + + amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE); + amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE); + + for (i = adev->num_ip_blocks - 1; i >= 0; i--) { + ip_block = BIT(adev->ip_blocks[i].version->type); + if (!(ip_block_mask & ip_block)) + continue; + + r = amdgpu_ip_block_suspend(&adev->ip_blocks[i]); + if (r) + return r; + } + + return 0; +} + +static int +aldebaran_mode2_prepare_hwcontext(struct amdgpu_reset_control *reset_ctl, + struct amdgpu_reset_context *reset_context) +{ + int r = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle; + + dev_dbg(adev->dev, "Aldebaran prepare hw context\n"); + /* Don't suspend on bare metal if we are not going to HW reset the ASIC */ + if (!amdgpu_sriov_vf(adev)) + r = aldebaran_mode2_suspend_ip(adev); + + return r; +} + +static void aldebaran_async_reset(struct work_struct *work) +{ + struct amdgpu_reset_handler *handler; + struct amdgpu_reset_control *reset_ctl = + container_of(work, struct amdgpu_reset_control, reset_work); + struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle; + int i; + + for_each_handler(i, handler, reset_ctl) { + if (handler->reset_method == reset_ctl->active_reset) { + dev_dbg(adev->dev, "Resetting device\n"); + handler->do_reset(adev); + break; + } + } +} + +static int aldebaran_mode2_reset(struct amdgpu_device *adev) +{ + /* disable BM */ + pci_clear_master(adev->pdev); + adev->asic_reset_res = amdgpu_dpm_mode2_reset(adev); + return adev->asic_reset_res; +} + +static int +aldebaran_mode2_perform_reset(struct amdgpu_reset_control *reset_ctl, + struct amdgpu_reset_context *reset_context) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle; + struct list_head *reset_device_list = reset_context->reset_device_list; + struct amdgpu_device *tmp_adev = NULL; + int r = 0; + + dev_dbg(adev->dev, "aldebaran perform hw reset\n"); + + if (reset_device_list == NULL) + return -EINVAL; + + if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 2) && + reset_context->hive == NULL) { + /* Wrong context, return error */ + return -EINVAL; + } + + list_for_each_entry(tmp_adev, reset_device_list, reset_list) { + mutex_lock(&tmp_adev->reset_cntl->reset_lock); + tmp_adev->reset_cntl->active_reset = AMD_RESET_METHOD_MODE2; + } + /* + * Mode2 reset doesn't need any sync between nodes in XGMI hive, instead launch + * them together so that they can be completed asynchronously on multiple nodes + */ + list_for_each_entry(tmp_adev, reset_device_list, reset_list) { + /* For XGMI run all resets in parallel to speed up the process */ + if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) { + if (!queue_work(system_unbound_wq, + &tmp_adev->reset_cntl->reset_work)) + r = -EALREADY; + } else + r = aldebaran_mode2_reset(tmp_adev); + if (r) { + dev_err(tmp_adev->dev, + "ASIC reset failed with error, %d for drm dev, %s", + r, adev_to_drm(tmp_adev)->unique); + break; + } + } + + /* For XGMI wait for all resets to complete before proceed */ + if (!r) { + list_for_each_entry(tmp_adev, reset_device_list, reset_list) { + if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) { + flush_work(&tmp_adev->reset_cntl->reset_work); + r = tmp_adev->asic_reset_res; + if (r) + break; + } + } + } + + list_for_each_entry(tmp_adev, reset_device_list, reset_list) { + mutex_unlock(&tmp_adev->reset_cntl->reset_lock); + tmp_adev->reset_cntl->active_reset = AMD_RESET_METHOD_NONE; + } + + return r; +} + +static int aldebaran_mode2_restore_ip(struct amdgpu_device *adev) +{ + struct amdgpu_firmware_info *ucode_list[AMDGPU_UCODE_ID_MAXIMUM]; + uint32_t ip_block_mask = aldebaran_get_ip_block_mask(adev); + struct amdgpu_firmware_info *ucode; + struct amdgpu_ip_block *cmn_block; + struct amdgpu_ip_block *ih_block; + int ucode_count = 0; + int i, r; + + dev_dbg(adev->dev, "Reloading ucodes after reset\n"); + for (i = 0; i < adev->firmware.max_ucodes; i++) { + ucode = &adev->firmware.ucode[i]; + if (!ucode->fw) + continue; + switch (ucode->ucode_id) { + case AMDGPU_UCODE_ID_SDMA0: + case AMDGPU_UCODE_ID_SDMA1: + case AMDGPU_UCODE_ID_SDMA2: + case AMDGPU_UCODE_ID_SDMA3: + case AMDGPU_UCODE_ID_SDMA4: + case AMDGPU_UCODE_ID_SDMA5: + case AMDGPU_UCODE_ID_SDMA6: + case AMDGPU_UCODE_ID_SDMA7: + case AMDGPU_UCODE_ID_CP_MEC1: + case AMDGPU_UCODE_ID_CP_MEC1_JT: + case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL: + case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM: + case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM: + case AMDGPU_UCODE_ID_RLC_G: + ucode_list[ucode_count++] = ucode; + break; + default: + break; + } + } + + /* Reinit NBIF block */ + cmn_block = + amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_COMMON); + if (unlikely(!cmn_block)) { + dev_err(adev->dev, "Failed to get BIF handle\n"); + return -EINVAL; + } + r = amdgpu_ip_block_resume(cmn_block); + if (r) + return r; + + if (ip_block_mask & BIT(AMD_IP_BLOCK_TYPE_IH)) { + ih_block = amdgpu_device_ip_get_ip_block(adev, + AMD_IP_BLOCK_TYPE_IH); + if (unlikely(!ih_block)) { + dev_err(adev->dev, "Failed to get IH handle\n"); + return -EINVAL; + } + r = amdgpu_ip_block_resume(ih_block); + if (r) + return r; + } + + /* Reinit GFXHUB */ + adev->gfxhub.funcs->init(adev); + r = adev->gfxhub.funcs->gart_enable(adev); + if (r) { + dev_err(adev->dev, "GFXHUB gart reenable failed after reset\n"); + return r; + } + + /* Reload GFX firmware */ + r = psp_load_fw_list(&adev->psp, ucode_list, ucode_count); + if (r) { + dev_err(adev->dev, "GFX ucode load failed after reset\n"); + return r; + } + + /* Resume RLC, FW needs RLC alive to complete reset process */ + adev->gfx.rlc.funcs->resume(adev); + + /* Wait for FW reset event complete */ + r = amdgpu_dpm_wait_for_event(adev, SMU_EVENT_RESET_COMPLETE, 0); + if (r) { + dev_err(adev->dev, + "Failed to get response from firmware after reset\n"); + return r; + } + + for (i = 0; i < adev->num_ip_blocks; i++) { + if (!(adev->ip_blocks[i].version->type == + AMD_IP_BLOCK_TYPE_GFX || + adev->ip_blocks[i].version->type == + AMD_IP_BLOCK_TYPE_SDMA)) + continue; + + r = amdgpu_ip_block_resume(&adev->ip_blocks[i]); + if (r) + return r; + } + + for (i = 0; i < adev->num_ip_blocks; i++) { + if (!(adev->ip_blocks[i].version->type == + AMD_IP_BLOCK_TYPE_GFX || + adev->ip_blocks[i].version->type == + AMD_IP_BLOCK_TYPE_SDMA || + adev->ip_blocks[i].version->type == + AMD_IP_BLOCK_TYPE_COMMON)) + continue; + + if (adev->ip_blocks[i].version->funcs->late_init) { + r = adev->ip_blocks[i].version->funcs->late_init( + &adev->ip_blocks[i]); + if (r) { + dev_err(adev->dev, + "late_init of IP block <%s> failed %d after reset\n", + adev->ip_blocks[i].version->funcs->name, + r); + return r; + } + } + adev->ip_blocks[i].status.late_initialized = true; + } + + amdgpu_device_set_cg_state(adev, AMD_CG_STATE_GATE); + amdgpu_device_set_pg_state(adev, AMD_PG_STATE_GATE); + + return r; +} + +static int +aldebaran_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl, + struct amdgpu_reset_context *reset_context) +{ + struct list_head *reset_device_list = reset_context->reset_device_list; + struct amdgpu_device *tmp_adev = NULL; + struct amdgpu_ras *con; + int r; + + if (reset_device_list == NULL) + return -EINVAL; + + if (amdgpu_ip_version(reset_context->reset_req_dev, MP1_HWIP, 0) == + IP_VERSION(13, 0, 2) && + reset_context->hive == NULL) { + /* Wrong context, return error */ + return -EINVAL; + } + + list_for_each_entry(tmp_adev, reset_device_list, reset_list) { + amdgpu_set_init_level(tmp_adev, + AMDGPU_INIT_LEVEL_RESET_RECOVERY); + dev_info(tmp_adev->dev, + "GPU reset succeeded, trying to resume\n"); + /*TBD: Ideally should clear only GFX, SDMA blocks*/ + amdgpu_ras_clear_err_state(tmp_adev); + r = aldebaran_mode2_restore_ip(tmp_adev); + if (r) + goto end; + + /* + * Add this ASIC as tracked as reset was already + * complete successfully. + */ + amdgpu_register_gpu_instance(tmp_adev); + + /* Resume RAS, ecc_irq */ + con = amdgpu_ras_get_context(tmp_adev); + if (!amdgpu_sriov_vf(tmp_adev) && con) { + if (tmp_adev->sdma.ras && + tmp_adev->sdma.ras->ras_block.ras_late_init) { + r = tmp_adev->sdma.ras->ras_block.ras_late_init(tmp_adev, + &tmp_adev->sdma.ras->ras_block.ras_comm); + if (r) { + dev_err(tmp_adev->dev, "SDMA failed to execute ras_late_init! ret:%d\n", r); + goto end; + } + } + + if (tmp_adev->gfx.ras && + tmp_adev->gfx.ras->ras_block.ras_late_init) { + r = tmp_adev->gfx.ras->ras_block.ras_late_init(tmp_adev, + &tmp_adev->gfx.ras->ras_block.ras_comm); + if (r) { + dev_err(tmp_adev->dev, "GFX failed to execute ras_late_init! ret:%d\n", r); + goto end; + } + } + } + + amdgpu_ras_resume(tmp_adev); + + /* Update PSP FW topology after reset */ + if (reset_context->hive && + tmp_adev->gmc.xgmi.num_physical_nodes > 1) + r = amdgpu_xgmi_update_topology(reset_context->hive, + tmp_adev); + + if (!r) { + amdgpu_set_init_level(tmp_adev, + AMDGPU_INIT_LEVEL_DEFAULT); + amdgpu_irq_gpu_reset_resume_helper(tmp_adev); + + r = amdgpu_ib_ring_tests(tmp_adev); + if (r) { + dev_err(tmp_adev->dev, + "ib ring test failed (%d).\n", r); + r = -EAGAIN; + tmp_adev->asic_reset_res = r; + goto end; + } + } + } + +end: + return r; +} + +static struct amdgpu_reset_handler aldebaran_mode2_handler = { + .reset_method = AMD_RESET_METHOD_MODE2, + .prepare_env = NULL, + .prepare_hwcontext = aldebaran_mode2_prepare_hwcontext, + .perform_reset = aldebaran_mode2_perform_reset, + .restore_hwcontext = aldebaran_mode2_restore_hwcontext, + .restore_env = NULL, + .do_reset = aldebaran_mode2_reset, +}; + +static struct amdgpu_reset_handler + *aldebaran_rst_handlers[AMDGPU_RESET_MAX_HANDLERS] = { + &aldebaran_mode2_handler, + &xgmi_reset_on_init_handler, + }; + +int aldebaran_reset_init(struct amdgpu_device *adev) +{ + struct amdgpu_reset_control *reset_ctl; + + reset_ctl = kzalloc(sizeof(*reset_ctl), GFP_KERNEL); + if (!reset_ctl) + return -ENOMEM; + + reset_ctl->handle = adev; + reset_ctl->async_reset = aldebaran_async_reset; + reset_ctl->active_reset = AMD_RESET_METHOD_NONE; + reset_ctl->get_reset_handler = aldebaran_get_reset_handler; + + INIT_WORK(&reset_ctl->reset_work, reset_ctl->async_reset); + /* Only mode2 is handled through reset control now */ + reset_ctl->reset_handlers = &aldebaran_rst_handlers; + + adev->reset_cntl = reset_ctl; + + return 0; +} + +int aldebaran_reset_fini(struct amdgpu_device *adev) +{ + kfree(adev->reset_cntl); + adev->reset_cntl = NULL; + return 0; +} diff --git a/drivers/gpu/drm/amd/amdgpu/aldebaran.h b/drivers/gpu/drm/amd/amdgpu/aldebaran.h new file mode 100644 index 000000000000..a07db5454d49 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/aldebaran.h @@ -0,0 +1,32 @@ +/* + * Copyright 2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __ALDEBARAN_H__ +#define __ALDEBARAN_H__ + +#include "amdgpu.h" + +int aldebaran_reset_init(struct amdgpu_device *adev); +int aldebaran_reset_fini(struct amdgpu_device *adev); + +#endif diff --git a/drivers/gpu/drm/amd/amdgpu/aldebaran_reg_init.c b/drivers/gpu/drm/amd/amdgpu/aldebaran_reg_init.c new file mode 100644 index 000000000000..28e6c9ab8767 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/aldebaran_reg_init.c @@ -0,0 +1,54 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include "amdgpu.h" +#include "soc15.h" + +#include "soc15_common.h" +#include "aldebaran_ip_offset.h" + +int aldebaran_reg_base_init(struct amdgpu_device *adev) +{ + /* HW has more IP blocks, only initialized the block needed by our driver */ + uint32_t i; + for (i = 0 ; i < MAX_INSTANCE ; ++i) { + adev->reg_offset[GC_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i])); + adev->reg_offset[HDP_HWIP][i] = (uint32_t *)(&(HDP_BASE.instance[i])); + adev->reg_offset[MMHUB_HWIP][i] = (uint32_t *)(&(MMHUB_BASE.instance[i])); + adev->reg_offset[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i])); + adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIO_BASE.instance[i])); + adev->reg_offset[MP0_HWIP][i] = (uint32_t *)(&(MP0_BASE.instance[i])); + adev->reg_offset[MP1_HWIP][i] = (uint32_t *)(&(MP1_BASE.instance[i])); + adev->reg_offset[DF_HWIP][i] = (uint32_t *)(&(DF_BASE.instance[i])); + adev->reg_offset[OSSSYS_HWIP][i] = (uint32_t *)(&(OSSSYS_BASE.instance[i])); + adev->reg_offset[SDMA0_HWIP][i] = (uint32_t *)(&(SDMA0_BASE.instance[i])); + adev->reg_offset[SDMA1_HWIP][i] = (uint32_t *)(&(SDMA1_BASE.instance[i])); + adev->reg_offset[SDMA2_HWIP][i] = (uint32_t *)(&(SDMA2_BASE.instance[i])); + adev->reg_offset[SDMA3_HWIP][i] = (uint32_t *)(&(SDMA3_BASE.instance[i])); + adev->reg_offset[SDMA4_HWIP][i] = (uint32_t *)(&(SDMA4_BASE.instance[i])); + adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i])); + adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i])); + adev->reg_offset[UMC_HWIP][i] = (uint32_t *)(&(UMC_BASE.instance[i])); + adev->reg_offset[VCN_HWIP][i] = (uint32_t *)(&(VCN_BASE.instance[i])); + } + return 0; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 97dd9596d17a..9f9774f58ce1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -28,6 +28,18 @@ #ifndef __AMDGPU_H__ #define __AMDGPU_H__ +#ifdef pr_fmt +#undef pr_fmt +#endif + +#define pr_fmt(fmt) "amdgpu: " fmt + +#ifdef dev_fmt +#undef dev_fmt +#endif + +#define dev_fmt(fmt) "amdgpu: " fmt + #include "amdgpu_ctx.h" #include <linux/atomic.h> @@ -37,23 +49,21 @@ #include <linux/rbtree.h> #include <linux/hashtable.h> #include <linux/dma-fence.h> +#include <linux/pci.h> -#include <drm/ttm/ttm_bo_api.h> -#include <drm/ttm/ttm_bo_driver.h> +#include <drm/ttm/ttm_bo.h> #include <drm/ttm/ttm_placement.h> -#include <drm/ttm/ttm_module.h> -#include <drm/ttm/ttm_execbuf_util.h> #include <drm/amdgpu_drm.h> #include <drm/drm_gem.h> #include <drm/drm_ioctl.h> -#include <drm/gpu_scheduler.h> #include <kgd_kfd_interface.h> #include "dm_pp_interface.h" #include "kgd_pp_interface.h" #include "amd_shared.h" +#include "amdgpu_utils.h" #include "amdgpu_mode.h" #include "amdgpu_ih.h" #include "amdgpu_irq.h" @@ -70,14 +80,18 @@ #include "amdgpu_vce.h" #include "amdgpu_vcn.h" #include "amdgpu_jpeg.h" -#include "amdgpu_mn.h" +#include "amdgpu_vpe.h" +#include "amdgpu_umsch_mm.h" #include "amdgpu_gmc.h" #include "amdgpu_gfx.h" #include "amdgpu_sdma.h" +#include "amdgpu_lsdma.h" #include "amdgpu_nbio.h" +#include "amdgpu_hdp.h" #include "amdgpu_dm.h" #include "amdgpu_virt.h" #include "amdgpu_csa.h" +#include "amdgpu_mes_ctx.h" #include "amdgpu_gart.h" #include "amdgpu_debugfs.h" #include "amdgpu_job.h" @@ -85,23 +99,37 @@ #include "amdgpu_gem.h" #include "amdgpu_doorbell.h" #include "amdgpu_amdkfd.h" -#include "amdgpu_smu.h" #include "amdgpu_discovery.h" #include "amdgpu_mes.h" #include "amdgpu_umc.h" #include "amdgpu_mmhub.h" +#include "amdgpu_gfxhub.h" #include "amdgpu_df.h" +#include "amdgpu_smuio.h" +#include "amdgpu_fdinfo.h" +#include "amdgpu_mca.h" +#include "amdgpu_aca.h" +#include "amdgpu_ras.h" +#include "amdgpu_cper.h" +#include "amdgpu_xcp.h" +#include "amdgpu_seq64.h" +#include "amdgpu_reg_state.h" +#include "amdgpu_userq.h" +#include "amdgpu_eviction_fence.h" +#if defined(CONFIG_DRM_AMD_ISP) +#include "amdgpu_isp.h" +#endif -#define MAX_GPU_INSTANCE 16 +#define MAX_GPU_INSTANCE 64 -struct amdgpu_gpu_instance -{ +#define GFX_SLICE_PERIOD_MS 250 + +struct amdgpu_gpu_instance { struct amdgpu_device *adev; int mgpu_fan_enabled; }; -struct amdgpu_mgpu_info -{ +struct amdgpu_mgpu_info { struct amdgpu_gpu_instance gpu_ins[MAX_GPU_INSTANCE]; struct mutex mutex; uint32_t num_gpu; @@ -109,19 +137,37 @@ struct amdgpu_mgpu_info uint32_t num_apu; }; +enum amdgpu_ss { + AMDGPU_SS_DRV_LOAD, + AMDGPU_SS_DEV_D0, + AMDGPU_SS_DEV_D3, + AMDGPU_SS_DRV_UNLOAD +}; + +struct amdgpu_hwip_reg_entry { + u32 hwip; + u32 inst; + u32 seg; + u32 reg_offset; + const char *reg_name; +}; + +struct amdgpu_watchdog_timer { + bool timeout_fatal_disable; + uint32_t period; /* maxCycles = (1 << period), the number of cycles before a timeout */ +}; + #define AMDGPU_MAX_TIMEOUT_PARAM_LENGTH 256 /* * Modules parameters. */ extern int amdgpu_modeset; -extern int amdgpu_vram_limit; +extern unsigned int amdgpu_vram_limit; extern int amdgpu_vis_vram_limit; extern int amdgpu_gart_size; extern int amdgpu_gtt_size; extern int amdgpu_moverate; -extern int amdgpu_benchmarking; -extern int amdgpu_testing; extern int amdgpu_audio; extern int amdgpu_disp_priority; extern int amdgpu_hw_i2c; @@ -147,35 +193,63 @@ extern int amdgpu_sched_jobs; extern int amdgpu_sched_hw_submission; extern uint amdgpu_pcie_gen_cap; extern uint amdgpu_pcie_lane_cap; -extern uint amdgpu_cg_mask; +extern u64 amdgpu_cg_mask; extern uint amdgpu_pg_mask; extern uint amdgpu_sdma_phase_quantum; extern char *amdgpu_disable_cu; extern char *amdgpu_virtual_display; extern uint amdgpu_pp_feature_mask; extern uint amdgpu_force_long_training; -extern int amdgpu_job_hang_limit; extern int amdgpu_lbpw; extern int amdgpu_compute_multipipe; extern int amdgpu_gpu_recovery; extern int amdgpu_emu_mode; extern uint amdgpu_smu_memory_pool_size; +extern int amdgpu_smu_pptable_id; extern uint amdgpu_dc_feature_mask; -extern uint amdgpu_dm_abm_level; +extern uint amdgpu_freesync_vid_mode; +extern uint amdgpu_dc_debug_mask; +extern uint amdgpu_dc_visual_confirm; +extern int amdgpu_dm_abm_level; +extern int amdgpu_backlight; +extern int amdgpu_damage_clips; extern struct amdgpu_mgpu_info mgpu_info; extern int amdgpu_ras_enable; extern uint amdgpu_ras_mask; +extern int amdgpu_bad_page_threshold; +extern bool amdgpu_ignore_bad_page_threshold; +extern struct amdgpu_watchdog_timer amdgpu_watchdog_timer; extern int amdgpu_async_gfx_ring; extern int amdgpu_mcbp; extern int amdgpu_discovery; extern int amdgpu_mes; +extern int amdgpu_mes_log_enable; +extern int amdgpu_mes_kiq; +extern int amdgpu_uni_mes; extern int amdgpu_noretry; extern int amdgpu_force_asic_type; +extern int amdgpu_smartshift_bias; +extern int amdgpu_use_xgmi_p2p; +extern int amdgpu_mtype_local; +extern int amdgpu_enforce_isolation; #ifdef CONFIG_HSA_AMD extern int sched_policy; +extern bool debug_evictions; +extern bool no_system_mem_limit; +extern int halt_if_hws_hang; +extern uint amdgpu_svm_default_granularity; #else -static const int sched_policy = KFD_SCHED_POLICY_HWS; +static const int __maybe_unused sched_policy = KFD_SCHED_POLICY_HWS; +static const bool __maybe_unused debug_evictions; /* = false */ +static const bool __maybe_unused no_system_mem_limit; +static const int __maybe_unused halt_if_hws_hang; #endif +#ifdef CONFIG_HSA_AMD_P2P +extern bool pcie_p2p; +#endif + +extern int amdgpu_tmz; +extern int amdgpu_reset_method; #ifdef CONFIG_DRM_AMDGPU_SI extern int amdgpu_si_support; @@ -183,19 +257,34 @@ extern int amdgpu_si_support; #ifdef CONFIG_DRM_AMDGPU_CIK extern int amdgpu_cik_support; #endif +extern int amdgpu_num_kcq; + +#define AMDGPU_VCNFW_LOG_SIZE (32 * 1024) +#define AMDGPU_UMSCHFW_LOG_SIZE (32 * 1024) +extern int amdgpu_vcnfw_log; +extern int amdgpu_sg_display; +extern int amdgpu_umsch_mm; +extern int amdgpu_seamless; +extern int amdgpu_umsch_mm_fwlog; + +extern int amdgpu_user_partt_mode; +extern int amdgpu_agp; +extern int amdgpu_rebar; + +extern int amdgpu_wbrf; +extern int amdgpu_user_queue; #define AMDGPU_VM_MAX_NUM_CTX 4096 #define AMDGPU_SG_THRESHOLD (256*1024*1024) -#define AMDGPU_DEFAULT_GTT_SIZE_MB 3072ULL /* 3GB by default */ #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000 #define AMDGPU_MAX_USEC_TIMEOUT 100000 /* 100 ms */ #define AMDGPU_FENCE_JIFFIES_TIMEOUT (HZ / 2) -/* AMDGPU_IB_POOL_SIZE must be a power of 2 */ -#define AMDGPU_IB_POOL_SIZE 16 #define AMDGPU_DEBUGFS_MAX_COMPONENTS 32 #define AMDGPUFB_CONN_LIMIT 4 #define AMDGPU_BIOS_NUM_SCRATCH 16 +#define AMDGPU_VBIOS_VGA_ALLOCATION (9 * 1024 * 1024) /* reserve 8MB for vga emulator and 1 MB for FB */ + /* hard reset data */ #define AMDGPU_ASIC_RESET_DATA 0x39d5e86b @@ -216,19 +305,32 @@ extern int amdgpu_cik_support; #define AMDGPU_RESET_VCE (1 << 13) #define AMDGPU_RESET_VCE1 (1 << 14) +/* reset mask */ +#define AMDGPU_RESET_TYPE_FULL (1 << 0) /* full adapter reset, mode1/mode2/BACO/etc. */ +#define AMDGPU_RESET_TYPE_SOFT_RESET (1 << 1) /* IP level soft reset */ +#define AMDGPU_RESET_TYPE_PER_QUEUE (1 << 2) /* per queue */ +#define AMDGPU_RESET_TYPE_PER_PIPE (1 << 3) /* per pipe */ + /* max cursor sizes (in pixels) */ #define CIK_CURSOR_WIDTH 128 #define CIK_CURSOR_HEIGHT 128 +/* smart shift bias level limits */ +#define AMDGPU_SMARTSHIFT_MAX_BIAS (100) +#define AMDGPU_SMARTSHIFT_MIN_BIAS (-100) + +/* Extra time delay(in ms) to eliminate the influence of temperature momentary fluctuation */ +#define AMDGPU_SWCTF_EXTRA_DELAY 50 + +struct amdgpu_xcp_mgr; struct amdgpu_device; -struct amdgpu_ib; -struct amdgpu_cs_parser; -struct amdgpu_job; struct amdgpu_irq_src; struct amdgpu_fpriv; struct amdgpu_bo_va_mapping; -struct amdgpu_atif; struct kfd_vm_fault_info; +struct amdgpu_hive_info; +struct amdgpu_reset_context; +struct amdgpu_reset_control; |
