mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
drm next for 5.9-rc1
core: - add user def flag to cmd line modes - dma_fence_wait added might_sleep - dma-fence lockdep annotations - indefinite fences are bad documentation - gem CMA functions used in more drivers - struct mutex removal - more drm_ debug macro usage - set/drop master api fixes - fix for drm/mm hole size comparison - drm/mm remove invalid entry optimization - optimise drm/mm hole handling - VRR debugfs added - uncompressed AFBC modifier support - multiple display id blocks in EDID - multiple driver sg handling fixes - __drm_atomic_helper_crtc_reset in all drivers - managed vram helpers ttm: - ttm_mem_reg handling cleanup - remove bo offset field - drop CMA memtype flag - drop mappable flag xilinx: - New Xilinx ZynqMP DisplayPort Subsystem driver nouveau: - add CRC support - start using NVIDIA published class header files - convert all push buffer emission to new macros - Proper push buffer space management for EVO/NVD channels. - firmware loading fixes - 2MiB system memory pages support on Pascal and newer vkms: - larget cursor support i915: - Rocketlake platform enablement - Early DG1 enablement - Numerous GEM refactorings - DP MST fixes - FBC, PSR, Cursor, Color, Gamma fixes - TGL, RKL, EHL workaround updates - TGL 8K display support fixes - SDVO/HDMI/DVI fixes amdgpu: - Initial support for Sienna Cichlid GPU - Initial support for Navy Flounder GPU - SI UVD/VCE support - expose rotation property - Add support for unique id on Arcturus - Enable runtime PM on vega10 boards that support BACO - Skip BAR resizing if the bios already did id - Major swSMU code cleanup - Fixes for DCN bandwidth calculations amdkfd: - Track SDMA usage per process - SMI events interface radeon: - Default to on chip GART for AGP boards on all arches - Runtime PM reference count fixes msm: - headers regenerated causing churn - a650/a640 display and GPU enablement - dpu dither support for 6bpc panels - dpu cursor fix - dsi/mdp5 enablement for sdm630/sdm636/sdm66 tegra: - video capture prep support - reflection support mediatek: - convert mtk_dsi to bridge API meson: - FBC support sun4i: - iommu support rockchip: - register locking fix - per-pixel alpha support PX30 VOP - mgag200: - ported to simple and shmem helpers - device init cleanups - use managed pci functions - dropped hw cursor support ast: - use managed pci functions - use managed VRAM helpers - rework cursor support malidp: - dev_groups support hibmc: - refactor hibmc_drv_vdac: vc4: - create TXP CRTC imx: - error path fixes and cleanups etnaviv: - clock handling and error handling cleanups - use pin_user_pages -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJfK1atAAoJEAx081l5xIa+vDkQAJvl/mjbEA7fDy8Ysa0cgPLI 8nI4Bo/MaxkyRfUcP8+f/n3QQrRME37C0xa/Mn6SG1oFAdlovPwDqmDr5kjhkrMI geo8oJb2Q+AsrJr+ejpuF+iq0FxWi64bLbwJFJ2nBet+lHTMzoPceWeq3gG1Vvfl h6PV4B/9TjrnbhcKLIQSEmJ0kZp9uMkDBF/iynVn4+AKAkG1rQNjigdTH48IFPoz 28KuqG0B4NWu648zYXhjsN0kD3Dxjv3YOH+FsoWQpQa9icCTySYbySsQ7l0/XvA3 4BPtP3rWMhU46FHTBkWF72WQR4F0B4wm5DJJKMeG4vb1mXakOqAKcAq7JAbka+wL PBIiU+AcAKRSiwHmYDuDWtDoSpvYncuo0p3IvNP5hhih+7hqCnLIULDWS+V8AUzW 39usS/DXsVKk/HGYIYC89cRwsqWYD4c7edzOBdPQxW4LNYCD2gXezLJ5TeeR2lih y9JIVnPiluWleOovs4W3BoZNRuLc1rHBO6COToXjlme/48Z+sRHBAoge6UZurqRN jr+e60cS7n/DOeJQuNf4UHZnK48Pc24+3kVfMHlX+OKn8VuKPGr+USkeHV/NYL/B USiKCAxkkZM0dxerSb1/Ra9kGnchf0QBpA6Fsem8kV61Z4GVc+K6xJWg7KXB6n/3 7ZyalUKLwlOCz9sYsCCe =Yvtd -----END PGP SIGNATURE----- Merge tag 'drm-next-2020-08-06' of git://anongit.freedesktop.org/drm/drm Pull drm updates from Dave Airlie: "New xilinx displayport driver, AMD support for two new GPUs (more header files), i915 initial support for RocketLake and some work on their DG1 (discrete chip). The core also grew some lockdep annotations to try and constrain what drivers do with dma-fences, and added some documentation on why the idea of indefinite fences doesn't work. The long list is below. I do have some fixes trees outstanding, but I'll follow up with those later. core: - add user def flag to cmd line modes - dma_fence_wait added might_sleep - dma-fence lockdep annotations - indefinite fences are bad documentation - gem CMA functions used in more drivers - struct mutex removal - more drm_ debug macro usage - set/drop master api fixes - fix for drm/mm hole size comparison - drm/mm remove invalid entry optimization - optimise drm/mm hole handling - VRR debugfs added - uncompressed AFBC modifier support - multiple display id blocks in EDID - multiple driver sg handling fixes - __drm_atomic_helper_crtc_reset in all drivers - managed vram helpers ttm: - ttm_mem_reg handling cleanup - remove bo offset field - drop CMA memtype flag - drop mappable flag xilinx: - New Xilinx ZynqMP DisplayPort Subsystem driver nouveau: - add CRC support - start using NVIDIA published class header files - convert all push buffer emission to new macros - Proper push buffer space management for EVO/NVD channels. - firmware loading fixes - 2MiB system memory pages support on Pascal and newer vkms: - larger cursor support i915: - Rocketlake platform enablement - Early DG1 enablement - Numerous GEM refactorings - DP MST fixes - FBC, PSR, Cursor, Color, Gamma fixes - TGL, RKL, EHL workaround updates - TGL 8K display support fixes - SDVO/HDMI/DVI fixes amdgpu: - Initial support for Sienna Cichlid GPU - Initial support for Navy Flounder GPU - SI UVD/VCE support - expose rotation property - Add support for unique id on Arcturus - Enable runtime PM on vega10 boards that support BACO - Skip BAR resizing if the bios already did id - Major swSMU code cleanup - Fixes for DCN bandwidth calculations amdkfd: - Track SDMA usage per process - SMI events interface radeon: - Default to on chip GART for AGP boards on all arches - Runtime PM reference count fixes msm: - headers regenerated causing churn - a650/a640 display and GPU enablement - dpu dither support for 6bpc panels - dpu cursor fix - dsi/mdp5 enablement for sdm630/sdm636/sdm66 tegra: - video capture prep support - reflection support mediatek: - convert mtk_dsi to bridge API meson: - FBC support sun4i: - iommu support rockchip: - register locking fix - per-pixel alpha support PX30 VOP mgag200: - ported to simple and shmem helpers - device init cleanups - use managed pci functions - dropped hw cursor support ast: - use managed pci functions - use managed VRAM helpers - rework cursor support malidp: - dev_groups support hibmc: - refactor hibmc_drv_vdac: vc4: - create TXP CRTC imx: - error path fixes and cleanups etnaviv: - clock handling and error handling cleanups - use pin_user_pages" * tag 'drm-next-2020-08-06' of git://anongit.freedesktop.org/drm/drm: (1747 commits) drm/msm: use kthread_create_worker instead of kthread_run drm/msm/mdp5: Add MDP5 configuration for SDM636/660 drm/msm/dsi: Add DSI configuration for SDM660 drm/msm/mdp5: Add MDP5 configuration for SDM630 drm/msm/dsi: Add phy configuration for SDM630/636/660 drm/msm/a6xx: add A640/A650 hwcg drm/msm/a6xx: hwcg tables in gpulist drm/msm/dpu: add SM8250 to hw catalog drm/msm/dpu: add SM8150 to hw catalog drm/msm/dpu: intf timing path for displayport drm/msm/dpu: set missing flush bits for INTF_2 and INTF_3 drm/msm/dpu: don't use INTF_INPUT_CTRL feature on sdm845 drm/msm/dpu: move some sspp caps to dpu_caps drm/msm/dpu: update UBWC config for sm8150 and sm8250 drm/msm/dpu: use right setup_blend_config for sm8150 and sm8250 drm/msm/a6xx: set ubwc config for A640 and A650 drm/msm/adreno: un-open-code some packets drm/msm: sync generated headers drm/msm/a6xx: add build_bw_table for A640/A650 drm/msm/a6xx: fix crashstate capture for A650 ...
This commit is contained in:
commit
8186749621
@ -36,6 +36,9 @@ properties:
|
||||
- const: bus
|
||||
- const: mod
|
||||
|
||||
iommus:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
|
@ -1,174 +0,0 @@
|
||||
Broadcom VC4 (VideoCore4) GPU
|
||||
|
||||
The VC4 device present on the Raspberry Pi includes a display system
|
||||
with HDMI output and the HVS (Hardware Video Scaler) for compositing
|
||||
display planes.
|
||||
|
||||
Required properties for VC4:
|
||||
- compatible: Should be "brcm,bcm2835-vc4" or "brcm,cygnus-vc4"
|
||||
|
||||
Required properties for Pixel Valve:
|
||||
- compatible: Should be one of "brcm,bcm2835-pixelvalve0",
|
||||
"brcm,bcm2835-pixelvalve1", or "brcm,bcm2835-pixelvalve2"
|
||||
- reg: Physical base address and length of the PV's registers
|
||||
- interrupts: The interrupt number
|
||||
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
|
||||
|
||||
Required properties for HVS:
|
||||
- compatible: Should be "brcm,bcm2835-hvs"
|
||||
- reg: Physical base address and length of the HVS's registers
|
||||
- interrupts: The interrupt number
|
||||
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
|
||||
|
||||
Required properties for HDMI
|
||||
- compatible: Should be "brcm,bcm2835-hdmi"
|
||||
- reg: Physical base address and length of the two register ranges
|
||||
("HDMI" and "HD", in that order)
|
||||
- interrupts: The interrupt numbers
|
||||
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
|
||||
- ddc: phandle of the I2C controller used for DDC EDID probing
|
||||
- clocks: a) hdmi: The HDMI state machine clock
|
||||
b) pixel: The pixel clock.
|
||||
|
||||
Optional properties for HDMI:
|
||||
- hpd-gpios: The GPIO pin for HDMI hotplug detect (if it doesn't appear
|
||||
as an interrupt/status bit in the HDMI controller
|
||||
itself). See bindings/pinctrl/brcm,bcm2835-gpio.txt
|
||||
- dmas: Should contain one entry pointing to the DMA channel used to
|
||||
transfer audio data
|
||||
- dma-names: Should contain "audio-rx"
|
||||
|
||||
Required properties for DPI:
|
||||
- compatible: Should be "brcm,bcm2835-dpi"
|
||||
- reg: Physical base address and length of the registers
|
||||
- clocks: a) core: The core clock the unit runs on
|
||||
b) pixel: The pixel clock that feeds the pixelvalve
|
||||
- port: Port node with a single endpoint connecting to the panel
|
||||
device, as defined in [1]
|
||||
|
||||
Required properties for VEC:
|
||||
- compatible: Should be "brcm,bcm2835-vec"
|
||||
- reg: Physical base address and length of the registers
|
||||
- clocks: The core clock the unit runs on
|
||||
- interrupts: The interrupt number
|
||||
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
|
||||
|
||||
Required properties for V3D:
|
||||
- compatible: Should be "brcm,bcm2835-v3d" or "brcm,cygnus-v3d"
|
||||
- reg: Physical base address and length of the V3D's registers
|
||||
- interrupts: The interrupt number
|
||||
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
|
||||
|
||||
Optional properties for V3D:
|
||||
- clocks: The clock the unit runs on
|
||||
|
||||
Required properties for DSI:
|
||||
- compatible: Should be "brcm,bcm2835-dsi0" or "brcm,bcm2835-dsi1"
|
||||
- reg: Physical base address and length of the DSI block's registers
|
||||
- interrupts: The interrupt number
|
||||
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
|
||||
- clocks: a) phy: The DSI PLL clock feeding the DSI analog PHY
|
||||
b) escape: The DSI ESC clock from CPRMAN
|
||||
c) pixel: The DSI pixel clock from CPRMAN
|
||||
- clock-output-names:
|
||||
The 3 clocks output from the DSI analog PHY: dsi[01]_byte,
|
||||
dsi[01]_ddr2, and dsi[01]_ddr
|
||||
|
||||
Required properties for the TXP (writeback) block:
|
||||
- compatible: Should be "brcm,bcm2835-txp"
|
||||
- reg: Physical base address and length of the TXP block's registers
|
||||
- interrupts: The interrupt number
|
||||
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
|
||||
|
||||
[1] Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
|
||||
Example:
|
||||
pixelvalve@7e807000 {
|
||||
compatible = "brcm,bcm2835-pixelvalve2";
|
||||
reg = <0x7e807000 0x100>;
|
||||
interrupts = <2 10>; /* pixelvalve */
|
||||
};
|
||||
|
||||
hvs@7e400000 {
|
||||
compatible = "brcm,bcm2835-hvs";
|
||||
reg = <0x7e400000 0x6000>;
|
||||
interrupts = <2 1>;
|
||||
};
|
||||
|
||||
hdmi: hdmi@7e902000 {
|
||||
compatible = "brcm,bcm2835-hdmi";
|
||||
reg = <0x7e902000 0x600>,
|
||||
<0x7e808000 0x100>;
|
||||
interrupts = <2 8>, <2 9>;
|
||||
ddc = <&i2c2>;
|
||||
hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
|
||||
clocks = <&clocks BCM2835_PLLH_PIX>,
|
||||
<&clocks BCM2835_CLOCK_HSM>;
|
||||
clock-names = "pixel", "hdmi";
|
||||
};
|
||||
|
||||
dpi: dpi@7e208000 {
|
||||
compatible = "brcm,bcm2835-dpi";
|
||||
reg = <0x7e208000 0x8c>;
|
||||
clocks = <&clocks BCM2835_CLOCK_VPU>,
|
||||
<&clocks BCM2835_CLOCK_DPI>;
|
||||
clock-names = "core", "pixel";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port {
|
||||
dpi_out: endpoint@0 {
|
||||
remote-endpoint = <&panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dsi1: dsi@7e700000 {
|
||||
compatible = "brcm,bcm2835-dsi1";
|
||||
reg = <0x7e700000 0x8c>;
|
||||
interrupts = <2 12>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#clock-cells = <1>;
|
||||
|
||||
clocks = <&clocks BCM2835_PLLD_DSI1>,
|
||||
<&clocks BCM2835_CLOCK_DSI1E>,
|
||||
<&clocks BCM2835_CLOCK_DSI1P>;
|
||||
clock-names = "phy", "escape", "pixel";
|
||||
|
||||
clock-output-names = "dsi1_byte", "dsi1_ddr2", "dsi1_ddr";
|
||||
|
||||
pitouchscreen: panel@0 {
|
||||
compatible = "raspberrypi,touchscreen";
|
||||
reg = <0>;
|
||||
|
||||
<...>
|
||||
};
|
||||
};
|
||||
|
||||
vec: vec@7e806000 {
|
||||
compatible = "brcm,bcm2835-vec";
|
||||
reg = <0x7e806000 0x1000>;
|
||||
clocks = <&clocks BCM2835_CLOCK_VEC>;
|
||||
interrupts = <2 27>;
|
||||
};
|
||||
|
||||
v3d: v3d@7ec00000 {
|
||||
compatible = "brcm,bcm2835-v3d";
|
||||
reg = <0x7ec00000 0x1000>;
|
||||
interrupts = <1 10>;
|
||||
};
|
||||
|
||||
vc4: gpu {
|
||||
compatible = "brcm,bcm2835-vc4";
|
||||
};
|
||||
|
||||
panel: panel {
|
||||
compatible = "ontat,yx700wv03", "simple-panel";
|
||||
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&dpi_out>;
|
||||
};
|
||||
};
|
||||
};
|
@ -0,0 +1,62 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-dpi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) DPI Controller
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: brcm,bcm2835-dpi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: The core clock the unit runs on
|
||||
- description: The pixel clock that feeds the pixelvalve
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
- const: pixel
|
||||
|
||||
port:
|
||||
type: object
|
||||
description: >
|
||||
Port node with a single endpoint connecting to the panel, as
|
||||
defined in Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/bcm2835.h>
|
||||
|
||||
dpi: dpi@7e208000 {
|
||||
compatible = "brcm,bcm2835-dpi";
|
||||
reg = <0x7e208000 0x8c>;
|
||||
clocks = <&clocks BCM2835_CLOCK_VPU>,
|
||||
<&clocks BCM2835_CLOCK_DPI>;
|
||||
clock-names = "core", "pixel";
|
||||
|
||||
port {
|
||||
dpi_out: endpoint {
|
||||
remote-endpoint = <&panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -0,0 +1,84 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-dsi0.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) DSI Controller
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
properties:
|
||||
"#clock-cells":
|
||||
const: 1
|
||||
|
||||
compatible:
|
||||
enum:
|
||||
- brcm,bcm2835-dsi0
|
||||
- brcm,bcm2835-dsi1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: The DSI PLL clock feeding the DSI analog PHY
|
||||
- description: The DSI ESC clock
|
||||
- description: The DSI pixel clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: escape
|
||||
- const: pixel
|
||||
|
||||
clock-output-names: true
|
||||
# FIXME: The meta-schemas don't seem to allow it for now
|
||||
# items:
|
||||
# - description: The DSI byte clock for the PHY
|
||||
# - description: The DSI DDR2 clock
|
||||
# - description: The DSI DDR clock
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- "#clock-cells"
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- clock-output-names
|
||||
- interrupts
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/bcm2835.h>
|
||||
|
||||
dsi1: dsi@7e700000 {
|
||||
compatible = "brcm,bcm2835-dsi1";
|
||||
reg = <0x7e700000 0x8c>;
|
||||
interrupts = <2 12>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#clock-cells = <1>;
|
||||
|
||||
clocks = <&clocks BCM2835_PLLD_DSI1>,
|
||||
<&clocks BCM2835_CLOCK_DSI1E>,
|
||||
<&clocks BCM2835_CLOCK_DSI1P>;
|
||||
clock-names = "phy", "escape", "pixel";
|
||||
|
||||
clock-output-names = "dsi1_byte", "dsi1_ddr2", "dsi1_ddr";
|
||||
|
||||
pitouchscreen: panel@0 {
|
||||
compatible = "raspberrypi,touchscreen";
|
||||
reg = <0>;
|
||||
|
||||
/* ... */
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -0,0 +1,80 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-hdmi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) HDMI Controller
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: brcm,bcm2835-hdmi
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: HDMI register range
|
||||
- description: HD register range
|
||||
|
||||
interrupts:
|
||||
minItems: 2
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: The pixel clock
|
||||
- description: The HDMI state machine clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pixel
|
||||
- const: hdmi
|
||||
|
||||
ddc:
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: >
|
||||
Phandle of the I2C controller used for DDC EDID probing
|
||||
|
||||
hpd-gpios:
|
||||
description: >
|
||||
The GPIO pin for the HDMI hotplug detect (if it doesn't appear
|
||||
as an interrupt/status bit in the HDMI controller itself)
|
||||
|
||||
dmas:
|
||||
maxItems: 1
|
||||
description: >
|
||||
Should contain one entry pointing to the DMA channel used to
|
||||
transfer audio data.
|
||||
|
||||
dma-names:
|
||||
const: audio-rx
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- ddc
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/bcm2835.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
hdmi: hdmi@7e902000 {
|
||||
compatible = "brcm,bcm2835-hdmi";
|
||||
reg = <0x7e902000 0x600>,
|
||||
<0x7e808000 0x100>;
|
||||
interrupts = <2 8>, <2 9>;
|
||||
ddc = <&i2c2>;
|
||||
hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
|
||||
clocks = <&clocks BCM2835_PLLH_PIX>,
|
||||
<&clocks BCM2835_CLOCK_HSM>;
|
||||
clock-names = "pixel", "hdmi";
|
||||
};
|
||||
|
||||
...
|
@ -0,0 +1,37 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-hvs.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) Hardware Video Scaler
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: brcm,bcm2835-hvs
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
hvs@7e400000 {
|
||||
compatible = "brcm,bcm2835-hvs";
|
||||
reg = <0x7e400000 0x6000>;
|
||||
interrupts = <2 1>;
|
||||
};
|
||||
|
||||
...
|
@ -0,0 +1,40 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-pixelvalve0.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) PixelValve
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- brcm,bcm2835-pixelvalve0
|
||||
- brcm,bcm2835-pixelvalve1
|
||||
- brcm,bcm2835-pixelvalve2
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
pixelvalve@7e807000 {
|
||||
compatible = "brcm,bcm2835-pixelvalve2";
|
||||
reg = <0x7e807000 0x100>;
|
||||
interrupts = <2 10>; /* pixelvalve */
|
||||
};
|
||||
|
||||
...
|
@ -0,0 +1,37 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-txp.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) TXP (writeback) Controller
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: brcm,bcm2835-txp
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
txp: txp@7e004000 {
|
||||
compatible = "brcm,bcm2835-txp";
|
||||
reg = <0x7e004000 0x20>;
|
||||
interrupts = <1 11>;
|
||||
};
|
||||
|
||||
...
|
@ -0,0 +1,42 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-v3d.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) V3D GPU
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- brcm,bcm2835-v3d
|
||||
- brcm,cygnus-v3d
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
v3d: v3d@7ec00000 {
|
||||
compatible = "brcm,bcm2835-v3d";
|
||||
reg = <0x7ec00000 0x1000>;
|
||||
interrupts = <1 10>;
|
||||
};
|
||||
|
||||
...
|
@ -0,0 +1,34 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-vc4.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) GPU
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
description: >
|
||||
The VC4 device present on the Raspberry Pi includes a display system
|
||||
with HDMI output and the HVS (Hardware Video Scaler) for compositing
|
||||
display planes.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- brcm,bcm2835-vc4
|
||||
- brcm,cygnus-vc4
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
vc4: gpu {
|
||||
compatible = "brcm,bcm2835-vc4";
|
||||
};
|
||||
|
||||
...
|
@ -0,0 +1,44 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-vec.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) VEC
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: brcm,bcm2835-vec
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/bcm2835.h>
|
||||
|
||||
vec: vec@7e806000 {
|
||||
compatible = "brcm,bcm2835-vec";
|
||||
reg = <0x7e806000 0x1000>;
|
||||
clocks = <&clocks BCM2835_CLOCK_VEC>;
|
||||
interrupts = <2 27>;
|
||||
};
|
||||
|
||||
...
|
@ -165,6 +165,7 @@ examples:
|
||||
- |
|
||||
|
||||
#include <dt-bindings/clock/imx8mq-clock.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/reset/imx8mq-reset.h>
|
||||
|
||||
@ -191,12 +192,12 @@ examples:
|
||||
phy-names = "dphy";
|
||||
|
||||
panel@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "rocktech,jh057n00900";
|
||||
reg = <0>;
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
vcc-supply = <®_2v8_p>;
|
||||
iovcc-supply = <®_1v8_p>;
|
||||
reset-gpios = <&gpio3 13 GPIO_ACTIVE_LOW>;
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&mipi_dsi_out>;
|
||||
};
|
||||
|
@ -1,85 +0,0 @@
|
||||
Renesas R-Car LVDS Encoder
|
||||
==========================
|
||||
|
||||
These DT bindings describe the LVDS encoder embedded in the Renesas R-Car
|
||||
Gen2, R-Car Gen3 and RZ/G SoCs.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : Shall contain one of
|
||||
- "renesas,r8a7743-lvds" for R8A7743 (RZ/G1M) compatible LVDS encoders
|
||||
- "renesas,r8a7744-lvds" for R8A7744 (RZ/G1N) compatible LVDS encoders
|
||||
- "renesas,r8a774a1-lvds" for R8A774A1 (RZ/G2M) compatible LVDS encoders
|
||||
- "renesas,r8a774b1-lvds" for R8A774B1 (RZ/G2N) compatible LVDS encoders
|
||||
- "renesas,r8a774c0-lvds" for R8A774C0 (RZ/G2E) compatible LVDS encoders
|
||||
- "renesas,r8a7790-lvds" for R8A7790 (R-Car H2) compatible LVDS encoders
|
||||
- "renesas,r8a7791-lvds" for R8A7791 (R-Car M2-W) compatible LVDS encoders
|
||||
- "renesas,r8a7793-lvds" for R8A7793 (R-Car M2-N) compatible LVDS encoders
|
||||
- "renesas,r8a7795-lvds" for R8A7795 (R-Car H3) compatible LVDS encoders
|
||||
- "renesas,r8a7796-lvds" for R8A7796 (R-Car M3-W) compatible LVDS encoders
|
||||
- "renesas,r8a77965-lvds" for R8A77965 (R-Car M3-N) compatible LVDS encoders
|
||||
- "renesas,r8a77970-lvds" for R8A77970 (R-Car V3M) compatible LVDS encoders
|
||||
- "renesas,r8a77980-lvds" for R8A77980 (R-Car V3H) compatible LVDS encoders
|
||||
- "renesas,r8a77990-lvds" for R8A77990 (R-Car E3) compatible LVDS encoders
|
||||
- "renesas,r8a77995-lvds" for R8A77995 (R-Car D3) compatible LVDS encoders
|
||||
|
||||
- reg: Base address and length for the memory-mapped registers
|
||||
- clocks: A list of phandles + clock-specifier pairs, one for each entry in
|
||||
the clock-names property.
|
||||
- clock-names: Name of the clocks. This property is model-dependent.
|
||||
- The functional clock, which mandatory for all models, shall be listed
|
||||
first, and shall be named "fck".
|
||||
- On R8A77990, R8A77995 and R8A774C0, the LVDS encoder can use the EXTAL or
|
||||
DU_DOTCLKINx clocks. Those clocks are optional. When supplied they must be
|
||||
named "extal" and "dclkin.x" respectively, with "x" being the DU_DOTCLKIN
|
||||
numerical index.
|
||||
- When the clocks property only contains the functional clock, the
|
||||
clock-names property may be omitted.
|
||||
- resets: A phandle + reset specifier for the module reset
|
||||
|
||||
Required nodes:
|
||||
|
||||
The LVDS encoder has two video ports. Their connections are modelled using the
|
||||
OF graph bindings specified in Documentation/devicetree/bindings/graph.txt.
|
||||
|
||||
- Video port 0 corresponds to the parallel RGB input
|
||||
- Video port 1 corresponds to the LVDS output
|
||||
|
||||
Each port shall have a single endpoint.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- renesas,companion : phandle to the companion LVDS encoder. This property is
|
||||
mandatory for the first LVDS encoder on D3 and E3 SoCs, and shall point to
|
||||
the second encoder to be used as a companion in dual-link mode. It shall not
|
||||
be set for any other LVDS encoder.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
lvds0: lvds@feb90000 {
|
||||
compatible = "renesas,r8a77990-lvds";
|
||||
reg = <0 0xfeb90000 0 0x20>;
|
||||
clocks = <&cpg CPG_MOD 727>;
|
||||
power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 727>;
|
||||
|
||||
renesas,companion = <&lvds1>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
lvds0_in: endpoint {
|
||||
remote-endpoint = <&du_out_lvds0>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
lvds0_out: endpoint {
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -0,0 +1,248 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/renesas,lvds.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas R-Car LVDS Encoder
|
||||
|
||||
maintainers:
|
||||
- Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
|
||||
description: |
|
||||
These DT bindings describe the LVDS encoder embedded in the Renesas R-Car
|
||||
Gen2, R-Car Gen3, RZ/G1 and RZ/G2 SoCs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- renesas,r8a7743-lvds # for RZ/G1M compatible LVDS encoders
|
||||
- renesas,r8a7744-lvds # for RZ/G1N compatible LVDS encoders
|
||||
- renesas,r8a774a1-lvds # for RZ/G2M compatible LVDS encoders
|
||||
- renesas,r8a774b1-lvds # for RZ/G2N compatible LVDS encoders
|
||||
- renesas,r8a774c0-lvds # for RZ/G2E compatible LVDS encoders
|
||||
- renesas,r8a7790-lvds # for R-Car H2 compatible LVDS encoders
|
||||
- renesas,r8a7791-lvds # for R-Car M2-W compatible LVDS encoders
|
||||
- renesas,r8a7793-lvds # for R-Car M2-N compatible LVDS encoders
|
||||
- renesas,r8a7795-lvds # for R-Car H3 compatible LVDS encoders
|
||||
- renesas,r8a7796-lvds # for R-Car M3-W compatible LVDS encoders
|
||||
- renesas,r8a77965-lvds # for R-Car M3-N compatible LVDS encoders
|
||||
- renesas,r8a77970-lvds # for R-Car V3M compatible LVDS encoders
|
||||
- renesas,r8a77980-lvds # for R-Car V3H compatible LVDS encoders
|
||||
- renesas,r8a77990-lvds # for R-Car E3 compatible LVDS encoders
|
||||
- renesas,r8a77995-lvds # for R-Car D3 compatible LVDS encoders
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
type: object
|
||||
description: |
|
||||
This device has two video ports. Their connections are modelled using the
|
||||
OF graph bindings specified in Documentation/devicetree/bindings/graph.txt.
|
||||
Each port shall have a single endpoint.
|
||||
|
||||
properties:
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
port@0:
|
||||
type: object
|
||||
description: Parallel RGB input port
|
||||
|
||||
port@1:
|
||||
type: object
|
||||
description: LVDS output port
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
renesas,companion:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
phandle to the companion LVDS encoder. This property is mandatory
|
||||
for the first LVDS encoder on D3 and E3 SoCs, and shall point to
|
||||
the second encoder to be used as a companion in dual-link mode. It
|
||||
shall not be set for any other LVDS encoder.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- power-domains
|
||||
- resets
|
||||
- ports
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- renesas,r8a774c0-lvds
|
||||
- renesas,r8a77990-lvds
|
||||
- renesas,r8a77995-lvds
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
items:
|
||||
- description: Functional clock
|
||||
- description: EXTAL input clock
|
||||
- description: DU_DOTCLKIN0 input clock
|
||||
- description: DU_DOTCLKIN1 input clock
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
items:
|
||||
- const: fck
|
||||
# The LVDS encoder can use the EXTAL or DU_DOTCLKINx clocks.
|
||||
# These clocks are optional.
|
||||
- enum:
|
||||
- extal
|
||||
- dclkin.0
|
||||
- dclkin.1
|
||||
- enum:
|
||||
- extal
|
||||
- dclkin.0
|
||||
- dclkin.1
|
||||
- enum:
|
||||
- extal
|
||||
- dclkin.0
|
||||
- dclkin.1
|
||||
|
||||
required:
|
||||
- clock-names
|
||||
|
||||
else:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
items:
|
||||
- description: Functional clock
|
||||
|
||||
clock-names:
|
||||
maxItems: 1
|
||||
items:
|
||||
- const: fck
|
||||
|
||||
renesas,companion: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/renesas-cpg-mssr.h>
|
||||
#include <dt-bindings/power/r8a7795-sysc.h>
|
||||
|
||||
lvds@feb90000 {
|
||||
compatible = "renesas,r8a7795-lvds";
|
||||
reg = <0xfeb90000 0x14>;
|
||||
clocks = <&cpg CPG_MOD 727>;
|
||||
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 727>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
lvds_in: endpoint {
|
||||
remote-endpoint = <&du_out_lvds0>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
lvds_out: endpoint {
|
||||
remote-endpoint = <&panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
#include <dt-bindings/clock/renesas-cpg-mssr.h>
|
||||
#include <dt-bindings/power/r8a77990-sysc.h>
|
||||
|
||||
lvds0: lvds@feb90000 {
|
||||
compatible = "renesas,r8a77990-lvds";
|
||||
reg = <0xfeb90000 0x20>;
|
||||
clocks = <&cpg CPG_MOD 727>,
|
||||
<&x13_clk>,
|
||||
<&extal_clk>;
|
||||
clock-names = "fck", "dclkin.0", "extal";
|
||||
power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 727>;
|
||||
|
||||
renesas,companion = <&lvds1>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
lvds0_in: endpoint {
|
||||
remote-endpoint = <&du_out_lvds0>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
lvds0_out: endpoint {
|
||||
remote-endpoint = <&panel_in1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
lvds1: lvds@feb90100 {
|
||||
compatible = "renesas,r8a77990-lvds";
|
||||
reg = <0xfeb90100 0x20>;
|
||||
clocks = <&cpg CPG_MOD 727>,
|
||||
<&x13_clk>,
|
||||
<&extal_clk>;
|
||||
clock-names = "fck", "dclkin.0", "extal";
|
||||
power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 726>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
lvds1_in: endpoint {
|
||||
remote-endpoint = <&du_out_lvds1>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
lvds1_out: endpoint {
|
||||
remote-endpoint = <&panel_in2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -1,87 +0,0 @@
|
||||
SN65DSI86 DSI to eDP bridge chip
|
||||
--------------------------------
|
||||
|
||||
This is the binding for Texas Instruments SN65DSI86 bridge.
|
||||
https://www.ti.com/general/docs/lit/getliterature.tsp?genericPartNumber=sn65dsi86&fileType=pdf
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "ti,sn65dsi86"
|
||||
- reg: i2c address of the chip, 0x2d as per datasheet
|
||||
- enable-gpios: gpio specification for bridge_en pin (active high)
|
||||
|
||||
- vccio-supply: A 1.8V supply that powers up the digital IOs.
|
||||
- vpll-supply: A 1.8V supply that powers up the displayport PLL.
|
||||
- vcca-supply: A 1.2V supply that powers up the analog circuits.
|
||||
- vcc-supply: A 1.2V supply that powers up the digital core.
|
||||
|
||||
Optional properties:
|
||||
- interrupts-extended: Specifier for the SN65DSI86 interrupt line.
|
||||
|
||||
- gpio-controller: Marks the device has a GPIO controller.
|
||||
- #gpio-cells : Should be two. The first cell is the pin number and
|
||||
the second cell is used to specify flags.
|
||||
See ../../gpio/gpio.txt for more information.
|
||||
- #pwm-cells : Should be one. See ../../pwm/pwm.yaml for description of
|
||||
the cell formats.
|
||||
|
||||
- clock-names: should be "refclk"
|
||||
- clocks: Specification for input reference clock. The reference
|
||||
clock rate must be 12 MHz, 19.2 MHz, 26 MHz, 27 MHz or 38.4 MHz.
|
||||
|
||||
- data-lanes: See ../../media/video-interface.txt
|
||||
- lane-polarities: See ../../media/video-interface.txt
|
||||
|
||||
- suspend-gpios: specification for GPIO1 pin on bridge (active low)
|
||||
|
||||
Required nodes:
|
||||
This device has two video ports. Their connections are modelled using the
|
||||
OF graph bindings specified in Documentation/devicetree/bindings/graph.txt.
|
||||
|
||||
- Video port 0 for DSI input
|
||||
- Video port 1 for eDP output
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
edp-bridge@2d {
|
||||
compatible = "ti,sn65dsi86";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x2d>;
|
||||
|
||||
enable-gpios = <&msmgpio 33 GPIO_ACTIVE_HIGH>;
|
||||
suspend-gpios = <&msmgpio 34 GPIO_ACTIVE_LOW>;
|
||||
|
||||
interrupts-extended = <&gpio3 4 IRQ_TYPE_EDGE_FALLING>;
|
||||
|
||||
vccio-supply = <&pm8916_l17>;
|
||||
vcca-supply = <&pm8916_l6>;
|
||||
vpll-supply = <&pm8916_l17>;
|
||||
vcc-supply = <&pm8916_l6>;
|
||||
|
||||
clock-names = "refclk";
|
||||
clocks = <&input_refclk>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
edp_bridge_in: endpoint {
|
||||
remote-endpoint = <&dsi_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
edp_bridge_out: endpoint {
|
||||
data-lanes = <2 1 3 0>;
|
||||
lane-polarities = <0 1 0 1>;
|
||||
remote-endpoint = <&edp_panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
@ -0,0 +1,293 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/ti,sn65dsi86.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: SN65DSI86 DSI to eDP bridge chip
|
||||
|
||||
maintainers:
|
||||
- Sandeep Panda <spanda@codeaurora.org>
|
||||
|
||||
description: |
|
||||
The Texas Instruments SN65DSI86 bridge takes MIPI DSI in and outputs eDP.
|
||||
https://www.ti.com/general/docs/lit/getliterature.tsp?genericPartNumber=sn65dsi86&fileType=pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ti,sn65dsi86
|
||||
|
||||
reg:
|
||||
const: 0x2d
|
||||
|
||||
enable-gpios:
|
||||
maxItems: 1
|
||||
description: GPIO specifier for bridge_en pin (active high).
|
||||
|
||||
suspend-gpios:
|
||||
maxItems: 1
|
||||
description: GPIO specifier for GPIO1 pin on bridge (active low).
|
||||
|
||||
no-hpd:
|
||||
type: boolean
|
||||
description:
|
||||
Set if the HPD line on the bridge isn't hooked up to anything or is
|
||||
otherwise unusable.
|
||||
|
||||
vccio-supply:
|
||||
description: A 1.8V supply that powers the digital IOs.
|
||||
|
||||
vpll-supply:
|
||||
description: A 1.8V supply that powers the DisplayPort PLL.
|
||||
|
||||
vcca-supply:
|
||||
description: A 1.2V supply that powers the analog circuits.
|
||||
|
||||
vcc-supply:
|
||||
description: A 1.2V supply that powers the digital core.
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
description:
|
||||
Clock specifier for input reference clock. The reference clock rate must
|
||||
be 12 MHz, 19.2 MHz, 26 MHz, 27 MHz or 38.4 MHz.
|
||||
|
||||
clock-names:
|
||||
const: refclk
|
||||
|
||||
gpio-controller: true
|
||||
'#gpio-cells':
|
||||
const: 2
|
||||
description:
|
||||
First cell is pin number, second cell is flags. GPIO pin numbers are
|
||||
1-based to match the datasheet. See ../../gpio/gpio.txt for more
|
||||
information.
|
||||
|
||||
'#pwm-cells':
|
||||
const: 1
|
||||
description: See ../../pwm/pwm.yaml for description of the cell formats.
|
||||
|
||||
ports:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
port@0:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
description:
|
||||
Video port for MIPI DSI input
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 0
|
||||
|
||||
endpoint:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
remote-endpoint: true
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
port@1:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
description:
|
||||
Video port for eDP output (panel or connector).
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 1
|
||||
|
||||
endpoint:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
remote-endpoint: true
|
||||
|
||||
data-lanes:
|
||||
oneOf:
|
||||
- minItems: 1
|
||||
maxItems: 1
|
||||
uniqueItems: true
|
||||
items:
|
||||
enum:
|
||||
- 0
|
||||
- 1
|
||||
description:
|
||||
If you have 1 logical lane the bridge supports routing
|
||||
to either port 0 or port 1. Port 0 is suggested.
|
||||
See ../../media/video-interface.txt for details.
|
||||
|
||||
- minItems: 2
|
||||
maxItems: 2
|
||||
uniqueItems: true
|
||||
items:
|
||||
enum:
|
||||
- 0
|
||||
- 1
|
||||
description:
|
||||
If you have 2 logical lanes the bridge supports
|
||||
reordering but only on physical ports 0 and 1.
|
||||
See ../../media/video-interface.txt for details.
|
||||
|
||||
- minItems: 4
|
||||
maxItems: 4
|
||||
uniqueItems: true
|
||||
items:
|
||||
enum:
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
description:
|
||||
If you have 4 logical lanes the bridge supports
|
||||
reordering in any way.
|
||||
See ../../media/video-interface.txt for details.
|
||||
|
||||
lane-polarities:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
items:
|
||||
enum:
|
||||
- 0
|
||||
- 1
|
||||
description: See ../../media/video-interface.txt
|
||||
|
||||
dependencies:
|
||||
lane-polarities: [data-lanes]
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
required:
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- enable-gpios
|
||||
- vccio-supply
|
||||
- vpll-supply
|
||||
- vcca-supply
|
||||
- vcc-supply
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
bridge@2d {
|
||||
compatible = "ti,sn65dsi86";
|
||||
reg = <0x2d>;
|
||||
|
||||
interrupt-parent = <&tlmm>;
|
||||
interrupts = <10 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
enable-gpios = <&tlmm 102 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
vpll-supply = <&src_pp1800_s4a>;
|
||||
vccio-supply = <&src_pp1800_s4a>;
|
||||
vcca-supply = <&src_pp1200_l2a>;
|
||||
vcc-supply = <&src_pp1200_l2a>;
|
||||
|
||||
clocks = <&rpmhcc RPMH_LN_BB_CLK2>;
|
||||
clock-names = "refclk";
|
||||
|
||||
no-hpd;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
endpoint {
|
||||
remote-endpoint = <&panel_in_edp>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
bridge@2d {
|
||||
compatible = "ti,sn65dsi86";
|
||||
reg = <0x2d>;
|
||||
|
||||
enable-gpios = <&msmgpio 33 GPIO_ACTIVE_HIGH>;
|
||||
suspend-gpios = <&msmgpio 34 GPIO_ACTIVE_LOW>;
|
||||
|
||||
interrupts-extended = <&gpio3 4 IRQ_TYPE_EDGE_FALLING>;
|
||||
|
||||
vccio-supply = <&pm8916_l17>;
|
||||
vcca-supply = <&pm8916_l6>;
|
||||
vpll-supply = <&pm8916_l17>;
|
||||
vcc-supply = <&pm8916_l6>;
|
||||
|
||||
clock-names = "refclk";
|
||||
clocks = <&input_refclk>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
edp_bridge_in: endpoint {
|
||||
remote-endpoint = <&dsi_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
edp_bridge_out: endpoint {
|
||||
data-lanes = <2 1 3 0>;
|
||||
lane-polarities = <0 1 0 1>;
|
||||
remote-endpoint = <&edp_panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -1,66 +0,0 @@
|
||||
TFP410 DPI to DVI encoder
|
||||
=========================
|
||||
|
||||
Required properties:
|
||||
- compatible: "ti,tfp410"
|
||||
|
||||
Optional properties:
|
||||
- powerdown-gpios: power-down gpio
|
||||
- reg: I2C address. If and only if present the device node should be placed
|
||||
into the I2C controller node where the TFP410 I2C is connected to.
|
||||
- ti,deskew: data de-skew in 350ps increments, from -4 to +3, as configured
|
||||
through th DK[3:1] pins. This property shall be present only if the TFP410
|
||||
is not connected through I2C.
|
||||
|
||||
Required nodes:
|
||||
|
||||
This device has two video ports. Their connections are modeled using the OF
|
||||
graph bindings specified in [1]. Each port node shall have a single endpoint.
|
||||
|
||||
- Port 0 is the DPI input port. Its endpoint subnode shall contain a
|
||||
pclk-sample and bus-width property and a remote-endpoint property as specified
|
||||
in [1].
|
||||
- If pclk-sample is not defined, pclk-sample = 0 should be assumed for
|
||||
backward compatibility.
|
||||
- If bus-width is not defined then bus-width = 24 should be assumed for
|
||||
backward compatibility.
|
||||
bus-width = 24: 24 data lines are connected and single-edge mode
|
||||
bus-width = 12: 12 data lines are connected and dual-edge mode
|
||||
|
||||
- Port 1 is the DVI output port. Its endpoint subnode shall contain a
|
||||
remote-endpoint property is specified in [1].
|
||||
|
||||
[1] Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
tfp410: encoder@0 {
|
||||
compatible = "ti,tfp410";
|
||||
powerdown-gpios = <&twl_gpio 2 GPIO_ACTIVE_LOW>;
|
||||
ti,deskew = <4>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
tfp410_in: endpoint@0 {
|
||||
pclk-sample = <1>;
|
||||
bus-width = <24>;
|
||||
remote-endpoint = <&dpi_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
tfp410_out: endpoint@0 {
|
||||
remote-endpoint = <&dvi_connector_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
131
Documentation/devicetree/bindings/display/bridge/ti,tfp410.yaml
Normal file
131
Documentation/devicetree/bindings/display/bridge/ti,tfp410.yaml
Normal file
@ -0,0 +1,131 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/ti,tfp410.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: TFP410 DPI to DVI encoder
|
||||
|
||||
maintainers:
|
||||
- Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
- Jyri Sarha <jsarha@ti.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ti,tfp410
|
||||
|
||||
reg:
|
||||
description: I2C address of the device.
|
||||
maxItems: 1
|
||||
|
||||
powerdown-gpios:
|
||||
maxItems: 1
|
||||
|
||||
ti,deskew:
|
||||
description:
|
||||
Data de-skew value in 350ps increments, from 0 to 7, as configured
|
||||
through the DK[3:1] pins. The de-skew multiplier is computed as
|
||||
(DK[3:1] - 4), so it ranges from -4 to 3.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 7
|
||||
|
||||
ports:
|
||||
description:
|
||||
A node containing input and output port nodes with endpoint
|
||||
definitions as documented in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
type: object
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
description: DPI input port.
|
||||
type: object
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 0
|
||||
|
||||
endpoint:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
pclk-sample:
|
||||
description:
|
||||
Endpoint sampling edge.
|
||||
enum:
|
||||
- 0 # Falling edge
|
||||
- 1 # Rising edge
|
||||
default: 0
|
||||
|
||||
bus-width:
|
||||
description:
|
||||
Endpoint bus width.
|
||||
enum:
|
||||
- 12 # 12 data lines connected and dual-edge mode
|
||||
- 24 # 24 data lines connected and single-edge mode
|
||||
default: 24
|
||||
|
||||
port@1:
|
||||
description: DVI output port.
|
||||
type: object
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 1
|
||||
|
||||
endpoint:
|
||||
type: object
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- ports
|
||||
|
||||
if:
|
||||
required:
|
||||
- reg
|
||||
then:
|
||||
properties:
|
||||
ti,deskew: false
|
||||
else:
|
||||
required:
|
||||
- ti,deskew
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
tfp410: encoder {
|
||||
compatible = "ti,tfp410";
|
||||
powerdown-gpios = <&twl_gpio 2 GPIO_ACTIVE_LOW>;
|
||||
ti,deskew = <3>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
tfp410_in: endpoint {
|
||||
pclk-sample = <1>;
|
||||
bus-width = <24>;
|
||||
remote-endpoint = <&dpi_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
tfp410_out: endpoint {
|
||||
remote-endpoint = <&dvi_connector_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -1,31 +0,0 @@
|
||||
Analog TV Connector
|
||||
===================
|
||||
|
||||
Required properties:
|
||||
- compatible: "composite-video-connector" or "svideo-connector"
|
||||
|
||||
Optional properties:
|
||||
- label: a symbolic name for the connector
|
||||
- sdtv-standards: limit the supported TV standards on a connector to the given
|
||||
ones. If not specified all TV standards are allowed.
|
||||
Possible TV standards are defined in
|
||||
include/dt-bindings/display/sdtv-standards.h.
|
||||
|
||||
Required nodes:
|
||||
- Video port for TV input
|
||||
|
||||
Example
|
||||
-------
|
||||
#include <dt-bindings/display/sdtv-standards.h>
|
||||
|
||||
tv: connector {
|
||||
compatible = "composite-video-connector";
|
||||
label = "tv";
|
||||
sdtv-standards = <(SDTV_STD_PAL | SDTV_STD_NTSC)>;
|
||||
|
||||
port {
|
||||
tv_connector_in: endpoint {
|
||||
remote-endpoint = <&venc_out>;
|
||||
};
|
||||
};
|
||||
};
|
@ -0,0 +1,52 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/connector/analog-tv-connector.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog TV Connector
|
||||
|
||||
maintainers:
|
||||
- Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- composite-video-connector
|
||||
- svideo-connector
|
||||
|
||||
label: true
|
||||
|
||||
sdtv-standards:
|
||||
description:
|
||||
Limit the supported TV standards on a connector to the given ones. If
|
||||
not specified all TV standards are allowed. Possible TV standards are
|
||||
defined in include/dt-bindings/display/sdtv-standards.h.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
port:
|
||||
description: Connection to controller providing analog TV signals
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/display/sdtv-standards.h>
|
||||
|
||||
connector {
|
||||
compatible = "composite-video-connector";
|
||||
label = "tv";
|
||||
sdtv-standards = <(SDTV_STD_PAL | SDTV_STD_NTSC)>;
|
||||
|
||||
port {
|
||||
tv_connector_in: endpoint {
|
||||
remote-endpoint = <&venc_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -1,36 +0,0 @@
|
||||
DVI Connector
|
||||
==============
|
||||
|
||||
Required properties:
|
||||
- compatible: "dvi-connector"
|
||||
|
||||
Optional properties:
|
||||
- label: a symbolic name for the connector
|
||||
- ddc-i2c-bus: phandle to the i2c bus that is connected to DVI DDC
|
||||
- analog: the connector has DVI analog pins
|
||||
- digital: the connector has DVI digital pins
|
||||
- dual-link: the connector has pins for DVI dual-link
|
||||
- hpd-gpios: HPD GPIO number
|
||||
|
||||
Required nodes:
|
||||
- Video port for DVI input
|
||||
|
||||
Note: One (or both) of 'analog' or 'digital' must be set.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
dvi0: connector@0 {
|
||||
compatible = "dvi-connector";
|
||||
label = "dvi";
|
||||
|
||||
digital;
|
||||
|
||||
ddc-i2c-bus = <&i2c3>;
|
||||
|
||||
port {
|
||||
dvi_connector_in: endpoint {
|
||||
remote-endpoint = <&tfp410_out>;
|
||||
};
|
||||
};
|
||||
};
|
@ -0,0 +1,70 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/connector/dvi-connector.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: DVI Connector
|
||||
|
||||
maintainers:
|
||||
- Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: dvi-connector
|
||||
|
||||
label: true
|
||||
|
||||
hpd-gpios:
|
||||
description: A GPIO line connected to HPD
|
||||
maxItems: 1
|
||||
|
||||
ddc-i2c-bus:
|
||||
description: phandle link to the I2C controller used for DDC EDID probing
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
||||
analog:
|
||||
type: boolean
|
||||
description: the connector has DVI analog pins
|
||||
|
||||
digital:
|
||||
type: boolean
|
||||
description: the connector has DVI digital pins
|
||||
|
||||
dual-link:
|
||||
type: boolean
|
||||
description: the connector has pins for DVI dual-link
|
||||
|
||||
port:
|
||||
description: Connection to controller providing DVI signals
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- port
|
||||
|
||||
anyOf:
|
||||
- required:
|
||||
- analog
|
||||
- required:
|
||||
- digital
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
connector {
|
||||
compatible = "dvi-connector";
|
||||
label = "dvi";
|
||||
|
||||
digital;
|
||||
|
||||
ddc-i2c-bus = <&i2c3>;
|
||||
|
||||
port {
|
||||
dvi_connector_in: endpoint {
|
||||
remote-endpoint = <&tfp410_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -1,31 +0,0 @@
|
||||
HDMI Connector
|
||||
==============
|
||||
|
||||
Required properties:
|
||||
- compatible: "hdmi-connector"
|
||||
- type: the HDMI connector type: "a", "b", "c", "d" or "e"
|
||||
|
||||
Optional properties:
|
||||
- label: a symbolic name for the connector
|
||||
- hpd-gpios: HPD GPIO number
|
||||
- ddc-i2c-bus: phandle link to the I2C controller used for DDC EDID probing
|
||||
- ddc-en-gpios: signal to enable DDC bus
|
||||
|
||||
Required nodes:
|
||||
- Video port for HDMI input
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
hdmi0: connector@1 {
|
||||
compatible = "hdmi-connector";
|
||||
label = "hdmi";
|
||||
|
||||
type = "a";
|
||||
|
||||
port {
|
||||
hdmi_connector_in: endpoint {
|
||||
remote-endpoint = <&tpd12s015_out>;
|
||||
};
|
||||
};
|
||||
};
|
@ -0,0 +1,64 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/connector/hdmi-connector.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: HDMI Connector
|
||||
|
||||
maintainers:
|
||||
- Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: hdmi-connector
|
||||
|
||||
type:
|
||||
description: The HDMI connector type
|
||||
enum:
|
||||
- a # Standard full size
|
||||
- b # Never deployed?
|
||||
- c # Mini
|
||||
- d # Micro
|
||||
- e # automotive
|
||||
|
||||
label: true
|
||||
|
||||
hpd-gpios:
|
||||
description: A GPIO line connected to HPD
|
||||
maxItems: 1
|
||||
|
||||
ddc-i2c-bus:
|
||||
description: phandle link to the I2C controller used for DDC EDID probing
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
||||
ddc-en-gpios:
|
||||
description: GPIO signal to enable DDC bus
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
description: Connection to controller providing HDMI signals
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- port
|
||||
- type
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
connector {
|
||||
compatible = "hdmi-connector";
|
||||
label = "hdmi";
|
||||
|
||||
type = "a";
|
||||
|
||||
port {
|
||||
hdmi_connector_in: endpoint {
|
||||
remote-endpoint = <&tpd12s015_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -1,36 +0,0 @@
|
||||
VGA Connector
|
||||
=============
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: "vga-connector"
|
||||
|
||||
Optional properties:
|
||||
|
||||
- label: a symbolic name for the connector corresponding to a hardware label
|
||||
- ddc-i2c-bus: phandle to the I2C bus that is connected to VGA DDC
|
||||
|
||||
Required nodes:
|
||||
|
||||
The VGA connector internal connections are modeled using the OF graph bindings
|
||||
specified in Documentation/devicetree/bindings/graph.txt.
|
||||
|
||||
The VGA connector has a single port that must be connected to a video source
|
||||
port.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
vga0: connector@0 {
|
||||
compatible = "vga-connector";
|
||||
label = "vga";
|
||||
|
||||
ddc-i2c-bus = <&i2c3>;
|
||||
|
||||
port {
|
||||
vga_connector_in: endpoint {
|
||||
remote-endpoint = <&adv7123_out>;
|
||||
};
|
||||
};
|
||||
};
|
@ -0,0 +1,46 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/connector/vga-connector.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: VGA Connector
|
||||
|
||||
maintainers:
|
||||
- Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: vga-connector
|
||||
|
||||
label: true
|
||||
|
||||
ddc-i2c-bus:
|
||||
description: phandle link to the I2C controller used for DDC EDID probing
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
||||
port:
|
||||
description: Connection to controller providing VGA signals
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
connector {
|
||||
compatible = "vga-connector";
|
||||
label = "vga";
|
||||
|
||||
ddc-i2c-bus = <&i2c3>;
|
||||
|
||||
port {
|
||||
vga_connector_in: endpoint {
|
||||
remote-endpoint = <&adv7123_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
65
Documentation/devicetree/bindings/display/ingenic,ipu.yaml
Normal file
65
Documentation/devicetree/bindings/display/ingenic,ipu.yaml
Normal file
@ -0,0 +1,65 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/ingenic,ipu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Ingenic SoCs Image Processing Unit (IPU) devicetree bindings
|
||||
|
||||
maintainers:
|
||||
- Paul Cercueil <paul@crapouillou.net>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- enum:
|
||||
- ingenic,jz4725b-ipu
|
||||
- ingenic,jz4760-ipu
|
||||
- items:
|
||||
- const: ingenic,jz4770-ipu
|
||||
- const: ingenic,jz4760-ipu
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
const: ipu
|
||||
|
||||
patternProperties:
|
||||
"^ports?$":
|
||||
description: OF graph bindings (specified in bindings/graph.txt).
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/jz4770-cgu.h>
|
||||
ipu@13080000 {
|
||||
compatible = "ingenic,jz4770-ipu", "ingenic,jz4760-ipu";
|
||||
reg = <0x13080000 0x800>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <29>;
|
||||
|
||||
clocks = <&cgu JZ4770_CLK_IPU>;
|
||||
clock-names = "ipu";
|
||||
|
||||
port {
|
||||
ipu_ep: endpoint {
|
||||
remote-endpoint = <&lcdc_ep>;
|
||||
};
|
||||
};
|
||||
};
|
@ -1,45 +0,0 @@
|
||||
Ingenic JZ47xx LCD driver
|
||||
|
||||
Required properties:
|
||||
- compatible: one of:
|
||||
* ingenic,jz4740-lcd
|
||||
* ingenic,jz4725b-lcd
|
||||
* ingenic,jz4770-lcd
|
||||
- reg: LCD registers location and length
|
||||
- clocks: LCD pixclock and device clock specifiers.
|
||||
The device clock is only required on the JZ4740.
|
||||
- clock-names: "lcd_pclk" and "lcd"
|
||||
- interrupts: Specifies the interrupt line the LCD controller is connected to.
|
||||
|
||||
Example:
|
||||
|
||||
panel {
|
||||
compatible = "sharp,ls020b1dd01d";
|
||||
|
||||
backlight = <&backlight>;
|
||||
power-supply = <&vcc>;
|
||||
|
||||
port {
|
||||
panel_input: endpoint {
|
||||
remote-endpoint = <&panel_output>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
lcd: lcd-controller@13050000 {
|
||||
compatible = "ingenic,jz4725b-lcd";
|
||||
reg = <0x13050000 0x1000>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <31>;
|
||||
|
||||
clocks = <&cgu JZ4725B_CLK_LCD>;
|
||||
clock-names = "lcd";
|
||||
|
||||
port {
|
||||
panel_output: endpoint {
|
||||
remote-endpoint = <&panel_input>;
|
||||
};
|
||||
};
|
||||
};
|
126
Documentation/devicetree/bindings/display/ingenic,lcd.yaml
Normal file
126
Documentation/devicetree/bindings/display/ingenic,lcd.yaml
Normal file
@ -0,0 +1,126 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/ingenic,lcd.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Ingenic SoCs LCD controller devicetree bindings
|
||||
|
||||
maintainers:
|
||||
- Paul Cercueil <paul@crapouillou.net>
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^lcd-controller@[0-9a-f]+$"
|
||||
|
||||
compatible:
|
||||
enum:
|
||||
- ingenic,jz4740-lcd
|
||||
- ingenic,jz4725b-lcd
|
||||
- ingenic,jz4770-lcd
|
||||
- ingenic,jz4780-lcd
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Pixel clock
|
||||
- description: Module clock
|
||||
minItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: lcd_pclk
|
||||
- const: lcd
|
||||
minItems: 1
|
||||
|
||||
port:
|
||||
description: OF graph bindings (specified in bindings/graph.txt).
|
||||
|
||||
ports:
|
||||
description: OF graph bindings (specified in bindings/graph.txt).
|
||||
type: object
|
||||
properties:
|
||||
port@0:
|
||||
type: object
|
||||
description: DPI output, to interface with TFT panels.
|
||||
|
||||
port@8:
|
||||
type: object
|
||||
description: Link to the Image Processing Unit (IPU).
|
||||
(See ingenic,ipu.yaml).
|
||||
|
||||
required:
|
||||
- port@0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- ingenic,jz4740-lcd
|
||||
- ingenic,jz4780-lcd
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 2
|
||||
clock-names:
|
||||
minItems: 2
|
||||
else:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
clock-names:
|
||||
maxItems: 1
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/jz4740-cgu.h>
|
||||
lcd-controller@13050000 {
|
||||
compatible = "ingenic,jz4740-lcd";
|
||||
reg = <0x13050000 0x1000>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <30>;
|
||||
|
||||
clocks = <&cgu JZ4740_CLK_LCD_PCLK>, <&cgu JZ4740_CLK_LCD>;
|
||||
clock-names = "lcd_pclk", "lcd";
|
||||
|
||||
port {
|
||||
endpoint {
|
||||
remote-endpoint = <&panel_input>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
#include <dt-bindings/clock/jz4725b-cgu.h>
|
||||
lcd-controller@13050000 {
|
||||
compatible = "ingenic,jz4725b-lcd";
|
||||
reg = <0x13050000 0x1000>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <31>;
|
||||
|
||||
clocks = <&cgu JZ4725B_CLK_LCD>;
|
||||
clock-names = "lcd_pclk";
|
||||
|
||||
port {
|
||||
endpoint {
|
||||
remote-endpoint = <&panel_input>;
|
||||
};
|
||||
};
|
||||
};
|
@ -87,6 +87,7 @@ Required properties:
|
||||
* "qcom,dsi-phy-20nm"
|
||||
* "qcom,dsi-phy-28nm-8960"
|
||||
* "qcom,dsi-phy-14nm"
|
||||
* "qcom,dsi-phy-14nm-660"
|
||||
* "qcom,dsi-phy-10nm"
|
||||
* "qcom,dsi-phy-10nm-8998"
|
||||
- reg: Physical base address and length of the registers of PLL, PHY. Some
|
||||
|
@ -112,6 +112,34 @@ Example a6xx (with GMU):
|
||||
interconnects = <&rsc_hlos MASTER_GFX3D &rsc_hlos SLAVE_EBI1>;
|
||||
interconnect-names = "gfx-mem";
|
||||
|
||||
gpu_opp_table: opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
|
||||
opp-430000000 {
|
||||
opp-hz = /bits/ 64 <430000000>;
|
||||
opp-level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
|
||||
opp-peak-kBps = <5412000>;
|
||||
};
|
||||
|
||||
opp-355000000 {
|
||||
opp-hz = /bits/ 64 <355000000>;
|
||||
opp-level = <RPMH_REGULATOR_LEVEL_SVS>;
|
||||
opp-peak-kBps = <3072000>;
|
||||
};
|
||||
|
||||
opp-267000000 {
|
||||
opp-hz = /bits/ 64 <267000000>;
|
||||
opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
|
||||
opp-peak-kBps = <3072000>;
|
||||
};
|
||||
|
||||
opp-180000000 {
|
||||
opp-hz = /bits/ 64 <180000000>;
|
||||
opp-level = <RPMH_REGULATOR_LEVEL_MIN_SVS>;
|
||||
opp-peak-kBps = <1804000>;
|
||||
};
|
||||
};
|
||||
|
||||
qcom,gmu = <&gmu>;
|
||||
|
||||
zap-shader {
|
||||
|
@ -1,22 +0,0 @@
|
||||
Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "innolux,p079zca"
|
||||
- reg: DSI virtual channel of the peripheral
|
||||
- power-supply: phandle of the regulator that provides the supply voltage
|
||||
- enable-gpios: panel enable gpio
|
||||
|
||||
Optional properties:
|
||||
- backlight: phandle of the backlight device attached to the panel
|
||||
|
||||
Example:
|
||||
|
||||
&mipi_dsi {
|
||||
panel@0 {
|
||||
compatible = "innolux,p079zca";
|
||||
reg = <0>;
|
||||
power-supply = <...>;
|
||||
backlight = <&backlight>;
|
||||
enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
@ -1,29 +0,0 @@
|
||||
Generic MIPI DSI Command Mode Panel
|
||||
===================================
|
||||
|
||||
Required properties:
|
||||
- compatible: "panel-dsi-cm"
|
||||
|
||||
Optional properties:
|
||||
- label: a symbolic name for the panel
|
||||
- reset-gpios: panel reset gpio
|
||||
- te-gpios: panel TE gpio
|
||||
|
||||
Required nodes:
|
||||
- Video port for DSI input
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
lcd0: display {
|
||||
compatible = "tpo,taal", "panel-dsi-cm";
|
||||
label = "lcd0";
|
||||
|
||||
reset-gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
port {
|
||||
lcd0_in: endpoint {
|
||||
remote-endpoint = <&dsi1_out_ep>;
|
||||
};
|
||||
};
|
||||
};
|
@ -0,0 +1,86 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/panel-dsi-cm.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: DSI command mode panels
|
||||
|
||||
maintainers:
|
||||
- Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
- Sebastian Reichel <sre@kernel.org>
|
||||
|
||||
description: |
|
||||
This binding file is a collection of the DSI panels that
|
||||
are usually driven in command mode. If no backlight is
|
||||
referenced via the optional backlight property, the DSI
|
||||
panel is assumed to have native backlight support.
|
||||
The panel may use an OF graph binding for the association
|
||||
to the display, or it may be a direct child node of the
|
||||
display.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- motorola,droid4-panel # Panel from Motorola Droid4 phone
|
||||
- nokia,himalaya # Panel from Nokia N950 phone
|
||||
- tpo,taal # Panel from OMAP4 SDP board
|
||||
- const: panel-dsi-cm # Generic DSI command mode panel compatible fallback
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
description: DSI virtual channel
|
||||
|
||||
vddi-supply:
|
||||
description:
|
||||
Display panels require power to be supplied. While several panels need
|
||||
more than one power supply with panel-specific constraints governing the
|
||||
order and timings of the power supplies, in many cases a single power
|
||||
supply is sufficient, either because the panel has a single power rail, or
|
||||
because all its power rails can be driven by the same supply. In that case
|
||||
the vddi-supply property specifies the supply powering the panel as a
|
||||
phandle to a regulator.
|
||||
|
||||
vpnl-supply:
|
||||
description:
|
||||
When the display panel needs a second power supply, this property can be
|
||||
used in addition to vddi-supply. Both supplies will be enabled at the
|
||||
same time before the panel is being accessed.
|
||||
|
||||
width-mm: true
|
||||
height-mm: true
|
||||
label: true
|
||||
rotation: true
|
||||
panel-timing: true
|
||||
port: true
|
||||
reset-gpios: true
|
||||
te-gpios: true
|
||||
backlight: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi-controller {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "tpo,taal", "panel-dsi-cm";
|
||||
reg = <0>;
|
||||
reset-gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -33,6 +33,8 @@ properties:
|
||||
- auo,b080uan01
|
||||
# Boe Corporation 8.0" WUXGA TFT LCD panel
|
||||
- boe,tv080wum-nl0
|
||||
# Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
|
||||
- innolux,p079zca
|
||||
# Kingdisplay KD097D04 9.7" 1536x2048 TFT LCD panel
|
||||
- kingdisplay,kd097d04
|
||||
# LG ACX467AKM-7 4.95" 1080×1920 LCD Panel
|
||||
|
@ -81,6 +81,10 @@ properties:
|
||||
- boe,nv140fhmn49
|
||||
# CDTech(H.K.) Electronics Limited 4.3" 480x272 color TFT-LCD panel
|
||||
- cdtech,s043wq26h-ct7
|
||||
# CDTech(H.K.) Electronics Limited 7" WSVGA (1024x600) TFT LCD Panel
|
||||
- cdtech,s070pws19hp-fc21
|
||||
# CDTech(H.K.) Electronics Limited 7" WVGA (800x480) TFT LCD Panel
|
||||
- cdtech,s070swv29hg-dc44
|
||||
# CDTech(H.K.) Electronics Limited 7" 800x480 color TFT-LCD panel
|
||||
- cdtech,s070wv95-ct16
|
||||
# Chunghwa Picture Tubes Ltd. 7" WXGA TFT LCD panel
|
||||
@ -157,6 +161,8 @@ properties:
|
||||
- innolux,zj070na-01p
|
||||
# Kaohsiung Opto-Electronics Inc. 5.7" QVGA (320 x 240) TFT LCD panel
|
||||
- koe,tx14d24vm1bpa
|
||||
# Kaohsiung Opto-Electronics Inc. 10.1" WUXGA (1920 x 1200) LVDS TFT LCD panel
|
||||
- koe,tx26d202vm0bwa
|
||||
# Kaohsiung Opto-Electronics. TX31D200VM0BAA 12.3" HSXGA LVDS panel
|
||||
- koe,tx31d200vm0baa
|
||||
# Kyocera Corporation 12.1" XGA (1024x768) TFT LCD panel
|
||||
@ -245,6 +251,8 @@ properties:
|
||||
- starry,kr122ea0sra
|
||||
# Tianma Micro-electronics TM070JDHG30 7.0" WXGA TFT LCD panel
|
||||
- tianma,tm070jdhg30
|
||||
# Tianma Micro-electronics TM070JVHG33 7.0" WXGA TFT LCD panel
|
||||
- tianma,tm070jvhg33
|
||||
# Tianma Micro-electronics TM070RVHG71 7.0" WXGA TFT LCD panel
|
||||
- tianma,tm070rvhg71
|
||||
# Toshiba 8.9" WXGA (1280x768) TFT LCD panel
|
||||
|
@ -1,23 +0,0 @@
|
||||
Rocktech jh057n00900 5.5" 720x1440 TFT LCD panel
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "rocktech,jh057n00900"
|
||||
- reg: DSI virtual channel of the peripheral
|
||||
- reset-gpios: panel reset gpio
|
||||
- backlight: phandle of the backlight device attached to the panel
|
||||
- vcc-supply: phandle of the regulator that provides the vcc supply voltage.
|
||||
- iovcc-supply: phandle of the regulator that provides the iovcc supply
|
||||
voltage.
|
||||
|
||||
Example:
|
||||
|
||||
&mipi_dsi {
|
||||
panel@0 {
|
||||
compatible = "rocktech,jh057n00900";
|
||||
reg = <0>;
|
||||
backlight = <&backlight>;
|
||||
reset-gpios = <&gpio3 13 GPIO_ACTIVE_LOW>;
|
||||
vcc-supply = <®_2v8_p>;
|
||||
iovcc-supply = <®_1v8_p>;
|
||||
};
|
||||
};
|
@ -0,0 +1,71 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/rocktech,jh057n00900.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Rocktech JH057N00900 5.5" 720x1440 TFT LCD panel
|
||||
|
||||
maintainers:
|
||||
- Ondrej Jirman <megi@xff.cz>
|
||||
|
||||
description: |
|
||||
Rocktech JH057N00900 is a 720x1440 TFT LCD panel
|
||||
connected using a MIPI-DSI video interface.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
# Rocktech JH057N00900 5.5" 720x1440 TFT LCD panel
|
||||
- rocktech,jh057n00900
|
||||
# Xingbangda XBD599 5.99" 720x1440 TFT LCD panel
|
||||
- xingbangda,xbd599
|
||||
|
||||
port: true
|
||||
reg:
|
||||
maxItems: 1
|
||||
description: DSI virtual channel
|
||||
|
||||
vcc-supply:
|
||||
description: Panel power supply
|
||||
|
||||
iovcc-supply:
|
||||
description: I/O voltage supply
|
||||
|
||||
reset-gpios:
|
||||
description: GPIO used for the reset pin
|
||||
maxItems: 1
|
||||
|
||||
backlight:
|
||||
description: Backlight used by the panel
|
||||
$ref: "/schemas/types.yaml#/definitions/phandle"
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vcc-supply
|
||||
- iovcc-supply
|
||||
- reset-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
panel@0 {
|
||||
compatible = "rocktech,jh057n00900";
|
||||
reg = <0>;
|
||||
vcc-supply = <®_2v8_p>;
|
||||
iovcc-supply = <®_1v8_p>;
|
||||
reset-gpios = <&gpio3 13 GPIO_ACTIVE_LOW>;
|
||||
backlight = <&backlight>;
|
||||
};
|
||||
};
|
||||
...
|
@ -1,56 +0,0 @@
|
||||
Samsung S6E8AA0 AMOLED LCD 5.3 inch panel
|
||||
|
||||
Required properties:
|
||||
- compatible: "samsung,s6e8aa0"
|
||||
- reg: the virtual channel number of a DSI peripheral
|
||||
- vdd3-supply: core voltage supply
|
||||
- vci-supply: voltage supply for analog circuits
|
||||
- reset-gpios: a GPIO spec for the reset pin
|
||||
- display-timings: timings for the connected panel as described by [1]
|
||||
|
||||
Optional properties:
|
||||
- power-on-delay: delay after turning regulators on [ms]
|
||||
- reset-delay: delay after reset sequence [ms]
|
||||
- init-delay: delay after initialization sequence [ms]
|
||||
- panel-width-mm: physical panel width [mm]
|
||||
- panel-height-mm: physical panel height [mm]
|
||||
- flip-horizontal: boolean to flip image horizontally
|
||||
- flip-vertical: boolean to flip image vertically
|
||||
|
||||
The device node can contain one 'port' child node with one child
|
||||
'endpoint' node, according to the bindings defined in [2]. This
|
||||
node should describe panel's video bus.
|
||||
|
||||
[1]: Documentation/devicetree/bindings/display/panel/display-timing.txt
|
||||
[2]: Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
|
||||
Example:
|
||||
|
||||
panel {
|
||||
compatible = "samsung,s6e8aa0";
|
||||
reg = <0>;
|
||||
vdd3-supply = <&vcclcd_reg>;
|
||||
vci-supply = <&vlcd_reg>;
|
||||
reset-gpios = <&gpy4 5 0>;
|
||||
power-on-delay= <50>;
|
||||
reset-delay = <100>;
|
||||
init-delay = <100>;
|
||||
panel-width-mm = <58>;
|
||||
panel-height-mm = <103>;
|
||||
flip-horizontal;
|
||||
flip-vertical;
|
||||
|
||||
display-timings {
|
||||
timing0: timing-0 {
|
||||
clock-frequency = <57153600>;
|
||||
hactive = <720>;
|
||||
vactive = <1280>;
|
||||
hfront-porch = <5>;
|
||||
hback-porch = <5>;
|
||||
hsync-len = <5>;
|
||||
vfront-porch = <13>;
|
||||
vback-porch = <1>;
|
||||
vsync-len = <2>;
|
||||
};
|
||||
};
|
||||
};
|
@ -0,0 +1,100 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/samsung,s6e8aa0.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Samsung S6E8AA0 AMOLED LCD 5.3 inch panel
|
||||
|
||||
maintainers:
|
||||
- Andrzej Hajda <a.hajda@samsung.com>
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: samsung,s6e8aa0
|
||||
|
||||
reg: true
|
||||
reset-gpios: true
|
||||
display-timings: true
|
||||
|
||||
vdd3-supply:
|
||||
description: core voltage supply
|
||||
|
||||
vci-supply:
|
||||
description: voltage supply for analog circuits
|
||||
|
||||
power-on-delay:
|
||||
description: delay after turning regulators on [ms]
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
reset-delay:
|
||||
description: delay after reset sequence [ms]
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
init-delay:
|
||||
description: delay after initialization sequence [ms]
|
||||
|
||||
panel-width-mm:
|
||||
description: physical panel width [mm]
|
||||
|
||||
panel-height-mm:
|
||||
description: physical panel height [mm]
|
||||
|
||||
flip-horizontal:
|
||||
description: boolean to flip image horizontally
|
||||
type: boolean
|
||||
|
||||
flip-vertical:
|
||||
description: boolean to flip image vertically
|
||||
type: boolean
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd3-supply
|
||||
- vci-supply
|
||||
- reset-gpios
|
||||
- display-timings
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "samsung,s6e8aa0";
|
||||
reg = <0>;
|
||||
vdd3-supply = <&vcclcd_reg>;
|
||||
vci-supply = <&vlcd_reg>;
|
||||
reset-gpios = <&gpy4 5 0>;
|
||||
power-on-delay= <50>;
|
||||
reset-delay = <100>;
|
||||
init-delay = <100>;
|
||||
panel-width-mm = <58>;
|
||||
panel-height-mm = <103>;
|
||||
flip-horizontal;
|
||||
flip-vertical;
|
||||
|
||||
display-timings {
|
||||
timing0: timing-0 {
|
||||
clock-frequency = <57153600>;
|
||||
hactive = <720>;
|
||||
vactive = <1280>;
|
||||
hfront-porch = <5>;
|
||||
hback-porch = <5>;
|
||||
hsync-len = <5>;
|
||||
vfront-porch = <13>;
|
||||
vback-porch = <1>;
|
||||
vsync-len = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -1,49 +0,0 @@
|
||||
Sharp Microelectronics 10.1" WQXGA TFT LCD panel
|
||||
|
||||
This panel requires a dual-channel DSI host to operate. It supports two modes:
|
||||
- left-right: each channel drives the left or right half of the screen
|
||||
- even-odd: each channel drives the even or odd lines of the screen
|
||||
|
||||
Each of the DSI channels controls a separate DSI peripheral. The peripheral
|
||||
driven by the first link (DSI-LINK1), left or even, is considered the primary
|
||||
peripheral and controls the device. The 'link2' property contains a phandle
|
||||
to the peripheral driven by the second link (DSI-LINK2, right or odd).
|
||||
|
||||
Note that in video mode the DSI-LINK1 interface always provides the left/even
|
||||
pixels and DSI-LINK2 always provides the right/odd pixels. In command mode it
|
||||
is possible to program either link to drive the left/even or right/odd pixels
|
||||
but for the sake of consistency this binding assumes that the same assignment
|
||||
is chosen as for video mode.
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "sharp,lq101r1sx01"
|
||||
- reg: DSI virtual channel of the peripheral
|
||||
|
||||
Required properties (for DSI-LINK1 only):
|
||||
- link2: phandle to the DSI peripheral on the secondary link. Note that the
|
||||
presence of this property marks the containing node as DSI-LINK1.
|
||||
- power-supply: phandle of the regulator that provides the supply voltage
|
||||
|
||||
Optional properties (for DSI-LINK1 only):
|
||||
- backlight: phandle of the backlight device attached to the panel
|
||||
|
||||
Example:
|
||||
|
||||
dsi@54300000 {
|
||||
panel: panel@0 {
|
||||
compatible = "sharp,lq101r1sx01";
|
||||
reg = <0>;
|
||||
|
||||
link2 = <&secondary>;
|
||||
|
||||
power-supply = <...>;
|
||||
backlight = <...>;
|
||||
};
|
||||
};
|
||||
|
||||
dsi@54400000 {
|
||||
secondary: panel@0 {
|
||||
compatible = "sharp,lq101r1sx01";
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
@ -0,0 +1,87 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/sharp,lq101r1sx01.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sharp Microelectronics 10.1" WQXGA TFT LCD panel
|
||||
|
||||
maintainers:
|
||||
- Thierry Reding <treding@nvidia.com>
|
||||
|
||||
description: |
|
||||
This panel requires a dual-channel DSI host to operate. It supports two modes:
|
||||
- left-right: each channel drives the left or right half of the screen
|
||||
- even-odd: each channel drives the even or odd lines of the screen
|
||||
|
||||
Each of the DSI channels controls a separate DSI peripheral. The peripheral
|
||||
driven by the first link (DSI-LINK1), left or even, is considered the primary
|
||||
peripheral and controls the device. The 'link2' property contains a phandle
|
||||
to the peripheral driven by the second link (DSI-LINK2, right or odd).
|
||||
|
||||
Note that in video mode the DSI-LINK1 interface always provides the left/even
|
||||
pixels and DSI-LINK2 always provides the right/odd pixels. In command mode it
|
||||
is possible to program either link to drive the left/even or right/odd pixels
|
||||
but for the sake of consistency this binding assumes that the same assignment
|
||||
is chosen as for video mode.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sharp,lq101r1sx01
|
||||
|
||||
reg: true
|
||||
power-supply: true
|
||||
backlight: true
|
||||
|
||||
link2:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: |
|
||||
phandle to the DSI peripheral on the secondary link. Note that the
|
||||
presence of this property marks the containing node as DSI-LINK1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
if:
|
||||
required:
|
||||
- link2
|
||||
then:
|
||||
required:
|
||||
- power-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
dsi0: dsi@fd922800 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0xfd922800 0x200>;
|
||||
|
||||
panel: panel@0 {
|
||||
compatible = "sharp,lq101r1sx01";
|
||||
reg = <0>;
|
||||
|
||||
link2 = <&secondary>;
|
||||
|
||||
power-supply = <&power>;
|
||||
backlight = <&backlight>;
|
||||
};
|
||||
};
|
||||
|
||||
dsi1: dsi@fd922a00 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0xfd922a00 0x200>;
|
||||
|
||||
secondary: panel@0 {
|
||||
compatible = "sharp,lq101r1sx01";
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -152,28 +152,28 @@ additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
aliases {
|
||||
display0 = &lcdc0;
|
||||
};
|
||||
/ {
|
||||
compatible = "foo";
|
||||
model = "foo";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
chosen {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
stdout-path = "display0";
|
||||
framebuffer0: framebuffer@1d385000 {
|
||||
compatible = "allwinner,simple-framebuffer", "simple-framebuffer";
|
||||
allwinner,pipeline = "de_be0-lcd0";
|
||||
reg = <0x1d385000 3840000>;
|
||||
width = <1600>;
|
||||
height = <1200>;
|
||||
stride = <3200>;
|
||||
format = "r5g6b5";
|
||||
clocks = <&ahb_gates 36>, <&ahb_gates 43>, <&ahb_gates 44>;
|
||||
lcd-supply = <®_dc1sw>;
|
||||
display = <&lcdc0>;
|
||||
};
|
||||
chosen {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
framebuffer0: framebuffer@1d385000 {
|
||||
compatible = "allwinner,simple-framebuffer", "simple-framebuffer";
|
||||
allwinner,pipeline = "de_be0-lcd0";
|
||||
reg = <0x1d385000 3840000>;
|
||||
width = <1600>;
|
||||
height = <1200>;
|
||||
stride = <3200>;
|
||||
format = "r5g6b5";
|
||||
clocks = <&ahb_gates 36>, <&ahb_gates 43>, <&ahb_gates 44>;
|
||||
lcd-supply = <®_dc1sw>;
|
||||
display = <&lcdc0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
lcdc0: lcdc { };
|
||||
|
||||
...
|
||||
|
@ -0,0 +1,174 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/xlnx/xlnx,zynqmp-dpsub.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Xilinx ZynqMP DisplayPort Subsystem
|
||||
|
||||
description: |
|
||||
The DisplayPort subsystem of Xilinx ZynqMP (Zynq UltraScale+ MPSoC)
|
||||
implements the display and audio pipelines based on the DisplayPort v1.2
|
||||
standard. The subsystem includes multiple functional blocks as below:
|
||||
|
||||
+------------------------------------------------------------+
|
||||
+--------+ | +----------------+ +-----------+ |
|
||||
| DPDMA | --->| | --> | Video | Video +-------------+ |
|
||||
| 4x vid | | | | | Rendering | -+--> | | | +------+
|
||||
| 2x aud | | | Audio/Video | --> | Pipeline | | | DisplayPort |---> | PHY0 |
|
||||
+--------+ | | Buffer Manager | +-----------+ | | Source | | +------+
|
||||
| | and STC | +-----------+ | | Controller | | +------+
|
||||
Live Video --->| | --> | Audio | Audio | |---> | PHY1 |
|
||||
| | | | Mixer | --+-> | | | +------+
|
||||
Live Audio --->| | --> | | || +-------------+ |
|
||||
| +----------------+ +-----------+ || |
|
||||
+---------------------------------------||-------------------+
|
||||
vv
|
||||
Blended Video and
|
||||
Mixed Audio to PL
|
||||
|
||||
The Buffer Manager interacts with external interface such as DMA engines or
|
||||
live audio/video streams from the programmable logic. The Video Rendering
|
||||
Pipeline blends the video and graphics layers and performs colorspace
|
||||
conversion. The Audio Mixer mixes the incoming audio streams. The DisplayPort
|
||||
Source Controller handles the DisplayPort protocol and connects to external
|
||||
PHYs.
|
||||
|
||||
The subsystem supports 2 video and 2 audio streams, and various pixel formats
|
||||
and depths up to 4K@30 resolution.
|
||||
|
||||
Please refer to "Zynq UltraScale+ Device Technical Reference Manual"
|
||||
(https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf)
|
||||
for more details.
|
||||
|
||||
maintainers:
|
||||
- Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: xlnx,zynqmp-dpsub-1.7
|
||||
|
||||
reg:
|
||||
maxItems: 4
|
||||
reg-names:
|
||||
items:
|
||||
- const: dp
|
||||
- const: blend
|
||||
- const: av_buf
|
||||
- const: aud
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
description:
|
||||
The APB clock and at least one video clock are mandatory, the audio clock
|
||||
is optional.
|
||||
minItems: 2
|
||||
maxItems: 4
|
||||
items:
|
||||
- description: dp_apb_clk is the APB clock
|
||||
- description: dp_aud_clk is the Audio clock
|
||||
- description:
|
||||
dp_vtc_pixel_clk_in is the non-live video clock (from Processing
|
||||
System)
|
||||
- description:
|
||||
dp_live_video_in_clk is the live video clock (from Programmable
|
||||
Logic)
|
||||
clock-names:
|
||||
oneOf:
|
||||
- minItems: 2
|
||||
maxItems: 3
|
||||
items:
|
||||
- const: dp_apb_clk
|
||||
- enum: [ dp_vtc_pixel_clk_in, dp_live_video_in_clk ]
|
||||
- enum: [ dp_vtc_pixel_clk_in, dp_live_video_in_clk ]
|
||||
- minItems: 3
|
||||
maxItems: 4
|
||||
items:
|
||||
- const: dp_apb_clk
|
||||
- const: dp_aud_clk
|
||||
- enum: [ dp_vtc_pixel_clk_in, dp_live_video_in_clk ]
|
||||
- enum: [ dp_vtc_pixel_clk_in, dp_live_video_in_clk ]
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
dmas:
|
||||
maxItems: 4
|
||||
items:
|
||||
- description: Video layer, plane 0 (RGB or luma)
|
||||
- description: Video layer, plane 1 (U/V or U)
|
||||
- description: Video layer, plane 2 (V)
|
||||
- description: Graphics layer
|
||||
dma-names:
|
||||
items:
|
||||
- const: vid0
|
||||
- const: vid1
|
||||
- const: vid2
|
||||
- const: gfx0
|
||||
|
||||
phys:
|
||||
description: PHYs for the DP data lanes
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
phy-names:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
items:
|
||||
- const: dp-phy0
|
||||
- const: dp-phy1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- power-domains
|
||||
- resets
|
||||
- dmas
|
||||
- dma-names
|
||||
- phys
|
||||
- phy-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/phy/phy.h>
|
||||
#include <dt-bindings/reset/xlnx-zynqmp-resets.h>
|
||||
|
||||
display@fd4a0000 {
|
||||
compatible = "xlnx,zynqmp-dpsub-1.7";
|
||||
reg = <0x0 0xfd4a0000 0x0 0x1000>,
|
||||
<0x0 0xfd4aa000 0x0 0x1000>,
|
||||
<0x0 0xfd4ab000 0x0 0x1000>,
|
||||
<0x0 0xfd4ac000 0x0 0x1000>;
|
||||
reg-names = "dp", "blend", "av_buf", "aud";
|
||||
interrupts = <0 119 4>;
|
||||
interrupt-parent = <&gic>;
|
||||
|
||||
clock-names = "dp_apb_clk", "dp_aud_clk", "dp_live_video_in_clk";
|
||||
clocks = <&dp_aclk>, <&clkc 17>, <&si570_1>;
|
||||
|
||||
power-domains = <&pd_dp>;
|
||||
resets = <&reset ZYNQMP_RESET_DP>;
|
||||
|
||||
dma-names = "vid0", "vid1", "vid2", "gfx0";
|
||||
dmas = <&xlnx_dpdma 0>,
|
||||
<&xlnx_dpdma 1>,
|
||||
<&xlnx_dpdma 2>,
|
||||
<&xlnx_dpdma 3>;
|
||||
|
||||
phys = <&psgtr 1 PHY_TYPE_DP 0 3 27000000>,
|
||||
<&psgtr 0 PHY_TYPE_DP 1 3 27000000>;
|
||||
|
||||
phy-names = "dp-phy0", "dp-phy1";
|
||||
};
|
||||
|
||||
...
|
@ -0,0 +1,68 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/dma/xilinx/xlnx,zynqmp-dpdma.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Xilinx ZynqMP DisplayPort DMA Controller Device Tree Bindings
|
||||
|
||||
description: |
|
||||
These bindings describe the DMA engine included in the Xilinx ZynqMP
|
||||
DisplayPort Subsystem. The DMA engine supports up to 6 DMA channels (3
|
||||
channels for a video stream, 1 channel for a graphics stream, and 2 channels
|
||||
for an audio stream).
|
||||
|
||||
maintainers:
|
||||
- Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
|
||||
allOf:
|
||||
- $ref: "../dma-controller.yaml#"
|
||||
|
||||
properties:
|
||||
"#dma-cells":
|
||||
const: 1
|
||||
description: |
|
||||
The cell is the DMA channel ID (see dt-bindings/dma/xlnx-zynqmp-dpdma.h
|
||||
for a list of channel IDs).
|
||||
|
||||
compatible:
|
||||
const: xlnx,zynqmp-dpdma
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
description: The AXI clock
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
const: axi_clk
|
||||
|
||||
required:
|
||||
- "#dma-cells"
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
dma: dma-controller@fd4c0000 {
|
||||
compatible = "xlnx,zynqmp-dpdma";
|
||||
reg = <0x0 0xfd4c0000 0x0 0x1000>;
|
||||
interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-parent = <&gic>;
|
||||
clocks = <&dpdma_clk>;
|
||||
clock-names = "axi_clk";
|
||||
#dma-cells = <1>;
|
||||
};
|
||||
|
||||
...
|
@ -1167,6 +1167,8 @@ patternProperties:
|
||||
description: Xiaomi Technology Co., Ltd.
|
||||
"^xillybus,.*":
|
||||
description: Xillybus Ltd.
|
||||
"^xingbangda,.*":
|
||||
description: Shenzhen Xingbangda Display Technology Co., Ltd
|
||||
"^xinpeng,.*":
|
||||
description: Shenzhen Xinpeng Technology Co., Ltd
|
||||
"^xlnx,.*":
|
||||
|
@ -100,11 +100,11 @@ CPU Access to DMA Buffer Objects
|
||||
.. kernel-doc:: drivers/dma-buf/dma-buf.c
|
||||
:doc: cpu access
|
||||
|
||||
Fence Poll Support
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
Implicit Fence Poll Support
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. kernel-doc:: drivers/dma-buf/dma-buf.c
|
||||
:doc: fence polling
|
||||
:doc: implicit fence polling
|
||||
|
||||
Kernel Functions and Structures Reference
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -133,6 +133,18 @@ DMA Fences
|
||||
.. kernel-doc:: drivers/dma-buf/dma-fence.c
|
||||
:doc: DMA fences overview
|
||||
|
||||
DMA Fence Cross-Driver Contract
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. kernel-doc:: drivers/dma-buf/dma-fence.c
|
||||
:doc: fence cross-driver contract
|
||||
|
||||
DMA Fence Signalling Annotations
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. kernel-doc:: drivers/dma-buf/dma-fence.c
|
||||
:doc: fence signalling annotation
|
||||
|
||||
DMA Fences Functions Reference
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -166,3 +178,73 @@ DMA Fence uABI/Sync File
|
||||
.. kernel-doc:: include/linux/sync_file.h
|
||||
:internal:
|
||||
|
||||
Indefinite DMA Fences
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
At various times &dma_fence with an indefinite time until dma_fence_wait()
|
||||
finishes have been proposed. Examples include:
|
||||
|
||||
* Future fences, used in HWC1 to signal when a buffer isn't used by the display
|
||||
any longer, and created with the screen update that makes the buffer visible.
|
||||
The time this fence completes is entirely under userspace's control.
|
||||
|
||||
* Proxy fences, proposed to handle &drm_syncobj for which the fence has not yet
|
||||
been set. Used to asynchronously delay command submission.
|
||||
|
||||
* Userspace fences or gpu futexes, fine-grained locking within a command buffer
|
||||
that userspace uses for synchronization across engines or with the CPU, which
|
||||
are then imported as a DMA fence for integration into existing winsys
|
||||
protocols.
|
||||
|
||||
* Long-running compute command buffers, while still using traditional end of
|
||||
batch DMA fences for memory management instead of context preemption DMA
|
||||
fences which get reattached when the compute job is rescheduled.
|
||||
|
||||
Common to all these schemes is that userspace controls the dependencies of these
|
||||
fences and controls when they fire. Mixing indefinite fences with normal
|
||||
in-kernel DMA fences does not work, even when a fallback timeout is included to
|
||||
protect against malicious userspace:
|
||||
|
||||
* Only the kernel knows about all DMA fence dependencies, userspace is not aware
|
||||
of dependencies injected due to memory management or scheduler decisions.
|
||||
|
||||
* Only userspace knows about all dependencies in indefinite fences and when
|
||||
exactly they will complete, the kernel has no visibility.
|
||||
|
||||
Furthermore the kernel has to be able to hold up userspace command submission
|
||||
for memory management needs, which means we must support indefinite fences being
|
||||
dependent upon DMA fences. If the kernel also support indefinite fences in the
|
||||
kernel like a DMA fence, like any of the above proposal would, there is the
|
||||
potential for deadlocks.
|
||||
|
||||
.. kernel-render:: DOT
|
||||
:alt: Indefinite Fencing Dependency Cycle
|
||||
:caption: Indefinite Fencing Dependency Cycle
|
||||
|
||||
digraph "Fencing Cycle" {
|
||||
node [shape=box bgcolor=grey style=filled]
|
||||
kernel [label="Kernel DMA Fences"]
|
||||
userspace [label="userspace controlled fences"]
|
||||
kernel -> userspace [label="memory management"]
|
||||
userspace -> kernel [label="Future fence, fence proxy, ..."]
|
||||
|
||||
{ rank=same; kernel userspace }
|
||||
}
|
||||
|
||||
This means that the kernel might accidentally create deadlocks
|
||||
through memory management dependencies which userspace is unaware of, which
|
||||
randomly hangs workloads until the timeout kicks in. Workloads, which from
|
||||
userspace's perspective, do not contain a deadlock. In such a mixed fencing
|
||||
architecture there is no single entity with knowledge of all dependencies.
|
||||
Thefore preventing such deadlocks from within the kernel is not possible.
|
||||
|
||||
The only solution to avoid dependencies loops is by not allowing indefinite
|
||||
fences in the kernel. This means:
|
||||
|
||||
* No future fences, proxy fences or userspace fences imported as DMA fences,
|
||||
with or without a timeout.
|
||||
|
||||
* No DMA fences that signal end of batchbuffer for command submission where
|
||||
userspace is allowed to use userspace fencing or long running compute
|
||||
workloads. This also means no implicit fencing for shared buffers in these
|
||||
cases.
|
||||
|
@ -86,7 +86,9 @@ The details of these operations are:
|
||||
- interleaved_dma: This is common to Slave as well as M2M clients. For slave
|
||||
address of devices' fifo could be already known to the driver.
|
||||
Various types of operations could be expressed by setting
|
||||
appropriate values to the 'dma_interleaved_template' members.
|
||||
appropriate values to the 'dma_interleaved_template' members. Cyclic
|
||||
interleaved DMA transfers are also possible if supported by the channel by
|
||||
setting the DMA_PREP_REPEAT transfer flag.
|
||||
|
||||
A non-NULL return of this transfer API represents a "descriptor" for
|
||||
the given transaction.
|
||||
|
@ -239,6 +239,27 @@ Currently, the types available are:
|
||||
want to transfer a portion of uncompressed data directly to the
|
||||
display to print it
|
||||
|
||||
- DMA_REPEAT
|
||||
|
||||
- The device supports repeated transfers. A repeated transfer, indicated by
|
||||
the DMA_PREP_REPEAT transfer flag, is similar to a cyclic transfer in that
|
||||
it gets automatically repeated when it ends, but can additionally be
|
||||
replaced by the client.
|
||||
|
||||
- This feature is limited to interleaved transfers, this flag should thus not
|
||||
be set if the DMA_INTERLEAVE flag isn't set. This limitation is based on
|
||||
the current needs of DMA clients, support for additional transfer types
|
||||
should be added in the future if and when the need arises.
|
||||
|
||||
- DMA_LOAD_EOT
|
||||
|
||||
- The device supports replacing repeated transfers at end of transfer (EOT)
|
||||
by queuing a new transfer with the DMA_PREP_LOAD_EOT flag set.
|
||||
|
||||
- Support for replacing a currently running transfer at another point (such
|
||||
as end of burst instead of end of transfer) will be added in the future
|
||||
based on DMA clients needs, if and when the need arises.
|
||||
|
||||
These various types will also affect how the source and destination
|
||||
addresses change over time.
|
||||
|
||||
@ -531,6 +552,34 @@ DMA_CTRL_REUSE
|
||||
writes for which the descriptor should be in different format from
|
||||
normal data descriptors.
|
||||
|
||||
- DMA_PREP_REPEAT
|
||||
|
||||
- If set, the transfer will be automatically repeated when it ends until a
|
||||
new transfer is queued on the same channel with the DMA_PREP_LOAD_EOT flag.
|
||||
If the next transfer to be queued on the channel does not have the
|
||||
DMA_PREP_LOAD_EOT flag set, the current transfer will be repeated until the
|
||||
client terminates all transfers.
|
||||
|
||||
- This flag is only supported if the channel reports the DMA_REPEAT
|
||||
capability.
|
||||
|
||||
- DMA_PREP_LOAD_EOT
|
||||
|
||||
- If set, the transfer will replace the transfer currently being executed at
|
||||
the end of the transfer.
|
||||
|
||||
- This is the default behaviour for non-repeated transfers, specifying
|
||||
DMA_PREP_LOAD_EOT for non-repeated transfers will thus make no difference.
|
||||
|
||||
- When using repeated transfers, DMA clients will usually need to set the
|
||||
DMA_PREP_LOAD_EOT flag on all transfers, otherwise the channel will keep
|
||||
repeating the last repeated transfer and ignore the new transfers being
|
||||
queued. Failure to set DMA_PREP_LOAD_EOT will appear as if the channel was
|
||||
stuck on the previous transfer.
|
||||
|
||||
- This flag is only supported if the channel reports the DMA_LOAD_EOT
|
||||
capability.
|
||||
|
||||
General Design Notes
|
||||
====================
|
||||
|
||||
|
@ -127,7 +127,7 @@ At least on the EP9315 there is a silicon bug which causes bit 27 of
|
||||
the VIDSCRNPAGE (framebuffer physical offset) to be tied low. There is
|
||||
an unofficial errata for this bug at::
|
||||
|
||||
http://marc.info/?l=linux-arm-kernel&m=110061245502000&w=2
|
||||
https://marc.info/?l=linux-arm-kernel&m=110061245502000&w=2
|
||||
|
||||
By default the EP93xx framebuffer driver checks if the allocated physical
|
||||
address has bit 27 set. If it does, then the memory is freed and an
|
||||
|
@ -411,15 +411,3 @@ Legacy CRTC/Modeset Helper Functions Reference
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
|
||||
:export:
|
||||
|
||||
SHMEM GEM Helper Reference
|
||||
==========================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_shmem_helper.c
|
||||
:doc: overview
|
||||
|
||||
.. kernel-doc:: include/drm/drm_gem_shmem_helper.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_shmem_helper.c
|
||||
:export:
|
||||
|
@ -460,6 +460,12 @@ HDMI Specific Connector Properties
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_connector.c
|
||||
:doc: HDMI connector properties
|
||||
|
||||
Standard CRTC Properties
|
||||
------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
|
||||
:doc: standard CRTC properties
|
||||
|
||||
Plane Composition Properties
|
||||
----------------------------
|
||||
|
||||
@ -537,3 +543,18 @@ Vertical Blanking and Interrupt Handling Functions Reference
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_vblank.c
|
||||
:export:
|
||||
|
||||
Vertical Blank Work
|
||||
===================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_vblank_work.c
|
||||
:doc: vblank works
|
||||
|
||||
Vertical Blank Work Functions Reference
|
||||
---------------------------------------
|
||||
|
||||
.. kernel-doc:: include/drm/drm_vblank_work.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_vblank_work.c
|
||||
:export:
|
||||
|
@ -179,10 +179,7 @@ GEM Objects Lifetime
|
||||
|
||||
All GEM objects are reference-counted by the GEM core. References can be
|
||||
acquired and release by calling drm_gem_object_get() and drm_gem_object_put()
|
||||
respectively. The caller must hold the :c:type:`struct drm_device <drm_device>`
|
||||
struct_mutex lock when calling drm_gem_object_get(). As a convenience, GEM
|
||||
provides drm_gem_object_put_unlocked() functions that can be called without
|
||||
holding the lock.
|
||||
respectively.
|
||||
|
||||
When the last reference to a GEM object is released the GEM core calls
|
||||
the :c:type:`struct drm_driver <drm_driver>` gem_free_object_unlocked
|
||||
@ -373,6 +370,18 @@ GEM CMA Helper Functions Reference
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c
|
||||
:export:
|
||||
|
||||
GEM SHMEM Helper Function Reference
|
||||
-----------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_shmem_helper.c
|
||||
:doc: overview
|
||||
|
||||
.. kernel-doc:: include/drm/drm_gem_shmem_helper.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_shmem_helper.c
|
||||
:export:
|
||||
|
||||
GEM VRAM Helper Functions Reference
|
||||
-----------------------------------
|
||||
|
||||
|
@ -157,8 +157,8 @@ private lock. The tricky part is the BO free functions, since those can't
|
||||
reliably take that lock any more. Instead state needs to be protected with
|
||||
suitable subordinate locks or some cleanup work pushed to a worker thread. For
|
||||
performance-critical drivers it might also be better to go with a more
|
||||
fine-grained per-buffer object and per-context lockings scheme. Currently only the
|
||||
``msm`` driver still use ``struct_mutex``.
|
||||
fine-grained per-buffer object and per-context lockings scheme. Currently only
|
||||
the ``msm`` and `i915` drivers use ``struct_mutex``.
|
||||
|
||||
Contact: Daniel Vetter, respective driver maintainers
|
||||
|
||||
@ -305,7 +305,7 @@ acquire context. Replace the boilerplate code surrounding
|
||||
drm_modeset_lock_all_ctx() with DRM_MODESET_LOCK_ALL_BEGIN() and
|
||||
DRM_MODESET_LOCK_ALL_END() instead.
|
||||
|
||||
This should also be done for all places where drm_modest_lock_all() is still
|
||||
This should also be done for all places where drm_modeset_lock_all() is still
|
||||
used.
|
||||
|
||||
As a reference, take a look at the conversions already completed in drm core.
|
||||
@ -327,26 +327,6 @@ Contact: Laurent Pinchart, Daniel Vetter
|
||||
Level: Intermediate (mostly because it is a huge tasks without good partial
|
||||
milestones, not technically itself that challenging)
|
||||
|
||||
Convert direct mode.vrefresh accesses to use drm_mode_vrefresh()
|
||||
----------------------------------------------------------------
|
||||
|
||||
drm_display_mode.vrefresh isn't guaranteed to be populated. As such, using it
|
||||
is risky and has been known to cause div-by-zero bugs. Fortunately, drm core
|
||||
has helper which will use mode.vrefresh if it's !0 and will calculate it from
|
||||
the timings when it's 0.
|
||||
|
||||
Use simple search/replace, or (more fun) cocci to replace instances of direct
|
||||
vrefresh access with a call to the helper. Check out
|
||||
https://lists.freedesktop.org/archives/dri-devel/2019-January/205186.html for
|
||||
inspiration.
|
||||
|
||||
Once all instances of vrefresh have been converted, remove vrefresh from
|
||||
drm_display_mode to avoid future use.
|
||||
|
||||
Contact: Sean Paul
|
||||
|
||||
Level: Starter
|
||||
|
||||
connector register/unregister fixes
|
||||
-----------------------------------
|
||||
|
||||
@ -392,6 +372,38 @@ Contact: Laurent Pinchart, respective driver maintainers
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
Consolidate custom driver modeset properties
|
||||
--------------------------------------------
|
||||
|
||||
Before atomic modeset took place, many drivers where creating their own
|
||||
properties. Among other things, atomic brought the requirement that custom,
|
||||
driver specific properties should not be used.
|
||||
|
||||
For this task, we aim to introduce core helpers or reuse the existing ones
|
||||
if available:
|
||||
|
||||
A quick, unconfirmed, examples list.
|
||||
|
||||
Introduce core helpers:
|
||||
- audio (amdgpu, intel, gma500, radeon)
|
||||
- brightness, contrast, etc (armada, nouveau) - overlay only (?)
|
||||
- broadcast rgb (gma500, intel)
|
||||
- colorkey (armada, nouveau, rcar) - overlay only (?)
|
||||
- dither (amdgpu, nouveau, radeon) - varies across drivers
|
||||
- underscan family (amdgpu, radeon, nouveau)
|
||||
|
||||
Already in core:
|
||||
- colorspace (sti)
|
||||
- tv format names, enhancements (gma500, intel)
|
||||
- tv overscan, margins, etc. (gma500, intel)
|
||||
- zorder (omapdrm) - same as zpos (?)
|
||||
|
||||
|
||||
Contact: Emil Velikov, respective driver maintainers
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
|
||||
Core refactorings
|
||||
=================
|
||||
|
||||
|
@ -185,7 +185,7 @@ enhancing the kernel code to adapt as a kernel module and also did the
|
||||
implementation of the user space side [3]. Now (2009) Tiago Vignatti and Dave
|
||||
Airlie finally put this work in shape and queued to Jesse Barnes' PCI tree.
|
||||
|
||||
0) http://cgit.freedesktop.org/xorg/xserver/commit/?id=4b42448a2388d40f257774fbffdccaea87bd0347
|
||||
1) http://lists.freedesktop.org/archives/xorg/2005-March/006663.html
|
||||
2) http://lists.freedesktop.org/archives/xorg/2005-March/006745.html
|
||||
3) http://lists.freedesktop.org/archives/xorg/2007-October/029507.html
|
||||
0) https://cgit.freedesktop.org/xorg/xserver/commit/?id=4b42448a2388d40f257774fbffdccaea87bd0347
|
||||
1) https://lists.freedesktop.org/archives/xorg/2005-March/006663.html
|
||||
2) https://lists.freedesktop.org/archives/xorg/2005-March/006745.html
|
||||
3) https://lists.freedesktop.org/archives/xorg/2007-October/029507.html
|
||||
|
26
MAINTAINERS
26
MAINTAINERS
@ -1460,11 +1460,6 @@ S: Odd Fixes
|
||||
F: drivers/amba/
|
||||
F: include/linux/amba/bus.h
|
||||
|
||||
ARM PRIMECELL CLCD PL110 DRIVER
|
||||
M: Russell King <linux@armlinux.org.uk>
|
||||
S: Odd Fixes
|
||||
F: drivers/video/fbdev/amba-clcd.*
|
||||
|
||||
ARM PRIMECELL KMI PL050 DRIVER
|
||||
M: Russell King <linux@armlinux.org.uk>
|
||||
S: Odd Fixes
|
||||
@ -5143,6 +5138,7 @@ F: fs/dlm/
|
||||
|
||||
DMA BUFFER SHARING FRAMEWORK
|
||||
M: Sumit Semwal <sumit.semwal@linaro.org>
|
||||
M: Christian König <christian.koenig@amd.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
L: linaro-mm-sig@lists.linaro.org (moderated for non-subscribers)
|
||||
@ -5868,7 +5864,7 @@ M: Eric Anholt <eric@anholt.net>
|
||||
S: Supported
|
||||
T: git git://github.com/anholt/linux
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt
|
||||
F: Documentation/devicetree/bindings/display/brcm,bcm2835-*.yaml
|
||||
F: drivers/gpu/drm/vc4/
|
||||
F: include/uapi/drm/vc4_drm.h
|
||||
|
||||
@ -5892,6 +5888,15 @@ T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: Documentation/gpu/xen-front.rst
|
||||
F: drivers/gpu/drm/xen/
|
||||
|
||||
DRM DRIVERS FOR XILINX
|
||||
M: Hyun Kwon <hyun.kwon@xilinx.com>
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: Documentation/devicetree/bindings/display/xlnx/
|
||||
F: drivers/gpu/drm/xlnx/
|
||||
|
||||
DRM DRIVERS FOR ZTE ZX
|
||||
M: Shawn Guo <shawnguo@kernel.org>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
@ -18938,6 +18943,15 @@ F: Documentation/devicetree/bindings/media/xilinx/
|
||||
F: drivers/media/platform/xilinx/
|
||||
F: include/uapi/linux/xilinx-v4l2-controls.h
|
||||
|
||||
XILINX ZYNQMP DPDMA DRIVER
|
||||
M: Hyun Kwon <hyun.kwon@xilinx.com>
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
L: dmaengine@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dpdma.yaml
|
||||
F: drivers/dma/xilinx/xilinx_dpdma.c
|
||||
F: include/dt-bindings/dma/xlnx-zynqmp-dpdma.h
|
||||
|
||||
XILINX ZYNQMP PSGTR PHY DRIVER
|
||||
M: Anurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com>
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
|
@ -550,6 +550,7 @@ static const struct pci_device_id intel_early_ids[] __initconst = {
|
||||
INTEL_ICL_11_IDS(&gen11_early_ops),
|
||||
INTEL_EHL_IDS(&gen11_early_ops),
|
||||
INTEL_TGL_12_IDS(&gen11_early_ops),
|
||||
INTEL_RKL_IDS(&gen11_early_ops),
|
||||
};
|
||||
|
||||
struct resource intel_graphics_stolen_res __ro_after_init = DEFINE_RES_MEM(0, 0);
|
||||
|
@ -304,8 +304,10 @@ static int intel_gtt_setup_scratch_page(void)
|
||||
if (intel_private.needs_dmar) {
|
||||
dma_addr = pci_map_page(intel_private.pcidev, page, 0,
|
||||
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
|
||||
if (pci_dma_mapping_error(intel_private.pcidev, dma_addr))
|
||||
if (pci_dma_mapping_error(intel_private.pcidev, dma_addr)) {
|
||||
__free_page(page);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
intel_private.scratch_page_dma = dma_addr;
|
||||
} else
|
||||
|
@ -158,11 +158,11 @@ static loff_t dma_buf_llseek(struct file *file, loff_t offset, int whence)
|
||||
}
|
||||
|
||||
/**
|
||||
* DOC: fence polling
|
||||
* DOC: implicit fence polling
|
||||
*
|
||||
* To support cross-device and cross-driver synchronization of buffer access
|
||||
* implicit fences (represented internally in the kernel with &struct fence) can
|
||||
* be attached to a &dma_buf. The glue for that and a few related things are
|
||||
* implicit fences (represented internally in the kernel with &struct dma_fence)
|
||||
* can be attached to a &dma_buf. The glue for that and a few related things are
|
||||
* provided in the &dma_resv structure.
|
||||
*
|
||||
* Userspace can query the state of these implicitly tracked fences using poll()
|
||||
|
@ -99,12 +99,6 @@ int dma_fence_chain_find_seqno(struct dma_fence **pfence, uint64_t seqno)
|
||||
return -EINVAL;
|
||||
|
||||
dma_fence_chain_for_each(*pfence, &chain->base) {
|
||||
if ((*pfence)->seqno < seqno) { /* already signaled */
|
||||
dma_fence_put(*pfence);
|
||||
*pfence = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((*pfence)->context != chain->base.context ||
|
||||
to_dma_fence_chain(*pfence)->prev_seqno < seqno)
|
||||
break;
|
||||
@ -228,7 +222,6 @@ EXPORT_SYMBOL(dma_fence_chain_ops);
|
||||
* @chain: the chain node to initialize
|
||||
* @prev: the previous fence
|
||||
* @fence: the current fence
|
||||
* @seqno: the sequence number (syncpt) of the fence within the chain
|
||||
*
|
||||
* Initialize a new chain node and either start a new chain or add the node to
|
||||
* the existing chain of the previous fence.
|
||||
|
@ -64,6 +64,52 @@ static atomic64_t dma_fence_context_counter = ATOMIC64_INIT(1);
|
||||
* &dma_buf.resv pointer.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: fence cross-driver contract
|
||||
*
|
||||
* Since &dma_fence provide a cross driver contract, all drivers must follow the
|
||||
* same rules:
|
||||
*
|
||||
* * Fences must complete in a reasonable time. Fences which represent kernels
|
||||
* and shaders submitted by userspace, which could run forever, must be backed
|
||||
* up by timeout and gpu hang recovery code. Minimally that code must prevent
|
||||
* further command submission and force complete all in-flight fences, e.g.
|
||||
* when the driver or hardware do not support gpu reset, or if the gpu reset
|
||||
* failed for some reason. Ideally the driver supports gpu recovery which only
|
||||
* affects the offending userspace context, and no other userspace
|
||||
* submissions.
|
||||
*
|
||||
* * Drivers may have different ideas of what completion within a reasonable
|
||||
* time means. Some hang recovery code uses a fixed timeout, others a mix
|
||||
* between observing forward progress and increasingly strict timeouts.
|
||||
* Drivers should not try to second guess timeout handling of fences from
|
||||
* other drivers.
|
||||
*
|
||||
* * To ensure there's no deadlocks of dma_fence_wait() against other locks
|
||||
* drivers should annotate all code required to reach dma_fence_signal(),
|
||||
* which completes the fences, with dma_fence_begin_signalling() and
|
||||
* dma_fence_end_signalling().
|
||||
*
|
||||
* * Drivers are allowed to call dma_fence_wait() while holding dma_resv_lock().
|
||||
* This means any code required for fence completion cannot acquire a
|
||||
* &dma_resv lock. Note that this also pulls in the entire established
|
||||
* locking hierarchy around dma_resv_lock() and dma_resv_unlock().
|
||||
*
|
||||
* * Drivers are allowed to call dma_fence_wait() from their &shrinker
|
||||
* callbacks. This means any code required for fence completion cannot
|
||||
* allocate memory with GFP_KERNEL.
|
||||
*
|
||||
* * Drivers are allowed to call dma_fence_wait() from their &mmu_notifier
|
||||
* respectively &mmu_interval_notifier callbacks. This means any code required
|
||||
* for fence completeion cannot allocate memory with GFP_NOFS or GFP_NOIO.
|
||||
* Only GFP_ATOMIC is permissible, which might fail.
|
||||
*
|
||||
* Note that only GPU drivers have a reasonable excuse for both requiring
|
||||
* &mmu_interval_notifier and &shrinker callbacks at the same time as having to
|
||||
* track asynchronous compute work using &dma_fence. No driver outside of
|
||||
* drivers/gpu should ever call dma_fence_wait() in such contexts.
|
||||
*/
|
||||
|
||||
static const char *dma_fence_stub_get_name(struct dma_fence *fence)
|
||||
{
|
||||
return "stub";
|
||||
@ -110,6 +156,160 @@ u64 dma_fence_context_alloc(unsigned num)
|
||||
}
|
||||
EXPORT_SYMBOL(dma_fence_context_alloc);
|
||||
|
||||
/**
|
||||
* DOC: fence signalling annotation
|
||||
*
|
||||
* Proving correctness of all the kernel code around &dma_fence through code
|
||||
* review and testing is tricky for a few reasons:
|
||||
*
|
||||
* * It is a cross-driver contract, and therefore all drivers must follow the
|
||||
* same rules for lock nesting order, calling contexts for various functions
|
||||
* and anything else significant for in-kernel interfaces. But it is also
|
||||
* impossible to test all drivers in a single machine, hence brute-force N vs.
|
||||
* N testing of all combinations is impossible. Even just limiting to the
|
||||
* possible combinations is infeasible.
|
||||
*
|
||||
* * There is an enormous amount of driver code involved. For render drivers
|
||||
* there's the tail of command submission, after fences are published,
|
||||
* scheduler code, interrupt and workers to process job completion,
|
||||
* and timeout, gpu reset and gpu hang recovery code. Plus for integration
|
||||
* with core mm with have &mmu_notifier, respectively &mmu_interval_notifier,
|
||||
* and &shrinker. For modesetting drivers there's the commit tail functions
|
||||
* between when fences for an atomic modeset are published, and when the
|
||||
* corresponding vblank completes, including any interrupt processing and
|
||||
* related workers. Auditing all that code, across all drivers, is not
|
||||
* feasible.
|
||||
*
|
||||
* * Due to how many other subsystems are involved and the locking hierarchies
|
||||
* this pulls in there is extremely thin wiggle-room for driver-specific
|
||||
* differences. &dma_fence interacts with almost all of the core memory
|
||||
* handling through page fault handlers via &dma_resv, dma_resv_lock() and
|
||||
* dma_resv_unlock(). On the other side it also interacts through all
|
||||
* allocation sites through &mmu_notifier and &shrinker.
|
||||
*
|
||||
* Furthermore lockdep does not handle cross-release dependencies, which means
|
||||
* any deadlocks between dma_fence_wait() and dma_fence_signal() can't be caught
|
||||
* at runtime with some quick testing. The simplest example is one thread
|
||||
* waiting on a &dma_fence while holding a lock::
|
||||
*
|
||||
* lock(A);
|
||||
* dma_fence_wait(B);
|
||||
* unlock(A);
|
||||
*
|
||||
* while the other thread is stuck trying to acquire the same lock, which
|
||||
* prevents it from signalling the fence the previous thread is stuck waiting
|
||||
* on::
|
||||
*
|
||||
* lock(A);
|
||||
* unlock(A);
|
||||
* dma_fence_signal(B);
|
||||
*
|
||||
* By manually annotating all code relevant to signalling a &dma_fence we can
|
||||
* teach lockdep about these dependencies, which also helps with the validation
|
||||
* headache since now lockdep can check all the rules for us::
|
||||
*
|
||||
* cookie = dma_fence_begin_signalling();
|
||||
* lock(A);
|
||||
* unlock(A);
|
||||
* dma_fence_signal(B);
|
||||
* dma_fence_end_signalling(cookie);
|
||||
*
|
||||
* For using dma_fence_begin_signalling() and dma_fence_end_signalling() to
|
||||
* annotate critical sections the following rules need to be observed:
|
||||
*
|
||||
* * All code necessary to complete a &dma_fence must be annotated, from the
|
||||
* point where a fence is accessible to other threads, to the point where
|
||||
* dma_fence_signal() is called. Un-annotated code can contain deadlock issues,
|
||||
* and due to the very strict rules and many corner cases it is infeasible to
|
||||
* catch these just with review or normal stress testing.
|
||||
*
|
||||
* * &struct dma_resv deserves a special note, since the readers are only
|
||||
* protected by rcu. This means the signalling critical section starts as soon
|
||||
* as the new fences are installed, even before dma_resv_unlock() is called.
|
||||
*
|
||||
* * The only exception are fast paths and opportunistic signalling code, which
|
||||
* calls dma_fence_signal() purely as an optimization, but is not required to
|
||||
* guarantee completion of a &dma_fence. The usual example is a wait IOCTL
|
||||
* which calls dma_fence_signal(), while the mandatory completion path goes
|
||||
* through a hardware interrupt and possible job completion worker.
|
||||
*
|
||||
* * To aid composability of code, the annotations can be freely nested, as long
|
||||
* as the overall locking hierarchy is consistent. The annotations also work
|
||||
* both in interrupt and process context. Due to implementation details this
|
||||
* requires that callers pass an opaque cookie from
|
||||
* dma_fence_begin_signalling() to dma_fence_end_signalling().
|
||||
*
|
||||
* * Validation against the cross driver contract is implemented by priming
|
||||
* lockdep with the relevant hierarchy at boot-up. This means even just
|
||||
* testing with a single device is enough to validate a driver, at least as
|
||||
* far as deadlocks with dma_fence_wait() against dma_fence_signal() are
|
||||
* concerned.
|
||||
*/
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
static struct lockdep_map dma_fence_lockdep_map = {
|
||||
.name = "dma_fence_map"
|
||||
};
|
||||
|
||||
/**
|
||||
* dma_fence_begin_signalling - begin a critical DMA fence signalling section
|
||||
*
|
||||
* Drivers should use this to annotate the beginning of any code section
|
||||
* required to eventually complete &dma_fence by calling dma_fence_signal().
|
||||
*
|
||||
* The end of these critical sections are annotated with
|
||||
* dma_fence_end_signalling().
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* Opaque cookie needed by the implementation, which needs to be passed to
|
||||
* dma_fence_end_signalling().
|
||||
*/
|
||||
bool dma_fence_begin_signalling(void)
|
||||
{
|
||||
/* explicitly nesting ... */
|
||||
if (lock_is_held_type(&dma_fence_lockdep_map, 1))
|
||||
return true;
|
||||
|
||||
/* rely on might_sleep check for soft/hardirq locks */
|
||||
if (in_atomic())
|
||||
return true;
|
||||
|
||||
/* ... and non-recursive readlock */
|
||||
lock_acquire(&dma_fence_lockdep_map, 0, 0, 1, 1, NULL, _RET_IP_);
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_fence_begin_signalling);
|
||||
|
||||
/**
|
||||
* dma_fence_end_signalling - end a critical DMA fence signalling section
|
||||
*
|
||||
* Closes a critical section annotation opened by dma_fence_begin_signalling().
|
||||
*/
|
||||
void dma_fence_end_signalling(bool cookie)
|
||||
{
|
||||
if (cookie)
|
||||
return;
|
||||
|
||||
lock_release(&dma_fence_lockdep_map, _RET_IP_);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_fence_end_signalling);
|
||||
|
||||
void __dma_fence_might_wait(void)
|
||||
{
|
||||
bool tmp;
|
||||
|
||||
tmp = lock_is_held_type(&dma_fence_lockdep_map, 1);
|
||||
if (tmp)
|
||||
lock_release(&dma_fence_lockdep_map, _THIS_IP_);
|
||||
lock_map_acquire(&dma_fence_lockdep_map);
|
||||
lock_map_release(&dma_fence_lockdep_map);
|
||||
if (tmp)
|
||||
lock_acquire(&dma_fence_lockdep_map, 0, 0, 1, 1, NULL, _THIS_IP_);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* dma_fence_signal_locked - signal completion of a fence
|
||||
* @fence: the fence to signal
|
||||
@ -170,14 +370,19 @@ int dma_fence_signal(struct dma_fence *fence)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
bool tmp;
|
||||
|
||||
if (!fence)
|
||||
return -EINVAL;
|
||||
|
||||
tmp = dma_fence_begin_signalling();
|
||||
|
||||
spin_lock_irqsave(fence->lock, flags);
|
||||
ret = dma_fence_signal_locked(fence);
|
||||
spin_unlock_irqrestore(fence->lock, flags);
|
||||
|
||||
dma_fence_end_signalling(tmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_fence_signal);
|
||||
@ -208,6 +413,10 @@ dma_fence_wait_timeout(struct dma_fence *fence, bool intr, signed long timeout)
|
||||
if (WARN_ON(timeout < 0))
|
||||
return -EINVAL;
|
||||
|
||||
might_sleep();
|
||||
|
||||
__dma_fence_might_wait();
|
||||
|
||||
trace_dma_fence_wait_start(fence);
|
||||
if (fence->ops->wait)
|
||||
ret = fence->ops->wait(fence, intr, timeout);
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched/mm.h>
|
||||
#include <linux/mmu_notifier.h>
|
||||
|
||||
/**
|
||||
* DOC: Reservation Object Overview
|
||||
@ -116,6 +117,13 @@ static int __init dma_resv_lockdep(void)
|
||||
if (ret == -EDEADLK)
|
||||
dma_resv_lock_slow(&obj, &ctx);
|
||||
fs_reclaim_acquire(GFP_KERNEL);
|
||||
#ifdef CONFIG_MMU_NOTIFIER
|
||||
lock_map_acquire(&__mmu_notifier_invalidate_range_start_map);
|
||||
__dma_fence_might_wait();
|
||||
lock_map_release(&__mmu_notifier_invalidate_range_start_map);
|
||||
#else
|
||||
__dma_fence_might_wait();
|
||||
#endif
|
||||
fs_reclaim_release(GFP_KERNEL);
|
||||
ww_mutex_unlock(&obj.lock);
|
||||
ww_acquire_fini(&ctx);
|
||||
|
@ -5,7 +5,7 @@
|
||||
* a module parameter. It must be unique and legal for a C identifier.
|
||||
*
|
||||
* The function should be of type int function(void). It may be conditionally
|
||||
* compiled using #if IS_ENABLED(DRM_I915_SELFTEST).
|
||||
* compiled using #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST).
|
||||
*
|
||||
* Tests are executed in order by igt/dmabuf_selftest
|
||||
*/
|
||||
|
@ -318,15 +318,16 @@ static int find_out_of_order(void *arg)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (fence && fence != fc.chains[1]) {
|
||||
/*
|
||||
* We signaled the middle fence (2) of the 1-2-3 chain. The behavior
|
||||
* of the dma-fence-chain is to make us wait for all the fences up to
|
||||
* the point we want. Since fence 1 is still not signaled, this what
|
||||
* we should get as fence to wait upon (fence 2 being garbage
|
||||
* collected during the traversal of the chain).
|
||||
*/
|
||||
if (fence != fc.chains[0]) {
|
||||
pr_err("Incorrect chain-fence.seqno:%lld reported for completed seqno:2\n",
|
||||
fence->seqno);
|
||||
|
||||
dma_fence_get(fence);
|
||||
err = dma_fence_chain_find_seqno(&fence, 2);
|
||||
dma_fence_put(fence);
|
||||
if (err)
|
||||
pr_err("Reported %d for finding self!\n", err);
|
||||
fence ? fence->seqno : 0);
|
||||
|
||||
err = -EINVAL;
|
||||
}
|
||||
@ -415,20 +416,18 @@ static int __find_race(void *arg)
|
||||
if (!fence)
|
||||
goto signal;
|
||||
|
||||
err = dma_fence_chain_find_seqno(&fence, seqno);
|
||||
if (err) {
|
||||
pr_err("Reported an invalid fence for find-self:%d\n",
|
||||
seqno);
|
||||
dma_fence_put(fence);
|
||||
break;
|
||||
}
|
||||
|
||||
if (fence->seqno < seqno) {
|
||||
pr_err("Reported an earlier fence.seqno:%lld for seqno:%d\n",
|
||||
fence->seqno, seqno);
|
||||
err = -EINVAL;
|
||||
dma_fence_put(fence);
|
||||
break;
|
||||
/*
|
||||
* We can only find ourselves if we are on fence we were
|
||||
* looking for.
|
||||
*/
|
||||
if (fence->seqno == seqno) {
|
||||
err = dma_fence_chain_find_seqno(&fence, seqno);
|
||||
if (err) {
|
||||
pr_err("Reported an invalid fence for find-self:%d\n",
|
||||
seqno);
|
||||
dma_fence_put(fence);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dma_fence_put(fence);
|
||||
|
@ -707,6 +707,16 @@ config XILINX_ZYNQMP_DMA
|
||||
help
|
||||
Enable support for Xilinx ZynqMP DMA controller.
|
||||
|
||||
config XILINX_ZYNQMP_DPDMA
|
||||
tristate "Xilinx DPDMA Engine"
|
||||
select DMA_ENGINE
|
||||
select DMA_VIRTUAL_CHANNELS
|
||||
help
|
||||
Enable support for Xilinx ZynqMP DisplayPort DMA. Choose this option
|
||||
if you have a Xilinx ZynqMP SoC with a DisplayPort subsystem. The
|
||||
driver provides the dmaengine required by the DisplayPort subsystem
|
||||
display driver.
|
||||
|
||||
config ZX_DMA
|
||||
tristate "ZTE ZX DMA support"
|
||||
depends on ARCH_ZX || COMPILE_TEST
|
||||
|
@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_XILINX_DMA) += xilinx_dma.o
|
||||
obj-$(CONFIG_XILINX_ZYNQMP_DMA) += zynqmp_dma.o
|
||||
obj-$(CONFIG_XILINX_ZYNQMP_DPDMA) += xilinx_dpdma.o
|
||||
|
1533
drivers/dma/xilinx/xilinx_dpdma.c
Normal file
1533
drivers/dma/xilinx/xilinx_dpdma.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -386,6 +386,8 @@ source "drivers/gpu/drm/mcde/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/tidss/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/xlnx/Kconfig"
|
||||
|
||||
# Keep legacy drivers last
|
||||
|
||||
menuconfig DRM_LEGACY
|
||||
|
@ -18,7 +18,7 @@ drm-y := drm_auth.o drm_cache.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_managed.o
|
||||
drm_managed.o drm_vblank_work.o
|
||||
|
||||
drm-$(CONFIG_DRM_LEGACY) += drm_legacy_misc.o drm_bufs.o drm_context.o drm_dma.o drm_scatter.o drm_lock.o
|
||||
drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
|
||||
@ -123,3 +123,4 @@ obj-$(CONFIG_DRM_PANFROST) += panfrost/
|
||||
obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/
|
||||
obj-$(CONFIG_DRM_MCDE) += mcde/
|
||||
obj-$(CONFIG_DRM_TIDSS) += tidss/
|
||||
obj-y += xlnx/
|
||||
|
@ -63,12 +63,13 @@ amdgpu-$(CONFIG_PERF_EVENTS) += amdgpu_pmu.o
|
||||
amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.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 si_dpm.o si_smc.o \
|
||||
uvd_v3_1.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
|
||||
arct_reg_init.o navi12_reg_init.o mxgpu_nv.o sienna_cichlid_reg_init.o
|
||||
|
||||
# add DF block
|
||||
amdgpu-y += \
|
||||
@ -80,7 +81,7 @@ 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
|
||||
|
||||
# add UMC block
|
||||
amdgpu-y += \
|
||||
@ -129,7 +130,8 @@ amdgpu-y += \
|
||||
sdma_v2_4.o \
|
||||
sdma_v3_0.o \
|
||||
sdma_v4_0.o \
|
||||
sdma_v5_0.o
|
||||
sdma_v5_0.o \
|
||||
sdma_v5_2.o
|
||||
|
||||
# add MES block
|
||||
amdgpu-y += \
|
||||
@ -154,15 +156,18 @@ amdgpu-y += \
|
||||
vcn_v1_0.o \
|
||||
vcn_v2_0.o \
|
||||
vcn_v2_5.o \
|
||||
vcn_v3_0.o \
|
||||
amdgpu_jpeg.o \
|
||||
jpeg_v1_0.o \
|
||||
jpeg_v2_0.o \
|
||||
jpeg_v2_5.o
|
||||
jpeg_v2_5.o \
|
||||
jpeg_v3_0.o
|
||||
|
||||
# add ATHUB block
|
||||
amdgpu-y += \
|
||||
athub_v1_0.o \
|
||||
athub_v2_0.o
|
||||
athub_v2_0.o \
|
||||
athub_v2_1.o
|
||||
|
||||
# add amdkfd interfaces
|
||||
amdgpu-y += amdgpu_amdkfd.o
|
||||
@ -172,12 +177,13 @@ 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_gfx_v10.o \
|
||||
amdgpu_amdkfd_gfx_v10_3.o
|
||||
|
||||
ifneq ($(CONFIG_DRM_AMDGPU_CIK),)
|
||||
amdgpu-y += amdgpu_amdkfd_gfx_v7.o
|
||||
|
@ -186,11 +186,14 @@ extern int amdgpu_noretry;
|
||||
extern int amdgpu_force_asic_type;
|
||||
#ifdef CONFIG_HSA_AMD
|
||||
extern int sched_policy;
|
||||
extern bool debug_evictions;
|
||||
#else
|
||||
static const int sched_policy = KFD_SCHED_POLICY_HWS;
|
||||
static const bool debug_evictions; /* = false */
|
||||
#endif
|
||||
|
||||
extern int amdgpu_tmz;
|
||||
extern int amdgpu_reset_method;
|
||||
|
||||
#ifdef CONFIG_DRM_AMDGPU_SI
|
||||
extern int amdgpu_si_support;
|
||||
@ -652,10 +655,6 @@ struct amdgpu_fw_vram_usage {
|
||||
u64 size;
|
||||
struct amdgpu_bo *reserved_bo;
|
||||
void *va;
|
||||
|
||||
/* GDDR6 training support flag.
|
||||
*/
|
||||
bool mem_train_support;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -990,9 +989,12 @@ struct amdgpu_device {
|
||||
/* Chip product information */
|
||||
char product_number[16];
|
||||
char product_name[32];
|
||||
char serial[16];
|
||||
char serial[20];
|
||||
|
||||
struct amdgpu_autodump autodump;
|
||||
|
||||
atomic_t throttling_logging_enabled;
|
||||
struct ratelimit_state throttling_logging_rs;
|
||||
};
|
||||
|
||||
static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev)
|
||||
@ -1009,10 +1011,10 @@ int amdgpu_gpu_wait_for_idle(struct amdgpu_device *adev);
|
||||
|
||||
void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
|
||||
uint32_t *buf, size_t size, bool write);
|
||||
uint32_t amdgpu_device_rreg(struct amdgpu_device *adev, uint32_t reg,
|
||||
uint32_t acc_flags);
|
||||
void amdgpu_device_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v,
|
||||
uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg,
|
||||
uint32_t acc_flags);
|
||||
void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v,
|
||||
uint32_t acc_flags);
|
||||
void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev, uint32_t reg, uint32_t v,
|
||||
uint32_t acc_flags);
|
||||
void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value);
|
||||
@ -1031,8 +1033,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
|
||||
*/
|
||||
#define AMDGPU_REGS_NO_KIQ (1<<1)
|
||||
|
||||
#define RREG32_NO_KIQ(reg) amdgpu_device_rreg(adev, (reg), AMDGPU_REGS_NO_KIQ)
|
||||
#define WREG32_NO_KIQ(reg, v) amdgpu_device_wreg(adev, (reg), (v), AMDGPU_REGS_NO_KIQ)
|
||||
#define RREG32_NO_KIQ(reg) amdgpu_mm_rreg(adev, (reg), AMDGPU_REGS_NO_KIQ)
|
||||
#define WREG32_NO_KIQ(reg, v) amdgpu_mm_wreg(adev, (reg), (v), AMDGPU_REGS_NO_KIQ)
|
||||
|
||||
#define RREG32_KIQ(reg) amdgpu_kiq_rreg(adev, (reg))
|
||||
#define WREG32_KIQ(reg, v) amdgpu_kiq_wreg(adev, (reg), (v))
|
||||
@ -1040,9 +1042,9 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
|
||||
#define RREG8(reg) amdgpu_mm_rreg8(adev, (reg))
|
||||
#define WREG8(reg, v) amdgpu_mm_wreg8(adev, (reg), (v))
|
||||
|
||||
#define RREG32(reg) amdgpu_device_rreg(adev, (reg), 0)
|
||||
#define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", amdgpu_device_rreg(adev, (reg), 0))
|
||||
#define WREG32(reg, v) amdgpu_device_wreg(adev, (reg), (v), 0)
|
||||
#define RREG32(reg) amdgpu_mm_rreg(adev, (reg), 0)
|
||||
#define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", amdgpu_mm_rreg(adev, (reg), 0))
|
||||
#define WREG32(reg, v) amdgpu_mm_wreg(adev, (reg), (v), 0)
|
||||
#define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
|
||||
#define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
|
||||
#define RREG32_PCIE(reg) adev->pcie_rreg(adev, (reg))
|
||||
@ -1079,7 +1081,16 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
|
||||
tmp_ |= ((val) & ~(mask)); \
|
||||
WREG32_PLL(reg, tmp_); \
|
||||
} while (0)
|
||||
#define DREG32_SYS(sqf, adev, reg) seq_printf((sqf), #reg " : 0x%08X\n", amdgpu_device_rreg((adev), (reg), false))
|
||||
|
||||
#define WREG32_SMC_P(_Reg, _Val, _Mask) \
|
||||
do { \
|
||||
u32 tmp = RREG32_SMC(_Reg); \
|
||||
tmp &= (_Mask); \
|
||||
tmp |= ((_Val) & ~(_Mask)); \
|
||||
WREG32_SMC(_Reg, tmp); \
|
||||
} while (0)
|
||||
|
||||
#define DREG32_SYS(sqf, adev, reg) seq_printf((sqf), #reg " : 0x%08X\n", amdgpu_mm_rreg((adev), (reg), false))
|
||||
#define RREG32_IO(reg) amdgpu_io_rreg(adev, (reg))
|
||||
#define WREG32_IO(reg, v) amdgpu_io_wreg(adev, (reg), (v))
|
||||
|
||||
|
@ -64,7 +64,9 @@ struct amdgpu_atif {
|
||||
struct amdgpu_atif_notifications notifications;
|
||||
struct amdgpu_atif_functions functions;
|
||||
struct amdgpu_atif_notification_cfg notification_cfg;
|
||||
struct amdgpu_encoder *encoder_for_bl;
|
||||
#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
|
||||
struct backlight_device *bd;
|
||||
#endif
|
||||
struct amdgpu_dm_backlight_caps backlight_caps;
|
||||
};
|
||||
|
||||
@ -444,45 +446,21 @@ static int amdgpu_atif_handler(struct amdgpu_device *adev,
|
||||
|
||||
DRM_DEBUG_DRIVER("ATIF: %d pending SBIOS requests\n", count);
|
||||
|
||||
if ((req.pending & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST) &&
|
||||
!amdgpu_device_has_dc_support(adev)) {
|
||||
struct amdgpu_encoder *enc = atif->encoder_for_bl;
|
||||
|
||||
if (enc) {
|
||||
struct amdgpu_encoder_atom_dig *dig = enc->enc_priv;
|
||||
|
||||
if (req.pending & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST) {
|
||||
#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
|
||||
if (atif->bd) {
|
||||
DRM_DEBUG_DRIVER("Changing brightness to %d\n",
|
||||
req.backlight_level);
|
||||
|
||||
amdgpu_display_backlight_set_level(adev, enc, req.backlight_level);
|
||||
|
||||
#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
|
||||
backlight_force_update(dig->bl_dev,
|
||||
BACKLIGHT_UPDATE_HOTKEY);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if defined(CONFIG_DRM_AMD_DC)
|
||||
#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
|
||||
if ((req.pending & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST) &&
|
||||
amdgpu_device_has_dc_support(adev)) {
|
||||
struct amdgpu_display_manager *dm = &adev->dm;
|
||||
struct backlight_device *bd = dm->backlight_dev;
|
||||
|
||||
if (bd) {
|
||||
DRM_DEBUG_DRIVER("Changing brightness to %d\n",
|
||||
req.backlight_level);
|
||||
|
||||
/*
|
||||
* XXX backlight_device_set_brightness() is
|
||||
* hardwired to post BACKLIGHT_UPDATE_SYSFS.
|
||||
* It probably should accept 'reason' parameter.
|
||||
*/
|
||||
backlight_device_set_brightness(bd, req.backlight_level);
|
||||
backlight_device_set_brightness(atif->bd, req.backlight_level);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (req.pending & ATIF_DGPU_DISPLAY_EVENT) {
|
||||
if (adev->flags & AMD_IS_PX) {
|
||||
pm_runtime_get_sync(adev->ddev->dev);
|
||||
@ -829,23 +807,32 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
|
||||
adev->atif = atif;
|
||||
|
||||
if (atif->notifications.brightness_change) {
|
||||
struct drm_encoder *tmp;
|
||||
#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
|
||||
if (amdgpu_device_has_dc_support(adev)) {
|
||||
#if defined(CONFIG_DRM_AMD_DC)
|
||||
struct amdgpu_display_manager *dm = &adev->dm;
|
||||
atif->bd = dm->backlight_dev;
|
||||
#endif
|
||||
} else {
|
||||
struct drm_encoder *tmp;
|
||||
|
||||
/* Find the encoder controlling the brightness */
|
||||
list_for_each_entry(tmp, &adev->ddev->mode_config.encoder_list,
|
||||
head) {
|
||||
struct amdgpu_encoder *enc = to_amdgpu_encoder(tmp);
|
||||
/* Find the encoder controlling the brightness */
|
||||
list_for_each_entry(tmp, &adev->ddev->mode_config.encoder_list,
|
||||
head) {
|
||||
struct amdgpu_encoder *enc = to_amdgpu_encoder(tmp);
|
||||
|
||||
if ((enc->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
|
||||
enc->enc_priv) {
|
||||
struct amdgpu_encoder_atom_dig *dig = enc->enc_priv;
|
||||
if (dig->bl_dev) {
|
||||
atif->encoder_for_bl = enc;
|
||||
break;
|
||||
if ((enc->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
|
||||
enc->enc_priv) {
|
||||
struct amdgpu_encoder_atom_dig *dig = enc->enc_priv;
|
||||
if (dig->bl_dev) {
|
||||
atif->bd = dig->bl_dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (atif->functions.sbios_requests && !atif->functions.system_params) {
|
||||
/* XXX check this workraround, if sbios request function is
|
||||
|
@ -31,8 +31,6 @@
|
||||
#include "amdgpu_xgmi.h"
|
||||
#include <uapi/linux/kfd_ioctl.h>
|
||||
|
||||
static const unsigned int compute_vmid_bitmap = 0xFF00;
|
||||
|
||||
/* Total memory size in system memory and all GPU VRAM. Used to
|
||||
* estimate worst case amount of memory to reserve for page tables
|
||||
*/
|
||||
@ -113,7 +111,9 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
|
||||
|
||||
if (adev->kfd.dev) {
|
||||
struct kgd2kfd_shared_resources gpu_resources = {
|
||||
.compute_vmid_bitmap = compute_vmid_bitmap,
|
||||
.compute_vmid_bitmap =
|
||||
((1 << AMDGPU_NUM_VMID) - 1) -
|
||||
((1 << adev->vm_manager.first_kfd_vmid) - 1),
|
||||
.num_pipe_per_mec = adev->gfx.mec.num_pipe_per_mec,
|
||||
.num_queue_per_pipe = adev->gfx.mec.num_queue_per_pipe,
|
||||
.gpuvm_size = min(adev->vm_manager.max_pfn
|
||||
@ -637,10 +637,8 @@ void amdgpu_amdkfd_set_compute_idle(struct kgd_dev *kgd, bool idle)
|
||||
|
||||
bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid)
|
||||
{
|
||||
if (adev->kfd.dev) {
|
||||
if ((1 << vmid) & compute_vmid_bitmap)
|
||||
return true;
|
||||
}
|
||||
if (adev->kfd.dev)
|
||||
return vmid >= adev->vm_manager.first_kfd_vmid;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
834
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c
Normal file
834
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c
Normal file
@ -0,0 +1,834 @@
|
||||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <linux/mmu_context.h>
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "gc/gc_10_3_0_offset.h"
|
||||
#include "gc/gc_10_3_0_sh_mask.h"
|
||||
#include "navi10_enum.h"
|
||||
#include "oss/osssys_5_0_0_offset.h"
|
||||
#include "oss/osssys_5_0_0_sh_mask.h"
|
||||
#include "soc15_common.h"
|
||||
#include "v10_structs.h"
|
||||
#include "nv.h"
|
||||
#include "nvd.h"
|
||||
#include "gfxhub_v2_1.h"
|
||||
|
||||
enum hqd_dequeue_request_type {
|
||||
NO_ACTION = 0,
|
||||
DRAIN_PIPE,
|
||||
RESET_WAVES,
|
||||
SAVE_WAVES
|
||||
};
|
||||
|
||||
static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
|
||||
{
|
||||
return (struct amdgpu_device *)kgd;
|
||||
}
|
||||
|
||||
static void lock_srbm(struct kgd_dev *kgd, uint32_t mec, uint32_t pipe,
|
||||
uint32_t queue, uint32_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
nv_grbm_select(adev, mec, pipe, queue, vmid);
|
||||
}
|
||||
|
||||
static void unlock_srbm(struct kgd_dev *kgd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
nv_grbm_select(adev, 0, 0, 0, 0);
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
}
|
||||
|
||||
static void acquire_queue(struct kgd_dev *kgd, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
uint32_t mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
uint32_t pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
||||
lock_srbm(kgd, mec, pipe, queue_id, 0);
|
||||
}
|
||||
|
||||
static uint64_t get_queue_mask(struct amdgpu_device *adev,
|
||||
uint32_t pipe_id, uint32_t queue_id)
|
||||
{
|
||||
unsigned int bit = pipe_id * adev->gfx.mec.num_queue_per_pipe +
|
||||
queue_id;
|
||||
|
||||
return 1ull << bit;
|
||||
}
|
||||
|
||||
static void release_queue(struct kgd_dev *kgd)
|
||||
{
|
||||
unlock_srbm(kgd);
|
||||
}
|
||||
|
||||
static void program_sh_mem_settings_v10_3(struct kgd_dev *kgd, uint32_t vmid,
|
||||
uint32_t sh_mem_config,
|
||||
uint32_t sh_mem_ape1_base,
|
||||
uint32_t sh_mem_ape1_limit,
|
||||
uint32_t sh_mem_bases)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
lock_srbm(kgd, 0, 0, 0, vmid);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_CONFIG), sh_mem_config);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_BASES), sh_mem_bases);
|
||||
/* APE1 no longer exists on GFX9 */
|
||||
|
||||
unlock_srbm(kgd);
|
||||
}
|
||||
|
||||
/* ATC is defeatured on Sienna_Cichlid */
|
||||
static int set_pasid_vmid_mapping_v10_3(struct kgd_dev *kgd, unsigned int pasid,
|
||||
unsigned int vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
uint32_t value = pasid << IH_VMID_0_LUT__PASID__SHIFT;
|
||||
|
||||
/* Mapping vmid to pasid also for IH block */
|
||||
pr_debug("mapping vmid %d -> pasid %d in IH block for GFX client\n",
|
||||
vmid, pasid);
|
||||
WREG32(SOC15_REG_OFFSET(OSSSYS, 0, mmIH_VMID_0_LUT) + vmid, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_interrupts_v10_3(struct kgd_dev *kgd, uint32_t pipe_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t mec;
|
||||
uint32_t pipe;
|
||||
|
||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
||||
lock_srbm(kgd, mec, pipe, 0, 0);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCPC_INT_CNTL),
|
||||
CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
|
||||
CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
|
||||
|
||||
unlock_srbm(kgd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev,
|
||||
unsigned int engine_id,
|
||||
unsigned int queue_id)
|
||||
{
|
||||
uint32_t sdma_engine_reg_base = 0;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
|
||||
switch (engine_id) {
|
||||
default:
|
||||
dev_warn(adev->dev,
|
||||
"Invalid sdma engine id (%d), using engine id 0\n",
|
||||
engine_id);
|
||||
/* fall through */
|
||||
case 0:
|
||||
sdma_engine_reg_base = SOC15_REG_OFFSET(SDMA0, 0,
|
||||
mmSDMA0_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL;
|
||||
break;
|
||||
case 1:
|
||||
sdma_engine_reg_base = SOC15_REG_OFFSET(SDMA1, 0,
|
||||
mmSDMA1_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL;
|
||||
break;
|
||||
case 2:
|
||||
sdma_engine_reg_base = SOC15_REG_OFFSET(SDMA2, 0,
|
||||
mmSDMA2_RLC0_RB_CNTL) - mmSDMA2_RLC0_RB_CNTL;
|
||||
break;
|
||||
case 3:
|
||||
sdma_engine_reg_base = SOC15_REG_OFFSET(SDMA3, 0,
|
||||
mmSDMA3_RLC0_RB_CNTL) - mmSDMA2_RLC0_RB_CNTL;
|
||||
break;
|
||||
}
|
||||
|
||||
sdma_rlc_reg_offset = sdma_engine_reg_base
|
||||
+ queue_id * (mmSDMA0_RLC1_RB_CNTL - mmSDMA0_RLC0_RB_CNTL);
|
||||
|
||||
pr_debug("RLC register offset for SDMA%d RLC%d: 0x%x\n", engine_id,
|
||||
queue_id, sdma_rlc_reg_offset);
|
||||
|
||||
return sdma_rlc_reg_offset;
|
||||
}
|
||||
|
||||
static inline struct v10_compute_mqd *get_mqd(void *mqd)
|
||||
{
|
||||
return (struct v10_compute_mqd *)mqd;
|
||||
}
|
||||
|
||||
static inline struct v10_sdma_mqd *get_sdma_mqd(void *mqd)
|
||||
{
|
||||
return (struct v10_sdma_mqd *)mqd;
|
||||
}
|
||||
|
||||
static int hqd_load_v10_3(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id,
|
||||
uint32_t queue_id, uint32_t __user *wptr,
|
||||
uint32_t wptr_shift, uint32_t wptr_mask,
|
||||
struct mm_struct *mm)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v10_compute_mqd *m;
|
||||
uint32_t *mqd_hqd;
|
||||
uint32_t reg, hqd_base, data;
|
||||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
pr_debug("Load hqd of pipe %d queue %d\n", pipe_id, queue_id);
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
|
||||
/* HIQ is set during driver init period with vmid set to 0*/
|
||||
if (m->cp_hqd_vmid == 0) {
|
||||
uint32_t value, mec, pipe;
|
||||
|
||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
||||
pr_debug("kfd: set HIQ, mec:%d, pipe:%d, queue:%d.\n",
|
||||
mec, pipe, queue_id);
|
||||
value = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CP_SCHEDULERS));
|
||||
value = REG_SET_FIELD(value, RLC_CP_SCHEDULERS, scheduler1,
|
||||
((mec << 5) | (pipe << 3) | queue_id | 0x80));
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CP_SCHEDULERS), value);
|
||||
}
|
||||
|
||||
/* HQD registers extend from CP_MQD_BASE_ADDR to CP_HQD_EOP_WPTR_MEM. */
|
||||
mqd_hqd = &m->cp_mqd_base_addr_lo;
|
||||
hqd_base = SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR);
|
||||
|
||||
for (reg = hqd_base;
|
||||
reg <= SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI); reg++)
|
||||
WREG32(reg, mqd_hqd[reg - hqd_base]);
|
||||
|
||||
|
||||
/* Activate doorbell logic before triggering WPTR poll. */
|
||||
data = REG_SET_FIELD(m->cp_hqd_pq_doorbell_control,
|
||||
CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 1);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL), data);
|
||||
|
||||
if (wptr) {
|
||||
/* Don't read wptr with get_user because the user
|
||||
* context may not be accessible (if this function
|
||||
* runs in a work queue). Instead trigger a one-shot
|
||||
* polling read from memory in the CP. This assumes
|
||||
* that wptr is GPU-accessible in the queue's VMID via
|
||||
* ATC or SVM. WPTR==RPTR before starting the poll so
|
||||
* the CP starts fetching new commands from the right
|
||||
* place.
|
||||
*
|
||||
* Guessing a 64-bit WPTR from a 32-bit RPTR is a bit
|
||||
* tricky. Assume that the queue didn't overflow. The
|
||||
* number of valid bits in the 32-bit RPTR depends on
|
||||
* the queue size. The remaining bits are taken from
|
||||
* the saved 64-bit WPTR. If the WPTR wrapped, add the
|
||||
* queue size.
|
||||
*/
|
||||
uint32_t queue_size =
|
||||
2 << REG_GET_FIELD(m->cp_hqd_pq_control,
|
||||
CP_HQD_PQ_CONTROL, QUEUE_SIZE);
|
||||
uint64_t guessed_wptr = m->cp_hqd_pq_rptr & (queue_size - 1);
|
||||
|
||||
if ((m->cp_hqd_pq_wptr_lo & (queue_size - 1)) < guessed_wptr)
|
||||
guessed_wptr += queue_size;
|
||||
guessed_wptr += m->cp_hqd_pq_wptr_lo & ~(queue_size - 1);
|
||||
guessed_wptr += (uint64_t)m->cp_hqd_pq_wptr_hi << 32;
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_LO),
|
||||
lower_32_bits(guessed_wptr));
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI),
|
||||
upper_32_bits(guessed_wptr));
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR),
|
||||
lower_32_bits((uint64_t)wptr));
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI),
|
||||
upper_32_bits((uint64_t)wptr));
|
||||
pr_debug("%s setting CP_PQ_WPTR_POLL_CNTL1 to %x\n", __func__,
|
||||
(uint32_t)get_queue_mask(adev, pipe_id, queue_id));
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_PQ_WPTR_POLL_CNTL1),
|
||||
(uint32_t)get_queue_mask(adev, pipe_id, queue_id));
|
||||
}
|
||||
|
||||
/* Start the EOP fetcher */
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_RPTR),
|
||||
REG_SET_FIELD(m->cp_hqd_eop_rptr,
|
||||
CP_HQD_EOP_RPTR, INIT_FETCHER, 1));
|
||||
|
||||
data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE), data);
|
||||
|
||||
release_queue(kgd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hiq_mqd_load_v10_3(struct kgd_dev *kgd, void *mqd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t doorbell_off)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct amdgpu_ring *kiq_ring = &adev->gfx.kiq.ring;
|
||||
struct v10_compute_mqd *m;
|
||||
uint32_t mec, pipe;
|
||||
int r;
|
||||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
|
||||
mec = (pipe_id / adev->gfx.mec.num_pipe_per_mec) + 1;
|
||||
pipe = (pipe_id % adev->gfx.mec.num_pipe_per_mec);
|
||||
|
||||
pr_debug("kfd: set HIQ, mec:%d, pipe:%d, queue:%d.\n",
|
||||
mec, pipe, queue_id);
|
||||
|
||||
spin_lock(&adev->gfx.kiq.ring_lock);
|
||||
r = amdgpu_ring_alloc(kiq_ring, 7);
|
||||
if (r) {
|
||||
pr_err("Failed to alloc KIQ (%d).\n", r);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_MAP_QUEUES, 5));
|
||||
amdgpu_ring_write(kiq_ring,
|
||||
PACKET3_MAP_QUEUES_QUEUE_SEL(0) | /* Queue_Sel */
|
||||
PACKET3_MAP_QUEUES_VMID(m->cp_hqd_vmid) | /* VMID */
|
||||
PACKET3_MAP_QUEUES_QUEUE(queue_id) |
|
||||
PACKET3_MAP_QUEUES_PIPE(pipe) |
|
||||
PACKET3_MAP_QUEUES_ME((mec - 1)) |
|
||||
PACKET3_MAP_QUEUES_QUEUE_TYPE(0) | /*queue_type: normal compute queue */
|
||||
PACKET3_MAP_QUEUES_ALLOC_FORMAT(0) | /* alloc format: all_on_one_pipe */
|
||||
PACKET3_MAP_QUEUES_ENGINE_SEL(1) | /* engine_sel: hiq */
|
||||
PACKET3_MAP_QUEUES_NUM_QUEUES(1)); /* num_queues: must be 1 */
|
||||
amdgpu_ring_write(kiq_ring,
|
||||
PACKET3_MAP_QUEUES_DOORBELL_OFFSET(doorbell_off));
|
||||
amdgpu_ring_write(kiq_ring, m->cp_mqd_base_addr_lo);
|
||||
amdgpu_ring_write(kiq_ring, m->cp_mqd_base_addr_hi);
|
||||
amdgpu_ring_write(kiq_ring, m->cp_hqd_pq_wptr_poll_addr_lo);
|
||||
amdgpu_ring_write(kiq_ring, m->cp_hqd_pq_wptr_poll_addr_hi);
|
||||
amdgpu_ring_commit(kiq_ring);
|
||||
|
||||
out_unlock:
|
||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||
release_queue(kgd);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int hqd_dump_v10_3(struct kgd_dev *kgd,
|
||||
uint32_t pipe_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t i = 0, reg;
|
||||
#define HQD_N_REGS 56
|
||||
#define DUMP_REG(addr) do { \
|
||||
if (WARN_ON_ONCE(i >= HQD_N_REGS)) \
|
||||
break; \
|
||||
(*dump)[i][0] = (addr) << 2; \
|
||||
(*dump)[i++][1] = RREG32(addr); \
|
||||
} while (0)
|
||||
|
||||
*dump = kmalloc(HQD_N_REGS*2*sizeof(uint32_t), GFP_KERNEL);
|
||||
if (*dump == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
|
||||
for (reg = SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR);
|
||||
reg <= SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI); reg++)
|
||||
DUMP_REG(reg);
|
||||
|
||||
release_queue(kgd);
|
||||
|
||||
WARN_ON_ONCE(i != HQD_N_REGS);
|
||||
*n_regs = i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hqd_sdma_load_v10_3(struct kgd_dev *kgd, void *mqd,
|
||||
uint32_t __user *wptr, struct mm_struct *mm)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v10_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
unsigned long end_jiffies;
|
||||
uint32_t data;
|
||||
uint64_t data64;
|
||||
uint64_t __user *wptr64 = (uint64_t __user *)wptr;
|
||||
|
||||
m = get_sdma_mqd(mqd);
|
||||
sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
|
||||
m->sdma_queue_id);
|
||||
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL,
|
||||
m->sdmax_rlcx_rb_cntl & (~SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK));
|
||||
|
||||
end_jiffies = msecs_to_jiffies(2000) + jiffies;
|
||||
while (true) {
|
||||
data = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_CONTEXT_STATUS);
|
||||
if (data & SDMA0_RLC0_CONTEXT_STATUS__IDLE_MASK)
|
||||
break;
|
||||
if (time_after(jiffies, end_jiffies)) {
|
||||
pr_err("SDMA RLC not idle in %s\n", __func__);
|
||||
return -ETIME;
|
||||
}
|
||||
usleep_range(500, 1000);
|
||||
}
|
||||
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_DOORBELL_OFFSET,
|
||||
m->sdmax_rlcx_doorbell_offset);
|
||||
|
||||
data = REG_SET_FIELD(m->sdmax_rlcx_doorbell, SDMA0_RLC0_DOORBELL,
|
||||
ENABLE, 1);
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_DOORBELL, data);
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR,
|
||||
m->sdmax_rlcx_rb_rptr);
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_HI,
|
||||
m->sdmax_rlcx_rb_rptr_hi);
|
||||
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_MINOR_PTR_UPDATE, 1);
|
||||
if (read_user_wptr(mm, wptr64, data64)) {
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR,
|
||||
lower_32_bits(data64));
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR_HI,
|
||||
upper_32_bits(data64));
|
||||
} else {
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR,
|
||||
m->sdmax_rlcx_rb_rptr);
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_WPTR_HI,
|
||||
m->sdmax_rlcx_rb_rptr_hi);
|
||||
}
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_MINOR_PTR_UPDATE, 0);
|
||||
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_BASE, m->sdmax_rlcx_rb_base);
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_BASE_HI,
|
||||
m->sdmax_rlcx_rb_base_hi);
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_ADDR_LO,
|
||||
m->sdmax_rlcx_rb_rptr_addr_lo);
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_ADDR_HI,
|
||||
m->sdmax_rlcx_rb_rptr_addr_hi);
|
||||
|
||||
data = REG_SET_FIELD(m->sdmax_rlcx_rb_cntl, SDMA0_RLC0_RB_CNTL,
|
||||
RB_ENABLE, 1);
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hqd_sdma_dump_v10_3(struct kgd_dev *kgd,
|
||||
uint32_t engine_id, uint32_t queue_id,
|
||||
uint32_t (**dump)[2], uint32_t *n_regs)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev,
|
||||
engine_id, queue_id);
|
||||
uint32_t i = 0, reg;
|
||||
#undef HQD_N_REGS
|
||||
#define HQD_N_REGS (19+6+7+10)
|
||||
|
||||
*dump = kmalloc(HQD_N_REGS*2*sizeof(uint32_t), GFP_KERNEL);
|
||||
if (*dump == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
for (reg = mmSDMA0_RLC0_RB_CNTL; reg <= mmSDMA0_RLC0_DOORBELL; reg++)
|
||||
DUMP_REG(sdma_rlc_reg_offset + reg);
|
||||
for (reg = mmSDMA0_RLC0_STATUS; reg <= mmSDMA0_RLC0_CSA_ADDR_HI; reg++)
|
||||
DUMP_REG(sdma_rlc_reg_offset + reg);
|
||||
for (reg = mmSDMA0_RLC0_IB_SUB_REMAIN;
|
||||
reg <= mmSDMA0_RLC0_MINOR_PTR_UPDATE; reg++)
|
||||
DUMP_REG(sdma_rlc_reg_offset + reg);
|
||||
for (reg = mmSDMA0_RLC0_MIDCMD_DATA0;
|
||||
reg <= mmSDMA0_RLC0_MIDCMD_CNTL; reg++)
|
||||
DUMP_REG(sdma_rlc_reg_offset + reg);
|
||||
|
||||
WARN_ON_ONCE(i != HQD_N_REGS);
|
||||
*n_regs = i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool hqd_is_occupied_v10_3(struct kgd_dev *kgd, uint64_t queue_address,
|
||||
uint32_t pipe_id, uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t act;
|
||||
bool retval = false;
|
||||
uint32_t low, high;
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
act = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE));
|
||||
if (act) {
|
||||
low = lower_32_bits(queue_address >> 8);
|
||||
high = upper_32_bits(queue_address >> 8);
|
||||
|
||||
if (low == RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_BASE)) &&
|
||||
high == RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_BASE_HI)))
|
||||
retval = true;
|
||||
}
|
||||
release_queue(kgd);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool hqd_sdma_is_occupied_v10_3(struct kgd_dev *kgd, void *mqd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v10_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
uint32_t sdma_rlc_rb_cntl;
|
||||
|
||||
m = get_sdma_mqd(mqd);
|
||||
sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
|
||||
m->sdma_queue_id);
|
||||
|
||||
sdma_rlc_rb_cntl = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL);
|
||||
|
||||
if (sdma_rlc_rb_cntl & SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int hqd_destroy_v10_3(struct kgd_dev *kgd, void *mqd,
|
||||
enum kfd_preempt_type reset_type,
|
||||
unsigned int utimeout, uint32_t pipe_id,
|
||||
uint32_t queue_id)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
enum hqd_dequeue_request_type type;
|
||||
unsigned long end_jiffies;
|
||||
uint32_t temp;
|
||||
struct v10_compute_mqd *m = get_mqd(mqd);
|
||||
|
||||
acquire_queue(kgd, pipe_id, queue_id);
|
||||
|
||||
if (m->cp_hqd_vmid == 0)
|
||||
WREG32_FIELD15(GC, 0, RLC_CP_SCHEDULERS, scheduler1, 0);
|
||||
|
||||
switch (reset_type) {
|
||||
case KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN:
|
||||
type = DRAIN_PIPE;
|
||||
break;
|
||||
case KFD_PREEMPT_TYPE_WAVEFRONT_RESET:
|
||||
type = RESET_WAVES;
|
||||
break;
|
||||
default:
|
||||
type = DRAIN_PIPE;
|
||||
break;
|
||||
}
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_DEQUEUE_REQUEST), type);
|
||||
|
||||
end_jiffies = (utimeout * HZ / 1000) + jiffies;
|
||||
while (true) {
|
||||
temp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE));
|
||||
if (!(temp & CP_HQD_ACTIVE__ACTIVE_MASK))
|
||||
break;
|
||||
if (time_after(jiffies, end_jiffies)) {
|
||||
pr_err("cp queue pipe %d queue %d preemption failed\n",
|
||||
pipe_id, queue_id);
|
||||
release_queue(kgd);
|
||||
return -ETIME;
|
||||
}
|
||||
usleep_range(500, 1000);
|
||||
}
|
||||
|
||||
release_queue(kgd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hqd_sdma_destroy_v10_3(struct kgd_dev *kgd, void *mqd,
|
||||
unsigned int utimeout)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct v10_sdma_mqd *m;
|
||||
uint32_t sdma_rlc_reg_offset;
|
||||
uint32_t temp;
|
||||
unsigned long end_jiffies = (utimeout * HZ / 1000) + jiffies;
|
||||
|
||||
m = get_sdma_mqd(mqd);
|
||||
sdma_rlc_reg_offset = get_sdma_rlc_reg_offset(adev, m->sdma_engine_id,
|
||||
m->sdma_queue_id);
|
||||
|
||||
temp = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL);
|
||||
temp = temp & ~SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK;
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL, temp);
|
||||
|
||||
while (true) {
|
||||
temp = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_CONTEXT_STATUS);
|
||||
if (temp & SDMA0_RLC0_CONTEXT_STATUS__IDLE_MASK)
|
||||
break;
|
||||
if (time_after(jiffies, end_jiffies)) {
|
||||
pr_err("SDMA RLC not idle in %s\n", __func__);
|
||||
return -ETIME;
|
||||
}
|
||||
usleep_range(500, 1000);
|
||||
}
|
||||
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_DOORBELL, 0);
|
||||
WREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL,
|
||||
RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_CNTL) |
|
||||
SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK);
|
||||
|
||||
m->sdmax_rlcx_rb_rptr = RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR);
|
||||
m->sdmax_rlcx_rb_rptr_hi =
|
||||
RREG32(sdma_rlc_reg_offset + mmSDMA0_RLC0_RB_RPTR_HI);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int address_watch_disable_v10_3(struct kgd_dev *kgd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int address_watch_execute_v10_3(struct kgd_dev *kgd,
|
||||
unsigned int watch_point_id,
|
||||
uint32_t cntl_val,
|
||||
uint32_t addr_hi,
|
||||
uint32_t addr_lo)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wave_control_execute_v10_3(struct kgd_dev *kgd,
|
||||
uint32_t gfx_index_val,
|
||||
uint32_t sq_cmd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t data = 0;
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_INDEX), gfx_index_val);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_CMD), sq_cmd);
|
||||
|
||||
data = REG_SET_FIELD(data, GRBM_GFX_INDEX,
|
||||
INSTANCE_BROADCAST_WRITES, 1);
|
||||
data = REG_SET_FIELD(data, GRBM_GFX_INDEX,
|
||||
SA_BROADCAST_WRITES, 1);
|
||||
data = REG_SET_FIELD(data, GRBM_GFX_INDEX,
|
||||
SE_BROADCAST_WRITES, 1);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_INDEX), data);
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t address_watch_get_offset_v10_3(struct kgd_dev *kgd,
|
||||
unsigned int watch_point_id,
|
||||
unsigned int reg_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_vm_context_page_table_base_v10_3(struct kgd_dev *kgd, uint32_t vmid,
|
||||
uint64_t page_table_base)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
/* SDMA is on gfxhub as well for Navi1* series */
|
||||
gfxhub_v2_1_setup_vm_pt_regs(adev, vmid, page_table_base);
|
||||
}
|
||||
|
||||
#if 0
|
||||
uint32_t enable_debug_trap_v10_3(struct kgd_dev *kgd,
|
||||
uint32_t trap_debug_wave_launch_mode,
|
||||
uint32_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t data = 0;
|
||||
uint32_t orig_wave_cntl_value;
|
||||
uint32_t orig_stall_vmid;
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
orig_wave_cntl_value = RREG32(SOC15_REG_OFFSET(GC,
|
||||
0,
|
||||
mmSPI_GDBG_WAVE_CNTL));
|
||||
orig_stall_vmid = REG_GET_FIELD(orig_wave_cntl_value,
|
||||
SPI_GDBG_WAVE_CNTL,
|
||||
STALL_VMID);
|
||||
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL, STALL_RA, 1);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), data);
|
||||
|
||||
data = 0;
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), data);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), orig_stall_vmid);
|
||||
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t disable_debug_trap_v10_3(struct kgd_dev *kgd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
|
||||
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t set_wave_launch_trap_override_v10_3(struct kgd_dev *kgd,
|
||||
uint32_t trap_override,
|
||||
uint32_t trap_mask)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t data = 0;
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL, STALL_RA, 1);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), data);
|
||||
|
||||
data = 0;
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_TRAP_MASK,
|
||||
EXCP_EN, trap_mask);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_TRAP_MASK,
|
||||
REPLACE, trap_override);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), data);
|
||||
|
||||
data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL, STALL_RA, 0);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), data);
|
||||
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t set_wave_launch_mode_v10_3(struct kgd_dev *kgd,
|
||||
uint8_t wave_launch_mode,
|
||||
uint32_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
uint32_t data = 0;
|
||||
bool is_stall_mode;
|
||||
bool is_mode_set;
|
||||
|
||||
is_stall_mode = (wave_launch_mode == 4);
|
||||
is_mode_set = (wave_launch_mode != 0 && wave_launch_mode != 4);
|
||||
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL2,
|
||||
VMID_MASK, is_mode_set ? 1 << vmid : 0);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL2,
|
||||
MODE, is_mode_set ? wave_launch_mode : 0);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL2), data);
|
||||
|
||||
data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL));
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL,
|
||||
STALL_VMID, is_stall_mode ? 1 << vmid : 0);
|
||||
data = REG_SET_FIELD(data, SPI_GDBG_WAVE_CNTL,
|
||||
STALL_RA, is_stall_mode ? 1 : 0);
|
||||
WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_WAVE_CNTL), data);
|
||||
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* kgd_get_iq_wait_times: Returns the mmCP_IQ_WAIT_TIME1/2 values
|
||||
* The values read are:
|
||||
* ib_offload_wait_time -- Wait Count for Indirect Buffer Offloads.
|
||||
* atomic_offload_wait_time -- Wait Count for L2 and GDS Atomics Offloads.
|
||||
* wrm_offload_wait_time -- Wait Count for WAIT_REG_MEM Offloads.
|
||||
* gws_wait_time -- Wait Count for Global Wave Syncs.
|
||||
* que_sleep_wait_time -- Wait Count for Dequeue Retry.
|
||||
* sch_wave_wait_time -- Wait Count for Scheduling Wave Message.
|
||||
* sem_rearm_wait_time -- Wait Count for Semaphore re-arm.
|
||||
* deq_retry_wait_time -- Wait Count for Global Wave Syncs.
|
||||
*/
|
||||
void get_iq_wait_times_v10_3(struct kgd_dev *kgd,
|
||||
uint32_t *wait_times)
|
||||
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
*wait_times = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_IQ_WAIT_TIME2));
|
||||
}
|
||||
|
||||
void build_grace_period_packet_info_v10_3(struct kgd_dev *kgd,
|
||||
uint32_t wait_times,
|
||||
uint32_t grace_period,
|
||||
uint32_t *reg_offset,
|
||||
uint32_t *reg_data)
|
||||
{
|
||||
*reg_data = wait_times;
|
||||
|
||||
*reg_data = REG_SET_FIELD(*reg_data,
|
||||
CP_IQ_WAIT_TIME2,
|
||||
SCH_WAVE,
|
||||
grace_period);
|
||||
|
||||
*reg_offset = mmCP_IQ_WAIT_TIME2;
|
||||
}
|
||||
#endif
|
||||
|
||||
const struct kfd2kgd_calls gfx_v10_3_kfd2kgd = {
|
||||
.program_sh_mem_settings = program_sh_mem_settings_v10_3,
|
||||
.set_pasid_vmid_mapping = set_pasid_vmid_mapping_v10_3,
|
||||
.init_interrupts = init_interrupts_v10_3,
|
||||
.hqd_load = hqd_load_v10_3,
|
||||
.hiq_mqd_load = hiq_mqd_load_v10_3,
|
||||
.hqd_sdma_load = hqd_sdma_load_v10_3,
|
||||
.hqd_dump = hqd_dump_v10_3,
|
||||
.hqd_sdma_dump = hqd_sdma_dump_v10_3,
|
||||
.hqd_is_occupied = hqd_is_occupied_v10_3,
|
||||
.hqd_sdma_is_occupied = hqd_sdma_is_occupied_v10_3,
|
||||
.hqd_destroy = hqd_destroy_v10_3,
|
||||
.hqd_sdma_destroy = hqd_sdma_destroy_v10_3,
|
||||
.address_watch_disable = address_watch_disable_v10_3,
|
||||
.address_watch_execute = address_watch_execute_v10_3,
|
||||
.wave_control_execute = wave_control_execute_v10_3,
|
||||
.address_watch_get_offset = address_watch_get_offset_v10_3,
|
||||
.get_atc_vmid_pasid_mapping_info = NULL,
|
||||
.set_vm_context_page_table_base = set_vm_context_page_table_base_v10_3,
|
||||
.get_hive_id = amdgpu_amdkfd_get_hive_id,
|
||||
#if 0
|
||||
.enable_debug_trap = enable_debug_trap_v10_3,
|
||||
.disable_debug_trap = disable_debug_trap_v10_3,
|
||||
.set_wave_launch_trap_override = set_wave_launch_trap_override_v10_3,
|
||||
.set_wave_launch_mode = set_wave_launch_mode_v10_3,
|
||||
.get_iq_wait_times = get_iq_wait_times_v10_3,
|
||||
.build_grace_period_packet_info = build_grace_period_packet_info_v10_3,
|
||||
#endif
|
||||
};
|
@ -395,7 +395,7 @@ static int vm_update_pds(struct amdgpu_vm *vm, struct amdgpu_sync *sync)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return amdgpu_sync_fence(sync, vm->last_update, false);
|
||||
return amdgpu_sync_fence(sync, vm->last_update);
|
||||
}
|
||||
|
||||
static uint64_t get_pte_flags(struct amdgpu_device *adev, struct kgd_mem *mem)
|
||||
@ -785,7 +785,7 @@ static int unmap_bo_from_gpuvm(struct amdgpu_device *adev,
|
||||
|
||||
amdgpu_vm_clear_freed(adev, vm, &bo_va->last_pt_update);
|
||||
|
||||
amdgpu_sync_fence(sync, bo_va->last_pt_update, false);
|
||||
amdgpu_sync_fence(sync, bo_va->last_pt_update);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -804,7 +804,7 @@ static int update_gpuvm_pte(struct amdgpu_device *adev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
return amdgpu_sync_fence(sync, bo_va->last_pt_update, false);
|
||||
return amdgpu_sync_fence(sync, bo_va->last_pt_update);
|
||||
}
|
||||
|
||||
static int map_bo_to_gpuvm(struct amdgpu_device *adev,
|
||||
@ -1354,7 +1354,7 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
||||
}
|
||||
|
||||
/* Free the BO*/
|
||||
drm_gem_object_put_unlocked(&mem->bo->tbo.base);
|
||||
drm_gem_object_put(&mem->bo->tbo.base);
|
||||
mutex_destroy(&mem->lock);
|
||||
kfree(mem);
|
||||
|
||||
@ -2102,7 +2102,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef)
|
||||
pr_debug("Memory eviction: Validate BOs failed. Try again\n");
|
||||
goto validate_map_fail;
|
||||
}
|
||||
ret = amdgpu_sync_fence(&sync_obj, bo->tbo.moving, false);
|
||||
ret = amdgpu_sync_fence(&sync_obj, bo->tbo.moving);
|
||||
if (ret) {
|
||||
pr_debug("Memory eviction: Sync BO fence failed. Try again\n");
|
||||
goto validate_map_fail;
|
||||
|
@ -2022,11 +2022,6 @@ int amdgpu_atombios_init(struct amdgpu_device *adev)
|
||||
if (adev->is_atom_fw) {
|
||||
amdgpu_atomfirmware_scratch_regs_init(adev);
|
||||
amdgpu_atomfirmware_allocate_fb_scratch(adev);
|
||||
ret = amdgpu_atomfirmware_get_mem_train_info(adev);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to get mem train fb location.\n");
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
amdgpu_atombios_scratch_regs_init(adev);
|
||||
amdgpu_atombios_allocate_fb_scratch(adev);
|
||||
@ -2041,3 +2036,20 @@ int amdgpu_atombios_init(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_atombios_get_data_table(struct amdgpu_device *adev,
|
||||
uint32_t table,
|
||||
uint16_t *size,
|
||||
uint8_t *frev,
|
||||
uint8_t *crev,
|
||||
uint8_t **addr)
|
||||
{
|
||||
uint16_t data_start;
|
||||
|
||||
if (!amdgpu_atom_parse_data_header(adev->mode_info.atom_context, table,
|
||||
size, frev, crev, &data_start))
|
||||
return -EINVAL;
|
||||
|
||||
*addr = (uint8_t *)adev->mode_info.atom_context->bios + data_start;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -216,6 +216,13 @@ int amdgpu_atombios_get_svi2_info(struct amdgpu_device *adev,
|
||||
u8 voltage_type,
|
||||
u8 *svd_gpio_id, u8 *svc_gpio_id);
|
||||
|
||||
int amdgpu_atombios_get_data_table(struct amdgpu_device *adev,
|
||||
uint32_t table,
|
||||
uint16_t *size,
|
||||
uint8_t *frev,
|
||||
uint8_t *crev,
|
||||
uint8_t **addr);
|
||||
|
||||
void amdgpu_atombios_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_atombios_init(struct amdgpu_device *adev);
|
||||
|
||||
|
@ -111,6 +111,7 @@ int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev)
|
||||
|
||||
union igp_info {
|
||||
struct atom_integrated_system_info_v1_11 v11;
|
||||
struct atom_integrated_system_info_v1_12 v12;
|
||||
};
|
||||
|
||||
union umc_info {
|
||||
@ -120,11 +121,13 @@ union umc_info {
|
||||
union vram_info {
|
||||
struct atom_vram_info_header_v2_3 v23;
|
||||
struct atom_vram_info_header_v2_4 v24;
|
||||
struct atom_vram_info_header_v2_5 v25;
|
||||
};
|
||||
|
||||
union vram_module {
|
||||
struct atom_vram_module_v9 v9;
|
||||
struct atom_vram_module_v10 v10;
|
||||
struct atom_vram_module_v11 v11;
|
||||
};
|
||||
|
||||
static int convert_atom_mem_type_to_vram_type(struct amdgpu_device *adev,
|
||||
@ -204,7 +207,6 @@ amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
|
||||
(mode_info->atom_context->bios + data_offset);
|
||||
switch (crev) {
|
||||
case 11:
|
||||
case 12:
|
||||
mem_channel_number = igp_info->v11.umachannelnumber;
|
||||
/* channel width is 64 */
|
||||
if (vram_width)
|
||||
@ -213,6 +215,15 @@ amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
break;
|
||||
case 12:
|
||||
mem_channel_number = igp_info->v12.umachannelnumber;
|
||||
/* channel width is 64 */
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * 64;
|
||||
mem_type = igp_info->v12.memorytype;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -261,6 +272,26 @@ amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
case 5:
|
||||
if (module_id > vram_info->v25.vram_module_num)
|
||||
module_id = 0;
|
||||
vram_module = (union vram_module *)vram_info->v25.vram_module;
|
||||
while (i < module_id) {
|
||||
vram_module = (union vram_module *)
|
||||
((u8 *)vram_module + vram_module->v11.vram_module_size);
|
||||
i++;
|
||||
}
|
||||
mem_type = vram_module->v11.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_module->v11.channel_num;
|
||||
mem_channel_width = vram_module->v11.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
mem_vendor = (vram_module->v11.vender_rev_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -304,6 +335,9 @@ bool amdgpu_atomfirmware_mem_ecc_supported(struct amdgpu_device *adev)
|
||||
|
||||
union firmware_info {
|
||||
struct atom_firmware_info_v3_1 v31;
|
||||
struct atom_firmware_info_v3_2 v32;
|
||||
struct atom_firmware_info_v3_3 v33;
|
||||
struct atom_firmware_info_v3_4 v34;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -492,7 +526,7 @@ static bool gddr6_mem_train_vbios_support(struct amdgpu_device *adev)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int gddr6_mem_train_support(struct amdgpu_device *adev)
|
||||
int amdgpu_mem_train_support(struct amdgpu_device *adev)
|
||||
{
|
||||
int ret;
|
||||
uint32_t major, minor, revision, hw_v;
|
||||
@ -508,6 +542,7 @@ static int gddr6_mem_train_support(struct amdgpu_device *adev)
|
||||
switch (hw_v) {
|
||||
case HW_REV(11, 0, 0):
|
||||
case HW_REV(11, 0, 5):
|
||||
case HW_REV(11, 0, 7):
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
@ -526,46 +561,37 @@ static int gddr6_mem_train_support(struct amdgpu_device *adev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int amdgpu_atomfirmware_get_mem_train_info(struct amdgpu_device *adev)
|
||||
int amdgpu_atomfirmware_get_fw_reserved_fb_size(struct amdgpu_device *adev)
|
||||
{
|
||||
struct atom_context *ctx = adev->mode_info.atom_context;
|
||||
union firmware_info *firmware_info;
|
||||
int index;
|
||||
uint8_t frev, crev;
|
||||
uint16_t data_offset, size;
|
||||
int ret;
|
||||
|
||||
adev->fw_vram_usage.mem_train_support = false;
|
||||
|
||||
if (adev->asic_type != CHIP_NAVI10 &&
|
||||
adev->asic_type != CHIP_NAVI14)
|
||||
return 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
ret = gddr6_mem_train_support(adev);
|
||||
if (ret == -1)
|
||||
return -EINVAL;
|
||||
else if (ret == 0)
|
||||
return 0;
|
||||
u16 data_offset, size;
|
||||
u8 frev, crev;
|
||||
int fw_reserved_fb_size;
|
||||
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
|
||||
vram_usagebyfirmware);
|
||||
ret = amdgpu_atom_parse_data_header(ctx, index, &size, &frev, &crev,
|
||||
&data_offset);
|
||||
if (ret == 0) {
|
||||
DRM_ERROR("parse data header failed.\n");
|
||||
firmwareinfo);
|
||||
|
||||
if (!amdgpu_atom_parse_data_header(ctx, index, &size,
|
||||
&frev, &crev, &data_offset))
|
||||
/* fail to parse data_header */
|
||||
return 0;
|
||||
|
||||
firmware_info = (union firmware_info *)(ctx->bios + data_offset);
|
||||
|
||||
if (frev !=3)
|
||||
return -EINVAL;
|
||||
|
||||
switch (crev) {
|
||||
case 4:
|
||||
fw_reserved_fb_size =
|
||||
(firmware_info->v34.fw_reserved_size_in_kb << 10);
|
||||
break;
|
||||
default:
|
||||
fw_reserved_fb_size = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
DRM_DEBUG("atom firmware common table header size:0x%04x, frev:0x%02x,"
|
||||
" crev:0x%02x, data_offset:0x%04x.\n", size, frev, crev, data_offset);
|
||||
/* only support 2.1+ */
|
||||
if (((uint16_t)frev << 8 | crev) < 0x0201) {
|
||||
DRM_ERROR("frev:0x%02x, crev:0x%02x < 2.1 !\n", frev, crev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
adev->fw_vram_usage.mem_train_support = true;
|
||||
return 0;
|
||||
return fw_reserved_fb_size;
|
||||
}
|
||||
|
@ -31,10 +31,11 @@ void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev);
|
||||
int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev);
|
||||
int amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
|
||||
int *vram_width, int *vram_type, int *vram_vendor);
|
||||
int amdgpu_atomfirmware_get_mem_train_info(struct amdgpu_device *adev);
|
||||
int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev);
|
||||
int amdgpu_atomfirmware_get_gfx_info(struct amdgpu_device *adev);
|
||||
bool amdgpu_atomfirmware_mem_ecc_supported(struct amdgpu_device *adev);
|
||||
bool amdgpu_atomfirmware_sram_ecc_supported(struct amdgpu_device *adev);
|
||||
int amdgpu_atomfirmware_get_fw_reserved_fb_size(struct amdgpu_device *adev);
|
||||
int amdgpu_mem_train_support(struct amdgpu_device *adev);
|
||||
|
||||
#endif
|
||||
|
@ -102,7 +102,7 @@ int amdgpu_bo_list_create(struct amdgpu_device *adev, struct drm_file *filp,
|
||||
}
|
||||
|
||||
bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
|
||||
usermm = amdgpu_ttm_tt_get_usermm(bo->tbo.ttm);
|
||||
if (usermm) {
|
||||
|
@ -716,8 +716,10 @@ amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force)
|
||||
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
}
|
||||
|
||||
if (encoder) {
|
||||
@ -854,8 +856,10 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)
|
||||
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
}
|
||||
|
||||
encoder = amdgpu_connector_best_single_encoder(connector);
|
||||
@ -977,8 +981,10 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
|
||||
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
}
|
||||
|
||||
if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) {
|
||||
@ -1328,8 +1334,10 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force)
|
||||
|
||||
if (!drm_kms_helper_is_poll_worker()) {
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(connector->dev->dev);
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
}
|
||||
|
||||
if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) {
|
||||
|
@ -57,7 +57,7 @@ static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p,
|
||||
/* One for TTM and one for the CS job */
|
||||
p->uf_entry.tv.num_shared = 2;
|
||||
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
|
||||
size = amdgpu_bo_size(bo);
|
||||
if (size != PAGE_SIZE || (data->offset + 8) > size) {
|
||||
@ -992,7 +992,7 @@ static int amdgpu_cs_process_fence_dep(struct amdgpu_cs_parser *p,
|
||||
dma_fence_put(old);
|
||||
}
|
||||
|
||||
r = amdgpu_sync_fence(&p->job->sync, fence, true);
|
||||
r = amdgpu_sync_fence(&p->job->sync, fence);
|
||||
dma_fence_put(fence);
|
||||
if (r)
|
||||
return r;
|
||||
@ -1014,7 +1014,7 @@ static int amdgpu_syncobj_lookup_and_add_to_sync(struct amdgpu_cs_parser *p,
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_sync_fence(&p->job->sync, fence, true);
|
||||
r = amdgpu_sync_fence(&p->job->sync, fence);
|
||||
dma_fence_put(fence);
|
||||
|
||||
return r;
|
||||
|
@ -223,12 +223,16 @@ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f,
|
||||
*pos &= (1UL << 22) - 1;
|
||||
|
||||
r = pm_runtime_get_sync(adev->ddev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_virt_enable_access_debugfs(adev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (use_bank) {
|
||||
if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) ||
|
||||
@ -332,12 +336,16 @@ static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf,
|
||||
return -EINVAL;
|
||||
|
||||
r = pm_runtime_get_sync(adev->ddev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_virt_enable_access_debugfs(adev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
while (size) {
|
||||
uint32_t value;
|
||||
@ -387,12 +395,16 @@ static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user
|
||||
return -EINVAL;
|
||||
|
||||
r = pm_runtime_get_sync(adev->ddev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_virt_enable_access_debugfs(adev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
while (size) {
|
||||
uint32_t value;
|
||||
@ -443,12 +455,16 @@ static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf,
|
||||
return -EINVAL;
|
||||
|
||||
r = pm_runtime_get_sync(adev->ddev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_virt_enable_access_debugfs(adev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
while (size) {
|
||||
uint32_t value;
|
||||
@ -498,12 +514,16 @@ static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user
|
||||
return -EINVAL;
|
||||
|
||||
r = pm_runtime_get_sync(adev->ddev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_virt_enable_access_debugfs(adev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
while (size) {
|
||||
uint32_t value;
|
||||
@ -554,12 +574,16 @@ static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf,
|
||||
return -EINVAL;
|
||||
|
||||
r = pm_runtime_get_sync(adev->ddev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_virt_enable_access_debugfs(adev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
while (size) {
|
||||
uint32_t value;
|
||||
@ -609,12 +633,16 @@ static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user *
|
||||
return -EINVAL;
|
||||
|
||||
r = pm_runtime_get_sync(adev->ddev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_virt_enable_access_debugfs(adev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
while (size) {
|
||||
uint32_t value;
|
||||
@ -764,12 +792,16 @@ static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf,
|
||||
valuesize = sizeof(values);
|
||||
|
||||
r = pm_runtime_get_sync(adev->ddev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_virt_enable_access_debugfs(adev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_dpm_read_sensor(adev, idx, &values[0], &valuesize);
|
||||
|
||||
@ -842,12 +874,16 @@ static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf,
|
||||
simd = (*pos & GENMASK_ULL(44, 37)) >> 37;
|
||||
|
||||
r = pm_runtime_get_sync(adev->ddev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_virt_enable_access_debugfs(adev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* switch to the specific se/sh/cu */
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
@ -937,11 +973,11 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf,
|
||||
|
||||
r = pm_runtime_get_sync(adev->ddev->dev);
|
||||
if (r < 0)
|
||||
return r;
|
||||
goto err;
|
||||
|
||||
r = amdgpu_virt_enable_access_debugfs(adev);
|
||||
if (r < 0)
|
||||
return r;
|
||||
goto err;
|
||||
|
||||
/* switch to the specific se/sh/cu */
|
||||
mutex_lock(&adev->grbm_idx_mutex);
|
||||
@ -967,7 +1003,7 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf,
|
||||
value = data[result >> 2];
|
||||
r = put_user(value, (uint32_t *)buf);
|
||||
if (r) {
|
||||
result = r;
|
||||
amdgpu_virt_disable_access_debugfs(adev);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -976,10 +1012,14 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf,
|
||||
size -= 4;
|
||||
}
|
||||
|
||||
err:
|
||||
kfree(data);
|
||||
amdgpu_virt_disable_access_debugfs(adev);
|
||||
return result;
|
||||
|
||||
err:
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
kfree(data);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1003,8 +1043,10 @@ static ssize_t amdgpu_debugfs_gfxoff_write(struct file *f, const char __user *bu
|
||||
return -EINVAL;
|
||||
|
||||
r = pm_runtime_get_sync(adev->ddev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
while (size) {
|
||||
uint32_t value;
|
||||
@ -1031,6 +1073,57 @@ static ssize_t amdgpu_debugfs_gfxoff_write(struct file *f, const char __user *bu
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* amdgpu_debugfs_regs_gfxoff_status - read gfxoff status
|
||||
*
|
||||
* @f: open file handle
|
||||
* @buf: User buffer to store read data in
|
||||
* @size: Number of bytes to read
|
||||
* @pos: Offset to seek to
|
||||
*/
|
||||
static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf,
|
||||
size_t size, loff_t *pos)
|
||||
{
|
||||
struct amdgpu_device *adev = file_inode(f)->i_private;
|
||||
ssize_t result = 0;
|
||||
int r;
|
||||
|
||||
if (size & 0x3 || *pos & 0x3)
|
||||
return -EINVAL;
|
||||
|
||||
r = pm_runtime_get_sync(adev->ddev->dev);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
while (size) {
|
||||
uint32_t value;
|
||||
|
||||
r = amdgpu_get_gfx_off_status(adev, &value);
|
||||
if (r) {
|
||||
pm_runtime_mark_last_busy(adev->ddev->dev);
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = put_user(value, (uint32_t *)buf);
|
||||
if (r) {
|
||||
pm_runtime_mark_last_busy(adev->ddev->dev);
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
result += 4;
|
||||
buf += 4;
|
||||
*pos += 4;
|
||||
size -= 4;
|
||||
}
|
||||
|
||||
pm_runtime_mark_last_busy(adev->ddev->dev);
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static const struct file_operations amdgpu_debugfs_regs_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = amdgpu_debugfs_regs_read,
|
||||
@ -1081,7 +1174,9 @@ static const struct file_operations amdgpu_debugfs_gpr_fops = {
|
||||
|
||||
static const struct file_operations amdgpu_debugfs_gfxoff_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = amdgpu_debugfs_gfxoff_read,
|
||||
.write = amdgpu_debugfs_gfxoff_write,
|
||||
.llseek = default_llseek
|
||||
};
|
||||
|
||||
static const struct file_operations *debugfs_regs[] = {
|
||||
@ -1140,8 +1235,10 @@ static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data)
|
||||
int r = 0, i;
|
||||
|
||||
r = pm_runtime_get_sync(dev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Avoid accidently unparking the sched thread during GPU reset */
|
||||
mutex_lock(&adev->lock_reset);
|
||||
@ -1197,8 +1294,10 @@ static int amdgpu_debugfs_evict_vram(struct seq_file *m, void *data)
|
||||
int r;
|
||||
|
||||
r = pm_runtime_get_sync(dev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
seq_printf(m, "(%d)\n", amdgpu_bo_evict_vram(adev));
|
||||
|
||||
@ -1216,8 +1315,10 @@ static int amdgpu_debugfs_evict_gtt(struct seq_file *m, void *data)
|
||||
int r;
|
||||
|
||||
r = pm_runtime_get_sync(dev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
seq_printf(m, "(%d)\n", ttm_bo_evict_mm(&adev->mman.bdev, TTM_PL_TT));
|
||||
|
||||
@ -1417,14 +1518,16 @@ static int amdgpu_debugfs_sclk_set(void *data, u64 val)
|
||||
return -EINVAL;
|
||||
|
||||
ret = pm_runtime_get_sync(adev->ddev->dev);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
pm_runtime_put_autosuspend(adev->ddev->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (is_support_sw_smu(adev)) {
|
||||
ret = smu_get_dpm_freq_range(&adev->smu, SMU_SCLK, &min_freq, &max_freq, true);
|
||||
ret = smu_get_dpm_freq_range(&adev->smu, SMU_SCLK, &min_freq, &max_freq);
|
||||
if (ret || val > max_freq || val < min_freq)
|
||||
return -EINVAL;
|
||||
ret = smu_set_soft_freq_range(&adev->smu, SMU_SCLK, (uint32_t)val, (uint32_t)val, true);
|
||||
ret = smu_set_soft_freq_range(&adev->smu, SMU_SCLK, (uint32_t)val, (uint32_t)val);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -80,6 +80,8 @@ MODULE_FIRMWARE("amdgpu/renoir_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/navi10_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/navi14_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/navi12_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/sienna_cichlid_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/navy_flounder_gpu_info.bin");
|
||||
|
||||
#define AMDGPU_RESUME_MS 2000
|
||||
|
||||
@ -112,6 +114,8 @@ const char *amdgpu_asic_name[] = {
|
||||
"NAVI10",
|
||||
"NAVI14",
|
||||
"NAVI12",
|
||||
"SIENNA_CICHLID",
|
||||
"NAVY_FLOUNDER",
|
||||
"LAST",
|
||||
};
|
||||
|
||||
@ -299,10 +303,10 @@ void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
|
||||
}
|
||||
|
||||
/*
|
||||
* device register access helper functions.
|
||||
* MMIO register access helper functions.
|
||||
*/
|
||||
/**
|
||||
* amdgpu_device_rreg - read a register
|
||||
* amdgpu_mm_rreg - read a memory mapped IO register
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @reg: dword aligned register offset
|
||||
@ -310,8 +314,8 @@ void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
|
||||
*
|
||||
* Returns the 32 bit value from the offset specified.
|
||||
*/
|
||||
uint32_t amdgpu_device_rreg(struct amdgpu_device *adev, uint32_t reg,
|
||||
uint32_t acc_flags)
|
||||
uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg,
|
||||
uint32_t acc_flags)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
@ -320,9 +324,15 @@ uint32_t amdgpu_device_rreg(struct amdgpu_device *adev, uint32_t reg,
|
||||
|
||||
if ((reg * 4) < adev->rmmio_size)
|
||||
ret = readl(((void __iomem *)adev->rmmio) + (reg * 4));
|
||||
else
|
||||
ret = adev->pcie_rreg(adev, (reg * 4));
|
||||
trace_amdgpu_device_rreg(adev->pdev->device, reg, ret);
|
||||
else {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&adev->mmio_idx_lock, flags);
|
||||
writel((reg * 4), ((void __iomem *)adev->rmmio) + (mmMM_INDEX * 4));
|
||||
ret = readl(((void __iomem *)adev->rmmio) + (mmMM_DATA * 4));
|
||||
spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
|
||||
}
|
||||
trace_amdgpu_mm_rreg(adev->pdev->device, reg, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -368,19 +378,24 @@ void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value)
|
||||
BUG();
|
||||
}
|
||||
|
||||
void static inline amdgpu_device_wreg_no_kiq(struct amdgpu_device *adev, uint32_t reg,
|
||||
uint32_t v, uint32_t acc_flags)
|
||||
void static inline amdgpu_mm_wreg_mmio(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint32_t acc_flags)
|
||||
{
|
||||
trace_amdgpu_device_wreg(adev->pdev->device, reg, v);
|
||||
trace_amdgpu_mm_wreg(adev->pdev->device, reg, v);
|
||||
|
||||
if ((reg * 4) < adev->rmmio_size)
|
||||
writel(v, ((void __iomem *)adev->rmmio) + (reg * 4));
|
||||
else
|
||||
adev->pcie_wreg(adev, (reg * 4), v);
|
||||
else {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&adev->mmio_idx_lock, flags);
|
||||
writel((reg * 4), ((void __iomem *)adev->rmmio) + (mmMM_INDEX * 4));
|
||||
writel(v, ((void __iomem *)adev->rmmio) + (mmMM_DATA * 4));
|
||||
spin_unlock_irqrestore(&adev->mmio_idx_lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_wreg - write to a register
|
||||
* amdgpu_mm_wreg - write to a memory mapped IO register
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @reg: dword aligned register offset
|
||||
@ -389,13 +404,13 @@ void static inline amdgpu_device_wreg_no_kiq(struct amdgpu_device *adev, uint32_
|
||||
*
|
||||
* Writes the value specified to the offset specified.
|
||||
*/
|
||||
void amdgpu_device_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v,
|
||||
uint32_t acc_flags)
|
||||
void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v,
|
||||
uint32_t acc_flags)
|
||||
{
|
||||
if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev))
|
||||
return amdgpu_kiq_wreg(adev, reg, v);
|
||||
|
||||
amdgpu_device_wreg_no_kiq(adev, reg, v, acc_flags);
|
||||
amdgpu_mm_wreg_mmio(adev, reg, v, acc_flags);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -414,7 +429,7 @@ void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev, uint32_t reg, uint32_t
|
||||
return adev->gfx.rlc.funcs->rlcg_wreg(adev, reg, v);
|
||||
}
|
||||
|
||||
amdgpu_device_wreg_no_kiq(adev, reg, v, acc_flags);
|
||||
amdgpu_mm_wreg_mmio(adev, reg, v, acc_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -907,6 +922,11 @@ int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
/* skip if the bios has already enabled large BAR */
|
||||
if (adev->gmc.real_vram_size &&
|
||||
(pci_resource_len(adev->pdev, 0) >= adev->gmc.real_vram_size))
|
||||
return 0;
|
||||
|
||||
/* Check if the root BUS has 64bit memory resources */
|
||||
root = adev->pdev->bus;
|
||||
while (root->parent)
|
||||
@ -1159,6 +1179,16 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev)
|
||||
amdgpu_vm_fragment_size = -1;
|
||||
}
|
||||
|
||||
if (amdgpu_sched_hw_submission < 2) {
|
||||
dev_warn(adev->dev, "sched hw submission jobs (%d) must be at least 2\n",
|
||||
amdgpu_sched_hw_submission);
|
||||
amdgpu_sched_hw_submission = 2;
|
||||
} else if (!is_power_of_2(amdgpu_sched_hw_submission)) {
|
||||
dev_warn(adev->dev, "sched hw submission jobs (%d) must be a power of 2\n",
|
||||
amdgpu_sched_hw_submission);
|
||||
amdgpu_sched_hw_submission = roundup_pow_of_two(amdgpu_sched_hw_submission);
|
||||
}
|
||||
|
||||
amdgpu_device_check_smu_prv_buffer_size(adev);
|
||||
|
||||
amdgpu_device_check_vm_size(adev);
|
||||
@ -1527,22 +1557,25 @@ static void amdgpu_device_enable_virtual_display(struct amdgpu_device *adev)
|
||||
static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
|
||||
{
|
||||
const char *chip_name;
|
||||
char fw_name[30];
|
||||
char fw_name[40];
|
||||
int err;
|
||||
const struct gpu_info_firmware_header_v1_0 *hdr;
|
||||
|
||||
adev->firmware.gpu_info_fw = NULL;
|
||||
|
||||
if (adev->discovery_bin) {
|
||||
amdgpu_discovery_get_gfx_info(adev);
|
||||
|
||||
/*
|
||||
* FIXME: The bounding box is still needed by Navi12, so
|
||||
* temporarily read it from gpu_info firmware. Should be droped
|
||||
* when DAL no longer needs it.
|
||||
*/
|
||||
if (adev->asic_type != CHIP_NAVI12)
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_TOPAZ:
|
||||
case CHIP_TONGA:
|
||||
case CHIP_FIJI:
|
||||
case CHIP_POLARIS10:
|
||||
case CHIP_POLARIS11:
|
||||
case CHIP_POLARIS12:
|
||||
case CHIP_VEGAM:
|
||||
case CHIP_CARRIZO:
|
||||
case CHIP_STONEY:
|
||||
#ifdef CONFIG_DRM_AMDGPU_SI
|
||||
case CHIP_VERDE:
|
||||
case CHIP_TAHITI:
|
||||
@ -1557,6 +1590,15 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
|
||||
case CHIP_KABINI:
|
||||
case CHIP_MULLINS:
|
||||
#endif
|
||||
case CHIP_TOPAZ:
|
||||
case CHIP_TONGA:
|
||||
case CHIP_FIJI:
|
||||
case CHIP_POLARIS10:
|
||||
case CHIP_POLARIS11:
|
||||
case CHIP_POLARIS12:
|
||||
case CHIP_VEGAM:
|
||||
case CHIP_CARRIZO:
|
||||
case CHIP_STONEY:
|
||||
case CHIP_VEGA20:
|
||||
default:
|
||||
return 0;
|
||||
@ -1589,6 +1631,12 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
|
||||
case CHIP_NAVI12:
|
||||
chip_name = "navi12";
|
||||
break;
|
||||
case CHIP_SIENNA_CICHLID:
|
||||
chip_name = "sienna_cichlid";
|
||||
break;
|
||||
case CHIP_NAVY_FLOUNDER:
|
||||
chip_name = "navy_flounder";
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_gpu_info.bin", chip_name);
|
||||
@ -1617,10 +1665,11 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
|
||||
(const struct gpu_info_firmware_v1_0 *)(adev->firmware.gpu_info_fw->data +
|
||||
le32_to_cpu(hdr->header.ucode_array_offset_bytes));
|
||||
|
||||
if (amdgpu_discovery && adev->asic_type >= CHIP_NAVI10) {
|
||||
amdgpu_discovery_get_gfx_info(adev);
|
||||
/*
|
||||
* Should be droped when DAL no longer needs it.
|
||||
*/
|
||||
if (adev->asic_type == CHIP_NAVI12)
|
||||
goto parse_soc_bounding_box;
|
||||
}
|
||||
|
||||
adev->gfx.config.max_shader_engines = le32_to_cpu(gpu_info_fw->gc_num_se);
|
||||
adev->gfx.config.max_cu_per_sh = le32_to_cpu(gpu_info_fw->gc_num_cu_per_sh);
|
||||
@ -1653,7 +1702,7 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
|
||||
parse_soc_bounding_box:
|
||||
/*
|
||||
* soc bounding box info is not integrated in disocovery table,
|
||||
* we always need to parse it from gpu info firmware.
|
||||
* we always need to parse it from gpu info firmware if needed.
|
||||
*/
|
||||
if (hdr->version_minor == 2) {
|
||||
const struct gpu_info_firmware_v1_2 *gpu_info_fw =
|
||||
@ -1689,25 +1738,13 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
||||
|
||||
amdgpu_device_enable_virtual_display(adev);
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_TOPAZ:
|
||||
case CHIP_TONGA:
|
||||
case CHIP_FIJI:
|
||||
case CHIP_POLARIS10:
|
||||
case CHIP_POLARIS11:
|
||||
case CHIP_POLARIS12:
|
||||
case CHIP_VEGAM:
|
||||
case CHIP_CARRIZO:
|
||||
case CHIP_STONEY:
|
||||
if (adev->asic_type == CHIP_CARRIZO || adev->asic_type == CHIP_STONEY)
|
||||
adev->family = AMDGPU_FAMILY_CZ;
|
||||
else
|
||||
adev->family = AMDGPU_FAMILY_VI;
|
||||
|
||||
r = vi_set_ip_blocks(adev);
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
r = amdgpu_virt_request_full_gpu(adev, true);
|
||||
if (r)
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (adev->asic_type) {
|
||||
#ifdef CONFIG_DRM_AMDGPU_SI
|
||||
case CHIP_VERDE:
|
||||
case CHIP_TAHITI:
|
||||
@ -1726,24 +1763,41 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
||||
case CHIP_KAVERI:
|
||||
case CHIP_KABINI:
|
||||
case CHIP_MULLINS:
|
||||
if ((adev->asic_type == CHIP_BONAIRE) || (adev->asic_type == CHIP_HAWAII))
|
||||
adev->family = AMDGPU_FAMILY_CI;
|
||||
else
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
adev->family = AMDGPU_FAMILY_KV;
|
||||
else
|
||||
adev->family = AMDGPU_FAMILY_CI;
|
||||
|
||||
r = cik_set_ip_blocks(adev);
|
||||
if (r)
|
||||
return r;
|
||||
break;
|
||||
#endif
|
||||
case CHIP_TOPAZ:
|
||||
case CHIP_TONGA:
|
||||
case CHIP_FIJI:
|
||||
case CHIP_POLARIS10:
|
||||
case CHIP_POLARIS11:
|
||||
case CHIP_POLARIS12:
|
||||
case CHIP_VEGAM:
|
||||
case CHIP_CARRIZO:
|
||||
case CHIP_STONEY:
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
adev->family = AMDGPU_FAMILY_CZ;
|
||||
else
|
||||
adev->family = AMDGPU_FAMILY_VI;
|
||||
|
||||
r = vi_set_ip_blocks(adev);
|
||||
if (r)
|
||||
return r;
|
||||
break;
|
||||
case CHIP_VEGA10:
|
||||
case CHIP_VEGA12:
|
||||
case CHIP_VEGA20:
|
||||
case CHIP_RAVEN:
|
||||
case CHIP_ARCTURUS:
|
||||
case CHIP_RENOIR:
|
||||
if (adev->asic_type == CHIP_RAVEN ||
|
||||
adev->asic_type == CHIP_RENOIR)
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
adev->family = AMDGPU_FAMILY_RV;
|
||||
else
|
||||
adev->family = AMDGPU_FAMILY_AI;
|
||||
@ -1755,6 +1809,8 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
||||
case CHIP_NAVI10:
|
||||
case CHIP_NAVI14:
|
||||
case CHIP_NAVI12:
|
||||
case CHIP_SIENNA_CICHLID:
|
||||
case CHIP_NAVY_FLOUNDER:
|
||||
adev->family = AMDGPU_FAMILY_NV;
|
||||
|
||||
r = nv_set_ip_blocks(adev);
|
||||
@ -1768,31 +1824,6 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
||||
|
||||
amdgpu_amdkfd_device_probe(adev);
|
||||
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
/* handle vbios stuff prior full access mode for new handshake */
|
||||
if (adev->virt.req_init_data_ver == 1) {
|
||||
if (!amdgpu_get_bios(adev)) {
|
||||
DRM_ERROR("failed to get vbios\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = amdgpu_atombios_init(adev);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "amdgpu_atombios_init failed\n");
|
||||
amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_INIT_FAIL, 0, 0);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* we need to send REQ_GPU here for legacy handshaker otherwise the vbios
|
||||
* will not be prepared by host for this VF */
|
||||
if (amdgpu_sriov_vf(adev) && adev->virt.req_init_data_ver < 1) {
|
||||
r = amdgpu_virt_request_full_gpu(adev, true);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
adev->pm.pp_feature = amdgpu_pp_feature_mask;
|
||||
if (amdgpu_sriov_vf(adev) || sched_policy == KFD_SCHED_POLICY_NO_HWS)
|
||||
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
|
||||
@ -1824,10 +1855,6 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* skip vbios handling for new handshake */
|
||||
if (amdgpu_sriov_vf(adev) && adev->virt.req_init_data_ver == 1)
|
||||
continue;
|
||||
|
||||
/* Read BIOS */
|
||||
if (!amdgpu_get_bios(adev))
|
||||
return -EINVAL;
|
||||
@ -1954,12 +1981,6 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && adev->virt.req_init_data_ver > 0) {
|
||||
r = amdgpu_virt_request_full_gpu(adev, true);
|
||||
if (r)
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
for (i = 0; i < adev->num_ip_blocks; i++) {
|
||||
if (!adev->ip_blocks[i].status.valid)
|
||||
continue;
|
||||
@ -2308,6 +2329,9 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && adev->virt.ras_init_done)
|
||||
amdgpu_virt_release_ras_err_handler_data(adev);
|
||||
|
||||
amdgpu_ras_pre_fini(adev);
|
||||
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1)
|
||||
@ -2438,18 +2462,21 @@ static int amdgpu_device_ip_suspend_phase1(struct amdgpu_device *adev)
|
||||
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
|
||||
if (!adev->ip_blocks[i].status.valid)
|
||||
continue;
|
||||
|
||||
/* displays are handled separately */
|
||||
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE) {
|
||||
/* XXX handle errors */
|
||||
r = adev->ip_blocks[i].version->funcs->suspend(adev);
|
||||
/* XXX handle errors */
|
||||
if (r) {
|
||||
DRM_ERROR("suspend of IP block <%s> failed %d\n",
|
||||
adev->ip_blocks[i].version->funcs->name, r);
|
||||
return r;
|
||||
}
|
||||
adev->ip_blocks[i].status.hw = false;
|
||||
if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_DCE)
|
||||
continue;
|
||||
|
||||
/* XXX handle errors */
|
||||
r = adev->ip_blocks[i].version->funcs->suspend(adev);
|
||||
/* XXX handle errors */
|
||||
if (r) {
|
||||
DRM_ERROR("suspend of IP block <%s> failed %d\n",
|
||||
adev->ip_blocks[i].version->funcs->name, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
adev->ip_blocks[i].status.hw = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -2778,6 +2805,10 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
|
||||
case CHIP_NAVI14:
|
||||
case CHIP_NAVI12:
|
||||
case CHIP_RENOIR:
|
||||
#endif
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
|
||||
case CHIP_SIENNA_CICHLID:
|
||||
case CHIP_NAVY_FLOUNDER:
|
||||
#endif
|
||||
return amdgpu_dc != 0;
|
||||
#endif
|
||||
@ -3036,6 +3067,17 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
adev->gfx.gfx_off_req_count = 1;
|
||||
adev->pm.ac_power = power_supply_is_system_supplied() > 0;
|
||||
|
||||
atomic_set(&adev->throttling_logging_enabled, 1);
|
||||
/*
|
||||
* If throttling continues, logging will be performed every minute
|
||||
* to avoid log flooding. "-1" is subtracted since the thermal
|
||||
* throttling interrupt comes every second. Thus, the total logging
|
||||
* interval is 59 seconds(retelimited printk interval) + 1(waiting
|
||||
* for throttling interrupt) = 60 seconds.
|
||||
*/
|
||||
ratelimit_state_init(&adev->throttling_logging_rs, (60 - 1) * HZ, 1);
|
||||
ratelimit_set_flags(&adev->throttling_logging_rs, RATELIMIT_MSG_ON_RELEASE);
|
||||
|
||||
/* Registers mapping */
|
||||
/* TODO: block userspace mapping of io register */
|
||||
if (adev->asic_type >= CHIP_BONAIRE) {
|
||||
@ -3274,6 +3316,9 @@ fence_driver_init:
|
||||
queue_delayed_work(system_wq, &adev->delayed_init_work,
|
||||
msecs_to_jiffies(AMDGPU_RESUME_MS));
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
flush_delayed_work(&adev->delayed_init_work);
|
||||
|
||||
r = sysfs_create_files(&adev->dev->kobj, amdgpu_dev_attributes);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "Could not create amdgpu device attr\n");
|
||||
@ -3330,10 +3375,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
|
||||
amdgpu_pm_sysfs_fini(adev);
|
||||
amdgpu_fbdev_fini(adev);
|
||||
r = amdgpu_device_ip_fini(adev);
|
||||
if (adev->firmware.gpu_info_fw) {
|
||||
release_firmware(adev->firmware.gpu_info_fw);
|
||||
adev->firmware.gpu_info_fw = NULL;
|
||||
}
|
||||
release_firmware(adev->firmware.gpu_info_fw);
|
||||
adev->firmware.gpu_info_fw = NULL;
|
||||
adev->accel_working = false;
|
||||
/* free i2c buses */
|
||||
if (!amdgpu_device_has_dc_support(adev))
|
||||
@ -3365,7 +3408,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
|
||||
sysfs_remove_files(&adev->dev->kobj, amdgpu_dev_attributes);
|
||||
if (IS_ENABLED(CONFIG_PERF_EVENTS))
|
||||
amdgpu_pmu_fini(adev);
|
||||
if (amdgpu_discovery && adev->asic_type >= CHIP_NAVI10)
|
||||
if (adev->discovery_bin)
|
||||
amdgpu_discovery_fini(adev);
|
||||
}
|
||||
|
||||
@ -3377,7 +3420,6 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
|
||||
* amdgpu_device_suspend - initiate device suspend
|
||||
*
|
||||
* @dev: drm dev pointer
|
||||
* @suspend: suspend state
|
||||
* @fbcon : notify the fbdev of suspend
|
||||
*
|
||||
* Puts the hw in the suspend state (all asics).
|
||||
@ -3474,7 +3516,6 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
|
||||
* amdgpu_device_resume - initiate device resume
|
||||
*
|
||||
* @dev: drm dev pointer
|
||||
* @resume: resume state
|
||||
* @fbcon : notify the fbdev of resume
|
||||
*
|
||||
* Bring the hw back to operating state (all asics).
|
||||
@ -3905,6 +3946,7 @@ bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev)
|
||||
case CHIP_NAVI10:
|
||||
case CHIP_NAVI14:
|
||||
case CHIP_NAVI12:
|
||||
case CHIP_SIENNA_CICHLID:
|
||||
break;
|
||||
default:
|
||||
goto disabled;
|
||||
@ -4210,18 +4252,19 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
struct amdgpu_hive_info *hive = NULL;
|
||||
struct amdgpu_device *tmp_adev = NULL;
|
||||
int i, r = 0;
|
||||
bool in_ras_intr = amdgpu_ras_intr_triggered();
|
||||
bool use_baco =
|
||||
(amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) ?
|
||||
true : false;
|
||||
bool need_emergency_restart = false;
|
||||
bool audio_suspended = false;
|
||||
|
||||
/**
|
||||
* Special case: RAS triggered and full reset isn't supported
|
||||
*/
|
||||
need_emergency_restart = amdgpu_ras_need_emergency_restart(adev);
|
||||
|
||||
/*
|
||||
* Flush RAM to disk so that after reboot
|
||||
* the user can read log and see why the system rebooted.
|
||||
*/
|
||||
if (in_ras_intr && !use_baco && amdgpu_ras_get_context(adev)->reboot) {
|
||||
|
||||
if (need_emergency_restart && amdgpu_ras_get_context(adev)->reboot) {
|
||||
DRM_WARN("Emergency reboot.");
|
||||
|
||||
ksys_sync_helper();
|
||||
@ -4229,7 +4272,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
dev_info(adev->dev, "GPU %s begin!\n",
|
||||
(in_ras_intr && !use_baco) ? "jobs stop":"reset");
|
||||
need_emergency_restart ? "jobs stop":"reset");
|
||||
|
||||
/*
|
||||
* Here we trylock to avoid chain of resets executing from
|
||||
@ -4301,7 +4344,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
amdgpu_fbdev_set_suspend(tmp_adev, 1);
|
||||
|
||||
/* disable ras on ALL IPs */
|
||||
if (!(in_ras_intr && !use_baco) &&
|
||||
if (!need_emergency_restart &&
|
||||
amdgpu_device_ip_need_full_reset(tmp_adev))
|
||||
amdgpu_ras_suspend(tmp_adev);
|
||||
|
||||
@ -4313,12 +4356,12 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
|
||||
drm_sched_stop(&ring->sched, job ? &job->base : NULL);
|
||||
|
||||
if (in_ras_intr && !use_baco)
|
||||
if (need_emergency_restart)
|
||||
amdgpu_job_stop_all_jobs_on_sched(&ring->sched);
|
||||
}
|
||||
}
|
||||
|
||||
if (in_ras_intr && !use_baco)
|
||||
if (need_emergency_restart)
|
||||
goto skip_sched_resume;
|
||||
|
||||
/*
|
||||
@ -4395,7 +4438,7 @@ skip_hw_reset:
|
||||
skip_sched_resume:
|
||||
list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
|
||||
/*unlock kfd: SRIOV would do it separately */
|
||||
if (!(in_ras_intr && !use_baco) && !amdgpu_sriov_vf(tmp_adev))
|
||||
if (!need_emergency_restart && !amdgpu_sriov_vf(tmp_adev))
|
||||
amdgpu_amdkfd_post_reset(tmp_adev);
|
||||
if (audio_suspended)
|
||||
amdgpu_device_resume_display_audio(tmp_adev);
|
||||
|
@ -32,7 +32,7 @@
|
||||
#define mmMM_DATA 0x1
|
||||
#define HW_ID_MAX 300
|
||||
|
||||
const char *hw_id_names[HW_ID_MAX] = {
|
||||
static const char *hw_id_names[HW_ID_MAX] = {
|
||||
[MP1_HWID] = "MP1",
|
||||
[MP2_HWID] = "MP2",
|
||||
[THM_HWID] = "THM",
|
||||
@ -133,7 +133,7 @@ static int hw_id_map[MAX_HWIP] = {
|
||||
static int amdgpu_discovery_read_binary(struct amdgpu_device *adev, uint8_t *binary)
|
||||
{
|
||||
uint64_t vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;
|
||||
uint64_t pos = vram_size - adev->discovery_tmr_size;
|
||||
uint64_t pos = vram_size - DISCOVERY_TMR_OFFSET;
|
||||
|
||||
amdgpu_device_vram_access(adev, pos, (uint32_t *)binary,
|
||||
adev->discovery_tmr_size, false);
|
||||
|
@ -24,7 +24,8 @@
|
||||
#ifndef __AMDGPU_DISCOVERY__
|
||||
#define __AMDGPU_DISCOVERY__
|
||||
|
||||
#define DISCOVERY_TMR_SIZE (64 << 10)
|
||||
#define DISCOVERY_TMR_SIZE (4 << 10)
|
||||
#define DISCOVERY_TMR_OFFSET (64 << 10)
|
||||
|
||||
void amdgpu_discovery_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev);
|
||||
|
@ -282,7 +282,7 @@ int amdgpu_display_crtc_set_config(struct drm_mode_set *set,
|
||||
|
||||
ret = pm_runtime_get_sync(dev->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
ret = drm_crtc_helper_set_config(set, ctx);
|
||||
|
||||
@ -297,7 +297,7 @@ int amdgpu_display_crtc_set_config(struct drm_mode_set *set,
|
||||
take the current one */
|
||||
if (active && !adev->have_disp_power_ref) {
|
||||
adev->have_disp_power_ref = true;
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
/* if we have no active crtcs, then drop the power ref
|
||||
we got before */
|
||||
@ -306,6 +306,7 @@ int amdgpu_display_crtc_set_config(struct drm_mode_set *set,
|
||||
adev->have_disp_power_ref = false;
|
||||
}
|
||||
|
||||
out:
|
||||
/* drop the power reference we got coming in here */
|
||||
pm_runtime_put_autosuspend(dev->dev);
|
||||
return ret;
|
||||
@ -576,14 +577,14 @@ amdgpu_display_user_framebuffer_create(struct drm_device *dev,
|
||||
|
||||
amdgpu_fb = kzalloc(sizeof(*amdgpu_fb), GFP_KERNEL);
|
||||
if (amdgpu_fb == NULL) {
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
ret = amdgpu_display_framebuffer_init(dev, amdgpu_fb, mode_cmd, obj);
|
||||
if (ret) {
|
||||
kfree(amdgpu_fb);
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
|
@ -307,8 +307,8 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
|
||||
if (IS_ERR(sgt))
|
||||
return sgt;
|
||||
|
||||
if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
|
||||
DMA_ATTR_SKIP_CPU_SYNC))
|
||||
if (dma_map_sgtable(attach->dev, sgt, dir,
|
||||
DMA_ATTR_SKIP_CPU_SYNC))
|
||||
goto error_free;
|
||||
break;
|
||||
|
||||
@ -349,7 +349,7 @@ static void amdgpu_dma_buf_unmap(struct dma_buf_attachment *attach,
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
|
||||
if (sgt->sgl->page_link) {
|
||||
dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);
|
||||
dma_unmap_sgtable(attach->dev, sgt, dir, 0);
|
||||
sg_free_table(sgt);
|
||||
kfree(sgt);
|
||||
} else {
|
||||
|
@ -53,6 +53,7 @@ struct amdgpu_doorbell_index {
|
||||
uint32_t gfx_ring0;
|
||||
uint32_t gfx_ring1;
|
||||
uint32_t sdma_engine[8];
|
||||
uint32_t mes_ring;
|
||||
uint32_t ih;
|
||||
union {
|
||||
struct {
|
||||
@ -177,9 +178,12 @@ typedef enum _AMDGPU_NAVI10_DOORBELL_ASSIGNMENT
|
||||
AMDGPU_NAVI10_DOORBELL_USERQUEUE_END = 0x08A,
|
||||
AMDGPU_NAVI10_DOORBELL_GFX_RING0 = 0x08B,
|
||||
AMDGPU_NAVI10_DOORBELL_GFX_RING1 = 0x08C,
|
||||
AMDGPU_NAVI10_DOORBELL_MES_RING = 0x090,
|
||||
/* SDMA:256~335*/
|
||||
AMDGPU_NAVI10_DOORBELL_sDMA_ENGINE0 = 0x100,
|
||||
AMDGPU_NAVI10_DOORBELL_sDMA_ENGINE1 = 0x10A,
|
||||
AMDGPU_NAVI10_DOORBELL_sDMA_ENGINE2 = 0x114,
|
||||
AMDGPU_NAVI10_DOORBELL_sDMA_ENGINE3 = 0x11E,
|
||||
/* IH: 376~391 */
|
||||
AMDGPU_NAVI10_DOORBELL_IH = 0x178,
|
||||
/* MMSCH: 392~407
|
||||
@ -191,8 +195,13 @@ typedef enum _AMDGPU_NAVI10_DOORBELL_ASSIGNMENT
|
||||
AMDGPU_NAVI10_DOORBELL64_VCN4_5 = 0x18A,
|
||||
AMDGPU_NAVI10_DOORBELL64_VCN6_7 = 0x18B,
|
||||
|
||||
AMDGPU_NAVI10_DOORBELL64_VCN8_9 = 0x18C,
|
||||
AMDGPU_NAVI10_DOORBELL64_VCNa_b = 0x18D,
|
||||
AMDGPU_NAVI10_DOORBELL64_VCNc_d = 0x18E,
|
||||
AMDGPU_NAVI10_DOORBELL64_VCNe_f = 0x18F,
|
||||
|
||||
AMDGPU_NAVI10_DOORBELL64_FIRST_NON_CP = AMDGPU_NAVI10_DOORBELL_sDMA_ENGINE0,
|
||||
AMDGPU_NAVI10_DOORBELL64_LAST_NON_CP = AMDGPU_NAVI10_DOORBELL64_VCN6_7,
|
||||
AMDGPU_NAVI10_DOORBELL64_LAST_NON_CP = AMDGPU_NAVI10_DOORBELL64_VCNe_f,
|
||||
|
||||
AMDGPU_NAVI10_DOORBELL_MAX_ASSIGNMENT = 0x18F,
|
||||
AMDGPU_NAVI10_DOORBELL_INVALID = 0xFFFF
|
||||
|
@ -911,8 +911,7 @@ int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low)
|
||||
if (is_support_sw_smu(adev)) {
|
||||
ret = smu_get_dpm_freq_range(&adev->smu, SMU_GFXCLK,
|
||||
low ? &clk_freq : NULL,
|
||||
!low ? &clk_freq : NULL,
|
||||
true);
|
||||
!low ? &clk_freq : NULL);
|
||||
if (ret)
|
||||
return 0;
|
||||
return clk_freq * 100;
|
||||
@ -929,8 +928,7 @@ int amdgpu_dpm_get_mclk(struct amdgpu_device *adev, bool low)
|
||||
if (is_support_sw_smu(adev)) {
|
||||
ret = smu_get_dpm_freq_range(&adev->smu, SMU_UCLK,
|
||||
low ? &clk_freq : NULL,
|
||||
!low ? &clk_freq : NULL,
|
||||
true);
|
||||
!low ? &clk_freq : NULL);
|
||||
if (ret)
|
||||
return 0;
|
||||
return clk_freq * 100;
|
||||
@ -1141,6 +1139,26 @@ int amdgpu_dpm_baco_reset(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev)
|
||||
{
|
||||
struct smu_context *smu = &adev->smu;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
return smu_mode1_reset_is_support(smu);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
struct smu_context *smu = &adev->smu;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
return smu_mode1_reset(smu);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev,
|
||||
enum PP_SMC_POWER_PROFILE type,
|
||||
bool en)
|
||||
@ -1162,7 +1180,7 @@ int amdgpu_dpm_set_xgmi_pstate(struct amdgpu_device *adev,
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (is_support_sw_smu_xgmi(adev))
|
||||
if (is_support_sw_smu(adev))
|
||||
ret = smu_set_xgmi_pstate(&adev->smu, pstate);
|
||||
else if (adev->powerplay.pp_funcs &&
|
||||
adev->powerplay.pp_funcs->set_xgmi_pstate)
|
||||
@ -1197,4 +1215,4 @@ int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en)
|
||||
return smu_allow_xgmi_power_down(smu, en);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -425,6 +425,7 @@ struct amdgpu_pm {
|
||||
u32 default_sclk;
|
||||
u32 default_mclk;
|
||||
struct amdgpu_i2c_chan *i2c_bus;
|
||||
bool bus_locked;
|
||||
/* internal thermal controller on rv6xx+ */
|
||||
enum amdgpu_int_thermal_type int_thermal_type;
|
||||
struct device *int_hwmon_dev;
|
||||
@ -529,6 +530,9 @@ int amdgpu_dpm_mode2_reset(struct amdgpu_device *adev);
|
||||
|
||||
bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev);
|
||||
|
||||
bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev);
|
||||
int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev);
|
||||
|
||||
int amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev,
|
||||
enum pp_mp1_state mp1_state);
|
||||
|
||||
|
@ -87,9 +87,10 @@
|
||||
* - 3.36.0 - Allow reading more status registers on si/cik
|
||||
* - 3.37.0 - L2 is invalidated before SDMA IBs, needed for correctness
|
||||
* - 3.38.0 - Add AMDGPU_IB_FLAG_EMIT_MEM_SYNC
|
||||
* - 3.39.0 - DMABUF implicit sync does a full pipeline sync
|
||||
*/
|
||||
#define KMS_DRIVER_MAJOR 3
|
||||
#define KMS_DRIVER_MINOR 38
|
||||
#define KMS_DRIVER_MINOR 39
|
||||
#define KMS_DRIVER_PATCHLEVEL 0
|
||||
|
||||
int amdgpu_vram_limit = 0;
|
||||
@ -148,6 +149,7 @@ int amdgpu_mes = 0;
|
||||
int amdgpu_noretry;
|
||||
int amdgpu_force_asic_type = -1;
|
||||
int amdgpu_tmz = 0;
|
||||
int amdgpu_reset_method = -1; /* auto */
|
||||
|
||||
struct amdgpu_mgpu_info mgpu_info = {
|
||||
.mutex = __MUTEX_INITIALIZER(mgpu_info.mutex),
|
||||
@ -705,6 +707,14 @@ MODULE_PARM_DESC(hws_gws_support, "Assume MEC2 FW supports GWS barriers (false =
|
||||
int queue_preemption_timeout_ms = 9000;
|
||||
module_param(queue_preemption_timeout_ms, int, 0644);
|
||||
MODULE_PARM_DESC(queue_preemption_timeout_ms, "queue preemption timeout in ms (1 = Minimum, 9000 = default)");
|
||||
|
||||
/**
|
||||
* DOC: debug_evictions(bool)
|
||||
* Enable extra debug messages to help determine the cause of evictions
|
||||
*/
|
||||
bool debug_evictions;
|
||||
module_param(debug_evictions, bool, 0644);
|
||||
MODULE_PARM_DESC(debug_evictions, "enable eviction debug messages (false = default)");
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -748,6 +758,13 @@ module_param_named(abmlevel, amdgpu_dm_abm_level, uint, 0444);
|
||||
MODULE_PARM_DESC(tmz, "Enable TMZ feature (-1 = auto, 0 = off (default), 1 = on)");
|
||||
module_param_named(tmz, amdgpu_tmz, int, 0444);
|
||||
|
||||
/**
|
||||
* DOC: reset_method (int)
|
||||
* GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco)
|
||||
*/
|
||||
MODULE_PARM_DESC(reset_method, "GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco)");
|
||||
module_param_named(reset_method, amdgpu_reset_method, int, 0444);
|
||||
|
||||
static const struct pci_device_id pciidlist[] = {
|
||||
#ifdef CONFIG_DRM_AMDGPU_SI
|
||||
{0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
|
||||
@ -1111,7 +1128,9 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
|
||||
|
||||
pci_set_drvdata(pdev, dev);
|
||||
|
||||
amdgpu_driver_load_kms(dev, ent->driver_data);
|
||||
ret = amdgpu_driver_load_kms(dev, ent->driver_data);
|
||||
if (ret)
|
||||
goto err_pci;
|
||||
|
||||
retry_init:
|
||||
ret = drm_dev_register(dev, ent->driver_data);
|
||||
@ -1167,7 +1186,8 @@ amdgpu_pci_shutdown(struct pci_dev *pdev)
|
||||
* unfortunately we can't detect certain
|
||||
* hypervisors so just do this all the time.
|
||||
*/
|
||||
adev->mp1_state = PP_MP1_STATE_UNLOAD;
|
||||
if (!amdgpu_passthrough(adev))
|
||||
adev->mp1_state = PP_MP1_STATE_UNLOAD;
|
||||
amdgpu_device_ip_suspend(adev);
|
||||
adev->mp1_state = PP_MP1_STATE_NONE;
|
||||
}
|
||||
@ -1373,11 +1393,12 @@ long amdgpu_drm_ioctl(struct file *filp,
|
||||
dev = file_priv->minor->dev;
|
||||
ret = pm_runtime_get_sync(dev->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
ret = drm_ioctl(filp, cmd, arg);
|
||||
|
||||
pm_runtime_mark_last_busy(dev->dev);
|
||||
out:
|
||||
pm_runtime_put_autosuspend(dev->dev);
|
||||
return ret;
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ static void amdgpufb_destroy_pinned_object(struct drm_gem_object *gobj)
|
||||
amdgpu_bo_unpin(abo);
|
||||
amdgpu_bo_unreserve(abo);
|
||||
}
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
}
|
||||
|
||||
static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev,
|
||||
@ -278,7 +278,7 @@ out:
|
||||
|
||||
}
|
||||
if (fb && ret) {
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
drm_framebuffer_unregister_private(fb);
|
||||
drm_framebuffer_cleanup(fb);
|
||||
kfree(fb);
|
||||
|
@ -416,15 +416,16 @@ int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
|
||||
ring->fence_drv.gpu_addr = adev->uvd.inst[ring->me].gpu_addr + index;
|
||||
}
|
||||
amdgpu_fence_write(ring, atomic_read(&ring->fence_drv.last_seq));
|
||||
amdgpu_irq_get(adev, irq_src, irq_type);
|
||||
|
||||
if (irq_src)
|
||||
amdgpu_irq_get(adev, irq_src, irq_type);
|
||||
|
||||
ring->fence_drv.irq_src = irq_src;
|
||||
ring->fence_drv.irq_type = irq_type;
|
||||
ring->fence_drv.initialized = true;
|
||||
|
||||
DRM_DEV_DEBUG(adev->dev, "fence driver on ring %s use gpu addr "
|
||||
"0x%016llx, cpu addr 0x%p\n", ring->name,
|
||||
ring->fence_drv.gpu_addr, ring->fence_drv.cpu_addr);
|
||||
DRM_DEV_DEBUG(adev->dev, "fence driver on ring %s use gpu addr 0x%016llx\n",
|
||||
ring->name, ring->fence_drv.gpu_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -448,8 +449,7 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
|
||||
if (!adev)
|
||||
return -EINVAL;
|
||||
|
||||
/* Check that num_hw_submission is a power of two */
|
||||
if ((num_hw_submission & (num_hw_submission - 1)) != 0)
|
||||
if (!is_power_of_2(num_hw_submission))
|
||||
return -EINVAL;
|
||||
|
||||
ring->fence_drv.cpu_addr = NULL;
|
||||
@ -467,8 +467,8 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
|
||||
if (!ring->fence_drv.fences)
|
||||
return -ENOMEM;
|
||||
|
||||
/* No need to setup the GPU scheduler for KIQ ring */
|
||||
if (ring->funcs->type != AMDGPU_RING_TYPE_KIQ) {
|
||||
/* No need to setup the GPU scheduler for rings that don't need it */
|
||||
if (!ring->no_scheduler) {
|
||||
switch (ring->funcs->type) {
|
||||
case AMDGPU_RING_TYPE_GFX:
|
||||
timeout = adev->gfx_timeout;
|
||||
@ -537,9 +537,11 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev)
|
||||
/* no need to trigger GPU reset as we are unloading */
|
||||
amdgpu_fence_driver_force_completion(ring);
|
||||
}
|
||||
amdgpu_irq_put(adev, ring->fence_drv.irq_src,
|
||||
ring->fence_drv.irq_type);
|
||||
drm_sched_fini(&ring->sched);
|
||||
if (ring->fence_drv.irq_src)
|
||||
amdgpu_irq_put(adev, ring->fence_drv.irq_src,
|
||||
ring->fence_drv.irq_type);
|
||||
if (!ring->no_scheduler)
|
||||
drm_sched_fini(&ring->sched);
|
||||
del_timer_sync(&ring->fence_drv.fallback_timer);
|
||||
for (j = 0; j <= ring->fence_drv.num_fences_mask; ++j)
|
||||
dma_fence_put(ring->fence_drv.fences[j]);
|
||||
@ -574,8 +576,9 @@ void amdgpu_fence_driver_suspend(struct amdgpu_device *adev)
|
||||
}
|
||||
|
||||
/* disable the interrupt */
|
||||
amdgpu_irq_put(adev, ring->fence_drv.irq_src,
|
||||
ring->fence_drv.irq_type);
|
||||
if (ring->fence_drv.irq_src)
|
||||
amdgpu_irq_put(adev, ring->fence_drv.irq_src,
|
||||
ring->fence_drv.irq_type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -601,8 +604,9 @@ void amdgpu_fence_driver_resume(struct amdgpu_device *adev)
|
||||
continue;
|
||||
|
||||
/* enable the interrupt */
|
||||
amdgpu_irq_get(adev, ring->fence_drv.irq_src,
|
||||
ring->fence_drv.irq_type);
|
||||
if (ring->fence_drv.irq_src)
|
||||
amdgpu_irq_get(adev, ring->fence_drv.irq_src,
|
||||
ring->fence_drv.irq_type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -749,8 +753,10 @@ static int amdgpu_debugfs_gpu_recover(struct seq_file *m, void *data)
|
||||
int r;
|
||||
|
||||
r = pm_runtime_get_sync(dev->dev);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
pm_runtime_put_autosuspend(dev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
seq_printf(m, "gpu recover\n");
|
||||
amdgpu_device_gpu_recover(adev, NULL);
|
||||
@ -775,8 +781,10 @@ int amdgpu_debugfs_fence_init(struct amdgpu_device *adev)
|
||||
{
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_fence_list_sriov, 1);
|
||||
return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_fence_list, 2);
|
||||
return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_fence_list_sriov,
|
||||
ARRAY_SIZE(amdgpu_debugfs_fence_list_sriov));
|
||||
return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_fence_list,
|
||||
ARRAY_SIZE(amdgpu_debugfs_fence_list));
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
@ -26,12 +26,13 @@
|
||||
#include "amdgpu_i2c.h"
|
||||
#include "smu_v11_0_i2c.h"
|
||||
#include "atom.h"
|
||||
#include "amdgpu_fru_eeprom.h"
|
||||
|
||||
#define I2C_PRODUCT_INFO_ADDR 0xAC
|
||||
#define I2C_PRODUCT_INFO_ADDR_SIZE 0x2
|
||||
#define I2C_PRODUCT_INFO_OFFSET 0xC0
|
||||
|
||||
bool is_fru_eeprom_supported(struct amdgpu_device *adev)
|
||||
static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
|
||||
{
|
||||
/* TODO: Gaming SKUs don't have the FRU EEPROM.
|
||||
* Use this hack to address hangs on modprobe on gaming SKUs
|
||||
@ -47,7 +48,7 @@ bool is_fru_eeprom_supported(struct amdgpu_device *adev)
|
||||
return false;
|
||||
}
|
||||
|
||||
int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
|
||||
static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
|
||||
unsigned char *buff)
|
||||
{
|
||||
int ret, size;
|
||||
|
@ -21,8 +21,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __AMDGPU_PRODINFO_H__
|
||||
#define __AMDGPU_PRODINFO_H__
|
||||
#ifndef __AMDGPU_FRU_EEPROM_H__
|
||||
#define __AMDGPU_FRU_EEPROM_H__
|
||||
|
||||
int amdgpu_fru_get_product_info(struct amdgpu_device *adev);
|
||||
|
||||
|
@ -106,7 +106,7 @@ void amdgpu_gem_force_release(struct amdgpu_device *adev)
|
||||
spin_lock(&file->table_lock);
|
||||
idr_for_each_entry(&file->object_idr, gobj, handle) {
|
||||
WARN_ONCE(1, "And also active allocations!\n");
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
}
|
||||
idr_destroy(&file->object_idr);
|
||||
spin_unlock(&file->table_lock);
|
||||
@ -285,7 +285,7 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
|
||||
|
||||
r = drm_gem_handle_create(filp, gobj, &handle);
|
||||
/* drop reference from allocate - handle holds it now */
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@ -369,7 +369,7 @@ user_pages_done:
|
||||
amdgpu_ttm_tt_get_user_pages_done(bo->tbo.ttm);
|
||||
|
||||
release_object:
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -388,11 +388,11 @@ int amdgpu_mode_dumb_mmap(struct drm_file *filp,
|
||||
robj = gem_to_amdgpu_bo(gobj);
|
||||
if (amdgpu_ttm_tt_get_usermm(robj->tbo.ttm) ||
|
||||
(robj->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) {
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
return -EPERM;
|
||||
}
|
||||
*offset_p = amdgpu_bo_mmap_offset(robj);
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -462,7 +462,7 @@ int amdgpu_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
|
||||
} else
|
||||
r = ret;
|
||||
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -505,7 +505,7 @@ int amdgpu_gem_metadata_ioctl(struct drm_device *dev, void *data,
|
||||
unreserve:
|
||||
amdgpu_bo_unreserve(robj);
|
||||
out:
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -704,7 +704,7 @@ error_backoff:
|
||||
ttm_eu_backoff_reservation(&ticket, &list);
|
||||
|
||||
error_unref:
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -780,7 +780,7 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
|
||||
}
|
||||
|
||||
out:
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -817,7 +817,7 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
|
||||
|
||||
r = drm_gem_handle_create(file_priv, gobj, &handle);
|
||||
/* drop reference from allocate - handle holds it now */
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
@ -930,7 +930,8 @@ static const struct drm_info_list amdgpu_debugfs_gem_list[] = {
|
||||
int amdgpu_debugfs_gem_init(struct amdgpu_device *adev)
|
||||
{
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_gem_list, 1);
|
||||
return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_gem_list,
|
||||
ARRAY_SIZE(amdgpu_debugfs_gem_list));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -578,6 +578,20 @@ void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable)
|
||||
mutex_unlock(&adev->gfx.gfx_off_mutex);
|
||||
}
|
||||
|
||||
int amdgpu_get_gfx_off_status(struct amdgpu_device *adev, uint32_t *value)
|
||||
{
|
||||
|
||||
int r = 0;
|
||||
|
||||
mutex_lock(&adev->gfx.gfx_off_mutex);
|
||||
|
||||
r = smu_get_status_gfxoff(adev, value);
|
||||
|
||||
mutex_unlock(&adev->gfx.gfx_off_mutex);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
|
@ -134,6 +134,7 @@ struct gb_addr_config {
|
||||
uint8_t num_banks;
|
||||
uint8_t num_se;
|
||||
uint8_t num_rb_per_se;
|
||||
uint8_t num_pkrs;
|
||||
};
|
||||
|
||||
struct amdgpu_gfx_config {
|
||||
@ -377,6 +378,7 @@ void amdgpu_gfx_bit_to_me_queue(struct amdgpu_device *adev, int bit,
|
||||
bool amdgpu_gfx_is_me_queue_enabled(struct amdgpu_device *adev, int me,
|
||||
int pipe, int queue);
|
||||
void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable);
|
||||
int amdgpu_get_gfx_off_status(struct amdgpu_device *adev, uint32_t *value);
|
||||
int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev);
|
||||
void amdgpu_gfx_ras_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_gfx_process_ras_data_cb(struct amdgpu_device *adev,
|
||||
|
@ -357,6 +357,9 @@ int amdgpu_gmc_allocate_vm_inv_eng(struct amdgpu_device *adev)
|
||||
ring = adev->rings[i];
|
||||
vmhub = ring->funcs->vmhub;
|
||||
|
||||
if (ring == &adev->mes.ring)
|
||||
continue;
|
||||
|
||||
inv_eng = ffs(vm_inv_engs[vmhub]);
|
||||
if (!inv_eng) {
|
||||
dev_err(adev->dev, "no VM inv eng for ring %s\n",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user