]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge tag 'drm-misc-next-2017-03-31' of git://anongit.freedesktop.org/git/drm-misc...
authorDave Airlie <airlied@redhat.com>
Mon, 3 Apr 2017 06:30:24 +0000 (16:30 +1000)
committerDave Airlie <airlied@redhat.com>
Mon, 3 Apr 2017 06:30:24 +0000 (16:30 +1000)
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
  ...

101 files changed:
Documentation/EDID/edid.S
Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
Documentation/gpu/drm-uapi.rst
Documentation/gpu/introduction.rst
Documentation/gpu/kms-properties.csv
Documentation/gpu/todo.rst
Documentation/process/index.rst
MAINTAINERS
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
drivers/gpu/drm/armada/armada_crtc.c
drivers/gpu/drm/armada/armada_overlay.c
drivers/gpu/drm/bochs/bochs_fbdev.c
drivers/gpu/drm/bochs/bochs_kms.c
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
drivers/gpu/drm/bridge/ti-tfp410.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_debugfs.c
drivers/gpu/drm/drm_debugfs_crc.c
drivers/gpu/drm/drm_dp_mst_topology.c
drivers/gpu/drm/drm_fb_cma_helper.c
drivers/gpu/drm/drm_fourcc.c
drivers/gpu/drm/drm_framebuffer.c
drivers/gpu/drm/drm_internal.h
drivers/gpu/drm/drm_ioctl.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/drm_modeset_helper.c
drivers/gpu/drm/drm_plane.c
drivers/gpu/drm/drm_plane_helper.c
drivers/gpu/drm/drm_simple_kms_helper.c
drivers/gpu/drm/gma500/gma_display.c
drivers/gpu/drm/gma500/gma_display.h
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp_mst.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
drivers/gpu/drm/nouveau/dispnv04/crtc.c
drivers/gpu/drm/nouveau/dispnv04/overlay.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_display.h
drivers/gpu/drm/nouveau/nouveau_vga.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_dp_mst.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/rockchip/Kconfig
drivers/gpu/drm/rockchip/Makefile
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
drivers/gpu/drm/rockchip/cdn-dp-core.c
drivers/gpu/drm/rockchip/dw-mipi-dsi.c
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
drivers/gpu/drm/rockchip/inno_hdmi.c
drivers/gpu/drm/rockchip/rockchip_drm_drv.c
drivers/gpu/drm/rockchip/rockchip_drm_drv.h
drivers/gpu/drm/rockchip/rockchip_vop_reg.c
drivers/gpu/drm/shmobile/shmob_drm_crtc.c
drivers/gpu/drm/shmobile/shmob_drm_plane.c
drivers/gpu/drm/tegra/dc.c
drivers/gpu/drm/tilcdc/tilcdc_crtc.c
drivers/gpu/drm/tinydrm/core/tinydrm-core.c
drivers/gpu/drm/tinydrm/mi0283qt.c
drivers/gpu/drm/udl/udl_modeset.c
drivers/gpu/drm/vc4/vc4_crtc.c
drivers/gpu/drm/vc4/vc4_plane.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
drivers/gpu/drm/zte/zx_hdmi.c
drivers/pci/pci.h
drivers/pci/probe.c
drivers/platform/x86/apple-gmux.c
include/drm/drmP.h
include/drm/drm_atomic.h
include/drm/drm_atomic_helper.h
include/drm/drm_connector.h
include/drm/drm_crtc.h
include/drm/drm_crtc_helper.h
include/drm/drm_debugfs.h [new file with mode: 0644]
include/drm/drm_dp_mst_helper.h
include/drm/drm_drv.h
include/drm/drm_fourcc.h
include/drm/drm_global.h
include/drm/drm_hashtab.h
include/drm/drm_ioctl.h [new file with mode: 0644]
include/drm/drm_mode_config.h
include/drm/drm_of.h
include/drm/drm_pci.h
include/drm/drm_plane.h
include/drm/drm_plane_helper.h
include/drm/drm_prime.h
include/drm/drm_scdc_helper.h
include/drm/drm_simple_kms_helper.h
include/drm/drm_sysfs.h
include/drm/tinydrm/tinydrm.h
include/linux/pci.h

index 7ac03276d7a2363200f21b09135da008e8b02da9..ef082dcc6084d77df02aae964b157c016f6f1d7b 100644 (file)
@@ -59,9 +59,9 @@
 /* Fixed header pattern */
 header:                .byte   0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00
 
-mfg_id:                .word   swap16(mfgname2id(MFG_LNX1, MFG_LNX2, MFG_LNX3))
+mfg_id:                .hword  swap16(mfgname2id(MFG_LNX1, MFG_LNX2, MFG_LNX3))
 
-prod_code:     .word   0
+prod_code:     .hword  0
 
 /* Serial number. 32 bits, little endian. */
 serial_number: .long   SERIAL
@@ -177,7 +177,7 @@ std_vres:   .byte   (XY_RATIO<<6)+VFREQ-60
 
 descriptor1:
 /* Pixel clock in 10 kHz units. (0.-655.35 MHz, little-endian) */
-clock:         .word   CLOCK/10
+clock:         .hword  CLOCK/10
 
 /* Horizontal active pixels 8 lsbits (0-4095) */
 x_act_lsb:     .byte   XPIX&0xff
index 188f6f7403e6720d258e7fde119f618e76794c83..1d722f5055ab1a5c657a287b483f468a650fe772 100644 (file)
@@ -10,7 +10,7 @@ Required properties:
 - interrupts: Represent the controller's interrupt to the CPU(s).
 - clocks, clock-names: Phandles to the controller's pll reference
   clock(ref) and APB clock(pclk). For RK3399, a phy config clock
-  (phy_cfg) is additional required. As described in [1].
+  (phy_cfg) and a grf clock(grf) are required. As described in [1].
 - rockchip,grf: this soc should set GRF regs to mux vopl/vopb.
 - ports: contain a port node with endpoint definitions as defined in [2].
   For vopb,set the reg = <0> and set the reg = <1> for vopl.
index 352652810dab7c4cd8be7ca7f3eec23046a8b156..76356c86e358859e157adc9872cd9afe6cd0b666 100644 (file)
@@ -207,6 +207,18 @@ Display CRC Support
 .. kernel-doc:: drivers/gpu/drm/drm_debugfs_crc.c
    :doc: CRC ABI
 
+.. kernel-doc:: drivers/gpu/drm/drm_debugfs_crc.c
+   :export:
+
+Debugfs Support
+---------------
+
+.. kernel-doc:: include/drm/drm_debugfs.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_debugfs.c
+   :export:
+
 VBlank event handling
 =====================
 
index 1f8bd5ef5f9dbc40853f1f6fbdc8c5860c9cc729..05a82bdfbca4d195ca6b5cd675554d13804ce8fc 100644 (file)
@@ -60,3 +60,28 @@ checkpatch or sparse. We welcome such contributions.
 
 Anyone looking to kick it up a notch can find a list of janitorial tasks on
 the :ref:`TODO list <todo>`.
+
+Contribution Process
+====================
+
+Mostly the DRM subsystem works like any other kernel subsystem, see :ref:`the
+main process guidelines and documentation <process_index>` for how things work.
+Here we just document some of the specialities of the GPU subsystem.
+
+Feature Merge Deadlines
+-----------------------
+
+All feature work must be in the linux-next tree by the -rc6 release of the
+current release cycle, otherwise they must be postponed and can't reach the next
+merge window. All patches must have landed in the drm-next tree by latest -rc7,
+but if your branch is not in linux-next then this must have happened by -rc6
+already.
+
+After that point only bugfixes (like after the upstream merge window has closed
+with the -rc1 release) are allowed. No new platform enabling or new drivers are
+allowed.
+
+This means that there's a blackout-period of about one month where feature work
+can't be merged. The recommended way to deal with that is having a -next tree
+that's always open, but making sure to not feed it into linux-next during the
+blackout period. As an example, drm-misc works like that.
index 981873a05d14845a334ef767e5de6673132dac09..927b65e14219d57c01a1993670a9572ddb7f5570 100644 (file)
@@ -1,10 +1,5 @@
 Owner Module/Drivers,Group,Property Name,Type,Property Values,Object attached,Description/Restrictions
 ,,“scaling mode”,ENUM,"{ ""None"", ""Full"", ""Center"", ""Full aspect"" }",Connector,"Supported by: amdgpu, gma500, i915, nouveau and radeon."
-,Connector,“EDID”,BLOB | IMMUTABLE,0,Connector,Contains id of edid blob ptr object.
-,,“DPMS”,ENUM,"{ “On”, “Standby”, “Suspend”, “Off” }",Connector,Contains DPMS operation mode value.
-,,“PATH”,BLOB | IMMUTABLE,0,Connector,Contains topology path to a connector.
-,,“TILE”,BLOB | IMMUTABLE,0,Connector,Contains tiling information for a connector.
-,,“CRTC_ID”,OBJECT,DRM_MODE_OBJECT_CRTC,Connector,CRTC that connector is attached to (atomic)
 ,DVI-I,“subconnector”,ENUM,"{ “Unknown”, “DVI-D”, “DVI-A” }",Connector,TBD
 ,,“select subconnector”,ENUM,"{ “Automatic”, “DVI-D”, “DVI-A” }",Connector,TBD
 ,TV,“subconnector”,ENUM,"{ ""Unknown"", ""Composite"", ""SVIDEO"", ""Component"", ""SCART"" }",Connector,TBD
index 64e9d16170ce702399a1ad71e126dae30ba693b8..e255b36b34a3220f52dbd3935b0aa6f39927cd05 100644 (file)
@@ -99,6 +99,30 @@ events for atomic commits correctly. But fixing these bugs is good anyway.
 
 Contact: Daniel Vetter, respective driver maintainers
 
+Better manual-upload support for atomic
+---------------------------------------
+
+This would be especially useful for tinydrm:
+
+- Add a struct drm_rect dirty_clip to drm_crtc_state. When duplicating the
+  crtc state, clear that to the max values, x/y = 0 and w/h = MAX_INT, in
+  __drm_atomic_helper_crtc_duplicate_state().
+
+- Move tinydrm_merge_clips into drm_framebuffer.c, dropping the tinydrm_
+  prefix ofc and using drm_fb_. drm_framebuffer.c makes sense since this
+  is a function useful to implement the fb->dirty function.
+
+- Create a new drm_fb_dirty function which does essentially what e.g.
+  mipi_dbi_fb_dirty does. You can use e.g. drm_atomic_helper_update_plane as the
+  template. But instead of doing a simple full-screen plane update, this new
+  helper also sets crtc_state->dirty_clip to the right coordinates. And of
+  course it needs to check whether the fb is actually active (and maybe where),
+  so there's some book-keeping involved. There's also some good fun involved in
+  scaling things appropriately. For that case we might simply give up and
+  declare the entire area covered by the plane as dirty.
+
+Contact: Noralf Trønnes, Daniel Vetter
+
 Fallout from atomic KMS
 -----------------------
 
@@ -272,6 +296,32 @@ This is a really varied tasks with lots of little bits and pieces:
 
 Contact: Daniel Vetter
 
+Clean up the debugfs support
+----------------------------
+
+There's a bunch of issues with it:
+
+- The drm_info_list ->show() function doesn't even bother to cast to the drm
+  structure for you. This is lazy.
+
+- We probably want to have some support for debugfs files on crtc/connectors and
+  maybe other kms objects directly in core. There's even drm_print support in
+  the funcs for these objects to dump kms state, so it's all there. And then the
+  ->show() functions should obviously give you a pointer to the right object.
+
+- The drm_info_list stuff is centered on drm_minor instead of drm_device. For
+  anything we want to print drm_device (or maybe drm_file) is the right thing.
+
+- The drm_driver->debugfs_init hooks we have is just an artifact of the old
+  midlayered load sequence. DRM debugfs should work more like sysfs, where you
+  can create properties/files for an object anytime you want, and the core
+  takes care of publishing/unpuplishing all the files at register/unregister
+  time. Drivers shouldn't need to worry about these technicalities, and fixing
+  this (together with the drm_minor->drm_device move) would allow us to remove
+  debugfs_init.
+
+Contact: Daniel Vetter
+
 Better Testing
 ==============
 
@@ -310,6 +360,52 @@ Contact: Daniel Vetter
 Driver Specific
 ===============
 
+tinydrm
+-------
+
+Tinydrm is the helper driver for really simple fb drivers. The goal is to make
+those drivers as simple as possible, so lots of room for refactoring:
+
+- backlight helpers, probably best to put them into a new drm_backlight.c.
+  This is because drivers/video is de-facto unmaintained. We could also
+  move drivers/video/backlight to drivers/gpu/backlight and take it all
+  over within drm-misc, but that's more work.
+
+- spi helpers, probably best put into spi core/helper code. Thierry said
+  the spi maintainer is fast&reactive, so shouldn't be a big issue.
+
+- extract the mipi-dbi helper (well, the non-tinydrm specific parts at
+  least) into a separate helper, like we have for mipi-dsi already. Or follow
+  one of the ideas for having a shared dsi/dbi helper, abstracting away the
+  transport details more.
+
+- tinydrm_lastclose could be drm_fb_helper_lastclose. Only thing we need
+  for that is to store the drm_fb_helper pointer somewhere in
+  drm_device->mode_config. And then we could roll that out to all the
+  drivers.
+
+- tinydrm_gem_cma_prime_import_sg_table should probably go into the cma
+  helpers, as a _vmapped variant (since not every driver needs the vmap).
+  And tinydrm_gem_cma_free_object could the be merged into
+  drm_gem_cma_free_object().
+
+- tinydrm_fb_create we could move into drm_simple_pipe, only need to add
+  the fb_create hook to drm_simple_pipe_funcs, which would again simplify a
+  bunch of things (since it gives you a one-stop vfunc for simple drivers).
+
+- Quick aside: The unregister devm stuff is kinda getting the lifetimes of
+  a drm_device wrong. Doesn't matter, since everyone else gets it wrong
+  too :-)
+
+- With the fbdev pointer in dev->mode_config we could also make
+  suspend/resume helpers entirely generic, at least if we add a
+  dev->mode_config.suspend_state. We could even provide a generic pm_ops
+  structure with those.
+
+- also rework the drm_framebuffer_funcs->dirty hook wire-up, see above.
+
+Contact: Noralf Trønnes, Daniel Vetter
+
 Outside DRM
 ===========
 
index 10aa6920709a462789278f670eee8f8ea68cbc0c..82fc399fcd33d1628289ec5ccfeb3193a368c2fc 100644 (file)
@@ -3,6 +3,7 @@
        \renewcommand\thesection*
        \renewcommand\thesubsection*
 
+.. _process_index:
 
 Working with the kernel development community
 =============================================
index be86eee3353f1d36872afa40db3f2697e9ec522c..fa8479e1799ab37cdf754866649979e70c1650b5 100644 (file)
@@ -4145,6 +4145,7 @@ F:        Documentation/devicetree/bindings/video/
 F:     Documentation/gpu/
 F:     include/drm/
 F:     include/uapi/drm/
+F:     include/linux/vga*
 
 DRM DRIVERS AND MISC GPU PATCHES
 M:     Daniel Vetter <daniel.vetter@intel.com>
@@ -4158,6 +4159,7 @@ F:        drivers/gpu/vga/
 F:     drivers/gpu/drm/*
 F:     include/drm/drm*
 F:     include/uapi/drm/drm*
+F:     include/linux/vga*
 
 DRM DRIVER FOR AST SERVER GRAPHICS CHIPS
 M:     Dave Airlie <airlied@redhat.com>
@@ -13257,6 +13259,14 @@ L:     kvm@vger.kernel.org
 S:     Maintained
 F:     drivers/vfio/platform/
 
+VGA_SWITCHEROO
+R:     Lukas Wunner <lukas@wunner.de>
+S:     Maintained
+F:     Documentation/gpu/vga-switcheroo.rst
+F:     drivers/gpu/vga/vga_switcheroo.c
+F:     include/linux/vga_switcheroo.h
+T:     git git://anongit.freedesktop.org/drm/drm-misc
+
 VIDEOBUF2 FRAMEWORK
 M:     Pawel Osciak <pawel@osciak.com>
 M:     Marek Szyprowski <m.szyprowski@samsung.com>
index 93061a439dbc1a25a12e70c229513dc00438e54a..83dda05325b856312d5aa6e3134dff57167ef24b 100644 (file)
@@ -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);
index 39fc388f222ac61966eb7199e6727f913c745dd3..ce15721caddab9dcd622de06294da70f80ff10f8 100644 (file)
@@ -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)
index 5ded370a4b35c428887b4a5a3d90bac216ec9c42..dfb029ab34483988ace5ee1427a254e9abfba767 100644 (file)
@@ -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
index c12497bd38895e5668351fb689524fb24524ec35..db8f8dda209c7880b0ede9e79268a7c9726b3b5c 100644 (file)
@@ -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,
index 1341e0b9368a4f796afcb654284e9043b9d7cfd0..4fe19fde84f9624dbae3bdbc062e282401f617c7 100644 (file)
@@ -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;
index 34cb73d0db77b2ab7cb06e26942b40091338da6b..424e465ff407e5cc3e131b0f9e08efa94807c2f9 100644 (file)
@@ -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;
index 471bd588550bc6e76325dfeac47e5904b2d2c7b8..c38deffa14de24054711ab96d28fbe30a17c8f35 100644 (file)
@@ -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;
 }
index d5e63eff357b08bb6fcf4b5abb693e64d3c16366..6a91e62da2f4aee18e423b90076bbfcbd51d1e05 100644 (file)
@@ -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);
index af93f7a20697a577e2998b66419ac7e56726c94d..32f02e92e0b93c72b35000b51bc5cc7114534a18 100644 (file)
@@ -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.
index b379d046991b3eaea962b67de754c86b530084cc..7d519b46aee4ff96d7844af8c9ee6d2a5b84b8a8 100644 (file)
@@ -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>
 #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;
 }
index 4e26b73bb0d548a85a522dd465a590f71a02a377..c3994b4d5f324702afbc06e4da10f76d93438fac 100644 (file)
@@ -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)
@@ -2516,6 +2463,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);
 
index e2974d3c92e7870cd25617eb904ad584af425776..d69e180fc563c9b61fa3615c53bfee9f8a3098eb 100644 (file)
@@ -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;
 }
 
index 8aa8c10841217445117e34e49c423c878e76237d..4afdf7902eda7d4a50c2ac0bacb30ca40ec3f31d 100644 (file)
@@ -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;
index 1d2d18d82d2e52d6562ebdf534bd4c45cd887b72..c1807d5754b2a865c39a6540f5911a524014dbc3 100644 (file)
@@ -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
  *
 #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)
index 96891c4a6e23b200874afc6b92930d587219ea9f..1722d8f214499794d5304dc7e9597bfcd0dadd6b 100644 (file)
@@ -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.
  * 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;
index f2cc375907d0caddd50e1de18a104ac0cf8c07f2..d3fc7e4e85b7413eb586256540467cbd25f6090d 100644 (file)
@@ -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;
index 74cd393a640778b69262b3a7f81443bc389e9edb..50abd1faf38f08681673cc09f2b290c6cf0d1aa3 100644 (file)
@@ -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);
 
index 92bf3306d4b3232f7d0962c17bcb6768f361ca44..9c0152df45adbee02432d51948eeed29df4900cb 100644 (file)
@@ -206,6 +206,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_*)
index e4909aef75d73cb7e430a14782169ea932c438b2..e8f9c13a0afd90cb2880f03ea057d4ea4a9ce406 100644 (file)
@@ -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);
index 92ff4b9393b17f95b3f2ef8a659c42d219029693..3d8e8f878924d6213681916ea51b37baf7fe0954 100644 (file)
@@ -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);
index a7c61c23685a618caf888461c0c2492338ba7534..7d6deaa91281c6f94ca9eb52a7ba404210493505 100644 (file)
@@ -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"
index 53a526c7b24dcab0ad0a9e9f4302c9fc9803581f..dac1b2593cb15324372164ab70f2855e67cb5979 100644 (file)
@@ -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);
index cc44a9a4b004076e660154d7966f78ca2287d80d..2b33825f2f93138066b3593289bd076ad9f43409 100644 (file)
@@ -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++) {
index a22e76837065a04f64e67654da3c6419e8066508..bc71aa2b78728d1c241682ce9eee852faafade13 100644 (file)
@@ -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;
 }
index de1ac5e08f4d160b4e49739ee7a16eef3c9b1936..b84a295230fcd4ba7f7493a53d219e5c2ae93d4b 100644 (file)
@@ -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;
 }
index 16789faa9291f5b51a5dfe6f5f96eb7819b78155..e084f9f8ca666c168e1df7e7108abdb1cc39744b 100644 (file)
@@ -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,
index d1c5642b1c1e3d3bc21d48f025af3083aac80d7b..93ff46535c046bb0bb698af909a68481033574ab 100644 (file)
@@ -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;
index e72dd08b701bb7830005e371cbc424b5b3ab37cc..166e608923dbd589077f993432d6daa0499d0d25 100644 (file)
@@ -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);
index 03d9e45694c9739b97d8ff1cdace5664af75d521..98b17070a12388aae54fc4bc057eb9dd154a2baf 100644 (file)
@@ -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);
 
index 010e5ddb198adad2db7527385b4d5cd4c0773e0b..e27ea89efd6788b47087467c29b0f991ae8d2ffd 100644 (file)
@@ -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 = {
index 094cbdcbcd6dd4e4c44a009b7d697caae6a17146..c1f62eb07c07a7ce49b3ed39e1e6ee2b23eb65e8 100644 (file)
@@ -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;
index 0ffb8affef35848b458b77ce145478e7a9638a2b..60a5451ae0b9caeaaccae0c9066585e232752f0a 100644 (file)
@@ -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)
index ab7b69c11d40fab09c710c9a3cde981aa9863990..43ab560de7f98884a4c5f018805093b9af69f7d6 100644 (file)
@@ -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);
 
index 5319f2a7f24d28aeed7c2100321518ad660fd6d1..e54944d2326863f8260314c0dd0fcfc019d04003 100644 (file)
@@ -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);
index 33269c7df30f17b50097bf91d7259fe91ba6914b..6104f61b00fcb02d6cb18b68dba54dcea3f16045 100644 (file)
@@ -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;
index 4a75df06c139cf9a7e815b6523c69d7f9ede91c9..e1d772d394887eb91cbc09672169ccd7becf2393 100644 (file)
@@ -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 *);
index ccb597eac53865287599d5eff2e39dd9563a6723..a4aacbc0cec8efe603d18152099aaecdeab93dce 100644 (file)
@@ -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);
 }
 
 
index 7ad1ee580cf097de5d52bbde95a93ff970698d9e..418872b493a396221927f33ab7bd299586421607 100644 (file)
@@ -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)
index 64b02f3c79065d5137cbbed1ccd58c5f67a815f2..6ecf42783d4b0c45539325edd2e5ffd2fc08e29f 100644 (file)
@@ -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);
index aea8b62835a4ad91b23d906c267e3c7b12432033..146297a702ab0fe95752fa72e581f86c1d917954 100644 (file)
@@ -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)
index 7d5ada3980dc80d012813078b161f371557002c5..6598306dca9b87b5a508e921c7e008e9ec43167a 100644 (file)
@@ -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,
index a32a62e03a44791fa1d6ecc18a7510ea186497b6..e3e7cb1d10a2941d1790d36a9f5250f70aeb78cd 100644 (file)
@@ -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
index 0e4eb845cbb0f5911a9e89bd2346cf62f006c4af..50c41c0a50ef3f989553bc091193b57288a28914 100644 (file)
@@ -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
index c931e2a7d8de34bcdcf4bc70b7f09b41f158c536..fa8dc9d9aac28dfdf546bd84cbc0b54f723b4121 100644 (file)
@@ -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
index 8548e8271639c665be80420dc7e77905ded5cf9a..91ebe5c2c7a02bf9975ff1e7ad4ef694dd3e3b55 100644 (file)
@@ -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");
index 9edb8dc1ea14404a515a3ecc87a379feb02886b2..4e55d63c3ef381debc17b6bb7f7570e7f19ed57f 100644 (file)
@@ -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");
index f84f9ae2fd35047a9b17fd6a38b1853e70e7b68d..21b9737662ae9a23e2f7496dce59172a303d2f38 100644 (file)
@@ -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)
 
 #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);
index d53827413996aaee0bc3180b1ac2a1350768ab35..63dab6f1b1911bb9293099fbb40f85082060d8ab 100644 (file)
@@ -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");
index 006260de9dbd22a0be6fda85e1c17ec8a04f1b44..7d9b75eb6c44ad0a3262e1a85feeb87213ad952d 100644 (file)
@@ -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");
index ccf45693879260f6e4aee57f331bab0048635990..cd7d02e1f758f1d48dcf3b47bb06e8084d943f4d 100644 (file)
@@ -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");
index 8aca219ec4c8f822e193e6e4a872ae9c0c848e05..a48fcce3f5f65edb70ca216583a87c7a1ae5a11c 100644 (file)
@@ -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_ */
index 91fbc7b521477a7afd0795a5f45498b677463137..0da44442aab097b8f4b40d67c8995be625bccfcd 100644 (file)
@@ -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");
index 5fcabc04f307101169c99f65b2c66453e03a31ce..e7738939a86dc9f3f8b9c21825f79536f233beb2 100644 (file)
@@ -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;
index 2023a93cee2b40a925a9463588ce5f4c1268c579..97f6e4a3eb0de0e86634cb4c4d9d3c2501b5dfab 100644 (file)
@@ -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);
 }
 
index 0db5d5a8d3b980fd5d62e85d4801e8b82da0232a..95b373f739f20c1c98e0bf2788d8265759f320ca 100644 (file)
@@ -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;
 }
 
index c92faa8f7560dd0bdf3c6574d4f739f46759733d..afd2a7b2aff72db22191fef86f0f51afbb090ce8 100644 (file)
@@ -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
index 6a257dd08ee03b7326930b6aa2b7c99d579fe1ef..551709e6b11449d2086b98966979f54991b570c6 100644 (file)
@@ -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);
 
index b29fe86158f7a672cabac47f2a0c81fc148b5720..482ff1c3db61b58e50848eec4eeee3519ac1f26c 100644 (file)
@@ -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,
index f2b2481cad525785868444002289803c42e1ab64..5bcae76497959bf3a14ba483df525eb052dd6300 100644 (file)
@@ -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;
index 24edd0c22cc9b6094395e213e6cceeafa17c0678..865e9f494bcc52d32e86ccc43cefc125452c43a7 100644 (file)
@@ -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)
index 0f4564beb0179a1f9126389435eab09ab2f1a487..d34cd5393a9b021f851fab8b16b042e84e99f6c4 100644 (file)
@@ -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 = {
index c18c81f63ac360b527fac5d748916b4efb80dd66..6078654d033b5af1f3be338ca1fa4fde9c9226d6 100644 (file)
@@ -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);
 }
index 9c161d29aaeb7d54651e0ed856d6e01bd874039f..0c226b2adea5e34f4007fad71395dcdae9b8e2ed 100644 (file)
@@ -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
index 2664e4c1675055457a1620503ecc7b5d09c8f94c..8d7dc9def7c20ba5fe101dd55e5612e4f9e5d631 100644 (file)
@@ -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;
index e872ffe5f0dbb9026d2103b24495abbc3b3550bd..bad31bdf09b6c1d8bd31663c7973e1ebb912f340 100644 (file)
@@ -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;
index c47b9cbfe270a3f28b72d65e21d0474a76aebfae..0df7366e594b32d8d732987727f0bc2f60f60325 100644 (file)
@@ -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;
 };
 
index 8dd38e69d6f2a8ae4f4b7d6801f3f321abb5ac1a..4dbf9f96ae5ba31d761b30ee43c11d2f053140fe 100644 (file)
@@ -3,6 +3,8 @@
 
 #define PCI_FIND_CAP_TTL       48
 
+#define PCI_VSEC_ID_INTEL_TBT  0x1234  /* Thunderbolt */
+
 extern const unsigned char pcie_link_speed[];
 
 bool pcie_cap_has_lnkctl(const struct pci_dev *dev);
index dfc9a27941418976c0fadee7e6628531fbb47613..90592d424e9b67458ad740ddb3b09d50f5ec30ff 100644 (file)
@@ -1208,6 +1208,24 @@ void set_pcie_hotplug_bridge(struct pci_dev *pdev)
                pdev->is_hotplug_bridge = 1;
 }
 
+static void set_pcie_thunderbolt(struct pci_dev *dev)
+{
+       int vsec = 0;
+       u32 header;
+
+       while ((vsec = pci_find_next_ext_capability(dev, vsec,
+                                                   PCI_EXT_CAP_ID_VNDR))) {
+               pci_read_config_dword(dev, vsec + PCI_VNDR_HEADER, &header);
+
+               /* Is the device part of a Thunderbolt controller? */
+               if (dev->vendor == PCI_VENDOR_ID_INTEL &&
+                   PCI_VNDR_HEADER_ID(header) == PCI_VSEC_ID_INTEL_TBT) {
+                       dev->is_thunderbolt = 1;
+                       return;
+               }
+       }
+}
+
 /**
  * pci_ext_cfg_is_aliased - is ext config space just an alias of std config?
  * @dev: PCI device
@@ -1360,6 +1378,9 @@ int pci_setup_device(struct pci_dev *dev)
        /* need to have dev->class ready */
        dev->cfg_size = pci_cfg_space_size(dev);
 
+       /* need to have dev->cfg_size ready */
+       set_pcie_thunderbolt(dev);
+
        /* "Unknown power state" */
        dev->current_state = PCI_UNKNOWN;
 
index a66be137324c096a3a6b0f1e5fba18a3c4993f1b..623d322447a2192fcfba9e0041ddbe76080b30bb 100644 (file)
@@ -60,6 +60,7 @@ struct apple_gmux_data {
        /* switcheroo data */
        acpi_handle dhandle;
        int gpe;
+       bool external_switchable;
        enum vga_switcheroo_client_id switch_state_display;
        enum vga_switcheroo_client_id switch_state_ddc;
        enum vga_switcheroo_client_id switch_state_external;
@@ -358,6 +359,19 @@ static const struct backlight_ops gmux_bl_ops = {
  * ports while the discrete GPU is asleep, but currently we do not make use
  * of this feature.
  *
+ * Our switching policy for the external port is that on those generations
+ * which are able to switch it fully, the port is switched together with the
+ * panel when IGD / DIS commands are issued to vga_switcheroo. It is thus
+ * possible to drive e.g. a beamer on battery power with the integrated GPU.
+ * The user may manually switch to the discrete GPU if more performance is
+ * needed.
+ *
+ * On all newer generations, the external port can only be driven by the
+ * discrete GPU. If a display is plugged in while the panel is switched to
+ * the integrated GPU, *both* GPUs will be in use for maximum performance.
+ * To decrease power consumption, the user may manually switch to the
+ * discrete GPU, thereby suspending the integrated GPU.
+ *
  * gmux' initial switch state on bootup is user configurable via the EFI
  * variable ``gpu-power-prefs-fa4ce28d-b62f-4c99-9cc3-6815686e30f9`` (5th byte,
  * 1 = IGD, 0 = DIS). Based on this setting, the EFI firmware tells gmux to
@@ -414,7 +428,8 @@ static int gmux_switchto(enum vga_switcheroo_client_id id)
 {
        apple_gmux_data->switch_state_ddc = id;
        apple_gmux_data->switch_state_display = id;
-       apple_gmux_data->switch_state_external = id;
+       if (apple_gmux_data->external_switchable)
+               apple_gmux_data->switch_state_external = id;
 
        gmux_write_switch_state(apple_gmux_data);
 
@@ -601,6 +616,11 @@ static struct pci_dev *gmux_get_io_pdev(void)
        return NULL;
 }
 
+static int is_thunderbolt(struct device *dev, void *data)
+{
+       return to_pci_dev(dev)->is_thunderbolt;
+}
+
 static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
 {
        struct apple_gmux_data *gmux_data;
@@ -755,6 +775,15 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
                gmux_data->gpe = -1;
        }
 
+       /*
+        * If Thunderbolt is present, the external DP port is not fully
+        * switchable. Force its AUX channel to the discrete GPU.
+        */
+       gmux_data->external_switchable =
+               !bus_for_each_dev(&pci_bus_type, NULL, NULL, is_thunderbolt);
+       if (!gmux_data->external_switchable)
+               gmux_write8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3);
+
        apple_gmux_data = gmux_data;
        init_completion(&gmux_data->powerchange_done);
        gmux_enable_interrupts(gmux_data);
index 0e383438f79326095edbc5b2d5eaf80642dedd47..3bfafcdb8710a996d38522bc9d90ff3f92c5404f 100644 (file)
@@ -78,6 +78,8 @@
 #include <drm/drm_prime.h>
 #include <drm/drm_pci.h>
 #include <drm/drm_file.h>
+#include <drm/drm_debugfs.h>
+#include <drm/drm_ioctl.h>
 
 struct module;
 
@@ -316,81 +318,16 @@ struct pci_controller;
 
 #define DRM_IF_VERSION(maj, min) (maj << 16 | min)
 
-/**
- * Ioctl function type.
- *
- * \param inode device inode.
- * \param file_priv DRM file private pointer.
- * \param cmd command.
- * \param arg argument.
- */
-typedef int drm_ioctl_t(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv);
-
-typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
-                              unsigned long arg);
-
-#define DRM_IOCTL_NR(n)                _IOC_NR(n)
-#define DRM_MAJOR       226
-
-#define DRM_AUTH       0x1
-#define        DRM_MASTER      0x2
-#define DRM_ROOT_ONLY  0x4
-#define DRM_CONTROL_ALLOW 0x8
-#define DRM_UNLOCKED   0x10
-#define DRM_RENDER_ALLOW 0x20
-
-struct drm_ioctl_desc {
-       unsigned int cmd;
-       int flags;
-       drm_ioctl_t *func;
-       const char *name;
-};
-
-/**
- * Creates a driver or general drm_ioctl_desc array entry for the given
- * ioctl, for use by drm_ioctl().
- */
-
-#define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags)                                \
-       [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = {        \
-               .cmd = DRM_IOCTL_##ioctl,                               \
-               .func = _func,                                          \
-               .flags = _flags,                                        \
-               .name = #ioctl                                          \
-        }
 
 /* Flags and return codes for get_vblank_timestamp() driver function. */
 #define DRM_CALLED_FROM_VBLIRQ 1
 #define DRM_VBLANKTIME_SCANOUTPOS_METHOD (1 << 0)
-#define DRM_VBLANKTIME_IN_VBLANK         (1 << 1)
 
 /* get_scanout_position() return flags */
 #define DRM_SCANOUTPOS_VALID        (1 << 0)
 #define DRM_SCANOUTPOS_IN_VBLANK    (1 << 1)
 #define DRM_SCANOUTPOS_ACCURATE     (1 << 2)
 
-/**
- * Info file list entry. This structure represents a debugfs or proc file to
- * be created by the drm core
- */
-struct drm_info_list {
-       const char *name; /** file name */
-       int (*show)(struct seq_file*, void*); /** show callback */
-       u32 driver_features; /**< Required driver features for this entry */
-       void *data;
-};
-
-/**
- * debugfs node structure. This structure represents a debugfs file.
- */
-struct drm_info_node {
-       struct list_head list;
-       struct drm_minor *minor;
-       const struct drm_info_list *info_ent;
-       struct dentry *dent;
-};
-
 /**
  * DRM device structure. This structure represent a complete card that
  * may contain multiple heads.
@@ -569,51 +506,12 @@ static inline int drm_device_is_unplugged(struct drm_device *dev)
 /*@{*/
 
                                /* Driver support (drm_drv.h) */
-extern int drm_ioctl_permit(u32 flags, struct drm_file *file_priv);
-extern long drm_ioctl(struct file *filp,
-                     unsigned int cmd, unsigned long arg);
-#ifdef CONFIG_COMPAT
-extern long drm_compat_ioctl(struct file *filp,
-                            unsigned int cmd, unsigned long arg);
-#else
-/* Let drm_compat_ioctl be assigned to .compat_ioctl unconditionally */
-#define drm_compat_ioctl NULL
-#endif
-extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags);
-
-/* Misc. IOCTL support (drm_ioctl.c) */
-int drm_noop(struct drm_device *dev, void *data,
-            struct drm_file *file_priv);
-int drm_invalid_op(struct drm_device *dev, void *data,
-                  struct drm_file *file_priv);
 
 /*
  * These are exported to drivers so that they can implement fencing using
  * DMA quiscent + idle. DMA quiescent usually requires the hardware lock.
  */
 
-                               /* Debugfs support */
-#if defined(CONFIG_DEBUG_FS)
-extern int drm_debugfs_create_files(const struct drm_info_list *files,
-                                   int count, struct dentry *root,
-                                   struct drm_minor *minor);
-extern int drm_debugfs_remove_files(const struct drm_info_list *files,
-                                   int count, struct drm_minor *minor);
-#else
-static inline int drm_debugfs_create_files(const struct drm_info_list *files,
-                                          int count, struct dentry *root,
-                                          struct drm_minor *minor)
-{
-       return 0;
-}
-
-static inline int drm_debugfs_remove_files(const struct drm_info_list *files,
-                                          int count, struct drm_minor *minor)
-{
-       return 0;
-}
-#endif
-
                               /* sysfs support (drm_sysfs.c) */
 extern void drm_sysfs_hotplug_event(struct drm_device *dev);
 
index 0147a047878d08657977fb47e6ed5508763108c9..fd33ed5eaeb4b031818b5a3a1ed466803fa5fdc7 100644 (file)
@@ -498,6 +498,23 @@ int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state);
 
 void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
 
+/**
+ * for_each_connector_in_state - iterate over all connectors in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @connector: &struct drm_connector iteration cursor
+ * @connector_state: &struct drm_connector_state iteration cursor
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all connectors in an atomic update. Note that before the
+ * software state is committed (by calling drm_atomic_helper_swap_state(), this
+ * points to the new state, while afterwards it points to the old state. Due to
+ * this tricky confusion this macro is deprecated.
+ *
+ * FIXME:
+ *
+ * Replace all usage of this with one of the explicit iterators below and then
+ * remove this macro.
+ */
 #define for_each_connector_in_state(__state, connector, connector_state, __i) \
        for ((__i) = 0;                                                 \
             (__i) < (__state)->num_connector &&                                \
@@ -506,6 +523,20 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
             (__i)++)                                                   \
                for_each_if (connector)
 
+/**
+ * for_each_oldnew_connector_in_state - iterate over all connectors in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @connector: &struct drm_connector iteration cursor
+ * @old_connector_state: &struct drm_connector_state iteration cursor for the
+ *     old state
+ * @new_connector_state: &struct drm_connector_state iteration cursor for the
+ *     new state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all connectors in an atomic update, tracking both old and
+ * new state. This is useful in places where the state delta needs to be
+ * considered, for example in atomic check functions.
+ */
 #define for_each_oldnew_connector_in_state(__state, connector, old_connector_state, new_connector_state, __i) \
        for ((__i) = 0;                                                         \
             (__i) < (__state)->num_connector &&                                \
@@ -515,6 +546,18 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
             (__i)++)                                                   \
                for_each_if (connector)
 
+/**
+ * for_each_old_connector_in_state - iterate over all connectors in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @connector: &struct drm_connector iteration cursor
+ * @old_connector_state: &struct drm_connector_state iteration cursor for the
+ *     old state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all connectors in an atomic update, tracking only the old
+ * state. This is useful in disable functions, where we need the old state the
+ * hardware is still in.
+ */
 #define for_each_old_connector_in_state(__state, connector, old_connector_state, __i) \
        for ((__i) = 0;                                                         \
             (__i) < (__state)->num_connector &&                                \
@@ -523,6 +566,18 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
             (__i)++)                                                   \
                for_each_if (connector)
 
+/**
+ * for_each_new_connector_in_state - iterate over all connectors in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @connector: &struct drm_connector iteration cursor
+ * @new_connector_state: &struct drm_connector_state iteration cursor for the
+ *     new state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all connectors in an atomic update, tracking only the new
+ * state. This is useful in enable functions, where we need the new state the
+ * hardware should be in when the atomic commit operation has completed.
+ */
 #define for_each_new_connector_in_state(__state, connector, new_connector_state, __i) \
        for ((__i) = 0;                                                         \
             (__i) < (__state)->num_connector &&                                \
@@ -531,6 +586,23 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
             (__i)++)                                                   \
                for_each_if (connector)
 
+/**
+ * for_each_crtc_in_state - iterate over all connectors in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @crtc: &struct drm_crtc iteration cursor
+ * @crtc_state: &struct drm_crtc_state iteration cursor
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all CRTCs in an atomic update. Note that before the
+ * software state is committed (by calling drm_atomic_helper_swap_state(), this
+ * points to the new state, while afterwards it points to the old state. Due to
+ * this tricky confusion this macro is deprecated.
+ *
+ * FIXME:
+ *
+ * Replace all usage of this with one of the explicit iterators below and then
+ * remove this macro.
+ */
 #define for_each_crtc_in_state(__state, crtc, crtc_state, __i) \
        for ((__i) = 0;                                         \
             (__i) < (__state)->dev->mode_config.num_crtc &&    \
@@ -539,6 +611,18 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
             (__i)++)                                           \
                for_each_if (crtc_state)
 
+/**
+ * for_each_oldnew_crtc_in_state - iterate over all CRTCs in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @crtc: &struct drm_crtc iteration cursor
+ * @old_crtc_state: &struct drm_crtc_state iteration cursor for the old state
+ * @new_crtc_state: &struct drm_crtc_state iteration cursor for the new state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all CRTCs in an atomic update, tracking both old and
+ * new state. This is useful in places where the state delta needs to be
+ * considered, for example in atomic check functions.
+ */
 #define for_each_oldnew_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state, __i) \
        for ((__i) = 0;                                                 \
             (__i) < (__state)->dev->mode_config.num_crtc &&            \
@@ -548,6 +632,17 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
             (__i)++)                                                   \
                for_each_if (crtc)
 
+/**
+ * for_each_old_crtc_in_state - iterate over all CRTCs in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @crtc: &struct drm_crtc iteration cursor
+ * @old_crtc_state: &struct drm_crtc_state iteration cursor for the old state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all CRTCs in an atomic update, tracking only the old
+ * state. This is useful in disable functions, where we need the old state the
+ * hardware is still in.
+ */
 #define for_each_old_crtc_in_state(__state, crtc, old_crtc_state, __i) \
        for ((__i) = 0;                                                 \
             (__i) < (__state)->dev->mode_config.num_crtc &&            \
@@ -556,6 +651,17 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
             (__i)++)                                                   \
                for_each_if (crtc)
 
+/**
+ * for_each_new_crtc_in_state - iterate over all CRTCs in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @crtc: &struct drm_crtc iteration cursor
+ * @new_crtc_state: &struct drm_crtc_state iteration cursor for the new state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all CRTCs in an atomic update, tracking only the new
+ * state. This is useful in enable functions, where we need the new state the
+ * hardware should be in when the atomic commit operation has completed.
+ */
 #define for_each_new_crtc_in_state(__state, crtc, new_crtc_state, __i) \
        for ((__i) = 0;                                                 \
             (__i) < (__state)->dev->mode_config.num_crtc &&            \
@@ -564,6 +670,23 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
             (__i)++)                                                   \
                for_each_if (crtc)
 
+/**
+ * for_each_plane_in_state - iterate over all planes in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @plane: &struct drm_plane iteration cursor
+ * @plane_state: &struct drm_plane_state iteration cursor
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all planes in an atomic update. Note that before the
+ * software state is committed (by calling drm_atomic_helper_swap_state(), this
+ * points to the new state, while afterwards it points to the old state. Due to
+ * this tricky confusion this macro is deprecated.
+ *
+ * FIXME:
+ *
+ * Replace all usage of this with one of the explicit iterators below and then
+ * remove this macro.
+ */
 #define for_each_plane_in_state(__state, plane, plane_state, __i)              \
        for ((__i) = 0;                                                 \
             (__i) < (__state)->dev->mode_config.num_total_plane &&     \
@@ -572,6 +695,18 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
             (__i)++)                                                   \
                for_each_if (plane_state)
 
+/**
+ * for_each_oldnew_plane_in_state - iterate over all planes in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @plane: &struct drm_plane iteration cursor
+ * @old_plane_state: &struct drm_plane_state iteration cursor for the old state
+ * @new_plane_state: &struct drm_plane_state iteration cursor for the new state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all planes in an atomic update, tracking both old and
+ * new state. This is useful in places where the state delta needs to be
+ * considered, for example in atomic check functions.
+ */
 #define for_each_oldnew_plane_in_state(__state, plane, old_plane_state, new_plane_state, __i) \
        for ((__i) = 0;                                                 \
             (__i) < (__state)->dev->mode_config.num_total_plane &&     \
@@ -581,6 +716,17 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
             (__i)++)                                                   \
                for_each_if (plane)
 
+/**
+ * for_each_old_plane_in_state - iterate over all planes in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @plane: &struct drm_plane iteration cursor
+ * @old_plane_state: &struct drm_plane_state iteration cursor for the old state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all planes in an atomic update, tracking only the old
+ * state. This is useful in disable functions, where we need the old state the
+ * hardware is still in.
+ */
 #define for_each_old_plane_in_state(__state, plane, old_plane_state, __i) \
        for ((__i) = 0;                                                 \
             (__i) < (__state)->dev->mode_config.num_total_plane &&     \
@@ -589,6 +735,17 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
             (__i)++)                                                   \
                for_each_if (plane)
 
+/**
+ * for_each_new_plane_in_state - iterate over all planes in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @plane: &struct drm_plane iteration cursor
+ * @new_plane_state: &struct drm_plane_state iteration cursor for the new state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all planes in an atomic update, tracking only the new
+ * state. This is useful in enable functions, where we need the new state the
+ * hardware should be in when the atomic commit operation has completed.
+ */
 #define for_each_new_plane_in_state(__state, plane, new_plane_state, __i) \
        for ((__i) = 0;                                                 \
             (__i) < (__state)->dev->mode_config.num_total_plane &&     \
@@ -603,7 +760,7 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
  *
  * To give drivers flexibility &struct drm_crtc_state has 3 booleans to track
  * whether the state CRTC changed enough to need a full modeset cycle:
- * connectors_changed, mode_changed and active_changed. This helper simply
+ * planes_changed, mode_changed and active_changed. This helper simply
  * combines these three to compute the overall need for a modeset for @state.
  *
  * The atomic helper code sets these booleans, but drivers can and should
index dc16274987c753d7820894ede77ba6e225426a59..fd395dc050ee36c56b38ff4e26ac30cffa988b14 100644 (file)
@@ -94,16 +94,20 @@ 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);
-int drm_atomic_helper_disable_plane(struct drm_plane *plane);
+                                  uint32_t src_w, uint32_t src_h,
+                                  struct drm_modeset_acquire_ctx *ctx);
+int drm_atomic_helper_disable_plane(struct drm_plane *plane,
+                                   struct drm_modeset_acquire_ctx *ctx);
 int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
                struct drm_plane_state *plane_state);
-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);
 int __drm_atomic_helper_set_config(struct drm_mode_set *set,
                struct drm_atomic_state *state);
 
 int drm_atomic_helper_disable_all(struct drm_device *dev,
                                  struct drm_modeset_acquire_ctx *ctx);
+void drm_atomic_helper_shutdown(struct drm_device *dev);
 struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev);
 int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
                                              struct drm_modeset_acquire_ctx *ctx);
@@ -122,13 +126,15 @@ int drm_atomic_helper_connector_set_property(struct drm_connector *connector,
 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);
 int drm_atomic_helper_page_flip_target(
                                struct drm_crtc *crtc,
                                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);
 int drm_atomic_helper_connector_dpms(struct drm_connector *connector,
                                     int mode);
 struct drm_encoder *
index f8b766d70a46390c57c58e28328acc8dafe6e004..941f57f311aa2221bea207958225e4e1e894a358 100644 (file)
@@ -133,6 +133,7 @@ struct drm_scdc {
  * This information is available in CEA-861-F extension blocks (like HF-VSDB).
  */
 struct drm_hdmi_info {
+       /** @scdc: sink's scdc support and capabilities */
        struct drm_scdc scdc;
 };
 
@@ -655,7 +656,6 @@ struct drm_cmdline_mode {
  * @bad_edid_counter: track sinks that give us an EDID with invalid checksum
  * @edid_corrupt: indicates whether the last read EDID was corrupt
  * @debugfs_entry: debugfs directory for this connector
- * @state: current atomic state for this connector
  * @has_tile: is this connector connected to a tiled monitor
  * @tile_group: tile group for the connected monitor
  * @tile_is_single_monitor: whether the tile is one monitor housing
@@ -823,6 +823,21 @@ struct drm_connector {
 
        struct dentry *debugfs_entry;
 
+       /**
+        * @state:
+        *
+        * Current atomic state for this connector.
+        *
+        * This is protected by @drm_mode_config.connection_mutex. Note that
+        * nonblocking atomic commits access the current connector state without
+        * taking locks. Either by going through the &struct drm_atomic_state
+        * pointers, see for_each_connector_in_state(),
+        * for_each_oldnew_connector_in_state(),
+        * for_each_old_connector_in_state() and
+        * for_each_new_connector_in_state(). Or through careful ordering of
+        * atomic commit operations as implemented in the atomic helpers, see
+        * &struct drm_crtc_commit.
+        */
        struct drm_connector_state *state;
 
        /* DisplayID bits */
index 6ef59da3fd8ef3842bd864218261cdf3d7aa966e..2be2192b13733cf2b6b714bea65ce56cab868f7e 100644 (file)
@@ -347,7 +347,8 @@ struct drm_crtc_funcs {
         *
         * 0 on success or a negative error code on failure.
         */
-       int (*set_config)(struct drm_mode_set *set);
+       int (*set_config)(struct drm_mode_set *set,
+                         struct drm_modeset_acquire_ctx *ctx);
 
        /**
         * @page_flip:
@@ -405,7 +406,8 @@ struct drm_crtc_funcs {
        int (*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);
 
        /**
         * @page_flip_target:
@@ -423,7 +425,8 @@ struct drm_crtc_funcs {
        int (*page_flip_target)(struct drm_crtc *crtc,
                                struct drm_framebuffer *fb,
                                struct drm_pending_vblank_event *event,
-                               uint32_t flags, uint32_t target);
+                               uint32_t flags, uint32_t target,
+                               struct drm_modeset_acquire_ctx *ctx);
 
        /**
         * @set_property:
@@ -590,9 +593,12 @@ struct drm_crtc_funcs {
         * When CRC generation is enabled, the driver should call
         * drm_crtc_add_crc_entry() at each frame, providing any information
         * that characterizes the frame contents in the crcN arguments, as
-        * provided from the configured source. Drivers must accept a "auto"
+        * provided from the configured source. Drivers must accept an "auto"
         * source name that will select a default source for this CRTC.
         *
+        * Note that "auto" can depend upon the current modeset configuration,
+        * e.g. it could pick an encoder or output specific CRC sampling point.
+        *
         * This callback is optional if the driver does not support any CRC
         * generation functionality.
         *
@@ -696,10 +702,12 @@ struct drm_crtc {
        /**
         * @mutex:
         *
-        * This provides a read lock for the overall crtc state (mode, dpms
+        * This provides a read lock for the overall CRTC state (mode, dpms
         * state, ...) and a write lock for everything which can be update
-        * without a full modeset (fb, cursor data, crtc properties ...). A full
+        * without a full modeset (fb, cursor data, CRTC properties ...). A full
         * modeset also need to grab &drm_mode_config.connection_mutex.
+        *
+        * For atomic drivers specifically this protects @state.
         */
        struct drm_modeset_lock mutex;
 
@@ -745,6 +753,14 @@ struct drm_crtc {
         * @state:
         *
         * Current atomic state for this CRTC.
+        *
+        * This is protected by @mutex. Note that nonblocking atomic commits
+        * access the current CRTC state without taking locks. Either by going
+        * through the &struct drm_atomic_state pointers, see
+        * for_each_crtc_in_state(), for_each_oldnew_crtc_in_state(),
+        * for_each_old_crtc_in_state() and for_each_new_crtc_in_state(). Or
+        * through careful ordering of atomic commit operations as implemented
+        * in the atomic helpers, see &struct drm_crtc_commit.
         */
        struct drm_crtc_state *state;
 
index d026f5017c33cea2c9766b28b5ccb67d635fbe85..43505c7b2b3ffe2ef9d4bf33904e3c36c7bf186e 100644 (file)
 #include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_modeset_helper.h>
 
-extern void drm_helper_disable_unused_functions(struct drm_device *dev);
-extern int drm_crtc_helper_set_config(struct drm_mode_set *set);
-extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
-                                    struct drm_display_mode *mode,
-                                    int x, int y,
-                                    struct drm_framebuffer *old_fb);
-extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
-extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
+void drm_helper_disable_unused_functions(struct drm_device *dev);
+int drm_crtc_helper_set_config(struct drm_mode_set *set,
+                              struct drm_modeset_acquire_ctx *ctx);
+bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
+                             struct drm_display_mode *mode,
+                             int x, int y,
+                             struct drm_framebuffer *old_fb);
+bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
+bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
 
-extern int drm_helper_connector_dpms(struct drm_connector *connector, int mode);
+int drm_helper_connector_dpms(struct drm_connector *connector, int mode);
 
-extern void drm_helper_resume_force_mode(struct drm_device *dev);
+void drm_helper_resume_force_mode(struct drm_device *dev);
 
 int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
                             struct drm_display_mode *adjusted_mode, int x, int y,
@@ -63,15 +64,15 @@ int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
                                  struct drm_framebuffer *old_fb);
 
 /* drm_probe_helper.c */
-extern int drm_helper_probe_single_connector_modes(struct drm_connector
-                                                  *connector, uint32_t maxX,
-                                                  uint32_t maxY);
-extern void drm_kms_helper_poll_init(struct drm_device *dev);
-extern void drm_kms_helper_poll_fini(struct drm_device *dev);
-extern bool drm_helper_hpd_irq_event(struct drm_device *dev);
-extern void drm_kms_helper_hotplug_event(struct drm_device *dev);
+int drm_helper_probe_single_connector_modes(struct drm_connector
+                                           *connector, uint32_t maxX,
+                                           uint32_t maxY);
+void drm_kms_helper_poll_init(struct drm_device *dev);
+void drm_kms_helper_poll_fini(struct drm_device *dev);
+bool drm_helper_hpd_irq_event(struct drm_device *dev);
+void drm_kms_helper_hotplug_event(struct drm_device *dev);
 
-extern void drm_kms_helper_poll_disable(struct drm_device *dev);
-extern void drm_kms_helper_poll_enable(struct drm_device *dev);
+void drm_kms_helper_poll_disable(struct drm_device *dev);
+void drm_kms_helper_poll_enable(struct drm_device *dev);
 
 #endif
diff --git a/include/drm/drm_debugfs.h b/include/drm/drm_debugfs.h
new file mode 100644 (file)
index 0000000..ac0f75d
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Internal Header for the Direct Rendering Manager
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * Copyright (c) 2009-2010, Code Aurora Forum.
+ * All rights reserved.
+ *
+ * Author: Rickard E. (Rik) Faith <faith@valinux.com>
+ * Author: Gareth Hughes <gareth@valinux.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DRM_DEBUGFS_H_
+#define _DRM_DEBUGFS_H_
+
+/**
+ * struct drm_info_list - debugfs info list entry
+ *
+ * This structure represents a debugfs file to be created by the drm
+ * core.
+ */
+struct drm_info_list {
+       /** @name: file name */
+       const char *name;
+       /**
+        * @show:
+        *
+        * Show callback. &seq_file->private will be set to the &struct
+        * drm_info_node corresponding to the instance of this info on a given
+        * &struct drm_minor.
+        */
+       int (*show)(struct seq_file*, void*);
+       /** @driver_features: Required driver features for this entry */
+       u32 driver_features;
+       /** @data: Driver-private data, should not be device-specific. */
+       void *data;
+};
+
+/**
+ * struct drm_info_node - Per-minor debugfs node structure
+ *
+ * This structure represents a debugfs file, as an instantiation of a &struct
+ * drm_info_list on a &struct drm_minor.
+ *
+ * FIXME:
+ *
+ * No it doesn't make a hole lot of sense that we duplicate debugfs entries for
+ * both the render and the primary nodes, but that's how this has organically
+ * grown. It should probably be fixed, with a compatibility link, if needed.
+ */
+struct drm_info_node {
+       /** @minor: &struct drm_minor for this node. */
+       struct drm_minor *minor;
+       /** @info_ent: template for this node. */
+       const struct drm_info_list *info_ent;
+       /* private: */
+       struct list_head list;
+       struct dentry *dent;
+};
+
+#if defined(CONFIG_DEBUG_FS)
+int drm_debugfs_create_files(const struct drm_info_list *files,
+                            int count, struct dentry *root,
+                            struct drm_minor *minor);
+int drm_debugfs_remove_files(const struct drm_info_list *files,
+                            int count, struct drm_minor *minor);
+#else
+static inline int drm_debugfs_create_files(const struct drm_info_list *files,
+                                          int count, struct dentry *root,
+                                          struct drm_minor *minor)
+{
+       return 0;
+}
+
+static inline int drm_debugfs_remove_files(const struct drm_info_list *files,
+                                          int count, struct drm_minor *minor)
+{
+       return 0;
+}
+#endif
+
+#endif /* _DRM_DEBUGFS_H_ */
index f4b4d154b98e723ca1fba78f7f4908512d4cd75f..5b024764666c2b2b82cdc66fb7a1171417fc1def 100644 (file)
@@ -479,18 +479,6 @@ struct drm_dp_mst_topology_mgr {
         * @pbn_div: PBN to slots divisor.
         */
        int pbn_div;
-       /**
-        * @total_slots: Total slots that can be allocated.
-        */
-       int total_slots;
-       /**
-        * @avail_slots: Still available slots that can be allocated.
-        */
-       int avail_slots;
-       /**
-        * @total_pbn: Total PBN count.
-        */
-       int total_pbn;
 
        /**
         * @qlock: protects @tx_msg_downq, the &drm_dp_mst_branch.txslost and
@@ -579,7 +567,8 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
 int drm_dp_calc_pbn_mode(int clock, int bpp);
 
 
-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 drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
 
index 8f900fb30275564ab1708bc5c1b4256d5a7c96ac..53b98321df9b2d6497b5d84afaef0d2b9d91c0e0 100644 (file)
@@ -522,11 +522,11 @@ struct drm_driver {
        int dev_priv_size;
 };
 
-extern __printf(6, 7)
+__printf(6, 7)
 void drm_dev_printk(const struct device *dev, const char *level,
                    unsigned int category, const char *function_name,
                    const char *prefix, const char *format, ...);
-extern __printf(3, 4)
+__printf(3, 4)
 void drm_printk(const char *level, unsigned int category,
                const char *format, ...);
 extern unsigned int drm_debug;
index fcc08da850c854f332dcca7ec65df0b04d0261a2..6942e84b6edde56a1e5a16b1cde2e325a76a6a54 100644 (file)
@@ -25,6 +25,9 @@
 #include <linux/types.h>
 #include <uapi/drm/drm_fourcc.h>
 
+struct drm_device;
+struct drm_mode_fb_cmd2;
+
 /**
  * struct drm_format_info - information about a DRM format
  * @format: 4CC format identifier (DRM_FORMAT_*)
@@ -55,6 +58,9 @@ struct drm_format_name_buf {
 
 const struct drm_format_info *__drm_format_info(u32 format);
 const struct drm_format_info *drm_format_info(u32 format);
+const struct drm_format_info *
+drm_get_format_info(struct drm_device *dev,
+                   const struct drm_mode_fb_cmd2 *mode_cmd);
 uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);
 int drm_format_num_planes(uint32_t format);
 int drm_format_plane_cpp(uint32_t format, int plane);
index a06805eaf649ae1ab97740ca735af00b574b93e0..3a830602a2e461e264e7cb39f6f68d66de84084f 100644 (file)
@@ -45,9 +45,9 @@ struct drm_global_reference {
        void (*release) (struct drm_global_reference *);
 };
 
-extern void drm_global_init(void);
-extern void drm_global_release(void);
-extern int drm_global_item_ref(struct drm_global_reference *ref);
-extern void drm_global_item_unref(struct drm_global_reference *ref);
+void drm_global_init(void);
+void drm_global_release(void);
+int drm_global_item_ref(struct drm_global_reference *ref);
+void drm_global_item_unref(struct drm_global_reference *ref);
 
 #endif
index fce2ef3fdfffecabdd23ece757ce539ef7619bfe..bb95ff011bafa290043852554507c4d2848f4ec2 100644 (file)
@@ -49,17 +49,17 @@ struct drm_open_hash {
        u8 order;
 };
 
-extern int drm_ht_create(struct drm_open_hash *ht, unsigned int order);
-extern int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item);
-extern int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
-                                    unsigned long seed, int bits, int shift,
-                                    unsigned long add);
-extern int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item);
+int drm_ht_create(struct drm_open_hash *ht, unsigned int order);
+int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item);
+int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
+                             unsigned long seed, int bits, int shift,
+                             unsigned long add);
+int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item);
 
-extern void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key);
-extern int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key);
-extern int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item);
-extern void drm_ht_remove(struct drm_open_hash *ht);
+void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key);
+int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key);
+int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item);
+void drm_ht_remove(struct drm_open_hash *ht);
 
 /*
  * RCU-safe interface
diff --git a/include/drm/drm_ioctl.h b/include/drm/drm_ioctl.h
new file mode 100644 (file)
index 0000000..f17ee07
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Internal Header for the Direct Rendering Manager
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * Copyright (c) 2009-2010, Code Aurora Forum.
+ * All rights reserved.
+ *
+ * Author: Rickard E. (Rik) Faith <faith@valinux.com>
+ * Author: Gareth Hughes <gareth@valinux.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DRM_IOCTL_H_
+#define _DRM_IOCTL_H_
+
+#include <linux/types.h>
+
+#include <asm/ioctl.h>
+
+struct drm_device;
+struct drm_file;
+struct file;
+
+/**
+ * Ioctl function type.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private pointer.
+ * \param cmd command.
+ * \param arg argument.
+ */
+typedef int drm_ioctl_t(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+
+typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
+                              unsigned long arg);
+
+#define DRM_IOCTL_NR(n)                _IOC_NR(n)
+#define DRM_MAJOR       226
+
+#define DRM_AUTH       0x1
+#define        DRM_MASTER      0x2
+#define DRM_ROOT_ONLY  0x4
+#define DRM_CONTROL_ALLOW 0x8
+#define DRM_UNLOCKED   0x10
+#define DRM_RENDER_ALLOW 0x20
+
+struct drm_ioctl_desc {
+       unsigned int cmd;
+       int flags;
+       drm_ioctl_t *func;
+       const char *name;
+};
+
+/**
+ * Creates a driver or general drm_ioctl_desc array entry for the given
+ * ioctl, for use by drm_ioctl().
+ */
+
+#define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags)                                \
+       [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = {        \
+               .cmd = DRM_IOCTL_##ioctl,                               \
+               .func = _func,                                          \
+               .flags = _flags,                                        \
+               .name = #ioctl                                          \
+       }
+
+int drm_ioctl_permit(u32 flags, struct drm_file *file_priv);
+long drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+#ifdef CONFIG_COMPAT
+long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+#else
+/* Let drm_compat_ioctl be assigned to .compat_ioctl unconditionally */
+#define drm_compat_ioctl NULL
+#endif
+bool drm_ioctl_flags(unsigned int nr, unsigned int *flags);
+
+int drm_noop(struct drm_device *dev, void *data,
+            struct drm_file *file_priv);
+int drm_invalid_op(struct drm_device *dev, void *data,
+                  struct drm_file *file_priv);
+
+#endif /* _DRM_IOCTL_H_ */
index ea169a90b3c4322d010b7dccb260be22eff791a5..42981711189bda6d93d282ede8d5607f88b1d434 100644 (file)
@@ -34,6 +34,7 @@ struct drm_file;
 struct drm_device;
 struct drm_atomic_state;
 struct drm_mode_fb_cmd2;
+struct drm_format_info;
 
 /**
  * struct drm_mode_config_funcs - basic driver provided mode setting functions
@@ -69,6 +70,19 @@ struct drm_mode_config_funcs {
                                             struct drm_file *file_priv,
                                             const struct drm_mode_fb_cmd2 *mode_cmd);
 
+       /**
+        * @get_format_info:
+        *
+        * Allows a driver to return custom format information for special
+        * fb layouts (eg. ones with auxiliary compression control planes).
+        *
+        * RETURNS:
+        *
+        * The format information specific to the given fb metadata, or
+        * NULL if none is found.
+        */
+       const struct drm_format_info *(*get_format_info)(const struct drm_mode_fb_cmd2 *mode_cmd);
+
        /**
         * @output_poll_changed:
         *
@@ -293,21 +307,6 @@ struct drm_mode_config_funcs {
 
 /**
  * struct drm_mode_config - Mode configuration control structure
- * @mutex: mutex protecting KMS related lists and structures
- * @connection_mutex: ww mutex protecting connector state and routing
- * @acquire_ctx: global implicit acquire context used by atomic drivers for
- *     legacy IOCTLs
- * @fb_lock: mutex to protect fb state and lists
- * @num_fb: number of fbs available
- * @fb_list: list of framebuffers available
- * @num_encoder: number of encoders on this device
- * @encoder_list: list of encoder objects
- * @num_overlay_plane: number of overlay planes on this device
- * @num_total_plane: number of universal (i.e. with primary/curso) planes on this device
- * @plane_list: list of plane objects
- * @num_crtc: number of CRTCs on this device
- * @crtc_list: list of CRTC objects
- * @property_list: list of property objects
  * @min_width: minimum pixel width on this device
  * @min_height: minimum pixel height on this device
  * @max_width: maximum pixel width on this device
@@ -318,9 +317,6 @@ struct drm_mode_config_funcs {
  * @poll_running: track polling status for this device
  * @delayed_event: track delayed poll uevent deliver for this device
  * @output_poll_work: delayed work for polling in process context
- * @property_blob_list: list of all the blob property objects
- * @blob_lock: mutex for blob property allocation and management
- * @*_property: core property tracking
  * @preferred_depth: preferred RBG pixel depth, used by fb helpers
  * @prefer_shadow: hint to userspace to prefer shadow-fb rendering
  * @cursor_width: hint to userspace for max cursor width
@@ -332,9 +328,37 @@ struct drm_mode_config_funcs {
  * global restrictions are also here, e.g. dimension restrictions.
  */
 struct drm_mode_config {
-       struct mutex mutex; /* protects configuration (mode lists etc.) */
-       struct drm_modeset_lock connection_mutex; /* protects connector->encoder and encoder->crtc links */
-       struct drm_modeset_acquire_ctx *acquire_ctx; /* for legacy _lock_all() / _unlock_all() */
+       /**
+        * @mutex:
+        *
+        * This is the big scary modeset BKL which protects everything that
+        * isn't protect otherwise. Scope is unclear and fuzzy, try to remove
+        * anything from under it's protection and move it into more well-scoped
+        * locks.
+        *
+        * The one important thing this protects is the use of @acquire_ctx.
+        */
+       struct mutex mutex;
+
+       /**
+        * @connection_mutex:
+        *
+        * This protects connector state and the connector to encoder to CRTC
+        * routing chain.
+        *
+        * For atomic drivers specifically this protects &drm_connector.state.
+        */
+       struct drm_modeset_lock connection_mutex;
+
+       /**
+        * @acquire_ctx:
+        *
+        * Global implicit acquire context used by atomic drivers for legacy
+        * IOCTLs. Deprecated, since implicit locking contexts make it
+        * impossible to use driver-private &struct drm_modeset_lock. Users of
+        * this must hold @mutex.
+        */
+       struct drm_modeset_acquire_ctx *acquire_ctx;
 
        /**
         * @idr_mutex:
@@ -360,8 +384,11 @@ struct drm_mode_config {
         */
        struct idr tile_idr;
 
-       struct mutex fb_lock; /* proctects global and per-file fb lists */
+       /** @fb_lock: Mutex to protect fb the global @fb_list and @num_fb. */
+       struct mutex fb_lock;
+       /** @num_fb: Number of entries on @fb_list. */
        int num_fb;
+       /** @fb_list: List of all &struct drm_framebuffer. */
        struct list_head fb_list;
 
        /**
@@ -379,27 +406,80 @@ struct drm_mode_config {
         */
        struct ida connector_ida;
        /**
-        * @connector_list: List of connector objects. Protected by
-        * @connector_list_lock. Only use drm_for_each_connector_iter() and
+        * @connector_list:
+        *
+        * List of connector objects linked with &drm_connector.head. Protected
+        * by @connector_list_lock. Only use drm_for_each_connector_iter() and
         * &struct drm_connector_list_iter to walk this list.
         */
        struct list_head connector_list;
+       /**
+        * @num_encoder:
+        *
+        * Number of encoders on this device. This is invariant over the
+        * lifetime of a device and hence doesn't need any locks.
+        */
        int num_encoder;
+       /**
+        * @encoder_list:
+        *
+        * List of encoder objects linked with &drm_encoder.head. This is
+        * invariant over the lifetime of a device and hence doesn't need any
+        * locks.
+        */
        struct list_head encoder_list;
 
-       /*
-        * Track # of overlay planes separately from # of total planes.  By
-        * default we only advertise overlay planes to userspace; if userspace
-        * sets the "universal plane" capability bit, we'll go ahead and
-        * expose all planes.
+       /**
+        * @num_overlay_plane:
+        *
+        * Number of overlay planes on this device, excluding primary and cursor
+        * planes.
+        *
+        * Track number of overlay planes separately from number of total
+        * planes.  By default we only advertise overlay planes to userspace; if
+        * userspace sets the "universal plane" capability bit, we'll go ahead
+        * and expose all planes. This is invariant over the lifetime of a
+        * device and hence doesn't need any locks.
         */
        int num_overlay_plane;
+       /**
+        * @num_total_plane:
+        *
+        * Number of universal (i.e. with primary/curso) planes on this device.
+        * This is invariant over the lifetime of a device and hence doesn't
+        * need any locks.
+        */
        int num_total_plane;
+       /**
+        * @plane_list:
+        *
+        * List of plane objects linked with &drm_plane.head. This is invariant
+        * over the lifetime of a device and hence doesn't need any locks.
+        */
        struct list_head plane_list;
 
+       /**
+        * @num_crtc:
+        *
+        * Number of CRTCs on this device linked with &drm_crtc.head. This is invariant over the lifetime
+        * of a device and hence doesn't need any locks.
+        */
        int num_crtc;
+       /**
+        * @crtc_list:
+        *
+        * List of CRTC objects linked with &drm_crtc.head. This is invariant
+        * over the lifetime of a device and hence doesn't need any locks.
+        */
        struct list_head crtc_list;
 
+       /**
+        * @property_list:
+        *
+        * List of property type objects linked with &drm_property.head. This is
+        * invariant over the lifetime of a device and hence doesn't need any
+        * locks.
+        */
        struct list_head property_list;
 
        int min_width, min_height;
@@ -413,10 +493,24 @@ struct drm_mode_config {
        bool delayed_event;
        struct delayed_work output_poll_work;
 
+       /**
+        * @blob_lock:
+        *
+        * Mutex for blob property allocation and management, protects
+        * @property_blob_list and &drm_file.blobs.
+        */
        struct mutex blob_lock;
 
-       /* pointers to standard properties */
+       /**
+        * @property_blob_list:
+        *
+        * List of all the blob property objects linked with
+        * &drm_property_blob.head. Protected by @blob_lock.
+        */
        struct list_head property_blob_list;
+
+       /* pointers to standard properties */
+
        /**
         * @edid_property: Default connector property to hold the EDID of the
         * currently connected sink, if any.
index 26a64805cc15eefb2958478bc2831fa43cbc8684..d1fc563f068a556a8ddce2443c10ba1f1d3d55c9 100644 (file)
@@ -11,18 +11,18 @@ struct drm_encoder;
 struct device_node;
 
 #ifdef CONFIG_OF
-extern uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
-                                          struct device_node *port);
-extern void drm_of_component_match_add(struct device *master,
-                                      struct component_match **matchptr,
-                                      int (*compare)(struct device *, void *),
-                                      struct device_node *node);
-extern int drm_of_component_probe(struct device *dev,
-                                 int (*compare_of)(struct device *, void *),
-                                 const struct component_master_ops *m_ops);
-extern int drm_of_encoder_active_endpoint(struct device_node *node,
-                                         struct drm_encoder *encoder,
-                                         struct of_endpoint *endpoint);
+uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
+                                   struct device_node *port);
+void drm_of_component_match_add(struct device *master,
+                               struct component_match **matchptr,
+                               int (*compare)(struct device *, void *),
+                               struct device_node *node);
+int drm_of_component_probe(struct device *dev,
+                          int (*compare_of)(struct device *, void *),
+                          const struct component_master_ops *m_ops);
+int drm_of_encoder_active_endpoint(struct device_node *node,
+                                  struct drm_encoder *encoder,
+                                  struct of_endpoint *endpoint);
 #else
 static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
                                                  struct device_node *port)
index f5ebfcaf69e01ea752155598054bc82ccff7a902..4579fac1080c665b49b9fb3572768072f17228cd 100644 (file)
@@ -39,17 +39,17 @@ struct drm_device;
 struct drm_driver;
 struct drm_master;
 
-extern struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size,
-                                           size_t align);
-extern void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah);
+struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size,
+                                    size_t align);
+void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah);
 
-extern int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver);
-extern void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver);
+int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver);
+void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver);
 #ifdef CONFIG_PCI
-extern int drm_get_pci_dev(struct pci_dev *pdev,
-                          const struct pci_device_id *ent,
-                          struct drm_driver *driver);
-extern int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master);
+int drm_get_pci_dev(struct pci_dev *pdev,
+                   const struct pci_device_id *ent,
+                   struct drm_driver *driver);
+int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master);
 #else
 static inline int drm_get_pci_dev(struct pci_dev *pdev,
                                  const struct pci_device_id *ent,
@@ -69,7 +69,7 @@ static inline int drm_pci_set_busid(struct drm_device *dev,
 #define DRM_PCIE_SPEED_50 2
 #define DRM_PCIE_SPEED_80 4
 
-extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask);
-extern int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw);
+int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask);
+int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw);
 
 #endif /* _DRM_PCI_H_ */
index 20867b4371abded8276b99f1a9236ac571f4c2f7..9ab3e70448127902aad5414f7fe1e109ed298e21 100644 (file)
@@ -29,6 +29,7 @@
 
 struct drm_crtc;
 struct drm_printer;
+struct drm_modeset_acquire_ctx;
 
 /**
  * struct drm_plane_state - mutable plane state
@@ -184,7 +185,8 @@ struct drm_plane_funcs {
                            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);
 
        /**
         * @disable_plane:
@@ -201,7 +203,8 @@ struct drm_plane_funcs {
         *
         * 0 on success or a negative error code on failure.
         */
-       int (*disable_plane)(struct drm_plane *plane);
+       int (*disable_plane)(struct drm_plane *plane,
+                            struct drm_modeset_acquire_ctx *ctx);
 
        /**
         * @destroy:
@@ -456,7 +459,6 @@ enum drm_plane_type {
  * @funcs: helper functions
  * @properties: property tracking for this plane
  * @type: type of plane (overlay, primary, cursor)
- * @state: current atomic state for this plane
  * @zpos_property: zpos property for this plane
  * @rotation_property: rotation property for this plane
  * @helper_private: mid-layer private data
@@ -473,6 +475,8 @@ struct drm_plane {
         * Protects modeset plane state, together with the &drm_crtc.mutex of
         * CRTC this plane is linked to (when active, getting activated or
         * getting disabled).
+        *
+        * For atomic drivers specifically this protects @state.
         */
        struct drm_modeset_lock mutex;
 
@@ -502,6 +506,19 @@ struct drm_plane {
 
        const struct drm_plane_helper_funcs *helper_private;
 
+       /**
+        * @state:
+        *
+        * Current atomic state for this plane.
+        *
+        * This is protected by @mutex. Note that nonblocking atomic commits
+        * access the current plane state without taking locks. Either by going
+        * through the &struct drm_atomic_state pointers, see
+        * for_each_plane_in_state(), for_each_oldnew_plane_in_state(),
+        * for_each_old_plane_in_state() and for_each_new_plane_in_state(). Or
+        * through careful ordering of atomic commit operations as implemented
+        * in the atomic helpers, see &struct drm_crtc_commit.
+        */
        struct drm_plane_state *state;
 
        struct drm_property *zpos_property;
@@ -510,7 +527,7 @@ struct drm_plane {
 
 #define obj_to_plane(x) container_of(x, struct drm_plane, base)
 
-extern __printf(8, 9)
+__printf(8, 9)
 int drm_universal_plane_init(struct drm_device *dev,
                             struct drm_plane *plane,
                             uint32_t possible_crtcs,
@@ -519,13 +536,13 @@ int drm_universal_plane_init(struct drm_device *dev,
                             unsigned int format_count,
                             enum drm_plane_type type,
                             const char *name, ...);
-extern int drm_plane_init(struct drm_device *dev,
-                         struct drm_plane *plane,
-                         uint32_t possible_crtcs,
-                         const struct drm_plane_funcs *funcs,
-                         const uint32_t *formats, unsigned int format_count,
-                         bool is_primary);
-extern void drm_plane_cleanup(struct drm_plane *plane);
+int drm_plane_init(struct drm_device *dev,
+                  struct drm_plane *plane,
+                  uint32_t possible_crtcs,
+                  const struct drm_plane_funcs *funcs,
+                  const uint32_t *formats, unsigned int format_count,
+                  bool is_primary);
+void drm_plane_cleanup(struct drm_plane *plane);
 
 /**
  * drm_plane_index - find the index of a registered plane
@@ -538,8 +555,8 @@ static inline unsigned int drm_plane_index(struct drm_plane *plane)
 {
        return plane->index;
 }
-extern struct drm_plane * drm_plane_from_index(struct drm_device *dev, int idx);
-extern void drm_plane_force_disable(struct drm_plane *plane);
+struct drm_plane * drm_plane_from_index(struct drm_device *dev, int idx);
+void drm_plane_force_disable(struct drm_plane *plane);
 
 int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
                                       struct drm_property *property,
index c18959685c06c301ffae57084a4a1f0a9805d98d..7c8a00ceadb742f1895d2e442397b0d1e44a4ef2 100644 (file)
@@ -61,8 +61,10 @@ int drm_primary_helper_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);
-int drm_primary_helper_disable(struct drm_plane *plane);
+                             uint32_t src_w, uint32_t src_h,
+                             struct drm_modeset_acquire_ctx *ctx);
+int drm_primary_helper_disable(struct drm_plane *plane,
+                              struct drm_modeset_acquire_ctx *ctx);
 void drm_primary_helper_destroy(struct drm_plane *plane);
 extern const struct drm_plane_funcs drm_primary_helper_funcs;
 
index d09563ecc4b769ad14018a5683dacfc25a92794f..0b2a235c4be052d539a8e90af56f79caf0b33124 100644 (file)
@@ -57,24 +57,24 @@ struct drm_device;
 struct drm_gem_object;
 struct drm_file;
 
-extern struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
-                                           struct drm_gem_object *obj,
-                                           int flags);
-extern int drm_gem_prime_handle_to_fd(struct drm_device *dev,
-               struct drm_file *file_priv, uint32_t handle, uint32_t flags,
-               int *prime_fd);
-extern struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
-               struct dma_buf *dma_buf);
-extern int drm_gem_prime_fd_to_handle(struct drm_device *dev,
-               struct drm_file *file_priv, int prime_fd, uint32_t *handle);
+struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
+                                    struct drm_gem_object *obj,
+                                    int flags);
+int drm_gem_prime_handle_to_fd(struct drm_device *dev,
+                              struct drm_file *file_priv, uint32_t handle, uint32_t flags,
+                              int *prime_fd);
+struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
+                                           struct dma_buf *dma_buf);
+int drm_gem_prime_fd_to_handle(struct drm_device *dev,
+                              struct drm_file *file_priv, int prime_fd, uint32_t *handle);
 struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
                                      struct dma_buf_export_info *exp_info);
-extern void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
+void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
 
-extern int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
-                                           dma_addr_t *addrs, int max_pages);
-extern struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages);
-extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
+int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
+                                    dma_addr_t *addrs, int max_pages);
+struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages);
+void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
 
 
 #endif /* __DRM_PRIME_H__ */
index ab6bcfbceba98062de45cb5af38cad52fe31ec6a..c25122bb490a345528f0228b0ef11ff542c5bc50 100644 (file)
@@ -129,6 +129,8 @@ static inline int drm_scdc_writeb(struct i2c_adapter *adapter, u8 offset,
        return drm_scdc_write(adapter, offset, &value, sizeof(value));
 }
 
+bool drm_scdc_get_scrambling_status(struct i2c_adapter *adapter);
+
 /**
  * drm_scdc_set_scrambling - enable scrambling
  * @adapter: I2C adapter for DDC channel
index fffbb95a091589fb1ac5a53791f726d572655ec3..2d36538e4a17ebdabe7fa9e20de25fb8cf952dbe 100644 (file)
@@ -72,7 +72,7 @@ struct drm_simple_display_pipe_funcs {
         * the hardware lacks vblank support entirely.
         */
        void (*update)(struct drm_simple_display_pipe *pipe,
-                      struct drm_plane_state *plane_state);
+                      struct drm_plane_state *old_plane_state);
 
        /**
         * @prepare_fb:
index 1d8e033fde6739baff8e227774dd7f290fe16fb2..23418c1f10d1d71f5ebafb66e283f983a3e7bf6f 100644 (file)
@@ -6,7 +6,7 @@
  * don't want to include the full drmP.h file.
  */
 
-extern int drm_class_device_register(struct device *dev);
-extern void drm_class_device_unregister(struct device *dev);
+int drm_class_device_register(struct device *dev);
+void drm_class_device_unregister(struct device *dev);
 
 #endif
index cf9ca207b8b1fa041436d3fcf98073dbd2c07389..00b800df4d1b2b6c6cbe69a3646c8fc577b524db 100644 (file)
@@ -58,8 +58,7 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe)
        .gem_prime_mmap         = drm_gem_cma_prime_mmap, \
        .dumb_create            = drm_gem_cma_dumb_create, \
        .dumb_map_offset        = drm_gem_cma_dumb_map_offset, \
-       .dumb_destroy           = drm_gem_dumb_destroy, \
-       .fops                   = &tinydrm_fops
+       .dumb_destroy           = drm_gem_dumb_destroy
 
 /**
  * TINYDRM_MODE - tinydrm display mode
@@ -84,7 +83,6 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe)
        .type = DRM_MODE_TYPE_DRIVER, \
        .clock = 1 /* pass validation */
 
-extern const struct file_operations tinydrm_fops;
 void tinydrm_lastclose(struct drm_device *drm);
 void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj);
 struct drm_gem_object *
index eb3da1a04e6cdc7d3f4efab5532f53abcdf3a28f..5948cfdc984e2f849507fa1d0fb8f2bed3c01cfa 100644 (file)
@@ -358,6 +358,7 @@ struct pci_dev {
        unsigned int    is_virtfn:1;
        unsigned int    reset_fn:1;
        unsigned int    is_hotplug_bridge:1;
+       unsigned int    is_thunderbolt:1; /* Thunderbolt controller */
        unsigned int    __aer_firmware_first_valid:1;
        unsigned int    __aer_firmware_first:1;
        unsigned int    broken_intx_masking:1;
@@ -2160,6 +2161,28 @@ static inline bool pci_ari_enabled(struct pci_bus *bus)
        return bus->self && bus->self->ari_enabled;
 }
 
+/**
+ * pci_is_thunderbolt_attached - whether device is on a Thunderbolt daisy chain
+ * @pdev: PCI device to check
+ *
+ * Walk upwards from @pdev and check for each encountered bridge if it's part
+ * of a Thunderbolt controller.  Reaching the host bridge means @pdev is not
+ * Thunderbolt-attached.  (But rather soldered to the mainboard usually.)
+ */
+static inline bool pci_is_thunderbolt_attached(struct pci_dev *pdev)
+{
+       struct pci_dev *parent = pdev;
+
+       if (pdev->is_thunderbolt)
+               return true;
+
+       while ((parent = pci_upstream_bridge(parent)))
+               if (parent->is_thunderbolt)
+                       return true;
+
+       return false;
+}
+
 /* provide the legacy pci_dma_* API */
 #include <linux/pci-dma-compat.h>