summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2017-04-03 09:30:24 +0300
committerDave Airlie <airlied@redhat.com>2017-04-03 09:30:24 +0300
commit320d8c3d38739fa8e31a076b86cbdafcf8897d5e (patch)
treeac43e4981ad56b9612cd0cfc0e075401da38f89f /drivers/gpu/drm
parent7558ab66424e61819cbf3d778d9f780f3aa205e9 (diff)
parentb121b051d14cc6e4e799e96e9c06c55989f9e073 (diff)
downloadlinux-320d8c3d38739fa8e31a076b86cbdafcf8897d5e.tar.xz
Merge tag 'drm-misc-next-2017-03-31' of git://anongit.freedesktop.org/git/drm-misc into drm-next
drm-misc for 4.12: Core: - Removed some fb subsampling dimension checks from core (Ville) - Some MST slot cleanup (Dhinakaran) - Extracted drm_debugfs.h & drm_ioctl.h from drmP.h (Daniel) - Added drm_atomic_helper_shutdown() to compliment suspend/resume counterparts (Daniel) - Pipe context through legacy modeset to remove legacy_backoff nasties (Daniel) - Cleanups around vblank as well as allowing lockless counter reads (Chris W.) - VGA Switcheroo added to MAINTAINERS with Lukas Wunner as reviewer (Lukas) Drivers: - Enhancements to rockchip driver probe (Jeffy) and dsi (Chris Z.) - Thunderbolt external GPU awareness added (Lukas) * tag 'drm-misc-next-2017-03-31' of git://anongit.freedesktop.org/git/drm-misc: (63 commits) apple-gmux: Don't switch external DP port on 2011+ MacBook Pros drm/nouveau: Don't register Thunderbolt eGPU with vga_switcheroo drm/amdgpu: Don't register Thunderbolt eGPU with vga_switcheroo drm/radeon: Don't register Thunderbolt eGPU with vga_switcheroo PCI: Recognize Thunderbolt devices MAINTAINERS: Add Lukas Wunner as reviewer for vga_switcheroo drm: Fix locking gotcha in page_flip ioctl drm: Clarify the role of plane_state argument to drm_simple update(). drm: Clear e after kfree in drm_mode_page_flip_ioctl drm: Convert cmpxchg(bool) back to a two step operation drm/bridge: ti-tfp410: support hpd via gpio drm: use .hword to represent 16-bit numbers Revert unrelated part of "drm: simplify the locking in the GETCRTC ioctl" drm: Fixup failure paths in drm_atomic_helper_set_config drm: Peek at the current counter/timestamp for vblank queries drm: Refactor vblank sequence number comparison drm: vblank cannot be enabled if dev->irq_enabled is false drm: Mark up accesses of vblank->enabled outside of its spinlock drm: Make the decision to keep vblank irq enabled earlier drm/atomic-helper: Remove the backoff hack from set_config ...
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_display.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h6
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.c3
-rw-r--r--drivers/gpu/drm/armada/armada_overlay.c6
-rw-r--r--drivers/gpu/drm/bochs/bochs_fbdev.c4
-rw-r--r--drivers/gpu/drm/bochs/bochs_kms.c3
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi.c2
-rw-r--r--drivers/gpu/drm/bridge/ti-tfp410.c72
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c171
-rw-r--r--drivers/gpu/drm/drm_crtc.c73
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c4
-rw-r--r--drivers/gpu/drm/drm_debugfs.c56
-rw-r--r--drivers/gpu/drm/drm_debugfs_crc.c17
-rw-r--r--drivers/gpu/drm/drm_dp_mst_topology.c35
-rw-r--r--drivers/gpu/drm/drm_fb_cma_helper.c2
-rw-r--r--drivers/gpu/drm/drm_fourcc.c25
-rw-r--r--drivers/gpu/drm/drm_framebuffer.c45
-rw-r--r--drivers/gpu/drm/drm_internal.h2
-rw-r--r--drivers/gpu/drm/drm_ioctl.c1
-rw-r--r--drivers/gpu/drm/drm_irq.c90
-rw-r--r--drivers/gpu/drm/drm_modeset_helper.c2
-rw-r--r--drivers/gpu/drm/drm_plane.c91
-rw-r--r--drivers/gpu/drm/drm_plane_helper.c11
-rw-r--r--drivers/gpu/drm/drm_simple_kms_helper.c4
-rw-r--r--drivers/gpu/drm/gma500/gma_display.c7
-rw-r--r--drivers/gpu/drm/gma500/gma_display.h3
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c20
-rw-r--r--drivers/gpu/drm/i915/intel_display.c5
-rw-r--r--drivers/gpu/drm/i915/intel_dp_mst.c4
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c8
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/crtc.c7
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/overlay.c18
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c11
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.h4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vga.c10
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c7
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c8
-rw-r--r--drivers/gpu/drm/radeon/radeon_dp_mst.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c3
-rw-r--r--drivers/gpu/drm/rockchip/Kconfig10
-rw-r--r--drivers/gpu/drm/rockchip/Makefile16
-rw-r--r--drivers/gpu/drm/rockchip/analogix_dp-rockchip.c9
-rw-r--r--drivers/gpu/drm/rockchip/cdn-dp-core.c8
-rw-r--r--drivers/gpu/drm/rockchip/dw-mipi-dsi.c50
-rw-r--r--drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c10
-rw-r--r--drivers/gpu/drm/rockchip/inno_hdmi.c10
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c141
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.h6
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_vop_reg.c8
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_crtc.c3
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_plane.c8
-rw-r--r--drivers/gpu/drm/tegra/dc.c8
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_crtc.c12
-rw-r--r--drivers/gpu/drm/tinydrm/core/tinydrm-core.c19
-rw-r--r--drivers/gpu/drm/tinydrm/mi0283qt.c3
-rw-r--r--drivers/gpu/drm/udl/udl_modeset.c3
-rw-r--r--drivers/gpu/drm/vc4/vc4_crtc.c5
-rw-r--r--drivers/gpu/drm/vc4/vc4_plane.c6
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c5
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.h3
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c5
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c5
-rw-r--r--drivers/gpu/drm/zte/zx_hdmi.c1
66 files changed, 714 insertions, 505 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 93061a439dbc..83dda05325b8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1929,7 +1929,9 @@ int amdgpu_device_init(struct amdgpu_device *adev,
runtime = true;
if (amdgpu_device_is_px(ddev))
runtime = true;
- vga_switcheroo_register_client(adev->pdev, &amdgpu_switcheroo_ops, runtime);
+ if (!pci_is_thunderbolt_attached(adev->pdev))
+ vga_switcheroo_register_client(adev->pdev,
+ &amdgpu_switcheroo_ops, runtime);
if (runtime)
vga_switcheroo_init_domain_pm_ops(adev->dev, &adev->vga_pm_domain);
@@ -2084,7 +2086,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
amdgpu_atombios_fini(adev);
kfree(adev->bios);
adev->bios = NULL;
- vga_switcheroo_unregister_client(adev->pdev);
+ if (!pci_is_thunderbolt_attached(adev->pdev))
+ vga_switcheroo_unregister_client(adev->pdev);
if (adev->flags & AMD_IS_PX)
vga_switcheroo_fini_domain_pm_ops(adev->dev);
vga_client_register(adev->pdev, NULL, NULL, NULL);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 39fc388f222a..ce15721cadda 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -311,7 +311,8 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
uint32_t page_flip_flags,
- uint32_t target)
+ uint32_t target,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct amdgpu_bo *new_abo;
struct amdgpu_flip_work *work;
@@ -332,7 +333,8 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
return 0;
}
-int amdgpu_crtc_set_config(struct drm_mode_set *set)
+int amdgpu_crtc_set_config(struct drm_mode_set *set,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_device *dev;
struct amdgpu_device *adev;
@@ -349,7 +351,7 @@ int amdgpu_crtc_set_config(struct drm_mode_set *set)
if (ret < 0)
return ret;
- ret = drm_crtc_helper_set_config(set);
+ ret = drm_crtc_helper_set_config(set, ctx);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
if (crtc->enabled)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 5ded370a4b35..dfb029ab3448 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -103,7 +103,8 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags)
amdgpu_has_atpx() &&
(amdgpu_is_atpx_hybrid() ||
amdgpu_has_atpx_dgpu_power_cntl()) &&
- ((flags & AMD_IS_APU) == 0))
+ ((flags & AMD_IS_APU) == 0) &&
+ !pci_is_thunderbolt_attached(dev->pdev))
flags |= AMD_IS_PX;
/* amdgpu_device_init should report only fatal error
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index c12497bd3889..db8f8dda209c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -590,11 +590,13 @@ int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int bpp, bool tile
/* amdgpu_display.c */
void amdgpu_print_display_setup(struct drm_device *dev);
int amdgpu_modeset_create_props(struct amdgpu_device *adev);
-int amdgpu_crtc_set_config(struct drm_mode_set *set);
+int amdgpu_crtc_set_config(struct drm_mode_set *set,
+ struct drm_modeset_acquire_ctx *ctx);
int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
- uint32_t page_flip_flags, uint32_t target);
+ uint32_t page_flip_flags, uint32_t target,
+ struct drm_modeset_acquire_ctx *ctx);
void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work,
struct amdgpu_bo *new_abo);
int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 1341e0b9368a..4fe19fde84f9 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -1027,7 +1027,8 @@ static void armada_drm_crtc_destroy(struct drm_crtc *crtc)
* and a mode_set.
*/
static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
- struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, uint32_t page_flip_flags)
+ struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, uint32_t page_flip_flags,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
struct armada_frame_work *work;
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index 34cb73d0db77..424e465ff407 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -94,7 +94,8 @@ static int
armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb,
int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h,
- uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h)
+ uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane);
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
@@ -257,7 +258,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
return 0;
}
-static int armada_ovl_plane_disable(struct drm_plane *plane)
+static int armada_ovl_plane_disable(struct drm_plane *plane,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane);
struct drm_framebuffer *fb;
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c
index 471bd588550b..c38deffa14de 100644
--- a/drivers/gpu/drm/bochs/bochs_fbdev.c
+++ b/drivers/gpu/drm/bochs/bochs_fbdev.c
@@ -192,6 +192,8 @@ void bochs_fbdev_fini(struct bochs_device *bochs)
if (bochs->fb.initialized)
bochs_fbdev_destroy(bochs);
- drm_fb_helper_fini(&bochs->fb.helper);
+ if (bochs->fb.helper.fbdev)
+ drm_fb_helper_fini(&bochs->fb.helper);
+
bochs->fb.initialized = false;
}
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index d5e63eff357b..6a91e62da2f4 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -96,7 +96,8 @@ static void bochs_crtc_commit(struct drm_crtc *crtc)
static int bochs_crtc_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
- uint32_t page_flip_flags)
+ uint32_t page_flip_flags,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct bochs_device *bochs =
container_of(crtc, struct bochs_device, crtc);
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index af93f7a20697..32f02e92e0b9 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1916,7 +1916,7 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
if (intr_stat &
(HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) {
mutex_lock(&hdmi->mutex);
- if (!hdmi->disabled && !hdmi->force) {
+ if (!hdmi->force) {
/*
* If the RX sense status indicates we're disconnected,
* clear the software rxsense status.
diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
index b379d046991b..7d519b46aee4 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -8,6 +8,10 @@
*
*/
+#include <linux/delay.h>
+#include <linux/fwnode.h>
+#include <linux/gpio/consumer.h>
+#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
@@ -18,11 +22,15 @@
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
+#define HOTPLUG_DEBOUNCE_MS 1100
+
struct tfp410 {
struct drm_bridge bridge;
struct drm_connector connector;
struct i2c_adapter *ddc;
+ struct gpio_desc *hpd;
+ struct delayed_work hpd_work;
struct device *dev;
};
@@ -76,6 +84,13 @@ tfp410_connector_detect(struct drm_connector *connector, bool force)
{
struct tfp410 *dvi = drm_connector_to_tfp410(connector);
+ if (dvi->hpd) {
+ if (gpiod_get_value_cansleep(dvi->hpd))
+ return connector_status_connected;
+ else
+ return connector_status_disconnected;
+ }
+
if (dvi->ddc) {
if (drm_probe_ddc(dvi->ddc))
return connector_status_connected;
@@ -106,6 +121,9 @@ static int tfp410_attach(struct drm_bridge *bridge)
return -ENODEV;
}
+ if (dvi->hpd)
+ dvi->connector.polled = DRM_CONNECTOR_POLL_HPD;
+
drm_connector_helper_add(&dvi->connector,
&tfp410_con_helper_funcs);
ret = drm_connector_init(bridge->dev, &dvi->connector,
@@ -125,7 +143,27 @@ static const struct drm_bridge_funcs tfp410_bridge_funcs = {
.attach = tfp410_attach,
};
-static int tfp410_get_connector_ddc(struct tfp410 *dvi)
+static void tfp410_hpd_work_func(struct work_struct *work)
+{
+ struct tfp410 *dvi;
+
+ dvi = container_of(work, struct tfp410, hpd_work.work);
+
+ if (dvi->bridge.dev)
+ drm_helper_hpd_irq_event(dvi->bridge.dev);
+}
+
+static irqreturn_t tfp410_hpd_irq_thread(int irq, void *arg)
+{
+ struct tfp410 *dvi = arg;
+
+ mod_delayed_work(system_wq, &dvi->hpd_work,
+ msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
+
+ return IRQ_HANDLED;
+}
+
+static int tfp410_get_connector_properties(struct tfp410 *dvi)
{
struct device_node *ep = NULL, *connector_node = NULL;
struct device_node *ddc_phandle = NULL;
@@ -140,6 +178,17 @@ static int tfp410_get_connector_ddc(struct tfp410 *dvi)
if (!connector_node)
goto fail;
+ dvi->hpd = fwnode_get_named_gpiod(&connector_node->fwnode,
+ "hpd-gpios", 0, GPIOD_IN, "hpd");
+ if (IS_ERR(dvi->hpd)) {
+ ret = PTR_ERR(dvi->hpd);
+ dvi->hpd = NULL;
+ if (ret == -ENOENT)
+ ret = 0;
+ else
+ goto fail;
+ }
+
ddc_phandle = of_parse_phandle(connector_node, "ddc-i2c-bus", 0);
if (!ddc_phandle)
goto fail;
@@ -176,10 +225,23 @@ static int tfp410_init(struct device *dev)
dvi->bridge.of_node = dev->of_node;
dvi->dev = dev;
- ret = tfp410_get_connector_ddc(dvi);
+ ret = tfp410_get_connector_properties(dvi);
if (ret)
goto fail;
+ if (dvi->hpd) {
+ INIT_DELAYED_WORK(&dvi->hpd_work, tfp410_hpd_work_func);
+
+ ret = devm_request_threaded_irq(dev, gpiod_to_irq(dvi->hpd),
+ NULL, tfp410_hpd_irq_thread, IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "hdmi-hpd", dvi);
+ if (ret) {
+ DRM_ERROR("failed to register hpd interrupt\n");
+ goto fail;
+ }
+ }
+
ret = drm_bridge_add(&dvi->bridge);
if (ret) {
dev_err(dev, "drm_bridge_add() failed: %d\n", ret);
@@ -189,6 +251,8 @@ static int tfp410_init(struct device *dev)
return 0;
fail:
i2c_put_adapter(dvi->ddc);
+ if (dvi->hpd)
+ gpiod_put(dvi->hpd);
return ret;
}
@@ -196,10 +260,14 @@ static int tfp410_fini(struct device *dev)
{
struct tfp410 *dvi = dev_get_drvdata(dev);
+ cancel_delayed_work_sync(&dvi->hpd_work);
+
drm_bridge_remove(&dvi->bridge);
if (dvi->ddc)
i2c_put_adapter(dvi->ddc);
+ if (dvi->hpd)
+ gpiod_put(dvi->hpd);
return 0;
}
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 4e26b73bb0d5..c3994b4d5f32 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -2077,6 +2077,7 @@ EXPORT_SYMBOL(drm_atomic_helper_swap_state);
* @src_y: y offset of @fb for panning
* @src_w: width of source rectangle in @fb
* @src_h: height of source rectangle in @fb
+ * @ctx: lock acquire context
*
* Provides a default plane update handler using the atomic driver interface.
*
@@ -2089,7 +2090,8 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h)
+ uint32_t src_w, uint32_t src_h,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_atomic_state *state;
struct drm_plane_state *plane_state;
@@ -2099,8 +2101,7 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane,
if (!state)
return -ENOMEM;
- state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
-retry:
+ state->acquire_ctx = ctx;
plane_state = drm_atomic_get_plane_state(state, plane);
if (IS_ERR(plane_state)) {
ret = PTR_ERR(plane_state);
@@ -2125,59 +2126,33 @@ retry:
ret = drm_atomic_commit(state);
fail:
- if (ret == -EDEADLK)
- goto backoff;
-
drm_atomic_state_put(state);
return ret;
-
-backoff:
- drm_atomic_state_clear(state);
- drm_atomic_legacy_backoff(state);
-
- /*
- * Someone might have exchanged the framebuffer while we dropped locks
- * in the backoff code. We need to fix up the fb refcount tracking the
- * core does for us.
- */
- plane->old_fb = plane->fb;
-
- goto retry;
}
EXPORT_SYMBOL(drm_atomic_helper_update_plane);
/**
* drm_atomic_helper_disable_plane - Helper for primary plane disable using * atomic
* @plane: plane to disable
+ * @ctx: lock acquire context
*
* Provides a default plane disable handler using the atomic driver interface.
*
* RETURNS:
* Zero on success, error code on failure
*/
-int drm_atomic_helper_disable_plane(struct drm_plane *plane)
+int drm_atomic_helper_disable_plane(struct drm_plane *plane,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_atomic_state *state;
struct drm_plane_state *plane_state;
int ret = 0;
- /*
- * FIXME: Without plane->crtc set we can't get at the implicit legacy
- * acquire context. The real fix will be to wire the acquire ctx through
- * everywhere we need it, but meanwhile prevent chaos by just skipping
- * this noop. The critical case is the cursor ioctls which a) only grab
- * crtc/cursor-plane locks (so we need the crtc to get at the right
- * acquire context) and b) can try to disable the plane multiple times.
- */
- if (!plane->crtc)
- return 0;
-
state = drm_atomic_state_alloc(plane->dev);
if (!state)
return -ENOMEM;
- state->acquire_ctx = drm_modeset_legacy_acquire_ctx(plane->crtc);
-retry:
+ state->acquire_ctx = ctx;
plane_state = drm_atomic_get_plane_state(state, plane);
if (IS_ERR(plane_state)) {
ret = PTR_ERR(plane_state);
@@ -2193,24 +2168,8 @@ retry:
ret = drm_atomic_commit(state);
fail:
- if (ret == -EDEADLK)
- goto backoff;
-
drm_atomic_state_put(state);
return ret;
-
-backoff:
- drm_atomic_state_clear(state);
- drm_atomic_legacy_backoff(state);
-
- /*
- * Someone might have exchanged the framebuffer while we dropped locks
- * in the backoff code. We need to fix up the fb refcount tracking the
- * core does for us.
- */
- plane->old_fb = plane->fb;
-
- goto retry;
}
EXPORT_SYMBOL(drm_atomic_helper_disable_plane);
@@ -2306,6 +2265,7 @@ static int update_output_state(struct drm_atomic_state *state,
/**
* drm_atomic_helper_set_config - set a new config from userspace
* @set: mode set configuration
+ * @ctx: lock acquisition context
*
* Provides a default crtc set_config handler using the atomic driver interface.
*
@@ -2318,7 +2278,8 @@ static int update_output_state(struct drm_atomic_state *state,
* Returns:
* Returns 0 on success, negative errno numbers on failure.
*/
-int drm_atomic_helper_set_config(struct drm_mode_set *set)
+int drm_atomic_helper_set_config(struct drm_mode_set *set,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_atomic_state *state;
struct drm_crtc *crtc = set->crtc;
@@ -2329,32 +2290,16 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set)
return -ENOMEM;
state->legacy_set_config = true;
- state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
-retry:
+ state->acquire_ctx = ctx;
ret = __drm_atomic_helper_set_config(set, state);
if (ret != 0)
goto fail;
ret = drm_atomic_commit(state);
-fail:
- if (ret == -EDEADLK)
- goto backoff;
+fail:
drm_atomic_state_put(state);
return ret;
-
-backoff:
- drm_atomic_state_clear(state);
- drm_atomic_legacy_backoff(state);
-
- /*
- * Someone might have exchanged the framebuffer while we dropped locks
- * in the backoff code. We need to fix up the fb refcount tracking the
- * core does for us.
- */
- crtc->primary->old_fb = crtc->primary->fb;
-
- goto retry;
}
EXPORT_SYMBOL(drm_atomic_helper_set_config);
@@ -2443,7 +2388,8 @@ commit:
* that they are connected to.
*
* This is used for example in suspend/resume to disable all currently active
- * functions when suspending.
+ * functions when suspending. If you just want to shut down everything at e.g.
+ * driver unload, look at drm_atomic_helper_shutdown().
*
* Note that if callers haven't already acquired all modeset locks this might
* return -EDEADLK, which must be handled by calling drm_modeset_backoff().
@@ -2452,7 +2398,8 @@ commit:
* 0 on success or a negative error code on failure.
*
* See also:
- * drm_atomic_helper_suspend(), drm_atomic_helper_resume()
+ * drm_atomic_helper_suspend(), drm_atomic_helper_resume() and
+ * drm_atomic_helper_shutdown().
*/
int drm_atomic_helper_disable_all(struct drm_device *dev,
struct drm_modeset_acquire_ctx *ctx)
@@ -2517,6 +2464,42 @@ free:
EXPORT_SYMBOL(drm_atomic_helper_disable_all);
/**
+ * drm_atomic_helper_shutdown - shutdown all CRTC
+ * @dev: DRM device
+ *
+ * This shuts down all CRTC, which is useful for driver unloading. Shutdown on
+ * suspend should instead be handled with drm_atomic_helper_suspend(), since
+ * that also takes a snapshot of the modeset state to be restored on resume.
+ *
+ * This is just a convenience wrapper around drm_atomic_helper_disable_all(),
+ * and it is the atomic version of drm_crtc_force_disable_all().
+ */
+void drm_atomic_helper_shutdown(struct drm_device *dev)
+{
+ struct drm_modeset_acquire_ctx ctx;
+ int ret;
+
+ drm_modeset_acquire_init(&ctx, 0);
+ while (1) {
+ ret = drm_modeset_lock_all_ctx(dev, &ctx);
+ if (!ret)
+ ret = drm_atomic_helper_disable_all(dev, &ctx);
+
+ if (ret != -EDEADLK)
+ break;
+
+ drm_modeset_backoff(&ctx);
+ }
+
+ if (ret)
+ DRM_ERROR("Disabling all crtc's during unload failed with %i\n", ret);
+
+ drm_modeset_drop_locks(&ctx);
+ drm_modeset_acquire_fini(&ctx);
+}
+EXPORT_SYMBOL(drm_atomic_helper_shutdown);
+
+/**
* drm_atomic_helper_suspend - subsystem-level suspend helper
* @dev: DRM device
*
@@ -2862,6 +2845,7 @@ static int page_flip_common(
* @fb: DRM framebuffer
* @event: optional DRM event to signal upon completion
* @flags: flip flags for non-vblank sync'ed updates
+ * @ctx: lock acquisition context
*
* Provides a default &drm_crtc_funcs.page_flip implementation
* using the atomic driver interface.
@@ -2875,7 +2859,8 @@ static int page_flip_common(
int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
- uint32_t flags)
+ uint32_t flags,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_plane *plane = crtc->primary;
struct drm_atomic_state *state;
@@ -2885,34 +2870,16 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
if (!state)
return -ENOMEM;
- state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
+ state->acquire_ctx = ctx;
-retry:
ret = page_flip_common(state, crtc, fb, event, flags);
if (ret != 0)
goto fail;
ret = drm_atomic_nonblocking_commit(state);
-
fail:
- if (ret == -EDEADLK)
- goto backoff;
-
drm_atomic_state_put(state);
return ret;
-
-backoff:
- drm_atomic_state_clear(state);
- drm_atomic_legacy_backoff(state);
-
- /*
- * Someone might have exchanged the framebuffer while we dropped locks
- * in the backoff code. We need to fix up the fb refcount tracking the
- * core does for us.
- */
- plane->old_fb = plane->fb;
-
- goto retry;
}
EXPORT_SYMBOL(drm_atomic_helper_page_flip);
@@ -2923,6 +2890,7 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip);
* @event: optional DRM event to signal upon completion
* @flags: flip flags for non-vblank sync'ed updates
* @target: specifying the target vblank period when the flip to take effect
+ * @ctx: lock acquisition context
*
* Provides a default &drm_crtc_funcs.page_flip_target implementation.
* Similar to drm_atomic_helper_page_flip() with extra parameter to specify
@@ -2936,7 +2904,8 @@ int drm_atomic_helper_page_flip_target(
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
uint32_t flags,
- uint32_t target)
+ uint32_t target,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_plane *plane = crtc->primary;
struct drm_atomic_state *state;
@@ -2947,9 +2916,8 @@ int drm_atomic_helper_page_flip_target(
if (!state)
return -ENOMEM;
- state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
+ state->acquire_ctx = ctx;
-retry:
ret = page_flip_common(state, crtc, fb, event, flags);
if (ret != 0)
goto fail;
@@ -2962,26 +2930,9 @@ retry:
crtc_state->target_vblank = target;
ret = drm_atomic_nonblocking_commit(state);
-
fail:
- if (ret == -EDEADLK)
- goto backoff;
-
drm_atomic_state_put(state);
return ret;
-
-backoff:
- drm_atomic_state_clear(state);
- drm_atomic_legacy_backoff(state);
-
- /*
- * Someone might have exchanged the framebuffer while we dropped locks
- * in the backoff code. We need to fix up the fb refcount tracking the
- * core does for us.
- */
- plane->old_fb = plane->fb;
-
- goto retry;
}
EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index e2974d3c92e7..d69e180fc563 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -94,6 +94,8 @@ EXPORT_SYMBOL(drm_crtc_from_index);
* drm_crtc_force_disable - Forcibly turn off a CRTC
* @crtc: CRTC to turn off
*
+ * Note: This should only be used by non-atomic legacy drivers.
+ *
* Returns:
* Zero on success, error code on failure.
*/
@@ -103,6 +105,8 @@ int drm_crtc_force_disable(struct drm_crtc *crtc)
.crtc = crtc,
};
+ WARN_ON(drm_drv_uses_atomic_modeset(crtc->dev));
+
return drm_mode_set_config_internal(&set);
}
EXPORT_SYMBOL(drm_crtc_force_disable);
@@ -114,6 +118,9 @@ EXPORT_SYMBOL(drm_crtc_force_disable);
* Drivers may want to call this on unload to ensure that all displays are
* unlit and the GPU is in a consistent, low power state. Takes modeset locks.
*
+ * Note: This should only be used by non-atomic legacy drivers. For an atomic
+ * version look at drm_atomic_helper_shutdown().
+ *
* Returns:
* Zero on success, error code on failure.
*/
@@ -399,9 +406,9 @@ int drm_mode_getcrtc(struct drm_device *dev,
if (!crtc)
return -ENOENT;
- drm_modeset_lock_crtc(crtc, crtc->primary);
crtc_resp->gamma_size = crtc->gamma_size;
+ drm_modeset_lock(&crtc->primary->mutex, NULL);
if (crtc->primary->state && crtc->primary->state->fb)
crtc_resp->fb_id = crtc->primary->state->fb->base.id;
else if (!crtc->primary->state && crtc->primary->fb)
@@ -409,9 +416,14 @@ int drm_mode_getcrtc(struct drm_device *dev,
else
crtc_resp->fb_id = 0;
- if (crtc->state) {
+ if (crtc->primary->state) {
crtc_resp->x = crtc->primary->state->src_x >> 16;
crtc_resp->y = crtc->primary->state->src_y >> 16;
+ }
+ drm_modeset_unlock(&crtc->primary->mutex);
+
+ drm_modeset_lock(&crtc->mutex, NULL);
+ if (crtc->state) {
if (crtc->state->enable) {
drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode);
crtc_resp->mode_valid = 1;
@@ -430,23 +442,13 @@ int drm_mode_getcrtc(struct drm_device *dev,
crtc_resp->mode_valid = 0;
}
}
- drm_modeset_unlock_crtc(crtc);
+ drm_modeset_unlock(&crtc->mutex);
return 0;
}
-/**
- * drm_mode_set_config_internal - helper to call &drm_mode_config_funcs.set_config
- * @set: modeset config to set
- *
- * This is a little helper to wrap internal calls to the
- * &drm_mode_config_funcs.set_config driver interface. The only thing it adds is
- * correct refcounting dance.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_set_config_internal(struct drm_mode_set *set)
+static int __drm_mode_set_config_internal(struct drm_mode_set *set,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_crtc *crtc = set->crtc;
struct drm_framebuffer *fb;
@@ -463,7 +465,7 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
fb = set->fb;
- ret = crtc->funcs->set_config(set);
+ ret = crtc->funcs->set_config(set, ctx);
if (ret == 0) {
crtc->primary->crtc = crtc;
crtc->primary->fb = fb;
@@ -479,6 +481,25 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
return ret;
}
+/**
+ * drm_mode_set_config_internal - helper to call &drm_mode_config_funcs.set_config
+ * @set: modeset config to set
+ *
+ * This is a little helper to wrap internal calls to the
+ * &drm_mode_config_funcs.set_config driver interface. The only thing it adds is
+ * correct refcounting dance.
+ *
+ * This should only be used by non-atomic legacy drivers.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_set_config_internal(struct drm_mode_set *set)
+{
+ WARN_ON(drm_drv_uses_atomic_modeset(set->crtc->dev));
+
+ return __drm_mode_set_config_internal(set, NULL);
+}
EXPORT_SYMBOL(drm_mode_set_config_internal);
/**
@@ -534,6 +555,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
struct drm_display_mode *mode = NULL;
struct drm_mode_set set;
uint32_t __user *set_connectors_ptr;
+ struct drm_modeset_acquire_ctx ctx;
int ret;
int i;
@@ -547,15 +569,18 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)
return -ERANGE;
- drm_modeset_lock_all(dev);
crtc = drm_crtc_find(dev, crtc_req->crtc_id);
if (!crtc) {
DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
- ret = -ENOENT;
- goto out;
+ return -ENOENT;
}
DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
+ drm_modeset_acquire_init(&ctx, 0);
+retry:
+ ret = drm_modeset_lock_all_ctx(crtc->dev, &ctx);
+ if (ret)
+ goto out;
if (crtc_req->mode_valid) {
/* If we have a mode we need a framebuffer. */
/* If we pass -1, set the mode with the currently bound fb */
@@ -676,7 +701,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
set.connectors = connector_set;
set.num_connectors = crtc_req->count_connectors;
set.fb = fb;
- ret = drm_mode_set_config_internal(&set);
+ ret = __drm_mode_set_config_internal(&set, &ctx);
out:
if (fb)
@@ -690,7 +715,13 @@ out:
}
kfree(connector_set);
drm_mode_destroy(dev, mode);
- drm_modeset_unlock_all(dev);
+ if (ret == -EDEADLK) {
+ drm_modeset_backoff(&ctx);
+ goto retry;
+ }
+ drm_modeset_drop_locks(&ctx);
+ drm_modeset_acquire_fini(&ctx);
+
return ret;
}
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 8aa8c1084121..4afdf7902eda 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -476,6 +476,7 @@ drm_crtc_helper_disable(struct drm_crtc *crtc)
/**
* drm_crtc_helper_set_config - set a new config from userspace
* @set: mode set configuration
+ * @ctx: lock acquire context, not used here
*
* The drm_crtc_helper_set_config() helper function implements the of
* &drm_crtc_funcs.set_config callback for drivers using the legacy CRTC
@@ -510,7 +511,8 @@ drm_crtc_helper_disable(struct drm_crtc *crtc)
* Returns:
* Returns 0 on success, negative errno numbers on failure.
*/
-int drm_crtc_helper_set_config(struct drm_mode_set *set)
+int drm_crtc_helper_set_config(struct drm_mode_set *set,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_device *dev;
struct drm_crtc **save_encoder_crtcs, *new_crtc;
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
index 1d2d18d82d2e..c1807d5754b2 100644
--- a/drivers/gpu/drm/drm_debugfs.c
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -1,10 +1,3 @@
-/**
- * \file drm_debugfs.c
- * debugfs support for DRM
- *
- * \author Ben Gamari <bgamari@gmail.com>
- */
-
/*
* Created: Sun Dec 21 13:08:50 2008 by bgamari@gmail.com
*
@@ -34,9 +27,12 @@
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/export.h>
-#include <drm/drmP.h>
+
+#include <drm/drm_debugfs.h>
#include <drm/drm_edid.h>
#include <drm/drm_atomic.h>
+#include <drm/drmP.h>
+
#include "drm_internal.h"
#include "drm_crtc_internal.h"
@@ -72,16 +68,15 @@ static const struct file_operations drm_debugfs_fops = {
/**
- * Initialize a given set of debugfs files for a device
- *
- * \param files The array of files to create
- * \param count The number of files given
- * \param root DRI debugfs dir entry.
- * \param minor device minor number
- * \return Zero on success, non-zero on failure
+ * drm_debugfs_create_files - Initialize a given set of debugfs files for DRM
+ * minor
+ * @files: The array of files to create
+ * @count: The number of files given
+ * @root: DRI debugfs dir entry.
+ * @minor: device minor number
*
* Create a given set of debugfs files represented by an array of
- * &drm_info_list in the given root directory. These files will be removed
+ * &struct drm_info_list in the given root directory. These files will be removed
* automatically on drm_debugfs_cleanup().
*/
int drm_debugfs_create_files(const struct drm_info_list *files, int count,
@@ -130,17 +125,6 @@ fail:
}
EXPORT_SYMBOL(drm_debugfs_create_files);
-/**
- * Initialize the DRI debugfs filesystem for a device
- *
- * \param dev DRM device
- * \param minor device minor number
- * \param root DRI debugfs dir entry.
- *
- * Create the DRI debugfs root entry "/sys/kernel/debug/dri", the device debugfs root entry
- * "/sys/kernel/debug/dri/%minor%/", and each entry in debugfs_list as
- * "/sys/kernel/debug/dri/%minor%/%name%".
- */
int drm_debugfs_init(struct drm_minor *minor, int minor_id,
struct dentry *root)
{
@@ -186,16 +170,6 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id,
}
-/**
- * Remove a list of debugfs files
- *
- * \param files The list of files
- * \param count The number of files
- * \param minor The minor of which we should remove the files
- * \return always zero.
- *
- * Remove all debugfs entries created by debugfs_init().
- */
int drm_debugfs_remove_files(const struct drm_info_list *files, int count,
struct drm_minor *minor)
{
@@ -232,14 +206,6 @@ static void drm_debugfs_remove_all_files(struct drm_minor *minor)
mutex_unlock(&minor->debugfs_lock);
}
-/**
- * Cleanup the debugfs filesystem resources.
- *
- * \param minor device minor number.
- * \return always zero.
- *
- * Remove all debugfs entries created by debugfs_init().
- */
int drm_debugfs_cleanup(struct drm_minor *minor)
{
if (!minor->debugfs_root)
diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c
index 96891c4a6e23..1722d8f21449 100644
--- a/drivers/gpu/drm/drm_debugfs_crc.c
+++ b/drivers/gpu/drm/drm_debugfs_crc.c
@@ -36,7 +36,7 @@
* DOC: CRC ABI
*
* DRM device drivers can provide to userspace CRC information of each frame as
- * it reached a given hardware component (a "source").
+ * it reached a given hardware component (a CRC sampling "source").
*
* Userspace can control generation of CRCs in a given CRTC by writing to the
* file dri/0/crtc-N/crc/control in debugfs, with N being the index of the CRTC.
@@ -57,6 +57,11 @@
* rely on being able to generate matching CRC values for the frame contents that
* it submits. In this general case, the maximum userspace can do is to compare
* the reported CRCs of frames that should have the same contents.
+ *
+ * On the driver side the implementation effort is minimal, drivers only need to
+ * implement &drm_crtc_funcs.set_crc_source. The debugfs files are automatically
+ * set up if that vfunc is set. CRC samples need to be captured in the driver by
+ * calling drm_crtc_add_crc_entry().
*/
static int crc_control_show(struct seq_file *m, void *data)
@@ -280,16 +285,6 @@ static const struct file_operations drm_crtc_crc_data_fops = {
.release = crtc_crc_release,
};
-/**
- * drm_debugfs_crtc_crc_add - Add files to debugfs for capture of frame CRCs
- * @crtc: CRTC to whom the frames will belong
- *
- * Adds files to debugfs directory that allows userspace to control the
- * generation of frame CRCs and to read them.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc)
{
struct dentry *crc_ent, *ent;
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index f2cc375907d0..d3fc7e4e85b7 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -2042,10 +2042,6 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
goto out_unlock;
}
- mgr->total_pbn = 2560;
- mgr->total_slots = DIV_ROUND_UP(mgr->total_pbn, mgr->pbn_div);
- mgr->avail_slots = mgr->total_slots;
-
/* add initial branch device at LCT 1 */
mstb = drm_dp_add_mst_branch_device(1, NULL);
if (mstb == NULL) {
@@ -2475,26 +2471,25 @@ int drm_dp_find_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr,
num_slots = DIV_ROUND_UP(pbn, mgr->pbn_div);
- if (num_slots > mgr->avail_slots)
+ /* max. time slots - one slot for MTP header */
+ if (num_slots > 63)
return -ENOSPC;
return num_slots;
}
EXPORT_SYMBOL(drm_dp_find_vcpi_slots);
static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr,
- struct drm_dp_vcpi *vcpi, int pbn)
+ struct drm_dp_vcpi *vcpi, int pbn, int slots)
{
- int num_slots;
int ret;
- num_slots = DIV_ROUND_UP(pbn, mgr->pbn_div);
-
- if (num_slots > mgr->avail_slots)
+ /* max. time slots - one slot for MTP header */
+ if (slots > 63)
return -ENOSPC;
vcpi->pbn = pbn;
- vcpi->aligned_pbn = num_slots * mgr->pbn_div;
- vcpi->num_slots = num_slots;
+ vcpi->aligned_pbn = slots * mgr->pbn_div;
+ vcpi->num_slots = slots;
ret = drm_dp_mst_assign_payload_id(mgr, vcpi);
if (ret < 0)
@@ -2509,7 +2504,8 @@ static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr,
* @pbn: payload bandwidth number to request
* @slots: returned number of slots for this PBN.
*/
-bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int pbn, int *slots)
+bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_port *port, int pbn, int slots)
{
int ret;
@@ -2517,22 +2513,25 @@ bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp
if (!port)
return false;
+ if (slots < 0)
+ return false;
+
if (port->vcpi.vcpi > 0) {
DRM_DEBUG_KMS("payload: vcpi %d already allocated for pbn %d - requested pbn %d\n", port->vcpi.vcpi, port->vcpi.pbn, pbn);
if (pbn == port->vcpi.pbn) {
- *slots = port->vcpi.num_slots;
drm_dp_put_port(port);
return true;
}
}
- ret = drm_dp_init_vcpi(mgr, &port->vcpi, pbn);
+ ret = drm_dp_init_vcpi(mgr, &port->vcpi, pbn, slots);
if (ret) {
- DRM_DEBUG_KMS("failed to init vcpi %d %d %d\n", DIV_ROUND_UP(pbn, mgr->pbn_div), mgr->avail_slots, ret);
+ DRM_DEBUG_KMS("failed to init vcpi slots=%d max=63 ret=%d\n",
+ DIV_ROUND_UP(pbn, mgr->pbn_div), ret);
goto out;
}
- DRM_DEBUG_KMS("initing vcpi for %d %d\n", pbn, port->vcpi.num_slots);
- *slots = port->vcpi.num_slots;
+ DRM_DEBUG_KMS("initing vcpi for pbn=%d slots=%d\n",
+ pbn, port->vcpi.num_slots);
drm_dp_put_port(port);
return true;
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index 74cd393a6407..50abd1faf38f 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -177,7 +177,7 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev,
int ret;
int i;
- info = drm_format_info(mode_cmd->pixel_format);
+ info = drm_get_format_info(dev, mode_cmd);
if (!info)
return ERR_PTR(-EINVAL);
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index 92bf3306d4b3..9c0152df45ad 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -207,6 +207,31 @@ const struct drm_format_info *drm_format_info(u32 format)
EXPORT_SYMBOL(drm_format_info);
/**
+ * drm_get_format_info - query information for a given framebuffer configuration
+ * @dev: DRM device
+ * @mode_cmd: metadata from the userspace fb creation request
+ *
+ * Returns:
+ * The instance of struct drm_format_info that describes the pixel format, or
+ * NULL if the format is unsupported.
+ */
+const struct drm_format_info *
+drm_get_format_info(struct drm_device *dev,
+ const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+ const struct drm_format_info *info = NULL;
+
+ if (dev->mode_config.funcs->get_format_info)
+ info = dev->mode_config.funcs->get_format_info(mode_cmd);
+
+ if (!info)
+ info = drm_format_info(mode_cmd->pixel_format);
+
+ return info;
+}
+EXPORT_SYMBOL(drm_get_format_info);
+
+/**
* drm_format_num_planes - get the number of planes for format
* @format: pixel format (DRM_FORMAT_*)
*
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
index e4909aef75d7..e8f9c13a0afd 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -126,11 +126,31 @@ int drm_mode_addfb(struct drm_device *dev,
return 0;
}
-static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
+static int fb_plane_width(int width,
+ const struct drm_format_info *format, int plane)
+{
+ if (plane == 0)
+ return width;
+
+ return DIV_ROUND_UP(width, format->hsub);
+}
+
+static int fb_plane_height(int height,
+ const struct drm_format_info *format, int plane)
+{
+ if (plane == 0)
+ return height;
+
+ return DIV_ROUND_UP(height, format->vsub);
+}
+
+static int framebuffer_check(struct drm_device *dev,
+ const struct drm_mode_fb_cmd2 *r)
{
const struct drm_format_info *info;
int i;
+ /* check if the format is supported at all */
info = __drm_format_info(r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN);
if (!info) {
struct drm_format_name_buf format_name;
@@ -140,19 +160,22 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
return -EINVAL;
}
- if (r->width == 0 || r->width % info->hsub) {
+ /* now let the driver pick its own format info */
+ info = drm_get_format_info(dev, r);
+
+ if (r->width == 0) {
DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width);
return -EINVAL;
}
- if (r->height == 0 || r->height % info->vsub) {
+ if (r->height == 0) {
DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
return -EINVAL;
}
for (i = 0; i < info->num_planes; i++) {
- unsigned int width = r->width / (i != 0 ? info->hsub : 1);
- unsigned int height = r->height / (i != 0 ? info->vsub : 1);
+ unsigned int width = fb_plane_width(r->width, info, i);
+ unsigned int height = fb_plane_height(r->height, info, i);
unsigned int cpp = info->cpp[i];
if (!r->handles[i]) {
@@ -263,7 +286,7 @@ drm_internal_framebuffer_create(struct drm_device *dev,
return ERR_PTR(-EINVAL);
}
- ret = framebuffer_check(r);
+ ret = framebuffer_check(dev, r);
if (ret)
return ERR_PTR(ret);
@@ -816,10 +839,7 @@ int drm_framebuffer_plane_width(int width,
if (plane >= fb->format->num_planes)
return 0;
- if (plane == 0)
- return width;
-
- return width / fb->format->hsub;
+ return fb_plane_width(width, fb->format, plane);
}
EXPORT_SYMBOL(drm_framebuffer_plane_width);
@@ -838,9 +858,6 @@ int drm_framebuffer_plane_height(int height,
if (plane >= fb->format->num_planes)
return 0;
- if (plane == 0)
- return height;
-
- return height / fb->format->vsub;
+ return fb_plane_height(height, fb->format, plane);
}
EXPORT_SYMBOL(drm_framebuffer_plane_height);
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index 92ff4b9393b1..3d8e8f878924 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -100,7 +100,7 @@ int drm_gem_open_ioctl(struct drm_device *dev, void *data,
void drm_gem_open(struct drm_device *dev, struct drm_file *file_private);
void drm_gem_release(struct drm_device *dev, struct drm_file *file_private);
-/* drm_debugfs.c */
+/* drm_debugfs.c drm_debugfs_crc.c */
#if defined(CONFIG_DEBUG_FS)
int drm_debugfs_init(struct drm_minor *minor, int minor_id,
struct dentry *root);
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index a7c61c23685a..7d6deaa91281 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -28,6 +28,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <drm/drm_ioctl.h>
#include <drm/drmP.h>
#include <drm/drm_auth.h>
#include "drm_legacy.h"
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 53a526c7b24d..dac1b2593cb1 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -325,6 +325,8 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
unsigned long irqflags;
+ assert_spin_locked(&dev->vbl_lock);
+
/* Prevent vblank irq processing while disabling vblank irqs,
* so no updates of timestamps or count can happen after we've
* disabled. Needed to prevent races in case of delayed irq's.
@@ -384,7 +386,7 @@ void drm_vblank_cleanup(struct drm_device *dev)
for (pipe = 0; pipe < dev->num_crtcs; pipe++) {
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
- WARN_ON(vblank->enabled &&
+ WARN_ON(READ_ONCE(vblank->enabled) &&
drm_core_check_feature(dev, DRIVER_MODESET));
del_timer_sync(&vblank->disable_timer);
@@ -810,14 +812,6 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
/* Return upper bound of timestamp precision error. */
*max_error = duration_ns;
- /* Check if in vblank area:
- * vpos is >=0 in video scanout area, but negative
- * within vblank area, counting down the number of lines until
- * start of scanout.
- */
- if (vbl_status & DRM_SCANOUTPOS_IN_VBLANK)
- ret |= DRM_VBLANKTIME_IN_VBLANK;
-
/* Convert scanout position into elapsed time at raw_time query
* since start of scanout at first display scanline. delta_ns
* can be negative if start of scanout hasn't happened yet.
@@ -1105,11 +1099,16 @@ static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe)
*/
ret = __enable_vblank(dev, pipe);
DRM_DEBUG("enabling vblank on crtc %u, ret: %d\n", pipe, ret);
- if (ret)
+ if (ret) {
atomic_dec(&vblank->refcount);
- else {
- vblank->enabled = true;
+ } else {
drm_update_vblank_count(dev, pipe, 0);
+ /* drm_update_vblank_count() includes a wmb so we just
+ * need to ensure that the compiler emits the write
+ * to mark the vblank as enabled after the call
+ * to drm_update_vblank_count().
+ */
+ WRITE_ONCE(vblank->enabled, true);
}
}
@@ -1487,6 +1486,11 @@ int drm_legacy_modeset_ctl(struct drm_device *dev, void *data,
return 0;
}
+static inline bool vblank_passed(u32 seq, u32 ref)
+{
+ return (seq - ref) <= (1 << 23);
+}
+
static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
union drm_wait_vblank *vblwait,
struct drm_file *file_priv)
@@ -1517,7 +1521,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
* vblank disable, so no need for further locking. The reference from
* drm_vblank_get() protects against vblank disable from another source.
*/
- if (!vblank->enabled) {
+ if (!READ_ONCE(vblank->enabled)) {
ret = -EINVAL;
goto err_unlock;
}
@@ -1537,7 +1541,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
vblwait->request.sequence);
e->event.sequence = vblwait->request.sequence;
- if ((seq - vblwait->request.sequence) <= (1 << 23)) {
+ if (vblank_passed(seq, vblwait->request.sequence)) {
drm_vblank_put(dev, pipe);
send_vblank_event(dev, e, seq, &now);
vblwait->reply.sequence = seq;
@@ -1559,6 +1563,17 @@ err_put:
return ret;
}
+static bool drm_wait_vblank_is_query(union drm_wait_vblank *vblwait)
+{
+ if (vblwait->request.sequence)
+ return false;
+
+ return _DRM_VBLANK_RELATIVE ==
+ (vblwait->request.type & (_DRM_VBLANK_TYPES_MASK |
+ _DRM_VBLANK_EVENT |
+ _DRM_VBLANK_NEXTONMISS));
+}
+
/*
* Wait for VBLANK.
*
@@ -1608,6 +1623,21 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
vblank = &dev->vblank[pipe];
+ /* If the counter is currently enabled and accurate, short-circuit
+ * queries to return the cached timestamp of the last vblank.
+ */
+ if (dev->vblank_disable_immediate &&
+ drm_wait_vblank_is_query(vblwait) &&
+ READ_ONCE(vblank->enabled)) {
+ struct timeval now;
+
+ vblwait->reply.sequence =
+ drm_vblank_count_and_time(dev, pipe, &now);
+ vblwait->reply.tval_sec = now.tv_sec;
+ vblwait->reply.tval_usec = now.tv_usec;
+ return 0;
+ }
+
ret = drm_vblank_get(dev, pipe);
if (ret) {
DRM_DEBUG("crtc %d failed to acquire vblank counter, %d\n", pipe, ret);
@@ -1627,9 +1657,8 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
}
if ((flags & _DRM_VBLANK_NEXTONMISS) &&
- (seq - vblwait->request.sequence) <= (1 << 23)) {
+ vblank_passed(seq, vblwait->request.sequence))
vblwait->request.sequence = seq + 1;
- }
if (flags & _DRM_VBLANK_EVENT) {
/* must hold on to the vblank ref until the event fires
@@ -1642,10 +1671,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
DRM_DEBUG("waiting on vblank count %u, crtc %u\n",
vblwait->request.sequence, pipe);
DRM_WAIT_ON(ret, vblank->queue, 3 * HZ,
- (((drm_vblank_count(dev, pipe) -
- vblwait->request.sequence) <= (1 << 23)) ||
- !vblank->enabled ||
- !dev->irq_enabled));
+ vblank_passed(drm_vblank_count(dev, pipe),
+ vblwait->request.sequence) ||
+ !READ_ONCE(vblank->enabled));
}
if (ret != -EINTR) {
@@ -1679,7 +1707,7 @@ static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe)
list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
if (e->pipe != pipe)
continue;
- if ((seq - e->event.sequence) > (1<<23))
+ if (!vblank_passed(seq, e->event.sequence))
continue;
DRM_DEBUG("vblank event on %u, current %u\n",
@@ -1707,6 +1735,7 @@ bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)
{
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
unsigned long irqflags;
+ bool disable_irq;
if (WARN_ON_ONCE(!dev->num_crtcs))
return false;
@@ -1734,20 +1763,23 @@ bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)
spin_unlock(&dev->vblank_time_lock);
wake_up(&vblank->queue);
- drm_handle_vblank_events(dev, pipe);
/* With instant-off, we defer disabling the interrupt until after
- * we finish processing the following vblank. The disable has to
- * be last (after drm_handle_vblank_events) so that the timestamp
- * is always accurate.
+ * we finish processing the following vblank after all events have
+ * been signaled. The disable has to be last (after
+ * drm_handle_vblank_events) so that the timestamp is always accurate.
*/
- if (dev->vblank_disable_immediate &&
- drm_vblank_offdelay > 0 &&
- !atomic_read(&vblank->refcount))
- vblank_disable_fn((unsigned long)vblank);
+ disable_irq = (dev->vblank_disable_immediate &&
+ drm_vblank_offdelay > 0 &&
+ !atomic_read(&vblank->refcount));
+
+ drm_handle_vblank_events(dev, pipe);
spin_unlock_irqrestore(&dev->event_lock, irqflags);
+ if (disable_irq)
+ vblank_disable_fn((unsigned long)vblank);
+
return true;
}
EXPORT_SYMBOL(drm_handle_vblank);
diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c
index cc44a9a4b004..2b33825f2f93 100644
--- a/drivers/gpu/drm/drm_modeset_helper.c
+++ b/drivers/gpu/drm/drm_modeset_helper.c
@@ -78,7 +78,7 @@ void drm_helper_mode_fill_fb_struct(struct drm_device *dev,
int i;
fb->dev = dev;
- fb->format = drm_format_info(mode_cmd->pixel_format);
+ fb->format = drm_get_format_info(dev, mode_cmd);
fb->width = mode_cmd->width;
fb->height = mode_cmd->height;
for (i = 0; i < 4; i++) {
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index a22e76837065..bc71aa2b7872 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -277,6 +277,12 @@ EXPORT_SYMBOL(drm_plane_from_index);
*
* Used when the plane's current framebuffer is destroyed,
* and when restoring fbdev mode.
+ *
+ * Note that this function is not suitable for atomic drivers, since it doesn't
+ * wire through the lock acquisition context properly and hence can't handle
+ * retries or driver private locks. You probably want to use
+ * drm_atomic_helper_disable_plane() or
+ * drm_atomic_helper_disable_planes_on_crtc() instead.
*/
void drm_plane_force_disable(struct drm_plane *plane)
{
@@ -285,8 +291,10 @@ void drm_plane_force_disable(struct drm_plane *plane)
if (!plane->fb)
return;
+ WARN_ON(drm_drv_uses_atomic_modeset(plane->dev));
+
plane->old_fb = plane->fb;
- ret = plane->funcs->disable_plane(plane);
+ ret = plane->funcs->disable_plane(plane, NULL);
if (ret) {
DRM_ERROR("failed to disable plane with busy fb\n");
plane->old_fb = NULL;
@@ -457,14 +465,15 @@ static int __setplane_internal(struct drm_plane *plane,
uint32_t crtc_w, uint32_t crtc_h,
/* src_{x,y,w,h} values are 16.16 fixed point */
uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h)
+ uint32_t src_w, uint32_t src_h,
+ struct drm_modeset_acquire_ctx *ctx)
{
int ret = 0;
/* No fb means shut it down */
if (!fb) {
plane->old_fb = plane->fb;
- ret = plane->funcs->disable_plane(plane);
+ ret = plane->funcs->disable_plane(plane, ctx);
if (!ret) {
plane->crtc = NULL;
plane->fb = NULL;
@@ -509,7 +518,7 @@ static int __setplane_internal(struct drm_plane *plane,
plane->old_fb = plane->fb;
ret = plane->funcs->update_plane(plane, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h,
- src_x, src_y, src_w, src_h);
+ src_x, src_y, src_w, src_h, ctx);
if (!ret) {
plane->crtc = crtc;
plane->fb = fb;
@@ -537,13 +546,25 @@ static int setplane_internal(struct drm_plane *plane,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
{
+ struct drm_modeset_acquire_ctx ctx;
int ret;
- drm_modeset_lock_all(plane->dev);
+ drm_modeset_acquire_init(&ctx, 0);
+retry:
+ ret = drm_modeset_lock_all_ctx(plane->dev, &ctx);
+ if (ret)
+ goto fail;
ret = __setplane_internal(plane, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h,
- src_x, src_y, src_w, src_h);
- drm_modeset_unlock_all(plane->dev);
+ src_x, src_y, src_w, src_h, &ctx);
+
+fail:
+ if (ret == -EDEADLK) {
+ drm_modeset_backoff(&ctx);
+ goto retry;
+ }
+ drm_modeset_drop_locks(&ctx);
+ drm_modeset_acquire_fini(&ctx);
return ret;
}
@@ -613,11 +634,21 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
int32_t crtc_x, crtc_y;
uint32_t crtc_w = 0, crtc_h = 0;
uint32_t src_w = 0, src_h = 0;
+ struct drm_modeset_acquire_ctx ctx;
int ret = 0;
BUG_ON(!crtc->cursor);
WARN_ON(crtc->cursor->crtc != crtc && crtc->cursor->crtc != NULL);
+ drm_modeset_acquire_init(&ctx, 0);
+retry:
+ ret = drm_modeset_lock(&crtc->mutex, &ctx);
+ if (ret)
+ goto fail;
+ ret = drm_modeset_lock(&crtc->cursor->mutex, &ctx);
+ if (ret)
+ goto fail;
+
/*
* Obtain fb we'll be using (either new or existing) and take an extra
* reference to it if fb != null. setplane will take care of dropping
@@ -662,7 +693,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
*/
ret = __setplane_internal(crtc->cursor, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h,
- 0, 0, src_w, src_h);
+ 0, 0, src_w, src_h, &ctx);
/* Update successful; save new cursor position, if necessary */
if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) {
@@ -670,6 +701,15 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
crtc->cursor_y = req->y;
}
+fail:
+ if (ret == -EDEADLK) {
+ drm_modeset_backoff(&ctx);
+ goto retry;
+ }
+
+ drm_modeset_drop_locks(&ctx);
+ drm_modeset_acquire_fini(&ctx);
+
return ret;
}
@@ -696,12 +736,10 @@ static int drm_mode_cursor_common(struct drm_device *dev,
* If this crtc has a universal cursor plane, call that plane's update
* handler rather than using legacy cursor handlers.
*/
- drm_modeset_lock_crtc(crtc, crtc->cursor);
- if (crtc->cursor) {
- ret = drm_mode_cursor_universal(crtc, req, file_priv);
- goto out;
- }
+ if (crtc->cursor)
+ return drm_mode_cursor_universal(crtc, req, file_priv);
+ drm_modeset_lock_crtc(crtc, crtc->cursor);
if (req->flags & DRM_MODE_CURSOR_BO) {
if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
ret = -ENXIO;
@@ -765,6 +803,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
struct drm_framebuffer *fb = NULL;
struct drm_pending_vblank_event *e = NULL;
u32 target_vblank = page_flip->sequence;
+ struct drm_modeset_acquire_ctx ctx;
int ret = -EINVAL;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
@@ -828,7 +867,15 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
return -EINVAL;
}
- drm_modeset_lock_crtc(crtc, crtc->primary);
+ drm_modeset_acquire_init(&ctx, 0);
+retry:
+ ret = drm_modeset_lock(&crtc->mutex, &ctx);
+ if (ret)
+ goto out;
+ ret = drm_modeset_lock(&crtc->primary->mutex, &ctx);
+ if (ret)
+ goto out;
+
if (crtc->primary->fb == NULL) {
/* The framebuffer is currently unbound, presumably
* due to a hotplug event, that userspace has not
@@ -876,6 +923,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base);
if (ret) {
kfree(e);
+ e = NULL;
goto out;
}
}
@@ -884,9 +932,11 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
if (crtc->funcs->page_flip_target)
ret = crtc->funcs->page_flip_target(crtc, fb, e,
page_flip->flags,
- target_vblank);
+ target_vblank,
+ &ctx);
else
- ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
+ ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags,
+ &ctx);
if (ret) {
if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT)
drm_event_cancel_free(dev, &e->base);
@@ -906,7 +956,14 @@ out:
if (crtc->primary->old_fb)
drm_framebuffer_put(crtc->primary->old_fb);
crtc->primary->old_fb = NULL;
- drm_modeset_unlock_crtc(crtc);
+
+ if (ret == -EDEADLK) {
+ drm_modeset_backoff(&ctx);
+ goto retry;
+ }
+
+ drm_modeset_drop_locks(&ctx);
+ drm_modeset_acquire_fini(&ctx);
return ret;
}
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index de1ac5e08f4d..b84a295230fc 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -275,6 +275,7 @@ EXPORT_SYMBOL(drm_plane_helper_check_update);
* @src_y: y offset of @fb for panning
* @src_w: width of source rectangle in @fb
* @src_h: height of source rectangle in @fb
+ * @ctx: lock acquire context, not used here
*
* Provides a default plane update handler for primary planes. This is handler
* is called in response to a userspace SetPlane operation on the plane with a
@@ -303,7 +304,8 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h)
+ uint32_t src_w, uint32_t src_h,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_mode_set set = {
.crtc = crtc,
@@ -347,7 +349,7 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
* provides their own disable function, this will just
* wind up returning -EINVAL to userspace.
*/
- return plane->funcs->disable_plane(plane);
+ return plane->funcs->disable_plane(plane, ctx);
/* Find current connectors for CRTC */
num_connectors = get_connectors_for_crtc(crtc, NULL, 0);
@@ -369,7 +371,7 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
* drm_mode_setplane() already handles the basic refcounting for the
* framebuffers involved in this operation.
*/
- ret = crtc->funcs->set_config(&set);
+ ret = crtc->funcs->set_config(&set, ctx);
kfree(connector_list);
return ret;
@@ -396,7 +398,8 @@ EXPORT_SYMBOL(drm_primary_helper_update);
* RETURNS:
* Unconditionally returns -EINVAL.
*/
-int drm_primary_helper_disable(struct drm_plane *plane)
+int drm_primary_helper_disable(struct drm_plane *plane,
+ struct drm_modeset_acquire_ctx *ctx)
{
return -EINVAL;
}
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index 16789faa9291..e084f9f8ca66 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -114,7 +114,7 @@ static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane,
}
static void drm_simple_kms_plane_atomic_update(struct drm_plane *plane,
- struct drm_plane_state *pstate)
+ struct drm_plane_state *old_pstate)
{
struct drm_simple_display_pipe *pipe;
@@ -122,7 +122,7 @@ static void drm_simple_kms_plane_atomic_update(struct drm_plane *plane,
if (!pipe->funcs || !pipe->funcs->update)
return;
- pipe->funcs->update(pipe, pstate);
+ pipe->funcs->update(pipe, old_pstate);
}
static int drm_simple_kms_plane_prepare_fb(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c
index d1c5642b1c1e..93ff46535c04 100644
--- a/drivers/gpu/drm/gma500/gma_display.c
+++ b/drivers/gpu/drm/gma500/gma_display.c
@@ -514,17 +514,18 @@ void gma_crtc_destroy(struct drm_crtc *crtc)
kfree(gma_crtc);
}
-int gma_crtc_set_config(struct drm_mode_set *set)
+int gma_crtc_set_config(struct drm_mode_set *set,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_device *dev = set->crtc->dev;
struct drm_psb_private *dev_priv = dev->dev_private;
int ret;
if (!dev_priv->rpm_enabled)
- return drm_crtc_helper_set_config(set);
+ return drm_crtc_helper_set_config(set, ctx);
pm_runtime_forbid(&dev->pdev->dev);
- ret = drm_crtc_helper_set_config(set);
+ ret = drm_crtc_helper_set_config(set, ctx);
pm_runtime_allow(&dev->pdev->dev);
return ret;
diff --git a/drivers/gpu/drm/gma500/gma_display.h b/drivers/gpu/drm/gma500/gma_display.h
index e72dd08b701b..166e608923db 100644
--- a/drivers/gpu/drm/gma500/gma_display.h
+++ b/drivers/gpu/drm/gma500/gma_display.h
@@ -79,7 +79,8 @@ extern void gma_crtc_prepare(struct drm_crtc *crtc);
extern void gma_crtc_commit(struct drm_crtc *crtc);
extern void gma_crtc_disable(struct drm_crtc *crtc);
extern void gma_crtc_destroy(struct drm_crtc *crtc);
-extern int gma_crtc_set_config(struct drm_mode_set *set);
+extern int gma_crtc_set_config(struct drm_mode_set *set,
+ struct drm_modeset_acquire_ctx *ctx);
extern void gma_crtc_save(struct drm_crtc *crtc);
extern void gma_crtc_restore(struct drm_crtc *crtc);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 03d9e45694c9..98b17070a123 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1307,8 +1307,6 @@ void i915_driver_unload(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct pci_dev *pdev = dev_priv->drm.pdev;
- struct drm_modeset_acquire_ctx ctx;
- int ret;
intel_fbdev_fini(dev);
@@ -1317,23 +1315,7 @@ void i915_driver_unload(struct drm_device *dev)
intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
- drm_modeset_acquire_init(&ctx, 0);
- while (1) {
- ret = drm_modeset_lock_all_ctx(dev, &ctx);
- if (!ret)
- ret = drm_atomic_helper_disable_all(dev, &ctx);
-
- if (ret != -EDEADLK)
- break;
-
- drm_modeset_backoff(&ctx);
- }
-
- if (ret)
- DRM_ERROR("Disabling all crtc's during unload failed with %i\n", ret);
-
- drm_modeset_drop_locks(&ctx);
- drm_modeset_acquire_fini(&ctx);
+ drm_atomic_helper_shutdown(dev);
intel_gvt_cleanup(dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 010e5ddb198a..e27ea89efd67 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13426,7 +13426,8 @@ intel_legacy_cursor_update(struct drm_plane *plane,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h)
+ uint32_t src_w, uint32_t src_h,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
int ret;
@@ -13539,7 +13540,7 @@ out_free:
slow:
return drm_atomic_helper_update_plane(plane, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h,
- src_x, src_y, src_w, src_h);
+ src_x, src_y, src_w, src_h, ctx);
}
static const struct drm_plane_funcs intel_cursor_plane_funcs = {
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index 094cbdcbcd6d..c1f62eb07c07 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -149,7 +149,6 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder,
to_intel_connector(conn_state->connector);
int ret;
uint32_t temp;
- int slots;
/* MST encoders are bound to a crtc, not to a connector,
* force the mapping here for get_hw_state.
@@ -165,7 +164,8 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder,
ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr,
connector->port,
- pipe_config->pbn, &slots);
+ pipe_config->pbn,
+ pipe_config->dp_m_n.tu);
if (ret == false) {
DRM_ERROR("failed to allocate vcpi\n");
return;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 0ffb8affef35..60a5451ae0b9 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -37,7 +37,8 @@ static int mdp5_update_cursor_plane_legacy(struct drm_plane *plane,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h);
+ uint32_t src_w, uint32_t src_h,
+ struct drm_modeset_acquire_ctx *ctx);
static void set_scanout_locked(struct drm_plane *plane,
struct drm_framebuffer *fb);
@@ -886,7 +887,8 @@ static int mdp5_update_cursor_plane_legacy(struct drm_plane *plane,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h)
+ uint32_t src_w, uint32_t src_h,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_plane_state *plane_state, *new_plane_state;
struct mdp5_plane_state *mdp5_pstate;
@@ -954,7 +956,7 @@ slow_free:
slow:
return drm_atomic_helper_update_plane(plane, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h,
- src_x, src_y, src_w, src_h);
+ src_x, src_y, src_w, src_h, ctx);
}
enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane)
diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
index ab7b69c11d40..43ab560de7f9 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
@@ -1031,8 +1031,9 @@ nv04_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
return 0;
}
-int
-nouveau_crtc_set_config(struct drm_mode_set *set)
+static int
+nouveau_crtc_set_config(struct drm_mode_set *set,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_device *dev;
struct nouveau_drm *drm;
@@ -1049,7 +1050,7 @@ nouveau_crtc_set_config(struct drm_mode_set *set)
if (ret < 0 && ret != -EACCES)
return ret;
- ret = drm_crtc_helper_set_config(set);
+ ret = drm_crtc_helper_set_config(set, ctx);
drm = nouveau_drm(dev);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
index 5319f2a7f24d..e54944d23268 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
@@ -94,7 +94,8 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb, int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h)
+ uint32_t src_w, uint32_t src_h,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct nouveau_drm *drm = nouveau_drm(plane->dev);
struct nvif_object *dev = &drm->client.device.object;
@@ -172,7 +173,8 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
}
static int
-nv10_disable_plane(struct drm_plane *plane)
+nv10_disable_plane(struct drm_plane *plane,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct nvif_object *dev = &nouveau_drm(plane->dev)->client.device.object;
struct nouveau_plane *nv_plane =
@@ -190,7 +192,7 @@ nv10_disable_plane(struct drm_plane *plane)
static void
nv_destroy_plane(struct drm_plane *plane)
{
- plane->funcs->disable_plane(plane);
+ drm_plane_force_disable(plane);
drm_plane_cleanup(plane);
kfree(plane);
}
@@ -331,7 +333,7 @@ nv10_overlay_init(struct drm_device *device)
plane->set_params = nv10_set_params;
nv10_set_params(plane);
- nv10_disable_plane(&plane->base);
+ drm_plane_force_disable(&plane->base);
return;
cleanup:
drm_plane_cleanup(&plane->base);
@@ -345,7 +347,8 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb, int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h)
+ uint32_t src_w, uint32_t src_h,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct nvif_object *dev = &nouveau_drm(plane->dev)->client.device.object;
struct nouveau_plane *nv_plane =
@@ -425,7 +428,8 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
}
static int
-nv04_disable_plane(struct drm_plane *plane)
+nv04_disable_plane(struct drm_plane *plane,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct nvif_object *dev = &nouveau_drm(plane->dev)->client.device.object;
struct nouveau_plane *nv_plane =
@@ -483,7 +487,7 @@ nv04_overlay_init(struct drm_device *device)
drm_object_attach_property(&plane->base.base,
plane->props.brightness, plane->brightness);
- nv04_disable_plane(&plane->base);
+ drm_plane_force_disable(&plane->base);
return;
cleanup:
drm_plane_cleanup(&plane->base);
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 33269c7df30f..6104f61b00fc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -436,8 +436,12 @@ nouveau_display_fini(struct drm_device *dev, bool suspend)
struct drm_connector *connector;
struct drm_crtc *crtc;
- if (!suspend)
- drm_crtc_force_disable_all(dev);
+ if (!suspend) {
+ if (drm_drv_uses_atomic_modeset(dev))
+ drm_atomic_helper_shutdown(dev);
+ else
+ drm_crtc_force_disable_all(dev);
+ }
/* Make sure that drm and hw vblank irqs get properly disabled. */
drm_for_each_crtc(crtc, dev)
@@ -788,7 +792,8 @@ fail:
int
nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
- struct drm_pending_vblank_event *event, u32 flags)
+ struct drm_pending_vblank_event *event, u32 flags,
+ struct drm_modeset_acquire_ctx *ctx)
{
const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1;
struct drm_device *dev = crtc->dev;
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index 4a75df06c139..e1d772d39488 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -76,7 +76,8 @@ int nouveau_display_vblstamp(struct drm_device *, unsigned int, int *,
int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
- uint32_t page_flip_flags);
+ uint32_t page_flip_flags,
+ struct drm_modeset_acquire_ctx *ctx);
int nouveau_finish_page_flip(struct nouveau_channel *,
struct nouveau_page_flip_state *);
@@ -87,7 +88,6 @@ int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *,
void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *);
-int nouveau_crtc_set_config(struct drm_mode_set *set);
#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
extern int nouveau_backlight_init(struct drm_device *);
extern void nouveau_backlight_exit(struct drm_device *);
diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c
index ccb597eac538..a4aacbc0cec8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vga.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
@@ -95,6 +95,10 @@ nouveau_vga_init(struct nouveau_drm *drm)
vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
+ /* don't register Thunderbolt eGPU with vga_switcheroo */
+ if (pci_is_thunderbolt_attached(dev->pdev))
+ return;
+
if (nouveau_runtime_pm == 1)
runtime = true;
if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm()))
@@ -111,6 +115,11 @@ nouveau_vga_fini(struct nouveau_drm *drm)
struct drm_device *dev = drm->dev;
bool runtime = false;
+ vga_client_register(dev->pdev, NULL, NULL, NULL);
+
+ if (pci_is_thunderbolt_attached(dev->pdev))
+ return;
+
if (nouveau_runtime_pm == 1)
runtime = true;
if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm()))
@@ -119,7 +128,6 @@ nouveau_vga_fini(struct nouveau_drm *drm)
vga_switcheroo_unregister_client(dev->pdev);
if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus())
vga_switcheroo_fini_domain_pm_ops(drm->dev->dev);
- vga_client_register(dev->pdev, NULL, NULL, NULL);
}
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 7ad1ee580cf0..418872b493a3 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -2895,7 +2895,8 @@ nv50_msto_enable(struct drm_encoder *encoder)
if (WARN_ON(!mstc))
return;
- r = drm_dp_mst_allocate_vcpi(&mstm->mgr, mstc->port, mstc->pbn, &slots);
+ slots = drm_dp_find_vcpi_slots(&mstm->mgr, mstc->pbn);
+ r = drm_dp_mst_allocate_vcpi(&mstm->mgr, mstc->port, mstc->pbn, slots);
WARN_ON(!r);
if (mstm->outp->dcb->sorconf.link & 1)
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 64b02f3c7906..6ecf42783d4b 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1468,7 +1468,9 @@ int radeon_device_init(struct radeon_device *rdev,
if (rdev->flags & RADEON_IS_PX)
runtime = true;
- vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, runtime);
+ if (!pci_is_thunderbolt_attached(rdev->pdev))
+ vga_switcheroo_register_client(rdev->pdev,
+ &radeon_switcheroo_ops, runtime);
if (runtime)
vga_switcheroo_init_domain_pm_ops(rdev->dev, &rdev->vga_pm_domain);
@@ -1561,7 +1563,8 @@ void radeon_device_fini(struct radeon_device *rdev)
/* evict vram memory */
radeon_bo_evict_vram(rdev);
radeon_fini(rdev);
- vga_switcheroo_unregister_client(rdev->pdev);
+ if (!pci_is_thunderbolt_attached(rdev->pdev))
+ vga_switcheroo_unregister_client(rdev->pdev);
if (rdev->flags & RADEON_IS_PX)
vga_switcheroo_fini_domain_pm_ops(rdev->dev);
vga_client_register(rdev->pdev, NULL, NULL, NULL);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index aea8b62835a4..146297a702ab 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -485,7 +485,8 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
uint32_t page_flip_flags,
- uint32_t target)
+ uint32_t target,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
@@ -623,7 +624,8 @@ cleanup:
}
static int
-radeon_crtc_set_config(struct drm_mode_set *set)
+radeon_crtc_set_config(struct drm_mode_set *set,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_device *dev;
struct radeon_device *rdev;
@@ -640,7 +642,7 @@ radeon_crtc_set_config(struct drm_mode_set *set)
if (ret < 0)
return ret;
- ret = drm_crtc_helper_set_config(set);
+ ret = drm_crtc_helper_set_config(set, ctx);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
if (crtc->enabled)
diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c
index 7d5ada3980dc..6598306dca9b 100644
--- a/drivers/gpu/drm/radeon/radeon_dp_mst.c
+++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c
@@ -453,9 +453,11 @@ radeon_mst_encoder_dpms(struct drm_encoder *encoder, int mode)
DRM_DEBUG_KMS("dig encoder is %d %d %d\n", dig_enc->dig_encoder,
dig_enc->linkb, radeon_crtc->crtc_id);
+ slots = drm_dp_find_vcpi_slots(&radeon_connector->mst_port->mst_mgr,
+ mst_enc->pbn);
ret = drm_dp_mst_allocate_vcpi(&radeon_connector->mst_port->mst_mgr,
radeon_connector->port,
- mst_enc->pbn, &slots);
+ mst_enc->pbn, slots);
ret = drm_dp_update_payload_part1(&radeon_connector->mst_port->mst_mgr);
radeon_dp_mst_set_be_cntl(primary, mst_enc,
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index a32a62e03a44..e3e7cb1d10a2 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -115,7 +115,8 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
if ((radeon_runtime_pm != 0) &&
radeon_has_atpx() &&
- ((flags & RADEON_IS_IGP) == 0))
+ ((flags & RADEON_IS_IGP) == 0) &&
+ !pci_is_thunderbolt_attached(rdev->pdev))
flags |= RADEON_IS_PX;
/* radeon_device_init should report only fatal error
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 0e4eb845cbb0..50c41c0a50ef 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -13,7 +13,7 @@ config DRM_ROCKCHIP
IP found on the SoC.
config ROCKCHIP_ANALOGIX_DP
- tristate "Rockchip specific extensions for Analogix DP driver"
+ bool "Rockchip specific extensions for Analogix DP driver"
depends on DRM_ROCKCHIP
select DRM_ANALOGIX_DP
help
@@ -22,7 +22,7 @@ config ROCKCHIP_ANALOGIX_DP
on RK3288 based SoC, you should selet this option.
config ROCKCHIP_CDN_DP
- tristate "Rockchip cdn DP"
+ bool "Rockchip cdn DP"
depends on DRM_ROCKCHIP
depends on EXTCON
select SND_SOC_HDMI_CODEC if SND_SOC
@@ -33,7 +33,7 @@ config ROCKCHIP_CDN_DP
option.
config ROCKCHIP_DW_HDMI
- tristate "Rockchip specific extensions for Synopsys DW HDMI"
+ bool "Rockchip specific extensions for Synopsys DW HDMI"
depends on DRM_ROCKCHIP
select DRM_DW_HDMI
help
@@ -43,7 +43,7 @@ config ROCKCHIP_DW_HDMI
option.
config ROCKCHIP_DW_MIPI_DSI
- tristate "Rockchip specific extensions for Synopsys DW MIPI DSI"
+ bool "Rockchip specific extensions for Synopsys DW MIPI DSI"
depends on DRM_ROCKCHIP
select DRM_MIPI_DSI
help
@@ -53,7 +53,7 @@ config ROCKCHIP_DW_MIPI_DSI
option.
config ROCKCHIP_INNO_HDMI
- tristate "Rockchip specific extensions for Innosilicon HDMI"
+ bool "Rockchip specific extensions for Innosilicon HDMI"
depends on DRM_ROCKCHIP
help
This selects support for Rockchip SoC specific extensions
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index c931e2a7d8de..fa8dc9d9aac2 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -3,14 +3,14 @@
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
- rockchip_drm_gem.o rockchip_drm_psr.o rockchip_drm_vop.o
+ rockchip_drm_gem.o rockchip_drm_psr.o \
+ rockchip_drm_vop.o rockchip_vop_reg.o
rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
-obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
-obj-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp.o
-cdn-dp-objs := cdn-dp-core.o cdn-dp-reg.o
-obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
-obj-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
-obj-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
+rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
+rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
+rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
+rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
+rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
-obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_vop_reg.o
+obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 8548e8271639..91ebe5c2c7a0 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -507,7 +507,7 @@ static const struct of_device_id rockchip_dp_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, rockchip_dp_dt_ids);
-static struct platform_driver rockchip_dp_driver = {
+struct platform_driver rockchip_dp_driver = {
.probe = rockchip_dp_probe,
.remove = rockchip_dp_remove,
.driver = {
@@ -516,10 +516,3 @@ static struct platform_driver rockchip_dp_driver = {
.of_match_table = of_match_ptr(rockchip_dp_dt_ids),
},
};
-
-module_platform_driver(rockchip_dp_driver);
-
-MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
-MODULE_AUTHOR("Jeff chen <jeff.chen@rock-chips.com>");
-MODULE_DESCRIPTION("Rockchip Specific Analogix-DP Driver Extension");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index 9edb8dc1ea14..4e55d63c3ef3 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -1244,7 +1244,7 @@ static const struct dev_pm_ops cdn_dp_pm_ops = {
cdn_dp_resume)
};
-static struct platform_driver cdn_dp_driver = {
+struct platform_driver cdn_dp_driver = {
.probe = cdn_dp_probe,
.remove = cdn_dp_remove,
.shutdown = cdn_dp_shutdown,
@@ -1255,9 +1255,3 @@ static struct platform_driver cdn_dp_driver = {
.pm = &cdn_dp_pm_ops,
},
};
-
-module_platform_driver(cdn_dp_driver);
-
-MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
-MODULE_DESCRIPTION("cdn DP Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index f84f9ae2fd35..21b9737662ae 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -34,7 +34,7 @@
#define RK3288_DSI0_SEL_VOP_LIT BIT(6)
#define RK3288_DSI1_SEL_VOP_LIT BIT(9)
-#define RK3399_GRF_SOC_CON19 0x6250
+#define RK3399_GRF_SOC_CON20 0x6250
#define RK3399_DSI0_SEL_VOP_LIT BIT(0)
#define RK3399_DSI1_SEL_VOP_LIT BIT(4)
@@ -251,6 +251,9 @@
#define THS_PRE_PROGRAM_EN BIT(7)
#define THS_ZERO_PROGRAM_EN BIT(6)
+#define DW_MIPI_NEEDS_PHY_CFG_CLK BIT(0)
+#define DW_MIPI_NEEDS_GRF_CLK BIT(1)
+
enum {
BANDGAP_97_07,
BANDGAP_98_05,
@@ -279,6 +282,7 @@ struct dw_mipi_dsi_plat_data {
u32 grf_switch_reg;
u32 grf_dsi0_mode;
u32 grf_dsi0_mode_reg;
+ unsigned int flags;
unsigned int max_data_lanes;
};
@@ -291,6 +295,7 @@ struct dw_mipi_dsi {
struct regmap *grf_regmap;
void __iomem *base;
+ struct clk *grf_clk;
struct clk *pllref_clk;
struct clk *pclk;
struct clk *phy_cfg_clk;
@@ -979,6 +984,17 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder)
dw_mipi_dsi_dphy_interface_config(dsi);
dw_mipi_dsi_clear_err(dsi);
+ /*
+ * For the RK3399, the clk of grf must be enabled before writing grf
+ * register. And for RK3288 or other soc, this grf_clk must be NULL,
+ * the clk_prepare_enable return true directly.
+ */
+ ret = clk_prepare_enable(dsi->grf_clk);
+ if (ret) {
+ dev_err(dsi->dev, "Failed to enable grf_clk: %d\n", ret);
+ return;
+ }
+
if (pdata->grf_dsi0_mode_reg)
regmap_write(dsi->grf_regmap, pdata->grf_dsi0_mode_reg,
pdata->grf_dsi0_mode);
@@ -1003,6 +1019,8 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder)
regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val);
dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
dsi->dpms_mode = DRM_MODE_DPMS_ON;
+
+ clk_disable_unprepare(dsi->grf_clk);
}
static int
@@ -1133,9 +1151,10 @@ static struct dw_mipi_dsi_plat_data rk3288_mipi_dsi_drv_data = {
static struct dw_mipi_dsi_plat_data rk3399_mipi_dsi_drv_data = {
.dsi0_en_bit = RK3399_DSI0_SEL_VOP_LIT,
.dsi1_en_bit = RK3399_DSI1_SEL_VOP_LIT,
- .grf_switch_reg = RK3399_GRF_SOC_CON19,
+ .grf_switch_reg = RK3399_GRF_SOC_CON20,
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
+ .flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK,
.max_data_lanes = 4,
};
@@ -1227,15 +1246,22 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
clk_disable_unprepare(dsi->pclk);
}
- dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
- if (IS_ERR(dsi->phy_cfg_clk)) {
- ret = PTR_ERR(dsi->phy_cfg_clk);
- if (ret != -ENOENT) {
+ if (pdata->flags & DW_MIPI_NEEDS_PHY_CFG_CLK) {
+ dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
+ if (IS_ERR(dsi->phy_cfg_clk)) {
+ ret = PTR_ERR(dsi->phy_cfg_clk);
dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret);
return ret;
}
- dsi->phy_cfg_clk = NULL;
- dev_dbg(dev, "have not phy_cfg_clk\n");
+ }
+
+ if (pdata->flags & DW_MIPI_NEEDS_GRF_CLK) {
+ dsi->grf_clk = devm_clk_get(dev, "grf");
+ if (IS_ERR(dsi->grf_clk)) {
+ ret = PTR_ERR(dsi->grf_clk);
+ dev_err(dev, "Unable to get grf_clk: %d\n", ret);
+ return ret;
+ }
}
ret = clk_prepare_enable(dsi->pllref_clk);
@@ -1304,7 +1330,7 @@ static int dw_mipi_dsi_remove(struct platform_device *pdev)
return 0;
}
-static struct platform_driver dw_mipi_dsi_driver = {
+struct platform_driver dw_mipi_dsi_driver = {
.probe = dw_mipi_dsi_probe,
.remove = dw_mipi_dsi_remove,
.driver = {
@@ -1312,9 +1338,3 @@ static struct platform_driver dw_mipi_dsi_driver = {
.name = DRIVER_NAME,
},
};
-module_platform_driver(dw_mipi_dsi_driver);
-
-MODULE_DESCRIPTION("ROCKCHIP MIPI DSI host controller driver");
-MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index d53827413996..63dab6f1b191 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -325,7 +325,7 @@ static int dw_hdmi_rockchip_remove(struct platform_device *pdev)
return 0;
}
-static struct platform_driver dw_hdmi_rockchip_pltfm_driver = {
+struct platform_driver dw_hdmi_rockchip_pltfm_driver = {
.probe = dw_hdmi_rockchip_probe,
.remove = dw_hdmi_rockchip_remove,
.driver = {
@@ -333,11 +333,3 @@ static struct platform_driver dw_hdmi_rockchip_pltfm_driver = {
.of_match_table = dw_hdmi_rockchip_dt_ids,
},
};
-
-module_platform_driver(dw_hdmi_rockchip_pltfm_driver);
-
-MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>");
-MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
-MODULE_DESCRIPTION("Rockchip Specific DW-HDMI Driver Extension");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:dwhdmi-rockchip");
diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c
index 006260de9dbd..7d9b75eb6c44 100644
--- a/drivers/gpu/drm/rockchip/inno_hdmi.c
+++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
@@ -923,7 +923,7 @@ static const struct of_device_id inno_hdmi_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
-static struct platform_driver inno_hdmi_driver = {
+struct platform_driver inno_hdmi_driver = {
.probe = inno_hdmi_probe,
.remove = inno_hdmi_remove,
.driver = {
@@ -931,11 +931,3 @@ static struct platform_driver inno_hdmi_driver = {
.of_match_table = inno_hdmi_dt_ids,
},
};
-
-module_platform_driver(inno_hdmi_driver);
-
-MODULE_AUTHOR("Zheng Yang <zhengyang@rock-chips.com>");
-MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
-MODULE_DESCRIPTION("Rockchip Specific INNO-HDMI Driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:innohdmi-rockchip");
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index ccf456938792..cd7d02e1f758 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -304,34 +304,37 @@ static const struct dev_pm_ops rockchip_drm_pm_ops = {
rockchip_drm_sys_resume)
};
-static int compare_of(struct device *dev, void *data)
-{
- struct device_node *np = data;
+#define MAX_ROCKCHIP_SUB_DRIVERS 16
+static struct platform_driver *rockchip_sub_drivers[MAX_ROCKCHIP_SUB_DRIVERS];
+static int num_rockchip_sub_drivers;
- return dev->of_node == np;
+static int compare_dev(struct device *dev, void *data)
+{
+ return dev == (struct device *)data;
}
-static void rockchip_add_endpoints(struct device *dev,
- struct component_match **match,
- struct device_node *port)
+static struct component_match *rockchip_drm_match_add(struct device *dev)
{
- struct device_node *ep, *remote;
+ struct component_match *match = NULL;
+ int i;
- for_each_child_of_node(port, ep) {
- remote = of_graph_get_remote_port_parent(ep);
- if (!remote || !of_device_is_available(remote)) {
- of_node_put(remote);
- continue;
- } else if (!of_device_is_available(remote->parent)) {
- dev_warn(dev, "parent device of %s is not available\n",
- remote->full_name);
- of_node_put(remote);
- continue;
- }
+ for (i = 0; i < num_rockchip_sub_drivers; i++) {
+ struct platform_driver *drv = rockchip_sub_drivers[i];
+ struct device *p = NULL, *d;
+
+ do {
+ d = bus_find_device(&platform_bus_type, p, &drv->driver,
+ (void *)platform_bus_type.match);
+ put_device(p);
+ p = d;
- drm_of_component_match_add(dev, match, compare_of, remote);
- of_node_put(remote);
+ if (!d)
+ break;
+ component_match_add(dev, &match, compare_dev, d);
+ } while (true);
}
+
+ return match ?: ERR_PTR(-ENODEV);
}
static const struct component_master_ops rockchip_drm_ops = {
@@ -339,21 +342,16 @@ static const struct component_master_ops rockchip_drm_ops = {
.unbind = rockchip_drm_unbind,
};
-static int rockchip_drm_platform_probe(struct platform_device *pdev)
+static int rockchip_drm_platform_of_probe(struct device *dev)
{
- struct device *dev = &pdev->dev;
- struct component_match *match = NULL;
struct device_node *np = dev->of_node;
struct device_node *port;
+ bool found = false;
int i;
if (!np)
return -ENODEV;
- /*
- * Bind the crtc ports first, so that
- * drm_of_find_possible_crtcs called from encoder .bind callbacks
- * works as expected.
- */
+
for (i = 0;; i++) {
struct device_node *iommu;
@@ -377,9 +375,9 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
is_support_iommu = false;
}
+ found = true;
+
of_node_put(iommu);
- drm_of_component_match_add(dev, &match, compare_of,
- port->parent);
of_node_put(port);
}
@@ -388,27 +386,27 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
return -ENODEV;
}
- if (!match) {
+ if (!found) {
dev_err(dev, "No available vop found for display-subsystem.\n");
return -ENODEV;
}
- /*
- * For each bound crtc, bind the encoders attached to its
- * remote endpoint.
- */
- for (i = 0;; i++) {
- port = of_parse_phandle(np, "ports", i);
- if (!port)
- break;
- if (!of_device_is_available(port->parent)) {
- of_node_put(port);
- continue;
- }
+ return 0;
+}
- rockchip_add_endpoints(dev, &match, port);
- of_node_put(port);
- }
+static int rockchip_drm_platform_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct component_match *match = NULL;
+ int ret;
+
+ ret = rockchip_drm_platform_of_probe(dev);
+ if (ret)
+ return ret;
+
+ match = rockchip_drm_match_add(dev);
+ if (IS_ERR(match))
+ return PTR_ERR(match);
return component_master_add_with_match(dev, &rockchip_drm_ops, match);
}
@@ -436,7 +434,54 @@ static struct platform_driver rockchip_drm_platform_driver = {
},
};
-module_platform_driver(rockchip_drm_platform_driver);
+#define ADD_ROCKCHIP_SUB_DRIVER(drv, cond) { \
+ if (IS_ENABLED(cond) && \
+ !WARN_ON(num_rockchip_sub_drivers >= MAX_ROCKCHIP_SUB_DRIVERS)) \
+ rockchip_sub_drivers[num_rockchip_sub_drivers++] = &drv; \
+}
+
+static int __init rockchip_drm_init(void)
+{
+ int ret;
+
+ num_rockchip_sub_drivers = 0;
+ ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_DRM_ROCKCHIP);
+ ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
+ CONFIG_ROCKCHIP_ANALOGIX_DP);
+ ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP);
+ ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_rockchip_pltfm_driver,
+ CONFIG_ROCKCHIP_DW_HDMI);
+ ADD_ROCKCHIP_SUB_DRIVER(dw_mipi_dsi_driver,
+ CONFIG_ROCKCHIP_DW_MIPI_DSI);
+ ADD_ROCKCHIP_SUB_DRIVER(inno_hdmi_driver, CONFIG_ROCKCHIP_INNO_HDMI);
+
+ ret = platform_register_drivers(rockchip_sub_drivers,
+ num_rockchip_sub_drivers);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&rockchip_drm_platform_driver);
+ if (ret)
+ goto err_unreg_drivers;
+
+ return 0;
+
+err_unreg_drivers:
+ platform_unregister_drivers(rockchip_sub_drivers,
+ num_rockchip_sub_drivers);
+ return ret;
+}
+
+static void __exit rockchip_drm_fini(void)
+{
+ platform_driver_unregister(&rockchip_drm_platform_driver);
+
+ platform_unregister_drivers(rockchip_sub_drivers,
+ num_rockchip_sub_drivers);
+}
+
+module_init(rockchip_drm_init);
+module_exit(rockchip_drm_fini);
MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>");
MODULE_DESCRIPTION("ROCKCHIP DRM Driver");
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 8aca219ec4c8..a48fcce3f5f6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -65,4 +65,10 @@ void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
unsigned int mstimeout);
+extern struct platform_driver cdn_dp_driver;
+extern struct platform_driver dw_hdmi_rockchip_pltfm_driver;
+extern struct platform_driver dw_mipi_dsi_driver;
+extern struct platform_driver inno_hdmi_driver;
+extern struct platform_driver rockchip_dp_driver;
+extern struct platform_driver vop_platform_driver;
#endif /* _ROCKCHIP_DRM_DRV_H_ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index 91fbc7b52147..0da44442aab0 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -404,7 +404,7 @@ static int vop_remove(struct platform_device *pdev)
return 0;
}
-static struct platform_driver vop_platform_driver = {
+struct platform_driver vop_platform_driver = {
.probe = vop_probe,
.remove = vop_remove,
.driver = {
@@ -412,9 +412,3 @@ static struct platform_driver vop_platform_driver = {
.of_match_table = of_match_ptr(vop_driver_dt_match),
},
};
-
-module_platform_driver(vop_platform_driver);
-
-MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>");
-MODULE_DESCRIPTION("ROCKCHIP VOP Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
index 5fcabc04f307..e7738939a86d 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
@@ -449,7 +449,8 @@ void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc)
static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
- uint32_t page_flip_flags)
+ uint32_t page_flip_flags,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);
struct drm_device *dev = scrtc->crtc.dev;
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/shmobile/shmob_drm_plane.c
index 2023a93cee2b..97f6e4a3eb0d 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_plane.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.c
@@ -177,7 +177,8 @@ shmob_drm_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb, int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h)
+ uint32_t src_w, uint32_t src_h,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct shmob_drm_plane *splane = to_shmob_plane(plane);
struct shmob_drm_device *sdev = plane->dev->dev_private;
@@ -208,7 +209,8 @@ shmob_drm_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
return 0;
}
-static int shmob_drm_plane_disable(struct drm_plane *plane)
+static int shmob_drm_plane_disable(struct drm_plane *plane,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct shmob_drm_plane *splane = to_shmob_plane(plane);
struct shmob_drm_device *sdev = plane->dev->dev_private;
@@ -221,7 +223,7 @@ static int shmob_drm_plane_disable(struct drm_plane *plane)
static void shmob_drm_plane_destroy(struct drm_plane *plane)
{
- shmob_drm_plane_disable(plane);
+ drm_plane_force_disable(plane);
drm_plane_cleanup(plane);
}
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 0db5d5a8d3b9..95b373f739f2 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -1382,7 +1382,7 @@ static int tegra_dc_show_regs(struct seq_file *s, void *data)
struct tegra_dc *dc = node->info_ent->data;
int err = 0;
- drm_modeset_lock_crtc(&dc->base, NULL);
+ drm_modeset_lock(&dc->base.mutex, NULL);
if (!dc->base.state->active) {
err = -EBUSY;
@@ -1609,7 +1609,7 @@ static int tegra_dc_show_regs(struct seq_file *s, void *data)
#undef DUMP_REG
unlock:
- drm_modeset_unlock_crtc(&dc->base);
+ drm_modeset_unlock(&dc->base.mutex);
return err;
}
@@ -1620,7 +1620,7 @@ static int tegra_dc_show_crc(struct seq_file *s, void *data)
int err = 0;
u32 value;
- drm_modeset_lock_crtc(&dc->base, NULL);
+ drm_modeset_lock(&dc->base.mutex, NULL);
if (!dc->base.state->active) {
err = -EBUSY;
@@ -1640,7 +1640,7 @@ static int tegra_dc_show_crc(struct seq_file *s, void *data)
tegra_dc_writel(dc, 0, DC_COM_CRC_CONTROL);
unlock:
- drm_modeset_unlock_crtc(&dc->base);
+ drm_modeset_unlock(&dc->base.mutex);
return err;
}
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
index c92faa8f7560..afd2a7b2aff7 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
@@ -579,7 +579,7 @@ static void tilcdc_crtc_recover_work(struct work_struct *work)
dev_info(crtc->dev->dev, "%s: Reset CRTC", __func__);
- drm_modeset_lock_crtc(crtc, NULL);
+ drm_modeset_lock(&crtc->mutex, NULL);
if (!tilcdc_crtc_is_on(crtc))
goto out;
@@ -587,7 +587,7 @@ static void tilcdc_crtc_recover_work(struct work_struct *work)
tilcdc_crtc_disable(crtc);
tilcdc_crtc_enable(crtc);
out:
- drm_modeset_unlock_crtc(crtc);
+ drm_modeset_unlock(&crtc->mutex);
}
static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
@@ -595,9 +595,9 @@ static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
struct tilcdc_drm_private *priv = crtc->dev->dev_private;
- drm_modeset_lock_crtc(crtc, NULL);
+ drm_modeset_lock(&crtc->mutex, NULL);
tilcdc_crtc_disable(crtc);
- drm_modeset_unlock_crtc(crtc);
+ drm_modeset_unlock(&crtc->mutex);
flush_workqueue(priv->wq);
@@ -856,7 +856,7 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc)
struct tilcdc_drm_private *priv = dev->dev_private;
struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
- drm_modeset_lock_crtc(crtc, NULL);
+ drm_modeset_lock(&crtc->mutex, NULL);
if (tilcdc_crtc->lcd_fck_rate != clk_get_rate(priv->clk)) {
if (tilcdc_crtc_is_on(crtc)) {
pm_runtime_get_sync(dev->dev);
@@ -868,7 +868,7 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc)
pm_runtime_put_sync(dev->dev);
}
}
- drm_modeset_unlock_crtc(crtc);
+ drm_modeset_unlock(&crtc->mutex);
}
#define SYNC_LOST_COUNT_LIMIT 50
diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
index 6a257dd08ee0..551709e6b114 100644
--- a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
+++ b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
@@ -122,21 +122,6 @@ void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj)
}
EXPORT_SYMBOL_GPL(tinydrm_gem_cma_free_object);
-const struct file_operations tinydrm_fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .release = drm_release,
- .unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = drm_compat_ioctl,
-#endif
- .poll = drm_poll,
- .read = drm_read,
- .llseek = no_llseek,
- .mmap = drm_gem_cma_mmap,
-};
-EXPORT_SYMBOL(tinydrm_fops);
-
static struct drm_framebuffer *
tinydrm_fb_create(struct drm_device *drm, struct drm_file *file_priv,
const struct drm_mode_fb_cmd2 *mode_cmd)
@@ -251,7 +236,7 @@ static void tinydrm_unregister(struct tinydrm_device *tdev)
{
struct drm_fbdev_cma *fbdev_cma = tdev->fbdev_cma;
- drm_crtc_force_disable_all(tdev->drm);
+ drm_atomic_helper_shutdown(tdev->drm);
/* don't restore fbdev in lastclose, keep pipeline disabled */
tdev->fbdev_cma = NULL;
drm_dev_unregister(tdev->drm);
@@ -302,7 +287,7 @@ EXPORT_SYMBOL(devm_tinydrm_register);
*/
void tinydrm_shutdown(struct tinydrm_device *tdev)
{
- drm_crtc_force_disable_all(tdev->drm);
+ drm_atomic_helper_shutdown(tdev->drm);
}
EXPORT_SYMBOL(tinydrm_shutdown);
diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c
index b29fe86158f7..482ff1c3db61 100644
--- a/drivers/gpu/drm/tinydrm/mi0283qt.c
+++ b/drivers/gpu/drm/tinydrm/mi0283qt.c
@@ -132,9 +132,12 @@ static const struct drm_display_mode mi0283qt_mode = {
TINYDRM_MODE(320, 240, 58, 43),
};
+DEFINE_DRM_GEM_CMA_FOPS(mi0283qt_fops);
+
static struct drm_driver mi0283qt_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
DRIVER_ATOMIC,
+ .fops = &mi0283qt_fops,
TINYDRM_GEM_DRIVER_OPS,
.lastclose = tinydrm_lastclose,
.debugfs_init = mipi_dbi_debugfs_init,
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
index f2b2481cad52..5bcae7649795 100644
--- a/drivers/gpu/drm/udl/udl_modeset.c
+++ b/drivers/gpu/drm/udl/udl_modeset.c
@@ -361,7 +361,8 @@ static void udl_crtc_destroy(struct drm_crtc *crtc)
static int udl_crtc_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
- uint32_t page_flip_flags)
+ uint32_t page_flip_flags,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct udl_framebuffer *ufb = to_udl_fb(fb);
struct drm_device *dev = crtc->dev;
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 24edd0c22cc9..865e9f494bcc 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -807,12 +807,13 @@ static int vc4_async_page_flip(struct drm_crtc *crtc,
static int vc4_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
- uint32_t flags)
+ uint32_t flags,
+ struct drm_modeset_acquire_ctx *ctx)
{
if (flags & DRM_MODE_PAGE_FLIP_ASYNC)
return vc4_async_page_flip(crtc, fb, event, flags);
else
- return drm_atomic_helper_page_flip(crtc, fb, event, flags);
+ return drm_atomic_helper_page_flip(crtc, fb, event, flags, ctx);
}
static struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 0f4564beb017..d34cd5393a9b 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -756,7 +756,8 @@ vc4_update_plane(struct drm_plane *plane,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h)
+ uint32_t src_w, uint32_t src_h,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_plane_state *plane_state;
struct vc4_plane_state *vc4_state;
@@ -817,7 +818,8 @@ out:
crtc_x, crtc_y,
crtc_w, crtc_h,
src_x, src_y,
- src_w, src_h);
+ src_w, src_h,
+ ctx);
}
static const struct drm_plane_funcs vc4_plane_funcs = {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index c18c81f63ac3..6078654d033b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -2947,10 +2947,11 @@ vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv,
* the vmwgfx modesetting. So explicitly clear that member before calling
* into drm_atomic_helper_set_config.
*/
-int vmw_kms_set_config(struct drm_mode_set *set)
+int vmw_kms_set_config(struct drm_mode_set *set,
+ struct drm_modeset_acquire_ctx *ctx)
{
if (set && set->mode)
set->mode->type = 0;
- return drm_atomic_helper_set_config(set);
+ return drm_atomic_helper_set_config(set, ctx);
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 9c161d29aaeb..0c226b2adea5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -453,6 +453,7 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
bool to_surface,
bool interruptible);
-int vmw_kms_set_config(struct drm_mode_set *set);
+int vmw_kms_set_config(struct drm_mode_set *set,
+ struct drm_modeset_acquire_ctx *ctx);
#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index 2664e4c16750..8d7dc9def7c2 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -310,7 +310,8 @@ static void vmw_sou_crtc_helper_disable(struct drm_crtc *crtc)
static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *new_fb,
struct drm_pending_vblank_event *event,
- uint32_t flags)
+ uint32_t flags,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct vmw_private *dev_priv = vmw_priv(crtc->dev);
struct drm_framebuffer *old_fb = crtc->primary->fb;
@@ -323,7 +324,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
return -EINVAL;
flags &= ~DRM_MODE_PAGE_FLIP_ASYNC;
- ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags);
+ ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags, ctx);
if (ret) {
DRM_ERROR("Page flip error %d.\n", ret);
return ret;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index e872ffe5f0db..bad31bdf09b6 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -481,7 +481,8 @@ static void vmw_stdu_crtc_helper_disable(struct drm_crtc *crtc)
static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *new_fb,
struct drm_pending_vblank_event *event,
- uint32_t flags)
+ uint32_t flags,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct vmw_private *dev_priv = vmw_priv(crtc->dev);
@@ -504,7 +505,7 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
* don't hand it to the helper.
*/
flags &= ~DRM_MODE_PAGE_FLIP_ASYNC;
- ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags);
+ ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags, ctx);
if (ret) {
DRM_ERROR("Page flip error %d.\n", ret);
return ret;
diff --git a/drivers/gpu/drm/zte/zx_hdmi.c b/drivers/gpu/drm/zte/zx_hdmi.c
index c47b9cbfe270..0df7366e594b 100644
--- a/drivers/gpu/drm/zte/zx_hdmi.c
+++ b/drivers/gpu/drm/zte/zx_hdmi.c
@@ -50,7 +50,6 @@ struct zx_hdmi {
struct clk *xclk;
bool sink_is_hdmi;
bool sink_has_audio;
- const struct vou_inf *inf;
struct platform_device *audio_pdev;
};