aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt65
-rw-r--r--Documentation/devicetree/bindings/drm/msm/hdmi.txt3
-rw-r--r--Documentation/devicetree/bindings/drm/msm/mdp.txt3
-rw-r--r--Documentation/devicetree/bindings/video/renesas,du.txt14
-rw-r--r--MAINTAINERS1
-rw-r--r--drivers/gpu/drm/Kconfig2
-rw-r--r--drivers/gpu/drm/Makefile1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_display.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c50
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c29
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c43
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c35
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik_sdma.c19
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cz_dpm.c21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cz_smc.c60
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v10_0.c15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v11_0.c36
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v8_0.c15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c20
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c412
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c19
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c47
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v2_0.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vce_v3_0.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vi.c36
-rw-r--r--drivers/gpu/drm/amd/include/amd_shared.h1
-rw-r--r--drivers/gpu/drm/amd/include/atombios.h2
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h18
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c99
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c46
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c38
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h172
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c45
-rw-r--r--drivers/gpu/drm/i915/intel_acpi.c1
-rw-r--r--drivers/gpu/drm/i915/intel_atomic.c1
-rw-r--r--drivers/gpu/drm/i915/intel_audio.c12
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c25
-rw-r--r--drivers/gpu/drm/i915/intel_display.c182
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c10
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h9
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c26
-rw-r--r--drivers/gpu/drm/i915/intel_i2c.c54
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c30
-rw-r--r--drivers/gpu/drm/i915/intel_opregion.c83
-rw-r--r--drivers/gpu/drm/i915/intel_panel.c2
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c479
-rw-r--r--drivers/gpu/drm/i915/intel_psr.c18
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c44
-rw-r--r--drivers/gpu/drm/i915/intel_sprite.c18
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c16
-rw-r--r--drivers/gpu/drm/msm/Kconfig14
-rw-r--r--drivers/gpu/drm/msm/Makefile2
-rw-r--r--drivers/gpu/drm/msm/adreno/a2xx.xml.h9
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx.xml.h27
-rw-r--r--drivers/gpu/drm/msm/adreno/a4xx.xml.h15
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_common.xml.h13
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h9
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.xml.h238
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c2
-rw-r--r--drivers/gpu/drm/msm/dsi/mmss_cc.xml.h8
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.c2
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c6
-rw-r--r--drivers/gpu/drm/msm/dsi/sfpb.xml.h21
-rw-r--r--drivers/gpu/drm/msm/edp/edp.xml.h8
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c17
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.xml.h8
-rw-r--r--drivers/gpu/drm/msm/hdmi/qfprom.xml.h8
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h8
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h86
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c95
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h11
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c46
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c201
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c8
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_common.xml.h15
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_kms.h6
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c8
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c8
-rw-r--r--drivers/gpu/drm/radeon/cayman_blit_shaders.c2
-rw-r--r--drivers/gpu/drm/radeon/evergreen_blit_shaders.c2
-rw-r--r--drivers/gpu/drm/radeon/r600_blit_shaders.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c10
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.c27
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_group.c5
-rw-r--r--drivers/gpu/drm/vc4/Kconfig13
-rw-r--r--drivers/gpu/drm/vc4/Makefile17
-rw-r--r--drivers/gpu/drm/vc4/vc4_bo.c52
-rw-r--r--drivers/gpu/drm/vc4/vc4_crtc.c672
-rw-r--r--drivers/gpu/drm/vc4/vc4_debugfs.c39
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.c298
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.h145
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c590
-rw-r--r--drivers/gpu/drm/vc4/vc4_hvs.c163
-rw-r--r--drivers/gpu/drm/vc4/vc4_kms.c67
-rw-r--r--drivers/gpu/drm/vc4/vc4_plane.c320
-rw-r--r--drivers/gpu/drm/vc4/vc4_regs.h570
-rw-r--r--include/uapi/drm/amdgpu_drm.h2
111 files changed, 5150 insertions, 1217 deletions
diff --git a/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt b/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt
new file mode 100644
index 000000000000..56a961aa5061
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt
@@ -0,0 +1,65 @@
+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"
+
+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
+
+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";
+};
+
+vc4: gpu {
+ compatible = "brcm,bcm2835-vc4";
+};
diff --git a/Documentation/devicetree/bindings/drm/msm/hdmi.txt b/Documentation/devicetree/bindings/drm/msm/hdmi.txt
index e926239e1101..379ee2ea9a3d 100644
--- a/Documentation/devicetree/bindings/drm/msm/hdmi.txt
+++ b/Documentation/devicetree/bindings/drm/msm/hdmi.txt
@@ -2,6 +2,7 @@ Qualcomm adreno/snapdragon hdmi output
Required properties:
- compatible: one of the following
+ * "qcom,hdmi-tx-8996"
* "qcom,hdmi-tx-8994"
* "qcom,hdmi-tx-8084"
* "qcom,hdmi-tx-8974"
@@ -21,6 +22,7 @@ Required properties:
Optional properties:
- qcom,hdmi-tx-mux-en-gpio: hdmi mux enable pin
- qcom,hdmi-tx-mux-sel-gpio: hdmi mux select pin
+- power-domains: reference to the power domain(s), if available.
- pinctrl-names: the pin control state names; should contain "default"
- pinctrl-0: the default pinctrl state (active)
- pinctrl-1: the "sleep" pinctrl state
@@ -35,6 +37,7 @@ Example:
reg-names = "core_physical";
reg = <0x04a00000 0x1000>;
interrupts = <GIC_SPI 79 0>;
+ power-domains = <&mmcc MDSS_GDSC>;
clock-names =
"core_clk",
"master_iface_clk",
diff --git a/Documentation/devicetree/bindings/drm/msm/mdp.txt b/Documentation/devicetree/bindings/drm/msm/mdp.txt
index 1a0598e5279d..0833edaba4c3 100644
--- a/Documentation/devicetree/bindings/drm/msm/mdp.txt
+++ b/Documentation/devicetree/bindings/drm/msm/mdp.txt
@@ -11,13 +11,14 @@ Required properties:
- clock-names: the following clocks are required:
* "core_clk"
* "iface_clk"
- * "lut_clk"
* "src_clk"
* "hdmi_clk"
* "mpd_clk"
Optional properties:
- gpus: phandle for gpu device
+- clock-names: the following clocks are optional:
+ * "lut_clk"
Example:
diff --git a/Documentation/devicetree/bindings/video/renesas,du.txt b/Documentation/devicetree/bindings/video/renesas,du.txt
index c902323928f7..eccd4f4867b2 100644
--- a/Documentation/devicetree/bindings/video/renesas,du.txt
+++ b/Documentation/devicetree/bindings/video/renesas,du.txt
@@ -5,7 +5,9 @@ Required Properties:
- compatible: must be one of the following.
- "renesas,du-r8a7779" for R8A7779 (R-Car H1) compatible DU
- "renesas,du-r8a7790" for R8A7790 (R-Car H2) compatible DU
- - "renesas,du-r8a7791" for R8A7791 (R-Car M2) compatible DU
+ - "renesas,du-r8a7791" for R8A7791 (R-Car M2-W) compatible DU
+ - "renesas,du-r8a7793" for R8A7793 (R-Car M2-N) compatible DU
+ - "renesas,du-r8a7794" for R8A7794 (R-Car E2) compatible DU
- reg: A list of base address and length of each memory resource, one for
each entry in the reg-names property.
@@ -22,9 +24,9 @@ Required Properties:
- clock-names: Name of the clocks. This property is model-dependent.
- R8A7779 uses a single functional clock. The clock doesn't need to be
named.
- - R8A7790 and R8A7791 use one functional clock per channel and one clock
- per LVDS encoder. The functional clocks must be named "du.x" with "x"
- being the channel numerical index. The LVDS clocks must be named
+ - R8A779[0134] use one functional clock per channel and one clock per LVDS
+ encoder (if available). The functional clocks must be named "du.x" with
+ "x" being the channel numerical index. The LVDS clocks must be named
"lvds.x" with "x" being the LVDS encoder numerical index.
- In addition to the functional and encoder clocks, all DU versions also
support externally supplied pixel clocks. Those clocks are optional.
@@ -43,7 +45,9 @@ corresponding to each DU output.
-----------------------------------------------------------------------------
R8A7779 (H1) DPAD 0 DPAD 1 -
R8A7790 (H2) DPAD LVDS 0 LVDS 1
- R8A7791 (M2) DPAD LVDS 0 -
+ R8A7791 (M2-W) DPAD LVDS 0 -
+ R8A7793 (M2-N) DPAD LVDS 0 -
+ R8A7794 (E2) DPAD 0 DPAD 1 -
Example: R8A7790 (R-Car H2) DU
diff --git a/MAINTAINERS b/MAINTAINERS
index 5f467845ef72..95c6bcb6bf22 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3584,6 +3584,7 @@ M: Daniel Vetter <[email protected]>
M: Jani Nikula <[email protected]>
+W: https://01.org/linuxgraphics/
Q: http://patchwork.freedesktop.org/project/intel-gfx/
T: git git://anongit.freedesktop.org/drm-intel
S: Supported
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 1a0a8df2eed8..c4bf9a1cf4a6 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -264,3 +264,5 @@ source "drivers/gpu/drm/sti/Kconfig"
source "drivers/gpu/drm/amd/amdkfd/Kconfig"
source "drivers/gpu/drm/imx/Kconfig"
+
+source "drivers/gpu/drm/vc4/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index e814517513ce..1e9ff4c3e3db 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_DRM_MGA) += mga/
obj-$(CONFIG_DRM_I810) += i810/
obj-$(CONFIG_DRM_I915) += i915/
obj-$(CONFIG_DRM_MGAG200) += mgag200/
+obj-$(CONFIG_DRM_VC4) += vc4/
obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus/
obj-$(CONFIG_DRM_SIS) += sis/
obj-$(CONFIG_DRM_SAVAGE)+= savage/
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 3fa1397fd7ae..5c400f4b87fd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -345,7 +345,6 @@ struct amdgpu_ring_funcs {
/* testing functions */
int (*test_ring)(struct amdgpu_ring *ring);
int (*test_ib)(struct amdgpu_ring *ring);
- bool (*is_lockup)(struct amdgpu_ring *ring);
/* insert NOP packets */
void (*insert_nop)(struct amdgpu_ring *ring, uint32_t count);
};
@@ -448,8 +447,7 @@ int amdgpu_fence_wait_next(struct amdgpu_ring *ring);
int amdgpu_fence_wait_empty(struct amdgpu_ring *ring);
unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring);
-signed long amdgpu_fence_wait_any(struct amdgpu_device *adev,
- struct fence **array,
+signed long amdgpu_fence_wait_any(struct fence **array,
uint32_t count,
bool intr,
signed long t);
@@ -907,8 +905,6 @@ struct amdgpu_ring {
unsigned ring_size;
unsigned ring_free_dw;
int count_dw;
- atomic_t last_rptr;
- atomic64_t last_activity;
uint64_t gpu_addr;
uint32_t align_mask;
uint32_t ptr_mask;
@@ -1230,8 +1226,6 @@ void amdgpu_ring_commit(struct amdgpu_ring *ring);
void amdgpu_ring_unlock_commit(struct amdgpu_ring *ring);
void amdgpu_ring_undo(struct amdgpu_ring *ring);
void amdgpu_ring_unlock_undo(struct amdgpu_ring *ring);
-void amdgpu_ring_lockup_update(struct amdgpu_ring *ring);
-bool amdgpu_ring_test_lockup(struct amdgpu_ring *ring);
unsigned amdgpu_ring_backup(struct amdgpu_ring *ring,
uint32_t **data);
int amdgpu_ring_restore(struct amdgpu_ring *ring,
@@ -1960,7 +1954,6 @@ struct amdgpu_device {
struct device *dev;
struct drm_device *ddev;
struct pci_dev *pdev;
- struct rw_semaphore exclusive_lock;
/* ASIC */
enum amd_asic_type asic_type;
@@ -1974,7 +1967,6 @@ struct amdgpu_device {
bool suspend;
bool need_dma32;
bool accel_working;
- bool needs_reset;
struct work_struct reset_work;
struct notifier_block acpi_nb;
struct amdgpu_i2c_chan *i2c_bus[AMDGPU_MAX_I2C_BUS];
@@ -2253,7 +2245,6 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
#define amdgpu_ring_parse_cs(r, p, ib) ((r)->funcs->parse_cs((p), (ib)))
#define amdgpu_ring_test_ring(r) (r)->funcs->test_ring((r))
#define amdgpu_ring_test_ib(r) (r)->funcs->test_ib((r))
-#define amdgpu_ring_is_lockup(r) (r)->funcs->is_lockup((r))
#define amdgpu_ring_get_rptr(r) (r)->funcs->get_rptr((r))
#define amdgpu_ring_get_wptr(r) (r)->funcs->get_wptr((r))
#define amdgpu_ring_set_wptr(r) (r)->funcs->set_wptr((r))
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index baf00617fe90..27ef52847e6d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -609,7 +609,6 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev,
}
}
- mutex_lock(&vm->mutex);
r = amdgpu_bo_vm_update_pte(parser, vm);
if (r) {
goto out;
@@ -620,7 +619,6 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev,
parser->filp);
out:
- mutex_unlock(&vm->mutex);
return r;
}
@@ -828,15 +826,14 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
{
struct amdgpu_device *adev = dev->dev_private;
union drm_amdgpu_cs *cs = data;
+ struct amdgpu_fpriv *fpriv = filp->driver_priv;
+ struct amdgpu_vm *vm = &fpriv->vm;
struct amdgpu_cs_parser *parser;
bool reserved_buffers = false;
int i, r;
- down_read(&adev->exclusive_lock);
- if (!adev->accel_working) {
- up_read(&adev->exclusive_lock);
+ if (!adev->accel_working)
return -EBUSY;
- }
parser = amdgpu_cs_parser_create(adev, filp, NULL, NULL, 0);
if (!parser)
@@ -844,12 +841,11 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
r = amdgpu_cs_parser_init(parser, data);
if (r) {
DRM_ERROR("Failed to initialize parser !\n");
- kfree(parser);
- up_read(&adev->exclusive_lock);
+ amdgpu_cs_parser_fini(parser, r, false);
r = amdgpu_cs_handle_lockup(adev, r);
return r;
}
-
+ mutex_lock(&vm->mutex);
r = amdgpu_cs_parser_relocs(parser);
if (r == -ENOMEM)
DRM_ERROR("Not enough memory for command submission!\n");
@@ -916,14 +912,14 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
mutex_unlock(&job->job_lock);
amdgpu_cs_parser_fini_late(parser);
- up_read(&adev->exclusive_lock);
+ mutex_unlock(&vm->mutex);
return 0;
}
cs->out.handle = parser->ibs[parser->num_ibs - 1].sequence;
out:
amdgpu_cs_parser_fini(parser, r, reserved_buffers);
- up_read(&adev->exclusive_lock);
+ mutex_unlock(&vm->mutex);
r = amdgpu_cs_handle_lockup(adev, r);
return r;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 901a460b2c55..d5b421330145 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -57,6 +57,7 @@ static const char *amdgpu_asic_name[] = {
"TONGA",
"FIJI",
"CARRIZO",
+ "STONEY",
"LAST",
};
@@ -1165,7 +1166,8 @@ static int amdgpu_early_init(struct amdgpu_device *adev)
case CHIP_TONGA:
case CHIP_FIJI:
case CHIP_CARRIZO:
- if (adev->asic_type == 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;
@@ -1418,7 +1420,6 @@ int amdgpu_device_init(struct amdgpu_device *adev,
mutex_init(&adev->gfx.gpu_clock_mutex);
mutex_init(&adev->srbm_mutex);
mutex_init(&adev->grbm_idx_mutex);
- init_rwsem(&adev->exclusive_lock);
mutex_init(&adev->mn_lock);
hash_init(adev->mn_hash);
@@ -1814,14 +1815,6 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)
int i, r;
int resched;
- down_write(&adev->exclusive_lock);
-
- if (!adev->needs_reset) {
- up_write(&adev->exclusive_lock);
- return 0;
- }
-
- adev->needs_reset = false;
atomic_inc(&adev->gpu_reset_counter);
/* block TTM */
@@ -1885,7 +1878,6 @@ retry:
dev_info(adev->dev, "GPU reset failed\n");
}
- up_write(&adev->exclusive_lock);
return r;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index de116398fa49..d747fca59669 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -47,11 +47,8 @@ static void amdgpu_flip_wait_fence(struct amdgpu_device *adev,
fence = to_amdgpu_fence(*f);
if (fence) {
r = fence_wait(&fence->base, false);
- if (r == -EDEADLK) {
- up_read(&adev->exclusive_lock);
+ if (r == -EDEADLK)
r = amdgpu_gpu_reset(adev);
- down_read(&adev->exclusive_lock);
- }
} else
r = fence_wait(*f, false);
@@ -77,7 +74,6 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
unsigned long flags;
unsigned i;
- down_read(&adev->exclusive_lock);
amdgpu_flip_wait_fence(adev, &work->excl);
for (i = 0; i < work->shared_count; ++i)
amdgpu_flip_wait_fence(adev, &work->shared[i]);
@@ -93,7 +89,6 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
amdgpuCrtc->pflip_status = AMDGPU_FLIP_SUBMITTED;
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
- up_read(&adev->exclusive_lock);
}
/*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index ef58774b242c..0508c5cd103a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -73,7 +73,7 @@ int amdgpu_hard_reset = 0;
unsigned amdgpu_ip_block_mask = 0xffffffff;
int amdgpu_bapm = -1;
int amdgpu_deep_color = 0;
-int amdgpu_vm_size = 8;
+int amdgpu_vm_size = 64;
int amdgpu_vm_block_size = -1;
int amdgpu_vm_fault_stop = 0;
int amdgpu_vm_debug = 0;
@@ -137,7 +137,7 @@ module_param_named(bapm, amdgpu_bapm, int, 0444);
MODULE_PARM_DESC(deep_color, "Deep Color support (1 = enable, 0 = disable (default))");
module_param_named(deep_color, amdgpu_deep_color, int, 0444);
-MODULE_PARM_DESC(vm_size, "VM address space size in gigabytes (default 8GB)");
+MODULE_PARM_DESC(vm_size, "VM address space size in gigabytes (default 64GB)");
module_param_named(vm_size, amdgpu_vm_size, int, 0444);
MODULE_PARM_DESC(vm_block_size, "VM page table size in bits (default depending on vm_size)");
@@ -273,6 +273,8 @@ static struct pci_device_id pciidlist[] = {
{0x1002, 0x9875, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU},
{0x1002, 0x9876, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU},
{0x1002, 0x9877, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU},
+ /* stoney */
+ {0x1002, 0x98E4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_STONEY|AMD_IS_APU},
{0, 0, 0}
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
index fcad7e060938..003a219943f1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -260,27 +260,8 @@ static void amdgpu_fence_check_lockup(struct work_struct *work)
lockup_work.work);
ring = fence_drv->ring;
- if (!down_read_trylock(&ring->adev->exclusive_lock)) {
- /* just reschedule the check if a reset is going on */
- amdgpu_fence_schedule_check(ring);
- return;
- }
-
- if (amdgpu_fence_activity(ring)) {
- wake_up_all(&ring->fence_drv.fence_queue);
- }
- else if (amdgpu_ring_is_lockup(ring)) {
- /* good news we believe it's a lockup */
- dev_warn(ring->adev->dev, "GPU lockup (current fence id "
- "0x%016llx last fence id 0x%016llx on ring %d)\n",
- (uint64_t)atomic64_read(&fence_drv->last_seq),
- fence_drv->sync_seq[ring->idx], ring->idx);
-
- /* remember that we need an reset */
- ring->adev->needs_reset = true;
+ if (amdgpu_fence_activity(ring))
wake_up_all(&ring->fence_drv.fence_queue);
- }
- up_read(&ring->adev->exclusive_lock);
}
/**
@@ -328,18 +309,15 @@ static bool amdgpu_fence_is_signaled(struct fence *f)
{
struct amdgpu_fence *fence = to_amdgpu_fence(f);
struct amdgpu_ring *ring = fence->ring;
- struct amdgpu_device *adev = ring->adev;
if (atomic64_read(&ring->fence_drv.last_seq) >= fence->seq)
return true;
- if (down_read_trylock(&adev->exclusive_lock)) {
- amdgpu_fence_process(ring);
- up_read(&adev->exclusive_lock);
+ amdgpu_fence_process(ring);
+
+ if (atomic64_read(&ring->fence_drv.last_seq) >= fence->seq)
+ return true;
- if (atomic64_read(&ring->fence_drv.last_seq) >= fence->seq)
- return true;
- }
return false;
}
@@ -380,7 +358,6 @@ static bool amdgpu_fence_enable_signaling(struct fence *f)
*/
static int amdgpu_fence_ring_wait_seq(struct amdgpu_ring *ring, uint64_t seq)
{
- struct amdgpu_device *adev = ring->adev;
bool signaled = false;
BUG_ON(!ring);
@@ -391,8 +368,7 @@ static int amdgpu_fence_ring_wait_seq(struct amdgpu_ring *ring, uint64_t seq)
return 0;
wait_event(ring->fence_drv.fence_queue, (
- (signaled = amdgpu_fence_seq_signaled(ring, seq))
- || adev->needs_reset));
+ (signaled = amdgpu_fence_seq_signaled(ring, seq))));
if (signaled)
return 0;
@@ -881,16 +857,12 @@ static void amdgpu_fence_wait_cb(struct fence *fence, struct fence_cb *cb)
static signed long amdgpu_fence_default_wait(struct fence *f, bool intr,
signed long t)
{
- struct amdgpu_fence *fence = to_amdgpu_fence(f);
- struct amdgpu_device *adev = fence->ring->adev;
-
- return amdgpu_fence_wait_any(adev, &f, 1, intr, t);
+ return amdgpu_fence_wait_any(&f, 1, intr, t);
}
/**
* Wait the fence array with timeout
*
- * @adev: amdgpu device
* @array: the fence array with amdgpu fence pointer
* @count: the number of the fence array
* @intr: when sleep, set the current task interruptable or not
@@ -898,8 +870,7 @@ static signed long amdgpu_fence_default_wait(struct fence *f, bool intr,
*
* It will return when any fence is signaled or timeout.
*/
-signed long amdgpu_fence_wait_any(struct amdgpu_device *adev,
- struct fence **array, uint32_t count,
+signed long amdgpu_fence_wait_any(struct fence **array, uint32_t count,
bool intr, signed long t)
{
struct amdgpu_wait_cb *cb;
@@ -939,11 +910,6 @@ signed long amdgpu_fence_wait_any(struct amdgpu_device *adev,
if (amdgpu_test_signaled_any(array, count))
break;
- if (adev->needs_reset) {
- t = -EDEADLK;
- break;
- }
-
t = schedule_timeout(t);
if (t > 0 && intr && signal_pending(current))
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index 7297ca3a0ba7..087332858853 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -115,9 +115,10 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_pri
struct amdgpu_vm *vm = &fpriv->vm;
struct amdgpu_bo_va *bo_va;
int r;
-
+ mutex_lock(&vm->mutex);
r = amdgpu_bo_reserve(rbo, false);
if (r) {
+ mutex_unlock(&vm->mutex);
return r;
}
@@ -128,7 +129,7 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_pri
++bo_va->ref_count;
}
amdgpu_bo_unreserve(rbo);
-
+ mutex_unlock(&vm->mutex);
return 0;
}
@@ -141,9 +142,10 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj,
struct amdgpu_vm *vm = &fpriv->vm;
struct amdgpu_bo_va *bo_va;
int r;
-
+ mutex_lock(&vm->mutex);
r = amdgpu_bo_reserve(rbo, true);
if (r) {
+ mutex_unlock(&vm->mutex);
dev_err(adev->dev, "leaking bo va because "
"we fail to reserve bo (%d)\n", r);
return;
@@ -155,6 +157,7 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj,
}
}
amdgpu_bo_unreserve(rbo);
+ mutex_unlock(&vm->mutex);
}
static int amdgpu_gem_handle_lockup(struct amdgpu_device *adev, int r)
@@ -181,7 +184,6 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
bool kernel = false;
int r;
- down_read(&adev->exclusive_lock);
/* create a gem object to contain this object in */
if (args->in.domains & (AMDGPU_GEM_DOMAIN_GDS |
AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA)) {
@@ -214,11 +216,9 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
memset(args, 0, sizeof(*args));
args->out.handle = handle;
- up_read(&adev->exclusive_lock);
return 0;
error_unlock:
- up_read(&adev->exclusive_lock);
r = amdgpu_gem_handle_lockup(adev, r);
return r;
}
@@ -250,8 +250,6 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data,
return -EACCES;
}
- down_read(&adev->exclusive_lock);
-
/* create a gem object to contain this object in */
r = amdgpu_gem_object_create(adev, args->size, 0,
AMDGPU_GEM_DOMAIN_CPU, 0,
@@ -293,14 +291,12 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data,
goto handle_lockup;
args->handle = handle;
- up_read(&adev->exclusive_lock);
return 0;
release_object:
drm_gem_object_unreference_unlocked(gobj);
handle_lockup:
- up_read(&adev->exclusive_lock);
r = amdgpu_gem_handle_lockup(adev, r);
return r;
@@ -488,18 +484,13 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
goto error_unreserve;
}
- mutex_lock(&bo_va->vm->mutex);
r = amdgpu_vm_clear_freed(adev, bo_va->vm);
if (r)
- goto error_unlock;
-
+ goto error_unreserve;
if (operation == AMDGPU_VA_OP_MAP)
r = amdgpu_vm_bo_update(adev, bo_va, &bo_va->bo->tbo.mem);
-error_unlock:
- mutex_unlock(&bo_va->vm->mutex);
-
error_unreserve:
ttm_eu_backoff_reservation(&ticket, &list);
@@ -556,10 +547,11 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
gobj = drm_gem_object_lookup(dev, filp, args->handle);
if (gobj == NULL)
return -ENOENT;
-
+ mutex_lock(&fpriv->vm.mutex);
rbo = gem_to_amdgpu_bo(gobj);
r = amdgpu_bo_reserve(rbo, false);
if (r) {
+ mutex_unlock(&fpriv->vm.mutex);
drm_gem_object_unreference_unlocked(gobj);
return r;
}
@@ -567,6 +559,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
bo_va = amdgpu_vm_bo_find(&fpriv->vm, rbo);
if (!bo_va) {
amdgpu_bo_unreserve(rbo);
+ mutex_unlock(&fpriv->vm.mutex);
return -ENOENT;
}
@@ -591,7 +584,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE))
amdgpu_gem_va_update_vm(adev, bo_va, args->operation);
-
+ mutex_unlock(&fpriv->vm.mutex);
drm_gem_object_unreference_unlocked(gobj);
return r;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index c439735ee670..aad4c1c69448 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -298,7 +298,6 @@ int amdgpu_ib_ring_tests(struct amdgpu_device *adev)
r = amdgpu_ring_test_ib(ring);
if (r) {
ring->ready = false;
- adev->needs_reset = false;
if (ring == &adev->gfx.gfx_ring[0]) {
/* oh, oh, that's really bad */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
index b13a74b273a6..b2df348aa223 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
@@ -67,8 +67,6 @@ void amdgpu_ring_free_size(struct amdgpu_ring *ring)
if (!ring->ring_free_dw) {
/* this is an empty ring */
ring->ring_free_dw = ring->ring_size / 4;
- /* update lockup info to avoid false positive */
- amdgpu_ring_lockup_update(ring);
}
}
@@ -209,46 +207,6 @@ void amdgpu_ring_unlock_undo(struct amdgpu_ring *ring)
}
/**
- * amdgpu_ring_lockup_update - update lockup variables
- *
- * @ring: amdgpu_ring structure holding ring information
- *
- * Update the last rptr value and timestamp (all asics).
- */
-void amdgpu_ring_lockup_update(struct amdgpu_ring *ring)
-{
- atomic_set(&ring->last_rptr, amdgpu_ring_get_rptr(ring));
- atomic64_set(&ring->last_activity, jiffies_64);
-}
-
-/**
- * amdgpu_ring_test_lockup() - check if ring is lockedup by recording information
- * @ring: amdgpu_ring structure holding ring information
- *
- */
-bool amdgpu_ring_test_lockup(struct amdgpu_ring *ring)
-{
- uint32_t rptr = amdgpu_ring_get_rptr(ring);
- uint64_t last = atomic64_read(&ring->last_activity);
- uint64_t elapsed;
-
- if (rptr != atomic_read(&ring->last_rptr)) {
- /* ring is still working, no lockup */
- amdgpu_ring_lockup_update(ring);
- return false;
- }
-
- elapsed = jiffies_to_msecs(jiffies_64 - last);
- if (amdgpu_lockup_timeout && elapsed >= amdgpu_lockup_timeout) {
- dev_err(ring->adev->dev, "ring %d stalled for more than %llumsec\n",
- ring->idx, elapsed);
- return true;
- }
- /* give a chance to the GPU ... */
- return false;
-}
-
-/**
* amdgpu_ring_backup - Back up the content of a ring
*
* @ring: the ring we want to back up
@@ -436,7 +394,6 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
if (amdgpu_debugfs_ring_init(adev, ring)) {
DRM_ERROR("Failed to register debugfs file for rings !\n");
}
- amdgpu_ring_lockup_update(ring);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
index e90712443fe9..5cb27d525e43 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
@@ -372,7 +372,7 @@ int amdgpu_sa_bo_new(struct amdgpu_device *adev,
} while (amdgpu_sa_bo_next_hole(sa_manager, fences, tries));
spin_unlock(&sa_manager->wq.lock);
- t = amdgpu_fence_wait_any(adev, fences, AMDGPU_MAX_RINGS,
+ t = amdgpu_fence_wait_any(fences, AMDGPU_MAX_RINGS,
false, MAX_SCHEDULE_TIMEOUT);
r = (t > 0) ? 0 : t;
spin_lock(&sa_manager->wq.lock);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index d0312364d950..53f987aeeacf 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -53,6 +53,7 @@
#define FIRMWARE_TONGA "amdgpu/tonga_uvd.bin"
#define FIRMWARE_CARRIZO "amdgpu/carrizo_uvd.bin"
#define FIRMWARE_FIJI "amdgpu/fiji_uvd.bin"
+#define FIRMWARE_STONEY "amdgpu/stoney_uvd.bin"
/**
* amdgpu_uvd_cs_ctx - Command submission parser context
@@ -83,6 +84,7 @@ MODULE_FIRMWARE(FIRMWARE_MULLINS);
MODULE_FIRMWARE(FIRMWARE_TONGA);
MODULE_FIRMWARE(FIRMWARE_CARRIZO);
MODULE_FIRMWARE(FIRMWARE_FIJI);
+MODULE_FIRMWARE(FIRMWARE_STONEY);
static void amdgpu_uvd_note_usage(struct amdgpu_device *adev);
static void amdgpu_uvd_idle_work_handler(struct work_struct *work);
@@ -124,6 +126,9 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
case CHIP_CARRIZO:
fw_name = FIRMWARE_CARRIZO;
break;
+ case CHIP_STONEY:
+ fw_name = FIRMWARE_STONEY;
+ break;
default:
return -EINVAL;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index 74f2038ac747..03f0c3bae516 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -49,6 +49,7 @@
#define FIRMWARE_TONGA "amdgpu/tonga_vce.bin"
#define FIRMWARE_CARRIZO "amdgpu/carrizo_vce.bin"
#define FIRMWARE_FIJI "amdgpu/fiji_vce.bin"
+#define FIRMWARE_STONEY "amdgpu/stoney_vce.bin"
#ifdef CONFIG_DRM_AMDGPU_CIK
MODULE_FIRMWARE(FIRMWARE_BONAIRE);
@@ -60,6 +61,7 @@ MODULE_FIRMWARE(FIRMWARE_MULLINS);
MODULE_FIRMWARE(FIRMWARE_TONGA);
MODULE_FIRMWARE(FIRMWARE_CARRIZO);
MODULE_FIRMWARE(FIRMWARE_FIJI);
+MODULE_FIRMWARE(FIRMWARE_STONEY);
static void amdgpu_vce_idle_work_handler(struct work_struct *work);
@@ -106,6 +108,9 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
case CHIP_FIJI:
fw_name = FIRMWARE_FIJI;
break;
+ case CHIP_STONEY:
+ fw_name = FIRMWARE_STONEY;
+ break;
default:
return -EINVAL;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 644fd9b8591f..ff26e330ccd6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -90,11 +90,9 @@ struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev,
struct amdgpu_bo_list_entry *list;
unsigned i, idx;
- mutex_lock(&vm->mutex);
list = drm_malloc_ab(vm->max_pde_used + 2,
sizeof(struct amdgpu_bo_list_entry));
if (!list) {
- mutex_unlock(&vm->mutex);
return NULL;
}
@@ -119,7 +117,6 @@ struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev,
list[idx].tv.shared = true;
list_add(&list[idx++].tv.head, head);
}
- mutex_unlock(&vm->mutex);
return list;
}
@@ -972,9 +969,7 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
INIT_LIST_HEAD(&bo_va->invalids);
INIT_LIST_HEAD(&bo_va->vm_status);
- mutex_lock(&vm->mutex);
list_add_tail(&bo_va->bo_list, &bo->va);
- mutex_unlock(&vm->mutex);
return bo_va;
}
@@ -1027,8 +1022,6 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
return -EINVAL;
}
- mutex_lock(&vm->mutex);
-
saddr /= AMDGPU_GPU_PAGE_SIZE;
eaddr /= AMDGPU_GPU_PAGE_SIZE;
@@ -1042,14 +1035,14 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
tmp->it.start, tmp->it.last + 1);
amdgpu_bo_unreserve(bo_va->bo);
r = -EINVAL;
- goto error_unlock;
+ goto error;
}
mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
if (!mapping) {
amdgpu_bo_unreserve(bo_va->bo);
r = -ENOMEM;
- goto error_unlock;
+ goto error;
}
INIT_LIST_HEAD(&mapping->list);
@@ -1081,9 +1074,6 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
if (vm->page_tables[pt_idx].bo)
continue;
- /* drop mutex to allocate and clear page table */
- mutex_unlock(&vm->mutex);
-
ww_mutex_lock(&resv->lock, NULL);
r = amdgpu_bo_create(adev, AMDGPU_VM_PTE_COUNT * 8,
AMDGPU_GPU_PAGE_SIZE, true,
@@ -1100,32 +1090,19 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
goto error_free;
}
- /* aquire mutex again */
- mutex_lock(&vm->mutex);
- if (vm->page_tables[pt_idx].bo) {
- /* someone else allocated the pt in the meantime */
- mutex_unlock(&vm->mutex);
- amdgpu_bo_unref(&pt);
- mutex_lock(&vm->mutex);
- continue;
- }
-
vm->page_tables[pt_idx].addr = 0;
vm->page_tables[pt_idx].bo = pt;
}
- mutex_unlock(&vm->mutex);
return 0;
error_free:
- mutex_lock(&vm->mutex);
list_del(&mapping->list);
interval_tree_remove(&mapping->it, &vm->va);
trace_amdgpu_vm_bo_unmap(bo_va, mapping);
kfree(mapping);
-error_unlock:
- mutex_unlock(&vm->mutex);
+error:
return r;
}
@@ -1170,7 +1147,6 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
}
}
- mutex_lock(&vm->mutex);
list_del(&mapping->list);
interval_tree_remove(&mapping->it, &vm->va);
trace_amdgpu_vm_bo_unmap(bo_va, mapping);
@@ -1179,7 +1155,6 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
list_add(&mapping->list, &vm->freed);
else
kfree(mapping);
- mutex_unlock(&vm->mutex);
amdgpu_bo_unreserve(bo_va->bo);
return 0;
@@ -1203,8 +1178,6 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
list_del(&bo_va->bo_list);
- mutex_lock(&vm->mutex);
-
spin_lock(&vm->status_lock);
list_del(&bo_va->vm_status);
spin_unlock(&vm->status_lock);
@@ -1223,8 +1196,6 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
fence_put(bo_va->last_pt_update);
kfree(bo_va);
-
- mutex_unlock(&vm->mutex);
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
index 814598e76c98..5f712ceddf08 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
@@ -1290,24 +1290,6 @@ const struct amd_ip_funcs cik_sdma_ip_funcs = {
.set_powergating_state = cik_sdma_set_powergating_state,
};
-/**
- * cik_sdma_ring_is_lockup - Check if the DMA engine is locked up
- *
- * @ring: amdgpu_ring structure holding ring information
- *
- * Check if the async DMA engine is locked up (CIK).
- * Returns true if the engine appears to be locked up, false if not.
- */
-static bool cik_sdma_ring_is_lockup(struct amdgpu_ring *ring)
-{
-
- if (cik_sdma_is_idle(ring->adev)) {
- amdgpu_ring_lockup_update(ring);
- return false;
- }
- return amdgpu_ring_test_lockup(ring);
-}
-
static const struct amdgpu_ring_funcs cik_sdma_ring_funcs = {
.get_rptr = cik_sdma_ring_get_rptr,
.get_wptr = cik_sdma_ring_get_wptr,
@@ -1320,7 +1302,6 @@ static const struct amdgpu_ring_funcs cik_sdma_ring_funcs = {
.emit_hdp_flush = cik_sdma_ring_emit_hdp_flush,
.test_ring = cik_sdma_ring_test_ring,
.test_ib = cik_sdma_ring_test_ib,
- .is_lockup = cik_sdma_ring_is_lockup,
.insert_nop = cik_sdma_ring_insert_nop,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
index 2e3373ed4c94..8035d4d6a4f5 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
@@ -1264,6 +1264,7 @@ static void cz_apply_state_adjust_rules(struct amdgpu_device *adev,
static int cz_dpm_enable(struct amdgpu_device *adev)
{
+ const char *chip_name;
int ret = 0;
/* renable will hang up SMU, so check first */
@@ -1272,21 +1273,33 @@ static int cz_dpm_enable(struct amdgpu_device *adev)
cz_program_voting_clients(adev);
+ switch (adev->asic_type) {
+ case CHIP_CARRIZO:
+ chip_name = "carrizo";
+ break;
+ case CHIP_STONEY:
+ chip_name = "stoney";
+ break;
+ default:
+ BUG();
+ }
+
+
ret = cz_start_dpm(adev);
if (ret) {
- DRM_ERROR("Carrizo DPM enable failed\n");
+ DRM_ERROR("%s DPM enable failed\n", chip_name);
return -EINVAL;
}
ret = cz_program_bootup_state(adev);
if (ret) {
- DRM_ERROR("Carrizo bootup state program failed\n");
+ DRM_ERROR("%s bootup state program failed\n", chip_name);
return -EINVAL;
}
ret = cz_enable_didt(adev, true);
if (ret) {
- DRM_ERROR("Carrizo enable di/dt failed\n");
+ DRM_ERROR("%s enable di/dt failed\n", chip_name);
return -EINVAL;
}
@@ -1353,7 +1366,7 @@ static int cz_dpm_disable(struct amdgpu_device *adev)
ret = cz_enable_didt(adev, false);
if (ret) {
- DRM_ERROR("Carrizo disable di/dt failed\n");
+ DRM_ERROR("disable di/dt failed\n");
return -EINVAL;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_smc.c b/drivers/gpu/drm/amd/amdgpu/cz_smc.c
index e33180d3314a..ac7fee7b7eca 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_smc.c
+++ b/drivers/gpu/drm/amd/amdgpu/cz_smc.c
@@ -312,13 +312,16 @@ int cz_smu_start(struct amdgpu_device *adev)
UCODE_ID_CP_MEC_JT1_MASK |
UCODE_ID_CP_MEC_JT2_MASK;
+ if (adev->asic_type == CHIP_STONEY)
+ fw_to_check &= ~(UCODE_ID_SDMA1_MASK | UCODE_ID_CP_MEC_JT2_MASK);
+
cz_smu_request_load_fw(adev);
ret = cz_smu_check_fw_load_finish(adev, fw_to_check);
if (ret)
return ret;
/* manually load MEC firmware for CZ */
- if (adev->asic_type == CHIP_CARRIZO) {
+ if (adev->asic_type == CHIP_CARRIZO || adev->asic_type == CHIP_STONEY) {
ret = cz_load_mec_firmware(adev);
if (ret) {
dev_err(adev->dev, "(%d) Mec Firmware load failed\n", ret);
@@ -336,6 +339,9 @@ int cz_smu_start(struct amdgpu_device *adev)
AMDGPU_CPMEC2_UCODE_LOADED |
AMDGPU_CPRLC_UCODE_LOADED;
+ if (adev->asic_type == CHIP_STONEY)
+ adev->smu.fw_flags &= ~(AMDGPU_SDMA1_UCODE_LOADED | AMDGPU_CPMEC2_UCODE_LOADED);
+
return ret;
}
@@ -601,8 +607,13 @@ static int cz_smu_construct_toc_for_vddgfx_exit(struct amdgpu_device *adev)
CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false);
cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
- cz_smu_populate_single_ucode_load_task(adev,
+ if (adev->asic_type == CHIP_STONEY) {
+ cz_smu_populate_single_ucode_load_task(adev,
+ CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
+ } else {
+ cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false);
+ }
cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, false);
}
@@ -642,8 +653,13 @@ static int cz_smu_construct_toc_for_bootup(struct amdgpu_device *adev)
if (adev->firmware.smu_load) {
cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0, false);
- cz_smu_populate_single_ucode_load_task(adev,
+ if (adev->asic_type == CHIP_STONEY) {
+ cz_smu_populate_single_ucode_load_task(adev,
+ CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0, false);
+ } else {
+ cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1, false);
+ }
cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, false);
cz_smu_populate_single_ucode_load_task(adev,
@@ -652,8 +668,13 @@ static int cz_smu_construct_toc_for_bootup(struct amdgpu_device *adev)
CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false);
cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
- cz_smu_populate_single_ucode_load_task(adev,
+ if (adev->asic_type == CHIP_STONEY) {
+ cz_smu_populate_single_ucode_load_task(adev,
+ CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
+ } else {
+ cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false);
+ }
cz_smu_populate_single_ucode_load_task(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, true);
}
@@ -888,10 +909,18 @@ int cz_smu_init(struct amdgpu_device *adev)
CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0,
&priv->driver_buffer[priv->driver_buffer_length++]))
goto smu_init_failed;
- if (cz_smu_populate_single_firmware_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1,
- &priv->driver_buffer[priv->driver_buffer_length++]))
- goto smu_init_failed;
+
+ if (adev->asic_type == CHIP_STONEY) {
+ if (cz_smu_populate_single_firmware_entry(adev,
+ CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0,
+ &priv->driver_buffer[priv->driver_buffer_length++]))
+ goto smu_init_failed;
+ } else {
+ if (cz_smu_populate_single_firmware_entry(adev,
+ CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1,
+ &priv->driver_buffer[priv->driver_buffer_length++]))
+ goto smu_init_failed;
+ }
if (cz_smu_populate_single_firmware_entry(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE,
&priv->driver_buffer[priv->driver_buffer_length++]))
@@ -908,10 +937,17 @@ int cz_smu_init(struct amdgpu_device *adev)
CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1,
&priv->driver_buffer[priv->driver_buffer_length++]))
goto smu_init_failed;
- if (cz_smu_populate_single_firmware_entry(adev,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2,
- &priv->driver_buffer[priv->driver_buffer_length++]))
- goto smu_init_failed;
+ if (adev->asic_type == CHIP_STONEY) {
+ if (cz_smu_populate_single_firmware_entry(adev,
+ CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1,
+ &priv->driver_buffer[priv->driver_buffer_length++]))
+ goto smu_init_failed;
+ } else {
+ if (cz_smu_populate_single_firmware_entry(adev,
+ CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2,
+ &priv->driver_buffer[priv->driver_buffer_length++]))
+ goto smu_init_failed;
+ }
if (cz_smu_populate_single_firmware_entry(adev,
CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G,
&priv->driver_buffer[priv->driver_buffer_length++]))
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
index 37073930e2c9..a6ea2d8e85df 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
@@ -3086,22 +3086,18 @@ static int dce_v10_0_suspend(void *handle)
amdgpu_atombios_scratch_regs_save(adev);
- dce_v10_0_hpd_fini(adev);
-
- return 0;
+ return dce_v10_0_hw_fini(handle);
}
static int dce_v10_0_resume(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int ret;
- dce_v10_0_init_golden_registers(adev);
+ ret = dce_v10_0_hw_init(handle);
amdgpu_atombios_scratch_regs_restore(adev);
- /* init dig PHYs, disp eng pll */
- amdgpu_atombios_encoder_init_dig(adev);
- amdgpu_atombios_crtc_set_disp_eng_pll(adev, adev->clock.default_dispclk);
/* turn on the BL */
if (adev->mode_info.bl_encoder) {
u8 bl_level = amdgpu_display_backlight_get_level(adev,
@@ -3110,10 +3106,7 @@ static int dce_v10_0_resume(void *handle)
bl_level);
}
- /* initialize hpd */
- dce_v10_0_hpd_init(adev);
-
- return 0;
+ return ret;
}
static bool dce_v10_0_is_idle(void *handle)
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
index 5be83a3f0192..784afb5978ac 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -126,6 +126,13 @@ static const u32 cz_mgcg_cgcg_init[] =
mmXDMA_MEM_POWER_CNTL, 0x00000101, 0x00000000,
};
+static const u32 stoney_golden_settings_a11[] =
+{
+ mmCRTC_DOUBLE_BUFFER_CONTROL, 0x00010101, 0x00010000,
+ mmFBC_MISC, 0x1f311fff, 0x14302000,
+};
+
+
static void dce_v11_0_init_golden_registers(struct amdgpu_device *adev)
{
switch (adev->asic_type) {
@@ -137,6 +144,11 @@ static void dce_v11_0_init_golden_registers(struct amdgpu_device *adev)
cz_golden_settings_a11,
(const u32)ARRAY_SIZE(cz_golden_settings_a11));
break;
+ case CHIP_STONEY:
+ amdgpu_program_register_sequence(adev,
+ stoney_golden_settings_a11,
+ (const u32)ARRAY_SIZE(stoney_golden_settings_a11));
+ break;
default:
break;
}
@@ -2425,7 +2437,7 @@ static u32 dce_v11_0_pick_pll(struct drm_crtc *crtc)
/* XXX need to determine what plls are available on each DCE11 part */
pll_in_use = amdgpu_pll_get_use_mask(crtc);
- if (adev->asic_type == CHIP_CARRIZO) {
+ if (adev->asic_type == CHIP_CARRIZO || adev->asic_type == CHIP_STONEY) {
if (!(pll_in_use & (1 << ATOM_PPLL1)))
return ATOM_PPLL1;
if (!(pll_in_use & (1 << ATOM_PPLL0)))
@@ -2930,6 +2942,11 @@ static int dce_v11_0_early_init(void *handle)
adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 9;
break;
+ case CHIP_STONEY:
+ adev->mode_info.num_crtc = 2;
+ adev->mode_info.num_hpd = 6;
+ adev->mode_info.num_dig = 9;
+ break;
default:
/* FIXME: not supported yet */
return -EINVAL;
@@ -3028,6 +3045,7 @@ static int dce_v11_0_hw_init(void *handle)
dce_v11_0_init_golden_registers(adev);
/* init dig PHYs, disp eng pll */
+ amdgpu_atombios_crtc_powergate_init(adev);
amdgpu_atombios_encoder_init_dig(adev);
amdgpu_atombios_crtc_set_disp_eng_pll(adev, adev->clock.default_dispclk);
@@ -3061,23 +3079,18 @@ static int dce_v11_0_suspend(void *handle)
amdgpu_atombios_scratch_regs_save(adev);
- dce_v11_0_hpd_fini(adev);
-
- return 0;
+ return dce_v11_0_hw_fini(handle);
}
static int dce_v11_0_resume(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int ret;
- dce_v11_0_init_golden_registers(adev);
+ ret = dce_v11_0_hw_init(handle);
amdgpu_atombios_scratch_regs_restore(adev);
- /* init dig PHYs, disp eng pll */
- amdgpu_atombios_crtc_powergate_init(adev);
- amdgpu_atombios_encoder_init_dig(adev);
- amdgpu_atombios_crtc_set_disp_eng_pll(adev, adev->clock.default_dispclk);
/* turn on the BL */
if (adev->mode_info.bl_encoder) {
u8 bl_level = amdgpu_display_backlight_get_level(adev,
@@ -3086,10 +3099,7 @@ static int dce_v11_0_resume(void *handle)
bl_level);
}
- /* initialize hpd */
- dce_v11_0_hpd_init(adev);
-
- return 0;
+ return ret;
}
static bool dce_v11_0_is_idle(void *handle)
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
index d784fb43efc2..00c34f87ac20 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -2994,20 +2994,18 @@ static int dce_v8_0_suspend(void *handle)
amdgpu_atombios_scratch_regs_save(adev);
- dce_v8_0_hpd_fini(adev);
-
- return 0;
+ return dce_v8_0_hw_fini(handle);
}
static int dce_v8_0_resume(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int ret;
+
+ ret = dce_v8_0_hw_init(handle);
amdgpu_atombios_scratch_regs_restore(adev);
- /* init dig PHYs, disp eng pll */
- amdgpu_atombios_encoder_init_dig(adev);
- amdgpu_atombios_crtc_set_disp_eng_pll(adev, adev->clock.default_dispclk);
/* turn on the BL */
if (adev->mode_info.bl_encoder) {
u8 bl_level = amdgpu_display_backlight_get_level(adev,
@@ -3016,10 +3014,7 @@ static int dce_v8_0_resume(void *handle)
bl_level);
}
- /* initialize hpd */
- dce_v8_0_hpd_init(adev);
-
- return 0;
+ return ret;
}
static bool dce_v8_0_is_idle(void *handle)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
index e992bf2ff66c..72793f93e2fc 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
@@ -5542,24 +5542,6 @@ const struct amd_ip_funcs gfx_v7_0_ip_funcs = {
.set_powergating_state = gfx_v7_0_set_powergating_state,
};
-/**
- * gfx_v7_0_ring_is_lockup - check if the 3D engine is locked up
- *
- * @adev: amdgpu_device pointer
- * @ring: amdgpu_ring structure holding ring information
- *
- * Check if the 3D engine is locked up (CIK).
- * Returns true if the engine is locked, false if not.
- */
-static bool gfx_v7_0_ring_is_lockup(struct amdgpu_ring *ring)
-{
- if (gfx_v7_0_is_idle(ring->adev)) {
- amdgpu_ring_lockup_update(ring);
- return false;
- }
- return amdgpu_ring_test_lockup(ring);
-}
-
static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = {
.get_rptr = gfx_v7_0_ring_get_rptr_gfx,
.get_wptr = gfx_v7_0_ring_get_wptr_gfx,
@@ -5573,7 +5555,6 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = {
.emit_hdp_flush = gfx_v7_0_ring_emit_hdp_flush,
.test_ring = gfx_v7_0_ring_test_ring,
.test_ib = gfx_v7_0_ring_test_ib,
- .is_lockup = gfx_v7_0_ring_is_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
@@ -5590,7 +5571,6 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = {
.emit_hdp_flush = gfx_v7_0_ring_emit_hdp_flush,
.test_ring = gfx_v7_0_ring_test_ring,
.test_ib = gfx_v7_0_ring_test_ib,
- .is_lockup = gfx_v7_0_ring_is_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index 718250ae9856..cbc46a34987c 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -73,6 +73,12 @@ MODULE_FIRMWARE("amdgpu/carrizo_mec.bin");
MODULE_FIRMWARE("amdgpu/carrizo_mec2.bin");
MODULE_FIRMWARE("amdgpu/carrizo_rlc.bin");
+MODULE_FIRMWARE("amdgpu/stoney_ce.bin");
+MODULE_FIRMWARE("amdgpu/stoney_pfp.bin");
+MODULE_FIRMWARE("amdgpu/stoney_me.bin");
+MODULE_FIRMWARE("amdgpu/stoney_mec.bin");
+MODULE_FIRMWARE("amdgpu/stoney_rlc.bin");
+
MODULE_FIRMWARE("amdgpu/tonga_ce.bin");
MODULE_FIRMWARE("amdgpu/tonga_pfp.bin");
MODULE_FIRMWARE("amdgpu/tonga_me.bin");
@@ -493,6 +499,42 @@ static const u32 cz_mgcg_cgcg_init[] =
mmCP_MEM_SLP_CNTL, 0x00000001, 0x00000001,
};
+static const u32 stoney_golden_settings_a11[] =
+{
+ mmDB_DEBUG2, 0xf00fffff, 0x00000400,
+ mmGB_GPU_ID, 0x0000000f, 0x00000000,
+ mmPA_SC_ENHANCE, 0xffffffff, 0x20000001,
+ mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000,
+ mmRLC_CGCG_CGLS_CTRL, 0x00000003, 0x0001003c,
+ mmTA_CNTL_AUX, 0x000f000f, 0x000b0000,
+ mmTCC_CTRL, 0x00100000, 0xf31fff7f,
+ mmTCC_EXE_DISABLE, 0x00000002, 0x00000002,
+ mmTCP_ADDR_CONFIG, 0x0000000f, 0x000000f1,
+ mmTCP_CHAN_STEER_LO, 0xffffffff, 0x10101010,
+};
+
+static const u32 stoney_golden_common_all[] =
+{
+ mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000,
+ mmPA_SC_RASTER_CONFIG, 0xffffffff, 0x00000000,
+ mmPA_SC_RASTER_CONFIG_1, 0xffffffff, 0x00000000,
+ mmGB_ADDR_CONFIG, 0xffffffff, 0x12010001,
+ mmSPI_RESOURCE_RESERVE_CU_0, 0xffffffff, 0x00000800,
+ mmSPI_RESOURCE_RESERVE_CU_1, 0xffffffff, 0x00000800,
+ mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00007FBF,
+ mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00007FAF,
+};
+
+static const u32 stoney_mgcg_cgcg_init[] =
+{
+ mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000,
+ mmRLC_CGCG_CGLS_CTRL, 0xffffffff, 0x0020003f,
+ mmCP_MEM_SLP_CNTL, 0xffffffff, 0x00020201,
+ mmRLC_MEM_SLP_CNTL, 0xffffffff, 0x00020201,
+ mmCGTS_SM_CTRL_REG, 0xffffffff, 0x96940200,
+ mmATC_MISC_CG, 0xffffffff, 0x000c0200,
+};
+
static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev);
static void gfx_v8_0_set_irq_funcs(struct amdgpu_device *adev);
static void gfx_v8_0_set_gds_init(struct amdgpu_device *adev);
@@ -545,6 +587,17 @@ static void gfx_v8_0_init_golden_registers(struct amdgpu_device *adev)
cz_golden_common_all,
(const u32)ARRAY_SIZE(cz_golden_common_all));
break;
+ case CHIP_STONEY:
+ amdgpu_program_register_sequence(adev,
+ stoney_mgcg_cgcg_init,
+ (const u32)ARRAY_SIZE(stoney_mgcg_cgcg_init));
+ amdgpu_program_register_sequence(adev,
+ stoney_golden_settings_a11,
+ (const u32)ARRAY_SIZE(stoney_golden_settings_a11));
+ amdgpu_program_register_sequence(adev,
+ stoney_golden_common_all,
+ (const u32)ARRAY_SIZE(stoney_golden_common_all));
+ break;
default:
break;
}
@@ -691,6 +744,9 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
case CHIP_FIJI:
chip_name = "fiji";
break;
+ case CHIP_STONEY:
+ chip_name = "stoney";
+ break;
default:
BUG();
}
@@ -748,21 +804,23 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
adev->gfx.mec_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
adev->gfx.mec_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);
- err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev);
- if (!err) {
- err = amdgpu_ucode_validate(adev->gfx.mec2_fw);
- if (err)
- goto out;
- cp_hdr = (const struct gfx_firmware_header_v1_0 *)
- adev->gfx.mec2_fw->data;
- adev->gfx.mec2_fw_version = le32_to_cpu(
- cp_hdr->header.ucode_version);
- adev->gfx.mec2_feature_version = le32_to_cpu(
- cp_hdr->ucode_feature_version);
- } else {
- err = 0;
- adev->gfx.mec2_fw = NULL;
+ if (adev->asic_type != CHIP_STONEY) {
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);
+ err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev);
+ if (!err) {
+ err = amdgpu_ucode_validate(adev->gfx.mec2_fw);
+ if (err)
+ goto out;
+ cp_hdr = (const struct gfx_firmware_header_v1_0 *)
+ adev->gfx.mec2_fw->data;
+ adev->gfx.mec2_fw_version =
+ le32_to_cpu(cp_hdr->header.ucode_version);
+ adev->gfx.mec2_feature_version =
+ le32_to_cpu(cp_hdr->ucode_feature_version);
+ } else {
+ err = 0;
+ adev->gfx.mec2_fw = NULL;
+ }
}
if (adev->firmware.smu_load) {
@@ -1010,6 +1068,40 @@ static void gfx_v8_0_gpu_early_init(struct amdgpu_device *adev)
adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
gb_addr_config = CARRIZO_GB_ADDR_CONFIG_GOLDEN;
break;
+ case CHIP_STONEY:
+ adev->gfx.config.max_shader_engines = 1;
+ adev->gfx.config.max_tile_pipes = 2;
+ adev->gfx.config.max_sh_per_se = 1;
+ adev->gfx.config.max_backends_per_se = 1;
+
+ switch (adev->pdev->revision) {
+ case 0xc0:
+ case 0xc1:
+ case 0xc2:
+ case 0xc4:
+ case 0xc8:
+ case 0xc9:
+ adev->gfx.config.max_cu_per_sh = 3;
+ break;
+ case 0xd0:
+ case 0xd1:
+ case 0xd2:
+ default:
+ adev->gfx.config.max_cu_per_sh = 2;
+ break;
+ }
+
+ adev->gfx.config.max_texture_channel_caches = 2;
+ adev->gfx.config.max_gprs = 256;
+ adev->gfx.config.max_gs_threads = 16;
+ adev->gfx.config.max_hw_contexts = 8;
+
+ adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
+ adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
+ adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
+ adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
+ gb_addr_config = CARRIZO_GB_ADDR_CONFIG_GOLDEN;
+ break;
default:
adev->gfx.config.max_shader_engines = 2;
adev->gfx.config.max_tile_pipes = 4;
@@ -1797,6 +1889,273 @@ static void gfx_v8_0_tiling_mode_table_init(struct amdgpu_device *adev)
WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden);
}
break;
+ case CHIP_STONEY:
+ for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
+ switch (reg_offset) {
+ case 0:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 1:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 2:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 3:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 4:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 5:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 6:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+ break;
+ case 8:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
+ PIPE_CONFIG(ADDR_SURF_P2));
+ break;
+ case 9:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 10:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 11:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+ break;
+ case 13:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 14:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 15:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 16:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+ break;
+ case 18:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 19:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 20:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 21:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 22:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 24:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 25:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 26:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+ break;
+ case 27:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 28:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+ break;
+ case 29:
+ gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
+ MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+ SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+ break;
+ case 7:
+ case 12:
+ case 17:
+ case 23:
+ /* unused idx */
+ continue;
+ default:
+ gb_tile_moden = 0;
+ break;
+ };
+ adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden;
+ WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden);
+ }
+ for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) {
+ switch (reg_offset) {
+ case 0:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 1:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 2:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 3:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 4:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 5:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 6:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 8:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+ NUM_BANKS(ADDR_SURF_16_BANK));
+ break;
+ case 9:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+ NUM_BANKS(ADDR_SURF_16_BANK));
+ break;
+ case 10:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+ NUM_BANKS(ADDR_SURF_16_BANK));
+ break;
+ case 11:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+ NUM_BANKS(ADDR_SURF_16_BANK));
+ break;
+ case 12:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+ NUM_BANKS(ADDR_SURF_16_BANK));
+ break;
+ case 13:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+ NUM_BANKS(ADDR_SURF_16_BANK));
+ break;
+ case 14:
+ gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+ BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+ MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+ NUM_BANKS(ADDR_SURF_8_BANK));
+ break;
+ case 7:
+ /* unused idx */
+ continue;
+ default:
+ gb_tile_moden = 0;
+ break;
+ };
+ adev->gfx.config.macrotile_mode_array[reg_offset] = gb_tile_moden;
+ WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden);
+ }
+ break;
case CHIP_CARRIZO:
default:
for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
@@ -2384,7 +2743,7 @@ static void gfx_v8_0_rlc_start(struct amdgpu_device *adev)
WREG32(mmRLC_CNTL, tmp);
/* carrizo do enable cp interrupt after cp inited */
- if (adev->asic_type != CHIP_CARRIZO)
+ if (!(adev->flags & AMD_IS_APU))
gfx_v8_0_enable_gui_idle_interrupt(adev, true);
udelay(50);
@@ -2606,6 +2965,10 @@ static int gfx_v8_0_cp_gfx_start(struct amdgpu_device *adev)
amdgpu_ring_write(ring, 0x00000002);
amdgpu_ring_write(ring, 0x00000000);
break;
+ case CHIP_STONEY:
+ amdgpu_ring_write(ring, 0x00000000);
+ amdgpu_ring_write(ring, 0x00000000);
+ break;
default:
BUG();
}
@@ -3240,7 +3603,8 @@ static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev)
/* enable the doorbell if requested */
if (use_doorbell) {
if ((adev->asic_type == CHIP_CARRIZO) ||
- (adev->asic_type == CHIP_FIJI)) {
+ (adev->asic_type == CHIP_FIJI) ||
+ (adev->asic_type == CHIP_STONEY)) {
WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER,
AMDGPU_DOORBELL_KIQ << 2);
WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER,
@@ -3312,7 +3676,7 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev)
{
int r;
- if (adev->asic_type != CHIP_CARRIZO)
+ if (!(adev->flags & AMD_IS_APU))
gfx_v8_0_enable_gui_idle_interrupt(adev, false);
if (!adev->firmware.smu_load) {
@@ -4075,15 +4439,6 @@ static void gfx_v8_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
}
}
-static bool gfx_v8_0_ring_is_lockup(struct amdgpu_ring *ring)
-{
- if (gfx_v8_0_is_idle(ring->adev)) {
- amdgpu_ring_lockup_update(ring);
- return false;
- }
- return amdgpu_ring_test_lockup(ring);
-}
-
static u32 gfx_v8_0_ring_get_rptr_compute(struct amdgpu_ring *ring)
{
return ring->adev->wb.wb[ring->rptr_offs];
@@ -4114,6 +4469,7 @@ static void gfx_v8_0_ring_emit_fence_compute(struct amdgpu_ring *ring,
amdgpu_ring_write(ring, PACKET3(PACKET3_RELEASE_MEM, 5));
amdgpu_ring_write(ring, (EOP_TCL1_ACTION_EN |
EOP_TC_ACTION_EN |
+ EOP_TC_WB_ACTION_EN |
EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) |
EVENT_INDEX(5)));
amdgpu_ring_write(ring, DATA_SEL(write64bit ? 2 : 1) | INT_SEL(int_sel ? 2 : 0));
@@ -4364,7 +4720,6 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
.emit_hdp_flush = gfx_v8_0_ring_emit_hdp_flush,
.test_ring = gfx_v8_0_ring_test_ring,
.test_ib = gfx_v8_0_ring_test_ib,
- .is_lockup = gfx_v8_0_ring_is_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
@@ -4381,7 +4736,6 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = {
.emit_hdp_flush = gfx_v8_0_ring_emit_hdp_flush,
.test_ring = gfx_v8_0_ring_test_ring,
.test_ib = gfx_v8_0_ring_test_ib,
- .is_lockup = gfx_v8_0_ring_is_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
index 42b5ff827055..72e977b1685d 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
@@ -93,6 +93,12 @@ static const u32 cz_mgcg_cgcg_init[] =
mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104
};
+static const u32 stoney_mgcg_cgcg_init[] =
+{
+ mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104
+};
+
+
static void gmc_v8_0_init_golden_registers(struct amdgpu_device *adev)
{
switch (adev->asic_type) {
@@ -125,6 +131,11 @@ static void gmc_v8_0_init_golden_registers(struct amdgpu_device *adev)
cz_mgcg_cgcg_init,
(const u32)ARRAY_SIZE(cz_mgcg_cgcg_init));
break;
+ case CHIP_STONEY:
+ amdgpu_program_register_sequence(adev,
+ stoney_mgcg_cgcg_init,
+ (const u32)ARRAY_SIZE(stoney_mgcg_cgcg_init));
+ break;
default:
break;
}
@@ -228,6 +239,7 @@ static int gmc_v8_0_init_microcode(struct amdgpu_device *adev)
chip_name = "fiji";
break;
case CHIP_CARRIZO:
+ case CHIP_STONEY:
return 0;
default: BUG();
}
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
index f8b868c7c496..2cf50180cc51 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
@@ -1295,24 +1295,6 @@ const struct amd_ip_funcs sdma_v2_4_ip_funcs = {
.set_powergating_state = sdma_v2_4_set_powergating_state,
};
-/**
- * sdma_v2_4_ring_is_lockup - Check if the DMA engine is locked up
- *
- * @ring: amdgpu_ring structure holding ring information
- *
- * Check if the async DMA engine is locked up (VI).
- * Returns true if the engine appears to be locked up, false if not.
- */
-static bool sdma_v2_4_ring_is_lockup(struct amdgpu_ring *ring)
-{
-
- if (sdma_v2_4_is_idle(ring->adev)) {
- amdgpu_ring_lockup_update(ring);
- return false;
- }
- return amdgpu_ring_test_lockup(ring);
-}
-
static const struct amdgpu_ring_funcs sdma_v2_4_ring_funcs = {
.get_rptr = sdma_v2_4_ring_get_rptr,
.get_wptr = sdma_v2_4_ring_get_wptr,
@@ -1325,7 +1307,6 @@ static const struct amdgpu_ring_funcs sdma_v2_4_ring_funcs = {
.emit_hdp_flush = sdma_v2_4_ring_emit_hdp_flush,
.test_ring = sdma_v2_4_ring_test_ring,
.test_ib = sdma_v2_4_ring_test_ib,
- .is_lockup = sdma_v2_4_ring_is_lockup,
.insert_nop = sdma_v2_4_ring_insert_nop,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
index 670555a45da9..7253132f04b8 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -55,6 +55,7 @@ MODULE_FIRMWARE("amdgpu/carrizo_sdma.bin");
MODULE_FIRMWARE("amdgpu/carrizo_sdma1.bin");
MODULE_FIRMWARE("amdgpu/fiji_sdma.bin");
MODULE_FIRMWARE("amdgpu/fiji_sdma1.bin");
+MODULE_FIRMWARE("amdgpu/stoney_sdma.bin");
static const u32 sdma_offsets[SDMA_MAX_INSTANCE] =
{
@@ -122,6 +123,19 @@ static const u32 cz_mgcg_cgcg_init[] =
mmSDMA1_CLK_CTRL, 0xff000ff0, 0x00000100
};
+static const u32 stoney_golden_settings_a11[] =
+{
+ mmSDMA0_GFX_IB_CNTL, 0x00000100, 0x00000100,
+ mmSDMA0_POWER_CNTL, 0x00000800, 0x0003c800,
+ mmSDMA0_RLC0_IB_CNTL, 0x00000100, 0x00000100,
+ mmSDMA0_RLC1_IB_CNTL, 0x00000100, 0x00000100,
+};
+
+static const u32 stoney_mgcg_cgcg_init[] =
+{
+ mmSDMA0_CLK_CTRL, 0xffffffff, 0x00000100,
+};
+
/*
* sDMA - System DMA
* Starting with CIK, the GPU has new asynchronous
@@ -166,6 +180,14 @@ static void sdma_v3_0_init_golden_registers(struct amdgpu_device *adev)
cz_golden_settings_a11,
(const u32)ARRAY_SIZE(cz_golden_settings_a11));
break;
+ case CHIP_STONEY:
+ amdgpu_program_register_sequence(adev,
+ stoney_mgcg_cgcg_init,
+ (const u32)ARRAY_SIZE(stoney_mgcg_cgcg_init));
+ amdgpu_program_register_sequence(adev,
+ stoney_golden_settings_a11,
+ (const u32)ARRAY_SIZE(stoney_golden_settings_a11));
+ break;
default:
break;
}
@@ -201,6 +223,9 @@ static int sdma_v3_0_init_microcode(struct amdgpu_device *adev)
case CHIP_CARRIZO:
chip_name = "carrizo";
break;
+ case CHIP_STONEY:
+ chip_name = "stoney";
+ break;
default: BUG();
}
@@ -1071,6 +1096,9 @@ static int sdma_v3_0_early_init(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
switch (adev->asic_type) {
+ case CHIP_STONEY:
+ adev->sdma.num_instances = 1;
+ break;
default:
adev->sdma.num_instances = SDMA_MAX_INSTANCE;
break;
@@ -1428,24 +1456,6 @@ const struct amd_ip_funcs sdma_v3_0_ip_funcs = {
.set_powergating_state = sdma_v3_0_set_powergating_state,
};
-/**
- * sdma_v3_0_ring_is_lockup - Check if the DMA engine is locked up
- *
- * @ring: amdgpu_ring structure holding ring information
- *
- * Check if the async DMA engine is locked up (VI).
- * Returns true if the engine appears to be locked up, false if not.
- */
-static bool sdma_v3_0_ring_is_lockup(struct amdgpu_ring *ring)
-{
-
- if (sdma_v3_0_is_idle(ring->adev)) {
- amdgpu_ring_lockup_update(ring);
- return false;
- }
- return amdgpu_ring_test_lockup(ring);
-}
-
static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = {
.get_rptr = sdma_v3_0_ring_get_rptr,
.get_wptr = sdma_v3_0_ring_get_wptr,
@@ -1458,7 +1468,6 @@ static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = {
.emit_hdp_flush = sdma_v3_0_ring_emit_hdp_flush,
.test_ring = sdma_v3_0_ring_test_ring,
.test_ib = sdma_v3_0_ring_test_ib,
- .is_lockup = sdma_v3_0_ring_is_lockup,
.insert_nop = sdma_v3_0_ring_insert_nop,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
index ed50dd725788..5e9f73af83a8 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
@@ -885,7 +885,6 @@ static const struct amdgpu_ring_funcs uvd_v4_2_ring_funcs = {
.emit_semaphore = uvd_v4_2_ring_emit_semaphore,
.test_ring = uvd_v4_2_ring_test_ring,
.test_ib = uvd_v4_2_ring_test_ib,
- .is_lockup = amdgpu_ring_test_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
index 9ad8b9906c0b..38864f562981 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
@@ -824,7 +824,6 @@ static const struct amdgpu_ring_funcs uvd_v5_0_ring_funcs = {
.emit_semaphore = uvd_v5_0_ring_emit_semaphore,
.test_ring = uvd_v5_0_ring_test_ring,
.test_ib = uvd_v5_0_ring_test_ib,
- .is_lockup = amdgpu_ring_test_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
index 7e9934fa4193..121915bbc3b6 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
@@ -808,7 +808,6 @@ static const struct amdgpu_ring_funcs uvd_v6_0_ring_funcs = {
.emit_semaphore = uvd_v6_0_ring_emit_semaphore,
.test_ring = uvd_v6_0_ring_test_ring,
.test_ib = uvd_v6_0_ring_test_ib,
- .is_lockup = amdgpu_ring_test_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
index cd16df543f64..52ac7a8f1e58 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
@@ -642,7 +642,6 @@ static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = {
.emit_semaphore = amdgpu_vce_ring_emit_semaphore,
.test_ring = amdgpu_vce_ring_test_ring,
.test_ib = amdgpu_vce_ring_test_ib,
- .is_lockup = amdgpu_ring_test_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
index f0656dfb53f3..6a52db6ad8d7 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
@@ -205,8 +205,9 @@ static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev)
u32 tmp;
unsigned ret;
- /* Fiji is single pipe */
- if (adev->asic_type == CHIP_FIJI) {
+ /* Fiji, Stoney are single pipe */
+ if ((adev->asic_type == CHIP_FIJI) ||
+ (adev->asic_type == CHIP_STONEY)){
ret = AMDGPU_VCE_HARVEST_VCE1;
return ret;
}
@@ -643,7 +644,6 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = {
.emit_semaphore = amdgpu_vce_ring_emit_semaphore,
.test_ring = amdgpu_vce_ring_test_ring,
.test_ib = amdgpu_vce_ring_test_ib,
- .is_lockup = amdgpu_ring_test_lockup,
.insert_nop = amdgpu_ring_insert_nop,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index 0bac8702e934..d8c93f14c3b5 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -232,6 +232,13 @@ static const u32 cz_mgcg_cgcg_init[] =
mmHDP_XDP_CGTT_BLK_CTRL, 0xc0000fff, 0x00000104,
};
+static const u32 stoney_mgcg_cgcg_init[] =
+{
+ mmCGTT_DRM_CLK_CTRL0, 0xffffffff, 0x00000100,
+ mmHDP_XDP_CGTT_BLK_CTRL, 0xffffffff, 0x00000104,
+ mmHDP_HOST_PATH_CNTL, 0xffffffff, 0x0f000027,
+};
+
static void vi_init_golden_registers(struct amdgpu_device *adev)
{
/* Some of the registers might be dependent on GRBM_GFX_INDEX */
@@ -258,6 +265,11 @@ static void vi_init_golden_registers(struct amdgpu_device *adev)
cz_mgcg_cgcg_init,
(const u32)ARRAY_SIZE(cz_mgcg_cgcg_init));
break;
+ case CHIP_STONEY:
+ amdgpu_program_register_sequence(adev,
+ stoney_mgcg_cgcg_init,
+ (const u32)ARRAY_SIZE(stoney_mgcg_cgcg_init));
+ break;
default:
break;
}
@@ -488,6 +500,7 @@ static int vi_read_register(struct amdgpu_device *adev, u32 se_num,
case CHIP_FIJI:
case CHIP_TONGA:
case CHIP_CARRIZO:
+ case CHIP_STONEY:
asic_register_table = cz_allowed_read_registers;
size = ARRAY_SIZE(cz_allowed_read_registers);
break;
@@ -543,8 +556,10 @@ static void vi_print_gpu_status_regs(struct amdgpu_device *adev)
RREG32(mmSRBM_STATUS2));
dev_info(adev->dev, " SDMA0_STATUS_REG = 0x%08X\n",
RREG32(mmSDMA0_STATUS_REG + SDMA0_REGISTER_OFFSET));
- dev_info(adev->dev, " SDMA1_STATUS_REG = 0x%08X\n",
- RREG32(mmSDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET));
+ if (adev->sdma.num_instances > 1) {
+ dev_info(adev->dev, " SDMA1_STATUS_REG = 0x%08X\n",
+ RREG32(mmSDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET));
+ }
dev_info(adev->dev, " CP_STAT = 0x%08x\n", RREG32(mmCP_STAT));
dev_info(adev->dev, " CP_STALLED_STAT1 = 0x%08x\n",
RREG32(mmCP_STALLED_STAT1));
@@ -639,9 +654,11 @@ u32 vi_gpu_check_soft_reset(struct amdgpu_device *adev)
reset_mask |= AMDGPU_RESET_DMA;
/* SDMA1_STATUS_REG */
- tmp = RREG32(mmSDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET);
- if (!(tmp & SDMA0_STATUS_REG__IDLE_MASK))
- reset_mask |= AMDGPU_RESET_DMA1;
+ if (adev->sdma.num_instances > 1) {
+ tmp = RREG32(mmSDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET);
+ if (!(tmp & SDMA0_STATUS_REG__IDLE_MASK))
+ reset_mask |= AMDGPU_RESET_DMA1;
+ }
#if 0
/* VCE_STATUS */
if (adev->asic_type != CHIP_TOPAZ) {
@@ -1319,6 +1336,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks);
break;
case CHIP_CARRIZO:
+ case CHIP_STONEY:
adev->ip_blocks = cz_ip_blocks;
adev->num_ip_blocks = ARRAY_SIZE(cz_ip_blocks);
break;
@@ -1330,11 +1348,18 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
return 0;
}
+#define ATI_REV_ID_FUSE_MACRO__ADDRESS 0xC0014044
+#define ATI_REV_ID_FUSE_MACRO__SHIFT 9
+#define ATI_REV_ID_FUSE_MACRO__MASK 0x00001E00
+
static uint32_t vi_get_rev_id(struct amdgpu_device *adev)
{
if (adev->asic_type == CHIP_TOPAZ)
return (RREG32(mmPCIE_EFUSE4) & PCIE_EFUSE4__STRAP_BIF_ATI_REV_ID_MASK)
>> PCIE_EFUSE4__STRAP_BIF_ATI_REV_ID__SHIFT;
+ else if (adev->flags & AMD_IS_APU)
+ return (RREG32_SMC(ATI_REV_ID_FUSE_MACRO__ADDRESS) & ATI_REV_ID_FUSE_MACRO__MASK)
+ >> ATI_REV_ID_FUSE_MACRO__SHIFT;
else
return (RREG32(mmCC_DRM_ID_STRAPS) & CC_DRM_ID_STRAPS__ATI_REV_ID_MASK)
>> CC_DRM_ID_STRAPS__ATI_REV_ID__SHIFT;
@@ -1401,6 +1426,7 @@ static int vi_common_early_init(void *handle)
adev->firmware.smu_load = true;
break;
case CHIP_CARRIZO:
+ case CHIP_STONEY:
adev->has_uvd = true;
adev->cg_flags = 0;
/* Disable UVD pg */
diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h
index 68a8eaa1b7d0..fe28fb353fab 100644
--- a/drivers/gpu/drm/amd/include/amd_shared.h
+++ b/drivers/gpu/drm/amd/include/amd_shared.h
@@ -47,6 +47,7 @@ enum amd_asic_type {
CHIP_TONGA,
CHIP_FIJI,
CHIP_CARRIZO,
+ CHIP_STONEY,
CHIP_LAST,
};
diff --git a/drivers/gpu/drm/amd/include/atombios.h b/drivers/gpu/drm/amd/include/atombios.h
index 44c5d4a4d1bf..552622675ace 100644
--- a/drivers/gpu/drm/amd/include/atombios.h
+++ b/drivers/gpu/drm/amd/include/atombios.h
@@ -6784,7 +6784,7 @@ typedef struct _ATOM_MC_INIT_PARAM_TABLE_V2_1
ULONG ulMCUcodeRomStartAddr;
ULONG ulMCUcodeLength;
USHORT usMcRegInitTableOffset; // offset of ATOM_REG_INIT_SETTING array for MC core register settings.
- USHORT usReserved; // offset of ATOM_INIT_REG_BLOCK for MC SEQ/PHY regsiter setting
+ USHORT usReserved; // offset of ATOM_INIT_REG_BLOCK for MC SEQ/PHY register setting
}ATOM_MC_INIT_PARAM_TABLE_V2_1;
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 3f2a7a7c7cd4..a3b22bdacd44 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1850,7 +1850,7 @@ static int i915_opregion(struct seq_file *m, void *unused)
goto out;
if (opregion->header) {
- memcpy_fromio(data, opregion->header, OPREGION_SIZE);
+ memcpy(data, opregion->header, OPREGION_SIZE);
seq_write(m, data, OPREGION_SIZE);
}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 5adba06a85d1..8afda459a26e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -450,14 +450,14 @@ struct opregion_swsci;
struct opregion_asle;
struct intel_opregion {
- struct opregion_header __iomem *header;
- struct opregion_acpi __iomem *acpi;
- struct opregion_swsci __iomem *swsci;
+ struct opregion_header *header;
+ struct opregion_acpi *acpi;
+ struct opregion_swsci *swsci;
u32 swsci_gbda_sub_functions;
u32 swsci_sbcb_sub_functions;
- struct opregion_asle __iomem *asle;
- void __iomem *vbt;
- u32 __iomem *lid_state;
+ struct opregion_asle *asle;
+ void *vbt;
+ u32 *lid_state;
struct work_struct asle_work;
};
#define OPREGION_SIZE (8*1024)
@@ -628,6 +628,10 @@ struct drm_i915_display_funcs {
struct dpll *match_clock,
struct dpll *best_clock);
void (*update_wm)(struct drm_crtc *crtc);
+ void (*update_sprite_wm)(struct drm_plane *plane,
+ struct drm_crtc *crtc,
+ uint32_t sprite_width, uint32_t sprite_height,
+ int pixel_size, bool enable, bool scaled);
int (*modeset_calc_cdclk)(struct drm_atomic_state *state);
void (*modeset_commit_cdclk)(struct drm_atomic_state *state);
/* Returns the active state of the crtc, and if the crtc is active,
@@ -1031,7 +1035,7 @@ struct i915_suspend_saved_registers {
u32 saveMI_ARB_STATE;
u32 saveSWF0[16];
u32 saveSWF1[16];
- u32 saveSWF2[3];
+ u32 saveSWF3[3];
uint64_t saveFENCE[I915_MAX_NUM_FENCES];
u32 savePCH_PORT_HOTPLUG;
u16 saveGCDGMBUS;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 1e67484fd5dc..e57061ac0219 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3657,53 +3657,106 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
return 0;
}
+/**
+ * Changes the cache-level of an object across all VMA.
+ *
+ * After this function returns, the object will be in the new cache-level
+ * across all GTT and the contents of the backing storage will be coherent,
+ * with respect to the new cache-level. In order to keep the backing storage
+ * coherent for all users, we only allow a single cache level to be set
+ * globally on the object and prevent it from being changed whilst the
+ * hardware is reading from the object. That is if the object is currently
+ * on the scanout it will be set to uncached (or equivalent display
+ * cache coherency) and all non-MOCS GPU access will also be uncached so
+ * that all direct access to the scanout remains coherent.
+ */
int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
enum i915_cache_level cache_level)
{
struct drm_device *dev = obj->base.dev;
struct i915_vma *vma, *next;
+ bool bound = false;
int ret = 0;
if (obj->cache_level == cache_level)
goto out;
- if (i915_gem_obj_is_pinned(obj)) {
- DRM_DEBUG("can not change the cache level of pinned objects\n");
- return -EBUSY;
- }
-
+ /* Inspect the list of currently bound VMA and unbind any that would
+ * be invalid given the new cache-level. This is principally to
+ * catch the issue of the CS prefetch crossing page boundaries and
+ * reading an invalid PTE on older architectures.
+ */
list_for_each_entry_safe(vma, next, &obj->vma_list, vma_link) {
+ if (!drm_mm_node_allocated(&vma->node))
+ continue;
+
+ if (vma->pin_count) {
+ DRM_DEBUG("can not change the cache level of pinned objects\n");
+ return -EBUSY;
+ }
+
if (!i915_gem_valid_gtt_space(vma, cache_level)) {
ret = i915_vma_unbind(vma);
if (ret)
return ret;
- }
+ } else
+ bound = true;
}
- if (i915_gem_obj_bound_any(obj)) {
+ /* We can reuse the existing drm_mm nodes but need to change the
+ * cache-level on the PTE. We could simply unbind them all and
+ * rebind with the correct cache-level on next use. However since
+ * we already have a valid slot, dma mapping, pages etc, we may as
+ * rewrite the PTE in the belief that doing so tramples upon less
+ * state and so involves less work.
+ */
+ if (bound) {
+ /* Before we change the PTE, the GPU must not be accessing it.
+ * If we wait upon the object, we know that all the bound
+ * VMA are no longer active.
+ */
ret = i915_gem_object_wait_rendering(obj, false);
if (ret)
return ret;
- i915_gem_object_finish_gtt(obj);
-
- /* Before SandyBridge, you could not use tiling or fence
- * registers with snooped memory, so relinquish any fences
- * currently pointing to our region in the aperture.
- */
- if (INTEL_INFO(dev)->gen < 6) {
+ if (!HAS_LLC(dev) && cache_level != I915_CACHE_NONE) {
+ /* Access to snoopable pages through the GTT is
+ * incoherent and on some machines causes a hard
+ * lockup. Relinquish the CPU mmaping to force
+ * userspace to refault in the pages and we can
+ * then double check if the GTT mapping is still
+ * valid for that pointer access.
+ */
+ i915_gem_release_mmap(obj);
+
+ /* As we no longer need a fence for GTT access,
+ * we can relinquish it now (and so prevent having
+ * to steal a fence from someone else on the next
+ * fence request). Note GPU activity would have
+ * dropped the fence as all snoopable access is
+ * supposed to be linear.
+ */
ret = i915_gem_object_put_fence(obj);
if (ret)
return ret;
+ } else {
+ /* We either have incoherent backing store and
+ * so no GTT access or the architecture is fully
+ * coherent. In such cases, existing GTT mmaps
+ * ignore the cache bit in the PTE and we can
+ * rewrite it without confusing the GPU or having
+ * to force userspace to fault back in its mmaps.
+ */
}
- list_for_each_entry(vma, &obj->vma_list, vma_link)
- if (drm_mm_node_allocated(&vma->node)) {
- ret = i915_vma_bind(vma, cache_level,
- PIN_UPDATE);
- if (ret)
- return ret;
- }
+ list_for_each_entry(vma, &obj->vma_list, vma_link) {
+ if (!drm_mm_node_allocated(&vma->node))
+ continue;
+
+ ret = i915_vma_bind(vma, cache_level, PIN_UPDATE);
+ if (ret)
+ return ret;
+ }
}
list_for_each_entry(vma, &obj->vma_list, vma_link)
@@ -3711,6 +3764,10 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
obj->cache_level = cache_level;
out:
+ /* Flush the dirty CPU caches to the backing storage so that the
+ * object is now coherent at its new cache level (with respect
+ * to the access domain).
+ */
if (obj->cache_dirty &&
obj->base.write_domain != I915_GEM_DOMAIN_CPU &&
cpu_write_needs_clflush(obj)) {
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 620d57e2526b..43f35d12b677 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -2502,6 +2502,36 @@ static int ggtt_bind_vma(struct i915_vma *vma,
enum i915_cache_level cache_level,
u32 flags)
{
+ struct drm_i915_gem_object *obj = vma->obj;
+ u32 pte_flags = 0;
+ int ret;
+
+ ret = i915_get_ggtt_vma_pages(vma);
+ if (ret)
+ return ret;
+
+ /* Currently applicable only to VLV */
+ if (obj->gt_ro)
+ pte_flags |= PTE_READ_ONLY;
+
+ vma->vm->insert_entries(vma->vm, vma->ggtt_view.pages,
+ vma->node.start,
+ cache_level, pte_flags);
+
+ /*
+ * Without aliasing PPGTT there's no difference between
+ * GLOBAL/LOCAL_BIND, it's all the same ptes. Hence unconditionally
+ * upgrade to both bound if we bind either to avoid double-binding.
+ */
+ vma->bound |= GLOBAL_BIND | LOCAL_BIND;
+
+ return 0;
+}
+
+static int aliasing_gtt_bind_vma(struct i915_vma *vma,
+ enum i915_cache_level cache_level,
+ u32 flags)
+{
struct drm_device *dev = vma->vm->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj = vma->obj;
@@ -2519,23 +2549,13 @@ static int ggtt_bind_vma(struct i915_vma *vma,
pte_flags |= PTE_READ_ONLY;
- if (!dev_priv->mm.aliasing_ppgtt || flags & GLOBAL_BIND) {
+ if (flags & GLOBAL_BIND) {
vma->vm->insert_entries(vma->vm, pages,
vma->node.start,
cache_level, pte_flags);
-
- /* Note the inconsistency here is due to absence of the
- * aliasing ppgtt on gen4 and earlier. Though we always
- * request PIN_USER for execbuffer (translated to LOCAL_BIND),
- * without the appgtt, we cannot honour that request and so
- * must substitute it with a global binding. Since we do this
- * behind the upper layers back, we need to explicitly set
- * the bound flag ourselves.
- */
- vma->bound |= GLOBAL_BIND;
}
- if (dev_priv->mm.aliasing_ppgtt && flags & LOCAL_BIND) {
+ if (flags & LOCAL_BIND) {
struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt;
appgtt->base.insert_entries(&appgtt->base, pages,
vma->node.start,
@@ -2699,6 +2719,8 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
true);
dev_priv->mm.aliasing_ppgtt = ppgtt;
+ WARN_ON(dev_priv->gtt.base.bind_vma != ggtt_bind_vma);
+ dev_priv->gtt.base.bind_vma = aliasing_gtt_bind_vma;
}
return 0;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 4fb8a2f56281..d68328fa175b 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -139,27 +139,30 @@ static const u32 hpd_bxt[HPD_NUM_PINS] = {
/*
* We should clear IMR at preinstall/uninstall, and just check at postinstall.
*/
-#define GEN5_ASSERT_IIR_IS_ZERO(reg) do { \
- u32 val = I915_READ(reg); \
- if (val) { \
- WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n", \
- (reg), val); \
- I915_WRITE((reg), 0xffffffff); \
- POSTING_READ(reg); \
- I915_WRITE((reg), 0xffffffff); \
- POSTING_READ(reg); \
- } \
-} while (0)
+static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv, u32 reg)
+{
+ u32 val = I915_READ(reg);
+
+ if (val == 0)
+ return;
+
+ WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n",
+ reg, val);
+ I915_WRITE(reg, 0xffffffff);
+ POSTING_READ(reg);
+ I915_WRITE(reg, 0xffffffff);
+ POSTING_READ(reg);
+}
#define GEN8_IRQ_INIT_NDX(type, which, imr_val, ier_val) do { \
- GEN5_ASSERT_IIR_IS_ZERO(GEN8_##type##_IIR(which)); \
+ gen5_assert_iir_is_zero(dev_priv, GEN8_##type##_IIR(which)); \
I915_WRITE(GEN8_##type##_IER(which), (ier_val)); \
I915_WRITE(GEN8_##type##_IMR(which), (imr_val)); \
POSTING_READ(GEN8_##type##_IMR(which)); \
} while (0)
#define GEN5_IRQ_INIT(type, imr_val, ier_val) do { \
- GEN5_ASSERT_IIR_IS_ZERO(type##IIR); \
+ gen5_assert_iir_is_zero(dev_priv, type##IIR); \
I915_WRITE(type##IER, (ier_val)); \
I915_WRITE(type##IMR, (imr_val)); \
POSTING_READ(type##IMR); \
@@ -707,12 +710,11 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff;
}
-static u32 gm45_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
+static u32 g4x_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- int reg = PIPE_FRMCOUNT_GM45(pipe);
- return I915_READ(reg);
+ return I915_READ(PIPE_FRMCOUNT_G4X(pipe));
}
/* raw reads, only for fast reads of display block, no need for forcewake etc. */
@@ -3365,7 +3367,7 @@ static void ibx_irq_postinstall(struct drm_device *dev)
else
mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
- GEN5_ASSERT_IIR_IS_ZERO(SDEIIR);
+ gen5_assert_iir_is_zero(dev_priv, SDEIIR);
I915_WRITE(SDEIMR, ~mask);
}
@@ -4397,7 +4399,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
dev->driver->get_vblank_counter = i8xx_get_vblank_counter;
} else if (IS_G4X(dev_priv) || INTEL_INFO(dev_priv)->gen >= 5) {
dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
- dev->driver->get_vblank_counter = gm45_get_vblank_counter;
+ dev->driver->get_vblank_counter = g4x_get_vblank_counter;
} else {
dev->driver->get_vblank_counter = i915_get_vblank_counter;
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 6be853d2233c..bc7b8faba84d 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -429,7 +429,7 @@
#define ASYNC_FLIP (1<<22)
#define DISPLAY_PLANE_A (0<<20)
#define DISPLAY_PLANE_B (1<<20)
-#define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2))
+#define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|((len)-2))
#define PIPE_CONTROL_FLUSH_L3 (1<<27)
#define PIPE_CONTROL_GLOBAL_GTT_IVB (1<<24) /* gen7+ */
#define PIPE_CONTROL_MMIO_WRITE (1<<23)
@@ -1255,7 +1255,7 @@ enum skl_disp_power_wells {
#define PORT_PLL_DCO_AMP_OVR_EN_H (1<<27)
#define PORT_PLL_DCO_AMP_DEFAULT 15
#define PORT_PLL_DCO_AMP_MASK 0x3c00
-#define PORT_PLL_DCO_AMP(x) (x<<10)
+#define PORT_PLL_DCO_AMP(x) ((x)<<10)
#define _PORT_PLL_BASE(port) _PORT3(port, _PORT_PLL_0_A, \
_PORT_PLL_0_B, \
_PORT_PLL_0_C)
@@ -1552,8 +1552,8 @@ enum skl_disp_power_wells {
#define RENDER_HWS_PGA_GEN7 (0x04080)
#define RING_FAULT_REG(ring) (0x4094 + 0x100*(ring)->id)
#define RING_FAULT_GTTSEL_MASK (1<<11)
-#define RING_FAULT_SRCID(x) ((x >> 3) & 0xff)
-#define RING_FAULT_FAULT_TYPE(x) ((x >> 1) & 0x3)
+#define RING_FAULT_SRCID(x) (((x) >> 3) & 0xff)
+#define RING_FAULT_FAULT_TYPE(x) (((x) >> 1) & 0x3)
#define RING_FAULT_VALID (1<<0)
#define DONE_REG 0x40b0
#define GEN8_PRIVATE_PAT_LO 0x40e0
@@ -1641,9 +1641,9 @@ enum skl_disp_power_wells {
#define ERR_INT_PIPE_CRC_DONE_B (1<<5)
#define ERR_INT_FIFO_UNDERRUN_B (1<<3)
#define ERR_INT_PIPE_CRC_DONE_A (1<<2)
-#define ERR_INT_PIPE_CRC_DONE(pipe) (1<<(2 + pipe*3))
+#define ERR_INT_PIPE_CRC_DONE(pipe) (1<<(2 + (pipe)*3))
#define ERR_INT_FIFO_UNDERRUN_A (1<<0)
-#define ERR_INT_FIFO_UNDERRUN(pipe) (1<<(pipe*3))
+#define ERR_INT_FIFO_UNDERRUN(pipe) (1<<((pipe)*3))
#define GEN8_FAULT_TLB_DATA0 0x04b10
#define GEN8_FAULT_TLB_DATA1 0x04b14
@@ -1704,8 +1704,8 @@ enum skl_disp_power_wells {
#define GEN6_WIZ_HASHING_16x4 GEN6_WIZ_HASHING(1, 0)
#define GEN6_WIZ_HASHING_MASK GEN6_WIZ_HASHING(1, 1)
#define GEN6_TD_FOUR_ROW_DISPATCH_DISABLE (1 << 5)
-#define GEN9_IZ_HASHING_MASK(slice) (0x3 << (slice * 2))
-#define GEN9_IZ_HASHING(slice, val) ((val) << (slice * 2))
+#define GEN9_IZ_HASHING_MASK(slice) (0x3 << ((slice) * 2))
+#define GEN9_IZ_HASHING(slice, val) ((val) << ((slice) * 2))
#define GFX_MODE 0x02520
#define GFX_MODE_GEN7 0x0229c
@@ -2144,7 +2144,7 @@ enum skl_disp_power_wells {
# define GPIO_DATA_VAL_IN (1 << 12)
# define GPIO_DATA_PULLUP_DISABLE (1 << 13)
-#define GMBUS0 0x5100 /* clock/port select */
+#define GMBUS0 (dev_priv->gpio_mmio_base + 0x5100) /* clock/port select */
#define GMBUS_RATE_100KHZ (0<<8)
#define GMBUS_RATE_50KHZ (1<<8)
#define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */
@@ -2163,7 +2163,7 @@ enum skl_disp_power_wells {
#define GMBUS_PIN_2_BXT 2
#define GMBUS_PIN_3_BXT 3
#define GMBUS_NUM_PINS 7 /* including 0 */
-#define GMBUS1 0x5104 /* command/status */
+#define GMBUS1 (dev_priv->gpio_mmio_base + 0x5104) /* command/status */
#define GMBUS_SW_CLR_INT (1<<31)
#define GMBUS_SW_RDY (1<<30)
#define GMBUS_ENT (1<<29) /* enable timeout */
@@ -2177,7 +2177,7 @@ enum skl_disp_power_wells {
#define GMBUS_SLAVE_ADDR_SHIFT 1
#define GMBUS_SLAVE_READ (1<<0)
#define GMBUS_SLAVE_WRITE (0<<0)
-#define GMBUS2 0x5108 /* status */
+#define GMBUS2 (dev_priv->gpio_mmio_base + 0x5108) /* status */
#define GMBUS_INUSE (1<<15)
#define GMBUS_HW_WAIT_PHASE (1<<14)
#define GMBUS_STALL_TIMEOUT (1<<13)
@@ -2185,14 +2185,14 @@ enum skl_disp_power_wells {
#define GMBUS_HW_RDY (1<<11)
#define GMBUS_SATOER (1<<10)
#define GMBUS_ACTIVE (1<<9)
-#define GMBUS3 0x510c /* data buffer bytes 3-0 */
-#define GMBUS4 0x5110 /* interrupt mask (Pineview+) */
+#define GMBUS3 (dev_priv->gpio_mmio_base + 0x510c) /* data buffer bytes 3-0 */
+#define GMBUS4 (dev_priv->gpio_mmio_base + 0x5110) /* interrupt mask (Pineview+) */
#define GMBUS_SLAVE_TIMEOUT_EN (1<<4)
#define GMBUS_NAK_EN (1<<3)
#define GMBUS_IDLE_EN (1<<2)
#define GMBUS_HW_WAIT_EN (1<<1)
#define GMBUS_HW_RDY_EN (1<<0)
-#define GMBUS5 0x5120 /* byte index */
+#define GMBUS5 (dev_priv->gpio_mmio_base + 0x5120) /* byte index */
#define GMBUS_2BYTE_INDEX_EN (1<<31)
/*
@@ -2866,21 +2866,21 @@ enum skl_disp_power_wells {
* doesn't need saving on GT1
*/
#define CXT_SIZE 0x21a0
-#define GEN6_CXT_POWER_SIZE(cxt_reg) ((cxt_reg >> 24) & 0x3f)
-#define GEN6_CXT_RING_SIZE(cxt_reg) ((cxt_reg >> 18) & 0x3f)
-#define GEN6_CXT_RENDER_SIZE(cxt_reg) ((cxt_reg >> 12) & 0x3f)
-#define GEN6_CXT_EXTENDED_SIZE(cxt_reg) ((cxt_reg >> 6) & 0x3f)
-#define GEN6_CXT_PIPELINE_SIZE(cxt_reg) ((cxt_reg >> 0) & 0x3f)
+#define GEN6_CXT_POWER_SIZE(cxt_reg) (((cxt_reg) >> 24) & 0x3f)
+#define GEN6_CXT_RING_SIZE(cxt_reg) (((cxt_reg) >> 18) & 0x3f)
+#define GEN6_CXT_RENDER_SIZE(cxt_reg) (((cxt_reg) >> 12) & 0x3f)
+#define GEN6_CXT_EXTENDED_SIZE(cxt_reg) (((cxt_reg) >> 6) & 0x3f)
+#define GEN6_CXT_PIPELINE_SIZE(cxt_reg) (((cxt_reg) >> 0) & 0x3f)
#define GEN6_CXT_TOTAL_SIZE(cxt_reg) (GEN6_CXT_RING_SIZE(cxt_reg) + \
GEN6_CXT_EXTENDED_SIZE(cxt_reg) + \
GEN6_CXT_PIPELINE_SIZE(cxt_reg))
#define GEN7_CXT_SIZE 0x21a8
-#define GEN7_CXT_POWER_SIZE(ctx_reg) ((ctx_reg >> 25) & 0x7f)
-#define GEN7_CXT_RING_SIZE(ctx_reg) ((ctx_reg >> 22) & 0x7)
-#define GEN7_CXT_RENDER_SIZE(ctx_reg) ((ctx_reg >> 16) & 0x3f)
-#define GEN7_CXT_EXTENDED_SIZE(ctx_reg) ((ctx_reg >> 9) & 0x7f)
-#define GEN7_CXT_GT1_SIZE(ctx_reg) ((ctx_reg >> 6) & 0x7)
-#define GEN7_CXT_VFSTATE_SIZE(ctx_reg) ((ctx_reg >> 0) & 0x3f)
+#define GEN7_CXT_POWER_SIZE(ctx_reg) (((ctx_reg) >> 25) & 0x7f)
+#define GEN7_CXT_RING_SIZE(ctx_reg) (((ctx_reg) >> 22) & 0x7)
+#define GEN7_CXT_RENDER_SIZE(ctx_reg) (((ctx_reg) >> 16) & 0x3f)
+#define GEN7_CXT_EXTENDED_SIZE(ctx_reg) (((ctx_reg) >> 9) & 0x7f)
+#define GEN7_CXT_GT1_SIZE(ctx_reg) (((ctx_reg) >> 6) & 0x7)
+#define GEN7_CXT_VFSTATE_SIZE(ctx_reg) (((ctx_reg) >> 0) & 0x3f)
#define GEN7_CXT_TOTAL_SIZE(ctx_reg) (GEN7_CXT_EXTENDED_SIZE(ctx_reg) + \
GEN7_CXT_VFSTATE_SIZE(ctx_reg))
/* Haswell does have the CXT_SIZE register however it does not appear to be
@@ -4284,7 +4284,7 @@ enum skl_disp_power_wells {
#define DP_AUX_CH_CTL_PSR_DATA_AUX_REG_SKL (1 << 14)
#define DP_AUX_CH_CTL_FS_DATA_AUX_REG_SKL (1 << 13)
#define DP_AUX_CH_CTL_GTC_DATA_AUX_REG_SKL (1 << 12)
-#define DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL_MASK (1f << 5)
+#define DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL_MASK (0x1f << 5)
#define DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(c) (((c) - 1) << 5)
#define DP_AUX_CH_CTL_SYNC_PULSE_SKL(c) ((c) - 1)
@@ -4846,10 +4846,10 @@ enum skl_disp_power_wells {
#define PIPE_PIXEL_MASK 0x00ffffff
#define PIPE_PIXEL_SHIFT 0
/* GM45+ just has to be different */
-#define _PIPEA_FRMCOUNT_GM45 0x70040
-#define _PIPEA_FLIPCOUNT_GM45 0x70044
-#define PIPE_FRMCOUNT_GM45(pipe) _PIPE2(pipe, _PIPEA_FRMCOUNT_GM45)
-#define PIPE_FLIPCOUNT_GM45(pipe) _PIPE2(pipe, _PIPEA_FLIPCOUNT_GM45)
+#define _PIPEA_FRMCOUNT_G4X 0x70040
+#define _PIPEA_FLIPCOUNT_G4X 0x70044
+#define PIPE_FRMCOUNT_G4X(pipe) _PIPE2(pipe, _PIPEA_FRMCOUNT_G4X)
+#define PIPE_FLIPCOUNT_G4X(pipe) _PIPE2(pipe, _PIPEA_FLIPCOUNT_G4X)
/* Cursor A & B regs */
#define _CURACNTR 0x70080
@@ -4991,20 +4991,20 @@ enum skl_disp_power_wells {
#define I915_LO_DISPBASE(val) (val & ~DISP_BASEADDR_MASK)
#define I915_HI_DISPBASE(val) (val & DISP_BASEADDR_MASK)
-/* VBIOS flags */
-#define SWF00 (dev_priv->info.display_mmio_offset + 0x71410)
-#define SWF01 (dev_priv->info.display_mmio_offset + 0x71414)
-#define SWF02 (dev_priv->info.display_mmio_offset + 0x71418)
-#define SWF03 (dev_priv->info.display_mmio_offset + 0x7141c)
-#define SWF04 (dev_priv->info.display_mmio_offset + 0x71420)
-#define SWF05 (dev_priv->info.display_mmio_offset + 0x71424)
-#define SWF06 (dev_priv->info.display_mmio_offset + 0x71428)
-#define SWF10 (dev_priv->info.display_mmio_offset + 0x70410)
-#define SWF11 (dev_priv->info.display_mmio_offset + 0x70414)
-#define SWF14 (dev_priv->info.display_mmio_offset + 0x71420)
-#define SWF30 (dev_priv->info.display_mmio_offset + 0x72414)
-#define SWF31 (dev_priv->info.display_mmio_offset + 0x72418)
-#define SWF32 (dev_priv->info.display_mmio_offset + 0x7241c)
+/*
+ * VBIOS flags
+ * gen2:
+ * [00:06] alm,mgm
+ * [10:16] all
+ * [30:32] alm,mgm
+ * gen3+:
+ * [00:0f] all
+ * [10:1f] all
+ * [30:32] all
+ */
+#define SWF0(i) (dev_priv->info.display_mmio_offset + 0x70410 + (i) * 4)
+#define SWF1(i) (dev_priv->info.display_mmio_offset + 0x71410 + (i) * 4)
+#define SWF3(i) (dev_priv->info.display_mmio_offset + 0x72414 + (i) * 4)
/* Pipe B */
#define _PIPEBDSL (dev_priv->info.display_mmio_offset + 0x71000)
@@ -5012,8 +5012,8 @@ enum skl_disp_power_wells {
#define _PIPEBSTAT (dev_priv->info.display_mmio_offset + 0x71024)
#define _PIPEBFRAMEHIGH 0x71040
#define _PIPEBFRAMEPIXEL 0x71044
-#define _PIPEB_FRMCOUNT_GM45 (dev_priv->info.display_mmio_offset + 0x71040)
-#define _PIPEB_FLIPCOUNT_GM45 (dev_priv->info.display_mmio_offset + 0x71044)
+#define _PIPEB_FRMCOUNT_G4X (dev_priv->info.display_mmio_offset + 0x71040)
+#define _PIPEB_FLIPCOUNT_G4X (dev_priv->info.display_mmio_offset + 0x71044)
/* Display B control */
@@ -5223,18 +5223,18 @@ enum skl_disp_power_wells {
#define _SPBCONSTALPHA (VLV_DISPLAY_BASE + 0x722a8)
#define _SPBGAMC (VLV_DISPLAY_BASE + 0x722f4)
-#define SPCNTR(pipe, plane) _PIPE(pipe * 2 + plane, _SPACNTR, _SPBCNTR)
-#define SPLINOFF(pipe, plane) _PIPE(pipe * 2 + plane, _SPALINOFF, _SPBLINOFF)
-#define SPSTRIDE(pipe, plane) _PIPE(pipe * 2 + plane, _SPASTRIDE, _SPBSTRIDE)
-#define SPPOS(pipe, plane) _PIPE(pipe * 2 + plane, _SPAPOS, _SPBPOS)
-#define SPSIZE(pipe, plane) _PIPE(pipe * 2 + plane, _SPASIZE, _SPBSIZE)
-#define SPKEYMINVAL(pipe, plane) _PIPE(pipe * 2 + plane, _SPAKEYMINVAL, _SPBKEYMINVAL)
-#define SPKEYMSK(pipe, plane) _PIPE(pipe * 2 + plane, _SPAKEYMSK, _SPBKEYMSK)
-#define SPSURF(pipe, plane) _PIPE(pipe * 2 + plane, _SPASURF, _SPBSURF)
-#define SPKEYMAXVAL(pipe, plane) _PIPE(pipe * 2 + plane, _SPAKEYMAXVAL, _SPBKEYMAXVAL)
-#define SPTILEOFF(pipe, plane) _PIPE(pipe * 2 + plane, _SPATILEOFF, _SPBTILEOFF)
-#define SPCONSTALPHA(pipe, plane) _PIPE(pipe * 2 + plane, _SPACONSTALPHA, _SPBCONSTALPHA)
-#define SPGAMC(pipe, plane) _PIPE(pipe * 2 + plane, _SPAGAMC, _SPBGAMC)
+#define SPCNTR(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPACNTR, _SPBCNTR)
+#define SPLINOFF(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPALINOFF, _SPBLINOFF)
+#define SPSTRIDE(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPASTRIDE, _SPBSTRIDE)
+#define SPPOS(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAPOS, _SPBPOS)
+#define SPSIZE(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPASIZE, _SPBSIZE)
+#define SPKEYMINVAL(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAKEYMINVAL, _SPBKEYMINVAL)
+#define SPKEYMSK(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAKEYMSK, _SPBKEYMSK)
+#define SPSURF(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPASURF, _SPBSURF)
+#define SPKEYMAXVAL(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAKEYMAXVAL, _SPBKEYMAXVAL)
+#define SPTILEOFF(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPATILEOFF, _SPBTILEOFF)
+#define SPCONSTALPHA(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPACONSTALPHA, _SPBCONSTALPHA)
+#define SPGAMC(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAGAMC, _SPBGAMC)
/*
* CHV pipe B sprite CSC
@@ -5580,7 +5580,7 @@ enum skl_disp_power_wells {
#define PS_SCALER_MODE_DYN (0 << 28)
#define PS_SCALER_MODE_HQ (1 << 28)
#define PS_PLANE_SEL_MASK (7 << 25)
-#define PS_PLANE_SEL(plane) ((plane + 1) << 25)
+#define PS_PLANE_SEL(plane) (((plane) + 1) << 25)
#define PS_FILTER_MASK (3 << 23)
#define PS_FILTER_MEDIUM (0 << 23)
#define PS_FILTER_EDGE_ENHANCE (2 << 23)
@@ -5745,7 +5745,7 @@ enum skl_disp_power_wells {
#define DE_PLANEA_FLIP_DONE_IVB (1<<3)
#define DE_PLANE_FLIP_DONE_IVB(plane) (1<< (3 + 5*(plane)))
#define DE_PIPEA_VBLANK_IVB (1<<0)
-#define DE_PIPE_VBLANK_IVB(pipe) (1 << (pipe * 5))
+#define DE_PIPE_VBLANK_IVB(pipe) (1 << ((pipe) * 5))
#define VLV_MASTER_IER 0x4400c /* Gunit master IER */
#define MASTER_INTERRUPT_ENABLE (1<<31)
@@ -5769,7 +5769,7 @@ enum skl_disp_power_wells {
#define GEN8_DE_PIPE_C_IRQ (1<<18)
#define GEN8_DE_PIPE_B_IRQ (1<<17)
#define GEN8_DE_PIPE_A_IRQ (1<<16)
-#define GEN8_DE_PIPE_IRQ(pipe) (1<<(16+pipe))
+#define GEN8_DE_PIPE_IRQ(pipe) (1<<(16+(pipe)))
#define GEN8_GT_VECS_IRQ (1<<6)
#define GEN8_GT_PM_IRQ (1<<4)
#define GEN8_GT_VCS2_IRQ (1<<3)
@@ -5813,7 +5813,7 @@ enum skl_disp_power_wells {
#define GEN9_PIPE_PLANE3_FLIP_DONE (1 << 5)
#define GEN9_PIPE_PLANE2_FLIP_DONE (1 << 4)
#define GEN9_PIPE_PLANE1_FLIP_DONE (1 << 3)
-#define GEN9_PIPE_PLANE_FLIP_DONE(p) (1 << (3 + p))
+#define GEN9_PIPE_PLANE_FLIP_DONE(p) (1 << (3 + (p)))
#define GEN8_DE_PIPE_IRQ_FAULT_ERRORS \
(GEN8_PIPE_CURSOR_FAULT | \
GEN8_PIPE_SPRITE_FAULT | \
@@ -6072,7 +6072,7 @@ enum skl_disp_power_wells {
#define SERR_INT_TRANS_C_FIFO_UNDERRUN (1<<6)
#define SERR_INT_TRANS_B_FIFO_UNDERRUN (1<<3)
#define SERR_INT_TRANS_A_FIFO_UNDERRUN (1<<0)
-#define SERR_INT_TRANS_FIFO_UNDERRUN(pipe) (1<<(pipe*3))
+#define SERR_INT_TRANS_FIFO_UNDERRUN(pipe) (1<<((pipe)*3))
/* digital port hotplug */
#define PCH_PORT_HOTPLUG 0xc4030 /* SHOTPLUG_CTL */
@@ -6183,9 +6183,9 @@ enum skl_disp_power_wells {
#define PCH_SSC4_AUX_PARMS 0xc6214
#define PCH_DPLL_SEL 0xc7000
-#define TRANS_DPLLB_SEL(pipe) (1 << (pipe * 4))
+#define TRANS_DPLLB_SEL(pipe) (1 << ((pipe) * 4))
#define TRANS_DPLLA_SEL(pipe) 0
-#define TRANS_DPLL_ENABLE(pipe) (1 << (pipe * 4 + 3))
+#define TRANS_DPLL_ENABLE(pipe) (1 << ((pipe) * 4 + 3))
/* transcoder */
@@ -6286,16 +6286,16 @@ enum skl_disp_power_wells {
#define HSW_TVIDEO_DIP_CTL(trans) \
_TRANSCODER2(trans, HSW_VIDEO_DIP_CTL_A)
-#define HSW_TVIDEO_DIP_AVI_DATA(trans) \
- _TRANSCODER2(trans, HSW_VIDEO_DIP_AVI_DATA_A)
-#define HSW_TVIDEO_DIP_VS_DATA(trans) \
- _TRANSCODER2(trans, HSW_VIDEO_DIP_VS_DATA_A)
-#define HSW_TVIDEO_DIP_SPD_DATA(trans) \
- _TRANSCODER2(trans, HSW_VIDEO_DIP_SPD_DATA_A)
+#define HSW_TVIDEO_DIP_AVI_DATA(trans, i) \
+ (_TRANSCODER2(trans, HSW_VIDEO_DIP_AVI_DATA_A) + (i) * 4)
+#define HSW_TVIDEO_DIP_VS_DATA(trans, i) \
+ (_TRANSCODER2(trans, HSW_VIDEO_DIP_VS_DATA_A) + (i) * 4)
+#define HSW_TVIDEO_DIP_SPD_DATA(trans, i) \
+ (_TRANSCODER2(trans, HSW_VIDEO_DIP_SPD_DATA_A) + (i) * 4)
#define HSW_TVIDEO_DIP_GCP(trans) \
_TRANSCODER2(trans, HSW_VIDEO_DIP_GCP_A)
-#define HSW_TVIDEO_DIP_VSC_DATA(trans) \
- _TRANSCODER2(trans, HSW_VIDEO_DIP_VSC_DATA_A)
+#define HSW_TVIDEO_DIP_VSC_DATA(trans, i) \
+ (_TRANSCODER2(trans, HSW_VIDEO_DIP_VSC_DATA_A) + (i) * 4)
#define HSW_STEREO_3D_CTL_A 0x70020
#define S3D_ENABLE (1<<31)
@@ -6587,10 +6587,10 @@ enum skl_disp_power_wells {
#define _BXT_PP_ON_DELAYS2 0xc7308
#define _BXT_PP_OFF_DELAYS2 0xc730c
-#define BXT_PP_STATUS(n) ((!n) ? PCH_PP_STATUS : _BXT_PP_STATUS2)
-#define BXT_PP_CONTROL(n) ((!n) ? PCH_PP_CONTROL : _BXT_PP_CONTROL2)
-#define BXT_PP_ON_DELAYS(n) ((!n) ? PCH_PP_ON_DELAYS : _BXT_PP_ON_DELAYS2)
-#define BXT_PP_OFF_DELAYS(n) ((!n) ? PCH_PP_OFF_DELAYS : _BXT_PP_OFF_DELAYS2)
+#define BXT_PP_STATUS(n) _PIPE(n, PCH_PP_STATUS, _BXT_PP_STATUS2)
+#define BXT_PP_CONTROL(n) _PIPE(n, PCH_PP_CONTROL, _BXT_PP_CONTROL2)
+#define BXT_PP_ON_DELAYS(n) _PIPE(n, PCH_PP_ON_DELAYS, _BXT_PP_ON_DELAYS2)
+#define BXT_PP_OFF_DELAYS(n) _PIPE(n, PCH_PP_OFF_DELAYS, _BXT_PP_OFF_DELAYS2)
#define PCH_DP_B 0xe4100
#define PCH_DPB_AUX_CH_CTL 0xe4110
@@ -7348,7 +7348,7 @@ enum skl_disp_power_wells {
#define TRANS_CLK_SEL(tran) _TRANSCODER(tran, TRANS_CLK_SEL_A, TRANS_CLK_SEL_B)
/* For each transcoder, we need to select the corresponding port clock */
#define TRANS_CLK_SEL_DISABLED (0x0<<29)
-#define TRANS_CLK_SEL_PORT(x) ((x+1)<<29)
+#define TRANS_CLK_SEL_PORT(x) (((x)+1)<<29)
#define TRANSA_MSA_MISC 0x60410
#define TRANSB_MSA_MISC 0x61410
@@ -7421,10 +7421,10 @@ enum skl_disp_power_wells {
/* DPLL control2 */
#define DPLL_CTRL2 0x6C05C
-#define DPLL_CTRL2_DDI_CLK_OFF(port) (1<<(port+15))
+#define DPLL_CTRL2_DDI_CLK_OFF(port) (1<<((port)+15))
#define DPLL_CTRL2_DDI_CLK_SEL_MASK(port) (3<<((port)*3+1))
#define DPLL_CTRL2_DDI_CLK_SEL_SHIFT(port) ((port)*3+1)
-#define DPLL_CTRL2_DDI_CLK_SEL(clk, port) (clk<<((port)*3+1))
+#define DPLL_CTRL2_DDI_CLK_SEL(clk, port) ((clk)<<((port)*3+1))
#define DPLL_CTRL2_DDI_SEL_OVERRIDE(port) (1<<((port)*3))
/* DPLL Status */
@@ -7437,23 +7437,23 @@ enum skl_disp_power_wells {
#define DPLL3_CFGCR1 0x6C050
#define DPLL_CFGCR1_FREQ_ENABLE (1<<31)
#define DPLL_CFGCR1_DCO_FRACTION_MASK (0x7fff<<9)
-#define DPLL_CFGCR1_DCO_FRACTION(x) (x<<9)
+#define DPLL_CFGCR1_DCO_FRACTION(x) ((x)<<9)
#define DPLL_CFGCR1_DCO_INTEGER_MASK (0x1ff)
#define DPLL1_CFGCR2 0x6C044
#define DPLL2_CFGCR2 0x6C04C
#define DPLL3_CFGCR2 0x6C054
#define DPLL_CFGCR2_QDIV_RATIO_MASK (0xff<<8)
-#define DPLL_CFGCR2_QDIV_RATIO(x) (x<<8)
-#define DPLL_CFGCR2_QDIV_MODE(x) (x<<7)
+#define DPLL_CFGCR2_QDIV_RATIO(x) ((x)<<8)
+#define DPLL_CFGCR2_QDIV_MODE(x) ((x)<<7)
#define DPLL_CFGCR2_KDIV_MASK (3<<5)
-#define DPLL_CFGCR2_KDIV(x) (x<<5)
+#define DPLL_CFGCR2_KDIV(x) ((x)<<5)
#define DPLL_CFGCR2_KDIV_5 (0<<5)
#define DPLL_CFGCR2_KDIV_2 (1<<5)
#define DPLL_CFGCR2_KDIV_3 (2<<5)
#define DPLL_CFGCR2_KDIV_1 (3<<5)
#define DPLL_CFGCR2_PDIV_MASK (7<<2)
-#define DPLL_CFGCR2_PDIV(x) (x<<2)
+#define DPLL_CFGCR2_PDIV(x) ((x)<<2)
#define DPLL_CFGCR2_PDIV_1 (0<<2)
#define DPLL_CFGCR2_PDIV_2 (1<<2)
#define DPLL_CFGCR2_PDIV_3 (2<<2)
@@ -7979,7 +7979,7 @@ enum skl_disp_power_wells {
#define VIRTUAL_CHANNEL_SHIFT 6
#define VIRTUAL_CHANNEL_MASK (3 << 6)
#define DATA_TYPE_SHIFT 0
-#define DATA_TYPE_MASK (3f << 0)
+#define DATA_TYPE_MASK (0x3f << 0)
/* data type values, see include/video/mipi_display.h */
#define _MIPIA_GEN_FIFO_STAT (dev_priv->mipi_mmio_base + 0xb074)
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 1ccac618468e..2d9182189422 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -122,12 +122,24 @@ int i915_save_state(struct drm_device *dev)
dev_priv->regfile.saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
/* Scratch space */
- for (i = 0; i < 16; i++) {
- dev_priv->regfile.saveSWF0[i] = I915_READ(SWF00 + (i << 2));
- dev_priv->regfile.saveSWF1[i] = I915_READ(SWF10 + (i << 2));
+ if (IS_GEN2(dev_priv) && IS_MOBILE(dev_priv)) {
+ for (i = 0; i < 7; i++) {
+ dev_priv->regfile.saveSWF0[i] = I915_READ(SWF0(i));
+ dev_priv->regfile.saveSWF1[i] = I915_READ(SWF1(i));
+ }
+ for (i = 0; i < 3; i++)
+ dev_priv->regfile.saveSWF3[i] = I915_READ(SWF3(i));
+ } else if (IS_GEN2(dev_priv)) {
+ for (i = 0; i < 7; i++)
+ dev_priv->regfile.saveSWF1[i] = I915_READ(SWF1(i));
+ } else if (HAS_GMCH_DISPLAY(dev_priv)) {
+ for (i = 0; i < 16; i++) {
+ dev_priv->regfile.saveSWF0[i] = I915_READ(SWF0(i));
+ dev_priv->regfile.saveSWF1[i] = I915_READ(SWF1(i));
+ }
+ for (i = 0; i < 3; i++)
+ dev_priv->regfile.saveSWF3[i] = I915_READ(SWF3(i));
}
- for (i = 0; i < 3; i++)
- dev_priv->regfile.saveSWF2[i] = I915_READ(SWF30 + (i << 2));
mutex_unlock(&dev->struct_mutex);
@@ -156,12 +168,25 @@ int i915_restore_state(struct drm_device *dev)
/* Memory arbitration state */
I915_WRITE(MI_ARB_STATE, dev_priv->regfile.saveMI_ARB_STATE | 0xffff0000);
- for (i = 0; i < 16; i++) {
- I915_WRITE(SWF00 + (i << 2), dev_priv->regfile.saveSWF0[i]);
- I915_WRITE(SWF10 + (i << 2), dev_priv->regfile.saveSWF1[i]);
+ /* Scratch space */
+ if (IS_GEN2(dev_priv) && IS_MOBILE(dev_priv)) {
+ for (i = 0; i < 7; i++) {
+ I915_WRITE(SWF0(i), dev_priv->regfile.saveSWF0[i]);
+ I915_WRITE(SWF1(i), dev_priv->regfile.saveSWF1[i]);
+ }
+ for (i = 0; i < 3; i++)
+ I915_WRITE(SWF3(i), dev_priv->regfile.saveSWF3[i]);
+ } else if (IS_GEN2(dev_priv)) {
+ for (i = 0; i < 7; i++)
+ I915_WRITE(SWF1(i), dev_priv->regfile.saveSWF1[i]);
+ } else if (HAS_GMCH_DISPLAY(dev_priv)) {
+ for (i = 0; i < 16; i++) {
+ I915_WRITE(SWF0(i), dev_priv->regfile.saveSWF0[i]);
+ I915_WRITE(SWF1(i), dev_priv->regfile.saveSWF1[i]);
+ }
+ for (i = 0; i < 3; i++)
+ I915_WRITE(SWF3(i), dev_priv->regfile.saveSWF3[i]);
}
- for (i = 0; i < 3; i++)
- I915_WRITE(SWF30 + (i << 2), dev_priv->regfile.saveSWF2[i]);
mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c
index 8b13b9d0373a..eb638a1e69d2 100644
--- a/drivers/gpu/drm/i915/intel_acpi.c
+++ b/drivers/gpu/drm/i915/intel_acpi.c
@@ -5,7 +5,6 @@
*/
#include <linux/pci.h>
#include <linux/acpi.h>
-#include <linux/vga_switcheroo.h>
#include <drm/drmP.h>
#include "i915_drv.h"
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 05b12032d262..f1975f267710 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -94,7 +94,6 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
__drm_atomic_helper_crtc_duplicate_state(crtc, &crtc_state->base);
crtc_state->update_pipe = false;
- crtc_state->disable_lp_wm = false;
return &crtc_state->base;
}
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index 56c2f54801c4..4dccd9b003a1 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -61,21 +61,21 @@ static const struct {
int clock;
u32 config;
} hdmi_audio_clock[] = {
- { DIV_ROUND_UP(25200 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 },
+ { 25175, AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 },
{ 25200, AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 }, /* default per bspec */
{ 27000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 },
- { 27000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 },
+ { 27027, AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 },
{ 54000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 },
- { 54000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 },
- { DIV_ROUND_UP(74250 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 },
+ { 54054, AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 },
+ { 74176, AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 },
{ 74250, AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 },
- { DIV_ROUND_UP(148500 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 },
+ { 148352, AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 },
{ 148500, AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 },
};
/* HDMI N/CTS table */
#define TMDS_297M 297000
-#define TMDS_296M DIV_ROUND_UP(297000 * 1000, 1001)
+#define TMDS_296M 296703
static const struct {
int sample_rate;
int clock;
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 68421c273c8c..ce82f9c7df24 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -1231,20 +1231,13 @@ static const struct dmi_system_id intel_no_opregion_vbt[] = {
{ }
};
-static const struct bdb_header *validate_vbt(const void __iomem *_base,
+static const struct bdb_header *validate_vbt(const void *base,
size_t size,
- const void __iomem *_vbt,
+ const void *_vbt,
const char *source)
{
- /*
- * This is the one place where we explicitly discard the address space
- * (__iomem) of the BIOS/VBT. (And this will cause a sparse complaint.)
- * From now on everything is based on 'base', and treated as regular
- * memory.
- */
- const void *base = (const void *) _base;
- size_t offset = _vbt - _base;
- const struct vbt_header *vbt = base + offset;
+ size_t offset = _vbt - base;
+ const struct vbt_header *vbt = _vbt;
const struct bdb_header *bdb;
if (offset + sizeof(struct vbt_header) > size) {
@@ -1282,7 +1275,15 @@ static const struct bdb_header *find_vbt(void __iomem *bios, size_t size)
/* Scour memory looking for the VBT signature. */
for (i = 0; i + 4 < size; i++) {
if (ioread32(bios + i) == *((const u32 *) "$VBT")) {
- bdb = validate_vbt(bios, size, bios + i, "PCI ROM");
+ /*
+ * This is the one place where we explicitly discard the
+ * address space (__iomem) of the BIOS/VBT. From now on
+ * everything is based on 'base', and treated as regular
+ * memory.
+ */
+ void *_bios = (void __force *) bios;
+
+ bdb = validate_vbt(_bios, size, _bios + i, "PCI ROM");
break;
}
}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index cddb0c692334..82128b95785c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1157,12 +1157,10 @@ static const char *state_string(bool enabled)
void assert_pll(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state)
{
- int reg;
u32 val;
bool cur_state;
- reg = DPLL(pipe);
- val = I915_READ(reg);
+ val = I915_READ(DPLL(pipe));
cur_state = !!(val & DPLL_VCO_ENABLE);
I915_STATE_WARN(cur_state != state,
"PLL state assertion failure (expected %s, current %s)\n",
@@ -1219,20 +1217,16 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv,
static void assert_fdi_tx(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state)
{
- int reg;
- u32 val;
bool cur_state;
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
pipe);
if (HAS_DDI(dev_priv->dev)) {
/* DDI does not have a specific FDI_TX register */
- reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);
- val = I915_READ(reg);
+ u32 val = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
cur_state = !!(val & TRANS_DDI_FUNC_ENABLE);
} else {
- reg = FDI_TX_CTL(pipe);
- val = I915_READ(reg);
+ u32 val = I915_READ(FDI_TX_CTL(pipe));
cur_state = !!(val & FDI_TX_ENABLE);
}
I915_STATE_WARN(cur_state != state,
@@ -1245,12 +1239,10 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv,
static void assert_fdi_rx(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state)
{
- int reg;
u32 val;
bool cur_state;
- reg = FDI_RX_CTL(pipe);
- val = I915_READ(reg);
+ val = I915_READ(FDI_RX_CTL(pipe));
cur_state = !!(val & FDI_RX_ENABLE);
I915_STATE_WARN(cur_state != state,
"FDI RX state assertion failure (expected %s, current %s)\n",
@@ -1262,7 +1254,6 @@ static void assert_fdi_rx(struct drm_i915_private *dev_priv,
static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
- int reg;
u32 val;
/* ILK FDI PLL is always enabled */
@@ -1273,20 +1264,17 @@ static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv,
if (HAS_DDI(dev_priv->dev))
return;
- reg = FDI_TX_CTL(pipe);
- val = I915_READ(reg);
+ val = I915_READ(FDI_TX_CTL(pipe));
I915_STATE_WARN(!(val & FDI_TX_PLL_ENABLE), "FDI TX PLL assertion failure, should be active but is disabled\n");
}
void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state)
{
- int reg;
u32 val;
bool cur_state;
- reg = FDI_RX_CTL(pipe);
- val = I915_READ(reg);
+ val = I915_READ(FDI_RX_CTL(pipe));
cur_state = !!(val & FDI_RX_PLL_ENABLE);
I915_STATE_WARN(cur_state != state,
"FDI RX PLL assertion failure (expected %s, current %s)\n",
@@ -1356,8 +1344,6 @@ static void assert_cursor(struct drm_i915_private *dev_priv,
void assert_pipe(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state)
{
- int reg;
- u32 val;
bool cur_state;
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
pipe);
@@ -1371,8 +1357,7 @@ void assert_pipe(struct drm_i915_private *dev_priv,
POWER_DOMAIN_TRANSCODER(cpu_transcoder))) {
cur_state = false;
} else {
- reg = PIPECONF(cpu_transcoder);
- val = I915_READ(reg);
+ u32 val = I915_READ(PIPECONF(cpu_transcoder));
cur_state = !!(val & PIPECONF_ENABLE);
}
@@ -1384,12 +1369,10 @@ void assert_pipe(struct drm_i915_private *dev_priv,
static void assert_plane(struct drm_i915_private *dev_priv,
enum plane plane, bool state)
{
- int reg;
u32 val;
bool cur_state;
- reg = DSPCNTR(plane);
- val = I915_READ(reg);
+ val = I915_READ(DSPCNTR(plane));
cur_state = !!(val & DISPLAY_PLANE_ENABLE);
I915_STATE_WARN(cur_state != state,
"plane %c assertion failure (expected %s, current %s)\n",
@@ -1403,14 +1386,11 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
struct drm_device *dev = dev_priv->dev;
- int reg, i;
- u32 val;
- int cur_pipe;
+ int i;
/* Primary planes are fixed to pipes on gen4+ */
if (INTEL_INFO(dev)->gen >= 4) {
- reg = DSPCNTR(pipe);
- val = I915_READ(reg);
+ u32 val = I915_READ(DSPCNTR(pipe));
I915_STATE_WARN(val & DISPLAY_PLANE_ENABLE,
"plane %c assertion failure, should be disabled but not\n",
plane_name(pipe));
@@ -1419,9 +1399,8 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv,
/* Need to check both planes against the pipe */
for_each_pipe(dev_priv, i) {
- reg = DSPCNTR(i);
- val = I915_READ(reg);
- cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
+ u32 val = I915_READ(DSPCNTR(i));
+ enum pipe cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
DISPPLANE_SEL_PIPE_SHIFT;
I915_STATE_WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe,
"plane %c assertion failure, should be off on pipe %c but is still active\n",
@@ -1433,33 +1412,29 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
struct drm_device *dev = dev_priv->dev;
- int reg, sprite;
- u32 val;
+ int sprite;
if (INTEL_INFO(dev)->gen >= 9) {
for_each_sprite(dev_priv, pipe, sprite) {
- val = I915_READ(PLANE_CTL(pipe, sprite));
+ u32 val = I915_READ(PLANE_CTL(pipe, sprite));
I915_STATE_WARN(val & PLANE_CTL_ENABLE,
"plane %d assertion failure, should be off on pipe %c but is still active\n",
sprite, pipe_name(pipe));
}
} else if (IS_VALLEYVIEW(dev)) {
for_each_sprite(dev_priv, pipe, sprite) {
- reg = SPCNTR(pipe, sprite);
- val = I915_READ(reg);
+ u32 val = I915_READ(SPCNTR(pipe, sprite));
I915_STATE_WARN(val & SP_ENABLE,
"sprite %c assertion failure, should be off on pipe %c but is still active\n",
sprite_name(pipe, sprite), pipe_name(pipe));
}
} else if (INTEL_INFO(dev)->gen >= 7) {
- reg = SPRCTL(pipe);
- val = I915_READ(reg);
+ u32 val = I915_READ(SPRCTL(pipe));
I915_STATE_WARN(val & SPRITE_ENABLE,
"sprite %c assertion failure, should be off on pipe %c but is still active\n",
plane_name(pipe), pipe_name(pipe));
} else if (INTEL_INFO(dev)->gen >= 5) {
- reg = DVSCNTR(pipe);
- val = I915_READ(reg);
+ u32 val = I915_READ(DVSCNTR(pipe));
I915_STATE_WARN(val & DVS_ENABLE,
"sprite %c assertion failure, should be off on pipe %c but is still active\n",
plane_name(pipe), pipe_name(pipe));
@@ -1488,12 +1463,10 @@ static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
- int reg;
u32 val;
bool enabled;
- reg = PCH_TRANSCONF(pipe);
- val = I915_READ(reg);
+ val = I915_READ(PCH_TRANSCONF(pipe));
enabled = !!(val & TRANS_ENABLE);
I915_STATE_WARN(enabled,
"transcoder assertion failed, should be off on pipe %c but is still active\n",
@@ -1600,21 +1573,18 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
- int reg;
u32 val;
assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_B, TRANS_DP_PORT_SEL_B);
assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_C, TRANS_DP_PORT_SEL_C);
assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_D, TRANS_DP_PORT_SEL_D);
- reg = PCH_ADPA;
- val = I915_READ(reg);
+ val = I915_READ(PCH_ADPA);
I915_STATE_WARN(adpa_pipe_enabled(dev_priv, pipe, val),
"PCH VGA enabled on transcoder %c, should be disabled\n",
pipe_name(pipe));
- reg = PCH_LVDS;
- val = I915_READ(reg);
+ val = I915_READ(PCH_LVDS);
I915_STATE_WARN(lvds_pipe_enabled(dev_priv, pipe, val),
"PCH LVDS enabled on transcoder %c, should be disabled\n",
pipe_name(pipe));
@@ -4804,6 +4774,7 @@ static void intel_post_plane_update(struct intel_crtc *crtc)
struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_plane *plane;
if (atomic->wait_vblank)
intel_wait_for_vblank(dev, crtc->pipe);
@@ -4822,6 +4793,10 @@ static void intel_post_plane_update(struct intel_crtc *crtc)
if (atomic->post_enable_primary)
intel_post_enable_primary(&crtc->base);
+ drm_for_each_plane_mask(plane, dev, atomic->update_sprite_watermarks)
+ intel_update_sprite_watermarks(plane, &crtc->base,
+ 0, 0, 0, false, false);
+
memset(atomic, 0, sizeof(*atomic));
}
@@ -9952,7 +9927,7 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
}
cntl |= pipe << 28; /* Connect to correct pipe */
- if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+ if (HAS_DDI(dev))
cntl |= CURSOR_PIPE_CSC_ENABLE;
}
@@ -10822,7 +10797,7 @@ static bool page_flip_finished(struct intel_crtc *crtc)
*/
return (I915_READ(DSPSURFLIVE(crtc->plane)) & ~0xfff) ==
crtc->unpin_work->gtt_offset &&
- g4x_flip_count_after_eq(I915_READ(PIPE_FLIPCOUNT_GM45(crtc->pipe)),
+ g4x_flip_count_after_eq(I915_READ(PIPE_FLIPCOUNT_G4X(crtc->pipe)),
crtc->unpin_work->flip_count);
}
@@ -10848,11 +10823,11 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane)
spin_unlock_irqrestore(&dev->event_lock, flags);
}
-static inline void intel_mark_page_flip_active(struct intel_crtc *intel_crtc)
+static inline void intel_mark_page_flip_active(struct intel_unpin_work *work)
{
/* Ensure that the work item is consistent when activating it ... */
smp_wmb();
- atomic_set(&intel_crtc->unpin_work->pending, INTEL_FLIP_PENDING);
+ atomic_set(&work->pending, INTEL_FLIP_PENDING);
/* and that it is marked active as soon as the irq could fire. */
smp_wmb();
}
@@ -10888,7 +10863,7 @@ static int intel_gen2_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
intel_ring_emit(ring, 0); /* aux display base address, unused */
- intel_mark_page_flip_active(intel_crtc);
+ intel_mark_page_flip_active(intel_crtc->unpin_work);
return 0;
}
@@ -10920,7 +10895,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
intel_ring_emit(ring, MI_NOOP);
- intel_mark_page_flip_active(intel_crtc);
+ intel_mark_page_flip_active(intel_crtc->unpin_work);
return 0;
}
@@ -10959,7 +10934,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev,
pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
intel_ring_emit(ring, pf | pipesrc);
- intel_mark_page_flip_active(intel_crtc);
+ intel_mark_page_flip_active(intel_crtc->unpin_work);
return 0;
}
@@ -10995,7 +10970,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev,
pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
intel_ring_emit(ring, pf | pipesrc);
- intel_mark_page_flip_active(intel_crtc);
+ intel_mark_page_flip_active(intel_crtc->unpin_work);
return 0;
}
@@ -11090,7 +11065,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
intel_ring_emit(ring, (MI_NOOP));
- intel_mark_page_flip_active(intel_crtc);
+ intel_mark_page_flip_active(intel_crtc->unpin_work);
return 0;
}
@@ -11121,7 +11096,8 @@ static bool use_mmio_flip(struct intel_engine_cs *ring,
return ring != i915_gem_request_get_ring(obj->last_write_req);
}
-static void skl_do_mmio_flip(struct intel_crtc *intel_crtc)
+static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
+ struct intel_unpin_work *work)
{
struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -11162,11 +11138,12 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc)
I915_WRITE(PLANE_CTL(pipe, 0), ctl);
I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
- I915_WRITE(PLANE_SURF(pipe, 0), intel_crtc->unpin_work->gtt_offset);
+ I915_WRITE(PLANE_SURF(pipe, 0), work->gtt_offset);
POSTING_READ(PLANE_SURF(pipe, 0));
}
-static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc)
+static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc,
+ struct intel_unpin_work *work)
{
struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -11186,31 +11163,36 @@ static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc)
I915_WRITE(reg, dspcntr);
- I915_WRITE(DSPSURF(intel_crtc->plane),
- intel_crtc->unpin_work->gtt_offset);
+ I915_WRITE(DSPSURF(intel_crtc->plane), work->gtt_offset);
POSTING_READ(DSPSURF(intel_crtc->plane));
-
}
/*
* XXX: This is the temporary way to update the plane registers until we get
* around to using the usual plane update functions for MMIO flips
*/
-static void intel_do_mmio_flip(struct intel_crtc *intel_crtc)
+static void intel_do_mmio_flip(struct intel_mmio_flip *mmio_flip)
{
- struct drm_device *dev = intel_crtc->base.dev;
+ struct intel_crtc *crtc = mmio_flip->crtc;
+ struct intel_unpin_work *work;
- intel_mark_page_flip_active(intel_crtc);
+ spin_lock_irq(&crtc->base.dev->event_lock);
+ work = crtc->unpin_work;
+ spin_unlock_irq(&crtc->base.dev->event_lock);
+ if (work == NULL)
+ return;
- intel_pipe_update_start(intel_crtc);
+ intel_mark_page_flip_active(work);
- if (INTEL_INFO(dev)->gen >= 9)
- skl_do_mmio_flip(intel_crtc);
+ intel_pipe_update_start(crtc);
+
+ if (INTEL_INFO(mmio_flip->i915)->gen >= 9)
+ skl_do_mmio_flip(crtc, work);
else
/* use_mmio_flip() retricts MMIO flips to ilk+ */
- ilk_do_mmio_flip(intel_crtc);
+ ilk_do_mmio_flip(crtc, work);
- intel_pipe_update_end(intel_crtc);
+ intel_pipe_update_end(crtc);
}
static void intel_mmio_flip_work_func(struct work_struct *work)
@@ -11218,15 +11200,15 @@ static void intel_mmio_flip_work_func(struct work_struct *work)
struct intel_mmio_flip *mmio_flip =
container_of(work, struct intel_mmio_flip, work);
- if (mmio_flip->req)
+ if (mmio_flip->req) {
WARN_ON(__i915_wait_request(mmio_flip->req,
mmio_flip->crtc->reset_counter,
false, NULL,
&mmio_flip->i915->rps.mmioflips));
+ i915_gem_request_unreference__unlocked(mmio_flip->req);
+ }
- intel_do_mmio_flip(mmio_flip->crtc);
-
- i915_gem_request_unreference__unlocked(mmio_flip->req);
+ intel_do_mmio_flip(mmio_flip);
kfree(mmio_flip);
}
@@ -11427,7 +11409,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
intel_crtc->reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
- work->flip_count = I915_READ(PIPE_FLIPCOUNT_GM45(pipe)) + 1;
+ work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1;
if (IS_VALLEYVIEW(dev)) {
ring = &dev_priv->ring[BCS];
@@ -11577,30 +11559,16 @@ retry:
static bool intel_wm_need_update(struct drm_plane *plane,
struct drm_plane_state *state)
{
- struct intel_plane_state *new = to_intel_plane_state(state);
- struct intel_plane_state *cur = to_intel_plane_state(plane->state);
-
- /* Update watermarks on tiling or size changes. */
+ /* Update watermarks on tiling changes. */
if (!plane->state->fb || !state->fb ||
plane->state->fb->modifier[0] != state->fb->modifier[0] ||
- plane->state->rotation != state->rotation ||
- drm_rect_width(&new->src) != drm_rect_width(&cur->src) ||
- drm_rect_height(&new->src) != drm_rect_height(&cur->src) ||
- drm_rect_width(&new->dst) != drm_rect_width(&cur->dst) ||
- drm_rect_height(&new->dst) != drm_rect_height(&cur->dst))
+ plane->state->rotation != state->rotation)
return true;
- return false;
-}
-
-static bool needs_scaling(struct intel_plane_state *state)
-{
- int src_w = drm_rect_width(&state->src) >> 16;
- int src_h = drm_rect_height(&state->src) >> 16;
- int dst_w = drm_rect_width(&state->dst);
- int dst_h = drm_rect_height(&state->dst);
+ if (plane->state->crtc_w != state->crtc_w)
+ return true;
- return (src_w != dst_w || src_h != dst_h);
+ return false;
}
int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
@@ -11618,6 +11586,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
bool mode_changed = needs_modeset(crtc_state);
bool was_crtc_enabled = crtc->state->active;
bool is_crtc_enabled = crtc_state->active;
+
bool turn_off, turn_on, visible, was_visible;
struct drm_framebuffer *fb = plane_state->fb;
@@ -11735,23 +11704,11 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
case DRM_PLANE_TYPE_CURSOR:
break;
case DRM_PLANE_TYPE_OVERLAY:
- /*
- * WaCxSRDisabledForSpriteScaling:ivb
- *
- * cstate->update_wm was already set above, so this flag will
- * take effect when we commit and program watermarks.
- */
- if (IS_IVYBRIDGE(dev) &&
- needs_scaling(to_intel_plane_state(plane_state)) &&
- !needs_scaling(old_plane_state)) {
- to_intel_crtc_state(crtc_state)->disable_lp_wm = true;
- } else if (turn_off && !mode_changed) {
+ if (turn_off && !mode_changed) {
intel_crtc->atomic.wait_vblank = true;
intel_crtc->atomic.update_sprite_watermarks |=
1 << i;
}
-
- break;
}
return 0;
}
@@ -14942,13 +14899,12 @@ intel_check_plane_mapping(struct intel_crtc *crtc)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 reg, val;
+ u32 val;
if (INTEL_INFO(dev)->num_pipes == 1)
return true;
- reg = DSPCNTR(!crtc->plane);
- val = I915_READ(reg);
+ val = I915_READ(DSPCNTR(!crtc->plane));
if ((val & DISPLAY_PLANE_ENABLE) &&
(!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe))
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 18bcfbe0b8ba..09bdd94ca3ba 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -574,8 +574,6 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
edp_notifier);
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 pp_div;
- u32 pp_ctrl_reg, pp_div_reg;
if (!is_edp(intel_dp) || code != SYS_RESTART)
return 0;
@@ -584,6 +582,8 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
if (IS_VALLEYVIEW(dev)) {
enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
+ u32 pp_ctrl_reg, pp_div_reg;
+ u32 pp_div;
pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
pp_div_reg = VLV_PIPE_PP_DIVISOR(pipe);
@@ -5536,7 +5536,6 @@ static void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
struct intel_dp *intel_dp = dev_priv->drrs.dp;
struct intel_crtc_state *config = NULL;
struct intel_crtc *intel_crtc = NULL;
- u32 reg, val;
enum drrs_refresh_rate_type index = DRRS_HIGH_RR;
if (refresh_rate <= 0) {
@@ -5598,9 +5597,10 @@ static void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
DRM_ERROR("Unsupported refreshrate type\n");
}
} else if (INTEL_INFO(dev)->gen > 6) {
- reg = PIPECONF(intel_crtc->config->cpu_transcoder);
- val = I915_READ(reg);
+ u32 reg = PIPECONF(intel_crtc->config->cpu_transcoder);
+ u32 val;
+ val = I915_READ(reg);
if (index > DRRS_HIGH_RR) {
if (IS_VALLEYVIEW(dev))
val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 91b6b4060333..0598932ce623 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -468,9 +468,6 @@ struct intel_crtc_state {
/* w/a for waiting 2 vblanks during crtc enable */
enum pipe hsw_workaround_pipe;
-
- /* IVB sprite scaling w/a (WaCxSRDisabledForSpriteScaling:ivb) */
- bool disable_lp_wm;
};
struct vlv_wm_state {
@@ -1399,6 +1396,12 @@ void intel_init_clock_gating(struct drm_device *dev);
void intel_suspend_hw(struct drm_device *dev);
int ilk_wm_max_level(const struct drm_device *dev);
void intel_update_watermarks(struct drm_crtc *crtc);
+void intel_update_sprite_watermarks(struct drm_plane *plane,
+ struct drm_crtc *crtc,
+ uint32_t sprite_width,
+ uint32_t sprite_height,
+ int pixel_size,
+ bool enabled, bool scaled);
void intel_init_pm(struct drm_device *dev);
void intel_pm_setup(struct drm_device *dev);
void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 3b28ed3237d3..9eafa191cee2 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -113,17 +113,18 @@ static u32 hsw_infoframe_enable(enum hdmi_infoframe_type type)
}
}
-static u32 hsw_infoframe_data_reg(enum hdmi_infoframe_type type,
- enum transcoder cpu_transcoder,
- struct drm_i915_private *dev_priv)
+static u32 hsw_dip_data_reg(struct drm_i915_private *dev_priv,
+ enum transcoder cpu_transcoder,
+ enum hdmi_infoframe_type type,
+ int i)
{
switch (type) {
case HDMI_INFOFRAME_TYPE_AVI:
- return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder);
+ return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder, i);
case HDMI_INFOFRAME_TYPE_SPD:
- return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder);
+ return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder, i);
case HDMI_INFOFRAME_TYPE_VENDOR:
- return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder);
+ return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder, i);
default:
DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
return 0;
@@ -365,14 +366,13 @@ static void hsw_write_infoframe(struct drm_encoder *encoder,
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
- u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config->cpu_transcoder);
+ enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
+ u32 ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder);
u32 data_reg;
int i;
u32 val = I915_READ(ctl_reg);
- data_reg = hsw_infoframe_data_reg(type,
- intel_crtc->config->cpu_transcoder,
- dev_priv);
+ data_reg = hsw_dip_data_reg(dev_priv, cpu_transcoder, type, 0);
if (data_reg == 0)
return;
@@ -381,12 +381,14 @@ static void hsw_write_infoframe(struct drm_encoder *encoder,
mmiowb();
for (i = 0; i < len; i += 4) {
- I915_WRITE(data_reg + i, *data);
+ I915_WRITE(hsw_dip_data_reg(dev_priv, cpu_transcoder,
+ type, i >> 2), *data);
data++;
}
/* Write every possible data byte to force correct ECC calculation. */
for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
- I915_WRITE(data_reg + i, 0);
+ I915_WRITE(hsw_dip_data_reg(dev_priv, cpu_transcoder,
+ type, i >> 2), 0);
mmiowb();
val |= hsw_infoframe_enable(type);
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index a64f26c670af..1369fc41d039 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -114,8 +114,8 @@ intel_i2c_reset(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- I915_WRITE(dev_priv->gpio_mmio_base + GMBUS0, 0);
- I915_WRITE(dev_priv->gpio_mmio_base + GMBUS4, 0);
+ I915_WRITE(GMBUS0, 0);
+ I915_WRITE(GMBUS4, 0);
}
static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable)
@@ -261,7 +261,6 @@ gmbus_wait_hw_status(struct drm_i915_private *dev_priv,
u32 gmbus4_irq_en)
{
int i;
- int reg_offset = dev_priv->gpio_mmio_base;
u32 gmbus2 = 0;
DEFINE_WAIT(wait);
@@ -271,13 +270,13 @@ gmbus_wait_hw_status(struct drm_i915_private *dev_priv,
/* Important: The hw handles only the first bit, so set only one! Since
* we also need to check for NAKs besides the hw ready/idle signal, we
* need to wake up periodically and check that ourselves. */
- I915_WRITE(GMBUS4 + reg_offset, gmbus4_irq_en);
+ I915_WRITE(GMBUS4, gmbus4_irq_en);
for (i = 0; i < msecs_to_jiffies_timeout(50); i++) {
prepare_to_wait(&dev_priv->gmbus_wait_queue, &wait,
TASK_UNINTERRUPTIBLE);
- gmbus2 = I915_READ_NOTRACE(GMBUS2 + reg_offset);
+ gmbus2 = I915_READ_NOTRACE(GMBUS2);
if (gmbus2 & (GMBUS_SATOER | gmbus2_status))
break;
@@ -285,7 +284,7 @@ gmbus_wait_hw_status(struct drm_i915_private *dev_priv,
}
finish_wait(&dev_priv->gmbus_wait_queue, &wait);
- I915_WRITE(GMBUS4 + reg_offset, 0);
+ I915_WRITE(GMBUS4, 0);
if (gmbus2 & GMBUS_SATOER)
return -ENXIO;
@@ -298,20 +297,19 @@ static int
gmbus_wait_idle(struct drm_i915_private *dev_priv)
{
int ret;
- int reg_offset = dev_priv->gpio_mmio_base;
-#define C ((I915_READ_NOTRACE(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0)
+#define C ((I915_READ_NOTRACE(GMBUS2) & GMBUS_ACTIVE) == 0)
if (!HAS_GMBUS_IRQ(dev_priv->dev))
return wait_for(C, 10);
/* Important: The hw handles only the first bit, so set only one! */
- I915_WRITE(GMBUS4 + reg_offset, GMBUS_IDLE_EN);
+ I915_WRITE(GMBUS4, GMBUS_IDLE_EN);
ret = wait_event_timeout(dev_priv->gmbus_wait_queue, C,
msecs_to_jiffies_timeout(10));
- I915_WRITE(GMBUS4 + reg_offset, 0);
+ I915_WRITE(GMBUS4, 0);
if (ret)
return 0;
@@ -325,9 +323,7 @@ gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
unsigned short addr, u8 *buf, unsigned int len,
u32 gmbus1_index)
{
- int reg_offset = dev_priv->gpio_mmio_base;
-
- I915_WRITE(GMBUS1 + reg_offset,
+ I915_WRITE(GMBUS1,
gmbus1_index |
GMBUS_CYCLE_WAIT |
(len << GMBUS_BYTE_COUNT_SHIFT) |
@@ -342,7 +338,7 @@ gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
if (ret)
return ret;
- val = I915_READ(GMBUS3 + reg_offset);
+ val = I915_READ(GMBUS3);
do {
*buf++ = val & 0xff;
val >>= 8;
@@ -380,7 +376,6 @@ static int
gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv,
unsigned short addr, u8 *buf, unsigned int len)
{
- int reg_offset = dev_priv->gpio_mmio_base;
unsigned int chunk_size = len;
u32 val, loop;
@@ -390,8 +385,8 @@ gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv,
len -= 1;
}
- I915_WRITE(GMBUS3 + reg_offset, val);
- I915_WRITE(GMBUS1 + reg_offset,
+ I915_WRITE(GMBUS3, val);
+ I915_WRITE(GMBUS1,
GMBUS_CYCLE_WAIT |
(chunk_size << GMBUS_BYTE_COUNT_SHIFT) |
(addr << GMBUS_SLAVE_ADDR_SHIFT) |
@@ -404,7 +399,7 @@ gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv,
val |= *buf++ << (8 * loop);
} while (--len && ++loop < 4);
- I915_WRITE(GMBUS3 + reg_offset, val);
+ I915_WRITE(GMBUS3, val);
ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY,
GMBUS_HW_RDY_EN);
@@ -452,7 +447,6 @@ gmbus_is_index_read(struct i2c_msg *msgs, int i, int num)
static int
gmbus_xfer_index_read(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
{
- int reg_offset = dev_priv->gpio_mmio_base;
u32 gmbus1_index = 0;
u32 gmbus5 = 0;
int ret;
@@ -466,13 +460,13 @@ gmbus_xfer_index_read(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
/* GMBUS5 holds 16-bit index */
if (gmbus5)
- I915_WRITE(GMBUS5 + reg_offset, gmbus5);
+ I915_WRITE(GMBUS5, gmbus5);
ret = gmbus_xfer_read(dev_priv, &msgs[1], gmbus1_index);
/* Clear GMBUS5 after each index transfer */
if (gmbus5)
- I915_WRITE(GMBUS5 + reg_offset, 0);
+ I915_WRITE(GMBUS5, 0);
return ret;
}
@@ -486,7 +480,7 @@ gmbus_xfer(struct i2c_adapter *adapter,
struct intel_gmbus,
adapter);
struct drm_i915_private *dev_priv = bus->dev_priv;
- int i = 0, inc, try = 0, reg_offset;
+ int i = 0, inc, try = 0;
int ret = 0;
intel_aux_display_runtime_get(dev_priv);
@@ -497,10 +491,8 @@ gmbus_xfer(struct i2c_adapter *adapter,
goto out;
}
- reg_offset = dev_priv->gpio_mmio_base;
-
retry:
- I915_WRITE(GMBUS0 + reg_offset, bus->reg0);
+ I915_WRITE(GMBUS0, bus->reg0);
for (; i < num; i += inc) {
inc = 1;
@@ -530,7 +522,7 @@ retry:
* a STOP on the very first cycle. To simplify the code we
* unconditionally generate the STOP condition with an additional gmbus
* cycle. */
- I915_WRITE(GMBUS1 + reg_offset, GMBUS_CYCLE_STOP | GMBUS_SW_RDY);
+ I915_WRITE(GMBUS1, GMBUS_CYCLE_STOP | GMBUS_SW_RDY);
/* Mark the GMBUS interface as disabled after waiting for idle.
* We will re-enable it at the start of the next xfer,
@@ -541,7 +533,7 @@ retry:
adapter->name);
ret = -ETIMEDOUT;
}
- I915_WRITE(GMBUS0 + reg_offset, 0);
+ I915_WRITE(GMBUS0, 0);
ret = ret ?: i;
goto out;
@@ -570,9 +562,9 @@ clear_err:
* of resetting the GMBUS controller and so clearing the
* BUS_ERROR raised by the slave's NAK.
*/
- I915_WRITE(GMBUS1 + reg_offset, GMBUS_SW_CLR_INT);
- I915_WRITE(GMBUS1 + reg_offset, 0);
- I915_WRITE(GMBUS0 + reg_offset, 0);
+ I915_WRITE(GMBUS1, GMBUS_SW_CLR_INT);
+ I915_WRITE(GMBUS1, 0);
+ I915_WRITE(GMBUS0, 0);
DRM_DEBUG_KMS("GMBUS [%s] NAK for addr: %04x %c(%d)\n",
adapter->name, msgs[i].addr,
@@ -595,7 +587,7 @@ clear_err:
timeout:
DRM_INFO("GMBUS [%s] timed out, falling back to bit banging on pin %d\n",
bus->adapter.name, bus->reg0 & 0xff);
- I915_WRITE(GMBUS0 + reg_offset, 0);
+ I915_WRITE(GMBUS0, 0);
/* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */
bus->force_bit = 1;
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 5e70acf944c3..7f39b8ad88ae 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -98,15 +98,11 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
{
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 lvds_reg, tmp, flags = 0;
+ struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
+ u32 tmp, flags = 0;
int dotclock;
- if (HAS_PCH_SPLIT(dev))
- lvds_reg = PCH_LVDS;
- else
- lvds_reg = LVDS;
-
- tmp = I915_READ(lvds_reg);
+ tmp = I915_READ(lvds_encoder->reg);
if (tmp & LVDS_HSYNC_POLARITY)
flags |= DRM_MODE_FLAG_NHSYNC;
else
@@ -943,6 +939,7 @@ void intel_lvds_init(struct drm_device *dev)
struct drm_display_mode *downclock_mode = NULL;
struct edid *edid;
struct drm_crtc *crtc;
+ u32 lvds_reg;
u32 lvds;
int pipe;
u8 pin;
@@ -965,8 +962,15 @@ void intel_lvds_init(struct drm_device *dev)
if (dmi_check_system(intel_no_lvds))
return;
+ if (HAS_PCH_SPLIT(dev))
+ lvds_reg = PCH_LVDS;
+ else
+ lvds_reg = LVDS;
+
+ lvds = I915_READ(lvds_reg);
+
if (HAS_PCH_SPLIT(dev)) {
- if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
+ if ((lvds & LVDS_DETECTED) == 0)
return;
if (dev_priv->vbt.edp_support) {
DRM_DEBUG_KMS("disable LVDS for eDP support\n");
@@ -976,8 +980,7 @@ void intel_lvds_init(struct drm_device *dev)
pin = GMBUS_PIN_PANEL;
if (!lvds_is_present_in_vbt(dev, &pin)) {
- u32 reg = HAS_PCH_SPLIT(dev) ? PCH_LVDS : LVDS;
- if ((I915_READ(reg) & LVDS_PORT_EN) == 0) {
+ if ((lvds & LVDS_PORT_EN) == 0) {
DRM_DEBUG_KMS("LVDS is not present in VBT\n");
return;
}
@@ -1054,11 +1057,7 @@ void intel_lvds_init(struct drm_device *dev)
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
- if (HAS_PCH_SPLIT(dev)) {
- lvds_encoder->reg = PCH_LVDS;
- } else {
- lvds_encoder->reg = LVDS;
- }
+ lvds_encoder->reg = lvds_reg;
/* create the scaling mode property */
drm_mode_create_scaling_mode_property(dev);
@@ -1139,7 +1138,6 @@ void intel_lvds_init(struct drm_device *dev)
if (HAS_PCH_SPLIT(dev))
goto failed;
- lvds = I915_READ(LVDS);
pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
crtc = intel_get_crtc_for_pipe(dev, pipe);
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index b706b4e750da..6dc13c02c28e 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -239,7 +239,7 @@ struct opregion_asle {
static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct opregion_swsci __iomem *swsci = dev_priv->opregion.swsci;
+ struct opregion_swsci *swsci = dev_priv->opregion.swsci;
u32 main_function, sub_function, scic;
u16 pci_swsci;
u32 dslp;
@@ -264,7 +264,7 @@ static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
}
/* Driver sleep timeout in ms. */
- dslp = ioread32(&swsci->dslp);
+ dslp = swsci->dslp;
if (!dslp) {
/* The spec says 2ms should be the default, but it's too small
* for some machines. */
@@ -277,7 +277,7 @@ static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
}
/* The spec tells us to do this, but we are the only user... */
- scic = ioread32(&swsci->scic);
+ scic = swsci->scic;
if (scic & SWSCI_SCIC_INDICATOR) {
DRM_DEBUG_DRIVER("SWSCI request already in progress\n");
return -EBUSY;
@@ -285,8 +285,8 @@ static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
scic = function | SWSCI_SCIC_INDICATOR;
- iowrite32(parm, &swsci->parm);
- iowrite32(scic, &swsci->scic);
+ swsci->parm = parm;
+ swsci->scic = scic;
/* Ensure SCI event is selected and event trigger is cleared. */
pci_read_config_word(dev->pdev, PCI_SWSCI, &pci_swsci);
@@ -301,7 +301,7 @@ static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
pci_write_config_word(dev->pdev, PCI_SWSCI, pci_swsci);
/* Poll for the result. */
-#define C (((scic = ioread32(&swsci->scic)) & SWSCI_SCIC_INDICATOR) == 0)
+#define C (((scic = swsci->scic) & SWSCI_SCIC_INDICATOR) == 0)
if (wait_for(C, dslp)) {
DRM_DEBUG_DRIVER("SWSCI request timed out\n");
return -ETIMEDOUT;
@@ -317,7 +317,7 @@ static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
}
if (parm_out)
- *parm_out = ioread32(&swsci->parm);
+ *parm_out = swsci->parm;
return 0;
@@ -412,7 +412,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_connector *intel_connector;
- struct opregion_asle __iomem *asle = dev_priv->opregion.asle;
+ struct opregion_asle *asle = dev_priv->opregion.asle;
DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
@@ -437,7 +437,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp);
list_for_each_entry(intel_connector, &dev->mode_config.connector_list, base.head)
intel_panel_set_backlight_acpi(intel_connector, bclp, 255);
- iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv);
+ asle->cblv = DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID;
drm_modeset_unlock(&dev->mode_config.connection_mutex);
@@ -524,14 +524,14 @@ static void asle_work(struct work_struct *work)
struct drm_i915_private *dev_priv =
container_of(opregion, struct drm_i915_private, opregion);
struct drm_device *dev = dev_priv->dev;
- struct opregion_asle __iomem *asle = dev_priv->opregion.asle;
+ struct opregion_asle *asle = dev_priv->opregion.asle;
u32 aslc_stat = 0;
u32 aslc_req;
if (!asle)
return;
- aslc_req = ioread32(&asle->aslc);
+ aslc_req = asle->aslc;
if (!(aslc_req & ASLC_REQ_MSK)) {
DRM_DEBUG_DRIVER("No request on ASLC interrupt 0x%08x\n",
@@ -540,34 +540,34 @@ static void asle_work(struct work_struct *work)
}
if (aslc_req & ASLC_SET_ALS_ILLUM)
- aslc_stat |= asle_set_als_illum(dev, ioread32(&asle->alsi));
+ aslc_stat |= asle_set_als_illum(dev, asle->alsi);
if (aslc_req & ASLC_SET_BACKLIGHT)
- aslc_stat |= asle_set_backlight(dev, ioread32(&asle->bclp));
+ aslc_stat |= asle_set_backlight(dev, asle->bclp);
if (aslc_req & ASLC_SET_PFIT)
- aslc_stat |= asle_set_pfit(dev, ioread32(&asle->pfit));
+ aslc_stat |= asle_set_pfit(dev, asle->pfit);
if (aslc_req & ASLC_SET_PWM_FREQ)
- aslc_stat |= asle_set_pwm_freq(dev, ioread32(&asle->pfmb));
+ aslc_stat |= asle_set_pwm_freq(dev, asle->pfmb);
if (aslc_req & ASLC_SUPPORTED_ROTATION_ANGLES)
aslc_stat |= asle_set_supported_rotation_angles(dev,
- ioread32(&asle->srot));
+ asle->srot);
if (aslc_req & ASLC_BUTTON_ARRAY)
- aslc_stat |= asle_set_button_array(dev, ioread32(&asle->iuer));
+ aslc_stat |= asle_set_button_array(dev, asle->iuer);
if (aslc_req & ASLC_CONVERTIBLE_INDICATOR)
- aslc_stat |= asle_set_convertible(dev, ioread32(&asle->iuer));
+ aslc_stat |= asle_set_convertible(dev, asle->iuer);
if (aslc_req & ASLC_DOCKING_INDICATOR)
- aslc_stat |= asle_set_docking(dev, ioread32(&asle->iuer));
+ aslc_stat |= asle_set_docking(dev, asle->iuer);
if (aslc_req & ASLC_ISCT_STATE_CHANGE)
aslc_stat |= asle_isct_state(dev);
- iowrite32(aslc_stat, &asle->aslc);
+ asle->aslc = aslc_stat;
}
void intel_opregion_asle_intr(struct drm_device *dev)
@@ -592,8 +592,8 @@ static int intel_opregion_video_event(struct notifier_block *nb,
Linux, these are handled by the dock, button and video drivers.
*/
- struct opregion_acpi __iomem *acpi;
struct acpi_bus_event *event = data;
+ struct opregion_acpi *acpi;
int ret = NOTIFY_OK;
if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0)
@@ -604,11 +604,10 @@ static int intel_opregion_video_event(struct notifier_block *nb,
acpi = system_opregion->acpi;
- if (event->type == 0x80 &&
- (ioread32(&acpi->cevt) & 1) == 0)
+ if (event->type == 0x80 && ((acpi->cevt & 1) == 0))
ret = NOTIFY_BAD;
- iowrite32(0, &acpi->csts);
+ acpi->csts = 0;
return ret;
}
@@ -628,14 +627,14 @@ static u32 get_did(struct intel_opregion *opregion, int i)
u32 did;
if (i < ARRAY_SIZE(opregion->acpi->didl)) {
- did = ioread32(&opregion->acpi->didl[i]);
+ did = opregion->acpi->didl[i];
} else {
i -= ARRAY_SIZE(opregion->acpi->didl);
if (WARN_ON(i >= ARRAY_SIZE(opregion->acpi->did2)))
return 0;
- did = ioread32(&opregion->acpi->did2[i]);
+ did = opregion->acpi->did2[i];
}
return did;
@@ -644,14 +643,14 @@ static u32 get_did(struct intel_opregion *opregion, int i)
static void set_did(struct intel_opregion *opregion, int i, u32 val)
{
if (i < ARRAY_SIZE(opregion->acpi->didl)) {
- iowrite32(val, &opregion->acpi->didl[i]);
+ opregion->acpi->didl[i] = val;
} else {
i -= ARRAY_SIZE(opregion->acpi->didl);
if (WARN_ON(i >= ARRAY_SIZE(opregion->acpi->did2)))
return;
- iowrite32(val, &opregion->acpi->did2[i]);
+ opregion->acpi->did2[i] = val;
}
}
@@ -773,7 +772,7 @@ static void intel_setup_cadls(struct drm_device *dev)
* there are less than eight devices. */
do {
disp_id = get_did(opregion, i);
- iowrite32(disp_id, &opregion->acpi->cadl[i]);
+ opregion->acpi->cadl[i] = disp_id;
} while (++i < 8 && disp_id != 0);
}
@@ -792,16 +791,16 @@ void intel_opregion_init(struct drm_device *dev)
/* Notify BIOS we are ready to handle ACPI video ext notifs.
* Right now, all the events are handled by the ACPI video module.
* We don't actually need to do anything with them. */
- iowrite32(0, &opregion->acpi->csts);
- iowrite32(1, &opregion->acpi->drdy);
+ opregion->acpi->csts = 0;
+ opregion->acpi->drdy = 1;
system_opregion = opregion;
register_acpi_notifier(&intel_opregion_notifier);
}
if (opregion->asle) {
- iowrite32(ASLE_TCHE_BLC_EN, &opregion->asle->tche);
- iowrite32(ASLE_ARDY_READY, &opregion->asle->ardy);
+ opregion->asle->tche = ASLE_TCHE_BLC_EN;
+ opregion->asle->ardy = ASLE_ARDY_READY;
}
}
@@ -814,19 +813,19 @@ void intel_opregion_fini(struct drm_device *dev)
return;
if (opregion->asle)
- iowrite32(ASLE_ARDY_NOT_READY, &opregion->asle->ardy);
+ opregion->asle->ardy = ASLE_ARDY_NOT_READY;
cancel_work_sync(&dev_priv->opregion.asle_work);
if (opregion->acpi) {
- iowrite32(0, &opregion->acpi->drdy);
+ opregion->acpi->drdy = 0;
system_opregion = NULL;
unregister_acpi_notifier(&intel_opregion_notifier);
}
/* just clear all opregion memory pointers now */
- iounmap(opregion->header);
+ memunmap(opregion->header);
opregion->header = NULL;
opregion->acpi = NULL;
opregion->swsci = NULL;
@@ -899,10 +898,10 @@ int intel_opregion_setup(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_opregion *opregion = &dev_priv->opregion;
- void __iomem *base;
u32 asls, mboxes;
char buf[sizeof(OPREGION_SIGNATURE)];
int err = 0;
+ void *base;
BUILD_BUG_ON(sizeof(struct opregion_header) != 0x100);
BUILD_BUG_ON(sizeof(struct opregion_acpi) != 0x100);
@@ -920,11 +919,11 @@ int intel_opregion_setup(struct drm_device *dev)
INIT_WORK(&opregion->asle_work, asle_work);
#endif
- base = acpi_os_ioremap(asls, OPREGION_SIZE);
+ base = memremap(asls, OPREGION_SIZE, MEMREMAP_WB);
if (!base)
return -ENOMEM;
- memcpy_fromio(buf, base, sizeof(buf));
+ memcpy(buf, base, sizeof(buf));
if (memcmp(buf, OPREGION_SIGNATURE, 16)) {
DRM_DEBUG_DRIVER("opregion signature mismatch\n");
@@ -936,7 +935,7 @@ int intel_opregion_setup(struct drm_device *dev)
opregion->lid_state = base + ACPI_CLID;
- mboxes = ioread32(&opregion->header->mboxes);
+ mboxes = opregion->header->mboxes;
if (mboxes & MBOX_ACPI) {
DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
opregion->acpi = base + OPREGION_ACPI_OFFSET;
@@ -951,12 +950,12 @@ int intel_opregion_setup(struct drm_device *dev)
DRM_DEBUG_DRIVER("ASLE supported\n");
opregion->asle = base + OPREGION_ASLE_OFFSET;
- iowrite32(ASLE_ARDY_NOT_READY, &opregion->asle->ardy);
+ opregion->asle->ardy = ASLE_ARDY_NOT_READY;
}
return 0;
err_out:
- iounmap(base);
+ memunmap(base);
return err;
}
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index f30c996e882c..b05c6d9b3be7 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -381,7 +381,7 @@ intel_panel_detect(struct drm_device *dev)
/* Assume that the BIOS does not lie through the OpRegion... */
if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) {
- return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
+ return *dev_priv->opregion.lid_state & 0x1 ?
connector_status_connected :
connector_status_disconnected;
}
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index d031d74abd27..9dda3eaebd12 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -52,56 +52,10 @@
#define INTEL_RC6p_ENABLE (1<<1)
#define INTEL_RC6pp_ENABLE (1<<2)
-static void gen9_init_clock_gating(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
-
- /* WaEnableLbsSlaRetryTimerDecrement:skl */
- I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) |
- GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE);
-
- /* WaDisableKillLogic:bxt,skl */
- I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
- ECOCHK_DIS_TLB);
-}
-
-static void skl_init_clock_gating(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
-
- gen9_init_clock_gating(dev);
-
- if (INTEL_REVID(dev) <= SKL_REVID_D0) {
- /* WaDisableHDCInvalidation:skl */
- I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
- BDW_DISABLE_HDC_INVALIDATION);
-
- /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */
- I915_WRITE(FF_SLICE_CS_CHICKEN2,
- _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE));
- }
-
- /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes
- * involving this register should also be added to WA batch as required.
- */
- if (INTEL_REVID(dev) <= SKL_REVID_E0)
- /* WaDisableLSQCROPERFforOCL:skl */
- I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
- GEN8_LQSC_RO_PERF_DIS);
-
- /* WaEnableGapsTsvCreditFix:skl */
- if (IS_SKYLAKE(dev) && (INTEL_REVID(dev) >= SKL_REVID_C0)) {
- I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
- GEN9_GAPS_TSV_CREDIT_DISABLE));
- }
-}
-
static void bxt_init_clock_gating(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- gen9_init_clock_gating(dev);
-
/* WaDisableSDEUnitClockGating:bxt */
I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) |
GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
@@ -112,17 +66,6 @@ static void bxt_init_clock_gating(struct drm_device *dev)
*/
I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) |
GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ);
-
- /* WaStoreMultiplePTEenable:bxt */
- /* This is a requirement according to Hardware specification */
- if (INTEL_REVID(dev) == BXT_REVID_A0)
- I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF);
-
- /* WaSetClckGatingDisableMedia:bxt */
- if (INTEL_REVID(dev) == BXT_REVID_A0) {
- I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) &
- ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE));
- }
}
static void i915_pineview_get_mem_freq(struct drm_device *dev)
@@ -1765,6 +1708,13 @@ static uint32_t ilk_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels,
return DIV_ROUND_UP(pri_val * 64, horiz_pixels * bytes_per_pixel) + 2;
}
+struct skl_pipe_wm_parameters {
+ bool active;
+ uint32_t pipe_htotal;
+ uint32_t pixel_rate; /* in KHz */
+ struct intel_plane_wm_parameters plane[I915_MAX_PLANES];
+};
+
struct ilk_wm_maximums {
uint16_t pri;
uint16_t spr;
@@ -2805,40 +2755,18 @@ static bool ilk_disable_lp_wm(struct drm_device *dev)
#define SKL_DDB_SIZE 896 /* in blocks */
#define BXT_DDB_SIZE 512
-/*
- * Return the index of a plane in the SKL DDB and wm result arrays. Primary
- * plane is always in slot 0, cursor is always in slot I915_MAX_PLANES-1, and
- * other universal planes are in indices 1..n. Note that this may leave unused
- * indices between the top "sprite" plane and the cursor.
- */
-static int
-skl_wm_plane_id(const struct intel_plane *plane)
-{
- switch (plane->base.type) {
- case DRM_PLANE_TYPE_PRIMARY:
- return 0;
- case DRM_PLANE_TYPE_CURSOR:
- return PLANE_CURSOR;
- case DRM_PLANE_TYPE_OVERLAY:
- return plane->plane + 1;
- default:
- MISSING_CASE(plane->base.type);
- return plane->plane;
- }
-}
-
static void
skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
- const struct intel_crtc_state *cstate,
+ struct drm_crtc *for_crtc,
const struct intel_wm_config *config,
+ const struct skl_pipe_wm_parameters *params,
struct skl_ddb_entry *alloc /* out */)
{
- struct drm_crtc *for_crtc = cstate->base.crtc;
struct drm_crtc *crtc;
unsigned int pipe_size, ddb_size;
int nth_active_pipe;
- if (!cstate->base.active) {
+ if (!params->active) {
alloc->start = 0;
alloc->end = 0;
return;
@@ -2904,29 +2832,19 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
}
static unsigned int
-skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
- const struct drm_plane_state *pstate,
- int y)
+skl_plane_relative_data_rate(const struct intel_plane_wm_parameters *p, int y)
{
- struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
- struct drm_framebuffer *fb = pstate->fb;
/* for planar format */
- if (fb->pixel_format == DRM_FORMAT_NV12) {
+ if (p->y_bytes_per_pixel) {
if (y) /* y-plane data rate */
- return intel_crtc->config->pipe_src_w *
- intel_crtc->config->pipe_src_h *
- drm_format_plane_cpp(fb->pixel_format, 0);
+ return p->horiz_pixels * p->vert_pixels * p->y_bytes_per_pixel;
else /* uv-plane data rate */
- return (intel_crtc->config->pipe_src_w/2) *
- (intel_crtc->config->pipe_src_h/2) *
- drm_format_plane_cpp(fb->pixel_format, 1);
+ return (p->horiz_pixels/2) * (p->vert_pixels/2) * p->bytes_per_pixel;
}
/* for packed formats */
- return intel_crtc->config->pipe_src_w *
- intel_crtc->config->pipe_src_h *
- drm_format_plane_cpp(fb->pixel_format, 0);
+ return p->horiz_pixels * p->vert_pixels * p->bytes_per_pixel;
}
/*
@@ -2935,51 +2853,46 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
* 3 * 4096 * 8192 * 4 < 2^32
*/
static unsigned int
-skl_get_total_relative_data_rate(const struct intel_crtc_state *cstate)
+skl_get_total_relative_data_rate(struct intel_crtc *intel_crtc,
+ const struct skl_pipe_wm_parameters *params)
{
- struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
- struct drm_device *dev = intel_crtc->base.dev;
- const struct intel_plane *intel_plane;
unsigned int total_data_rate = 0;
+ int plane;
- for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
- const struct drm_plane_state *pstate = intel_plane->base.state;
+ for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) {
+ const struct intel_plane_wm_parameters *p;
- if (pstate->fb == NULL)
+ p = &params->plane[plane];
+ if (!p->enabled)
continue;
- /* packed/uv */
- total_data_rate += skl_plane_relative_data_rate(cstate,
- pstate,
- 0);
-
- if (pstate->fb->pixel_format == DRM_FORMAT_NV12)
- /* y-plane */
- total_data_rate += skl_plane_relative_data_rate(cstate,
- pstate,
- 1);
+ total_data_rate += skl_plane_relative_data_rate(p, 0); /* packed/uv */
+ if (p->y_bytes_per_pixel) {
+ total_data_rate += skl_plane_relative_data_rate(p, 1); /* y-plane */
+ }
}
return total_data_rate;
}
static void
-skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
+skl_allocate_pipe_ddb(struct drm_crtc *crtc,
const struct intel_wm_config *config,
+ const struct skl_pipe_wm_parameters *params,
struct skl_ddb_allocation *ddb /* out */)
{
- struct drm_crtc *crtc = cstate->base.crtc;
struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct intel_plane *intel_plane;
enum pipe pipe = intel_crtc->pipe;
struct skl_ddb_entry *alloc = &ddb->pipe[pipe];
uint16_t alloc_size, start, cursor_blocks;
uint16_t minimum[I915_MAX_PLANES];
uint16_t y_minimum[I915_MAX_PLANES];
unsigned int total_data_rate;
+ int plane;
- skl_ddb_get_pipe_allocation_limits(dev, cstate, config, alloc);
+ skl_ddb_get_pipe_allocation_limits(dev, crtc, config, params, alloc);
alloc_size = skl_ddb_entry_size(alloc);
if (alloc_size == 0) {
memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
@@ -2996,20 +2909,17 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
alloc->end -= cursor_blocks;
/* 1. Allocate the mininum required blocks for each active plane */
- for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
- struct drm_plane *plane = &intel_plane->base;
- struct drm_framebuffer *fb = plane->fb;
- int id = skl_wm_plane_id(intel_plane);
+ for_each_plane(dev_priv, pipe, plane) {
+ const struct intel_plane_wm_parameters *p;
- if (fb == NULL)
- continue;
- if (plane->type == DRM_PLANE_TYPE_CURSOR)
+ p = &params->plane[plane];
+ if (!p->enabled)
continue;
- minimum[id] = 8;
- alloc_size -= minimum[id];
- y_minimum[id] = (fb->pixel_format == DRM_FORMAT_NV12) ? 8 : 0;
- alloc_size -= y_minimum[id];
+ minimum[plane] = 8;
+ alloc_size -= minimum[plane];
+ y_minimum[plane] = p->y_bytes_per_pixel ? 8 : 0;
+ alloc_size -= y_minimum[plane];
}
/*
@@ -3018,50 +2928,45 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
*
* FIXME: we may not allocate every single block here.
*/
- total_data_rate = skl_get_total_relative_data_rate(cstate);
+ total_data_rate = skl_get_total_relative_data_rate(intel_crtc, params);
start = alloc->start;
- for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
- struct drm_plane *plane = &intel_plane->base;
- struct drm_plane_state *pstate = intel_plane->base.state;
+ for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) {
+ const struct intel_plane_wm_parameters *p;
unsigned int data_rate, y_data_rate;
uint16_t plane_blocks, y_plane_blocks = 0;
- int id = skl_wm_plane_id(intel_plane);
- if (pstate->fb == NULL)
- continue;
- if (plane->type == DRM_PLANE_TYPE_CURSOR)
+ p = &params->plane[plane];
+ if (!p->enabled)
continue;
- data_rate = skl_plane_relative_data_rate(cstate, pstate, 0);
+ data_rate = skl_plane_relative_data_rate(p, 0);
/*
* allocation for (packed formats) or (uv-plane part of planar format):
* promote the expression to 64 bits to avoid overflowing, the
* result is < available as data_rate / total_data_rate < 1
*/
- plane_blocks = minimum[id];
+ plane_blocks = minimum[plane];
plane_blocks += div_u64((uint64_t)alloc_size * data_rate,
total_data_rate);
- ddb->plane[pipe][id].start = start;
- ddb->plane[pipe][id].end = start + plane_blocks;
+ ddb->plane[pipe][plane].start = start;
+ ddb->plane[pipe][plane].end = start + plane_blocks;
start += plane_blocks;
/*
* allocation for y_plane part of planar format:
*/
- if (pstate->fb->pixel_format == DRM_FORMAT_NV12) {
- y_data_rate = skl_plane_relative_data_rate(cstate,
- pstate,
- 1);
- y_plane_blocks = y_minimum[id];
+ if (p->y_bytes_per_pixel) {
+ y_data_rate = skl_plane_relative_data_rate(p, 1);
+ y_plane_blocks = y_minimum[plane];
y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate,
total_data_rate);
- ddb->y_plane[pipe][id].start = start;
- ddb->y_plane[pipe][id].end = start + y_plane_blocks;
+ ddb->y_plane[pipe][plane].start = start;
+ ddb->y_plane[pipe][plane].end = start + y_plane_blocks;
start += y_plane_blocks;
}
@@ -3148,21 +3053,87 @@ static void skl_compute_wm_global_parameters(struct drm_device *dev,
struct intel_wm_config *config)
{
struct drm_crtc *crtc;
+ struct drm_plane *plane;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
config->num_pipes_active += to_intel_crtc(crtc)->active;
+
+ /* FIXME: I don't think we need those two global parameters on SKL */
+ list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
+ struct intel_plane *intel_plane = to_intel_plane(plane);
+
+ config->sprites_enabled |= intel_plane->wm.enabled;
+ config->sprites_scaled |= intel_plane->wm.scaled;
+ }
+}
+
+static void skl_compute_wm_pipe_parameters(struct drm_crtc *crtc,
+ struct skl_pipe_wm_parameters *p)
+{
+ struct drm_device *dev = crtc->dev;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ enum pipe pipe = intel_crtc->pipe;
+ struct drm_plane *plane;
+ struct drm_framebuffer *fb;
+ int i = 1; /* Index for sprite planes start */
+
+ p->active = intel_crtc->active;
+ if (p->active) {
+ p->pipe_htotal = intel_crtc->config->base.adjusted_mode.crtc_htotal;
+ p->pixel_rate = skl_pipe_pixel_rate(intel_crtc->config);
+
+ fb = crtc->primary->state->fb;
+ /* For planar: Bpp is for uv plane, y_Bpp is for y plane */
+ if (fb) {
+ p->plane[0].enabled = true;
+ p->plane[0].bytes_per_pixel = fb->pixel_format == DRM_FORMAT_NV12 ?
+ drm_format_plane_cpp(fb->pixel_format, 1) :
+ drm_format_plane_cpp(fb->pixel_format, 0);
+ p->plane[0].y_bytes_per_pixel = fb->pixel_format == DRM_FORMAT_NV12 ?
+ drm_format_plane_cpp(fb->pixel_format, 0) : 0;
+ p->plane[0].tiling = fb->modifier[0];
+ } else {
+ p->plane[0].enabled = false;
+ p->plane[0].bytes_per_pixel = 0;
+ p->plane[0].y_bytes_per_pixel = 0;
+ p->plane[0].tiling = DRM_FORMAT_MOD_NONE;
+ }
+ p->plane[0].horiz_pixels = intel_crtc->config->pipe_src_w;
+ p->plane[0].vert_pixels = intel_crtc->config->pipe_src_h;
+ p->plane[0].rotation = crtc->primary->state->rotation;
+
+ fb = crtc->cursor->state->fb;
+ p->plane[PLANE_CURSOR].y_bytes_per_pixel = 0;
+ if (fb) {
+ p->plane[PLANE_CURSOR].enabled = true;
+ p->plane[PLANE_CURSOR].bytes_per_pixel = fb->bits_per_pixel / 8;
+ p->plane[PLANE_CURSOR].horiz_pixels = crtc->cursor->state->crtc_w;
+ p->plane[PLANE_CURSOR].vert_pixels = crtc->cursor->state->crtc_h;
+ } else {
+ p->plane[PLANE_CURSOR].enabled = false;
+ p->plane[PLANE_CURSOR].bytes_per_pixel = 0;
+ p->plane[PLANE_CURSOR].horiz_pixels = 64;
+ p->plane[PLANE_CURSOR].vert_pixels = 64;
+ }
+ }
+
+ list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
+ struct intel_plane *intel_plane = to_intel_plane(plane);
+
+ if (intel_plane->pipe == pipe &&
+ plane->type == DRM_PLANE_TYPE_OVERLAY)
+ p->plane[i++] = intel_plane->wm;
+ }
}
static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
- struct intel_crtc_state *cstate,
- struct intel_plane *intel_plane,
+ struct skl_pipe_wm_parameters *p,
+ struct intel_plane_wm_parameters *p_params,
uint16_t ddb_allocation,
int level,
uint16_t *out_blocks, /* out */
uint8_t *out_lines /* out */)
{
- struct drm_plane *plane = &intel_plane->base;
- struct drm_framebuffer *fb = plane->state->fb;
uint32_t latency = dev_priv->wm.skl_latency[level];
uint32_t method1, method2;
uint32_t plane_bytes_per_line, plane_blocks_per_line;
@@ -3170,35 +3141,31 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
uint32_t selected_result;
uint8_t bytes_per_pixel;
- if (latency == 0 || !cstate->base.active || !fb)
+ if (latency == 0 || !p->active || !p_params->enabled)
return false;
- bytes_per_pixel = (fb->pixel_format == DRM_FORMAT_NV12) ?
- drm_format_plane_cpp(DRM_FORMAT_NV12, 0) :
- drm_format_plane_cpp(DRM_FORMAT_NV12, 1);
- method1 = skl_wm_method1(skl_pipe_pixel_rate(cstate),
+ bytes_per_pixel = p_params->y_bytes_per_pixel ?
+ p_params->y_bytes_per_pixel :
+ p_params->bytes_per_pixel;
+ method1 = skl_wm_method1(p->pixel_rate,
bytes_per_pixel,
latency);
- method2 = skl_wm_method2(skl_pipe_pixel_rate(cstate),
- cstate->base.adjusted_mode.crtc_htotal,
- cstate->pipe_src_w,
+ method2 = skl_wm_method2(p->pixel_rate,
+ p->pipe_htotal,
+ p_params->horiz_pixels,
bytes_per_pixel,
- fb->modifier[0],
+ p_params->tiling,
latency);
- plane_bytes_per_line = cstate->pipe_src_w * bytes_per_pixel;
+ plane_bytes_per_line = p_params->horiz_pixels * bytes_per_pixel;
plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512);
- if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
- fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) {
+ if (p_params->tiling == I915_FORMAT_MOD_Y_TILED ||
+ p_params->tiling == I915_FORMAT_MOD_Yf_TILED) {
uint32_t min_scanlines = 4;
uint32_t y_tile_minimum;
- if (intel_rotation_90_or_270(plane->state->rotation)) {
- int bpp = (fb->pixel_format == DRM_FORMAT_NV12) ?
- drm_format_plane_cpp(fb->pixel_format, 1) :
- drm_format_plane_cpp(fb->pixel_format, 0);
-
- switch (bpp) {
+ if (intel_rotation_90_or_270(p_params->rotation)) {
+ switch (p_params->bytes_per_pixel) {
case 1:
min_scanlines = 16;
break;
@@ -3222,8 +3189,8 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
res_lines = DIV_ROUND_UP(selected_result, plane_blocks_per_line);
if (level >= 1 && level <= 7) {
- if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
- fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)
+ if (p_params->tiling == I915_FORMAT_MOD_Y_TILED ||
+ p_params->tiling == I915_FORMAT_MOD_Yf_TILED)
res_lines += 4;
else
res_blocks++;
@@ -3240,80 +3207,84 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
static void skl_compute_wm_level(const struct drm_i915_private *dev_priv,
struct skl_ddb_allocation *ddb,
- struct intel_crtc_state *cstate,
+ struct skl_pipe_wm_parameters *p,
+ enum pipe pipe,
int level,
+ int num_planes,
struct skl_wm_level *result)
{
- struct drm_device *dev = dev_priv->dev;
- struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
- struct intel_plane *intel_plane;
uint16_t ddb_blocks;
- enum pipe pipe = intel_crtc->pipe;
-
- for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
- int i = skl_wm_plane_id(intel_plane);
+ int i;
+ for (i = 0; i < num_planes; i++) {
ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]);
result->plane_en[i] = skl_compute_plane_wm(dev_priv,
- cstate,
- intel_plane,
+ p, &p->plane[i],
ddb_blocks,
level,
&result->plane_res_b[i],
&result->plane_res_l[i]);
}
+
+ ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][PLANE_CURSOR]);
+ result->plane_en[PLANE_CURSOR] = skl_compute_plane_wm(dev_priv, p,
+ &p->plane[PLANE_CURSOR],
+ ddb_blocks, level,
+ &result->plane_res_b[PLANE_CURSOR],
+ &result->plane_res_l[PLANE_CURSOR]);
}
static uint32_t
-skl_compute_linetime_wm(struct intel_crtc_state *cstate)
+skl_compute_linetime_wm(struct drm_crtc *crtc, struct skl_pipe_wm_parameters *p)
{
- if (!cstate->base.active)
+ if (!to_intel_crtc(crtc)->active)
return 0;
- if (WARN_ON(skl_pipe_pixel_rate(cstate) == 0))
+ if (WARN_ON(p->pixel_rate == 0))
return 0;
- return DIV_ROUND_UP(8 * cstate->base.adjusted_mode.crtc_htotal * 1000,
- skl_pipe_pixel_rate(cstate));
+ return DIV_ROUND_UP(8 * p->pipe_htotal * 1000, p->pixel_rate);
}
-static void skl_compute_transition_wm(struct intel_crtc_state *cstate,
+static void skl_compute_transition_wm(struct drm_crtc *crtc,
+ struct skl_pipe_wm_parameters *params,
struct skl_wm_level *trans_wm /* out */)
{
- struct drm_crtc *crtc = cstate->base.crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct intel_plane *intel_plane;
+ int i;
- if (!cstate->base.active)
+ if (!params->active)
return;
/* Until we know more, just disable transition WMs */
- for_each_intel_plane_on_crtc(crtc->dev, intel_crtc, intel_plane) {
- int i = skl_wm_plane_id(intel_plane);
-
+ for (i = 0; i < intel_num_planes(intel_crtc); i++)
trans_wm->plane_en[i] = false;
- }
+ trans_wm->plane_en[PLANE_CURSOR] = false;
}
-static void skl_compute_pipe_wm(struct intel_crtc_state *cstate,
+static void skl_compute_pipe_wm(struct drm_crtc *crtc,
struct skl_ddb_allocation *ddb,
+ struct skl_pipe_wm_parameters *params,
struct skl_pipe_wm *pipe_wm)
{
- struct drm_device *dev = cstate->base.crtc->dev;
+ struct drm_device *dev = crtc->dev;
const struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int level, max_level = ilk_wm_max_level(dev);
for (level = 0; level <= max_level; level++) {
- skl_compute_wm_level(dev_priv, ddb, cstate,
- level, &pipe_wm->wm[level]);
+ skl_compute_wm_level(dev_priv, ddb, params, intel_crtc->pipe,
+ level, intel_num_planes(intel_crtc),
+ &pipe_wm->wm[level]);
}
- pipe_wm->linetime = skl_compute_linetime_wm(cstate);
+ pipe_wm->linetime = skl_compute_linetime_wm(crtc, params);
- skl_compute_transition_wm(cstate, &pipe_wm->trans_wm);
+ skl_compute_transition_wm(crtc, params, &pipe_wm->trans_wm);
}
static void skl_compute_wm_results(struct drm_device *dev,
+ struct skl_pipe_wm_parameters *p,
struct skl_pipe_wm *p_wm,
struct skl_wm_values *r,
struct intel_crtc *intel_crtc)
@@ -3557,15 +3528,16 @@ static void skl_flush_wm_values(struct drm_i915_private *dev_priv,
}
static bool skl_update_pipe_wm(struct drm_crtc *crtc,
+ struct skl_pipe_wm_parameters *params,
struct intel_wm_config *config,
struct skl_ddb_allocation *ddb, /* out */
struct skl_pipe_wm *pipe_wm /* out */)
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
- skl_allocate_pipe_ddb(cstate, config, ddb);
- skl_compute_pipe_wm(cstate, ddb, pipe_wm);
+ skl_compute_wm_pipe_parameters(crtc, params);
+ skl_allocate_pipe_ddb(crtc, config, params, ddb);
+ skl_compute_pipe_wm(crtc, ddb, params, pipe_wm);
if (!memcmp(&intel_crtc->wm.skl_active, pipe_wm, sizeof(*pipe_wm)))
return false;
@@ -3598,6 +3570,7 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
*/
list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
base.head) {
+ struct skl_pipe_wm_parameters params = {};
struct skl_pipe_wm pipe_wm = {};
bool wm_changed;
@@ -3607,7 +3580,8 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
if (!intel_crtc->active)
continue;
- wm_changed = skl_update_pipe_wm(&intel_crtc->base, config,
+ wm_changed = skl_update_pipe_wm(&intel_crtc->base,
+ &params, config,
&r->ddb, &pipe_wm);
/*
@@ -3617,7 +3591,7 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
*/
WARN_ON(!wm_changed);
- skl_compute_wm_results(dev, &pipe_wm, r, intel_crtc);
+ skl_compute_wm_results(dev, &params, &pipe_wm, r, intel_crtc);
r->dirty[intel_crtc->pipe] = true;
}
}
@@ -3647,6 +3621,7 @@ static void skl_update_wm(struct drm_crtc *crtc)
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
+ struct skl_pipe_wm_parameters params = {};
struct skl_wm_values *results = &dev_priv->wm.skl_results;
struct skl_pipe_wm pipe_wm = {};
struct intel_wm_config config = {};
@@ -3659,10 +3634,11 @@ static void skl_update_wm(struct drm_crtc *crtc)
skl_compute_wm_global_parameters(dev, &config);
- if (!skl_update_pipe_wm(crtc, &config, &results->ddb, &pipe_wm))
+ if (!skl_update_pipe_wm(crtc, &params, &config,
+ &results->ddb, &pipe_wm))
return;
- skl_compute_wm_results(dev, &pipe_wm, results, intel_crtc);
+ skl_compute_wm_results(dev, &params, &pipe_wm, results, intel_crtc);
results->dirty[intel_crtc->pipe] = true;
skl_update_other_pipe_wm(dev, crtc, &config, results);
@@ -3673,6 +3649,39 @@ static void skl_update_wm(struct drm_crtc *crtc)
dev_priv->wm.skl_hw = *results;
}
+static void
+skl_update_sprite_wm(struct drm_plane *plane, struct drm_crtc *crtc,
+ uint32_t sprite_width, uint32_t sprite_height,
+ int pixel_size, bool enabled, bool scaled)
+{
+ struct intel_plane *intel_plane = to_intel_plane(plane);
+ struct drm_framebuffer *fb = plane->state->fb;
+
+ intel_plane->wm.enabled = enabled;
+ intel_plane->wm.scaled = scaled;
+ intel_plane->wm.horiz_pixels = sprite_width;
+ intel_plane->wm.vert_pixels = sprite_height;
+ intel_plane->wm.tiling = DRM_FORMAT_MOD_NONE;
+
+ /* For planar: Bpp is for UV plane, y_Bpp is for Y plane */
+ intel_plane->wm.bytes_per_pixel =
+ (fb && fb->pixel_format == DRM_FORMAT_NV12) ?
+ drm_format_plane_cpp(plane->state->fb->pixel_format, 1) : pixel_size;
+ intel_plane->wm.y_bytes_per_pixel =
+ (fb && fb->pixel_format == DRM_FORMAT_NV12) ?
+ drm_format_plane_cpp(plane->state->fb->pixel_format, 0) : 0;
+
+ /*
+ * Framebuffer can be NULL on plane disable, but it does not
+ * matter for watermarks if we assume no tiling in that case.
+ */
+ if (fb)
+ intel_plane->wm.tiling = fb->modifier[0];
+ intel_plane->wm.rotation = plane->state->rotation;
+
+ skl_update_wm(crtc);
+}
+
static void ilk_update_wm(struct drm_crtc *crtc)
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -3688,18 +3697,6 @@ static void ilk_update_wm(struct drm_crtc *crtc)
WARN_ON(cstate->base.active != intel_crtc->active);
- /*
- * IVB workaround: must disable low power watermarks for at least
- * one frame before enabling scaling. LP watermarks can be re-enabled
- * when scaling is disabled.
- *
- * WaCxSRDisabledForSpriteScaling:ivb
- */
- if (cstate->disable_lp_wm) {
- ilk_disable_lp_wm(dev);
- intel_wait_for_vblank(dev, intel_crtc->pipe);
- }
-
intel_compute_pipe_wm(cstate, &pipe_wm);
if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
@@ -3731,6 +3728,28 @@ static void ilk_update_wm(struct drm_crtc *crtc)
ilk_write_wm_values(dev_priv, &results);
}
+static void
+ilk_update_sprite_wm(struct drm_plane *plane,
+ struct drm_crtc *crtc,
+ uint32_t sprite_width, uint32_t sprite_height,
+ int pixel_size, bool enabled, bool scaled)
+{
+ struct drm_device *dev = plane->dev;
+ struct intel_plane *intel_plane = to_intel_plane(plane);
+
+ /*
+ * IVB workaround: must disable low power watermarks for at least
+ * one frame before enabling scaling. LP watermarks can be re-enabled
+ * when scaling is disabled.
+ *
+ * WaCxSRDisabledForSpriteScaling:ivb
+ */
+ if (IS_IVYBRIDGE(dev) && scaled && ilk_disable_lp_wm(dev))
+ intel_wait_for_vblank(dev, intel_plane->pipe);
+
+ ilk_update_wm(crtc);
+}
+
static void skl_pipe_wm_active_state(uint32_t val,
struct skl_pipe_wm *active,
bool is_transwm,
@@ -4108,6 +4127,21 @@ void intel_update_watermarks(struct drm_crtc *crtc)
dev_priv->display.update_wm(crtc);
}
+void intel_update_sprite_watermarks(struct drm_plane *plane,
+ struct drm_crtc *crtc,
+ uint32_t sprite_width,
+ uint32_t sprite_height,
+ int pixel_size,
+ bool enabled, bool scaled)
+{
+ struct drm_i915_private *dev_priv = plane->dev->dev_private;
+
+ if (dev_priv->display.update_sprite_wm)
+ dev_priv->display.update_sprite_wm(plane, crtc,
+ sprite_width, sprite_height,
+ pixel_size, enabled, scaled);
+}
+
/**
* Lock protecting IPS related data structures
*/
@@ -7018,10 +7052,8 @@ void intel_init_pm(struct drm_device *dev)
if (IS_BROXTON(dev))
dev_priv->display.init_clock_gating =
bxt_init_clock_gating;
- else if (IS_SKYLAKE(dev))
- dev_priv->display.init_clock_gating =
- skl_init_clock_gating;
dev_priv->display.update_wm = skl_update_wm;
+ dev_priv->display.update_sprite_wm = skl_update_sprite_wm;
} else if (HAS_PCH_SPLIT(dev)) {
ilk_setup_wm_latency(dev);
@@ -7030,6 +7062,7 @@ void intel_init_pm(struct drm_device *dev)
(!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] &&
dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
dev_priv->display.update_wm = ilk_update_wm;
+ dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
} else {
DRM_DEBUG_KMS("Failed to read display plane latency. "
"Disable CxSR\n");
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index a04b4dc5ed9b..213581c215b3 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -73,14 +73,14 @@ static bool vlv_is_psr_active_on_pipe(struct drm_device *dev, int pipe)
}
static void intel_psr_write_vsc(struct intel_dp *intel_dp,
- struct edp_vsc_psr *vsc_psr)
+ const struct edp_vsc_psr *vsc_psr)
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_device *dev = dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc);
- u32 ctl_reg = HSW_TVIDEO_DIP_CTL(crtc->config->cpu_transcoder);
- u32 data_reg = HSW_TVIDEO_DIP_VSC_DATA(crtc->config->cpu_transcoder);
+ enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
+ u32 ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder);
uint32_t *data = (uint32_t *) vsc_psr;
unsigned int i;
@@ -90,12 +90,14 @@ static void intel_psr_write_vsc(struct intel_dp *intel_dp,
I915_WRITE(ctl_reg, 0);
POSTING_READ(ctl_reg);
- for (i = 0; i < VIDEO_DIP_VSC_DATA_SIZE; i += 4) {
- if (i < sizeof(struct edp_vsc_psr))
- I915_WRITE(data_reg + i, *data++);
- else
- I915_WRITE(data_reg + i, 0);
+ for (i = 0; i < sizeof(*vsc_psr); i += 4) {
+ I915_WRITE(HSW_TVIDEO_DIP_VSC_DATA(cpu_transcoder,
+ i >> 2), *data);
+ data++;
}
+ for (; i < VIDEO_DIP_VSC_DATA_SIZE; i += 4)
+ I915_WRITE(HSW_TVIDEO_DIP_VSC_DATA(cpu_transcoder,
+ i >> 2), 0);
I915_WRITE(ctl_reg, VIDEO_DIP_ENABLE_VSC_HSW);
POSTING_READ(ctl_reg);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 654ae991ea13..0359736fe979 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -906,6 +906,14 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring)
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t tmp;
+ /* WaEnableLbsSlaRetryTimerDecrement:skl */
+ I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) |
+ GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE);
+
+ /* WaDisableKillLogic:bxt,skl */
+ I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
+ ECOCHK_DIS_TLB);
+
/* WaDisablePartialInstShootdown:skl,bxt */
WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
@@ -1018,7 +1026,6 @@ static int skl_tune_iz_hashing(struct intel_engine_cs *ring)
return 0;
}
-
static int skl_init_workarounds(struct intel_engine_cs *ring)
{
int ret;
@@ -1029,6 +1036,30 @@ static int skl_init_workarounds(struct intel_engine_cs *ring)
if (ret)
return ret;
+ if (INTEL_REVID(dev) <= SKL_REVID_D0) {
+ /* WaDisableHDCInvalidation:skl */
+ I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
+ BDW_DISABLE_HDC_INVALIDATION);
+
+ /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */
+ I915_WRITE(FF_SLICE_CS_CHICKEN2,
+ _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE));
+ }
+
+ /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes
+ * involving this register should also be added to WA batch as required.
+ */
+ if (INTEL_REVID(dev) <= SKL_REVID_E0)
+ /* WaDisableLSQCROPERFforOCL:skl */
+ I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
+ GEN8_LQSC_RO_PERF_DIS);
+
+ /* WaEnableGapsTsvCreditFix:skl */
+ if (IS_SKYLAKE(dev) && (INTEL_REVID(dev) >= SKL_REVID_C0)) {
+ I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
+ GEN9_GAPS_TSV_CREDIT_DISABLE));
+ }
+
/* WaDisablePowerCompilerClockGating:skl */
if (INTEL_REVID(dev) == SKL_REVID_B0)
WA_SET_BIT_MASKED(HIZ_CHICKEN,
@@ -1072,6 +1103,17 @@ static int bxt_init_workarounds(struct intel_engine_cs *ring)
if (ret)
return ret;
+ /* WaStoreMultiplePTEenable:bxt */
+ /* This is a requirement according to Hardware specification */
+ if (INTEL_REVID(dev) == BXT_REVID_A0)
+ I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF);
+
+ /* WaSetClckGatingDisableMedia:bxt */
+ if (INTEL_REVID(dev) == BXT_REVID_A0) {
+ I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) &
+ ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE));
+ }
+
/* WaDisableThreadStallDopClockGating:bxt */
WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
STALL_DOP_GATING_DISABLE);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index dd2d5683fcb1..56dc132e8e20 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -192,6 +192,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
const int pipe = intel_plane->pipe;
const int plane = intel_plane->plane + 1;
u32 plane_ctl, stride_div, stride;
+ int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
const struct drm_intel_sprite_colorkey *key =
&to_intel_plane_state(drm_plane->state)->ckey;
unsigned long surf_addr;
@@ -202,6 +203,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
int scaler_id;
plane_ctl = PLANE_CTL_ENABLE |
+ PLANE_CTL_PIPE_GAMMA_ENABLE |
PLANE_CTL_PIPE_CSC_ENABLE;
plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
@@ -210,6 +212,10 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
rotation = drm_plane->state->rotation;
plane_ctl |= skl_plane_ctl_rotation(rotation);
+ intel_update_sprite_watermarks(drm_plane, crtc, src_w, src_h,
+ pixel_size, true,
+ src_w != crtc_w || src_h != crtc_h);
+
stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
fb->pixel_format);
@@ -291,6 +297,8 @@ skl_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
I915_WRITE(PLANE_SURF(pipe, plane), 0);
POSTING_READ(PLANE_SURF(pipe, plane));
+
+ intel_update_sprite_watermarks(dplane, crtc, 0, 0, 0, false, false);
}
static void
@@ -533,6 +541,10 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
sprctl |= SPRITE_PIPE_CSC_ENABLE;
+ intel_update_sprite_watermarks(plane, crtc, src_w, src_h, pixel_size,
+ true,
+ src_w != crtc_w || src_h != crtc_h);
+
/* Sizes are 0 based */
src_w--;
src_h--;
@@ -601,7 +613,7 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
struct intel_plane *intel_plane = to_intel_plane(plane);
int pipe = intel_plane->pipe;
- I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
+ I915_WRITE(SPRCTL(pipe), 0);
/* Can't leave the scaler enabled... */
if (intel_plane->can_scale)
I915_WRITE(SPRSCALE(pipe), 0);
@@ -666,6 +678,10 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
if (IS_GEN6(dev))
dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
+ intel_update_sprite_watermarks(plane, crtc, src_w, src_h,
+ pixel_size, true,
+ src_w != crtc_w || src_h != crtc_h);
+
/* Sizes are 0 based */
src_w--;
src_h--;
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index b43c6d025ac3..1663ea55e37c 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -525,7 +525,7 @@ void assert_forcewakes_inactive(struct drm_i915_private *dev_priv)
}
/* We give fast paths for the really cool registers */
-#define NEEDS_FORCE_WAKE(dev_priv, reg) \
+#define NEEDS_FORCE_WAKE(reg) \
((reg) < 0x40000 && (reg) != FORCEWAKE)
#define REG_RANGE(reg, start, end) ((reg) >= (start) && (reg) < (end))
@@ -727,7 +727,7 @@ static u##x \
gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
GEN6_READ_HEADER(x); \
hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \
- if (NEEDS_FORCE_WAKE((dev_priv), (reg))) \
+ if (NEEDS_FORCE_WAKE(reg)) \
__force_wake_get(dev_priv, FORCEWAKE_RENDER); \
val = __raw_i915_read##x(dev_priv, reg); \
hsw_unclaimed_reg_debug(dev_priv, reg, true, false); \
@@ -761,7 +761,7 @@ chv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
GEN6_READ_FOOTER; \
}
-#define SKL_NEEDS_FORCE_WAKE(dev_priv, reg) \
+#define SKL_NEEDS_FORCE_WAKE(reg) \
((reg) < 0x40000 && !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg))
#define __gen9_read(x) \
@@ -770,9 +770,9 @@ gen9_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
enum forcewake_domains fw_engine; \
GEN6_READ_HEADER(x); \
hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \
- if (!SKL_NEEDS_FORCE_WAKE((dev_priv), (reg))) \
+ if (!SKL_NEEDS_FORCE_WAKE(reg)) \
fw_engine = 0; \
- else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg)) \
+ else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg)) \
fw_engine = FORCEWAKE_RENDER; \
else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg)) \
fw_engine = FORCEWAKE_MEDIA; \
@@ -868,7 +868,7 @@ static void \
gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
u32 __fifo_ret = 0; \
GEN6_WRITE_HEADER; \
- if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
+ if (NEEDS_FORCE_WAKE(reg)) { \
__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
} \
__raw_i915_write##x(dev_priv, reg, val); \
@@ -883,7 +883,7 @@ static void \
hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
u32 __fifo_ret = 0; \
GEN6_WRITE_HEADER; \
- if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
+ if (NEEDS_FORCE_WAKE(reg)) { \
__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
} \
hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \
@@ -985,7 +985,7 @@ gen9_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, \
enum forcewake_domains fw_engine; \
GEN6_WRITE_HEADER; \
hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \
- if (!SKL_NEEDS_FORCE_WAKE((dev_priv), (reg)) || \
+ if (!SKL_NEEDS_FORCE_WAKE(reg) || \
is_gen9_shadowed(dev_priv, reg)) \
fw_engine = 0; \
else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg)) \
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 8e6c7c638e24..84d3ec98e6b9 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -14,20 +14,6 @@ config DRM_MSM
help
DRM/KMS driver for MSM/snapdragon.
-config DRM_MSM_FBDEV
- bool "Enable legacy fbdev support for MSM modesetting driver"
- depends on DRM_MSM
- select DRM_KMS_FB_HELPER
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- default y
- help
- Choose this option if you have a need for the legacy fbdev
- support. Note that this support also provide the linux console
- support on top of the MSM modesetting driver.
-
config DRM_MSM_REGISTER_LOGGING
bool "MSM DRM register logging"
depends on DRM_MSM
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 0a543eb5e5d7..1c90290be716 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -50,7 +50,7 @@ msm-y := \
msm_rd.o \
msm_ringbuffer.o
-msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o
+msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o
msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o
msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
diff --git a/drivers/gpu/drm/msm/adreno/a2xx.xml.h b/drivers/gpu/drm/msm/adreno/a2xx.xml.h
index 0261f0d31612..9e2aceb4ffe6 100644
--- a/drivers/gpu/drm/msm/adreno/a2xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a2xx.xml.h
@@ -8,13 +8,14 @@ http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 398 bytes, from 2015-09-24 17:25:31)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2015-05-20 20:03:14)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10755 bytes, from 2015-09-14 20:46:55)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14968 bytes, from 2015-05-20 20:12:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67120 bytes, from 2015-08-14 23:22:03)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63785 bytes, from 2015-08-14 18:27:06)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67771 bytes, from 2015-09-14 20:46:55)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63970 bytes, from 2015-09-14 20:50:12)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2015-09-24 17:30:00)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <[email protected]> (robclark)
diff --git a/drivers/gpu/drm/msm/adreno/a3xx.xml.h b/drivers/gpu/drm/msm/adreno/a3xx.xml.h
index 48d133711487..97dc1c6ec107 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a3xx.xml.h
@@ -8,13 +8,14 @@ http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 398 bytes, from 2015-09-24 17:25:31)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2015-05-20 20:03:14)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10755 bytes, from 2015-09-14 20:46:55)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14968 bytes, from 2015-05-20 20:12:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67120 bytes, from 2015-08-14 23:22:03)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63785 bytes, from 2015-08-14 18:27:06)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67771 bytes, from 2015-09-14 20:46:55)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63970 bytes, from 2015-09-14 20:50:12)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2015-09-24 17:30:00)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <[email protected]> (robclark)
@@ -280,6 +281,8 @@ enum a3xx_rb_blend_opcode {
enum a3xx_intp_mode {
SMOOTH = 0,
FLAT = 1,
+ ZERO = 2,
+ ONE = 3,
};
enum a3xx_repl_mode {
@@ -680,9 +683,16 @@ static inline uint32_t REG_A3XX_CP_PROTECT_REG(uint32_t i0) { return 0x00000460
#define A3XX_GRAS_CL_CLIP_CNTL_VP_CLIP_CODE_IGNORE 0x00080000
#define A3XX_GRAS_CL_CLIP_CNTL_VP_XFORM_DISABLE 0x00100000
#define A3XX_GRAS_CL_CLIP_CNTL_PERSP_DIVISION_DISABLE 0x00200000
+#define A3XX_GRAS_CL_CLIP_CNTL_ZERO_GB_SCALE_Z 0x00400000
#define A3XX_GRAS_CL_CLIP_CNTL_ZCOORD 0x00800000
#define A3XX_GRAS_CL_CLIP_CNTL_WCOORD 0x01000000
#define A3XX_GRAS_CL_CLIP_CNTL_ZCLIP_DISABLE 0x02000000
+#define A3XX_GRAS_CL_CLIP_CNTL_NUM_USER_CLIP_PLANES__MASK 0x1c000000
+#define A3XX_GRAS_CL_CLIP_CNTL_NUM_USER_CLIP_PLANES__SHIFT 26
+static inline uint32_t A3XX_GRAS_CL_CLIP_CNTL_NUM_USER_CLIP_PLANES(uint32_t val)
+{
+ return ((val) << A3XX_GRAS_CL_CLIP_CNTL_NUM_USER_CLIP_PLANES__SHIFT) & A3XX_GRAS_CL_CLIP_CNTL_NUM_USER_CLIP_PLANES__MASK;
+}
#define REG_A3XX_GRAS_CL_GB_CLIP_ADJ 0x00002044
#define A3XX_GRAS_CL_GB_CLIP_ADJ_HORZ__MASK 0x000003ff
@@ -773,7 +783,7 @@ static inline uint32_t A3XX_GRAS_SU_POINT_SIZE(float val)
#define A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__SHIFT 0
static inline uint32_t A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL(float val)
{
- return ((((int32_t)(val * 16384.0))) << A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__SHIFT) & A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__MASK;
+ return ((((int32_t)(val * 1048576.0))) << A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__SHIFT) & A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__MASK;
}
#define REG_A3XX_GRAS_SU_POLY_OFFSET_OFFSET 0x0000206d
@@ -894,6 +904,9 @@ static inline uint32_t A3XX_RB_MODE_CONTROL_MRT(uint32_t val)
#define A3XX_RB_MODE_CONTROL_PACKER_TIMER_ENABLE 0x00010000
#define REG_A3XX_RB_RENDER_CONTROL 0x000020c1
+#define A3XX_RB_RENDER_CONTROL_DUAL_COLOR_IN_ENABLE 0x00000001
+#define A3XX_RB_RENDER_CONTROL_YUV_IN_ENABLE 0x00000002
+#define A3XX_RB_RENDER_CONTROL_COV_VALUE_INPUT_ENABLE 0x00000004
#define A3XX_RB_RENDER_CONTROL_FACENESS 0x00000008
#define A3XX_RB_RENDER_CONTROL_BIN_WIDTH__MASK 0x00000ff0
#define A3XX_RB_RENDER_CONTROL_BIN_WIDTH__SHIFT 4
@@ -907,6 +920,8 @@ static inline uint32_t A3XX_RB_RENDER_CONTROL_BIN_WIDTH(uint32_t val)
#define A3XX_RB_RENDER_CONTROL_YCOORD 0x00008000
#define A3XX_RB_RENDER_CONTROL_ZCOORD 0x00010000
#define A3XX_RB_RENDER_CONTROL_WCOORD 0x00020000
+#define A3XX_RB_RENDER_CONTROL_I_CLAMP_ENABLE 0x00080000
+#define A3XX_RB_RENDER_CONTROL_COV_VALUE_OUTPUT_ENABLE 0x00100000
#define A3XX_RB_RENDER_CONTROL_ALPHA_TEST 0x00400000
#define A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC__MASK 0x07000000
#define A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC__SHIFT 24
@@ -914,6 +929,8 @@ static inline uint32_t A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(enum adreno_compar
{
return ((val) << A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC__SHIFT) & A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC__MASK;
}
+#define A3XX_RB_RENDER_CONTROL_ALPHA_TO_COVERAGE 0x40000000
+#define A3XX_RB_RENDER_CONTROL_ALPHA_TO_ONE 0x80000000
#define REG_A3XX_RB_MSAA_CONTROL 0x000020c2
#define A3XX_RB_MSAA_CONTROL_DISABLE 0x00000400
diff --git a/drivers/gpu/drm/msm/adreno/a4xx.xml.h b/drivers/gpu/drm/msm/adreno/a4xx.xml.h
index ac55066db3b0..99de8271dba8 100644
--- a/drivers/gpu/drm/msm/adreno/a4xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a4xx.xml.h
@@ -8,13 +8,14 @@ http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 398 bytes, from 2015-09-24 17:25:31)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2015-05-20 20:03:14)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10755 bytes, from 2015-09-14 20:46:55)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14968 bytes, from 2015-05-20 20:12:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67120 bytes, from 2015-08-14 23:22:03)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63785 bytes, from 2015-08-14 18:27:06)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67771 bytes, from 2015-09-14 20:46:55)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63970 bytes, from 2015-09-14 20:50:12)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2015-09-24 17:30:00)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <[email protected]> (robclark)
@@ -162,10 +163,13 @@ enum a4xx_tex_fmt {
TFMT4_8_UNORM = 4,
TFMT4_8_8_UNORM = 14,
TFMT4_8_8_8_8_UNORM = 28,
+ TFMT4_8_SNORM = 5,
TFMT4_8_8_SNORM = 15,
TFMT4_8_8_8_8_SNORM = 29,
+ TFMT4_8_UINT = 6,
TFMT4_8_8_UINT = 16,
TFMT4_8_8_8_8_UINT = 30,
+ TFMT4_8_SINT = 7,
TFMT4_8_8_SINT = 17,
TFMT4_8_8_8_8_SINT = 31,
TFMT4_16_UINT = 21,
@@ -246,7 +250,8 @@ enum a4xx_tex_clamp {
A4XX_TEX_REPEAT = 0,
A4XX_TEX_CLAMP_TO_EDGE = 1,
A4XX_TEX_MIRROR_REPEAT = 2,
- A4XX_TEX_CLAMP_NONE = 3,
+ A4XX_TEX_CLAMP_TO_BORDER = 3,
+ A4XX_TEX_MIRROR_CLAMP = 4,
};
enum a4xx_tex_aniso {
diff --git a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
index 399a9e528139..c304468cf2bd 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
@@ -8,13 +8,14 @@ http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 398 bytes, from 2015-09-24 17:25:31)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2015-05-20 20:03:14)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10755 bytes, from 2015-09-14 20:46:55)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14968 bytes, from 2015-05-20 20:12:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67120 bytes, from 2015-08-14 23:22:03)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63785 bytes, from 2015-08-14 18:27:06)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67771 bytes, from 2015-09-14 20:46:55)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63970 bytes, from 2015-09-14 20:50:12)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2015-09-24 17:30:00)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <[email protected]> (robclark)
@@ -85,6 +86,10 @@ enum adreno_rb_blend_factor {
FACTOR_CONSTANT_ALPHA = 14,
FACTOR_ONE_MINUS_CONSTANT_ALPHA = 15,
FACTOR_SRC_ALPHA_SATURATE = 16,
+ FACTOR_SRC1_COLOR = 20,
+ FACTOR_ONE_MINUS_SRC1_COLOR = 21,
+ FACTOR_SRC1_ALPHA = 22,
+ FACTOR_ONE_MINUS_SRC1_ALPHA = 23,
};
enum adreno_rb_surface_endian {
diff --git a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
index 41904fed1350..a22fef569499 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
@@ -8,13 +8,14 @@ http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 398 bytes, from 2015-09-24 17:25:31)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2015-05-20 20:03:14)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10755 bytes, from 2015-09-14 20:46:55)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14968 bytes, from 2015-05-20 20:12:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67120 bytes, from 2015-08-14 23:22:03)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63785 bytes, from 2015-08-14 18:27:06)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67771 bytes, from 2015-09-14 20:46:55)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63970 bytes, from 2015-09-14 20:50:12)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2015-09-24 17:30:00)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <[email protected]> (robclark)
diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 1d2e32f0817b..b2b5f3dd1b4c 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
@@ -567,114 +567,234 @@ static inline uint32_t DSI_VERSION_MAJOR(uint32_t val)
#define REG_DSI_8x60_PHY_CAL_STATUS 0x000000fc
#define DSI_8x60_PHY_CAL_STATUS_CAL_BUSY 0x10000000
-static inline uint32_t REG_DSI_8960_LN(uint32_t i0) { return 0x00000300 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN(uint32_t i0) { return 0x00000000 + 0x40*i0; }
-static inline uint32_t REG_DSI_8960_LN_CFG_0(uint32_t i0) { return 0x00000300 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_CFG_0(uint32_t i0) { return 0x00000000 + 0x40*i0; }
-static inline uint32_t REG_DSI_8960_LN_CFG_1(uint32_t i0) { return 0x00000304 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_CFG_1(uint32_t i0) { return 0x00000004 + 0x40*i0; }
-static inline uint32_t REG_DSI_8960_LN_CFG_2(uint32_t i0) { return 0x00000308 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_CFG_2(uint32_t i0) { return 0x00000008 + 0x40*i0; }
-static inline uint32_t REG_DSI_8960_LN_TEST_DATAPATH(uint32_t i0) { return 0x0000030c + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_TEST_DATAPATH(uint32_t i0) { return 0x0000000c + 0x40*i0; }
-static inline uint32_t REG_DSI_8960_LN_TEST_STR_0(uint32_t i0) { return 0x00000314 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_TEST_STR_0(uint32_t i0) { return 0x00000014 + 0x40*i0; }
-static inline uint32_t REG_DSI_8960_LN_TEST_STR_1(uint32_t i0) { return 0x00000318 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_TEST_STR_1(uint32_t i0) { return 0x00000018 + 0x40*i0; }
-#define REG_DSI_8960_PHY_LNCK_CFG_0 0x00000400
+#define REG_DSI_28nm_8960_PHY_LNCK_CFG_0 0x00000100
-#define REG_DSI_8960_PHY_LNCK_CFG_1 0x00000404
+#define REG_DSI_28nm_8960_PHY_LNCK_CFG_1 0x00000104
-#define REG_DSI_8960_PHY_LNCK_CFG_2 0x00000408
+#define REG_DSI_28nm_8960_PHY_LNCK_CFG_2 0x00000108
-#define REG_DSI_8960_PHY_LNCK_TEST_DATAPATH 0x0000040c
+#define REG_DSI_28nm_8960_PHY_LNCK_TEST_DATAPATH 0x0000010c
-#define REG_DSI_8960_PHY_LNCK_TEST_STR0 0x00000414
+#define REG_DSI_28nm_8960_PHY_LNCK_TEST_STR0 0x00000114
-#define REG_DSI_8960_PHY_LNCK_TEST_STR1 0x00000418
+#define REG_DSI_28nm_8960_PHY_LNCK_TEST_STR1 0x00000118
-#define REG_DSI_8960_PHY_TIMING_CTRL_0 0x00000440
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_0 0x00000140
+#define DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_1 0x00000144
+#define DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_2 0x00000148
+#define DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_3 0x0000014c
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_4 0x00000150
+#define DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_5 0x00000154
+#define DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_6 0x00000158
+#define DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_7 0x0000015c
+#define DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_8 0x00000160
+#define DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_9 0x00000164
+#define DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO__MASK 0x00000007
+#define DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO__MASK;
+}
+#define DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE__MASK 0x00000070
+#define DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE__SHIFT 4
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_10 0x00000168
+#define DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET__MASK 0x00000007
+#define DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_11 0x0000016c
+#define DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD__MASK 0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD__SHIFT 0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD(uint32_t val)
+{
+ return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_CTRL_0 0x00000170
+
+#define REG_DSI_28nm_8960_PHY_CTRL_1 0x00000174
+
+#define REG_DSI_28nm_8960_PHY_CTRL_2 0x00000178
+
+#define REG_DSI_28nm_8960_PHY_CTRL_3 0x0000017c
+
+#define REG_DSI_28nm_8960_PHY_STRENGTH_0 0x00000180
+
+#define REG_DSI_28nm_8960_PHY_STRENGTH_1 0x00000184
+
+#define REG_DSI_28nm_8960_PHY_STRENGTH_2 0x00000188
+
+#define REG_DSI_28nm_8960_PHY_BIST_CTRL_0 0x0000018c
+
+#define REG_DSI_28nm_8960_PHY_BIST_CTRL_1 0x00000190
+
+#define REG_DSI_28nm_8960_PHY_BIST_CTRL_2 0x00000194
+
+#define REG_DSI_28nm_8960_PHY_BIST_CTRL_3 0x00000198
+
+#define REG_DSI_28nm_8960_PHY_BIST_CTRL_4 0x0000019c
-#define REG_DSI_8960_PHY_TIMING_CTRL_1 0x00000444
+#define REG_DSI_28nm_8960_PHY_LDO_CTRL 0x000001b0
-#define REG_DSI_8960_PHY_TIMING_CTRL_2 0x00000448
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_0 0x00000000
-#define REG_DSI_8960_PHY_TIMING_CTRL_3 0x0000044c
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_1 0x00000004
-#define REG_DSI_8960_PHY_TIMING_CTRL_4 0x00000450
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_2 0x00000008
-#define REG_DSI_8960_PHY_TIMING_CTRL_5 0x00000454
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_3 0x0000000c
-#define REG_DSI_8960_PHY_TIMING_CTRL_6 0x00000458
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_4 0x00000010
-#define REG_DSI_8960_PHY_TIMING_CTRL_7 0x0000045c
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_5 0x00000014
-#define REG_DSI_8960_PHY_TIMING_CTRL_8 0x00000460
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CAL_PWR_CFG 0x00000018
-#define REG_DSI_8960_PHY_TIMING_CTRL_9 0x00000464
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_TRIGGER 0x00000028
-#define REG_DSI_8960_PHY_TIMING_CTRL_10 0x00000468
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_SW_CFG_0 0x0000002c
-#define REG_DSI_8960_PHY_TIMING_CTRL_11 0x0000046c
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_SW_CFG_1 0x00000030
-#define REG_DSI_8960_PHY_CTRL_0 0x00000470
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_SW_CFG_2 0x00000034
-#define REG_DSI_8960_PHY_CTRL_1 0x00000474
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_0 0x00000038
-#define REG_DSI_8960_PHY_CTRL_2 0x00000478
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_1 0x0000003c
-#define REG_DSI_8960_PHY_CTRL_3 0x0000047c
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_2 0x00000040
-#define REG_DSI_8960_PHY_STRENGTH_0 0x00000480
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_3 0x00000044
-#define REG_DSI_8960_PHY_STRENGTH_1 0x00000484
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_4 0x00000048
-#define REG_DSI_8960_PHY_STRENGTH_2 0x00000488
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_STATUS 0x00000050
+#define DSI_28nm_8960_PHY_MISC_CAL_STATUS_CAL_BUSY 0x00000010
-#define REG_DSI_8960_PHY_BIST_CTRL_0 0x0000048c
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_0 0x00000000
+#define DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE 0x00000001
-#define REG_DSI_8960_PHY_BIST_CTRL_1 0x00000490
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_1 0x00000004
-#define REG_DSI_8960_PHY_BIST_CTRL_2 0x00000494
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_2 0x00000008
-#define REG_DSI_8960_PHY_BIST_CTRL_3 0x00000498
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_3 0x0000000c
-#define REG_DSI_8960_PHY_BIST_CTRL_4 0x0000049c
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_4 0x00000010
-#define REG_DSI_8960_PHY_LDO_CTRL 0x000004b0
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_5 0x00000014
-#define REG_DSI_8960_PHY_REGULATOR_CTRL_0 0x00000500
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_6 0x00000018
-#define REG_DSI_8960_PHY_REGULATOR_CTRL_1 0x00000504
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_7 0x0000001c
-#define REG_DSI_8960_PHY_REGULATOR_CTRL_2 0x00000508
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_8 0x00000020
-#define REG_DSI_8960_PHY_REGULATOR_CTRL_3 0x0000050c
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_9 0x00000024
-#define REG_DSI_8960_PHY_REGULATOR_CTRL_4 0x00000510
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_10 0x00000028
-#define REG_DSI_8960_PHY_REGULATOR_CAL_PWR_CFG 0x00000518
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_11 0x0000002c
-#define REG_DSI_8960_PHY_CAL_HW_TRIGGER 0x00000528
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_12 0x00000030
-#define REG_DSI_8960_PHY_CAL_SW_CFG_0 0x0000052c
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_13 0x00000034
-#define REG_DSI_8960_PHY_CAL_SW_CFG_1 0x00000530
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_14 0x00000038
-#define REG_DSI_8960_PHY_CAL_SW_CFG_2 0x00000534
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_15 0x0000003c
-#define REG_DSI_8960_PHY_CAL_HW_CFG_0 0x00000538
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_16 0x00000040
-#define REG_DSI_8960_PHY_CAL_HW_CFG_1 0x0000053c
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_17 0x00000044
-#define REG_DSI_8960_PHY_CAL_HW_CFG_2 0x00000540
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_18 0x00000048
-#define REG_DSI_8960_PHY_CAL_HW_CFG_3 0x00000544
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_19 0x0000004c
-#define REG_DSI_8960_PHY_CAL_HW_CFG_4 0x00000548
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_20 0x00000050
-#define REG_DSI_8960_PHY_CAL_STATUS 0x00000550
-#define DSI_8960_PHY_CAL_STATUS_CAL_BUSY 0x00000010
+#define REG_DSI_28nm_8960_PHY_PLL_RDY 0x00000080
+#define DSI_28nm_8960_PHY_PLL_RDY_PLL_RDY 0x00000001
static inline uint32_t REG_DSI_28nm_PHY_LN(uint32_t i0) { return 0x00000000 + 0x40*i0; }
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 8d82973fe9db..4c49868efcda 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -278,7 +278,7 @@ static int dsi_regulator_init(struct msm_dsi_host *msm_host)
}
for (i = 0; i < num; i++) {
- if ((regs[i].min_voltage >= 0) && (regs[i].max_voltage >= 0)) {
+ if (regulator_can_change_voltage(s[i].consumer)) {
ret = regulator_set_voltage(s[i].consumer,
regs[i].min_voltage, regs[i].max_voltage);
if (ret < 0) {
diff --git a/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h b/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
index 5de505e627be..80ec65e47468 100644
--- a/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
+++ b/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index 401ff58d6893..f1f955f571fa 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -178,7 +178,7 @@ static int dsi_phy_regulator_init(struct msm_dsi_phy *phy)
}
for (i = 0; i < num; i++) {
- if ((regs[i].min_voltage >= 0) && (regs[i].max_voltage >= 0)) {
+ if (regulator_can_change_voltage(s[i].consumer)) {
ret = regulator_set_voltage(s[i].consumer,
regs[i].min_voltage, regs[i].max_voltage);
if (ret < 0) {
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
index f1a7c7b46420..edf74110ced7 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
@@ -99,16 +99,14 @@ static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_1(i), 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_2(i), 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_3(i), 0);
+ dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(i), 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_TEST_DATAPATH(i), 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_DEBUG_SEL(i), 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_TEST_STR_0(i), 0x1);
dsi_phy_write(base + REG_DSI_28nm_PHY_LN_TEST_STR_1(i), 0x97);
}
- dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(0), 0);
- dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(1), 0x5);
- dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(2), 0xa);
- dsi_phy_write(base + REG_DSI_28nm_PHY_LN_CFG_4(3), 0xf);
+ dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_CFG_4, 0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_CFG_1, 0xc0);
dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_TEST_STR0, 0x1);
dsi_phy_write(base + REG_DSI_28nm_PHY_LNCK_TEST_STR1, 0xbb);
diff --git a/drivers/gpu/drm/msm/dsi/sfpb.xml.h b/drivers/gpu/drm/msm/dsi/sfpb.xml.h
index 06cbddfc914f..7d7662e69e11 100644
--- a/drivers/gpu/drm/msm/dsi/sfpb.xml.h
+++ b/drivers/gpu/drm/msm/dsi/sfpb.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
@@ -45,7 +45,18 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#define REG_SFPB_CFG 0x00000058
+enum sfpb_ahb_arb_master_port_en {
+ SFPB_MASTER_PORT_ENABLE = 3,
+ SFPB_MASTER_PORT_DISABLE = 0,
+};
+
+#define REG_SFPB_GPREG 0x00000058
+#define SFPB_GPREG_MASTER_PORT_EN__MASK 0x00001800
+#define SFPB_GPREG_MASTER_PORT_EN__SHIFT 11
+static inline uint32_t SFPB_GPREG_MASTER_PORT_EN(enum sfpb_ahb_arb_master_port_en val)
+{
+ return ((val) << SFPB_GPREG_MASTER_PORT_EN__SHIFT) & SFPB_GPREG_MASTER_PORT_EN__MASK;
+}
#endif /* SFPB_XML */
diff --git a/drivers/gpu/drm/msm/edp/edp.xml.h b/drivers/gpu/drm/msm/edp/edp.xml.h
index bef1d65fe28c..90bf5ed46746 100644
--- a/drivers/gpu/drm/msm/edp/edp.xml.h
+++ b/drivers/gpu/drm/msm/edp/edp.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 101b324cdeef..1f4a95eeb348 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -328,6 +328,9 @@ fail:
.item ## _names = item ##_names_ ## entry, \
.item ## _cnt = ARRAY_SIZE(item ## _names_ ## entry)
+static const char *pwr_reg_names_none[] = {};
+static const char *hpd_reg_names_none[] = {};
+
static struct hdmi_platform_config hdmi_tx_8660_config = {
.phy_init = hdmi_phy_8x60_init,
};
@@ -367,18 +370,26 @@ static struct hdmi_platform_config hdmi_tx_8084_config = {
.hpd_freq = hpd_clk_freq_8x74,
};
-static const char *hpd_reg_names_8x94[] = {};
-
static struct hdmi_platform_config hdmi_tx_8994_config = {
.phy_init = NULL, /* nothing to do for this HDMI PHY 20nm */
HDMI_CFG(pwr_reg, 8x74),
- HDMI_CFG(hpd_reg, 8x94),
+ HDMI_CFG(hpd_reg, none),
+ HDMI_CFG(pwr_clk, 8x74),
+ HDMI_CFG(hpd_clk, 8x74),
+ .hpd_freq = hpd_clk_freq_8x74,
+};
+
+static struct hdmi_platform_config hdmi_tx_8996_config = {
+ .phy_init = NULL,
+ HDMI_CFG(pwr_reg, none),
+ HDMI_CFG(hpd_reg, none),
HDMI_CFG(pwr_clk, 8x74),
HDMI_CFG(hpd_clk, 8x74),
.hpd_freq = hpd_clk_freq_8x74,
};
static const struct of_device_id dt_match[] = {
+ { .compatible = "qcom,hdmi-tx-8996", .data = &hdmi_tx_8996_config },
{ .compatible = "qcom,hdmi-tx-8994", .data = &hdmi_tx_8994_config },
{ .compatible = "qcom,hdmi-tx-8084", .data = &hdmi_tx_8084_config },
{ .compatible = "qcom,hdmi-tx-8974", .data = &hdmi_tx_8974_config },
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
index 0b1b5586ff35..10c45700aefe 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
diff --git a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
index 2aa23b98f8aa..dbd9cc4daf2e 100644
--- a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
+++ b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
index 74b86734fef5..d5d94575fa1b 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
index 3469f50d5590..c37da9c61e29 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
@@ -895,6 +895,7 @@ static inline uint32_t MDP5_PIPE_SRC_OP_MODE_BWC(enum mdp5_pipe_bwc val)
#define MDP5_PIPE_SRC_OP_MODE_IGC_ROM_1 0x00040000
#define MDP5_PIPE_SRC_OP_MODE_DEINTERLACE 0x00400000
#define MDP5_PIPE_SRC_OP_MODE_DEINTERLACE_ODD 0x00800000
+#define MDP5_PIPE_SRC_OP_MODE_SW_PIX_EXT_OVERRIDE 0x80000000
static inline uint32_t REG_MDP5_PIPE_SRC_CONSTANT_COLOR(enum mdp5_pipe i0) { return 0x0000003c + __offset_PIPE(i0); }
@@ -932,6 +933,83 @@ static inline uint32_t MDP5_PIPE_DECIMATION_HORZ(uint32_t val)
return ((val) << MDP5_PIPE_DECIMATION_HORZ__SHIFT) & MDP5_PIPE_DECIMATION_HORZ__MASK;
}
+static inline uint32_t __offset_SW_PIX_EXT(enum mdp_component_type idx)
+{
+ switch (idx) {
+ case COMP_0: return 0x00000100;
+ case COMP_1_2: return 0x00000110;
+ case COMP_3: return 0x00000120;
+ default: return INVALID_IDX(idx);
+ }
+}
+static inline uint32_t REG_MDP5_PIPE_SW_PIX_EXT(enum mdp5_pipe i0, enum mdp_component_type i1) { return 0x00000000 + __offset_PIPE(i0) + __offset_SW_PIX_EXT(i1); }
+
+static inline uint32_t REG_MDP5_PIPE_SW_PIX_EXT_LR(enum mdp5_pipe i0, enum mdp_component_type i1) { return 0x00000000 + __offset_PIPE(i0) + __offset_SW_PIX_EXT(i1); }
+#define MDP5_PIPE_SW_PIX_EXT_LR_LEFT_RPT__MASK 0x000000ff
+#define MDP5_PIPE_SW_PIX_EXT_LR_LEFT_RPT__SHIFT 0
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_LR_LEFT_RPT(uint32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_LR_LEFT_RPT__SHIFT) & MDP5_PIPE_SW_PIX_EXT_LR_LEFT_RPT__MASK;
+}
+#define MDP5_PIPE_SW_PIX_EXT_LR_LEFT_OVF__MASK 0x0000ff00
+#define MDP5_PIPE_SW_PIX_EXT_LR_LEFT_OVF__SHIFT 8
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_LR_LEFT_OVF(int32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_LR_LEFT_OVF__SHIFT) & MDP5_PIPE_SW_PIX_EXT_LR_LEFT_OVF__MASK;
+}
+#define MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_RPT__MASK 0x00ff0000
+#define MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_RPT__SHIFT 16
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_RPT(uint32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_RPT__SHIFT) & MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_RPT__MASK;
+}
+#define MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_OVF__MASK 0xff000000
+#define MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_OVF__SHIFT 24
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_OVF(int32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_OVF__SHIFT) & MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_OVF__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SW_PIX_EXT_TB(enum mdp5_pipe i0, enum mdp_component_type i1) { return 0x00000004 + __offset_PIPE(i0) + __offset_SW_PIX_EXT(i1); }
+#define MDP5_PIPE_SW_PIX_EXT_TB_TOP_RPT__MASK 0x000000ff
+#define MDP5_PIPE_SW_PIX_EXT_TB_TOP_RPT__SHIFT 0
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_TB_TOP_RPT(uint32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_TB_TOP_RPT__SHIFT) & MDP5_PIPE_SW_PIX_EXT_TB_TOP_RPT__MASK;
+}
+#define MDP5_PIPE_SW_PIX_EXT_TB_TOP_OVF__MASK 0x0000ff00
+#define MDP5_PIPE_SW_PIX_EXT_TB_TOP_OVF__SHIFT 8
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_TB_TOP_OVF(int32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_TB_TOP_OVF__SHIFT) & MDP5_PIPE_SW_PIX_EXT_TB_TOP_OVF__MASK;
+}
+#define MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_RPT__MASK 0x00ff0000
+#define MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_RPT__SHIFT 16
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_RPT(uint32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_RPT__SHIFT) & MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_RPT__MASK;
+}
+#define MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_OVF__MASK 0xff000000
+#define MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_OVF__SHIFT 24
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_OVF(int32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_OVF__SHIFT) & MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_OVF__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS(enum mdp5_pipe i0, enum mdp_component_type i1) { return 0x00000008 + __offset_PIPE(i0) + __offset_SW_PIX_EXT(i1); }
+#define MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_LEFT_RIGHT__MASK 0x0000ffff
+#define MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_LEFT_RIGHT__SHIFT 0
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_LEFT_RIGHT(uint32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_LEFT_RIGHT__SHIFT) & MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_LEFT_RIGHT__MASK;
+}
+#define MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_TOP_BOTTOM__MASK 0xffff0000
+#define MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_TOP_BOTTOM__SHIFT 16
+static inline uint32_t MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_TOP_BOTTOM(uint32_t val)
+{
+ return ((val) << MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_TOP_BOTTOM__SHIFT) & MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_TOP_BOTTOM__MASK;
+}
+
static inline uint32_t REG_MDP5_PIPE_SCALE_CONFIG(enum mdp5_pipe i0) { return 0x00000204 + __offset_PIPE(i0); }
#define MDP5_PIPE_SCALE_CONFIG_SCALEX_EN 0x00000001
#define MDP5_PIPE_SCALE_CONFIG_SCALEY_EN 0x00000002
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
index a1e26f23c7cc..bb1225aa2f75 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
@@ -27,6 +27,8 @@ const struct mdp5_cfg_hw msm8x74v1_config = {
.mdp = {
.count = 1,
.base = { 0x00100 },
+ .caps = MDP_CAP_SMP |
+ 0,
},
.smp = {
.mmb_count = 22,
@@ -96,6 +98,8 @@ const struct mdp5_cfg_hw msm8x74v2_config = {
.mdp = {
.count = 1,
.base = { 0x00100 },
+ .caps = MDP_CAP_SMP |
+ 0,
},
.smp = {
.mmb_count = 22,
@@ -165,6 +169,8 @@ const struct mdp5_cfg_hw apq8084_config = {
.mdp = {
.count = 1,
.base = { 0x00100 },
+ .caps = MDP_CAP_SMP |
+ 0,
},
.smp = {
.mmb_count = 44,
@@ -242,6 +248,8 @@ const struct mdp5_cfg_hw msm8x16_config = {
.mdp = {
.count = 1,
.base = { 0x01000 },
+ .caps = MDP_CAP_SMP |
+ 0,
},
.smp = {
.mmb_count = 8,
@@ -301,6 +309,8 @@ const struct mdp5_cfg_hw msm8x94_config = {
.mdp = {
.count = 1,
.base = { 0x01000 },
+ .caps = MDP_CAP_SMP |
+ 0,
},
.smp = {
.mmb_count = 44,
@@ -370,7 +380,89 @@ const struct mdp5_cfg_hw msm8x94_config = {
[3] = INTF_HDMI,
},
},
- .max_clk = 320000000,
+ .max_clk = 400000000,
+};
+
+const struct mdp5_cfg_hw msm8x96_config = {
+ .name = "msm8x96",
+ .mdp = {
+ .count = 1,
+ .base = { 0x01000 },
+ .caps = MDP_CAP_DSC |
+ MDP_CAP_CDM |
+ 0,
+ },
+ .ctl = {
+ .count = 5,
+ .base = { 0x02000, 0x02200, 0x02400, 0x02600, 0x02800 },
+ .flush_hw_mask = 0xf4ffffff,
+ },
+ .pipe_vig = {
+ .count = 4,
+ .base = { 0x05000, 0x07000, 0x09000, 0x0b000 },
+ .caps = MDP_PIPE_CAP_HFLIP |
+ MDP_PIPE_CAP_VFLIP |
+ MDP_PIPE_CAP_SCALE |
+ MDP_PIPE_CAP_CSC |
+ MDP_PIPE_CAP_DECIMATION |
+ MDP_PIPE_CAP_SW_PIX_EXT |
+ 0,
+ },
+ .pipe_rgb = {
+ .count = 4,
+ .base = { 0x15000, 0x17000, 0x19000, 0x1b000 },
+ .caps = MDP_PIPE_CAP_HFLIP |
+ MDP_PIPE_CAP_VFLIP |
+ MDP_PIPE_CAP_SCALE |
+ MDP_PIPE_CAP_DECIMATION |
+ MDP_PIPE_CAP_SW_PIX_EXT |
+ 0,
+ },
+ .pipe_dma = {
+ .count = 2,
+ .base = { 0x25000, 0x27000 },
+ .caps = MDP_PIPE_CAP_HFLIP |
+ MDP_PIPE_CAP_VFLIP |
+ MDP_PIPE_CAP_SW_PIX_EXT |
+ 0,
+ },
+ .lm = {
+ .count = 6,
+ .base = { 0x45000, 0x46000, 0x47000, 0x48000, 0x49000, 0x4a000 },
+ .nb_stages = 8,
+ .max_width = 2560,
+ .max_height = 0xFFFF,
+ },
+ .dspp = {
+ .count = 2,
+ .base = { 0x55000, 0x57000 },
+ },
+ .ad = {
+ .count = 3,
+ .base = { 0x79000, 0x79800, 0x7a000 },
+ },
+ .pp = {
+ .count = 4,
+ .base = { 0x71000, 0x71800, 0x72000, 0x72800 },
+ },
+ .cdm = {
+ .count = 1,
+ .base = { 0x7a200 },
+ },
+ .dsc = {
+ .count = 2,
+ .base = { 0x81000, 0x81400 },
+ },
+ .intf = {
+ .base = { 0x6b000, 0x6b800, 0x6c000, 0x6c800, 0x6d000 },
+ .connect = {
+ [0] = INTF_DISABLED,
+ [1] = INTF_DSI,
+ [2] = INTF_DSI,
+ [3] = INTF_HDMI,
+ },
+ },
+ .max_clk = 412500000,
};
static const struct mdp5_cfg_handler cfg_handlers[] = {
@@ -379,6 +471,7 @@ static const struct mdp5_cfg_handler cfg_handlers[] = {
{ .revision = 3, .config = { .hw = &apq8084_config } },
{ .revision = 6, .config = { .hw = &msm8x16_config } },
{ .revision = 9, .config = { .hw = &msm8x94_config } },
+ { .revision = 7, .config = { .hw = &msm8x96_config } },
};
static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
index efb918d9f68b..050e1618c836 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
@@ -61,7 +61,12 @@ struct mdp5_smp_block {
int mmb_size; /* MMB: size in bytes */
uint32_t clients[MAX_CLIENTS]; /* SMP port allocation /pipe */
mdp5_smp_state_t reserved_state;/* SMP MMBs statically allocated */
- int reserved[MAX_CLIENTS]; /* # of MMBs allocated per client */
+ uint8_t reserved[MAX_CLIENTS]; /* # of MMBs allocated per client */
+};
+
+struct mdp5_mdp_block {
+ MDP5_SUB_BLOCK_DEFINITION;
+ uint32_t caps; /* MDP capabilities: MDP_CAP_xxx bits */
};
#define MDP5_INTF_NUM_MAX 5
@@ -74,7 +79,7 @@ struct mdp5_intf_block {
struct mdp5_cfg_hw {
char *name;
- struct mdp5_sub_block mdp;
+ struct mdp5_mdp_block mdp;
struct mdp5_smp_block smp;
struct mdp5_ctl_block ctl;
struct mdp5_pipe_block pipe_vig;
@@ -84,6 +89,8 @@ struct mdp5_cfg_hw {
struct mdp5_sub_block dspp;
struct mdp5_sub_block ad;
struct mdp5_sub_block pp;
+ struct mdp5_sub_block dsc;
+ struct mdp5_sub_block cdm;
struct mdp5_intf_block intf;
uint32_t max_clk;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 047cb0433ccb..b532faa8026d 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -452,15 +452,19 @@ static void read_hw_revision(struct mdp5_kms *mdp5_kms,
}
static int get_clk(struct platform_device *pdev, struct clk **clkp,
- const char *name)
+ const char *name, bool mandatory)
{
struct device *dev = &pdev->dev;
struct clk *clk = devm_clk_get(dev, name);
- if (IS_ERR(clk)) {
+ if (IS_ERR(clk) && mandatory) {
dev_err(dev, "failed to get %s (%ld)\n", name, PTR_ERR(clk));
return PTR_ERR(clk);
}
- *clkp = clk;
+ if (IS_ERR(clk))
+ DBG("skipping %s", name);
+ else
+ *clkp = clk;
+
return 0;
}
@@ -514,25 +518,26 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
goto fail;
}
- ret = get_clk(pdev, &mdp5_kms->axi_clk, "bus_clk");
+ /* mandatory clocks: */
+ ret = get_clk(pdev, &mdp5_kms->axi_clk, "bus_clk", true);
if (ret)
goto fail;
- ret = get_clk(pdev, &mdp5_kms->ahb_clk, "iface_clk");
+ ret = get_clk(pdev, &mdp5_kms->ahb_clk, "iface_clk", true);
if (ret)
goto fail;
- ret = get_clk(pdev, &mdp5_kms->src_clk, "core_clk_src");
+ ret = get_clk(pdev, &mdp5_kms->src_clk, "core_clk_src", true);
if (ret)
goto fail;
- ret = get_clk(pdev, &mdp5_kms->core_clk, "core_clk");
+ ret = get_clk(pdev, &mdp5_kms->core_clk, "core_clk", true);
if (ret)
goto fail;
- ret = get_clk(pdev, &mdp5_kms->lut_clk, "lut_clk");
- if (ret)
- DBG("failed to get (optional) lut_clk clock");
- ret = get_clk(pdev, &mdp5_kms->vsync_clk, "vsync_clk");
+ ret = get_clk(pdev, &mdp5_kms->vsync_clk, "vsync_clk", true);
if (ret)
goto fail;
+ /* optional clocks: */
+ get_clk(pdev, &mdp5_kms->lut_clk, "lut_clk", false);
+
/* we need to set a default rate before enabling. Set a safe
* rate first, then figure out hw revision, and then set a
* more optimal rate:
@@ -549,15 +554,23 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
}
config = mdp5_cfg_get_config(mdp5_kms->cfg);
+ mdp5_kms->caps = config->hw->mdp.caps;
/* TODO: compute core clock rate at runtime */
clk_set_rate(mdp5_kms->src_clk, config->hw->max_clk);
- mdp5_kms->smp = mdp5_smp_init(mdp5_kms->dev, &config->hw->smp);
- if (IS_ERR(mdp5_kms->smp)) {
- ret = PTR_ERR(mdp5_kms->smp);
- mdp5_kms->smp = NULL;
- goto fail;
+ /*
+ * Some chipsets have a Shared Memory Pool (SMP), while others
+ * have dedicated latency buffering per source pipe instead;
+ * this section initializes the SMP:
+ */
+ if (mdp5_kms->caps & MDP_CAP_SMP) {
+ mdp5_kms->smp = mdp5_smp_init(mdp5_kms->dev, &config->hw->smp);
+ if (IS_ERR(mdp5_kms->smp)) {
+ ret = PTR_ERR(mdp5_kms->smp);
+ mdp5_kms->smp = NULL;
+ goto fail;
+ }
}
mdp5_kms->ctlm = mdp5_ctlm_init(dev, mdp5_kms->mmio, mdp5_kms->cfg);
@@ -586,6 +599,7 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
if (IS_ERR(mmu)) {
ret = PTR_ERR(mmu);
dev_err(dev->dev, "failed to init iommu: %d\n", ret);
+ iommu_domain_free(config->platform.iommu);
goto fail;
}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index 0bb62423586e..84f65d415598 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -32,6 +32,8 @@ struct mdp5_kms {
struct drm_device *dev;
struct mdp5_cfg_handler *cfg;
+ uint32_t caps; /* MDP capabilities (MDP_CAP_XXX bits) */
+
/* mapper-id used to request GEM buffer mapped for scanout: */
int id;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index a0f5ff0ce8dc..81cd49045ffc 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -500,7 +500,7 @@ static int calc_phase_step(uint32_t src, uint32_t dst, uint32_t *out_phase)
static int calc_scalex_steps(struct drm_plane *plane,
uint32_t pixel_format, uint32_t src, uint32_t dest,
- uint32_t phasex_steps[2])
+ uint32_t phasex_steps[COMP_MAX])
{
struct mdp5_kms *mdp5_kms = get_kms(plane);
struct device *dev = mdp5_kms->dev->dev;
@@ -516,15 +516,16 @@ static int calc_scalex_steps(struct drm_plane *plane,
hsub = drm_format_horz_chroma_subsampling(pixel_format);
- phasex_steps[0] = phasex_step;
- phasex_steps[1] = phasex_step / hsub;
+ phasex_steps[COMP_0] = phasex_step;
+ phasex_steps[COMP_3] = phasex_step;
+ phasex_steps[COMP_1_2] = phasex_step / hsub;
return 0;
}
static int calc_scaley_steps(struct drm_plane *plane,
uint32_t pixel_format, uint32_t src, uint32_t dest,
- uint32_t phasey_steps[2])
+ uint32_t phasey_steps[COMP_MAX])
{
struct mdp5_kms *mdp5_kms = get_kms(plane);
struct device *dev = mdp5_kms->dev->dev;
@@ -540,46 +541,127 @@ static int calc_scaley_steps(struct drm_plane *plane,
vsub = drm_format_vert_chroma_subsampling(pixel_format);
- phasey_steps[0] = phasey_step;
- phasey_steps[1] = phasey_step / vsub;
+ phasey_steps[COMP_0] = phasey_step;
+ phasey_steps[COMP_3] = phasey_step;
+ phasey_steps[COMP_1_2] = phasey_step / vsub;
return 0;
}
-static uint32_t get_scale_config(enum mdp_chroma_samp_type chroma_sample,
- uint32_t src, uint32_t dest, bool hor)
+static uint32_t get_scale_config(const struct mdp_format *format,
+ uint32_t src, uint32_t dst, bool horz)
{
- uint32_t y_filter = (src <= dest) ? SCALE_FILTER_CA : SCALE_FILTER_PCMN;
- uint32_t y_a_filter = (src <= dest) ? SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
- uint32_t uv_filter = ((src / 2) <= dest) ? /* 2x upsample */
- SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
- uint32_t value = 0;
-
- if (chroma_sample == CHROMA_420 || chroma_sample == CHROMA_H2V1) {
- if (hor)
- value = MDP5_PIPE_SCALE_CONFIG_SCALEX_EN |
- MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_0(y_filter) |
- MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_3(y_a_filter) |
- MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_1_2(uv_filter);
- else
- value = MDP5_PIPE_SCALE_CONFIG_SCALEY_EN |
- MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_0(y_filter) |
- MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_3(y_a_filter) |
- MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_1_2(uv_filter);
- } else if (src != dest) {
- if (hor)
- value = MDP5_PIPE_SCALE_CONFIG_SCALEX_EN |
- MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_0(y_a_filter) |
- MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_3(y_a_filter);
- else
- value = MDP5_PIPE_SCALE_CONFIG_SCALEY_EN |
- MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_0(y_a_filter) |
- MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_3(y_a_filter);
+ bool scaling = format->is_yuv ? true : (src != dst);
+ uint32_t sub, pix_fmt = format->base.pixel_format;
+ uint32_t ya_filter, uv_filter;
+ bool yuv = format->is_yuv;
+
+ if (!scaling)
+ return 0;
+
+ if (yuv) {
+ sub = horz ? drm_format_horz_chroma_subsampling(pix_fmt) :
+ drm_format_vert_chroma_subsampling(pix_fmt);
+ uv_filter = ((src / sub) <= dst) ?
+ SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
}
+ ya_filter = (src <= dst) ? SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
- return value;
+ if (horz)
+ return MDP5_PIPE_SCALE_CONFIG_SCALEX_EN |
+ MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_0(ya_filter) |
+ MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_3(ya_filter) |
+ COND(yuv, MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_1_2(uv_filter));
+ else
+ return MDP5_PIPE_SCALE_CONFIG_SCALEY_EN |
+ MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_0(ya_filter) |
+ MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_3(ya_filter) |
+ COND(yuv, MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_1_2(uv_filter));
}
+static void calc_pixel_ext(const struct mdp_format *format,
+ uint32_t src, uint32_t dst, uint32_t phase_step[2],
+ int pix_ext_edge1[COMP_MAX], int pix_ext_edge2[COMP_MAX],
+ bool horz)
+{
+ bool scaling = format->is_yuv ? true : (src != dst);
+ int i;
+
+ /*
+ * Note:
+ * We assume here that:
+ * 1. PCMN filter is used for downscale
+ * 2. bilinear filter is used for upscale
+ * 3. we are in a single pipe configuration
+ */
+
+ for (i = 0; i < COMP_MAX; i++) {
+ pix_ext_edge1[i] = 0;
+ pix_ext_edge2[i] = scaling ? 1 : 0;
+ }
+}
+
+static void mdp5_write_pixel_ext(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe,
+ const struct mdp_format *format,
+ uint32_t src_w, int pe_left[COMP_MAX], int pe_right[COMP_MAX],
+ uint32_t src_h, int pe_top[COMP_MAX], int pe_bottom[COMP_MAX])
+{
+ uint32_t pix_fmt = format->base.pixel_format;
+ uint32_t lr, tb, req;
+ int i;
+
+ for (i = 0; i < COMP_MAX; i++) {
+ uint32_t roi_w = src_w;
+ uint32_t roi_h = src_h;
+
+ if (format->is_yuv && i == COMP_1_2) {
+ roi_w /= drm_format_horz_chroma_subsampling(pix_fmt);
+ roi_h /= drm_format_vert_chroma_subsampling(pix_fmt);
+ }
+
+ lr = (pe_left[i] >= 0) ?
+ MDP5_PIPE_SW_PIX_EXT_LR_LEFT_RPT(pe_left[i]) :
+ MDP5_PIPE_SW_PIX_EXT_LR_LEFT_OVF(pe_left[i]);
+
+ lr |= (pe_right[i] >= 0) ?
+ MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_RPT(pe_right[i]) :
+ MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_OVF(pe_right[i]);
+
+ tb = (pe_top[i] >= 0) ?
+ MDP5_PIPE_SW_PIX_EXT_TB_TOP_RPT(pe_top[i]) :
+ MDP5_PIPE_SW_PIX_EXT_TB_TOP_OVF(pe_top[i]);
+
+ tb |= (pe_bottom[i] >= 0) ?
+ MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_RPT(pe_bottom[i]) :
+ MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_OVF(pe_bottom[i]);
+
+ req = MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_LEFT_RIGHT(roi_w +
+ pe_left[i] + pe_right[i]);
+
+ req |= MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_TOP_BOTTOM(roi_h +
+ pe_top[i] + pe_bottom[i]);
+
+ mdp5_write(mdp5_kms, REG_MDP5_PIPE_SW_PIX_EXT_LR(pipe, i), lr);
+ mdp5_write(mdp5_kms, REG_MDP5_PIPE_SW_PIX_EXT_TB(pipe, i), tb);
+ mdp5_write(mdp5_kms, REG_MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS(pipe, i), req);
+
+ DBG("comp-%d (L/R): rpt=%d/%d, ovf=%d/%d, req=%d", i,
+ FIELD(lr, MDP5_PIPE_SW_PIX_EXT_LR_LEFT_RPT),
+ FIELD(lr, MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_RPT),
+ FIELD(lr, MDP5_PIPE_SW_PIX_EXT_LR_LEFT_OVF),
+ FIELD(lr, MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_OVF),
+ FIELD(req, MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_LEFT_RIGHT));
+
+ DBG("comp-%d (T/B): rpt=%d/%d, ovf=%d/%d, req=%d", i,
+ FIELD(tb, MDP5_PIPE_SW_PIX_EXT_TB_TOP_RPT),
+ FIELD(tb, MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_RPT),
+ FIELD(tb, MDP5_PIPE_SW_PIX_EXT_TB_TOP_OVF),
+ FIELD(tb, MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_OVF),
+ FIELD(req, MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_TOP_BOTTOM));
+ }
+}
+
+
static int mdp5_plane_mode_set(struct drm_plane *plane,
struct drm_crtc *crtc, struct drm_framebuffer *fb,
int crtc_x, int crtc_y,
@@ -593,8 +675,10 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
enum mdp5_pipe pipe = mdp5_plane->pipe;
const struct mdp_format *format;
uint32_t nplanes, config = 0;
- /* below array -> index 0: comp 0/3 ; index 1: comp 1/2 */
- uint32_t phasex_step[2] = {0,}, phasey_step[2] = {0,};
+ uint32_t phasex_step[COMP_MAX] = {0,}, phasey_step[COMP_MAX] = {0,};
+ bool pe = mdp5_plane->caps & MDP_PIPE_CAP_SW_PIX_EXT;
+ int pe_left[COMP_MAX], pe_right[COMP_MAX];
+ int pe_top[COMP_MAX], pe_bottom[COMP_MAX];
uint32_t hdecm = 0, vdecm = 0;
uint32_t pix_format;
bool vflip, hflip;
@@ -621,10 +705,12 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h);
/* Request some memory from the SMP: */
- ret = mdp5_smp_request(mdp5_kms->smp,
- mdp5_plane->pipe, format, src_w, false);
- if (ret)
- return ret;
+ if (mdp5_kms->smp) {
+ ret = mdp5_smp_request(mdp5_kms->smp,
+ mdp5_plane->pipe, format, src_w, false);
+ if (ret)
+ return ret;
+ }
/*
* Currently we update the hw for allocations/requests immediately,
@@ -632,7 +718,8 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
* would move into atomic->check_plane_state(), while updating the
* hw would remain here:
*/
- mdp5_smp_configure(mdp5_kms->smp, pipe);
+ if (mdp5_kms->smp)
+ mdp5_smp_configure(mdp5_kms->smp, pipe);
ret = calc_scalex_steps(plane, pix_format, src_w, crtc_w, phasex_step);
if (ret)
@@ -642,11 +729,18 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
if (ret)
return ret;
+ if (mdp5_plane->caps & MDP_PIPE_CAP_SW_PIX_EXT) {
+ calc_pixel_ext(format, src_w, crtc_w, phasex_step,
+ pe_left, pe_right, true);
+ calc_pixel_ext(format, src_h, crtc_h, phasey_step,
+ pe_top, pe_bottom, false);
+ }
+
/* TODO calc hdecm, vdecm */
/* SCALE is used to both scale and up-sample chroma components */
- config |= get_scale_config(format->chroma_sample, src_w, crtc_w, true);
- config |= get_scale_config(format->chroma_sample, src_h, crtc_h, false);
+ config |= get_scale_config(format, src_w, crtc_w, true);
+ config |= get_scale_config(format, src_h, crtc_h, false);
DBG("scale config = %x", config);
hflip = !!(pstate->rotation & BIT(DRM_REFLECT_X));
@@ -695,20 +789,26 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_OP_MODE(pipe),
(hflip ? MDP5_PIPE_SRC_OP_MODE_FLIP_LR : 0) |
(vflip ? MDP5_PIPE_SRC_OP_MODE_FLIP_UD : 0) |
+ COND(pe, MDP5_PIPE_SRC_OP_MODE_SW_PIX_EXT_OVERRIDE) |
MDP5_PIPE_SRC_OP_MODE_BWC(BWC_LOSSLESS));
/* not using secure mode: */
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(pipe), 0);
+ if (mdp5_plane->caps & MDP_PIPE_CAP_SW_PIX_EXT)
+ mdp5_write_pixel_ext(mdp5_kms, pipe, format,
+ src_w, pe_left, pe_right,
+ src_h, pe_top, pe_bottom);
+
if (mdp5_plane->caps & MDP_PIPE_CAP_SCALE) {
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe),
- phasex_step[0]);
+ phasex_step[COMP_0]);
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe),
- phasey_step[0]);
+ phasey_step[COMP_0]);
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_X(pipe),
- phasex_step[1]);
+ phasex_step[COMP_1_2]);
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_Y(pipe),
- phasey_step[1]);
+ phasey_step[COMP_1_2]);
mdp5_write(mdp5_kms, REG_MDP5_PIPE_DECIMATION(pipe),
MDP5_PIPE_DECIMATION_VERT(vdecm) |
MDP5_PIPE_DECIMATION_HORZ(hdecm));
@@ -738,7 +838,8 @@ void mdp5_plane_complete_flip(struct drm_plane *plane)
DBG("%s: complete flip", mdp5_plane->name);
- mdp5_smp_commit(mdp5_kms->smp, pipe);
+ if (mdp5_kms->smp)
+ mdp5_smp_commit(mdp5_kms->smp, pipe);
to_mdp5_plane_state(plane->state)->pending = false;
}
@@ -764,7 +865,7 @@ void mdp5_plane_complete_commit(struct drm_plane *plane,
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
enum mdp5_pipe pipe = mdp5_plane->pipe;
- if (!plane_enabled(plane->state)) {
+ if (!plane_enabled(plane->state) && mdp5_kms->smp) {
DBG("%s: free SMP", mdp5_plane->name);
mdp5_smp_release(mdp5_kms->smp, pipe);
}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
index 563cca972dcb..6f425c25d9fe 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
@@ -90,7 +90,7 @@
struct mdp5_smp {
struct drm_device *dev;
- const struct mdp5_smp_block *cfg;
+ uint8_t reserved[MAX_CLIENTS]; /* fixed MMBs allocation per client */
int blk_cnt;
int blk_size;
@@ -141,10 +141,10 @@ static int smp_request_block(struct mdp5_smp *smp,
struct mdp5_kms *mdp5_kms = get_kms(smp);
struct mdp5_client_smp_state *ps = &smp->client_state[cid];
int i, ret, avail, cur_nblks, cnt = smp->blk_cnt;
- int reserved;
+ uint8_t reserved;
unsigned long flags;
- reserved = smp->cfg->reserved[cid];
+ reserved = smp->reserved[cid];
spin_lock_irqsave(&smp->state_lock, flags);
@@ -405,12 +405,12 @@ struct mdp5_smp *mdp5_smp_init(struct drm_device *dev, const struct mdp5_smp_blo
}
smp->dev = dev;
- smp->cfg = cfg;
smp->blk_cnt = cfg->mmb_count;
smp->blk_size = cfg->mmb_size;
/* statically tied MMBs cannot be re-allocated: */
bitmap_copy(smp->state, cfg->reserved_state, smp->blk_cnt);
+ memcpy(smp->reserved, cfg->reserved, sizeof(smp->reserved));
spin_lock_init(&smp->state_lock);
return smp;
diff --git a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
index 4f792c4e40f4..0aec1ac1f6d0 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
@@ -11,10 +11,10 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 602 bytes, from 2015-10-22 16:35:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2015-05-20 20:03:07)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29154 bytes, from 2015-08-10 21:25:43)
@@ -78,6 +78,13 @@ enum mdp_alpha_type {
BG_PIXEL = 3,
};
+enum mdp_component_type {
+ COMP_0 = 0,
+ COMP_1_2 = 1,
+ COMP_3 = 2,
+ COMP_MAX = 3,
+};
+
enum mdp_bpc {
BPC1 = 0,
BPC5 = 1,
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h b/drivers/gpu/drm/msm/mdp/mdp_kms.h
index 46a94e7d50e2..303130320748 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_kms.h
@@ -100,12 +100,18 @@ struct mdp_format {
uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats, bool rgb_only);
const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format);
+/* MDP capabilities */
+#define MDP_CAP_SMP BIT(0) /* Shared Memory Pool */
+#define MDP_CAP_DSC BIT(1) /* VESA Display Stream Compression */
+#define MDP_CAP_CDM BIT(2) /* Chroma Down Module (HDMI 2.0 YUV) */
+
/* MDP pipe capabilities */
#define MDP_PIPE_CAP_HFLIP BIT(0)
#define MDP_PIPE_CAP_VFLIP BIT(1)
#define MDP_PIPE_CAP_SCALE BIT(2)
#define MDP_PIPE_CAP_CSC BIT(3)
#define MDP_PIPE_CAP_DECIMATION BIT(4)
+#define MDP_PIPE_CAP_SW_PIX_EXT BIT(5)
static inline bool pipe_supports_yuv(uint32_t pipe_caps)
{
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index d170131b0978..b88ce514eb8e 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -21,11 +21,9 @@
static void msm_fb_output_poll_changed(struct drm_device *dev)
{
-#ifdef CONFIG_DRM_MSM_FBDEV
struct msm_drm_private *priv = dev->dev_private;
if (priv->fbdev)
drm_fb_helper_hotplug_event(priv->fbdev);
-#endif
}
static const struct drm_mode_config_funcs mode_config_funcs = {
@@ -56,7 +54,7 @@ module_param(reglog, bool, 0600);
#define reglog 0
#endif
-#ifdef CONFIG_DRM_MSM_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
static bool fbdev = true;
MODULE_PARM_DESC(fbdev, "Enable fbdev compat layer");
module_param(fbdev, bool, 0600);
@@ -423,7 +421,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
drm_mode_config_reset(dev);
-#ifdef CONFIG_DRM_MSM_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
if (fbdev)
priv->fbdev = msm_fbdev_init(dev);
#endif
@@ -491,11 +489,9 @@ static void msm_preclose(struct drm_device *dev, struct drm_file *file)
static void msm_lastclose(struct drm_device *dev)
{
-#ifdef CONFIG_DRM_MSM_FBDEV
struct msm_drm_private *priv = dev->dev_private;
if (priv->fbdev)
drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
-#endif
}
static irqreturn_t msm_irq(int irq, void *arg)
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 8f70d9248ac5..6b02ada6579a 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -651,6 +651,14 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
if (iommu) {
dev_info(drm->dev, "%s: using IOMMU\n", name);
gpu->mmu = msm_iommu_new(&pdev->dev, iommu);
+ if (IS_ERR(gpu->mmu)) {
+ ret = PTR_ERR(gpu->mmu);
+ dev_err(drm->dev, "failed to init iommu: %d\n", ret);
+ gpu->mmu = NULL;
+ iommu_domain_free(iommu);
+ goto fail;
+ }
+
} else {
dev_info(drm->dev, "%s: no IOMMU, fallback to VRAM carveout!\n", name);
}
diff --git a/drivers/gpu/drm/radeon/cayman_blit_shaders.c b/drivers/gpu/drm/radeon/cayman_blit_shaders.c
index 98d009e154bf..9fec4d09f383 100644
--- a/drivers/gpu/drm/radeon/cayman_blit_shaders.c
+++ b/drivers/gpu/drm/radeon/cayman_blit_shaders.c
@@ -32,7 +32,7 @@
* evergreen cards need to use the 3D engine to blit data which requires
* quite a bit of hw state setup. Rather than pull the whole 3D driver
* (which normally generates the 3D state) into the DRM, we opt to use
- * statically generated state tables. The regsiter state and shaders
+ * statically generated state tables. The register state and shaders
* were hand generated to support blitting functionality. See the 3D
* driver or documentation for descriptions of the registers and
* shader instructions.
diff --git a/drivers/gpu/drm/radeon/evergreen_blit_shaders.c b/drivers/gpu/drm/radeon/evergreen_blit_shaders.c
index d43383470cdf..1a96ddb3e5ed 100644
--- a/drivers/gpu/drm/radeon/evergreen_blit_shaders.c
+++ b/drivers/gpu/drm/radeon/evergreen_blit_shaders.c
@@ -32,7 +32,7 @@
* evergreen cards need to use the 3D engine to blit data which requires
* quite a bit of hw state setup. Rather than pull the whole 3D driver
* (which normally generates the 3D state) into the DRM, we opt to use
- * statically generated state tables. The regsiter state and shaders
+ * statically generated state tables. The register state and shaders
* were hand generated to support blitting functionality. See the 3D
* driver or documentation for descriptions of the registers and
* shader instructions.
diff --git a/drivers/gpu/drm/radeon/r600_blit_shaders.c b/drivers/gpu/drm/radeon/r600_blit_shaders.c
index 34c8b2340f33..443cbe59b274 100644
--- a/drivers/gpu/drm/radeon/r600_blit_shaders.c
+++ b/drivers/gpu/drm/radeon/r600_blit_shaders.c
@@ -32,7 +32,7 @@
* R6xx+ cards need to use the 3D engine to blit data which requires
* quite a bit of hw state setup. Rather than pull the whole 3D driver
* (which normally generates the 3D state) into the DRM, we opt to use
- * statically generated state tables. The regsiter state and shaders
+ * statically generated state tables. The register state and shaders
* were hand generated to support blitting functionality. See the 3D
* driver or documentation for descriptions of the registers and
* shader instructions.
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 5f687c95a1e1..0ec6fcca16d3 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -181,7 +181,9 @@ static void radeon_set_filp_rights(struct drm_device *dev,
struct drm_file *applier,
uint32_t *value)
{
- mutex_lock(&dev->struct_mutex);
+ struct radeon_device *rdev = dev->dev_private;
+
+ mutex_lock(&rdev->gem.mutex);
if (*value == 1) {
/* wants rights */
if (!*owner)
@@ -192,7 +194,7 @@ static void radeon_set_filp_rights(struct drm_device *dev,
*owner = NULL;
}
*value = *owner == applier ? 1 : 0;
- mutex_unlock(&dev->struct_mutex);
+ mutex_unlock(&rdev->gem.mutex);
}
/*
@@ -727,10 +729,14 @@ void radeon_driver_preclose_kms(struct drm_device *dev,
struct drm_file *file_priv)
{
struct radeon_device *rdev = dev->dev_private;
+
+ mutex_lock(&rdev->gem.mutex);
if (rdev->hyperz_filp == file_priv)
rdev->hyperz_filp = NULL;
if (rdev->cmask_filp == file_priv)
rdev->cmask_filp = NULL;
+ mutex_unlock(&rdev->gem.mutex);
+
radeon_uvd_free_handles(rdev, file_priv);
radeon_vce_free_handles(rdev, file_priv);
}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index bebcc97db5e5..40422f6b645e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -84,12 +84,13 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = {
.num_lvds = 2,
};
+/* M2-W (r8a7791) and M2-N (r8a7793) are identical */
static const struct rcar_du_device_info rcar_du_r8a7791_info = {
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS,
.num_crtcs = 2,
.routes = {
- /* R8A7791 has one RGB output, one LVDS output and one
+ /* R8A779[13] has one RGB output, one LVDS output and one
* (currently unsupported) TCON output.
*/
[RCAR_DU_OUTPUT_DPAD0] = {
@@ -106,10 +107,34 @@ static const struct rcar_du_device_info rcar_du_r8a7791_info = {
.num_lvds = 1,
};
+static const struct rcar_du_device_info rcar_du_r8a7794_info = {
+ .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
+ | RCAR_DU_FEATURE_EXT_CTRL_REGS,
+ .num_crtcs = 2,
+ .routes = {
+ /* R8A7794 has two RGB outputs and one (currently unsupported)
+ * TCON output.
+ */
+ [RCAR_DU_OUTPUT_DPAD0] = {
+ .possible_crtcs = BIT(0),
+ .encoder_type = DRM_MODE_ENCODER_NONE,
+ .port = 0,
+ },
+ [RCAR_DU_OUTPUT_DPAD1] = {
+ .possible_crtcs = BIT(1),
+ .encoder_type = DRM_MODE_ENCODER_NONE,
+ .port = 1,
+ },
+ },
+ .num_lvds = 0,
+};
+
static const struct of_device_id rcar_du_of_table[] = {
{ .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
{ .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
{ .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
+ { .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info },
+ { .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
{ }
};
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 7fd39a7d91c8..8e2ffe025153 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -49,9 +49,10 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;
/* The DEFR8 register for the first group also controls RGB output
- * routing to DPAD0
+ * routing to DPAD0 for DU instances that support it.
*/
- if (rgrp->index == 0)
+ if (rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1 &&
+ rgrp->index == 0)
defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
rcar_du_group_write(rgrp, DEFR8, defr8);
diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig
new file mode 100644
index 000000000000..e502802d74b6
--- /dev/null
+++ b/drivers/gpu/drm/vc4/Kconfig
@@ -0,0 +1,13 @@
+config DRM_VC4
+ tristate "Broadcom VC4 Graphics"
+ depends on ARCH_BCM2835 || COMPILE_TEST
+ depends on DRM
+ select DRM_KMS_HELPER
+ select DRM_KMS_CMA_HELPER
+ help
+ Choose this option if you have a system that has a Broadcom
+ VC4 GPU, such as the Raspberry Pi or other BCM2708/BCM2835.
+
+ This driver requires that "avoid_warnings=2" be present in
+ the config.txt for the firmware, to keep it from smashing
+ our display setup.
diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile
new file mode 100644
index 000000000000..32b4f9cd8f52
--- /dev/null
+++ b/drivers/gpu/drm/vc4/Makefile
@@ -0,0 +1,17 @@
+ccflags-y := -Iinclude/drm
+
+# Please keep these build lists sorted!
+
+# core driver code
+vc4-y := \
+ vc4_bo.o \
+ vc4_crtc.o \
+ vc4_drv.o \
+ vc4_kms.o \
+ vc4_hdmi.o \
+ vc4_hvs.o \
+ vc4_plane.o
+
+vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o
+
+obj-$(CONFIG_DRM_VC4) += vc4.o
diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c
new file mode 100644
index 000000000000..ab9f5108ae1a
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_bo.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright © 2015 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* DOC: VC4 GEM BO management support.
+ *
+ * The VC4 GPU architecture (both scanout and rendering) has direct
+ * access to system memory with no MMU in between. To support it, we
+ * use the GEM CMA helper functions to allocate contiguous ranges of
+ * physical memory for our BOs.
+ */
+
+#include "vc4_drv.h"
+
+struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t size)
+{
+ struct drm_gem_cma_object *cma_obj;
+
+ cma_obj = drm_gem_cma_create(dev, size);
+ if (IS_ERR(cma_obj))
+ return NULL;
+ else
+ return to_vc4_bo(&cma_obj->base);
+}
+
+int vc4_dumb_create(struct drm_file *file_priv,
+ struct drm_device *dev,
+ struct drm_mode_create_dumb *args)
+{
+ int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+ struct vc4_bo *bo = NULL;
+ int ret;
+
+ if (args->pitch < min_pitch)
+ args->pitch = min_pitch;
+
+ if (args->size < args->pitch * args->height)
+ args->size = args->pitch * args->height;
+
+ bo = vc4_bo_create(dev, roundup(args->size, PAGE_SIZE));
+ if (!bo)
+ return -ENOMEM;
+
+ ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle);
+ drm_gem_object_unreference_unlocked(&bo->base.base);
+
+ return ret;
+}
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
new file mode 100644
index 000000000000..7a9f4768591e
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -0,0 +1,672 @@
+/*
+ * Copyright (C) 2015 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/**
+ * DOC: VC4 CRTC module
+ *
+ * In VC4, the Pixel Valve is what most closely corresponds to the
+ * DRM's concept of a CRTC. The PV generates video timings from the
+ * output's clock plus its configuration. It pulls scaled pixels from
+ * the HVS at that timing, and feeds it to the encoder.
+ *
+ * However, the DRM CRTC also collects the configuration of all the
+ * DRM planes attached to it. As a result, this file also manages
+ * setup of the VC4 HVS's display elements on the CRTC.
+ *
+ * The 2835 has 3 different pixel valves. pv0 in the audio power
+ * domain feeds DSI0 or DPI, while pv1 feeds DS1 or SMI. pv2 in the
+ * image domain can feed either HDMI or the SDTV controller. The
+ * pixel valve chooses from the CPRMAN clocks (HSM for HDMI, VEC for
+ * SDTV, etc.) according to which output type is chosen in the mux.
+ *
+ * For power management, the pixel valve's registers are all clocked
+ * by the AXI clock, while the timings and FIFOs make use of the
+ * output-specific clock. Since the encoders also directly consume
+ * the CPRMAN clocks, and know what timings they need, they are the
+ * ones that set the clock.
+ */
+
+#include "drm_atomic.h"
+#include "drm_atomic_helper.h"
+#include "drm_crtc_helper.h"
+#include "linux/clk.h"
+#include "linux/component.h"
+#include "linux/of_device.h"
+#include "vc4_drv.h"
+#include "vc4_regs.h"
+
+struct vc4_crtc {
+ struct drm_crtc base;
+ const struct vc4_crtc_data *data;
+ void __iomem *regs;
+
+ /* Which HVS channel we're using for our CRTC. */
+ int channel;
+
+ /* Pointer to the actual hardware display list memory for the
+ * crtc.
+ */
+ u32 __iomem *dlist;
+
+ u32 dlist_size; /* in dwords */
+
+ struct drm_pending_vblank_event *event;
+};
+
+static inline struct vc4_crtc *
+to_vc4_crtc(struct drm_crtc *crtc)
+{
+ return (struct vc4_crtc *)crtc;
+}
+
+struct vc4_crtc_data {
+ /* Which channel of the HVS this pixelvalve sources from. */
+ int hvs_channel;
+
+ enum vc4_encoder_type encoder0_type;
+ enum vc4_encoder_type encoder1_type;
+};
+
+#define CRTC_WRITE(offset, val) writel(val, vc4_crtc->regs + (offset))
+#define CRTC_READ(offset) readl(vc4_crtc->regs + (offset))
+
+#define CRTC_REG(reg) { reg, #reg }
+static const struct {
+ u32 reg;
+ const char *name;
+} crtc_regs[] = {
+ CRTC_REG(PV_CONTROL),
+ CRTC_REG(PV_V_CONTROL),
+ CRTC_REG(PV_VSYNCD),
+ CRTC_REG(PV_HORZA),
+ CRTC_REG(PV_HORZB),
+ CRTC_REG(PV_VERTA),
+ CRTC_REG(PV_VERTB),
+ CRTC_REG(PV_VERTA_EVEN),
+ CRTC_REG(PV_VERTB_EVEN),
+ CRTC_REG(PV_INTEN),
+ CRTC_REG(PV_INTSTAT),
+ CRTC_REG(PV_STAT),
+ CRTC_REG(PV_HACT_ACT),
+};
+
+static void vc4_crtc_dump_regs(struct vc4_crtc *vc4_crtc)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(crtc_regs); i++) {
+ DRM_INFO("0x%04x (%s): 0x%08x\n",
+ crtc_regs[i].reg, crtc_regs[i].name,
+ CRTC_READ(crtc_regs[i].reg));
+ }
+}
+
+#ifdef CONFIG_DEBUG_FS
+int vc4_crtc_debugfs_regs(struct seq_file *m, void *unused)
+{
+ struct drm_info_node *node = (struct drm_info_node *)m->private;
+ struct drm_device *dev = node->minor->dev;
+ int crtc_index = (uintptr_t)node->info_ent->data;
+ struct drm_crtc *crtc;
+ struct vc4_crtc *vc4_crtc;
+ int i;
+
+ i = 0;
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ if (i == crtc_index)
+ break;
+ i++;
+ }
+ if (!crtc)
+ return 0;
+ vc4_crtc = to_vc4_crtc(crtc);
+
+ for (i = 0; i < ARRAY_SIZE(crtc_regs); i++) {
+ seq_printf(m, "%s (0x%04x): 0x%08x\n",
+ crtc_regs[i].name, crtc_regs[i].reg,
+ CRTC_READ(crtc_regs[i].reg));
+ }
+
+ return 0;
+}
+#endif
+
+static void vc4_crtc_destroy(struct drm_crtc *crtc)
+{
+ drm_crtc_cleanup(crtc);
+}
+
+static u32 vc4_get_fifo_full_level(u32 format)
+{
+ static const u32 fifo_len_bytes = 64;
+ static const u32 hvs_latency_pix = 6;
+
+ switch (format) {
+ case PV_CONTROL_FORMAT_DSIV_16:
+ case PV_CONTROL_FORMAT_DSIC_16:
+ return fifo_len_bytes - 2 * hvs_latency_pix;
+ case PV_CONTROL_FORMAT_DSIV_18:
+ return fifo_len_bytes - 14;
+ case PV_CONTROL_FORMAT_24:
+ case PV_CONTROL_FORMAT_DSIV_24:
+ default:
+ return fifo_len_bytes - 3 * hvs_latency_pix;
+ }
+}
+
+/*
+ * Returns the clock select bit for the connector attached to the
+ * CRTC.
+ */
+static int vc4_get_clock_select(struct drm_crtc *crtc)
+{
+ struct drm_connector *connector;
+
+ drm_for_each_connector(connector, crtc->dev) {
+ if (connector && connector->state->crtc == crtc) {
+ struct drm_encoder *encoder = connector->encoder;
+ struct vc4_encoder *vc4_encoder =
+ to_vc4_encoder(encoder);
+
+ return vc4_encoder->clock_select;
+ }
+ }
+
+ return -1;
+}
+
+static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ struct drm_crtc_state *state = crtc->state;
+ struct drm_display_mode *mode = &state->adjusted_mode;
+ bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
+ u32 vactive = (mode->vdisplay >> (interlace ? 1 : 0));
+ u32 format = PV_CONTROL_FORMAT_24;
+ bool debug_dump_regs = false;
+ int clock_select = vc4_get_clock_select(crtc);
+
+ if (debug_dump_regs) {
+ DRM_INFO("CRTC %d regs before:\n", drm_crtc_index(crtc));
+ vc4_crtc_dump_regs(vc4_crtc);
+ }
+
+ /* Reset the PV fifo. */
+ CRTC_WRITE(PV_CONTROL, 0);
+ CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR | PV_CONTROL_EN);
+ CRTC_WRITE(PV_CONTROL, 0);
+
+ CRTC_WRITE(PV_HORZA,
+ VC4_SET_FIELD(mode->htotal - mode->hsync_end,
+ PV_HORZA_HBP) |
+ VC4_SET_FIELD(mode->hsync_end - mode->hsync_start,
+ PV_HORZA_HSYNC));
+ CRTC_WRITE(PV_HORZB,
+ VC4_SET_FIELD(mode->hsync_start - mode->hdisplay,
+ PV_HORZB_HFP) |
+ VC4_SET_FIELD(mode->hdisplay, PV_HORZB_HACTIVE));
+
+ if (interlace) {
+ CRTC_WRITE(PV_VERTA_EVEN,
+ VC4_SET_FIELD(mode->vtotal - mode->vsync_end - 1,
+ PV_VERTA_VBP) |
+ VC4_SET_FIELD(mode->vsync_end - mode->vsync_start,
+ PV_VERTA_VSYNC));
+ CRTC_WRITE(PV_VERTB_EVEN,
+ VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
+ PV_VERTB_VFP) |
+ VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE));
+ }
+
+ CRTC_WRITE(PV_HACT_ACT, mode->hdisplay);
+
+ CRTC_WRITE(PV_V_CONTROL,
+ PV_VCONTROL_CONTINUOUS |
+ (interlace ? PV_VCONTROL_INTERLACE : 0));
+
+ CRTC_WRITE(PV_CONTROL,
+ VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
+ VC4_SET_FIELD(vc4_get_fifo_full_level(format),
+ PV_CONTROL_FIFO_LEVEL) |
+ PV_CONTROL_CLR_AT_START |
+ PV_CONTROL_TRIGGER_UNDERFLOW |
+ PV_CONTROL_WAIT_HSTART |
+ VC4_SET_FIELD(clock_select, PV_CONTROL_CLK_SELECT) |
+ PV_CONTROL_FIFO_CLR |
+ PV_CONTROL_EN);
+
+ if (debug_dump_regs) {
+ DRM_INFO("CRTC %d regs after:\n", drm_crtc_index(crtc));
+ vc4_crtc_dump_regs(vc4_crtc);
+ }
+}
+
+static void require_hvs_enabled(struct drm_device *dev)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+ WARN_ON_ONCE((HVS_READ(SCALER_DISPCTRL) & SCALER_DISPCTRL_ENABLE) !=
+ SCALER_DISPCTRL_ENABLE);
+}
+
+static void vc4_crtc_disable(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ u32 chan = vc4_crtc->channel;
+ int ret;
+ require_hvs_enabled(dev);
+
+ CRTC_WRITE(PV_V_CONTROL,
+ CRTC_READ(PV_V_CONTROL) & ~PV_VCONTROL_VIDEN);
+ ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
+ WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
+
+ if (HVS_READ(SCALER_DISPCTRLX(chan)) &
+ SCALER_DISPCTRLX_ENABLE) {
+ HVS_WRITE(SCALER_DISPCTRLX(chan),
+ SCALER_DISPCTRLX_RESET);
+
+ /* While the docs say that reset is self-clearing, it
+ * seems it doesn't actually.
+ */
+ HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
+ }
+
+ /* Once we leave, the scaler should be disabled and its fifo empty. */
+
+ WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET);
+
+ WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)),
+ SCALER_DISPSTATX_MODE) !=
+ SCALER_DISPSTATX_MODE_DISABLED);
+
+ WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
+ (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
+ SCALER_DISPSTATX_EMPTY);
+}
+
+static void vc4_crtc_enable(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ struct drm_crtc_state *state = crtc->state;
+ struct drm_display_mode *mode = &state->adjusted_mode;
+
+ require_hvs_enabled(dev);
+
+ /* Turn on the scaler, which will wait for vstart to start
+ * compositing.
+ */
+ HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel),
+ VC4_SET_FIELD(mode->hdisplay, SCALER_DISPCTRLX_WIDTH) |
+ VC4_SET_FIELD(mode->vdisplay, SCALER_DISPCTRLX_HEIGHT) |
+ SCALER_DISPCTRLX_ENABLE);
+
+ /* Turn on the pixel valve, which will emit the vstart signal. */
+ CRTC_WRITE(PV_V_CONTROL,
+ CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
+}
+
+static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ struct drm_device *dev = crtc->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ struct drm_plane *plane;
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ u32 dlist_count = 0;
+
+ /* The pixelvalve can only feed one encoder (and encoders are
+ * 1:1 with connectors.)
+ */
+ if (drm_atomic_connectors_for_crtc(state->state, crtc) > 1)
+ return -EINVAL;
+
+ drm_atomic_crtc_state_for_each_plane(plane, state) {
+ struct drm_plane_state *plane_state =
+ state->state->plane_states[drm_plane_index(plane)];
+
+ /* plane might not have changed, in which case take
+ * current state:
+ */
+ if (!plane_state)
+ plane_state = plane->state;
+
+ dlist_count += vc4_plane_dlist_size(plane_state);
+ }
+
+ dlist_count++; /* Account for SCALER_CTL0_END. */
+
+ if (!vc4_crtc->dlist || dlist_count > vc4_crtc->dlist_size) {
+ vc4_crtc->dlist = ((u32 __iomem *)vc4->hvs->dlist +
+ HVS_BOOTLOADER_DLIST_END);
+ vc4_crtc->dlist_size = ((SCALER_DLIST_SIZE >> 2) -
+ HVS_BOOTLOADER_DLIST_END);
+
+ if (dlist_count > vc4_crtc->dlist_size) {
+ DRM_DEBUG_KMS("dlist too large for CRTC (%d > %d).\n",
+ dlist_count, vc4_crtc->dlist_size);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_state)
+{
+ struct drm_device *dev = crtc->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ struct drm_plane *plane;
+ bool debug_dump_regs = false;
+ u32 __iomem *dlist_next = vc4_crtc->dlist;
+
+ if (debug_dump_regs) {
+ DRM_INFO("CRTC %d HVS before:\n", drm_crtc_index(crtc));
+ vc4_hvs_dump_state(dev);
+ }
+
+ /* Copy all the active planes' dlist contents to the hardware dlist.
+ *
+ * XXX: If the new display list was large enough that it
+ * overlapped a currently-read display list, we need to do
+ * something like disable scanout before putting in the new
+ * list. For now, we're safe because we only have the two
+ * planes.
+ */
+ drm_atomic_crtc_for_each_plane(plane, crtc) {
+ dlist_next += vc4_plane_write_dlist(plane, dlist_next);
+ }
+
+ if (dlist_next == vc4_crtc->dlist) {
+ /* If no planes were enabled, use the SCALER_CTL0_END
+ * at the start of the display list memory (in the
+ * bootloader section). We'll rewrite that
+ * SCALER_CTL0_END, just in case, though.
+ */
+ writel(SCALER_CTL0_END, vc4->hvs->dlist);
+ HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel), 0);
+ } else {
+ writel(SCALER_CTL0_END, dlist_next);
+ dlist_next++;
+
+ HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+ (u32 *)vc4_crtc->dlist - (u32 *)vc4->hvs->dlist);
+
+ /* Make the next display list start after ours. */
+ vc4_crtc->dlist_size -= (dlist_next - vc4_crtc->dlist);
+ vc4_crtc->dlist = dlist_next;
+ }
+
+ if (debug_dump_regs) {
+ DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc));
+ vc4_hvs_dump_state(dev);
+ }
+
+ if (crtc->state->event) {
+ unsigned long flags;
+
+ crtc->state->event->pipe = drm_crtc_index(crtc);
+
+ WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+ vc4_crtc->event = crtc->state->event;
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ crtc->state->event = NULL;
+ }
+}
+
+int vc4_enable_vblank(struct drm_device *dev, unsigned int crtc_id)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ struct vc4_crtc *vc4_crtc = vc4->crtc[crtc_id];
+
+ CRTC_WRITE(PV_INTEN, PV_INT_VFP_START);
+
+ return 0;
+}
+
+void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ struct vc4_crtc *vc4_crtc = vc4->crtc[crtc_id];
+
+ CRTC_WRITE(PV_INTEN, 0);
+}
+
+static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
+{
+ struct drm_crtc *crtc = &vc4_crtc->base;
+ struct drm_device *dev = crtc->dev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+ if (vc4_crtc->event) {
+ drm_crtc_send_vblank_event(crtc, vc4_crtc->event);
+ vc4_crtc->event = NULL;
+ }
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+static irqreturn_t vc4_crtc_irq_handler(int irq, void *data)
+{
+ struct vc4_crtc *vc4_crtc = data;
+ u32 stat = CRTC_READ(PV_INTSTAT);
+ irqreturn_t ret = IRQ_NONE;
+
+ if (stat & PV_INT_VFP_START) {
+ CRTC_WRITE(PV_INTSTAT, PV_INT_VFP_START);
+ drm_crtc_handle_vblank(&vc4_crtc->base);
+ vc4_crtc_handle_page_flip(vc4_crtc);
+ ret = IRQ_HANDLED;
+ }
+
+ return ret;
+}
+
+static const struct drm_crtc_funcs vc4_crtc_funcs = {
+ .set_config = drm_atomic_helper_set_config,
+ .destroy = vc4_crtc_destroy,
+ .page_flip = drm_atomic_helper_page_flip,
+ .set_property = NULL,
+ .cursor_set = NULL, /* handled by drm_mode_cursor_universal */
+ .cursor_move = NULL, /* handled by drm_mode_cursor_universal */
+ .reset = drm_atomic_helper_crtc_reset,
+ .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
+ .mode_set_nofb = vc4_crtc_mode_set_nofb,
+ .disable = vc4_crtc_disable,
+ .enable = vc4_crtc_enable,
+ .atomic_check = vc4_crtc_atomic_check,
+ .atomic_flush = vc4_crtc_atomic_flush,
+};
+
+/* Frees the page flip event when the DRM device is closed with the
+ * event still outstanding.
+ */
+void vc4_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
+{
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+
+ if (vc4_crtc->event && vc4_crtc->event->base.file_priv == file) {
+ vc4_crtc->event->base.destroy(&vc4_crtc->event->base);
+ drm_crtc_vblank_put(crtc);
+ vc4_crtc->event = NULL;
+ }
+
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+static const struct vc4_crtc_data pv0_data = {
+ .hvs_channel = 0,
+ .encoder0_type = VC4_ENCODER_TYPE_DSI0,
+ .encoder1_type = VC4_ENCODER_TYPE_DPI,
+};
+
+static const struct vc4_crtc_data pv1_data = {
+ .hvs_channel = 2,
+ .encoder0_type = VC4_ENCODER_TYPE_DSI1,
+ .encoder1_type = VC4_ENCODER_TYPE_SMI,
+};
+
+static const struct vc4_crtc_data pv2_data = {
+ .hvs_channel = 1,
+ .encoder0_type = VC4_ENCODER_TYPE_VEC,
+ .encoder1_type = VC4_ENCODER_TYPE_HDMI,
+};
+
+static const struct of_device_id vc4_crtc_dt_match[] = {
+ { .compatible = "brcm,bcm2835-pixelvalve0", .data = &pv0_data },
+ { .compatible = "brcm,bcm2835-pixelvalve1", .data = &pv1_data },
+ { .compatible = "brcm,bcm2835-pixelvalve2", .data = &pv2_data },
+ {}
+};
+
+static void vc4_set_crtc_possible_masks(struct drm_device *drm,
+ struct drm_crtc *crtc)
+{
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ struct drm_encoder *encoder;
+
+ drm_for_each_encoder(encoder, drm) {
+ struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
+
+ if (vc4_encoder->type == vc4_crtc->data->encoder0_type) {
+ vc4_encoder->clock_select = 0;
+ encoder->possible_crtcs |= drm_crtc_mask(crtc);
+ } else if (vc4_encoder->type == vc4_crtc->data->encoder1_type) {
+ vc4_encoder->clock_select = 1;
+ encoder->possible_crtcs |= drm_crtc_mask(crtc);
+ }
+ }
+}
+
+static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm = dev_get_drvdata(master);
+ struct vc4_dev *vc4 = to_vc4_dev(drm);
+ struct vc4_crtc *vc4_crtc;
+ struct drm_crtc *crtc;
+ struct drm_plane *primary_plane, *cursor_plane;
+ const struct of_device_id *match;
+ int ret;
+
+ vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
+ if (!vc4_crtc)
+ return -ENOMEM;
+ crtc = &vc4_crtc->base;
+
+ match = of_match_device(vc4_crtc_dt_match, dev);
+ if (!match)
+ return -ENODEV;
+ vc4_crtc->data = match->data;
+
+ vc4_crtc->regs = vc4_ioremap_regs(pdev, 0);
+ if (IS_ERR(vc4_crtc->regs))
+ return PTR_ERR(vc4_crtc->regs);
+
+ /* For now, we create just the primary and the legacy cursor
+ * planes. We should be able to stack more planes on easily,
+ * but to do that we would need to compute the bandwidth
+ * requirement of the plane configuration, and reject ones
+ * that will take too much.
+ */
+ primary_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_PRIMARY);
+ if (!primary_plane) {
+ dev_err(dev, "failed to construct primary plane\n");
+ ret = PTR_ERR(primary_plane);
+ goto err;
+ }
+
+ cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR);
+ if (!cursor_plane) {
+ dev_err(dev, "failed to construct cursor plane\n");
+ ret = PTR_ERR(cursor_plane);
+ goto err_primary;
+ }
+
+ drm_crtc_init_with_planes(drm, crtc, primary_plane, cursor_plane,
+ &vc4_crtc_funcs);
+ drm_crtc_helper_add(crtc, &vc4_crtc_helper_funcs);
+ primary_plane->crtc = crtc;
+ cursor_plane->crtc = crtc;
+ vc4->crtc[drm_crtc_index(crtc)] = vc4_crtc;
+ vc4_crtc->channel = vc4_crtc->data->hvs_channel;
+
+ CRTC_WRITE(PV_INTEN, 0);
+ CRTC_WRITE(PV_INTSTAT, PV_INT_VFP_START);
+ ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
+ vc4_crtc_irq_handler, 0, "vc4 crtc", vc4_crtc);
+ if (ret)
+ goto err_cursor;
+
+ vc4_set_crtc_possible_masks(drm, crtc);
+
+ platform_set_drvdata(pdev, vc4_crtc);
+
+ return 0;
+
+err_cursor:
+ cursor_plane->funcs->destroy(cursor_plane);
+err_primary:
+ primary_plane->funcs->destroy(primary_plane);
+err:
+ return ret;
+}
+
+static void vc4_crtc_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct vc4_crtc *vc4_crtc = dev_get_drvdata(dev);
+
+ vc4_crtc_destroy(&vc4_crtc->base);
+
+ CRTC_WRITE(PV_INTEN, 0);
+
+ platform_set_drvdata(pdev, NULL);
+}
+
+static const struct component_ops vc4_crtc_ops = {
+ .bind = vc4_crtc_bind,
+ .unbind = vc4_crtc_unbind,
+};
+
+static int vc4_crtc_dev_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &vc4_crtc_ops);
+}
+
+static int vc4_crtc_dev_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &vc4_crtc_ops);
+ return 0;
+}
+
+struct platform_driver vc4_crtc_driver = {
+ .probe = vc4_crtc_dev_probe,
+ .remove = vc4_crtc_dev_remove,
+ .driver = {
+ .name = "vc4_crtc",
+ .of_match_table = vc4_crtc_dt_match,
+ },
+};
diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c
new file mode 100644
index 000000000000..4297b0a5b74e
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_debugfs.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2014 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/seq_file.h>
+#include <linux/circ_buf.h>
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <drm/drmP.h>
+
+#include "vc4_drv.h"
+#include "vc4_regs.h"
+
+static const struct drm_info_list vc4_debugfs_list[] = {
+ {"hdmi_regs", vc4_hdmi_debugfs_regs, 0},
+ {"hvs_regs", vc4_hvs_debugfs_regs, 0},
+ {"crtc0_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)0},
+ {"crtc1_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)1},
+ {"crtc2_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)2},
+};
+
+#define VC4_DEBUGFS_ENTRIES ARRAY_SIZE(vc4_debugfs_list)
+
+int
+vc4_debugfs_init(struct drm_minor *minor)
+{
+ return drm_debugfs_create_files(vc4_debugfs_list, VC4_DEBUGFS_ENTRIES,
+ minor->debugfs_root, minor);
+}
+
+void
+vc4_debugfs_cleanup(struct drm_minor *minor)
+{
+ drm_debugfs_remove_files(vc4_debugfs_list, VC4_DEBUGFS_ENTRIES, minor);
+}
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
new file mode 100644
index 000000000000..6e730605edcc
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2014-2015 Broadcom
+ * Copyright (C) 2013 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include "drm_fb_cma_helper.h"
+
+#include "vc4_drv.h"
+#include "vc4_regs.h"
+
+#define DRIVER_NAME "vc4"
+#define DRIVER_DESC "Broadcom VC4 graphics"
+#define DRIVER_DATE "20140616"
+#define DRIVER_MAJOR 0
+#define DRIVER_MINOR 0
+#define DRIVER_PATCHLEVEL 0
+
+/* Helper function for mapping the regs on a platform device. */
+void __iomem *vc4_ioremap_regs(struct platform_device *dev, int index)
+{
+ struct resource *res;
+ void __iomem *map;
+
+ res = platform_get_resource(dev, IORESOURCE_MEM, index);
+ map = devm_ioremap_resource(&dev->dev, res);
+ if (IS_ERR(map)) {
+ DRM_ERROR("Failed to map registers: %ld\n", PTR_ERR(map));
+ return map;
+ }
+
+ return map;
+}
+
+static void vc4_drm_preclose(struct drm_device *dev, struct drm_file *file)
+{
+ struct drm_crtc *crtc;
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+ vc4_cancel_page_flip(crtc, file);
+}
+
+static void vc4_lastclose(struct drm_device *dev)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+ if (vc4->fbdev)
+ drm_fbdev_cma_restore_mode(vc4->fbdev);
+}
+
+static const struct file_operations vc4_drm_fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .unlocked_ioctl = drm_ioctl,
+ .mmap = drm_gem_cma_mmap,
+ .poll = drm_poll,
+ .read = drm_read,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = drm_compat_ioctl,
+#endif
+ .llseek = noop_llseek,
+};
+
+static const struct drm_ioctl_desc vc4_drm_ioctls[] = {
+};
+
+static struct drm_driver vc4_drm_driver = {
+ .driver_features = (DRIVER_MODESET |
+ DRIVER_ATOMIC |
+ DRIVER_GEM |
+ DRIVER_PRIME),
+ .lastclose = vc4_lastclose,
+ .preclose = vc4_drm_preclose,
+
+ .enable_vblank = vc4_enable_vblank,
+ .disable_vblank = vc4_disable_vblank,
+ .get_vblank_counter = drm_vblank_count,
+
+#if defined(CONFIG_DEBUG_FS)
+ .debugfs_init = vc4_debugfs_init,
+ .debugfs_cleanup = vc4_debugfs_cleanup,
+#endif
+
+ .gem_free_object = drm_gem_cma_free_object,
+ .gem_vm_ops = &drm_gem_cma_vm_ops,
+
+ .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+ .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+ .gem_prime_import = drm_gem_prime_import,
+ .gem_prime_export = drm_gem_prime_export,
+ .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
+ .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+ .gem_prime_vmap = drm_gem_cma_prime_vmap,
+ .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
+ .gem_prime_mmap = drm_gem_cma_prime_mmap,
+
+ .dumb_create = vc4_dumb_create,
+ .dumb_map_offset = drm_gem_cma_dumb_map_offset,
+ .dumb_destroy = drm_gem_dumb_destroy,
+
+ .ioctls = vc4_drm_ioctls,
+ .num_ioctls = ARRAY_SIZE(vc4_drm_ioctls),
+ .fops = &vc4_drm_fops,
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+static int compare_dev(struct device *dev, void *data)
+{
+ return dev == data;
+}
+
+static void vc4_match_add_drivers(struct device *dev,
+ struct component_match **match,
+ struct platform_driver *const *drivers,
+ int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ struct device_driver *drv = &drivers[i]->driver;
+ struct device *p = NULL, *d;
+
+ while ((d = bus_find_device(&platform_bus_type, p, drv,
+ (void *)platform_bus_type.match))) {
+ put_device(p);
+ component_match_add(dev, match, compare_dev, d);
+ p = d;
+ }
+ put_device(p);
+ }
+}
+
+static int vc4_drm_bind(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm;
+ struct drm_connector *connector;
+ struct vc4_dev *vc4;
+ int ret = 0;
+
+ dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+ vc4 = devm_kzalloc(dev, sizeof(*vc4), GFP_KERNEL);
+ if (!vc4)
+ return -ENOMEM;
+
+ drm = drm_dev_alloc(&vc4_drm_driver, dev);
+ if (!drm)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, drm);
+ vc4->dev = drm;
+ drm->dev_private = vc4;
+
+ drm_dev_set_unique(drm, dev_name(dev));
+
+ drm_mode_config_init(drm);
+ if (ret)
+ goto unref;
+
+ ret = component_bind_all(dev, drm);
+ if (ret)
+ goto unref;
+
+ ret = drm_dev_register(drm, 0);
+ if (ret < 0)
+ goto unbind_all;
+
+ /* Connector registration has to occur after DRM device
+ * registration, because it creates sysfs entries based on the
+ * DRM device.
+ */
+ list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
+ ret = drm_connector_register(connector);
+ if (ret)
+ goto unregister;
+ }
+
+ vc4_kms_load(drm);
+
+ return 0;
+
+unregister:
+ drm_dev_unregister(drm);
+unbind_all:
+ component_unbind_all(dev, drm);
+unref:
+ drm_dev_unref(drm);
+ return ret;
+}
+
+static void vc4_drm_unbind(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm = platform_get_drvdata(pdev);
+ struct vc4_dev *vc4 = to_vc4_dev(drm);
+
+ if (vc4->fbdev)
+ drm_fbdev_cma_fini(vc4->fbdev);
+
+ drm_mode_config_cleanup(drm);
+
+ drm_put_dev(drm);
+}
+
+static const struct component_master_ops vc4_drm_ops = {
+ .bind = vc4_drm_bind,
+ .unbind = vc4_drm_unbind,
+};
+
+static struct platform_driver *const component_drivers[] = {
+ &vc4_hdmi_driver,
+ &vc4_crtc_driver,
+ &vc4_hvs_driver,
+};
+
+static int vc4_platform_drm_probe(struct platform_device *pdev)
+{
+ struct component_match *match = NULL;
+ struct device *dev = &pdev->dev;
+
+ vc4_match_add_drivers(dev, &match,
+ component_drivers, ARRAY_SIZE(component_drivers));
+
+ return component_master_add_with_match(dev, &vc4_drm_ops, match);
+}
+
+static int vc4_platform_drm_remove(struct platform_device *pdev)
+{
+ component_master_del(&pdev->dev, &vc4_drm_ops);
+
+ return 0;
+}
+
+static const struct of_device_id vc4_of_match[] = {
+ { .compatible = "brcm,bcm2835-vc4", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, vc4_of_match);
+
+static struct platform_driver vc4_platform_driver = {
+ .probe = vc4_platform_drm_probe,
+ .remove = vc4_platform_drm_remove,
+ .driver = {
+ .name = "vc4-drm",
+ .owner = THIS_MODULE,
+ .of_match_table = vc4_of_match,
+ },
+};
+
+static int __init vc4_drm_register(void)
+{
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(component_drivers); i++) {
+ ret = platform_driver_register(component_drivers[i]);
+ if (ret) {
+ while (--i >= 0)
+ platform_driver_unregister(component_drivers[i]);
+ return ret;
+ }
+ }
+ return platform_driver_register(&vc4_platform_driver);
+}
+
+static void __exit vc4_drm_unregister(void)
+{
+ int i;
+
+ for (i = ARRAY_SIZE(component_drivers) - 1; i >= 0; i--)
+ platform_driver_unregister(component_drivers[i]);
+
+ platform_driver_unregister(&vc4_platform_driver);
+}
+
+module_init(vc4_drm_register);
+module_exit(vc4_drm_unregister);
+
+MODULE_ALIAS("platform:vc4-drm");
+MODULE_DESCRIPTION("Broadcom VC4 DRM Driver");
+MODULE_AUTHOR("Eric Anholt <[email protected]>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
new file mode 100644
index 000000000000..fd8319fa682e
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2015 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "drmP.h"
+#include "drm_gem_cma_helper.h"
+
+struct vc4_dev {
+ struct drm_device *dev;
+
+ struct vc4_hdmi *hdmi;
+ struct vc4_hvs *hvs;
+ struct vc4_crtc *crtc[3];
+
+ struct drm_fbdev_cma *fbdev;
+};
+
+static inline struct vc4_dev *
+to_vc4_dev(struct drm_device *dev)
+{
+ return (struct vc4_dev *)dev->dev_private;
+}
+
+struct vc4_bo {
+ struct drm_gem_cma_object base;
+};
+
+static inline struct vc4_bo *
+to_vc4_bo(struct drm_gem_object *bo)
+{
+ return (struct vc4_bo *)bo;
+}
+
+struct vc4_hvs {
+ struct platform_device *pdev;
+ void __iomem *regs;
+ void __iomem *dlist;
+};
+
+struct vc4_plane {
+ struct drm_plane base;
+};
+
+static inline struct vc4_plane *
+to_vc4_plane(struct drm_plane *plane)
+{
+ return (struct vc4_plane *)plane;
+}
+
+enum vc4_encoder_type {
+ VC4_ENCODER_TYPE_HDMI,
+ VC4_ENCODER_TYPE_VEC,
+ VC4_ENCODER_TYPE_DSI0,
+ VC4_ENCODER_TYPE_DSI1,
+ VC4_ENCODER_TYPE_SMI,
+ VC4_ENCODER_TYPE_DPI,
+};
+
+struct vc4_encoder {
+ struct drm_encoder base;
+ enum vc4_encoder_type type;
+ u32 clock_select;
+};
+
+static inline struct vc4_encoder *
+to_vc4_encoder(struct drm_encoder *encoder)
+{
+ return container_of(encoder, struct vc4_encoder, base);
+}
+
+#define HVS_READ(offset) readl(vc4->hvs->regs + offset)
+#define HVS_WRITE(offset, val) writel(val, vc4->hvs->regs + offset)
+
+/**
+ * _wait_for - magic (register) wait macro
+ *
+ * Does the right thing for modeset paths when run under kdgb or similar atomic
+ * contexts. Note that it's important that we check the condition again after
+ * having timed out, since the timeout could be due to preemption or similar and
+ * we've never had a chance to check the condition before the timeout.
+ */
+#define _wait_for(COND, MS, W) ({ \
+ unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1; \
+ int ret__ = 0; \
+ while (!(COND)) { \
+ if (time_after(jiffies, timeout__)) { \
+ if (!(COND)) \
+ ret__ = -ETIMEDOUT; \
+ break; \
+ } \
+ if (W && drm_can_sleep()) { \
+ msleep(W); \
+ } else { \
+ cpu_relax(); \
+ } \
+ } \
+ ret__; \
+})
+
+#define wait_for(COND, MS) _wait_for(COND, MS, 1)
+
+/* vc4_bo.c */
+void vc4_free_object(struct drm_gem_object *gem_obj);
+struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t size);
+int vc4_dumb_create(struct drm_file *file_priv,
+ struct drm_device *dev,
+ struct drm_mode_create_dumb *args);
+struct dma_buf *vc4_prime_export(struct drm_device *dev,
+ struct drm_gem_object *obj, int flags);
+
+/* vc4_crtc.c */
+extern struct platform_driver vc4_crtc_driver;
+int vc4_enable_vblank(struct drm_device *dev, unsigned int crtc_id);
+void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id);
+void vc4_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file);
+int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg);
+
+/* vc4_debugfs.c */
+int vc4_debugfs_init(struct drm_minor *minor);
+void vc4_debugfs_cleanup(struct drm_minor *minor);
+
+/* vc4_drv.c */
+void __iomem *vc4_ioremap_regs(struct platform_device *dev, int index);
+
+/* vc4_hdmi.c */
+extern struct platform_driver vc4_hdmi_driver;
+int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused);
+
+/* vc4_hvs.c */
+extern struct platform_driver vc4_hvs_driver;
+void vc4_hvs_dump_state(struct drm_device *dev);
+int vc4_hvs_debugfs_regs(struct seq_file *m, void *unused);
+
+/* vc4_kms.c */
+int vc4_kms_load(struct drm_device *dev);
+
+/* vc4_plane.c */
+struct drm_plane *vc4_plane_init(struct drm_device *dev,
+ enum drm_plane_type type);
+u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist);
+u32 vc4_plane_dlist_size(struct drm_plane_state *state);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
new file mode 100644
index 000000000000..da9a36d6e1d1
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -0,0 +1,590 @@
+/*
+ * Copyright (C) 2015 Broadcom
+ * Copyright (c) 2014 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * DOC: VC4 Falcon HDMI module
+ *
+ * The HDMI core has a state machine and a PHY. Most of the unit
+ * operates off of the HSM clock from CPRMAN. It also internally uses
+ * the PLLH_PIX clock for the PHY.
+ */
+
+#include "drm_atomic_helper.h"
+#include "drm_crtc_helper.h"
+#include "drm_edid.h"
+#include "linux/clk.h"
+#include "linux/component.h"
+#include "linux/i2c.h"
+#include "linux/of_gpio.h"
+#include "linux/of_platform.h"
+#include "vc4_drv.h"
+#include "vc4_regs.h"
+
+/* General HDMI hardware state. */
+struct vc4_hdmi {
+ struct platform_device *pdev;
+
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
+
+ struct i2c_adapter *ddc;
+ void __iomem *hdmicore_regs;
+ void __iomem *hd_regs;
+ int hpd_gpio;
+
+ struct clk *pixel_clock;
+ struct clk *hsm_clock;
+};
+
+#define HDMI_READ(offset) readl(vc4->hdmi->hdmicore_regs + offset)
+#define HDMI_WRITE(offset, val) writel(val, vc4->hdmi->hdmicore_regs + offset)
+#define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
+#define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
+
+/* VC4 HDMI encoder KMS struct */
+struct vc4_hdmi_encoder {
+ struct vc4_encoder base;
+ bool hdmi_monitor;
+};
+
+static inline struct vc4_hdmi_encoder *
+to_vc4_hdmi_encoder(struct drm_encoder *encoder)
+{
+ return container_of(encoder, struct vc4_hdmi_encoder, base.base);
+}
+
+/* VC4 HDMI connector KMS struct */
+struct vc4_hdmi_connector {
+ struct drm_connector base;
+
+ /* Since the connector is attached to just the one encoder,
+ * this is the reference to it so we can do the best_encoder()
+ * hook.
+ */
+ struct drm_encoder *encoder;
+};
+
+static inline struct vc4_hdmi_connector *
+to_vc4_hdmi_connector(struct drm_connector *connector)
+{
+ return container_of(connector, struct vc4_hdmi_connector, base);
+}
+
+#define HDMI_REG(reg) { reg, #reg }
+static const struct {
+ u32 reg;
+ const char *name;
+} hdmi_regs[] = {
+ HDMI_REG(VC4_HDMI_CORE_REV),
+ HDMI_REG(VC4_HDMI_SW_RESET_CONTROL),
+ HDMI_REG(VC4_HDMI_HOTPLUG_INT),
+ HDMI_REG(VC4_HDMI_HOTPLUG),
+ HDMI_REG(VC4_HDMI_HORZA),
+ HDMI_REG(VC4_HDMI_HORZB),
+ HDMI_REG(VC4_HDMI_FIFO_CTL),
+ HDMI_REG(VC4_HDMI_SCHEDULER_CONTROL),
+ HDMI_REG(VC4_HDMI_VERTA0),
+ HDMI_REG(VC4_HDMI_VERTA1),
+ HDMI_REG(VC4_HDMI_VERTB0),
+ HDMI_REG(VC4_HDMI_VERTB1),
+ HDMI_REG(VC4_HDMI_TX_PHY_RESET_CTL),
+};
+
+static const struct {
+ u32 reg;
+ const char *name;
+} hd_regs[] = {
+ HDMI_REG(VC4_HD_M_CTL),
+ HDMI_REG(VC4_HD_MAI_CTL),
+ HDMI_REG(VC4_HD_VID_CTL),
+ HDMI_REG(VC4_HD_CSC_CTL),
+ HDMI_REG(VC4_HD_FRAME_COUNT),
+};
+
+#ifdef CONFIG_DEBUG_FS
+int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
+{
+ struct drm_info_node *node = (struct drm_info_node *)m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(hdmi_regs); i++) {
+ seq_printf(m, "%s (0x%04x): 0x%08x\n",
+ hdmi_regs[i].name, hdmi_regs[i].reg,
+ HDMI_READ(hdmi_regs[i].reg));
+ }
+
+ for (i = 0; i < ARRAY_SIZE(hd_regs); i++) {
+ seq_printf(m, "%s (0x%04x): 0x%08x\n",
+ hd_regs[i].name, hd_regs[i].reg,
+ HD_READ(hd_regs[i].reg));
+ }
+
+ return 0;
+}
+#endif /* CONFIG_DEBUG_FS */
+
+static void vc4_hdmi_dump_regs(struct drm_device *dev)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(hdmi_regs); i++) {
+ DRM_INFO("0x%04x (%s): 0x%08x\n",
+ hdmi_regs[i].reg, hdmi_regs[i].name,
+ HDMI_READ(hdmi_regs[i].reg));
+ }
+ for (i = 0; i < ARRAY_SIZE(hd_regs); i++) {
+ DRM_INFO("0x%04x (%s): 0x%08x\n",
+ hd_regs[i].reg, hd_regs[i].name,
+ HD_READ(hd_regs[i].reg));
+ }
+}
+
+static enum drm_connector_status
+vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
+{
+ struct drm_device *dev = connector->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+ if (vc4->hdmi->hpd_gpio) {
+ if (gpio_get_value(vc4->hdmi->hpd_gpio))
+ return connector_status_connected;
+ else
+ return connector_status_disconnected;
+ }
+
+ if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
+ return connector_status_connected;
+ else
+ return connector_status_disconnected;
+}
+
+static void vc4_hdmi_connector_destroy(struct drm_connector *connector)
+{
+ drm_connector_unregister(connector);
+ drm_connector_cleanup(connector);
+}
+
+static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
+{
+ struct vc4_hdmi_connector *vc4_connector =
+ to_vc4_hdmi_connector(connector);
+ struct drm_encoder *encoder = vc4_connector->encoder;
+ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+ struct drm_device *dev = connector->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ int ret = 0;
+ struct edid *edid;
+
+ edid = drm_get_edid(connector, vc4->hdmi->ddc);
+ if (!edid)
+ return -ENODEV;
+
+ vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
+ drm_mode_connector_update_edid_property(connector, edid);
+ ret = drm_add_edid_modes(connector, edid);
+
+ return ret;
+}
+
+static struct drm_encoder *
+vc4_hdmi_connector_best_encoder(struct drm_connector *connector)
+{
+ struct vc4_hdmi_connector *hdmi_connector =
+ to_vc4_hdmi_connector(connector);
+ return hdmi_connector->encoder;
+}
+
+static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
+ .dpms = drm_atomic_helper_connector_dpms,
+ .detect = vc4_hdmi_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = vc4_hdmi_connector_destroy,
+ .reset = drm_atomic_helper_connector_reset,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs = {
+ .get_modes = vc4_hdmi_connector_get_modes,
+ .best_encoder = vc4_hdmi_connector_best_encoder,
+};
+
+static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
+ struct drm_encoder *encoder)
+{
+ struct drm_connector *connector = NULL;
+ struct vc4_hdmi_connector *hdmi_connector;
+ int ret = 0;
+
+ hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector),
+ GFP_KERNEL);
+ if (!hdmi_connector) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+ connector = &hdmi_connector->base;
+
+ hdmi_connector->encoder = encoder;
+
+ drm_connector_init(dev, connector, &vc4_hdmi_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA);
+ drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs);
+
+ connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
+ DRM_CONNECTOR_POLL_DISCONNECT);
+
+ connector->interlace_allowed = 0;
+ connector->doublescan_allowed = 0;
+
+ drm_mode_connector_attach_encoder(connector, encoder);
+
+ return connector;
+
+ fail:
+ if (connector)
+ vc4_hdmi_connector_destroy(connector);
+
+ return ERR_PTR(ret);
+}
+
+static void vc4_hdmi_encoder_destroy(struct drm_encoder *encoder)
+{
+ drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs vc4_hdmi_encoder_funcs = {
+ .destroy = vc4_hdmi_encoder_destroy,
+};
+
+static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *unadjusted_mode,
+ struct drm_display_mode *mode)
+{
+ struct drm_device *dev = encoder->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ bool debug_dump_regs = false;
+ bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
+ bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
+ u32 vactive = (mode->vdisplay >>
+ ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0));
+ u32 verta = (VC4_SET_FIELD(mode->vsync_end - mode->vsync_start,
+ VC4_HDMI_VERTA_VSP) |
+ VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
+ VC4_HDMI_VERTA_VFP) |
+ VC4_SET_FIELD(vactive, VC4_HDMI_VERTA_VAL));
+ u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
+ VC4_SET_FIELD(mode->vtotal - mode->vsync_end,
+ VC4_HDMI_VERTB_VBP));
+
+ if (debug_dump_regs) {
+ DRM_INFO("HDMI regs before:\n");
+ vc4_hdmi_dump_regs(dev);
+ }
+
+ HD_WRITE(VC4_HD_VID_CTL, 0);
+
+ clk_set_rate(vc4->hdmi->pixel_clock, mode->clock * 1000);
+
+ HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
+ HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
+ VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
+ VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
+
+ HDMI_WRITE(VC4_HDMI_HORZA,
+ (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
+ (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
+ VC4_SET_FIELD(mode->hdisplay, VC4_HDMI_HORZA_HAP));
+
+ HDMI_WRITE(VC4_HDMI_HORZB,
+ VC4_SET_FIELD(mode->htotal - mode->hsync_end,
+ VC4_HDMI_HORZB_HBP) |
+ VC4_SET_FIELD(mode->hsync_end - mode->hsync_start,
+ VC4_HDMI_HORZB_HSP) |
+ VC4_SET_FIELD(mode->hsync_start - mode->hdisplay,
+ VC4_HDMI_HORZB_HFP));
+
+ HDMI_WRITE(VC4_HDMI_VERTA0, verta);
+ HDMI_WRITE(VC4_HDMI_VERTA1, verta);
+
+ HDMI_WRITE(VC4_HDMI_VERTB0, vertb);
+ HDMI_WRITE(VC4_HDMI_VERTB1, vertb);
+
+ HD_WRITE(VC4_HD_VID_CTL,
+ (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
+ (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
+
+ /* The RGB order applies even when CSC is disabled. */
+ HD_WRITE(VC4_HD_CSC_CTL, VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
+ VC4_HD_CSC_CTL_ORDER));
+
+ HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
+
+ if (debug_dump_regs) {
+ DRM_INFO("HDMI regs after:\n");
+ vc4_hdmi_dump_regs(dev);
+ }
+}
+
+static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
+{
+ struct drm_device *dev = encoder->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+ HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+ HD_WRITE(VC4_HD_VID_CTL,
+ HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
+}
+
+static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+{
+ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+ struct drm_device *dev = encoder->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ int ret;
+
+ HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0);
+
+ HD_WRITE(VC4_HD_VID_CTL,
+ HD_READ(VC4_HD_VID_CTL) |
+ VC4_HD_VID_CTL_ENABLE |
+ VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
+ VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
+
+ if (vc4_encoder->hdmi_monitor) {
+ HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
+ HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
+ VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
+
+ ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1);
+ WARN_ONCE(ret, "Timeout waiting for "
+ "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
+ } else {
+ HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
+ HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
+ ~(VC4_HDMI_RAM_PACKET_ENABLE));
+ HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
+ HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+ ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
+
+ ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1);
+ WARN_ONCE(ret, "Timeout waiting for "
+ "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
+ }
+
+ if (vc4_encoder->hdmi_monitor) {
+ u32 drift;
+
+ WARN_ON(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+ VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
+ HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
+ HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
+ VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT);
+
+ /* XXX: Set HDMI_RAM_PACKET_CONFIG (1 << 16) and set
+ * up the infoframe.
+ */
+
+ drift = HDMI_READ(VC4_HDMI_FIFO_CTL);
+ drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
+
+ HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+ drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
+ HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+ drift | VC4_HDMI_FIFO_CTL_RECENTER);
+ udelay(1000);
+ HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+ drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
+ HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+ drift | VC4_HDMI_FIFO_CTL_RECENTER);
+
+ ret = wait_for(HDMI_READ(VC4_HDMI_FIFO_CTL) &
+ VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
+ WARN_ONCE(ret, "Timeout waiting for "
+ "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
+ }
+}
+
+static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
+ .mode_set = vc4_hdmi_encoder_mode_set,
+ .disable = vc4_hdmi_encoder_disable,
+ .enable = vc4_hdmi_encoder_enable,
+};
+
+static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm = dev_get_drvdata(master);
+ struct vc4_dev *vc4 = drm->dev_private;
+ struct vc4_hdmi *hdmi;
+ struct vc4_hdmi_encoder *vc4_hdmi_encoder;
+ struct device_node *ddc_node;
+ u32 value;
+ int ret;
+
+ hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
+ if (!hdmi)
+ return -ENOMEM;
+
+ vc4_hdmi_encoder = devm_kzalloc(dev, sizeof(*vc4_hdmi_encoder),
+ GFP_KERNEL);
+ if (!vc4_hdmi_encoder)
+ return -ENOMEM;
+ vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI;
+ hdmi->encoder = &vc4_hdmi_encoder->base.base;
+
+ hdmi->pdev = pdev;
+ hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
+ if (IS_ERR(hdmi->hdmicore_regs))
+ return PTR_ERR(hdmi->hdmicore_regs);
+
+ hdmi->hd_regs = vc4_ioremap_regs(pdev, 1);
+ if (IS_ERR(hdmi->hd_regs))
+ return PTR_ERR(hdmi->hd_regs);
+
+ ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
+ if (!ddc_node) {
+ DRM_ERROR("Failed to find ddc node in device tree\n");
+ return -ENODEV;
+ }
+
+ hdmi->pixel_clock = devm_clk_get(dev, "pixel");
+ if (IS_ERR(hdmi->pixel_clock)) {
+ DRM_ERROR("Failed to get pixel clock\n");
+ return PTR_ERR(hdmi->pixel_clock);
+ }
+ hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
+ if (IS_ERR(hdmi->hsm_clock)) {
+ DRM_ERROR("Failed to get HDMI state machine clock\n");
+ return PTR_ERR(hdmi->hsm_clock);
+ }
+
+ hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
+ if (!hdmi->ddc) {
+ DRM_DEBUG("Failed to get ddc i2c adapter by node\n");
+ return -EPROBE_DEFER;
+ }
+
+ /* Enable the clocks at startup. We can't quite recover from
+ * turning off the pixel clock during disable/enables yet, so
+ * it's always running.
+ */
+ ret = clk_prepare_enable(hdmi->pixel_clock);
+ if (ret) {
+ DRM_ERROR("Failed to turn on pixel clock: %d\n", ret);
+ goto err_put_i2c;
+ }
+
+ ret = clk_prepare_enable(hdmi->hsm_clock);
+ if (ret) {
+ DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
+ ret);
+ goto err_unprepare_pix;
+ }
+
+ /* Only use the GPIO HPD pin if present in the DT, otherwise
+ * we'll use the HDMI core's register.
+ */
+ if (of_find_property(dev->of_node, "hpd-gpios", &value)) {
+ hdmi->hpd_gpio = of_get_named_gpio(dev->of_node, "hpd-gpios", 0);
+ if (hdmi->hpd_gpio < 0) {
+ ret = hdmi->hpd_gpio;
+ goto err_unprepare_hsm;
+ }
+ }
+
+ vc4->hdmi = hdmi;
+
+ /* HDMI core must be enabled. */
+ WARN_ON_ONCE((HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE) == 0);
+
+ drm_encoder_init(drm, hdmi->encoder, &vc4_hdmi_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS);
+ drm_encoder_helper_add(hdmi->encoder, &vc4_hdmi_encoder_helper_funcs);
+
+ hdmi->connector = vc4_hdmi_connector_init(drm, hdmi->encoder);
+ if (IS_ERR(hdmi->connector)) {
+ ret = PTR_ERR(hdmi->connector);
+ goto err_destroy_encoder;
+ }
+
+ return 0;
+
+err_destroy_encoder:
+ vc4_hdmi_encoder_destroy(hdmi->encoder);
+err_unprepare_hsm:
+ clk_disable_unprepare(hdmi->hsm_clock);
+err_unprepare_pix:
+ clk_disable_unprepare(hdmi->pixel_clock);
+err_put_i2c:
+ put_device(&vc4->hdmi->ddc->dev);
+
+ return ret;
+}
+
+static void vc4_hdmi_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct drm_device *drm = dev_get_drvdata(master);
+ struct vc4_dev *vc4 = drm->dev_private;
+ struct vc4_hdmi *hdmi = vc4->hdmi;
+
+ vc4_hdmi_connector_destroy(hdmi->connector);
+ vc4_hdmi_encoder_destroy(hdmi->encoder);
+
+ clk_disable_unprepare(hdmi->pixel_clock);
+ clk_disable_unprepare(hdmi->hsm_clock);
+ put_device(&hdmi->ddc->dev);
+
+ vc4->hdmi = NULL;
+}
+
+static const struct component_ops vc4_hdmi_ops = {
+ .bind = vc4_hdmi_bind,
+ .unbind = vc4_hdmi_unbind,
+};
+
+static int vc4_hdmi_dev_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &vc4_hdmi_ops);
+}
+
+static int vc4_hdmi_dev_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &vc4_hdmi_ops);
+ return 0;
+}
+
+static const struct of_device_id vc4_hdmi_dt_match[] = {
+ { .compatible = "brcm,bcm2835-hdmi" },
+ {}
+};
+
+struct platform_driver vc4_hdmi_driver = {
+ .probe = vc4_hdmi_dev_probe,
+ .remove = vc4_hdmi_dev_remove,
+ .driver = {
+ .name = "vc4_hdmi",
+ .of_match_table = vc4_hdmi_dt_match,
+ },
+};
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
new file mode 100644
index 000000000000..ab1673f672a4
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2015 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/**
+ * DOC: VC4 HVS module.
+ *
+ * The HVS is the piece of hardware that does translation, scaling,
+ * colorspace conversion, and compositing of pixels stored in
+ * framebuffers into a FIFO of pixels going out to the Pixel Valve
+ * (CRTC). It operates at the system clock rate (the system audio
+ * clock gate, specifically), which is much higher than the pixel
+ * clock rate.
+ *
+ * There is a single global HVS, with multiple output FIFOs that can
+ * be consumed by the PVs. This file just manages the resources for
+ * the HVS, while the vc4_crtc.c code actually drives HVS setup for
+ * each CRTC.
+ */
+
+#include "linux/component.h"
+#include "vc4_drv.h"
+#include "vc4_regs.h"
+
+#define HVS_REG(reg) { reg, #reg }
+static const struct {
+ u32 reg;
+ const char *name;
+} hvs_regs[] = {
+ HVS_REG(SCALER_DISPCTRL),
+ HVS_REG(SCALER_DISPSTAT),
+ HVS_REG(SCALER_DISPID),
+ HVS_REG(SCALER_DISPECTRL),
+ HVS_REG(SCALER_DISPPROF),
+ HVS_REG(SCALER_DISPDITHER),
+ HVS_REG(SCALER_DISPEOLN),
+ HVS_REG(SCALER_DISPLIST0),
+ HVS_REG(SCALER_DISPLIST1),
+ HVS_REG(SCALER_DISPLIST2),
+ HVS_REG(SCALER_DISPLSTAT),
+ HVS_REG(SCALER_DISPLACT0),
+ HVS_REG(SCALER_DISPLACT1),
+ HVS_REG(SCALER_DISPLACT2),
+ HVS_REG(SCALER_DISPCTRL0),
+ HVS_REG(SCALER_DISPBKGND0),
+ HVS_REG(SCALER_DISPSTAT0),
+ HVS_REG(SCALER_DISPBASE0),
+ HVS_REG(SCALER_DISPCTRL1),
+ HVS_REG(SCALER_DISPBKGND1),
+ HVS_REG(SCALER_DISPSTAT1),
+ HVS_REG(SCALER_DISPBASE1),
+ HVS_REG(SCALER_DISPCTRL2),
+ HVS_REG(SCALER_DISPBKGND2),
+ HVS_REG(SCALER_DISPSTAT2),
+ HVS_REG(SCALER_DISPBASE2),
+ HVS_REG(SCALER_DISPALPHA2),
+};
+
+void vc4_hvs_dump_state(struct drm_device *dev)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(hvs_regs); i++) {
+ DRM_INFO("0x%04x (%s): 0x%08x\n",
+ hvs_regs[i].reg, hvs_regs[i].name,
+ HVS_READ(hvs_regs[i].reg));
+ }
+
+ DRM_INFO("HVS ctx:\n");
+ for (i = 0; i < 64; i += 4) {
+ DRM_INFO("0x%08x (%s): 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ i * 4, i < HVS_BOOTLOADER_DLIST_END ? "B" : "D",
+ ((uint32_t *)vc4->hvs->dlist)[i + 0],
+ ((uint32_t *)vc4->hvs->dlist)[i + 1],
+ ((uint32_t *)vc4->hvs->dlist)[i + 2],
+ ((uint32_t *)vc4->hvs->dlist)[i + 3]);
+ }
+}
+
+#ifdef CONFIG_DEBUG_FS
+int vc4_hvs_debugfs_regs(struct seq_file *m, void *unused)
+{
+ struct drm_info_node *node = (struct drm_info_node *)m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(hvs_regs); i++) {
+ seq_printf(m, "%s (0x%04x): 0x%08x\n",
+ hvs_regs[i].name, hvs_regs[i].reg,
+ HVS_READ(hvs_regs[i].reg));
+ }
+
+ return 0;
+}
+#endif
+
+static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm = dev_get_drvdata(master);
+ struct vc4_dev *vc4 = drm->dev_private;
+ struct vc4_hvs *hvs = NULL;
+
+ hvs = devm_kzalloc(&pdev->dev, sizeof(*hvs), GFP_KERNEL);
+ if (!hvs)
+ return -ENOMEM;
+
+ hvs->pdev = pdev;
+
+ hvs->regs = vc4_ioremap_regs(pdev, 0);
+ if (IS_ERR(hvs->regs))
+ return PTR_ERR(hvs->regs);
+
+ hvs->dlist = hvs->regs + SCALER_DLIST_START;
+
+ vc4->hvs = hvs;
+ return 0;
+}
+
+static void vc4_hvs_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct drm_device *drm = dev_get_drvdata(master);
+ struct vc4_dev *vc4 = drm->dev_private;
+
+ vc4->hvs = NULL;
+}
+
+static const struct component_ops vc4_hvs_ops = {
+ .bind = vc4_hvs_bind,
+ .unbind = vc4_hvs_unbind,
+};
+
+static int vc4_hvs_dev_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &vc4_hvs_ops);
+}
+
+static int vc4_hvs_dev_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &vc4_hvs_ops);
+ return 0;
+}
+
+static const struct of_device_id vc4_hvs_dt_match[] = {
+ { .compatible = "brcm,bcm2835-hvs" },
+ {}
+};
+
+struct platform_driver vc4_hvs_driver = {
+ .probe = vc4_hvs_dev_probe,
+ .remove = vc4_hvs_dev_remove,
+ .driver = {
+ .name = "vc4_hvs",
+ .of_match_table = vc4_hvs_dt_match,
+ },
+};
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
new file mode 100644
index 000000000000..2e5597d10cc6
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/**
+ * DOC: VC4 KMS
+ *
+ * This is the general code for implementing KMS mode setting that
+ * doesn't clearly associate with any of the other objects (plane,
+ * crtc, HDMI encoder).
+ */
+
+#include "drm_crtc.h"
+#include "drm_atomic_helper.h"
+#include "drm_crtc_helper.h"
+#include "drm_plane_helper.h"
+#include "drm_fb_cma_helper.h"
+#include "vc4_drv.h"
+
+static void vc4_output_poll_changed(struct drm_device *dev)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+ if (vc4->fbdev)
+ drm_fbdev_cma_hotplug_event(vc4->fbdev);
+}
+
+static const struct drm_mode_config_funcs vc4_mode_funcs = {
+ .output_poll_changed = vc4_output_poll_changed,
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
+ .fb_create = drm_fb_cma_create,
+};
+
+int vc4_kms_load(struct drm_device *dev)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ int ret;
+
+ ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+ if (ret < 0) {
+ dev_err(dev->dev, "failed to initialize vblank\n");
+ return ret;
+ }
+
+ dev->mode_config.max_width = 2048;
+ dev->mode_config.max_height = 2048;
+ dev->mode_config.funcs = &vc4_mode_funcs;
+ dev->mode_config.preferred_depth = 24;
+ dev->vblank_disable_allowed = true;
+
+ drm_mode_config_reset(dev);
+
+ vc4->fbdev = drm_fbdev_cma_init(dev, 32,
+ dev->mode_config.num_crtc,
+ dev->mode_config.num_connector);
+ if (IS_ERR(vc4->fbdev))
+ vc4->fbdev = NULL;
+
+ drm_kms_helper_poll_init(dev);
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
new file mode 100644
index 000000000000..cdd8b10c0147
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2015 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/**
+ * DOC: VC4 plane module
+ *
+ * Each DRM plane is a layer of pixels being scanned out by the HVS.
+ *
+ * At atomic modeset check time, we compute the HVS display element
+ * state that would be necessary for displaying the plane (giving us a
+ * chance to figure out if a plane configuration is invalid), then at
+ * atomic flush time the CRTC will ask us to write our element state
+ * into the region of the HVS that it has allocated for us.
+ */
+
+#include "vc4_drv.h"
+#include "vc4_regs.h"
+#include "drm_atomic_helper.h"
+#include "drm_fb_cma_helper.h"
+#include "drm_plane_helper.h"
+
+struct vc4_plane_state {
+ struct drm_plane_state base;
+ u32 *dlist;
+ u32 dlist_size; /* Number of dwords in allocated for the display list */
+ u32 dlist_count; /* Number of used dwords in the display list. */
+};
+
+static inline struct vc4_plane_state *
+to_vc4_plane_state(struct drm_plane_state *state)
+{
+ return (struct vc4_plane_state *)state;
+}
+
+static const struct hvs_format {
+ u32 drm; /* DRM_FORMAT_* */
+ u32 hvs; /* HVS_FORMAT_* */
+ u32 pixel_order;
+ bool has_alpha;
+} hvs_formats[] = {
+ {
+ .drm = DRM_FORMAT_XRGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
+ .pixel_order = HVS_PIXEL_ORDER_ABGR, .has_alpha = false,
+ },
+ {
+ .drm = DRM_FORMAT_ARGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
+ .pixel_order = HVS_PIXEL_ORDER_ABGR, .has_alpha = true,
+ },
+};
+
+static const struct hvs_format *vc4_get_hvs_format(u32 drm_format)
+{
+ unsigned i;
+
+ for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) {
+ if (hvs_formats[i].drm == drm_format)
+ return &hvs_formats[i];
+ }
+
+ return NULL;
+}
+
+static bool plane_enabled(struct drm_plane_state *state)
+{
+ return state->fb && state->crtc;
+}
+
+struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane)
+{
+ struct vc4_plane_state *vc4_state;
+
+ if (WARN_ON(!plane->state))
+ return NULL;
+
+ vc4_state = kmemdup(plane->state, sizeof(*vc4_state), GFP_KERNEL);
+ if (!vc4_state)
+ return NULL;
+
+ __drm_atomic_helper_plane_duplicate_state(plane, &vc4_state->base);
+
+ if (vc4_state->dlist) {
+ vc4_state->dlist = kmemdup(vc4_state->dlist,
+ vc4_state->dlist_count * 4,
+ GFP_KERNEL);
+ if (!vc4_state->dlist) {
+ kfree(vc4_state);
+ return NULL;
+ }
+ vc4_state->dlist_size = vc4_state->dlist_count;
+ }
+
+ return &vc4_state->base;
+}
+
+void vc4_plane_destroy_state(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
+
+ kfree(vc4_state->dlist);
+ __drm_atomic_helper_plane_destroy_state(plane, &vc4_state->base);
+ kfree(state);
+}
+
+/* Called during init to allocate the plane's atomic state. */
+void vc4_plane_reset(struct drm_plane *plane)
+{
+ struct vc4_plane_state *vc4_state;
+
+ WARN_ON(plane->state);
+
+ vc4_state = kzalloc(sizeof(*vc4_state), GFP_KERNEL);
+ if (!vc4_state)
+ return;
+
+ plane->state = &vc4_state->base;
+ vc4_state->base.plane = plane;
+}
+
+static void vc4_dlist_write(struct vc4_plane_state *vc4_state, u32 val)
+{
+ if (vc4_state->dlist_count == vc4_state->dlist_size) {
+ u32 new_size = max(4u, vc4_state->dlist_count * 2);
+ u32 *new_dlist = kmalloc(new_size * 4, GFP_KERNEL);
+
+ if (!new_dlist)
+ return;
+ memcpy(new_dlist, vc4_state->dlist, vc4_state->dlist_count * 4);
+
+ kfree(vc4_state->dlist);
+ vc4_state->dlist = new_dlist;
+ vc4_state->dlist_size = new_size;
+ }
+
+ vc4_state->dlist[vc4_state->dlist_count++] = val;
+}
+
+/* Writes out a full display list for an active plane to the plane's
+ * private dlist state.
+ */
+static int vc4_plane_mode_set(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
+ struct drm_framebuffer *fb = state->fb;
+ struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
+ u32 ctl0_offset = vc4_state->dlist_count;
+ const struct hvs_format *format = vc4_get_hvs_format(fb->pixel_format);
+ uint32_t offset = fb->offsets[0];
+ int crtc_x = state->crtc_x;
+ int crtc_y = state->crtc_y;
+ int crtc_w = state->crtc_w;
+ int crtc_h = state->crtc_h;
+
+ if (crtc_x < 0) {
+ offset += drm_format_plane_cpp(fb->pixel_format, 0) * -crtc_x;
+ crtc_w += crtc_x;
+ crtc_x = 0;
+ }
+
+ if (crtc_y < 0) {
+ offset += fb->pitches[0] * -crtc_y;
+ crtc_h += crtc_y;
+ crtc_y = 0;
+ }
+
+ vc4_dlist_write(vc4_state,
+ SCALER_CTL0_VALID |
+ (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) |
+ (format->hvs << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
+ SCALER_CTL0_UNITY);
+
+ /* Position Word 0: Image Positions and Alpha Value */
+ vc4_dlist_write(vc4_state,
+ VC4_SET_FIELD(0xff, SCALER_POS0_FIXED_ALPHA) |
+ VC4_SET_FIELD(crtc_x, SCALER_POS0_START_X) |
+ VC4_SET_FIELD(crtc_y, SCALER_POS0_START_Y));
+
+ /* Position Word 1: Scaled Image Dimensions.
+ * Skipped due to SCALER_CTL0_UNITY scaling.
+ */
+
+ /* Position Word 2: Source Image Size, Alpha Mode */
+ vc4_dlist_write(vc4_state,
+ VC4_SET_FIELD(format->has_alpha ?
+ SCALER_POS2_ALPHA_MODE_PIPELINE :
+ SCALER_POS2_ALPHA_MODE_FIXED,
+ SCALER_POS2_ALPHA_MODE) |
+ VC4_SET_FIELD(crtc_w, SCALER_POS2_WIDTH) |
+ VC4_SET_FIELD(crtc_h, SCALER_POS2_HEIGHT));
+
+ /* Position Word 3: Context. Written by the HVS. */
+ vc4_dlist_write(vc4_state, 0xc0c0c0c0);
+
+ /* Pointer Word 0: RGB / Y Pointer */
+ vc4_dlist_write(vc4_state, bo->paddr + offset);
+
+ /* Pointer Context Word 0: Written by the HVS */
+ vc4_dlist_write(vc4_state, 0xc0c0c0c0);
+
+ /* Pitch word 0: Pointer 0 Pitch */
+ vc4_dlist_write(vc4_state,
+ VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH));
+
+ vc4_state->dlist[ctl0_offset] |=
+ VC4_SET_FIELD(vc4_state->dlist_count, SCALER_CTL0_SIZE);
+
+ return 0;
+}
+
+/* If a modeset involves changing the setup of a plane, the atomic
+ * infrastructure will call this to validate a proposed plane setup.
+ * However, if a plane isn't getting updated, this (and the
+ * corresponding vc4_plane_atomic_update) won't get called. Thus, we
+ * compute the dlist here and have all active plane dlists get updated
+ * in the CRTC's flush.
+ */
+static int vc4_plane_atomic_check(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
+
+ vc4_state->dlist_count = 0;
+
+ if (plane_enabled(state))
+ return vc4_plane_mode_set(plane, state);
+ else
+ return 0;
+}
+
+static void vc4_plane_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ /* No contents here. Since we don't know where in the CRTC's
+ * dlist we should be stored, our dlist is uploaded to the
+ * hardware with vc4_plane_write_dlist() at CRTC atomic_flush
+ * time.
+ */
+}
+
+u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist)
+{
+ struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state);
+ int i;
+
+ /* Can't memcpy_toio() because it needs to be 32-bit writes. */
+ for (i = 0; i < vc4_state->dlist_count; i++)
+ writel(vc4_state->dlist[i], &dlist[i]);
+
+ return vc4_state->dlist_count;
+}
+
+u32 vc4_plane_dlist_size(struct drm_plane_state *state)
+{
+ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
+
+ return vc4_state->dlist_count;
+}
+
+static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = {
+ .prepare_fb = NULL,
+ .cleanup_fb = NULL,
+ .atomic_check = vc4_plane_atomic_check,
+ .atomic_update = vc4_plane_atomic_update,
+};
+
+static void vc4_plane_destroy(struct drm_plane *plane)
+{
+ drm_plane_helper_disable(plane);
+ drm_plane_cleanup(plane);
+}
+
+static const struct drm_plane_funcs vc4_plane_funcs = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .destroy = vc4_plane_destroy,
+ .set_property = NULL,
+ .reset = vc4_plane_reset,
+ .atomic_duplicate_state = vc4_plane_duplicate_state,
+ .atomic_destroy_state = vc4_plane_destroy_state,
+};
+
+struct drm_plane *vc4_plane_init(struct drm_device *dev,
+ enum drm_plane_type type)
+{
+ struct drm_plane *plane = NULL;
+ struct vc4_plane *vc4_plane;
+ u32 formats[ARRAY_SIZE(hvs_formats)];
+ int ret = 0;
+ unsigned i;
+
+ vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane),
+ GFP_KERNEL);
+ if (!vc4_plane) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(hvs_formats); i++)
+ formats[i] = hvs_formats[i].drm;
+ plane = &vc4_plane->base;
+ ret = drm_universal_plane_init(dev, plane, 0xff,
+ &vc4_plane_funcs,
+ formats, ARRAY_SIZE(formats),
+ type);
+
+ drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
+
+ return plane;
+fail:
+ if (plane)
+ vc4_plane_destroy(plane);
+
+ return ERR_PTR(ret);
+}
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
new file mode 100644
index 000000000000..9e4e904c668e
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -0,0 +1,570 @@
+/*
+ * Copyright © 2014-2015 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef VC4_REGS_H
+#define VC4_REGS_H
+
+#include <linux/bitops.h>
+
+#define VC4_MASK(high, low) ((u32)GENMASK(high, low))
+/* Using the GNU statement expression extension */
+#define VC4_SET_FIELD(value, field) \
+ ({ \
+ uint32_t fieldval = (value) << field##_SHIFT; \
+ WARN_ON((fieldval & ~field##_MASK) != 0); \
+ fieldval & field##_MASK; \
+ })
+
+#define VC4_GET_FIELD(word, field) (((word) & field##_MASK) >> \
+ field##_SHIFT)
+
+#define V3D_IDENT0 0x00000
+# define V3D_EXPECTED_IDENT0 \
+ ((2 << 24) | \
+ ('V' << 0) | \
+ ('3' << 8) | \
+ ('D' << 16))
+
+#define V3D_IDENT1 0x00004
+/* Multiples of 1kb */
+# define V3D_IDENT1_VPM_SIZE_MASK VC4_MASK(31, 28)
+# define V3D_IDENT1_VPM_SIZE_SHIFT 28
+# define V3D_IDENT1_NSEM_MASK VC4_MASK(23, 16)
+# define V3D_IDENT1_NSEM_SHIFT 16
+# define V3D_IDENT1_TUPS_MASK VC4_MASK(15, 12)
+# define V3D_IDENT1_TUPS_SHIFT 12
+# define V3D_IDENT1_QUPS_MASK VC4_MASK(11, 8)
+# define V3D_IDENT1_QUPS_SHIFT 8
+# define V3D_IDENT1_NSLC_MASK VC4_MASK(7, 4)
+# define V3D_IDENT1_NSLC_SHIFT 4
+# define V3D_IDENT1_REV_MASK VC4_MASK(3, 0)
+# define V3D_IDENT1_REV_SHIFT 0
+
+#define V3D_IDENT2 0x00008
+#define V3D_SCRATCH 0x00010
+#define V3D_L2CACTL 0x00020
+# define V3D_L2CACTL_L2CCLR BIT(2)
+# define V3D_L2CACTL_L2CDIS BIT(1)
+# define V3D_L2CACTL_L2CENA BIT(0)
+
+#define V3D_SLCACTL 0x00024
+# define V3D_SLCACTL_T1CC_MASK VC4_MASK(27, 24)
+# define V3D_SLCACTL_T1CC_SHIFT 24
+# define V3D_SLCACTL_T0CC_MASK VC4_MASK(19, 16)
+# define V3D_SLCACTL_T0CC_SHIFT 16
+# define V3D_SLCACTL_UCC_MASK VC4_MASK(11, 8)
+# define V3D_SLCACTL_UCC_SHIFT 8
+# define V3D_SLCACTL_ICC_MASK VC4_MASK(3, 0)
+# define V3D_SLCACTL_ICC_SHIFT 0
+
+#define V3D_INTCTL 0x00030
+#define V3D_INTENA 0x00034
+#define V3D_INTDIS 0x00038
+# define V3D_INT_SPILLUSE BIT(3)
+# define V3D_INT_OUTOMEM BIT(2)
+# define V3D_INT_FLDONE BIT(1)
+# define V3D_INT_FRDONE BIT(0)
+
+#define V3D_CT0CS 0x00100
+#define V3D_CT1CS 0x00104
+#define V3D_CTNCS(n) (V3D_CT0CS + 4 * n)
+# define V3D_CTRSTA BIT(15)
+# define V3D_CTSEMA BIT(12)
+# define V3D_CTRTSD BIT(8)
+# define V3D_CTRUN BIT(5)
+# define V3D_CTSUBS BIT(4)
+# define V3D_CTERR BIT(3)
+# define V3D_CTMODE BIT(0)
+
+#define V3D_CT0EA 0x00108
+#define V3D_CT1EA 0x0010c
+#define V3D_CTNEA(n) (V3D_CT0EA + 4 * (n))
+#define V3D_CT0CA 0x00110
+#define V3D_CT1CA 0x00114
+#define V3D_CTNCA(n) (V3D_CT0CA + 4 * (n))
+#define V3D_CT00RA0 0x00118
+#define V3D_CT01RA0 0x0011c
+#define V3D_CTNRA0(n) (V3D_CT00RA0 + 4 * (n))
+#define V3D_CT0LC 0x00120
+#define V3D_CT1LC 0x00124
+#define V3D_CTNLC(n) (V3D_CT0LC + 4 * (n))
+#define V3D_CT0PC 0x00128
+#define V3D_CT1PC 0x0012c
+#define V3D_CTNPC(n) (V3D_CT0PC + 4 * (n))
+
+#define V3D_PCS 0x00130
+# define V3D_BMOOM BIT(8)
+# define V3D_RMBUSY BIT(3)
+# define V3D_RMACTIVE BIT(2)
+# define V3D_BMBUSY BIT(1)
+# define V3D_BMACTIVE BIT(0)
+
+#define V3D_BFC 0x00134
+#define V3D_RFC 0x00138
+#define V3D_BPCA 0x00300
+#define V3D_BPCS 0x00304
+#define V3D_BPOA 0x00308
+#define V3D_BPOS 0x0030c
+#define V3D_BXCF 0x00310
+#define V3D_SQRSV0 0x00410
+#define V3D_SQRSV1 0x00414
+#define V3D_SQCNTL 0x00418
+#define V3D_SRQPC 0x00430
+#define V3D_SRQUA 0x00434
+#define V3D_SRQUL 0x00438
+#define V3D_SRQCS 0x0043c
+#define V3D_VPACNTL 0x00500
+#define V3D_VPMBASE 0x00504
+#define V3D_PCTRC 0x00670
+#define V3D_PCTRE 0x00674
+#define V3D_PCTR0 0x00680
+#define V3D_PCTRS0 0x00684
+#define V3D_PCTR1 0x00688
+#define V3D_PCTRS1 0x0068c
+#define V3D_PCTR2 0x00690
+#define V3D_PCTRS2 0x00694
+#define V3D_PCTR3 0x00698
+#define V3D_PCTRS3 0x0069c
+#define V3D_PCTR4 0x006a0
+#define V3D_PCTRS4 0x006a4
+#define V3D_PCTR5 0x006a8
+#define V3D_PCTRS5 0x006ac
+#define V3D_PCTR6 0x006b0
+#define V3D_PCTRS6 0x006b4
+#define V3D_PCTR7 0x006b8
+#define V3D_PCTRS7 0x006bc
+#define V3D_PCTR8 0x006c0
+#define V3D_PCTRS8 0x006c4
+#define V3D_PCTR9 0x006c8
+#define V3D_PCTRS9 0x006cc
+#define V3D_PCTR10 0x006d0
+#define V3D_PCTRS10 0x006d4
+#define V3D_PCTR11 0x006d8
+#define V3D_PCTRS11 0x006dc
+#define V3D_PCTR12 0x006e0
+#define V3D_PCTRS12 0x006e4
+#define V3D_PCTR13 0x006e8
+#define V3D_PCTRS13 0x006ec
+#define V3D_PCTR14 0x006f0
+#define V3D_PCTRS14 0x006f4
+#define V3D_PCTR15 0x006f8
+#define V3D_PCTRS15 0x006fc
+#define V3D_BGE 0x00f00
+#define V3D_FDBGO 0x00f04
+#define V3D_FDBGB 0x00f08
+#define V3D_FDBGR 0x00f0c
+#define V3D_FDBGS 0x00f10
+#define V3D_ERRSTAT 0x00f20
+
+#define PV_CONTROL 0x00
+# define PV_CONTROL_FORMAT_MASK VC4_MASK(23, 21)
+# define PV_CONTROL_FORMAT_SHIFT 21
+# define PV_CONTROL_FORMAT_24 0
+# define PV_CONTROL_FORMAT_DSIV_16 1
+# define PV_CONTROL_FORMAT_DSIC_16 2
+# define PV_CONTROL_FORMAT_DSIV_18 3
+# define PV_CONTROL_FORMAT_DSIV_24 4
+
+# define PV_CONTROL_FIFO_LEVEL_MASK VC4_MASK(20, 15)
+# define PV_CONTROL_FIFO_LEVEL_SHIFT 15
+# define PV_CONTROL_CLR_AT_START BIT(14)
+# define PV_CONTROL_TRIGGER_UNDERFLOW BIT(13)
+# define PV_CONTROL_WAIT_HSTART BIT(12)
+# define PV_CONTROL_CLK_SELECT_DSI_VEC 0
+# define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI 1
+# define PV_CONTROL_CLK_SELECT_MASK VC4_MASK(3, 2)
+# define PV_CONTROL_CLK_SELECT_SHIFT 2
+# define PV_CONTROL_FIFO_CLR BIT(1)
+# define PV_CONTROL_EN BIT(0)
+
+#define PV_V_CONTROL 0x04
+# define PV_VCONTROL_INTERLACE BIT(4)
+# define PV_VCONTROL_CONTINUOUS BIT(1)
+# define PV_VCONTROL_VIDEN BIT(0)
+
+#define PV_VSYNCD 0x08
+
+#define PV_HORZA 0x0c
+# define PV_HORZA_HBP_MASK VC4_MASK(31, 16)
+# define PV_HORZA_HBP_SHIFT 16
+# define PV_HORZA_HSYNC_MASK VC4_MASK(15, 0)
+# define PV_HORZA_HSYNC_SHIFT 0
+
+#define PV_HORZB 0x10
+# define PV_HORZB_HFP_MASK VC4_MASK(31, 16)
+# define PV_HORZB_HFP_SHIFT 16
+# define PV_HORZB_HACTIVE_MASK VC4_MASK(15, 0)
+# define PV_HORZB_HACTIVE_SHIFT 0
+
+#define PV_VERTA 0x14
+# define PV_VERTA_VBP_MASK VC4_MASK(31, 16)
+# define PV_VERTA_VBP_SHIFT 16
+# define PV_VERTA_VSYNC_MASK VC4_MASK(15, 0)
+# define PV_VERTA_VSYNC_SHIFT 0
+
+#define PV_VERTB 0x18
+# define PV_VERTB_VFP_MASK VC4_MASK(31, 16)
+# define PV_VERTB_VFP_SHIFT 16
+# define PV_VERTB_VACTIVE_MASK VC4_MASK(15, 0)
+# define PV_VERTB_VACTIVE_SHIFT 0
+
+#define PV_VERTA_EVEN 0x1c
+#define PV_VERTB_EVEN 0x20
+
+#define PV_INTEN 0x24
+#define PV_INTSTAT 0x28
+# define PV_INT_VID_IDLE BIT(9)
+# define PV_INT_VFP_END BIT(8)
+# define PV_INT_VFP_START BIT(7)
+# define PV_INT_VACT_START BIT(6)
+# define PV_INT_VBP_START BIT(5)
+# define PV_INT_VSYNC_START BIT(4)
+# define PV_INT_HFP_START BIT(3)
+# define PV_INT_HACT_START BIT(2)
+# define PV_INT_HBP_START BIT(1)
+# define PV_INT_HSYNC_START BIT(0)
+
+#define PV_STAT 0x2c
+
+#define PV_HACT_ACT 0x30
+
+#define SCALER_DISPCTRL 0x00000000
+/* Global register for clock gating the HVS */
+# define SCALER_DISPCTRL_ENABLE BIT(31)
+# define SCALER_DISPCTRL_DSP2EISLUR BIT(15)
+# define SCALER_DISPCTRL_DSP1EISLUR BIT(14)
+/* Enables Display 0 short line and underrun contribution to
+ * SCALER_DISPSTAT_IRQDISP0. Note that short frame contributions are
+ * always enabled.
+ */
+# define SCALER_DISPCTRL_DSP0EISLUR BIT(13)
+# define SCALER_DISPCTRL_DSP2EIEOLN BIT(12)
+# define SCALER_DISPCTRL_DSP2EIEOF BIT(11)
+# define SCALER_DISPCTRL_DSP1EIEOLN BIT(10)
+# define SCALER_DISPCTRL_DSP1EIEOF BIT(9)
+/* Enables Display 0 end-of-line-N contribution to
+ * SCALER_DISPSTAT_IRQDISP0
+ */
+# define SCALER_DISPCTRL_DSP0EIEOLN BIT(8)
+/* Enables Display 0 EOF contribution to SCALER_DISPSTAT_IRQDISP0 */
+# define SCALER_DISPCTRL_DSP0EIEOF BIT(7)
+
+# define SCALER_DISPCTRL_SLVRDEIRQ BIT(6)
+# define SCALER_DISPCTRL_SLVWREIRQ BIT(5)
+# define SCALER_DISPCTRL_DMAEIRQ BIT(4)
+# define SCALER_DISPCTRL_DISP2EIRQ BIT(3)
+# define SCALER_DISPCTRL_DISP1EIRQ BIT(2)
+/* Enables interrupt generation on the enabled EOF/EOLN/EISLUR
+ * bits and short frames..
+ */
+# define SCALER_DISPCTRL_DISP0EIRQ BIT(1)
+/* Enables interrupt generation on scaler profiler interrupt. */
+# define SCALER_DISPCTRL_SCLEIRQ BIT(0)
+
+#define SCALER_DISPSTAT 0x00000004
+# define SCALER_DISPSTAT_COBLOW2 BIT(29)
+# define SCALER_DISPSTAT_EOLN2 BIT(28)
+# define SCALER_DISPSTAT_ESFRAME2 BIT(27)
+# define SCALER_DISPSTAT_ESLINE2 BIT(26)
+# define SCALER_DISPSTAT_EUFLOW2 BIT(25)
+# define SCALER_DISPSTAT_EOF2 BIT(24)
+
+# define SCALER_DISPSTAT_COBLOW1 BIT(21)
+# define SCALER_DISPSTAT_EOLN1 BIT(20)
+# define SCALER_DISPSTAT_ESFRAME1 BIT(19)
+# define SCALER_DISPSTAT_ESLINE1 BIT(18)
+# define SCALER_DISPSTAT_EUFLOW1 BIT(17)
+# define SCALER_DISPSTAT_EOF1 BIT(16)
+
+# define SCALER_DISPSTAT_RESP_MASK VC4_MASK(15, 14)
+# define SCALER_DISPSTAT_RESP_SHIFT 14
+# define SCALER_DISPSTAT_RESP_OKAY 0
+# define SCALER_DISPSTAT_RESP_EXOKAY 1
+# define SCALER_DISPSTAT_RESP_SLVERR 2
+# define SCALER_DISPSTAT_RESP_DECERR 3
+
+# define SCALER_DISPSTAT_COBLOW0 BIT(13)
+/* Set when the DISPEOLN line is done compositing. */
+# define SCALER_DISPSTAT_EOLN0 BIT(12)
+/* Set when VSTART is seen but there are still pixels in the current
+ * output line.
+ */
+# define SCALER_DISPSTAT_ESFRAME0 BIT(11)
+/* Set when HSTART is seen but there are still pixels in the current
+ * output line.
+ */
+# define SCALER_DISPSTAT_ESLINE0 BIT(10)
+/* Set when the the downstream tries to read from the display FIFO
+ * while it's empty.
+ */
+# define SCALER_DISPSTAT_EUFLOW0 BIT(9)
+/* Set when the display mode changes from RUN to EOF */
+# define SCALER_DISPSTAT_EOF0 BIT(8)
+
+/* Set on AXI invalid DMA ID error. */
+# define SCALER_DISPSTAT_DMA_ERROR BIT(7)
+/* Set on AXI slave read decode error */
+# define SCALER_DISPSTAT_IRQSLVRD BIT(6)
+/* Set on AXI slave write decode error */
+# define SCALER_DISPSTAT_IRQSLVWR BIT(5)
+/* Set when SCALER_DISPSTAT_DMA_ERROR is set, or
+ * SCALER_DISPSTAT_RESP_ERROR is not SCALER_DISPSTAT_RESP_OKAY.
+ */
+# define SCALER_DISPSTAT_IRQDMA BIT(4)
+# define SCALER_DISPSTAT_IRQDISP2 BIT(3)
+# define SCALER_DISPSTAT_IRQDISP1 BIT(2)
+/* Set when any of the EOF/EOLN/ESFRAME/ESLINE bits are set and their
+ * corresponding interrupt bit is enabled in DISPCTRL.
+ */
+# define SCALER_DISPSTAT_IRQDISP0 BIT(1)
+/* On read, the profiler interrupt. On write, clear *all* interrupt bits. */
+# define SCALER_DISPSTAT_IRQSCL BIT(0)
+
+#define SCALER_DISPID 0x00000008
+#define SCALER_DISPECTRL 0x0000000c
+#define SCALER_DISPPROF 0x00000010
+#define SCALER_DISPDITHER 0x00000014
+#define SCALER_DISPEOLN 0x00000018
+#define SCALER_DISPLIST0 0x00000020
+#define SCALER_DISPLIST1 0x00000024
+#define SCALER_DISPLIST2 0x00000028
+#define SCALER_DISPLSTAT 0x0000002c
+#define SCALER_DISPLISTX(x) (SCALER_DISPLIST0 + \
+ (x) * (SCALER_DISPLIST1 - \
+ SCALER_DISPLIST0))
+
+#define SCALER_DISPLACT0 0x00000030
+#define SCALER_DISPLACT1 0x00000034
+#define SCALER_DISPLACT2 0x00000038
+#define SCALER_DISPCTRL0 0x00000040
+# define SCALER_DISPCTRLX_ENABLE BIT(31)
+# define SCALER_DISPCTRLX_RESET BIT(30)
+# define SCALER_DISPCTRLX_WIDTH_MASK VC4_MASK(23, 12)
+# define SCALER_DISPCTRLX_WIDTH_SHIFT 12
+# define SCALER_DISPCTRLX_HEIGHT_MASK VC4_MASK(11, 0)
+# define SCALER_DISPCTRLX_HEIGHT_SHIFT 0
+
+#define SCALER_DISPBKGND0 0x00000044
+#define SCALER_DISPSTAT0 0x00000048
+#define SCALER_DISPBASE0 0x0000004c
+# define SCALER_DISPSTATX_MODE_MASK VC4_MASK(31, 30)
+# define SCALER_DISPSTATX_MODE_SHIFT 30
+# define SCALER_DISPSTATX_MODE_DISABLED 0
+# define SCALER_DISPSTATX_MODE_INIT 1
+# define SCALER_DISPSTATX_MODE_RUN 2
+# define SCALER_DISPSTATX_MODE_EOF 3
+# define SCALER_DISPSTATX_FULL BIT(29)
+# define SCALER_DISPSTATX_EMPTY BIT(28)
+#define SCALER_DISPCTRL1 0x00000050
+#define SCALER_DISPBKGND1 0x00000054
+#define SCALER_DISPSTAT1 0x00000058
+#define SCALER_DISPSTATX(x) (SCALER_DISPSTAT0 + \
+ (x) * (SCALER_DISPSTAT1 - \
+ SCALER_DISPSTAT0))
+#define SCALER_DISPBASE1 0x0000005c
+#define SCALER_DISPCTRL2 0x00000060
+#define SCALER_DISPCTRLX(x) (SCALER_DISPCTRL0 + \
+ (x) * (SCALER_DISPCTRL1 - \
+ SCALER_DISPCTRL0))
+#define SCALER_DISPBKGND2 0x00000064
+#define SCALER_DISPSTAT2 0x00000068
+#define SCALER_DISPBASE2 0x0000006c
+#define SCALER_DISPALPHA2 0x00000070
+#define SCALER_GAMADDR 0x00000078
+#define SCALER_GAMDATA 0x000000e0
+#define SCALER_DLIST_START 0x00002000
+#define SCALER_DLIST_SIZE 0x00004000
+
+#define VC4_HDMI_CORE_REV 0x000
+
+#define VC4_HDMI_SW_RESET_CONTROL 0x004
+# define VC4_HDMI_SW_RESET_FORMAT_DETECT BIT(1)
+# define VC4_HDMI_SW_RESET_HDMI BIT(0)
+
+#define VC4_HDMI_HOTPLUG_INT 0x008
+
+#define VC4_HDMI_HOTPLUG 0x00c
+# define VC4_HDMI_HOTPLUG_CONNECTED BIT(0)
+
+#define VC4_HDMI_RAM_PACKET_CONFIG 0x0a0
+# define VC4_HDMI_RAM_PACKET_ENABLE BIT(16)
+
+#define VC4_HDMI_HORZA 0x0c4
+# define VC4_HDMI_HORZA_VPOS BIT(14)
+# define VC4_HDMI_HORZA_HPOS BIT(13)
+/* Horizontal active pixels (hdisplay). */
+# define VC4_HDMI_HORZA_HAP_MASK VC4_MASK(12, 0)
+# define VC4_HDMI_HORZA_HAP_SHIFT 0
+
+#define VC4_HDMI_HORZB 0x0c8
+/* Horizontal pack porch (htotal - hsync_end). */
+# define VC4_HDMI_HORZB_HBP_MASK VC4_MASK(29, 20)
+# define VC4_HDMI_HORZB_HBP_SHIFT 20
+/* Horizontal sync pulse (hsync_end - hsync_start). */
+# define VC4_HDMI_HORZB_HSP_MASK VC4_MASK(19, 10)
+# define VC4_HDMI_HORZB_HSP_SHIFT 10
+/* Horizontal front porch (hsync_start - hdisplay). */
+# define VC4_HDMI_HORZB_HFP_MASK VC4_MASK(9, 0)
+# define VC4_HDMI_HORZB_HFP_SHIFT 0
+
+#define VC4_HDMI_FIFO_CTL 0x05c
+# define VC4_HDMI_FIFO_CTL_RECENTER_DONE BIT(14)
+# define VC4_HDMI_FIFO_CTL_USE_EMPTY BIT(13)
+# define VC4_HDMI_FIFO_CTL_ON_VB BIT(7)
+# define VC4_HDMI_FIFO_CTL_RECENTER BIT(6)
+# define VC4_HDMI_FIFO_CTL_FIFO_RESET BIT(5)
+# define VC4_HDMI_FIFO_CTL_USE_PLL_LOCK BIT(4)
+# define VC4_HDMI_FIFO_CTL_INV_CLK_XFR BIT(3)
+# define VC4_HDMI_FIFO_CTL_CAPTURE_PTR BIT(2)
+# define VC4_HDMI_FIFO_CTL_USE_FULL BIT(1)
+# define VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N BIT(0)
+# define VC4_HDMI_FIFO_VALID_WRITE_MASK 0xefff
+
+#define VC4_HDMI_SCHEDULER_CONTROL 0x0c0
+# define VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT BIT(15)
+# define VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS BIT(5)
+# define VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT BIT(3)
+# define VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE BIT(1)
+# define VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI BIT(0)
+
+#define VC4_HDMI_VERTA0 0x0cc
+#define VC4_HDMI_VERTA1 0x0d4
+/* Vertical sync pulse (vsync_end - vsync_start). */
+# define VC4_HDMI_VERTA_VSP_MASK VC4_MASK(24, 20)
+# define VC4_HDMI_VERTA_VSP_SHIFT 20
+/* Vertical front porch (vsync_start - vdisplay). */
+# define VC4_HDMI_VERTA_VFP_MASK VC4_MASK(19, 13)
+# define VC4_HDMI_VERTA_VFP_SHIFT 13
+/* Vertical active lines (vdisplay). */
+# define VC4_HDMI_VERTA_VAL_MASK VC4_MASK(12, 0)
+# define VC4_HDMI_VERTA_VAL_SHIFT 0
+
+#define VC4_HDMI_VERTB0 0x0d0
+#define VC4_HDMI_VERTB1 0x0d8
+/* Vertical sync pulse offset (for interlaced) */
+# define VC4_HDMI_VERTB_VSPO_MASK VC4_MASK(21, 9)
+# define VC4_HDMI_VERTB_VSPO_SHIFT 9
+/* Vertical pack porch (vtotal - vsync_end). */
+# define VC4_HDMI_VERTB_VBP_MASK VC4_MASK(8, 0)
+# define VC4_HDMI_VERTB_VBP_SHIFT 0
+
+#define VC4_HDMI_TX_PHY_RESET_CTL 0x2c0
+
+#define VC4_HD_M_CTL 0x00c
+# define VC4_HD_M_SW_RST BIT(2)
+# define VC4_HD_M_ENABLE BIT(0)
+
+#define VC4_HD_MAI_CTL 0x014
+
+#define VC4_HD_VID_CTL 0x038
+# define VC4_HD_VID_CTL_ENABLE BIT(31)
+# define VC4_HD_VID_CTL_UNDERFLOW_ENABLE BIT(30)
+# define VC4_HD_VID_CTL_FRAME_COUNTER_RESET BIT(29)
+# define VC4_HD_VID_CTL_VSYNC_LOW BIT(28)
+# define VC4_HD_VID_CTL_HSYNC_LOW BIT(27)
+
+#define VC4_HD_CSC_CTL 0x040
+# define VC4_HD_CSC_CTL_ORDER_MASK VC4_MASK(7, 5)
+# define VC4_HD_CSC_CTL_ORDER_SHIFT 5
+# define VC4_HD_CSC_CTL_ORDER_RGB 0
+# define VC4_HD_CSC_CTL_ORDER_BGR 1
+# define VC4_HD_CSC_CTL_ORDER_BRG 2
+# define VC4_HD_CSC_CTL_ORDER_GRB 3
+# define VC4_HD_CSC_CTL_ORDER_GBR 4
+# define VC4_HD_CSC_CTL_ORDER_RBG 5
+# define VC4_HD_CSC_CTL_PADMSB BIT(4)
+# define VC4_HD_CSC_CTL_MODE_MASK VC4_MASK(3, 2)
+# define VC4_HD_CSC_CTL_MODE_SHIFT 2
+# define VC4_HD_CSC_CTL_MODE_RGB_TO_SD_YPRPB 0
+# define VC4_HD_CSC_CTL_MODE_RGB_TO_HD_YPRPB 1
+# define VC4_HD_CSC_CTL_MODE_CUSTOM 2
+# define VC4_HD_CSC_CTL_RGB2YCC BIT(1)
+# define VC4_HD_CSC_CTL_ENABLE BIT(0)
+
+#define VC4_HD_FRAME_COUNT 0x068
+
+/* HVS display list information. */
+#define HVS_BOOTLOADER_DLIST_END 32
+
+enum hvs_pixel_format {
+ /* 8bpp */
+ HVS_PIXEL_FORMAT_RGB332 = 0,
+ /* 16bpp */
+ HVS_PIXEL_FORMAT_RGBA4444 = 1,
+ HVS_PIXEL_FORMAT_RGB555 = 2,
+ HVS_PIXEL_FORMAT_RGBA5551 = 3,
+ HVS_PIXEL_FORMAT_RGB565 = 4,
+ /* 24bpp */
+ HVS_PIXEL_FORMAT_RGB888 = 5,
+ HVS_PIXEL_FORMAT_RGBA6666 = 6,
+ /* 32bpp */
+ HVS_PIXEL_FORMAT_RGBA8888 = 7
+};
+
+/* Note: the LSB is the rightmost character shown. Only valid for
+ * HVS_PIXEL_FORMAT_RGB8888, not RGB888.
+ */
+#define HVS_PIXEL_ORDER_RGBA 0
+#define HVS_PIXEL_ORDER_BGRA 1
+#define HVS_PIXEL_ORDER_ARGB 2
+#define HVS_PIXEL_ORDER_ABGR 3
+
+#define HVS_PIXEL_ORDER_XBRG 0
+#define HVS_PIXEL_ORDER_XRBG 1
+#define HVS_PIXEL_ORDER_XRGB 2
+#define HVS_PIXEL_ORDER_XBGR 3
+
+#define HVS_PIXEL_ORDER_XYCBCR 0
+#define HVS_PIXEL_ORDER_XYCRCB 1
+#define HVS_PIXEL_ORDER_YXCBCR 2
+#define HVS_PIXEL_ORDER_YXCRCB 3
+
+#define SCALER_CTL0_END BIT(31)
+#define SCALER_CTL0_VALID BIT(30)
+
+#define SCALER_CTL0_SIZE_MASK VC4_MASK(29, 24)
+#define SCALER_CTL0_SIZE_SHIFT 24
+
+#define SCALER_CTL0_HFLIP BIT(16)
+#define SCALER_CTL0_VFLIP BIT(15)
+
+#define SCALER_CTL0_ORDER_MASK VC4_MASK(14, 13)
+#define SCALER_CTL0_ORDER_SHIFT 13
+
+/* Set to indicate no scaling. */
+#define SCALER_CTL0_UNITY BIT(4)
+
+#define SCALER_CTL0_PIXEL_FORMAT_MASK VC4_MASK(3, 0)
+#define SCALER_CTL0_PIXEL_FORMAT_SHIFT 0
+
+#define SCALER_POS0_FIXED_ALPHA_MASK VC4_MASK(31, 24)
+#define SCALER_POS0_FIXED_ALPHA_SHIFT 24
+
+#define SCALER_POS0_START_Y_MASK VC4_MASK(23, 12)
+#define SCALER_POS0_START_Y_SHIFT 12
+
+#define SCALER_POS0_START_X_MASK VC4_MASK(11, 0)
+#define SCALER_POS0_START_X_SHIFT 0
+
+#define SCALER_POS2_ALPHA_MODE_MASK VC4_MASK(31, 30)
+#define SCALER_POS2_ALPHA_MODE_SHIFT 30
+#define SCALER_POS2_ALPHA_MODE_PIPELINE 0
+#define SCALER_POS2_ALPHA_MODE_FIXED 1
+#define SCALER_POS2_ALPHA_MODE_FIXED_NONZERO 2
+#define SCALER_POS2_ALPHA_MODE_FIXED_OVER_0x07 3
+
+#define SCALER_POS2_HEIGHT_MASK VC4_MASK(27, 16)
+#define SCALER_POS2_HEIGHT_SHIFT 16
+
+#define SCALER_POS2_WIDTH_MASK VC4_MASK(11, 0)
+#define SCALER_POS2_WIDTH_SHIFT 0
+
+#define SCALER_SRC_PITCH_MASK VC4_MASK(15, 0)
+#define SCALER_SRC_PITCH_SHIFT 0
+
+#endif /* VC4_REGS_H */
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index fbdd11851725..e52933a73580 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -640,6 +640,6 @@ struct drm_amdgpu_info_hw_ip {
#define AMDGPU_FAMILY_CI 120 /* Bonaire, Hawaii */
#define AMDGPU_FAMILY_KV 125 /* Kaveri, Kabini, Mullins */
#define AMDGPU_FAMILY_VI 130 /* Iceland, Tonga */
-#define AMDGPU_FAMILY_CZ 135 /* Carrizo */
+#define AMDGPU_FAMILY_CZ 135 /* Carrizo, Stoney */
#endif