]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge tag 'drm-misc-next-2017-03-06' of git://anongit.freedesktop.org/git/drm-misc...
authorDave Airlie <airlied@redhat.com>
Tue, 7 Mar 2017 03:59:53 +0000 (13:59 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 7 Mar 2017 03:59:53 +0000 (13:59 +1000)
First slice of drm-misc-next for 4.12:

Core/subsystem-wide:
- link status core patch from Manasi, for signalling link train fail
  to userspace. I also had the i915 patch in here, but that had a
  small buglet in our CI, so reverted.
- more debugfs_remove removal from Noralf, almost there now (Noralf
  said he'll try to follow up with the stragglers).
- drm todo moved into kerneldoc, for better visibility (see
  Documentation/gpu/todo.rst), lots of starter tasks in there.
- devm_ of helpers + use it in sti (from Ben Gaignard, acked by Rob
  Herring)
- extended framebuffer fbdev support (for fbdev flipping), and vblank
  wait ioctl fbdev support (Maxime Ripard)
- misc small things all over, as usual
- add vblank callbacks to drm_crtc_funcs, plus make lots of good use
  of this to simplify drivers (Shawn Guo)
- new atomic iterator macros to unconfuse old vs. new state

Small drivers:
- vc4 improvements from Eric
- vc4 kerneldocs (Eric)!
- tons of improvements for dw-mipi-dsi in rockchip from John Keeping
  and Chris Zhong.
- MAINTAINERS entries for drivers managed in drm-misc. It's not yet
  official, still an experiment, but definitely not complete fail and
  better to avoid confusion. We kinda screwed that up with drm-misc a
  bit when we started committers last year.
- qxl atomic conversion (Gabriel Krisman)
- bunch of virtual driver polish (qxl, virgl, ...)
- misc tiny patches all over

This is the first time we've done the same merge-window blackout for
drm-misc as we've done for drm-intel for ages, hence why we have a
_lot_ of stuff queued already. But it's still only half of drm-intel
(room to grow!), and the drivers in drm-misc experiment seems to work
at least insofar as that you also get lots of driver updates here
alredy.

* tag 'drm-misc-next-2017-03-06' of git://anongit.freedesktop.org/git/drm-misc: (141 commits)
  drm/vc4: Fix OOPSes from trying to cache a partially constructed BO.
  drm/vc4: Fulfill user BO creation requests from the kernel BO cache.
  Revert "drm/i915: Implement Link Rate fallback on Link training failure"
  drm/fb-helper: implement ioctl FBIO_WAITFORVSYNC
  drm: Update drm_fbdev_cma_init documentation
  drm/rockchip/dsi: add dw-mipi power domain support
  drm/rockchip/dsi: fix insufficient bandwidth of some panel
  dt-bindings: add power domain node for dw-mipi-rockchip
  drm/rockchip/dsi: remove mode_valid function
  drm/rockchip/dsi: dw-mipi: correct the coding style
  drm/rockchip/dsi: dw-mipi: support RK3399 mipi dsi
  dt-bindings: add rk3399 support for dw-mipi-rockchip
  drm/rockchip: dw-mipi-dsi: add reset control
  drm/rockchip: dw-mipi-dsi: support non-burst modes
  drm/rockchip: dw-mipi-dsi: defer probe if panel is not loaded
  drm/rockchip: vop: test for P{H,V}SYNC
  drm/rockchip: dw-mipi-dsi: use positive check for N{H, V}SYNC
  drm/rockchip: dw-mipi-dsi: use specific poll helper
  drm/rockchip: dw-mipi-dsi: improve PLL configuration
  drm/rockchip: dw-mipi-dsi: properly configure PHY timing
  ...

207 files changed:
Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
Documentation/gpu/drm-mm.rst
Documentation/gpu/index.rst
Documentation/gpu/introduction.rst
Documentation/gpu/todo.rst [new file with mode: 0644]
Documentation/gpu/vc4.rst [new file with mode: 0644]
MAINTAINERS
drivers/dma-buf/dma-fence.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
drivers/gpu/drm/arc/arcpgu_drv.c
drivers/gpu/drm/arm/hdlcd_crtc.c
drivers/gpu/drm/arm/hdlcd_drv.c
drivers/gpu/drm/arm/malidp_crtc.c
drivers/gpu/drm/arm/malidp_drv.c
drivers/gpu/drm/armada/armada_crtc.c
drivers/gpu/drm/armada/armada_crtc.h
drivers/gpu/drm/armada/armada_debugfs.c
drivers/gpu/drm/armada/armada_drm.h
drivers/gpu/drm/armada/armada_drv.c
drivers/gpu/drm/armada/armada_fbdev.c
drivers/gpu/drm/ast/ast_fb.c
drivers/gpu/drm/atmel-hlcdc/Makefile
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_layer.c [deleted file]
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_layer.h [deleted file]
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
drivers/gpu/drm/bochs/bochs_fbdev.c
drivers/gpu/drm/bridge/sil-sii8620.c
drivers/gpu/drm/bridge/ti-tfp410.c
drivers/gpu/drm/cirrus/cirrus_fbdev.c
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_cache.c
drivers/gpu/drm/drm_connector.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_crtc_internal.h
drivers/gpu/drm/drm_debugfs.c
drivers/gpu/drm/drm_dp_dual_mode_helper.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_edid_load.c
drivers/gpu/drm/drm_encoder.c
drivers/gpu/drm/drm_fb_cma_helper.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_framebuffer.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_gem_cma_helper.c
drivers/gpu/drm/drm_ioc32.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/drm_mm.c
drivers/gpu/drm/drm_mode_config.c
drivers/gpu/drm/drm_mode_object.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/drm_plane.c
drivers/gpu/drm/drm_plane_helper.c
drivers/gpu/drm/drm_prime.c
drivers/gpu/drm/drm_print.c
drivers/gpu/drm/drm_probe_helper.c
drivers/gpu/drm/drm_property.c
drivers/gpu/drm/exynos/exynos_drm_crtc.c
drivers/gpu/drm/exynos/exynos_drm_crtc.h
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
drivers/gpu/drm/gma500/cdv_intel_lvds.c
drivers/gpu/drm/gma500/framebuffer.c
drivers/gpu/drm/gma500/oaktrail_lvds.c
drivers/gpu/drm/gma500/psb_drv.h
drivers/gpu/drm/gma500/psb_intel_lvds.c
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_sw_fence.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_fbdev.c
drivers/gpu/drm/i915/intel_pipe_crc.c
drivers/gpu/drm/imx/imx-drm-core.c
drivers/gpu/drm/imx/imx-drm.h
drivers/gpu/drm/imx/ipuv3-crtc.c
drivers/gpu/drm/mediatek/mtk_drm_crtc.c
drivers/gpu/drm/mediatek/mtk_drm_crtc.h
drivers/gpu/drm/mediatek/mtk_drm_drv.c
drivers/gpu/drm/meson/meson_crtc.c
drivers/gpu/drm/meson/meson_drv.c
drivers/gpu/drm/mgag200/mgag200_fb.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/msm/dsi/dsi_host.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
drivers/gpu/drm/msm/msm_debugfs.c
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_fbdev.c
drivers/gpu/drm/msm/msm_perf.c
drivers/gpu/drm/msm/msm_rd.c
drivers/gpu/drm/mxsfb/mxsfb_drv.c
drivers/gpu/drm/nouveau/nouveau_acpi.c
drivers/gpu/drm/nouveau/nouveau_debugfs.c
drivers/gpu/drm/nouveau/nouveau_debugfs.h
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_vga.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nvkm/core/mm.c
drivers/gpu/drm/omapdrm/dss/dsi.c
drivers/gpu/drm/omapdrm/dss/dss.c
drivers/gpu/drm/omapdrm/dss/dss.h
drivers/gpu/drm/omapdrm/omap_crtc.c
drivers/gpu/drm/omapdrm/omap_drv.c
drivers/gpu/drm/omapdrm/omap_drv.h
drivers/gpu/drm/omapdrm/omap_fbdev.c
drivers/gpu/drm/omapdrm/omap_gem.c
drivers/gpu/drm/omapdrm/omap_irq.c
drivers/gpu/drm/qxl/qxl_debugfs.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_drv.c
drivers/gpu/drm/qxl/qxl_drv.h
drivers/gpu/drm/qxl/qxl_fb.c
drivers/gpu/drm/qxl/qxl_kms.c
drivers/gpu/drm/qxl/qxl_object.c
drivers/gpu/drm/r128/r128_cce.c
drivers/gpu/drm/radeon/radeon_fb.c
drivers/gpu/drm/rcar-du/rcar_du_crtc.c
drivers/gpu/drm/rcar-du/rcar_du_crtc.h
drivers/gpu/drm/rcar-du/rcar_du_drv.c
drivers/gpu/drm/rockchip/dw-mipi-dsi.c
drivers/gpu/drm/rockchip/rockchip_drm_drv.c
drivers/gpu/drm/rockchip/rockchip_drm_drv.h
drivers/gpu/drm/rockchip/rockchip_drm_fb.c
drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/selftests/test-drm_mm.c
drivers/gpu/drm/shmobile/shmob_drm_crtc.c
drivers/gpu/drm/shmobile/shmob_drm_crtc.h
drivers/gpu/drm/shmobile/shmob_drm_drv.c
drivers/gpu/drm/sti/sti_drv.c
drivers/gpu/drm/sun4i/sun4i_crtc.c
drivers/gpu/drm/sun4i/sun4i_drv.c
drivers/gpu/drm/tegra/dc.c
drivers/gpu/drm/tegra/drm.c
drivers/gpu/drm/tegra/drm.h
drivers/gpu/drm/tegra/fb.c
drivers/gpu/drm/tilcdc/tilcdc_crtc.c
drivers/gpu/drm/tilcdc/tilcdc_drv.c
drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/udl/udl_fb.c
drivers/gpu/drm/vc4/vc4_bo.c
drivers/gpu/drm/vc4/vc4_crtc.c
drivers/gpu/drm/vc4/vc4_dpi.c
drivers/gpu/drm/vc4/vc4_drv.c
drivers/gpu/drm/vc4/vc4_drv.h
drivers/gpu/drm/vc4/vc4_dsi.c
drivers/gpu/drm/vc4/vc4_gem.c
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/gpu/drm/vc4/vc4_hvs.c
drivers/gpu/drm/vc4/vc4_irq.c
drivers/gpu/drm/vc4/vc4_plane.c
drivers/gpu/drm/vc4/vc4_render_cl.c
drivers/gpu/drm/vc4/vc4_validate.c
drivers/gpu/drm/vc4/vc4_validate_shaders.c
drivers/gpu/drm/vc4/vc4_vec.c
drivers/gpu/drm/via/via_dmablit.c
drivers/gpu/drm/virtio/virtgpu_debugfs.c
drivers/gpu/drm/virtio/virtgpu_display.c
drivers/gpu/drm/virtio/virtgpu_drv.c
drivers/gpu/drm/virtio/virtgpu_drv.h
drivers/gpu/drm/virtio/virtgpu_fb.c
drivers/gpu/drm/virtio/virtgpu_plane.c
drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/gpu/drm/zte/zx_drm_drv.c
drivers/gpu/drm/zte/zx_vou.c
drivers/gpu/drm/zte/zx_vou.h
drivers/gpu/vga/vga_switcheroo.c
drivers/of/platform.c
include/drm/drm_atomic.h
include/drm/drm_atomic_helper.h
include/drm/drm_connector.h
include/drm/drm_crtc.h
include/drm/drm_drv.h
include/drm/drm_edid.h
include/drm/drm_fb_helper.h
include/drm/drm_framebuffer.h
include/drm/drm_gem.h
include/drm/drm_irq.h
include/drm/drm_mm.h
include/drm/drm_mode_config.h
include/drm/drm_mode_object.h
include/drm/drm_print.h
include/drm/drm_property.h
include/linux/of_platform.h
include/linux/reservation.h
include/uapi/drm/drm_mode.h
scripts/coccinelle/api/drm-get-put.cocci [new file with mode: 0644]

index 1753f0cc6fad6c799351ed35e412dd7ed97514ab..188f6f7403e6720d258e7fde119f618e76794c83 100644 (file)
@@ -5,14 +5,19 @@ Required properties:
 - #address-cells: Should be <1>.
 - #size-cells: Should be <0>.
 - compatible: "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi".
+             "rockchip,rk3399-mipi-dsi", "snps,dw-mipi-dsi".
 - reg: Represent the physical address range of the controller.
 - 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), as described in [1].
+  clock(ref) and APB clock(pclk). For RK3399, a phy config clock
+  (phy_cfg) is additional 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.
 
+Optional properties:
+- power-domains: a phandle to mipi dsi power domain node.
+
 [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
 [2] Documentation/devicetree/bindings/media/video-interfaces.txt
 
index f5760b140f13f19a3e27a037355e2875ea67006c..fd35998acefc1d96ee39013827d202eb472b6625 100644 (file)
@@ -183,14 +183,12 @@ GEM Objects Lifetime
 --------------------
 
 All GEM objects are reference-counted by the GEM core. References can be
-acquired and release by :c:func:`calling
-drm_gem_object_reference()` and
-:c:func:`drm_gem_object_unreference()` respectively. The caller
-must hold the :c:type:`struct drm_device <drm_device>`
-struct_mutex lock when calling
-:c:func:`drm_gem_object_reference()`. As a convenience, GEM
-provides :c:func:`drm_gem_object_unreference_unlocked()`
-functions that can be called without holding the lock.
+acquired and release by :c:func:`calling drm_gem_object_get()` and
+:c:func:`drm_gem_object_put()` respectively. The caller must hold the
+:c:type:`struct drm_device <drm_device>` struct_mutex lock when calling
+:c:func:`drm_gem_object_get()`. As a convenience, GEM provides
+:c:func:`drm_gem_object_put_unlocked()` functions that can be called without
+holding the lock.
 
 When the last reference to a GEM object is released the GEM core calls
 the :c:type:`struct drm_driver <drm_driver>` gem_free_object
index f81278a7c2cc57aa74c1c7053f080247cdc7288c..e998ee0d0dd588b9d18a769a0a908e3d228d6eae 100644 (file)
@@ -12,8 +12,10 @@ Linux GPU Driver Developer's Guide
    drm-uapi
    i915
    tinydrm
+   vc4
    vga-switcheroo
    vgaarbiter
+   todo
 
 .. only::  subproject and html
 
index eb284eb748ba9b6596af7fee5244a1de3db50cd4..1f8bd5ef5f9dbc40853f1f6fbdc8c5860c9cc729 100644 (file)
@@ -50,3 +50,13 @@ names are "Notes" with information for dangerous or tricky corner cases,
 and "FIXME" where the interface could be cleaned up.
 
 Also read the :ref:`guidelines for the kernel documentation at large <doc_guide>`.
+
+Getting Started
+===============
+
+Developers interested in helping out with the DRM subsystem are very welcome.
+Often people will resort to sending in patches for various issues reported by
+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>`.
diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
new file mode 100644 (file)
index 0000000..ce0f1a5
--- /dev/null
@@ -0,0 +1,321 @@
+.. _todo:
+
+=========
+TODO list
+=========
+
+This section contains a list of smaller janitorial tasks in the kernel DRM
+graphics subsystem useful as newbie projects. Or for slow rainy days.
+
+Subsystem-wide refactorings
+===========================
+
+De-midlayer drivers
+-------------------
+
+With the recent ``drm_bus`` cleanup patches for 3.17 it is no longer required
+to have a ``drm_bus`` structure set up. Drivers can directly set up the
+``drm_device`` structure instead of relying on bus methods in ``drm_usb.c``
+and ``drm_platform.c``. The goal is to get rid of the driver's ``->load`` /
+``->unload`` callbacks and open-code the load/unload sequence properly, using
+the new two-stage ``drm_device`` setup/teardown.
+
+Once all existing drivers are converted we can also remove those bus support
+files for USB and platform devices.
+
+All you need is a GPU for a non-converted driver (currently almost all of
+them, but also all the virtual ones used by KVM, so everyone qualifies).
+
+Contact: Daniel Vetter, Thierry Reding, respective driver maintainers
+
+Switch from reference/unreference to get/put
+--------------------------------------------
+
+For some reason DRM core uses ``reference``/``unreference`` suffixes for
+refcounting functions, but kernel uses ``get``/``put`` (e.g.
+``kref_get``/``put()``). It would be good to switch over for consistency, and
+it's shorter. Needs to be done in 3 steps for each pair of functions:
+
+* Create new ``get``/``put`` functions, define the old names as compatibility
+  wrappers
+* Switch over each file/driver using a cocci-generated spatch.
+* Once all users of the old names are gone, remove them.
+
+This way drivers/patches in the progress of getting merged won't break.
+
+Contact: Daniel Vetter
+
+Convert existing KMS drivers to atomic modesetting
+--------------------------------------------------
+
+3.19 has the atomic modeset interfaces and helpers, so drivers can now be
+converted over. Modern compositors like Wayland or Surfaceflinger on Android
+really want an atomic modeset interface, so this is all about the bright
+future.
+
+There is a conversion guide for atomic and all you need is a GPU for a
+non-converted driver (again virtual HW drivers for KVM are still all
+suitable).
+
+As part of this drivers also need to convert to universal plane (which means
+exposing primary & cursor as proper plane objects). But that's much easier to
+do by directly using the new atomic helper driver callbacks.
+
+Contact: Daniel Vetter, respective driver maintainers
+
+Clean up the clipped coordination confusion around planes
+---------------------------------------------------------
+
+We have a helper to get this right with drm_plane_helper_check_update(), but
+it's not consistently used. This should be fixed, preferrably in the atomic
+helpers (and drivers then moved over to clipped coordinates). Probably the
+helper should also be moved from drm_plane_helper.c to the atomic helpers, to
+avoid confusion - the other helpers in that file are all deprecated legacy
+helpers.
+
+Contact: Ville Syrjälä, Daniel Vetter, driver maintainers
+
+Implement deferred fbdev setup in the helper
+--------------------------------------------
+
+Many (especially embedded drivers) want to delay fbdev setup until there's a
+real screen plugged in. This is to avoid the dreaded fallback to the low-res
+fbdev default. Many drivers have a hacked-up (and often broken) version of this,
+better to do it once in the shared helpers. Thierry has a patch series, but that
+one needs to be rebased and final polish applied.
+
+Contact: Thierry Reding, Daniel Vetter, driver maintainers
+
+Convert early atomic drivers to async commit helpers
+----------------------------------------------------
+
+For the first year the atomic modeset helpers didn't support asynchronous /
+nonblocking commits, and every driver had to hand-roll them. This is fixed
+now, but there's still a pile of existing drivers that easily could be
+converted over to the new infrastructure.
+
+One issue with the helpers is that they require that drivers handle completion
+events for atomic commits correctly. But fixing these bugs is good anyway.
+
+Contact: Daniel Vetter, respective driver maintainers
+
+Fallout from atomic KMS
+-----------------------
+
+``drm_atomic_helper.c`` provides a batch of functions which implement legacy
+IOCTLs on top of the new atomic driver interface. Which is really nice for
+gradual conversion of drivers, but unfortunately the semantic mismatches are
+a bit too severe. So there's some follow-up work to adjust the function
+interfaces to fix these issues:
+
+* atomic needs the lock acquire context. At the moment that's passed around
+  implicitly with some horrible hacks, and it's also allocate with
+  ``GFP_NOFAIL`` behind the scenes. All legacy paths need to start allocating
+  the acquire context explicitly on stack and then also pass it down into
+  drivers explicitly so that the legacy-on-atomic functions can use them.
+
+* A bunch of the vtable hooks are now in the wrong place: DRM has a split
+  between core vfunc tables (named ``drm_foo_funcs``), which are used to
+  implement the userspace ABI. And then there's the optional hooks for the
+  helper libraries (name ``drm_foo_helper_funcs``), which are purely for
+  internal use. Some of these hooks should be move from ``_funcs`` to
+  ``_helper_funcs`` since they are not part of the core ABI. There's a
+  ``FIXME`` comment in the kerneldoc for each such case in ``drm_crtc.h``.
+
+* There's a new helper ``drm_atomic_helper_best_encoder()`` which could be
+  used by all atomic drivers which don't select the encoder for a given
+  connector at runtime. That's almost all of them, and would allow us to get
+  rid of a lot of ``best_encoder`` boilerplate in drivers.
+
+Contact: Daniel Vetter
+
+Get rid of dev->struct_mutex from GEM drivers
+---------------------------------------------
+
+``dev->struct_mutex`` is the Big DRM Lock from legacy days and infested
+everything. Nowadays in modern drivers the only bit where it's mandatory is
+serializing GEM buffer object destruction. Which unfortunately means drivers
+have to keep track of that lock and either call ``unreference`` or
+``unreference_locked`` depending upon context.
+
+Core GEM doesn't have a need for ``struct_mutex`` any more since kernel 4.8,
+and there's a ``gem_free_object_unlocked`` callback for any drivers which are
+entirely ``struct_mutex`` free.
+
+For drivers that need ``struct_mutex`` it should be replaced with a driver-
+private lock. The tricky part is the BO free functions, since those can't
+reliably take that lock any more. Instead state needs to be protected with
+suitable subordinate locks or some cleanup work pushed to a worker thread. For
+performance-critical drivers it might also be better to go with a more
+fine-grained per-buffer object and per-context lockings scheme. Currently the
+following drivers still use ``struct_mutex``: ``msm``, ``omapdrm`` and
+``udl``.
+
+Contact: Daniel Vetter
+
+Core refactorings
+=================
+
+Use new IDR deletion interface to clean up drm_gem_handle_delete()
+------------------------------------------------------------------
+
+See the "This is gross" comment -- apparently the IDR system now can return an
+error code instead of oopsing.
+
+Clean up the DRM header mess
+----------------------------
+
+Currently the DRM subsystem has only one global header, ``drmP.h``. This is
+used both for functions exported to helper libraries and drivers and functions
+only used internally in the ``drm.ko`` module. The goal would be to move all
+header declarations not needed outside of ``drm.ko`` into
+``drivers/gpu/drm/drm_*_internal.h`` header files. ``EXPORT_SYMBOL`` also
+needs to be dropped for these functions.
+
+This would nicely tie in with the below task to create kerneldoc after the API
+is cleaned up. Or with the "hide legacy cruft better" task.
+
+Note that this is well in progress, but ``drmP.h`` is still huge. The updated
+plan is to switch to per-file driver API headers, which will also structure
+the kerneldoc better. This should also allow more fine-grained ``#include``
+directives.
+
+Contact: Daniel Vetter
+
+Add missing kerneldoc for exported functions
+--------------------------------------------
+
+The DRM reference documentation is still lacking kerneldoc in a few areas. The
+task would be to clean up interfaces like moving functions around between
+files to better group them and improving the interfaces like dropping return
+values for functions that never fail. Then write kerneldoc for all exported
+functions and an overview section and integrate it all into the drm DocBook.
+
+See https://dri.freedesktop.org/docs/drm/ for what's there already.
+
+Contact: Daniel Vetter
+
+Hide legacy cruft better
+------------------------
+
+Way back DRM supported only drivers which shadow-attached to PCI devices with
+userspace or fbdev drivers setting up outputs. Modern DRM drivers take charge
+of the entire device, you can spot them with the DRIVER_MODESET flag.
+
+Unfortunately there's still large piles of legacy code around which needs to
+be hidden so that driver writers don't accidentally end up using it. And to
+prevent security issues in those legacy IOCTLs from being exploited on modern
+drivers. This has multiple possible subtasks:
+
+* Make sure legacy IOCTLs can't be used on modern drivers.
+* Extract support code for legacy features into a ``drm-legacy.ko`` kernel
+  module and compile it only when one of the legacy drivers is enabled.
+* Extract legacy functions into their own headers and remove it that from the
+  monolithic ``drmP.h`` header.
+* Remove any lingering cruft from the OS abstraction layer from modern
+  drivers.
+
+This is mostly done, the only thing left is to split up ``drm_irq.c`` into
+legacy cruft and the parts needed by modern KMS drivers.
+
+Contact: Daniel Vetter
+
+Make panic handling work
+------------------------
+
+This is a really varied tasks with lots of little bits and pieces:
+
+* The panic path can't be tested currently, leading to constant breaking. The
+  main issue here is that panics can be triggered from hardirq contexts and
+  hence all panic related callback can run in hardirq context. It would be
+  awesome if we could test at least the fbdev helper code and driver code by
+  e.g. trigger calls through drm debugfs files. hardirq context could be
+  achieved by using an IPI to the local processor.
+
+* There's a massive confusion of different panic handlers. DRM fbdev emulation
+  helpers have one, but on top of that the fbcon code itself also has one. We
+  need to make sure that they stop fighting over each another.
+
+* ``drm_can_sleep()`` is a mess. It hides real bugs in normal operations and
+  isn't a full solution for panic paths. We need to make sure that it only
+  returns true if there's a panic going on for real, and fix up all the
+  fallout.
+
+* The panic handler must never sleep, which also means it can't ever
+  ``mutex_lock()``. Also it can't grab any other lock unconditionally, not
+  even spinlocks (because NMI and hardirq can panic too). We need to either
+  make sure to not call such paths, or trylock everything. Really tricky.
+
+* For the above locking troubles reasons it's pretty much impossible to
+  attempt a synchronous modeset from panic handlers. The only thing we could
+  try to achive is an atomic ``set_base`` of the primary plane, and hope that
+  it shows up. Everything else probably needs to be delayed to some worker or
+  something else which happens later on. Otherwise it just kills the box
+  harder, prevent the panic from going out on e.g. netconsole.
+
+* There's also proposal for a simplied DRM console instead of the full-blown
+  fbcon and DRM fbdev emulation. Any kind of panic handling tricks should
+  obviously work for both console, in case we ever get kmslog merged.
+
+Contact: Daniel Vetter
+
+Better Testing
+==============
+
+Enable trinity for DRM
+----------------------
+
+And fix up the fallout. Should be really interesting ...
+
+Make KMS tests in i-g-t generic
+-------------------------------
+
+The i915 driver team maintains an extensive testsuite for the i915 DRM driver,
+including tons of testcases for corner-cases in the modesetting API. It would
+be awesome if those tests (at least the ones not relying on Intel-specific GEM
+features) could be made to run on any KMS driver.
+
+Basic work to run i-g-t tests on non-i915 is done, what's now missing is mass-
+converting things over. For modeset tests we also first need a bit of
+infrastructure to use dumb buffers for untiled buffers, to be able to run all
+the non-i915 specific modeset tests.
+
+Contact: Daniel Vetter
+
+Create a virtual KMS driver for testing (vkms)
+----------------------------------------------
+
+With all the latest helpers it should be fairly simple to create a virtual KMS
+driver useful for testing, or for running X or similar on headless machines
+(to be able to still use the GPU). This would be similar to vgem, but aimed at
+the modeset side.
+
+Once the basics are there there's tons of possibilities to extend it.
+
+Contact: Daniel Vetter
+
+Driver Specific
+===============
+
+Outside DRM
+===========
+
+Better kerneldoc
+----------------
+
+This is pretty much done, but there's some advanced topics:
+
+Come up with a way to hyperlink to struct members. Currently you can hyperlink
+to the struct using ``#struct_name``, but not to a member within. Would need
+buy-in from kerneldoc maintainers, and the big question is how to make it work
+without totally unsightly
+``drm_foo_bar_really_long_structure->even_longer_memeber`` all over the text
+which breaks text flow.
+
+Figure out how to integrate the asciidoc support for ascii-diagrams. We have a
+few of those (e.g. to describe mode timings), and asciidoc supports converting
+some ascii-art dialect into pngs. Would be really pretty to make that work.
+
+Contact: Daniel Vetter, Jani Nikula
+
+Jani is working on this already, hopefully lands in 4.8.
diff --git a/Documentation/gpu/vc4.rst b/Documentation/gpu/vc4.rst
new file mode 100644 (file)
index 0000000..5df1d98
--- /dev/null
@@ -0,0 +1,89 @@
+=====================================
+ drm/vc4 Broadcom VC4 Graphics Driver
+=====================================
+
+.. kernel-doc:: drivers/gpu/drm/vc4/vc4_drv.c
+   :doc: Broadcom VC4 Graphics Driver
+
+Display Hardware Handling
+=========================
+
+This section covers everything related to the display hardware including
+the mode setting infrastructure, plane, sprite and cursor handling and
+display, output probing and related topics.
+
+Pixel Valve (DRM CRTC)
+----------------------
+
+.. kernel-doc:: drivers/gpu/drm/vc4/vc4_crtc.c
+   :doc: VC4 CRTC module
+
+HVS
+---
+
+.. kernel-doc:: drivers/gpu/drm/vc4/vc4_hvs.c
+   :doc: VC4 HVS module.
+
+HVS planes
+----------
+
+.. kernel-doc:: drivers/gpu/drm/vc4/vc4_plane.c
+   :doc: VC4 plane module
+
+HDMI encoder
+------------
+
+.. kernel-doc:: drivers/gpu/drm/vc4/vc4_hdmi.c
+   :doc: VC4 Falcon HDMI module
+
+DSI encoder
+-----------
+
+.. kernel-doc:: drivers/gpu/drm/vc4/vc4_dsi.c
+   :doc: VC4 DSI0/DSI1 module
+
+DPI encoder
+-----------
+
+.. kernel-doc:: drivers/gpu/drm/vc4/vc4_dpi.c
+   :doc: VC4 DPI module
+
+VEC (Composite TV out) encoder
+------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/vc4/vc4_vec.c
+   :doc: VC4 SDTV module
+
+Memory Management and 3D Command Submission
+===========================================
+
+This section covers the GEM implementation in the vc4 driver.
+
+GPU buffer object (BO) management
+---------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/vc4/vc4_bo.c
+   :doc: VC4 GEM BO management support
+
+V3D binner command list (BCL) validation
+----------------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/vc4/vc4_validate.c
+   :doc: Command list validator for VC4.
+
+V3D render command list (RCL) generation
+----------------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/vc4/vc4_render_cl.c
+   :doc: Render command list generation
+
+Shader validator for VC4
+---------------------------
+.. kernel-doc:: drivers/gpu/drm/vc4/vc4_validate_shaders.c
+   :doc: Shader validator for VC4.
+
+V3D Interrupts
+--------------
+
+.. kernel-doc:: drivers/gpu/drm/vc4/vc4_irq.c
+   :doc: Interrupt management for the V3D engine
index c265a5fe48481f548629079cb529137e0a377f31..4084e2fa39c93abc85ff5d5c5ba3ce0938dea8c9 100644 (file)
@@ -4174,7 +4174,7 @@ F:        drivers/gpu/drm/bridge/
 DRM DRIVER FOR BOCHS VIRTUAL GPU
 M:     Gerd Hoffmann <kraxel@redhat.com>
 L:     virtualization@lists.linux-foundation.org
-T:     git git://git.kraxel.org/linux drm-qemu
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 S:     Maintained
 F:     drivers/gpu/drm/bochs/
 
@@ -4182,7 +4182,7 @@ DRM DRIVER FOR QEMU'S CIRRUS DEVICE
 M:     Dave Airlie <airlied@redhat.com>
 M:     Gerd Hoffmann <kraxel@redhat.com>
 L:     virtualization@lists.linux-foundation.org
-T:     git git://git.kraxel.org/linux drm-qemu
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 S:     Obsolete
 W:     https://www.kraxel.org/blog/2014/10/qemu-using-cirrus-considered-harmful/
 F:     drivers/gpu/drm/cirrus/
@@ -4239,6 +4239,7 @@ L:        dri-devel@lists.freedesktop.org
 S:     Supported
 F:     drivers/gpu/drm/atmel-hlcdc/
 F:     Documentation/devicetree/bindings/drm/atmel/
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 
 DRM DRIVERS FOR ALLWINNER A10
 M:     Maxime Ripard  <maxime.ripard@free-electrons.com>
@@ -4255,6 +4256,8 @@ W:        http://linux-meson.com/
 S:     Supported
 F:     drivers/gpu/drm/meson/
 F:     Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt
+T:     git git://anongit.freedesktop.org/drm/drm-meson
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 
 DRM DRIVERS FOR EXYNOS
 M:     Inki Dae <inki.dae@samsung.com>
@@ -4385,7 +4388,7 @@ DRM DRIVER FOR QXL VIRTUAL GPU
 M:     Dave Airlie <airlied@redhat.com>
 M:     Gerd Hoffmann <kraxel@redhat.com>
 L:     virtualization@lists.linux-foundation.org
-T:     git git://git.kraxel.org/linux drm-qemu
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 S:     Maintained
 F:     drivers/gpu/drm/qxl/
 F:     include/uapi/drm/qxl_drm.h
@@ -4396,6 +4399,7 @@ L:        dri-devel@lists.freedesktop.org
 S:     Maintained
 F:     drivers/gpu/drm/rockchip/
 F:     Documentation/devicetree/bindings/display/rockchip/
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 
 DRM DRIVER FOR SAVAGE VIDEO CARDS
 S:     Orphan / Obsolete
@@ -4454,6 +4458,7 @@ S:        Supported
 F:     drivers/gpu/drm/vc4/
 F:     include/uapi/drm/vc4_drm.h
 F:     Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 
 DRM DRIVERS FOR TI OMAP
 M:     Tomi Valkeinen <tomi.valkeinen@ti.com>
@@ -4476,6 +4481,7 @@ L:        dri-devel@lists.freedesktop.org
 S:     Maintained
 F:     drivers/gpu/drm/zte/
 F:     Documentation/devicetree/bindings/display/zte,vou.txt
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 
 DSBR100 USB FM RADIO DRIVER
 M:     Alexey Klimov <klimov.linux@gmail.com>
@@ -13314,7 +13320,7 @@ M:      David Airlie <airlied@linux.ie>
 M:     Gerd Hoffmann <kraxel@redhat.com>
 L:     dri-devel@lists.freedesktop.org
 L:     virtualization@lists.linux-foundation.org
-T:     git git://git.kraxel.org/linux drm-qemu
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 S:     Maintained
 F:     drivers/gpu/drm/virtio/
 F:     include/uapi/linux/virtio_gpu.h
index d195d617076d6cd86f1cea471a6d2d8a5835a636..0918d3f003d65d633a6e06a2c8d41a47fc42f9b5 100644 (file)
@@ -240,6 +240,8 @@ EXPORT_SYMBOL(dma_fence_enable_sw_signaling);
  * after it signals with dma_fence_signal. The callback itself can be called
  * from irq context.
  *
+ * Returns 0 in case of success, -ENOENT if the fence is already signaled
+ * and -EINVAL in case of error.
  */
 int dma_fence_add_callback(struct dma_fence *fence, struct dma_fence_cb *cb,
                           dma_fence_func_t func)
index 88e01e08e27923d83940078f9591ba16b4fe8e82..78d7fc0ebb57e69980059d1e01d02c5b988da95e 100644 (file)
@@ -99,6 +99,15 @@ config DRM_FBDEV_EMULATION
 
          If in doubt, say "Y".
 
+config DRM_FBDEV_OVERALLOC
+       int "Overallocation of the fbdev buffer"
+       depends on DRM_FBDEV_EMULATION
+       default 100
+       help
+         Defines the fbdev buffer overallocation in percent. Default
+         is 100. Typical values for double buffering will be 200,
+         triple buffering 300.
+
 config DRM_LOAD_EDID_FIRMWARE
        bool "Allow to specify an EDID data set instead of probing for it"
        depends on DRM_KMS_HELPER
index 36ce3cac81ba8541c845cf5bad0d10dcaf4137ee..72505b15dd13ea6f0fc36f8a1b4c19c942f14ebd 100644 (file)
@@ -224,7 +224,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
        info = drm_fb_helper_alloc_fbi(helper);
        if (IS_ERR(info)) {
                ret = PTR_ERR(info);
-               goto out_unref;
+               goto out;
        }
 
        info->par = rfbdev;
@@ -233,7 +233,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
        ret = amdgpu_framebuffer_init(adev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
        if (ret) {
                DRM_ERROR("failed to initialize framebuffer %d\n", ret);
-               goto out_destroy_fbi;
+               goto out;
        }
 
        fb = &rfbdev->rfb.base;
@@ -266,7 +266,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
 
        if (info->screen_base == NULL) {
                ret = -ENOSPC;
-               goto out_destroy_fbi;
+               goto out;
        }
 
        DRM_INFO("fb mappable at 0x%lX\n",  info->fix.smem_start);
@@ -278,9 +278,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
        vga_switcheroo_client_fb_set(adev->ddev->pdev, info);
        return 0;
 
-out_destroy_fbi:
-       drm_fb_helper_release_fbi(helper);
-out_unref:
+out:
        if (abo) {
 
        }
@@ -304,7 +302,6 @@ static int amdgpu_fbdev_destroy(struct drm_device *dev, struct amdgpu_fbdev *rfb
        struct amdgpu_framebuffer *rfb = &rfbdev->rfb;
 
        drm_fb_helper_unregister_fbi(&rfbdev->helper);
-       drm_fb_helper_release_fbi(&rfbdev->helper);
 
        if (rfb->obj) {
                amdgpufb_destroy_pinned_object(rfb->obj);
index 8d8344ed655e21f90c61515a3e3cbf01ab7ac2fc..1926b200e4cb3eade1178ec27fd95fd453f6d8b4 100644 (file)
@@ -175,7 +175,6 @@ static struct drm_driver arcpgu_drm_driver = {
        .dumb_create = drm_gem_cma_dumb_create,
        .dumb_map_offset = drm_gem_cma_dumb_map_offset,
        .dumb_destroy = drm_gem_dumb_destroy,
-       .get_vblank_counter = drm_vblank_no_hw_counter,
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
index 20ebfb4fbdfa39e7a97743a4e33ee3c8113b22e2..798a3cc480a2eefc8510417a883dcded6dedc741 100644 (file)
@@ -42,6 +42,24 @@ static void hdlcd_crtc_cleanup(struct drm_crtc *crtc)
        drm_crtc_cleanup(crtc);
 }
 
+static int hdlcd_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+       struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
+       unsigned int mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
+
+       hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, mask | HDLCD_INTERRUPT_VSYNC);
+
+       return 0;
+}
+
+static void hdlcd_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+       struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
+       unsigned int mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
+
+       hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, mask & ~HDLCD_INTERRUPT_VSYNC);
+}
+
 static const struct drm_crtc_funcs hdlcd_crtc_funcs = {
        .destroy = hdlcd_crtc_cleanup,
        .set_config = drm_atomic_helper_set_config,
@@ -49,6 +67,8 @@ static const struct drm_crtc_funcs hdlcd_crtc_funcs = {
        .reset = drm_atomic_helper_crtc_reset,
        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+       .enable_vblank = hdlcd_crtc_enable_vblank,
+       .disable_vblank = hdlcd_crtc_disable_vblank,
 };
 
 static struct simplefb_format supported_formats[] = SIMPLEFB_FORMATS;
index 4ce4f970920b24607cefc1539c2b600b0662995b..4840dc27733900edda44a2f42077ac3e9859086e 100644 (file)
@@ -199,24 +199,6 @@ static void hdlcd_irq_uninstall(struct drm_device *drm)
        hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
 }
 
-static int hdlcd_enable_vblank(struct drm_device *drm, unsigned int crtc)
-{
-       struct hdlcd_drm_private *hdlcd = drm->dev_private;
-       unsigned int mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
-
-       hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, mask | HDLCD_INTERRUPT_VSYNC);
-
-       return 0;
-}
-
-static void hdlcd_disable_vblank(struct drm_device *drm, unsigned int crtc)
-{
-       struct hdlcd_drm_private *hdlcd = drm->dev_private;
-       unsigned int mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
-
-       hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, mask & ~HDLCD_INTERRUPT_VSYNC);
-}
-
 #ifdef CONFIG_DEBUG_FS
 static int hdlcd_show_underrun_count(struct seq_file *m, void *arg)
 {
@@ -278,9 +260,6 @@ static struct drm_driver hdlcd_driver = {
        .irq_preinstall = hdlcd_irq_preinstall,
        .irq_postinstall = hdlcd_irq_postinstall,
        .irq_uninstall = hdlcd_irq_uninstall,
-       .get_vblank_counter = drm_vblank_no_hw_counter,
-       .enable_vblank = hdlcd_enable_vblank,
-       .disable_vblank = hdlcd_disable_vblank,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_vm_ops = &drm_gem_cma_vm_ops,
        .dumb_create = drm_gem_cma_dumb_create,
index 08e6a71f5d05f412946496f39ee82303d19a56a4..bad4d80cb711b8176ac45abe0c812a0a7c567a49 100644 (file)
@@ -167,6 +167,25 @@ static const struct drm_crtc_helper_funcs malidp_crtc_helper_funcs = {
        .atomic_check = malidp_crtc_atomic_check,
 };
 
+static int malidp_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+       struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
+       struct malidp_hw_device *hwdev = malidp->dev;
+
+       malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
+                            hwdev->map.de_irq_map.vsync_irq);
+       return 0;
+}
+
+static void malidp_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+       struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
+       struct malidp_hw_device *hwdev = malidp->dev;
+
+       malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK,
+                             hwdev->map.de_irq_map.vsync_irq);
+}
+
 static const struct drm_crtc_funcs malidp_crtc_funcs = {
        .destroy = drm_crtc_cleanup,
        .set_config = drm_atomic_helper_set_config,
@@ -174,6 +193,8 @@ static const struct drm_crtc_funcs malidp_crtc_funcs = {
        .reset = drm_atomic_helper_crtc_reset,
        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+       .enable_vblank = malidp_crtc_enable_vblank,
+       .disable_vblank = malidp_crtc_disable_vblank,
 };
 
 int malidp_crtc_init(struct drm_device *drm)
index 8b0672d4aee9137d316a454e3f4d219219d99028..a9608a2e5a29896f251523939ac9dfc4da1c2241 100644 (file)
@@ -100,7 +100,7 @@ static void malidp_atomic_commit_tail(struct drm_atomic_state *state)
        drm_atomic_helper_cleanup_planes(drm, state);
 }
 
-static struct drm_mode_config_helper_funcs malidp_mode_config_helpers = {
+static const struct drm_mode_config_helper_funcs malidp_mode_config_helpers = {
        .atomic_commit_tail = malidp_atomic_commit_tail,
 };
 
@@ -111,25 +111,6 @@ static const struct drm_mode_config_funcs malidp_mode_config_funcs = {
        .atomic_commit = drm_atomic_helper_commit,
 };
 
-static int malidp_enable_vblank(struct drm_device *drm, unsigned int crtc)
-{
-       struct malidp_drm *malidp = drm->dev_private;
-       struct malidp_hw_device *hwdev = malidp->dev;
-
-       malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
-                            hwdev->map.de_irq_map.vsync_irq);
-       return 0;
-}
-
-static void malidp_disable_vblank(struct drm_device *drm, unsigned int pipe)
-{
-       struct malidp_drm *malidp = drm->dev_private;
-       struct malidp_hw_device *hwdev = malidp->dev;
-
-       malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK,
-                             hwdev->map.de_irq_map.vsync_irq);
-}
-
 static int malidp_init(struct drm_device *drm)
 {
        int ret;
@@ -213,9 +194,6 @@ static struct drm_driver malidp_driver = {
        .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC |
                           DRIVER_PRIME,
        .lastclose = malidp_lastclose,
-       .get_vblank_counter = drm_vblank_no_hw_counter,
-       .enable_vblank = malidp_enable_vblank,
-       .disable_vblank = malidp_disable_vblank,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_vm_ops = &drm_gem_cma_vm_ops,
        .dumb_create = drm_gem_cma_dumb_create,
index e62ee4498ce49a11eed2b0e256e312883a4e58ef..1341e0b9368a4f796afcb654284e9043b9d7cfd0 100644 (file)
@@ -418,6 +418,25 @@ static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
        return true;
 }
 
+/* These are locked by dev->vbl_lock */
+static void armada_drm_crtc_disable_irq(struct armada_crtc *dcrtc, u32 mask)
+{
+       if (dcrtc->irq_ena & mask) {
+               dcrtc->irq_ena &= ~mask;
+               writel(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
+       }
+}
+
+static void armada_drm_crtc_enable_irq(struct armada_crtc *dcrtc, u32 mask)
+{
+       if ((dcrtc->irq_ena & mask) != mask) {
+               dcrtc->irq_ena |= mask;
+               writel(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
+               if (readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR) & mask)
+                       writel(0, dcrtc->base + LCD_SPU_IRQ_ISR);
+       }
+}
+
 static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
 {
        void __iomem *base = dcrtc->base;
@@ -491,25 +510,6 @@ static irqreturn_t armada_drm_irq(int irq, void *arg)
        return IRQ_NONE;
 }
 
-/* These are locked by dev->vbl_lock */
-void armada_drm_crtc_disable_irq(struct armada_crtc *dcrtc, u32 mask)
-{
-       if (dcrtc->irq_ena & mask) {
-               dcrtc->irq_ena &= ~mask;
-               writel(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
-       }
-}
-
-void armada_drm_crtc_enable_irq(struct armada_crtc *dcrtc, u32 mask)
-{
-       if ((dcrtc->irq_ena & mask) != mask) {
-               dcrtc->irq_ena |= mask;
-               writel(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
-               if (readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR) & mask)
-                       writel(0, dcrtc->base + LCD_SPU_IRQ_ISR);
-       }
-}
-
 static uint32_t armada_drm_crtc_calculate_csc(struct armada_crtc *dcrtc)
 {
        struct drm_display_mode *adj = &dcrtc->crtc.mode;
@@ -1109,6 +1109,22 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc,
        return 0;
 }
 
+/* These are called under the vbl_lock. */
+static int armada_drm_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+       struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+
+       armada_drm_crtc_enable_irq(dcrtc, VSYNC_IRQ_ENA);
+       return 0;
+}
+
+static void armada_drm_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+       struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+
+       armada_drm_crtc_disable_irq(dcrtc, VSYNC_IRQ_ENA);
+}
+
 static const struct drm_crtc_funcs armada_crtc_funcs = {
        .cursor_set     = armada_drm_crtc_cursor_set,
        .cursor_move    = armada_drm_crtc_cursor_move,
@@ -1116,6 +1132,8 @@ static const struct drm_crtc_funcs armada_crtc_funcs = {
        .set_config     = drm_crtc_helper_set_config,
        .page_flip      = armada_drm_crtc_page_flip,
        .set_property   = armada_drm_crtc_set_property,
+       .enable_vblank  = armada_drm_crtc_enable_vblank,
+       .disable_vblank = armada_drm_crtc_disable_vblank,
 };
 
 static const struct drm_plane_funcs armada_primary_plane_funcs = {
index b08043e8cc3b45c129fdb8c2bd90a0dde373ea77..7e8906d3ae2677bd8f644f1f0e3be8b1815719f0 100644 (file)
@@ -104,8 +104,6 @@ struct armada_crtc {
 
 void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int);
 void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int);
-void armada_drm_crtc_disable_irq(struct armada_crtc *, u32);
-void armada_drm_crtc_enable_irq(struct armada_crtc *, u32);
 void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *);
 
 void armada_drm_crtc_plane_disable(struct armada_crtc *dcrtc,
index a8020cf9da2ef1a7fc34f0048684f801e6787407..6758c3a83de24bde1d7201a2babfa70dc45bbf56 100644 (file)
@@ -107,40 +107,9 @@ static struct drm_info_list armada_debugfs_list[] = {
 };
 #define ARMADA_DEBUGFS_ENTRIES ARRAY_SIZE(armada_debugfs_list)
 
-static int drm_add_fake_info_node(struct drm_minor *minor, struct dentry *ent,
-       const void *key)
-{
-       struct drm_info_node *node;
-
-       node = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
-       if (!node) {
-               debugfs_remove(ent);
-               return -ENOMEM;
-       }
-
-       node->minor = minor;
-       node->dent = ent;
-       node->info_ent = (void *) key;
-
-       mutex_lock(&minor->debugfs_lock);
-       list_add(&node->list, &minor->debugfs_list);
-       mutex_unlock(&minor->debugfs_lock);
-
-       return 0;
-}
-
-static int armada_debugfs_create(struct dentry *root, struct drm_minor *minor,
-       const char *name, umode_t mode, const struct file_operations *fops)
-{
-       struct dentry *de;
-
-       de = debugfs_create_file(name, mode, root, minor->dev, fops);
-
-       return drm_add_fake_info_node(minor, de, fops);
-}
-
 int armada_drm_debugfs_init(struct drm_minor *minor)
 {
+       struct dentry *de;
        int ret;
 
        ret = drm_debugfs_create_files(armada_debugfs_list,
@@ -149,29 +118,15 @@ int armada_drm_debugfs_init(struct drm_minor *minor)
        if (ret)
                return ret;
 
-       ret = armada_debugfs_create(minor->debugfs_root, minor,
-                                  "reg", S_IFREG | S_IRUSR, &fops_reg_r);
-       if (ret)
-               goto err_1;
+       de = debugfs_create_file("reg", S_IFREG | S_IRUSR,
+                                minor->debugfs_root, minor->dev, &fops_reg_r);
+       if (!de)
+               return -ENOMEM;
 
-       ret = armada_debugfs_create(minor->debugfs_root, minor,
-                               "reg_wr", S_IFREG | S_IWUSR, &fops_reg_w);
-       if (ret)
-               goto err_2;
-       return ret;
-
- err_2:
-       drm_debugfs_remove_files((struct drm_info_list *)&fops_reg_r, 1, minor);
- err_1:
-       drm_debugfs_remove_files(armada_debugfs_list, ARMADA_DEBUGFS_ENTRIES,
-                                minor);
-       return ret;
-}
+       de = debugfs_create_file("reg_wr", S_IFREG | S_IWUSR,
+                                minor->debugfs_root, minor->dev, &fops_reg_w);
+       if (!de)
+               return -ENOMEM;
 
-void armada_drm_debugfs_cleanup(struct drm_minor *minor)
-{
-       drm_debugfs_remove_files((struct drm_info_list *)&fops_reg_w, 1, minor);
-       drm_debugfs_remove_files((struct drm_info_list *)&fops_reg_r, 1, minor);
-       drm_debugfs_remove_files(armada_debugfs_list, ARMADA_DEBUGFS_ENTRIES,
-                                minor);
+       return 0;
 }
index 77952d559a3c0370e126c0d0610512db9c0227d5..b064879ecdbd1073a379dbb438854094cdd30f80 100644 (file)
@@ -90,6 +90,5 @@ void armada_fbdev_fini(struct drm_device *);
 int armada_overlay_plane_create(struct drm_device *, unsigned long);
 
 int armada_drm_debugfs_init(struct drm_minor *);
-void armada_drm_debugfs_cleanup(struct drm_minor *);
 
 #endif
index 63f42d001f33d9ac1737d358c21ccdb4184083ff..1952e8748fea4788fc5664090fff3f62586b7280 100644 (file)
@@ -49,20 +49,6 @@ void armada_drm_queue_unref_work(struct drm_device *dev,
        spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
-/* These are called under the vbl_lock. */
-static int armada_drm_enable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-       struct armada_private *priv = dev->dev_private;
-       armada_drm_crtc_enable_irq(priv->dcrtc[pipe], VSYNC_IRQ_ENA);
-       return 0;
-}
-
-static void armada_drm_disable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-       struct armada_private *priv = dev->dev_private;
-       armada_drm_crtc_disable_irq(priv->dcrtc[pipe], VSYNC_IRQ_ENA);
-}
-
 static struct drm_ioctl_desc armada_ioctls[] = {
        DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl,0),
        DRM_IOCTL_DEF_DRV(ARMADA_GEM_MMAP, armada_gem_mmap_ioctl, 0),
@@ -87,9 +73,6 @@ static const struct file_operations armada_drm_fops = {
 
 static struct drm_driver armada_drm_driver = {
        .lastclose              = armada_drm_lastclose,
-       .get_vblank_counter     = drm_vblank_no_hw_counter,
-       .enable_vblank          = armada_drm_enable_vblank,
-       .disable_vblank         = armada_drm_disable_vblank,
        .gem_free_object_unlocked = armada_gem_free_object,
        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
@@ -226,9 +209,6 @@ static void armada_drm_unbind(struct device *dev)
        drm_kms_helper_poll_fini(&priv->drm);
        armada_fbdev_fini(&priv->drm);
 
-#ifdef CONFIG_DEBUG_FS
-       armada_drm_debugfs_cleanup(priv->drm.primary);
-#endif
        drm_dev_unregister(&priv->drm);
 
        component_unbind_all(dev, &priv->drm);
index 0233e1dc33e1b229f340ecc749c69c7435818f08..602dfead8eefa6b6bc70e3290fa9671efc3eada1 100644 (file)
@@ -157,7 +157,6 @@ int armada_fbdev_init(struct drm_device *dev)
 
        return 0;
  err_fb_setup:
-       drm_fb_helper_release_fbi(fbh);
        drm_fb_helper_fini(fbh);
  err_fb_helper:
        priv->fbdev = NULL;
@@ -179,7 +178,6 @@ void armada_fbdev_fini(struct drm_device *dev)
 
        if (fbh) {
                drm_fb_helper_unregister_fbi(fbh);
-               drm_fb_helper_release_fbi(fbh);
 
                drm_fb_helper_fini(fbh);
 
index 5d0ffab411a80b4a267ed24a26e2d2249c6b3f09..4ad4acd0ccab8528d52be211f321f7f589443dc1 100644 (file)
@@ -215,13 +215,13 @@ static int astfb_create(struct drm_fb_helper *helper,
        info = drm_fb_helper_alloc_fbi(helper);
        if (IS_ERR(info)) {
                ret = PTR_ERR(info);
-               goto err_free_vram;
+               goto out;
        }
        info->par = afbdev;
 
        ret = ast_framebuffer_init(dev, &afbdev->afb, &mode_cmd, gobj);
        if (ret)
-               goto err_release_fbi;
+               goto out;
 
        afbdev->sysram = sysram;
        afbdev->size = size;
@@ -250,9 +250,7 @@ static int astfb_create(struct drm_fb_helper *helper,
 
        return 0;
 
-err_release_fbi:
-       drm_fb_helper_release_fbi(helper);
-err_free_vram:
+out:
        vfree(sysram);
        return ret;
 }
@@ -287,7 +285,6 @@ static void ast_fbdev_destroy(struct drm_device *dev,
        struct ast_framebuffer *afb = &afbdev->afb;
 
        drm_fb_helper_unregister_fbi(&afbdev->helper);
-       drm_fb_helper_release_fbi(&afbdev->helper);
 
        if (afb->obj) {
                drm_gem_object_unreference_unlocked(afb->obj);
index 10ae426e60bd2cb0f36264f29c584d189558a386..bb5f8507a8cee8d893beb23117ad01da98b2c010 100644 (file)
@@ -1,6 +1,5 @@
 atmel-hlcdc-dc-y := atmel_hlcdc_crtc.o \
                atmel_hlcdc_dc.o \
-               atmel_hlcdc_layer.o \
                atmel_hlcdc_output.o \
                atmel_hlcdc_plane.o
 
index 9b17a66cf0e16245a50360d22d80a44e8602a94f..6b50fb706c0e6e0e77db14690adcda64f115168f 100644 (file)
@@ -434,6 +434,25 @@ static void atmel_hlcdc_crtc_destroy_state(struct drm_crtc *crtc,
        kfree(state);
 }
 
+static int atmel_hlcdc_crtc_enable_vblank(struct drm_crtc *c)
+{
+       struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
+       struct regmap *regmap = crtc->dc->hlcdc->regmap;
+
+       /* Enable SOF (Start Of Frame) interrupt for vblank counting */
+       regmap_write(regmap, ATMEL_HLCDC_IER, ATMEL_HLCDC_SOF);
+
+       return 0;
+}
+
+static void atmel_hlcdc_crtc_disable_vblank(struct drm_crtc *c)
+{
+       struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
+       struct regmap *regmap = crtc->dc->hlcdc->regmap;
+
+       regmap_write(regmap, ATMEL_HLCDC_IDR, ATMEL_HLCDC_SOF);
+}
+
 static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = {
        .page_flip = drm_atomic_helper_page_flip,
        .set_config = drm_atomic_helper_set_config,
@@ -441,12 +460,14 @@ static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = {
        .reset = atmel_hlcdc_crtc_reset,
        .atomic_duplicate_state =  atmel_hlcdc_crtc_duplicate_state,
        .atomic_destroy_state = atmel_hlcdc_crtc_destroy_state,
+       .enable_vblank = atmel_hlcdc_crtc_enable_vblank,
+       .disable_vblank = atmel_hlcdc_crtc_disable_vblank,
 };
 
 int atmel_hlcdc_crtc_create(struct drm_device *dev)
 {
+       struct atmel_hlcdc_plane *primary = NULL, *cursor = NULL;
        struct atmel_hlcdc_dc *dc = dev->dev_private;
-       struct atmel_hlcdc_planes *planes = dc->planes;
        struct atmel_hlcdc_crtc *crtc;
        int ret;
        int i;
@@ -457,20 +478,41 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev)
 
        crtc->dc = dc;
 
-       ret = drm_crtc_init_with_planes(dev, &crtc->base,
-                               &planes->primary->base,
-                               planes->cursor ? &planes->cursor->base : NULL,
-                               &atmel_hlcdc_crtc_funcs, NULL);
+       for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) {
+               if (!dc->layers[i])
+                       continue;
+
+               switch (dc->layers[i]->desc->type) {
+               case ATMEL_HLCDC_BASE_LAYER:
+                       primary = atmel_hlcdc_layer_to_plane(dc->layers[i]);
+                       break;
+
+               case ATMEL_HLCDC_CURSOR_LAYER:
+                       cursor = atmel_hlcdc_layer_to_plane(dc->layers[i]);
+                       break;
+
+               default:
+                       break;
+               }
+       }
+
+       ret = drm_crtc_init_with_planes(dev, &crtc->base, &primary->base,
+                                       &cursor->base, &atmel_hlcdc_crtc_funcs,
+                                       NULL);
        if (ret < 0)
                goto fail;
 
        crtc->id = drm_crtc_index(&crtc->base);
 
-       if (planes->cursor)
-               planes->cursor->base.possible_crtcs = 1 << crtc->id;
+       for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) {
+               struct atmel_hlcdc_plane *overlay;
 
-       for (i = 0; i < planes->noverlays; i++)
-               planes->overlays[i]->base.possible_crtcs = 1 << crtc->id;
+               if (dc->layers[i] &&
+                   dc->layers[i]->desc->type == ATMEL_HLCDC_OVERLAY_LAYER) {
+                       overlay = atmel_hlcdc_layer_to_plane(dc->layers[i]);
+                       overlay->base.possible_crtcs = 1 << crtc->id;
+               }
+       }
 
        drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs);
        drm_crtc_vblank_reset(&crtc->base);
index 427bdff425c24fc502e8b767eb6dcc26cd367289..970bd87d7ccec26a8699eb5fb2f289c4b4cb2d69 100644 (file)
@@ -36,7 +36,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9n12_layers[] = {
                .regs_offset = 0x40,
                .id = 0,
                .type = ATMEL_HLCDC_BASE_LAYER,
-               .nconfigs = 5,
+               .cfgs_offset = 0x2c,
                .layout = {
                        .xstride = { 2 },
                        .default_color = 3,
@@ -65,7 +65,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
                .regs_offset = 0x40,
                .id = 0,
                .type = ATMEL_HLCDC_BASE_LAYER,
-               .nconfigs = 5,
+               .cfgs_offset = 0x2c,
                .layout = {
                        .xstride = { 2 },
                        .default_color = 3,
@@ -80,7 +80,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
                .regs_offset = 0x100,
                .id = 1,
                .type = ATMEL_HLCDC_OVERLAY_LAYER,
-               .nconfigs = 10,
+               .cfgs_offset = 0x2c,
                .layout = {
                        .pos = 2,
                        .size = 3,
@@ -98,7 +98,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
                .regs_offset = 0x280,
                .id = 2,
                .type = ATMEL_HLCDC_OVERLAY_LAYER,
-               .nconfigs = 17,
+               .cfgs_offset = 0x4c,
                .layout = {
                        .pos = 2,
                        .size = 3,
@@ -109,6 +109,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
                        .chroma_key = 10,
                        .chroma_key_mask = 11,
                        .general_config = 12,
+                       .scaler_config = 13,
                        .csc = 14,
                },
        },
@@ -118,9 +119,9 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
                .regs_offset = 0x340,
                .id = 3,
                .type = ATMEL_HLCDC_CURSOR_LAYER,
-               .nconfigs = 10,
                .max_width = 128,
                .max_height = 128,
+               .cfgs_offset = 0x2c,
                .layout = {
                        .pos = 2,
                        .size = 3,
@@ -153,7 +154,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
                .regs_offset = 0x40,
                .id = 0,
                .type = ATMEL_HLCDC_BASE_LAYER,
-               .nconfigs = 7,
+               .cfgs_offset = 0x2c,
                .layout = {
                        .xstride = { 2 },
                        .default_color = 3,
@@ -168,7 +169,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
                .regs_offset = 0x140,
                .id = 1,
                .type = ATMEL_HLCDC_OVERLAY_LAYER,
-               .nconfigs = 10,
+               .cfgs_offset = 0x2c,
                .layout = {
                        .pos = 2,
                        .size = 3,
@@ -186,7 +187,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
                .regs_offset = 0x240,
                .id = 2,
                .type = ATMEL_HLCDC_OVERLAY_LAYER,
-               .nconfigs = 10,
+               .cfgs_offset = 0x2c,
                .layout = {
                        .pos = 2,
                        .size = 3,
@@ -204,7 +205,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
                .regs_offset = 0x340,
                .id = 3,
                .type = ATMEL_HLCDC_OVERLAY_LAYER,
-               .nconfigs = 42,
+               .cfgs_offset = 0x4c,
                .layout = {
                        .pos = 2,
                        .size = 3,
@@ -215,6 +216,11 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
                        .chroma_key = 10,
                        .chroma_key_mask = 11,
                        .general_config = 12,
+                       .scaler_config = 13,
+                       .phicoeffs = {
+                               .x = 17,
+                               .y = 33,
+                       },
                        .csc = 14,
                },
        },
@@ -224,9 +230,9 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
                .regs_offset = 0x440,
                .id = 4,
                .type = ATMEL_HLCDC_CURSOR_LAYER,
-               .nconfigs = 10,
                .max_width = 128,
                .max_height = 128,
+               .cfgs_offset = 0x2c,
                .layout = {
                        .pos = 2,
                        .size = 3,
@@ -236,6 +242,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
                        .chroma_key = 7,
                        .chroma_key_mask = 8,
                        .general_config = 9,
+                       .scaler_config = 13,
                },
        },
 };
@@ -260,7 +267,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
                .regs_offset = 0x40,
                .id = 0,
                .type = ATMEL_HLCDC_BASE_LAYER,
-               .nconfigs = 7,
+               .cfgs_offset = 0x2c,
                .layout = {
                        .xstride = { 2 },
                        .default_color = 3,
@@ -275,7 +282,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
                .regs_offset = 0x140,
                .id = 1,
                .type = ATMEL_HLCDC_OVERLAY_LAYER,
-               .nconfigs = 10,
+               .cfgs_offset = 0x2c,
                .layout = {
                        .pos = 2,
                        .size = 3,
@@ -293,7 +300,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
                .regs_offset = 0x240,
                .id = 2,
                .type = ATMEL_HLCDC_OVERLAY_LAYER,
-               .nconfigs = 10,
+               .cfgs_offset = 0x2c,
                .layout = {
                        .pos = 2,
                        .size = 3,
@@ -311,7 +318,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
                .regs_offset = 0x340,
                .id = 3,
                .type = ATMEL_HLCDC_OVERLAY_LAYER,
-               .nconfigs = 42,
+               .cfgs_offset = 0x4c,
                .layout = {
                        .pos = 2,
                        .size = 3,
@@ -322,6 +329,11 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
                        .chroma_key = 10,
                        .chroma_key_mask = 11,
                        .general_config = 12,
+                       .scaler_config = 13,
+                       .phicoeffs = {
+                               .x = 17,
+                               .y = 33,
+                       },
                        .csc = 14,
                },
        },
@@ -392,6 +404,17 @@ int atmel_hlcdc_dc_mode_valid(struct atmel_hlcdc_dc *dc,
        return MODE_OK;
 }
 
+static void atmel_hlcdc_layer_irq(struct atmel_hlcdc_layer *layer)
+{
+       if (!layer)
+               return;
+
+       if (layer->desc->type == ATMEL_HLCDC_BASE_LAYER ||
+           layer->desc->type == ATMEL_HLCDC_OVERLAY_LAYER ||
+           layer->desc->type == ATMEL_HLCDC_CURSOR_LAYER)
+               atmel_hlcdc_plane_irq(atmel_hlcdc_layer_to_plane(layer));
+}
+
 static irqreturn_t atmel_hlcdc_dc_irq_handler(int irq, void *data)
 {
        struct drm_device *dev = data;
@@ -410,12 +433,8 @@ static irqreturn_t atmel_hlcdc_dc_irq_handler(int irq, void *data)
                atmel_hlcdc_crtc_irq(dc->crtc);
 
        for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) {
-               struct atmel_hlcdc_layer *layer = dc->layers[i];
-
-               if (!(ATMEL_HLCDC_LAYER_STATUS(i) & status) || !layer)
-                       continue;
-
-               atmel_hlcdc_layer_irq(layer);
+               if (ATMEL_HLCDC_LAYER_STATUS(i) & status)
+                       atmel_hlcdc_layer_irq(dc->layers[i]);
        }
 
        return IRQ_HANDLED;
@@ -537,9 +556,7 @@ static const struct drm_mode_config_funcs mode_config_funcs = {
 static int atmel_hlcdc_dc_modeset_init(struct drm_device *dev)
 {
        struct atmel_hlcdc_dc *dc = dev->dev_private;
-       struct atmel_hlcdc_planes *planes;
        int ret;
-       int i;
 
        drm_mode_config_init(dev);
 
@@ -549,25 +566,12 @@ static int atmel_hlcdc_dc_modeset_init(struct drm_device *dev)
                return ret;
        }
 
-       planes = atmel_hlcdc_create_planes(dev);
-       if (IS_ERR(planes)) {
-               dev_err(dev->dev, "failed to create planes\n");
-               return PTR_ERR(planes);
+       ret = atmel_hlcdc_create_planes(dev);
+       if (ret) {
+               dev_err(dev->dev, "failed to create planes: %d\n", ret);
+               return ret;
        }
 
-       dc->planes = planes;
-
-       dc->layers[planes->primary->layer.desc->id] =
-                                               &planes->primary->layer;
-
-       if (planes->cursor)
-               dc->layers[planes->cursor->layer.desc->id] =
-                                                       &planes->cursor->layer;
-
-       for (i = 0; i < planes->noverlays; i++)
-               dc->layers[planes->overlays[i]->layer.desc->id] =
-                                               &planes->overlays[i]->layer;
-
        ret = atmel_hlcdc_crtc_create(dev);
        if (ret) {
                dev_err(dev->dev, "failed to create crtc\n");
@@ -720,25 +724,6 @@ static void atmel_hlcdc_dc_irq_uninstall(struct drm_device *dev)
        regmap_read(dc->hlcdc->regmap, ATMEL_HLCDC_ISR, &isr);
 }
 
-static int atmel_hlcdc_dc_enable_vblank(struct drm_device *dev,
-                                       unsigned int pipe)
-{
-       struct atmel_hlcdc_dc *dc = dev->dev_private;
-
-       /* Enable SOF (Start Of Frame) interrupt for vblank counting */
-       regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IER, ATMEL_HLCDC_SOF);
-
-       return 0;
-}
-
-static void atmel_hlcdc_dc_disable_vblank(struct drm_device *dev,
-                                         unsigned int pipe)
-{
-       struct atmel_hlcdc_dc *dc = dev->dev_private;
-
-       regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IDR, ATMEL_HLCDC_SOF);
-}
-
 static const struct file_operations fops = {
        .owner              = THIS_MODULE,
        .open               = drm_open,
@@ -760,9 +745,6 @@ static struct drm_driver atmel_hlcdc_dc_driver = {
        .irq_preinstall = atmel_hlcdc_dc_irq_uninstall,
        .irq_postinstall = atmel_hlcdc_dc_irq_postinstall,
        .irq_uninstall = atmel_hlcdc_dc_irq_uninstall,
-       .get_vblank_counter = drm_vblank_no_hw_counter,
-       .enable_vblank = atmel_hlcdc_dc_enable_vblank,
-       .disable_vblank = atmel_hlcdc_dc_disable_vblank,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_vm_ops = &drm_gem_cma_vm_ops,
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
index 7a47f8c094d021d75a3ec86263145eb8326d7f22..da7f25a59be58445a9f3b79c72b716960dcc4175 100644 (file)
@@ -23,7 +23,9 @@
 #define DRM_ATMEL_HLCDC_H
 
 #include <linux/clk.h>
+#include <linux/dmapool.h>
 #include <linux/irqdomain.h>
+#include <linux/mfd/atmel-hlcdc.h>
 #include <linux/pwm.h>
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drmP.h>
 
-#include "atmel_hlcdc_layer.h"
+#define ATMEL_HLCDC_LAYER_CHER                 0x0
+#define ATMEL_HLCDC_LAYER_CHDR                 0x4
+#define ATMEL_HLCDC_LAYER_CHSR                 0x8
+#define ATMEL_HLCDC_LAYER_EN                   BIT(0)
+#define ATMEL_HLCDC_LAYER_UPDATE               BIT(1)
+#define ATMEL_HLCDC_LAYER_A2Q                  BIT(2)
+#define ATMEL_HLCDC_LAYER_RST                  BIT(8)
 
-#define ATMEL_HLCDC_MAX_LAYERS         5
+#define ATMEL_HLCDC_LAYER_IER                  0xc
+#define ATMEL_HLCDC_LAYER_IDR                  0x10
+#define ATMEL_HLCDC_LAYER_IMR                  0x14
+#define ATMEL_HLCDC_LAYER_ISR                  0x18
+#define ATMEL_HLCDC_LAYER_DFETCH               BIT(0)
+#define ATMEL_HLCDC_LAYER_LFETCH               BIT(1)
+#define ATMEL_HLCDC_LAYER_DMA_IRQ(p)           BIT(2 + (8 * (p)))
+#define ATMEL_HLCDC_LAYER_DSCR_IRQ(p)          BIT(3 + (8 * (p)))
+#define ATMEL_HLCDC_LAYER_ADD_IRQ(p)           BIT(4 + (8 * (p)))
+#define ATMEL_HLCDC_LAYER_DONE_IRQ(p)          BIT(5 + (8 * (p)))
+#define ATMEL_HLCDC_LAYER_OVR_IRQ(p)           BIT(6 + (8 * (p)))
+
+#define ATMEL_HLCDC_LAYER_PLANE_HEAD(p)                (((p) * 0x10) + 0x1c)
+#define ATMEL_HLCDC_LAYER_PLANE_ADDR(p)                (((p) * 0x10) + 0x20)
+#define ATMEL_HLCDC_LAYER_PLANE_CTRL(p)                (((p) * 0x10) + 0x24)
+#define ATMEL_HLCDC_LAYER_PLANE_NEXT(p)                (((p) * 0x10) + 0x28)
+
+#define ATMEL_HLCDC_LAYER_DMA_CFG              0
+#define ATMEL_HLCDC_LAYER_DMA_SIF              BIT(0)
+#define ATMEL_HLCDC_LAYER_DMA_BLEN_MASK                GENMASK(5, 4)
+#define ATMEL_HLCDC_LAYER_DMA_BLEN_SINGLE      (0 << 4)
+#define ATMEL_HLCDC_LAYER_DMA_BLEN_INCR4       (1 << 4)
+#define ATMEL_HLCDC_LAYER_DMA_BLEN_INCR8       (2 << 4)
+#define ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16      (3 << 4)
+#define ATMEL_HLCDC_LAYER_DMA_DLBO             BIT(8)
+#define ATMEL_HLCDC_LAYER_DMA_ROTDIS           BIT(12)
+#define ATMEL_HLCDC_LAYER_DMA_LOCKDIS          BIT(13)
+
+#define ATMEL_HLCDC_LAYER_FORMAT_CFG           1
+#define ATMEL_HLCDC_LAYER_RGB                  (0 << 0)
+#define ATMEL_HLCDC_LAYER_CLUT                 (1 << 0)
+#define ATMEL_HLCDC_LAYER_YUV                  (2 << 0)
+#define ATMEL_HLCDC_RGB_MODE(m)                        \
+       (ATMEL_HLCDC_LAYER_RGB | (((m) & 0xf) << 4))
+#define ATMEL_HLCDC_CLUT_MODE(m)               \
+       (ATMEL_HLCDC_LAYER_CLUT | (((m) & 0x3) << 8))
+#define ATMEL_HLCDC_YUV_MODE(m)                        \
+       (ATMEL_HLCDC_LAYER_YUV | (((m) & 0xf) << 12))
+#define ATMEL_HLCDC_YUV422ROT                  BIT(16)
+#define ATMEL_HLCDC_YUV422SWP                  BIT(17)
+#define ATMEL_HLCDC_DSCALEOPT                  BIT(20)
+
+#define ATMEL_HLCDC_XRGB4444_MODE              ATMEL_HLCDC_RGB_MODE(0)
+#define ATMEL_HLCDC_ARGB4444_MODE              ATMEL_HLCDC_RGB_MODE(1)
+#define ATMEL_HLCDC_RGBA4444_MODE              ATMEL_HLCDC_RGB_MODE(2)
+#define ATMEL_HLCDC_RGB565_MODE                        ATMEL_HLCDC_RGB_MODE(3)
+#define ATMEL_HLCDC_ARGB1555_MODE              ATMEL_HLCDC_RGB_MODE(4)
+#define ATMEL_HLCDC_XRGB8888_MODE              ATMEL_HLCDC_RGB_MODE(9)
+#define ATMEL_HLCDC_RGB888_MODE                        ATMEL_HLCDC_RGB_MODE(10)
+#define ATMEL_HLCDC_ARGB8888_MODE              ATMEL_HLCDC_RGB_MODE(12)
+#define ATMEL_HLCDC_RGBA8888_MODE              ATMEL_HLCDC_RGB_MODE(13)
+
+#define ATMEL_HLCDC_AYUV_MODE                  ATMEL_HLCDC_YUV_MODE(0)
+#define ATMEL_HLCDC_YUYV_MODE                  ATMEL_HLCDC_YUV_MODE(1)
+#define ATMEL_HLCDC_UYVY_MODE                  ATMEL_HLCDC_YUV_MODE(2)
+#define ATMEL_HLCDC_YVYU_MODE                  ATMEL_HLCDC_YUV_MODE(3)
+#define ATMEL_HLCDC_VYUY_MODE                  ATMEL_HLCDC_YUV_MODE(4)
+#define ATMEL_HLCDC_NV61_MODE                  ATMEL_HLCDC_YUV_MODE(5)
+#define ATMEL_HLCDC_YUV422_MODE                        ATMEL_HLCDC_YUV_MODE(6)
+#define ATMEL_HLCDC_NV21_MODE                  ATMEL_HLCDC_YUV_MODE(7)
+#define ATMEL_HLCDC_YUV420_MODE                        ATMEL_HLCDC_YUV_MODE(8)
+
+#define ATMEL_HLCDC_LAYER_POS(x, y)            ((x) | ((y) << 16))
+#define ATMEL_HLCDC_LAYER_SIZE(w, h)           (((w) - 1) | (((h) - 1) << 16))
+
+#define ATMEL_HLCDC_LAYER_CRKEY                        BIT(0)
+#define ATMEL_HLCDC_LAYER_INV                  BIT(1)
+#define ATMEL_HLCDC_LAYER_ITER2BL              BIT(2)
+#define ATMEL_HLCDC_LAYER_ITER                 BIT(3)
+#define ATMEL_HLCDC_LAYER_REVALPHA             BIT(4)
+#define ATMEL_HLCDC_LAYER_GAEN                 BIT(5)
+#define ATMEL_HLCDC_LAYER_LAEN                 BIT(6)
+#define ATMEL_HLCDC_LAYER_OVR                  BIT(7)
+#define ATMEL_HLCDC_LAYER_DMA                  BIT(8)
+#define ATMEL_HLCDC_LAYER_REP                  BIT(9)
+#define ATMEL_HLCDC_LAYER_DSTKEY               BIT(10)
+#define ATMEL_HLCDC_LAYER_DISCEN               BIT(11)
+#define ATMEL_HLCDC_LAYER_GA_SHIFT             16
+#define ATMEL_HLCDC_LAYER_GA_MASK              \
+       GENMASK(23, ATMEL_HLCDC_LAYER_GA_SHIFT)
+#define ATMEL_HLCDC_LAYER_GA(x)                        \
+       ((x) << ATMEL_HLCDC_LAYER_GA_SHIFT)
+
+#define ATMEL_HLCDC_LAYER_DISC_POS(x, y)       ((x) | ((y) << 16))
+#define ATMEL_HLCDC_LAYER_DISC_SIZE(w, h)      (((w) - 1) | (((h) - 1) << 16))
+
+#define ATMEL_HLCDC_LAYER_SCALER_FACTORS(x, y) ((x) | ((y) << 16))
+#define ATMEL_HLCDC_LAYER_SCALER_ENABLE                BIT(31)
+
+#define ATMEL_HLCDC_LAYER_MAX_PLANES           3
+
+#define ATMEL_HLCDC_DMA_CHANNEL_DSCR_RESERVED  BIT(0)
+#define ATMEL_HLCDC_DMA_CHANNEL_DSCR_LOADED    BIT(1)
+#define ATMEL_HLCDC_DMA_CHANNEL_DSCR_DONE      BIT(2)
+#define ATMEL_HLCDC_DMA_CHANNEL_DSCR_OVERRUN   BIT(3)
+
+#define ATMEL_HLCDC_MAX_LAYERS                 6
 
 /**
- * Atmel HLCDC Display Controller description structure.
+ * Atmel HLCDC Layer registers layout structure
  *
- * This structure describe the HLCDC IP capabilities and depends on the
- * HLCDC IP version (or Atmel SoC family).
+ * Each HLCDC layer has its own register organization and a given register
+ * can be placed differently on 2 different layers depending on its
+ * capabilities.
+ * This structure stores common registers layout for a given layer and is
+ * used by HLCDC layer code to choose the appropriate register to write to
+ * or to read from.
  *
- * @min_width: minimum width supported by the Display Controller
- * @min_height: minimum height supported by the Display Controller
- * @max_width: maximum width supported by the Display Controller
- * @max_height: maximum height supported by the Display Controller
- * @max_spw: maximum vertical/horizontal pulse width
- * @max_vpw: maximum vertical back/front porch width
- * @max_hpw: maximum horizontal back/front porch width
- * @conflicting_output_formats: true if RGBXXX output formats conflict with
- *                             each other.
- * @layers: a layer description table describing available layers
- * @nlayers: layer description table size
+ * For all fields, a value of zero means "unsupported".
+ *
+ * See Atmel's datasheet for a detailled description of these registers.
+ *
+ * @xstride: xstride registers
+ * @pstride: pstride registers
+ * @pos: position register
+ * @size: displayed size register
+ * @memsize: memory size register
+ * @default_color: default color register
+ * @chroma_key: chroma key register
+ * @chroma_key_mask: chroma key mask register
+ * @general_config: general layer config register
+ * @sacler_config: scaler factors register
+ * @phicoeffs: X/Y PHI coefficient registers
+ * @disc_pos: discard area position register
+ * @disc_size: discard area size register
+ * @csc: color space conversion register
  */
-struct atmel_hlcdc_dc_desc {
-       int min_width;
-       int min_height;
+struct atmel_hlcdc_layer_cfg_layout {
+       int xstride[ATMEL_HLCDC_LAYER_MAX_PLANES];
+       int pstride[ATMEL_HLCDC_LAYER_MAX_PLANES];
+       int pos;
+       int size;
+       int memsize;
+       int default_color;
+       int chroma_key;
+       int chroma_key_mask;
+       int general_config;
+       int scaler_config;
+       struct {
+               int x;
+               int y;
+       } phicoeffs;
+       int disc_pos;
+       int disc_size;
+       int csc;
+};
+
+/**
+ * Atmel HLCDC DMA descriptor structure
+ *
+ * This structure is used by the HLCDC DMA engine to schedule a DMA transfer.
+ *
+ * The structure fields must remain in this specific order, because they're
+ * used by the HLCDC DMA engine, which expect them in this order.
+ * HLCDC DMA descriptors must be aligned on 64 bits.
+ *
+ * @addr: buffer DMA address
+ * @ctrl: DMA transfer options
+ * @next: next DMA descriptor to fetch
+ * @self: descriptor DMA address
+ */
+struct atmel_hlcdc_dma_channel_dscr {
+       dma_addr_t addr;
+       u32 ctrl;
+       dma_addr_t next;
+       dma_addr_t self;
+} __aligned(sizeof(u64));
+
+/**
+ * Atmel HLCDC layer types
+ */
+enum atmel_hlcdc_layer_type {
+       ATMEL_HLCDC_NO_LAYER,
+       ATMEL_HLCDC_BASE_LAYER,
+       ATMEL_HLCDC_OVERLAY_LAYER,
+       ATMEL_HLCDC_CURSOR_LAYER,
+       ATMEL_HLCDC_PP_LAYER,
+};
+
+/**
+ * Atmel HLCDC Supported formats structure
+ *
+ * This structure list all the formats supported by a given layer.
+ *
+ * @nformats: number of supported formats
+ * @formats: supported formats
+ */
+struct atmel_hlcdc_formats {
+       int nformats;
+       u32 *formats;
+};
+
+/**
+ * Atmel HLCDC Layer description structure
+ *
+ * This structure describes the capabilities provided by a given layer.
+ *
+ * @name: layer name
+ * @type: layer type
+ * @id: layer id
+ * @regs_offset: offset of the layer registers from the HLCDC registers base
+ * @cfgs_offset: CFGX registers offset from the layer registers base
+ * @formats: supported formats
+ * @layout: config registers layout
+ * @max_width: maximum width supported by this layer (0 means unlimited)
+ * @max_height: maximum height supported by this layer (0 means unlimited)
+ */
+struct atmel_hlcdc_layer_desc {
+       const char *name;
+       enum atmel_hlcdc_layer_type type;
+       int id;
+       int regs_offset;
+       int cfgs_offset;
+       struct atmel_hlcdc_formats *formats;
+       struct atmel_hlcdc_layer_cfg_layout layout;
        int max_width;
        int max_height;
-       int max_spw;
-       int max_vpw;
-       int max_hpw;
-       bool conflicting_output_formats;
-       const struct atmel_hlcdc_layer_desc *layers;
-       int nlayers;
 };
 
 /**
- * Atmel HLCDC Plane properties.
+ * Atmel HLCDC Layer.
  *
- * This structure stores plane property definitions.
+ * A layer can be a DRM plane of a post processing layer used to render
+ * HLCDC composition into memory.
  *
- * @alpha: alpha blending (or transparency) property
- * @rotation: rotation property
+ * @desc: layer description
+ * @regmap: pointer to the HLCDC regmap
  */
-struct atmel_hlcdc_plane_properties {
-       struct drm_property *alpha;
+struct atmel_hlcdc_layer {
+       const struct atmel_hlcdc_layer_desc *desc;
+       struct regmap *regmap;
 };
 
 /**
@@ -89,7 +285,6 @@ struct atmel_hlcdc_plane_properties {
  * @base: base DRM plane structure
  * @layer: HLCDC layer structure
  * @properties: pointer to the property definitions structure
- * @rotation: current rotation status
  */
 struct atmel_hlcdc_plane {
        struct drm_plane base;
@@ -104,47 +299,73 @@ drm_plane_to_atmel_hlcdc_plane(struct drm_plane *p)
 }
 
 static inline struct atmel_hlcdc_plane *
-atmel_hlcdc_layer_to_plane(struct atmel_hlcdc_layer *l)
+atmel_hlcdc_layer_to_plane(struct atmel_hlcdc_layer *layer)
 {
-       return container_of(l, struct atmel_hlcdc_plane, layer);
+       return container_of(layer, struct atmel_hlcdc_plane, layer);
 }
 
 /**
- * Atmel HLCDC Planes.
+ * Atmel HLCDC Display Controller description structure.
  *
- * This structure stores the instantiated HLCDC Planes and can be accessed by
- * the HLCDC Display Controller or the HLCDC CRTC.
+ * This structure describes the HLCDC IP capabilities and depends on the
+ * HLCDC IP version (or Atmel SoC family).
  *
- * @primary: primary plane
- * @cursor: hardware cursor plane
- * @overlays: overlay plane table
- * @noverlays: number of overlay planes
+ * @min_width: minimum width supported by the Display Controller
+ * @min_height: minimum height supported by the Display Controller
+ * @max_width: maximum width supported by the Display Controller
+ * @max_height: maximum height supported by the Display Controller
+ * @max_spw: maximum vertical/horizontal pulse width
+ * @max_vpw: maximum vertical back/front porch width
+ * @max_hpw: maximum horizontal back/front porch width
+ * @conflicting_output_formats: true if RGBXXX output formats conflict with
+ *                             each other.
+ * @layers: a layer description table describing available layers
+ * @nlayers: layer description table size
  */
-struct atmel_hlcdc_planes {
-       struct atmel_hlcdc_plane *primary;
-       struct atmel_hlcdc_plane *cursor;
-       struct atmel_hlcdc_plane **overlays;
-       int noverlays;
+struct atmel_hlcdc_dc_desc {
+       int min_width;
+       int min_height;
+       int max_width;
+       int max_height;
+       int max_spw;
+       int max_vpw;
+       int max_hpw;
+       bool conflicting_output_formats;
+       const struct atmel_hlcdc_layer_desc *layers;
+       int nlayers;
+};
+
+/**
+ * Atmel HLCDC Plane properties.
+ *
+ * This structure stores plane property definitions.
+ *
+ * @alpha: alpha blending (or transparency) property
+ * @rotation: rotation property
+ */
+struct atmel_hlcdc_plane_properties {
+       struct drm_property *alpha;
 };
 
 /**
  * Atmel HLCDC Display Controller.
  *
  * @desc: HLCDC Display Controller description
+ * @dscrpool: DMA coherent pool used to allocate DMA descriptors
  * @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device
  * @fbdev: framebuffer device attached to the Display Controller
  * @crtc: CRTC provided by the display controller
  * @planes: instantiated planes
- * @layers: active HLCDC layer
+ * @layers: active HLCDC layers
  * @wq: display controller workqueue
  * @commit: used for async commit handling
  */
 struct atmel_hlcdc_dc {
        const struct atmel_hlcdc_dc_desc *desc;
+       struct dma_pool *dscrpool;
        struct atmel_hlcdc *hlcdc;
        struct drm_fbdev_cma *fbdev;
        struct drm_crtc *crtc;
-       struct atmel_hlcdc_planes *planes;
        struct atmel_hlcdc_layer *layers[ATMEL_HLCDC_MAX_LAYERS];
        struct workqueue_struct *wq;
        struct {
@@ -156,11 +377,51 @@ struct atmel_hlcdc_dc {
 extern struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats;
 extern struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_and_yuv_formats;
 
+static inline void atmel_hlcdc_layer_write_reg(struct atmel_hlcdc_layer *layer,
+                                              unsigned int reg, u32 val)
+{
+       regmap_write(layer->regmap, layer->desc->regs_offset + reg, val);
+}
+
+static inline u32 atmel_hlcdc_layer_read_reg(struct atmel_hlcdc_layer *layer,
+                                            unsigned int reg)
+{
+       u32 val;
+
+       regmap_read(layer->regmap, layer->desc->regs_offset + reg, &val);
+
+       return val;
+}
+
+static inline void atmel_hlcdc_layer_write_cfg(struct atmel_hlcdc_layer *layer,
+                                              unsigned int cfgid, u32 val)
+{
+       atmel_hlcdc_layer_write_reg(layer,
+                                   layer->desc->cfgs_offset +
+                                   (cfgid * sizeof(u32)), val);
+}
+
+static inline u32 atmel_hlcdc_layer_read_cfg(struct atmel_hlcdc_layer *layer,
+                                            unsigned int cfgid)
+{
+       return atmel_hlcdc_layer_read_reg(layer,
+                                         layer->desc->cfgs_offset +
+                                         (cfgid * sizeof(u32)));
+}
+
+static inline void atmel_hlcdc_layer_init(struct atmel_hlcdc_layer *layer,
+                               const struct atmel_hlcdc_layer_desc *desc,
+                               struct regmap *regmap)
+{
+       layer->desc = desc;
+       layer->regmap = regmap;
+}
+
 int atmel_hlcdc_dc_mode_valid(struct atmel_hlcdc_dc *dc,
                              struct drm_display_mode *mode);
 
-struct atmel_hlcdc_planes *
-atmel_hlcdc_create_planes(struct drm_device *dev);
+int atmel_hlcdc_create_planes(struct drm_device *dev);
+void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane);
 
 int atmel_hlcdc_plane_prepare_disc_area(struct drm_crtc_state *c_state);
 int atmel_hlcdc_plane_prepare_ahb_routing(struct drm_crtc_state *c_state);
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_layer.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_layer.c
deleted file mode 100644 (file)
index 63dfdbf..0000000
+++ /dev/null
@@ -1,666 +0,0 @@
-/*
- * Copyright (C) 2014 Free Electrons
- * Copyright (C) 2014 Atmel
- *
- * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-
-#include "atmel_hlcdc_dc.h"
-
-static void
-atmel_hlcdc_layer_fb_flip_release(struct drm_flip_work *work, void *val)
-{
-       struct atmel_hlcdc_layer_fb_flip *flip = val;
-
-       if (flip->fb)
-               drm_framebuffer_unreference(flip->fb);
-       kfree(flip);
-}
-
-static void
-atmel_hlcdc_layer_fb_flip_destroy(struct atmel_hlcdc_layer_fb_flip *flip)
-{
-       if (flip->fb)
-               drm_framebuffer_unreference(flip->fb);
-       kfree(flip->task);
-       kfree(flip);
-}
-
-static void
-atmel_hlcdc_layer_fb_flip_release_queue(struct atmel_hlcdc_layer *layer,
-                                       struct atmel_hlcdc_layer_fb_flip *flip)
-{
-       int i;
-
-       if (!flip)
-               return;
-
-       for (i = 0; i < layer->max_planes; i++) {
-               if (!flip->dscrs[i])
-                       break;
-
-               flip->dscrs[i]->status = 0;
-               flip->dscrs[i] = NULL;
-       }
-
-       drm_flip_work_queue_task(&layer->gc, flip->task);
-       drm_flip_work_commit(&layer->gc, layer->wq);
-}
-
-static void atmel_hlcdc_layer_update_reset(struct atmel_hlcdc_layer *layer,
-                                          int id)
-{
-       struct atmel_hlcdc_layer_update *upd = &layer->update;
-       struct atmel_hlcdc_layer_update_slot *slot;
-
-       if (id < 0 || id > 1)
-               return;
-
-       slot = &upd->slots[id];
-       bitmap_clear(slot->updated_configs, 0, layer->desc->nconfigs);
-       memset(slot->configs, 0,
-              sizeof(*slot->configs) * layer->desc->nconfigs);
-
-       if (slot->fb_flip) {
-               atmel_hlcdc_layer_fb_flip_release_queue(layer, slot->fb_flip);
-               slot->fb_flip = NULL;
-       }
-}
-
-static void atmel_hlcdc_layer_update_apply(struct atmel_hlcdc_layer *layer)
-{
-       struct atmel_hlcdc_layer_dma_channel *dma = &layer->dma;
-       const struct atmel_hlcdc_layer_desc *desc = layer->desc;
-       struct atmel_hlcdc_layer_update *upd = &layer->update;
-       struct regmap *regmap = layer->hlcdc->regmap;
-       struct atmel_hlcdc_layer_update_slot *slot;
-       struct atmel_hlcdc_layer_fb_flip *fb_flip;
-       struct atmel_hlcdc_dma_channel_dscr *dscr;
-       unsigned int cfg;
-       u32 action = 0;
-       int i = 0;
-
-       if (upd->pending < 0 || upd->pending > 1)
-               return;
-
-       slot = &upd->slots[upd->pending];
-
-       for_each_set_bit(cfg, slot->updated_configs, layer->desc->nconfigs) {
-               regmap_write(regmap,
-                            desc->regs_offset +
-                            ATMEL_HLCDC_LAYER_CFG(layer, cfg),
-                            slot->configs[cfg]);
-               action |= ATMEL_HLCDC_LAYER_UPDATE;
-       }
-
-       fb_flip = slot->fb_flip;
-
-       if (!fb_flip->fb)
-               goto apply;
-
-       if (dma->status == ATMEL_HLCDC_LAYER_DISABLED) {
-               for (i = 0; i < fb_flip->ngems; i++) {
-                       dscr = fb_flip->dscrs[i];
-                       dscr->ctrl = ATMEL_HLCDC_LAYER_DFETCH |
-                                    ATMEL_HLCDC_LAYER_DMA_IRQ |
-                                    ATMEL_HLCDC_LAYER_ADD_IRQ |
-                                    ATMEL_HLCDC_LAYER_DONE_IRQ;
-
-                       regmap_write(regmap,
-                                    desc->regs_offset +
-                                    ATMEL_HLCDC_LAYER_PLANE_ADDR(i),
-                                    dscr->addr);
-                       regmap_write(regmap,
-                                    desc->regs_offset +
-                                    ATMEL_HLCDC_LAYER_PLANE_CTRL(i),
-                                    dscr->ctrl);
-                       regmap_write(regmap,
-                                    desc->regs_offset +
-                                    ATMEL_HLCDC_LAYER_PLANE_NEXT(i),
-                                    dscr->next);
-               }
-
-               action |= ATMEL_HLCDC_LAYER_DMA_CHAN;
-               dma->status = ATMEL_HLCDC_LAYER_ENABLED;
-       } else {
-               for (i = 0; i < fb_flip->ngems; i++) {
-                       dscr =  fb_flip->dscrs[i];
-                       dscr->ctrl = ATMEL_HLCDC_LAYER_DFETCH |
-                                    ATMEL_HLCDC_LAYER_DMA_IRQ |
-                                    ATMEL_HLCDC_LAYER_DSCR_IRQ |
-                                    ATMEL_HLCDC_LAYER_DONE_IRQ;
-
-                       regmap_write(regmap,
-                                    desc->regs_offset +
-                                    ATMEL_HLCDC_LAYER_PLANE_HEAD(i),
-                                    dscr->next);
-               }
-
-               action |= ATMEL_HLCDC_LAYER_A2Q;
-       }
-
-       /* Release unneeded descriptors */
-       for (i = fb_flip->ngems; i < layer->max_planes; i++) {
-               fb_flip->dscrs[i]->status = 0;
-               fb_flip->dscrs[i] = NULL;
-       }
-
-       dma->queue = fb_flip;
-       slot->fb_flip = NULL;
-
-apply:
-       if (action)
-               regmap_write(regmap,
-                            desc->regs_offset + ATMEL_HLCDC_LAYER_CHER,
-                            action);
-
-       atmel_hlcdc_layer_update_reset(layer, upd->pending);
-
-       upd->pending = -1;
-}
-
-void atmel_hlcdc_layer_irq(struct atmel_hlcdc_layer *layer)
-{
-       struct atmel_hlcdc_layer_dma_channel *dma = &layer->dma;
-       const struct atmel_hlcdc_layer_desc *desc = layer->desc;
-       struct regmap *regmap = layer->hlcdc->regmap;
-       struct atmel_hlcdc_layer_fb_flip *flip;
-       unsigned long flags;
-       unsigned int isr, imr;
-       unsigned int status;
-       unsigned int plane_status;
-       u32 flip_status;
-
-       int i;
-
-       regmap_read(regmap, desc->regs_offset + ATMEL_HLCDC_LAYER_IMR, &imr);
-       regmap_read(regmap, desc->regs_offset + ATMEL_HLCDC_LAYER_ISR, &isr);
-       status = imr & isr;
-       if (!status)
-               return;
-
-       spin_lock_irqsave(&layer->lock, flags);
-
-       flip = dma->queue ? dma->queue : dma->cur;
-
-       if (!flip) {
-               spin_unlock_irqrestore(&layer->lock, flags);
-               return;
-       }
-
-       /*
-        * Set LOADED and DONE flags: they'll be cleared if at least one
-        * memory plane is not LOADED or DONE.
-        */
-       flip_status = ATMEL_HLCDC_DMA_CHANNEL_DSCR_LOADED |
-                     ATMEL_HLCDC_DMA_CHANNEL_DSCR_DONE;
-       for (i = 0; i < flip->ngems; i++) {
-               plane_status = (status >> (8 * i));
-
-               if (plane_status &
-                   (ATMEL_HLCDC_LAYER_ADD_IRQ |
-                    ATMEL_HLCDC_LAYER_DSCR_IRQ) &
-                   ~flip->dscrs[i]->ctrl) {
-                       flip->dscrs[i]->status |=
-                                       ATMEL_HLCDC_DMA_CHANNEL_DSCR_LOADED;
-                       flip->dscrs[i]->ctrl |=
-                                       ATMEL_HLCDC_LAYER_ADD_IRQ |
-                                       ATMEL_HLCDC_LAYER_DSCR_IRQ;
-               }
-
-               if (plane_status &
-                   ATMEL_HLCDC_LAYER_DONE_IRQ &
-                   ~flip->dscrs[i]->ctrl) {
-                       flip->dscrs[i]->status |=
-                                       ATMEL_HLCDC_DMA_CHANNEL_DSCR_DONE;
-                       flip->dscrs[i]->ctrl |=
-                                       ATMEL_HLCDC_LAYER_DONE_IRQ;
-               }
-
-               if (plane_status & ATMEL_HLCDC_LAYER_OVR_IRQ)
-                       flip->dscrs[i]->status |=
-                                       ATMEL_HLCDC_DMA_CHANNEL_DSCR_OVERRUN;
-
-               /*
-                * Clear LOADED and DONE flags if the memory plane is either
-                * not LOADED or not DONE.
-                */
-               if (!(flip->dscrs[i]->status &
-                     ATMEL_HLCDC_DMA_CHANNEL_DSCR_LOADED))
-                       flip_status &= ~ATMEL_HLCDC_DMA_CHANNEL_DSCR_LOADED;
-
-               if (!(flip->dscrs[i]->status &
-                     ATMEL_HLCDC_DMA_CHANNEL_DSCR_DONE))
-                       flip_status &= ~ATMEL_HLCDC_DMA_CHANNEL_DSCR_DONE;
-
-               /*
-                * An overrun on one memory plane impact the whole framebuffer
-                * transfer, hence we set the OVERRUN flag as soon as there's
-                * one memory plane reporting such an overrun.
-                */
-               flip_status |= flip->dscrs[i]->status &
-                              ATMEL_HLCDC_DMA_CHANNEL_DSCR_OVERRUN;
-       }
-
-       /* Get changed bits */
-       flip_status ^= flip->status;
-       flip->status |= flip_status;
-
-       if (flip_status & ATMEL_HLCDC_DMA_CHANNEL_DSCR_LOADED) {
-               atmel_hlcdc_layer_fb_flip_release_queue(layer, dma->cur);
-               dma->cur = dma->queue;
-               dma->queue = NULL;
-       }
-
-       if (flip_status & ATMEL_HLCDC_DMA_CHANNEL_DSCR_DONE) {
-               atmel_hlcdc_layer_fb_flip_release_queue(layer, dma->cur);
-               dma->cur = NULL;
-       }
-
-       if (flip_status & ATMEL_HLCDC_DMA_CHANNEL_DSCR_OVERRUN) {
-               regmap_write(regmap,
-                            desc->regs_offset + ATMEL_HLCDC_LAYER_CHDR,
-                            ATMEL_HLCDC_LAYER_RST);
-               if (dma->queue)
-                       atmel_hlcdc_layer_fb_flip_release_queue(layer,
-                                                               dma->queue);
-
-               if (dma->cur)
-                       atmel_hlcdc_layer_fb_flip_release_queue(layer,
-                                                               dma->cur);
-
-               dma->cur = NULL;
-               dma->queue = NULL;
-       }
-
-       if (!dma->queue) {
-               atmel_hlcdc_layer_update_apply(layer);
-
-               if (!dma->cur)
-                       dma->status = ATMEL_HLCDC_LAYER_DISABLED;
-       }
-
-       spin_unlock_irqrestore(&layer->lock, flags);
-}
-
-void atmel_hlcdc_layer_disable(struct atmel_hlcdc_layer *layer)
-{
-       struct atmel_hlcdc_layer_dma_channel *dma = &layer->dma;
-       struct atmel_hlcdc_layer_update *upd = &layer->update;
-       struct regmap *regmap = layer->hlcdc->regmap;
-       const struct atmel_hlcdc_layer_desc *desc = layer->desc;
-       unsigned long flags;
-       unsigned int isr;
-
-       spin_lock_irqsave(&layer->lock, flags);
-
-       /* Disable the layer */
-       regmap_write(regmap, desc->regs_offset + ATMEL_HLCDC_LAYER_CHDR,
-                    ATMEL_HLCDC_LAYER_RST | ATMEL_HLCDC_LAYER_A2Q |
-                    ATMEL_HLCDC_LAYER_UPDATE);
-
-       /* Clear all pending interrupts */
-       regmap_read(regmap, desc->regs_offset + ATMEL_HLCDC_LAYER_ISR, &isr);
-
-       /* Discard current and queued framebuffer transfers. */
-       if (dma->cur) {
-               atmel_hlcdc_layer_fb_flip_release_queue(layer, dma->cur);
-               dma->cur = NULL;
-       }
-
-       if (dma->queue) {
-               atmel_hlcdc_layer_fb_flip_release_queue(layer, dma->queue);
-               dma->queue = NULL;
-       }
-
-       /*
-        * Then discard the pending update request (if any) to prevent
-        * DMA irq handler from restarting the DMA channel after it has
-        * been disabled.
-        */
-       if (upd->pending >= 0) {
-               atmel_hlcdc_layer_update_reset(layer, upd->pending);
-               upd->pending = -1;
-       }
-
-       dma->status = ATMEL_HLCDC_LAYER_DISABLED;
-
-       spin_unlock_irqrestore(&layer->lock, flags);
-}
-
-int atmel_hlcdc_layer_update_start(struct atmel_hlcdc_layer *layer)
-{
-       struct atmel_hlcdc_layer_dma_channel *dma = &layer->dma;
-       struct atmel_hlcdc_layer_update *upd = &layer->update;
-       struct regmap *regmap = layer->hlcdc->regmap;
-       struct atmel_hlcdc_layer_fb_flip *fb_flip;
-       struct atmel_hlcdc_layer_update_slot *slot;
-       unsigned long flags;
-       int i, j = 0;
-
-       fb_flip = kzalloc(sizeof(*fb_flip), GFP_KERNEL);
-       if (!fb_flip)
-               return -ENOMEM;
-
-       fb_flip->task = drm_flip_work_allocate_task(fb_flip, GFP_KERNEL);
-       if (!fb_flip->task) {
-               kfree(fb_flip);
-               return -ENOMEM;
-       }
-
-       spin_lock_irqsave(&layer->lock, flags);
-
-       upd->next = upd->pending ? 0 : 1;
-
-       slot = &upd->slots[upd->next];
-
-       for (i = 0; i < layer->max_planes * 4; i++) {
-               if (!dma->dscrs[i].status) {
-                       fb_flip->dscrs[j++] = &dma->dscrs[i];
-                       dma->dscrs[i].status =
-                               ATMEL_HLCDC_DMA_CHANNEL_DSCR_RESERVED;
-                       if (j == layer->max_planes)
-                               break;
-               }
-       }
-
-       if (j < layer->max_planes) {
-               for (i = 0; i < j; i++)
-                       fb_flip->dscrs[i]->status = 0;
-       }
-
-       if (j < layer->max_planes) {
-               spin_unlock_irqrestore(&layer->lock, flags);
-               atmel_hlcdc_layer_fb_flip_destroy(fb_flip);
-               return -EBUSY;
-       }
-
-       slot->fb_flip = fb_flip;
-
-       if (upd->pending >= 0) {
-               memcpy(slot->configs,
-                      upd->slots[upd->pending].configs,
-                      layer->desc->nconfigs * sizeof(u32));
-               memcpy(slot->updated_configs,
-                      upd->slots[upd->pending].updated_configs,
-                      DIV_ROUND_UP(layer->desc->nconfigs,
-                                   BITS_PER_BYTE * sizeof(unsigned long)) *
-                      sizeof(unsigned long));
-               slot->fb_flip->fb = upd->slots[upd->pending].fb_flip->fb;
-               if (upd->slots[upd->pending].fb_flip->fb) {
-                       slot->fb_flip->fb =
-                               upd->slots[upd->pending].fb_flip->fb;
-                       slot->fb_flip->ngems =
-                               upd->slots[upd->pending].fb_flip->ngems;
-                       drm_framebuffer_reference(slot->fb_flip->fb);
-               }
-       } else {
-               regmap_bulk_read(regmap,
-                                layer->desc->regs_offset +
-                                ATMEL_HLCDC_LAYER_CFG(layer, 0),
-                                upd->slots[upd->next].configs,
-                                layer->desc->nconfigs);
-       }
-
-       spin_unlock_irqrestore(&layer->lock, flags);
-
-       return 0;
-}
-
-void atmel_hlcdc_layer_update_rollback(struct atmel_hlcdc_layer *layer)
-{
-       struct atmel_hlcdc_layer_update *upd = &layer->update;
-
-       atmel_hlcdc_layer_update_reset(layer, upd->next);
-       upd->next = -1;
-}
-
-void atmel_hlcdc_layer_update_set_fb(struct atmel_hlcdc_layer *layer,
-                                    struct drm_framebuffer *fb,
-                                    unsigned int *offsets)
-{
-       struct atmel_hlcdc_layer_update *upd = &layer->update;
-       struct atmel_hlcdc_layer_fb_flip *fb_flip;
-       struct atmel_hlcdc_layer_update_slot *slot;
-       struct atmel_hlcdc_dma_channel_dscr *dscr;
-       struct drm_framebuffer *old_fb;
-       int nplanes = 0;
-       int i;
-
-       if (upd->next < 0 || upd->next > 1)
-               return;
-
-       if (fb)
-               nplanes = fb->format->num_planes;
-
-       if (nplanes > layer->max_planes)
-               return;
-
-       slot = &upd->slots[upd->next];
-
-       fb_flip = slot->fb_flip;
-       old_fb = slot->fb_flip->fb;
-
-       for (i = 0; i < nplanes; i++) {
-               struct drm_gem_cma_object *gem;
-
-               dscr = slot->fb_flip->dscrs[i];
-               gem = drm_fb_cma_get_gem_obj(fb, i);
-               dscr->addr = gem->paddr + offsets[i];
-       }
-
-       fb_flip->ngems = nplanes;
-       fb_flip->fb = fb;
-
-       if (fb)
-               drm_framebuffer_reference(fb);
-
-       if (old_fb)
-               drm_framebuffer_unreference(old_fb);
-}
-
-void atmel_hlcdc_layer_update_cfg(struct atmel_hlcdc_layer *layer, int cfg,
-                                 u32 mask, u32 val)
-{
-       struct atmel_hlcdc_layer_update *upd = &layer->update;
-       struct atmel_hlcdc_layer_update_slot *slot;
-
-       if (upd->next < 0 || upd->next > 1)
-               return;
-
-       if (cfg >= layer->desc->nconfigs)
-               return;
-
-       slot = &upd->slots[upd->next];
-       slot->configs[cfg] &= ~mask;
-       slot->configs[cfg] |= (val & mask);
-       set_bit(cfg, slot->updated_configs);
-}
-
-void atmel_hlcdc_layer_update_commit(struct atmel_hlcdc_layer *layer)
-{
-       struct atmel_hlcdc_layer_dma_channel *dma = &layer->dma;
-       struct atmel_hlcdc_layer_update *upd = &layer->update;
-       struct atmel_hlcdc_layer_update_slot *slot;
-       unsigned long flags;
-
-       if (upd->next < 0  || upd->next > 1)
-               return;
-
-       slot = &upd->slots[upd->next];
-
-       spin_lock_irqsave(&layer->lock, flags);
-
-       /*
-        * Release pending update request and replace it by the new one.
-        */
-       if (upd->pending >= 0)
-               atmel_hlcdc_layer_update_reset(layer, upd->pending);
-
-       upd->pending = upd->next;
-       upd->next = -1;
-
-       if (!dma->queue)
-               atmel_hlcdc_layer_update_apply(layer);
-
-       spin_unlock_irqrestore(&layer->lock, flags);
-
-
-       upd->next = -1;
-}
-
-static int atmel_hlcdc_layer_dma_init(struct drm_device *dev,
-                                     struct atmel_hlcdc_layer *layer)
-{
-       struct atmel_hlcdc_layer_dma_channel *dma = &layer->dma;
-       dma_addr_t dma_addr;
-       int i;
-
-       dma->dscrs = dma_alloc_coherent(dev->dev,
-                                       layer->max_planes * 4 *
-                                       sizeof(*dma->dscrs),
-                                       &dma_addr, GFP_KERNEL);
-       if (!dma->dscrs)
-               return -ENOMEM;
-
-       for (i = 0; i < layer->max_planes * 4; i++) {
-               struct atmel_hlcdc_dma_channel_dscr *dscr = &dma->dscrs[i];
-
-               dscr->next = dma_addr + (i * sizeof(*dscr));
-       }
-
-       return 0;
-}
-
-static void atmel_hlcdc_layer_dma_cleanup(struct drm_device *dev,
-                                         struct atmel_hlcdc_layer *layer)
-{
-       struct atmel_hlcdc_layer_dma_channel *dma = &layer->dma;
-       int i;
-
-       for (i = 0; i < layer->max_planes * 4; i++) {
-               struct atmel_hlcdc_dma_channel_dscr *dscr = &dma->dscrs[i];
-
-               dscr->status = 0;
-       }
-
-       dma_free_coherent(dev->dev, layer->max_planes * 4 *
-                         sizeof(*dma->dscrs), dma->dscrs,
-                         dma->dscrs[0].next);
-}
-
-static int atmel_hlcdc_layer_update_init(struct drm_device *dev,
-                               struct atmel_hlcdc_layer *layer,
-                               const struct atmel_hlcdc_layer_desc *desc)
-{
-       struct atmel_hlcdc_layer_update *upd = &layer->update;
-       int updated_size;
-       void *buffer;
-       int i;
-
-       updated_size = DIV_ROUND_UP(desc->nconfigs,
-                                   BITS_PER_BYTE *
-                                   sizeof(unsigned long));
-
-       buffer = devm_kzalloc(dev->dev,
-                             ((desc->nconfigs * sizeof(u32)) +
-                               (updated_size * sizeof(unsigned long))) * 2,
-                             GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
-       for (i = 0; i < 2; i++) {
-               upd->slots[i].updated_configs = buffer;
-               buffer += updated_size * sizeof(unsigned long);
-               upd->slots[i].configs = buffer;
-               buffer += desc->nconfigs * sizeof(u32);
-       }
-
-       upd->pending = -1;
-       upd->next = -1;
-
-       return 0;
-}
-
-int atmel_hlcdc_layer_init(struct drm_device *dev,
-                          struct atmel_hlcdc_layer *layer,
-                          const struct atmel_hlcdc_layer_desc *desc)
-{
-       struct atmel_hlcdc_dc *dc = dev->dev_private;
-       struct regmap *regmap = dc->hlcdc->regmap;
-       unsigned int tmp;
-       int ret;
-       int i;
-
-       layer->hlcdc = dc->hlcdc;
-       layer->wq = dc->wq;
-       layer->desc = desc;
-
-       regmap_write(regmap, desc->regs_offset + ATMEL_HLCDC_LAYER_CHDR,
-                    ATMEL_HLCDC_LAYER_RST);
-       for (i = 0; i < desc->formats->nformats; i++) {
-               int nplanes = drm_format_num_planes(desc->formats->formats[i]);
-
-               if (nplanes > layer->max_planes)
-                       layer->max_planes = nplanes;
-       }
-
-       spin_lock_init(&layer->lock);
-       drm_flip_work_init(&layer->gc, desc->name,
-                          atmel_hlcdc_layer_fb_flip_release);
-       ret = atmel_hlcdc_layer_dma_init(dev, layer);
-       if (ret)
-               return ret;
-
-       ret = atmel_hlcdc_layer_update_init(dev, layer, desc);
-       if (ret)
-               return ret;
-
-       /* Flush Status Register */
-       regmap_write(regmap, desc->regs_offset + ATMEL_HLCDC_LAYER_IDR,
-                    0xffffffff);
-       regmap_read(regmap, desc->regs_offset + ATMEL_HLCDC_LAYER_ISR,
-                   &tmp);
-
-       tmp = 0;
-       for (i = 0; i < layer->max_planes; i++)
-               tmp |= (ATMEL_HLCDC_LAYER_DMA_IRQ |
-                       ATMEL_HLCDC_LAYER_DSCR_IRQ |
-                       ATMEL_HLCDC_LAYER_ADD_IRQ |
-                       ATMEL_HLCDC_LAYER_DONE_IRQ |
-                       ATMEL_HLCDC_LAYER_OVR_IRQ) << (8 * i);
-
-       regmap_write(regmap, desc->regs_offset + ATMEL_HLCDC_LAYER_IER, tmp);
-
-       return 0;
-}
-
-void atmel_hlcdc_layer_cleanup(struct drm_device *dev,
-                              struct atmel_hlcdc_layer *layer)
-{
-       const struct atmel_hlcdc_layer_desc *desc = layer->desc;
-       struct regmap *regmap = layer->hlcdc->regmap;
-
-       regmap_write(regmap, desc->regs_offset + ATMEL_HLCDC_LAYER_IDR,
-                    0xffffffff);
-       regmap_write(regmap, desc->regs_offset + ATMEL_HLCDC_LAYER_CHDR,
-                    ATMEL_HLCDC_LAYER_RST);
-
-       atmel_hlcdc_layer_dma_cleanup(dev, layer);
-       drm_flip_work_cleanup(&layer->gc);
-}
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_layer.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_layer.h
deleted file mode 100644 (file)
index 9beabc9..0000000
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * Copyright (C) 2014 Free Electrons
- * Copyright (C) 2014 Atmel
- *
- * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef DRM_ATMEL_HLCDC_LAYER_H
-#define DRM_ATMEL_HLCDC_LAYER_H
-
-#include <linux/mfd/atmel-hlcdc.h>
-
-#include <drm/drm_crtc.h>
-#include <drm/drm_flip_work.h>
-#include <drm/drmP.h>
-
-#define ATMEL_HLCDC_LAYER_CHER                 0x0
-#define ATMEL_HLCDC_LAYER_CHDR                 0x4
-#define ATMEL_HLCDC_LAYER_CHSR                 0x8
-#define ATMEL_HLCDC_LAYER_DMA_CHAN             BIT(0)
-#define ATMEL_HLCDC_LAYER_UPDATE               BIT(1)
-#define ATMEL_HLCDC_LAYER_A2Q                  BIT(2)
-#define ATMEL_HLCDC_LAYER_RST                  BIT(8)
-
-#define ATMEL_HLCDC_LAYER_IER                  0xc
-#define ATMEL_HLCDC_LAYER_IDR                  0x10
-#define ATMEL_HLCDC_LAYER_IMR                  0x14
-#define ATMEL_HLCDC_LAYER_ISR                  0x18
-#define ATMEL_HLCDC_LAYER_DFETCH               BIT(0)
-#define ATMEL_HLCDC_LAYER_LFETCH               BIT(1)
-#define ATMEL_HLCDC_LAYER_DMA_IRQ              BIT(2)
-#define ATMEL_HLCDC_LAYER_DSCR_IRQ             BIT(3)
-#define ATMEL_HLCDC_LAYER_ADD_IRQ              BIT(4)
-#define ATMEL_HLCDC_LAYER_DONE_IRQ             BIT(5)
-#define ATMEL_HLCDC_LAYER_OVR_IRQ              BIT(6)
-
-#define ATMEL_HLCDC_LAYER_PLANE_HEAD(n)                (((n) * 0x10) + 0x1c)
-#define ATMEL_HLCDC_LAYER_PLANE_ADDR(n)                (((n) * 0x10) + 0x20)
-#define ATMEL_HLCDC_LAYER_PLANE_CTRL(n)                (((n) * 0x10) + 0x24)
-#define ATMEL_HLCDC_LAYER_PLANE_NEXT(n)                (((n) * 0x10) + 0x28)
-#define ATMEL_HLCDC_LAYER_CFG(p, c)            (((c) * 4) + ((p)->max_planes * 0x10) + 0x1c)
-
-#define ATMEL_HLCDC_LAYER_DMA_CFG_ID           0
-#define ATMEL_HLCDC_LAYER_DMA_CFG(p)           ATMEL_HLCDC_LAYER_CFG(p, ATMEL_HLCDC_LAYER_DMA_CFG_ID)
-#define ATMEL_HLCDC_LAYER_DMA_SIF              BIT(0)
-#define ATMEL_HLCDC_LAYER_DMA_BLEN_MASK                GENMASK(5, 4)
-#define ATMEL_HLCDC_LAYER_DMA_BLEN_SINGLE      (0 << 4)
-#define ATMEL_HLCDC_LAYER_DMA_BLEN_INCR4       (1 << 4)
-#define ATMEL_HLCDC_LAYER_DMA_BLEN_INCR8       (2 << 4)
-#define ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16      (3 << 4)
-#define ATMEL_HLCDC_LAYER_DMA_DLBO             BIT(8)
-#define ATMEL_HLCDC_LAYER_DMA_ROTDIS           BIT(12)
-#define ATMEL_HLCDC_LAYER_DMA_LOCKDIS          BIT(13)
-
-#define ATMEL_HLCDC_LAYER_FORMAT_CFG_ID                1
-#define ATMEL_HLCDC_LAYER_FORMAT_CFG(p)                ATMEL_HLCDC_LAYER_CFG(p, ATMEL_HLCDC_LAYER_FORMAT_CFG_ID)
-#define ATMEL_HLCDC_LAYER_RGB                  (0 << 0)
-#define ATMEL_HLCDC_LAYER_CLUT                 (1 << 0)
-#define ATMEL_HLCDC_LAYER_YUV                  (2 << 0)
-#define ATMEL_HLCDC_RGB_MODE(m)                        (((m) & 0xf) << 4)
-#define ATMEL_HLCDC_CLUT_MODE(m)               (((m) & 0x3) << 8)
-#define ATMEL_HLCDC_YUV_MODE(m)                        (((m) & 0xf) << 12)
-#define ATMEL_HLCDC_YUV422ROT                  BIT(16)
-#define ATMEL_HLCDC_YUV422SWP                  BIT(17)
-#define ATMEL_HLCDC_DSCALEOPT                  BIT(20)
-
-#define ATMEL_HLCDC_XRGB4444_MODE              (ATMEL_HLCDC_LAYER_RGB | ATMEL_HLCDC_RGB_MODE(0))
-#define ATMEL_HLCDC_ARGB4444_MODE              (ATMEL_HLCDC_LAYER_RGB | ATMEL_HLCDC_RGB_MODE(1))
-#define ATMEL_HLCDC_RGBA4444_MODE              (ATMEL_HLCDC_LAYER_RGB | ATMEL_HLCDC_RGB_MODE(2))
-#define ATMEL_HLCDC_RGB565_MODE                        (ATMEL_HLCDC_LAYER_RGB | ATMEL_HLCDC_RGB_MODE(3))
-#define ATMEL_HLCDC_ARGB1555_MODE              (ATMEL_HLCDC_LAYER_RGB | ATMEL_HLCDC_RGB_MODE(4))
-#define ATMEL_HLCDC_XRGB8888_MODE              (ATMEL_HLCDC_LAYER_RGB | ATMEL_HLCDC_RGB_MODE(9))
-#define ATMEL_HLCDC_RGB888_MODE                        (ATMEL_HLCDC_LAYER_RGB | ATMEL_HLCDC_RGB_MODE(10))
-#define ATMEL_HLCDC_ARGB8888_MODE              (ATMEL_HLCDC_LAYER_RGB | ATMEL_HLCDC_RGB_MODE(12))
-#define ATMEL_HLCDC_RGBA8888_MODE              (ATMEL_HLCDC_LAYER_RGB | ATMEL_HLCDC_RGB_MODE(13))
-
-#define ATMEL_HLCDC_AYUV_MODE                  (ATMEL_HLCDC_LAYER_YUV | ATMEL_HLCDC_YUV_MODE(0))
-#define ATMEL_HLCDC_YUYV_MODE                  (ATMEL_HLCDC_LAYER_YUV | ATMEL_HLCDC_YUV_MODE(1))
-#define ATMEL_HLCDC_UYVY_MODE                  (ATMEL_HLCDC_LAYER_YUV | ATMEL_HLCDC_YUV_MODE(2))
-#define ATMEL_HLCDC_YVYU_MODE                  (ATMEL_HLCDC_LAYER_YUV | ATMEL_HLCDC_YUV_MODE(3))
-#define ATMEL_HLCDC_VYUY_MODE                  (ATMEL_HLCDC_LAYER_YUV | ATMEL_HLCDC_YUV_MODE(4))
-#define ATMEL_HLCDC_NV61_MODE                  (ATMEL_HLCDC_LAYER_YUV | ATMEL_HLCDC_YUV_MODE(5))
-#define ATMEL_HLCDC_YUV422_MODE                        (ATMEL_HLCDC_LAYER_YUV | ATMEL_HLCDC_YUV_MODE(6))
-#define ATMEL_HLCDC_NV21_MODE                  (ATMEL_HLCDC_LAYER_YUV | ATMEL_HLCDC_YUV_MODE(7))
-#define ATMEL_HLCDC_YUV420_MODE                        (ATMEL_HLCDC_LAYER_YUV | ATMEL_HLCDC_YUV_MODE(8))
-
-#define ATMEL_HLCDC_LAYER_POS_CFG(p)           ATMEL_HLCDC_LAYER_CFG(p, (p)->desc->layout.pos)
-#define ATMEL_HLCDC_LAYER_SIZE_CFG(p)          ATMEL_HLCDC_LAYER_CFG(p, (p)->desc->layout.size)
-#define ATMEL_HLCDC_LAYER_MEMSIZE_CFG(p)       ATMEL_HLCDC_LAYER_CFG(p, (p)->desc->layout.memsize)
-#define ATMEL_HLCDC_LAYER_XSTRIDE_CFG(p)       ATMEL_HLCDC_LAYER_CFG(p, (p)->desc->layout.xstride)
-#define ATMEL_HLCDC_LAYER_PSTRIDE_CFG(p)       ATMEL_HLCDC_LAYER_CFG(p, (p)->desc->layout.pstride)
-#define ATMEL_HLCDC_LAYER_DFLTCOLOR_CFG(p)     ATMEL_HLCDC_LAYER_CFG(p, (p)->desc->layout.default_color)
-#define ATMEL_HLCDC_LAYER_CRKEY_CFG(p)         ATMEL_HLCDC_LAYER_CFG(p, (p)->desc->layout.chroma_key)
-#define ATMEL_HLCDC_LAYER_CRKEY_MASK_CFG(p)    ATMEL_HLCDC_LAYER_CFG(p, (p)->desc->layout.chroma_key_mask)
-
-#define ATMEL_HLCDC_LAYER_GENERAL_CFG(p)       ATMEL_HLCDC_LAYER_CFG(p, (p)->desc->layout.general_config)
-#define ATMEL_HLCDC_LAYER_CRKEY                        BIT(0)
-#define ATMEL_HLCDC_LAYER_INV                  BIT(1)
-#define ATMEL_HLCDC_LAYER_ITER2BL              BIT(2)
-#define ATMEL_HLCDC_LAYER_ITER                 BIT(3)
-#define ATMEL_HLCDC_LAYER_REVALPHA             BIT(4)
-#define ATMEL_HLCDC_LAYER_GAEN                 BIT(5)
-#define ATMEL_HLCDC_LAYER_LAEN                 BIT(6)
-#define ATMEL_HLCDC_LAYER_OVR                  BIT(7)
-#define ATMEL_HLCDC_LAYER_DMA                  BIT(8)
-#define ATMEL_HLCDC_LAYER_REP                  BIT(9)
-#define ATMEL_HLCDC_LAYER_DSTKEY               BIT(10)
-#define ATMEL_HLCDC_LAYER_DISCEN               BIT(11)
-#define ATMEL_HLCDC_LAYER_GA_SHIFT             16
-#define ATMEL_HLCDC_LAYER_GA_MASK              GENMASK(23, ATMEL_HLCDC_LAYER_GA_SHIFT)
-#define ATMEL_HLCDC_LAYER_GA(x)                        ((x) << ATMEL_HLCDC_LAYER_GA_SHIFT)
-
-#define ATMEL_HLCDC_LAYER_CSC_CFG(p, o)                ATMEL_HLCDC_LAYER_CFG(p, (p)->desc->layout.csc + o)
-
-#define ATMEL_HLCDC_LAYER_DISC_POS_CFG(p)      ATMEL_HLCDC_LAYER_CFG(p, (p)->desc->layout.disc_pos)
-
-#define ATMEL_HLCDC_LAYER_DISC_SIZE_CFG(p)     ATMEL_HLCDC_LAYER_CFG(p, (p)->desc->layout.disc_size)
-
-#define ATMEL_HLCDC_MAX_PLANES                 3
-
-#define ATMEL_HLCDC_DMA_CHANNEL_DSCR_RESERVED  BIT(0)
-#define ATMEL_HLCDC_DMA_CHANNEL_DSCR_LOADED    BIT(1)
-#define ATMEL_HLCDC_DMA_CHANNEL_DSCR_DONE      BIT(2)
-#define ATMEL_HLCDC_DMA_CHANNEL_DSCR_OVERRUN   BIT(3)
-
-/**
- * Atmel HLCDC Layer registers layout structure
- *
- * Each HLCDC layer has its own register organization and a given register
- * can be placed differently on 2 different layers depending on its
- * capabilities.
- * This structure stores common registers layout for a given layer and is
- * used by HLCDC layer code to choose the appropriate register to write to
- * or to read from.
- *
- * For all fields, a value of zero means "unsupported".
- *
- * See Atmel's datasheet for a detailled description of these registers.
- *
- * @xstride: xstride registers
- * @pstride: pstride registers
- * @pos: position register
- * @size: displayed size register
- * @memsize: memory size register
- * @default_color: default color register
- * @chroma_key: chroma key register
- * @chroma_key_mask: chroma key mask register
- * @general_config: general layer config register
- * @disc_pos: discard area position register
- * @disc_size: discard area size register
- * @csc: color space conversion register
- */
-struct atmel_hlcdc_layer_cfg_layout {
-       int xstride[ATMEL_HLCDC_MAX_PLANES];
-       int pstride[ATMEL_HLCDC_MAX_PLANES];
-       int pos;
-       int size;
-       int memsize;
-       int default_color;
-       int chroma_key;
-       int chroma_key_mask;
-       int general_config;
-       int disc_pos;
-       int disc_size;
-       int csc;
-};
-
-/**
- * Atmel HLCDC framebuffer flip structure
- *
- * This structure is allocated when someone asked for a layer update (most
- * likely a DRM plane update, either primary, overlay or cursor plane) and
- * released when the layer do not need to reference the framebuffer object
- * anymore (i.e. the layer was disabled or updated).
- *
- * @dscrs: DMA descriptors
- * @fb: the referenced framebuffer object
- * @ngems: number of GEM objects referenced by the fb element
- * @status: fb flip operation status
- */
-struct atmel_hlcdc_layer_fb_flip {
-       struct atmel_hlcdc_dma_channel_dscr *dscrs[ATMEL_HLCDC_MAX_PLANES];
-       struct drm_flip_task *task;
-       struct drm_framebuffer *fb;
-       int ngems;
-       u32 status;
-};
-
-/**
- * Atmel HLCDC DMA descriptor structure
- *
- * This structure is used by the HLCDC DMA engine to schedule a DMA transfer.
- *
- * The structure fields must remain in this specific order, because they're
- * used by the HLCDC DMA engine, which expect them in this order.
- * HLCDC DMA descriptors must be aligned on 64 bits.
- *
- * @addr: buffer DMA address
- * @ctrl: DMA transfer options
- * @next: next DMA descriptor to fetch
- * @gem_flip: the attached gem_flip operation
- */
-struct atmel_hlcdc_dma_channel_dscr {
-       dma_addr_t addr;
-       u32 ctrl;
-       dma_addr_t next;
-       u32 status;
-} __aligned(sizeof(u64));
-
-/**
- * Atmel HLCDC layer types
- */
-enum atmel_hlcdc_layer_type {
-       ATMEL_HLCDC_BASE_LAYER,
-       ATMEL_HLCDC_OVERLAY_LAYER,
-       ATMEL_HLCDC_CURSOR_LAYER,
-       ATMEL_HLCDC_PP_LAYER,
-};
-
-/**
- * Atmel HLCDC Supported formats structure
- *
- * This structure list all the formats supported by a given layer.
- *
- * @nformats: number of supported formats
- * @formats: supported formats
- */
-struct atmel_hlcdc_formats {
-       int nformats;
-       uint32_t *formats;
-};
-
-/**
- * Atmel HLCDC Layer description structure
- *
- * This structure describe the capabilities provided by a given layer.
- *
- * @name: layer name
- * @type: layer type
- * @id: layer id
- * @regs_offset: offset of the layer registers from the HLCDC registers base
- * @nconfigs: number of config registers provided by this layer
- * @formats: supported formats
- * @layout: config registers layout
- * @max_width: maximum width supported by this layer (0 means unlimited)
- * @max_height: maximum height supported by this layer (0 means unlimited)
- */
-struct atmel_hlcdc_layer_desc {
-       const char *name;
-       enum atmel_hlcdc_layer_type type;
-       int id;
-       int regs_offset;
-       int nconfigs;
-       struct atmel_hlcdc_formats *formats;
-       struct atmel_hlcdc_layer_cfg_layout layout;
-       int max_width;
-       int max_height;
-};
-
-/**
- * Atmel HLCDC Layer Update Slot structure
- *
- * This structure stores layer update requests to be applied on next frame.
- * This is the base structure behind the atomic layer update infrastructure.
- *
- * Atomic layer update provides a way to update all layer's parameters
- * simultaneously. This is needed to avoid incompatible sequential updates
- * like this one:
- * 1) update layer format from RGB888 (1 plane/buffer) to YUV422
- *    (2 planes/buffers)
- * 2) the format update is applied but the DMA channel for the second
- *    plane/buffer is not enabled
- * 3) enable the DMA channel for the second plane
- *
- * @fb_flip: fb_flip object
- * @updated_configs: bitmask used to record modified configs
- * @configs: new config values
- */
-struct atmel_hlcdc_layer_update_slot {
-       struct atmel_hlcdc_layer_fb_flip *fb_flip;
-       unsigned long *updated_configs;
-       u32 *configs;
-};
-
-/**
- * Atmel HLCDC Layer Update structure
- *
- * This structure provides a way to queue layer update requests.
- *
- * At a given time there is at most:
- *  - one pending update request, which means the update request has been
- *    committed (or validated) and is waiting for the DMA channel(s) to be
- *    available
- *  - one request being prepared, which means someone started a layer update
- *    but has not committed it yet. There cannot be more than one started
- *    request, because the update lock is taken when starting a layer update
- *    and release when committing or rolling back the request.
- *
- * @slots: update slots. One is used for pending request and the other one
- *        for started update request
- * @pending: the pending slot index or -1 if no request is pending
- * @next: the started update slot index or -1 no update has been started
- */
-struct atmel_hlcdc_layer_update {
-       struct atmel_hlcdc_layer_update_slot slots[2];
-       int pending;
-       int next;
-};
-
-enum atmel_hlcdc_layer_dma_channel_status {
-       ATMEL_HLCDC_LAYER_DISABLED,
-       ATMEL_HLCDC_LAYER_ENABLED,
-       ATMEL_HLCDC_LAYER_DISABLING,
-};
-
-/**
- * Atmel HLCDC Layer DMA channel structure
- *
- * This structure stores information on the DMA channel associated to a
- * given layer.
- *
- * @status: DMA channel status
- * @cur: current framebuffer
- * @queue: next framebuffer
- * @dscrs: allocated DMA descriptors
- */
-struct atmel_hlcdc_layer_dma_channel {
-       enum atmel_hlcdc_layer_dma_channel_status status;
-       struct atmel_hlcdc_layer_fb_flip *cur;
-       struct atmel_hlcdc_layer_fb_flip *queue;
-       struct atmel_hlcdc_dma_channel_dscr *dscrs;
-};
-
-/**
- * Atmel HLCDC Layer structure
- *
- * This structure stores information on the layer instance.
- *
- * @desc: layer description
- * @max_planes: maximum planes/buffers that can be associated with this layer.
- *            This depends on the supported formats.
- * @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device
- * @dma: dma channel
- * @gc: fb flip garbage collector
- * @update: update handler
- * @lock: layer lock
- */
-struct atmel_hlcdc_layer {
-       const struct atmel_hlcdc_layer_desc *desc;
-       int max_planes;
-       struct atmel_hlcdc *hlcdc;
-       struct workqueue_struct *wq;
-       struct drm_flip_work gc;
-       struct atmel_hlcdc_layer_dma_channel dma;
-       struct atmel_hlcdc_layer_update update;
-       spinlock_t lock;
-};
-
-void atmel_hlcdc_layer_irq(struct atmel_hlcdc_layer *layer);
-
-int atmel_hlcdc_layer_init(struct drm_device *dev,
-                          struct atmel_hlcdc_layer *layer,
-                          const struct atmel_hlcdc_layer_desc *desc);
-
-void atmel_hlcdc_layer_cleanup(struct drm_device *dev,
-                              struct atmel_hlcdc_layer *layer);
-
-void atmel_hlcdc_layer_disable(struct atmel_hlcdc_layer *layer);
-
-int atmel_hlcdc_layer_update_start(struct atmel_hlcdc_layer *layer);
-
-void atmel_hlcdc_layer_update_cfg(struct atmel_hlcdc_layer *layer, int cfg,
-                                 u32 mask, u32 val);
-
-void atmel_hlcdc_layer_update_set_fb(struct atmel_hlcdc_layer *layer,
-                                    struct drm_framebuffer *fb,
-                                    unsigned int *offsets);
-
-void atmel_hlcdc_layer_update_set_finished(struct atmel_hlcdc_layer *layer,
-                                          void (*finished)(void *data),
-                                          void *finished_data);
-
-void atmel_hlcdc_layer_update_rollback(struct atmel_hlcdc_layer *layer);
-
-void atmel_hlcdc_layer_update_commit(struct atmel_hlcdc_layer *layer);
-
-#endif /* DRM_ATMEL_HLCDC_LAYER_H */
index bd2791c4b0027c2cf15df5c0eb0add426499b2b1..29cc10d053ebc3cbd2c60c37d91bb1e5f5f83934 100644 (file)
  * @src_w: buffer width
  * @src_h: buffer height
  * @alpha: alpha blending of the plane
+ * @disc_x: x discard position
+ * @disc_y: y discard position
+ * @disc_w: discard width
+ * @disc_h: discard height
  * @bpp: bytes per pixel deduced from pixel_format
  * @offsets: offsets to apply to the GEM buffers
  * @xstride: value to add to the pixel pointer between each line
  * @pstride: value to add to the pixel pointer between each pixel
  * @nplanes: number of planes (deduced from pixel_format)
- * @prepared: plane update has been prepared
+ * @dscrs: DMA descriptors
  */
 struct atmel_hlcdc_plane_state {
        struct drm_plane_state base;
@@ -52,8 +56,6 @@ struct atmel_hlcdc_plane_state {
 
        u8 alpha;
 
-       bool disc_updated;
-
        int disc_x;
        int disc_y;
        int disc_w;
@@ -62,12 +64,14 @@ struct atmel_hlcdc_plane_state {
        int ahb_id;
 
        /* These fields are private and should not be touched */
-       int bpp[ATMEL_HLCDC_MAX_PLANES];
-       unsigned int offsets[ATMEL_HLCDC_MAX_PLANES];
-       int xstride[ATMEL_HLCDC_MAX_PLANES];
-       int pstride[ATMEL_HLCDC_MAX_PLANES];
+       int bpp[ATMEL_HLCDC_LAYER_MAX_PLANES];
+       unsigned int offsets[ATMEL_HLCDC_LAYER_MAX_PLANES];
+       int xstride[ATMEL_HLCDC_LAYER_MAX_PLANES];
+       int pstride[ATMEL_HLCDC_LAYER_MAX_PLANES];
        int nplanes;
-       bool prepared;
+
+       /* DMA descriptors. */
+       struct atmel_hlcdc_dma_channel_dscr *dscrs[ATMEL_HLCDC_LAYER_MAX_PLANES];
 };
 
 static inline struct atmel_hlcdc_plane_state *
@@ -259,125 +263,145 @@ static u32 heo_upscaling_ycoef[] = {
        0x00205907,
 };
 
+#define ATMEL_HLCDC_XPHIDEF    4
+#define ATMEL_HLCDC_YPHIDEF    4
+
+static u32 atmel_hlcdc_plane_phiscaler_get_factor(u32 srcsize,
+                                                 u32 dstsize,
+                                                 u32 phidef)
+{
+       u32 factor, max_memsize;
+
+       factor = (256 * ((8 * (srcsize - 1)) - phidef)) / (dstsize - 1);
+       max_memsize = ((factor * (dstsize - 1)) + (256 * phidef)) / 2048;
+
+       if (max_memsize > srcsize - 1)
+               factor--;
+
+       return factor;
+}
+
 static void
-atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane,
-                                     struct atmel_hlcdc_plane_state *state)
+atmel_hlcdc_plane_scaler_set_phicoeff(struct atmel_hlcdc_plane *plane,
+                                     const u32 *coeff_tab, int size,
+                                     unsigned int cfg_offs)
 {
-       const struct atmel_hlcdc_layer_cfg_layout *layout =
-                                               &plane->layer.desc->layout;
-
-       if (layout->size)
-               atmel_hlcdc_layer_update_cfg(&plane->layer,
-                                            layout->size,
-                                            0xffffffff,
-                                            (state->crtc_w - 1) |
-                                            ((state->crtc_h - 1) << 16));
-
-       if (layout->memsize)
-               atmel_hlcdc_layer_update_cfg(&plane->layer,
-                                            layout->memsize,
-                                            0xffffffff,
-                                            (state->src_w - 1) |
-                                            ((state->src_h - 1) << 16));
-
-       if (layout->pos)
-               atmel_hlcdc_layer_update_cfg(&plane->layer,
-                                            layout->pos,
-                                            0xffffffff,
-                                            state->crtc_x |
-                                            (state->crtc_y  << 16));
-
-       /* TODO: rework the rescaling part */
-       if (state->crtc_w != state->src_w || state->crtc_h != state->src_h) {
-               u32 factor_reg = 0;
-
-               if (state->crtc_w != state->src_w) {
-                       int i;
-                       u32 factor;
-                       u32 *coeff_tab = heo_upscaling_xcoef;
-                       u32 max_memsize;
-
-                       if (state->crtc_w < state->src_w)
-                               coeff_tab = heo_downscaling_xcoef;
-                       for (i = 0; i < ARRAY_SIZE(heo_upscaling_xcoef); i++)
-                               atmel_hlcdc_layer_update_cfg(&plane->layer,
-                                                            17 + i,
-                                                            0xffffffff,
-                                                            coeff_tab[i]);
-                       factor = ((8 * 256 * state->src_w) - (256 * 4)) /
-                                state->crtc_w;
-                       factor++;
-                       max_memsize = ((factor * state->crtc_w) + (256 * 4)) /
-                                     2048;
-                       if (max_memsize > state->src_w)
-                               factor--;
-                       factor_reg |= factor | 0x80000000;
-               }
+       int i;
 
-               if (state->crtc_h != state->src_h) {
-                       int i;
-                       u32 factor;
-                       u32 *coeff_tab = heo_upscaling_ycoef;
-                       u32 max_memsize;
-
-                       if (state->crtc_h < state->src_h)
-                               coeff_tab = heo_downscaling_ycoef;
-                       for (i = 0; i < ARRAY_SIZE(heo_upscaling_ycoef); i++)
-                               atmel_hlcdc_layer_update_cfg(&plane->layer,
-                                                            33 + i,
-                                                            0xffffffff,
-                                                            coeff_tab[i]);
-                       factor = ((8 * 256 * state->src_h) - (256 * 4)) /
-                                state->crtc_h;
-                       factor++;
-                       max_memsize = ((factor * state->crtc_h) + (256 * 4)) /
-                                     2048;
-                       if (max_memsize > state->src_h)
-                               factor--;
-                       factor_reg |= (factor << 16) | 0x80000000;
-               }
+       for (i = 0; i < size; i++)
+               atmel_hlcdc_layer_write_cfg(&plane->layer, cfg_offs + i,
+                                           coeff_tab[i]);
+}
+
+void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane,
+                                   struct atmel_hlcdc_plane_state *state)
+{
+       const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
+       u32 xfactor, yfactor;
+
+       if (!desc->layout.scaler_config)
+               return;
 
-               atmel_hlcdc_layer_update_cfg(&plane->layer, 13, 0xffffffff,
-                                            factor_reg);
+       if (state->crtc_w == state->src_w && state->crtc_h == state->src_h) {
+               atmel_hlcdc_layer_write_cfg(&plane->layer,
+                                           desc->layout.scaler_config, 0);
+               return;
+       }
+
+       if (desc->layout.phicoeffs.x) {
+               xfactor = atmel_hlcdc_plane_phiscaler_get_factor(state->src_w,
+                                                       state->crtc_w,
+                                                       ATMEL_HLCDC_XPHIDEF);
+
+               yfactor = atmel_hlcdc_plane_phiscaler_get_factor(state->src_h,
+                                                       state->crtc_h,
+                                                       ATMEL_HLCDC_YPHIDEF);
+
+               atmel_hlcdc_plane_scaler_set_phicoeff(plane,
+                               state->crtc_w < state->src_w ?
+                               heo_downscaling_xcoef :
+                               heo_upscaling_xcoef,
+                               ARRAY_SIZE(heo_upscaling_xcoef),
+                               desc->layout.phicoeffs.x);
+
+               atmel_hlcdc_plane_scaler_set_phicoeff(plane,
+                               state->crtc_h < state->src_h ?
+                               heo_downscaling_ycoef :
+                               heo_upscaling_ycoef,
+                               ARRAY_SIZE(heo_upscaling_ycoef),
+                               desc->layout.phicoeffs.y);
        } else {
-               atmel_hlcdc_layer_update_cfg(&plane->layer, 13, 0xffffffff, 0);
+               xfactor = (1024 * state->src_w) / state->crtc_w;
+               yfactor = (1024 * state->src_h) / state->crtc_h;
        }
+
+       atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config,
+                                   ATMEL_HLCDC_LAYER_SCALER_ENABLE |
+                                   ATMEL_HLCDC_LAYER_SCALER_FACTORS(xfactor,
+                                                                    yfactor));
+}
+
+static void
+atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane,
+                                     struct atmel_hlcdc_plane_state *state)
+{
+       const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
+
+       if (desc->layout.size)
+               atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.size,
+                                       ATMEL_HLCDC_LAYER_SIZE(state->crtc_w,
+                                                              state->crtc_h));
+
+       if (desc->layout.memsize)
+               atmel_hlcdc_layer_write_cfg(&plane->layer,
+                                       desc->layout.memsize,
+                                       ATMEL_HLCDC_LAYER_SIZE(state->src_w,
+                                                              state->src_h));
+
+       if (desc->layout.pos)
+               atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.pos,
+                                       ATMEL_HLCDC_LAYER_POS(state->crtc_x,
+                                                             state->crtc_y));
+
+       atmel_hlcdc_plane_setup_scaler(plane, state);
 }
 
 static void
 atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
                                        struct atmel_hlcdc_plane_state *state)
 {
-       const struct atmel_hlcdc_layer_cfg_layout *layout =
-                                               &plane->layer.desc->layout;
-       unsigned int cfg = ATMEL_HLCDC_LAYER_DMA;
+       unsigned int cfg = ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id;
+       const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
+       u32 format = state->base.fb->format->format;
+
+       /*
+        * Rotation optimization is not working on RGB888 (rotation is still
+        * working but without any optimization).
+        */
+       if (format == DRM_FORMAT_RGB888)
+               cfg |= ATMEL_HLCDC_LAYER_DMA_ROTDIS;
+
+       atmel_hlcdc_layer_write_cfg(&plane->layer, ATMEL_HLCDC_LAYER_DMA_CFG,
+                                   cfg);
+
+       cfg = ATMEL_HLCDC_LAYER_DMA;
 
        if (plane->base.type != DRM_PLANE_TYPE_PRIMARY) {
                cfg |= ATMEL_HLCDC_LAYER_OVR | ATMEL_HLCDC_LAYER_ITER2BL |
                       ATMEL_HLCDC_LAYER_ITER;
 
-               if (atmel_hlcdc_format_embeds_alpha(state->base.fb->format->format))
+               if (atmel_hlcdc_format_embeds_alpha(format))
                        cfg |= ATMEL_HLCDC_LAYER_LAEN;
                else
                        cfg |= ATMEL_HLCDC_LAYER_GAEN |
                               ATMEL_HLCDC_LAYER_GA(state->alpha);
        }
 
-       atmel_hlcdc_layer_update_cfg(&plane->layer,
-                                    ATMEL_HLCDC_LAYER_DMA_CFG_ID,
-                                    ATMEL_HLCDC_LAYER_DMA_BLEN_MASK |
-                                    ATMEL_HLCDC_LAYER_DMA_SIF,
-                                    ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 |
-                                    state->ahb_id);
-
-       atmel_hlcdc_layer_update_cfg(&plane->layer, layout->general_config,
-                                    ATMEL_HLCDC_LAYER_ITER2BL |
-                                    ATMEL_HLCDC_LAYER_ITER |
-                                    ATMEL_HLCDC_LAYER_GAEN |
-                                    ATMEL_HLCDC_LAYER_GA_MASK |
-                                    ATMEL_HLCDC_LAYER_LAEN |
-                                    ATMEL_HLCDC_LAYER_OVR |
-                                    ATMEL_HLCDC_LAYER_DMA, cfg);
+       if (state->disc_h && state->disc_w)
+               cfg |= ATMEL_HLCDC_LAYER_DISCEN;
+
+       atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.general_config,
+                                   cfg);
 }
 
 static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane,
@@ -396,50 +420,50 @@ static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane,
            drm_rotation_90_or_270(state->base.rotation))
                cfg |= ATMEL_HLCDC_YUV422ROT;
 
-       atmel_hlcdc_layer_update_cfg(&plane->layer,
-                                    ATMEL_HLCDC_LAYER_FORMAT_CFG_ID,
-                                    0xffffffff,
-                                    cfg);
-
-       /*
-        * Rotation optimization is not working on RGB888 (rotation is still
-        * working but without any optimization).
-        */
-       if (state->base.fb->format->format == DRM_FORMAT_RGB888)
-               cfg = ATMEL_HLCDC_LAYER_DMA_ROTDIS;
-       else
-               cfg = 0;
-
-       atmel_hlcdc_layer_update_cfg(&plane->layer,
-                                    ATMEL_HLCDC_LAYER_DMA_CFG_ID,
-                                    ATMEL_HLCDC_LAYER_DMA_ROTDIS, cfg);
+       atmel_hlcdc_layer_write_cfg(&plane->layer,
+                                   ATMEL_HLCDC_LAYER_FORMAT_CFG, cfg);
 }
 
 static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane,
                                        struct atmel_hlcdc_plane_state *state)
 {
-       struct atmel_hlcdc_layer *layer = &plane->layer;
-       const struct atmel_hlcdc_layer_cfg_layout *layout =
-                                                       &layer->desc->layout;
+       const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
+       struct drm_framebuffer *fb = state->base.fb;
+       u32 sr;
        int i;
 
-       atmel_hlcdc_layer_update_set_fb(&plane->layer, state->base.fb,
-                                       state->offsets);
+       sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR);
 
        for (i = 0; i < state->nplanes; i++) {
-               if (layout->xstride[i]) {
-                       atmel_hlcdc_layer_update_cfg(&plane->layer,
-                                               layout->xstride[i],
-                                               0xffffffff,
-                                               state->xstride[i]);
+               struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, i);
+
+               state->dscrs[i]->addr = gem->paddr + state->offsets[i];
+
+               atmel_hlcdc_layer_write_reg(&plane->layer,
+                                           ATMEL_HLCDC_LAYER_PLANE_HEAD(i),
+                                           state->dscrs[i]->self);
+
+               if (!(sr & ATMEL_HLCDC_LAYER_EN)) {
+                       atmel_hlcdc_layer_write_reg(&plane->layer,
+                                       ATMEL_HLCDC_LAYER_PLANE_ADDR(i),
+                                       state->dscrs[i]->addr);
+                       atmel_hlcdc_layer_write_reg(&plane->layer,
+                                       ATMEL_HLCDC_LAYER_PLANE_CTRL(i),
+                                       state->dscrs[i]->ctrl);
+                       atmel_hlcdc_layer_write_reg(&plane->layer,
+                                       ATMEL_HLCDC_LAYER_PLANE_NEXT(i),
+                                       state->dscrs[i]->self);
                }
 
-               if (layout->pstride[i]) {
-                       atmel_hlcdc_layer_update_cfg(&plane->layer,
-                                               layout->pstride[i],
-                                               0xffffffff,
-                                               state->pstride[i]);
-               }
+               if (desc->layout.xstride[i])
+                       atmel_hlcdc_layer_write_cfg(&plane->layer,
+                                                   desc->layout.xstride[i],
+                                                   state->xstride[i]);
+
+               if (desc->layout.pstride[i])
+                       atmel_hlcdc_layer_write_cfg(&plane->layer,
+                                                   desc->layout.pstride[i],
+                                                   state->pstride[i]);
        }
 }
 
@@ -528,18 +552,10 @@ atmel_hlcdc_plane_prepare_disc_area(struct drm_crtc_state *c_state)
                disc_w = ovl_state->crtc_w;
        }
 
-       if (disc_x == primary_state->disc_x &&
-           disc_y == primary_state->disc_y &&
-           disc_w == primary_state->disc_w &&
-           disc_h == primary_state->disc_h)
-               return 0;
-
-
        primary_state->disc_x = disc_x;
        primary_state->disc_y = disc_y;
        primary_state->disc_w = disc_w;
        primary_state->disc_h = disc_h;
-       primary_state->disc_updated = true;
 
        return 0;
 }
@@ -548,32 +564,19 @@ static void
 atmel_hlcdc_plane_update_disc_area(struct atmel_hlcdc_plane *plane,
                                   struct atmel_hlcdc_plane_state *state)
 {
-       const struct atmel_hlcdc_layer_cfg_layout *layout =
-                                               &plane->layer.desc->layout;
-       int disc_surface = 0;
-
-       if (!state->disc_updated)
-               return;
-
-       disc_surface = state->disc_h * state->disc_w;
-
-       atmel_hlcdc_layer_update_cfg(&plane->layer, layout->general_config,
-                               ATMEL_HLCDC_LAYER_DISCEN,
-                               disc_surface ? ATMEL_HLCDC_LAYER_DISCEN : 0);
+       const struct atmel_hlcdc_layer_cfg_layout *layout;
 
-       if (!disc_surface)
+       layout = &plane->layer.desc->layout;
+       if (!layout->disc_pos || !layout->disc_size)
                return;
 
-       atmel_hlcdc_layer_update_cfg(&plane->layer,
-                                    layout->disc_pos,
-                                    0xffffffff,
-                                    state->disc_x | (state->disc_y << 16));
+       atmel_hlcdc_layer_write_cfg(&plane->layer, layout->disc_pos,
+                               ATMEL_HLCDC_LAYER_DISC_POS(state->disc_x,
+                                                          state->disc_y));
 
-       atmel_hlcdc_layer_update_cfg(&plane->layer,
-                                    layout->disc_size,
-                                    0xffffffff,
-                                    (state->disc_w - 1) |
-                                    ((state->disc_h - 1) << 16));
+       atmel_hlcdc_layer_write_cfg(&plane->layer, layout->disc_size,
+                               ATMEL_HLCDC_LAYER_DISC_SIZE(state->disc_w,
+                                                           state->disc_h));
 }
 
 static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
@@ -582,8 +585,7 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
        struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
        struct atmel_hlcdc_plane_state *state =
                                drm_plane_state_to_atmel_hlcdc_plane_state(s);
-       const struct atmel_hlcdc_layer_cfg_layout *layout =
-                                               &plane->layer.desc->layout;
+       const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
        struct drm_framebuffer *fb = state->base.fb;
        const struct drm_display_mode *mode;
        struct drm_crtc_state *crtc_state;
@@ -622,7 +624,7 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
        state->src_h >>= 16;
 
        state->nplanes = fb->format->num_planes;
-       if (state->nplanes > ATMEL_HLCDC_MAX_PLANES)
+       if (state->nplanes > ATMEL_HLCDC_LAYER_MAX_PLANES)
                return -EINVAL;
 
        /*
@@ -726,21 +728,19 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
        state->crtc_w = patched_crtc_w;
        state->crtc_h = patched_crtc_h;
 
-       if (!layout->size &&
+       if (!desc->layout.size &&
            (mode->hdisplay != state->crtc_w ||
             mode->vdisplay != state->crtc_h))
                return -EINVAL;
 
-       if (plane->layer.desc->max_height &&
-           state->crtc_h > plane->layer.desc->max_height)
+       if (desc->max_height && state->crtc_h > desc->max_height)
                return -EINVAL;
 
-       if (plane->layer.desc->max_width &&
-           state->crtc_w > plane->layer.desc->max_width)
+       if (desc->max_width && state->crtc_w > desc->max_width)
                return -EINVAL;
 
        if ((state->crtc_h != state->src_h || state->crtc_w != state->src_w) &&
-           (!layout->memsize ||
+           (!desc->layout.memsize ||
             atmel_hlcdc_format_embeds_alpha(state->base.fb->format->format)))
                return -EINVAL;
 
@@ -754,65 +754,13 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
        return 0;
 }
 
-static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p,
-                                       struct drm_plane_state *new_state)
-{
-       /*
-        * FIXME: we should avoid this const -> non-const cast but it's
-        * currently the only solution we have to modify the ->prepared
-        * state and rollback the update request.
-        * Ideally, we should rework the code to attach all the resources
-        * to atmel_hlcdc_plane_state (including the DMA desc allocation),
-        * but this require a complete rework of the atmel_hlcdc_layer
-        * code.
-        */
-       struct drm_plane_state *s = (struct drm_plane_state *)new_state;
-       struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
-       struct atmel_hlcdc_plane_state *state =
-                       drm_plane_state_to_atmel_hlcdc_plane_state(s);
-       int ret;
-
-       ret = atmel_hlcdc_layer_update_start(&plane->layer);
-       if (!ret)
-               state->prepared = true;
-
-       return ret;
-}
-
-static void atmel_hlcdc_plane_cleanup_fb(struct drm_plane *p,
-                                        struct drm_plane_state *old_state)
-{
-       /*
-        * FIXME: we should avoid this const -> non-const cast but it's
-        * currently the only solution we have to modify the ->prepared
-        * state and rollback the update request.
-        * Ideally, we should rework the code to attach all the resources
-        * to atmel_hlcdc_plane_state (including the DMA desc allocation),
-        * but this require a complete rework of the atmel_hlcdc_layer
-        * code.
-        */
-       struct drm_plane_state *s = (struct drm_plane_state *)old_state;
-       struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
-       struct atmel_hlcdc_plane_state *state =
-                       drm_plane_state_to_atmel_hlcdc_plane_state(s);
-
-       /*
-        * The Request has already been applied or cancelled, nothing to do
-        * here.
-        */
-       if (!state->prepared)
-               return;
-
-       atmel_hlcdc_layer_update_rollback(&plane->layer);
-       state->prepared = false;
-}
-
 static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
                                            struct drm_plane_state *old_s)
 {
        struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
        struct atmel_hlcdc_plane_state *state =
                        drm_plane_state_to_atmel_hlcdc_plane_state(p->state);
+       u32 sr;
 
        if (!p->state->crtc || !p->state->fb)
                return;
@@ -823,7 +771,18 @@ static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
        atmel_hlcdc_plane_update_buffers(plane, state);
        atmel_hlcdc_plane_update_disc_area(plane, state);
 
-       atmel_hlcdc_layer_update_commit(&plane->layer);
+       /* Enable the overrun interrupts. */
+       atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IER,
+                                   ATMEL_HLCDC_LAYER_OVR_IRQ(0) |
+                                   ATMEL_HLCDC_LAYER_OVR_IRQ(1) |
+                                   ATMEL_HLCDC_LAYER_OVR_IRQ(2));
+
+       /* Apply the new config at the next SOF event. */
+       sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR);
+       atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHER,
+                       ATMEL_HLCDC_LAYER_UPDATE |
+                       (sr & ATMEL_HLCDC_LAYER_EN ?
+                        ATMEL_HLCDC_LAYER_A2Q : ATMEL_HLCDC_LAYER_EN));
 }
 
 static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p,
@@ -831,7 +790,18 @@ static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p,
 {
        struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
 
-       atmel_hlcdc_layer_disable(&plane->layer);
+       /* Disable interrupts */
+       atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IDR,
+                                   0xffffffff);
+
+       /* Disable the layer */
+       atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHDR,
+                                   ATMEL_HLCDC_LAYER_RST |
+                                   ATMEL_HLCDC_LAYER_A2Q |
+                                   ATMEL_HLCDC_LAYER_UPDATE);
+
+       /* Clear all pending interrupts */
+       atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR);
 }
 
 static void atmel_hlcdc_plane_destroy(struct drm_plane *p)
@@ -841,10 +811,7 @@ static void atmel_hlcdc_plane_destroy(struct drm_plane *p)
        if (plane->base.fb)
                drm_framebuffer_unreference(plane->base.fb);
 
-       atmel_hlcdc_layer_cleanup(p->dev, &plane->layer);
-
        drm_plane_cleanup(p);
-       devm_kfree(p->dev->dev, plane);
 }
 
 static int atmel_hlcdc_plane_atomic_set_property(struct drm_plane *p,
@@ -884,24 +851,15 @@ static int atmel_hlcdc_plane_atomic_get_property(struct drm_plane *p,
 }
 
 static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane,
-                                            const struct atmel_hlcdc_layer_desc *desc,
-                                            struct atmel_hlcdc_plane_properties *props)
+                               struct atmel_hlcdc_plane_properties *props)
 {
-       struct regmap *regmap = plane->layer.hlcdc->regmap;
+       const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
 
        if (desc->type == ATMEL_HLCDC_OVERLAY_LAYER ||
-           desc->type == ATMEL_HLCDC_CURSOR_LAYER) {
+           desc->type == ATMEL_HLCDC_CURSOR_LAYER)
                drm_object_attach_property(&plane->base.base,
                                           props->alpha, 255);
 
-               /* Set default alpha value */
-               regmap_update_bits(regmap,
-                               desc->regs_offset +
-                               ATMEL_HLCDC_LAYER_GENERAL_CFG(&plane->layer),
-                               ATMEL_HLCDC_LAYER_GA_MASK,
-                               ATMEL_HLCDC_LAYER_GA_MASK);
-       }
-
        if (desc->layout.xstride && desc->layout.pstride) {
                int ret;
 
@@ -920,31 +878,78 @@ static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane,
                 * TODO: decare a "yuv-to-rgb-conv-factors" property to let
                 * userspace modify these factors (using a BLOB property ?).
                 */
-               regmap_write(regmap,
-                            desc->regs_offset +
-                            ATMEL_HLCDC_LAYER_CSC_CFG(&plane->layer, 0),
-                            0x4c900091);
-               regmap_write(regmap,
-                            desc->regs_offset +
-                            ATMEL_HLCDC_LAYER_CSC_CFG(&plane->layer, 1),
-                            0x7a5f5090);
-               regmap_write(regmap,
-                            desc->regs_offset +
-                            ATMEL_HLCDC_LAYER_CSC_CFG(&plane->layer, 2),
-                            0x40040890);
+               atmel_hlcdc_layer_write_cfg(&plane->layer,
+                                           desc->layout.csc,
+                                           0x4c900091);
+               atmel_hlcdc_layer_write_cfg(&plane->layer,
+                                           desc->layout.csc + 1,
+                                           0x7a5f5090);
+               atmel_hlcdc_layer_write_cfg(&plane->layer,
+                                           desc->layout.csc + 2,
+                                           0x40040890);
        }
 
        return 0;
 }
 
+void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane)
+{
+       const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
+       u32 isr;
+
+       isr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR);
+
+       /*
+        * There's not much we can do in case of overrun except informing
+        * the user. However, we are in interrupt context here, hence the
+        * use of dev_dbg().
+        */
+       if (isr &
+           (ATMEL_HLCDC_LAYER_OVR_IRQ(0) | ATMEL_HLCDC_LAYER_OVR_IRQ(1) |
+            ATMEL_HLCDC_LAYER_OVR_IRQ(2)))
+               dev_dbg(plane->base.dev->dev, "overrun on plane %s\n",
+                       desc->name);
+}
+
 static struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = {
-       .prepare_fb = atmel_hlcdc_plane_prepare_fb,
-       .cleanup_fb = atmel_hlcdc_plane_cleanup_fb,
        .atomic_check = atmel_hlcdc_plane_atomic_check,
        .atomic_update = atmel_hlcdc_plane_atomic_update,
        .atomic_disable = atmel_hlcdc_plane_atomic_disable,
 };
 
+static int atmel_hlcdc_plane_alloc_dscrs(struct drm_plane *p,
+                                        struct atmel_hlcdc_plane_state *state)
+{
+       struct atmel_hlcdc_dc *dc = p->dev->dev_private;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(state->dscrs); i++) {
+               struct atmel_hlcdc_dma_channel_dscr *dscr;
+               dma_addr_t dscr_dma;
+
+               dscr = dma_pool_alloc(dc->dscrpool, GFP_KERNEL, &dscr_dma);
+               if (!dscr)
+                       goto err;
+
+               dscr->addr = 0;
+               dscr->next = dscr_dma;
+               dscr->self = dscr_dma;
+               dscr->ctrl = ATMEL_HLCDC_LAYER_DFETCH;
+
+               state->dscrs[i] = dscr;
+       }
+
+       return 0;
+
+err:
+       for (i--; i >= 0; i--) {
+               dma_pool_free(dc->dscrpool, state->dscrs[i],
+                             state->dscrs[i]->self);
+       }
+
+       return -ENOMEM;
+}
+
 static void atmel_hlcdc_plane_reset(struct drm_plane *p)
 {
        struct atmel_hlcdc_plane_state *state;
@@ -961,6 +966,13 @@ static void atmel_hlcdc_plane_reset(struct drm_plane *p)
 
        state = kzalloc(sizeof(*state), GFP_KERNEL);
        if (state) {
+               if (atmel_hlcdc_plane_alloc_dscrs(p, state)) {
+                       kfree(state);
+                       dev_err(p->dev->dev,
+                               "Failed to allocate initial plane state\n");
+                       return;
+               }
+
                state->alpha = 255;
                p->state = &state->base;
                p->state->plane = p;
@@ -978,8 +990,10 @@ atmel_hlcdc_plane_atomic_duplicate_state(struct drm_plane *p)
        if (!copy)
                return NULL;
 
-       copy->disc_updated = false;
-       copy->prepared = false;
+       if (atmel_hlcdc_plane_alloc_dscrs(p, copy)) {
+               kfree(copy);
+               return NULL;
+       }
 
        if (copy->base.fb)
                drm_framebuffer_reference(copy->base.fb);
@@ -987,11 +1001,18 @@ atmel_hlcdc_plane_atomic_duplicate_state(struct drm_plane *p)
        return &copy->base;
 }
 
-static void atmel_hlcdc_plane_atomic_destroy_state(struct drm_plane *plane,
+static void atmel_hlcdc_plane_atomic_destroy_state(struct drm_plane *p,
                                                   struct drm_plane_state *s)
 {
        struct atmel_hlcdc_plane_state *state =
                        drm_plane_state_to_atmel_hlcdc_plane_state(s);
+       struct atmel_hlcdc_dc *dc = p->dev->dev_private;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(state->dscrs); i++) {
+               dma_pool_free(dc->dscrpool, state->dscrs[i],
+                             state->dscrs[i]->self);
+       }
 
        if (s->fb)
                drm_framebuffer_unreference(s->fb);
@@ -1011,22 +1032,21 @@ static struct drm_plane_funcs layer_plane_funcs = {
        .atomic_get_property = atmel_hlcdc_plane_atomic_get_property,
 };
 
-static struct atmel_hlcdc_plane *
-atmel_hlcdc_plane_create(struct drm_device *dev,
-                        const struct atmel_hlcdc_layer_desc *desc,
-                        struct atmel_hlcdc_plane_properties *props)
+static int atmel_hlcdc_plane_create(struct drm_device *dev,
+                                   const struct atmel_hlcdc_layer_desc *desc,
+                                   struct atmel_hlcdc_plane_properties *props)
 {
+       struct atmel_hlcdc_dc *dc = dev->dev_private;
        struct atmel_hlcdc_plane *plane;
        enum drm_plane_type type;
        int ret;
 
        plane = devm_kzalloc(dev->dev, sizeof(*plane), GFP_KERNEL);
        if (!plane)
-               return ERR_PTR(-ENOMEM);
+               return -ENOMEM;
 
-       ret = atmel_hlcdc_layer_init(dev, &plane->layer, desc);
-       if (ret)
-               return ERR_PTR(ret);
+       atmel_hlcdc_layer_init(&plane->layer, desc, dc->hlcdc->regmap);
+       plane->properties = props;
 
        if (desc->type == ATMEL_HLCDC_BASE_LAYER)
                type = DRM_PLANE_TYPE_PRIMARY;
@@ -1040,17 +1060,19 @@ atmel_hlcdc_plane_create(struct drm_device *dev,
                                       desc->formats->formats,
                                       desc->formats->nformats, type, NULL);
        if (ret)
-               return ERR_PTR(ret);
+               return ret;
 
        drm_plane_helper_add(&plane->base,
                             &atmel_hlcdc_layer_plane_helper_funcs);
 
        /* Set default property values*/
-       ret = atmel_hlcdc_plane_init_properties(plane, desc, props);
+       ret = atmel_hlcdc_plane_init_properties(plane, props);
        if (ret)
-               return ERR_PTR(ret);
+               return ret;
+
+       dc->layers[desc->id] = &plane->layer;
 
-       return plane;
+       return 0;
 }
 
 static struct atmel_hlcdc_plane_properties *
@@ -1069,72 +1091,34 @@ atmel_hlcdc_plane_create_properties(struct drm_device *dev)
        return props;
 }
 
-struct atmel_hlcdc_planes *
-atmel_hlcdc_create_planes(struct drm_device *dev)
+int atmel_hlcdc_create_planes(struct drm_device *dev)
 {
        struct atmel_hlcdc_dc *dc = dev->dev_private;
        struct atmel_hlcdc_plane_properties *props;
-       struct atmel_hlcdc_planes *planes;
        const struct atmel_hlcdc_layer_desc *descs = dc->desc->layers;
        int nlayers = dc->desc->nlayers;
-       int i;
-
-       planes = devm_kzalloc(dev->dev, sizeof(*planes), GFP_KERNEL);
-       if (!planes)
-               return ERR_PTR(-ENOMEM);
-
-       for (i = 0; i < nlayers; i++) {
-               if (descs[i].type == ATMEL_HLCDC_OVERLAY_LAYER)
-                       planes->noverlays++;
-       }
-
-       if (planes->noverlays) {
-               planes->overlays = devm_kzalloc(dev->dev,
-                                               planes->noverlays *
-                                               sizeof(*planes->overlays),
-                                               GFP_KERNEL);
-               if (!planes->overlays)
-                       return ERR_PTR(-ENOMEM);
-       }
+       int i, ret;
 
        props = atmel_hlcdc_plane_create_properties(dev);
        if (IS_ERR(props))
-               return ERR_CAST(props);
+               return PTR_ERR(props);
 
-       planes->noverlays = 0;
-       for (i = 0; i < nlayers; i++) {
-               struct atmel_hlcdc_plane *plane;
+       dc->dscrpool = dmam_pool_create("atmel-hlcdc-dscr", dev->dev,
+                               sizeof(struct atmel_hlcdc_dma_channel_dscr),
+                               sizeof(u64), 0);
+       if (!dc->dscrpool)
+               return -ENOMEM;
 
-               if (descs[i].type == ATMEL_HLCDC_PP_LAYER)
+       for (i = 0; i < nlayers; i++) {
+               if (descs[i].type != ATMEL_HLCDC_BASE_LAYER &&
+                   descs[i].type != ATMEL_HLCDC_OVERLAY_LAYER &&
+                   descs[i].type != ATMEL_HLCDC_CURSOR_LAYER)
                        continue;
 
-               plane = atmel_hlcdc_plane_create(dev, &descs[i], props);
-               if (IS_ERR(plane))
-                       return ERR_CAST(plane);
-
-               plane->properties = props;
-
-               switch (descs[i].type) {
-               case ATMEL_HLCDC_BASE_LAYER:
-                       if (planes->primary)
-                               return ERR_PTR(-EINVAL);
-                       planes->primary = plane;
-                       break;
-
-               case ATMEL_HLCDC_OVERLAY_LAYER:
-                       planes->overlays[planes->noverlays++] = plane;
-                       break;
-
-               case ATMEL_HLCDC_CURSOR_LAYER:
-                       if (planes->cursor)
-                               return ERR_PTR(-EINVAL);
-                       planes->cursor = plane;
-                       break;
-
-               default:
-                       break;
-               }
+               ret = atmel_hlcdc_plane_create(dev, &descs[i], props);
+               if (ret)
+                       return ret;
        }
 
-       return planes;
+       return 0;
 }
index 932a769637efedb021585f61f93645a3fe14edd4..a11debaad626eed5cb5fd716f12f622def5c0f8d 100644 (file)
@@ -107,10 +107,8 @@ static int bochsfb_create(struct drm_fb_helper *helper,
        info->par = &bochs->fb.helper;
 
        ret = bochs_framebuffer_init(bochs->dev, &bochs->fb.gfb, &mode_cmd, gobj);
-       if (ret) {
-               drm_fb_helper_release_fbi(helper);
+       if (ret)
                return ret;
-       }
 
        bochs->fb.size = size;
 
@@ -144,7 +142,6 @@ static int bochs_fbdev_destroy(struct bochs_device *bochs)
        DRM_DEBUG_DRIVER("\n");
 
        drm_fb_helper_unregister_fbi(&bochs->fb.helper);
-       drm_fb_helper_release_fbi(&bochs->fb.helper);
 
        if (gfb->obj) {
                drm_gem_object_unreference_unlocked(gfb->obj);
index cdd0a9d44ba188d236755b8aa612bec0c59442e5..2d51a2269fc610ffc705abcb7a49c1bdcaffbae9 100644 (file)
@@ -2184,6 +2184,10 @@ static int sii8620_probe(struct i2c_client *client,
                                        sii8620_irq_thread,
                                        IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
                                        "sii8620", ctx);
+       if (ret < 0) {
+               dev_err(dev, "failed to install IRQ handler\n");
+               return ret;
+       }
 
        ctx->gpio_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
        if (IS_ERR(ctx->gpio_reset)) {
index b054ea349952033f1e2643c75b2b7df989a5b979..b379d046991b3eaea962b67de754c86b530084cc 100644 (file)
@@ -220,7 +220,7 @@ static const struct of_device_id tfp410_match[] = {
 };
 MODULE_DEVICE_TABLE(of, tfp410_match);
 
-struct platform_driver tfp410_platform_driver = {
+static struct platform_driver tfp410_platform_driver = {
        .probe  = tfp410_probe,
        .remove = tfp410_remove,
        .driver = {
index 4cc679278182da01f526b77843576a17e6767eca..7fa58eeadc9d05d743de30d6033985224b245ea3 100644 (file)
@@ -250,7 +250,6 @@ static int cirrus_fbdev_destroy(struct drm_device *dev,
        struct cirrus_framebuffer *gfb = &gfbdev->gfb;
 
        drm_fb_helper_unregister_fbi(&gfbdev->helper);
-       drm_fb_helper_release_fbi(&gfbdev->helper);
 
        if (gfb->obj) {
                drm_gem_object_unreference_unlocked(gfb->obj);
index a5673107db26c403236d2562ce8d6c36bc162c54..236d947011f96629ab52b68456b6760369837d93 100644 (file)
@@ -150,7 +150,7 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state)
                                                       state->connectors[i].state);
                state->connectors[i].ptr = NULL;
                state->connectors[i].state = NULL;
-               drm_connector_unreference(connector);
+               drm_connector_put(connector);
        }
 
        for (i = 0; i < config->num_crtc; i++) {
@@ -275,6 +275,8 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state,
                return ERR_PTR(-ENOMEM);
 
        state->crtcs[index].state = crtc_state;
+       state->crtcs[index].old_state = crtc->state;
+       state->crtcs[index].new_state = crtc_state;
        state->crtcs[index].ptr = crtc;
        crtc_state->state = state;
 
@@ -322,7 +324,7 @@ int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
        if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0)
                return 0;
 
-       drm_property_unreference_blob(state->mode_blob);
+       drm_property_blob_put(state->mode_blob);
        state->mode_blob = NULL;
 
        if (mode) {
@@ -368,7 +370,7 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
        if (blob == state->mode_blob)
                return 0;
 
-       drm_property_unreference_blob(state->mode_blob);
+       drm_property_blob_put(state->mode_blob);
        state->mode_blob = NULL;
 
        memset(&state->mode, 0, sizeof(state->mode));
@@ -380,7 +382,7 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
                                            blob->data))
                        return -EINVAL;
 
-               state->mode_blob = drm_property_reference_blob(blob);
+               state->mode_blob = drm_property_blob_get(blob);
                state->enable = true;
                DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n",
                                 state->mode.name, state);
@@ -413,9 +415,9 @@ drm_atomic_replace_property_blob(struct drm_property_blob **blob,
        if (old_blob == new_blob)
                return;
 
-       drm_property_unreference_blob(old_blob);
+       drm_property_blob_put(old_blob);
        if (new_blob)
-               drm_property_reference_blob(new_blob);
+               drm_property_blob_get(new_blob);
        *blob = new_blob;
        *replaced = true;
 
@@ -437,13 +439,13 @@ drm_atomic_replace_property_blob_from_id(struct drm_crtc *crtc,
                        return -EINVAL;
 
                if (expected_size > 0 && expected_size != new_blob->length) {
-                       drm_property_unreference_blob(new_blob);
+                       drm_property_blob_put(new_blob);
                        return -EINVAL;
                }
        }
 
        drm_atomic_replace_property_blob(blob, new_blob, replaced);
-       drm_property_unreference_blob(new_blob);
+       drm_property_blob_put(new_blob);
 
        return 0;
 }
@@ -478,7 +480,7 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
                struct drm_property_blob *mode =
                        drm_property_lookup_blob(dev, val);
                ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
-               drm_property_unreference_blob(mode);
+               drm_property_blob_put(mode);
                return ret;
        } else if (property == config->degamma_lut_property) {
                ret = drm_atomic_replace_property_blob_from_id(crtc,
@@ -621,8 +623,8 @@ static int drm_atomic_crtc_check(struct drm_crtc *crtc,
         * pipe.
         */
        if (state->event && !state->active && !crtc->state->active) {
-               DRM_DEBUG_ATOMIC("[CRTC:%d] requesting event but off\n",
-                                crtc->base.id);
+               DRM_DEBUG_ATOMIC("[CRTC:%d:%s] requesting event but off\n",
+                                crtc->base.id, crtc->name);
                return -EINVAL;
        }
 
@@ -689,6 +691,8 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state,
 
        state->planes[index].state = plane_state;
        state->planes[index].ptr = plane;
+       state->planes[index].old_state = plane->state;
+       state->planes[index].new_state = plane_state;
        plane_state->state = state;
 
        DRM_DEBUG_ATOMIC("Added [PLANE:%d:%s] %p state to %p\n",
@@ -733,7 +737,7 @@ int drm_atomic_plane_set_property(struct drm_plane *plane,
                struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, val);
                drm_atomic_set_fb_for_plane(state, fb);
                if (fb)
-                       drm_framebuffer_unreference(fb);
+                       drm_framebuffer_put(fb);
        } else if (property == config->prop_in_fence_fd) {
                if (state->fence)
                        return -EINVAL;
@@ -1026,13 +1030,16 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state,
        if (!connector_state)
                return ERR_PTR(-ENOMEM);
 
-       drm_connector_reference(connector);
+       drm_connector_get(connector);
        state->connectors[index].state = connector_state;
+       state->connectors[index].old_state = connector->state;
+       state->connectors[index].new_state = connector_state;
        state->connectors[index].ptr = connector;
        connector_state->state = state;
 
-       DRM_DEBUG_ATOMIC("Added [CONNECTOR:%d] %p state to %p\n",
-                        connector->base.id, connector_state, state);
+       DRM_DEBUG_ATOMIC("Added [CONNECTOR:%d:%s] %p state to %p\n",
+                        connector->base.id, connector->name,
+                        connector_state, state);
 
        if (connector_state->crtc) {
                struct drm_crtc_state *crtc_state;
@@ -1102,6 +1109,20 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
                state->tv.saturation = val;
        } else if (property == config->tv_hue_property) {
                state->tv.hue = val;
+       } else if (property == config->link_status_property) {
+               /* Never downgrade from GOOD to BAD on userspace's request here,
+                * only hw issues can do that.
+                *
+                * For an atomic property the userspace doesn't need to be able
+                * to understand all the properties, but needs to be able to
+                * restore the state it wants on VT switch. So if the userspace
+                * tries to change the link_status from GOOD to BAD, driver
+                * silently rejects it and returns a 0. This prevents userspace
+                * from accidently breaking  the display when it restores the
+                * state.
+                */
+               if (state->link_status != DRM_LINK_STATUS_GOOD)
+                       state->link_status = val;
        } else if (connector->funcs->atomic_set_property) {
                return connector->funcs->atomic_set_property(connector,
                                state, property, val);
@@ -1176,6 +1197,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
                *val = state->tv.saturation;
        } else if (property == config->tv_hue_property) {
                *val = state->tv.hue;
+       } else if (property == config->link_status_property) {
+               *val = state->link_status;
        } else if (connector->funcs->atomic_get_property) {
                return connector->funcs->atomic_get_property(connector,
                                state, property, val);
@@ -1357,7 +1380,7 @@ drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
                crtc_state->connector_mask &=
                        ~(1 << drm_connector_index(conn_state->connector));
 
-               drm_connector_unreference(conn_state->connector);
+               drm_connector_put(conn_state->connector);
                conn_state->crtc = NULL;
        }
 
@@ -1369,7 +1392,7 @@ drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
                crtc_state->connector_mask |=
                        1 << drm_connector_index(conn_state->connector);
 
-               drm_connector_reference(conn_state->connector);
+               drm_connector_get(conn_state->connector);
                conn_state->crtc = crtc;
 
                DRM_DEBUG_ATOMIC("Link connector state %p to [CRTC:%d:%s]\n",
@@ -1408,8 +1431,13 @@ drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
        struct drm_connector *connector;
        struct drm_connector_state *conn_state;
        struct drm_connector_list_iter conn_iter;
+       struct drm_crtc_state *crtc_state;
        int ret;
 
+       crtc_state = drm_atomic_get_crtc_state(state, crtc);
+       if (IS_ERR(crtc_state))
+               return PTR_ERR(crtc_state);
+
        ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx);
        if (ret)
                return ret;
@@ -1418,21 +1446,21 @@ drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
                         crtc->base.id, crtc->name, state);
 
        /*
-        * Changed connectors are already in @state, so only need to look at the
-        * current configuration.
+        * Changed connectors are already in @state, so only need to look
+        * at the connector_mask in crtc_state.
         */
-       drm_connector_list_iter_get(state->dev, &conn_iter);
+       drm_connector_list_iter_begin(state->dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
-               if (connector->state->crtc != crtc)
+               if (!(crtc_state->connector_mask & (1 << drm_connector_index(connector))))
                        continue;
 
                conn_state = drm_atomic_get_connector_state(state, connector);
                if (IS_ERR(conn_state)) {
-                       drm_connector_list_iter_put(&conn_iter);
+                       drm_connector_list_iter_end(&conn_iter);
                        return PTR_ERR(conn_state);
                }
        }
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 
        return 0;
 }
@@ -1546,7 +1574,7 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
 
        DRM_DEBUG_ATOMIC("checking %p\n", state);
 
-       for_each_plane_in_state(state, plane, plane_state, i) {
+       for_each_new_plane_in_state(state, plane, plane_state, i) {
                ret = drm_atomic_plane_check(plane, plane_state);
                if (ret) {
                        DRM_DEBUG_ATOMIC("[PLANE:%d:%s] atomic core check failed\n",
@@ -1555,7 +1583,7 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
                }
        }
 
-       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
                ret = drm_atomic_crtc_check(crtc, crtc_state);
                if (ret) {
                        DRM_DEBUG_ATOMIC("[CRTC:%d:%s] atomic core check failed\n",
@@ -1568,7 +1596,7 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
                ret = config->funcs->atomic_check(state->dev, state);
 
        if (!state->allow_modeset) {
-               for_each_crtc_in_state(state, crtc, crtc_state, i) {
+               for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
                        if (drm_atomic_crtc_needs_modeset(crtc_state)) {
                                DRM_DEBUG_ATOMIC("[CRTC:%d:%s] requires full modeset\n",
                                                 crtc->base.id, crtc->name);
@@ -1652,13 +1680,13 @@ static void drm_atomic_print_state(const struct drm_atomic_state *state)
 
        DRM_DEBUG_ATOMIC("checking %p\n", state);
 
-       for_each_plane_in_state(state, plane, plane_state, i)
+       for_each_new_plane_in_state(state, plane, plane_state, i)
                drm_atomic_plane_print_state(&p, plane_state);
 
-       for_each_crtc_in_state(state, crtc, crtc_state, i)
+       for_each_new_crtc_in_state(state, crtc, crtc_state, i)
                drm_atomic_crtc_print_state(&p, crtc_state);
 
-       for_each_connector_in_state(state, connector, connector_state, i)
+       for_each_new_connector_in_state(state, connector, connector_state, i)
                drm_atomic_connector_print_state(&p, connector_state);
 }
 
@@ -1694,10 +1722,10 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p)
        list_for_each_entry(crtc, &config->crtc_list, head)
                drm_atomic_crtc_print_state(p, crtc->state);
 
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter)
                drm_atomic_connector_print_state(p, connector->state);
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 }
 EXPORT_SYMBOL(drm_state_dump);
 
@@ -1837,12 +1865,12 @@ void drm_atomic_clean_old_fb(struct drm_device *dev,
                if (ret == 0) {
                        struct drm_framebuffer *new_fb = plane->state->fb;
                        if (new_fb)
-                               drm_framebuffer_reference(new_fb);
+                               drm_framebuffer_get(new_fb);
                        plane->fb = new_fb;
                        plane->crtc = plane->state->crtc;
 
                        if (plane->old_fb)
-                               drm_framebuffer_unreference(plane->old_fb);
+                               drm_framebuffer_put(plane->old_fb);
                }
                plane->old_fb = NULL;
        }
@@ -1938,7 +1966,7 @@ static int prepare_crtc_signaling(struct drm_device *dev,
        if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
                return 0;
 
-       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
                s32 __user *fence_ptr;
 
                fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
@@ -2018,7 +2046,7 @@ static void complete_crtc_signaling(struct drm_device *dev,
                return;
        }
 
-       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
                struct drm_pending_vblank_event *event = crtc_state->event;
                /*
                 * Free the allocated event. drm_atomic_helper_setup_commit
@@ -2049,6 +2077,94 @@ static void complete_crtc_signaling(struct drm_device *dev,
        kfree(fence_state);
 }
 
+int drm_atomic_remove_fb(struct drm_framebuffer *fb)
+{
+       struct drm_modeset_acquire_ctx ctx;
+       struct drm_device *dev = fb->dev;
+       struct drm_atomic_state *state;
+       struct drm_plane *plane;
+       struct drm_connector *conn;
+       struct drm_connector_state *conn_state;
+       int i, ret = 0;
+       unsigned plane_mask;
+
+       state = drm_atomic_state_alloc(dev);
+       if (!state)
+               return -ENOMEM;
+
+       drm_modeset_acquire_init(&ctx, 0);
+       state->acquire_ctx = &ctx;
+
+retry:
+       plane_mask = 0;
+       ret = drm_modeset_lock_all_ctx(dev, &ctx);
+       if (ret)
+               goto unlock;
+
+       drm_for_each_plane(plane, dev) {
+               struct drm_plane_state *plane_state;
+
+               if (plane->state->fb != fb)
+                       continue;
+
+               plane_state = drm_atomic_get_plane_state(state, plane);
+               if (IS_ERR(plane_state)) {
+                       ret = PTR_ERR(plane_state);
+                       goto unlock;
+               }
+
+               if (plane_state->crtc->primary == plane) {
+                       struct drm_crtc_state *crtc_state;
+
+                       crtc_state = drm_atomic_get_existing_crtc_state(state, plane_state->crtc);
+
+                       ret = drm_atomic_add_affected_connectors(state, plane_state->crtc);
+                       if (ret)
+                               goto unlock;
+
+                       crtc_state->active = false;
+                       ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
+                       if (ret)
+                               goto unlock;
+               }
+
+               drm_atomic_set_fb_for_plane(plane_state, NULL);
+               ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
+               if (ret)
+                       goto unlock;
+
+               plane_mask |= BIT(drm_plane_index(plane));
+
+               plane->old_fb = plane->fb;
+       }
+
+       for_each_connector_in_state(state, conn, conn_state, i) {
+               ret = drm_atomic_set_crtc_for_connector(conn_state, NULL);
+
+               if (ret)
+                       goto unlock;
+       }
+
+       if (plane_mask)
+               ret = drm_atomic_commit(state);
+
+unlock:
+       if (plane_mask)
+               drm_atomic_clean_old_fb(dev, plane_mask, ret);
+
+       if (ret == -EDEADLK) {
+               drm_modeset_backoff(&ctx);
+               goto retry;
+       }
+
+       drm_atomic_state_put(state);
+
+       drm_modeset_drop_locks(&ctx);
+       drm_modeset_acquire_fini(&ctx);
+
+       return ret;
+}
+
 int drm_mode_atomic_ioctl(struct drm_device *dev,
                          void *data, struct drm_file *file_priv)
 {
@@ -2122,13 +2238,13 @@ retry:
                }
 
                if (!obj->properties) {
-                       drm_mode_object_unreference(obj);
+                       drm_mode_object_put(obj);
                        ret = -ENOENT;
                        goto out;
                }
 
                if (get_user(count_props, count_props_ptr + copied_objs)) {
-                       drm_mode_object_unreference(obj);
+                       drm_mode_object_put(obj);
                        ret = -EFAULT;
                        goto out;
                }
@@ -2141,14 +2257,14 @@ retry:
                        struct drm_property *prop;
 
                        if (get_user(prop_id, props_ptr + copied_props)) {
-                               drm_mode_object_unreference(obj);
+                               drm_mode_object_put(obj);
                                ret = -EFAULT;
                                goto out;
                        }
 
                        prop = drm_mode_obj_find_prop_id(obj, prop_id);
                        if (!prop) {
-                               drm_mode_object_unreference(obj);
+                               drm_mode_object_put(obj);
                                ret = -ENOENT;
                                goto out;
                        }
@@ -2156,14 +2272,14 @@ retry:
                        if (copy_from_user(&prop_value,
                                           prop_values_ptr + copied_props,
                                           sizeof(prop_value))) {
-                               drm_mode_object_unreference(obj);
+                               drm_mode_object_put(obj);
                                ret = -EFAULT;
                                goto out;
                        }
 
                        ret = atomic_set_prop(state, obj, prop, prop_value);
                        if (ret) {
-                               drm_mode_object_unreference(obj);
+                               drm_mode_object_put(obj);
                                goto out;
                        }
 
@@ -2176,7 +2292,7 @@ retry:
                        plane_mask |= (1 << drm_plane_index(plane));
                        plane->old_fb = plane->fb;
                }
-               drm_mode_object_unreference(obj);
+               drm_mode_object_put(obj);
        }
 
        ret = prepare_crtc_signaling(dev, state, arg, file_priv, &fence_state,
index 01d936b7be43c0fb3d4cf4a8037c81dafcd7f979..6b12396f718b3bd9d16901c541e464d5b43ca450 100644 (file)
@@ -145,7 +145,7 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state,
         * and the crtc is disabled if no encoder is left. This preserves
         * compatibility with the legacy set_config behavior.
         */
-       drm_connector_list_iter_get(state->dev, &conn_iter);
+       drm_connector_list_iter_begin(state->dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
                struct drm_crtc_state *crtc_state;
 
@@ -193,7 +193,7 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state,
                }
        }
 out:
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 
        return ret;
 }
@@ -322,10 +322,11 @@ update_connector_routing(struct drm_atomic_state *state,
        }
 
        if (!drm_encoder_crtc_ok(new_encoder, connector_state->crtc)) {
-               DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] incompatible with [CRTC:%d]\n",
+               DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] incompatible with [CRTC:%d:%s]\n",
                                 new_encoder->base.id,
                                 new_encoder->name,
-                                connector_state->crtc->base.id);
+                                connector_state->crtc->base.id,
+                                connector_state->crtc->name);
                return -EINVAL;
        }
 
@@ -529,6 +530,13 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
                                               connector_state);
                if (ret)
                        return ret;
+               if (connector->state->crtc) {
+                       crtc_state = drm_atomic_get_existing_crtc_state(state,
+                                                                       connector->state->crtc);
+                       if (connector->state->link_status !=
+                           connector_state->link_status)
+                               crtc_state->connectors_changed = true;
+               }
        }
 
        /*
@@ -1119,7 +1127,8 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
                                        drm_crtc_vblank_count(crtc),
                                msecs_to_jiffies(50));
 
-               WARN(!ret, "[CRTC:%d] vblank wait timed out\n", crtc->base.id);
+               WARN(!ret, "[CRTC:%d:%s] vblank wait timed out\n",
+                    crtc->base.id, crtc->name);
 
                drm_crtc_vblank_put(crtc);
        }
@@ -1170,7 +1179,7 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_tail);
 static void commit_tail(struct drm_atomic_state *old_state)
 {
        struct drm_device *dev = old_state->dev;
-       struct drm_mode_config_helper_funcs *funcs;
+       const struct drm_mode_config_helper_funcs *funcs;
 
        funcs = dev->mode_config.helper_private;
 
@@ -1977,11 +1986,11 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
        int i;
        long ret;
        struct drm_connector *connector;
-       struct drm_connector_state *conn_state;
+       struct drm_connector_state *conn_state, *old_conn_state;
        struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
+       struct drm_crtc_state *crtc_state, *old_crtc_state;
        struct drm_plane *plane;
-       struct drm_plane_state *plane_state;
+       struct drm_plane_state *plane_state, *old_plane_state;
        struct drm_crtc_commit *commit;
 
        if (stall) {
@@ -2005,13 +2014,17 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
                }
        }
 
-       for_each_connector_in_state(state, connector, conn_state, i) {
+       for_each_oldnew_connector_in_state(state, connector, old_conn_state, conn_state, i) {
+               WARN_ON(connector->state != old_conn_state);
+
                connector->state->state = state;
                swap(state->connectors[i].state, connector->state);
                connector->state->state = NULL;
        }
 
-       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) {
+               WARN_ON(crtc->state != old_crtc_state);
+
                crtc->state->state = state;
                swap(state->crtcs[i].state, crtc->state);
                crtc->state->state = NULL;
@@ -2026,7 +2039,9 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
                }
        }
 
-       for_each_plane_in_state(state, plane, plane_state, i) {
+       for_each_oldnew_plane_in_state(state, plane, old_plane_state, plane_state, i) {
+               WARN_ON(plane->state != old_plane_state);
+
                plane->state->state = state;
                swap(state->planes[i].state, plane->state);
                plane->state->state = NULL;
@@ -2233,6 +2248,8 @@ static int update_output_state(struct drm_atomic_state *state,
                                                                NULL);
                        if (ret)
                                return ret;
+                       /* Make sure legacy setCrtc always re-trains */
+                       conn_state->link_status = DRM_LINK_STATUS_GOOD;
                }
        }
 
@@ -2276,6 +2293,12 @@ static int update_output_state(struct drm_atomic_state *state,
  *
  * Provides a default crtc set_config handler using the atomic driver interface.
  *
+ * NOTE: For backwards compatibility with old userspace this automatically
+ * resets the "link-status" property to GOOD, to force any link
+ * re-training. The SETCRTC ioctl does not define whether an update does
+ * need a full modeset or just a plane update, hence we're allowed to do
+ * that. See also drm_mode_connector_set_link_status_property().
+ *
  * Returns:
  * Returns 0 on success, negative errno numbers on failure.
  */
@@ -2419,9 +2442,13 @@ int drm_atomic_helper_disable_all(struct drm_device *dev,
                                  struct drm_modeset_acquire_ctx *ctx)
 {
        struct drm_atomic_state *state;
+       struct drm_connector_state *conn_state;
        struct drm_connector *conn;
-       struct drm_connector_list_iter conn_iter;
-       int err;
+       struct drm_plane_state *plane_state;
+       struct drm_plane *plane;
+       struct drm_crtc_state *crtc_state;
+       struct drm_crtc *crtc;
+       int ret, i;
 
        state = drm_atomic_state_alloc(dev);
        if (!state)
@@ -2429,29 +2456,48 @@ int drm_atomic_helper_disable_all(struct drm_device *dev,
 
        state->acquire_ctx = ctx;
 
-       drm_connector_list_iter_get(dev, &conn_iter);
-       drm_for_each_connector_iter(conn, &conn_iter) {
-               struct drm_crtc *crtc = conn->state->crtc;
-               struct drm_crtc_state *crtc_state;
-
-               if (!crtc || conn->dpms != DRM_MODE_DPMS_ON)
-                       continue;
-
+       drm_for_each_crtc(crtc, dev) {
                crtc_state = drm_atomic_get_crtc_state(state, crtc);
                if (IS_ERR(crtc_state)) {
-                       err = PTR_ERR(crtc_state);
+                       ret = PTR_ERR(crtc_state);
                        goto free;
                }
 
                crtc_state->active = false;
+
+               ret = drm_atomic_set_mode_prop_for_crtc(crtc_state, NULL);
+               if (ret < 0)
+                       goto free;
+
+               ret = drm_atomic_add_affected_planes(state, crtc);
+               if (ret < 0)
+                       goto free;
+
+               ret = drm_atomic_add_affected_connectors(state, crtc);
+               if (ret < 0)
+                       goto free;
+       }
+
+       for_each_connector_in_state(state, conn, conn_state, i) {
+               ret = drm_atomic_set_crtc_for_connector(conn_state, NULL);
+               if (ret < 0)
+                       goto free;
        }
 
-       err = drm_atomic_commit(state);
+       for_each_plane_in_state(state, plane, plane_state, i) {
+               ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
+               if (ret < 0)
+                       goto free;
+
+               drm_atomic_set_fb_for_plane(plane_state, NULL);
+       }
+
+       ret = drm_atomic_commit(state);
 free:
-       drm_connector_list_iter_put(&conn_iter);
        drm_atomic_state_put(state);
-       return err;
+       return ret;
 }
+
 EXPORT_SYMBOL(drm_atomic_helper_disable_all);
 
 /**
@@ -2477,7 +2523,7 @@ EXPORT_SYMBOL(drm_atomic_helper_disable_all);
  *
  * See also:
  * drm_atomic_helper_duplicate_state(), drm_atomic_helper_disable_all(),
- * drm_atomic_helper_resume()
+ * drm_atomic_helper_resume(), drm_atomic_helper_commit_duplicated_state()
  */
 struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev)
 {
@@ -2517,6 +2563,47 @@ unlock:
 }
 EXPORT_SYMBOL(drm_atomic_helper_suspend);
 
+/**
+ * drm_atomic_helper_commit_duplicated_state - commit duplicated state
+ * @state: duplicated atomic state to commit
+ * @ctx: pointer to acquire_ctx to use for commit.
+ *
+ * The state returned by drm_atomic_helper_duplicate_state() and
+ * drm_atomic_helper_suspend() is partially invalid, and needs to
+ * be fixed up before commit.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ *
+ * See also:
+ * drm_atomic_helper_suspend()
+ */
+int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
+                                             struct drm_modeset_acquire_ctx *ctx)
+{
+       int i;
+       struct drm_plane *plane;
+       struct drm_plane_state *plane_state;
+       struct drm_connector *connector;
+       struct drm_connector_state *conn_state;
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *crtc_state;
+
+       state->acquire_ctx = ctx;
+
+       for_each_new_plane_in_state(state, plane, plane_state, i)
+               state->planes[i].old_state = plane->state;
+
+       for_each_new_crtc_in_state(state, crtc, crtc_state, i)
+               state->crtcs[i].old_state = crtc->state;
+
+       for_each_new_connector_in_state(state, connector, conn_state, i)
+               state->connectors[i].old_state = connector->state;
+
+       return drm_atomic_commit(state);
+}
+EXPORT_SYMBOL(drm_atomic_helper_commit_duplicated_state);
+
 /**
  * drm_atomic_helper_resume - subsystem-level resume helper
  * @dev: DRM device
@@ -2540,9 +2627,9 @@ int drm_atomic_helper_resume(struct drm_device *dev,
        int err;
 
        drm_mode_config_reset(dev);
+
        drm_modeset_lock_all(dev);
-       state->acquire_ctx = config->acquire_ctx;
-       err = drm_atomic_commit(state);
+       err = drm_atomic_helper_commit_duplicated_state(state, config->acquire_ctx);
        drm_modeset_unlock_all(dev);
 
        return err;
@@ -2718,7 +2805,8 @@ static int page_flip_common(
                                struct drm_atomic_state *state,
                                struct drm_crtc *crtc,
                                struct drm_framebuffer *fb,
-                               struct drm_pending_vblank_event *event)
+                               struct drm_pending_vblank_event *event,
+                               uint32_t flags)
 {
        struct drm_plane *plane = crtc->primary;
        struct drm_plane_state *plane_state;
@@ -2730,12 +2818,12 @@ static int page_flip_common(
                return PTR_ERR(crtc_state);
 
        crtc_state->event = event;
+       crtc_state->pageflip_flags = flags;
 
        plane_state = drm_atomic_get_plane_state(state, plane);
        if (IS_ERR(plane_state))
                return PTR_ERR(plane_state);
 
-
        ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
        if (ret != 0)
                return ret;
@@ -2744,8 +2832,8 @@ static int page_flip_common(
        /* Make sure we don't accidentally do a full modeset. */
        state->allow_modeset = false;
        if (!crtc_state->active) {
-               DRM_DEBUG_ATOMIC("[CRTC:%d] disabled, rejecting legacy flip\n",
-                                crtc->base.id);
+               DRM_DEBUG_ATOMIC("[CRTC:%d:%s] disabled, rejecting legacy flip\n",
+                                crtc->base.id, crtc->name);
                return -EINVAL;
        }
 
@@ -2762,10 +2850,6 @@ static int page_flip_common(
  * Provides a default &drm_crtc_funcs.page_flip implementation
  * using the atomic driver interface.
  *
- * Note that for now so called async page flips (i.e. updates which are not
- * synchronized to vblank) are not supported, since the atomic interfaces have
- * no provisions for this yet.
- *
  * Returns:
  * Returns 0 on success, negative errno numbers on failure.
  *
@@ -2781,9 +2865,6 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
        struct drm_atomic_state *state;
        int ret = 0;
 
-       if (flags & DRM_MODE_PAGE_FLIP_ASYNC)
-               return -EINVAL;
-
        state = drm_atomic_state_alloc(plane->dev);
        if (!state)
                return -ENOMEM;
@@ -2791,7 +2872,7 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
        state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
 
 retry:
-       ret = page_flip_common(state, crtc, fb, event);
+       ret = page_flip_common(state, crtc, fb, event, flags);
        if (ret != 0)
                goto fail;
 
@@ -2846,9 +2927,6 @@ int drm_atomic_helper_page_flip_target(
        struct drm_crtc_state *crtc_state;
        int ret = 0;
 
-       if (flags & DRM_MODE_PAGE_FLIP_ASYNC)
-               return -EINVAL;
-
        state = drm_atomic_state_alloc(plane->dev);
        if (!state)
                return -ENOMEM;
@@ -2856,7 +2934,7 @@ int drm_atomic_helper_page_flip_target(
        state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
 
 retry:
-       ret = page_flip_common(state, crtc, fb, event);
+       ret = page_flip_common(state, crtc, fb, event, flags);
        if (ret != 0)
                goto fail;
 
@@ -2940,7 +3018,7 @@ retry:
 
        WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
 
-       drm_connector_list_iter_get(connector->dev, &conn_iter);
+       drm_connector_list_iter_begin(connector->dev, &conn_iter);
        drm_for_each_connector_iter(tmp_connector, &conn_iter) {
                if (tmp_connector->state->crtc != crtc)
                        continue;
@@ -2950,7 +3028,7 @@ retry:
                        break;
                }
        }
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
        crtc_state->active = active;
 
        ret = drm_atomic_commit(state);
@@ -3042,13 +3120,13 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
        memcpy(state, crtc->state, sizeof(*state));
 
        if (state->mode_blob)
-               drm_property_reference_blob(state->mode_blob);
+               drm_property_blob_get(state->mode_blob);
        if (state->degamma_lut)
-               drm_property_reference_blob(state->degamma_lut);
+               drm_property_blob_get(state->degamma_lut);
        if (state->ctm)
-               drm_property_reference_blob(state->ctm);
+               drm_property_blob_get(state->ctm);
        if (state->gamma_lut)
-               drm_property_reference_blob(state->gamma_lut);
+               drm_property_blob_get(state->gamma_lut);
        state->mode_changed = false;
        state->active_changed = false;
        state->planes_changed = false;
@@ -3056,6 +3134,7 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
        state->color_mgmt_changed = false;
        state->zpos_changed = false;
        state->event = NULL;
+       state->pageflip_flags = 0;
 }
 EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
 
@@ -3092,10 +3171,10 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
  */
 void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state)
 {
-       drm_property_unreference_blob(state->mode_blob);
-       drm_property_unreference_blob(state->degamma_lut);
-       drm_property_unreference_blob(state->ctm);
-       drm_property_unreference_blob(state->gamma_lut);
+       drm_property_blob_put(state->mode_blob);
+       drm_property_blob_put(state->degamma_lut);
+       drm_property_blob_put(state->ctm);
+       drm_property_blob_put(state->gamma_lut);
 }
 EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
 
@@ -3151,7 +3230,7 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
        memcpy(state, plane->state, sizeof(*state));
 
        if (state->fb)
-               drm_framebuffer_reference(state->fb);
+               drm_framebuffer_get(state->fb);
 
        state->fence = NULL;
 }
@@ -3191,7 +3270,7 @@ EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state);
 void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state)
 {
        if (state->fb)
-               drm_framebuffer_unreference(state->fb);
+               drm_framebuffer_put(state->fb);
 
        if (state->fence)
                dma_fence_put(state->fence);
@@ -3272,7 +3351,7 @@ __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
 {
        memcpy(state, connector->state, sizeof(*state));
        if (state->crtc)
-               drm_connector_reference(connector);
+               drm_connector_get(connector);
 }
 EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state);
 
@@ -3360,18 +3439,18 @@ drm_atomic_helper_duplicate_state(struct drm_device *dev,
                }
        }
 
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(conn, &conn_iter) {
                struct drm_connector_state *conn_state;
 
                conn_state = drm_atomic_get_connector_state(state, conn);
                if (IS_ERR(conn_state)) {
                        err = PTR_ERR(conn_state);
-                       drm_connector_list_iter_put(&conn_iter);
+                       drm_connector_list_iter_end(&conn_iter);
                        goto free;
                }
        }
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 
        /* clear the acquire context so that it isn't accidentally reused */
        state->acquire_ctx = NULL;
@@ -3398,7 +3477,7 @@ void
 __drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state)
 {
        if (state->crtc)
-               drm_connector_unreference(state->connector);
+               drm_connector_put(state->connector);
 }
 EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
 
@@ -3493,7 +3572,7 @@ fail:
                goto backoff;
 
        drm_atomic_state_put(state);
-       drm_property_unreference_blob(blob);
+       drm_property_blob_put(blob);
        return ret;
 
 backoff:
index c3b9aaccdf4227bf668748723a592276131fbdfa..3bd76e918b5d29ab5e37a733960925d765c080c9 100644 (file)
@@ -88,7 +88,7 @@ drm_clflush_pages(struct page *pages[], unsigned long num_pages)
        }
 
        if (wbinvd_on_all_cpus())
-               printk(KERN_ERR "Timed out waiting for cache flush.\n");
+               pr_err("Timed out waiting for cache flush\n");
 
 #elif defined(__powerpc__)
        unsigned long i;
@@ -105,7 +105,7 @@ drm_clflush_pages(struct page *pages[], unsigned long num_pages)
                kunmap_atomic(page_virtual);
        }
 #else
-       printk(KERN_ERR "Architecture has no drm_cache.c support\n");
+       pr_err("Architecture has no drm_cache.c support\n");
        WARN_ON_ONCE(1);
 #endif
 }
@@ -134,9 +134,9 @@ drm_clflush_sg(struct sg_table *st)
        }
 
        if (wbinvd_on_all_cpus())
-               printk(KERN_ERR "Timed out waiting for cache flush.\n");
+               pr_err("Timed out waiting for cache flush\n");
 #else
-       printk(KERN_ERR "Architecture has no drm_cache.c support\n");
+       pr_err("Architecture has no drm_cache.c support\n");
        WARN_ON_ONCE(1);
 #endif
 }
@@ -167,9 +167,9 @@ drm_clflush_virt_range(void *addr, unsigned long length)
        }
 
        if (wbinvd_on_all_cpus())
-               printk(KERN_ERR "Timed out waiting for cache flush.\n");
+               pr_err("Timed out waiting for cache flush\n");
 #else
-       printk(KERN_ERR "Architecture has no drm_cache.c support\n");
+       pr_err("Architecture has no drm_cache.c support\n");
        WARN_ON_ONCE(1);
 #endif
 }
index 45464c8b797dea1edca2efd29590a970cd45514e..9f847615ac74ab012f6203a141627a5c6f5993e2 100644 (file)
@@ -35,8 +35,8 @@
  * als fixed panels or anything else that can display pixels in some form. As
  * opposed to all other KMS objects representing hardware (like CRTC, encoder or
  * plane abstractions) connectors can be hotplugged and unplugged at runtime.
- * Hence they are reference-counted using drm_connector_reference() and
- * drm_connector_unreference().
+ * Hence they are reference-counted using drm_connector_get() and
+ * drm_connector_put().
  *
  * KMS driver must create, initialize, register and attach at a &struct
  * drm_connector for each such sink. The instance is created as other KMS
@@ -128,22 +128,8 @@ static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
                return;
 
        if (mode->force) {
-               const char *s;
-
-               switch (mode->force) {
-               case DRM_FORCE_OFF:
-                       s = "OFF";
-                       break;
-               case DRM_FORCE_ON_DIGITAL:
-                       s = "ON - dig";
-                       break;
-               default:
-               case DRM_FORCE_ON:
-                       s = "ON";
-                       break;
-               }
-
-               DRM_INFO("forcing %s connector %s\n", connector->name, s);
+               DRM_INFO("forcing %s connector %s\n", connector->name,
+                        drm_get_connector_force_name(mode->force));
                connector->force = mode->force;
        }
 
@@ -189,9 +175,9 @@ int drm_connector_init(struct drm_device *dev,
        struct ida *connector_ida =
                &drm_connector_enum_list[connector_type].ida;
 
-       ret = drm_mode_object_get_reg(dev, &connector->base,
-                                     DRM_MODE_OBJECT_CONNECTOR,
-                                     false, drm_connector_free);
+       ret = __drm_mode_object_add(dev, &connector->base,
+                                   DRM_MODE_OBJECT_CONNECTOR,
+                                   false, drm_connector_free);
        if (ret)
                return ret;
 
@@ -244,6 +230,10 @@ int drm_connector_init(struct drm_device *dev,
        drm_object_attach_property(&connector->base,
                                      config->dpms_property, 0);
 
+       drm_object_attach_property(&connector->base,
+                                  config->link_status_property,
+                                  0);
+
        if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
                drm_object_attach_property(&connector->base, config->prop_crtc_id, 0);
        }
@@ -445,10 +435,10 @@ void drm_connector_unregister_all(struct drm_device *dev)
        struct drm_connector *connector;
        struct drm_connector_list_iter conn_iter;
 
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter)
                drm_connector_unregister(connector);
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 }
 
 int drm_connector_register_all(struct drm_device *dev)
@@ -457,13 +447,13 @@ int drm_connector_register_all(struct drm_device *dev)
        struct drm_connector_list_iter conn_iter;
        int ret = 0;
 
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
                ret = drm_connector_register(connector);
                if (ret)
                        break;
        }
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 
        if (ret)
                drm_connector_unregister_all(dev);
@@ -488,6 +478,28 @@ const char *drm_get_connector_status_name(enum drm_connector_status status)
 }
 EXPORT_SYMBOL(drm_get_connector_status_name);
 
+/**
+ * drm_get_connector_force_name - return a string for connector force
+ * @force: connector force to get name of
+ *
+ * Returns: const pointer to name.
+ */
+const char *drm_get_connector_force_name(enum drm_connector_force force)
+{
+       switch (force) {
+       case DRM_FORCE_UNSPECIFIED:
+               return "unspecified";
+       case DRM_FORCE_OFF:
+               return "off";
+       case DRM_FORCE_ON:
+               return "on";
+       case DRM_FORCE_ON_DIGITAL:
+               return "digital";
+       default:
+               return "unknown";
+       }
+}
+
 #ifdef CONFIG_LOCKDEP
 static struct lockdep_map connector_list_iter_dep_map = {
        .name = "drm_connector_list_iter"
@@ -495,23 +507,23 @@ static struct lockdep_map connector_list_iter_dep_map = {
 #endif
 
 /**
- * drm_connector_list_iter_get - initialize a connector_list iterator
+ * drm_connector_list_iter_begin - initialize a connector_list iterator
  * @dev: DRM device
  * @iter: connector_list iterator
  *
  * Sets @iter up to walk the &drm_mode_config.connector_list of @dev. @iter
- * must always be cleaned up again by calling drm_connector_list_iter_put().
+ * must always be cleaned up again by calling drm_connector_list_iter_end().
  * Iteration itself happens using drm_connector_list_iter_next() or
  * drm_for_each_connector_iter().
  */
-void drm_connector_list_iter_get(struct drm_device *dev,
-                                struct drm_connector_list_iter *iter)
+void drm_connector_list_iter_begin(struct drm_device *dev,
+                                  struct drm_connector_list_iter *iter)
 {
        iter->dev = dev;
        iter->conn = NULL;
        lock_acquire_shared_recursive(&connector_list_iter_dep_map, 0, 1, NULL, _RET_IP_);
 }
-EXPORT_SYMBOL(drm_connector_list_iter_get);
+EXPORT_SYMBOL(drm_connector_list_iter_begin);
 
 /**
  * drm_connector_list_iter_next - return next connector
@@ -545,14 +557,14 @@ drm_connector_list_iter_next(struct drm_connector_list_iter *iter)
        spin_unlock_irqrestore(&config->connector_list_lock, flags);
 
        if (old_conn)
-               drm_connector_unreference(old_conn);
+               drm_connector_put(old_conn);
 
        return iter->conn;
 }
 EXPORT_SYMBOL(drm_connector_list_iter_next);
 
 /**
- * drm_connector_list_iter_put - tear down a connector_list iterator
+ * drm_connector_list_iter_end - tear down a connector_list iterator
  * @iter: connector_list iterator
  *
  * Tears down @iter and releases any resources (like &drm_connector references)
@@ -560,14 +572,14 @@ EXPORT_SYMBOL(drm_connector_list_iter_next);
  * iteration completes fully or when it was aborted without walking the entire
  * list.
  */
-void drm_connector_list_iter_put(struct drm_connector_list_iter *iter)
+void drm_connector_list_iter_end(struct drm_connector_list_iter *iter)
 {
        iter->dev = NULL;
        if (iter->conn)
-               drm_connector_unreference(iter->conn);
+               drm_connector_put(iter->conn);
        lock_release(&connector_list_iter_dep_map, 0, _RET_IP_);
 }
-EXPORT_SYMBOL(drm_connector_list_iter_put);
+EXPORT_SYMBOL(drm_connector_list_iter_end);
 
 static const struct drm_prop_enum_list drm_subpixel_enum_list[] = {
        { SubPixelUnknown, "Unknown" },
@@ -599,6 +611,12 @@ static const struct drm_prop_enum_list drm_dpms_enum_list[] = {
 };
 DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
 
+static const struct drm_prop_enum_list drm_link_status_enum_list[] = {
+       { DRM_MODE_LINK_STATUS_GOOD, "Good" },
+       { DRM_MODE_LINK_STATUS_BAD, "Bad" },
+};
+DRM_ENUM_NAME_FN(drm_get_link_status_name, drm_link_status_enum_list)
+
 /**
  * drm_display_info_set_bus_formats - set the supported bus formats
  * @info: display info to store bus formats in
@@ -718,6 +736,11 @@ DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
  *     tiling and virtualize both &drm_crtc and &drm_plane if needed. Drivers
  *     should update this value using drm_mode_connector_set_tile_property().
  *     Userspace cannot change this property.
+ * link-status:
+ *      Connector link-status property to indicate the status of link. The default
+ *      value of link-status is "GOOD". If something fails during or after modeset,
+ *      the kernel driver may set this to "BAD" and issue a hotplug uevent. Drivers
+ *      should update this value using drm_mode_connector_set_link_status_property().
  *
  * Connectors also have one standardized atomic property:
  *
@@ -759,6 +782,13 @@ int drm_connector_create_standard_properties(struct drm_device *dev)
                return -ENOMEM;
        dev->mode_config.tile_property = prop;
 
+       prop = drm_property_create_enum(dev, 0, "link-status",
+                                       drm_link_status_enum_list,
+                                       ARRAY_SIZE(drm_link_status_enum_list));
+       if (!prop)
+               return -ENOMEM;
+       dev->mode_config.link_status_property = prop;
+
        return 0;
 }
 
@@ -1088,6 +1118,36 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
 
+/**
+ * drm_mode_connector_set_link_status_property - Set link status property of a connector
+ * @connector: drm connector
+ * @link_status: new value of link status property (0: Good, 1: Bad)
+ *
+ * In usual working scenario, this link status property will always be set to
+ * "GOOD". If something fails during or after a mode set, the kernel driver
+ * may set this link status property to "BAD". The caller then needs to send a
+ * hotplug uevent for userspace to re-check the valid modes through
+ * GET_CONNECTOR_IOCTL and retry modeset.
+ *
+ * Note: Drivers cannot rely on userspace to support this property and
+ * issue a modeset. As such, they may choose to handle issues (like
+ * re-training a link) without userspace's intervention.
+ *
+ * The reason for adding this property is to handle link training failures, but
+ * it is not limited to DP or link training. For example, if we implement
+ * asynchronous setcrtc, this property can be used to report any failures in that.
+ */
+void drm_mode_connector_set_link_status_property(struct drm_connector *connector,
+                                                uint64_t link_status)
+{
+       struct drm_device *dev = connector->dev;
+
+       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+       connector->state->link_status = link_status;
+       drm_modeset_unlock(&dev->mode_config.connection_mutex);
+}
+EXPORT_SYMBOL(drm_mode_connector_set_link_status_property);
+
 int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
                                    struct drm_property *property,
                                    uint64_t value)
@@ -1249,7 +1309,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
 out:
        mutex_unlock(&dev->mode_config.mutex);
 out_unref:
-       drm_connector_unreference(connector);
+       drm_connector_put(connector);
 
        return ret;
 }
index 6915f897bd8e73d42342d21ea1c1bd4e0bb16b2a..e2974d3c92e7870cd25617eb904ad584af425776 100644 (file)
@@ -282,7 +282,7 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
        spin_lock_init(&crtc->commit_lock);
 
        drm_modeset_lock_init(&crtc->mutex);
-       ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
+       ret = drm_mode_object_add(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
        if (ret)
                return ret;
 
@@ -471,9 +471,9 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
 
        drm_for_each_crtc(tmp, crtc->dev) {
                if (tmp->primary->fb)
-                       drm_framebuffer_reference(tmp->primary->fb);
+                       drm_framebuffer_get(tmp->primary->fb);
                if (tmp->primary->old_fb)
-                       drm_framebuffer_unreference(tmp->primary->old_fb);
+                       drm_framebuffer_put(tmp->primary->old_fb);
                tmp->primary->old_fb = NULL;
        }
 
@@ -567,7 +567,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
                        }
                        fb = crtc->primary->fb;
                        /* Make refcounting symmetric with the lookup path. */
-                       drm_framebuffer_reference(fb);
+                       drm_framebuffer_get(fb);
                } else {
                        fb = drm_framebuffer_lookup(dev, crtc_req->fb_id);
                        if (!fb) {
@@ -680,12 +680,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
 
 out:
        if (fb)
-               drm_framebuffer_unreference(fb);
+               drm_framebuffer_put(fb);
 
        if (connector_set) {
                for (i = 0; i < crtc_req->count_connectors; i++) {
                        if (connector_set[i])
-                               drm_connector_unreference(connector_set[i]);
+                               drm_connector_put(connector_set[i]);
                }
        }
        kfree(connector_set);
index 44ba0e990d6c9125f4b71c65de62035bb2559c3c..8aa8c10841217445117e34e49c423c878e76237d 100644 (file)
@@ -102,14 +102,14 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
        }
 
 
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
                if (connector->encoder == encoder) {
-                       drm_connector_list_iter_put(&conn_iter);
+                       drm_connector_list_iter_end(&conn_iter);
                        return true;
                }
        }
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
        return false;
 }
 EXPORT_SYMBOL(drm_helper_encoder_in_use);
@@ -449,7 +449,7 @@ drm_crtc_helper_disable(struct drm_crtc *crtc)
                if (encoder->crtc != crtc)
                        continue;
 
-               drm_connector_list_iter_get(dev, &conn_iter);
+               drm_connector_list_iter_begin(dev, &conn_iter);
                drm_for_each_connector_iter(connector, &conn_iter) {
                        if (connector->encoder != encoder)
                                continue;
@@ -465,9 +465,9 @@ drm_crtc_helper_disable(struct drm_crtc *crtc)
                        connector->dpms = DRM_MODE_DPMS_OFF;
 
                        /* we keep a reference while the encoder is bound */
-                       drm_connector_unreference(connector);
+                       drm_connector_put(connector);
                }
-               drm_connector_list_iter_put(&conn_iter);
+               drm_connector_list_iter_end(&conn_iter);
        }
 
        __drm_helper_disable_unused_functions(dev);
@@ -583,10 +583,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
        }
 
        count = 0;
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter)
                save_connector_encoders[count++] = connector->encoder;
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 
        save_set.crtc = set->crtc;
        save_set.mode = &set->crtc->mode;
@@ -623,12 +623,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
        for (ro = 0; ro < set->num_connectors; ro++) {
                if (set->connectors[ro]->encoder)
                        continue;
-               drm_connector_reference(set->connectors[ro]);
+               drm_connector_get(set->connectors[ro]);
        }
 
        /* a) traverse passed in connector list and get encoders for them */
        count = 0;
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
                const struct drm_connector_helper_funcs *connector_funcs =
                        connector->helper_private;
@@ -662,7 +662,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                        connector->encoder = new_encoder;
                }
        }
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 
        if (fail) {
                ret = -EINVAL;
@@ -670,7 +670,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
        }
 
        count = 0;
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
                if (!connector->encoder)
                        continue;
@@ -689,7 +689,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                if (new_crtc &&
                    !drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
                        ret = -EINVAL;
-                       drm_connector_list_iter_put(&conn_iter);
+                       drm_connector_list_iter_end(&conn_iter);
                        goto fail;
                }
                if (new_crtc != connector->encoder->crtc) {
@@ -706,7 +706,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                                      connector->base.id, connector->name);
                }
        }
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 
        /* mode_set_base is not a required function */
        if (fb_changed && !crtc_funcs->mode_set_base)
@@ -761,10 +761,10 @@ fail:
        }
 
        count = 0;
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter)
                connector->encoder = save_connector_encoders[count++];
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 
        /* after fail drop reference on all unbound connectors in set, let
         * bound connectors keep their reference
@@ -772,7 +772,7 @@ fail:
        for (ro = 0; ro < set->num_connectors; ro++) {
                if (set->connectors[ro]->encoder)
                        continue;
-               drm_connector_unreference(set->connectors[ro]);
+               drm_connector_put(set->connectors[ro]);
        }
 
        /* Try to restore the config */
@@ -794,12 +794,12 @@ static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder)
        struct drm_connector_list_iter conn_iter;
        struct drm_device *dev = encoder->dev;
 
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter)
                if (connector->encoder == encoder)
                        if (connector->dpms < dpms)
                                dpms = connector->dpms;
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 
        return dpms;
 }
@@ -835,12 +835,12 @@ static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
        struct drm_connector_list_iter conn_iter;
        struct drm_device *dev = crtc->dev;
 
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter)
                if (connector->encoder && connector->encoder->crtc == crtc)
                        if (connector->dpms < dpms)
                                dpms = connector->dpms;
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 
        return dpms;
 }
index 955c5690bf643117fc00e17108da9708acdc09cb..8c04275cf226811a024c51cfd303e7537c7a1aac 100644 (file)
@@ -98,15 +98,13 @@ int drm_mode_destroyblob_ioctl(struct drm_device *dev,
                               void *data, struct drm_file *file_priv);
 
 /* drm_mode_object.c */
-int drm_mode_object_get_reg(struct drm_device *dev,
-                           struct drm_mode_object *obj,
-                           uint32_t obj_type,
-                           bool register_obj,
-                           void (*obj_free_cb)(struct kref *kref));
+int __drm_mode_object_add(struct drm_device *dev, struct drm_mode_object *obj,
+                         uint32_t obj_type, bool register_obj,
+                         void (*obj_free_cb)(struct kref *kref));
+int drm_mode_object_add(struct drm_device *dev, struct drm_mode_object *obj,
+                       uint32_t obj_type);
 void drm_mode_object_register(struct drm_device *dev,
                              struct drm_mode_object *obj);
-int drm_mode_object_get(struct drm_device *dev,
-                       struct drm_mode_object *obj, uint32_t obj_type);
 struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
                                               uint32_t id, uint32_t type);
 void drm_mode_object_unregister(struct drm_device *dev,
@@ -142,6 +140,7 @@ int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
                                    struct drm_property *property,
                                    uint64_t value);
 int drm_connector_create_standard_properties(struct drm_device *dev);
+const char *drm_get_connector_force_name(enum drm_connector_force force);
 
 /* IOCTL */
 int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
@@ -183,6 +182,7 @@ int drm_atomic_get_property(struct drm_mode_object *obj,
                            struct drm_property *property, uint64_t *val);
 int drm_mode_atomic_ioctl(struct drm_device *dev,
                          void *data, struct drm_file *file_priv);
+int drm_atomic_remove_fb(struct drm_framebuffer *fb);
 
 
 /* drm_plane.c */
index 2290a74a6e466f2a2fda546c53a2077fd6753c48..8b2c61ae000446fccfd6afe7db7e68886cd1fccc 100644 (file)
@@ -261,30 +261,8 @@ int drm_debugfs_cleanup(struct drm_minor *minor)
 static int connector_show(struct seq_file *m, void *data)
 {
        struct drm_connector *connector = m->private;
-       const char *status;
 
-       switch (connector->force) {
-       case DRM_FORCE_ON:
-               status = "on\n";
-               break;
-
-       case DRM_FORCE_ON_DIGITAL:
-               status = "digital\n";
-               break;
-
-       case DRM_FORCE_OFF:
-               status = "off\n";
-               break;
-
-       case DRM_FORCE_UNSPECIFIED:
-               status = "unspecified\n";
-               break;
-
-       default:
-               return 0;
-       }
-
-       seq_puts(m, status);
+       seq_printf(m, "%s\n", drm_get_connector_force_name(connector->force));
 
        return 0;
 }
index e025639662718cc6441a897ffa713fc5404cc66e..80e62f6693215f1deaf9d40af232f56d800d9ac3 100644 (file)
@@ -386,6 +386,8 @@ const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type)
                return "type 2 DVI";
        case DRM_DP_DUAL_MODE_TYPE2_HDMI:
                return "type 2 HDMI";
+       case DRM_DP_DUAL_MODE_LSPCON:
+               return "lspcon";
        default:
                WARN_ON(type != DRM_DP_DUAL_MODE_UNKNOWN);
                return "unknown";
index c8baab9bee0d05cf904153021db5601ade303586..171d7a02ace0d473b46b9f85821d33e1a57b1514 100644 (file)
@@ -1131,23 +1131,26 @@ bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid,
 
        csum = drm_edid_block_checksum(raw_edid);
        if (csum) {
-               if (print_bad_edid) {
-                       DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum);
-               }
-
                if (edid_corrupt)
                        *edid_corrupt = true;
 
                /* allow CEA to slide through, switches mangle this */
-               if (raw_edid[0] != 0x02)
+               if (raw_edid[0] == CEA_EXT) {
+                       DRM_DEBUG("EDID checksum is invalid, remainder is %d\n", csum);
+                       DRM_DEBUG("Assuming a KVM switch modified the CEA block but left the original checksum\n");
+               } else {
+                       if (print_bad_edid)
+                               DRM_NOTE("EDID checksum is invalid, remainder is %d\n", csum);
+
                        goto bad;
+               }
        }
 
        /* per-block-type checks */
        switch (raw_edid[0]) {
        case 0: /* base */
                if (edid->version != 1) {
-                       DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version);
+                       DRM_NOTE("EDID has major version %d, instead of 1\n", edid->version);
                        goto bad;
                }
 
@@ -1164,11 +1167,12 @@ bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid,
 bad:
        if (print_bad_edid) {
                if (drm_edid_is_zero(raw_edid, EDID_LENGTH)) {
-                       printk(KERN_ERR "EDID block is all zeroes\n");
+                       pr_notice("EDID block is all zeroes\n");
                } else {
-                       printk(KERN_ERR "Raw EDID:\n");
-                       print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1,
-                              raw_edid, EDID_LENGTH, false);
+                       pr_notice("Raw EDID:\n");
+                       print_hex_dump(KERN_NOTICE,
+                                      " \t", DUMP_PREFIX_NONE, 16, 1,
+                                      raw_edid, EDID_LENGTH, false);
                }
        }
        return false;
@@ -1424,7 +1428,10 @@ struct edid *drm_get_edid(struct drm_connector *connector,
 {
        struct edid *edid;
 
-       if (!drm_probe_ddc(adapter))
+       if (connector->force == DRM_FORCE_OFF)
+               return NULL;
+
+       if (connector->force == DRM_FORCE_UNSPECIFIED && !drm_probe_ddc(adapter))
                return NULL;
 
        edid = drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter);
@@ -3433,6 +3440,9 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
        connector->video_latency[1] = 0;
        connector->audio_latency[1] = 0;
 
+       if (!edid)
+               return;
+
        cea = drm_find_cea_extension(edid);
        if (!cea) {
                DRM_DEBUG_KMS("ELD: no CEA Extension found\n");
@@ -3999,7 +4009,7 @@ static int validate_displayid(u8 *displayid, int length, int idx)
                csum += displayid[i];
        }
        if (csum) {
-               DRM_ERROR("DisplayID checksum invalid, remainder is %d\n", csum);
+               DRM_NOTE("DisplayID checksum invalid, remainder is %d\n", csum);
                return -EINVAL;
        }
        return 0;
index 622f788bff4603f7c97def996dc2838ca5e3dee5..1c0495acf341964f7684f9e2bf5336473e7f525a 100644 (file)
@@ -256,15 +256,14 @@ out:
        return edid;
 }
 
-int drm_load_edid_firmware(struct drm_connector *connector)
+struct edid *drm_load_edid_firmware(struct drm_connector *connector)
 {
        const char *connector_name = connector->name;
        char *edidname, *last, *colon, *fwstr, *edidstr, *fallback = NULL;
-       int ret;
        struct edid *edid;
 
        if (edid_firmware[0] == '\0')
-               return 0;
+               return ERR_PTR(-ENOENT);
 
        /*
         * If there are multiple edid files specified and separated
@@ -293,7 +292,7 @@ int drm_load_edid_firmware(struct drm_connector *connector)
        if (!edidname) {
                if (!fallback) {
                        kfree(fwstr);
-                       return 0;
+                       return ERR_PTR(-ENOENT);
                }
                edidname = fallback;
        }
@@ -305,13 +304,5 @@ int drm_load_edid_firmware(struct drm_connector *connector)
        edid = edid_load(connector, edidname, connector_name);
        kfree(fwstr);
 
-       if (IS_ERR_OR_NULL(edid))
-               return 0;
-
-       drm_mode_connector_update_edid_property(connector, edid);
-       ret = drm_add_edid_modes(connector, edid);
-       drm_edid_to_eld(connector, edid);
-       kfree(edid);
-
-       return ret;
+       return edid;
 }
index 129450713bb783a062638988d16a22b63c7fc7f1..0708779840d29ee2bdc9cfd1ec81fac58a9db0e7 100644 (file)
@@ -110,7 +110,7 @@ int drm_encoder_init(struct drm_device *dev,
 {
        int ret;
 
-       ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
+       ret = drm_mode_object_add(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
        if (ret)
                return ret;
 
@@ -188,7 +188,7 @@ static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
 
        /* For atomic drivers only state objects are synchronously updated and
         * protected by modeset locks, so check those first. */
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
                if (!connector->state)
                        continue;
@@ -198,10 +198,10 @@ static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
                if (connector->state->best_encoder != encoder)
                        continue;
 
-               drm_connector_list_iter_put(&conn_iter);
+               drm_connector_list_iter_end(&conn_iter);
                return connector->state->crtc;
        }
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 
        /* Don't return stale data (e.g. pending async disable). */
        if (uses_atomic)
index 596fabf18c3e6243133eb5f23a309d387c0bef80..74cd393a640778b69262b3a7f81443bc389e9edb 100644 (file)
@@ -102,7 +102,7 @@ void drm_fb_cma_destroy(struct drm_framebuffer *fb)
 
        for (i = 0; i < 4; i++) {
                if (fb_cma->obj[i])
-                       drm_gem_object_unreference_unlocked(&fb_cma->obj[i]->base);
+                       drm_gem_object_put_unlocked(&fb_cma->obj[i]->base);
        }
 
        drm_framebuffer_cleanup(fb);
@@ -190,7 +190,7 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev,
                if (!obj) {
                        dev_err(dev->dev, "Failed to lookup GEM object\n");
                        ret = -ENXIO;
-                       goto err_gem_object_unreference;
+                       goto err_gem_object_put;
                }
 
                min_size = (height - 1) * mode_cmd->pitches[i]
@@ -198,9 +198,9 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev,
                         + mode_cmd->offsets[i];
 
                if (obj->size < min_size) {
-                       drm_gem_object_unreference_unlocked(obj);
+                       drm_gem_object_put_unlocked(obj);
                        ret = -EINVAL;
-                       goto err_gem_object_unreference;
+                       goto err_gem_object_put;
                }
                objs[i] = to_drm_gem_cma_obj(obj);
        }
@@ -208,14 +208,14 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev,
        fb_cma = drm_fb_cma_alloc(dev, mode_cmd, objs, i, funcs);
        if (IS_ERR(fb_cma)) {
                ret = PTR_ERR(fb_cma);
-               goto err_gem_object_unreference;
+               goto err_gem_object_put;
        }
 
        return &fb_cma->fb;
 
-err_gem_object_unreference:
+err_gem_object_put:
        for (i--; i >= 0; i--)
-               drm_gem_object_unreference_unlocked(&objs[i]->base);
+               drm_gem_object_put_unlocked(&objs[i]->base);
        return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(drm_fb_cma_create_with_funcs);
@@ -475,9 +475,9 @@ drm_fbdev_cma_create(struct drm_fb_helper *helper,
 err_cma_destroy:
        drm_framebuffer_remove(&fbdev_cma->fb->fb);
 err_fb_info_destroy:
-       drm_fb_helper_release_fbi(helper);
+       drm_fb_helper_fini(helper);
 err_gem_free_object:
-       drm_gem_object_unreference_unlocked(&obj->base);
+       drm_gem_object_put_unlocked(&obj->base);
        return ret;
 }
 
@@ -547,7 +547,6 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_init_with_funcs);
  * drm_fbdev_cma_init() - Allocate and initializes a drm_fbdev_cma struct
  * @dev: DRM device
  * @preferred_bpp: Preferred bits per pixel for the device
- * @num_crtc: Number of CRTCs
  * @max_conn_count: Maximum number of connectors
  *
  * Returns a newly allocated drm_fbdev_cma struct or a ERR_PTR.
@@ -570,7 +569,6 @@ void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma)
        drm_fb_helper_unregister_fbi(&fbdev_cma->fb_helper);
        if (fbdev_cma->fb_helper.fbdev)
                drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev);
-       drm_fb_helper_release_fbi(&fbdev_cma->fb_helper);
 
        if (fbdev_cma->fb)
                drm_framebuffer_remove(&fbdev_cma->fb->fb);
index f6d4d9700734e6d48792e90d47c7bfe4081116a1..45fde2ffef2a24634a6f2824135bf288fd4dc1c5 100644 (file)
@@ -48,6 +48,12 @@ module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600);
 MODULE_PARM_DESC(fbdev_emulation,
                 "Enable legacy fbdev emulation [default=true]");
 
+static int drm_fbdev_overalloc = CONFIG_DRM_FBDEV_OVERALLOC;
+module_param(drm_fbdev_overalloc, int, 0444);
+MODULE_PARM_DESC(drm_fbdev_overalloc,
+                "Overallocation of the fbdev buffer (%) [default="
+                __MODULE_STRING(CONFIG_DRM_FBDEV_OVERALLOC) "]");
+
 static LIST_HEAD(kernel_fb_helper_list);
 static DEFINE_MUTEX(kernel_fb_helper_lock);
 
@@ -63,7 +69,8 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
  * drm_fb_helper_init(), drm_fb_helper_single_add_all_connectors() and
  * drm_fb_helper_initial_config(). Drivers with fancier requirements than the
  * default behaviour can override the third step with their own code.
- * Teardown is done with drm_fb_helper_fini().
+ * Teardown is done with drm_fb_helper_fini() after the fbdev device is
+ * unregisters using drm_fb_helper_unregister_fbi().
  *
  * At runtime drivers should restore the fbdev console by calling
  * drm_fb_helper_restore_fbdev_mode_unlocked() from their &drm_driver.lastclose
@@ -127,7 +134,7 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
                return 0;
 
        mutex_lock(&dev->mode_config.mutex);
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
                ret = drm_fb_helper_add_one_connector(fb_helper, connector);
 
@@ -141,14 +148,14 @@ fail:
                struct drm_fb_helper_connector *fb_helper_connector =
                        fb_helper->connector_info[i];
 
-               drm_connector_unreference(fb_helper_connector->connector);
+               drm_connector_put(fb_helper_connector->connector);
 
                kfree(fb_helper_connector);
                fb_helper->connector_info[i] = NULL;
        }
        fb_helper->connector_count = 0;
 out:
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
        mutex_unlock(&dev->mode_config.mutex);
 
        return ret;
@@ -178,7 +185,7 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_
        if (!fb_helper_connector)
                return -ENOMEM;
 
-       drm_connector_reference(connector);
+       drm_connector_get(connector);
        fb_helper_connector->connector = connector;
        fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
        return 0;
@@ -204,7 +211,7 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
        if (i == fb_helper->connector_count)
                return -EINVAL;
        fb_helper_connector = fb_helper->connector_info[i];
-       drm_connector_unreference(fb_helper_connector->connector);
+       drm_connector_put(fb_helper_connector->connector);
 
        for (j = i + 1; j < fb_helper->connector_count; j++) {
                fb_helper->connector_info[j - 1] = fb_helper->connector_info[j];
@@ -626,7 +633,7 @@ static void drm_fb_helper_modeset_release(struct drm_fb_helper *helper,
        int i;
 
        for (i = 0; i < modeset->num_connectors; i++) {
-               drm_connector_unreference(modeset->connectors[i]);
+               drm_connector_put(modeset->connectors[i]);
                modeset->connectors[i] = NULL;
        }
        modeset->num_connectors = 0;
@@ -643,7 +650,7 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
        int i;
 
        for (i = 0; i < helper->connector_count; i++) {
-               drm_connector_unreference(helper->connector_info[i]->connector);
+               drm_connector_put(helper->connector_info[i]->connector);
                kfree(helper->connector_info[i]);
        }
        kfree(helper->connector_info);
@@ -709,7 +716,7 @@ void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
 EXPORT_SYMBOL(drm_fb_helper_prepare);
 
 /**
- * drm_fb_helper_init - initialize a drm_fb_helper structure
+ * drm_fb_helper_init - initialize a &struct drm_fb_helper
  * @dev: drm device
  * @fb_helper: driver-allocated fbdev helper structure to initialize
  * @max_conn_count: max connector count
@@ -780,7 +787,9 @@ EXPORT_SYMBOL(drm_fb_helper_init);
  * @fb_helper: driver-allocated fbdev helper
  *
  * A helper to alloc fb_info and the members cmap and apertures. Called
- * by the driver within the fb_probe fb_helper callback function.
+ * by the driver within the fb_probe fb_helper callback function. Drivers do not
+ * need to release the allocated fb_info structure themselves, this is
+ * automatically done when calling drm_fb_helper_fini().
  *
  * RETURNS:
  * fb_info pointer if things went okay, pointer containing error code
@@ -823,7 +832,8 @@ EXPORT_SYMBOL(drm_fb_helper_alloc_fbi);
  * @fb_helper: driver-allocated fbdev helper
  *
  * A wrapper around unregister_framebuffer, to release the fb_info
- * framebuffer device
+ * framebuffer device. This must be called before releasing all resources for
+ * @fb_helper by calling drm_fb_helper_fini().
  */
 void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
 {
@@ -833,32 +843,26 @@ void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
 EXPORT_SYMBOL(drm_fb_helper_unregister_fbi);
 
 /**
- * drm_fb_helper_release_fbi - dealloc fb_info and its members
+ * drm_fb_helper_fini - finialize a &struct drm_fb_helper
  * @fb_helper: driver-allocated fbdev helper
  *
- * A helper to free memory taken by fb_info and the members cmap and
- * apertures
+ * This cleans up all remaining resources associated with @fb_helper. Must be
+ * called after drm_fb_helper_unlink_fbi() was called.
  */
-void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper)
+void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
 {
-       if (fb_helper) {
-               struct fb_info *info = fb_helper->fbdev;
+       struct fb_info *info;
 
-               if (info) {
-                       if (info->cmap.len)
-                               fb_dealloc_cmap(&info->cmap);
-                       framebuffer_release(info);
-               }
+       if (!drm_fbdev_emulation || !fb_helper)
+               return;
 
-               fb_helper->fbdev = NULL;
+       info = fb_helper->fbdev;
+       if (info) {
+               if (info->cmap.len)
+                       fb_dealloc_cmap(&info->cmap);
+               framebuffer_release(info);
        }
-}
-EXPORT_SYMBOL(drm_fb_helper_release_fbi);
-
-void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
-{
-       if (!drm_fbdev_emulation)
-               return;
+       fb_helper->fbdev = NULL;
 
        cancel_work_sync(&fb_helper->resume_work);
        cancel_work_sync(&fb_helper->dirty_work);
@@ -1240,6 +1244,74 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
 }
 EXPORT_SYMBOL(drm_fb_helper_setcmap);
 
+/**
+ * drm_fb_helper_ioctl - legacy ioctl implementation
+ * @info: fbdev registered by the helper
+ * @cmd: ioctl command
+ * @arg: ioctl argument
+ *
+ * A helper to implement the standard fbdev ioctl. Only
+ * FBIO_WAITFORVSYNC is implemented for now.
+ */
+int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
+                       unsigned long arg)
+{
+       struct drm_fb_helper *fb_helper = info->par;
+       struct drm_device *dev = fb_helper->dev;
+       struct drm_mode_set *mode_set;
+       struct drm_crtc *crtc;
+       int ret = 0;
+
+       mutex_lock(&dev->mode_config.mutex);
+       if (!drm_fb_helper_is_bound(fb_helper)) {
+               ret = -EBUSY;
+               goto unlock;
+       }
+
+       switch (cmd) {
+       case FBIO_WAITFORVSYNC:
+               /*
+                * Only consider the first CRTC.
+                *
+                * This ioctl is supposed to take the CRTC number as
+                * an argument, but in fbdev times, what that number
+                * was supposed to be was quite unclear, different
+                * drivers were passing that argument differently
+                * (some by reference, some by value), and most of the
+                * userspace applications were just hardcoding 0 as an
+                * argument.
+                *
+                * The first CRTC should be the integrated panel on
+                * most drivers, so this is the best choice we can
+                * make. If we're not smart enough here, one should
+                * just consider switch the userspace to KMS.
+                */
+               mode_set = &fb_helper->crtc_info[0].mode_set;
+               crtc = mode_set->crtc;
+
+               /*
+                * Only wait for a vblank event if the CRTC is
+                * enabled, otherwise just don't do anythintg,
+                * not even report an error.
+                */
+               ret = drm_crtc_vblank_get(crtc);
+               if (!ret) {
+                       drm_crtc_wait_one_vblank(crtc);
+                       drm_crtc_vblank_put(crtc);
+               }
+
+               ret = 0;
+               goto unlock;
+       default:
+               ret = -ENOTTY;
+       }
+
+unlock:
+       mutex_unlock(&dev->mode_config.mutex);
+       return ret;
+}
+EXPORT_SYMBOL(drm_fb_helper_ioctl);
+
 /**
  * drm_fb_helper_check_var - implementation for &fb_ops.fb_check_var
  * @var: screeninfo to check
@@ -1580,6 +1652,10 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
                sizes.fb_height = sizes.surface_height = 768;
        }
 
+       /* Handle our overallocation */
+       sizes.surface_height *= drm_fbdev_overalloc;
+       sizes.surface_height /= 100;
+
        /* push down into drivers */
        ret = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes);
        if (ret < 0)
@@ -2184,7 +2260,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
                        fb_crtc->y = offset->y;
                        modeset->mode = drm_mode_duplicate(dev,
                                                           fb_crtc->desired_mode);
-                       drm_connector_reference(connector);
+                       drm_connector_get(connector);
                        modeset->connectors[modeset->num_connectors++] = connector;
                        modeset->fb = fb_helper->fb;
                        modeset->x = offset->x;
index 28a0108a1ab85f9a4fbd87c39bff668027597585..e4909aef75d73cb7e430a14782169ea932c438b2 100644 (file)
  * metadata fields.
  *
  * The lifetime of a drm framebuffer is controlled with a reference count,
- * drivers can grab additional references with drm_framebuffer_reference() and
- * drop them again with drm_framebuffer_unreference(). For driver-private
- * framebuffers for which the last reference is never dropped (e.g. for the
- * fbdev framebuffer when the struct &struct drm_framebuffer is embedded into
- * the fbdev helper struct) drivers can manually clean up a framebuffer at
- * module unload time with drm_framebuffer_unregister_private(). But doing this
- * is not recommended, and it's better to have a normal free-standing &struct
+ * drivers can grab additional references with drm_framebuffer_get() and drop
+ * them again with drm_framebuffer_put(). For driver-private framebuffers for
+ * which the last reference is never dropped (e.g. for the fbdev framebuffer
+ * when the struct &struct drm_framebuffer is embedded into the fbdev helper
+ * struct) drivers can manually clean up a framebuffer at module unload time
+ * with drm_framebuffer_unregister_private(). But doing this is not
+ * recommended, and it's better to have a normal free-standing &struct
  * drm_framebuffer.
  */
 
@@ -374,7 +374,7 @@ int drm_mode_rmfb(struct drm_device *dev,
        mutex_unlock(&file_priv->fbs_lock);
 
        /* drop the reference we picked up in framebuffer lookup */
-       drm_framebuffer_unreference(fb);
+       drm_framebuffer_put(fb);
 
        /*
         * we now own the reference that was stored in the fbs list
@@ -394,12 +394,12 @@ int drm_mode_rmfb(struct drm_device *dev,
                flush_work(&arg.work);
                destroy_work_on_stack(&arg.work);
        } else
-               drm_framebuffer_unreference(fb);
+               drm_framebuffer_put(fb);
 
        return 0;
 
 fail_unref:
-       drm_framebuffer_unreference(fb);
+       drm_framebuffer_put(fb);
        return -ENOENT;
 }
 
@@ -453,7 +453,7 @@ int drm_mode_getfb(struct drm_device *dev,
                ret = -ENODEV;
        }
 
-       drm_framebuffer_unreference(fb);
+       drm_framebuffer_put(fb);
 
        return ret;
 }
@@ -540,7 +540,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
 out_err2:
        kfree(clips);
 out_err1:
-       drm_framebuffer_unreference(fb);
+       drm_framebuffer_put(fb);
 
        return ret;
 }
@@ -580,7 +580,7 @@ void drm_fb_release(struct drm_file *priv)
                        list_del_init(&fb->filp_head);
 
                        /* This drops the fpriv->fbs reference. */
-                       drm_framebuffer_unreference(fb);
+                       drm_framebuffer_put(fb);
                }
        }
 
@@ -638,8 +638,8 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
 
        fb->funcs = funcs;
 
-       ret = drm_mode_object_get_reg(dev, &fb->base, DRM_MODE_OBJECT_FB,
-                                     false, drm_framebuffer_free);
+       ret = __drm_mode_object_add(dev, &fb->base, DRM_MODE_OBJECT_FB,
+                                   false, drm_framebuffer_free);
        if (ret)
                goto out;
 
@@ -661,7 +661,7 @@ EXPORT_SYMBOL(drm_framebuffer_init);
  *
  * If successful, this grabs an additional reference to the framebuffer -
  * callers need to make sure to eventually unreference the returned framebuffer
- * again, using @drm_framebuffer_unreference.
+ * again, using drm_framebuffer_put().
  */
 struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
                                               uint32_t id)
@@ -687,8 +687,8 @@ EXPORT_SYMBOL(drm_framebuffer_lookup);
  *
  * NOTE: This function is deprecated. For driver-private framebuffers it is not
  * recommended to embed a framebuffer struct info fbdev struct, instead, a
- * framebuffer pointer is preferred and drm_framebuffer_unreference() should be
- * called when the framebuffer is to be cleaned up.
+ * framebuffer pointer is preferred and drm_framebuffer_put() should be called
+ * when the framebuffer is to be cleaned up.
  */
 void drm_framebuffer_unregister_private(struct drm_framebuffer *fb)
 {
@@ -773,6 +773,12 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
         * in this manner.
         */
        if (drm_framebuffer_read_refcount(fb) > 1) {
+               if (drm_drv_uses_atomic_modeset(dev)) {
+                       int ret = drm_atomic_remove_fb(fb);
+                       WARN(ret, "atomic remove_fb failed with %i\n", ret);
+                       goto out;
+               }
+
                drm_modeset_lock_all(dev);
                /* remove from any CRTC */
                drm_for_each_crtc(crtc, dev) {
@@ -790,7 +796,8 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
                drm_modeset_unlock_all(dev);
        }
 
-       drm_framebuffer_unreference(fb);
+out:
+       drm_framebuffer_put(fb);
 }
 EXPORT_SYMBOL(drm_framebuffer_remove);
 
index bc93de3086730fa056842f211583d646c91ecdfa..b1e28c9446370928fc82e9c17e8c9531937eedf9 100644 (file)
@@ -218,7 +218,7 @@ static void drm_gem_object_exported_dma_buf_free(struct drm_gem_object *obj)
 }
 
 static void
-drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj)
+drm_gem_object_handle_put_unlocked(struct drm_gem_object *obj)
 {
        struct drm_device *dev = obj->dev;
        bool final = false;
@@ -241,7 +241,7 @@ drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj)
        mutex_unlock(&dev->object_name_lock);
 
        if (final)
-               drm_gem_object_unreference_unlocked(obj);
+               drm_gem_object_put_unlocked(obj);
 }
 
 /*
@@ -262,7 +262,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
        if (dev->driver->gem_close_object)
                dev->driver->gem_close_object(obj, file_priv);
 
-       drm_gem_object_handle_unreference_unlocked(obj);
+       drm_gem_object_handle_put_unlocked(obj);
 
        return 0;
 }
@@ -352,7 +352,7 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
 
        WARN_ON(!mutex_is_locked(&dev->object_name_lock));
        if (obj->handle_count++ == 0)
-               drm_gem_object_reference(obj);
+               drm_gem_object_get(obj);
 
        /*
         * Get the user-visible handle using idr.  Preload and perform
@@ -392,7 +392,7 @@ err_remove:
        idr_remove(&file_priv->object_idr, handle);
        spin_unlock(&file_priv->table_lock);
 err_unref:
-       drm_gem_object_handle_unreference_unlocked(obj);
+       drm_gem_object_handle_put_unlocked(obj);
        return ret;
 }
 
@@ -606,7 +606,7 @@ drm_gem_object_lookup(struct drm_file *filp, u32 handle)
        /* Check if we currently have a reference on the object */
        obj = idr_find(&filp->object_idr, handle);
        if (obj)
-               drm_gem_object_reference(obj);
+               drm_gem_object_get(obj);
 
        spin_unlock(&filp->table_lock);
 
@@ -683,7 +683,7 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
 
 err:
        mutex_unlock(&dev->object_name_lock);
-       drm_gem_object_unreference_unlocked(obj);
+       drm_gem_object_put_unlocked(obj);
        return ret;
 }
 
@@ -713,7 +713,7 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data,
        mutex_lock(&dev->object_name_lock);
        obj = idr_find(&dev->object_name_idr, (int) args->name);
        if (obj) {
-               drm_gem_object_reference(obj);
+               drm_gem_object_get(obj);
        } else {
                mutex_unlock(&dev->object_name_lock);
                return -ENOENT;
@@ -721,7 +721,7 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data,
 
        /* drm_gem_handle_create_tail unlocks dev->object_name_lock. */
        ret = drm_gem_handle_create_tail(file_priv, obj, &handle);
-       drm_gem_object_unreference_unlocked(obj);
+       drm_gem_object_put_unlocked(obj);
        if (ret)
                return ret;
 
@@ -809,16 +809,16 @@ drm_gem_object_free(struct kref *kref)
 EXPORT_SYMBOL(drm_gem_object_free);
 
 /**
- * drm_gem_object_unreference_unlocked - release a GEM BO reference
+ * drm_gem_object_put_unlocked - drop a GEM buffer object reference
  * @obj: GEM buffer object
  *
  * This releases a reference to @obj. Callers must not hold the
  * &drm_device.struct_mutex lock when calling this function.
  *
- * See also __drm_gem_object_unreference().
+ * See also __drm_gem_object_put().
  */
 void
-drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
+drm_gem_object_put_unlocked(struct drm_gem_object *obj)
 {
        struct drm_device *dev;
 
@@ -834,10 +834,10 @@ drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
                                &dev->struct_mutex))
                mutex_unlock(&dev->struct_mutex);
 }
-EXPORT_SYMBOL(drm_gem_object_unreference_unlocked);
+EXPORT_SYMBOL(drm_gem_object_put_unlocked);
 
 /**
- * drm_gem_object_unreference - release a GEM BO reference
+ * drm_gem_object_put - release a GEM buffer object reference
  * @obj: GEM buffer object
  *
  * This releases a reference to @obj. Callers must hold the
@@ -845,10 +845,10 @@ EXPORT_SYMBOL(drm_gem_object_unreference_unlocked);
  * driver doesn't use &drm_device.struct_mutex for anything.
  *
  * For drivers not encumbered with legacy locking use
- * drm_gem_object_unreference_unlocked() instead.
+ * drm_gem_object_put_unlocked() instead.
  */
 void
-drm_gem_object_unreference(struct drm_gem_object *obj)
+drm_gem_object_put(struct drm_gem_object *obj)
 {
        if (obj) {
                WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
@@ -856,7 +856,7 @@ drm_gem_object_unreference(struct drm_gem_object *obj)
                kref_put(&obj->refcount, drm_gem_object_free);
        }
 }
-EXPORT_SYMBOL(drm_gem_object_unreference);
+EXPORT_SYMBOL(drm_gem_object_put);
 
 /**
  * drm_gem_vm_open - vma->ops->open implementation for GEM
@@ -869,7 +869,7 @@ void drm_gem_vm_open(struct vm_area_struct *vma)
 {
        struct drm_gem_object *obj = vma->vm_private_data;
 
-       drm_gem_object_reference(obj);
+       drm_gem_object_get(obj);
 }
 EXPORT_SYMBOL(drm_gem_vm_open);
 
@@ -884,7 +884,7 @@ void drm_gem_vm_close(struct vm_area_struct *vma)
 {
        struct drm_gem_object *obj = vma->vm_private_data;
 
-       drm_gem_object_unreference_unlocked(obj);
+       drm_gem_object_put_unlocked(obj);
 }
 EXPORT_SYMBOL(drm_gem_vm_close);
 
@@ -935,7 +935,7 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
         * (which should happen whether the vma was created by this call, or
         * by a vm_open due to mremap or partial unmap or whatever).
         */
-       drm_gem_object_reference(obj);
+       drm_gem_object_get(obj);
 
        return 0;
 }
@@ -992,14 +992,14 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
                return -EINVAL;
 
        if (!drm_vma_node_is_allowed(node, priv)) {
-               drm_gem_object_unreference_unlocked(obj);
+               drm_gem_object_put_unlocked(obj);
                return -EACCES;
        }
 
        ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node) << PAGE_SHIFT,
                               vma);
 
-       drm_gem_object_unreference_unlocked(obj);
+       drm_gem_object_put_unlocked(obj);
 
        return ret;
 }
index f7ba32bfe39b3e3435f9778b91bd5b6533d26036..bb968e76779b423a8c329cca4b89a8d93c8258e0 100644 (file)
@@ -121,7 +121,7 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
        return cma_obj;
 
 error:
-       drm_gem_object_unreference_unlocked(&cma_obj->base);
+       drm_gem_object_put_unlocked(&cma_obj->base);
        return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(drm_gem_cma_create);
@@ -163,7 +163,7 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv,
         */
        ret = drm_gem_handle_create(file_priv, gem_obj, handle);
        /* drop reference from allocate - handle holds it now. */
-       drm_gem_object_unreference_unlocked(gem_obj);
+       drm_gem_object_put_unlocked(gem_obj);
        if (ret)
                return ERR_PTR(ret);
 
@@ -293,7 +293,7 @@ int drm_gem_cma_dumb_map_offset(struct drm_file *file_priv,
 
        *offset = drm_vma_node_offset_addr(&gem_obj->vma_node);
 
-       drm_gem_object_unreference_unlocked(gem_obj);
+       drm_gem_object_put_unlocked(gem_obj);
 
        return 0;
 }
@@ -416,13 +416,13 @@ unsigned long drm_gem_cma_get_unmapped_area(struct file *filp,
                return -EINVAL;
 
        if (!drm_vma_node_is_allowed(node, priv)) {
-               drm_gem_object_unreference_unlocked(obj);
+               drm_gem_object_put_unlocked(obj);
                return -EACCES;
        }
 
        cma_obj = to_drm_gem_cma_obj(obj);
 
-       drm_gem_object_unreference_unlocked(obj);
+       drm_gem_object_put_unlocked(obj);
 
        return cma_obj->vaddr ? (unsigned long)cma_obj->vaddr : -EINVAL;
 }
index 867ab8c1582bf33f154c6519cd33f5c2f72a9be7..b134482f4022aa01c780591f8ccc4d5cab68200d 100644 (file)
@@ -257,8 +257,7 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd,
 
        m32.handle = (unsigned long)handle;
        if (m32.handle != (unsigned long)handle)
-               printk_ratelimited(KERN_ERR "compat_drm_addmap truncated handle"
-                                  " %p for type %d offset %x\n",
+               pr_err_ratelimited("compat_drm_addmap truncated handle %p for type %d offset %x\n",
                                   handle, m32.type, m32.offset);
 
        if (copy_to_user(argp, &m32, sizeof(m32)))
index e06cf11ebb4a92154af07d3266b9e2ed6eb0eee5..1906723af389360229da386aa8c2f64011e411db 100644 (file)
@@ -89,6 +89,31 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe,
        write_sequnlock(&vblank->seqlock);
 }
 
+/*
+ * "No hw counter" fallback implementation of .get_vblank_counter() hook,
+ * if there is no useable hardware frame counter available.
+ */
+static u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe)
+{
+       WARN_ON_ONCE(dev->max_vblank_count != 0);
+       return 0;
+}
+
+static u32 __get_vblank_counter(struct drm_device *dev, unsigned int pipe)
+{
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+               struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
+
+               if (crtc->funcs->get_vblank_counter)
+                       return crtc->funcs->get_vblank_counter(crtc);
+       }
+
+       if (dev->driver->get_vblank_counter)
+               return dev->driver->get_vblank_counter(dev, pipe);
+
+       return drm_vblank_no_hw_counter(dev, pipe);
+}
+
 /*
  * Reset the stored timestamp for the current vblank count to correspond
  * to the last vblank occurred.
@@ -112,9 +137,9 @@ static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe
         * when drm_vblank_enable() applies the diff
         */
        do {
-               cur_vblank = dev->driver->get_vblank_counter(dev, pipe);
+               cur_vblank = __get_vblank_counter(dev, pipe);
                rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, 0);
-       } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe) && --count > 0);
+       } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
 
        /*
         * Only reinitialize corresponding vblank timestamp if high-precision query
@@ -168,9 +193,9 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
         * corresponding vblank timestamp.
         */
        do {
-               cur_vblank = dev->driver->get_vblank_counter(dev, pipe);
+               cur_vblank = __get_vblank_counter(dev, pipe);
                rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, flags);
-       } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe) && --count > 0);
+       } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
 
        if (dev->max_vblank_count != 0) {
                /* trust the hw counter when it's around */
@@ -275,6 +300,20 @@ u32 drm_accurate_vblank_count(struct drm_crtc *crtc)
 }
 EXPORT_SYMBOL(drm_accurate_vblank_count);
 
+static void __disable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+               struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
+
+               if (crtc->funcs->disable_vblank) {
+                       crtc->funcs->disable_vblank(crtc);
+                       return;
+               }
+       }
+
+       dev->driver->disable_vblank(dev, pipe);
+}
+
 /*
  * Disable vblank irq's on crtc, make sure that last vblank count
  * of hardware and corresponding consistent software vblank counter
@@ -298,7 +337,7 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)
         * hardware potentially runtime suspended.
         */
        if (vblank->enabled) {
-               dev->driver->disable_vblank(dev, pipe);
+               __disable_vblank(dev, pipe);
                vblank->enabled = false;
        }
 
@@ -1027,6 +1066,18 @@ void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
 }
 EXPORT_SYMBOL(drm_crtc_send_vblank_event);
 
+static int __enable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+               struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
+
+               if (crtc->funcs->enable_vblank)
+                       return crtc->funcs->enable_vblank(crtc);
+       }
+
+       return dev->driver->enable_vblank(dev, pipe);
+}
+
 /**
  * drm_vblank_enable - enable the vblank interrupt on a CRTC
  * @dev: DRM device
@@ -1052,7 +1103,7 @@ static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe)
                 * timestamps. Filtercode in drm_handle_vblank() will
                 * prevent double-accounting of same vblank interval.
                 */
-               ret = dev->driver->enable_vblank(dev, pipe);
+               ret = __enable_vblank(dev, pipe);
                DRM_DEBUG("enabling vblank on crtc %u, ret: %d\n", pipe, ret);
                if (ret)
                        atomic_dec(&vblank->refcount);
@@ -1707,21 +1758,3 @@ bool drm_crtc_handle_vblank(struct drm_crtc *crtc)
        return drm_handle_vblank(crtc->dev, drm_crtc_index(crtc));
 }
 EXPORT_SYMBOL(drm_crtc_handle_vblank);
-
-/**
- * drm_vblank_no_hw_counter - "No hw counter" implementation of .get_vblank_counter()
- * @dev: DRM device
- * @pipe: CRTC for which to read the counter
- *
- * Drivers can plug this into the .get_vblank_counter() function if
- * there is no useable hardware frame counter available.
- *
- * Returns:
- * 0
- */
-u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe)
-{
-       WARN_ON_ONCE(dev->max_vblank_count != 0);
-       return 0;
-}
-EXPORT_SYMBOL(drm_vblank_no_hw_counter);
index 8bfb0b327267b461a5bb41cc5befe385f9637824..f794089d30ac21de22894774f13d4d2871213573 100644 (file)
@@ -170,7 +170,7 @@ struct drm_mm_node *
 __drm_mm_interval_first(const struct drm_mm *mm, u64 start, u64 last)
 {
        return drm_mm_interval_tree_iter_first((struct rb_root *)&mm->interval_tree,
-                                              start, last);
+                                              start, last) ?: (struct drm_mm_node *)&mm->head_node;
 }
 EXPORT_SYMBOL(__drm_mm_interval_first);
 
index 884cc4d26fb59e8568abac449252c248e253fdc1..d9862259a2a7919859fea4de629b1b34c7f1abfe 100644 (file)
@@ -139,19 +139,19 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
        }
        card_res->count_encoders = count;
 
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        count = 0;
        connector_id = u64_to_user_ptr(card_res->connector_id_ptr);
        drm_for_each_connector_iter(connector, &conn_iter) {
                if (count < card_res->count_connectors &&
                    put_user(connector->base.id, connector_id + count)) {
-                       drm_connector_list_iter_put(&conn_iter);
+                       drm_connector_list_iter_end(&conn_iter);
                        return -EFAULT;
                }
                count++;
        }
        card_res->count_connectors = count;
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 
        return ret;
 }
@@ -184,11 +184,11 @@ void drm_mode_config_reset(struct drm_device *dev)
                if (encoder->funcs->reset)
                        encoder->funcs->reset(encoder);
 
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter)
                if (connector->funcs->reset)
                        connector->funcs->reset(connector);
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 }
 EXPORT_SYMBOL(drm_mode_config_reset);
 
@@ -412,20 +412,20 @@ void drm_mode_config_cleanup(struct drm_device *dev)
                encoder->funcs->destroy(encoder);
        }
 
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
                /* drm_connector_list_iter holds an full reference to the
                 * current connector itself, which means it is inherently safe
                 * against unreferencing the current connector - but not against
                 * deleting it right away. */
-               drm_connector_unreference(connector);
+               drm_connector_put(connector);
        }
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
        if (WARN_ON(!list_empty(&dev->mode_config.connector_list))) {
-               drm_connector_list_iter_get(dev, &conn_iter);
+               drm_connector_list_iter_begin(dev, &conn_iter);
                drm_for_each_connector_iter(connector, &conn_iter)
                        DRM_ERROR("connector %s leaked!\n", connector->name);
-               drm_connector_list_iter_put(&conn_iter);
+               drm_connector_list_iter_end(&conn_iter);
        }
 
        list_for_each_entry_safe(property, pt, &dev->mode_config.property_list,
@@ -444,7 +444,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)
 
        list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
                                 head_global) {
-               drm_property_unreference_blob(blob);
+               drm_property_blob_put(blob);
        }
 
        /*
index 220a6c1f4ab95c26396a944481fc8f897d844f8d..da9a9adbcc9857ec37f9fa75e48bbc7a6ed1d283 100644 (file)
  * Internal function to assign a slot in the object idr and optionally
  * register the object into the idr.
  */
-int drm_mode_object_get_reg(struct drm_device *dev,
-                           struct drm_mode_object *obj,
-                           uint32_t obj_type,
-                           bool register_obj,
-                           void (*obj_free_cb)(struct kref *kref))
+int __drm_mode_object_add(struct drm_device *dev, struct drm_mode_object *obj,
+                         uint32_t obj_type, bool register_obj,
+                         void (*obj_free_cb)(struct kref *kref))
 {
        int ret;
 
@@ -59,23 +57,21 @@ int drm_mode_object_get_reg(struct drm_device *dev,
 }
 
 /**
- * drm_mode_object_get - allocate a new modeset identifier
+ * drm_mode_object_add - allocate a new modeset identifier
  * @dev: DRM device
  * @obj: object pointer, used to generate unique ID
  * @obj_type: object type
  *
  * Create a unique identifier based on @ptr in @dev's identifier space.  Used
- * for tracking modes, CRTCs and connectors. Note that despite the _get postfix
- * modeset identifiers are _not_ reference counted. Hence don't use this for
- * reference counted modeset objects like framebuffers.
+ * for tracking modes, CRTCs and connectors.
  *
  * Returns:
  * Zero on success, error code on failure.
  */
-int drm_mode_object_get(struct drm_device *dev,
+int drm_mode_object_add(struct drm_device *dev,
                        struct drm_mode_object *obj, uint32_t obj_type)
 {
-       return drm_mode_object_get_reg(dev, obj, obj_type, true, NULL);
+       return __drm_mode_object_add(dev, obj, obj_type, true, NULL);
 }
 
 void drm_mode_object_register(struct drm_device *dev,
@@ -137,7 +133,7 @@ struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
  *
  * This function is used to look up a modeset object. It will acquire a
  * reference for reference counted objects. This reference must be dropped again
- * by callind drm_mode_object_unreference().
+ * by callind drm_mode_object_put().
  */
 struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
                uint32_t id, uint32_t type)
@@ -150,38 +146,38 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
 EXPORT_SYMBOL(drm_mode_object_find);
 
 /**
- * drm_mode_object_unreference - decr the object refcnt
- * @obj: mode_object
+ * drm_mode_object_put - release a mode object reference
+ * @obj: DRM mode object
  *
  * This function decrements the object's refcount if it is a refcounted modeset
  * object. It is a no-op on any other object. This is used to drop references
- * acquired with drm_mode_object_reference().
+ * acquired with drm_mode_object_get().
  */
-void drm_mode_object_unreference(struct drm_mode_object *obj)
+void drm_mode_object_put(struct drm_mode_object *obj)
 {
        if (obj->free_cb) {
                DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount));
                kref_put(&obj->refcount, obj->free_cb);
        }
 }
-EXPORT_SYMBOL(drm_mode_object_unreference);
+EXPORT_SYMBOL(drm_mode_object_put);
 
 /**
- * drm_mode_object_reference - incr the object refcnt
- * @obj: mode_object
+ * drm_mode_object_get - acquire a mode object reference
+ * @obj: DRM mode object
  *
  * This function increments the object's refcount if it is a refcounted modeset
  * object. It is a no-op on any other object. References should be dropped again
- * by calling drm_mode_object_unreference().
+ * by calling drm_mode_object_put().
  */
-void drm_mode_object_reference(struct drm_mode_object *obj)
+void drm_mode_object_get(struct drm_mode_object *obj)
 {
        if (obj->free_cb) {
                DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, kref_read(&obj->refcount));
                kref_get(&obj->refcount);
        }
 }
-EXPORT_SYMBOL(drm_mode_object_reference);
+EXPORT_SYMBOL(drm_mode_object_get);
 
 /**
  * drm_object_attach_property - attach a property to a modeset object
@@ -367,7 +363,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
                        &arg->count_props);
 
 out_unref:
-       drm_mode_object_unreference(obj);
+       drm_mode_object_put(obj);
 out:
        drm_modeset_unlock_all(dev);
        return ret;
@@ -432,7 +428,7 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
        drm_property_change_valid_put(property, ref);
 
 out_unref:
-       drm_mode_object_unreference(arg_obj);
+       drm_mode_object_put(arg_obj);
 out:
        drm_modeset_unlock_all(dev);
        return ret;
index fd22c1c891bf867f934e7314ac46a1b3369ed2c3..f2493b9b82e6075e481833178b6279d728d8503d 100644 (file)
@@ -71,7 +71,7 @@ struct drm_display_mode *drm_mode_create(struct drm_device *dev)
        if (!nmode)
                return NULL;
 
-       if (drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE)) {
+       if (drm_mode_object_add(dev, &nmode->base, DRM_MODE_OBJECT_MODE)) {
                kfree(nmode);
                return NULL;
        }
index c464fc4a874d239907dfa9f6b54d27813e821ed3..a22e76837065a04f64e67654da3c6419e8066508 100644 (file)
@@ -88,7 +88,7 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
        struct drm_mode_config *config = &dev->mode_config;
        int ret;
 
-       ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
+       ret = drm_mode_object_add(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
        if (ret)
                return ret;
 
@@ -293,7 +293,7 @@ void drm_plane_force_disable(struct drm_plane *plane)
                return;
        }
        /* disconnect the plane from the fb and crtc: */
-       drm_framebuffer_unreference(plane->old_fb);
+       drm_framebuffer_put(plane->old_fb);
        plane->old_fb = NULL;
        plane->fb = NULL;
        plane->crtc = NULL;
@@ -520,9 +520,9 @@ static int __setplane_internal(struct drm_plane *plane,
 
 out:
        if (fb)
-               drm_framebuffer_unreference(fb);
+               drm_framebuffer_put(fb);
        if (plane->old_fb)
-               drm_framebuffer_unreference(plane->old_fb);
+               drm_framebuffer_put(plane->old_fb);
        plane->old_fb = NULL;
 
        return ret;
@@ -638,7 +638,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
        } else {
                fb = crtc->cursor->fb;
                if (fb)
-                       drm_framebuffer_reference(fb);
+                       drm_framebuffer_get(fb);
        }
 
        if (req->flags & DRM_MODE_CURSOR_MOVE) {
@@ -902,9 +902,9 @@ out:
        if (ret && crtc->funcs->page_flip_target)
                drm_crtc_vblank_put(crtc);
        if (fb)
-               drm_framebuffer_unreference(fb);
+               drm_framebuffer_put(fb);
        if (crtc->primary->old_fb)
-               drm_framebuffer_unreference(crtc->primary->old_fb);
+               drm_framebuffer_put(crtc->primary->old_fb);
        crtc->primary->old_fb = NULL;
        drm_modeset_unlock_crtc(crtc);
 
index 148688fb920a58745645cd0b57aa9d3c83aa36be..244cf2619294ce635279d79ce2b3aae06f84ed41 100644 (file)
@@ -85,7 +85,7 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc,
         */
        WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
 
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
                if (connector->encoder && connector->encoder->crtc == crtc) {
                        if (connector_list != NULL && count < num_connectors)
@@ -94,7 +94,7 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc,
                        count++;
                }
        }
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 
        return count;
 }
@@ -450,8 +450,7 @@ int drm_plane_helper_commit(struct drm_plane *plane,
                        goto out;
        }
 
-       if (plane_funcs->prepare_fb && plane_state->fb &&
-           plane_state->fb != old_fb) {
+       if (plane_funcs->prepare_fb && plane_state->fb != old_fb) {
                ret = plane_funcs->prepare_fb(plane,
                                              plane_state);
                if (ret)
index 25aa4558f1b5cb276d16f6d43430ed98fafcc566..866b294e7c6137d7ede59c55eb95ad9ec9849879 100644 (file)
@@ -318,7 +318,7 @@ struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
                return dma_buf;
 
        drm_dev_ref(dev);
-       drm_gem_object_reference(exp_info->priv);
+       drm_gem_object_get(exp_info->priv);
 
        return dma_buf;
 }
@@ -339,7 +339,7 @@ void drm_gem_dmabuf_release(struct dma_buf *dma_buf)
        struct drm_device *dev = obj->dev;
 
        /* drop the reference on the export fd holds */
-       drm_gem_object_unreference_unlocked(obj);
+       drm_gem_object_put_unlocked(obj);
 
        drm_dev_unref(dev);
 }
@@ -585,7 +585,7 @@ out_have_handle:
 fail_put_dmabuf:
        dma_buf_put(dmabuf);
 out:
-       drm_gem_object_unreference_unlocked(obj);
+       drm_gem_object_put_unlocked(obj);
 out_unlock:
        mutex_unlock(&file_priv->prime.lock);
 
@@ -616,7 +616,7 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
                         * Importing dmabuf exported from out own gem increases
                         * refcount on gem itself instead of f_count of dmabuf.
                         */
-                       drm_gem_object_reference(obj);
+                       drm_gem_object_get(obj);
                        return obj;
                }
        }
@@ -704,7 +704,7 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev,
 
        /* _handle_create_tail unconditionally unlocks dev->object_name_lock. */
        ret = drm_gem_handle_create_tail(file_priv, obj, handle);
-       drm_gem_object_unreference_unlocked(obj);
+       drm_gem_object_put_unlocked(obj);
        if (ret)
                goto out_put;
 
index 02a107d507067f70e4798a8df603780d26b11943..74c466aca62209e001d4430fd94b0ef8e7df257c 100644 (file)
@@ -36,7 +36,7 @@ EXPORT_SYMBOL(__drm_printfn_seq_file);
 
 void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf)
 {
-       dev_printk(KERN_INFO, p->arg, "[" DRM_NAME "] %pV", vaf);
+       dev_info(p->arg, "[" DRM_NAME "] %pV", vaf);
 }
 EXPORT_SYMBOL(__drm_printfn_info);
 
index dc4419ada12c3b1aa907280f5dc09dc35fdd8848..85005d57bde62f6276045880352dc923c72dd2ac 100644 (file)
@@ -140,13 +140,13 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
        if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
                return;
 
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
                if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
                                         DRM_CONNECTOR_POLL_DISCONNECT))
                        poll = true;
        }
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 
        if (dev->mode_config.delayed_event) {
                /*
@@ -311,7 +311,13 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
                count = drm_add_edid_modes(connector, edid);
                drm_edid_to_eld(connector, edid);
        } else {
-               count = drm_load_edid_firmware(connector);
+               struct edid *edid = drm_load_edid_firmware(connector);
+               if (!IS_ERR_OR_NULL(edid)) {
+                       drm_mode_connector_update_edid_property(connector, edid);
+                       count = drm_add_edid_modes(connector, edid);
+                       drm_edid_to_eld(connector, edid);
+                       kfree(edid);
+               }
                if (count == 0)
                        count = (*connector_funcs->get_modes)(connector);
        }
@@ -414,7 +420,7 @@ static void output_poll_execute(struct work_struct *work)
                goto out;
        }
 
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
                /* Ignore forced connectors. */
                if (connector->force)
@@ -468,7 +474,7 @@ static void output_poll_execute(struct work_struct *work)
                        changed = true;
                }
        }
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
 
        mutex_unlock(&dev->mode_config.mutex);
 
@@ -574,7 +580,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev)
                return false;
 
        mutex_lock(&dev->mode_config.mutex);
-       drm_connector_list_iter_get(dev, &conn_iter);
+       drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
                /* Only handle HPD capable connectors. */
                if (!(connector->polled & DRM_CONNECTOR_POLL_HPD))
@@ -591,7 +597,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev)
                if (old_status != connector->status)
                        changed = true;
        }
-       drm_connector_list_iter_put(&conn_iter);
+       drm_connector_list_iter_end(&conn_iter);
        mutex_unlock(&dev->mode_config.mutex);
 
        if (changed)
index 7fc070f3e49e3e1a87b435641661e4af38c83213..b17959c3e099ae1b3d24145eb01e51416b93e19f 100644 (file)
@@ -91,7 +91,7 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,
                        goto fail;
        }
 
-       ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
+       ret = drm_mode_object_add(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
        if (ret)
                goto fail;
 
@@ -570,8 +570,8 @@ drm_property_create_blob(struct drm_device *dev, size_t length,
        if (data)
                memcpy(blob->data, data, length);
 
-       ret = drm_mode_object_get_reg(dev, &blob->base, DRM_MODE_OBJECT_BLOB,
-                                     true, drm_property_free_blob);
+       ret = __drm_mode_object_add(dev, &blob->base, DRM_MODE_OBJECT_BLOB,
+                                   true, drm_property_free_blob);
        if (ret) {
                kfree(blob);
                return ERR_PTR(-EINVAL);
@@ -587,19 +587,19 @@ drm_property_create_blob(struct drm_device *dev, size_t length,
 EXPORT_SYMBOL(drm_property_create_blob);
 
 /**
- * drm_property_unreference_blob - Unreference a blob property
- * @blob: Pointer to blob property
+ * drm_property_blob_put - release a blob property reference
+ * @blob: DRM blob property
  *
- * Drop a reference on a blob property. May free the object.
+ * Releases a reference to a blob property. May free the object.
  */
-void drm_property_unreference_blob(struct drm_property_blob *blob)
+void drm_property_blob_put(struct drm_property_blob *blob)
 {
        if (!blob)
                return;
 
-       drm_mode_object_unreference(&blob->base);
+       drm_mode_object_put(&blob->base);
 }
-EXPORT_SYMBOL(drm_property_unreference_blob);
+EXPORT_SYMBOL(drm_property_blob_put);
 
 void drm_property_destroy_user_blobs(struct drm_device *dev,
                                     struct drm_file *file_priv)
@@ -612,23 +612,23 @@ void drm_property_destroy_user_blobs(struct drm_device *dev,
         */
        list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) {
                list_del_init(&blob->head_file);
-               drm_property_unreference_blob(blob);
+               drm_property_blob_put(blob);
        }
 }
 
 /**
- * drm_property_reference_blob - Take a reference on an existing property
- * @blob: Pointer to blob property
+ * drm_property_blob_get - acquire blob property reference
+ * @blob: DRM blob property
  *
- * Take a new reference on an existing blob property. Returns @blob, which
+ * Acquires a reference to an existing blob property. Returns @blob, which
  * allows this to be used as a shorthand in assignments.
  */
-struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob)
+struct drm_property_blob *drm_property_blob_get(struct drm_property_blob *blob)
 {
-       drm_mode_object_reference(&blob->base);
+       drm_mode_object_get(&blob->base);
        return blob;
 }
-EXPORT_SYMBOL(drm_property_reference_blob);
+EXPORT_SYMBOL(drm_property_blob_get);
 
 /**
  * drm_property_lookup_blob - look up a blob property and take a reference
@@ -637,7 +637,7 @@ EXPORT_SYMBOL(drm_property_reference_blob);
  *
  * If successful, this takes an additional reference to the blob property.
  * callers need to make sure to eventually unreference the returned property
- * again, using @drm_property_unreference_blob.
+ * again, using drm_property_blob_put().
  *
  * Return:
  * NULL on failure, pointer to the blob on success.
@@ -712,13 +712,13 @@ int drm_property_replace_global_blob(struct drm_device *dev,
                        goto err_created;
        }
 
-       drm_property_unreference_blob(old_blob);
+       drm_property_blob_put(old_blob);
        *replace = new_blob;
 
        return 0;
 
 err_created:
-       drm_property_unreference_blob(new_blob);
+       drm_property_blob_put(new_blob);
        return ret;
 }
 EXPORT_SYMBOL(drm_property_replace_global_blob);
@@ -747,7 +747,7 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,
        }
        out_resp->length = blob->length;
 unref:
-       drm_property_unreference_blob(blob);
+       drm_property_blob_put(blob);
 
        return ret;
 }
@@ -784,7 +784,7 @@ int drm_mode_createblob_ioctl(struct drm_device *dev,
        return 0;
 
 out_blob:
-       drm_property_unreference_blob(blob);
+       drm_property_blob_put(blob);
        return ret;
 }
 
@@ -823,14 +823,14 @@ int drm_mode_destroyblob_ioctl(struct drm_device *dev,
        mutex_unlock(&dev->mode_config.blob_lock);
 
        /* One reference from lookup, and one from the filp. */
-       drm_property_unreference_blob(blob);
-       drm_property_unreference_blob(blob);
+       drm_property_blob_put(blob);
+       drm_property_blob_put(blob);
 
        return 0;
 
 err:
        mutex_unlock(&dev->mode_config.blob_lock);
-       drm_property_unreference_blob(blob);
+       drm_property_blob_put(blob);
 
        return ret;
 }
@@ -906,7 +906,7 @@ void drm_property_change_valid_put(struct drm_property *property,
                return;
 
        if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
-               drm_mode_object_unreference(ref);
+               drm_mode_object_put(ref);
        } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
-               drm_property_unreference_blob(obj_to_blob(ref));
+               drm_property_blob_put(obj_to_blob(ref));
 }
index 5367b6664fe37d6ea1825eac48e620a7c6d902e7..fa32091af924326138f71b51017aee929e8b423b 100644 (file)
@@ -122,6 +122,24 @@ static void exynos_drm_crtc_destroy(struct drm_crtc *crtc)
        kfree(exynos_crtc);
 }
 
+static int exynos_drm_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+       struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+
+       if (exynos_crtc->ops->enable_vblank)
+               return exynos_crtc->ops->enable_vblank(exynos_crtc);
+
+       return 0;
+}
+
+static void exynos_drm_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+       struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+
+       if (exynos_crtc->ops->disable_vblank)
+               exynos_crtc->ops->disable_vblank(exynos_crtc);
+}
+
 static const struct drm_crtc_funcs exynos_crtc_funcs = {
        .set_config     = drm_atomic_helper_set_config,
        .page_flip      = drm_atomic_helper_page_flip,
@@ -129,6 +147,8 @@ static const struct drm_crtc_funcs exynos_crtc_funcs = {
        .reset = drm_atomic_helper_crtc_reset,
        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+       .enable_vblank = exynos_drm_crtc_enable_vblank,
+       .disable_vblank = exynos_drm_crtc_disable_vblank,
 };
 
 struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
@@ -168,26 +188,6 @@ err_crtc:
        return ERR_PTR(ret);
 }
 
-int exynos_drm_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-       struct exynos_drm_crtc *exynos_crtc = exynos_drm_crtc_from_pipe(dev,
-                                                                       pipe);
-
-       if (exynos_crtc->ops->enable_vblank)
-               return exynos_crtc->ops->enable_vblank(exynos_crtc);
-
-       return 0;
-}
-
-void exynos_drm_crtc_disable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-       struct exynos_drm_crtc *exynos_crtc = exynos_drm_crtc_from_pipe(dev,
-                                                                       pipe);
-
-       if (exynos_crtc->ops->disable_vblank)
-               exynos_crtc->ops->disable_vblank(exynos_crtc);
-}
-
 int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
                                       enum exynos_drm_output_type out_type)
 {
index 6a581a8af4650fcf5f07ea3fa84c6b1dd5e81ad4..4e986ba9232086a51b3af7b1be6df71c99d3d93b 100644 (file)
@@ -23,8 +23,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
                                        enum exynos_drm_output_type type,
                                        const struct exynos_drm_crtc_ops *ops,
                                        void *context);
-int exynos_drm_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe);
-void exynos_drm_crtc_disable_vblank(struct drm_device *dev, unsigned int pipe);
 void exynos_drm_crtc_wait_pending_update(struct exynos_drm_crtc *exynos_crtc);
 void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc,
                                   struct exynos_drm_plane *exynos_plane);
index 035d02ecffcdcffee4847f3e1823c2419b4883dd..b4522f67b3cb140685da9715e9a43287ef114022 100644 (file)
@@ -22,7 +22,6 @@
 #include <drm/exynos_drm.h>
 
 #include "exynos_drm_drv.h"
-#include "exynos_drm_crtc.h"
 #include "exynos_drm_fbdev.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_gem.h"
@@ -263,9 +262,6 @@ static struct drm_driver exynos_drm_driver = {
        .preclose               = exynos_drm_preclose,
        .lastclose              = exynos_drm_lastclose,
        .postclose              = exynos_drm_postclose,
-       .get_vblank_counter     = drm_vblank_no_hw_counter,
-       .enable_vblank          = exynos_drm_crtc_enable_vblank,
-       .disable_vblank         = exynos_drm_crtc_disable_vblank,
        .gem_free_object_unlocked = exynos_drm_gem_free_object,
        .gem_vm_ops             = &exynos_drm_gem_vm_ops,
        .dumb_create            = exynos_drm_gem_dumb_create,
index cf6e08cb35a7736f5ca9451540942345be028e84..cb317693059696b3c86bda9c93c2e5ebcefad921 100644 (file)
@@ -222,14 +222,6 @@ struct exynos_drm_private {
        wait_queue_head_t       wait;
 };
 
-static inline struct exynos_drm_crtc *
-exynos_drm_crtc_from_pipe(struct drm_device *dev, int pipe)
-{
-       struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
-
-       return to_exynos_crtc(crtc);
-}
-
 static inline struct device *to_dma_dev(struct drm_device *dev)
 {
        struct exynos_drm_private *priv = dev->dev_private;
index bcdb2720b68e70caa59faf9b53a2930833e930c1..40aa5056d4aee6d963b224faad6f13ff0976ece1 100644 (file)
@@ -99,7 +99,6 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
                                VM_MAP, pgprot_writecombine(PAGE_KERNEL));
        if (!exynos_gem->kvaddr) {
                DRM_ERROR("failed to map pages to kernel space.\n");
-               drm_fb_helper_release_fbi(helper);
                return -EIO;
        }
 
@@ -272,7 +271,6 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev,
        }
 
        drm_fb_helper_unregister_fbi(fb_helper);
-       drm_fb_helper_release_fbi(fb_helper);
 
        drm_fb_helper_fini(fb_helper);
 }
index 88ccc0469316b191d75f87de57ccad301dc42145..0814ed76445c90ed2a328a5b3cfe5939f6d891e8 100644 (file)
@@ -43,7 +43,6 @@
 
 #include <drm/exynos_drm.h>
 
-#include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
 
 #define HOTPLUG_DEBOUNCE_MS            1100
@@ -1703,6 +1702,8 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
        struct drm_device *drm_dev = data;
        struct hdmi_context *hdata = dev_get_drvdata(dev);
        struct drm_encoder *encoder = &hdata->encoder;
+       struct exynos_drm_crtc *exynos_crtc;
+       struct drm_crtc *crtc;
        int ret, pipe;
 
        hdata->drm_dev = drm_dev;
@@ -1714,7 +1715,9 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
 
        hdata->phy_clk.enable = hdmiphy_clk_enable;
 
-       exynos_drm_crtc_from_pipe(drm_dev, pipe)->pipe_clk = &hdata->phy_clk;
+       crtc = drm_crtc_from_index(drm_dev, pipe);
+       exynos_crtc = to_exynos_crtc(crtc);
+       exynos_crtc->pipe_clk = &hdata->phy_clk;
 
        encoder->possible_crtcs = 1 << pipe;
 
index deb57435cc89736e5531e411ef12bcbe8f4d35a1..cc4e944a1d3c668a595616ca208cc587bc794b1f 100644 (file)
@@ -137,6 +137,30 @@ static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = {
        .mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb,
 };
 
+static int fsl_dcu_drm_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
+       unsigned int value;
+
+       regmap_read(fsl_dev->regmap, DCU_INT_MASK, &value);
+       value &= ~DCU_INT_MASK_VBLANK;
+       regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);
+
+       return 0;
+}
+
+static void fsl_dcu_drm_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
+       unsigned int value;
+
+       regmap_read(fsl_dev->regmap, DCU_INT_MASK, &value);
+       value |= DCU_INT_MASK_VBLANK;
+       regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);
+}
+
 static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
@@ -144,6 +168,8 @@ static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
        .page_flip = drm_atomic_helper_page_flip,
        .reset = drm_atomic_helper_crtc_reset,
        .set_config = drm_atomic_helper_set_config,
+       .enable_vblank = fsl_dcu_drm_crtc_enable_vblank,
+       .disable_vblank = fsl_dcu_drm_crtc_disable_vblank,
 };
 
 int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
index 04173235f4482adb2a9de172fd420f9e85285654..b5391c124c64787a100ed5af51e21685f67122ab 100644 (file)
@@ -154,29 +154,6 @@ static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
        return IRQ_HANDLED;
 }
 
-static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-       struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
-       unsigned int value;
-
-       regmap_read(fsl_dev->regmap, DCU_INT_MASK, &value);
-       value &= ~DCU_INT_MASK_VBLANK;
-       regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);
-
-       return 0;
-}
-
-static void fsl_dcu_drm_disable_vblank(struct drm_device *dev,
-                                      unsigned int pipe)
-{
-       struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
-       unsigned int value;
-
-       regmap_read(fsl_dev->regmap, DCU_INT_MASK, &value);
-       value |= DCU_INT_MASK_VBLANK;
-       regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);
-}
-
 static void fsl_dcu_drm_lastclose(struct drm_device *dev)
 {
        struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
@@ -203,9 +180,6 @@ static struct drm_driver fsl_dcu_drm_driver = {
        .load                   = fsl_dcu_load,
        .unload                 = fsl_dcu_unload,
        .irq_handler            = fsl_dcu_drm_irq,
-       .get_vblank_counter     = drm_vblank_no_hw_counter,
-       .enable_vblank          = fsl_dcu_drm_enable_vblank,
-       .disable_vblank         = fsl_dcu_drm_disable_vblank,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_vm_ops             = &drm_gem_cma_vm_ops,
        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
index 5efdb7fbb7ee3ad01189b35d04550826e5fcbd36..e64960db32246d73902a946930835a0a90581811 100644 (file)
@@ -284,8 +284,7 @@ static bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder,
                            head) {
                if (tmp_encoder != encoder
                    && tmp_encoder->crtc == encoder->crtc) {
-                       printk(KERN_ERR "Can't enable LVDS and another "
-                              "encoder on the same pipe\n");
+                       pr_err("Can't enable LVDS and another encoder on the same pipe\n");
                        return false;
                }
        }
@@ -756,13 +755,13 @@ out:
 
 failed_find:
        mutex_unlock(&dev->mode_config.mutex);
-       printk(KERN_ERR "Failed find\n");
+       pr_err("Failed find\n");
        psb_intel_i2c_destroy(gma_encoder->ddc_bus);
 failed_ddc:
-       printk(KERN_ERR "Failed DDC\n");
+       pr_err("Failed DDC\n");
        psb_intel_i2c_destroy(gma_encoder->i2c_bus);
 failed_blc_i2c:
-       printk(KERN_ERR "Failed BLC\n");
+       pr_err("Failed BLC\n");
        drm_encoder_cleanup(encoder);
        drm_connector_cleanup(connector);
        kfree(lvds_priv);
index ffe6b4ffa1a8a75dabb1a6fcb0017d0ccb6c0f99..7da70b6c83f0163b30b64b4cde74662ff2db132c 100644 (file)
@@ -393,7 +393,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
        info = drm_fb_helper_alloc_fbi(&fbdev->psb_fb_helper);
        if (IS_ERR(info)) {
                ret = PTR_ERR(info);
-               goto err_free_range;
+               goto out;
        }
        info->par = fbdev;
 
@@ -401,7 +401,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 
        ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing);
        if (ret)
-               goto err_release;
+               goto out;
 
        fb = &psbfb->base;
        psbfb->fbdev = info;
@@ -446,9 +446,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
                                        psbfb->base.width, psbfb->base.height);
 
        return 0;
-err_release:
-       drm_fb_helper_release_fbi(&fbdev->psb_fb_helper);
-err_free_range:
+out:
        psb_gtt_free_range(dev, backing);
        return ret;
 }
@@ -537,7 +535,6 @@ static int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
        struct psb_framebuffer *psbfb = &fbdev->pfb;
 
        drm_fb_helper_unregister_fbi(&fbdev->psb_fb_helper);
-       drm_fb_helper_release_fbi(&fbdev->psb_fb_helper);
 
        drm_fb_helper_fini(&fbdev->psb_fb_helper);
        drm_framebuffer_unregister_private(&psbfb->base);
index f7038f12ac76321627894a488812d30b775a7945..e6943fef0611d1202c1f4cab9bda5efe28cdb2d2 100644 (file)
@@ -255,15 +255,15 @@ static void oaktrail_lvds_get_configuration_mode(struct drm_device *dev,
                                ((ti->vblank_hi << 8) | ti->vblank_lo);
                mode->clock = ti->pixel_clock * 10;
 #if 0
-               printk(KERN_INFO "hdisplay is %d\n", mode->hdisplay);
-               printk(KERN_INFO "vdisplay is %d\n", mode->vdisplay);
-               printk(KERN_INFO "HSS is %d\n", mode->hsync_start);
-               printk(KERN_INFO "HSE is %d\n", mode->hsync_end);
-               printk(KERN_INFO "htotal is %d\n", mode->htotal);
-               printk(KERN_INFO "VSS is %d\n", mode->vsync_start);
-               printk(KERN_INFO "VSE is %d\n", mode->vsync_end);
-               printk(KERN_INFO "vtotal is %d\n", mode->vtotal);
-               printk(KERN_INFO "clock is %d\n", mode->clock);
+               pr_info("hdisplay is %d\n", mode->hdisplay);
+               pr_info("vdisplay is %d\n", mode->vdisplay);
+               pr_info("HSS is %d\n", mode->hsync_start);
+               pr_info("HSE is %d\n", mode->hsync_end);
+               pr_info("htotal is %d\n", mode->htotal);
+               pr_info("VSS is %d\n", mode->vsync_start);
+               pr_info("VSE is %d\n", mode->vsync_end);
+               pr_info("vtotal is %d\n", mode->vtotal);
+               pr_info("clock is %d\n", mode->clock);
 #endif
                mode_dev->panel_fixed_mode = mode;
        }
index 83e22fd4cfc0111da5a3b5de8a9d3ce05ba7c7f7..83667087d6e5ddc55291bbefe092543604a0e802 100644 (file)
@@ -905,9 +905,8 @@ static inline void REGISTER_WRITE8(struct drm_device *dev,
 #define PSB_RSGX32(_offs)                                              \
 ({                                                                     \
        if (inl(dev_priv->apm_base + PSB_APM_STS) & 0x3) {              \
-               printk(KERN_ERR                                         \
-                       "access sgx when it's off!! (READ) %s, %d\n",   \
-              __FILE__, __LINE__);                                     \
+               pr_err("access sgx when it's off!! (READ) %s, %d\n",    \
+                      __FILE__, __LINE__);                             \
                melay(1000);                                            \
        }                                                               \
        ioread32(dev_priv->sgx_reg + (_offs));                          \
index 483fdce74e39a0dfbbfcc8a98e13cd3dd1667652..0066fe7e622ef75de181cc54770daeb2006a2d24 100644 (file)
@@ -388,11 +388,11 @@ bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
 
        /* PSB requires the LVDS is on pipe B, MRST has only one pipe anyway */
        if (!IS_MRST(dev) && gma_crtc->pipe == 0) {
-               printk(KERN_ERR "Can't support LVDS on pipe A\n");
+               pr_err("Can't support LVDS on pipe A\n");
                return false;
        }
        if (IS_MRST(dev) && gma_crtc->pipe != 0) {
-               printk(KERN_ERR "Must use PIPE A\n");
+               pr_err("Must use PIPE A\n");
                return false;
        }
        /* Should never happen!! */
@@ -400,8 +400,7 @@ bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
                            head) {
                if (tmp_encoder != encoder
                    && tmp_encoder->crtc == encoder->crtc) {
-                       printk(KERN_ERR "Can't enable LVDS and another "
-                              "encoder on the same pipe\n");
+                       pr_err("Can't enable LVDS and another encoder on the same pipe\n");
                        return false;
                }
        }
index c655883d3613c63c81e100ec32d878f36c499dcc..59542bddc9802838316d2a04e9a023ff546de014 100644 (file)
@@ -423,6 +423,24 @@ static void hibmc_crtc_atomic_flush(struct drm_crtc *crtc,
        spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 }
 
+static int hibmc_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+       struct hibmc_drm_private *priv = crtc->dev->dev_private;
+
+       writel(HIBMC_RAW_INTERRUPT_EN_VBLANK(1),
+              priv->mmio + HIBMC_RAW_INTERRUPT_EN);
+
+       return 0;
+}
+
+static void hibmc_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+       struct hibmc_drm_private *priv = crtc->dev->dev_private;
+
+       writel(HIBMC_RAW_INTERRUPT_EN_VBLANK(0),
+              priv->mmio + HIBMC_RAW_INTERRUPT_EN);
+}
+
 static const struct drm_crtc_funcs hibmc_crtc_funcs = {
        .page_flip = drm_atomic_helper_page_flip,
        .set_config = drm_atomic_helper_set_config,
@@ -430,6 +448,8 @@ static const struct drm_crtc_funcs hibmc_crtc_funcs = {
        .reset = drm_atomic_helper_crtc_reset,
        .atomic_duplicate_state =  drm_atomic_helper_crtc_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+       .enable_vblank = hibmc_crtc_enable_vblank,
+       .disable_vblank = hibmc_crtc_disable_vblank,
 };
 
 static const struct drm_crtc_helper_funcs hibmc_crtc_helper_funcs = {
index 7e2043f4348ce5c7aac6e0517fbe200a841a000f..2ffdbf9801bd644c3d1320b2499012c8ba6c83f0 100644 (file)
@@ -37,26 +37,6 @@ static const struct file_operations hibmc_fops = {
        .llseek         = no_llseek,
 };
 
-static int hibmc_enable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-       struct hibmc_drm_private *priv =
-               (struct hibmc_drm_private *)dev->dev_private;
-
-       writel(HIBMC_RAW_INTERRUPT_EN_VBLANK(1),
-              priv->mmio + HIBMC_RAW_INTERRUPT_EN);
-
-       return 0;
-}
-
-static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-       struct hibmc_drm_private *priv =
-               (struct hibmc_drm_private *)dev->dev_private;
-
-       writel(HIBMC_RAW_INTERRUPT_EN_VBLANK(0),
-              priv->mmio + HIBMC_RAW_INTERRUPT_EN);
-}
-
 irqreturn_t hibmc_drm_interrupt(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *)arg;
@@ -84,9 +64,6 @@ static struct drm_driver hibmc_driver = {
        .desc                   = "hibmc drm driver",
        .major                  = 1,
        .minor                  = 0,
-       .get_vblank_counter     = drm_vblank_no_hw_counter,
-       .enable_vblank          = hibmc_enable_vblank,
-       .disable_vblank         = hibmc_disable_vblank,
        .gem_free_object_unlocked = hibmc_gem_free_object,
        .dumb_create            = hibmc_dumb_create,
        .dumb_map_offset        = hibmc_dumb_mmap_offset,
index d7a4d9095b334d19ac28a0066da7a5e93cd20a7c..f5ac80daeef2de2d1f5eeac2da80c9855056d630 100644 (file)
@@ -147,7 +147,6 @@ static int hibmc_drm_fb_create(struct drm_fb_helper *helper,
        return 0;
 
 out_release_fbi:
-       drm_fb_helper_release_fbi(helper);
        ret1 = ttm_bo_reserve(&bo->bo, true, false, NULL);
        if (ret1) {
                DRM_ERROR("failed to rsv ttm_bo when release fbi: %d\n", ret1);
@@ -170,7 +169,6 @@ static void hibmc_fbdev_destroy(struct hibmc_fbdev *fbdev)
        struct drm_fb_helper *fbh = &fbdev->helper;
 
        drm_fb_helper_unregister_fbi(fbh);
-       drm_fb_helper_release_fbi(fbh);
 
        drm_fb_helper_fini(fbh);
 
index 9a0678a33e0dcd9cafaf95ec377cad354bfbcc01..c96c228a98980810d220eec84b2a8a3326e0c487 100644 (file)
@@ -302,9 +302,8 @@ static void ade_set_medianoc_qos(struct ade_crtc *acrtc)
                           SOCKET_QOS_EN, SOCKET_QOS_EN);
 }
 
-static int ade_enable_vblank(struct drm_device *dev, unsigned int pipe)
+static int ade_crtc_enable_vblank(struct drm_crtc *crtc)
 {
-       struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
        struct ade_crtc *acrtc = to_ade_crtc(crtc);
        struct ade_hw_ctx *ctx = acrtc->ctx;
        void __iomem *base = ctx->base;
@@ -318,9 +317,8 @@ static int ade_enable_vblank(struct drm_device *dev, unsigned int pipe)
        return 0;
 }
 
-static void ade_disable_vblank(struct drm_device *dev, unsigned int pipe)
+static void ade_crtc_disable_vblank(struct drm_crtc *crtc)
 {
-       struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
        struct ade_crtc *acrtc = to_ade_crtc(crtc);
        struct ade_hw_ctx *ctx = acrtc->ctx;
        void __iomem *base = ctx->base;
@@ -570,6 +568,8 @@ static const struct drm_crtc_funcs ade_crtc_funcs = {
        .set_property = drm_atomic_helper_crtc_set_property,
        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
        .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
+       .enable_vblank  = ade_crtc_enable_vblank,
+       .disable_vblank = ade_crtc_disable_vblank,
 };
 
 static int ade_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
@@ -1025,9 +1025,6 @@ static int ade_drm_init(struct platform_device *pdev)
                               IRQF_SHARED, dev->driver->name, acrtc);
        if (ret)
                return ret;
-       dev->driver->get_vblank_counter = drm_vblank_no_hw_counter;
-       dev->driver->enable_vblank = ade_enable_vblank;
-       dev->driver->disable_vblank = ade_disable_vblank;
 
        return 0;
 }
index fa69d72fdcb9ff45e6590402bb59b9b325d65c38..7d7244798507de0ac773927cba3e1676baa98696 100644 (file)
@@ -35,32 +35,6 @@ static inline struct drm_i915_private *node_to_i915(struct drm_info_node *node)
        return to_i915(node->minor->dev);
 }
 
-/* As the drm_debugfs_init() routines are called before dev->dev_private is
- * allocated we need to hook into the minor for release. */
-static int
-drm_add_fake_info_node(struct drm_minor *minor,
-                      struct dentry *ent,
-                      const void *key)
-{
-       struct drm_info_node *node;
-
-       node = kmalloc(sizeof(*node), GFP_KERNEL);
-       if (node == NULL) {
-               debugfs_remove(ent);
-               return -ENOMEM;
-       }
-
-       node->minor = minor;
-       node->dent = ent;
-       node->info_ent = (void *)key;
-
-       mutex_lock(&minor->debugfs_lock);
-       list_add(&node->list, &minor->debugfs_list);
-       mutex_unlock(&minor->debugfs_lock);
-
-       return 0;
-}
-
 static int i915_capabilities(struct seq_file *m, void *data)
 {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
@@ -4593,37 +4567,6 @@ static const struct file_operations i915_forcewake_fops = {
        .release = i915_forcewake_release,
 };
 
-static int i915_forcewake_create(struct dentry *root, struct drm_minor *minor)
-{
-       struct dentry *ent;
-
-       ent = debugfs_create_file("i915_forcewake_user",
-                                 S_IRUSR,
-                                 root, to_i915(minor->dev),
-                                 &i915_forcewake_fops);
-       if (!ent)
-               return -ENOMEM;
-
-       return drm_add_fake_info_node(minor, ent, &i915_forcewake_fops);
-}
-
-static int i915_debugfs_create(struct dentry *root,
-                              struct drm_minor *minor,
-                              const char *name,
-                              const struct file_operations *fops)
-{
-       struct dentry *ent;
-
-       ent = debugfs_create_file(name,
-                                 S_IRUGO | S_IWUSR,
-                                 root, to_i915(minor->dev),
-                                 fops);
-       if (!ent)
-               return -ENOMEM;
-
-       return drm_add_fake_info_node(minor, ent, fops);
-}
-
 static const struct drm_info_list i915_debugfs_list[] = {
        {"i915_capabilities", i915_capabilities, 0},
        {"i915_gem_objects", i915_gem_object_info, 0},
@@ -4706,22 +4649,27 @@ static const struct i915_debugfs_files {
 int i915_debugfs_register(struct drm_i915_private *dev_priv)
 {
        struct drm_minor *minor = dev_priv->drm.primary;
+       struct dentry *ent;
        int ret, i;
 
-       ret = i915_forcewake_create(minor->debugfs_root, minor);
-       if (ret)
-               return ret;
+       ent = debugfs_create_file("i915_forcewake_user", S_IRUSR,
+                                 minor->debugfs_root, to_i915(minor->dev),
+                                 &i915_forcewake_fops);
+       if (!ent)
+               return -ENOMEM;
 
        ret = intel_pipe_crc_create(minor);
        if (ret)
                return ret;
 
        for (i = 0; i < ARRAY_SIZE(i915_debugfs_files); i++) {
-               ret = i915_debugfs_create(minor->debugfs_root, minor,
-                                         i915_debugfs_files[i].name,
+               ent = debugfs_create_file(i915_debugfs_files[i].name,
+                                         S_IRUGO | S_IWUSR,
+                                         minor->debugfs_root,
+                                         to_i915(minor->dev),
                                          i915_debugfs_files[i].fops);
-               if (ret)
-                       return ret;
+               if (!ent)
+                       return -ENOMEM;
        }
 
        return drm_debugfs_create_files(i915_debugfs_list,
@@ -4729,27 +4677,6 @@ int i915_debugfs_register(struct drm_i915_private *dev_priv)
                                        minor->debugfs_root, minor);
 }
 
-void i915_debugfs_unregister(struct drm_i915_private *dev_priv)
-{
-       struct drm_minor *minor = dev_priv->drm.primary;
-       int i;
-
-       drm_debugfs_remove_files(i915_debugfs_list,
-                                I915_DEBUGFS_ENTRIES, minor);
-
-       drm_debugfs_remove_files((struct drm_info_list *)&i915_forcewake_fops,
-                                1, minor);
-
-       intel_pipe_crc_cleanup(minor);
-
-       for (i = 0; i < ARRAY_SIZE(i915_debugfs_files); i++) {
-               struct drm_info_list *info_list =
-                       (struct drm_info_list *)i915_debugfs_files[i].fops;
-
-               drm_debugfs_remove_files(info_list, 1, minor);
-       }
-}
-
 struct dpcd_block {
        /* DPCD dump start address. */
        unsigned int offset;
index e703556eba999a95fd1a728538f6412db28068ae..655d146e1126560a865d52dd29514e4037c036e6 100644 (file)
@@ -1167,7 +1167,6 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
 
        i915_teardown_sysfs(dev_priv);
        i915_guc_log_unregister(dev_priv);
-       i915_debugfs_unregister(dev_priv);
        drm_dev_unregister(&dev_priv->drm);
 
        i915_gem_shrinker_cleanup(dev_priv);
index 0a4b42d313912c3c5b56a449cfac33e63afeb16e..8df73751c367a1c9177bb68abc117e41086de36b 100644 (file)
@@ -3528,12 +3528,10 @@ u32 i915_gem_fence_alignment(struct drm_i915_private *dev_priv, u32 size,
 /* i915_debugfs.c */
 #ifdef CONFIG_DEBUG_FS
 int i915_debugfs_register(struct drm_i915_private *dev_priv);
-void i915_debugfs_unregister(struct drm_i915_private *dev_priv);
 int i915_debugfs_connector_add(struct drm_connector *connector);
 void intel_display_crc_init(struct drm_i915_private *dev_priv);
 #else
 static inline int i915_debugfs_register(struct drm_i915_private *dev_priv) {return 0;}
-static inline void i915_debugfs_unregister(struct drm_i915_private *dev_priv) {}
 static inline int i915_debugfs_connector_add(struct drm_connector *connector)
 { return 0; }
 static inline void intel_display_crc_init(struct drm_i915_private *dev_priv) {}
index e6ffef2f707a01934a3a6f777b1dc7548ef370c8..a62feb68689535d09a35ffda36ed9603a55b0ed4 100644 (file)
@@ -4249,7 +4249,6 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
        if (IS_GEN2(dev_priv)) {
                /* Gen2 doesn't have a hardware frame counter */
                dev->max_vblank_count = 0;
-               dev->driver->get_vblank_counter = drm_vblank_no_hw_counter;
        } else if (IS_G4X(dev_priv) || INTEL_INFO(dev_priv)->gen >= 5) {
                dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
                dev->driver->get_vblank_counter = g4x_get_vblank_counter;
index 40f4e5efaf837e52ad299bf66790383e424975d8..a277f8eb7beb8b5e12d5919275b63163a7ab2c5f 100644 (file)
@@ -395,10 +395,10 @@ static void timer_i915_sw_fence_wake(unsigned long data)
 {
        struct i915_sw_dma_fence_cb *cb = (struct i915_sw_dma_fence_cb *)data;
 
-       printk(KERN_WARNING "asynchronous wait on fence %s:%s:%x timed out\n",
-              cb->dma->ops->get_driver_name(cb->dma),
-              cb->dma->ops->get_timeline_name(cb->dma),
-              cb->dma->seqno);
+       pr_warn("asynchronous wait on fence %s:%s:%x timed out\n",
+               cb->dma->ops->get_driver_name(cb->dma),
+               cb->dma->ops->get_timeline_name(cb->dma),
+               cb->dma->seqno);
        dma_fence_put(cb->dma);
        cb->dma = NULL;
 
index 01341670738fbb118d8402bbda62d7234c8c3863..a2fece5e9fb38c80051ba6cea8be8af790c9e94b 100644 (file)
@@ -3482,7 +3482,8 @@ static void intel_update_primary_planes(struct drm_device *dev)
 
 static int
 __intel_display_resume(struct drm_device *dev,
-                      struct drm_atomic_state *state)
+                      struct drm_atomic_state *state,
+                      struct drm_modeset_acquire_ctx *ctx)
 {
        struct drm_crtc_state *crtc_state;
        struct drm_crtc *crtc;
@@ -3506,7 +3507,7 @@ __intel_display_resume(struct drm_device *dev,
        /* ignore any reset values/BIOS leftovers in the WM registers */
        to_intel_atomic_state(state)->skip_intermediate_wm = true;
 
-       ret = drm_atomic_commit(state);
+       ret = drm_atomic_helper_commit_duplicated_state(state, ctx);
 
        WARN_ON(ret == -EDEADLK);
        return ret;
@@ -3596,7 +3597,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
                         */
                        intel_update_primary_planes(dev);
                } else {
-                       ret = __intel_display_resume(dev, state);
+                       ret = __intel_display_resume(dev, state, ctx);
                        if (ret)
                                DRM_ERROR("Restoring old state failed with %i\n", ret);
                }
@@ -3616,7 +3617,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
                        dev_priv->display.hpd_irq_setup(dev_priv);
                spin_unlock_irq(&dev_priv->irq_lock);
 
-               ret = __intel_display_resume(dev, state);
+               ret = __intel_display_resume(dev, state, ctx);
                if (ret)
                        DRM_ERROR("Restoring old state failed with %i\n", ret);
 
@@ -11323,7 +11324,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
        if (!state)
                return;
 
-       ret = drm_atomic_commit(state);
+       ret = drm_atomic_helper_commit_duplicated_state(state, ctx);
        if (ret)
                DRM_DEBUG_KMS("Couldn't release load detect pipe: %i\n", ret);
        drm_atomic_state_put(state);
@@ -17240,7 +17241,7 @@ void intel_display_resume(struct drm_device *dev)
        }
 
        if (!ret)
-               ret = __intel_display_resume(dev, state);
+               ret = __intel_display_resume(dev, state, &ctx);
 
        drm_modeset_drop_locks(&ctx);
        drm_modeset_acquire_fini(&ctx);
index 344f238b283f3bfafcaac0ac27f28f141f4bf9ee..064582963ff61345e61f50f7ed40932fc083e514 100644 (file)
@@ -1891,7 +1891,6 @@ void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon);
 
 /* intel_pipe_crc.c */
 int intel_pipe_crc_create(struct drm_minor *minor);
-void intel_pipe_crc_cleanup(struct drm_minor *minor);
 #ifdef CONFIG_DEBUG_FS
 int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name,
                              size_t *values_cnt);
index 1b8ba2e77539577f5eb997f9e1eb315f1f7ae078..281c5c48a84d96a16998a79b0d2e1deff9a2194c 100644 (file)
@@ -253,7 +253,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
        if (IS_ERR(vaddr)) {
                DRM_ERROR("Failed to remap framebuffer into virtual memory\n");
                ret = PTR_ERR(vaddr);
-               goto out_destroy_fbi;
+               goto out_unpin;
        }
        info->screen_base = vaddr;
        info->screen_size = vma->node.size;
@@ -281,8 +281,6 @@ static int intelfb_create(struct drm_fb_helper *helper,
        vga_switcheroo_client_fb_set(pdev, info);
        return 0;
 
-out_destroy_fbi:
-       drm_fb_helper_release_fbi(helper);
 out_unpin:
        intel_unpin_fb_vma(vma);
 out_unlock:
@@ -543,7 +541,6 @@ static void intel_fbdev_destroy(struct intel_fbdev *ifbdev)
         */
 
        drm_fb_helper_unregister_fbi(&ifbdev->helper);
-       drm_fb_helper_release_fbi(&ifbdev->helper);
 
        drm_fb_helper_fini(&ifbdev->helper);
 
index c0b1f99da37b34c914fe180c856bec51dc4c333f..5aa524e32df776970445ef5258ba5ca4628928d7 100644 (file)
@@ -36,31 +36,6 @@ struct pipe_crc_info {
        enum pipe pipe;
 };
 
-/* As the drm_debugfs_init() routines are called before dev->dev_private is
- * allocated we need to hook into the minor for release.
- */
-static int drm_add_fake_info_node(struct drm_minor *minor,
-                                 struct dentry *ent, const void *key)
-{
-       struct drm_info_node *node;
-
-       node = kmalloc(sizeof(*node), GFP_KERNEL);
-       if (node == NULL) {
-               debugfs_remove(ent);
-               return -ENOMEM;
-       }
-
-       node->minor = minor;
-       node->dent = ent;
-       node->info_ent = (void *) key;
-
-       mutex_lock(&minor->debugfs_lock);
-       list_add(&node->list, &minor->debugfs_list);
-       mutex_unlock(&minor->debugfs_lock);
-
-       return 0;
-}
-
 static int i915_pipe_crc_open(struct inode *inode, struct file *filep)
 {
        struct pipe_crc_info *info = inode->i_private;
@@ -209,22 +184,6 @@ static struct pipe_crc_info i915_pipe_crc_data[I915_MAX_PIPES] = {
        },
 };
 
-static int i915_pipe_crc_create(struct dentry *root, struct drm_minor *minor,
-                               enum pipe pipe)
-{
-       struct drm_i915_private *dev_priv = to_i915(minor->dev);
-       struct dentry *ent;
-       struct pipe_crc_info *info = &i915_pipe_crc_data[pipe];
-
-       info->dev_priv = dev_priv;
-       ent = debugfs_create_file(info->name, S_IRUGO, root, info,
-                                 &i915_pipe_crc_fops);
-       if (!ent)
-               return -ENOMEM;
-
-       return drm_add_fake_info_node(minor, ent, info);
-}
-
 static const char * const pipe_crc_sources[] = {
        "none",
        "plane1",
@@ -928,27 +887,22 @@ void intel_display_crc_init(struct drm_i915_private *dev_priv)
 
 int intel_pipe_crc_create(struct drm_minor *minor)
 {
-       int ret, i;
-
-       for (i = 0; i < ARRAY_SIZE(i915_pipe_crc_data); i++) {
-               ret = i915_pipe_crc_create(minor->debugfs_root, minor, i);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-void intel_pipe_crc_cleanup(struct drm_minor *minor)
-{
+       struct drm_i915_private *dev_priv = to_i915(minor->dev);
+       struct dentry *ent;
        int i;
 
        for (i = 0; i < ARRAY_SIZE(i915_pipe_crc_data); i++) {
-               struct drm_info_list *info_list =
-                       (struct drm_info_list *)&i915_pipe_crc_data[i];
+               struct pipe_crc_info *info = &i915_pipe_crc_data[i];
 
-               drm_debugfs_remove_files(info_list, 1, minor);
+               info->dev_priv = dev_priv;
+               ent = debugfs_create_file(info->name, S_IRUGO,
+                                         minor->debugfs_root, info,
+                                         &i915_pipe_crc_fops);
+               if (!ent)
+                       return -ENOMEM;
        }
+
+       return 0;
 }
 
 int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name,
index f562cb7964b08ba65d06de2b16093e992456f2b8..4b7b92a7bcf7bdeb37aa5af08ecb336148c25d5d 100644 (file)
@@ -40,17 +40,11 @@ struct imx_drm_component {
 
 struct imx_drm_device {
        struct drm_device                       *drm;
-       struct imx_drm_crtc                     *crtc[MAX_CRTC];
        unsigned int                            pipes;
        struct drm_fbdev_cma                    *fbhelper;
        struct drm_atomic_state                 *state;
 };
 
-struct imx_drm_crtc {
-       struct drm_crtc                         *crtc;
-       struct imx_drm_crtc_helper_funcs        imx_drm_helper_funcs;
-};
-
 #if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)
 static int legacyfb_depth = 16;
 module_param(legacyfb_depth, int, 0444);
@@ -63,38 +57,6 @@ static void imx_drm_driver_lastclose(struct drm_device *drm)
        drm_fbdev_cma_restore_mode(imxdrm->fbhelper);
 }
 
-static int imx_drm_enable_vblank(struct drm_device *drm, unsigned int pipe)
-{
-       struct imx_drm_device *imxdrm = drm->dev_private;
-       struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[pipe];
-       int ret;
-
-       if (!imx_drm_crtc)
-               return -EINVAL;
-
-       if (!imx_drm_crtc->imx_drm_helper_funcs.enable_vblank)
-               return -ENOSYS;
-
-       ret = imx_drm_crtc->imx_drm_helper_funcs.enable_vblank(
-                       imx_drm_crtc->crtc);
-
-       return ret;
-}
-
-static void imx_drm_disable_vblank(struct drm_device *drm, unsigned int pipe)
-{
-       struct imx_drm_device *imxdrm = drm->dev_private;
-       struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[pipe];
-
-       if (!imx_drm_crtc)
-               return;
-
-       if (!imx_drm_crtc->imx_drm_helper_funcs.disable_vblank)
-               return;
-
-       imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc);
-}
-
 static const struct file_operations imx_drm_driver_fops = {
        .owner = THIS_MODULE,
        .open = drm_open,
@@ -176,71 +138,10 @@ static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state)
        drm_atomic_helper_cleanup_planes(dev, state);
 }
 
-static struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = {
+static const struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = {
        .atomic_commit_tail = imx_drm_atomic_commit_tail,
 };
 
-/*
- * imx_drm_add_crtc - add a new crtc
- */
-int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
-               struct imx_drm_crtc **new_crtc, struct drm_plane *primary_plane,
-               const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs,
-               struct device_node *port)
-{
-       struct imx_drm_device *imxdrm = drm->dev_private;
-       struct imx_drm_crtc *imx_drm_crtc;
-
-       /*
-        * The vblank arrays are dimensioned by MAX_CRTC - we can't
-        * pass IDs greater than this to those functions.
-        */
-       if (imxdrm->pipes >= MAX_CRTC)
-               return -EINVAL;
-
-       if (imxdrm->drm->open_count)
-               return -EBUSY;
-
-       imx_drm_crtc = kzalloc(sizeof(*imx_drm_crtc), GFP_KERNEL);
-       if (!imx_drm_crtc)
-               return -ENOMEM;
-
-       imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs;
-       imx_drm_crtc->crtc = crtc;
-
-       crtc->port = port;
-
-       imxdrm->crtc[imxdrm->pipes++] = imx_drm_crtc;
-
-       *new_crtc = imx_drm_crtc;
-
-       drm_crtc_helper_add(crtc,
-                       imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
-
-       drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
-                       imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs, NULL);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(imx_drm_add_crtc);
-
-/*
- * imx_drm_remove_crtc - remove a crtc
- */
-int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc)
-{
-       struct imx_drm_device *imxdrm = imx_drm_crtc->crtc->dev->dev_private;
-       unsigned int pipe = drm_crtc_index(imx_drm_crtc->crtc);
-
-       drm_crtc_cleanup(imx_drm_crtc->crtc);
-
-       imxdrm->crtc[pipe] = NULL;
-
-       kfree(imx_drm_crtc);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(imx_drm_remove_crtc);
 
 int imx_drm_encoder_parse_of(struct drm_device *drm,
        struct drm_encoder *encoder, struct device_node *np)
@@ -288,9 +189,6 @@ static struct drm_driver imx_drm_driver = {
        .gem_prime_vmap         = drm_gem_cma_prime_vmap,
        .gem_prime_vunmap       = drm_gem_cma_prime_vunmap,
        .gem_prime_mmap         = drm_gem_cma_prime_mmap,
-       .get_vblank_counter     = drm_vblank_no_hw_counter,
-       .enable_vblank          = imx_drm_enable_vblank,
-       .disable_vblank         = imx_drm_disable_vblank,
        .ioctls                 = imx_drm_ioctls,
        .num_ioctls             = ARRAY_SIZE(imx_drm_ioctls),
        .fops                   = &imx_drm_driver_fops,
index 5a91cb16c8fa53d4b84dcbcf332605c78483d171..cc003334505dc2a453b8152c225ec49a946997d8 100644 (file)
@@ -25,19 +25,6 @@ static inline struct imx_crtc_state *to_imx_crtc_state(struct drm_crtc_state *s)
 {
        return container_of(s, struct imx_crtc_state, base);
 }
-
-struct imx_drm_crtc_helper_funcs {
-       int (*enable_vblank)(struct drm_crtc *crtc);
-       void (*disable_vblank)(struct drm_crtc *crtc);
-       const struct drm_crtc_helper_funcs *crtc_helper_funcs;
-       const struct drm_crtc_funcs *crtc_funcs;
-};
-
-int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
-               struct imx_drm_crtc **new_crtc, struct drm_plane *primary_plane,
-               const struct imx_drm_crtc_helper_funcs *imx_helper_funcs,
-               struct device_node *port);
-int imx_drm_remove_crtc(struct imx_drm_crtc *);
 int imx_drm_init_drm(struct platform_device *pdev,
                int preferred_bpp);
 int imx_drm_exit_drm(void);
index 6be515a9fb694b5fdac53d880430ba218b08e544..a3f2843b78cd8b35f2da6f5e8196b6f93a561481 100644 (file)
@@ -129,18 +129,31 @@ static void imx_drm_crtc_destroy_state(struct drm_crtc *crtc,
        kfree(to_imx_crtc_state(state));
 }
 
-static void imx_drm_crtc_destroy(struct drm_crtc *crtc)
+static int ipu_enable_vblank(struct drm_crtc *crtc)
+{
+       struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
+
+       enable_irq(ipu_crtc->irq);
+
+       return 0;
+}
+
+static void ipu_disable_vblank(struct drm_crtc *crtc)
 {
-       imx_drm_remove_crtc(to_ipu_crtc(crtc)->imx_crtc);
+       struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
+
+       disable_irq_nosync(ipu_crtc->irq);
 }
 
 static const struct drm_crtc_funcs ipu_crtc_funcs = {
        .set_config = drm_atomic_helper_set_config,
-       .destroy = imx_drm_crtc_destroy,
+       .destroy = drm_crtc_cleanup,
        .page_flip = drm_atomic_helper_page_flip,
        .reset = imx_drm_crtc_reset,
        .atomic_duplicate_state = imx_drm_crtc_duplicate_state,
        .atomic_destroy_state = imx_drm_crtc_destroy_state,
+       .enable_vblank = ipu_enable_vblank,
+       .disable_vblank = ipu_disable_vblank,
 };
 
 static irqreturn_t ipu_irq_handler(int irq, void *dev_id)
@@ -261,29 +274,6 @@ static const struct drm_crtc_helper_funcs ipu_helper_funcs = {
        .enable = ipu_crtc_enable,
 };
 
-static int ipu_enable_vblank(struct drm_crtc *crtc)
-{
-       struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
-
-       enable_irq(ipu_crtc->irq);
-
-       return 0;
-}
-
-static void ipu_disable_vblank(struct drm_crtc *crtc)
-{
-       struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
-
-       disable_irq_nosync(ipu_crtc->irq);
-}
-
-static const struct imx_drm_crtc_helper_funcs ipu_crtc_helper_funcs = {
-       .enable_vblank = ipu_enable_vblank,
-       .disable_vblank = ipu_disable_vblank,
-       .crtc_funcs = &ipu_crtc_funcs,
-       .crtc_helper_funcs = &ipu_helper_funcs,
-};
-
 static void ipu_put_resources(struct ipu_crtc *ipu_crtc)
 {
        if (!IS_ERR_OR_NULL(ipu_crtc->dc))
@@ -321,6 +311,7 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
        struct ipu_client_platformdata *pdata, struct drm_device *drm)
 {
        struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
+       struct drm_crtc *crtc = &ipu_crtc->base;
        int dp = -EINVAL;
        int ret;
 
@@ -340,19 +331,16 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
                goto err_put_resources;
        }
 
-       ret = imx_drm_add_crtc(drm, &ipu_crtc->base, &ipu_crtc->imx_crtc,
-                       &ipu_crtc->plane[0]->base, &ipu_crtc_helper_funcs,
-                       pdata->of_node);
-       if (ret) {
-               dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret);
-               goto err_put_resources;
-       }
+       crtc->port = pdata->of_node;
+       drm_crtc_helper_add(crtc, &ipu_helper_funcs);
+       drm_crtc_init_with_planes(drm, crtc, &ipu_crtc->plane[0]->base, NULL,
+                                 &ipu_crtc_funcs, NULL);
 
        ret = ipu_plane_get_resources(ipu_crtc->plane[0]);
        if (ret) {
                dev_err(ipu_crtc->dev, "getting plane 0 resources failed with %d.\n",
                        ret);
-               goto err_remove_crtc;
+               goto err_put_resources;
        }
 
        /* If this crtc is using the DP, add an overlay plane */
@@ -390,8 +378,6 @@ err_put_plane1_res:
                ipu_plane_put_resources(ipu_crtc->plane[1]);
 err_put_plane0_res:
        ipu_plane_put_resources(ipu_crtc->plane[0]);
-err_remove_crtc:
-       imx_drm_remove_crtc(ipu_crtc->imx_crtc);
 err_put_resources:
        ipu_put_resources(ipu_crtc);
 
index a73de1e669c24832fffa4a30b664bff0461b398e..69982f5a61988d91ba704dcd3d46c1af14668984 100644 (file)
@@ -168,9 +168,8 @@ static void mtk_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
        state->pending_config = true;
 }
 
-int mtk_drm_crtc_enable_vblank(struct drm_device *drm, unsigned int pipe)
+static int mtk_drm_crtc_enable_vblank(struct drm_crtc *crtc)
 {
-       struct drm_crtc *crtc = drm_crtc_from_index(drm, pipe);
        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
        struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0];
 
@@ -179,9 +178,8 @@ int mtk_drm_crtc_enable_vblank(struct drm_device *drm, unsigned int pipe)
        return 0;
 }
 
-void mtk_drm_crtc_disable_vblank(struct drm_device *drm, unsigned int pipe)
+static void mtk_drm_crtc_disable_vblank(struct drm_crtc *crtc)
 {
-       struct drm_crtc *crtc = drm_crtc_from_index(drm, pipe);
        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
        struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0];
 
@@ -436,6 +434,8 @@ static const struct drm_crtc_funcs mtk_crtc_funcs = {
        .atomic_duplicate_state = mtk_drm_crtc_duplicate_state,
        .atomic_destroy_state   = mtk_drm_crtc_destroy_state,
        .gamma_set              = drm_atomic_helper_legacy_gamma_set,
+       .enable_vblank          = mtk_drm_crtc_enable_vblank,
+       .disable_vblank         = mtk_drm_crtc_disable_vblank,
 };
 
 static const struct drm_crtc_helper_funcs mtk_crtc_helper_funcs = {
index a1550fa3c9d2c119f9367eb546084750c4f20cb9..9d9410c67ae9eb2026181b4a361e5c4e5707028d 100644 (file)
@@ -23,8 +23,6 @@
 #define MTK_MAX_BPC    10
 #define MTK_MIN_BPC    3
 
-int mtk_drm_crtc_enable_vblank(struct drm_device *drm, unsigned int pipe);
-void mtk_drm_crtc_disable_vblank(struct drm_device *drm, unsigned int pipe);
 void mtk_drm_crtc_commit(struct drm_crtc *crtc);
 void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *ovl);
 int mtk_drm_crtc_create(struct drm_device *drm_dev,
index b5f88e6d078e6992cc99e13743e59671bd36ae4f..f5a1fd9b3ecc7f7ce65b252828f703224d2ddb8f 100644 (file)
@@ -256,10 +256,6 @@ static struct drm_driver mtk_drm_driver = {
        .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
                           DRIVER_ATOMIC,
 
-       .get_vblank_counter = drm_vblank_no_hw_counter,
-       .enable_vblank = mtk_drm_crtc_enable_vblank,
-       .disable_vblank = mtk_drm_crtc_disable_vblank,
-
        .gem_free_object_unlocked = mtk_drm_gem_free_object,
        .gem_vm_ops = &drm_gem_cma_vm_ops,
        .dumb_create = mtk_drm_gem_dumb_create,
index 749770e5c65f053ede4142fe3cfa02c1905472e1..0fe49eccda65e9194d16a6c2ff4670770efca100 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "meson_crtc.h"
 #include "meson_plane.h"
+#include "meson_venc.h"
 #include "meson_vpp.h"
 #include "meson_viu.h"
 #include "meson_registers.h"
@@ -48,6 +49,24 @@ struct meson_crtc {
 
 /* CRTC */
 
+static int meson_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+       struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
+       struct meson_drm *priv = meson_crtc->priv;
+
+       meson_venc_enable_vsync(priv);
+
+       return 0;
+}
+
+static void meson_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+       struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
+       struct meson_drm *priv = meson_crtc->priv;
+
+       meson_venc_disable_vsync(priv);
+}
+
 static const struct drm_crtc_funcs meson_crtc_funcs = {
        .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
@@ -55,6 +74,9 @@ static const struct drm_crtc_funcs meson_crtc_funcs = {
        .page_flip              = drm_atomic_helper_page_flip,
        .reset                  = drm_atomic_helper_crtc_reset,
        .set_config             = drm_atomic_helper_set_config,
+       .enable_vblank          = meson_crtc_enable_vblank,
+       .disable_vblank         = meson_crtc_disable_vblank,
+
 };
 
 static void meson_crtc_enable(struct drm_crtc *crtc)
index 6f2fd82ed483da291b7d3f4d6de8655f38a0281e..8d17d0e59cbe12932a930e2ba5249306265113f1 100644 (file)
@@ -79,22 +79,6 @@ static const struct drm_mode_config_funcs meson_mode_config_funcs = {
        .fb_create           = drm_fb_cma_create,
 };
 
-static int meson_enable_vblank(struct drm_device *dev, unsigned int crtc)
-{
-       struct meson_drm *priv = dev->dev_private;
-
-       meson_venc_enable_vsync(priv);
-
-       return 0;
-}
-
-static void meson_disable_vblank(struct drm_device *dev, unsigned int crtc)
-{
-       struct meson_drm *priv = dev->dev_private;
-
-       meson_venc_disable_vsync(priv);
-}
-
 static irqreturn_t meson_irq(int irq, void *arg)
 {
        struct drm_device *dev = arg;
@@ -126,11 +110,6 @@ static struct drm_driver meson_driver = {
                                  DRIVER_MODESET | DRIVER_PRIME |
                                  DRIVER_ATOMIC,
 
-       /* Vblank */
-       .enable_vblank          = meson_enable_vblank,
-       .disable_vblank         = meson_disable_vblank,
-       .get_vblank_counter     = drm_vblank_no_hw_counter,
-
        /* IRQ */
        .irq_handler            = meson_irq,
 
index a449bb91213aa8f3a7fa8b4db496eed42288d995..5d3b1fac906f44dc4e216dd10abf08c622f4ff6a 100644 (file)
@@ -198,7 +198,7 @@ static int mgag200fb_create(struct drm_fb_helper *helper,
 
        ret = mgag200_framebuffer_init(dev, &mfbdev->mfb, &mode_cmd, gobj);
        if (ret)
-               goto err_framebuffer_init;
+               goto err_alloc_fbi;
 
        mfbdev->sysram = sysram;
        mfbdev->size = size;
@@ -230,8 +230,6 @@ static int mgag200fb_create(struct drm_fb_helper *helper,
 
        return 0;
 
-err_framebuffer_init:
-       drm_fb_helper_release_fbi(helper);
 err_alloc_fbi:
        vfree(sysram);
 err_sysram:
@@ -246,7 +244,6 @@ static int mga_fbdev_destroy(struct drm_device *dev,
        struct mga_framebuffer *mfb = &mfbdev->mfb;
 
        drm_fb_helper_unregister_fbi(&mfbdev->helper);
-       drm_fb_helper_release_fbi(&mfbdev->helper);
 
        if (mfb->obj) {
                drm_gem_object_unreference_unlocked(mfb->obj);
index 3938120e505126b86c45cfc5db181f60eb94efb6..f2e9b2bc18a58da273a9d2b140737ff6db1f6bae 100644 (file)
@@ -195,7 +195,7 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
        }
 
        if (delta > permitteddelta) {
-               printk(KERN_WARNING "PLL delta too large\n");
+               pr_warn("PLL delta too large\n");
                return 1;
        }
 
index 1fc07ce24686b372252a43d3b9984467fbff2c28..4f79b109173db0e13c7e2218e958b96df9a682e3 100644 (file)
@@ -1740,6 +1740,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
 
        msm_host->rx_buf = devm_kzalloc(&pdev->dev, SZ_4K, GFP_KERNEL);
        if (!msm_host->rx_buf) {
+               ret = -ENOMEM;
                pr_err("%s: alloc rx temp buf failed\n", __func__);
                goto fail;
        }
index 3eb0749223d9d8c10a330c67a81fff45ea957661..41ccd2a15d3c690d180e8c4a228b3bd6c8eee611 100644 (file)
@@ -214,12 +214,6 @@ static int mdp5_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor)
 
        return 0;
 }
-
-static void mdp5_kms_debugfs_cleanup(struct msm_kms *kms, struct drm_minor *minor)
-{
-       drm_debugfs_remove_files(mdp5_debugfs_list,
-                       ARRAY_SIZE(mdp5_debugfs_list), minor);
-}
 #endif
 
 static const struct mdp_kms_funcs kms_funcs = {
@@ -242,7 +236,6 @@ static const struct mdp_kms_funcs kms_funcs = {
                .destroy         = mdp5_kms_destroy,
 #ifdef CONFIG_DEBUG_FS
                .debugfs_init    = mdp5_kms_debugfs_init,
-               .debugfs_cleanup = mdp5_kms_debugfs_cleanup,
 #endif
        },
        .set_irqmask         = mdp5_set_irqmask,
index 387f0616e115ce039623287682c44209ef21e94d..75609a1debf7f886111820960176c6d2198d6a87 100644 (file)
@@ -170,8 +170,6 @@ void msm_debugfs_cleanup(struct drm_minor *minor)
        struct drm_device *dev = minor->dev;
        struct msm_drm_private *priv = dev->dev_private;
 
-       drm_debugfs_remove_files(msm_debugfs_list,
-                       ARRAY_SIZE(msm_debugfs_list), minor);
        if (!priv)
                return;
 
index 70226eaa5cac24ad34a85e1b0117492acca3d471..6842d427cc2b83cde3657f905d894f86d80d36fe 100644 (file)
@@ -152,7 +152,7 @@ u32 msm_readl(const void __iomem *addr)
 {
        u32 val = readl(addr);
        if (reglog)
-               printk(KERN_ERR "IO:R %p %08x\n", addr, val);
+               pr_err("IO:R %p %08x\n", addr, val);
        return val;
 }
 
@@ -816,7 +816,6 @@ static struct drm_driver msm_driver = {
        .irq_preinstall     = msm_irq_preinstall,
        .irq_postinstall    = msm_irq_postinstall,
        .irq_uninstall      = msm_irq_uninstall,
-       .get_vblank_counter = drm_vblank_no_hw_counter,
        .enable_vblank      = msm_enable_vblank,
        .disable_vblank     = msm_disable_vblank,
        .gem_free_object    = msm_gem_free_object,
index 6b1b375653f726f9217f201fc8e11d004de8f7b7..951e40faf6e8dd0527b516a5c72f4ce6dbb42f2d 100644 (file)
@@ -235,7 +235,6 @@ void msm_fbdev_free(struct drm_device *dev)
        DBG();
 
        drm_fb_helper_unregister_fbi(helper);
-       drm_fb_helper_release_fbi(helper);
 
        drm_fb_helper_fini(helper);
 
index 1627294575cb4da1bf8e353e0638a407679a3d7d..fc5a948c124c1ee81dccf1ce4ae9db097e140f45 100644 (file)
@@ -41,9 +41,6 @@ struct msm_perf_state {
        int buftot, bufpos;
 
        unsigned long next_jiffies;
-
-       struct dentry *ent;
-       struct drm_info_node *node;
 };
 
 #define SAMPLE_TIME (HZ/4)
@@ -208,6 +205,7 @@ int msm_perf_debugfs_init(struct drm_minor *minor)
 {
        struct msm_drm_private *priv = minor->dev->dev_private;
        struct msm_perf_state *perf;
+       struct dentry *ent;
 
        /* only create on first minor: */
        if (priv->perf)
@@ -222,26 +220,14 @@ int msm_perf_debugfs_init(struct drm_minor *minor)
        mutex_init(&perf->read_lock);
        priv->perf = perf;
 
-       perf->node = kzalloc(sizeof(*perf->node), GFP_KERNEL);
-       if (!perf->node)
-               goto fail;
-
-       perf->ent = debugfs_create_file("perf", S_IFREG | S_IRUGO,
+       ent = debugfs_create_file("perf", S_IFREG | S_IRUGO,
                        minor->debugfs_root, perf, &perf_debugfs_fops);
-       if (!perf->ent) {
+       if (!ent) {
                DRM_ERROR("Cannot create /sys/kernel/debug/dri/%pd/perf\n",
                                minor->debugfs_root);
                goto fail;
        }
 
-       perf->node->minor = minor;
-       perf->node->dent  = perf->ent;
-       perf->node->info_ent = NULL;
-
-       mutex_lock(&minor->debugfs_lock);
-       list_add(&perf->node->list, &minor->debugfs_list);
-       mutex_unlock(&minor->debugfs_lock);
-
        return 0;
 
 fail:
@@ -259,15 +245,6 @@ void msm_perf_debugfs_cleanup(struct drm_minor *minor)
 
        priv->perf = NULL;
 
-       debugfs_remove(perf->ent);
-
-       if (perf->node) {
-               mutex_lock(&minor->debugfs_lock);
-               list_del(&perf->node->list);
-               mutex_unlock(&minor->debugfs_lock);
-               kfree(perf->node);
-       }
-
        mutex_destroy(&perf->read_lock);
 
        kfree(perf);
index 6607456dc62612527145f5f3d022d427155aed7b..ab0b39f56780e240e53dcf0b1f8df3db070f1667 100644 (file)
@@ -84,9 +84,6 @@ struct msm_rd_state {
 
        bool open;
 
-       struct dentry *ent;
-       struct drm_info_node *node;
-
        /* current submit to read out: */
        struct msm_gem_submit *submit;
 
@@ -219,6 +216,7 @@ int msm_rd_debugfs_init(struct drm_minor *minor)
 {
        struct msm_drm_private *priv = minor->dev->dev_private;
        struct msm_rd_state *rd;
+       struct dentry *ent;
 
        /* only create on first minor: */
        if (priv->rd)
@@ -236,26 +234,14 @@ int msm_rd_debugfs_init(struct drm_minor *minor)
 
        init_waitqueue_head(&rd->fifo_event);
 
-       rd->node = kzalloc(sizeof(*rd->node), GFP_KERNEL);
-       if (!rd->node)
-               goto fail;
-
-       rd->ent = debugfs_create_file("rd", S_IFREG | S_IRUGO,
+       ent = debugfs_create_file("rd", S_IFREG | S_IRUGO,
                        minor->debugfs_root, rd, &rd_debugfs_fops);
-       if (!rd->ent) {
+       if (!ent) {
                DRM_ERROR("Cannot create /sys/kernel/debug/dri/%pd/rd\n",
                                minor->debugfs_root);
                goto fail;
        }
 
-       rd->node->minor = minor;
-       rd->node->dent  = rd->ent;
-       rd->node->info_ent = NULL;
-
-       mutex_lock(&minor->debugfs_lock);
-       list_add(&rd->node->list, &minor->debugfs_list);
-       mutex_unlock(&minor->debugfs_lock);
-
        return 0;
 
 fail:
@@ -272,18 +258,7 @@ void msm_rd_debugfs_cleanup(struct drm_minor *minor)
                return;
 
        priv->rd = NULL;
-
-       debugfs_remove(rd->ent);
-
-       if (rd->node) {
-               mutex_lock(&minor->debugfs_lock);
-               list_del(&rd->node->list);
-               mutex_unlock(&minor->debugfs_lock);
-               kfree(rd->node);
-       }
-
        mutex_destroy(&rd->read_lock);
-
        kfree(rd);
 }
 
index cdfbe0284635decf262db79c0b048291cc87c026..a4633ada8429d658f4362bbd4f8f18da55454462 100644 (file)
@@ -126,7 +126,7 @@ static int mxsfb_pipe_prepare_fb(struct drm_simple_display_pipe *pipe,
        return drm_fb_cma_prepare_fb(&pipe->plane, plane_state);
 }
 
-struct drm_simple_display_pipe_funcs mxsfb_funcs = {
+static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
        .enable         = mxsfb_pipe_enable,
        .disable        = mxsfb_pipe_disable,
        .update         = mxsfb_pipe_update,
@@ -221,6 +221,7 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
        mxsfb->fbdev = drm_fbdev_cma_init(drm, 32,
                                          drm->mode_config.num_connector);
        if (IS_ERR(mxsfb->fbdev)) {
+               ret = PTR_ERR(mxsfb->fbdev);
                mxsfb->fbdev = NULL;
                dev_err(drm->dev, "Failed to init FB CMA area\n");
                goto err_cma;
@@ -340,7 +341,6 @@ static struct drm_driver mxsfb_driver = {
        .irq_handler            = mxsfb_irq_handler,
        .irq_preinstall         = mxsfb_irq_preinstall,
        .irq_uninstall          = mxsfb_irq_preinstall,
-       .get_vblank_counter     = drm_vblank_no_hw_counter,
        .enable_vblank          = mxsfb_enable_vblank,
        .disable_vblank         = mxsfb_disable_vblank,
        .gem_free_object        = drm_gem_cma_free_object,
index 193573d191e520a12ccdde4a791ebdf8e64a334c..39468c2180277618caddceb0681d1bdd39f53140 100644 (file)
@@ -326,7 +326,7 @@ static bool nouveau_dsm_detect(void)
                nouveau_dsm_priv.dhandle = dhandle;
                acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME,
                        &buffer);
-               printk(KERN_INFO "VGA switcheroo: detected Optimus DSM method %s handle\n",
+               pr_info("VGA switcheroo: detected Optimus DSM method %s handle\n",
                        acpi_method_name);
                if (has_power_resources)
                        pr_info("nouveau: detected PR support, will not use DSM\n");
@@ -338,7 +338,7 @@ static bool nouveau_dsm_detect(void)
                nouveau_dsm_priv.dhandle = dhandle;
                acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME,
                        &buffer);
-               printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
+               pr_info("VGA switcheroo: detected DSM switching method %s handle\n",
                        acpi_method_name);
                nouveau_dsm_priv.dsm_detected = true;
                ret = true;
@@ -406,7 +406,8 @@ static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios,
 
        status = acpi_evaluate_object(rom_handle, NULL, &rom_arg, &buffer);
        if (ACPI_FAILURE(status)) {
-               printk(KERN_INFO "failed to evaluate ROM got %s\n", acpi_format_exception(status));
+               pr_info("failed to evaluate ROM got %s\n",
+                       acpi_format_exception(status));
                return -ENODEV;
        }
        obj = (union acpi_object *)buffer.pointer;
index fd64dfdc7d4f54fb503318936eb8b6c65104a6d3..963a4dba8213eb6080ff3713cbbdbb20ddb4b61e 100644 (file)
@@ -49,8 +49,8 @@ nouveau_debugfs_vbios_image(struct seq_file *m, void *data)
 static int
 nouveau_debugfs_pstate_get(struct seq_file *m, void *data)
 {
-       struct drm_info_node *node = (struct drm_info_node *) m->private;
-       struct nouveau_debugfs *debugfs = nouveau_debugfs(node->minor->dev);
+       struct drm_device *drm = m->private;
+       struct nouveau_debugfs *debugfs = nouveau_debugfs(drm);
        struct nvif_object *ctrl = &debugfs->ctrl;
        struct nvif_control_pstate_info_v0 info = {};
        int ret, i;
@@ -120,8 +120,8 @@ nouveau_debugfs_pstate_set(struct file *file, const char __user *ubuf,
                           size_t len, loff_t *offp)
 {
        struct seq_file *m = file->private_data;
-       struct drm_info_node *node = (struct drm_info_node *) m->private;
-       struct nouveau_debugfs *debugfs = nouveau_debugfs(node->minor->dev);
+       struct drm_device *drm = m->private;
+       struct nouveau_debugfs *debugfs = nouveau_debugfs(drm);
        struct nvif_object *ctrl = &debugfs->ctrl;
        struct nvif_control_pstate_user_v0 args = { .pwrsrc = -EINVAL };
        char buf[32] = {}, *tmp, *cur = buf;
@@ -192,42 +192,19 @@ static const struct nouveau_debugfs_files {
        {"pstate", &nouveau_pstate_fops},
 };
 
-static int
-nouveau_debugfs_create_file(struct drm_minor *minor,
-               const struct nouveau_debugfs_files *ndf)
-{
-       struct drm_info_node *node;
-
-       node = kmalloc(sizeof(*node), GFP_KERNEL);
-       if (node == NULL)
-               return -ENOMEM;
-
-       node->minor = minor;
-       node->info_ent = (const void *)ndf->fops;
-       node->dent = debugfs_create_file(ndf->name, S_IRUGO | S_IWUSR,
-                                        minor->debugfs_root, node, ndf->fops);
-       if (!node->dent) {
-               kfree(node);
-               return -ENOMEM;
-       }
-
-       mutex_lock(&minor->debugfs_lock);
-       list_add(&node->list, &minor->debugfs_list);
-       mutex_unlock(&minor->debugfs_lock);
-       return 0;
-}
-
 int
 nouveau_drm_debugfs_init(struct drm_minor *minor)
 {
-       int i, ret;
+       struct dentry *dentry;
+       int i;
 
        for (i = 0; i < ARRAY_SIZE(nouveau_debugfs_files); i++) {
-               ret = nouveau_debugfs_create_file(minor,
-                                                 &nouveau_debugfs_files[i]);
-
-               if (ret)
-                       return ret;
+               dentry = debugfs_create_file(nouveau_debugfs_files[i].name,
+                                            S_IRUGO | S_IWUSR,
+                                            minor->debugfs_root, minor->dev,
+                                            nouveau_debugfs_files[i].fops);
+               if (!dentry)
+                       return -ENOMEM;
        }
 
        return drm_debugfs_create_files(nouveau_debugfs_list,
@@ -235,21 +212,6 @@ nouveau_drm_debugfs_init(struct drm_minor *minor)
                                        minor->debugfs_root, minor);
 }
 
-void
-nouveau_drm_debugfs_cleanup(struct drm_minor *minor)
-{
-       int i;
-
-       drm_debugfs_remove_files(nouveau_debugfs_list, NOUVEAU_DEBUGFS_ENTRIES,
-                                minor);
-
-       for (i = 0; i < ARRAY_SIZE(nouveau_debugfs_files); i++) {
-               drm_debugfs_remove_files((struct drm_info_list *)
-                                        nouveau_debugfs_files[i].fops,
-                                        1, minor);
-       }
-}
-
 int
 nouveau_debugfs_init(struct nouveau_drm *drm)
 {
index eab58811417a20fb72ad35f6017e6e11af78fd55..b799f8dfb2b244dddd477dd97642a8b8450d4e66 100644 (file)
@@ -18,7 +18,6 @@ nouveau_debugfs(struct drm_device *dev)
 }
 
 extern int  nouveau_drm_debugfs_init(struct drm_minor *);
-extern void nouveau_drm_debugfs_cleanup(struct drm_minor *);
 extern int  nouveau_debugfs_init(struct nouveau_drm *);
 extern void nouveau_debugfs_fini(struct nouveau_drm *);
 #else
@@ -28,11 +27,6 @@ nouveau_drm_debugfs_init(struct drm_minor *minor)
        return 0;
 }
 
-static inline void
-nouveau_drm_debugfs_cleanup(struct drm_minor *minor)
-{
-}
-
 static inline int
 nouveau_debugfs_init(struct nouveau_drm *drm)
 {
index 72fdba1a1c5d02bd393eee5d106befeed049fbca..33269c7df30f17b50097bf91d7259fe91ba6914b 100644 (file)
@@ -625,117 +625,6 @@ nouveau_display_destroy(struct drm_device *dev)
        kfree(disp);
 }
 
-static int
-nouveau_atomic_disable_connector(struct drm_atomic_state *state,
-                                struct drm_connector *connector)
-{
-       struct drm_connector_state *connector_state;
-       struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
-       struct drm_plane_state *plane_state;
-       struct drm_plane *plane;
-       int ret;
-
-       if (!(crtc = connector->state->crtc))
-               return 0;
-
-       connector_state = drm_atomic_get_connector_state(state, connector);
-       if (IS_ERR(connector_state))
-               return PTR_ERR(connector_state);
-
-       ret = drm_atomic_set_crtc_for_connector(connector_state, NULL);
-       if (ret)
-               return ret;
-
-       crtc_state = drm_atomic_get_crtc_state(state, crtc);
-       if (IS_ERR(crtc_state))
-               return PTR_ERR(crtc_state);
-
-       ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
-       if (ret)
-               return ret;
-
-       crtc_state->active = false;
-
-       drm_for_each_plane_mask(plane, connector->dev, crtc_state->plane_mask) {
-               plane_state = drm_atomic_get_plane_state(state, plane);
-               if (IS_ERR(plane_state))
-                       return PTR_ERR(plane_state);
-
-               ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
-               if (ret)
-                       return ret;
-
-               drm_atomic_set_fb_for_plane(plane_state, NULL);
-       }
-
-       return 0;
-}
-
-static int
-nouveau_atomic_disable(struct drm_device *dev,
-                      struct drm_modeset_acquire_ctx *ctx)
-{
-       struct drm_atomic_state *state;
-       struct drm_connector *connector;
-       int ret;
-
-       state = drm_atomic_state_alloc(dev);
-       if (!state)
-               return -ENOMEM;
-
-       state->acquire_ctx = ctx;
-
-       drm_for_each_connector(connector, dev) {
-               ret = nouveau_atomic_disable_connector(state, connector);
-               if (ret)
-                       break;
-       }
-
-       if (ret == 0)
-               ret = drm_atomic_commit(state);
-       drm_atomic_state_put(state);
-       return ret;
-}
-
-static struct drm_atomic_state *
-nouveau_atomic_suspend(struct drm_device *dev)
-{
-       struct drm_modeset_acquire_ctx ctx;
-       struct drm_atomic_state *state;
-       int ret;
-
-       drm_modeset_acquire_init(&ctx, 0);
-
-retry:
-       ret = drm_modeset_lock_all_ctx(dev, &ctx);
-       if (ret < 0) {
-               state = ERR_PTR(ret);
-               goto unlock;
-       }
-
-       state = drm_atomic_helper_duplicate_state(dev, &ctx);
-       if (IS_ERR(state))
-               goto unlock;
-
-       ret = nouveau_atomic_disable(dev, &ctx);
-       if (ret < 0) {
-               drm_atomic_state_put(state);
-               state = ERR_PTR(ret);
-               goto unlock;
-       }
-
-unlock:
-       if (PTR_ERR(state) == -EDEADLK) {
-               drm_modeset_backoff(&ctx);
-               goto retry;
-       }
-
-       drm_modeset_drop_locks(&ctx);
-       drm_modeset_acquire_fini(&ctx);
-       return state;
-}
-
 int
 nouveau_display_suspend(struct drm_device *dev, bool runtime)
 {
@@ -744,7 +633,7 @@ nouveau_display_suspend(struct drm_device *dev, bool runtime)
 
        if (drm_drv_uses_atomic_modeset(dev)) {
                if (!runtime) {
-                       disp->suspend = nouveau_atomic_suspend(dev);
+                       disp->suspend = drm_atomic_helper_suspend(dev);
                        if (IS_ERR(disp->suspend)) {
                                int ret = PTR_ERR(disp->suspend);
                                disp->suspend = NULL;
index 468ed1d3bb26ced7a2d669237a3c2dfe6173920f..f0bb7606eb8b77949b97e3b7989ecd0cdf53e0fd 100644 (file)
@@ -980,10 +980,8 @@ driver_stub = {
 
 #if defined(CONFIG_DEBUG_FS)
        .debugfs_init = nouveau_drm_debugfs_init,
-       .debugfs_cleanup = nouveau_drm_debugfs_cleanup,
 #endif
 
-       .get_vblank_counter = drm_vblank_no_hw_counter,
        .enable_vblank = nouveau_display_vblank_enable,
        .disable_vblank = nouveau_display_vblank_disable,
        .get_scanout_position = nouveau_display_scanoutpos,
index 442e25c173833983e221f3b4b3e7cfb4363bdef6..2665a078b6dac94bd0ff07bcfea69b772a9c044c 100644 (file)
@@ -445,7 +445,6 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon)
        struct nouveau_framebuffer *nouveau_fb = nouveau_framebuffer(fbcon->helper.fb);
 
        drm_fb_helper_unregister_fbi(&fbcon->helper);
-       drm_fb_helper_release_fbi(&fbcon->helper);
        drm_fb_helper_fini(&fbcon->helper);
 
        if (nouveau_fb->nvbo) {
index eef22c6b9665ced6ef501c3abf91da93ece960da..ccb597eac53865287599d5eff2e39dd9563a6723 100644 (file)
@@ -41,13 +41,13 @@ nouveau_switcheroo_set_state(struct pci_dev *pdev,
                return;
 
        if (state == VGA_SWITCHEROO_ON) {
-               printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
+               pr_err("VGA switcheroo: switched nouveau on\n");
                dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
                nouveau_pmops_resume(&pdev->dev);
                drm_kms_helper_poll_enable(dev);
                dev->switch_power_state = DRM_SWITCH_POWER_ON;
        } else {
-               printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
+               pr_err("VGA switcheroo: switched nouveau off\n");
                dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
                drm_kms_helper_poll_disable(dev);
                nouveau_switcheroo_optimus_dsm();
index 0b4440ffbeae21a3d33e67ed1c727e00cf3884b3..16915c29ec52e7bbe27b8da38e1274771451be5e 100644 (file)
@@ -705,7 +705,7 @@ evo_wait(void *evoc, int nr)
                                break;
                ) < 0) {
                        mutex_unlock(&dmac->lock);
-                       printk(KERN_ERR "nouveau: evo channel stalled\n");
+                       pr_err("nouveau: evo channel stalled\n");
                        return NULL;
                }
 
@@ -723,18 +723,18 @@ evo_kick(u32 *push, void *evoc)
        mutex_unlock(&dmac->lock);
 }
 
-#define evo_mthd(p,m,s) do {                                                   \
-       const u32 _m = (m), _s = (s);                                          \
-       if (drm_debug & DRM_UT_KMS)                                            \
-               printk(KERN_ERR "%04x %d %s\n", _m, _s, __func__);             \
-       *((p)++) = ((_s << 18) | _m);                                          \
+#define evo_mthd(p, m, s) do {                                         \
+       const u32 _m = (m), _s = (s);                                   \
+       if (drm_debug & DRM_UT_KMS)                                     \
+               pr_err("%04x %d %s\n", _m, _s, __func__);               \
+       *((p)++) = ((_s << 18) | _m);                                   \
 } while(0)
 
-#define evo_data(p,d) do {                                                     \
-       const u32 _d = (d);                                                    \
-       if (drm_debug & DRM_UT_KMS)                                            \
-               printk(KERN_ERR "\t%08x\n", _d);                               \
-       *((p)++) = _d;                                                         \
+#define evo_data(p, d) do {                                            \
+       const u32 _d = (d);                                             \
+       if (drm_debug & DRM_UT_KMS)                                     \
+               pr_err("\t%08x\n", _d);                                 \
+       *((p)++) = _d;                                                  \
 } while(0)
 
 /******************************************************************************
@@ -831,7 +831,8 @@ nv50_wndw_atomic_check_release(struct nv50_wndw *wndw,
 static int
 nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw,
                               struct nv50_wndw_atom *asyw,
-                              struct nv50_head_atom *asyh)
+                              struct nv50_head_atom *asyh,
+                              u32 pflip_flags)
 {
        struct nouveau_framebuffer *fb = nouveau_framebuffer(asyw->state.fb);
        struct nouveau_drm *drm = nouveau_drm(wndw->plane.dev);
@@ -846,6 +847,9 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw,
        asyw->image.w = fb->base.width;
        asyw->image.h = fb->base.height;
        asyw->image.kind = (fb->nvbo->tile_flags & 0x0000ff00) >> 8;
+
+       asyw->interval = pflip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? 0 : 1;
+
        if (asyw->image.kind) {
                asyw->image.layout = 0;
                if (drm->client.device.info.chipset >= 0xc0)
@@ -883,6 +887,7 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
        struct nv50_head_atom *harm = NULL, *asyh = NULL;
        bool varm = false, asyv = false, asym = false;
        int ret;
+       u32 pflip_flags = 0;
 
        NV_ATOMIC(drm, "%s atomic_check\n", plane->name);
        if (asyw->state.crtc) {
@@ -891,6 +896,7 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
                        return PTR_ERR(asyh);
                asym = drm_atomic_crtc_needs_modeset(&asyh->state);
                asyv = asyh->state.active;
+               pflip_flags = asyh->state.pageflip_flags;
        }
 
        if (armw->state.crtc) {
@@ -907,7 +913,8 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
                        asyw->set.point = true;
 
                if (!varm || asym || armw->state.fb != asyw->state.fb) {
-                       ret = nv50_wndw_atomic_check_acquire(wndw, asyw, asyh);
+                       ret = nv50_wndw_atomic_check_acquire(
+                                       wndw, asyw, asyh, pflip_flags);
                        if (ret)
                                return ret;
                }
@@ -2219,77 +2226,6 @@ nv50_head_help = {
        .atomic_check = nv50_head_atomic_check,
 };
 
-/* This is identical to the version in the atomic helpers, except that
- * it supports non-vblanked ("async") page flips.
- */
-static int
-nv50_head_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
-                   struct drm_pending_vblank_event *event, u32 flags)
-{
-       struct drm_plane *plane = crtc->primary;
-       struct drm_atomic_state *state;
-       struct drm_plane_state *plane_state;
-       struct drm_crtc_state *crtc_state;
-       int ret = 0;
-
-       state = drm_atomic_state_alloc(plane->dev);
-       if (!state)
-               return -ENOMEM;
-
-       state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
-retry:
-       crtc_state = drm_atomic_get_crtc_state(state, crtc);
-       if (IS_ERR(crtc_state)) {
-               ret = PTR_ERR(crtc_state);
-               goto fail;
-       }
-       crtc_state->event = event;
-
-       plane_state = drm_atomic_get_plane_state(state, plane);
-       if (IS_ERR(plane_state)) {
-               ret = PTR_ERR(plane_state);
-               goto fail;
-       }
-
-       ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
-       if (ret != 0)
-               goto fail;
-       drm_atomic_set_fb_for_plane(plane_state, fb);
-
-       /* Make sure we don't accidentally do a full modeset. */
-       state->allow_modeset = false;
-       if (!crtc_state->active) {
-               DRM_DEBUG_ATOMIC("[CRTC:%d] disabled, rejecting legacy flip\n",
-                                crtc->base.id);
-               ret = -EINVAL;
-               goto fail;
-       }
-
-       if (flags & DRM_MODE_PAGE_FLIP_ASYNC)
-               nv50_wndw_atom(plane_state)->interval = 0;
-
-       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;
-}
-
 static int
 nv50_head_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
                    uint32_t size)
@@ -2384,7 +2320,7 @@ nv50_head_func = {
        .gamma_set = nv50_head_gamma_set,
        .destroy = nv50_head_destroy,
        .set_config = drm_atomic_helper_set_config,
-       .page_flip = nv50_head_page_flip,
+       .page_flip = drm_atomic_helper_page_flip,
        .set_property = drm_atomic_helper_crtc_set_property,
        .atomic_duplicate_state = nv50_head_atomic_duplicate_state,
        .atomic_destroy_state = nv50_head_atomic_destroy_state,
index fd19d652a7ab29a4b527d31f33ca866ce0977efb..5c7891234eea5b33971bd87600dbd45fb89dc303 100644 (file)
@@ -31,15 +31,15 @@ nvkm_mm_dump(struct nvkm_mm *mm, const char *header)
 {
        struct nvkm_mm_node *node;
 
-       printk(KERN_ERR "nvkm: %s\n", header);
-       printk(KERN_ERR "nvkm: node list:\n");
+       pr_err("nvkm: %s\n", header);
+       pr_err("nvkm: node list:\n");
        list_for_each_entry(node, &mm->nodes, nl_entry) {
-               printk(KERN_ERR "nvkm: \t%08x %08x %d\n",
+               pr_err("nvkm: \t%08x %08x %d\n",
                       node->offset, node->length, node->type);
        }
-       printk(KERN_ERR "nvkm: free list:\n");
+       pr_err("nvkm: free list:\n");
        list_for_each_entry(node, &mm->free, fl_entry) {
-               printk(KERN_ERR "nvkm: \t%08x %08x %d\n",
+               pr_err("nvkm: \t%08x %08x %d\n",
                       node->offset, node->length, node->type);
        }
 }
index f74615d005a8fe29dabda24c406389a832f0050f..5e51a5649efb8e0651116a8e98d262669d646f7e 100644 (file)
@@ -582,15 +582,14 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name)
 
        total_bytes = dsi->update_bytes;
 
-       printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
-                       "%u bytes, %u kbytes/sec\n",
-                       name,
-                       setup_us,
-                       trans_us,
-                       total_us,
-                       1000*1000 / total_us,
-                       total_bytes,
-                       total_bytes * 1000 / total_us);
+       pr_info("DSI(%s): %u us + %u us = %u us (%uHz), %u bytes, %u kbytes/sec\n",
+               name,
+               setup_us,
+               trans_us,
+               total_us,
+               1000 * 1000 / total_us,
+               total_bytes,
+               total_bytes * 1000 / total_us);
 }
 #else
 static inline void dsi_perf_mark_setup(struct platform_device *dsidev)
index 14887d5b02e51f22f1271970e7905937e91fe75b..4e72d2fefb4df01e2f76683571590e6f62925de2 100644 (file)
@@ -1254,8 +1254,7 @@ static int dss_bind(struct device *dev)
        dss.lcd_clk_source[1] = DSS_CLK_SRC_FCK;
 
        rev = dss_read_reg(DSS_REVISION);
-       printk(KERN_INFO "OMAP DSS rev %d.%d\n",
-                       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+       pr_info("OMAP DSS rev %d.%d\n", FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
 
        dss_runtime_put();
 
index 56493b290731ee0ee66fcff8d791153bccba3bd3..78f6fc75948b511da2dfc85a5966200caa679391 100644 (file)
 
 #ifdef DSS_SUBSYS_NAME
 #define DSSERR(format, ...) \
-       printk(KERN_ERR "omapdss " DSS_SUBSYS_NAME " error: " format, \
-       ## __VA_ARGS__)
+       pr_err("omapdss " DSS_SUBSYS_NAME " error: " format, ##__VA_ARGS__)
 #else
 #define DSSERR(format, ...) \
-       printk(KERN_ERR "omapdss error: " format, ## __VA_ARGS__)
+       pr_err("omapdss error: " format, ##__VA_ARGS__)
 #endif
 
 #ifdef DSS_SUBSYS_NAME
 #define DSSINFO(format, ...) \
-       printk(KERN_INFO "omapdss " DSS_SUBSYS_NAME ": " format, \
-       ## __VA_ARGS__)
+       pr_info("omapdss " DSS_SUBSYS_NAME ": " format, ##__VA_ARGS__)
 #else
 #define DSSINFO(format, ...) \
-       printk(KERN_INFO "omapdss: " format, ## __VA_ARGS__)
+       pr_info("omapdss: " format, ## __VA_ARGS__)
 #endif
 
 #ifdef DSS_SUBSYS_NAME
 #define DSSWARN(format, ...) \
-       printk(KERN_WARNING "omapdss " DSS_SUBSYS_NAME ": " format, \
-       ## __VA_ARGS__)
+       pr_warn("omapdss " DSS_SUBSYS_NAME ": " format, ##__VA_ARGS__)
 #else
 #define DSSWARN(format, ...) \
-       printk(KERN_WARNING "omapdss: " format, ## __VA_ARGS__)
+       pr_warn("omapdss: " format, ##__VA_ARGS__)
 #endif
 
 /* OMAP TRM gives bitfields as start:end, where start is the higher bit
index b68c70eb395f2dccf55e6f775738ea4be3c62690..2fe735c269fc1c66990f212cdcf990fcd395070c 100644 (file)
@@ -495,6 +495,8 @@ static const struct drm_crtc_funcs omap_crtc_funcs = {
        .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
        .atomic_set_property = omap_crtc_atomic_set_property,
        .atomic_get_property = omap_crtc_atomic_get_property,
+       .enable_vblank = omap_irq_enable_vblank,
+       .disable_vblank = omap_irq_disable_vblank,
 };
 
 static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = {
index 3f2554235225b5b5a37960d4e8511be1ff057e09..79a4aad35e0fd043008d7f346f8c46793532ca26 100644 (file)
@@ -727,9 +727,6 @@ static struct drm_driver omap_drm_driver = {
                DRIVER_ATOMIC,
        .open = dev_open,
        .lastclose = dev_lastclose,
-       .get_vblank_counter = drm_vblank_no_hw_counter,
-       .enable_vblank = omap_irq_enable_vblank,
-       .disable_vblank = omap_irq_disable_vblank,
 #ifdef CONFIG_DEBUG_FS
        .debugfs_init = omap_debugfs_init,
 #endif
index 65977982f15f88114f86ee4b7fc2b4bfe5faeb53..9098ea138269714b2415cc02188f6802ee9d21f3 100644 (file)
@@ -112,8 +112,8 @@ void omap_gem_describe_objects(struct list_head *list, struct seq_file *m);
 int omap_gem_resume(struct device *dev);
 #endif
 
-int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe);
-void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe);
+int omap_irq_enable_vblank(struct drm_crtc *crtc);
+void omap_irq_disable_vblank(struct drm_crtc *crtc);
 void omap_drm_irq_uninstall(struct drm_device *dev);
 int omap_drm_irq_install(struct drm_device *dev);
 
index 942c4d4830080c15e8a81f0d6b1133da62b219b5..4e89dd53786232aac36cc10b2fa6ea1006a09371 100644 (file)
@@ -222,9 +222,6 @@ fail_unlock:
 fail:
 
        if (ret) {
-
-               drm_fb_helper_release_fbi(helper);
-
                if (fb)
                        drm_framebuffer_remove(fb);
        }
@@ -301,7 +298,6 @@ void omap_fbdev_free(struct drm_device *dev)
        DBG();
 
        drm_fb_helper_unregister_fbi(helper);
-       drm_fb_helper_release_fbi(helper);
 
        drm_fb_helper_fini(helper);
 
index 5d5a9f517c30e0a6a0f17fb0d93fe19eae95bd28..68a75b829b71b4a183636cde81efe612968c762c 100644 (file)
@@ -1107,9 +1107,8 @@ static inline bool is_waiting(struct omap_gem_sync_waiter *waiter)
 
 /* macro for sync debug.. */
 #define SYNCDBG 0
-#define SYNC(fmt, ...) do { if (SYNCDBG) \
-               printk(KERN_ERR "%s:%d: "fmt"\n", \
-                               __func__, __LINE__, ##__VA_ARGS__); \
+#define SYNC(fmt, ...) do { if (SYNCDBG)                               \
+               pr_err("%s:%d: " fmt "\n", __func__, __LINE__, ##__VA_ARGS__); \
        } while (0)
 
 
index 9adfa7c99695f320e4bf8e0063e2605d2f0717c6..59f21add6f1924b505c2d90dab4a114acac94cec 100644 (file)
@@ -101,16 +101,17 @@ int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
  * Zero on success, appropriate errno if the given @crtc's vblank
  * interrupt cannot be enabled.
  */
-int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe)
+int omap_irq_enable_vblank(struct drm_crtc *crtc)
 {
+       struct drm_device *dev = crtc->dev;
        struct omap_drm_private *priv = dev->dev_private;
-       struct drm_crtc *crtc = priv->crtcs[pipe];
        unsigned long flags;
+       enum omap_channel channel = omap_crtc_channel(crtc);
 
-       DBG("dev=%p, crtc=%u", dev, pipe);
+       DBG("dev=%p, crtc=%u", dev, channel);
 
        spin_lock_irqsave(&priv->wait_lock, flags);
-       priv->irq_mask |= dispc_mgr_get_vsync_irq(omap_crtc_channel(crtc));
+       priv->irq_mask |= dispc_mgr_get_vsync_irq(channel);
        omap_irq_update(dev);
        spin_unlock_irqrestore(&priv->wait_lock, flags);
 
@@ -126,16 +127,17 @@ int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe)
  * a hardware vblank counter, this routine should be a no-op, since
  * interrupts will have to stay on to keep the count accurate.
  */
-void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe)
+void omap_irq_disable_vblank(struct drm_crtc *crtc)
 {
+       struct drm_device *dev = crtc->dev;
        struct omap_drm_private *priv = dev->dev_private;
-       struct drm_crtc *crtc = priv->crtcs[pipe];
        unsigned long flags;
+       enum omap_channel channel = omap_crtc_channel(crtc);
 
-       DBG("dev=%p, crtc=%u", dev, pipe);
+       DBG("dev=%p, crtc=%u", dev, channel);
 
        spin_lock_irqsave(&priv->wait_lock, flags);
-       priv->irq_mask &= ~dispc_mgr_get_vsync_irq(omap_crtc_channel(crtc));
+       priv->irq_mask &= ~dispc_mgr_get_vsync_irq(channel);
        omap_irq_update(dev);
        spin_unlock_irqrestore(&priv->wait_lock, flags);
 }
index d58751c94618a9209cda2198003ab7b4849b1b9d..8e6c7800322626c8eb7d71cbc1afc9140b418a11 100644 (file)
@@ -100,15 +100,6 @@ qxl_debugfs_init(struct drm_minor *minor)
        return 0;
 }
 
-void
-qxl_debugfs_takedown(struct drm_minor *minor)
-{
-#if defined(CONFIG_DEBUG_FS)
-       drm_debugfs_remove_files(qxl_debugfs_list, QXL_DEBUGFS_ENTRIES,
-                                minor);
-#endif
-}
-
 int qxl_debugfs_add_files(struct qxl_device *qdev,
                          struct drm_info_list *files,
                          unsigned nfiles)
index 1094cd33eb06e9d78009c4fc91c0423da6df1182..2cd14bebc49ca060fe35457d5bf3d591ae8bfad5 100644 (file)
@@ -30,6 +30,8 @@
 #include "qxl_object.h"
 #include "drm_crtc_helper.h"
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_atomic.h>
 
 static bool qxl_head_enabled(struct qxl_head *head)
 {
@@ -251,310 +253,38 @@ static int qxl_add_common_modes(struct drm_connector *connector,
        return i - 1;
 }
 
-static void qxl_crtc_destroy(struct drm_crtc *crtc)
-{
-       struct qxl_crtc *qxl_crtc = to_qxl_crtc(crtc);
-
-       drm_crtc_cleanup(crtc);
-       qxl_bo_unref(&qxl_crtc->cursor_bo);
-       kfree(qxl_crtc);
-}
-
-static int qxl_crtc_page_flip(struct drm_crtc *crtc,
-                              struct drm_framebuffer *fb,
-                              struct drm_pending_vblank_event *event,
-                              uint32_t page_flip_flags)
+static void qxl_crtc_atomic_flush(struct drm_crtc *crtc,
+                                 struct drm_crtc_state *old_crtc_state)
 {
        struct drm_device *dev = crtc->dev;
-       struct qxl_device *qdev = dev->dev_private;
-       struct qxl_framebuffer *qfb_src = to_qxl_framebuffer(fb);
-       struct qxl_framebuffer *qfb_old = to_qxl_framebuffer(crtc->primary->fb);
-       struct qxl_bo *bo_old = gem_to_qxl_bo(qfb_old->obj);
-       struct qxl_bo *bo = gem_to_qxl_bo(qfb_src->obj);
+       struct drm_pending_vblank_event *event;
        unsigned long flags;
-       struct drm_clip_rect norect = {
-           .x1 = 0,
-           .y1 = 0,
-           .x2 = fb->width,
-           .y2 = fb->height
-       };
-       int inc = 1;
-       int one_clip_rect = 1;
-       int ret = 0;
-
-       crtc->primary->fb = fb;
-       bo_old->is_primary = false;
-       bo->is_primary = true;
-
-       ret = qxl_bo_reserve(bo, false);
-       if (ret)
-               return ret;
-       ret = qxl_bo_pin(bo, bo->type, NULL);
-       qxl_bo_unreserve(bo);
-       if (ret)
-               return ret;
-
-       qxl_draw_dirty_fb(qdev, qfb_src, bo, 0, 0,
-                         &norect, one_clip_rect, inc);
 
-       drm_crtc_vblank_get(crtc);
+       if (crtc->state && crtc->state->event) {
+               event = crtc->state->event;
+               crtc->state->event = NULL;
 
-       if (event) {
                spin_lock_irqsave(&dev->event_lock, flags);
                drm_crtc_send_vblank_event(crtc, event);
                spin_unlock_irqrestore(&dev->event_lock, flags);
        }
-       drm_crtc_vblank_put(crtc);
-
-       ret = qxl_bo_reserve(bo, false);
-       if (!ret) {
-               qxl_bo_unpin(bo);
-               qxl_bo_unreserve(bo);
-       }
-
-       return 0;
-}
-
-static int
-qxl_hide_cursor(struct qxl_device *qdev)
-{
-       struct qxl_release *release;
-       struct qxl_cursor_cmd *cmd;
-       int ret;
-
-       ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), QXL_RELEASE_CURSOR_CMD,
-                                        &release, NULL);
-       if (ret)
-               return ret;
-
-       ret = qxl_release_reserve_list(release, true);
-       if (ret) {
-               qxl_release_free(qdev, release);
-               return ret;
-       }
-
-       cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
-       cmd->type = QXL_CURSOR_HIDE;
-       qxl_release_unmap(qdev, release, &cmd->release_info);
-
-       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
-       qxl_release_fence_buffer_objects(release);
-       return 0;
-}
-
-static int qxl_crtc_apply_cursor(struct drm_crtc *crtc)
-{
-       struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
-       struct drm_device *dev = crtc->dev;
-       struct qxl_device *qdev = dev->dev_private;
-       struct qxl_cursor_cmd *cmd;
-       struct qxl_release *release;
-       int ret = 0;
-
-       if (!qcrtc->cursor_bo)
-               return 0;
-
-       ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
-                                        QXL_RELEASE_CURSOR_CMD,
-                                        &release, NULL);
-       if (ret)
-               return ret;
-
-       ret = qxl_release_list_add(release, qcrtc->cursor_bo);
-       if (ret)
-               goto out_free_release;
-
-       ret = qxl_release_reserve_list(release, false);
-       if (ret)
-               goto out_free_release;
-
-       cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
-       cmd->type = QXL_CURSOR_SET;
-       cmd->u.set.position.x = qcrtc->cur_x + qcrtc->hot_spot_x;
-       cmd->u.set.position.y = qcrtc->cur_y + qcrtc->hot_spot_y;
-
-       cmd->u.set.shape = qxl_bo_physical_address(qdev, qcrtc->cursor_bo, 0);
-
-       cmd->u.set.visible = 1;
-       qxl_release_unmap(qdev, release, &cmd->release_info);
-
-       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
-       qxl_release_fence_buffer_objects(release);
-
-       return ret;
-
-out_free_release:
-       qxl_release_free(qdev, release);
-       return ret;
-}
-
-static int qxl_crtc_cursor_set2(struct drm_crtc *crtc,
-                               struct drm_file *file_priv,
-                               uint32_t handle,
-                               uint32_t width,
-                               uint32_t height, int32_t hot_x, int32_t hot_y)
-{
-       struct drm_device *dev = crtc->dev;
-       struct qxl_device *qdev = dev->dev_private;
-       struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
-       struct drm_gem_object *obj;
-       struct qxl_cursor *cursor;
-       struct qxl_cursor_cmd *cmd;
-       struct qxl_bo *cursor_bo, *user_bo;
-       struct qxl_release *release;
-       void *user_ptr;
-
-       int size = 64*64*4;
-       int ret = 0;
-       if (!handle)
-               return qxl_hide_cursor(qdev);
-
-       obj = drm_gem_object_lookup(file_priv, handle);
-       if (!obj) {
-               DRM_ERROR("cannot find cursor object\n");
-               return -ENOENT;
-       }
-
-       user_bo = gem_to_qxl_bo(obj);
-
-       ret = qxl_bo_reserve(user_bo, false);
-       if (ret)
-               goto out_unref;
-
-       ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL);
-       qxl_bo_unreserve(user_bo);
-       if (ret)
-               goto out_unref;
-
-       ret = qxl_bo_kmap(user_bo, &user_ptr);
-       if (ret)
-               goto out_unpin;
-
-       ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
-                                        QXL_RELEASE_CURSOR_CMD,
-                                        &release, NULL);
-       if (ret)
-               goto out_kunmap;
-
-       ret = qxl_alloc_bo_reserved(qdev, release, sizeof(struct qxl_cursor) + size,
-                          &cursor_bo);
-       if (ret)
-               goto out_free_release;
-
-       ret = qxl_release_reserve_list(release, false);
-       if (ret)
-               goto out_free_bo;
-
-       ret = qxl_bo_kmap(cursor_bo, (void **)&cursor);
-       if (ret)
-               goto out_backoff;
-
-       cursor->header.unique = 0;
-       cursor->header.type = SPICE_CURSOR_TYPE_ALPHA;
-       cursor->header.width = 64;
-       cursor->header.height = 64;
-       cursor->header.hot_spot_x = hot_x;
-       cursor->header.hot_spot_y = hot_y;
-       cursor->data_size = size;
-       cursor->chunk.next_chunk = 0;
-       cursor->chunk.prev_chunk = 0;
-       cursor->chunk.data_size = size;
-
-       memcpy(cursor->chunk.data, user_ptr, size);
-
-       qxl_bo_kunmap(cursor_bo);
-
-       qxl_bo_kunmap(user_bo);
-
-       qcrtc->cur_x += qcrtc->hot_spot_x - hot_x;
-       qcrtc->cur_y += qcrtc->hot_spot_y - hot_y;
-       qcrtc->hot_spot_x = hot_x;
-       qcrtc->hot_spot_y = hot_y;
-
-       cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
-       cmd->type = QXL_CURSOR_SET;
-       cmd->u.set.position.x = qcrtc->cur_x + qcrtc->hot_spot_x;
-       cmd->u.set.position.y = qcrtc->cur_y + qcrtc->hot_spot_y;
-
-       cmd->u.set.shape = qxl_bo_physical_address(qdev, cursor_bo, 0);
-
-       cmd->u.set.visible = 1;
-       qxl_release_unmap(qdev, release, &cmd->release_info);
-
-       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
-       qxl_release_fence_buffer_objects(release);
-
-       /* finish with the userspace bo */
-       ret = qxl_bo_reserve(user_bo, false);
-       if (!ret) {
-               qxl_bo_unpin(user_bo);
-               qxl_bo_unreserve(user_bo);
-       }
-       drm_gem_object_unreference_unlocked(obj);
-
-       qxl_bo_unref (&qcrtc->cursor_bo);
-       qcrtc->cursor_bo = cursor_bo;
-
-       return ret;
-
-out_backoff:
-       qxl_release_backoff_reserve_list(release);
-out_free_bo:
-       qxl_bo_unref(&cursor_bo);
-out_free_release:
-       qxl_release_free(qdev, release);
-out_kunmap:
-       qxl_bo_kunmap(user_bo);
-out_unpin:
-       qxl_bo_unpin(user_bo);
-out_unref:
-       drm_gem_object_unreference_unlocked(obj);
-       return ret;
 }
 
-static int qxl_crtc_cursor_move(struct drm_crtc *crtc,
-                               int x, int y)
+static void qxl_crtc_destroy(struct drm_crtc *crtc)
 {
-       struct drm_device *dev = crtc->dev;
-       struct qxl_device *qdev = dev->dev_private;
-       struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
-       struct qxl_release *release;
-       struct qxl_cursor_cmd *cmd;
-       int ret;
-
-       ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), QXL_RELEASE_CURSOR_CMD,
-                                  &release, NULL);
-       if (ret)
-               return ret;
-
-       ret = qxl_release_reserve_list(release, true);
-       if (ret) {
-               qxl_release_free(qdev, release);
-               return ret;
-       }
-
-       qcrtc->cur_x = x;
-       qcrtc->cur_y = y;
-
-       cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
-       cmd->type = QXL_CURSOR_MOVE;
-       cmd->u.position.x = qcrtc->cur_x + qcrtc->hot_spot_x;
-       cmd->u.position.y = qcrtc->cur_y + qcrtc->hot_spot_y;
-       qxl_release_unmap(qdev, release, &cmd->release_info);
-
-       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
-       qxl_release_fence_buffer_objects(release);
+       struct qxl_crtc *qxl_crtc = to_qxl_crtc(crtc);
 
-       return 0;
+       drm_crtc_cleanup(crtc);
+       kfree(qxl_crtc);
 }
 
-
 static const struct drm_crtc_funcs qxl_crtc_funcs = {
-       .cursor_set2 = qxl_crtc_cursor_set2,
-       .cursor_move = qxl_crtc_cursor_move,
-       .set_config = drm_crtc_helper_set_config,
+       .set_config = drm_atomic_helper_set_config,
        .destroy = qxl_crtc_destroy,
-       .page_flip = qxl_crtc_page_flip,
+       .page_flip = drm_atomic_helper_page_flip,
+       .reset = drm_atomic_helper_crtc_reset,
+       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 };
 
 void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
@@ -692,143 +422,408 @@ static void qxl_monitors_config_set(struct qxl_device *qdev,
 
 }
 
-static int qxl_crtc_mode_set(struct drm_crtc *crtc,
-                              struct drm_display_mode *mode,
-                              struct drm_display_mode *adjusted_mode,
-                              int x, int y,
-                              struct drm_framebuffer *old_fb)
+void qxl_mode_set_nofb(struct drm_crtc *crtc)
 {
-       struct drm_device *dev = crtc->dev;
-       struct qxl_device *qdev = dev->dev_private;
-       struct qxl_framebuffer *qfb;
-       struct qxl_bo *bo, *old_bo = NULL;
+       struct qxl_device *qdev = crtc->dev->dev_private;
        struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
-       bool recreate_primary = false;
-       int ret;
-       int surf_id;
-       if (!crtc->primary->fb) {
-               DRM_DEBUG_KMS("No FB bound\n");
+       struct drm_display_mode *mode = &crtc->mode;
+
+       DRM_DEBUG("Mode set (%d,%d)\n",
+                 mode->hdisplay, mode->vdisplay);
+
+       qxl_monitors_config_set(qdev, qcrtc->index, 0, 0,
+                               mode->hdisplay, mode->vdisplay, 0);
+
+}
+
+static void qxl_crtc_commit(struct drm_crtc *crtc)
+{
+       DRM_DEBUG("\n");
+}
+
+static void qxl_crtc_disable(struct drm_crtc *crtc)
+{
+       struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
+       struct qxl_device *qdev = crtc->dev->dev_private;
+
+       qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, 0, 0, 0);
+
+       qxl_send_monitors_config(qdev);
+}
+
+static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = {
+       .dpms = qxl_crtc_dpms,
+       .disable = qxl_crtc_disable,
+       .mode_fixup = qxl_crtc_mode_fixup,
+       .mode_set_nofb = qxl_mode_set_nofb,
+       .commit = qxl_crtc_commit,
+       .atomic_flush = qxl_crtc_atomic_flush,
+};
+
+int qxl_primary_atomic_check(struct drm_plane *plane,
+                            struct drm_plane_state *state)
+{
+       struct qxl_device *qdev = plane->dev->dev_private;
+       struct qxl_framebuffer *qfb;
+       struct qxl_bo *bo;
+
+       if (!state->crtc || !state->fb)
                return 0;
-       }
 
-       if (old_fb) {
-               qfb = to_qxl_framebuffer(old_fb);
-               old_bo = gem_to_qxl_bo(qfb->obj);
-       }
-       qfb = to_qxl_framebuffer(crtc->primary->fb);
+       qfb = to_qxl_framebuffer(state->fb);
        bo = gem_to_qxl_bo(qfb->obj);
-       DRM_DEBUG("+%d+%d (%d,%d) => (%d,%d)\n",
-                 x, y,
-                 mode->hdisplay, mode->vdisplay,
-                 adjusted_mode->hdisplay,
-                 adjusted_mode->vdisplay);
-
-       if (bo->is_primary == false)
-               recreate_primary = true;
 
        if (bo->surf.stride * bo->surf.height > qdev->vram_size) {
                DRM_ERROR("Mode doesn't fit in vram size (vgamem)");
                return -EINVAL;
-        }
-
-       ret = qxl_bo_reserve(bo, false);
-       if (ret != 0)
-               return ret;
-       ret = qxl_bo_pin(bo, bo->type, NULL);
-       if (ret != 0) {
-               qxl_bo_unreserve(bo);
-               return -EINVAL;
        }
-       qxl_bo_unreserve(bo);
-       if (recreate_primary) {
-               qxl_io_destroy_primary(qdev);
+
+       return 0;
+}
+
+static void qxl_primary_atomic_update(struct drm_plane *plane,
+                                     struct drm_plane_state *old_state)
+{
+       struct qxl_device *qdev = plane->dev->dev_private;
+       struct qxl_framebuffer *qfb =
+               to_qxl_framebuffer(plane->state->fb);
+       struct qxl_framebuffer *qfb_old;
+       struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj);
+       struct qxl_bo *bo_old;
+       struct drm_clip_rect norect = {
+           .x1 = 0,
+           .y1 = 0,
+           .x2 = qfb->base.width,
+           .y2 = qfb->base.height
+       };
+
+       if (!old_state->fb) {
                qxl_io_log(qdev,
-                          "recreate primary: %dx%d,%d,%d\n",
+                          "create primary fb: %dx%d,%d,%d\n",
                           bo->surf.width, bo->surf.height,
                           bo->surf.stride, bo->surf.format);
+
                qxl_io_create_primary(qdev, 0, bo);
                bo->is_primary = true;
+               return;
 
-               ret = qxl_crtc_apply_cursor(crtc);
-               if (ret) {
-                       DRM_ERROR("could not set cursor after modeset");
-                       ret = 0;
-               }
-       }
-
-       if (bo->is_primary) {
-               DRM_DEBUG_KMS("setting surface_id to 0 for primary surface %d on crtc %d\n", bo->surface_id, qcrtc->index);
-               surf_id = 0;
        } else {
-               surf_id = bo->surface_id;
+               qfb_old = to_qxl_framebuffer(old_state->fb);
+               bo_old = gem_to_qxl_bo(qfb_old->obj);
+               bo_old->is_primary = false;
        }
 
-       if (old_bo && old_bo != bo) {
-               old_bo->is_primary = false;
-               ret = qxl_bo_reserve(old_bo, false);
-               qxl_bo_unpin(old_bo);
-               qxl_bo_unreserve(old_bo);
+       bo->is_primary = true;
+       qxl_draw_dirty_fb(qdev, qfb, bo, 0, 0, &norect, 1, 1);
+}
+
+static void qxl_primary_atomic_disable(struct drm_plane *plane,
+                                      struct drm_plane_state *old_state)
+{
+       struct qxl_device *qdev = plane->dev->dev_private;
+
+       if (old_state->fb)
+       {       struct qxl_framebuffer *qfb =
+                       to_qxl_framebuffer(old_state->fb);
+               struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj);
+
+               qxl_io_destroy_primary(qdev);
+               bo->is_primary = false;
        }
+}
 
-       qxl_monitors_config_set(qdev, qcrtc->index, x, y,
-                               mode->hdisplay,
-                               mode->vdisplay, surf_id);
+int qxl_plane_atomic_check(struct drm_plane *plane,
+                          struct drm_plane_state *state)
+{
        return 0;
 }
 
-static void qxl_crtc_prepare(struct drm_crtc *crtc)
+static void qxl_cursor_atomic_update(struct drm_plane *plane,
+                                    struct drm_plane_state *old_state)
 {
-       DRM_DEBUG("current: %dx%d+%d+%d (%d).\n",
-                 crtc->mode.hdisplay, crtc->mode.vdisplay,
-                 crtc->x, crtc->y, crtc->enabled);
+       struct drm_device *dev = plane->dev;
+       struct qxl_device *qdev = dev->dev_private;
+       struct drm_framebuffer *fb = plane->state->fb;
+       struct qxl_release *release;
+       struct qxl_cursor_cmd *cmd;
+       struct qxl_cursor *cursor;
+       struct drm_gem_object *obj;
+       struct qxl_bo *cursor_bo, *user_bo = NULL;
+       int ret;
+       void *user_ptr;
+       int size = 64*64*4;
+
+       ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
+                                        QXL_RELEASE_CURSOR_CMD,
+                                        &release, NULL);
+
+       cmd = (struct qxl_cursor_cmd *) qxl_release_map(qdev, release);
+
+       if (fb != old_state->fb) {
+               obj = to_qxl_framebuffer(fb)->obj;
+               user_bo = gem_to_qxl_bo(obj);
+
+               /* pinning is done in the prepare/cleanup framevbuffer */
+               ret = qxl_bo_kmap(user_bo, &user_ptr);
+               if (ret)
+                       goto out_free_release;
+
+               ret = qxl_alloc_bo_reserved(qdev, release,
+                                           sizeof(struct qxl_cursor) + size,
+                                           &cursor_bo);
+               if (ret)
+                       goto out_kunmap;
+
+               ret = qxl_release_reserve_list(release, true);
+               if (ret)
+                       goto out_free_bo;
+
+               ret = qxl_bo_kmap(cursor_bo, (void **)&cursor);
+               if (ret)
+                       goto out_backoff;
+
+               cursor->header.unique = 0;
+               cursor->header.type = SPICE_CURSOR_TYPE_ALPHA;
+               cursor->header.width = 64;
+               cursor->header.height = 64;
+               cursor->header.hot_spot_x = fb->hot_x;
+               cursor->header.hot_spot_y = fb->hot_y;
+               cursor->data_size = size;
+               cursor->chunk.next_chunk = 0;
+               cursor->chunk.prev_chunk = 0;
+               cursor->chunk.data_size = size;
+               memcpy(cursor->chunk.data, user_ptr, size);
+               qxl_bo_kunmap(cursor_bo);
+               qxl_bo_kunmap(user_bo);
+
+               cmd->u.set.visible = 1;
+               cmd->u.set.shape = qxl_bo_physical_address(qdev,
+                                                          cursor_bo, 0);
+               cmd->type = QXL_CURSOR_SET;
+       } else {
+
+               ret = qxl_release_reserve_list(release, true);
+               if (ret)
+                       goto out_free_release;
+
+               cmd->type = QXL_CURSOR_MOVE;
+       }
+
+       cmd->u.position.x = plane->state->crtc_x + fb->hot_x;
+       cmd->u.position.y = plane->state->crtc_y + fb->hot_y;
+
+       qxl_release_unmap(qdev, release, &cmd->release_info);
+       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
+       qxl_release_fence_buffer_objects(release);
+
+       return;
+
+out_backoff:
+       qxl_release_backoff_reserve_list(release);
+out_free_bo:
+       qxl_bo_unref(&cursor_bo);
+out_kunmap:
+       qxl_bo_kunmap(user_bo);
+out_free_release:
+       qxl_release_free(qdev, release);
+       return;
+
 }
 
-static void qxl_crtc_commit(struct drm_crtc *crtc)
+void qxl_cursor_atomic_disable(struct drm_plane *plane,
+                              struct drm_plane_state *old_state)
 {
-       DRM_DEBUG("\n");
+       struct qxl_device *qdev = plane->dev->dev_private;
+       struct qxl_release *release;
+       struct qxl_cursor_cmd *cmd;
+       int ret;
+
+       ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd),
+                                        QXL_RELEASE_CURSOR_CMD,
+                                        &release, NULL);
+       if (ret)
+               return;
+
+       ret = qxl_release_reserve_list(release, true);
+       if (ret) {
+               qxl_release_free(qdev, release);
+               return;
+       }
+
+       cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
+       cmd->type = QXL_CURSOR_HIDE;
+       qxl_release_unmap(qdev, release, &cmd->release_info);
+
+       qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
+       qxl_release_fence_buffer_objects(release);
 }
 
-static void qxl_crtc_disable(struct drm_crtc *crtc)
+int qxl_plane_prepare_fb(struct drm_plane *plane,
+                        struct drm_plane_state *new_state)
 {
-       struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
-       struct drm_device *dev = crtc->dev;
-       struct qxl_device *qdev = dev->dev_private;
-       if (crtc->primary->fb) {
-               struct qxl_framebuffer *qfb = to_qxl_framebuffer(crtc->primary->fb);
-               struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj);
-               int ret;
-               ret = qxl_bo_reserve(bo, false);
-               qxl_bo_unpin(bo);
-               qxl_bo_unreserve(bo);
-               crtc->primary->fb = NULL;
-       }
+       struct drm_gem_object *obj;
+       struct qxl_bo *user_bo;
+       int ret;
 
-       qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, 0, 0, 0);
+       if (!new_state->fb)
+               return 0;
 
-       qxl_send_monitors_config(qdev);
+       obj = to_qxl_framebuffer(new_state->fb)->obj;
+       user_bo = gem_to_qxl_bo(obj);
+
+       ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL);
+       if (ret)
+               return ret;
+
+       return 0;
 }
 
-static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = {
-       .dpms = qxl_crtc_dpms,
-       .disable = qxl_crtc_disable,
-       .mode_fixup = qxl_crtc_mode_fixup,
-       .mode_set = qxl_crtc_mode_set,
-       .prepare = qxl_crtc_prepare,
-       .commit = qxl_crtc_commit,
+static void qxl_plane_cleanup_fb(struct drm_plane *plane,
+                                struct drm_plane_state *old_state)
+{
+       struct drm_gem_object *obj;
+       struct qxl_bo *user_bo;
+
+       if (!plane->state->fb) {
+               /* we never executed prepare_fb, so there's nothing to
+                * unpin.
+                */
+               return;
+       }
+
+       obj = to_qxl_framebuffer(plane->state->fb)->obj;
+       user_bo = gem_to_qxl_bo(obj);
+       qxl_bo_unpin(user_bo);
+}
+
+static const uint32_t qxl_cursor_plane_formats[] = {
+       DRM_FORMAT_ARGB8888,
 };
 
+static const struct drm_plane_helper_funcs qxl_cursor_helper_funcs = {
+       .atomic_check = qxl_plane_atomic_check,
+       .atomic_update = qxl_cursor_atomic_update,
+       .atomic_disable = qxl_cursor_atomic_disable,
+       .prepare_fb = qxl_plane_prepare_fb,
+       .cleanup_fb = qxl_plane_cleanup_fb,
+};
+
+static const struct drm_plane_funcs qxl_cursor_plane_funcs = {
+       .update_plane   = drm_atomic_helper_update_plane,
+       .disable_plane  = drm_atomic_helper_disable_plane,
+       .destroy        = drm_primary_helper_destroy,
+       .reset          = drm_atomic_helper_plane_reset,
+       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static const uint32_t qxl_primary_plane_formats[] = {
+       DRM_FORMAT_XRGB8888,
+       DRM_FORMAT_ARGB8888,
+};
+
+static const struct drm_plane_helper_funcs primary_helper_funcs = {
+       .atomic_check = qxl_primary_atomic_check,
+       .atomic_update = qxl_primary_atomic_update,
+       .atomic_disable = qxl_primary_atomic_disable,
+       .prepare_fb = qxl_plane_prepare_fb,
+       .cleanup_fb = qxl_plane_cleanup_fb,
+};
+
+static const struct drm_plane_funcs qxl_primary_plane_funcs = {
+       .update_plane   = drm_atomic_helper_update_plane,
+       .disable_plane  = drm_atomic_helper_disable_plane,
+       .destroy        = drm_primary_helper_destroy,
+       .reset          = drm_atomic_helper_plane_reset,
+       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static struct drm_plane *qxl_create_plane(struct qxl_device *qdev,
+                                         unsigned int possible_crtcs,
+                                         enum drm_plane_type type)
+{
+       const struct drm_plane_helper_funcs *helper_funcs = NULL;
+       struct drm_plane *plane;
+       const struct drm_plane_funcs *funcs;
+       const uint32_t *formats;
+       int num_formats;
+       int err;
+
+       if (type == DRM_PLANE_TYPE_PRIMARY) {
+               funcs = &qxl_primary_plane_funcs;
+               formats = qxl_primary_plane_formats;
+               num_formats = ARRAY_SIZE(qxl_primary_plane_formats);
+               helper_funcs = &primary_helper_funcs;
+       } else if (type == DRM_PLANE_TYPE_CURSOR) {
+               funcs = &qxl_cursor_plane_funcs;
+               formats = qxl_cursor_plane_formats;
+               helper_funcs = &qxl_cursor_helper_funcs;
+               num_formats = ARRAY_SIZE(qxl_cursor_plane_formats);
+       } else {
+               return ERR_PTR(-EINVAL);
+       }
+
+       plane = kzalloc(sizeof(*plane), GFP_KERNEL);
+       if (!plane)
+               return ERR_PTR(-ENOMEM);
+
+       err = drm_universal_plane_init(&qdev->ddev, plane, possible_crtcs,
+                                      funcs, formats, num_formats,
+                                      type, NULL);
+       if (err)
+               goto free_plane;
+
+       drm_plane_helper_add(plane, helper_funcs);
+
+       return plane;
+
+free_plane:
+       kfree(plane);
+       return ERR_PTR(-EINVAL);
+}
+
 static int qdev_crtc_init(struct drm_device *dev, int crtc_id)
 {
        struct qxl_crtc *qxl_crtc;
+       struct drm_plane *primary, *cursor;
+       struct qxl_device *qdev = dev->dev_private;
+       int r;
 
        qxl_crtc = kzalloc(sizeof(struct qxl_crtc), GFP_KERNEL);
        if (!qxl_crtc)
                return -ENOMEM;
 
-       drm_crtc_init(dev, &qxl_crtc->base, &qxl_crtc_funcs);
+       primary = qxl_create_plane(qdev, 1 << crtc_id, DRM_PLANE_TYPE_PRIMARY);
+       if (IS_ERR(primary)) {
+               r = -ENOMEM;
+               goto free_mem;
+       }
+
+       cursor = qxl_create_plane(qdev, 1 << crtc_id, DRM_PLANE_TYPE_CURSOR);
+       if (IS_ERR(cursor)) {
+               r = -ENOMEM;
+               goto clean_primary;
+       }
+
+       r = drm_crtc_init_with_planes(dev, &qxl_crtc->base, primary, cursor,
+                                     &qxl_crtc_funcs, NULL);
+       if (r)
+               goto clean_cursor;
+
        qxl_crtc->index = crtc_id;
        drm_crtc_helper_add(&qxl_crtc->base, &qxl_crtc_helper_funcs);
        return 0;
+
+clean_cursor:
+       drm_plane_cleanup(cursor);
+       kfree(cursor);
+clean_primary:
+       drm_plane_cleanup(primary);
+       kfree(primary);
+free_mem:
+       kfree(qxl_crtc);
+       return r;
 }
 
 static void qxl_enc_dpms(struct drm_encoder *encoder, int mode)
@@ -1019,6 +1014,9 @@ static const struct drm_connector_funcs qxl_connector_funcs = {
        .fill_modes = drm_helper_probe_single_connector_modes,
        .set_property = qxl_conn_set_property,
        .destroy = qxl_conn_destroy,
+       .reset = drm_atomic_helper_connector_reset,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
 static void qxl_enc_destroy(struct drm_encoder *encoder)
@@ -1109,6 +1107,8 @@ qxl_user_framebuffer_create(struct drm_device *dev,
 
 static const struct drm_mode_config_funcs qxl_mode_funcs = {
        .fb_create = qxl_user_framebuffer_create,
+       .atomic_check = drm_atomic_helper_check,
+       .atomic_commit = drm_atomic_helper_commit,
 };
 
 int qxl_create_monitors_object(struct qxl_device *qdev)
@@ -1128,17 +1128,9 @@ int qxl_create_monitors_object(struct qxl_device *qdev)
        }
        qdev->monitors_config_bo = gem_to_qxl_bo(gobj);
 
-       ret = qxl_bo_reserve(qdev->monitors_config_bo, false);
-       if (ret)
-               return ret;
-
        ret = qxl_bo_pin(qdev->monitors_config_bo, QXL_GEM_DOMAIN_VRAM, NULL);
-       if (ret) {
-               qxl_bo_unreserve(qdev->monitors_config_bo);
+       if (ret)
                return ret;
-       }
-
-       qxl_bo_unreserve(qdev->monitors_config_bo);
 
        qxl_bo_kmap(qdev->monitors_config_bo, NULL);
 
@@ -1159,13 +1151,10 @@ int qxl_destroy_monitors_object(struct qxl_device *qdev)
        qdev->ram_header->monitors_config = 0;
 
        qxl_bo_kunmap(qdev->monitors_config_bo);
-       ret = qxl_bo_reserve(qdev->monitors_config_bo, false);
+       ret = qxl_bo_unpin(qdev->monitors_config_bo);
        if (ret)
                return ret;
 
-       qxl_bo_unpin(qdev->monitors_config_bo);
-       qxl_bo_unreserve(qdev->monitors_config_bo);
-
        qxl_bo_unref(&qdev->monitors_config_bo);
        return 0;
 }
@@ -1184,8 +1173,8 @@ int qxl_modeset_init(struct qxl_device *qdev)
        qdev->ddev.mode_config.funcs = (void *)&qxl_mode_funcs;
 
        /* modes will be validated against the framebuffer size */
-       qdev->ddev.mode_config.min_width = 320;
-       qdev->ddev.mode_config.min_height = 200;
+       qdev->ddev.mode_config.min_width = 0;
+       qdev->ddev.mode_config.min_height = 0;
        qdev->ddev.mode_config.max_width = 8192;
        qdev->ddev.mode_config.max_height = 8192;
 
@@ -1201,6 +1190,8 @@ int qxl_modeset_init(struct qxl_device *qdev)
 
        qdev->mode_info.mode_config_initialized = true;
 
+       drm_mode_config_reset(&qdev->ddev);
+
        /* primary surface must be created by this point, to allow
         * issuing command queue commands and having them read by
         * spice server. */
index 8e17c241e63c7681e5ab4b31f43c3c47e7f8c35c..abf7b8360361b854764c9d679163c971ec4ed05c 100644 (file)
@@ -79,17 +79,13 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (ret)
                goto free_dev;
 
-       ret = qxl_device_init(qdev, &qxl_driver, pdev, ent->driver_data);
+       ret = qxl_device_init(qdev, &qxl_driver, pdev);
        if (ret)
                goto disable_pci;
 
-       ret = drm_vblank_init(&qdev->ddev, 1);
-       if (ret)
-               goto unload;
-
        ret = qxl_modeset_init(qdev);
        if (ret)
-               goto vblank_cleanup;
+               goto unload;
 
        drm_kms_helper_poll_init(&qdev->ddev);
 
@@ -102,8 +98,6 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 modeset_cleanup:
        qxl_modeset_fini(qdev);
-vblank_cleanup:
-       drm_vblank_cleanup(&qdev->ddev);
 unload:
        qxl_device_fini(qdev);
 disable_pci:
@@ -247,21 +241,6 @@ static int qxl_pm_restore(struct device *dev)
        return qxl_drm_resume(drm_dev, false);
 }
 
-static u32 qxl_noop_get_vblank_counter(struct drm_device *dev,
-                                      unsigned int pipe)
-{
-       return 0;
-}
-
-static int qxl_noop_enable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-       return 0;
-}
-
-static void qxl_noop_disable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-}
-
 static const struct dev_pm_ops qxl_pm_ops = {
        .suspend = qxl_pm_suspend,
        .resume = qxl_pm_resume,
@@ -280,10 +259,8 @@ static struct pci_driver qxl_pci_driver = {
 
 static struct drm_driver qxl_driver = {
        .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
-                          DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
-       .get_vblank_counter = qxl_noop_get_vblank_counter,
-       .enable_vblank = qxl_noop_enable_vblank,
-       .disable_vblank = qxl_noop_disable_vblank,
+                          DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
+                          DRIVER_ATOMIC,
 
        .set_busid = drm_pci_set_busid,
 
@@ -292,7 +269,6 @@ static struct drm_driver qxl_driver = {
        .dumb_destroy = drm_gem_dumb_destroy,
 #if defined(CONFIG_DEBUG_FS)
        .debugfs_init = qxl_debugfs_init,
-       .debugfs_cleanup = qxl_debugfs_takedown,
 #endif
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
index 785c17b56f739c0e3ee5c39a941315cd04d22c56..c0481706e4b02a5580d2cc6515eaa7a2133d5479 100644 (file)
@@ -134,11 +134,6 @@ struct qxl_bo_list {
 struct qxl_crtc {
        struct drm_crtc base;
        int index;
-       int cur_x;
-       int cur_y;
-       int hot_spot_x;
-       int hot_spot_y;
-       struct qxl_bo *cursor_bo;
 };
 
 struct qxl_output {
@@ -243,7 +238,6 @@ struct qxl_device;
 
 struct qxl_device {
        struct drm_device ddev;
-       unsigned long flags;
 
        resource_size_t vram_base, vram_size;
        resource_size_t surfaceram_base, surfaceram_size;
@@ -335,7 +329,7 @@ extern const struct drm_ioctl_desc qxl_ioctls[];
 extern int qxl_max_ioctl;
 
 int qxl_device_init(struct qxl_device *qdev, struct drm_driver *drv,
-                   struct pci_dev *pdev, unsigned long flags);
+                   struct pci_dev *pdev);
 void qxl_device_fini(struct qxl_device *qdev);
 
 int qxl_modeset_init(struct qxl_device *qdev);
@@ -529,7 +523,6 @@ int qxl_garbage_collect(struct qxl_device *qdev);
 /* debugfs */
 
 int qxl_debugfs_init(struct drm_minor *minor);
-void qxl_debugfs_takedown(struct drm_minor *minor);
 int qxl_ttm_debugfs_init(struct qxl_device *qdev);
 
 /* qxl_prime.c */
index d479b7a7abe41aa9e1d0b7f4f2d4f2963bc6e73a..35124737666ef284863a9fbd4ccd06761b906f55 100644 (file)
@@ -90,14 +90,10 @@ static struct fb_ops qxlfb_ops = {
 static void qxlfb_destroy_pinned_object(struct drm_gem_object *gobj)
 {
        struct qxl_bo *qbo = gem_to_qxl_bo(gobj);
-       int ret;
 
-       ret = qxl_bo_reserve(qbo, false);
-       if (likely(ret == 0)) {
-               qxl_bo_kunmap(qbo);
-               qxl_bo_unpin(qbo);
-               qxl_bo_unreserve(qbo);
-       }
+       qxl_bo_kunmap(qbo);
+       qxl_bo_unpin(qbo);
+
        drm_gem_object_unreference_unlocked(gobj);
 }
 
@@ -148,16 +144,13 @@ static int qxlfb_create_pinned_object(struct qxl_fbdev *qfbdev,
        qbo->surf.height = mode_cmd->height;
        qbo->surf.stride = mode_cmd->pitches[0];
        qbo->surf.format = SPICE_SURFACE_FMT_32_xRGB;
-       ret = qxl_bo_reserve(qbo, false);
-       if (unlikely(ret != 0))
-               goto out_unref;
+
        ret = qxl_bo_pin(qbo, QXL_GEM_DOMAIN_SURFACE, NULL);
        if (ret) {
-               qxl_bo_unreserve(qbo);
                goto out_unref;
        }
        ret = qxl_bo_kmap(qbo, NULL);
-       qxl_bo_unreserve(qbo); /* unreserve, will be mmaped */
+
        if (ret)
                goto out_unref;
 
@@ -305,7 +298,7 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
 
        if (info->screen_base == NULL) {
                ret = -ENOSPC;
-               goto out_destroy_fbi;
+               goto out_unref;
        }
 
 #ifdef CONFIG_DRM_FBDEV_EMULATION
@@ -320,16 +313,10 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
                 fb->format->depth, fb->pitches[0], fb->width, fb->height);
        return 0;
 
-out_destroy_fbi:
-       drm_fb_helper_release_fbi(&qfbdev->helper);
 out_unref:
        if (qbo) {
-               ret = qxl_bo_reserve(qbo, false);
-               if (likely(ret == 0)) {
-                       qxl_bo_kunmap(qbo);
-                       qxl_bo_unpin(qbo);
-                       qxl_bo_unreserve(qbo);
-               }
+               qxl_bo_kunmap(qbo);
+               qxl_bo_unpin(qbo);
        }
        if (fb && ret) {
                drm_gem_object_unreference_unlocked(gobj);
@@ -363,7 +350,6 @@ static int qxl_fbdev_destroy(struct drm_device *dev, struct qxl_fbdev *qfbdev)
        struct qxl_framebuffer *qfb = &qfbdev->qfb;
 
        drm_fb_helper_unregister_fbi(&qfbdev->helper);
-       drm_fb_helper_release_fbi(&qfbdev->helper);
 
        if (qfb->obj) {
                qxlfb_destroy_pinned_object(qfb->obj);
index 2dcd5c14cb568c1b37fcb9ea4620ff0ea6e5e1ae..2b1e1f3c825d8ada53b60989063ee695a6c2ce7b 100644 (file)
@@ -117,8 +117,7 @@ static void qxl_gc_work(struct work_struct *work)
 
 int qxl_device_init(struct qxl_device *qdev,
                    struct drm_driver *drv,
-                   struct pci_dev *pdev,
-                   unsigned long flags)
+                   struct pci_dev *pdev)
 {
        int r, sb;
 
@@ -130,8 +129,6 @@ int qxl_device_init(struct qxl_device *qdev,
        pci_set_drvdata(pdev, &qdev->ddev);
        qdev->ddev.dev_private = qdev;
 
-       qdev->flags = flags;
-
        mutex_init(&qdev->gem.mutex);
        mutex_init(&qdev->update_area_mutex);
        mutex_init(&qdev->release_mutex);
index dbc13510a1f8cf62c74a35a465ee7a89216dc2bc..9a7eef7dd604e07d620c2b4435607e319d8f0f68 100644 (file)
@@ -221,7 +221,7 @@ struct qxl_bo *qxl_bo_ref(struct qxl_bo *bo)
        return bo;
 }
 
-int qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr)
+int __qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr)
 {
        struct drm_device *ddev = bo->gem_base.dev;
        int r;
@@ -244,7 +244,7 @@ int qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr)
        return r;
 }
 
-int qxl_bo_unpin(struct qxl_bo *bo)
+int __qxl_bo_unpin(struct qxl_bo *bo)
 {
        struct drm_device *ddev = bo->gem_base.dev;
        int r, i;
@@ -264,6 +264,43 @@ int qxl_bo_unpin(struct qxl_bo *bo)
        return r;
 }
 
+
+/*
+ * Reserve the BO before pinning the object.  If the BO was reserved
+ * beforehand, use the internal version directly __qxl_bo_pin.
+ *
+ */
+int qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr)
+{
+       int r;
+
+       r = qxl_bo_reserve(bo, false);
+       if (r)
+               return r;
+
+       r = __qxl_bo_pin(bo, bo->type, NULL);
+       qxl_bo_unreserve(bo);
+       return r;
+}
+
+/*
+ * Reserve the BO before pinning the object.  If the BO was reserved
+ * beforehand, use the internal version directly __qxl_bo_unpin.
+ *
+ */
+int qxl_bo_unpin(struct qxl_bo *bo)
+{
+       int r;
+
+       r = qxl_bo_reserve(bo, false);
+       if (r)
+               return r;
+
+       r = __qxl_bo_unpin(bo);
+       qxl_bo_unreserve(bo);
+       return r;
+}
+
 void qxl_bo_force_delete(struct qxl_device *qdev)
 {
        struct qxl_bo *bo, *n;
index 14fd83b5f497468a8764cedc4dcc98ae17b799b6..c9890afe69d6b0376c686c2442045b91c657f6a3 100644 (file)
@@ -149,20 +149,19 @@ static int r128_cce_load_microcode(drm_r128_private_t *dev_priv)
 
        pdev = platform_device_register_simple("r128_cce", 0, NULL, 0);
        if (IS_ERR(pdev)) {
-               printk(KERN_ERR "r128_cce: Failed to register firmware\n");
+               pr_err("r128_cce: Failed to register firmware\n");
                return PTR_ERR(pdev);
        }
        rc = request_firmware(&fw, FIRMWARE_NAME, &pdev->dev);
        platform_device_unregister(pdev);
        if (rc) {
-               printk(KERN_ERR "r128_cce: Failed to load firmware \"%s\"\n",
+               pr_err("r128_cce: Failed to load firmware \"%s\"\n",
                       FIRMWARE_NAME);
                return rc;
        }
 
        if (fw->size != 256 * 8) {
-               printk(KERN_ERR
-                      "r128_cce: Bogus length %zu in firmware \"%s\"\n",
+               pr_err("r128_cce: Bogus length %zu in firmware \"%s\"\n",
                       fw->size, FIRMWARE_NAME);
                rc = -EINVAL;
                goto out_release;
index 2be4fe9c7217f2730dca89e8be9cb41b0e1b7c08..8d28fe6a280a0a016b4fc43b85a9e134368ca836 100644 (file)
@@ -242,7 +242,7 @@ static int radeonfb_create(struct drm_fb_helper *helper,
        info = drm_fb_helper_alloc_fbi(helper);
        if (IS_ERR(info)) {
                ret = PTR_ERR(info);
-               goto out_unref;
+               goto out;
        }
 
        info->par = rfbdev;
@@ -251,7 +251,7 @@ static int radeonfb_create(struct drm_fb_helper *helper,
        ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
        if (ret) {
                DRM_ERROR("failed to initialize framebuffer %d\n", ret);
-               goto out_destroy_fbi;
+               goto out;
        }
 
        fb = &rfbdev->rfb.base;
@@ -284,7 +284,7 @@ static int radeonfb_create(struct drm_fb_helper *helper,
 
        if (info->screen_base == NULL) {
                ret = -ENOSPC;
-               goto out_destroy_fbi;
+               goto out;
        }
 
        DRM_INFO("fb mappable at 0x%lX\n",  info->fix.smem_start);
@@ -296,9 +296,7 @@ static int radeonfb_create(struct drm_fb_helper *helper,
        vga_switcheroo_client_fb_set(rdev->ddev->pdev, info);
        return 0;
 
-out_destroy_fbi:
-       drm_fb_helper_release_fbi(helper);
-out_unref:
+out:
        if (rbo) {
 
        }
@@ -322,7 +320,6 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb
        struct radeon_framebuffer *rfb = &rfbdev->rfb;
 
        drm_fb_helper_unregister_fbi(&rfbdev->helper);
-       drm_fb_helper_release_fbi(&rfbdev->helper);
 
        if (rfb->obj) {
                radeonfb_destroy_pinned_object(rfb->obj);
index a2ec6d8796a094e73bb888be55f08a9d9daf3532..edcbe2e3625df312385989369a0366c99fe499ba 100644 (file)
@@ -529,6 +529,23 @@ static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
        .atomic_flush = rcar_du_crtc_atomic_flush,
 };
 
+static int rcar_du_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+       struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
+
+       rcar_du_crtc_write(rcrtc, DSRCR, DSRCR_VBCL);
+       rcar_du_crtc_set(rcrtc, DIER, DIER_VBE);
+
+       return 0;
+}
+
+static void rcar_du_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+       struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
+
+       rcar_du_crtc_clr(rcrtc, DIER, DIER_VBE);
+}
+
 static const struct drm_crtc_funcs crtc_funcs = {
        .reset = drm_atomic_helper_crtc_reset,
        .destroy = drm_crtc_cleanup,
@@ -536,6 +553,8 @@ static const struct drm_crtc_funcs crtc_funcs = {
        .page_flip = drm_atomic_helper_page_flip,
        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+       .enable_vblank = rcar_du_crtc_enable_vblank,
+       .disable_vblank = rcar_du_crtc_disable_vblank,
 };
 
 /* -----------------------------------------------------------------------------
@@ -650,13 +669,3 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
 
        return 0;
 }
-
-void rcar_du_crtc_enable_vblank(struct rcar_du_crtc *rcrtc, bool enable)
-{
-       if (enable) {
-               rcar_du_crtc_write(rcrtc, DSRCR, DSRCR_VBCL);
-               rcar_du_crtc_set(rcrtc, DIER, DIER_VBE);
-       } else {
-               rcar_du_crtc_clr(rcrtc, DIER, DIER_VBE);
-       }
-}
index 6f08b7e7db06708cfa910fd7655d3d52ee3f78b7..a7194812997ed16f1a0040403eb1da31451daf6e 100644 (file)
@@ -66,7 +66,6 @@ enum rcar_du_output {
 };
 
 int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index);
-void rcar_du_crtc_enable_vblank(struct rcar_du_crtc *rcrtc, bool enable);
 void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc);
 void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc);
 
index c05e0087277871ffcc6d86db72055966e0ff9eaf..192346d4fb34a7eec178e20bf69d83561638248b 100644 (file)
@@ -26,7 +26,6 @@
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 
-#include "rcar_du_crtc.h"
 #include "rcar_du_drv.h"
 #include "rcar_du_kms.h"
 #include "rcar_du_regs.h"
@@ -227,22 +226,6 @@ static void rcar_du_lastclose(struct drm_device *dev)
        drm_fbdev_cma_restore_mode(rcdu->fbdev);
 }
 
-static int rcar_du_enable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-       struct rcar_du_device *rcdu = dev->dev_private;
-
-       rcar_du_crtc_enable_vblank(&rcdu->crtcs[pipe], true);
-
-       return 0;
-}
-
-static void rcar_du_disable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-       struct rcar_du_device *rcdu = dev->dev_private;
-
-       rcar_du_crtc_enable_vblank(&rcdu->crtcs[pipe], false);
-}
-
 static const struct file_operations rcar_du_fops = {
        .owner          = THIS_MODULE,
        .open           = drm_open,
@@ -259,9 +242,6 @@ static struct drm_driver rcar_du_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME
                                | DRIVER_ATOMIC,
        .lastclose              = rcar_du_lastclose,
-       .get_vblank_counter     = drm_vblank_no_hw_counter,
-       .enable_vblank          = rcar_du_enable_vblank,
-       .disable_vblank         = rcar_du_disable_vblank,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_vm_ops             = &drm_gem_cma_vm_ops,
        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
index d9aa382bb62993cca297a1824b9072bf3358497e..f84f9ae2fd35047a9b17fd6a38b1853e70e7b68d 100644 (file)
@@ -12,7 +12,9 @@
 #include <linux/math64.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
+#include <linux/reset.h>
 #include <linux/mfd/syscon.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 
 #define DRIVER_NAME    "dw-mipi-dsi"
 
-#define GRF_SOC_CON6                    0x025c
-#define DSI0_SEL_VOP_LIT                (1 << 6)
-#define DSI1_SEL_VOP_LIT                (1 << 9)
+#define RK3288_GRF_SOC_CON6            0x025c
+#define RK3288_DSI0_SEL_VOP_LIT                BIT(6)
+#define RK3288_DSI1_SEL_VOP_LIT                BIT(9)
+
+#define RK3399_GRF_SOC_CON19           0x6250
+#define RK3399_DSI0_SEL_VOP_LIT                BIT(0)
+#define RK3399_DSI1_SEL_VOP_LIT                BIT(4)
+
+/* disable turnrequest, turndisable, forcetxstopmode, forcerxmode */
+#define RK3399_GRF_SOC_CON22           0x6258
+#define RK3399_GRF_DSI_MODE            0xffff0000
 
 #define DSI_VERSION                    0x00
 #define DSI_PWR_UP                     0x04
@@ -82,7 +92,9 @@
 #define FRAME_BTA_ACK                  BIT(14)
 #define ENABLE_LOW_POWER               (0x3f << 8)
 #define ENABLE_LOW_POWER_MASK          (0x3f << 8)
-#define VID_MODE_TYPE_BURST_SYNC_PULSES                0x2
+#define VID_MODE_TYPE_NON_BURST_SYNC_PULSES    0x0
+#define VID_MODE_TYPE_NON_BURST_SYNC_EVENTS    0x1
+#define VID_MODE_TYPE_BURST                    0x2
 #define VID_MODE_TYPE_MASK                     0x3
 
 #define DSI_VID_PKT_SIZE               0x3c
 #define LPRX_TO_CNT(p)                 ((p) & 0xffff)
 
 #define DSI_BTA_TO_CNT                 0x8c
-
 #define DSI_LPCLK_CTRL                 0x94
 #define AUTO_CLKLANE_CTRL              BIT(1)
 #define PHY_TXREQUESTCLKHS             BIT(0)
 
 #define HSFREQRANGE_SEL(val)   (((val) & 0x3f) << 1)
 
-#define INPUT_DIVIDER(val)     ((val - 1) & 0x7f)
+#define INPUT_DIVIDER(val)     (((val) - 1) & 0x7f)
 #define LOW_PROGRAM_EN         0
 #define HIGH_PROGRAM_EN                BIT(7)
-#define LOOP_DIV_LOW_SEL(val)  ((val - 1) & 0x1f)
-#define LOOP_DIV_HIGH_SEL(val) (((val - 1) >> 5) & 0x1f)
+#define LOOP_DIV_LOW_SEL(val)  (((val) - 1) & 0x1f)
+#define LOOP_DIV_HIGH_SEL(val) ((((val) - 1) >> 5) & 0x1f)
 #define PLL_LOOP_DIV_EN                BIT(5)
 #define PLL_INPUT_DIV_EN       BIT(4)
 
@@ -263,9 +274,12 @@ enum {
 };
 
 struct dw_mipi_dsi_plat_data {
+       u32 dsi0_en_bit;
+       u32 dsi1_en_bit;
+       u32 grf_switch_reg;
+       u32 grf_dsi0_mode;
+       u32 grf_dsi0_mode_reg;
        unsigned int max_data_lanes;
-       enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
-                                          struct drm_display_mode *mode);
 };
 
 struct dw_mipi_dsi {
@@ -279,14 +293,16 @@ struct dw_mipi_dsi {
 
        struct clk *pllref_clk;
        struct clk *pclk;
+       struct clk *phy_cfg_clk;
 
+       int dpms_mode;
        unsigned int lane_mbps; /* per lane */
        u32 channel;
        u32 lanes;
        u32 format;
        u16 input_div;
        u16 feedback_div;
-       struct drm_display_mode *mode;
+       unsigned long mode_flags;
 
        const struct dw_mipi_dsi_plat_data *pdata;
 };
@@ -330,11 +346,11 @@ static int max_mbps_to_testdin(unsigned int max_mbps)
  * The controller should generate 2 frames before
  * preparing the peripheral.
  */
-static void dw_mipi_dsi_wait_for_two_frames(struct dw_mipi_dsi *dsi)
+static void dw_mipi_dsi_wait_for_two_frames(struct drm_display_mode *mode)
 {
        int refresh, two_frames;
 
-       refresh = drm_mode_vrefresh(dsi->mode);
+       refresh = drm_mode_vrefresh(mode);
        two_frames = DIV_ROUND_UP(MSEC_PER_SEC, refresh) * 2;
        msleep(two_frames);
 }
@@ -353,6 +369,7 @@ static inline struct dw_mipi_dsi *encoder_to_dsi(struct drm_encoder *encoder)
 {
        return container_of(encoder, struct dw_mipi_dsi, encoder);
 }
+
 static inline void dsi_write(struct dw_mipi_dsi *dsi, u32 reg, u32 val)
 {
        writel(val, dsi->base + reg);
@@ -364,7 +381,7 @@ static inline u32 dsi_read(struct dw_mipi_dsi *dsi, u32 reg)
 }
 
 static void dw_mipi_dsi_phy_write(struct dw_mipi_dsi *dsi, u8 test_code,
-                                u8 test_data)
+                                 u8 test_data)
 {
        /*
         * With the falling edge on TESTCLK, the TESTDIN[7:0] signal content
@@ -384,6 +401,22 @@ static void dw_mipi_dsi_phy_write(struct dw_mipi_dsi *dsi, u8 test_code,
        dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR);
 }
 
+/**
+ * ns2bc - Nanoseconds to byte clock cycles
+ */
+static inline unsigned int ns2bc(struct dw_mipi_dsi *dsi, int ns)
+{
+       return DIV_ROUND_UP(ns * dsi->lane_mbps / 8, 1000);
+}
+
+/**
+ * ns2ui - Nanoseconds to UI time periods
+ */
+static inline unsigned int ns2ui(struct dw_mipi_dsi *dsi, int ns)
+{
+       return DIV_ROUND_UP(ns * dsi->lane_mbps, 1000);
+}
+
 static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
 {
        int ret, testdin, vco, val;
@@ -398,7 +431,16 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
                return testdin;
        }
 
-       dsi_write(dsi, DSI_PWR_UP, POWERUP);
+       /* Start by clearing PHY state */
+       dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLR);
+       dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLR);
+       dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLR);
+
+       ret = clk_prepare_enable(dsi->phy_cfg_clk);
+       if (ret) {
+               dev_err(dsi->dev, "Failed to enable phy_cfg_clk\n");
+               return ret;
+       }
 
        dw_mipi_dsi_phy_write(dsi, 0x10, BYPASS_VCO_RANGE |
                                         VCO_RANGE_CON_SEL(vco) |
@@ -411,12 +453,17 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
 
        dw_mipi_dsi_phy_write(dsi, 0x44, HSFREQRANGE_SEL(testdin));
 
-       dw_mipi_dsi_phy_write(dsi, 0x19, PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN);
        dw_mipi_dsi_phy_write(dsi, 0x17, INPUT_DIVIDER(dsi->input_div));
        dw_mipi_dsi_phy_write(dsi, 0x18, LOOP_DIV_LOW_SEL(dsi->feedback_div) |
                                         LOW_PROGRAM_EN);
        dw_mipi_dsi_phy_write(dsi, 0x18, LOOP_DIV_HIGH_SEL(dsi->feedback_div) |
                                         HIGH_PROGRAM_EN);
+       dw_mipi_dsi_phy_write(dsi, 0x19, PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN);
+
+       dw_mipi_dsi_phy_write(dsi, 0x22, LOW_PROGRAM_EN |
+                                        BIASEXTR_SEL(BIASEXTR_127_7));
+       dw_mipi_dsi_phy_write(dsi, 0x22, HIGH_PROGRAM_EN |
+                                        BANDGAP_SEL(BANDGAP_96_10));
 
        dw_mipi_dsi_phy_write(dsi, 0x20, POWER_CONTROL | INTERNAL_REG_CURRENT |
                                         BIAS_BLOCK_ON | BANDGAP_ON);
@@ -427,39 +474,47 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)
                                         SETRD_MAX | POWER_MANAGE |
                                         TER_RESISTORS_ON);
 
-       dw_mipi_dsi_phy_write(dsi, 0x22, LOW_PROGRAM_EN |
-                                        BIASEXTR_SEL(BIASEXTR_127_7));
-       dw_mipi_dsi_phy_write(dsi, 0x22, HIGH_PROGRAM_EN |
-                                        BANDGAP_SEL(BANDGAP_96_10));
-
-       dw_mipi_dsi_phy_write(dsi, 0x70, TLP_PROGRAM_EN | 0xf);
-       dw_mipi_dsi_phy_write(dsi, 0x71, THS_PRE_PROGRAM_EN | 0x55);
-       dw_mipi_dsi_phy_write(dsi, 0x72, THS_ZERO_PROGRAM_EN | 0xa);
+       dw_mipi_dsi_phy_write(dsi, 0x60, TLP_PROGRAM_EN | ns2bc(dsi, 500));
+       dw_mipi_dsi_phy_write(dsi, 0x61, THS_PRE_PROGRAM_EN | ns2ui(dsi, 40));
+       dw_mipi_dsi_phy_write(dsi, 0x62, THS_ZERO_PROGRAM_EN | ns2bc(dsi, 300));
+       dw_mipi_dsi_phy_write(dsi, 0x63, THS_PRE_PROGRAM_EN | ns2ui(dsi, 100));
+       dw_mipi_dsi_phy_write(dsi, 0x64, BIT(5) | ns2bc(dsi, 100));
+       dw_mipi_dsi_phy_write(dsi, 0x65, BIT(5) | (ns2bc(dsi, 60) + 7));
+
+       dw_mipi_dsi_phy_write(dsi, 0x70, TLP_PROGRAM_EN | ns2bc(dsi, 500));
+       dw_mipi_dsi_phy_write(dsi, 0x71,
+                             THS_PRE_PROGRAM_EN | (ns2ui(dsi, 50) + 5));
+       dw_mipi_dsi_phy_write(dsi, 0x72,
+                             THS_ZERO_PROGRAM_EN | (ns2bc(dsi, 140) + 2));
+       dw_mipi_dsi_phy_write(dsi, 0x73,
+                             THS_PRE_PROGRAM_EN | (ns2ui(dsi, 60) + 8));
+       dw_mipi_dsi_phy_write(dsi, 0x74, BIT(5) | ns2bc(dsi, 100));
 
        dsi_write(dsi, DSI_PHY_RSTZ, PHY_ENFORCEPLL | PHY_ENABLECLK |
                                     PHY_UNRSTZ | PHY_UNSHUTDOWNZ);
 
-
-       ret = readx_poll_timeout(readl, dsi->base + DSI_PHY_STATUS,
+       ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS,
                                 val, val & LOCK, 1000, PHY_STATUS_TIMEOUT_US);
        if (ret < 0) {
                dev_err(dsi->dev, "failed to wait for phy lock state\n");
-               return ret;
+               goto phy_init_end;
        }
 
-       ret = readx_poll_timeout(readl, dsi->base + DSI_PHY_STATUS,
+       ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS,
                                 val, val & STOP_STATE_CLK_LANE, 1000,
                                 PHY_STATUS_TIMEOUT_US);
-       if (ret < 0) {
+       if (ret < 0)
                dev_err(dsi->dev,
                        "failed to wait for phy clk lane stop state\n");
-               return ret;
-       }
+
+phy_init_end:
+       clk_disable_unprepare(dsi->phy_cfg_clk);
 
        return ret;
 }
 
-static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi)
+static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi,
+                                   struct drm_display_mode *mode)
 {
        unsigned int i, pre;
        unsigned long mpclk, pllref, tmp;
@@ -474,10 +529,10 @@ static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi)
                return bpp;
        }
 
-       mpclk = DIV_ROUND_UP(dsi->mode->clock, MSEC_PER_SEC);
+       mpclk = DIV_ROUND_UP(mode->clock, MSEC_PER_SEC);
        if (mpclk) {
-               /* take 1 / 0.9, since mbps must big than bandwidth of RGB */
-               tmp = mpclk * (bpp / dsi->lanes) * 10 / 9;
+               /* take 1 / 0.8, since mbps must big than bandwidth of RGB */
+               tmp = mpclk * (bpp / dsi->lanes) * 10 / 8;
                if (tmp < max_mbps)
                        target_mbps = tmp;
                else
@@ -487,7 +542,18 @@ static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi)
        pllref = DIV_ROUND_UP(clk_get_rate(dsi->pllref_clk), USEC_PER_SEC);
        tmp = pllref;
 
-       for (i = 1; i < 6; i++) {
+       /*
+        * The limits on the PLL divisor are:
+        *
+        *      5MHz <= (pllref / n) <= 40MHz
+        *
+        * we walk over these values in descreasing order so that if we hit
+        * an exact match for target_mbps it is more likely that "m" will be
+        * even.
+        *
+        * TODO: ensure that "m" is even after this loop.
+        */
+       for (i = pllref / 5; i > (pllref / 40); i--) {
                pre = pllref / i;
                if ((tmp > (target_mbps % pre)) && (target_mbps / pre < 512)) {
                        tmp = target_mbps % pre;
@@ -512,19 +578,14 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,
 
        if (device->lanes > dsi->pdata->max_data_lanes) {
                dev_err(dsi->dev, "the number of data lanes(%u) is too many\n",
-                               device->lanes);
-               return -EINVAL;
-       }
-
-       if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) ||
-           !(device->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)) {
-               dev_err(dsi->dev, "device mode is unsupported\n");
+                       device->lanes);
                return -EINVAL;
        }
 
        dsi->lanes = device->lanes;
        dsi->channel = device->channel;
        dsi->format = device->format;
+       dsi->mode_flags = device->mode_flags;
        dsi->panel = of_drm_find_panel(device->dev.of_node);
        if (dsi->panel)
                return drm_panel_attach(dsi->panel, &dsi->connector);
@@ -542,11 +603,27 @@ static int dw_mipi_dsi_host_detach(struct mipi_dsi_host *host,
        return 0;
 }
 
-static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 val)
+static void dw_mipi_message_config(struct dw_mipi_dsi *dsi,
+                                  const struct mipi_dsi_msg *msg)
+{
+       bool lpm = msg->flags & MIPI_DSI_MSG_USE_LPM;
+       u32 val = 0;
+
+       if (msg->flags & MIPI_DSI_MSG_REQ_ACK)
+               val |= EN_ACK_RQST;
+       if (lpm)
+               val |= CMD_MODE_ALL_LP;
+
+       dsi_write(dsi, DSI_LPCLK_CTRL, lpm ? 0 : PHY_TXREQUESTCLKHS);
+       dsi_write(dsi, DSI_CMD_MODE_CFG, val);
+}
+
+static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val)
 {
        int ret;
+       u32 val, mask;
 
-       ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS,
+       ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS,
                                 val, !(val & GEN_CMD_FULL), 1000,
                                 CMD_PKT_STATUS_TIMEOUT_US);
        if (ret < 0) {
@@ -554,10 +631,11 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 val)
                return ret;
        }
 
-       dsi_write(dsi, DSI_GEN_HDR, val);
+       dsi_write(dsi, DSI_GEN_HDR, hdr_val);
 
-       ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS,
-                                val, val & (GEN_CMD_EMPTY | GEN_PLD_W_EMPTY),
+       mask = GEN_CMD_EMPTY | GEN_PLD_W_EMPTY;
+       ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS,
+                                val, (val & mask) == mask,
                                 1000, CMD_PKT_STATUS_TIMEOUT_US);
        if (ret < 0) {
                dev_err(dsi->dev, "failed to write command FIFO\n");
@@ -570,8 +648,14 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 val)
 static int dw_mipi_dsi_dcs_short_write(struct dw_mipi_dsi *dsi,
                                       const struct mipi_dsi_msg *msg)
 {
-       const u16 *tx_buf = msg->tx_buf;
-       u32 val = GEN_HDATA(*tx_buf) | GEN_HTYPE(msg->type);
+       const u8 *tx_buf = msg->tx_buf;
+       u16 data = 0;
+       u32 val;
+
+       if (msg->tx_len > 0)
+               data |= tx_buf[0];
+       if (msg->tx_len > 1)
+               data |= tx_buf[1] << 8;
 
        if (msg->tx_len > 2) {
                dev_err(dsi->dev, "too long tx buf length %zu for short write\n",
@@ -579,16 +663,18 @@ static int dw_mipi_dsi_dcs_short_write(struct dw_mipi_dsi *dsi,
                return -EINVAL;
        }
 
+       val = GEN_HDATA(data) | GEN_HTYPE(msg->type);
        return dw_mipi_dsi_gen_pkt_hdr_write(dsi, val);
 }
 
 static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi,
                                      const struct mipi_dsi_msg *msg)
 {
-       const u32 *tx_buf = msg->tx_buf;
-       int len = msg->tx_len, pld_data_bytes = sizeof(*tx_buf), ret;
-       u32 val = GEN_HDATA(msg->tx_len) | GEN_HTYPE(msg->type);
-       u32 remainder = 0;
+       const u8 *tx_buf = msg->tx_buf;
+       int len = msg->tx_len, pld_data_bytes = sizeof(u32), ret;
+       u32 hdr_val = GEN_HDATA(msg->tx_len) | GEN_HTYPE(msg->type);
+       u32 remainder;
+       u32 val;
 
        if (msg->tx_len < 3) {
                dev_err(dsi->dev, "wrong tx buf length %zu for long write\n",
@@ -598,16 +684,18 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi,
 
        while (DIV_ROUND_UP(len, pld_data_bytes)) {
                if (len < pld_data_bytes) {
+                       remainder = 0;
                        memcpy(&remainder, tx_buf, len);
                        dsi_write(dsi, DSI_GEN_PLD_DATA, remainder);
                        len = 0;
                } else {
-                       dsi_write(dsi, DSI_GEN_PLD_DATA, *tx_buf);
-                       tx_buf++;
+                       memcpy(&remainder, tx_buf, pld_data_bytes);
+                       dsi_write(dsi, DSI_GEN_PLD_DATA, remainder);
+                       tx_buf += pld_data_bytes;
                        len -= pld_data_bytes;
                }
 
-               ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS,
+               ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS,
                                         val, !(val & GEN_PLD_W_FULL), 1000,
                                         CMD_PKT_STATUS_TIMEOUT_US);
                if (ret < 0) {
@@ -617,7 +705,7 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi,
                }
        }
 
-       return dw_mipi_dsi_gen_pkt_hdr_write(dsi, val);
+       return dw_mipi_dsi_gen_pkt_hdr_write(dsi, hdr_val);
 }
 
 static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
@@ -626,6 +714,8 @@ static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
        struct dw_mipi_dsi *dsi = host_to_dsi(host);
        int ret;
 
+       dw_mipi_message_config(dsi, msg);
+
        switch (msg->type) {
        case MIPI_DSI_DCS_SHORT_WRITE:
        case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
@@ -636,7 +726,8 @@ static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
                ret = dw_mipi_dsi_dcs_long_write(dsi, msg);
                break;
        default:
-               dev_err(dsi->dev, "unsupported message type\n");
+               dev_err(dsi->dev, "unsupported message type 0x%02x\n",
+                       msg->type);
                ret = -EINVAL;
        }
 
@@ -653,7 +744,14 @@ static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi)
 {
        u32 val;
 
-       val = VID_MODE_TYPE_BURST_SYNC_PULSES | ENABLE_LOW_POWER;
+       val = ENABLE_LOW_POWER;
+
+       if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+               val |= VID_MODE_TYPE_BURST;
+       else if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
+               val |= VID_MODE_TYPE_NON_BURST_SYNC_PULSES;
+       else
+               val |= VID_MODE_TYPE_NON_BURST_SYNC_EVENTS;
 
        dsi_write(dsi, DSI_VID_MODE_CFG, val);
 }
@@ -669,6 +767,7 @@ static void dw_mipi_dsi_set_mode(struct dw_mipi_dsi *dsi,
                dsi_write(dsi, DSI_PWR_UP, RESET);
                dsi_write(dsi, DSI_MODE_CFG, ENABLE_VIDEO_MODE);
                dw_mipi_dsi_video_mode_config(dsi);
+               dsi_write(dsi, DSI_LPCLK_CTRL, PHY_TXREQUESTCLKHS);
                dsi_write(dsi, DSI_PWR_UP, POWERUP);
        }
 }
@@ -681,12 +780,21 @@ static void dw_mipi_dsi_disable(struct dw_mipi_dsi *dsi)
 
 static void dw_mipi_dsi_init(struct dw_mipi_dsi *dsi)
 {
+       /*
+        * The maximum permitted escape clock is 20MHz and it is derived from
+        * lanebyteclk, which is running at "lane_mbps / 8".  Thus we want:
+        *
+        *     (lane_mbps >> 3) / esc_clk_division < 20
+        * which is:
+        *     (lane_mbps >> 3) / 20 > esc_clk_division
+        */
+       u32 esc_clk_division = (dsi->lane_mbps >> 3) / 20 + 1;
+
        dsi_write(dsi, DSI_PWR_UP, RESET);
        dsi_write(dsi, DSI_PHY_RSTZ, PHY_DISFORCEPLL | PHY_DISABLECLK
                  | PHY_RSTZ | PHY_SHUTDOWNZ);
        dsi_write(dsi, DSI_CLKMGR_CFG, TO_CLK_DIVIDSION(10) |
-                 TX_ESC_CLK_DIVIDSION(7));
-       dsi_write(dsi, DSI_LPCLK_CTRL, PHY_TXREQUESTCLKHS);
+                 TX_ESC_CLK_DIVIDSION(esc_clk_division));
 }
 
 static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi,
@@ -709,9 +817,9 @@ static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi,
                break;
        }
 
-       if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
+       if (mode->flags & DRM_MODE_FLAG_NVSYNC)
                val |= VSYNC_ACTIVE_LOW;
-       if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
+       if (mode->flags & DRM_MODE_FLAG_NHSYNC)
                val |= HSYNC_ACTIVE_LOW;
 
        dsi_write(dsi, DSI_DPI_VCID, DPI_VID(dsi->channel));
@@ -736,49 +844,49 @@ static void dw_mipi_dsi_command_mode_config(struct dw_mipi_dsi *dsi)
 {
        dsi_write(dsi, DSI_TO_CNT_CFG, HSTX_TO_CNT(1000) | LPRX_TO_CNT(1000));
        dsi_write(dsi, DSI_BTA_TO_CNT, 0xd00);
-       dsi_write(dsi, DSI_CMD_MODE_CFG, CMD_MODE_ALL_LP);
        dsi_write(dsi, DSI_MODE_CFG, ENABLE_CMD_MODE);
 }
 
 /* Get lane byte clock cycles. */
 static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct dw_mipi_dsi *dsi,
+                                          struct drm_display_mode *mode,
                                           u32 hcomponent)
 {
        u32 frac, lbcc;
 
        lbcc = hcomponent * dsi->lane_mbps * MSEC_PER_SEC / 8;
 
-       frac = lbcc % dsi->mode->clock;
-       lbcc = lbcc / dsi->mode->clock;
+       frac = lbcc % mode->clock;
+       lbcc = lbcc / mode->clock;
        if (frac)
                lbcc++;
 
        return lbcc;
 }
 
-static void dw_mipi_dsi_line_timer_config(struct dw_mipi_dsi *dsi)
+static void dw_mipi_dsi_line_timer_config(struct dw_mipi_dsi *dsi,
+                                         struct drm_display_mode *mode)
 {
        u32 htotal, hsa, hbp, lbcc;
-       struct drm_display_mode *mode = dsi->mode;
 
        htotal = mode->htotal;
        hsa = mode->hsync_end - mode->hsync_start;
        hbp = mode->htotal - mode->hsync_end;
 
-       lbcc = dw_mipi_dsi_get_hcomponent_lbcc(dsi, htotal);
+       lbcc = dw_mipi_dsi_get_hcomponent_lbcc(dsi, mode, htotal);
        dsi_write(dsi, DSI_VID_HLINE_TIME, lbcc);
 
-       lbcc = dw_mipi_dsi_get_hcomponent_lbcc(dsi, hsa);
+       lbcc = dw_mipi_dsi_get_hcomponent_lbcc(dsi, mode, hsa);
        dsi_write(dsi, DSI_VID_HSA_TIME, lbcc);
 
-       lbcc = dw_mipi_dsi_get_hcomponent_lbcc(dsi, hbp);
+       lbcc = dw_mipi_dsi_get_hcomponent_lbcc(dsi, mode, hbp);
        dsi_write(dsi, DSI_VID_HBP_TIME, lbcc);
 }
 
-static void dw_mipi_dsi_vertical_timing_config(struct dw_mipi_dsi *dsi)
+static void dw_mipi_dsi_vertical_timing_config(struct dw_mipi_dsi *dsi,
+                                              struct drm_display_mode *mode)
 {
        u32 vactive, vsa, vfp, vbp;
-       struct drm_display_mode *mode = dsi->mode;
 
        vactive = mode->vdisplay;
        vsa = mode->vsync_end - mode->vsync_start;
@@ -814,17 +922,11 @@ static void dw_mipi_dsi_clear_err(struct dw_mipi_dsi *dsi)
        dsi_write(dsi, DSI_INT_MSK1, 0);
 }
 
-static void dw_mipi_dsi_encoder_mode_set(struct drm_encoder *encoder,
-                                       struct drm_display_mode *mode,
-                                       struct drm_display_mode *adjusted_mode)
+static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder)
 {
        struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder);
-       int ret;
-
-       dsi->mode = adjusted_mode;
 
-       ret = dw_mipi_dsi_get_lane_bps(dsi);
-       if (ret < 0)
+       if (dsi->dpms_mode != DRM_MODE_DPMS_ON)
                return;
 
        if (clk_prepare_enable(dsi->pclk)) {
@@ -832,62 +934,61 @@ static void dw_mipi_dsi_encoder_mode_set(struct drm_encoder *encoder,
                return;
        }
 
-       dw_mipi_dsi_init(dsi);
-       dw_mipi_dsi_dpi_config(dsi, mode);
-       dw_mipi_dsi_packet_handler_config(dsi);
-       dw_mipi_dsi_video_mode_config(dsi);
-       dw_mipi_dsi_video_packet_config(dsi, mode);
-       dw_mipi_dsi_command_mode_config(dsi);
-       dw_mipi_dsi_line_timer_config(dsi);
-       dw_mipi_dsi_vertical_timing_config(dsi);
-       dw_mipi_dsi_dphy_timing_config(dsi);
-       dw_mipi_dsi_dphy_interface_config(dsi);
-       dw_mipi_dsi_clear_err(dsi);
-       if (drm_panel_prepare(dsi->panel))
-               dev_err(dsi->dev, "failed to prepare panel\n");
-
-       clk_disable_unprepare(dsi->pclk);
-}
-
-static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder)
-{
-       struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder);
-
        drm_panel_disable(dsi->panel);
 
-       if (clk_prepare_enable(dsi->pclk)) {
-               dev_err(dsi->dev, "%s: Failed to enable pclk\n", __func__);
-               return;
-       }
-
        dw_mipi_dsi_set_mode(dsi, DW_MIPI_DSI_CMD_MODE);
        drm_panel_unprepare(dsi->panel);
-       dw_mipi_dsi_set_mode(dsi, DW_MIPI_DSI_VID_MODE);
-
-       /*
-        * This is necessary to make sure the peripheral will be driven
-        * normally when the display is enabled again later.
-        */
-       msleep(120);
 
-       dw_mipi_dsi_set_mode(dsi, DW_MIPI_DSI_CMD_MODE);
        dw_mipi_dsi_disable(dsi);
+       pm_runtime_put(dsi->dev);
        clk_disable_unprepare(dsi->pclk);
+       dsi->dpms_mode = DRM_MODE_DPMS_OFF;
 }
 
-static void dw_mipi_dsi_encoder_commit(struct drm_encoder *encoder)
+static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder)
 {
        struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder);
+       struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
+       const struct dw_mipi_dsi_plat_data *pdata = dsi->pdata;
        int mux = drm_of_encoder_active_endpoint_id(dsi->dev->of_node, encoder);
        u32 val;
+       int ret;
+
+       ret = dw_mipi_dsi_get_lane_bps(dsi, mode);
+       if (ret < 0)
+               return;
+
+       if (dsi->dpms_mode == DRM_MODE_DPMS_ON)
+               return;
 
        if (clk_prepare_enable(dsi->pclk)) {
                dev_err(dsi->dev, "%s: Failed to enable pclk\n", __func__);
                return;
        }
 
+       pm_runtime_get_sync(dsi->dev);
+       dw_mipi_dsi_init(dsi);
+       dw_mipi_dsi_dpi_config(dsi, mode);
+       dw_mipi_dsi_packet_handler_config(dsi);
+       dw_mipi_dsi_video_mode_config(dsi);
+       dw_mipi_dsi_video_packet_config(dsi, mode);
+       dw_mipi_dsi_command_mode_config(dsi);
+       dw_mipi_dsi_line_timer_config(dsi, mode);
+       dw_mipi_dsi_vertical_timing_config(dsi, mode);
+       dw_mipi_dsi_dphy_timing_config(dsi);
+       dw_mipi_dsi_dphy_interface_config(dsi);
+       dw_mipi_dsi_clear_err(dsi);
+
+       if (pdata->grf_dsi0_mode_reg)
+               regmap_write(dsi->grf_regmap, pdata->grf_dsi0_mode_reg,
+                            pdata->grf_dsi0_mode);
+
        dw_mipi_dsi_phy_init(dsi);
-       dw_mipi_dsi_wait_for_two_frames(dsi);
+       dw_mipi_dsi_wait_for_two_frames(mode);
+
+       dw_mipi_dsi_set_mode(dsi, DW_MIPI_DSI_CMD_MODE);
+       if (drm_panel_prepare(dsi->panel))
+               dev_err(dsi->dev, "failed to prepare panel\n");
 
        dw_mipi_dsi_set_mode(dsi, DW_MIPI_DSI_VID_MODE);
        drm_panel_enable(dsi->panel);
@@ -895,12 +996,13 @@ static void dw_mipi_dsi_encoder_commit(struct drm_encoder *encoder)
        clk_disable_unprepare(dsi->pclk);
 
        if (mux)
-               val = DSI0_SEL_VOP_LIT | (DSI0_SEL_VOP_LIT << 16);
+               val = pdata->dsi0_en_bit | (pdata->dsi0_en_bit << 16);
        else
-               val = DSI0_SEL_VOP_LIT << 16;
+               val = pdata->dsi0_en_bit << 16;
 
-       regmap_write(dsi->grf_regmap, GRF_SOC_CON6, val);
+       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;
 }
 
 static int
@@ -931,15 +1033,14 @@ dw_mipi_dsi_encoder_atomic_check(struct drm_encoder *encoder,
        return 0;
 }
 
-static struct drm_encoder_helper_funcs
+static const struct drm_encoder_helper_funcs
 dw_mipi_dsi_encoder_helper_funcs = {
-       .commit = dw_mipi_dsi_encoder_commit,
-       .mode_set = dw_mipi_dsi_encoder_mode_set,
+       .enable = dw_mipi_dsi_encoder_enable,
        .disable = dw_mipi_dsi_encoder_disable,
        .atomic_check = dw_mipi_dsi_encoder_atomic_check,
 };
 
-static struct drm_encoder_funcs dw_mipi_dsi_encoder_funcs = {
+static const struct drm_encoder_funcs dw_mipi_dsi_encoder_funcs = {
        .destroy = drm_encoder_cleanup,
 };
 
@@ -950,23 +1051,8 @@ static int dw_mipi_dsi_connector_get_modes(struct drm_connector *connector)
        return drm_panel_get_modes(dsi->panel);
 }
 
-static enum drm_mode_status dw_mipi_dsi_mode_valid(
-                                       struct drm_connector *connector,
-                                       struct drm_display_mode *mode)
-{
-       struct dw_mipi_dsi *dsi = con_to_dsi(connector);
-
-       enum drm_mode_status mode_status = MODE_OK;
-
-       if (dsi->pdata->mode_valid)
-               mode_status = dsi->pdata->mode_valid(connector, mode);
-
-       return mode_status;
-}
-
 static struct drm_connector_helper_funcs dw_mipi_dsi_connector_helper_funcs = {
        .get_modes = dw_mipi_dsi_connector_get_modes,
-       .mode_valid = dw_mipi_dsi_mode_valid,
 };
 
 static void dw_mipi_dsi_drm_connector_destroy(struct drm_connector *connector)
@@ -975,7 +1061,7 @@ static void dw_mipi_dsi_drm_connector_destroy(struct drm_connector *connector)
        drm_connector_cleanup(connector);
 }
 
-static struct drm_connector_funcs dw_mipi_dsi_atomic_connector_funcs = {
+static const struct drm_connector_funcs dw_mipi_dsi_atomic_connector_funcs = {
        .dpms = drm_atomic_helper_connector_dpms,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .destroy = dw_mipi_dsi_drm_connector_destroy,
@@ -985,7 +1071,7 @@ static struct drm_connector_funcs dw_mipi_dsi_atomic_connector_funcs = {
 };
 
 static int dw_mipi_dsi_register(struct drm_device *drm,
-                                     struct dw_mipi_dsi *dsi)
+                               struct dw_mipi_dsi *dsi)
 {
        struct drm_encoder *encoder = &dsi->encoder;
        struct drm_connector *connector = &dsi->connector;
@@ -1006,14 +1092,14 @@ static int dw_mipi_dsi_register(struct drm_device *drm,
        drm_encoder_helper_add(&dsi->encoder,
                               &dw_mipi_dsi_encoder_helper_funcs);
        ret = drm_encoder_init(drm, &dsi->encoder, &dw_mipi_dsi_encoder_funcs,
-                        DRM_MODE_ENCODER_DSI, NULL);
+                              DRM_MODE_ENCODER_DSI, NULL);
        if (ret) {
                dev_err(dev, "Failed to initialize encoder with drm\n");
                return ret;
        }
 
        drm_connector_helper_add(connector,
-                       &dw_mipi_dsi_connector_helper_funcs);
+                                &dw_mipi_dsi_connector_helper_funcs);
 
        drm_connector_init(drm, &dsi->connector,
                           &dw_mipi_dsi_atomic_connector_funcs,
@@ -1037,48 +1123,42 @@ static int rockchip_mipi_parse_dt(struct dw_mipi_dsi *dsi)
        return 0;
 }
 
-static enum drm_mode_status rk3288_mipi_dsi_mode_valid(
-                                       struct drm_connector *connector,
-                                       struct drm_display_mode *mode)
-{
-       /*
-        * The VID_PKT_SIZE field in the DSI_VID_PKT_CFG
-        * register is 11-bit.
-        */
-       if (mode->hdisplay > 0x7ff)
-               return MODE_BAD_HVALUE;
-
-       /*
-        * The V_ACTIVE_LINES field in the DSI_VTIMING_CFG
-        * register is 11-bit.
-        */
-       if (mode->vdisplay > 0x7ff)
-               return MODE_BAD_VVALUE;
-
-       return MODE_OK;
-}
-
 static struct dw_mipi_dsi_plat_data rk3288_mipi_dsi_drv_data = {
+       .dsi0_en_bit = RK3288_DSI0_SEL_VOP_LIT,
+       .dsi1_en_bit = RK3288_DSI1_SEL_VOP_LIT,
+       .grf_switch_reg = RK3288_GRF_SOC_CON6,
+       .max_data_lanes = 4,
+};
+
+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_dsi0_mode = RK3399_GRF_DSI_MODE,
+       .grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
        .max_data_lanes = 4,
-       .mode_valid = rk3288_mipi_dsi_mode_valid,
 };
 
 static const struct of_device_id dw_mipi_dsi_dt_ids[] = {
        {
         .compatible = "rockchip,rk3288-mipi-dsi",
         .data = &rk3288_mipi_dsi_drv_data,
+       }, {
+        .compatible = "rockchip,rk3399-mipi-dsi",
+        .data = &rk3399_mipi_dsi_drv_data,
        },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, dw_mipi_dsi_dt_ids);
 
 static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
-                            void *data)
+                           void *data)
 {
        const struct of_device_id *of_id =
                        of_match_device(dw_mipi_dsi_dt_ids, dev);
        const struct dw_mipi_dsi_plat_data *pdata = of_id->data;
        struct platform_device *pdev = to_platform_device(dev);
+       struct reset_control *apb_rst;
        struct drm_device *drm = data;
        struct dw_mipi_dsi *dsi;
        struct resource *res;
@@ -1090,6 +1170,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
 
        dsi->dev = dev;
        dsi->pdata = pdata;
+       dsi->dpms_mode = DRM_MODE_DPMS_OFF;
 
        ret = rockchip_mipi_parse_dt(dsi);
        if (ret)
@@ -1117,6 +1198,46 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
                return ret;
        }
 
+       /*
+        * Note that the reset was not defined in the initial device tree, so
+        * we have to be prepared for it not being found.
+        */
+       apb_rst = devm_reset_control_get(dev, "apb");
+       if (IS_ERR(apb_rst)) {
+               ret = PTR_ERR(apb_rst);
+               if (ret == -ENOENT) {
+                       apb_rst = NULL;
+               } else {
+                       dev_err(dev, "Unable to get reset control: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       if (apb_rst) {
+               ret = clk_prepare_enable(dsi->pclk);
+               if (ret) {
+                       dev_err(dev, "%s: Failed to enable pclk\n", __func__);
+                       return ret;
+               }
+
+               reset_control_assert(apb_rst);
+               usleep_range(10, 20);
+               reset_control_deassert(apb_rst);
+
+               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) {
+                       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");
+       }
+
        ret = clk_prepare_enable(dsi->pllref_clk);
        if (ret) {
                dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__);
@@ -1129,23 +1250,41 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
                goto err_pllref;
        }
 
-       dev_set_drvdata(dev, dsi);
+       pm_runtime_enable(dev);
 
        dsi->dsi_host.ops = &dw_mipi_dsi_host_ops;
        dsi->dsi_host.dev = dev;
-       return mipi_dsi_host_register(&dsi->dsi_host);
+       ret = mipi_dsi_host_register(&dsi->dsi_host);
+       if (ret) {
+               dev_err(dev, "Failed to register MIPI host: %d\n", ret);
+               goto err_cleanup;
+       }
+
+       if (!dsi->panel) {
+               ret = -EPROBE_DEFER;
+               goto err_mipi_dsi_host;
+       }
 
+       dev_set_drvdata(dev, dsi);
+       return 0;
+
+err_mipi_dsi_host:
+       mipi_dsi_host_unregister(&dsi->dsi_host);
+err_cleanup:
+       drm_encoder_cleanup(&dsi->encoder);
+       drm_connector_cleanup(&dsi->connector);
 err_pllref:
        clk_disable_unprepare(dsi->pllref_clk);
        return ret;
 }
 
 static void dw_mipi_dsi_unbind(struct device *dev, struct device *master,
-       void *data)
+                              void *data)
 {
        struct dw_mipi_dsi *dsi = dev_get_drvdata(dev);
 
        mipi_dsi_host_unregister(&dsi->dsi_host);
+       pm_runtime_disable(dev);
        clk_disable_unprepare(dsi->pllref_clk);
 }
 
index b360e6251836d990e382f0f7451788054336a0d5..ccf45693879260f6e4aee57f331bab0048635990 100644 (file)
@@ -77,55 +77,6 @@ void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
        iommu_detach_device(domain, dev);
 }
 
-int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
-                                const struct rockchip_crtc_funcs *crtc_funcs)
-{
-       int pipe = drm_crtc_index(crtc);
-       struct rockchip_drm_private *priv = crtc->dev->dev_private;
-
-       if (pipe >= ROCKCHIP_MAX_CRTC)
-               return -EINVAL;
-
-       priv->crtc_funcs[pipe] = crtc_funcs;
-
-       return 0;
-}
-
-void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc)
-{
-       int pipe = drm_crtc_index(crtc);
-       struct rockchip_drm_private *priv = crtc->dev->dev_private;
-
-       if (pipe >= ROCKCHIP_MAX_CRTC)
-               return;
-
-       priv->crtc_funcs[pipe] = NULL;
-}
-
-static int rockchip_drm_crtc_enable_vblank(struct drm_device *dev,
-                                          unsigned int pipe)
-{
-       struct rockchip_drm_private *priv = dev->dev_private;
-       struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
-
-       if (crtc && priv->crtc_funcs[pipe] &&
-           priv->crtc_funcs[pipe]->enable_vblank)
-               return priv->crtc_funcs[pipe]->enable_vblank(crtc);
-
-       return 0;
-}
-
-static void rockchip_drm_crtc_disable_vblank(struct drm_device *dev,
-                                            unsigned int pipe)
-{
-       struct rockchip_drm_private *priv = dev->dev_private;
-       struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
-
-       if (crtc && priv->crtc_funcs[pipe] &&
-           priv->crtc_funcs[pipe]->enable_vblank)
-               priv->crtc_funcs[pipe]->disable_vblank(crtc);
-}
-
 static int rockchip_drm_init_iommu(struct drm_device *drm_dev)
 {
        struct rockchip_drm_private *private = drm_dev->dev_private;
@@ -277,9 +228,6 @@ static struct drm_driver rockchip_drm_driver = {
        .driver_features        = DRIVER_MODESET | DRIVER_GEM |
                                  DRIVER_PRIME | DRIVER_ATOMIC,
        .lastclose              = rockchip_drm_lastclose,
-       .get_vblank_counter     = drm_vblank_no_hw_counter,
-       .enable_vblank          = rockchip_drm_crtc_enable_vblank,
-       .disable_vblank         = rockchip_drm_crtc_disable_vblank,
        .gem_vm_ops             = &drm_gem_cma_vm_ops,
        .gem_free_object_unlocked = rockchip_gem_free_object,
        .dumb_create            = rockchip_gem_dumb_create,
index adc39302bec56b07852ecf3855f3bfa09df12cc1..8aca219ec4c8f822e193e6e4a872ae9c0c848e05 100644 (file)
@@ -32,16 +32,6 @@ struct drm_device;
 struct drm_connector;
 struct iommu_domain;
 
-/*
- * Rockchip drm private crtc funcs.
- * @enable_vblank: enable crtc vblank irq.
- * @disable_vblank: disable crtc vblank irq.
- */
-struct rockchip_crtc_funcs {
-       int (*enable_vblank)(struct drm_crtc *crtc);
-       void (*disable_vblank)(struct drm_crtc *crtc);
-};
-
 struct rockchip_crtc_state {
        struct drm_crtc_state base;
        int output_type;
@@ -59,7 +49,6 @@ struct rockchip_crtc_state {
 struct rockchip_drm_private {
        struct drm_fb_helper fbdev_helper;
        struct drm_gem_object *fbdev_bo;
-       const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC];
        struct drm_atomic_state *state;
        struct iommu_domain *domain;
        /* protect drm_mm on multi-threads */
@@ -69,9 +58,6 @@ struct rockchip_drm_private {
        spinlock_t psr_list_lock;
 };
 
-int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
-                                const struct rockchip_crtc_funcs *crtc_funcs);
-void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc);
 int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
                                   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
index c9ccdf8f44bb2ba6ad049985b805f462d4a38af6..81f9548672b02734044a08f8ecae300df7edbf87 100644 (file)
@@ -193,7 +193,7 @@ rockchip_atomic_commit_tail(struct drm_atomic_state *state)
        drm_atomic_helper_cleanup_planes(dev, state);
 }
 
-static struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = {
+static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = {
        .atomic_commit_tail = rockchip_atomic_commit_tail,
 };
 
index 70ad50dd594d127d6cab5180e048afc6191e6848..ce946b9c57a9f36e7c3d50c6e4c00c837565690a 100644 (file)
@@ -78,7 +78,7 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper,
        if (IS_ERR(fbi)) {
                dev_err(dev->dev, "Failed to create framebuffer info.\n");
                ret = PTR_ERR(fbi);
-               goto err_rockchip_gem_free_object;
+               goto out;
        }
 
        helper->fb = rockchip_drm_framebuffer_init(dev, &mode_cmd,
@@ -86,7 +86,7 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper,
        if (IS_ERR(helper->fb)) {
                dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n");
                ret = PTR_ERR(helper->fb);
-               goto err_release_fbi;
+               goto out;
        }
 
        fbi->par = helper;
@@ -114,9 +114,7 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper,
 
        return 0;
 
-err_release_fbi:
-       drm_fb_helper_release_fbi(helper);
-err_rockchip_gem_free_object:
+out:
        rockchip_gem_free_object(&rk_obj->base);
        return ret;
 }
@@ -173,7 +171,6 @@ void rockchip_drm_fbdev_fini(struct drm_device *dev)
        helper = &private->fbdev_helper;
 
        drm_fb_helper_unregister_fbi(helper);
-       drm_fb_helper_release_fbi(helper);
 
        if (helper->fb)
                drm_framebuffer_unreference(helper->fb);
index 76c79ac57df06e26013d3ab656efa1421b34aff2..94d7b7327ff7e363f4f4d25ded0d63e628820038 100644 (file)
@@ -857,11 +857,6 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc)
        spin_unlock_irqrestore(&vop->irq_lock, flags);
 }
 
-static const struct rockchip_crtc_funcs private_crtc_funcs = {
-       .enable_vblank = vop_crtc_enable_vblank,
-       .disable_vblank = vop_crtc_disable_vblank,
-};
-
 static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
                                const struct drm_display_mode *mode,
                                struct drm_display_mode *adjusted_mode)
@@ -937,10 +932,10 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
        }
 
        pin_pol = BIT(DCLK_INVERT);
-       pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ?
-                  0 : BIT(HSYNC_POSITIVE);
-       pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ?
-                  0 : BIT(VSYNC_POSITIVE);
+       pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) ?
+                  BIT(HSYNC_POSITIVE) : 0;
+       pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) ?
+                  BIT(VSYNC_POSITIVE) : 0;
        VOP_CTRL_SET(vop, pin_pol, pin_pol);
 
        switch (s->output_type) {
@@ -1123,6 +1118,8 @@ static const struct drm_crtc_funcs vop_crtc_funcs = {
        .reset = vop_crtc_reset,
        .atomic_duplicate_state = vop_crtc_duplicate_state,
        .atomic_destroy_state = vop_crtc_destroy_state,
+       .enable_vblank = vop_crtc_enable_vblank,
+       .disable_vblank = vop_crtc_disable_vblank,
 };
 
 static void vop_fb_unref_worker(struct drm_flip_work *work, void *val)
@@ -1294,7 +1291,6 @@ static int vop_create_crtc(struct vop *vop)
        init_completion(&vop->dsp_hold_completion);
        init_completion(&vop->line_flag_completion);
        crtc->port = port;
-       rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);
 
        return 0;
 
@@ -1313,7 +1309,6 @@ static void vop_destroy_crtc(struct vop *vop)
        struct drm_device *drm_dev = vop->drm_dev;
        struct drm_plane *plane, *tmp;
 
-       rockchip_unregister_crtc_funcs(crtc);
        of_node_put(crtc->port);
 
        /*
index 1e71bc182ca96a6bda444650f3f30db15ce95df8..fa356f5dae27d309978424137236c6ac81a61436 100644 (file)
@@ -181,7 +181,7 @@ static bool assert_node(struct drm_mm_node *node, struct drm_mm *mm,
        }
 
        if (misalignment(node, alignment)) {
-               pr_err("node is misalinged, start %llx rem %llu, expected alignment %llu\n",
+               pr_err("node is misaligned, start %llx rem %llu, expected alignment %llu\n",
                       node->start, misalignment(node, alignment), alignment);
                ok = false;
        }
@@ -839,16 +839,18 @@ static bool assert_contiguous_in_range(struct drm_mm *mm,
                n++;
        }
 
-       drm_mm_for_each_node_in_range(node, mm, 0, start) {
-               if (node) {
+       if (start > 0) {
+               node = __drm_mm_interval_first(mm, 0, start - 1);
+               if (node->allocated) {
                        pr_err("node before start: node=%llx+%llu, start=%llx\n",
                               node->start, node->size, start);
                        return false;
                }
        }
 
-       drm_mm_for_each_node_in_range(node, mm, end, U64_MAX) {
-               if (node) {
+       if (end < U64_MAX) {
+               node = __drm_mm_interval_first(mm, end, U64_MAX);
+               if (node->allocated) {
                        pr_err("node after end: node=%llx+%llu, end=%llx\n",
                               node->start, node->size, end);
                        return false;
index 44547655169535991142cc6b164871f38c8c6146..8244890e6d53212133895e165d75c861ef8c1002 100644 (file)
@@ -476,10 +476,45 @@ static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc,
        return 0;
 }
 
+static void shmob_drm_crtc_enable_vblank(struct shmob_drm_device *sdev,
+                                        bool enable)
+{
+       unsigned long flags;
+       u32 ldintr;
+
+       /* Be careful not to acknowledge any pending interrupt. */
+       spin_lock_irqsave(&sdev->irq_lock, flags);
+       ldintr = lcdc_read(sdev, LDINTR) | LDINTR_STATUS_MASK;
+       if (enable)
+               ldintr |= LDINTR_VEE;
+       else
+               ldintr &= ~LDINTR_VEE;
+       lcdc_write(sdev, LDINTR, ldintr);
+       spin_unlock_irqrestore(&sdev->irq_lock, flags);
+}
+
+static int shmob_drm_enable_vblank(struct drm_crtc *crtc)
+{
+       struct shmob_drm_device *sdev = crtc->dev->dev_private;
+
+       shmob_drm_crtc_enable_vblank(sdev, true);
+
+       return 0;
+}
+
+static void shmob_drm_disable_vblank(struct drm_crtc *crtc)
+{
+       struct shmob_drm_device *sdev = crtc->dev->dev_private;
+
+       shmob_drm_crtc_enable_vblank(sdev, false);
+}
+
 static const struct drm_crtc_funcs crtc_funcs = {
        .destroy = drm_crtc_cleanup,
        .set_config = drm_crtc_helper_set_config,
        .page_flip = shmob_drm_crtc_page_flip,
+       .enable_vblank = shmob_drm_enable_vblank,
+       .disable_vblank = shmob_drm_disable_vblank,
 };
 
 int shmob_drm_crtc_create(struct shmob_drm_device *sdev)
@@ -594,22 +629,6 @@ int shmob_drm_encoder_create(struct shmob_drm_device *sdev)
        return 0;
 }
 
-void shmob_drm_crtc_enable_vblank(struct shmob_drm_device *sdev, bool enable)
-{
-       unsigned long flags;
-       u32 ldintr;
-
-       /* Be careful not to acknowledge any pending interrupt. */
-       spin_lock_irqsave(&sdev->irq_lock, flags);
-       ldintr = lcdc_read(sdev, LDINTR) | LDINTR_STATUS_MASK;
-       if (enable)
-               ldintr |= LDINTR_VEE;
-       else
-               ldintr &= ~LDINTR_VEE;
-       lcdc_write(sdev, LDINTR, ldintr);
-       spin_unlock_irqrestore(&sdev->irq_lock, flags);
-}
-
 /* -----------------------------------------------------------------------------
  * Connector
  */
index 818b31549ddcb9b2806a4c48a3f5a6cbf439c108..f152973df11c9859d36df6366ad4e34aea213291 100644 (file)
@@ -47,7 +47,6 @@ struct shmob_drm_connector {
 };
 
 int shmob_drm_crtc_create(struct shmob_drm_device *sdev);
-void shmob_drm_crtc_enable_vblank(struct shmob_drm_device *sdev, bool enable);
 void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc);
 void shmob_drm_crtc_suspend(struct shmob_drm_crtc *scrtc);
 void shmob_drm_crtc_resume(struct shmob_drm_crtc *scrtc);
index 33cec3d4238969579cf114f1775d4f94ad82d02b..34fefa0ba0f092cd40ce9850cf26441f588144c4 100644 (file)
@@ -23,7 +23,6 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 
-#include "shmob_drm_crtc.h"
 #include "shmob_drm_drv.h"
 #include "shmob_drm_kms.h"
 #include "shmob_drm_plane.h"
@@ -222,22 +221,6 @@ static irqreturn_t shmob_drm_irq(int irq, void *arg)
        return IRQ_HANDLED;
 }
 
-static int shmob_drm_enable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-       struct shmob_drm_device *sdev = dev->dev_private;
-
-       shmob_drm_crtc_enable_vblank(sdev, true);
-
-       return 0;
-}
-
-static void shmob_drm_disable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-       struct shmob_drm_device *sdev = dev->dev_private;
-
-       shmob_drm_crtc_enable_vblank(sdev, false);
-}
-
 static const struct file_operations shmob_drm_fops = {
        .owner          = THIS_MODULE,
        .open           = drm_open,
@@ -256,9 +239,6 @@ static struct drm_driver shmob_drm_driver = {
        .load                   = shmob_drm_load,
        .unload                 = shmob_drm_unload,
        .irq_handler            = shmob_drm_irq,
-       .get_vblank_counter     = drm_vblank_no_hw_counter,
-       .enable_vblank          = shmob_drm_enable_vblank,
-       .disable_vblank         = shmob_drm_disable_vblank,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_vm_ops             = &drm_gem_cma_vm_ops,
        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
index 20fc0fbfa84919d3aa52f5f58cdc73a45832396e..3b15c2cb2306a3ef07c17f0421aa0945709f0afc 100644 (file)
@@ -188,7 +188,6 @@ static struct drm_driver sti_driver = {
        .dumb_destroy = drm_gem_dumb_destroy,
        .fops = &sti_driver_fops,
 
-       .get_vblank_counter = drm_vblank_no_hw_counter,
        .enable_vblank = sti_crtc_enable_vblank,
        .disable_vblank = sti_crtc_disable_vblank,
 
@@ -325,7 +324,7 @@ static int sti_platform_probe(struct platform_device *pdev)
 
        dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
 
-       of_platform_populate(node, NULL, NULL, dev);
+       devm_of_platform_populate(dev);
 
        child_np = of_get_next_available_child(node, NULL);
 
@@ -341,7 +340,6 @@ static int sti_platform_probe(struct platform_device *pdev)
 static int sti_platform_remove(struct platform_device *pdev)
 {
        component_master_del(&pdev->dev, &sti_ops);
-       of_platform_depopulate(&pdev->dev);
 
        return 0;
 }
index 4a192210574f5ed442d09e33babb8697eacd4bad..a5d546a68e1651edb9e19bcdfd66da0f42cb6de8 100644 (file)
@@ -104,6 +104,28 @@ static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
        .enable         = sun4i_crtc_enable,
 };
 
+static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+       struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
+       struct sun4i_drv *drv = scrtc->drv;
+
+       DRM_DEBUG_DRIVER("Enabling VBLANK on crtc %p\n", crtc);
+
+       sun4i_tcon_enable_vblank(drv->tcon, true);
+
+       return 0;
+}
+
+static void sun4i_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+       struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
+       struct sun4i_drv *drv = scrtc->drv;
+
+       DRM_DEBUG_DRIVER("Disabling VBLANK on crtc %p\n", crtc);
+
+       sun4i_tcon_enable_vblank(drv->tcon, false);
+}
+
 static const struct drm_crtc_funcs sun4i_crtc_funcs = {
        .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
@@ -111,6 +133,8 @@ static const struct drm_crtc_funcs sun4i_crtc_funcs = {
        .page_flip              = drm_atomic_helper_page_flip,
        .reset                  = drm_atomic_helper_crtc_reset,
        .set_config             = drm_atomic_helper_set_config,
+       .enable_vblank          = sun4i_crtc_enable_vblank,
+       .disable_vblank         = sun4i_crtc_disable_vblank,
 };
 
 struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm)
index 4ce665349f6b6cef51a2e6142708e5ec34ac45a4..9ccf7c4deb6d32e409a39562607abb4f8ed6617e 100644 (file)
 #include "sun4i_drv.h"
 #include "sun4i_framebuffer.h"
 #include "sun4i_layer.h"
-#include "sun4i_tcon.h"
-
-static int sun4i_drv_enable_vblank(struct drm_device *drm, unsigned int pipe)
-{
-       struct sun4i_drv *drv = drm->dev_private;
-       struct sun4i_tcon *tcon = drv->tcon;
-
-       DRM_DEBUG_DRIVER("Enabling VBLANK on pipe %d\n", pipe);
-
-       sun4i_tcon_enable_vblank(tcon, true);
-
-       return 0;
-}
-
-static void sun4i_drv_disable_vblank(struct drm_device *drm, unsigned int pipe)
-{
-       struct sun4i_drv *drv = drm->dev_private;
-       struct sun4i_tcon *tcon = drv->tcon;
-
-       DRM_DEBUG_DRIVER("Disabling VBLANK on pipe %d\n", pipe);
-
-       sun4i_tcon_enable_vblank(tcon, false);
-}
 
 static const struct file_operations sun4i_drv_fops = {
        .owner          = THIS_MODULE,
@@ -90,11 +67,6 @@ static struct drm_driver sun4i_drv_driver = {
        .gem_prime_mmap         = drm_gem_cma_prime_mmap,
 
        /* Frame Buffer Operations */
-
-       /* VBlank Operations */
-       .get_vblank_counter     = drm_vblank_no_hw_counter,
-       .enable_vblank          = sun4i_drv_enable_vblank,
-       .disable_vblank         = sun4i_drv_disable_vblank,
 };
 
 static void sun4i_remove_framebuffers(void)
index 7561a95a54e383cb4df896f88a5b9903fe3347c6..0db5d5a8d3b980fd5d62e85d4801e8b82da0232a 100644 (file)
@@ -909,8 +909,10 @@ static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc)
        return 0;
 }
 
-u32 tegra_dc_get_vblank_counter(struct tegra_dc *dc)
+static u32 tegra_dc_get_vblank_counter(struct drm_crtc *crtc)
 {
+       struct tegra_dc *dc = to_tegra_dc(crtc);
+
        if (dc->syncpt)
                return host1x_syncpt_read(dc->syncpt);
 
@@ -918,8 +920,9 @@ u32 tegra_dc_get_vblank_counter(struct tegra_dc *dc)
        return drm_crtc_vblank_count(&dc->base);
 }
 
-void tegra_dc_enable_vblank(struct tegra_dc *dc)
+static int tegra_dc_enable_vblank(struct drm_crtc *crtc)
 {
+       struct tegra_dc *dc = to_tegra_dc(crtc);
        unsigned long value, flags;
 
        spin_lock_irqsave(&dc->lock, flags);
@@ -929,10 +932,13 @@ void tegra_dc_enable_vblank(struct tegra_dc *dc)
        tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
 
        spin_unlock_irqrestore(&dc->lock, flags);
+
+       return 0;
 }
 
-void tegra_dc_disable_vblank(struct tegra_dc *dc)
+static void tegra_dc_disable_vblank(struct drm_crtc *crtc)
 {
+       struct tegra_dc *dc = to_tegra_dc(crtc);
        unsigned long value, flags;
 
        spin_lock_irqsave(&dc->lock, flags);
@@ -1036,6 +1042,9 @@ static const struct drm_crtc_funcs tegra_crtc_funcs = {
        .reset = tegra_crtc_reset,
        .atomic_duplicate_state = tegra_crtc_atomic_duplicate_state,
        .atomic_destroy_state = tegra_crtc_atomic_destroy_state,
+       .get_vblank_counter = tegra_dc_get_vblank_counter,
+       .enable_vblank = tegra_dc_enable_vblank,
+       .disable_vblank = tegra_dc_disable_vblank,
 };
 
 static int tegra_dc_set_timings(struct tegra_dc *dc,
index ef215fef63d6fb8ddd80c5e6849aaafe4b272f9f..dba4e090d3dff8e07828ae9d293c77f60d8d6e0f 100644 (file)
@@ -804,40 +804,6 @@ static const struct file_operations tegra_drm_fops = {
        .llseek = noop_llseek,
 };
 
-static u32 tegra_drm_get_vblank_counter(struct drm_device *drm,
-                                       unsigned int pipe)
-{
-       struct drm_crtc *crtc = drm_crtc_from_index(drm, pipe);
-       struct tegra_dc *dc = to_tegra_dc(crtc);
-
-       if (!crtc)
-               return 0;
-
-       return tegra_dc_get_vblank_counter(dc);
-}
-
-static int tegra_drm_enable_vblank(struct drm_device *drm, unsigned int pipe)
-{
-       struct drm_crtc *crtc = drm_crtc_from_index(drm, pipe);
-       struct tegra_dc *dc = to_tegra_dc(crtc);
-
-       if (!crtc)
-               return -ENODEV;
-
-       tegra_dc_enable_vblank(dc);
-
-       return 0;
-}
-
-static void tegra_drm_disable_vblank(struct drm_device *drm, unsigned int pipe)
-{
-       struct drm_crtc *crtc = drm_crtc_from_index(drm, pipe);
-       struct tegra_dc *dc = to_tegra_dc(crtc);
-
-       if (crtc)
-               tegra_dc_disable_vblank(dc);
-}
-
 static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file)
 {
        struct tegra_drm_file *fpriv = file->driver_priv;
@@ -905,10 +871,6 @@ static struct drm_driver tegra_drm_driver = {
        .preclose = tegra_drm_preclose,
        .lastclose = tegra_drm_lastclose,
 
-       .get_vblank_counter = tegra_drm_get_vblank_counter,
-       .enable_vblank = tegra_drm_enable_vblank,
-       .disable_vblank = tegra_drm_disable_vblank,
-
 #if defined(CONFIG_DEBUG_FS)
        .debugfs_init = tegra_debugfs_init,
 #endif
index 5205790dd6798a9997254f557f906e56f4bfa89c..5747accb2271a0dc854a434e18ea883870d6313a 100644 (file)
@@ -193,9 +193,6 @@ struct tegra_dc_window {
 };
 
 /* from dc.c */
-u32 tegra_dc_get_vblank_counter(struct tegra_dc *dc);
-void tegra_dc_enable_vblank(struct tegra_dc *dc);
-void tegra_dc_disable_vblank(struct tegra_dc *dc);
 void tegra_dc_commit(struct tegra_dc *dc);
 int tegra_dc_state_setup_clock(struct tegra_dc *dc,
                               struct drm_crtc_state *crtc_state,
index f142f6a4db252a91402305829c91a9b10754a69b..c61d67d16ce398ce2252e4df720c443ce2752630 100644 (file)
@@ -235,7 +235,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
                dev_err(drm->dev, "failed to allocate DRM framebuffer: %d\n",
                        err);
                drm_gem_object_unreference_unlocked(&bo->gem);
-               goto release;
+               return PTR_ERR(fbdev->fb);
        }
 
        fb = &fbdev->fb->base;
@@ -272,8 +272,6 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
 
 destroy:
        drm_framebuffer_remove(fb);
-release:
-       drm_fb_helper_release_fbi(helper);
        return err;
 }
 
@@ -339,7 +337,6 @@ fini:
 static void tegra_fbdev_exit(struct tegra_fbdev *fbdev)
 {
        drm_fb_helper_unregister_fbi(&fbdev->base);
-       drm_fb_helper_release_fbi(&fbdev->base);
 
        if (fbdev->fb)
                drm_framebuffer_remove(&fbdev->fb->base);
index f80bf9385e412db766424bf00cacd76458a64a8e..93505bcfdf4b0aa21bd8a7aee8a473dd87dc75da 100644 (file)
@@ -695,6 +695,15 @@ static int tilcdc_crtc_atomic_check(struct drm_crtc *crtc,
        return 0;
 }
 
+static int tilcdc_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+       return 0;
+}
+
+static void tilcdc_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+}
+
 static const struct drm_crtc_funcs tilcdc_crtc_funcs = {
        .destroy        = tilcdc_crtc_destroy,
        .set_config     = drm_atomic_helper_set_config,
@@ -702,6 +711,8 @@ static const struct drm_crtc_funcs tilcdc_crtc_funcs = {
        .reset          = drm_atomic_helper_crtc_reset,
        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+       .enable_vblank  = tilcdc_crtc_enable_vblank,
+       .disable_vblank = tilcdc_crtc_disable_vblank,
 };
 
 static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = {
index 372d86fbb093865816845331aea01651a6e6f1c0..81d80a2ffeb10114093579d20794b6ee593bb85f 100644 (file)
@@ -437,16 +437,6 @@ static irqreturn_t tilcdc_irq(int irq, void *arg)
        return tilcdc_crtc_irq(priv->crtc);
 }
 
-static int tilcdc_enable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-       return 0;
-}
-
-static void tilcdc_disable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-       return;
-}
-
 #if defined(CONFIG_DEBUG_FS)
 static const struct {
        const char *name;
@@ -557,9 +547,6 @@ static struct drm_driver tilcdc_driver = {
                               DRIVER_PRIME | DRIVER_ATOMIC),
        .lastclose          = tilcdc_lastclose,
        .irq_handler        = tilcdc_irq,
-       .get_vblank_counter = drm_vblank_no_hw_counter,
-       .enable_vblank      = tilcdc_enable_vblank,
-       .disable_vblank     = tilcdc_disable_vblank,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_vm_ops         = &drm_gem_cma_vm_ops,
        .dumb_create        = drm_gem_cma_dumb_create,
index 3ccda6c1e159365b89825edf927af6a56e1e45d3..d4cda3308ac72b4a1d1858a16b98a8b3d214da3d 100644 (file)
@@ -451,7 +451,7 @@ int tinydrm_spi_transfer(struct spi_device *spi, u32 speed_hz,
                ret = spi_sync(spi, &m);
                if (ret)
                        return ret;
-       };
+       }
 
        return 0;
 }
index 17478f38dea35b933ce95bb8e2d52874aed277e3..dca2e809a9706ba540943d4aa747022e7368051c 100644 (file)
@@ -982,7 +982,7 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
        }
 
        if (!type_found) {
-               printk(KERN_ERR TTM_PFX "No compatible memory type found.\n");
+               pr_err(TTM_PFX "No compatible memory type found\n");
                return -EINVAL;
        }
 
index 8e8d60e9a1a26ba512932d865fac63cc3c476eb3..d05abc69e305ce896ffc823fcc74297fb2660f78 100644 (file)
@@ -381,7 +381,7 @@ static int udlfb_create(struct drm_fb_helper *helper,
 
        ret = udl_framebuffer_init(dev, &ufbdev->ufb, &mode_cmd, obj);
        if (ret)
-               goto out_destroy_fbi;
+               goto out_gfree;
 
        fb = &ufbdev->ufb.base;
 
@@ -403,8 +403,6 @@ static int udlfb_create(struct drm_fb_helper *helper,
                      ufbdev->ufb.obj->vmapping);
 
        return ret;
-out_destroy_fbi:
-       drm_fb_helper_release_fbi(helper);
 out_gfree:
        drm_gem_object_unreference_unlocked(&ufbdev->ufb.obj->base);
 out:
@@ -419,7 +417,6 @@ static void udl_fbdev_destroy(struct drm_device *dev,
                              struct udl_fbdev *ufbdev)
 {
        drm_fb_helper_unregister_fbi(&ufbdev->helper);
-       drm_fb_helper_release_fbi(&ufbdev->helper);
        drm_fb_helper_fini(&ufbdev->helper);
        drm_framebuffer_unregister_private(&ufbdev->ufb.base);
        drm_framebuffer_cleanup(&ufbdev->ufb.base);
index 3f6704cf6608d7be47637c6aa585de087b7f74ee..af29432a6471a1063da5e0611430052c754a8a16 100644 (file)
@@ -6,7 +6,8 @@
  * published by the Free Software Foundation.
  */
 
-/* DOC: VC4 GEM BO management support.
+/**
+ * DOC: VC4 GEM BO management support
  *
  * The VC4 GPU architecture (both scanout and rendering) has direct
  * access to system memory with no MMU in between.  To support it, we
@@ -186,6 +187,8 @@ out:
 
 /**
  * vc4_gem_create_object - Implementation of driver->gem_create_object.
+ * @dev: DRM device
+ * @size: Size in bytes of the memory the object will reference
  *
  * This lets the CMA helpers allocate object structs for us, and keep
  * our BO stats correct.
@@ -208,21 +211,22 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size)
 }
 
 struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size,
-                            bool from_cache)
+                            bool allow_unzeroed)
 {
        size_t size = roundup(unaligned_size, PAGE_SIZE);
        struct vc4_dev *vc4 = to_vc4_dev(dev);
        struct drm_gem_cma_object *cma_obj;
+       struct vc4_bo *bo;
 
        if (size == 0)
                return ERR_PTR(-EINVAL);
 
        /* First, try to get a vc4_bo from the kernel BO cache. */
-       if (from_cache) {
-               struct vc4_bo *bo = vc4_bo_get_from_cache(dev, size);
-
-               if (bo)
-                       return bo;
+       bo = vc4_bo_get_from_cache(dev, size);
+       if (bo) {
+               if (!allow_unzeroed)
+                       memset(bo->base.vaddr, 0, bo->base.base.size);
+               return bo;
        }
 
        cma_obj = drm_gem_cma_create(dev, size);
@@ -313,6 +317,14 @@ void vc4_free_object(struct drm_gem_object *gem_bo)
                goto out;
        }
 
+       /* If this object was partially constructed but CMA allocation
+        * had failed, just free it.
+        */
+       if (!bo->base.vaddr) {
+               vc4_bo_destroy(bo);
+               goto out;
+       }
+
        cache_list = vc4_get_cache_list_for_size(dev, gem_bo->size);
        if (!cache_list) {
                vc4_bo_destroy(bo);
index 0c06844af4455d6319e83c183fbbd594e61cd678..24edd0c22cc9b6094395e213e6cceeafa17c0678 100644 (file)
  *
  * In VC4, the Pixel Valve is what most closely corresponds to the
  * DRM's concept of a CRTC.  The PV generates video timings from the
- * output's clock plus its configuration.  It pulls scaled pixels from
+ * encoder's clock plus its configuration.  It pulls scaled pixels from
  * the HVS at that timing, and feeds it to the encoder.
  *
  * However, the DRM CRTC also collects the configuration of all the
- * DRM planes attached to it.  As a result, this file also manages
- * setup of the VC4 HVS's display elements on the CRTC.
+ * DRM planes attached to it.  As a result, the CRTC is also
+ * responsible for writing the display list for the HVS channel that
+ * the CRTC will use.
  *
  * The 2835 has 3 different pixel valves.  pv0 in the audio power
  * domain feeds DSI0 or DPI, while pv1 feeds DS1 or SMI.  pv2 in the
@@ -654,9 +655,8 @@ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
        }
 }
 
-int vc4_enable_vblank(struct drm_device *dev, unsigned int crtc_id)
+static int vc4_enable_vblank(struct drm_crtc *crtc)
 {
-       struct drm_crtc *crtc = drm_crtc_from_index(dev, crtc_id);
        struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 
        CRTC_WRITE(PV_INTEN, PV_INT_VFP_START);
@@ -664,9 +664,8 @@ int vc4_enable_vblank(struct drm_device *dev, unsigned int crtc_id)
        return 0;
 }
 
-void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id)
+static void vc4_disable_vblank(struct drm_crtc *crtc)
 {
-       struct drm_crtc *crtc = drm_crtc_from_index(dev, crtc_id);
        struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 
        CRTC_WRITE(PV_INTEN, 0);
@@ -857,6 +856,8 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = {
        .atomic_duplicate_state = vc4_crtc_duplicate_state,
        .atomic_destroy_state = vc4_crtc_destroy_state,
        .gamma_set = vc4_crtc_gamma_set,
+       .enable_vblank = vc4_enable_vblank,
+       .disable_vblank = vc4_disable_vblank,
 };
 
 static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
index 1e1f6b8184d058c6e55e092653798f4d75b55b7f..71435796c7100a65884013d479f4e446025c217e 100644 (file)
@@ -18,7 +18,8 @@
  * DOC: VC4 DPI module
  *
  * The VC4 DPI hardware supports MIPI DPI type 4 and Nokia ViSSI
- * signals, which are routed out to GPIO0-27 with the ALT2 function.
+ * signals.  On BCM2835, these can be routed out to GPIO0-27 with the
+ * ALT2 function.
  */
 
 #include "drm_atomic_helper.h"
@@ -144,17 +145,6 @@ static const struct {
        DPI_REG(DPI_ID),
 };
 
-static void vc4_dpi_dump_regs(struct vc4_dpi *dpi)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(dpi_regs); i++) {
-               DRM_INFO("0x%04x (%s): 0x%08x\n",
-                        dpi_regs[i].reg, dpi_regs[i].name,
-                        DPI_READ(dpi_regs[i].reg));
-       }
-}
-
 #ifdef CONFIG_DEBUG_FS
 int vc4_dpi_debugfs_regs(struct seq_file *m, void *unused)
 {
@@ -416,8 +406,6 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data)
        if (IS_ERR(dpi->regs))
                return PTR_ERR(dpi->regs);
 
-       vc4_dpi_dump_regs(dpi);
-
        if (DPI_READ(DPI_ID) != DPI_ID_VALUE) {
                dev_err(dev, "Port returned 0x%08x for ID instead of 0x%08x\n",
                        DPI_READ(DPI_ID), DPI_ID_VALUE);
index a459745e96f7bb1f81b24077042da4c0c0063525..205c1961ffb4c08b574724de32bc9814d116f63e 100644 (file)
@@ -7,6 +7,22 @@
  * published by the Free Software Foundation.
  */
 
+/**
+ * DOC: Broadcom VC4 Graphics Driver
+ *
+ * The Broadcom VideoCore 4 (present in the Raspberry Pi) contains a
+ * OpenGL ES 2.0-compatible 3D engine called V3D, and a highly
+ * configurable display output pipeline that supports HDMI, DSI, DPI,
+ * and Composite TV output.
+ *
+ * The 3D engine also has an interface for submitting arbitrary
+ * compute shader-style jobs using the same shader processor as is
+ * used for vertex and fragment shaders in GLES 2.0.  However, given
+ * that the hardware isn't able to expose any standard interfaces like
+ * OpenGL compute shaders or OpenCL, it isn't supported by this
+ * driver.
+ */
+
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/device.h>
@@ -137,9 +153,6 @@ static struct drm_driver vc4_drm_driver = {
        .irq_postinstall = vc4_irq_postinstall,
        .irq_uninstall = vc4_irq_uninstall,
 
-       .enable_vblank = vc4_enable_vblank,
-       .disable_vblank = vc4_disable_vblank,
-       .get_vblank_counter = drm_vblank_no_hw_counter,
        .get_scanout_position = vc4_crtc_get_scanoutpos,
        .get_vblank_timestamp = vc4_crtc_get_vblank_timestamp,
 
index 0e59f3ee1b8344505a8f9d1e3abd478cee3dd37a..dffce6293d875416e38a7c722a1e26dc925f4bf5 100644 (file)
@@ -444,8 +444,6 @@ int vc4_bo_stats_debugfs(struct seq_file *m, void *arg);
 
 /* vc4_crtc.c */
 extern struct platform_driver vc4_crtc_driver;
-int vc4_enable_vblank(struct drm_device *dev, unsigned int crtc_id);
-void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id);
 bool vc4_event_pending(struct drm_crtc *crtc);
 int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg);
 int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
index 2736b0331bebdf564681eaf7ae947a19e5c0fb2e..160f981d1cf49d2655bdeab730067d7bff2e8c1a 100644 (file)
@@ -771,16 +771,14 @@ static const struct drm_connector_helper_funcs vc4_dsi_connector_helper_funcs =
 static struct drm_connector *vc4_dsi_connector_init(struct drm_device *dev,
                                                    struct vc4_dsi *dsi)
 {
-       struct drm_connector *connector = NULL;
+       struct drm_connector *connector;
        struct vc4_dsi_connector *dsi_connector;
-       int ret = 0;
 
        dsi_connector = devm_kzalloc(dev->dev, sizeof(*dsi_connector),
                                     GFP_KERNEL);
-       if (!dsi_connector) {
-               ret = -ENOMEM;
-               goto fail;
-       }
+       if (!dsi_connector)
+               return ERR_PTR(-ENOMEM);
+
        connector = &dsi_connector->base;
 
        dsi_connector->dsi = dsi;
@@ -796,12 +794,6 @@ static struct drm_connector *vc4_dsi_connector_init(struct drm_device *dev,
        drm_mode_connector_attach_encoder(connector, dsi->encoder);
 
        return connector;
-
-fail:
-       if (connector)
-               vc4_dsi_connector_destroy(connector);
-
-       return ERR_PTR(ret);
 }
 
 static void vc4_dsi_encoder_destroy(struct drm_encoder *encoder)
@@ -1461,8 +1453,9 @@ static irqreturn_t vc4_dsi_irq_handler(int irq, void *data)
 }
 
 /**
- * Exposes clocks generated by the analog PHY that are consumed by
- * CPRMAN (clk-bcm2835.c).
+ * vc4_dsi_init_phy_clocks - Exposes clocks generated by the analog
+ * PHY that are consumed by CPRMAN (clk-bcm2835.c).
+ * @dsi: DSI encoder
  */
 static int
 vc4_dsi_init_phy_clocks(struct vc4_dsi *dsi)
index 1eef98c3331dfc270d5c9934648c17dfa4dc0433..e9c381c42139573ff0d62c1d14318a05386842e6 100644 (file)
@@ -512,9 +512,18 @@ vc4_queue_submit(struct drm_device *dev, struct vc4_exec_info *exec)
 }
 
 /**
- * Looks up a bunch of GEM handles for BOs and stores the array for
- * use in the command validator that actually writes relocated
- * addresses pointing to them.
+ * vc4_cl_lookup_bos() - Sets up exec->bo[] with the GEM objects
+ * referenced by the job.
+ * @dev: DRM device
+ * @file_priv: DRM file for this fd
+ * @exec: V3D job being set up
+ *
+ * The command validator needs to reference BOs by their index within
+ * the submitted job's BO list.  This does the validation of the job's
+ * BO list and reference counting for the lifetime of the job.
+ *
+ * Note that this function doesn't need to unreference the BOs on
+ * failure, because that will happen at vc4_complete_exec() time.
  */
 static int
 vc4_cl_lookup_bos(struct drm_device *dev,
@@ -847,9 +856,16 @@ vc4_wait_bo_ioctl(struct drm_device *dev, void *data,
 }
 
 /**
- * Submits a command list to the VC4.
+ * vc4_submit_cl_ioctl() - Submits a job (frame) to the VC4.
+ * @dev: DRM device
+ * @data: ioctl argument
+ * @file_priv: DRM file for this fd
  *
- * This is what is called batchbuffer emitting on other hardware.
+ * This is the main entrypoint for userspace to submit a 3D frame to
+ * the GPU.  Userspace provides the binner command list (if
+ * applicable), and the kernel sets up the render command list to draw
+ * to the framebuffer described in the ioctl, using the command lists
+ * that the 3D engine's binner will produce.
  */
 int
 vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
index 93d5994f3a044b1e2ceda5a1ccaec56ca5915778..1be1e83047207b637b158947f24c2942146eeed0 100644 (file)
 /**
  * DOC: VC4 Falcon HDMI module
  *
- * The HDMI core has a state machine and a PHY.  Most of the unit
- * operates off of the HSM clock from CPRMAN.  It also internally uses
- * the PLLH_PIX clock for the PHY.
+ * The HDMI core has a state machine and a PHY.  On BCM2835, most of
+ * the unit operates off of the HSM clock from CPRMAN.  It also
+ * internally uses the PLLH_PIX clock for the PHY.
+ *
+ * HDMI infoframes are kept within a small packet ram, where each
+ * packet can be individually enabled for including in a frame.
+ *
+ * HDMI audio is implemented entirely within the HDMI IP block.  A
+ * register in the HDMI encoder takes SPDIF frames from the DMA engine
+ * and transfers them over an internal MAI (multi-channel audio
+ * interconnect) bus to the encoder side for insertion into the video
+ * blank regions.
+ *
+ * The driver's HDMI encoder does not yet support power management.
+ * The HDMI encoder's power domain and the HSM/pixel clocks are kept
+ * continuously running, and only the HDMI logic and packet ram are
+ * powered off/on at disable/enable time.
+ *
+ * The driver does not yet support CEC control, though the HDMI
+ * encoder block has CEC support.
  */
 
 #include "drm_atomic_helper.h"
index f7f7677f6d8d72b62ed91c7d7e23dbe92a8506f2..fd421ba3c5d7a94a177cc211a599bab9dade76df 100644 (file)
@@ -9,12 +9,12 @@
 /**
  * DOC: VC4 HVS module.
  *
- * The HVS is the piece of hardware that does translation, scaling,
- * colorspace conversion, and compositing of pixels stored in
- * framebuffers into a FIFO of pixels going out to the Pixel Valve
- * (CRTC).  It operates at the system clock rate (the system audio
- * clock gate, specifically), which is much higher than the pixel
- * clock rate.
+ * The Hardware Video Scaler (HVS) is the piece of hardware that does
+ * translation, scaling, colorspace conversion, and compositing of
+ * pixels stored in framebuffers into a FIFO of pixels going out to
+ * the Pixel Valve (CRTC).  It operates at the system clock rate (the
+ * system audio clock gate, specifically), which is much higher than
+ * the pixel clock rate.
  *
  * There is a single global HVS, with multiple output FIFOs that can
  * be consumed by the PVs.  This file just manages the resources for
index 094bc6a475c1773923dfe8225cba9886fc9e5026..cdc6e67607056f06e5730cac05f46a19a4516ae1 100644 (file)
@@ -21,7 +21,8 @@
  * IN THE SOFTWARE.
  */
 
-/** DOC: Interrupt management for the V3D engine.
+/**
+ * DOC: Interrupt management for the V3D engine
  *
  * We have an interrupt status register (V3D_INTCTL) which reports
  * interrupts, and where writing 1 bits clears those interrupts.
index f7a229df572d52c775b03528fe0d02c440f5b925..110224c3a3ac13a070f607c9f7cffa66a5984d97 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "vc4_drv.h"
 #include "vc4_regs.h"
+#include "drm_atomic.h"
 #include "drm_atomic_helper.h"
 #include "drm_fb_cma_helper.h"
 #include "drm_plane_helper.h"
@@ -769,12 +770,6 @@ vc4_update_plane(struct drm_plane *plane,
        if (!plane_state)
                goto out;
 
-       /* If we're changing the cursor contents, do that in the
-        * normal vblank-synced atomic path.
-        */
-       if (fb != plane_state->fb)
-               goto out;
-
        /* No configuring new scaling in the fast path. */
        if (crtc_w != plane_state->crtc_w ||
            crtc_h != plane_state->crtc_h ||
@@ -783,6 +778,11 @@ vc4_update_plane(struct drm_plane *plane,
                goto out;
        }
 
+       if (fb != plane_state->fb) {
+               drm_atomic_set_fb_for_plane(plane->state, fb);
+               vc4_plane_async_set_fb(plane, fb);
+       }
+
        /* Set the cursor's position on the screen.  This is the
         * expected change from the drm_mode_cursor_universal()
         * helper.
index 5cdd003605f57c99faf31832e3f3dd38a75b7402..4339471f517f9503b3d8617dce12b6bbd74b03fb 100644 (file)
 /**
  * DOC: Render command list generation
  *
+ * In the V3D hardware, render command lists are what load and store
+ * tiles of a framebuffer and optionally call out to binner-generated
+ * command lists to do the 3D drawing for that tile.
+ *
  * In the VC4 driver, render command list generation is performed by the
  * kernel instead of userspace.  We do this because validating a
  * user-submitted command list is hard to get right and has high CPU overhead,
index 9fd171c361c23b52a4d507919ec7e26fd1e87aac..da6f1e138e8d1252180e9fe1e70d9c1483524636 100644 (file)
  */
 
 /**
- * Command list validator for VC4.
+ * DOC: Command list validator for VC4.
  *
- * The VC4 has no IOMMU between it and system memory.  So, a user with
- * access to execute command lists could escalate privilege by
+ * Since the VC4 has no IOMMU between it and system memory, a user
+ * with access to execute command lists could escalate privilege by
  * overwriting system memory (drawing to it as a framebuffer) or
- * reading system memory it shouldn't (reading it as a texture, or
- * uniform data, or vertex data).
+ * reading system memory it shouldn't (reading it as a vertex buffer
+ * or index buffer)
  *
- * This validates command lists to ensure that all accesses are within
- * the bounds of the GEM objects referenced.  It explicitly whitelists
- * packets, and looks at the offsets in any address fields to make
- * sure they're constrained within the BOs they reference.
+ * We validate binner command lists to ensure that all accesses are
+ * within the bounds of the GEM objects referenced by the submitted
+ * job.  It explicitly whitelists packets, and looks at the offsets in
+ * any address fields to make sure they're contained within the BOs
+ * they reference.
  *
- * Note that because of the validation that's happening anyway, this
- * is where GEM relocation processing happens.
+ * Note that because CL validation is already reading the
+ * user-submitted CL and writing the validated copy out to the memory
+ * that the GPU will actually read, this is also where GEM relocation
+ * processing (turning BO references into actual addresses for the GPU
+ * to use) happens.
  */
 
 #include "uapi/drm/vc4_drm.h"
@@ -84,8 +88,12 @@ utile_height(int cpp)
 }
 
 /**
- * The texture unit decides what tiling format a particular miplevel is using
- * this function, so we lay out our miptrees accordingly.
+ * size_is_lt() - Returns whether a miplevel of the given size will
+ * use the lineartile (LT) tiling layout rather than the normal T
+ * tiling layout.
+ * @width: Width in pixels of the miplevel
+ * @height: Height in pixels of the miplevel
+ * @cpp: Bytes per pixel of the pixel format
  */
 static bool
 size_is_lt(uint32_t width, uint32_t height, int cpp)
index 5dba13dd1e9b600b43a769d086d6eb428547ab66..0b2df5c6efb4a931cdb6bb9973d8d9ed2198298a 100644 (file)
 /**
  * DOC: Shader validator for VC4.
  *
- * The VC4 has no IOMMU between it and system memory, so a user with
- * access to execute shaders could escalate privilege by overwriting
- * system memory (using the VPM write address register in the
- * general-purpose DMA mode) or reading system memory it shouldn't
- * (reading it as a texture, or uniform data, or vertex data).
+ * Since the VC4 has no IOMMU between it and system memory, a user
+ * with access to execute shaders could escalate privilege by
+ * overwriting system memory (using the VPM write address register in
+ * the general-purpose DMA mode) or reading system memory it shouldn't
+ * (reading it as a texture, uniform data, or direct-addressed TMU
+ * lookup).
  *
- * This walks over a shader BO, ensuring that its accesses are
- * appropriately bounded, and recording how many texture accesses are
- * made and where so that we can do relocations for them in the
+ * The shader validator walks over a shader's BO, ensuring that its
+ * accesses are appropriately bounded, and recording where texture
+ * accesses are made so that we can do relocations for them in the
  * uniform stream.
+ *
+ * Shader BO are immutable for their lifetimes (enforced by not
+ * allowing mmaps, GEM prime export, or rendering to from a CL), so
+ * this validation is only performed at BO creation time.
  */
 
 #include "vc4_drv.h"
index 32bb8ef985fbc6f39f9e5f459846bb779b80c9e8..09c1e05765fa7ea8b64dac9ca21a612d93db82e6 100644 (file)
 
 /**
  * DOC: VC4 SDTV module
+ *
+ * The VEC encoder generates PAL or NTSC composite video output.
+ *
+ * TV mode selection is done by an atomic property on the encoder,
+ * because a drm_mode_modeinfo is insufficient to distinguish between
+ * PAL and PAL-M or NTSC and NTSC-J.
  */
 
 #include <drm/drm_atomic_helper.h>
index 1a3ad769f8c85bc0506741d105669dd66013b533..98aae9809249d6b8e897239c81e4c44925ca62db 100644 (file)
@@ -238,13 +238,9 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg,  drm_via_dmablit_t *xfer)
        vsg->pages = vzalloc(sizeof(struct page *) * vsg->num_pages);
        if (NULL == vsg->pages)
                return -ENOMEM;
-       down_read(&current->mm->mmap_sem);
-       ret = get_user_pages((unsigned long)xfer->mem_addr,
-                            vsg->num_pages,
-                            (vsg->direction == DMA_FROM_DEVICE) ? FOLL_WRITE : 0,
-                            vsg->pages, NULL);
-
-       up_read(&current->mm->mmap_sem);
+       ret = get_user_pages_unlocked((unsigned long)xfer->mem_addr,
+                       vsg->num_pages, vsg->pages,
+                       (vsg->direction == DMA_FROM_DEVICE) ? FOLL_WRITE : 0);
        if (ret != vsg->num_pages) {
                if (ret < 0)
                        return ret;
index 512263919282328cb55505abf2542987c5f9f9cd..f51240aa720d628fdaa7aa1e7e3c4d378d114f05 100644 (file)
@@ -54,11 +54,3 @@ virtio_gpu_debugfs_init(struct drm_minor *minor)
                                 minor->debugfs_root, minor);
        return 0;
 }
-
-void
-virtio_gpu_debugfs_takedown(struct drm_minor *minor)
-{
-       drm_debugfs_remove_files(virtio_gpu_debugfs_list,
-                                VIRTIO_GPU_DEBUGFS_ENTRIES,
-                                minor);
-}
index fad5a1cc59037367bca7433fd55fa78d606022a4..d51bd4521f170df0ab60472892fb013ff9989c42 100644 (file)
@@ -347,7 +347,7 @@ static void vgdev_atomic_commit_tail(struct drm_atomic_state *state)
        drm_atomic_helper_cleanup_planes(dev, state);
 }
 
-static struct drm_mode_config_helper_funcs virtio_mode_config_helpers = {
+static const struct drm_mode_config_helper_funcs virtio_mode_config_helpers = {
        .atomic_commit_tail = vgdev_atomic_commit_tail,
 };
 
index d824898150961b872db90c9b43ceffa11dac0e3a..2d29b014154511149a1b8c1a2b84dbfebcab89bf 100644 (file)
@@ -126,7 +126,6 @@ static struct drm_driver driver = {
 
 #if defined(CONFIG_DEBUG_FS)
        .debugfs_init = virtio_gpu_debugfs_init,
-       .debugfs_cleanup = virtio_gpu_debugfs_takedown,
 #endif
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
index 2f766735c16d56ebad7ca57f8846996ca59f3eea..d59f68936306d75d99f06a30a9b3048ad32c7927 100644 (file)
@@ -422,6 +422,5 @@ static inline void virtio_gpu_object_unreserve(struct virtio_gpu_object *bo)
 
 /* virgl debufs */
 int virtio_gpu_debugfs_init(struct drm_minor *minor);
-void virtio_gpu_debugfs_takedown(struct drm_minor *minor);
 
 #endif
index 163a67db8cf1e27f94af0457a9dc30f641435506..9bfaef3794697de30c6d44aa1c24359231dd6cba 100644 (file)
@@ -320,7 +320,7 @@ static int virtio_gpufb_create(struct drm_fb_helper *helper,
        ret = virtio_gpu_framebuffer_init(dev, &vfbdev->vgfb,
                                          &mode_cmd, &obj->gem_base);
        if (ret)
-               goto err_fb_init;
+               goto err_fb_alloc;
 
        fb = &vfbdev->vgfb.base;
 
@@ -341,8 +341,6 @@ static int virtio_gpufb_create(struct drm_fb_helper *helper,
        info->fix.mmio_len = 0;
        return 0;
 
-err_fb_init:
-       drm_fb_helper_release_fbi(helper);
 err_fb_alloc:
        virtio_gpu_cmd_resource_inval_backing(vgdev, resid);
 err_obj_attach:
@@ -357,7 +355,6 @@ static int virtio_gpu_fbdev_destroy(struct drm_device *dev,
        struct virtio_gpu_framebuffer *vgfb = &vgfbdev->vgfb;
 
        drm_fb_helper_unregister_fbi(&vgfbdev->helper);
-       drm_fb_helper_release_fbi(&vgfbdev->helper);
 
        if (vgfb->obj)
                vgfb->obj = NULL;
index 11288ffa4af68fc5eb9557026d9a511c6ea1a63c..1ff9c64c9ec068f97ce54f9eaba6bf0bfde4ec62 100644 (file)
@@ -44,6 +44,7 @@ static const uint32_t virtio_gpu_cursor_formats[] = {
 
 static void virtio_gpu_plane_destroy(struct drm_plane *plane)
 {
+       drm_plane_cleanup(plane);
        kfree(plane);
 }
 
index 6541dd8b82dc0747433403b64795843a29e0544c..b399f03a988d8e6a6b2af5995c2bb4fdbd07a054 100644 (file)
@@ -728,8 +728,7 @@ int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
 
        base = ttm_base_object_lookup(tfile, arg->handle);
        if (unlikely(base == NULL)) {
-               printk(KERN_ERR "Wait invalid fence object handle "
-                      "0x%08lx.\n",
+               pr_err("Wait invalid fence object handle 0x%08lx\n",
                       (unsigned long)arg->handle);
                return -EINVAL;
        }
@@ -773,8 +772,7 @@ int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data,
 
        base = ttm_base_object_lookup(tfile, arg->handle);
        if (unlikely(base == NULL)) {
-               printk(KERN_ERR "Fence signaled invalid fence object handle "
-                      "0x%08lx.\n",
+               pr_err("Fence signaled invalid fence object handle 0x%08lx\n",
                       (unsigned long)arg->handle);
                return -EINVAL;
        }
index fec7348cea2cbed0c79f10b89af773cbbc1400cf..c1900f4390a41efbf5a613fb6f451d391e336fed 100644 (file)
@@ -159,8 +159,7 @@ static int vmw_gmrid_man_takedown(struct ttm_mem_type_manager *man)
 static void vmw_gmrid_man_debug(struct ttm_mem_type_manager *man,
                                const char *prefix)
 {
-       printk(KERN_INFO "%s: No debug info available for the GMR "
-              "id manager.\n", prefix);
+       pr_info("%s: No debug info available for the GMR id manager\n", prefix);
 }
 
 const struct ttm_mem_type_manager_func vmw_gmrid_manager_func = {
index 65b3f0369636710eda49086f72e250478dfe288d..27033d944b0899afa3942e1fe12e8a2ab5745847 100644 (file)
@@ -736,14 +736,14 @@ int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
 
        base = ttm_base_object_lookup(tfile, handle);
        if (unlikely(base == NULL)) {
-               printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n",
+               pr_err("Invalid buffer object handle 0x%08lx\n",
                       (unsigned long)handle);
                return -ESRCH;
        }
 
        if (unlikely(ttm_base_object_type(base) != ttm_buffer_type)) {
                ttm_base_object_unref(&base);
-               printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n",
+               pr_err("Invalid buffer object handle 0x%08lx\n",
                       (unsigned long)handle);
                return -EINVAL;
        }
index 5c6944a1e72c3fa31340d189abb4be6aac168cb5..b24a70ba4b839fd488be2f0b9883b5c6d8418736 100644 (file)
@@ -71,9 +71,6 @@ static struct drm_driver zx_drm_driver = {
        .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
                           DRIVER_ATOMIC,
        .lastclose = zx_drm_lastclose,
-       .get_vblank_counter = drm_vblank_no_hw_counter,
-       .enable_vblank = zx_vou_enable_vblank,
-       .disable_vblank = zx_vou_disable_vblank,
        .gem_free_object = drm_gem_cma_free_object,
        .gem_vm_ops = &drm_gem_cma_vm_ops,
        .dumb_create = drm_gem_cma_dumb_create,
index cf92d675feaac903e394333aab4fe3a5b8ec6996..b500c8dd0d9d697612f07a851fab4e784f23f8a1 100644 (file)
@@ -470,6 +470,27 @@ static const struct drm_crtc_helper_funcs zx_crtc_helper_funcs = {
        .atomic_flush = zx_crtc_atomic_flush,
 };
 
+static int zx_vou_enable_vblank(struct drm_crtc *crtc)
+{
+       struct zx_crtc *zcrtc = to_zx_crtc(crtc);
+       struct zx_vou_hw *vou = crtc_to_vou(crtc);
+       u32 int_frame_mask = zcrtc->bits->int_frame_mask;
+
+       zx_writel_mask(vou->timing + TIMING_INT_CTRL, int_frame_mask,
+                      int_frame_mask);
+
+       return 0;
+}
+
+static void zx_vou_disable_vblank(struct drm_crtc *crtc)
+{
+       struct zx_crtc *zcrtc = to_zx_crtc(crtc);
+       struct zx_vou_hw *vou = crtc_to_vou(crtc);
+
+       zx_writel_mask(vou->timing + TIMING_INT_CTRL,
+                      zcrtc->bits->int_frame_mask, 0);
+}
+
 static const struct drm_crtc_funcs zx_crtc_funcs = {
        .destroy = drm_crtc_cleanup,
        .set_config = drm_atomic_helper_set_config,
@@ -477,6 +498,8 @@ static const struct drm_crtc_funcs zx_crtc_funcs = {
        .reset = drm_atomic_helper_crtc_reset,
        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+       .enable_vblank = zx_vou_enable_vblank,
+       .disable_vblank = zx_vou_disable_vblank,
 };
 
 static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
@@ -553,44 +576,6 @@ static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
        return 0;
 }
 
-int zx_vou_enable_vblank(struct drm_device *drm, unsigned int pipe)
-{
-       struct drm_crtc *crtc;
-       struct zx_crtc *zcrtc;
-       struct zx_vou_hw *vou;
-       u32 int_frame_mask;
-
-       crtc = drm_crtc_from_index(drm, pipe);
-       if (!crtc)
-               return 0;
-
-       vou = crtc_to_vou(crtc);
-       zcrtc = to_zx_crtc(crtc);
-       int_frame_mask = zcrtc->bits->int_frame_mask;
-
-       zx_writel_mask(vou->timing + TIMING_INT_CTRL, int_frame_mask,
-                      int_frame_mask);
-
-       return 0;
-}
-
-void zx_vou_disable_vblank(struct drm_device *drm, unsigned int pipe)
-{
-       struct drm_crtc *crtc;
-       struct zx_crtc *zcrtc;
-       struct zx_vou_hw *vou;
-
-       crtc = drm_crtc_from_index(drm, pipe);
-       if (!crtc)
-               return;
-
-       vou = crtc_to_vou(crtc);
-       zcrtc = to_zx_crtc(crtc);
-
-       zx_writel_mask(vou->timing + TIMING_INT_CTRL,
-                      zcrtc->bits->int_frame_mask, 0);
-}
-
 void zx_vou_layer_enable(struct drm_plane *plane)
 {
        struct zx_crtc *zcrtc = to_zx_crtc(plane->state->crtc);
index 57e3c31ee6a5ab6aed1eff7bdb89d2d6897eb0a7..97d72bfce982cdc4c0481fca4db87a8f050e1e3a 100644 (file)
@@ -61,9 +61,6 @@ struct vou_div_config {
 void zx_vou_config_dividers(struct drm_crtc *crtc,
                            struct vou_div_config *configs, int num);
 
-int zx_vou_enable_vblank(struct drm_device *drm, unsigned int pipe);
-void zx_vou_disable_vblank(struct drm_device *drm, unsigned int pipe);
-
 void zx_vou_layer_enable(struct drm_plane *plane);
 void zx_vou_layer_disable(struct drm_plane *plane);
 
index 5f962bfcb43c731c54ad8a6d4c54b564a9acd6f8..3cd153c6d271a5f451c3a6e6ea7893060e4441c5 100644 (file)
  * @pwr_state: current power state
  * @ops: client callbacks
  * @id: client identifier. Determining the id requires the handler,
- *     so gpus are initially assigned VGA_SWITCHEROO_UNKNOWN_ID
- *     and later given their true id in vga_switcheroo_enable()
+ *     so gpus are initially assigned VGA_SWITCHEROO_UNKNOWN_ID
+ *     and later given their true id in vga_switcheroo_enable()
  * @active: whether the outputs are currently switched to this client
  * @driver_power_control: whether power state is controlled by the driver's
- *     runtime pm. If true, writing ON and OFF to the vga_switcheroo debugfs
- *     interface is a no-op so as not to interfere with runtime pm
+ *     runtime pm. If true, writing ON and OFF to the vga_switcheroo debugfs
+ *     interface is a no-op so as not to interfere with runtime pm
  * @list: client list
  *
  * Registered client. A client can be either a GPU or an audio device on a GPU.
@@ -126,13 +126,13 @@ static DEFINE_MUTEX(vgasr_mutex);
 /**
  * struct vgasr_priv - vga_switcheroo private data
  * @active: whether vga_switcheroo is enabled.
- *     Prerequisite is the registration of two GPUs and a handler
+ *     Prerequisite is the registration of two GPUs and a handler
  * @delayed_switch_active: whether a delayed switch is pending
  * @delayed_client_id: client to which a delayed switch is pending
  * @debugfs_root: directory for vga_switcheroo debugfs interface
  * @switch_file: file for vga_switcheroo debugfs interface
  * @registered_clients: number of registered GPUs
- *     (counting only vga clients, not audio clients)
+ *     (counting only vga clients, not audio clients)
  * @clients: list of registered clients
  * @handler: registered handler
  * @handler_flags: flags of registered handler
@@ -214,8 +214,9 @@ static void vga_switcheroo_enable(void)
  *
  * Return: 0 on success, -EINVAL if a handler was already registered.
  */
-int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler,
-                                   enum vga_switcheroo_handler_flags_t handler_flags)
+int vga_switcheroo_register_handler(
+                         const struct vga_switcheroo_handler *handler,
+                         enum vga_switcheroo_handler_flags_t handler_flags)
 {
        mutex_lock(&vgasr_mutex);
        if (vgasr_priv.handler) {
@@ -305,7 +306,7 @@ static int register_client(struct pci_dev *pdev,
  * @pdev: client pci device
  * @ops: client callbacks
  * @driver_power_control: whether power state is controlled by the driver's
- *     runtime pm
+ *     runtime pm
  *
  * Register vga client (GPU). Enable vga_switcheroo if another GPU and a
  * handler have already registered. The power state of the client is assumed
@@ -337,8 +338,8 @@ EXPORT_SYMBOL(vga_switcheroo_register_client);
  * Return: 0 on success, -ENOMEM on memory allocation error.
  */
 int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
-                                        const struct vga_switcheroo_client_ops *ops,
-                                        enum vga_switcheroo_client_id id)
+                       const struct vga_switcheroo_client_ops *ops,
+                       enum vga_switcheroo_client_id id)
 {
        return register_client(pdev, ops, id | ID_BIT_AUDIO, false, false);
 }
@@ -1084,7 +1085,8 @@ static int vga_switcheroo_runtime_resume_hdmi_audio(struct device *dev)
        int ret;
 
        /* we need to check if we have to switch back on the video
-          device so the audio device can come back */
+        * device so the audio device can come back
+        */
        mutex_lock(&vgasr_mutex);
        list_for_each_entry(client, &vgasr_priv.clients, list) {
                if (PCI_SLOT(client->pdev->devfn) == PCI_SLOT(pdev->devfn) &&
@@ -1112,7 +1114,7 @@ static int vga_switcheroo_runtime_resume_hdmi_audio(struct device *dev)
 
 /**
  * vga_switcheroo_init_domain_pm_optimus_hdmi_audio() - helper for driver
- *     power control
+ *     power control
  * @dev: audio client device
  * @domain: power domain
  *
index 5dfcc967dd052454674364b201c30d77e19485c6..45b413e5a4447fea8c5e2355f438ba6ba8de9ca7 100644 (file)
@@ -571,6 +571,77 @@ void of_platform_depopulate(struct device *parent)
 }
 EXPORT_SYMBOL_GPL(of_platform_depopulate);
 
+static void devm_of_platform_populate_release(struct device *dev, void *res)
+{
+       of_platform_depopulate(*(struct device **)res);
+}
+
+/**
+ * devm_of_platform_populate() - Populate platform_devices from device tree data
+ * @dev: device that requested to populate from device tree data
+ *
+ * Similar to of_platform_populate(), but will automatically call
+ * of_platform_depopulate() when the device is unbound from the bus.
+ *
+ * Returns 0 on success, < 0 on failure.
+ */
+int devm_of_platform_populate(struct device *dev)
+{
+       struct device **ptr;
+       int ret;
+
+       if (!dev)
+               return -EINVAL;
+
+       ptr = devres_alloc(devm_of_platform_populate_release,
+                          sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return -ENOMEM;
+
+       ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
+       if (ret) {
+               devres_free(ptr);
+       } else {
+               *ptr = dev;
+               devres_add(dev, ptr);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(devm_of_platform_populate);
+
+static int devm_of_platform_match(struct device *dev, void *res, void *data)
+{
+       struct device **ptr = res;
+
+       if (!ptr) {
+               WARN_ON(!ptr);
+               return 0;
+       }
+
+       return *ptr == data;
+}
+
+/**
+ * devm_of_platform_depopulate() - Remove devices populated from device tree
+ * @dev: device that requested to depopulate from device tree data
+ *
+ * Complementary to devm_of_platform_populate(), this function removes children
+ * of the given device (and, recurrently, their children) that have been
+ * created from their respective device tree nodes (and only those,
+ * leaving others - eg. manually created - unharmed).
+ */
+void devm_of_platform_depopulate(struct device *dev)
+{
+       int ret;
+
+       ret = devres_release(dev, devm_of_platform_populate_release,
+                            devm_of_platform_match, dev);
+
+       WARN_ON(ret);
+}
+EXPORT_SYMBOL_GPL(devm_of_platform_depopulate);
+
 #ifdef CONFIG_OF_DYNAMIC
 static int of_platform_notify(struct notifier_block *nb,
                                unsigned long action, void *arg)
index 052ab161b239275cf8bc29891fa75ed0d9e1227e..c6f355a970d26e3b55c6b0706166560b5cbcc478 100644 (file)
@@ -138,12 +138,12 @@ struct drm_crtc_commit {
 
 struct __drm_planes_state {
        struct drm_plane *ptr;
-       struct drm_plane_state *state;
+       struct drm_plane_state *state, *old_state, *new_state;
 };
 
 struct __drm_crtcs_state {
        struct drm_crtc *ptr;
-       struct drm_crtc_state *state;
+       struct drm_crtc_state *state, *old_state, *new_state;
        struct drm_crtc_commit *commit;
        s32 __user *out_fence_ptr;
        unsigned last_vblank_count;
@@ -151,7 +151,7 @@ struct __drm_crtcs_state {
 
 struct __drm_connnectors_state {
        struct drm_connector *ptr;
-       struct drm_connector_state *state;
+       struct drm_connector_state *state, *old_state, *new_state;
 };
 
 /**
@@ -398,6 +398,31 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
             (__i)++)                                                   \
                for_each_if (connector)
 
+#define for_each_oldnew_connector_in_state(__state, connector, old_connector_state, new_connector_state, __i) \
+       for ((__i) = 0;                                                         \
+            (__i) < (__state)->num_connector &&                                \
+            ((connector) = (__state)->connectors[__i].ptr,                     \
+            (old_connector_state) = (__state)->connectors[__i].old_state,      \
+            (new_connector_state) = (__state)->connectors[__i].new_state, 1);  \
+            (__i)++)                                                   \
+               for_each_if (connector)
+
+#define for_each_old_connector_in_state(__state, connector, old_connector_state, __i) \
+       for ((__i) = 0;                                                         \
+            (__i) < (__state)->num_connector &&                                \
+            ((connector) = (__state)->connectors[__i].ptr,                     \
+            (old_connector_state) = (__state)->connectors[__i].old_state, 1);  \
+            (__i)++)                                                   \
+               for_each_if (connector)
+
+#define for_each_new_connector_in_state(__state, connector, new_connector_state, __i) \
+       for ((__i) = 0;                                                         \
+            (__i) < (__state)->num_connector &&                                \
+            ((connector) = (__state)->connectors[__i].ptr,                     \
+            (new_connector_state) = (__state)->connectors[__i].new_state, 1);  \
+            (__i)++)                                                   \
+               for_each_if (connector)
+
 #define for_each_crtc_in_state(__state, crtc, crtc_state, __i) \
        for ((__i) = 0;                                         \
             (__i) < (__state)->dev->mode_config.num_crtc &&    \
@@ -406,6 +431,31 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
             (__i)++)                                           \
                for_each_if (crtc_state)
 
+#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 &&            \
+            ((crtc) = (__state)->crtcs[__i].ptr,                       \
+            (old_crtc_state) = (__state)->crtcs[__i].old_state,        \
+            (new_crtc_state) = (__state)->crtcs[__i].new_state, 1);    \
+            (__i)++)                                                   \
+               for_each_if (crtc)
+
+#define for_each_old_crtc_in_state(__state, crtc, old_crtc_state, __i) \
+       for ((__i) = 0;                                                 \
+            (__i) < (__state)->dev->mode_config.num_crtc &&            \
+            ((crtc) = (__state)->crtcs[__i].ptr,                       \
+            (old_crtc_state) = (__state)->crtcs[__i].old_state, 1);    \
+            (__i)++)                                                   \
+               for_each_if (crtc)
+
+#define for_each_new_crtc_in_state(__state, crtc, new_crtc_state, __i) \
+       for ((__i) = 0;                                                 \
+            (__i) < (__state)->dev->mode_config.num_crtc &&            \
+            ((crtc) = (__state)->crtcs[__i].ptr,                       \
+            (new_crtc_state) = (__state)->crtcs[__i].new_state, 1);    \
+            (__i)++)                                                   \
+               for_each_if (crtc)
+
 #define for_each_plane_in_state(__state, plane, plane_state, __i)              \
        for ((__i) = 0;                                                 \
             (__i) < (__state)->dev->mode_config.num_total_plane &&     \
@@ -414,6 +464,31 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
             (__i)++)                                                   \
                for_each_if (plane_state)
 
+#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 &&     \
+            ((plane) = (__state)->planes[__i].ptr,                     \
+            (old_plane_state) = (__state)->planes[__i].old_state,      \
+            (new_plane_state) = (__state)->planes[__i].new_state, 1);  \
+            (__i)++)                                                   \
+               for_each_if (plane)
+
+#define for_each_old_plane_in_state(__state, plane, old_plane_state, __i) \
+       for ((__i) = 0;                                                 \
+            (__i) < (__state)->dev->mode_config.num_total_plane &&     \
+            ((plane) = (__state)->planes[__i].ptr,                     \
+            (old_plane_state) = (__state)->planes[__i].old_state, 1);  \
+            (__i)++)                                                   \
+               for_each_if (plane)
+
+#define for_each_new_plane_in_state(__state, plane, new_plane_state, __i) \
+       for ((__i) = 0;                                                 \
+            (__i) < (__state)->dev->mode_config.num_total_plane &&     \
+            ((plane) = (__state)->planes[__i].ptr,                     \
+            (new_plane_state) = (__state)->planes[__i].new_state, 1);  \
+            (__i)++)                                                   \
+               for_each_if (plane)
+
 /**
  * drm_atomic_crtc_needs_modeset - compute combined modeset need
  * @state: &drm_crtc_state for the CRTC
index d066e9491ae399796d5c64b96561b2c52cf6179c..9ceda379ce585ca03a0686e914c8e4a19a5ec797 100644 (file)
@@ -105,6 +105,8 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set,
 int drm_atomic_helper_disable_all(struct drm_device *dev,
                                  struct drm_modeset_acquire_ctx *ctx);
 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);
 int drm_atomic_helper_resume(struct drm_device *dev,
                             struct drm_atomic_state *state);
 
index e5e1eddd19fb19d168a18fb2607c0a5c81e2ec37..fabb35aba5f6fe4f9a4e506ca009064b4d77c798 100644 (file)
@@ -89,6 +89,22 @@ enum subpixel_order {
        SubPixelNone,
 };
 
+/**
+ * enum drm_link_status - connector's link_status property value
+ *
+ * This enum is used as the connector's link status property value.
+ * It is set to the values defined in uapi.
+ *
+ * @DRM_LINK_STATUS_GOOD: DP Link is Good as a result of successful
+ *                        link training
+ * @DRM_LINK_STATUS_BAD: DP Link is BAD as a result of link training
+ *                       failure
+ */
+enum drm_link_status {
+       DRM_LINK_STATUS_GOOD = DRM_MODE_LINK_STATUS_GOOD,
+       DRM_LINK_STATUS_BAD = DRM_MODE_LINK_STATUS_BAD,
+};
+
 /**
  * struct drm_display_info - runtime data about the connected sink
  *
@@ -243,6 +259,12 @@ struct drm_connector_state {
 
        struct drm_encoder *best_encoder;
 
+       /**
+        * @link_status: Connector link_status to keep track of whether link is
+        * GOOD or BAD to notify userspace if retraining is necessary.
+        */
+       enum drm_link_status link_status;
+
        struct drm_atomic_state *state;
 
        struct drm_tv_connector_state tv;
@@ -795,25 +817,50 @@ static inline struct drm_connector *drm_connector_lookup(struct drm_device *dev,
 }
 
 /**
- * drm_connector_reference - incr the connector refcnt
- * @connector: connector
+ * drm_connector_get - acquire a connector reference
+ * @connector: DRM connector
  *
  * This function increments the connector's refcount.
  */
+static inline void drm_connector_get(struct drm_connector *connector)
+{
+       drm_mode_object_get(&connector->base);
+}
+
+/**
+ * drm_connector_put - release a connector reference
+ * @connector: DRM connector
+ *
+ * This function decrements the connector's reference count and frees the
+ * object if the reference count drops to zero.
+ */
+static inline void drm_connector_put(struct drm_connector *connector)
+{
+       drm_mode_object_put(&connector->base);
+}
+
+/**
+ * drm_connector_reference - acquire a connector reference
+ * @connector: DRM connector
+ *
+ * This is a compatibility alias for drm_connector_get() and should not be
+ * used by new code.
+ */
 static inline void drm_connector_reference(struct drm_connector *connector)
 {
-       drm_mode_object_reference(&connector->base);
+       drm_connector_get(connector);
 }
 
 /**
- * drm_connector_unreference - unref a connector
- * @connector: connector to unref
+ * drm_connector_unreference - release a connector reference
+ * @connector: DRM connector
  *
- * This function decrements the connector's refcount and frees it if it drops to zero.
+ * This is a compatibility alias for drm_connector_put() and should not be
+ * used by new code.
  */
 static inline void drm_connector_unreference(struct drm_connector *connector)
 {
-       drm_mode_object_unreference(&connector->base);
+       drm_connector_put(connector);
 }
 
 const char *drm_get_connector_status_name(enum drm_connector_status status);
@@ -837,6 +884,8 @@ int drm_mode_connector_set_path_property(struct drm_connector *connector,
 int drm_mode_connector_set_tile_property(struct drm_connector *connector);
 int drm_mode_connector_update_edid_property(struct drm_connector *connector,
                                            const struct edid *edid);
+void drm_mode_connector_set_link_status_property(struct drm_connector *connector,
+                                                uint64_t link_status);
 
 /**
  * struct drm_tile_group - Tile group metadata
@@ -882,7 +931,7 @@ void drm_mode_put_tile_group(struct drm_device *dev,
  *
  * This iterator tracks state needed to be able to walk the connector_list
  * within struct drm_mode_config. Only use together with
- * drm_connector_list_iter_get(), drm_connector_list_iter_put() and
+ * drm_connector_list_iter_begin(), drm_connector_list_iter_end() and
  * drm_connector_list_iter_next() respectively the convenience macro
  * drm_for_each_connector_iter().
  */
@@ -892,11 +941,11 @@ struct drm_connector_list_iter {
        struct drm_connector *conn;
 };
 
-void drm_connector_list_iter_get(struct drm_device *dev,
-                                struct drm_connector_list_iter *iter);
+void drm_connector_list_iter_begin(struct drm_device *dev,
+                                  struct drm_connector_list_iter *iter);
 struct drm_connector *
 drm_connector_list_iter_next(struct drm_connector_list_iter *iter);
-void drm_connector_list_iter_put(struct drm_connector_list_iter *iter);
+void drm_connector_list_iter_end(struct drm_connector_list_iter *iter);
 
 /**
  * drm_for_each_connector_iter - connector_list iterator macro
@@ -904,8 +953,8 @@ void drm_connector_list_iter_put(struct drm_connector_list_iter *iter);
  * @iter: &struct drm_connector_list_iter
  *
  * Note that @connector is only valid within the list body, if you want to use
- * @connector after calling drm_connector_list_iter_put() then you need to grab
- * your own reference first using drm_connector_reference().
+ * @connector after calling drm_connector_list_iter_end() then you need to grab
+ * your own reference first using drm_connector_begin().
  */
 #define drm_for_each_connector_iter(connector, iter) \
        while ((connector = drm_connector_list_iter_next(iter)))
index 8f0b195e4a59c190417aaf6a18cd3196a04dbdc5..bda9347554a121ea665bac5e1eb73a2dec946729 100644 (file)
@@ -155,9 +155,16 @@ struct drm_crtc_state {
         * Target vertical blank period when a page flip
         * should take effect.
         */
-
        u32 target_vblank;
 
+       /**
+        * @pageflip_flags:
+        *
+        * DRM_MODE_PAGE_FLIP_* flags, as passed to the page flip ioctl.
+        * Zero in any other case.
+        */
+       u32 pageflip_flags;
+
        /**
         * @event:
         *
@@ -601,6 +608,50 @@ struct drm_crtc_funcs {
         */
        void (*atomic_print_state)(struct drm_printer *p,
                                   const struct drm_crtc_state *state);
+
+       /**
+        * @get_vblank_counter:
+        *
+        * Driver callback for fetching a raw hardware vblank counter for the
+        * CRTC. It's meant to be used by new drivers as the replacement of
+        * &drm_driver.get_vblank_counter hook.
+        *
+        * This callback is optional. If a device doesn't have a hardware
+        * counter, the driver can simply leave the hook as NULL. The DRM core
+        * will account for missed vblank events while interrupts where disabled
+        * based on system timestamps.
+        *
+        * Wraparound handling and loss of events due to modesetting is dealt
+        * with in the DRM core code, as long as drivers call
+        * drm_crtc_vblank_off() and drm_crtc_vblank_on() when disabling or
+        * enabling a CRTC.
+        *
+        * Returns:
+        *
+        * Raw vblank counter value.
+        */
+       u32 (*get_vblank_counter)(struct drm_crtc *crtc);
+
+       /**
+        * @enable_vblank:
+        *
+        * Enable vblank interrupts for the CRTC. It's meant to be used by
+        * new drivers as the replacement of &drm_driver.enable_vblank hook.
+        *
+        * Returns:
+        *
+        * Zero on success, appropriate errno if the vblank interrupt cannot
+        * be enabled.
+        */
+       int (*enable_vblank)(struct drm_crtc *crtc);
+
+       /**
+        * @disable_vblank:
+        *
+        * Disable vblank interrupts for the CRTC. It's meant to be used by
+        * new drivers as the replacement of &drm_driver.disable_vblank hook.
+        */
+       void (*disable_vblank)(struct drm_crtc *crtc);
 };
 
 /**
index 5699f42195fe1b9e1f26b825372423baad8906fd..4e66fbb567730649438719b16de36cc19335cd61 100644 (file)
@@ -120,16 +120,18 @@ struct drm_driver {
         *
         * Driver callback for fetching a raw hardware vblank counter for the
         * CRTC specified with the pipe argument.  If a device doesn't have a
-        * hardware counter, the driver can simply use
-        * drm_vblank_no_hw_counter() function. The DRM core will account for
-        * missed vblank events while interrupts where disabled based on system
-        * timestamps.
+        * hardware counter, the driver can simply leave the hook as NULL.
+        * The DRM core will account for missed vblank events while interrupts
+        * where disabled based on system timestamps.
         *
         * Wraparound handling and loss of events due to modesetting is dealt
         * with in the DRM core code, as long as drivers call
         * drm_crtc_vblank_off() and drm_crtc_vblank_on() when disabling or
         * enabling a CRTC.
         *
+        * This is deprecated and should not be used by new drivers.
+        * Use &drm_crtc_funcs.get_vblank_counter instead.
+        *
         * Returns:
         *
         * Raw vblank counter value.
@@ -142,6 +144,9 @@ struct drm_driver {
         * Enable vblank interrupts for the CRTC specified with the pipe
         * argument.
         *
+        * This is deprecated and should not be used by new drivers.
+        * Use &drm_crtc_funcs.enable_vblank instead.
+        *
         * Returns:
         *
         * Zero on success, appropriate errno if the given @crtc's vblank
@@ -154,6 +159,9 @@ struct drm_driver {
         *
         * Disable vblank interrupts for the CRTC specified with the pipe
         * argument.
+        *
+        * This is deprecated and should not be used by new drivers.
+        * Use &drm_crtc_funcs.disable_vblank instead.
         */
        void (*disable_vblank) (struct drm_device *dev, unsigned int pipe);
 
index 577d5063e63d7bb4fdc283832e07d961836a0060..3ead84d93792df1747dff7e4a2a4984470f75759 100644 (file)
@@ -332,11 +332,12 @@ int drm_av_sync_delay(struct drm_connector *connector,
                      const struct drm_display_mode *mode);
 
 #ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE
-int drm_load_edid_firmware(struct drm_connector *connector);
+struct edid *drm_load_edid_firmware(struct drm_connector *connector);
 #else
-static inline int drm_load_edid_firmware(struct drm_connector *connector)
+static inline struct edid *
+drm_load_edid_firmware(struct drm_connector *connector)
 {
-       return 0;
+       return ERR_PTR(-ENOENT);
 }
 #endif
 
index 6f5acebb266aa74fcc6861a3712b56e0ad2046ae..119e5e4609c7cef6fe6b099bc640495d7c314050 100644 (file)
@@ -230,7 +230,8 @@ struct drm_fb_helper {
        .fb_blank       = drm_fb_helper_blank, \
        .fb_pan_display = drm_fb_helper_pan_display, \
        .fb_debug_enter = drm_fb_helper_debug_enter, \
-       .fb_debug_leave = drm_fb_helper_debug_leave
+       .fb_debug_leave = drm_fb_helper_debug_leave, \
+       .fb_ioctl       = drm_fb_helper_ioctl
 
 #ifdef CONFIG_DRM_FBDEV_EMULATION
 void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
@@ -249,7 +250,6 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);
 
 struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper);
 void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper);
-void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper);
 void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
                            uint32_t fb_width, uint32_t fb_height);
 void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
@@ -285,6 +285,9 @@ void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
 
 int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
 
+int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
+                       unsigned long arg);
+
 int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
 int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);
 int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper);
@@ -354,9 +357,6 @@ drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper)
 static inline void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
 {
 }
-static inline void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper)
-{
-}
 
 static inline void drm_fb_helper_fill_var(struct fb_info *info,
                                          struct drm_fb_helper *fb_helper,
@@ -375,6 +375,12 @@ static inline int drm_fb_helper_setcmap(struct fb_cmap *cmap,
        return 0;
 }
 
+static inline int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
+                                     unsigned long arg)
+{
+       return 0;
+}
+
 static inline void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
 {
 }
index dd1e3e99dcffd078322b76106c957b7da8e5d78a..5244f059d23a06f6ad58fb6388451acf76cb8081 100644 (file)
@@ -101,8 +101,8 @@ struct drm_framebuffer_funcs {
  * cleanup (like releasing the reference(s) on the backing GEM bo(s))
  * should be deferred.  In cases like this, the driver would like to
  * hold a ref to the fb even though it has already been removed from
- * userspace perspective. See drm_framebuffer_reference() and
- * drm_framebuffer_unreference().
+ * userspace perspective. See drm_framebuffer_get() and
+ * drm_framebuffer_put().
  *
  * The refcount is stored inside the mode object @base.
  */
@@ -204,25 +204,50 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb);
 void drm_framebuffer_unregister_private(struct drm_framebuffer *fb);
 
 /**
- * drm_framebuffer_reference - incr the fb refcnt
- * @fb: framebuffer
+ * drm_framebuffer_get - acquire a framebuffer reference
+ * @fb: DRM framebuffer
+ *
+ * This function increments the framebuffer's reference count.
+ */
+static inline void drm_framebuffer_get(struct drm_framebuffer *fb)
+{
+       drm_mode_object_get(&fb->base);
+}
+
+/**
+ * drm_framebuffer_put - release a framebuffer reference
+ * @fb: DRM framebuffer
+ *
+ * This function decrements the framebuffer's reference count and frees the
+ * framebuffer if the reference count drops to zero.
+ */
+static inline void drm_framebuffer_put(struct drm_framebuffer *fb)
+{
+       drm_mode_object_put(&fb->base);
+}
+
+/**
+ * drm_framebuffer_reference - acquire a framebuffer reference
+ * @fb: DRM framebuffer
  *
- * This functions increments the fb's refcount.
+ * This is a compatibility alias for drm_framebuffer_get() and should not be
+ * used by new code.
  */
 static inline void drm_framebuffer_reference(struct drm_framebuffer *fb)
 {
-       drm_mode_object_reference(&fb->base);
+       drm_framebuffer_get(fb);
 }
 
 /**
- * drm_framebuffer_unreference - unref a framebuffer
- * @fb: framebuffer to unref
+ * drm_framebuffer_unreference - release a framebuffer reference
+ * @fb: DRM framebuffer
  *
- * This functions decrements the fb's refcount and frees it if it drops to zero.
+ * This is a compatibility alias for drm_framebuffer_put() and should not be
+ * used by new code.
  */
 static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb)
 {
-       drm_mode_object_unreference(&fb->base);
+       drm_framebuffer_put(fb);
 }
 
 /**
@@ -248,9 +273,9 @@ static inline void drm_framebuffer_assign(struct drm_framebuffer **p,
                                          struct drm_framebuffer *fb)
 {
        if (fb)
-               drm_framebuffer_reference(fb);
+               drm_framebuffer_get(fb);
        if (*p)
-               drm_framebuffer_unreference(*p);
+               drm_framebuffer_put(*p);
        *p = fb;
 }
 
index 449a41b56ffc4443f41c1e53813a60d053adfe3e..3b2a28f7f49fbd5174a13e2c9daf86a1cf16be50 100644 (file)
@@ -48,9 +48,9 @@ struct drm_gem_object {
         *
         * Reference count of this object
         *
-        * Please use drm_gem_object_reference() to acquire and
-        * drm_gem_object_unreference() or drm_gem_object_unreference_unlocked()
-        * to release a reference to a GEM buffer object.
+        * Please use drm_gem_object_get() to acquire and drm_gem_object_put()
+        * or drm_gem_object_put_unlocked() to release a reference to a GEM
+        * buffer object.
         */
        struct kref refcount;
 
@@ -187,42 +187,90 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
 int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
 
 /**
- * drm_gem_object_reference - acquire a GEM BO reference
+ * drm_gem_object_get - acquire a GEM buffer object reference
  * @obj: GEM buffer object
  *
- * This acquires additional reference to @obj. It is illegal to call this
- * without already holding a reference. No locks required.
+ * This function acquires an additional reference to @obj. It is illegal to
+ * call this without already holding a reference. No locks required.
  */
-static inline void
-drm_gem_object_reference(struct drm_gem_object *obj)
+static inline void drm_gem_object_get(struct drm_gem_object *obj)
 {
        kref_get(&obj->refcount);
 }
 
 /**
- * __drm_gem_object_unreference - raw function to release a GEM BO reference
+ * __drm_gem_object_put - raw function to release a GEM buffer object reference
  * @obj: GEM buffer object
  *
  * This function is meant to be used by drivers which are not encumbered with
  * &drm_device.struct_mutex legacy locking and which are using the
  * gem_free_object_unlocked callback. It avoids all the locking checks and
- * locking overhead of drm_gem_object_unreference() and
- * drm_gem_object_unreference_unlocked().
+ * locking overhead of drm_gem_object_put() and drm_gem_object_put_unlocked().
  *
  * Drivers should never call this directly in their code. Instead they should
- * wrap it up into a ``driver_gem_object_unreference(struct driver_gem_object
- * *obj)`` wrapper function, and use that. Shared code should never call this, to
+ * wrap it up into a ``driver_gem_object_put(struct driver_gem_object *obj)``
+ * wrapper function, and use that. Shared code should never call this, to
  * avoid breaking drivers by accident which still depend upon
  * &drm_device.struct_mutex locking.
  */
 static inline void
-__drm_gem_object_unreference(struct drm_gem_object *obj)
+__drm_gem_object_put(struct drm_gem_object *obj)
 {
        kref_put(&obj->refcount, drm_gem_object_free);
 }
 
-void drm_gem_object_unreference_unlocked(struct drm_gem_object *obj);
-void drm_gem_object_unreference(struct drm_gem_object *obj);
+void drm_gem_object_put_unlocked(struct drm_gem_object *obj);
+void drm_gem_object_put(struct drm_gem_object *obj);
+
+/**
+ * drm_gem_object_reference - acquire a GEM buffer object reference
+ * @obj: GEM buffer object
+ *
+ * This is a compatibility alias for drm_gem_object_get() and should not be
+ * used by new code.
+ */
+static inline void drm_gem_object_reference(struct drm_gem_object *obj)
+{
+       drm_gem_object_get(obj);
+}
+
+/**
+ * __drm_gem_object_unreference - raw function to release a GEM buffer object
+ *                                reference
+ * @obj: GEM buffer object
+ *
+ * This is a compatibility alias for __drm_gem_object_put() and should not be
+ * used by new code.
+ */
+static inline void __drm_gem_object_unreference(struct drm_gem_object *obj)
+{
+       __drm_gem_object_put(obj);
+}
+
+/**
+ * drm_gem_object_unreference_unlocked - release a GEM buffer object reference
+ * @obj: GEM buffer object
+ *
+ * This is a compatibility alias for drm_gem_object_put_unlocked() and should
+ * not be used by new code.
+ */
+static inline void
+drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
+{
+       drm_gem_object_put_unlocked(obj);
+}
+
+/**
+ * drm_gem_object_unreference - release a GEM buffer object reference
+ * @obj: GEM buffer object
+ *
+ * This is a compatibility alias for drm_gem_object_put() and should not be
+ * used by new code.
+ */
+static inline void drm_gem_object_unreference(struct drm_gem_object *obj)
+{
+       drm_gem_object_put(obj);
+}
 
 int drm_gem_handle_create(struct drm_file *file_priv,
                          struct drm_gem_object *obj,
index 2fb880462a57926a9e0d992106182e9d0c93e7a8..cf0be6594c8c7bb8c1774a2b43d68ea087bf64c5 100644 (file)
@@ -152,7 +152,6 @@ void drm_crtc_vblank_reset(struct drm_crtc *crtc);
 void drm_crtc_vblank_on(struct drm_crtc *crtc);
 void drm_vblank_cleanup(struct drm_device *dev);
 u32 drm_accurate_vblank_count(struct drm_crtc *crtc);
-u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe);
 
 int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
                                          unsigned int pipe, int *max_error,
index 2ef16bf258267ed33f442c78c6f622fde2716937..49b292e98fecf1da98e38c005eaf3137478626ef 100644 (file)
@@ -460,10 +460,13 @@ __drm_mm_interval_first(const struct drm_mm *mm, u64 start, u64 last);
  * but using the internal interval tree to accelerate the search for the
  * starting node, and so not safe against removal of elements. It assumes
  * that @end is within (or is the upper limit of) the drm_mm allocator.
+ * If [@start, @end] are beyond the range of the drm_mm, the iterator may walk
+ * over the special _unallocated_ &drm_mm.head_node, and may even continue
+ * indefinitely.
  */
 #define drm_mm_for_each_node_in_range(node__, mm__, start__, end__)    \
        for (node__ = __drm_mm_interval_first((mm__), (start__), (end__)-1); \
-            node__ && node__->start < (end__);                         \
+            node__->start < (end__);                                   \
             node__ = list_next_entry(node__, node_list))
 
 void drm_mm_scan_init_with_range(struct drm_mm_scan *scan,
index 26ff46ab26fb829d57ebc2cc4de8d25059ea5a99..ea169a90b3c4322d010b7dccb260be22eff791a5 100644 (file)
@@ -267,7 +267,7 @@ struct drm_mode_config_funcs {
         * passed-in &drm_atomic_state. This hook is called when the caller
         * encountered a &drm_modeset_lock deadlock and needs to drop all
         * already acquired locks as part of the deadlock avoidance dance
-        * implemented in drm_modeset_lock_backoff().
+        * implemented in drm_modeset_backoff().
         *
         * Any duplicated state must be invalidated since a concurrent atomic
         * update might change it, and the drm atomic interfaces always apply
@@ -285,8 +285,8 @@ struct drm_mode_config_funcs {
         * itself. Note that the core first calls drm_atomic_state_clear() to
         * avoid code duplicate between the clear and free hooks.
         *
-        * Drivers that implement this must call drm_atomic_state_default_free()
-        * to release common resources.
+        * Drivers that implement this must call
+        * drm_atomic_state_default_release() to release common resources.
         */
        void (*atomic_state_free)(struct drm_atomic_state *state);
 };
@@ -438,6 +438,11 @@ struct drm_mode_config {
         * multiple CRTCs.
         */
        struct drm_property *tile_property;
+       /**
+        * @link_status_property: Default connector property for link status
+        * of a connector
+        */
+       struct drm_property *link_status_property;
        /**
         * @plane_type_property: Default plane property to differentiate
         * CURSOR, PRIMARY and OVERLAY legacy uses of planes.
@@ -661,7 +666,7 @@ struct drm_mode_config {
        /* cursor size */
        uint32_t cursor_width, cursor_height;
 
-       struct drm_mode_config_helper_funcs *helper_private;
+       const struct drm_mode_config_helper_funcs *helper_private;
 };
 
 void drm_mode_config_init(struct drm_device *dev);
index 2c017adf6d744a68a98db117e7d3aef4af69051e..a767b4a30a6d37704c136c862eabee5417550bb7 100644 (file)
@@ -45,10 +45,10 @@ struct drm_device;
  *   drm_object_attach_property() before the object is visible to userspace.
  *
  * - For objects with dynamic lifetimes (as indicated by a non-NULL @free_cb) it
- *   provides reference counting through drm_mode_object_reference() and
- *   drm_mode_object_unreference(). This is used by &drm_framebuffer,
- *   &drm_connector and &drm_property_blob. These objects provide specialized
- *   reference counting wrappers.
+ *   provides reference counting through drm_mode_object_get() and
+ *   drm_mode_object_put(). This is used by &drm_framebuffer, &drm_connector
+ *   and &drm_property_blob. These objects provide specialized reference
+ *   counting wrappers.
  */
 struct drm_mode_object {
        uint32_t id;
@@ -114,8 +114,32 @@ struct drm_object_properties {
 
 struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
                                             uint32_t id, uint32_t type);
-void drm_mode_object_reference(struct drm_mode_object *obj);
-void drm_mode_object_unreference(struct drm_mode_object *obj);
+void drm_mode_object_get(struct drm_mode_object *obj);
+void drm_mode_object_put(struct drm_mode_object *obj);
+
+/**
+ * drm_mode_object_reference - acquire a mode object reference
+ * @obj: DRM mode object
+ *
+ * This is a compatibility alias for drm_mode_object_get() and should not be
+ * used by new code.
+ */
+static inline void drm_mode_object_reference(struct drm_mode_object *obj)
+{
+       drm_mode_object_get(obj);
+}
+
+/**
+ * drm_mode_object_unreference - release a mode object reference
+ * @obj: DRM mode object
+ *
+ * This is a compatibility alias for drm_mode_object_put() and should not be
+ * used by new code.
+ */
+static inline void drm_mode_object_unreference(struct drm_mode_object *obj)
+{
+       drm_mode_object_put(obj);
+}
 
 int drm_object_property_set_value(struct drm_mode_object *obj,
                                  struct drm_property *property,
index 7d98763c0444dac729e880d28c1596a059bf860c..ca4d7c6321f28fcea1286720f2da65a2db0395cf 100644 (file)
@@ -26,6 +26,8 @@
 #ifndef DRM_PRINT_H_
 #define DRM_PRINT_H_
 
+#include <linux/compiler.h>
+#include <linux/printk.h>
 #include <linux/seq_file.h>
 #include <linux/device.h>
 
@@ -75,6 +77,7 @@ void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf);
 void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf);
 void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf);
 
+__printf(2, 3)
 void drm_printf(struct drm_printer *p, const char *f, ...);
 
 
index f66fdb47551cea64146b568303d3e164ab47ddde..13e8c17d1c79b0704018e2ccbe32af7b6e2d723d 100644 (file)
@@ -200,9 +200,8 @@ struct drm_property {
  * Blobs are used to store bigger values than what fits directly into the 64
  * bits available for a &drm_property.
  *
- * Blobs are reference counted using drm_property_reference_blob() and
- * drm_property_unreference_blob(). They are created using
- * drm_property_create_blob().
+ * Blobs are reference counted using drm_property_blob_get() and
+ * drm_property_blob_put(). They are created using drm_property_create_blob().
  */
 struct drm_property_blob {
        struct drm_mode_object base;
@@ -274,8 +273,34 @@ int drm_property_replace_global_blob(struct drm_device *dev,
                                     const void *data,
                                     struct drm_mode_object *obj_holds_id,
                                     struct drm_property *prop_holds_id);
-struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob);
-void drm_property_unreference_blob(struct drm_property_blob *blob);
+struct drm_property_blob *drm_property_blob_get(struct drm_property_blob *blob);
+void drm_property_blob_put(struct drm_property_blob *blob);
+
+/**
+ * drm_property_reference_blob - acquire a blob property reference
+ * @blob: DRM blob property
+ *
+ * This is a compatibility alias for drm_property_blob_get() and should not be
+ * used by new code.
+ */
+static inline struct drm_property_blob *
+drm_property_reference_blob(struct drm_property_blob *blob)
+{
+       return drm_property_blob_get(blob);
+}
+
+/**
+ * drm_property_unreference_blob - release a blob property reference
+ * @blob: DRM blob property
+ *
+ * This is a compatibility alias for drm_property_blob_put() and should not be
+ * used by new code.
+ */
+static inline void
+drm_property_unreference_blob(struct drm_property_blob *blob)
+{
+       drm_property_blob_put(blob);
+}
 
 /**
  * drm_connector_find - find property object
index 956a1006aefc24053c643d4ad6bf653dbd2d012a..dc8224ae28d5d9e6106dc0d06a8a9bc2eb85fd0a 100644 (file)
@@ -76,6 +76,10 @@ extern int of_platform_default_populate(struct device_node *root,
                                        const struct of_dev_auxdata *lookup,
                                        struct device *parent);
 extern void of_platform_depopulate(struct device *parent);
+
+extern int devm_of_platform_populate(struct device *dev);
+
+extern void devm_of_platform_depopulate(struct device *dev);
 #else
 static inline int of_platform_populate(struct device_node *root,
                                        const struct of_device_id *matches,
@@ -91,6 +95,13 @@ static inline int of_platform_default_populate(struct device_node *root,
        return -ENODEV;
 }
 static inline void of_platform_depopulate(struct device *parent) { }
+
+static inline int devm_of_platform_populate(struct device *dev)
+{
+       return -ENODEV;
+}
+
+static inline void devm_of_platform_depopulate(struct device *dev) { }
 #endif
 
 #if defined(CONFIG_OF_DYNAMIC) && defined(CONFIG_OF_ADDRESS)
index 2b5a4679daeade8c1cb6ed195d6725f4799fdf31..156cfd330b6675c79780418e53cd0057410556ec 100644 (file)
@@ -166,6 +166,26 @@ reservation_object_lock(struct reservation_object *obj,
        return ww_mutex_lock(&obj->lock, ctx);
 }
 
+/**
+ * reservation_object_trylock - trylock the reservation object
+ * @obj: the reservation object
+ *
+ * Tries to lock the reservation object for exclusive access and modification.
+ * Note, that the lock is only against other writers, readers will run
+ * concurrently with a writer under RCU. The seqlock is used to notify readers
+ * if they overlap with a writer.
+ *
+ * Also note that since no context is provided, no deadlock protection is
+ * possible.
+ *
+ * Returns true if the lock was acquired, false otherwise.
+ */
+static inline bool __must_check
+reservation_object_trylock(struct reservation_object *obj)
+{
+       return ww_mutex_trylock(&obj->lock);
+}
+
 /**
  * reservation_object_unlock - unlock the reservation object
  * @obj: the reservation object
index ce7efe2e8a5e7698308b879b7d4c9826614b4673..8c67fc03d53dd630a8245fd2ae79fae5d5cbaccc 100644 (file)
@@ -123,6 +123,10 @@ extern "C" {
 #define DRM_MODE_DIRTY_ON       1
 #define DRM_MODE_DIRTY_ANNOTATE 2
 
+/* Link Status options */
+#define DRM_MODE_LINK_STATUS_GOOD      0
+#define DRM_MODE_LINK_STATUS_BAD       1
+
 struct drm_mode_modeinfo {
        __u32 clock;
        __u16 hdisplay;
diff --git a/scripts/coccinelle/api/drm-get-put.cocci b/scripts/coccinelle/api/drm-get-put.cocci
new file mode 100644 (file)
index 0000000..0c7a926
--- /dev/null
@@ -0,0 +1,92 @@
+///
+/// Use drm_*_get() and drm_*_put() helpers instead of drm_*_reference() and
+/// drm_*_unreference() helpers.
+///
+// Confidence: High
+// Copyright: (C) 2017 NVIDIA Corporation
+// Options: --no-includes --include-headers
+//
+
+virtual patch
+virtual report
+
+@depends on patch@
+expression object;
+@@
+
+(
+- drm_mode_object_reference(object)
++ drm_mode_object_get(object)
+|
+- drm_mode_object_unreference(object)
++ drm_mode_object_put(object)
+|
+- drm_connector_reference(object)
++ drm_connector_get(object)
+|
+- drm_connector_unreference(object)
++ drm_connector_put(object)
+|
+- drm_framebuffer_reference(object)
++ drm_framebuffer_get(object)
+|
+- drm_framebuffer_unreference(object)
++ drm_framebuffer_put(object)
+|
+- drm_gem_object_reference(object)
++ drm_gem_object_get(object)
+|
+- drm_gem_object_unreference(object)
++ drm_gem_object_put(object)
+|
+- __drm_gem_object_unreference(object)
++ __drm_gem_object_put(object)
+|
+- drm_gem_object_unreference_unlocked(object)
++ drm_gem_object_put_unlocked(object)
+|
+- drm_property_reference_blob(object)
++ drm_property_blob_get(object)
+|
+- drm_property_unreference_blob(object)
++ drm_property_blob_put(object)
+)
+
+@r depends on report@
+expression object;
+position p;
+@@
+
+(
+drm_mode_object_unreference@p(object)
+|
+drm_mode_object_reference@p(object)
+|
+drm_connector_unreference@p(object)
+|
+drm_connector_reference@p(object)
+|
+drm_framebuffer_unreference@p(object)
+|
+drm_framebuffer_reference@p(object)
+|
+drm_gem_object_unreference@p(object)
+|
+drm_gem_object_reference@p(object)
+|
+__drm_gem_object_unreference(object)
+|
+drm_gem_object_unreference_unlocked(object)
+|
+drm_property_unreference_blob@p(object)
+|
+drm_property_reference_blob@p(object)
+)
+
+@script:python depends on report@
+object << r.object;
+p << r.p;
+@@
+
+msg="WARNING: use get/put helpers to reference and dereference %s" % (object)
+coccilib.report.print_report(p[0], msg)