]> git.proxmox.com Git - mirror_ubuntu-disco-kernel.git/commitdiff
Merge tag 'drm-misc-next-2018-06-21' of git://anongit.freedesktop.org/drm/drm-misc...
authorDave Airlie <airlied@redhat.com>
Fri, 22 Jun 2018 02:56:48 +0000 (12:56 +1000)
committerDave Airlie <airlied@redhat.com>
Fri, 22 Jun 2018 02:58:08 +0000 (12:58 +1000)
drm-misc-next for 4.19:

UAPI Changes:
- Add writeback connector (Brian Starkey/Liviu Dudau)
- Add "content type" property to HDMI connectors (Stanislav Lisovskiy)

Cross-subsystem Changes:
- some devicetree Docs update
- fix compile breakage on ION due to the dma-buf cleanups (Christian König)

Core Changes:
- Reject over-sized allocation requests early (Chris Wilson)
- gem-fb-helper: Always do implicit sync (Daniel Vetter)
- dma-buf cleanups (Christian König)

Driver Changes:
- Fixes for the otm8009a panel driver (Philippe Cornu)
- Add Innolux TV123WAM panel driver support (Sandeep Panda)
- Move GEM BO to drm_framebuffer in few drivers (Daniel Stone)
- i915 pinning improvements (Chris Wilson)
- Stop consulting plane->fb/crtc in a few drivers (Ville Syrjälä)

Signed-off-by: Dave Airlie <airlied@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180621105428.GA20795@juma
131 files changed:
Documentation/devicetree/bindings/display/panel/auo,g070vvn01.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/innolux,tv123wam.txt [new file with mode: 0644]
Documentation/gpu/drm-kms.rst
Documentation/gpu/kms-properties.csv
drivers/dma-buf/dma-buf.c
drivers/gpu/drm/Makefile
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/arc/arcpgu_crtc.c
drivers/gpu/drm/armada/armada_fb.c
drivers/gpu/drm/armada/armada_fb.h
drivers/gpu/drm/armada/armada_gem.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
drivers/gpu/drm/bridge/Kconfig
drivers/gpu/drm/bridge/cdns-dsi.c
drivers/gpu/drm/cirrus/cirrus_drv.h
drivers/gpu/drm/cirrus/cirrus_fbdev.c
drivers/gpu/drm/cirrus/cirrus_main.c
drivers/gpu/drm/cirrus/cirrus_mode.c
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_connector.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_internal.h
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_framebuffer.c
drivers/gpu/drm/drm_gem_framebuffer_helper.c
drivers/gpu/drm/drm_ioctl.c
drivers/gpu/drm/drm_mm.c
drivers/gpu/drm/drm_mode_config.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/drm_panel.c
drivers/gpu/drm/drm_plane.c
drivers/gpu/drm/drm_plane_helper.c
drivers/gpu/drm/drm_prime.c
drivers/gpu/drm/drm_vm.c
drivers/gpu/drm/drm_writeback.c [new file with mode: 0644]
drivers/gpu/drm/exynos/exynos_drm_plane.c
drivers/gpu/drm/gma500/accel_2d.c
drivers/gpu/drm/gma500/framebuffer.c
drivers/gpu/drm/gma500/framebuffer.h
drivers/gpu/drm/gma500/gma_display.c
drivers/gpu/drm/gma500/gtt.h
drivers/gpu/drm/gma500/mdfld_intel_display.c
drivers/gpu/drm/gma500/oaktrail_crtc.c
drivers/gpu/drm/gma500/psb_intel_sdvo.c
drivers/gpu/drm/i2c/tda998x_drv.c
drivers/gpu/drm/i915/i915_gem_dmabuf.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/intel_atomic.c
drivers/gpu/drm/i915/intel_atomic_plane.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/i915/selftests/mock_dmabuf.c
drivers/gpu/drm/mediatek/mtk_drm_fb.c
drivers/gpu/drm/mediatek/mtk_drm_fb.h
drivers/gpu/drm/mediatek/mtk_drm_plane.c
drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c
drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
drivers/gpu/drm/msm/msm_fb.c
drivers/gpu/drm/omapdrm/omap_fb.c
drivers/gpu/drm/omapdrm/omap_fb.h
drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
drivers/gpu/drm/panel/panel-innolux-p079zca.c
drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
drivers/gpu/drm/panel/panel-lvds.c
drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
drivers/gpu/drm/panel/panel-simple.c
drivers/gpu/drm/panel/panel-sitronix-st7789v.c
drivers/gpu/drm/rockchip/cdn-dp-reg.c
drivers/gpu/drm/rockchip/rockchip_drm_fb.c
drivers/gpu/drm/rockchip/rockchip_drm_fb.h
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/rockchip/rockchip_lvds.c
drivers/gpu/drm/selftests/drm_mm_selftests.h
drivers/gpu/drm/selftests/test-drm_mm.c
drivers/gpu/drm/sti/sti_gdp.c
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
drivers/gpu/drm/tegra/gem.c
drivers/gpu/drm/udl/udl_dmabuf.c
drivers/gpu/drm/udl/udl_drv.h
drivers/gpu/drm/udl/udl_gem.c
drivers/gpu/drm/v3d/v3d_sched.c
drivers/gpu/drm/vc4/vc4_crtc.c
drivers/gpu/drm/vc4/vc4_plane.c
drivers/gpu/drm/vc4/vc4_regs.h
drivers/gpu/drm/vgem/vgem_drv.c
drivers/gpu/drm/virtio/virtgpu_display.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_fb.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_prime.c
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
drivers/gpu/drm/xen/xen_drm_front.c
drivers/gpu/drm/xen/xen_drm_front.h
drivers/gpu/drm/xen/xen_drm_front_shbuf.c
drivers/media/common/videobuf2/videobuf2-dma-contig.c
drivers/media/common/videobuf2/videobuf2-dma-sg.c
drivers/media/common/videobuf2/videobuf2-vmalloc.c
drivers/staging/android/ion/ion.c
drivers/tee/tee_shm.c
include/drm/drm_atomic.h
include/drm/drm_bridge.h
include/drm/drm_connector.h
include/drm/drm_crtc.h
include/drm/drm_file.h
include/drm/drm_mm.h
include/drm/drm_mode_config.h
include/drm/drm_modeset_helper_vtables.h
include/drm/drm_panel.h
include/drm/drm_plane.h
include/drm/drm_prime.h
include/drm/drm_writeback.h [new file with mode: 0644]
include/linux/dma-buf.h
include/uapi/drm/drm.h
include/uapi/drm/drm_fourcc.h
include/uapi/drm/drm_mode.h

diff --git a/Documentation/devicetree/bindings/display/panel/auo,g070vvn01.txt b/Documentation/devicetree/bindings/display/panel/auo,g070vvn01.txt
new file mode 100644 (file)
index 0000000..49e4105
--- /dev/null
@@ -0,0 +1,29 @@
+AU Optronics Corporation 7.0" FHD (800 x 480) TFT LCD panel
+
+Required properties:
+- compatible: should be "auo,g070vvn01"
+- backlight: phandle of the backlight device attached to the panel
+- power-supply: single regulator to provide the supply voltage
+
+Required nodes:
+- port: Parallel port mapping to connect this display
+
+This panel needs single power supply voltage. Its backlight is conntrolled
+via PWM signal.
+
+Example:
+--------
+
+Example device-tree definition when connected to iMX6Q based board
+
+       lcd_panel: lcd-panel {
+               compatible = "auo,g070vvn01";
+               backlight = <&backlight_lcd>;
+               power-supply = <&reg_display>;
+
+               port {
+                       lcd_panel_in: endpoint {
+                               remote-endpoint = <&lcd_display_out>;
+                       };
+               };
+       };
diff --git a/Documentation/devicetree/bindings/display/panel/innolux,tv123wam.txt b/Documentation/devicetree/bindings/display/panel/innolux,tv123wam.txt
new file mode 100644 (file)
index 0000000..a9b3526
--- /dev/null
@@ -0,0 +1,20 @@
+Innolux TV123WAM 12.3 inch eDP 2K display panel
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
+
+Required properties:
+- compatible: should be "innolux,tv123wam"
+- power-supply: regulator to provide the supply voltage
+
+Optional properties:
+- enable-gpios: GPIO pin to enable or disable the panel
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+       panel_edp: panel-edp {
+               compatible = "innolux,tv123wam";
+               enable-gpios = <&msmgpio 31 GPIO_ACTIVE_LOW>;
+               power-supply = <&pm8916_l2>;
+               backlight = <&backlight>;
+       };
index 1dffd1ac4cd44be310fa7b8855c265cc57cd30ae..4f6f113a7f5d5f99a8b85a217bfc8eaedcd0bd3e 100644 (file)
@@ -373,6 +373,15 @@ Connector Functions Reference
 .. kernel-doc:: drivers/gpu/drm/drm_connector.c
    :export:
 
+Writeback Connectors
+--------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_writeback.c
+  :doc: overview
+
+.. kernel-doc:: drivers/gpu/drm/drm_writeback.c
+  :export:
+
 Encoder Abstraction
 ===================
 
@@ -517,6 +526,12 @@ Standard Connector Properties
 .. kernel-doc:: drivers/gpu/drm/drm_connector.c
    :doc: standard connector properties
 
+HDMI Specific Connector Properties
+-----------------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_connector.c
+   :doc: HDMI connector properties
+
 Plane Composition Properties
 ----------------------------
 
index 07ed22ea3bd670f3acd2d016963c6d1c5426997d..bfde04eddd148b8f669c3d2b633e52b08f2dd3e2 100644 (file)
@@ -17,6 +17,7 @@ Owner Module/Drivers,Group,Property Name,Type,Property Values,Object attached,De
 ,Virtual GPU,“suggested X”,RANGE,"Min=0, Max=0xffffffff",Connector,property to suggest an X offset for a connector
 ,,“suggested Y”,RANGE,"Min=0, Max=0xffffffff",Connector,property to suggest an Y offset for a connector
 ,Optional,"""aspect ratio""",ENUM,"{ ""None"", ""4:3"", ""16:9"" }",Connector,TDB
+,Optional,"""content type""",ENUM,"{ ""No Data"", ""Graphics"", ""Photo"", ""Cinema"", ""Game"" }",Connector,TBD
 i915,Generic,"""Broadcast RGB""",ENUM,"{ ""Automatic"", ""Full"", ""Limited 16:235"" }",Connector,"When this property is set to Limited 16:235 and CTM is set, the hardware will be programmed with the result of the multiplication of CTM by the limited range matrix to ensure the pixels normaly in the range 0..1.0 are remapped to the range 16/255..235/255."
 ,,“audio”,ENUM,"{ ""force-dvi"", ""off"", ""auto"", ""on"" }",Connector,TBD
 ,SDVO-TV,“mode”,ENUM,"{ ""NTSC_M"", ""NTSC_J"", ""NTSC_443"", ""PAL_B"" } etc.",Connector,TBD
index d78d5fc173dc3d9b05b523462301a060e5482473..13884474d1588f7a086154d3b06dbd09ff28e881 100644 (file)
@@ -405,7 +405,6 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
                          || !exp_info->ops->map_dma_buf
                          || !exp_info->ops->unmap_dma_buf
                          || !exp_info->ops->release
-                         || !exp_info->ops->map_atomic
                          || !exp_info->ops->map
                          || !exp_info->ops->mmap)) {
                return ERR_PTR(-EINVAL);
@@ -568,7 +567,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
        mutex_lock(&dmabuf->lock);
 
        if (dmabuf->ops->attach) {
-               ret = dmabuf->ops->attach(dmabuf, dev, attach);
+               ret = dmabuf->ops->attach(dmabuf, attach);
                if (ret)
                        goto err_attach;
        }
@@ -687,26 +686,14 @@ EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
  *      void \*dma_buf_kmap(struct dma_buf \*, unsigned long);
  *      void dma_buf_kunmap(struct dma_buf \*, unsigned long, void \*);
  *
- *   There are also atomic variants of these interfaces. Like for kmap they
- *   facilitate non-blocking fast-paths. Neither the importer nor the exporter
- *   (in the callback) is allowed to block when using these.
- *
- *   Interfaces::
- *      void \*dma_buf_kmap_atomic(struct dma_buf \*, unsigned long);
- *      void dma_buf_kunmap_atomic(struct dma_buf \*, unsigned long, void \*);
- *
- *   For importers all the restrictions of using kmap apply, like the limited
- *   supply of kmap_atomic slots. Hence an importer shall only hold onto at
- *   max 2 atomic dma_buf kmaps at the same time (in any given process context).
+ *   Implementing the functions is optional for exporters and for importers all
+ *   the restrictions of using kmap apply.
  *
  *   dma_buf kmap calls outside of the range specified in begin_cpu_access are
  *   undefined. If the range is not PAGE_SIZE aligned, kmap needs to succeed on
  *   the partial chunks at the beginning and end but may return stale or bogus
  *   data outside of the range (in these partial chunks).
  *
- *   Note that these calls need to always succeed. The exporter needs to
- *   complete any preparations that might fail in begin_cpu_access.
- *
  *   For some cases the overhead of kmap can be too high, a vmap interface
  *   is introduced. This interface should be used very carefully, as vmalloc
  *   space is a limited resources on many architectures.
@@ -859,41 +846,6 @@ int dma_buf_end_cpu_access(struct dma_buf *dmabuf,
 }
 EXPORT_SYMBOL_GPL(dma_buf_end_cpu_access);
 
-/**
- * dma_buf_kmap_atomic - Map a page of the buffer object into kernel address
- * space. The same restrictions as for kmap_atomic and friends apply.
- * @dmabuf:    [in]    buffer to map page from.
- * @page_num:  [in]    page in PAGE_SIZE units to map.
- *
- * This call must always succeed, any necessary preparations that might fail
- * need to be done in begin_cpu_access.
- */
-void *dma_buf_kmap_atomic(struct dma_buf *dmabuf, unsigned long page_num)
-{
-       WARN_ON(!dmabuf);
-
-       return dmabuf->ops->map_atomic(dmabuf, page_num);
-}
-EXPORT_SYMBOL_GPL(dma_buf_kmap_atomic);
-
-/**
- * dma_buf_kunmap_atomic - Unmap a page obtained by dma_buf_kmap_atomic.
- * @dmabuf:    [in]    buffer to unmap page from.
- * @page_num:  [in]    page in PAGE_SIZE units to unmap.
- * @vaddr:     [in]    kernel space pointer obtained from dma_buf_kmap_atomic.
- *
- * This call must always succeed.
- */
-void dma_buf_kunmap_atomic(struct dma_buf *dmabuf, unsigned long page_num,
-                          void *vaddr)
-{
-       WARN_ON(!dmabuf);
-
-       if (dmabuf->ops->unmap_atomic)
-               dmabuf->ops->unmap_atomic(dmabuf, page_num, vaddr);
-}
-EXPORT_SYMBOL_GPL(dma_buf_kunmap_atomic);
-
 /**
  * dma_buf_kmap - Map a page of the buffer object into kernel address space. The
  * same restrictions as for kmap and friends apply.
@@ -907,6 +859,8 @@ void *dma_buf_kmap(struct dma_buf *dmabuf, unsigned long page_num)
 {
        WARN_ON(!dmabuf);
 
+       if (!dmabuf->ops->map)
+               return NULL;
        return dmabuf->ops->map(dmabuf, page_num);
 }
 EXPORT_SYMBOL_GPL(dma_buf_kmap);
index ef9f3dab287fd4b38188ea3354117b9abed5cd23..69c13517ea3a6a866a92607504d21878f6c443e9 100644 (file)
@@ -18,7 +18,7 @@ drm-y       :=        drm_auth.o drm_bufs.o drm_cache.o \
                drm_encoder.o drm_mode_object.o drm_property.o \
                drm_plane.o drm_color_mgmt.o drm_print.o \
                drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
-               drm_syncobj.o drm_lease.o
+               drm_syncobj.o drm_lease.o drm_writeback.o
 
 drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
 drm-$(CONFIG_DRM_VM) += drm_vm.o
index 4683626b065ff2cb06473ad8349bbaa6148cd68f..a156b3891a3f9aa27077525d8fa533182c82b252 100644 (file)
@@ -133,7 +133,6 @@ error:
 }
 
 static int amdgpu_gem_map_attach(struct dma_buf *dma_buf,
-                                struct device *target_dev,
                                 struct dma_buf_attachment *attach)
 {
        struct drm_gem_object *obj = dma_buf->priv;
@@ -141,7 +140,7 @@ static int amdgpu_gem_map_attach(struct dma_buf *dma_buf,
        struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
        long r;
 
-       r = drm_gem_map_attach(dma_buf, target_dev, attach);
+       r = drm_gem_map_attach(dma_buf, attach);
        if (r)
                return r;
 
@@ -245,9 +244,7 @@ static const struct dma_buf_ops amdgpu_dmabuf_ops = {
        .release = drm_gem_dmabuf_release,
        .begin_cpu_access = amdgpu_gem_begin_cpu_access,
        .map = drm_gem_dmabuf_kmap,
-       .map_atomic = drm_gem_dmabuf_kmap_atomic,
        .unmap = drm_gem_dmabuf_kunmap,
-       .unmap_atomic = drm_gem_dmabuf_kunmap_atomic,
        .mmap = drm_gem_dmabuf_mmap,
        .vmap = drm_gem_dmabuf_vmap,
        .vunmap = drm_gem_dmabuf_vunmap,
index f9add85157e7355432aab9d0d14728f8906774f9..a1dd49545a5b10430b1f4553a592bd32631e2f42 100644 (file)
@@ -3914,8 +3914,6 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc,
 
        /* Flip */
        spin_lock_irqsave(&crtc->dev->event_lock, flags);
-       /* update crtc fb */
-       crtc->primary->fb = fb;
 
        WARN_ON(acrtc->pflip_status != AMDGPU_FLIP_NONE);
        WARN_ON(!acrtc_state->stream);
index 16903dc7fe0dc465d7d6f93f138efeb337ca4c42..c3349b8fb58bcf0173e9bdcd9493ae097fd5156d 100644 (file)
@@ -136,9 +136,6 @@ static void arc_pgu_crtc_atomic_disable(struct drm_crtc *crtc,
 {
        struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
 
-       if (!crtc->primary->fb)
-               return;
-
        clk_disable_unprepare(arcpgu->clk);
        arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
                              arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) &
index ac92bce07ecd92aedffe35ea481df054e24175b8..edd15126bde93a70bcbf15e483c7afca53bf5edc 100644 (file)
@@ -7,30 +7,15 @@
  */
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 #include "armada_drm.h"
 #include "armada_fb.h"
 #include "armada_gem.h"
 #include "armada_hw.h"
 
-static void armada_fb_destroy(struct drm_framebuffer *fb)
-{
-       struct armada_framebuffer *dfb = drm_fb_to_armada_fb(fb);
-
-       drm_framebuffer_cleanup(&dfb->fb);
-       drm_gem_object_put_unlocked(&dfb->obj->obj);
-       kfree(dfb);
-}
-
-static int armada_fb_create_handle(struct drm_framebuffer *fb,
-       struct drm_file *dfile, unsigned int *handle)
-{
-       struct armada_framebuffer *dfb = drm_fb_to_armada_fb(fb);
-       return drm_gem_handle_create(dfile, &dfb->obj->obj, handle);
-}
-
 static const struct drm_framebuffer_funcs armada_fb_funcs = {
-       .destroy        = armada_fb_destroy,
-       .create_handle  = armada_fb_create_handle,
+       .destroy        = drm_gem_fb_destroy,
+       .create_handle  = drm_gem_fb_create_handle,
 };
 
 struct armada_framebuffer *armada_framebuffer_create(struct drm_device *dev,
@@ -78,7 +63,7 @@ struct armada_framebuffer *armada_framebuffer_create(struct drm_device *dev,
 
        dfb->fmt = format;
        dfb->mod = config;
-       dfb->obj = obj;
+       dfb->fb.obj[0] = &obj->obj;
 
        drm_helper_mode_fill_fb_struct(dev, &dfb->fb, mode);
 
index 48073c4f54d8d673bba030fa3893332a8eae93a2..5c130ff5da7707a63a60552451cd6f92584ec901 100644 (file)
 
 struct armada_framebuffer {
        struct drm_framebuffer  fb;
-       struct armada_gem_object *obj;
        uint8_t                 fmt;
        uint8_t                 mod;
 };
 #define drm_fb_to_armada_fb(dfb) \
        container_of(dfb, struct armada_framebuffer, fb)
-#define drm_fb_obj(fb) drm_fb_to_armada_fb(fb)->obj
+#define drm_fb_obj(fb) drm_to_armada_gem((fb)->obj[0])
 
 struct armada_framebuffer *armada_framebuffer_create(struct drm_device *,
        const struct drm_mode_fb_cmd2 *, struct armada_gem_object *);
index a97f509743a596631254ebcd4ec56b853fd9e034..3fb37c75c065d6c548df56f100eb678ed8924481 100644 (file)
@@ -490,8 +490,6 @@ static const struct dma_buf_ops armada_gem_prime_dmabuf_ops = {
        .map_dma_buf    = armada_gem_prime_map_dma_buf,
        .unmap_dma_buf  = armada_gem_prime_unmap_dma_buf,
        .release        = drm_gem_dmabuf_release,
-       .map_atomic     = armada_gem_dmabuf_no_kmap,
-       .unmap_atomic   = armada_gem_dmabuf_no_kunmap,
        .map            = armada_gem_dmabuf_no_kmap,
        .unmap          = armada_gem_dmabuf_no_kunmap,
        .mmap           = armada_gem_dmabuf_mmap,
index c1ea5c36b0061a9220a0c168eab6a8d588054f25..843cac222e60d8e801aa1ad5c95db75d848d69ff 100644 (file)
@@ -681,6 +681,7 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev)
        drm_fb_cma_fbdev_fini(dev);
        flush_workqueue(dc->wq);
        drm_kms_helper_poll_fini(dev);
+       drm_atomic_helper_shutdown(dev);
        drm_mode_config_cleanup(dev);
 
        pm_runtime_get_sync(dev->dev);
index 73c875db45f4346afd5a25408e9264c466401138..1aecc74cc463d7f159f85190d574cf3f300bc50a 100644 (file)
@@ -412,9 +412,10 @@ static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane,
                                    ATMEL_HLCDC_LAYER_FORMAT_CFG, cfg);
 }
 
-static void atmel_hlcdc_plane_update_clut(struct atmel_hlcdc_plane *plane)
+static void atmel_hlcdc_plane_update_clut(struct atmel_hlcdc_plane *plane,
+                                         struct atmel_hlcdc_plane_state *state)
 {
-       struct drm_crtc *crtc = plane->base.crtc;
+       struct drm_crtc *crtc = state->base.crtc;
        struct drm_color_lut *lut;
        int idx;
 
@@ -779,7 +780,7 @@ static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
        atmel_hlcdc_plane_update_pos_and_size(plane, state);
        atmel_hlcdc_plane_update_general_settings(plane, state);
        atmel_hlcdc_plane_update_format(plane, state);
-       atmel_hlcdc_plane_update_clut(plane);
+       atmel_hlcdc_plane_update_clut(plane, state);
        atmel_hlcdc_plane_update_buffers(plane, state);
        atmel_hlcdc_plane_update_disc_area(plane, state);
 
@@ -816,16 +817,6 @@ static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p,
        atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR);
 }
 
-static void atmel_hlcdc_plane_destroy(struct drm_plane *p)
-{
-       struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
-
-       if (plane->base.fb)
-               drm_framebuffer_put(plane->base.fb);
-
-       drm_plane_cleanup(p);
-}
-
 static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane)
 {
        const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
@@ -1002,7 +993,7 @@ static void atmel_hlcdc_plane_atomic_destroy_state(struct drm_plane *p,
 static const struct drm_plane_funcs layer_plane_funcs = {
        .update_plane = drm_atomic_helper_update_plane,
        .disable_plane = drm_atomic_helper_disable_plane,
-       .destroy = atmel_hlcdc_plane_destroy,
+       .destroy = drm_plane_cleanup,
        .reset = atmel_hlcdc_plane_reset,
        .atomic_duplicate_state = atmel_hlcdc_plane_atomic_duplicate_state,
        .atomic_destroy_state = atmel_hlcdc_plane_atomic_destroy_state,
index fa2c7997e2fdf977253ff365fe7fe2a12d5637b4..bf6cad6c9178b10eda1e639ac0d785631d1f6518 100644 (file)
@@ -82,9 +82,11 @@ config DRM_PARADE_PS8622
 
 config DRM_SIL_SII8620
        tristate "Silicon Image SII8620 HDMI/MHL bridge"
-       depends on OF && RC_CORE
+       depends on OF
        select DRM_KMS_HELPER
        imply EXTCON
+       select INPUT
+       select RC_CORE
        help
          Silicon Image SII8620 HDMI/MHL bridge chip driver.
 
index c255fc3e1be5d2cf13952613e608c53fe64fc3f3..f2d43f24acfbecfbd92eca83c7430677f057aa9e 100644 (file)
@@ -1337,7 +1337,7 @@ static const struct mipi_dsi_host_ops cdns_dsi_ops = {
        .transfer = cdns_dsi_transfer,
 };
 
-static int cdns_dsi_resume(struct device *dev)
+static int __maybe_unused cdns_dsi_resume(struct device *dev)
 {
        struct cdns_dsi *dsi = dev_get_drvdata(dev);
 
@@ -1350,7 +1350,7 @@ static int cdns_dsi_resume(struct device *dev)
        return 0;
 }
 
-static int cdns_dsi_suspend(struct device *dev)
+static int __maybe_unused cdns_dsi_suspend(struct device *dev)
 {
        struct cdns_dsi *dsi = dev_get_drvdata(dev);
 
index be2d7e4880621a075b4d0f900d14cc204e86c262..ce9db7aab2255c773218778aab7fd62e607a071d 100644 (file)
@@ -92,7 +92,6 @@
 
 #define to_cirrus_crtc(x) container_of(x, struct cirrus_crtc, base)
 #define to_cirrus_encoder(x) container_of(x, struct cirrus_encoder, base)
-#define to_cirrus_framebuffer(x) container_of(x, struct cirrus_framebuffer, base)
 
 struct cirrus_crtc {
        struct drm_crtc                 base;
@@ -117,11 +116,6 @@ struct cirrus_connector {
        struct drm_connector            base;
 };
 
-struct cirrus_framebuffer {
-       struct drm_framebuffer          base;
-       struct drm_gem_object *obj;
-};
-
 struct cirrus_mc {
        resource_size_t                 vram_size;
        resource_size_t                 vram_base;
@@ -152,7 +146,7 @@ struct cirrus_device {
 
 struct cirrus_fbdev {
        struct drm_fb_helper helper;
-       struct cirrus_framebuffer gfb;
+       struct drm_framebuffer gfb;
        void *sysram;
        int size;
        int x1, y1, x2, y2; /* dirty rect */
@@ -198,7 +192,7 @@ int cirrus_dumb_create(struct drm_file *file,
                       struct drm_mode_create_dumb *args);
 
 int cirrus_framebuffer_init(struct drm_device *dev,
-                          struct cirrus_framebuffer *gfb,
+                           struct drm_framebuffer *gfb,
                            const struct drm_mode_fb_cmd2 *mode_cmd,
                            struct drm_gem_object *obj);
 
index 32fbfba2c623a7ddbb43d68534316b5a8485d950..b643ac92801c81cacae37fc876497cb9a52accdf 100644 (file)
@@ -22,14 +22,14 @@ static void cirrus_dirty_update(struct cirrus_fbdev *afbdev,
        struct drm_gem_object *obj;
        struct cirrus_bo *bo;
        int src_offset, dst_offset;
-       int bpp = afbdev->gfb.base.format->cpp[0];
+       int bpp = afbdev->gfb.format->cpp[0];
        int ret = -EBUSY;
        bool unmap = false;
        bool store_for_later = false;
        int x2, y2;
        unsigned long flags;
 
-       obj = afbdev->gfb.obj;
+       obj = afbdev->gfb.obj[0];
        bo = gem_to_cirrus_bo(obj);
 
        /*
@@ -82,7 +82,7 @@ static void cirrus_dirty_update(struct cirrus_fbdev *afbdev,
        }
        for (i = y; i < y + height; i++) {
                /* assume equal stride for now */
-               src_offset = dst_offset = i * afbdev->gfb.base.pitches[0] + (x * bpp);
+               src_offset = dst_offset = i * afbdev->gfb.pitches[0] + (x * bpp);
                memcpy_toio(bo->kmap.virtual + src_offset, afbdev->sysram + src_offset, width * bpp);
 
        }
@@ -204,7 +204,7 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
        gfbdev->sysram = sysram;
        gfbdev->size = size;
 
-       fb = &gfbdev->gfb.base;
+       fb = &gfbdev->gfb;
        if (!fb) {
                DRM_INFO("fb is NULL\n");
                return -EINVAL;
@@ -246,19 +246,19 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
 static int cirrus_fbdev_destroy(struct drm_device *dev,
                                struct cirrus_fbdev *gfbdev)
 {
-       struct cirrus_framebuffer *gfb = &gfbdev->gfb;
+       struct drm_framebuffer *gfb = &gfbdev->gfb;
 
        drm_fb_helper_unregister_fbi(&gfbdev->helper);
 
-       if (gfb->obj) {
-               drm_gem_object_put_unlocked(gfb->obj);
-               gfb->obj = NULL;
+       if (gfb->obj[0]) {
+               drm_gem_object_put_unlocked(gfb->obj[0]);
+               gfb->obj[0] = NULL;
        }
 
        vfree(gfbdev->sysram);
        drm_fb_helper_fini(&gfbdev->helper);
-       drm_framebuffer_unregister_private(&gfb->base);
-       drm_framebuffer_cleanup(&gfb->base);
+       drm_framebuffer_unregister_private(gfb);
+       drm_framebuffer_cleanup(gfb);
 
        return 0;
 }
index 26df1e8cd490d57f9fd3af3624f484a588114735..60d54e10a34d434ef3d48fcaa299f1e8c305c13c 100644 (file)
  */
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 
 #include "cirrus_drv.h"
 
-static int cirrus_create_handle(struct drm_framebuffer *fb,
-                               struct drm_file* file_priv,
-                               unsigned int* handle)
-{
-       struct cirrus_framebuffer *cirrus_fb = to_cirrus_framebuffer(fb);
-
-       return drm_gem_handle_create(file_priv, cirrus_fb->obj, handle);
-}
-
-static void cirrus_user_framebuffer_destroy(struct drm_framebuffer *fb)
-{
-       struct cirrus_framebuffer *cirrus_fb = to_cirrus_framebuffer(fb);
-
-       drm_gem_object_put_unlocked(cirrus_fb->obj);
-       drm_framebuffer_cleanup(fb);
-       kfree(fb);
-}
-
 static const struct drm_framebuffer_funcs cirrus_fb_funcs = {
-       .create_handle = cirrus_create_handle,
-       .destroy = cirrus_user_framebuffer_destroy,
+       .create_handle = drm_gem_fb_create_handle,
+       .destroy = drm_gem_fb_destroy,
 };
 
 int cirrus_framebuffer_init(struct drm_device *dev,
-                           struct cirrus_framebuffer *gfb,
+                           struct drm_framebuffer *gfb,
                            const struct drm_mode_fb_cmd2 *mode_cmd,
                            struct drm_gem_object *obj)
 {
        int ret;
 
-       drm_helper_mode_fill_fb_struct(dev, &gfb->base, mode_cmd);
-       gfb->obj = obj;
-       ret = drm_framebuffer_init(dev, &gfb->base, &cirrus_fb_funcs);
+       drm_helper_mode_fill_fb_struct(dev, gfb, mode_cmd);
+       gfb->obj[0] = obj;
+       ret = drm_framebuffer_init(dev, gfb, &cirrus_fb_funcs);
        if (ret) {
                DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
                return ret;
@@ -60,7 +43,7 @@ cirrus_user_framebuffer_create(struct drm_device *dev,
 {
        struct cirrus_device *cdev = dev->dev_private;
        struct drm_gem_object *obj;
-       struct cirrus_framebuffer *cirrus_fb;
+       struct drm_framebuffer *fb;
        u32 bpp;
        int ret;
 
@@ -74,19 +57,19 @@ cirrus_user_framebuffer_create(struct drm_device *dev,
        if (obj == NULL)
                return ERR_PTR(-ENOENT);
 
-       cirrus_fb = kzalloc(sizeof(*cirrus_fb), GFP_KERNEL);
-       if (!cirrus_fb) {
+       fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+       if (!fb) {
                drm_gem_object_put_unlocked(obj);
                return ERR_PTR(-ENOMEM);
        }
 
-       ret = cirrus_framebuffer_init(dev, cirrus_fb, mode_cmd, obj);
+       ret = cirrus_framebuffer_init(dev, fb, mode_cmd, obj);
        if (ret) {
                drm_gem_object_put_unlocked(obj);
-               kfree(cirrus_fb);
+               kfree(fb);
                return ERR_PTR(ret);
        }
-       return &cirrus_fb->base;
+       return fb;
 }
 
 static const struct drm_mode_config_funcs cirrus_mode_funcs = {
index c91b9b054e3f77805bd3ae00b0db3bf74144f6d1..b529f8c8e2a6346d0c4073a95e9644497ed2bce8 100644 (file)
@@ -101,17 +101,13 @@ static int cirrus_crtc_do_set_base(struct drm_crtc *crtc,
                                int x, int y, int atomic)
 {
        struct cirrus_device *cdev = crtc->dev->dev_private;
-       struct drm_gem_object *obj;
-       struct cirrus_framebuffer *cirrus_fb;
        struct cirrus_bo *bo;
        int ret;
        u64 gpu_addr;
 
        /* push the previous fb to system ram */
        if (!atomic && fb) {
-               cirrus_fb = to_cirrus_framebuffer(fb);
-               obj = cirrus_fb->obj;
-               bo = gem_to_cirrus_bo(obj);
+               bo = gem_to_cirrus_bo(fb->obj[0]);
                ret = cirrus_bo_reserve(bo, false);
                if (ret)
                        return ret;
@@ -119,9 +115,7 @@ static int cirrus_crtc_do_set_base(struct drm_crtc *crtc,
                cirrus_bo_unreserve(bo);
        }
 
-       cirrus_fb = to_cirrus_framebuffer(crtc->primary->fb);
-       obj = cirrus_fb->obj;
-       bo = gem_to_cirrus_bo(obj);
+       bo = gem_to_cirrus_bo(crtc->primary->fb->obj[0]);
 
        ret = cirrus_bo_reserve(bo, false);
        if (ret)
@@ -133,7 +127,7 @@ static int cirrus_crtc_do_set_base(struct drm_crtc *crtc,
                return ret;
        }
 
-       if (&cdev->mode_info.gfbdev->gfb == cirrus_fb) {
+       if (&cdev->mode_info.gfbdev->gfb == crtc->primary->fb) {
                /* if pushing console in kmap it */
                ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
                if (ret)
index 895741e9cd7db291c099a69df24bb5d184eb0691..178842380f75847ae3666c4bec261ed5d57299d1 100644 (file)
@@ -30,6 +30,7 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_mode.h>
 #include <drm/drm_print.h>
+#include <drm/drm_writeback.h>
 #include <linux/sync_file.h>
 
 #include "drm_crtc_internal.h"
@@ -325,6 +326,35 @@ static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
        return fence_ptr;
 }
 
+static int set_out_fence_for_connector(struct drm_atomic_state *state,
+                                       struct drm_connector *connector,
+                                       s32 __user *fence_ptr)
+{
+       unsigned int index = drm_connector_index(connector);
+
+       if (!fence_ptr)
+               return 0;
+
+       if (put_user(-1, fence_ptr))
+               return -EFAULT;
+
+       state->connectors[index].out_fence_ptr = fence_ptr;
+
+       return 0;
+}
+
+static s32 __user *get_out_fence_for_connector(struct drm_atomic_state *state,
+                                              struct drm_connector *connector)
+{
+       unsigned int index = drm_connector_index(connector);
+       s32 __user *fence_ptr;
+
+       fence_ptr = state->connectors[index].out_fence_ptr;
+       state->connectors[index].out_fence_ptr = NULL;
+
+       return fence_ptr;
+}
+
 /**
  * drm_atomic_set_mode_for_crtc - set mode for CRTC
  * @state: the CRTC whose incoming state to update
@@ -339,6 +369,7 @@ static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
 int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
                                 const struct drm_display_mode *mode)
 {
+       struct drm_crtc *crtc = state->crtc;
        struct drm_mode_modeinfo umode;
 
        /* Early return for no change. */
@@ -359,13 +390,13 @@ int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
 
                drm_mode_copy(&state->mode, mode);
                state->enable = true;
-               DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n",
-                                mode->name, state);
+               DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
+                                mode->name, crtc->base.id, crtc->name, state);
        } else {
                memset(&state->mode, 0, sizeof(state->mode));
                state->enable = false;
-               DRM_DEBUG_ATOMIC("Set [NOMODE] for CRTC state %p\n",
-                                state);
+               DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
+                                crtc->base.id, crtc->name, state);
        }
 
        return 0;
@@ -388,6 +419,8 @@ EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc);
 int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
                                       struct drm_property_blob *blob)
 {
+       struct drm_crtc *crtc = state->crtc;
+
        if (blob == state->mode_blob)
                return 0;
 
@@ -397,19 +430,34 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
        memset(&state->mode, 0, sizeof(state->mode));
 
        if (blob) {
-               if (blob->length != sizeof(struct drm_mode_modeinfo) ||
-                   drm_mode_convert_umode(state->crtc->dev, &state->mode,
-                                          blob->data))
+               int ret;
+
+               if (blob->length != sizeof(struct drm_mode_modeinfo)) {
+                       DRM_DEBUG_ATOMIC("[CRTC:%d:%s] bad mode blob length: %zu\n",
+                                        crtc->base.id, crtc->name,
+                                        blob->length);
                        return -EINVAL;
+               }
+
+               ret = drm_mode_convert_umode(crtc->dev,
+                                            &state->mode, blob->data);
+               if (ret) {
+                       DRM_DEBUG_ATOMIC("[CRTC:%d:%s] invalid mode (ret=%d, status=%s):\n",
+                                        crtc->base.id, crtc->name,
+                                        ret, drm_get_mode_status_name(state->mode.status));
+                       drm_mode_debug_printmodeline(&state->mode);
+                       return -EINVAL;
+               }
 
                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);
+               DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
+                                state->mode.name, crtc->base.id, crtc->name,
+                                state);
        } else {
                state->enable = false;
-               DRM_DEBUG_ATOMIC("Set [NOMODE] for CRTC state %p\n",
-                                state);
+               DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
+                                crtc->base.id, crtc->name, state);
        }
 
        return 0;
@@ -539,10 +587,14 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
                        return -EFAULT;
 
                set_out_fence_for_crtc(state->state, crtc, fence_ptr);
-       } else if (crtc->funcs->atomic_set_property)
+       } else if (crtc->funcs->atomic_set_property) {
                return crtc->funcs->atomic_set_property(crtc, state, property, val);
-       else
+       } else {
+               DRM_DEBUG_ATOMIC("[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n",
+                                crtc->base.id, crtc->name,
+                                property->base.id, property->name);
                return -EINVAL;
+       }
 
        return 0;
 }
@@ -676,6 +728,51 @@ static void drm_atomic_crtc_print_state(struct drm_printer *p,
                crtc->funcs->atomic_print_state(p, state);
 }
 
+/**
+ * drm_atomic_connector_check - check connector state
+ * @connector: connector to check
+ * @state: connector state to check
+ *
+ * Provides core sanity checks for connector state.
+ *
+ * RETURNS:
+ * Zero on success, error code on failure
+ */
+static int drm_atomic_connector_check(struct drm_connector *connector,
+               struct drm_connector_state *state)
+{
+       struct drm_crtc_state *crtc_state;
+       struct drm_writeback_job *writeback_job = state->writeback_job;
+
+       if ((connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK) || !writeback_job)
+               return 0;
+
+       if (writeback_job->fb && !state->crtc) {
+               DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] framebuffer without CRTC\n",
+                                connector->base.id, connector->name);
+               return -EINVAL;
+       }
+
+       if (state->crtc)
+               crtc_state = drm_atomic_get_existing_crtc_state(state->state,
+                                                               state->crtc);
+
+       if (writeback_job->fb && !crtc_state->active) {
+               DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] has framebuffer, but [CRTC:%d] is off\n",
+                                connector->base.id, connector->name,
+                                state->crtc->base.id);
+               return -EINVAL;
+       }
+
+       if (writeback_job->out_fence && !writeback_job->fb) {
+               DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] requesting out-fence without framebuffer\n",
+                                connector->base.id, connector->name);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 /**
  * drm_atomic_get_plane_state - get plane state
  * @state: global atomic state object
@@ -700,6 +797,11 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state,
 
        WARN_ON(!state->acquire_ctx);
 
+       /* the legacy pointers should never be set */
+       WARN_ON(plane->fb);
+       WARN_ON(plane->old_fb);
+       WARN_ON(plane->crtc);
+
        plane_state = drm_atomic_get_existing_plane_state(state, plane);
        if (plane_state)
                return plane_state;
@@ -794,8 +896,11 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
        } else if (property == plane->alpha_property) {
                state->alpha = val;
        } else if (property == plane->rotation_property) {
-               if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK))
+               if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK)) {
+                       DRM_DEBUG_ATOMIC("[PLANE:%d:%s] bad rotation bitmask: 0x%llx\n",
+                                        plane->base.id, plane->name, val);
                        return -EINVAL;
+               }
                state->rotation = val;
        } else if (property == plane->zpos_property) {
                state->zpos = val;
@@ -807,6 +912,9 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
                return plane->funcs->atomic_set_property(plane, state,
                                property, val);
        } else {
+               DRM_DEBUG_ATOMIC("[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
+                                plane->base.id, plane->name,
+                                property->base.id, property->name);
                return -EINVAL;
        }
 
@@ -914,10 +1022,12 @@ static int drm_atomic_plane_check(struct drm_plane *plane,
 
        /* either *both* CRTC and FB must be set, or neither */
        if (state->crtc && !state->fb) {
-               DRM_DEBUG_ATOMIC("CRTC set but no FB\n");
+               DRM_DEBUG_ATOMIC("[PLANE:%d:%s] CRTC set but no FB\n",
+                                plane->base.id, plane->name);
                return -EINVAL;
        } else if (state->fb && !state->crtc) {
-               DRM_DEBUG_ATOMIC("FB set but no CRTC\n");
+               DRM_DEBUG_ATOMIC("[PLANE:%d:%s] FB set but no CRTC\n",
+                                plane->base.id, plane->name);
                return -EINVAL;
        }
 
@@ -927,7 +1037,9 @@ static int drm_atomic_plane_check(struct drm_plane *plane,
 
        /* Check whether this plane is usable on this CRTC */
        if (!(plane->possible_crtcs & drm_crtc_mask(state->crtc))) {
-               DRM_DEBUG_ATOMIC("Invalid crtc for plane\n");
+               DRM_DEBUG_ATOMIC("Invalid [CRTC:%d:%s] for [PLANE:%d:%s]\n",
+                                state->crtc->base.id, state->crtc->name,
+                                plane->base.id, plane->name);
                return -EINVAL;
        }
 
@@ -936,7 +1048,8 @@ static int drm_atomic_plane_check(struct drm_plane *plane,
                                           state->fb->modifier);
        if (ret) {
                struct drm_format_name_buf format_name;
-               DRM_DEBUG_ATOMIC("Invalid pixel format %s, modifier 0x%llx\n",
+               DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid pixel format %s, modifier 0x%llx\n",
+                                plane->base.id, plane->name,
                                 drm_get_format_name(state->fb->format->format,
                                                     &format_name),
                                 state->fb->modifier);
@@ -948,7 +1061,8 @@ static int drm_atomic_plane_check(struct drm_plane *plane,
            state->crtc_x > INT_MAX - (int32_t) state->crtc_w ||
            state->crtc_h > INT_MAX ||
            state->crtc_y > INT_MAX - (int32_t) state->crtc_h) {
-               DRM_DEBUG_ATOMIC("Invalid CRTC coordinates %ux%u+%d+%d\n",
+               DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid CRTC coordinates %ux%u+%d+%d\n",
+                                plane->base.id, plane->name,
                                 state->crtc_w, state->crtc_h,
                                 state->crtc_x, state->crtc_y);
                return -ERANGE;
@@ -962,8 +1076,9 @@ static int drm_atomic_plane_check(struct drm_plane *plane,
            state->src_x > fb_width - state->src_w ||
            state->src_h > fb_height ||
            state->src_y > fb_height - state->src_h) {
-               DRM_DEBUG_ATOMIC("Invalid source coordinates "
+               DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid source coordinates "
                                 "%u.%06ux%u.%06u+%u.%06u+%u.%06u (fb %ux%u)\n",
+                                plane->base.id, plane->name,
                                 state->src_w >> 16, ((state->src_w & 0xffff) * 15625) >> 10,
                                 state->src_h >> 16, ((state->src_h & 0xffff) * 15625) >> 10,
                                 state->src_x >> 16, ((state->src_x & 0xffff) * 15625) >> 10,
@@ -1120,6 +1235,7 @@ drm_atomic_get_private_obj_state(struct drm_atomic_state *state,
        state->private_objs[index].old_state = obj->state;
        state->private_objs[index].new_state = obj_state;
        state->private_objs[index].ptr = obj;
+       obj_state->state = state;
 
        state->num_private_objs = num_objs;
 
@@ -1278,6 +1394,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
                        state->link_status = val;
        } else if (property == config->aspect_ratio_property) {
                state->picture_aspect_ratio = val;
+       } else if (property == config->content_type_property) {
+               state->content_type = val;
        } else if (property == connector->scaling_mode_property) {
                state->scaling_mode = val;
        } else if (property == connector->content_protection_property) {
@@ -1286,10 +1404,24 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
                        return -EINVAL;
                }
                state->content_protection = val;
+       } else if (property == config->writeback_fb_id_property) {
+               struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
+               int ret = drm_atomic_set_writeback_fb_for_connector(state, fb);
+               if (fb)
+                       drm_framebuffer_put(fb);
+               return ret;
+       } else if (property == config->writeback_out_fence_ptr_property) {
+               s32 __user *fence_ptr = u64_to_user_ptr(val);
+
+               return set_out_fence_for_connector(state->state, connector,
+                                                  fence_ptr);
        } else if (connector->funcs->atomic_set_property) {
                return connector->funcs->atomic_set_property(connector,
                                state, property, val);
        } else {
+               DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",
+                                connector->base.id, connector->name,
+                                property->base.id, property->name);
                return -EINVAL;
        }
 
@@ -1363,10 +1495,17 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
                *val = state->link_status;
        } else if (property == config->aspect_ratio_property) {
                *val = state->picture_aspect_ratio;
+       } else if (property == config->content_type_property) {
+               *val = state->content_type;
        } else if (property == connector->scaling_mode_property) {
                *val = state->scaling_mode;
        } else if (property == connector->content_protection_property) {
                *val = state->content_protection;
+       } else if (property == config->writeback_fb_id_property) {
+               /* Writeback framebuffer is one-shot, write and forget */
+               *val = 0;
+       } else if (property == config->writeback_out_fence_ptr_property) {
+               *val = 0;
        } else if (connector->funcs->atomic_get_property) {
                return connector->funcs->atomic_get_property(connector,
                                state, property, val);
@@ -1456,11 +1595,12 @@ drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
        }
 
        if (crtc)
-               DRM_DEBUG_ATOMIC("Link plane state %p to [CRTC:%d:%s]\n",
-                                plane_state, crtc->base.id, crtc->name);
+               DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [CRTC:%d:%s]\n",
+                                plane->base.id, plane->name, plane_state,
+                                crtc->base.id, crtc->name);
        else
-               DRM_DEBUG_ATOMIC("Link plane state %p to [NOCRTC]\n",
-                                plane_state);
+               DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [NOCRTC]\n",
+                                plane->base.id, plane->name, plane_state);
 
        return 0;
 }
@@ -1480,12 +1620,15 @@ void
 drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
                            struct drm_framebuffer *fb)
 {
+       struct drm_plane *plane = plane_state->plane;
+
        if (fb)
-               DRM_DEBUG_ATOMIC("Set [FB:%d] for plane state %p\n",
-                                fb->base.id, plane_state);
-       else
-               DRM_DEBUG_ATOMIC("Set [NOFB] for plane state %p\n",
+               DRM_DEBUG_ATOMIC("Set [FB:%d] for [PLANE:%d:%s] state %p\n",
+                                fb->base.id, plane->base.id, plane->name,
                                 plane_state);
+       else
+               DRM_DEBUG_ATOMIC("Set [NOFB] for [PLANE:%d:%s] state %p\n",
+                                plane->base.id, plane->name, plane_state);
 
        drm_framebuffer_assign(&plane_state->fb, fb);
 }
@@ -1546,6 +1689,7 @@ int
 drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
                                  struct drm_crtc *crtc)
 {
+       struct drm_connector *connector = conn_state->connector;
        struct drm_crtc_state *crtc_state;
 
        if (conn_state->crtc == crtc)
@@ -1573,10 +1717,12 @@ drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
                drm_connector_get(conn_state->connector);
                conn_state->crtc = crtc;
 
-               DRM_DEBUG_ATOMIC("Link connector state %p to [CRTC:%d:%s]\n",
+               DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [CRTC:%d:%s]\n",
+                                connector->base.id, connector->name,
                                 conn_state, crtc->base.id, crtc->name);
        } else {
-               DRM_DEBUG_ATOMIC("Link connector state %p to [NOCRTC]\n",
+               DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [NOCRTC]\n",
+                                connector->base.id, connector->name,
                                 conn_state);
        }
 
@@ -1584,6 +1730,70 @@ drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
 }
 EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector);
 
+/*
+ * drm_atomic_get_writeback_job - return or allocate a writeback job
+ * @conn_state: Connector state to get the job for
+ *
+ * Writeback jobs have a different lifetime to the atomic state they are
+ * associated with. This convenience function takes care of allocating a job
+ * if there isn't yet one associated with the connector state, otherwise
+ * it just returns the existing job.
+ *
+ * Returns: The writeback job for the given connector state
+ */
+static struct drm_writeback_job *
+drm_atomic_get_writeback_job(struct drm_connector_state *conn_state)
+{
+       WARN_ON(conn_state->connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
+
+       if (!conn_state->writeback_job)
+               conn_state->writeback_job =
+                       kzalloc(sizeof(*conn_state->writeback_job), GFP_KERNEL);
+
+       return conn_state->writeback_job;
+}
+
+/**
+ * drm_atomic_set_writeback_fb_for_connector - set writeback framebuffer
+ * @conn_state: atomic state object for the connector
+ * @fb: fb to use for the connector
+ *
+ * This is used to set the framebuffer for a writeback connector, which outputs
+ * to a buffer instead of an actual physical connector.
+ * Changing the assigned framebuffer requires us to grab a reference to the new
+ * fb and drop the reference to the old fb, if there is one. This function
+ * takes care of all these details besides updating the pointer in the
+ * state object itself.
+ *
+ * Note: The only way conn_state can already have an fb set is if the commit
+ * sets the property more than once.
+ *
+ * See also: drm_writeback_connector_init()
+ *
+ * Returns: 0 on success
+ */
+int drm_atomic_set_writeback_fb_for_connector(
+               struct drm_connector_state *conn_state,
+               struct drm_framebuffer *fb)
+{
+       struct drm_writeback_job *job =
+               drm_atomic_get_writeback_job(conn_state);
+       if (!job)
+               return -ENOMEM;
+
+       drm_framebuffer_assign(&job->fb, fb);
+
+       if (fb)
+               DRM_DEBUG_ATOMIC("Set [FB:%d] for connector state %p\n",
+                                fb->base.id, conn_state);
+       else
+               DRM_DEBUG_ATOMIC("Set [NOFB] for connector state %p\n",
+                                conn_state);
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_atomic_set_writeback_fb_for_connector);
+
 /**
  * drm_atomic_add_affected_connectors - add connectors for crtc
  * @state: atomic state
@@ -1672,6 +1882,9 @@ drm_atomic_add_affected_planes(struct drm_atomic_state *state,
 
        WARN_ON(!drm_atomic_get_new_crtc_state(state, crtc));
 
+       DRM_DEBUG_ATOMIC("Adding all current planes for [CRTC:%d:%s] to %p\n",
+                        crtc->base.id, crtc->name, state);
+
        drm_for_each_plane_mask(plane, state->dev, crtc->state->plane_mask) {
                struct drm_plane_state *plane_state =
                        drm_atomic_get_plane_state(state, plane);
@@ -1702,6 +1915,8 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
        struct drm_plane_state *plane_state;
        struct drm_crtc *crtc;
        struct drm_crtc_state *crtc_state;
+       struct drm_connector *conn;
+       struct drm_connector_state *conn_state;
        int i, ret = 0;
 
        DRM_DEBUG_ATOMIC("checking %p\n", state);
@@ -1724,6 +1939,15 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
                }
        }
 
+       for_each_new_connector_in_state(state, conn, conn_state, i) {
+               ret = drm_atomic_connector_check(conn, conn_state);
+               if (ret) {
+                       DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] atomic core check failed\n",
+                                        conn->base.id, conn->name);
+                       return ret;
+               }
+       }
+
        if (config->funcs->atomic_check) {
                ret = config->funcs->atomic_check(state->dev, state);
 
@@ -2047,45 +2271,6 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
        return ret;
 }
 
-/**
- * drm_atomic_clean_old_fb -- Unset old_fb pointers and set plane->fb pointers.
- *
- * @dev: drm device to check.
- * @plane_mask: plane mask for planes that were updated.
- * @ret: return value, can be -EDEADLK for a retry.
- *
- * Before doing an update &drm_plane.old_fb is set to &drm_plane.fb, but before
- * dropping the locks old_fb needs to be set to NULL and plane->fb updated. This
- * is a common operation for each atomic update, so this call is split off as a
- * helper.
- */
-void drm_atomic_clean_old_fb(struct drm_device *dev,
-                            unsigned plane_mask,
-                            int ret)
-{
-       struct drm_plane *plane;
-
-       /* if succeeded, fixup legacy plane crtc/fb ptrs before dropping
-        * locks (ie. while it is still safe to deref plane->state).  We
-        * need to do this here because the driver entry points cannot
-        * distinguish between legacy and atomic ioctls.
-        */
-       drm_for_each_plane_mask(plane, dev, plane_mask) {
-               if (ret == 0) {
-                       struct drm_framebuffer *new_fb = plane->state->fb;
-                       if (new_fb)
-                               drm_framebuffer_get(new_fb);
-                       plane->fb = new_fb;
-                       plane->crtc = plane->state->crtc;
-
-                       if (plane->old_fb)
-                               drm_framebuffer_put(plane->old_fb);
-               }
-               plane->old_fb = NULL;
-       }
-}
-EXPORT_SYMBOL(drm_atomic_clean_old_fb);
-
 /**
  * DOC: explicit fencing properties
  *
@@ -2161,7 +2346,7 @@ static int setup_out_fence(struct drm_out_fence_state *fence_state,
        return 0;
 }
 
-static int prepare_crtc_signaling(struct drm_device *dev,
+static int prepare_signaling(struct drm_device *dev,
                                  struct drm_atomic_state *state,
                                  struct drm_mode_atomic *arg,
                                  struct drm_file *file_priv,
@@ -2170,6 +2355,8 @@ static int prepare_crtc_signaling(struct drm_device *dev,
 {
        struct drm_crtc *crtc;
        struct drm_crtc_state *crtc_state;
+       struct drm_connector *conn;
+       struct drm_connector_state *conn_state;
        int i, c = 0, ret;
 
        if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
@@ -2235,6 +2422,43 @@ static int prepare_crtc_signaling(struct drm_device *dev,
                c++;
        }
 
+       for_each_new_connector_in_state(state, conn, conn_state, i) {
+               struct drm_writeback_job *job;
+               struct drm_out_fence_state *f;
+               struct dma_fence *fence;
+               s32 __user *fence_ptr;
+
+               fence_ptr = get_out_fence_for_connector(state, conn);
+               if (!fence_ptr)
+                       continue;
+
+               job = drm_atomic_get_writeback_job(conn_state);
+               if (!job)
+                       return -ENOMEM;
+
+               f = krealloc(*fence_state, sizeof(**fence_state) *
+                            (*num_fences + 1), GFP_KERNEL);
+               if (!f)
+                       return -ENOMEM;
+
+               memset(&f[*num_fences], 0, sizeof(*f));
+
+               f[*num_fences].out_fence_ptr = fence_ptr;
+               *fence_state = f;
+
+               fence = drm_writeback_get_out_fence((struct drm_writeback_connector *)conn);
+               if (!fence)
+                       return -ENOMEM;
+
+               ret = setup_out_fence(&f[(*num_fences)++], fence);
+               if (ret) {
+                       dma_fence_put(fence);
+                       return ret;
+               }
+
+               job->out_fence = fence;
+       }
+
        /*
         * Having this flag means user mode pends on event which will never
         * reach due to lack of at least one CRTC for signaling
@@ -2245,11 +2469,11 @@ static int prepare_crtc_signaling(struct drm_device *dev,
        return 0;
 }
 
-static void complete_crtc_signaling(struct drm_device *dev,
-                                   struct drm_atomic_state *state,
-                                   struct drm_out_fence_state *fence_state,
-                                   unsigned int num_fences,
-                                   bool install_fds)
+static void complete_signaling(struct drm_device *dev,
+                              struct drm_atomic_state *state,
+                              struct drm_out_fence_state *fence_state,
+                              unsigned int num_fences,
+                              bool install_fds)
 {
        struct drm_crtc *crtc;
        struct drm_crtc_state *crtc_state;
@@ -2306,9 +2530,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
        unsigned int copied_objs, copied_props;
        struct drm_atomic_state *state;
        struct drm_modeset_acquire_ctx ctx;
-       struct drm_plane *plane;
        struct drm_out_fence_state *fence_state;
-       unsigned plane_mask;
        int ret = 0;
        unsigned int i, j, num_fences;
 
@@ -2348,7 +2570,6 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
        state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
 
 retry:
-       plane_mask = 0;
        copied_objs = 0;
        copied_props = 0;
        fence_state = NULL;
@@ -2419,17 +2640,11 @@ retry:
                        copied_props++;
                }
 
-               if (obj->type == DRM_MODE_OBJECT_PLANE && count_props &&
-                   !(arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)) {
-                       plane = obj_to_plane(obj);
-                       plane_mask |= (1 << drm_plane_index(plane));
-                       plane->old_fb = plane->fb;
-               }
                drm_mode_object_put(obj);
        }
 
-       ret = prepare_crtc_signaling(dev, state, arg, file_priv, &fence_state,
-                                    &num_fences);
+       ret = prepare_signaling(dev, state, arg, file_priv, &fence_state,
+                               &num_fences);
        if (ret)
                goto out;
 
@@ -2445,9 +2660,7 @@ retry:
        }
 
 out:
-       drm_atomic_clean_old_fb(dev, plane_mask, ret);
-
-       complete_crtc_signaling(dev, state, fence_state, num_fences, !ret);
+       complete_signaling(dev, state, fence_state, num_fences, !ret);
 
        if (ret == -EDEADLK) {
                drm_atomic_state_clear(state);
index 130da5195f3b622062c274507eb0727c76601473..17baf5057132ea6a5700b039e02252ed97d3859e 100644 (file)
@@ -30,6 +30,7 @@
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_writeback.h>
 #include <linux/dma-fence.h>
 
 #include "drm_crtc_helper_internal.h"
@@ -1172,6 +1173,25 @@ void drm_atomic_helper_commit_modeset_disables(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_disables);
 
+static void drm_atomic_helper_commit_writebacks(struct drm_device *dev,
+                                               struct drm_atomic_state *old_state)
+{
+       struct drm_connector *connector;
+       struct drm_connector_state *new_conn_state;
+       int i;
+
+       for_each_new_connector_in_state(old_state, connector, new_conn_state, i) {
+               const struct drm_connector_helper_funcs *funcs;
+
+               funcs = connector->helper_private;
+
+               if (new_conn_state->writeback_job && new_conn_state->writeback_job->fb) {
+                       WARN_ON(connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
+                       funcs->atomic_commit(connector, new_conn_state->writeback_job);
+               }
+       }
+}
+
 /**
  * drm_atomic_helper_commit_modeset_enables - modeset commit to enable outputs
  * @dev: DRM device
@@ -1251,6 +1271,8 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
 
                drm_bridge_enable(encoder->bridge);
        }
+
+       drm_atomic_helper_commit_writebacks(dev, old_state);
 }
 EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables);
 
@@ -2914,7 +2936,6 @@ static int __drm_atomic_helper_disable_all(struct drm_device *dev,
        struct drm_plane *plane;
        struct drm_crtc_state *crtc_state;
        struct drm_crtc *crtc;
-       unsigned plane_mask = 0;
        int ret, i;
 
        state = drm_atomic_state_alloc(dev);
@@ -2957,17 +2978,10 @@ static int __drm_atomic_helper_disable_all(struct drm_device *dev,
                        goto free;
 
                drm_atomic_set_fb_for_plane(plane_state, NULL);
-
-               if (clean_old_fbs) {
-                       plane->old_fb = plane->fb;
-                       plane_mask |= BIT(drm_plane_index(plane));
-               }
        }
 
        ret = drm_atomic_commit(state);
 free:
-       if (plane_mask)
-               drm_atomic_clean_old_fb(dev, plane_mask, ret);
        drm_atomic_state_put(state);
        return ret;
 }
@@ -3129,13 +3143,8 @@ int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
 
        state->acquire_ctx = ctx;
 
-       for_each_new_plane_in_state(state, plane, new_plane_state, i) {
-               WARN_ON(plane->crtc != new_plane_state->crtc);
-               WARN_ON(plane->fb != new_plane_state->fb);
-               WARN_ON(plane->old_fb);
-
+       for_each_new_plane_in_state(state, plane, new_plane_state, i)
                state->planes[i].old_state = plane->state;
-       }
 
        for_each_new_crtc_in_state(state, crtc, new_crtc_state, i)
                state->crtcs[i].old_state = crtc->state;
@@ -3660,6 +3669,9 @@ __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
        if (state->crtc)
                drm_connector_get(connector);
        state->commit = NULL;
+
+       /* Don't copy over a writeback job, they are used only once */
+       state->writeback_job = NULL;
 }
 EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state);
 
index 9b9ba5d5ec0cb30549e678346161d9f21dc01a78..2f9ebddd178e1e06e462dc8d32db869ee92efcc2 100644 (file)
@@ -87,6 +87,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = {
        { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
        { DRM_MODE_CONNECTOR_DSI, "DSI" },
        { DRM_MODE_CONNECTOR_DPI, "DPI" },
+       { DRM_MODE_CONNECTOR_WRITEBACK, "Writeback" },
 };
 
 void drm_connector_ida_init(void)
@@ -195,6 +196,10 @@ int drm_connector_init(struct drm_device *dev,
        struct ida *connector_ida =
                &drm_connector_enum_list[connector_type].ida;
 
+       WARN_ON(drm_drv_uses_atomic_modeset(dev) &&
+               (!funcs->atomic_destroy_state ||
+                !funcs->atomic_duplicate_state));
+
        ret = __drm_mode_object_add(dev, &connector->base,
                                    DRM_MODE_OBJECT_CONNECTOR,
                                    false, drm_connector_free);
@@ -249,7 +254,8 @@ int drm_connector_init(struct drm_device *dev,
        config->num_connector++;
        spin_unlock_irq(&config->connector_list_lock);
 
-       if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
+       if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL &&
+           connector_type != DRM_MODE_CONNECTOR_WRITEBACK)
                drm_object_attach_property(&connector->base,
                                              config->edid_property,
                                              0);
@@ -720,6 +726,14 @@ static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = {
        { DRM_MODE_PICTURE_ASPECT_16_9, "16:9" },
 };
 
+static const struct drm_prop_enum_list drm_content_type_enum_list[] = {
+       { DRM_MODE_CONTENT_TYPE_NO_DATA, "No Data" },
+       { DRM_MODE_CONTENT_TYPE_GRAPHICS, "Graphics" },
+       { DRM_MODE_CONTENT_TYPE_PHOTO, "Photo" },
+       { DRM_MODE_CONTENT_TYPE_CINEMA, "Cinema" },
+       { DRM_MODE_CONTENT_TYPE_GAME, "Game" },
+};
+
 static const struct drm_prop_enum_list drm_panel_orientation_enum_list[] = {
        { DRM_MODE_PANEL_ORIENTATION_NORMAL,    "Normal"        },
        { DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP, "Upside Down"   },
@@ -996,6 +1010,84 @@ int drm_mode_create_dvi_i_properties(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_mode_create_dvi_i_properties);
 
+/**
+ * DOC: HDMI connector properties
+ *
+ * content type (HDMI specific):
+ *     Indicates content type setting to be used in HDMI infoframes to indicate
+ *     content type for the external device, so that it adjusts it's display
+ *     settings accordingly.
+ *
+ *     The value of this property can be one of the following:
+ *
+ *     No Data:
+ *             Content type is unknown
+ *     Graphics:
+ *             Content type is graphics
+ *     Photo:
+ *             Content type is photo
+ *     Cinema:
+ *             Content type is cinema
+ *     Game:
+ *             Content type is game
+ *
+ *     Drivers can set up this property by calling
+ *     drm_connector_attach_content_type_property(). Decoding to
+ *     infoframe values is done through
+ *     drm_hdmi_get_content_type_from_property() and
+ *     drm_hdmi_get_itc_bit_from_property().
+ */
+
+/**
+ * drm_connector_attach_content_type_property - attach content-type property
+ * @connector: connector to attach content type property on.
+ *
+ * Called by a driver the first time a HDMI connector is made.
+ */
+int drm_connector_attach_content_type_property(struct drm_connector *connector)
+{
+       if (!drm_mode_create_content_type_property(connector->dev))
+               drm_object_attach_property(&connector->base,
+                                          connector->dev->mode_config.content_type_property,
+                                          DRM_MODE_CONTENT_TYPE_NO_DATA);
+       return 0;
+}
+EXPORT_SYMBOL(drm_connector_attach_content_type_property);
+
+
+/**
+ * drm_hdmi_avi_infoframe_content_type() - fill the HDMI AVI infoframe
+ *                                         content type information, based
+ *                                         on correspondent DRM property.
+ * @frame: HDMI AVI infoframe
+ * @conn_state: DRM display connector state
+ *
+ */
+void drm_hdmi_avi_infoframe_content_type(struct hdmi_avi_infoframe *frame,
+                                        const struct drm_connector_state *conn_state)
+{
+       switch (conn_state->content_type) {
+       case DRM_MODE_CONTENT_TYPE_GRAPHICS:
+               frame->content_type = HDMI_CONTENT_TYPE_GRAPHICS;
+               break;
+       case DRM_MODE_CONTENT_TYPE_CINEMA:
+               frame->content_type = HDMI_CONTENT_TYPE_CINEMA;
+               break;
+       case DRM_MODE_CONTENT_TYPE_GAME:
+               frame->content_type = HDMI_CONTENT_TYPE_GAME;
+               break;
+       case DRM_MODE_CONTENT_TYPE_PHOTO:
+               frame->content_type = HDMI_CONTENT_TYPE_PHOTO;
+               break;
+       default:
+               /* Graphics is the default(0) */
+               frame->content_type = HDMI_CONTENT_TYPE_GRAPHICS;
+       }
+
+       frame->itc = conn_state->content_type != DRM_MODE_CONTENT_TYPE_NO_DATA;
+}
+EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type);
+
 /**
  * drm_create_tv_properties - create TV specific connector properties
  * @dev: DRM device
@@ -1260,6 +1352,33 @@ int drm_mode_create_aspect_ratio_property(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property);
 
+/**
+ * drm_mode_create_content_type_property - create content type property
+ * @dev: DRM device
+ *
+ * Called by a driver the first time it's needed, must be attached to desired
+ * connectors.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_create_content_type_property(struct drm_device *dev)
+{
+       if (dev->mode_config.content_type_property)
+               return 0;
+
+       dev->mode_config.content_type_property =
+               drm_property_create_enum(dev, 0, "content type",
+                                        drm_content_type_enum_list,
+                                        ARRAY_SIZE(drm_content_type_enum_list));
+
+       if (dev->mode_config.content_type_property == NULL)
+               return -ENOMEM;
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_mode_create_content_type_property);
+
 /**
  * drm_mode_create_suggested_offset_properties - create suggests offset properties
  * @dev: DRM device
index 98a36e6c69ad1b158184daa434559800abf3b86a..f45e7a8d4acd61486e40091ac5cca45b6abbd095 100644 (file)
@@ -286,6 +286,10 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
        if (WARN_ON(config->num_crtc >= 32))
                return -EINVAL;
 
+       WARN_ON(drm_drv_uses_atomic_modeset(dev) &&
+               (!funcs->atomic_destroy_state ||
+                !funcs->atomic_duplicate_state));
+
        crtc->dev = dev;
        crtc->funcs = funcs;
 
@@ -469,23 +473,32 @@ static int __drm_mode_set_config_internal(struct drm_mode_set *set,
         * connectors from it), hence we need to refcount the fbs across all
         * crtcs. Atomic modeset will have saner semantics ...
         */
-       drm_for_each_crtc(tmp, crtc->dev)
-               tmp->primary->old_fb = tmp->primary->fb;
+       drm_for_each_crtc(tmp, crtc->dev) {
+               struct drm_plane *plane = tmp->primary;
+
+               plane->old_fb = plane->fb;
+       }
 
        fb = set->fb;
 
        ret = crtc->funcs->set_config(set, ctx);
        if (ret == 0) {
-               crtc->primary->crtc = fb ? crtc : NULL;
-               crtc->primary->fb = fb;
+               struct drm_plane *plane = crtc->primary;
+
+               if (!plane->state) {
+                       plane->crtc = fb ? crtc : NULL;
+                       plane->fb = fb;
+               }
        }
 
        drm_for_each_crtc(tmp, crtc->dev) {
-               if (tmp->primary->fb)
-                       drm_framebuffer_get(tmp->primary->fb);
-               if (tmp->primary->old_fb)
-                       drm_framebuffer_put(tmp->primary->old_fb);
-               tmp->primary->old_fb = NULL;
+               struct drm_plane *plane = tmp->primary;
+
+               if (plane->fb)
+                       drm_framebuffer_get(plane->fb);
+               if (plane->old_fb)
+                       drm_framebuffer_put(plane->old_fb);
+               plane->old_fb = NULL;
        }
 
        return ret;
@@ -640,7 +653,9 @@ retry:
 
                ret = drm_mode_convert_umode(dev, mode, &crtc_req->mode);
                if (ret) {
-                       DRM_DEBUG_KMS("Invalid mode\n");
+                       DRM_DEBUG_KMS("Invalid mode (ret=%d, status=%s)\n",
+                                     ret, drm_get_mode_status_name(mode->status));
+                       drm_mode_debug_printmodeline(mode);
                        goto out;
                }
 
index 5d307b23a4e66f176b8ce83cfd2119935a7da597..34499800932a2eb5deca0ae7b75bc7793f05cf3c 100644 (file)
@@ -56,6 +56,9 @@ int drm_mode_setcrtc(struct drm_device *dev,
 int drm_modeset_register_all(struct drm_device *dev);
 void drm_modeset_unregister_all(struct drm_device *dev);
 
+/* drm_modes.c */
+const char *drm_get_mode_status_name(enum drm_mode_status status);
+
 /* IOCTLs */
 int drm_mode_getresources(struct drm_device *dev,
                          void *data, struct drm_file *file_priv);
index a5808382bdf0333b2124a4ecf0d85c4346814000..5dc742b27ca033652880ceaabc1257ae5b633328 100644 (file)
@@ -163,8 +163,9 @@ static const struct edid_quirk {
        /* Rotel RSX-1058 forwards sink's EDID but only does HDMI 1.1*/
        { "ETR", 13896, EDID_QUIRK_FORCE_8BPC },
 
-       /* HTC Vive VR Headset */
+       /* HTC Vive and Vive Pro VR Headsets */
        { "HVR", 0xaa01, EDID_QUIRK_NON_DESKTOP },
+       { "HVR", 0xaa02, EDID_QUIRK_NON_DESKTOP },
 
        /* Oculus Rift DK1, DK2, and CV1 VR Headsets */
        { "OVR", 0x0001, EDID_QUIRK_NON_DESKTOP },
@@ -687,562 +688,562 @@ static const struct minimode extra_modes[] = {
 static const struct drm_display_mode edid_cea_modes[] = {
        /* 0 - dummy, VICs start at 1 */
        { },
-       /* 1 - 640x480@60Hz */
+       /* 1 - 640x480@60Hz 4:3 */
        { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
                   752, 800, 0, 480, 490, 492, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 2 - 720x480@60Hz */
+       /* 2 - 720x480@60Hz 4:3 */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 3 - 720x480@60Hz */
+       /* 3 - 720x480@60Hz 16:9 */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 4 - 1280x720@60Hz */
+       /* 4 - 1280x720@60Hz 16:9 */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390,
                   1430, 1650, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 5 - 1920x1080i@60Hz */
+       /* 5 - 1920x1080i@60Hz 16:9 */
        { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
-                       DRM_MODE_FLAG_INTERLACE),
+                  DRM_MODE_FLAG_INTERLACE),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 6 - 720(1440)x480i@60Hz */
+       /* 6 - 720(1440)x480i@60Hz 4:3 */
        { DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500, 720, 739,
                   801, 858, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
+                  DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 7 - 720(1440)x480i@60Hz */
+       /* 7 - 720(1440)x480i@60Hz 16:9 */
        { DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500, 720, 739,
                   801, 858, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
+                  DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 8 - 720(1440)x240@60Hz */
+       /* 8 - 720(1440)x240@60Hz 4:3 */
        { DRM_MODE("720x240", DRM_MODE_TYPE_DRIVER, 13500, 720, 739,
                   801, 858, 0, 240, 244, 247, 262, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_DBLCLK),
+                  DRM_MODE_FLAG_DBLCLK),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 9 - 720(1440)x240@60Hz */
+       /* 9 - 720(1440)x240@60Hz 16:9 */
        { DRM_MODE("720x240", DRM_MODE_TYPE_DRIVER, 13500, 720, 739,
                   801, 858, 0, 240, 244, 247, 262, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_DBLCLK),
+                  DRM_MODE_FLAG_DBLCLK),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 10 - 2880x480i@60Hz */
+       /* 10 - 2880x480i@60Hz 4:3 */
        { DRM_MODE("2880x480i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
                   3204, 3432, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_INTERLACE),
+                  DRM_MODE_FLAG_INTERLACE),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 11 - 2880x480i@60Hz */
+       /* 11 - 2880x480i@60Hz 16:9 */
        { DRM_MODE("2880x480i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
                   3204, 3432, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_INTERLACE),
+                  DRM_MODE_FLAG_INTERLACE),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 12 - 2880x240@60Hz */
+       /* 12 - 2880x240@60Hz 4:3 */
        { DRM_MODE("2880x240", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
                   3204, 3432, 0, 240, 244, 247, 262, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 13 - 2880x240@60Hz */
+       /* 13 - 2880x240@60Hz 16:9 */
        { DRM_MODE("2880x240", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
                   3204, 3432, 0, 240, 244, 247, 262, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 14 - 1440x480@60Hz */
+       /* 14 - 1440x480@60Hz 4:3 */
        { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1472,
                   1596, 1716, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 15 - 1440x480@60Hz */
+       /* 15 - 1440x480@60Hz 16:9 */
        { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1472,
                   1596, 1716, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 16 - 1920x1080@60Hz */
+       /* 16 - 1920x1080@60Hz 16:9 */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 17 - 720x576@50Hz */
+       /* 17 - 720x576@50Hz 4:3 */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 18 - 720x576@50Hz */
+       /* 18 - 720x576@50Hz 16:9 */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 19 - 1280x720@50Hz */
+       /* 19 - 1280x720@50Hz 16:9 */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720,
                   1760, 1980, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 20 - 1920x1080i@50Hz */
+       /* 20 - 1920x1080i@50Hz 16:9 */
        { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
-                       DRM_MODE_FLAG_INTERLACE),
+                  DRM_MODE_FLAG_INTERLACE),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 21 - 720(1440)x576i@50Hz */
+       /* 21 - 720(1440)x576i@50Hz 4:3 */
        { DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500, 720, 732,
                   795, 864, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
+                  DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 22 - 720(1440)x576i@50Hz */
+       /* 22 - 720(1440)x576i@50Hz 16:9 */
        { DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500, 720, 732,
                   795, 864, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
+                  DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 23 - 720(1440)x288@50Hz */
+       /* 23 - 720(1440)x288@50Hz 4:3 */
        { DRM_MODE("720x288", DRM_MODE_TYPE_DRIVER, 13500, 720, 732,
                   795, 864, 0, 288, 290, 293, 312, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_DBLCLK),
+                  DRM_MODE_FLAG_DBLCLK),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 24 - 720(1440)x288@50Hz */
+       /* 24 - 720(1440)x288@50Hz 16:9 */
        { DRM_MODE("720x288", DRM_MODE_TYPE_DRIVER, 13500, 720, 732,
                   795, 864, 0, 288, 290, 293, 312, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_DBLCLK),
+                  DRM_MODE_FLAG_DBLCLK),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 25 - 2880x576i@50Hz */
+       /* 25 - 2880x576i@50Hz 4:3 */
        { DRM_MODE("2880x576i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
                   3180, 3456, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_INTERLACE),
+                  DRM_MODE_FLAG_INTERLACE),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 26 - 2880x576i@50Hz */
+       /* 26 - 2880x576i@50Hz 16:9 */
        { DRM_MODE("2880x576i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
                   3180, 3456, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_INTERLACE),
+                  DRM_MODE_FLAG_INTERLACE),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 27 - 2880x288@50Hz */
+       /* 27 - 2880x288@50Hz 4:3 */
        { DRM_MODE("2880x288", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
                   3180, 3456, 0, 288, 290, 293, 312, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 28 - 2880x288@50Hz */
+       /* 28 - 2880x288@50Hz 16:9 */
        { DRM_MODE("2880x288", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
                   3180, 3456, 0, 288, 290, 293, 312, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 29 - 1440x576@50Hz */
+       /* 29 - 1440x576@50Hz 4:3 */
        { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464,
                   1592, 1728, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 30 - 1440x576@50Hz */
+       /* 30 - 1440x576@50Hz 16:9 */
        { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464,
                   1592, 1728, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 31 - 1920x1080@50Hz */
+       /* 31 - 1920x1080@50Hz 16:9 */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 32 - 1920x1080@24Hz */
+       /* 32 - 1920x1080@24Hz 16:9 */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2558,
                   2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 33 - 1920x1080@25Hz */
+       /* 33 - 1920x1080@25Hz 16:9 */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 34 - 1920x1080@30Hz */
+       /* 34 - 1920x1080@30Hz 16:9 */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 35 - 2880x480@60Hz */
+       /* 35 - 2880x480@60Hz 4:3 */
        { DRM_MODE("2880x480", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2944,
                   3192, 3432, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 36 - 2880x480@60Hz */
+       /* 36 - 2880x480@60Hz 16:9 */
        { DRM_MODE("2880x480", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2944,
                   3192, 3432, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 37 - 2880x576@50Hz */
+       /* 37 - 2880x576@50Hz 4:3 */
        { DRM_MODE("2880x576", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2928,
                   3184, 3456, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 38 - 2880x576@50Hz */
+       /* 38 - 2880x576@50Hz 16:9 */
        { DRM_MODE("2880x576", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2928,
                   3184, 3456, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 39 - 1920x1080i@50Hz */
+       /* 39 - 1920x1080i@50Hz 16:9 */
        { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 72000, 1920, 1952,
                   2120, 2304, 0, 1080, 1126, 1136, 1250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_INTERLACE),
+                  DRM_MODE_FLAG_INTERLACE),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 40 - 1920x1080i@100Hz */
+       /* 40 - 1920x1080i@100Hz 16:9 */
        { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
-                       DRM_MODE_FLAG_INTERLACE),
+                  DRM_MODE_FLAG_INTERLACE),
          .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 41 - 1280x720@100Hz */
+       /* 41 - 1280x720@100Hz 16:9 */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1720,
                   1760, 1980, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 42 - 720x576@100Hz */
+       /* 42 - 720x576@100Hz 4:3 */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 54000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 43 - 720x576@100Hz */
+       /* 43 - 720x576@100Hz 16:9 */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 54000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 44 - 720(1440)x576i@100Hz */
+       /* 44 - 720(1440)x576i@100Hz 4:3 */
        { DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 27000, 720, 732,
                   795, 864, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
+                  DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
          .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 45 - 720(1440)x576i@100Hz */
+       /* 45 - 720(1440)x576i@100Hz 16:9 */
        { DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 27000, 720, 732,
                   795, 864, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
+                  DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
          .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 46 - 1920x1080i@120Hz */
+       /* 46 - 1920x1080i@120Hz 16:9 */
        { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
-                       DRM_MODE_FLAG_INTERLACE),
+                  DRM_MODE_FLAG_INTERLACE),
          .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 47 - 1280x720@120Hz */
+       /* 47 - 1280x720@120Hz 16:9 */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1390,
                   1430, 1650, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 48 - 720x480@120Hz */
+       /* 48 - 720x480@120Hz 4:3 */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 54000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 49 - 720x480@120Hz */
+       /* 49 - 720x480@120Hz 16:9 */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 54000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 50 - 720(1440)x480i@120Hz */
+       /* 50 - 720(1440)x480i@120Hz 4:3 */
        { DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 27000, 720, 739,
                   801, 858, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
+                  DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
          .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 51 - 720(1440)x480i@120Hz */
+       /* 51 - 720(1440)x480i@120Hz 16:9 */
        { DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 27000, 720, 739,
                   801, 858, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
+                  DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
          .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 52 - 720x576@200Hz */
+       /* 52 - 720x576@200Hz 4:3 */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 108000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 200, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 53 - 720x576@200Hz */
+       /* 53 - 720x576@200Hz 16:9 */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 108000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 200, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 54 - 720(1440)x576i@200Hz */
+       /* 54 - 720(1440)x576i@200Hz 4:3 */
        { DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 54000, 720, 732,
                   795, 864, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
+                  DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
          .vrefresh = 200, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 55 - 720(1440)x576i@200Hz */
+       /* 55 - 720(1440)x576i@200Hz 16:9 */
        { DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 54000, 720, 732,
                   795, 864, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
+                  DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
          .vrefresh = 200, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 56 - 720x480@240Hz */
+       /* 56 - 720x480@240Hz 4:3 */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 108000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 240, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 57 - 720x480@240Hz */
+       /* 57 - 720x480@240Hz 16:9 */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 108000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
          .vrefresh = 240, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 58 - 720(1440)x480i@240Hz */
+       /* 58 - 720(1440)x480i@240Hz 4:3 */
        { DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 54000, 720, 739,
                   801, 858, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
+                  DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
          .vrefresh = 240, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-       /* 59 - 720(1440)x480i@240Hz */
+       /* 59 - 720(1440)x480i@240Hz 16:9 */
        { DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 54000, 720, 739,
                   801, 858, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
-                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
+                  DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
          .vrefresh = 240, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 60 - 1280x720@24Hz */
+       /* 60 - 1280x720@24Hz 16:9 */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 59400, 1280, 3040,
                   3080, 3300, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 61 - 1280x720@25Hz */
+       /* 61 - 1280x720@25Hz 16:9 */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3700,
                   3740, 3960, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 62 - 1280x720@30Hz */
+       /* 62 - 1280x720@30Hz 16:9 */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3040,
                   3080, 3300, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 63 - 1920x1080@120Hz */
+       /* 63 - 1920x1080@120Hz 16:9 */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-        .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 64 - 1920x1080@100Hz */
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
+       /* 64 - 1920x1080@100Hz 16:9 */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-        .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 65 - 1280x720@24Hz */
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
+       /* 65 - 1280x720@24Hz 64:27 */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 59400, 1280, 3040,
                   3080, 3300, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 66 - 1280x720@25Hz */
+       /* 66 - 1280x720@25Hz 64:27 */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3700,
                   3740, 3960, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 67 - 1280x720@30Hz */
+       /* 67 - 1280x720@30Hz 64:27 */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3040,
                   3080, 3300, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 68 - 1280x720@50Hz */
+       /* 68 - 1280x720@50Hz 64:27 */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720,
                   1760, 1980, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 69 - 1280x720@60Hz */
+       /* 69 - 1280x720@60Hz 64:27 */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390,
                   1430, 1650, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 70 - 1280x720@100Hz */
+       /* 70 - 1280x720@100Hz 64:27 */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1720,
                   1760, 1980, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 71 - 1280x720@120Hz */
+       /* 71 - 1280x720@120Hz 64:27 */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1390,
                   1430, 1650, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 72 - 1920x1080@24Hz */
+       /* 72 - 1920x1080@24Hz 64:27 */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2558,
                   2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 73 - 1920x1080@25Hz */
+       /* 73 - 1920x1080@25Hz 64:27 */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 74 - 1920x1080@30Hz */
+       /* 74 - 1920x1080@30Hz 64:27 */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 75 - 1920x1080@50Hz */
+       /* 75 - 1920x1080@50Hz 64:27 */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 76 - 1920x1080@60Hz */
+       /* 76 - 1920x1080@60Hz 64:27 */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 77 - 1920x1080@100Hz */
+       /* 77 - 1920x1080@100Hz 64:27 */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 78 - 1920x1080@120Hz */
+       /* 78 - 1920x1080@120Hz 64:27 */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 79 - 1680x720@24Hz */
+       /* 79 - 1680x720@24Hz 64:27 */
        { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 59400, 1680, 3040,
                   3080, 3300, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 80 - 1680x720@25Hz */
+       /* 80 - 1680x720@25Hz 64:27 */
        { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 59400, 1680, 2908,
                   2948, 3168, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 81 - 1680x720@30Hz */
+       /* 81 - 1680x720@30Hz 64:27 */
        { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 59400, 1680, 2380,
                   2420, 2640, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 82 - 1680x720@50Hz */
+       /* 82 - 1680x720@50Hz 64:27 */
        { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 82500, 1680, 1940,
                   1980, 2200, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 83 - 1680x720@60Hz */
+       /* 83 - 1680x720@60Hz 64:27 */
        { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 99000, 1680, 1940,
                   1980, 2200, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 84 - 1680x720@100Hz */
+       /* 84 - 1680x720@100Hz 64:27 */
        { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 165000, 1680, 1740,
                   1780, 2000, 0, 720, 725, 730, 825, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 85 - 1680x720@120Hz */
+       /* 85 - 1680x720@120Hz 64:27 */
        { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 198000, 1680, 1740,
                   1780, 2000, 0, 720, 725, 730, 825, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 86 - 2560x1080@24Hz */
+       /* 86 - 2560x1080@24Hz 64:27 */
        { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 99000, 2560, 3558,
                   3602, 3750, 0, 1080, 1084, 1089, 1100, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 87 - 2560x1080@25Hz */
+       /* 87 - 2560x1080@25Hz 64:27 */
        { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 90000, 2560, 3008,
                   3052, 3200, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 88 - 2560x1080@30Hz */
+       /* 88 - 2560x1080@30Hz 64:27 */
        { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 118800, 2560, 3328,
                   3372, 3520, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 89 - 2560x1080@50Hz */
+       /* 89 - 2560x1080@50Hz 64:27 */
        { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 185625, 2560, 3108,
                   3152, 3300, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 90 - 2560x1080@60Hz */
+       /* 90 - 2560x1080@60Hz 64:27 */
        { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 198000, 2560, 2808,
                   2852, 3000, 0, 1080, 1084, 1089, 1100, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 91 - 2560x1080@100Hz */
+       /* 91 - 2560x1080@100Hz 64:27 */
        { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 371250, 2560, 2778,
                   2822, 2970, 0, 1080, 1084, 1089, 1250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 92 - 2560x1080@120Hz */
+       /* 92 - 2560x1080@120Hz 64:27 */
        { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 495000, 2560, 3108,
                   3152, 3300, 0, 1080, 1084, 1089, 1250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 93 - 3840x2160p@24Hz 16:9 */
+       /* 93 - 3840x2160@24Hz 16:9 */
        { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 5116,
                   5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 94 - 3840x2160p@25Hz 16:9 */
+       /* 94 - 3840x2160@25Hz 16:9 */
        { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4896,
                   4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 95 - 3840x2160p@30Hz 16:9 */
+       /* 95 - 3840x2160@30Hz 16:9 */
        { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
                   4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 96 - 3840x2160p@50Hz 16:9 */
+       /* 96 - 3840x2160@50Hz 16:9 */
        { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4896,
                   4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 97 - 3840x2160p@60Hz 16:9 */
+       /* 97 - 3840x2160@60Hz 16:9 */
        { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016,
                   4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-       /* 98 - 4096x2160p@24Hz 256:135 */
+       /* 98 - 4096x2160@24Hz 256:135 */
        { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 5116,
                   5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
-       /* 99 - 4096x2160p@25Hz 256:135 */
+       /* 99 - 4096x2160@25Hz 256:135 */
        { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 5064,
                   5152, 5280, 0, 2160, 2168, 2178, 2250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
-       /* 100 - 4096x2160p@30Hz 256:135 */
+       /* 100 - 4096x2160@30Hz 256:135 */
        { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 4184,
                   4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
-       /* 101 - 4096x2160p@50Hz 256:135 */
+       /* 101 - 4096x2160@50Hz 256:135 */
        { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 5064,
                   5152, 5280, 0, 2160, 2168, 2178, 2250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
-       /* 102 - 4096x2160p@60Hz 256:135 */
+       /* 102 - 4096x2160@60Hz 256:135 */
        { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 4184,
                   4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
-       /* 103 - 3840x2160p@24Hz 64:27 */
+       /* 103 - 3840x2160@24Hz 64:27 */
        { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 5116,
                   5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 104 - 3840x2160p@25Hz 64:27 */
+       /* 104 - 3840x2160@25Hz 64:27 */
        { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4896,
                   4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 105 - 3840x2160p@30Hz 64:27 */
+       /* 105 - 3840x2160@30Hz 64:27 */
        { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
                   4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 106 - 3840x2160p@50Hz 64:27 */
+       /* 106 - 3840x2160@50Hz 64:27 */
        { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4896,
                   4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
          .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
-       /* 107 - 3840x2160p@60Hz 64:27 */
+       /* 107 - 3840x2160@60Hz 64:27 */
        { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016,
                   4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
@@ -4873,6 +4874,14 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
 
        frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
 
+       /*
+        * As some drivers don't support atomic, we can't use connector state.
+        * So just initialize the frame with default values, just the same way
+        * as it's done with other properties here.
+        */
+       frame->content_type = HDMI_CONTENT_TYPE_GRAPHICS;
+       frame->itc = 0;
+
        /*
         * Populate picture aspect ratio from either
         * user input (if specified) or from the CEA mode list.
index 2ee1eaa6618805308846e6a4629a2cb2b8804f76..cab14f2533840e071bf3b5f8f32556511a565b76 100644 (file)
@@ -368,7 +368,6 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ
        struct drm_plane *plane;
        struct drm_atomic_state *state;
        int i, ret;
-       unsigned int plane_mask;
        struct drm_modeset_acquire_ctx ctx;
 
        drm_modeset_acquire_init(&ctx, 0);
@@ -381,7 +380,6 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ
 
        state->acquire_ctx = &ctx;
 retry:
-       plane_mask = 0;
        drm_for_each_plane(plane, dev) {
                plane_state = drm_atomic_get_plane_state(state, plane);
                if (IS_ERR(plane_state)) {
@@ -391,9 +389,6 @@ retry:
 
                plane_state->rotation = DRM_MODE_ROTATE_0;
 
-               plane->old_fb = plane->fb;
-               plane_mask |= 1 << drm_plane_index(plane);
-
                /* disable non-primary: */
                if (plane->type == DRM_PLANE_TYPE_PRIMARY)
                        continue;
@@ -430,8 +425,6 @@ retry:
        ret = drm_atomic_commit(state);
 
 out_state:
-       drm_atomic_clean_old_fb(dev, plane_mask, ret);
-
        if (ret == -EDEADLK)
                goto backoff;
 
@@ -1164,7 +1157,7 @@ EXPORT_SYMBOL(drm_fb_helper_sys_imageblit);
  * @info: fbdev registered by the helper
  * @rect: info about rectangle to fill
  *
- * A wrapper around cfb_imageblit implemented by fbdev core
+ * A wrapper around cfb_fillrect implemented by fbdev core
  */
 void drm_fb_helper_cfb_fillrect(struct fb_info *info,
                                const struct fb_fillrect *rect)
index bfedceff87bba8101ff51d18e68e4e0c9d107182..46b11e46edbd61ef534cede0e9616eea3f1dffb0 100644 (file)
@@ -836,8 +836,6 @@ retry:
                        goto unlock;
 
                plane_mask |= BIT(drm_plane_index(plane));
-
-               plane->old_fb = plane->fb;
        }
 
        /* This list is only filled when disable_crtcs is set. */
@@ -852,9 +850,6 @@ retry:
                ret = drm_atomic_commit(state);
 
 unlock:
-       if (plane_mask)
-               drm_atomic_clean_old_fb(dev, plane_mask, ret);
-
        if (ret == -EDEADLK) {
                drm_atomic_state_clear(state);
                drm_modeset_backoff(&ctx);
index acfbc0641a06a1bd2f1a63f53ce01d0e2ea2da03..2810d413141182e4b6298524612670aa34a54757 100644 (file)
@@ -253,7 +253,7 @@ int drm_gem_fb_prepare_fb(struct drm_plane *plane,
        struct dma_buf *dma_buf;
        struct dma_fence *fence;
 
-       if (plane->state->fb == state->fb || !state->fb)
+       if (!state->fb)
                return 0;
 
        dma_buf = drm_gem_fb_get_obj(state->fb, 0)->dma_buf;
index 0d4cfb232576fc1b2d325cfa185a1477070e30c8..fe49fb0356b5abba563dc30e8409701ecb7a8170 100644 (file)
@@ -334,6 +334,13 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
                        return -EINVAL;
                file_priv->aspect_ratio_allowed = req->value;
                break;
+       case DRM_CLIENT_CAP_WRITEBACK_CONNECTORS:
+               if (!file_priv->atomic)
+                       return -EINVAL;
+               if (req->value > 1)
+                       return -EINVAL;
+               file_priv->writeback_connectors = req->value;
+               break;
        default:
                return -EINVAL;
        }
index 3166026a1874d7a9ffba190273dd1ab270fb83db..3cc5fbd78ee20b44eb2b722e96a158ac518c2e00 100644 (file)
@@ -239,6 +239,32 @@ static void drm_mm_interval_tree_add_node(struct drm_mm_node *hole_node,
 #define HOLE_SIZE(NODE) ((NODE)->hole_size)
 #define HOLE_ADDR(NODE) (__drm_mm_hole_node_start(NODE))
 
+static u64 rb_to_hole_size(struct rb_node *rb)
+{
+       return rb_entry(rb, struct drm_mm_node, rb_hole_size)->hole_size;
+}
+
+static void insert_hole_size(struct rb_root_cached *root,
+                            struct drm_mm_node *node)
+{
+       struct rb_node **link = &root->rb_root.rb_node, *rb = NULL;
+       u64 x = node->hole_size;
+       bool first = true;
+
+       while (*link) {
+               rb = *link;
+               if (x > rb_to_hole_size(rb)) {
+                       link = &rb->rb_left;
+               } else {
+                       link = &rb->rb_right;
+                       first = false;
+               }
+       }
+
+       rb_link_node(&node->rb_hole_size, rb, link);
+       rb_insert_color_cached(&node->rb_hole_size, root, first);
+}
+
 static void add_hole(struct drm_mm_node *node)
 {
        struct drm_mm *mm = node->mm;
@@ -247,7 +273,7 @@ static void add_hole(struct drm_mm_node *node)
                __drm_mm_hole_node_end(node) - __drm_mm_hole_node_start(node);
        DRM_MM_BUG_ON(!drm_mm_hole_follows(node));
 
-       RB_INSERT(mm->holes_size, rb_hole_size, HOLE_SIZE);
+       insert_hole_size(&mm->holes_size, node);
        RB_INSERT(mm->holes_addr, rb_hole_addr, HOLE_ADDR);
 
        list_add(&node->hole_stack, &mm->hole_stack);
@@ -258,7 +284,7 @@ static void rm_hole(struct drm_mm_node *node)
        DRM_MM_BUG_ON(!drm_mm_hole_follows(node));
 
        list_del(&node->hole_stack);
-       rb_erase(&node->rb_hole_size, &node->mm->holes_size);
+       rb_erase_cached(&node->rb_hole_size, &node->mm->holes_size);
        rb_erase(&node->rb_hole_addr, &node->mm->holes_addr);
        node->hole_size = 0;
 
@@ -282,38 +308,39 @@ static inline u64 rb_hole_size(struct rb_node *rb)
 
 static struct drm_mm_node *best_hole(struct drm_mm *mm, u64 size)
 {
-       struct rb_node *best = NULL;
-       struct rb_node **link = &mm->holes_size.rb_node;
+       struct rb_node *rb = mm->holes_size.rb_root.rb_node;
+       struct drm_mm_node *best = NULL;
 
-       while (*link) {
-               struct rb_node *rb = *link;
+       do {
+               struct drm_mm_node *node =
+                       rb_entry(rb, struct drm_mm_node, rb_hole_size);
 
-               if (size <= rb_hole_size(rb)) {
-                       link = &rb->rb_left;
-                       best = rb;
+               if (size <= node->hole_size) {
+                       best = node;
+                       rb = rb->rb_right;
                } else {
-                       link = &rb->rb_right;
+                       rb = rb->rb_left;
                }
-       }
+       } while (rb);
 
-       return rb_hole_size_to_node(best);
+       return best;
 }
 
 static struct drm_mm_node *find_hole(struct drm_mm *mm, u64 addr)
 {
+       struct rb_node *rb = mm->holes_addr.rb_node;
        struct drm_mm_node *node = NULL;
-       struct rb_node **link = &mm->holes_addr.rb_node;
 
-       while (*link) {
+       while (rb) {
                u64 hole_start;
 
-               node = rb_hole_addr_to_node(*link);
+               node = rb_hole_addr_to_node(rb);
                hole_start = __drm_mm_hole_node_start(node);
 
                if (addr < hole_start)
-                       link = &node->rb_hole_addr.rb_left;
+                       rb = node->rb_hole_addr.rb_left;
                else if (addr > hole_start + node->hole_size)
-                       link = &node->rb_hole_addr.rb_right;
+                       rb = node->rb_hole_addr.rb_right;
                else
                        break;
        }
@@ -326,9 +353,6 @@ first_hole(struct drm_mm *mm,
           u64 start, u64 end, u64 size,
           enum drm_mm_insert_mode mode)
 {
-       if (RB_EMPTY_ROOT(&mm->holes_size))
-               return NULL;
-
        switch (mode) {
        default:
        case DRM_MM_INSERT_BEST:
@@ -355,7 +379,7 @@ next_hole(struct drm_mm *mm,
        switch (mode) {
        default:
        case DRM_MM_INSERT_BEST:
-               return rb_hole_size_to_node(rb_next(&node->rb_hole_size));
+               return rb_hole_size_to_node(rb_prev(&node->rb_hole_size));
 
        case DRM_MM_INSERT_LOW:
                return rb_hole_addr_to_node(rb_next(&node->rb_hole_addr));
@@ -426,6 +450,11 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
 }
 EXPORT_SYMBOL(drm_mm_reserve_node);
 
+static u64 rb_to_hole_size_or_zero(struct rb_node *rb)
+{
+       return rb ? rb_to_hole_size(rb) : 0;
+}
+
 /**
  * drm_mm_insert_node_in_range - ranged search for space and insert @node
  * @mm: drm_mm to allocate from
@@ -451,18 +480,26 @@ int drm_mm_insert_node_in_range(struct drm_mm * const mm,
 {
        struct drm_mm_node *hole;
        u64 remainder_mask;
+       bool once;
 
        DRM_MM_BUG_ON(range_start >= range_end);
 
        if (unlikely(size == 0 || range_end - range_start < size))
                return -ENOSPC;
 
+       if (rb_to_hole_size_or_zero(rb_first_cached(&mm->holes_size)) < size)
+               return -ENOSPC;
+
        if (alignment <= 1)
                alignment = 0;
 
+       once = mode & DRM_MM_INSERT_ONCE;
+       mode &= ~DRM_MM_INSERT_ONCE;
+
        remainder_mask = is_power_of_2(alignment) ? alignment - 1 : 0;
-       for (hole = first_hole(mm, range_start, range_end, size, mode); hole;
-            hole = next_hole(mm, hole, mode)) {
+       for (hole = first_hole(mm, range_start, range_end, size, mode);
+            hole;
+            hole = once ? NULL : next_hole(mm, hole, mode)) {
                u64 hole_start = __drm_mm_hole_node_start(hole);
                u64 hole_end = hole_start + hole->hole_size;
                u64 adj_start, adj_end;
@@ -587,9 +624,9 @@ void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new)
 
        if (drm_mm_hole_follows(old)) {
                list_replace(&old->hole_stack, &new->hole_stack);
-               rb_replace_node(&old->rb_hole_size,
-                               &new->rb_hole_size,
-                               &mm->holes_size);
+               rb_replace_node_cached(&old->rb_hole_size,
+                                      &new->rb_hole_size,
+                                      &mm->holes_size);
                rb_replace_node(&old->rb_hole_addr,
                                &new->rb_hole_addr,
                                &mm->holes_addr);
@@ -885,7 +922,7 @@ void drm_mm_init(struct drm_mm *mm, u64 start, u64 size)
 
        INIT_LIST_HEAD(&mm->hole_stack);
        mm->interval_tree = RB_ROOT_CACHED;
-       mm->holes_size = RB_ROOT;
+       mm->holes_size = RB_ROOT_CACHED;
        mm->holes_addr = RB_ROOT;
 
        /* Clever trick to avoid a special case in the free hole tracking. */
index e5c653357024dc5ea522706df1a03be1f12d094d..21e353bd3948ece25235c844da7fd4e3689abe35 100644 (file)
@@ -145,6 +145,11 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
        count = 0;
        connector_id = u64_to_user_ptr(card_res->connector_id_ptr);
        drm_for_each_connector_iter(connector, &conn_iter) {
+               /* only expose writeback connectors if userspace understands them */
+               if (!file_priv->writeback_connectors &&
+                   (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK))
+                       continue;
+
                if (drm_lease_held(file_priv, connector->base.id)) {
                        if (count < card_res->count_connectors &&
                            put_user(connector->base.id, connector_id + count)) {
index c78ca0e84ffdc312860dc49805cc3b8e95bacce7..7f552d5fa88ee55b23cacfc8c8610da9a44c22f3 100644 (file)
@@ -1257,7 +1257,7 @@ static const char * const drm_mode_status_names[] = {
 
 #undef MODE_STATUS
 
-static const char *drm_get_mode_status_name(enum drm_mode_status status)
+const char *drm_get_mode_status_name(enum drm_mode_status status)
 {
        int index = status + 3;
 
index 308d442a531b2dda2145dd296ee309ccda88e214..965530a6f4cd355cc82386a258b46f2363b63430 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/err.h>
 #include <linux/module.h>
 
+#include <drm/drm_device.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_panel.h>
 
@@ -94,6 +95,9 @@ EXPORT_SYMBOL(drm_panel_remove);
  *
  * An error is returned if the panel is already attached to another connector.
  *
+ * When unloading, the driver should detach from the panel by calling
+ * drm_panel_detach().
+ *
  * Return: 0 on success or a negative error code on failure.
  */
 int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector)
@@ -101,6 +105,13 @@ int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector)
        if (panel->connector)
                return -EBUSY;
 
+       panel->link = device_link_add(connector->dev->dev, panel->dev, 0);
+       if (!panel->link) {
+               dev_err(panel->dev, "failed to link panel to %s\n",
+                       dev_name(connector->dev->dev));
+               return -EINVAL;
+       }
+
        panel->connector = connector;
        panel->drm = connector->dev;
 
@@ -115,10 +126,15 @@ EXPORT_SYMBOL(drm_panel_attach);
  * Detaches a panel from the connector it is attached to. If a panel is not
  * attached to any connector this is effectively a no-op.
  *
+ * This function should not be called by the panel device itself. It
+ * is only for the drm device that called drm_panel_attach().
+ *
  * Return: 0 on success or a negative error code on failure.
  */
 int drm_panel_detach(struct drm_panel *panel)
 {
+       device_link_del(panel->link);
+
        panel->connector = NULL;
        panel->drm = NULL;
 
index 0350544553010c374c122af5093d7d93aac95e4e..df0b4ebbedbf4e8b803bfbdc5eb791dbad4bc8b7 100644 (file)
@@ -177,6 +177,10 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
        if (WARN_ON(config->num_total_plane >= 32))
                return -EINVAL;
 
+       WARN_ON(drm_drv_uses_atomic_modeset(dev) &&
+               (!funcs->atomic_destroy_state ||
+                !funcs->atomic_duplicate_state));
+
        ret = drm_mode_object_add(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
        if (ret)
                return ret;
@@ -561,19 +565,20 @@ int drm_plane_check_pixel_format(struct drm_plane *plane,
        if (i == plane->format_count)
                return -EINVAL;
 
-       if (!plane->modifier_count)
-               return 0;
+       if (plane->funcs->format_mod_supported) {
+               if (!plane->funcs->format_mod_supported(plane, format, modifier))
+                       return -EINVAL;
+       } else {
+               if (!plane->modifier_count)
+                       return 0;
 
-       for (i = 0; i < plane->modifier_count; i++) {
-               if (modifier == plane->modifiers[i])
-                       break;
+               for (i = 0; i < plane->modifier_count; i++) {
+                       if (modifier == plane->modifiers[i])
+                               break;
+               }
+               if (i == plane->modifier_count)
+                       return -EINVAL;
        }
-       if (i == plane->modifier_count)
-               return -EINVAL;
-
-       if (plane->funcs->format_mod_supported &&
-           !plane->funcs->format_mod_supported(plane, format, modifier))
-               return -EINVAL;
 
        return 0;
 }
@@ -650,9 +655,11 @@ static int __setplane_internal(struct drm_plane *plane,
                                         crtc_x, crtc_y, crtc_w, crtc_h,
                                         src_x, src_y, src_w, src_h, ctx);
        if (!ret) {
-               plane->crtc = crtc;
-               plane->fb = fb;
-               drm_framebuffer_get(plane->fb);
+               if (!plane->state) {
+                       plane->crtc = crtc;
+                       plane->fb = fb;
+                       drm_framebuffer_get(plane->fb);
+               }
        } else {
                plane->old_fb = NULL;
        }
@@ -1092,8 +1099,10 @@ retry:
                /* Keep the old fb, don't unref it. */
                plane->old_fb = NULL;
        } else {
-               plane->fb = fb;
-               drm_framebuffer_get(fb);
+               if (!plane->state) {
+                       plane->fb = fb;
+                       drm_framebuffer_get(fb);
+               }
        }
 
 out:
index f88f681615193040e5375ecaca9c05c4590267d0..2010794943bcc2bbe80e271f5d32babc28bb29ae 100644 (file)
@@ -502,6 +502,7 @@ EXPORT_SYMBOL(drm_plane_helper_update);
 int drm_plane_helper_disable(struct drm_plane *plane)
 {
        struct drm_plane_state *plane_state;
+       struct drm_framebuffer *old_fb;
 
        /* crtc helpers love to call disable functions for already disabled hw
         * functions. So cope with that. */
@@ -521,8 +522,9 @@ int drm_plane_helper_disable(struct drm_plane *plane)
        plane_state->plane = plane;
 
        plane_state->crtc = NULL;
+       old_fb = plane_state->fb;
        drm_atomic_set_fb_for_plane(plane_state, NULL);
 
-       return drm_plane_helper_commit(plane, plane_state, plane->fb);
+       return drm_plane_helper_commit(plane, plane_state, old_fb);
 }
 EXPORT_SYMBOL(drm_plane_helper_disable);
index 397b46b337399952fb2a143146294cc818deb49d..186db2e4c57a11d60dbb4b3b7912e1de7fc03626 100644 (file)
@@ -186,7 +186,6 @@ static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpri
 /**
  * drm_gem_map_attach - dma_buf attach implementation for GEM
  * @dma_buf: buffer to attach device to
- * @target_dev: not used
  * @attach: buffer attachment data
  *
  * Allocates &drm_prime_attachment and calls &drm_driver.gem_prime_pin for
@@ -195,7 +194,7 @@ static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpri
  *
  * Returns 0 on success, negative error code on failure.
  */
-int drm_gem_map_attach(struct dma_buf *dma_buf, struct device *target_dev,
+int drm_gem_map_attach(struct dma_buf *dma_buf,
                       struct dma_buf_attachment *attach)
 {
        struct drm_prime_attachment *prime_attach;
@@ -434,35 +433,6 @@ void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
 }
 EXPORT_SYMBOL(drm_gem_dmabuf_vunmap);
 
-/**
- * drm_gem_dmabuf_kmap_atomic - map_atomic implementation for GEM
- * @dma_buf: buffer to be mapped
- * @page_num: page number within the buffer
- *
- * Not implemented. This can be used as the &dma_buf_ops.map_atomic callback.
- */
-void *drm_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf,
-                                unsigned long page_num)
-{
-       return NULL;
-}
-EXPORT_SYMBOL(drm_gem_dmabuf_kmap_atomic);
-
-/**
- * drm_gem_dmabuf_kunmap_atomic - unmap_atomic implementation for GEM
- * @dma_buf: buffer to be unmapped
- * @page_num: page number within the buffer
- * @addr: virtual address of the buffer
- *
- * Not implemented. This can be used as the &dma_buf_ops.unmap_atomic callback.
- */
-void drm_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf,
-                                 unsigned long page_num, void *addr)
-{
-
-}
-EXPORT_SYMBOL(drm_gem_dmabuf_kunmap_atomic);
-
 /**
  * drm_gem_dmabuf_kmap - map implementation for GEM
  * @dma_buf: buffer to be mapped
@@ -520,9 +490,7 @@ static const struct dma_buf_ops drm_gem_prime_dmabuf_ops =  {
        .unmap_dma_buf = drm_gem_unmap_dma_buf,
        .release = drm_gem_dmabuf_release,
        .map = drm_gem_dmabuf_kmap,
-       .map_atomic = drm_gem_dmabuf_kmap_atomic,
        .unmap = drm_gem_dmabuf_kunmap,
-       .unmap_atomic = drm_gem_dmabuf_kunmap_atomic,
        .mmap = drm_gem_dmabuf_mmap,
        .vmap = drm_gem_dmabuf_vmap,
        .vunmap = drm_gem_dmabuf_vunmap,
index 2660543ad86a571dab759a45370369d43fbb16c0..c3301046dfaa54d898198056dfb0631a9afb1b86 100644 (file)
@@ -100,7 +100,7 @@ static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma)
  * map, get the page, increment the use count and return it.
  */
 #if IS_ENABLED(CONFIG_AGP)
-static int drm_vm_fault(struct vm_fault *vmf)
+static vm_fault_t drm_vm_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct drm_file *priv = vma->vm_file->private_data;
@@ -173,7 +173,7 @@ vm_fault_error:
        return VM_FAULT_SIGBUS; /* Disallow mremap */
 }
 #else
-static int drm_vm_fault(struct vm_fault *vmf)
+static vm_fault_t drm_vm_fault(struct vm_fault *vmf)
 {
        return VM_FAULT_SIGBUS;
 }
@@ -189,7 +189,7 @@ static int drm_vm_fault(struct vm_fault *vmf)
  * Get the mapping, find the real physical page to map, get the page, and
  * return it.
  */
-static int drm_vm_shm_fault(struct vm_fault *vmf)
+static vm_fault_t drm_vm_shm_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct drm_local_map *map = vma->vm_private_data;
@@ -291,7 +291,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
  *
  * Determine the page number from the page offset and get it from drm_device_dma::pagelist.
  */
-static int drm_vm_dma_fault(struct vm_fault *vmf)
+static vm_fault_t drm_vm_dma_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct drm_file *priv = vma->vm_file->private_data;
@@ -326,7 +326,7 @@ static int drm_vm_dma_fault(struct vm_fault *vmf)
  *
  * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist.
  */
-static int drm_vm_sg_fault(struct vm_fault *vmf)
+static vm_fault_t drm_vm_sg_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct drm_local_map *map = vma->vm_private_data;
diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c
new file mode 100644 (file)
index 0000000..8273950
--- /dev/null
@@ -0,0 +1,350 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
+ * Author: Brian Starkey <brian.starkey@arm.com>
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ */
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_property.h>
+#include <drm/drm_writeback.h>
+#include <drm/drmP.h>
+#include <linux/dma-fence.h>
+
+/**
+ * DOC: overview
+ *
+ * Writeback connectors are used to expose hardware which can write the output
+ * from a CRTC to a memory buffer. They are used and act similarly to other
+ * types of connectors, with some important differences:
+ *  - Writeback connectors don't provide a way to output visually to the user.
+ *  - Writeback connectors should always report as "disconnected" (so that
+ *    clients which don't understand them will ignore them).
+ *  - Writeback connectors don't have EDID.
+ *
+ * A framebuffer may only be attached to a writeback connector when the
+ * connector is attached to a CRTC. The WRITEBACK_FB_ID property which sets the
+ * framebuffer applies only to a single commit (see below). A framebuffer may
+ * not be attached while the CRTC is off.
+ *
+ * Unlike with planes, when a writeback framebuffer is removed by userspace DRM
+ * makes no attempt to remove it from active use by the connector. This is
+ * because no method is provided to abort a writeback operation, and in any
+ * case making a new commit whilst a writeback is ongoing is undefined (see
+ * WRITEBACK_OUT_FENCE_PTR below). As soon as the current writeback is finished,
+ * the framebuffer will automatically no longer be in active use. As it will
+ * also have already been removed from the framebuffer list, there will be no
+ * way for any userspace application to retrieve a reference to it in the
+ * intervening period.
+ *
+ * Writeback connectors have some additional properties, which userspace
+ * can use to query and control them:
+ *
+ *  "WRITEBACK_FB_ID":
+ *     Write-only object property storing a DRM_MODE_OBJECT_FB: it stores the
+ *     framebuffer to be written by the writeback connector. This property is
+ *     similar to the FB_ID property on planes, but will always read as zero
+ *     and is not preserved across commits.
+ *     Userspace must set this property to an output buffer every time it
+ *     wishes the buffer to get filled.
+ *
+ *  "WRITEBACK_PIXEL_FORMATS":
+ *     Immutable blob property to store the supported pixel formats table. The
+ *     data is an array of u32 DRM_FORMAT_* fourcc values.
+ *     Userspace can use this blob to find out what pixel formats are supported
+ *     by the connector's writeback engine.
+ *
+ *  "WRITEBACK_OUT_FENCE_PTR":
+ *     Userspace can use this property to provide a pointer for the kernel to
+ *     fill with a sync_file file descriptor, which will signal once the
+ *     writeback is finished. The value should be the address of a 32-bit
+ *     signed integer, cast to a u64.
+ *     Userspace should wait for this fence to signal before making another
+ *     commit affecting any of the same CRTCs, Planes or Connectors.
+ *     **Failure to do so will result in undefined behaviour.**
+ *     For this reason it is strongly recommended that all userspace
+ *     applications making use of writeback connectors *always* retrieve an
+ *     out-fence for the commit and use it appropriately.
+ *     From userspace, this property will always read as zero.
+ */
+
+#define fence_to_wb_connector(x) container_of(x->lock, \
+                                             struct drm_writeback_connector, \
+                                             fence_lock)
+
+static const char *drm_writeback_fence_get_driver_name(struct dma_fence *fence)
+{
+       struct drm_writeback_connector *wb_connector =
+               fence_to_wb_connector(fence);
+
+       return wb_connector->base.dev->driver->name;
+}
+
+static const char *
+drm_writeback_fence_get_timeline_name(struct dma_fence *fence)
+{
+       struct drm_writeback_connector *wb_connector =
+               fence_to_wb_connector(fence);
+
+       return wb_connector->timeline_name;
+}
+
+static bool drm_writeback_fence_enable_signaling(struct dma_fence *fence)
+{
+       return true;
+}
+
+static const struct dma_fence_ops drm_writeback_fence_ops = {
+       .get_driver_name = drm_writeback_fence_get_driver_name,
+       .get_timeline_name = drm_writeback_fence_get_timeline_name,
+       .enable_signaling = drm_writeback_fence_enable_signaling,
+       .wait = dma_fence_default_wait,
+};
+
+static int create_writeback_properties(struct drm_device *dev)
+{
+       struct drm_property *prop;
+
+       if (!dev->mode_config.writeback_fb_id_property) {
+               prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
+                                                 "WRITEBACK_FB_ID",
+                                                 DRM_MODE_OBJECT_FB);
+               if (!prop)
+                       return -ENOMEM;
+               dev->mode_config.writeback_fb_id_property = prop;
+       }
+
+       if (!dev->mode_config.writeback_pixel_formats_property) {
+               prop = drm_property_create(dev, DRM_MODE_PROP_BLOB |
+                                          DRM_MODE_PROP_ATOMIC |
+                                          DRM_MODE_PROP_IMMUTABLE,
+                                          "WRITEBACK_PIXEL_FORMATS", 0);
+               if (!prop)
+                       return -ENOMEM;
+               dev->mode_config.writeback_pixel_formats_property = prop;
+       }
+
+       if (!dev->mode_config.writeback_out_fence_ptr_property) {
+               prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+                                                "WRITEBACK_OUT_FENCE_PTR", 0,
+                                                U64_MAX);
+               if (!prop)
+                       return -ENOMEM;
+               dev->mode_config.writeback_out_fence_ptr_property = prop;
+       }
+
+       return 0;
+}
+
+static const struct drm_encoder_funcs drm_writeback_encoder_funcs = {
+       .destroy = drm_encoder_cleanup,
+};
+
+/**
+ * drm_writeback_connector_init - Initialize a writeback connector and its properties
+ * @dev: DRM device
+ * @wb_connector: Writeback connector to initialize
+ * @con_funcs: Connector funcs vtable
+ * @enc_helper_funcs: Encoder helper funcs vtable to be used by the internal encoder
+ * @formats: Array of supported pixel formats for the writeback engine
+ * @n_formats: Length of the formats array
+ *
+ * This function creates the writeback-connector-specific properties if they
+ * have not been already created, initializes the connector as
+ * type DRM_MODE_CONNECTOR_WRITEBACK, and correctly initializes the property
+ * values. It will also create an internal encoder associated with the
+ * drm_writeback_connector and set it to use the @enc_helper_funcs vtable for
+ * the encoder helper.
+ *
+ * Drivers should always use this function instead of drm_connector_init() to
+ * set up writeback connectors.
+ *
+ * Returns: 0 on success, or a negative error code
+ */
+int drm_writeback_connector_init(struct drm_device *dev,
+                                struct drm_writeback_connector *wb_connector,
+                                const struct drm_connector_funcs *con_funcs,
+                                const struct drm_encoder_helper_funcs *enc_helper_funcs,
+                                const u32 *formats, int n_formats)
+{
+       struct drm_property_blob *blob;
+       struct drm_connector *connector = &wb_connector->base;
+       struct drm_mode_config *config = &dev->mode_config;
+       int ret = create_writeback_properties(dev);
+
+       if (ret != 0)
+               return ret;
+
+       blob = drm_property_create_blob(dev, n_formats * sizeof(*formats),
+                                       formats);
+       if (IS_ERR(blob))
+               return PTR_ERR(blob);
+
+       drm_encoder_helper_add(&wb_connector->encoder, enc_helper_funcs);
+       ret = drm_encoder_init(dev, &wb_connector->encoder,
+                              &drm_writeback_encoder_funcs,
+                              DRM_MODE_ENCODER_VIRTUAL, NULL);
+       if (ret)
+               goto fail;
+
+       connector->interlace_allowed = 0;
+
+       ret = drm_connector_init(dev, connector, con_funcs,
+                                DRM_MODE_CONNECTOR_WRITEBACK);
+       if (ret)
+               goto connector_fail;
+
+       ret = drm_mode_connector_attach_encoder(connector,
+                                               &wb_connector->encoder);
+       if (ret)
+               goto attach_fail;
+
+       INIT_LIST_HEAD(&wb_connector->job_queue);
+       spin_lock_init(&wb_connector->job_lock);
+
+       wb_connector->fence_context = dma_fence_context_alloc(1);
+       spin_lock_init(&wb_connector->fence_lock);
+       snprintf(wb_connector->timeline_name,
+                sizeof(wb_connector->timeline_name),
+                "CONNECTOR:%d-%s", connector->base.id, connector->name);
+
+       drm_object_attach_property(&connector->base,
+                                  config->writeback_out_fence_ptr_property, 0);
+
+       drm_object_attach_property(&connector->base,
+                                  config->writeback_fb_id_property, 0);
+
+       drm_object_attach_property(&connector->base,
+                                  config->writeback_pixel_formats_property,
+                                  blob->base.id);
+       wb_connector->pixel_formats_blob_ptr = blob;
+
+       return 0;
+
+attach_fail:
+       drm_connector_cleanup(connector);
+connector_fail:
+       drm_encoder_cleanup(&wb_connector->encoder);
+fail:
+       drm_property_blob_put(blob);
+       return ret;
+}
+EXPORT_SYMBOL(drm_writeback_connector_init);
+
+/**
+ * drm_writeback_queue_job - Queue a writeback job for later signalling
+ * @wb_connector: The writeback connector to queue a job on
+ * @job: The job to queue
+ *
+ * This function adds a job to the job_queue for a writeback connector. It
+ * should be considered to take ownership of the writeback job, and so any other
+ * references to the job must be cleared after calling this function.
+ *
+ * Drivers must ensure that for a given writeback connector, jobs are queued in
+ * exactly the same order as they will be completed by the hardware (and
+ * signaled via drm_writeback_signal_completion).
+ *
+ * For every call to drm_writeback_queue_job() there must be exactly one call to
+ * drm_writeback_signal_completion()
+ *
+ * See also: drm_writeback_signal_completion()
+ */
+void drm_writeback_queue_job(struct drm_writeback_connector *wb_connector,
+                            struct drm_writeback_job *job)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&wb_connector->job_lock, flags);
+       list_add_tail(&job->list_entry, &wb_connector->job_queue);
+       spin_unlock_irqrestore(&wb_connector->job_lock, flags);
+}
+EXPORT_SYMBOL(drm_writeback_queue_job);
+
+/*
+ * @cleanup_work: deferred cleanup of a writeback job
+ *
+ * The job cannot be cleaned up directly in drm_writeback_signal_completion,
+ * because it may be called in interrupt context. Dropping the framebuffer
+ * reference can sleep, and so the cleanup is deferred to a workqueue.
+ */
+static void cleanup_work(struct work_struct *work)
+{
+       struct drm_writeback_job *job = container_of(work,
+                                                    struct drm_writeback_job,
+                                                    cleanup_work);
+       drm_framebuffer_put(job->fb);
+       kfree(job);
+}
+
+
+/**
+ * drm_writeback_signal_completion - Signal the completion of a writeback job
+ * @wb_connector: The writeback connector whose job is complete
+ * @status: Status code to set in the writeback out_fence (0 for success)
+ *
+ * Drivers should call this to signal the completion of a previously queued
+ * writeback job. It should be called as soon as possible after the hardware
+ * has finished writing, and may be called from interrupt context.
+ * It is the driver's responsibility to ensure that for a given connector, the
+ * hardware completes writeback jobs in the same order as they are queued.
+ *
+ * Unless the driver is holding its own reference to the framebuffer, it must
+ * not be accessed after calling this function.
+ *
+ * See also: drm_writeback_queue_job()
+ */
+void
+drm_writeback_signal_completion(struct drm_writeback_connector *wb_connector,
+                               int status)
+{
+       unsigned long flags;
+       struct drm_writeback_job *job;
+
+       spin_lock_irqsave(&wb_connector->job_lock, flags);
+       job = list_first_entry_or_null(&wb_connector->job_queue,
+                                      struct drm_writeback_job,
+                                      list_entry);
+       if (job) {
+               list_del(&job->list_entry);
+               if (job->out_fence) {
+                       if (status)
+                               dma_fence_set_error(job->out_fence, status);
+                       dma_fence_signal(job->out_fence);
+                       dma_fence_put(job->out_fence);
+               }
+       }
+       spin_unlock_irqrestore(&wb_connector->job_lock, flags);
+
+       if (WARN_ON(!job))
+               return;
+
+       INIT_WORK(&job->cleanup_work, cleanup_work);
+       queue_work(system_long_wq, &job->cleanup_work);
+}
+EXPORT_SYMBOL(drm_writeback_signal_completion);
+
+struct dma_fence *
+drm_writeback_get_out_fence(struct drm_writeback_connector *wb_connector)
+{
+       struct dma_fence *fence;
+
+       if (WARN_ON(wb_connector->base.connector_type !=
+                   DRM_MODE_CONNECTOR_WRITEBACK))
+               return NULL;
+
+       fence = kzalloc(sizeof(*fence), GFP_KERNEL);
+       if (!fence)
+               return NULL;
+
+       dma_fence_init(fence, &drm_writeback_fence_ops,
+                      &wb_connector->fence_lock, wb_connector->fence_context,
+                      ++wb_connector->fence_seqno);
+
+       return fence;
+}
+EXPORT_SYMBOL(drm_writeback_get_out_fence);
index 38a2a7f1204be7a9ef416556db031cf8eaa07770..eb9915da7decc8a175563ca1b15089d64e929411 100644 (file)
@@ -263,8 +263,6 @@ static void exynos_plane_atomic_update(struct drm_plane *plane,
        if (!state->crtc)
                return;
 
-       plane->crtc = state->crtc;
-
        if (exynos_crtc->ops->update_plane)
                exynos_crtc->ops->update_plane(exynos_crtc, exynos_plane);
 }
index c51d9259c7a7c3f8713fd8ca46710b0c28a89671..204c8e452eb77efd3535fab25d12888837bc3464 100644 (file)
@@ -251,7 +251,7 @@ static void psbfb_copyarea_accel(struct fb_info *info,
        if (!fb)
                return;
 
-       offset = psbfb->gtt->offset;
+       offset = to_gtt_range(fb->obj[0])->offset;
        stride = fb->pitches[0];
 
        switch (fb->format->depth) {
index cb0a2ae916e094b4e1e52d123a320d5212c776aa..8fa4ef192c1eb95c69685af8f51384b4c154040a 100644 (file)
@@ -33,6 +33,7 @@
 #include <drm/drm.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 
 #include "psb_drv.h"
 #include "psb_intel_reg.h"
 #include "framebuffer.h"
 #include "gtt.h"
 
-static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb);
-static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
-                                             struct drm_file *file_priv,
-                                             unsigned int *handle);
-
 static const struct drm_framebuffer_funcs psb_fb_funcs = {
-       .destroy = psb_user_framebuffer_destroy,
-       .create_handle = psb_user_framebuffer_create_handle,
+       .destroy = drm_gem_fb_destroy,
+       .create_handle = drm_gem_fb_create_handle,
 };
 
 #define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
@@ -96,17 +92,18 @@ static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info)
        struct psb_fbdev *fbdev = info->par;
        struct psb_framebuffer *psbfb = &fbdev->pfb;
        struct drm_device *dev = psbfb->base.dev;
+       struct gtt_range *gtt = to_gtt_range(psbfb->base.obj[0]);
 
        /*
         *      We have to poke our nose in here. The core fb code assumes
         *      panning is part of the hardware that can be invoked before
         *      the actual fb is mapped. In our case that isn't quite true.
         */
-       if (psbfb->gtt->npage) {
+       if (gtt->npage) {
                /* GTT roll shifts in 4K pages, we need to shift the right
                   number of pages */
                int pages = info->fix.line_length >> 12;
-               psb_gtt_roll(dev, psbfb->gtt, var->yoffset * pages);
+               psb_gtt_roll(dev, gtt, var->yoffset * pages);
        }
         return 0;
 }
@@ -117,13 +114,14 @@ static int psbfb_vm_fault(struct vm_fault *vmf)
        struct psb_framebuffer *psbfb = vma->vm_private_data;
        struct drm_device *dev = psbfb->base.dev;
        struct drm_psb_private *dev_priv = dev->dev_private;
+       struct gtt_range *gtt = to_gtt_range(psbfb->base.obj[0]);
        int page_num;
        int i;
        unsigned long address;
        int ret;
        unsigned long pfn;
        unsigned long phys_addr = (unsigned long)dev_priv->stolen_base +
-                                 psbfb->gtt->offset;
+                                 gtt->offset;
 
        page_num = vma_pages(vma);
        address = vmf->address - (vmf->pgoff << PAGE_SHIFT);
@@ -246,7 +244,7 @@ static int psb_framebuffer_init(struct drm_device *dev,
                return -EINVAL;
 
        drm_helper_mode_fill_fb_struct(dev, &fb->base, mode_cmd);
-       fb->gtt = gt;
+       fb->base.obj[0] = &gt->gem;
        ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
        if (ret) {
                dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
@@ -518,8 +516,8 @@ static int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
        drm_framebuffer_unregister_private(&psbfb->base);
        drm_framebuffer_cleanup(&psbfb->base);
 
-       if (psbfb->gtt)
-               drm_gem_object_unreference_unlocked(&psbfb->gtt->gem);
+       if (psbfb->base.obj[0])
+               drm_gem_object_unreference_unlocked(psbfb->base.obj[0]);
        return 0;
 }
 
@@ -576,44 +574,6 @@ static void psb_fbdev_fini(struct drm_device *dev)
        dev_priv->fbdev = NULL;
 }
 
-/**
- *     psb_user_framebuffer_create_handle - add hamdle to a framebuffer
- *     @fb: framebuffer
- *     @file_priv: our DRM file
- *     @handle: returned handle
- *
- *     Our framebuffer object is a GTT range which also contains a GEM
- *     object. We need to turn it into a handle for userspace. GEM will do
- *     the work for us
- */
-static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
-                                             struct drm_file *file_priv,
-                                             unsigned int *handle)
-{
-       struct psb_framebuffer *psbfb = to_psb_fb(fb);
-       struct gtt_range *r = psbfb->gtt;
-       return drm_gem_handle_create(file_priv, &r->gem, handle);
-}
-
-/**
- *     psb_user_framebuffer_destroy    -       destruct user created fb
- *     @fb: framebuffer
- *
- *     User framebuffers are backed by GEM objects so all we have to do is
- *     clean up a bit and drop the reference, GEM will handle the fallout
- */
-static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
-{
-       struct psb_framebuffer *psbfb = to_psb_fb(fb);
-       struct gtt_range *r = psbfb->gtt;
-
-       /* Let DRM do its clean up */
-       drm_framebuffer_cleanup(fb);
-       /*  We are no longer using the resource in GEM */
-       drm_gem_object_unreference_unlocked(&r->gem);
-       kfree(fb);
-}
-
 static const struct drm_mode_config_funcs psb_mode_funcs = {
        .fb_create = psb_user_framebuffer_create,
        .output_poll_changed = drm_fb_helper_output_poll_changed,
index 395f20b07aabca38cd617f1e85c3ef2bdc19a898..23dc3c5f8f0de2b0a10fa946fcee0644d1477f17 100644 (file)
@@ -31,7 +31,6 @@ struct psb_framebuffer {
        struct drm_framebuffer base;
        struct address_space *addr_space;
        struct fb_info *fbdev;
-       struct gtt_range *gtt;
 };
 
 struct psb_fbdev {
index f3c48a2be71b87088e81becf739786bd7dc94755..c8f071c47dafa411f87b67747fbf69dcf7a4a6d6 100644 (file)
@@ -60,7 +60,7 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        struct drm_psb_private *dev_priv = dev->dev_private;
        struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
        struct drm_framebuffer *fb = crtc->primary->fb;
-       struct psb_framebuffer *psbfb = to_psb_fb(fb);
+       struct gtt_range *gtt = to_gtt_range(fb->obj[0]);
        int pipe = gma_crtc->pipe;
        const struct psb_offset *map = &dev_priv->regmap[pipe];
        unsigned long start, offset;
@@ -78,10 +78,10 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 
        /* We are displaying this buffer, make sure it is actually loaded
           into the GTT */
-       ret = psb_gtt_pin(psbfb->gtt);
+       ret = psb_gtt_pin(gtt);
        if (ret < 0)
                goto gma_pipe_set_base_exit;
-       start = psbfb->gtt->offset;
+       start = gtt->offset;
        offset = y * fb->pitches[0] + x * fb->format->cpp[0];
 
        REG_WRITE(map->stride, fb->pitches[0]);
@@ -129,7 +129,7 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 gma_pipe_cleaner:
        /* If there was a previous display we can now unpin it */
        if (old_fb)
-               psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
+               psb_gtt_unpin(to_gtt_range(old_fb->obj[0]));
 
 gma_pipe_set_base_exit:
        gma_power_end(dev);
@@ -491,7 +491,7 @@ void gma_crtc_disable(struct drm_crtc *crtc)
        crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
 
        if (crtc->primary->fb) {
-               gt = to_psb_fb(crtc->primary->fb)->gtt;
+               gt = to_gtt_range(crtc->primary->fb->obj[0]);
                psb_gtt_unpin(gt);
        }
 }
index cdbb350c9d5d2b23c3272ac908163e8b6610677d..cb0c3a2a1fd4b6882505c490af2a656953f9cdfe 100644 (file)
@@ -53,6 +53,8 @@ struct gtt_range {
        int roll;                       /* Roll applied to the GTT entries */
 };
 
+#define to_gtt_range(x) container_of(x, struct gtt_range, gem)
+
 extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
                                             const char *name, int backed,
                                             u32 align);
index 5c066448be5b7d6a69ab52259fea38f29e349d35..881d613cc2e5efe00140a7483f5314de3b725f80 100644 (file)
@@ -196,7 +196,7 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        if (!gma_power_begin(dev, true))
                return 0;
 
-       start = psbfb->gtt->offset;
+       start = to_gtt_range(fb->obj[0])->offset;
        offset = y * fb->pitches[0] + x * fb->format->cpp[0];
 
        REG_WRITE(map->stride, fb->pitches[0]);
index 0fff269d3fe68ee3e036cbda37fdfd1e63b2a984..1b7fd6a9d8a518ba5ad635a8524a109d822b1c54 100644 (file)
@@ -600,7 +600,6 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
        struct drm_psb_private *dev_priv = dev->dev_private;
        struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
        struct drm_framebuffer *fb = crtc->primary->fb;
-       struct psb_framebuffer *psbfb = to_psb_fb(fb);
        int pipe = gma_crtc->pipe;
        const struct psb_offset *map = &dev_priv->regmap[pipe];
        unsigned long start, offset;
@@ -617,7 +616,7 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
        if (!gma_power_begin(dev, true))
                return 0;
 
-       start = psbfb->gtt->offset;
+       start = to_gtt_range(fb->obj[0])->offset;
        offset = y * fb->pitches[0] + x * fb->format->cpp[0];
 
        REG_WRITE(map->stride, fb->pitches[0]);
index f2ee6aa10afa1e7e8fc143e582f044c187d663eb..1d40746ab6259d210e5332162667ab5032d13d2a 100644 (file)
@@ -429,13 +429,20 @@ static const char *cmd_status_names[] = {
        "Scaling not supported"
 };
 
+#define MAX_ARG_LEN 32
+
 static bool psb_intel_sdvo_write_cmd(struct psb_intel_sdvo *psb_intel_sdvo, u8 cmd,
                                 const void *args, int args_len)
 {
-       u8 buf[args_len*2 + 2], status;
-       struct i2c_msg msgs[args_len + 3];
+       u8 buf[MAX_ARG_LEN*2 + 2], status;
+       struct i2c_msg msgs[MAX_ARG_LEN + 3];
        int i, ret;
 
+       if (args_len > MAX_ARG_LEN) {
+               DRM_ERROR("Need to increase arg length\n");
+               return false;
+       }
+
        psb_intel_sdvo_debug_write(psb_intel_sdvo, cmd, args, args_len);
 
        for (i = 0; i < args_len; i++) {
index 6ebd8842dbcc8649c887d689becf69e017f5146b..0038c976536ac41d3e0f43f156d81c0fead5e50c 100644 (file)
@@ -589,13 +589,22 @@ out:
        return ret;
 }
 
+#define MAX_WRITE_RANGE_BUF 32
+
 static void
 reg_write_range(struct tda998x_priv *priv, u16 reg, u8 *p, int cnt)
 {
        struct i2c_client *client = priv->hdmi;
-       u8 buf[cnt+1];
+       /* This is the maximum size of the buffer passed in */
+       u8 buf[MAX_WRITE_RANGE_BUF + 1];
        int ret;
 
+       if (cnt > MAX_WRITE_RANGE_BUF) {
+               dev_err(&client->dev, "Fixed write buffer too small (%d)\n",
+                               MAX_WRITE_RANGE_BUF);
+               return;
+       }
+
        buf[0] = REG2ADDR(reg);
        memcpy(&buf[1], p, cnt);
 
@@ -805,7 +814,7 @@ static void
 tda998x_write_if(struct tda998x_priv *priv, u8 bit, u16 addr,
                 union hdmi_infoframe *frame)
 {
-       u8 buf[32];
+       u8 buf[MAX_WRITE_RANGE_BUF];
        ssize_t len;
 
        len = hdmi_infoframe_pack(frame, buf, sizeof(buf));
index 69a7aec49e84e06d70b5800af653d951d522049a..82e2ca17a441eed4c9f562b9d9ee9aa45f2e740a 100644 (file)
@@ -111,15 +111,6 @@ static void i915_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
        i915_gem_object_unpin_map(obj);
 }
 
-static void *i915_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf, unsigned long page_num)
-{
-       return NULL;
-}
-
-static void i915_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf, unsigned long page_num, void *addr)
-{
-
-}
 static void *i915_gem_dmabuf_kmap(struct dma_buf *dma_buf, unsigned long page_num)
 {
        struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
@@ -225,9 +216,7 @@ static const struct dma_buf_ops i915_dmabuf_ops =  {
        .unmap_dma_buf = i915_gem_unmap_dma_buf,
        .release = drm_gem_dmabuf_release,
        .map = i915_gem_dmabuf_kmap,
-       .map_atomic = i915_gem_dmabuf_kmap_atomic,
        .unmap = i915_gem_dmabuf_kunmap,
-       .unmap_atomic = i915_gem_dmabuf_kunmap_atomic,
        .mmap = i915_gem_dmabuf_mmap,
        .vmap = i915_gem_dmabuf_vmap,
        .vunmap = i915_gem_dmabuf_vunmap,
index 2b4a40a32b765ab9b44ec1e06c6a1bb272377bc1..284ae9574f03a60837b1eefdc3090270925c9ffe 100644 (file)
@@ -3945,7 +3945,7 @@ int i915_gem_gtt_insert(struct i915_address_space *vm,
 
        mode = DRM_MM_INSERT_BEST;
        if (flags & PIN_HIGH)
-               mode = DRM_MM_INSERT_HIGH;
+               mode = DRM_MM_INSERT_HIGHEST;
        if (flags & PIN_MAPPABLE)
                mode = DRM_MM_INSERT_LOW;
 
@@ -3965,6 +3965,15 @@ int i915_gem_gtt_insert(struct i915_address_space *vm,
        if (err != -ENOSPC)
                return err;
 
+       if (mode & DRM_MM_INSERT_ONCE) {
+               err = drm_mm_insert_node_in_range(&vm->mm, node,
+                                                 size, alignment, color,
+                                                 start, end,
+                                                 DRM_MM_INSERT_BEST);
+               if (err != -ENOSPC)
+                       return err;
+       }
+
        if (flags & PIN_NOEVICT)
                return -ENOSPC;
 
index 40285d1b91b7fb8968bcfea69b9353ab8b2e782f..61ddb5871d8a52fa6a4aca59f69510b6d063df50 100644 (file)
@@ -124,6 +124,7 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn,
        if (new_conn_state->force_audio != old_conn_state->force_audio ||
            new_conn_state->broadcast_rgb != old_conn_state->broadcast_rgb ||
            new_conn_state->base.picture_aspect_ratio != old_conn_state->base.picture_aspect_ratio ||
+           new_conn_state->base.content_type != old_conn_state->base.content_type ||
            new_conn_state->base.scaling_mode != old_conn_state->base.scaling_mode)
                crtc_state->mode_changed = true;
 
index 6d068786eb41367283494a4ec9213600045442fe..e8bf4cc499e1380b8d09f0ad2dd9fcfb43eb559a 100644 (file)
@@ -120,12 +120,6 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_
                &crtc_state->base.adjusted_mode;
        int ret;
 
-       /*
-        * Both crtc and plane->crtc could be NULL if we're updating a
-        * property while the plane is disabled.  We don't actually have
-        * anything driver-specific we need to test in that case, so
-        * just return success.
-        */
        if (!intel_state->base.crtc && !old_plane_state->base.crtc)
                return 0;
 
@@ -209,12 +203,6 @@ static int intel_plane_atomic_check(struct drm_plane *plane,
        const struct drm_crtc_state *old_crtc_state;
        struct drm_crtc_state *new_crtc_state;
 
-       /*
-        * Both crtc and plane->crtc could be NULL if we're updating a
-        * property while the plane is disabled.  We don't actually have
-        * anything driver-specific we need to test in that case, so
-        * just return success.
-        */
        if (!crtc)
                return 0;
 
index 17c590b42fd76e58208d6aa77ee2ee78e39643b9..2c16c3a3cdea94660f7ef6082da4b573a2dce28c 100644 (file)
@@ -1022,7 +1022,7 @@ bool intel_crtc_active(struct intel_crtc *crtc)
         * We can ditch the adjusted_mode.crtc_clock check as soon
         * as Haswell has gained clock readout/fastboot support.
         *
-        * We can ditch the crtc->primary->fb check as soon as we can
+        * We can ditch the crtc->primary->state->fb check as soon as we can
         * properly reconstruct framebuffers.
         *
         * FIXME: The intel_crtc->active here should be switched to
@@ -2882,9 +2882,8 @@ valid_fb:
        if (i915_gem_object_is_tiled(obj))
                dev_priv->preserve_bios_swizzle = true;
 
-       drm_framebuffer_get(fb);
-       primary->fb = primary->state->fb = fb;
-       primary->crtc = primary->state->crtc = &intel_crtc->base;
+       plane_state->fb = fb;
+       plane_state->crtc = &intel_crtc->base;
 
        intel_set_plane_visible(to_intel_crtc_state(crtc_state),
                                to_intel_plane_state(plane_state),
@@ -13241,8 +13240,17 @@ void intel_plane_destroy(struct drm_plane *plane)
        kfree(to_intel_plane(plane));
 }
 
-static bool i8xx_mod_supported(uint32_t format, uint64_t modifier)
+static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane,
+                                           u32 format, u64 modifier)
 {
+       switch (modifier) {
+       case DRM_FORMAT_MOD_LINEAR:
+       case I915_FORMAT_MOD_X_TILED:
+               break;
+       default:
+               return false;
+       }
+
        switch (format) {
        case DRM_FORMAT_C8:
        case DRM_FORMAT_RGB565:
@@ -13255,8 +13263,17 @@ static bool i8xx_mod_supported(uint32_t format, uint64_t modifier)
        }
 }
 
-static bool i965_mod_supported(uint32_t format, uint64_t modifier)
+static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
+                                           u32 format, u64 modifier)
 {
+       switch (modifier) {
+       case DRM_FORMAT_MOD_LINEAR:
+       case I915_FORMAT_MOD_X_TILED:
+               break;
+       default:
+               return false;
+       }
+
        switch (format) {
        case DRM_FORMAT_C8:
        case DRM_FORMAT_RGB565:
@@ -13271,8 +13288,26 @@ static bool i965_mod_supported(uint32_t format, uint64_t modifier)
        }
 }
 
-static bool skl_mod_supported(uint32_t format, uint64_t modifier)
+static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
+                                          u32 format, u64 modifier)
 {
+       struct intel_plane *plane = to_intel_plane(_plane);
+
+       switch (modifier) {
+       case DRM_FORMAT_MOD_LINEAR:
+       case I915_FORMAT_MOD_X_TILED:
+       case I915_FORMAT_MOD_Y_TILED:
+       case I915_FORMAT_MOD_Yf_TILED:
+               break;
+       case I915_FORMAT_MOD_Y_TILED_CCS:
+       case I915_FORMAT_MOD_Yf_TILED_CCS:
+               if (!plane->has_ccs)
+                       return false;
+               break;
+       default:
+               return false;
+       }
+
        switch (format) {
        case DRM_FORMAT_XRGB8888:
        case DRM_FORMAT_XBGR8888:
@@ -13304,38 +13339,36 @@ static bool skl_mod_supported(uint32_t format, uint64_t modifier)
        }
 }
 
-static bool intel_primary_plane_format_mod_supported(struct drm_plane *plane,
-                                                    uint32_t format,
-                                                    uint64_t modifier)
+static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
+                                             u32 format, u64 modifier)
 {
-       struct drm_i915_private *dev_priv = to_i915(plane->dev);
-
-       if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
-               return false;
-
-       if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_INTEL &&
-           modifier != DRM_FORMAT_MOD_LINEAR)
-               return false;
-
-       if (INTEL_GEN(dev_priv) >= 9)
-               return skl_mod_supported(format, modifier);
-       else if (INTEL_GEN(dev_priv) >= 4)
-               return i965_mod_supported(format, modifier);
-       else
-               return i8xx_mod_supported(format, modifier);
+       return modifier == DRM_FORMAT_MOD_LINEAR &&
+               format == DRM_FORMAT_ARGB8888;
 }
 
-static bool intel_cursor_plane_format_mod_supported(struct drm_plane *plane,
-                                                   uint32_t format,
-                                                   uint64_t modifier)
-{
-       if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
-               return false;
+static struct drm_plane_funcs skl_plane_funcs = {
+       .update_plane = drm_atomic_helper_update_plane,
+       .disable_plane = drm_atomic_helper_disable_plane,
+       .destroy = intel_plane_destroy,
+       .atomic_get_property = intel_plane_atomic_get_property,
+       .atomic_set_property = intel_plane_atomic_set_property,
+       .atomic_duplicate_state = intel_plane_duplicate_state,
+       .atomic_destroy_state = intel_plane_destroy_state,
+       .format_mod_supported = skl_plane_format_mod_supported,
+};
 
-       return modifier == DRM_FORMAT_MOD_LINEAR && format == DRM_FORMAT_ARGB8888;
-}
+static struct drm_plane_funcs i965_plane_funcs = {
+       .update_plane = drm_atomic_helper_update_plane,
+       .disable_plane = drm_atomic_helper_disable_plane,
+       .destroy = intel_plane_destroy,
+       .atomic_get_property = intel_plane_atomic_get_property,
+       .atomic_set_property = intel_plane_atomic_set_property,
+       .atomic_duplicate_state = intel_plane_duplicate_state,
+       .atomic_destroy_state = intel_plane_destroy_state,
+       .format_mod_supported = i965_plane_format_mod_supported,
+};
 
-static struct drm_plane_funcs intel_plane_funcs = {
+static struct drm_plane_funcs i8xx_plane_funcs = {
        .update_plane = drm_atomic_helper_update_plane,
        .disable_plane = drm_atomic_helper_disable_plane,
        .destroy = intel_plane_destroy,
@@ -13343,7 +13376,7 @@ static struct drm_plane_funcs intel_plane_funcs = {
        .atomic_set_property = intel_plane_atomic_set_property,
        .atomic_duplicate_state = intel_plane_duplicate_state,
        .atomic_destroy_state = intel_plane_destroy_state,
-       .format_mod_supported = intel_primary_plane_format_mod_supported,
+       .format_mod_supported = i8xx_plane_format_mod_supported,
 };
 
 static int
@@ -13468,7 +13501,7 @@ static const struct drm_plane_funcs intel_cursor_plane_funcs = {
        .atomic_set_property = intel_plane_atomic_set_property,
        .atomic_duplicate_state = intel_plane_duplicate_state,
        .atomic_destroy_state = intel_plane_destroy_state,
-       .format_mod_supported = intel_cursor_plane_format_mod_supported,
+       .format_mod_supported = intel_cursor_format_mod_supported,
 };
 
 static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
@@ -13526,6 +13559,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
        struct intel_plane *primary = NULL;
        struct intel_plane_state *state = NULL;
+       const struct drm_plane_funcs *plane_funcs;
        const uint32_t *intel_primary_formats;
        unsigned int supported_rotations;
        unsigned int num_formats;
@@ -13581,6 +13615,9 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
        primary->check_plane = intel_check_primary_plane;
 
        if (INTEL_GEN(dev_priv) >= 9) {
+               primary->has_ccs = skl_plane_has_ccs(dev_priv, pipe,
+                                                    PLANE_PRIMARY);
+
                if (skl_plane_has_planar(dev_priv, pipe, PLANE_PRIMARY)) {
                        intel_primary_formats = skl_pri_planar_formats;
                        num_formats = ARRAY_SIZE(skl_pri_planar_formats);
@@ -13589,7 +13626,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
                        num_formats = ARRAY_SIZE(skl_primary_formats);
                }
 
-               if (skl_plane_has_ccs(dev_priv, pipe, PLANE_PRIMARY))
+               if (primary->has_ccs)
                        modifiers = skl_format_modifiers_ccs;
                else
                        modifiers = skl_format_modifiers_noccs;
@@ -13597,6 +13634,8 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
                primary->update_plane = skl_update_plane;
                primary->disable_plane = skl_disable_plane;
                primary->get_hw_state = skl_plane_get_hw_state;
+
+               plane_funcs = &skl_plane_funcs;
        } else if (INTEL_GEN(dev_priv) >= 4) {
                intel_primary_formats = i965_primary_formats;
                num_formats = ARRAY_SIZE(i965_primary_formats);
@@ -13605,6 +13644,8 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
                primary->update_plane = i9xx_update_plane;
                primary->disable_plane = i9xx_disable_plane;
                primary->get_hw_state = i9xx_plane_get_hw_state;
+
+               plane_funcs = &i965_plane_funcs;
        } else {
                intel_primary_formats = i8xx_primary_formats;
                num_formats = ARRAY_SIZE(i8xx_primary_formats);
@@ -13613,25 +13654,27 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
                primary->update_plane = i9xx_update_plane;
                primary->disable_plane = i9xx_disable_plane;
                primary->get_hw_state = i9xx_plane_get_hw_state;
+
+               plane_funcs = &i8xx_plane_funcs;
        }
 
        if (INTEL_GEN(dev_priv) >= 9)
                ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
-                                              0, &intel_plane_funcs,
+                                              0, plane_funcs,
                                               intel_primary_formats, num_formats,
                                               modifiers,
                                               DRM_PLANE_TYPE_PRIMARY,
                                               "plane 1%c", pipe_name(pipe));
        else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
                ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
-                                              0, &intel_plane_funcs,
+                                              0, plane_funcs,
                                               intel_primary_formats, num_formats,
                                               modifiers,
                                               DRM_PLANE_TYPE_PRIMARY,
                                               "primary %c", pipe_name(pipe));
        else
                ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
-                                              0, &intel_plane_funcs,
+                                              0, plane_funcs,
                                               intel_primary_formats, num_formats,
                                               modifiers,
                                               DRM_PLANE_TYPE_PRIMARY,
index 8641583842be60e964faca17fd065c1b34040ed3..8840108749a5dccc5a878f23f443f155e879cece 100644 (file)
@@ -952,6 +952,7 @@ struct intel_plane {
        enum pipe pipe;
        bool can_scale;
        bool has_fbc;
+       bool has_ccs;
        int max_downscale;
        uint32_t frontbuffer_bit;
 
index ba5ea61fb7b96f4a00729a1e86178f6295c306cd..0ca4cc877520d82935567b8a7ff37583ed7e59f7 100644 (file)
@@ -461,7 +461,8 @@ static void intel_write_infoframe(struct drm_encoder *encoder,
 }
 
 static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
-                                        const struct intel_crtc_state *crtc_state)
+                                        const struct intel_crtc_state *crtc_state,
+                                        const struct drm_connector_state *conn_state)
 {
        struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
        const struct drm_display_mode *adjusted_mode =
@@ -491,6 +492,9 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
                                           intel_hdmi->rgb_quant_range_selectable,
                                           is_hdmi2_sink);
 
+       drm_hdmi_avi_infoframe_content_type(&frame.avi,
+                                           conn_state);
+
        /* TODO: handle pixel repetition for YCBCR420 outputs */
        intel_write_infoframe(encoder, crtc_state, &frame);
 }
@@ -586,7 +590,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder,
        I915_WRITE(reg, val);
        POSTING_READ(reg);
 
-       intel_hdmi_set_avi_infoframe(encoder, crtc_state);
+       intel_hdmi_set_avi_infoframe(encoder, crtc_state, conn_state);
        intel_hdmi_set_spd_infoframe(encoder, crtc_state);
        intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
 }
@@ -727,7 +731,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder,
        I915_WRITE(reg, val);
        POSTING_READ(reg);
 
-       intel_hdmi_set_avi_infoframe(encoder, crtc_state);
+       intel_hdmi_set_avi_infoframe(encoder, crtc_state, conn_state);
        intel_hdmi_set_spd_infoframe(encoder, crtc_state);
        intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
 }
@@ -770,7 +774,7 @@ static void cpt_set_infoframes(struct drm_encoder *encoder,
        I915_WRITE(reg, val);
        POSTING_READ(reg);
 
-       intel_hdmi_set_avi_infoframe(encoder, crtc_state);
+       intel_hdmi_set_avi_infoframe(encoder, crtc_state, conn_state);
        intel_hdmi_set_spd_infoframe(encoder, crtc_state);
        intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
 }
@@ -823,7 +827,7 @@ static void vlv_set_infoframes(struct drm_encoder *encoder,
        I915_WRITE(reg, val);
        POSTING_READ(reg);
 
-       intel_hdmi_set_avi_infoframe(encoder, crtc_state);
+       intel_hdmi_set_avi_infoframe(encoder, crtc_state, conn_state);
        intel_hdmi_set_spd_infoframe(encoder, crtc_state);
        intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
 }
@@ -856,7 +860,7 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
        I915_WRITE(reg, val);
        POSTING_READ(reg);
 
-       intel_hdmi_set_avi_infoframe(encoder, crtc_state);
+       intel_hdmi_set_avi_infoframe(encoder, crtc_state, conn_state);
        intel_hdmi_set_spd_infoframe(encoder, crtc_state);
        intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
 }
@@ -2048,6 +2052,7 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c
        intel_attach_force_audio_property(connector);
        intel_attach_broadcast_rgb_property(connector);
        intel_attach_aspect_ratio_property(connector);
+       drm_connector_attach_content_type_property(connector);
        connector->state->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
 }
 
index 6496c1d00dbbac3f96f876d7f531f5188124692c..65811e2fa7da90aaaba15bbb6b0733018d1cb14c 100644 (file)
@@ -1049,6 +1049,8 @@ int intel_ring_pin(struct intel_ring *ring,
                flags |= PIN_OFFSET_BIAS | offset_bias;
        if (vma->obj->stolen)
                flags |= PIN_MAPPABLE;
+       else
+               flags |= PIN_HIGH;
 
        if (!(vma->flags & I915_VMA_GLOBAL_BIND)) {
                if (flags & PIN_MAPPABLE || map == I915_MAP_WC)
index d474065ed2dd364c007d7412e5a1957a0fbaef93..1160bc3a1e8e445909baf89ac3e4d326312cb984 100644 (file)
@@ -1241,8 +1241,17 @@ static const uint64_t skl_plane_format_modifiers_ccs[] = {
        DRM_FORMAT_MOD_INVALID
 };
 
-static bool g4x_mod_supported(uint32_t format, uint64_t modifier)
+static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
+                                           u32 format, u64 modifier)
 {
+       switch (modifier) {
+       case DRM_FORMAT_MOD_LINEAR:
+       case I915_FORMAT_MOD_X_TILED:
+               break;
+       default:
+               return false;
+       }
+
        switch (format) {
        case DRM_FORMAT_XRGB8888:
        case DRM_FORMAT_YUYV:
@@ -1258,8 +1267,17 @@ static bool g4x_mod_supported(uint32_t format, uint64_t modifier)
        }
 }
 
-static bool snb_mod_supported(uint32_t format, uint64_t modifier)
+static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
+                                           u32 format, u64 modifier)
 {
+       switch (modifier) {
+       case DRM_FORMAT_MOD_LINEAR:
+       case I915_FORMAT_MOD_X_TILED:
+               break;
+       default:
+               return false;
+       }
+
        switch (format) {
        case DRM_FORMAT_XRGB8888:
        case DRM_FORMAT_XBGR8888:
@@ -1276,8 +1294,17 @@ static bool snb_mod_supported(uint32_t format, uint64_t modifier)
        }
 }
 
-static bool vlv_mod_supported(uint32_t format, uint64_t modifier)
+static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
+                                           u32 format, u64 modifier)
 {
+       switch (modifier) {
+       case DRM_FORMAT_MOD_LINEAR:
+       case I915_FORMAT_MOD_X_TILED:
+               break;
+       default:
+               return false;
+       }
+
        switch (format) {
        case DRM_FORMAT_RGB565:
        case DRM_FORMAT_ABGR8888:
@@ -1299,8 +1326,26 @@ static bool vlv_mod_supported(uint32_t format, uint64_t modifier)
        }
 }
 
-static bool skl_mod_supported(uint32_t format, uint64_t modifier)
+static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
+                                          u32 format, u64 modifier)
 {
+       struct intel_plane *plane = to_intel_plane(_plane);
+
+       switch (modifier) {
+       case DRM_FORMAT_MOD_LINEAR:
+       case I915_FORMAT_MOD_X_TILED:
+       case I915_FORMAT_MOD_Y_TILED:
+       case I915_FORMAT_MOD_Yf_TILED:
+               break;
+       case I915_FORMAT_MOD_Y_TILED_CCS:
+       case I915_FORMAT_MOD_Yf_TILED_CCS:
+               if (!plane->has_ccs)
+                       return false;
+               break;
+       default:
+               return false;
+       }
+
        switch (format) {
        case DRM_FORMAT_XRGB8888:
        case DRM_FORMAT_XBGR8888:
@@ -1332,30 +1377,40 @@ static bool skl_mod_supported(uint32_t format, uint64_t modifier)
        }
 }
 
-static bool intel_sprite_plane_format_mod_supported(struct drm_plane *plane,
-                                                   uint32_t format,
-                                                   uint64_t modifier)
-{
-       struct drm_i915_private *dev_priv = to_i915(plane->dev);
-
-       if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
-               return false;
+static const struct drm_plane_funcs g4x_sprite_funcs = {
+       .update_plane = drm_atomic_helper_update_plane,
+       .disable_plane = drm_atomic_helper_disable_plane,
+       .destroy = intel_plane_destroy,
+       .atomic_get_property = intel_plane_atomic_get_property,
+       .atomic_set_property = intel_plane_atomic_set_property,
+       .atomic_duplicate_state = intel_plane_duplicate_state,
+       .atomic_destroy_state = intel_plane_destroy_state,
+       .format_mod_supported = g4x_sprite_format_mod_supported,
+};
 
-       if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_INTEL &&
-           modifier != DRM_FORMAT_MOD_LINEAR)
-               return false;
+static const struct drm_plane_funcs snb_sprite_funcs = {
+       .update_plane = drm_atomic_helper_update_plane,
+       .disable_plane = drm_atomic_helper_disable_plane,
+       .destroy = intel_plane_destroy,
+       .atomic_get_property = intel_plane_atomic_get_property,
+       .atomic_set_property = intel_plane_atomic_set_property,
+       .atomic_duplicate_state = intel_plane_duplicate_state,
+       .atomic_destroy_state = intel_plane_destroy_state,
+       .format_mod_supported = snb_sprite_format_mod_supported,
+};
 
-       if (INTEL_GEN(dev_priv) >= 9)
-               return skl_mod_supported(format, modifier);
-       else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-               return vlv_mod_supported(format, modifier);
-       else if (INTEL_GEN(dev_priv) >= 6)
-               return snb_mod_supported(format, modifier);
-       else
-               return g4x_mod_supported(format, modifier);
-}
+static const struct drm_plane_funcs vlv_sprite_funcs = {
+       .update_plane = drm_atomic_helper_update_plane,
+       .disable_plane = drm_atomic_helper_disable_plane,
+       .destroy = intel_plane_destroy,
+       .atomic_get_property = intel_plane_atomic_get_property,
+       .atomic_set_property = intel_plane_atomic_set_property,
+       .atomic_duplicate_state = intel_plane_duplicate_state,
+       .atomic_destroy_state = intel_plane_destroy_state,
+       .format_mod_supported = vlv_sprite_format_mod_supported,
+};
 
-static const struct drm_plane_funcs intel_sprite_plane_funcs = {
+static const struct drm_plane_funcs skl_plane_funcs = {
        .update_plane = drm_atomic_helper_update_plane,
        .disable_plane = drm_atomic_helper_disable_plane,
        .destroy = intel_plane_destroy,
@@ -1363,7 +1418,7 @@ static const struct drm_plane_funcs intel_sprite_plane_funcs = {
        .atomic_set_property = intel_plane_atomic_set_property,
        .atomic_duplicate_state = intel_plane_duplicate_state,
        .atomic_destroy_state = intel_plane_destroy_state,
-       .format_mod_supported = intel_sprite_plane_format_mod_supported,
+       .format_mod_supported = skl_plane_format_mod_supported,
 };
 
 bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
@@ -1389,6 +1444,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 {
        struct intel_plane *intel_plane = NULL;
        struct intel_plane_state *state = NULL;
+       const struct drm_plane_funcs *plane_funcs;
        unsigned long possible_crtcs;
        const uint32_t *plane_formats;
        const uint64_t *modifiers;
@@ -1413,6 +1469,9 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
                intel_plane->can_scale = true;
                state->scaler_id = -1;
 
+               intel_plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe,
+                                                        PLANE_SPRITE0 + plane);
+
                intel_plane->update_plane = skl_update_plane;
                intel_plane->disable_plane = skl_disable_plane;
                intel_plane->get_hw_state = skl_plane_get_hw_state;
@@ -1426,10 +1485,12 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
                        num_plane_formats = ARRAY_SIZE(skl_plane_formats);
                }
 
-               if (skl_plane_has_ccs(dev_priv, pipe, PLANE_SPRITE0 + plane))
+               if (intel_plane->has_ccs)
                        modifiers = skl_plane_format_modifiers_ccs;
                else
                        modifiers = skl_plane_format_modifiers_noccs;
+
+               plane_funcs = &skl_plane_funcs;
        } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
                intel_plane->can_scale = false;
                intel_plane->max_downscale = 1;
@@ -1441,6 +1502,8 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
                plane_formats = vlv_plane_formats;
                num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
                modifiers = i9xx_plane_format_modifiers;
+
+               plane_funcs = &vlv_sprite_funcs;
        } else if (INTEL_GEN(dev_priv) >= 7) {
                if (IS_IVYBRIDGE(dev_priv)) {
                        intel_plane->can_scale = true;
@@ -1457,6 +1520,8 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
                plane_formats = snb_plane_formats;
                num_plane_formats = ARRAY_SIZE(snb_plane_formats);
                modifiers = i9xx_plane_format_modifiers;
+
+               plane_funcs = &snb_sprite_funcs;
        } else {
                intel_plane->can_scale = true;
                intel_plane->max_downscale = 16;
@@ -1469,9 +1534,13 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
                if (IS_GEN6(dev_priv)) {
                        plane_formats = snb_plane_formats;
                        num_plane_formats = ARRAY_SIZE(snb_plane_formats);
+
+                       plane_funcs = &snb_sprite_funcs;
                } else {
                        plane_formats = g4x_plane_formats;
                        num_plane_formats = ARRAY_SIZE(g4x_plane_formats);
+
+                       plane_funcs = &g4x_sprite_funcs;
                }
        }
 
@@ -1498,14 +1567,14 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 
        if (INTEL_GEN(dev_priv) >= 9)
                ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
-                                              possible_crtcs, &intel_sprite_plane_funcs,
+                                              possible_crtcs, plane_funcs,
                                               plane_formats, num_plane_formats,
                                               modifiers,
                                               DRM_PLANE_TYPE_OVERLAY,
                                               "plane %d%c", plane + 2, pipe_name(pipe));
        else
                ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
-                                              possible_crtcs, &intel_sprite_plane_funcs,
+                                              possible_crtcs, plane_funcs,
                                               plane_formats, num_plane_formats,
                                               modifiers,
                                               DRM_PLANE_TYPE_OVERLAY,
index 302f7d1036359ab47db4009037561b99e2d617d6..ca682caf1062f08913b482b073f85dde16af53e7 100644 (file)
@@ -94,18 +94,6 @@ static void mock_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
        vm_unmap_ram(vaddr, mock->npages);
 }
 
-static void *mock_dmabuf_kmap_atomic(struct dma_buf *dma_buf, unsigned long page_num)
-{
-       struct mock_dmabuf *mock = to_mock(dma_buf);
-
-       return kmap_atomic(mock->pages[page_num]);
-}
-
-static void mock_dmabuf_kunmap_atomic(struct dma_buf *dma_buf, unsigned long page_num, void *addr)
-{
-       kunmap_atomic(addr);
-}
-
 static void *mock_dmabuf_kmap(struct dma_buf *dma_buf, unsigned long page_num)
 {
        struct mock_dmabuf *mock = to_mock(dma_buf);
@@ -130,9 +118,7 @@ static const struct dma_buf_ops mock_dmabuf_ops =  {
        .unmap_dma_buf = mock_unmap_dma_buf,
        .release = mock_dmabuf_release,
        .map = mock_dmabuf_kmap,
-       .map_atomic = mock_dmabuf_kmap_atomic,
        .unmap = mock_dmabuf_kunmap,
-       .unmap_atomic = mock_dmabuf_kunmap_atomic,
        .mmap = mock_dmabuf_mmap,
        .vmap = mock_dmabuf_vmap,
        .vunmap = mock_dmabuf_vunmap,
index 0d8d506695f9f87d9622708f9144549fc1b63ef6..be5f6f1daf5542973f28b6c3db07f9decafd5bbe 100644 (file)
@@ -15,6 +15,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 #include <linux/dma-buf.h>
 #include <linux/reservation.h>
 
 #include "mtk_drm_fb.h"
 #include "mtk_drm_gem.h"
 
-/*
- * mtk specific framebuffer structure.
- *
- * @fb: drm framebuffer object.
- * @gem_obj: array of gem objects.
- */
-struct mtk_drm_fb {
-       struct drm_framebuffer  base;
-       /* For now we only support a single plane */
-       struct drm_gem_object   *gem_obj;
-};
-
-#define to_mtk_fb(x) container_of(x, struct mtk_drm_fb, base)
-
-struct drm_gem_object *mtk_fb_get_gem_obj(struct drm_framebuffer *fb)
-{
-       struct mtk_drm_fb *mtk_fb = to_mtk_fb(fb);
-
-       return mtk_fb->gem_obj;
-}
-
-static int mtk_drm_fb_create_handle(struct drm_framebuffer *fb,
-                                   struct drm_file *file_priv,
-                                   unsigned int *handle)
-{
-       struct mtk_drm_fb *mtk_fb = to_mtk_fb(fb);
-
-       return drm_gem_handle_create(file_priv, mtk_fb->gem_obj, handle);
-}
-
-static void mtk_drm_fb_destroy(struct drm_framebuffer *fb)
-{
-       struct mtk_drm_fb *mtk_fb = to_mtk_fb(fb);
-
-       drm_framebuffer_cleanup(fb);
-
-       drm_gem_object_put_unlocked(mtk_fb->gem_obj);
-
-       kfree(mtk_fb);
-}
-
 static const struct drm_framebuffer_funcs mtk_drm_fb_funcs = {
-       .create_handle = mtk_drm_fb_create_handle,
-       .destroy = mtk_drm_fb_destroy,
+       .create_handle = drm_gem_fb_create_handle,
+       .destroy = drm_gem_fb_destroy,
 };
 
-static struct mtk_drm_fb *mtk_drm_framebuffer_init(struct drm_device *dev,
+static struct drm_framebuffer *mtk_drm_framebuffer_init(struct drm_device *dev,
                                        const struct drm_mode_fb_cmd2 *mode,
                                        struct drm_gem_object *obj)
 {
-       struct mtk_drm_fb *mtk_fb;
+       struct drm_framebuffer *fb;
        int ret;
 
        if (drm_format_num_planes(mode->pixel_format) != 1)
                return ERR_PTR(-EINVAL);
 
-       mtk_fb = kzalloc(sizeof(*mtk_fb), GFP_KERNEL);
-       if (!mtk_fb)
+       fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+       if (!fb)
                return ERR_PTR(-ENOMEM);
 
-       drm_helper_mode_fill_fb_struct(dev, &mtk_fb->base, mode);
+       drm_helper_mode_fill_fb_struct(dev, fb, mode);
 
-       mtk_fb->gem_obj = obj;
+       fb->obj[0] = obj;
 
-       ret = drm_framebuffer_init(dev, &mtk_fb->base, &mtk_drm_fb_funcs);
+       ret = drm_framebuffer_init(dev, fb, &mtk_drm_fb_funcs);
        if (ret) {
                DRM_ERROR("failed to initialize framebuffer\n");
-               kfree(mtk_fb);
+               kfree(fb);
                return ERR_PTR(ret);
        }
 
-       return mtk_fb;
+       return fb;
 }
 
 /*
@@ -110,7 +70,7 @@ int mtk_fb_wait(struct drm_framebuffer *fb)
        if (!fb)
                return 0;
 
-       gem = mtk_fb_get_gem_obj(fb);
+       gem = fb->obj[0];
        if (!gem || !gem->dma_buf || !gem->dma_buf->resv)
                return 0;
 
@@ -128,7 +88,7 @@ struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
                                               struct drm_file *file,
                                               const struct drm_mode_fb_cmd2 *cmd)
 {
-       struct mtk_drm_fb *mtk_fb;
+       struct drm_framebuffer *fb;
        struct drm_gem_object *gem;
        unsigned int width = cmd->width;
        unsigned int height = cmd->height;
@@ -151,13 +111,13 @@ struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
                goto unreference;
        }
 
-       mtk_fb = mtk_drm_framebuffer_init(dev, cmd, gem);
-       if (IS_ERR(mtk_fb)) {
-               ret = PTR_ERR(mtk_fb);
+       fb = mtk_drm_framebuffer_init(dev, cmd, gem);
+       if (IS_ERR(fb)) {
+               ret = PTR_ERR(fb);
                goto unreference;
        }
 
-       return &mtk_fb->base;
+       return fb;
 
 unreference:
        drm_gem_object_put_unlocked(gem);
index 9b2ae345a4e901fa80493a6610cb61233a501f86..7f976b196a154b09e5422c6818eba4bca4e4477c 100644 (file)
@@ -14,7 +14,6 @@
 #ifndef MTK_DRM_FB_H
 #define MTK_DRM_FB_H
 
-struct drm_gem_object *mtk_fb_get_gem_obj(struct drm_framebuffer *fb);
 int mtk_fb_wait(struct drm_framebuffer *fb);
 struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
                                               struct drm_file *file,
index 2f4b0ffee598948e12a00822c073ca9f34d3fb31..f7e6aa1b5b7d1d4e5b994d1acc0f8166a9eb09f0 100644 (file)
@@ -95,11 +95,6 @@ static int mtk_plane_atomic_check(struct drm_plane *plane,
        if (!fb)
                return 0;
 
-       if (!mtk_fb_get_gem_obj(fb)) {
-               DRM_DEBUG_KMS("buffer is null\n");
-               return -EFAULT;
-       }
-
        if (!state->crtc)
                return 0;
 
@@ -127,7 +122,7 @@ static void mtk_plane_atomic_update(struct drm_plane *plane,
        if (!crtc || WARN_ON(!fb))
                return;
 
-       gem = mtk_fb_get_gem_obj(fb);
+       gem = fb->obj[0];
        mtk_gem = to_mtk_gem_obj(gem);
        addr = mtk_gem->dma_addr;
        pitch = fb->pitches[0];
index b001699297c486ab075a76bedd3c27d0c95572ee..457c29dba4a1a096012fad1fd7b21e3b47cdb22e 100644 (file)
@@ -201,7 +201,7 @@ static void blend_setup(struct drm_crtc *crtc)
                int idx = idxs[pipe_id];
                if (idx > 0) {
                        const struct mdp_format *format =
-                                       to_mdp_format(msm_framebuffer_format(plane->fb));
+                                       to_mdp_format(msm_framebuffer_format(plane->state->fb));
                        alpha[idx-1] = format->alpha_enable;
                }
        }
@@ -665,7 +665,6 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
        drm_crtc_init_with_planes(dev, crtc, plane, NULL, &mdp4_crtc_funcs,
                                  NULL);
        drm_crtc_helper_add(crtc, &mdp4_crtc_helper_funcs);
-       plane->crtc = crtc;
 
        return crtc;
 }
index 20e956e14c2153fd31a3bfa170416e49e191f7a4..7b641fa6dc4d635aff21437f9c586f6a69fa7623 100644 (file)
@@ -167,8 +167,6 @@ static void mdp4_plane_set_scanout(struct drm_plane *plane,
                        msm_framebuffer_iova(fb, kms->aspace, 2));
        mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP3_BASE(pipe),
                        msm_framebuffer_iova(fb, kms->aspace, 3));
-
-       plane->fb = fb;
 }
 
 static void mdp4_write_csc_config(struct mdp4_kms *mdp4_kms,
index 10271359789e2b150c2268ca1500e7379e10b2aa..24e00274844b9ab846ba54aabd1e8ca5d5230194 100644 (file)
@@ -1207,7 +1207,6 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
                        "unref cursor", unref_cursor_worker);
 
        drm_crtc_helper_add(crtc, &mdp5_crtc_helper_funcs);
-       plane->crtc = crtc;
 
        return crtc;
 }
index e09bc53a0e6543eb1093dc46c22617fd53647e0b..c4f115fe96ff2a0f9d61e70b8ab6a28e36101df4 100644 (file)
@@ -512,7 +512,7 @@ static void mdp5_plane_atomic_async_update(struct drm_plane *plane,
        if (plane_enabled(new_state)) {
                struct mdp5_ctl *ctl;
                struct mdp5_pipeline *pipeline =
-                                       mdp5_crtc_get_pipeline(plane->crtc);
+                                       mdp5_crtc_get_pipeline(new_state->crtc);
                int ret;
 
                ret = mdp5_plane_mode_set(plane, new_state->crtc, new_state->fb,
@@ -1029,8 +1029,6 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
                                     src_img_w, src_img_h,
                                     src_x + src_w, src_y, src_w, src_h);
 
-       plane->fb = fb;
-
        return ret;
 }
 
index 7a16242bf8bf28bb5d7493fb47ded89c754f7092..2a7348aeb38d1a785c79b874a4d6fef9bb080017 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 
 #include "msm_drv.h"
 #include "msm_kms.h"
 struct msm_framebuffer {
        struct drm_framebuffer base;
        const struct msm_format *format;
-       struct drm_gem_object *planes[MAX_PLANE];
 };
 #define to_msm_framebuffer(x) container_of(x, struct msm_framebuffer, base)
 
 static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
                const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos);
 
-static int msm_framebuffer_create_handle(struct drm_framebuffer *fb,
-               struct drm_file *file_priv,
-               unsigned int *handle)
-{
-       struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb);
-       return drm_gem_handle_create(file_priv,
-                       msm_fb->planes[0], handle);
-}
-
-static void msm_framebuffer_destroy(struct drm_framebuffer *fb)
-{
-       struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb);
-       int i, n = fb->format->num_planes;
-
-       DBG("destroy: FB ID: %d (%p)", fb->base.id, fb);
-
-       drm_framebuffer_cleanup(fb);
-
-       for (i = 0; i < n; i++) {
-               struct drm_gem_object *bo = msm_fb->planes[i];
-
-               drm_gem_object_put_unlocked(bo);
-       }
-
-       kfree(msm_fb);
-}
-
 static const struct drm_framebuffer_funcs msm_framebuffer_funcs = {
-       .create_handle = msm_framebuffer_create_handle,
-       .destroy = msm_framebuffer_destroy,
+       .create_handle = drm_gem_fb_create_handle,
+       .destroy = drm_gem_fb_destroy,
 };
 
 #ifdef CONFIG_DEBUG_FS
 void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m)
 {
-       struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb);
        int i, n = fb->format->num_planes;
 
        seq_printf(m, "fb: %dx%d@%4.4s (%2d, ID:%d)\n",
@@ -77,7 +49,7 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m)
        for (i = 0; i < n; i++) {
                seq_printf(m, "   %d: offset=%d pitch=%d, obj: ",
                                i, fb->offsets[i], fb->pitches[i]);
-               msm_gem_describe(msm_fb->planes[i], m);
+               msm_gem_describe(fb->obj[i], m);
        }
 }
 #endif
@@ -90,12 +62,11 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m)
 int msm_framebuffer_prepare(struct drm_framebuffer *fb,
                struct msm_gem_address_space *aspace)
 {
-       struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb);
        int ret, i, n = fb->format->num_planes;
        uint64_t iova;
 
        for (i = 0; i < n; i++) {
-               ret = msm_gem_get_iova(msm_fb->planes[i], aspace, &iova);
+               ret = msm_gem_get_iova(fb->obj[i], aspace, &iova);
                DBG("FB[%u]: iova[%d]: %08llx (%d)", fb->base.id, i, iova, ret);
                if (ret)
                        return ret;
@@ -107,26 +78,23 @@ int msm_framebuffer_prepare(struct drm_framebuffer *fb,
 void msm_framebuffer_cleanup(struct drm_framebuffer *fb,
                struct msm_gem_address_space *aspace)
 {
-       struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb);
        int i, n = fb->format->num_planes;
 
        for (i = 0; i < n; i++)
-               msm_gem_put_iova(msm_fb->planes[i], aspace);
+               msm_gem_put_iova(fb->obj[i], aspace);
 }
 
 uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb,
                struct msm_gem_address_space *aspace, int plane)
 {
-       struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb);
-       if (!msm_fb->planes[plane])
+       if (!fb->obj[plane])
                return 0;
-       return msm_gem_iova(msm_fb->planes[plane], aspace) + fb->offsets[plane];
+       return msm_gem_iova(fb->obj[plane], aspace) + fb->offsets[plane];
 }
 
 struct drm_gem_object *msm_framebuffer_bo(struct drm_framebuffer *fb, int plane)
 {
-       struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb);
-       return msm_fb->planes[plane];
+       return drm_gem_fb_get_obj(fb, plane);
 }
 
 const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb)
@@ -202,7 +170,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
 
        msm_fb->format = format;
 
-       if (n > ARRAY_SIZE(msm_fb->planes)) {
+       if (n > ARRAY_SIZE(fb->obj)) {
                ret = -EINVAL;
                goto fail;
        }
@@ -221,7 +189,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
                        goto fail;
                }
 
-               msm_fb->planes[i] = bos[i];
+               msm_fb->base.obj[i] = bos[i];
        }
 
        drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
index 5fd22ca7391382d96269f7a364985e8d6bf1f05e..9f1e3d8f8488c823cc9914e49559adae88613017 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 
 #include "omap_dmm_tiler.h"
 #include "omap_drv.h"
@@ -51,9 +52,6 @@ static const u32 formats[] = {
 
 /* per-plane info for the fb: */
 struct plane {
-       struct drm_gem_object *bo;
-       u32 pitch;
-       u32 offset;
        dma_addr_t dma_addr;
 };
 
@@ -68,56 +66,28 @@ struct omap_framebuffer {
        struct mutex lock;
 };
 
-static int omap_framebuffer_create_handle(struct drm_framebuffer *fb,
-               struct drm_file *file_priv,
-               unsigned int *handle)
-{
-       struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
-       return drm_gem_handle_create(file_priv,
-                       omap_fb->planes[0].bo, handle);
-}
-
-static void omap_framebuffer_destroy(struct drm_framebuffer *fb)
-{
-       struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
-       int i, n = fb->format->num_planes;
-
-       DBG("destroy: FB ID: %d (%p)", fb->base.id, fb);
-
-       drm_framebuffer_cleanup(fb);
-
-       for (i = 0; i < n; i++) {
-               struct plane *plane = &omap_fb->planes[i];
-
-               drm_gem_object_unreference_unlocked(plane->bo);
-       }
-
-       kfree(omap_fb);
-}
-
 static const struct drm_framebuffer_funcs omap_framebuffer_funcs = {
-       .create_handle = omap_framebuffer_create_handle,
-       .destroy = omap_framebuffer_destroy,
+       .create_handle = drm_gem_fb_create_handle,
+       .destroy = drm_gem_fb_destroy,
 };
 
-static u32 get_linear_addr(struct plane *plane,
+static u32 get_linear_addr(struct drm_framebuffer *fb,
                const struct drm_format_info *format, int n, int x, int y)
 {
+       struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
+       struct plane *plane = &omap_fb->planes[n];
        u32 offset;
 
-       offset = plane->offset
+       offset = fb->offsets[n]
               + (x * format->cpp[n] / (n == 0 ? 1 : format->hsub))
-              + (y * plane->pitch / (n == 0 ? 1 : format->vsub));
+              + (y * fb->pitches[n] / (n == 0 ? 1 : format->vsub));
 
        return plane->dma_addr + offset;
 }
 
 bool omap_framebuffer_supports_rotation(struct drm_framebuffer *fb)
 {
-       struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
-       struct plane *plane = &omap_fb->planes[0];
-
-       return omap_gem_flags(plane->bo) & OMAP_BO_TILED;
+       return omap_gem_flags(fb->obj[0]) & OMAP_BO_TILED;
 }
 
 /* Note: DRM rotates counter-clockwise, TILER & DSS rotates clockwise */
@@ -176,7 +146,7 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
        x = state->src_x >> 16;
        y = state->src_y >> 16;
 
-       if (omap_gem_flags(plane->bo) & OMAP_BO_TILED) {
+       if (omap_gem_flags(fb->obj[0]) & OMAP_BO_TILED) {
                u32 w = state->src_w >> 16;
                u32 h = state->src_h >> 16;
 
@@ -201,12 +171,12 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
                        x += w - 1;
 
                /* Note: x and y are in TILER units, not pixels */
-               omap_gem_rotated_dma_addr(plane->bo, orient, x, y,
+               omap_gem_rotated_dma_addr(fb->obj[0], orient, x, y,
                                          &info->paddr);
                info->rotation_type = OMAP_DSS_ROT_TILER;
                info->rotation = state->rotation ?: DRM_MODE_ROTATE_0;
                /* Note: stride in TILER units, not pixels */
-               info->screen_width  = omap_gem_tiled_stride(plane->bo, orient);
+               info->screen_width  = omap_gem_tiled_stride(fb->obj[0], orient);
        } else {
                switch (state->rotation & DRM_MODE_ROTATE_MASK) {
                case 0:
@@ -221,10 +191,10 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
                        break;
                }
 
-               info->paddr         = get_linear_addr(plane, format, 0, x, y);
+               info->paddr         = get_linear_addr(fb, format, 0, x, y);
                info->rotation_type = OMAP_DSS_ROT_NONE;
                info->rotation      = DRM_MODE_ROTATE_0;
-               info->screen_width  = plane->pitch;
+               info->screen_width  = fb->pitches[0];
        }
 
        /* convert to pixels: */
@@ -234,11 +204,11 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
                plane = &omap_fb->planes[1];
 
                if (info->rotation_type == OMAP_DSS_ROT_TILER) {
-                       WARN_ON(!(omap_gem_flags(plane->bo) & OMAP_BO_TILED));
-                       omap_gem_rotated_dma_addr(plane->bo, orient, x/2, y/2,
+                       WARN_ON(!(omap_gem_flags(fb->obj[1]) & OMAP_BO_TILED));
+                       omap_gem_rotated_dma_addr(fb->obj[1], orient, x/2, y/2,
                                                  &info->p_uv_addr);
                } else {
-                       info->p_uv_addr = get_linear_addr(plane, format, 1, x, y);
+                       info->p_uv_addr = get_linear_addr(fb, format, 1, x, y);
                }
        } else {
                info->p_uv_addr = 0;
@@ -261,10 +231,10 @@ int omap_framebuffer_pin(struct drm_framebuffer *fb)
 
        for (i = 0; i < n; i++) {
                struct plane *plane = &omap_fb->planes[i];
-               ret = omap_gem_pin(plane->bo, &plane->dma_addr);
+               ret = omap_gem_pin(fb->obj[i], &plane->dma_addr);
                if (ret)
                        goto fail;
-               omap_gem_dma_sync_buffer(plane->bo, DMA_TO_DEVICE);
+               omap_gem_dma_sync_buffer(fb->obj[i], DMA_TO_DEVICE);
        }
 
        omap_fb->pin_count++;
@@ -276,7 +246,7 @@ int omap_framebuffer_pin(struct drm_framebuffer *fb)
 fail:
        for (i--; i >= 0; i--) {
                struct plane *plane = &omap_fb->planes[i];
-               omap_gem_unpin(plane->bo);
+               omap_gem_unpin(fb->obj[i]);
                plane->dma_addr = 0;
        }
 
@@ -302,54 +272,25 @@ void omap_framebuffer_unpin(struct drm_framebuffer *fb)
 
        for (i = 0; i < n; i++) {
                struct plane *plane = &omap_fb->planes[i];
-               omap_gem_unpin(plane->bo);
+               omap_gem_unpin(fb->obj[i]);
                plane->dma_addr = 0;
        }
 
        mutex_unlock(&omap_fb->lock);
 }
 
-/* iterate thru all the connectors, returning ones that are attached
- * to the same fb..
- */
-struct drm_connector *omap_framebuffer_get_next_connector(
-               struct drm_framebuffer *fb, struct drm_connector *from)
-{
-       struct drm_device *dev = fb->dev;
-       struct list_head *connector_list = &dev->mode_config.connector_list;
-       struct drm_connector *connector = from;
-
-       if (!from)
-               return list_first_entry_or_null(connector_list, typeof(*from),
-                                               head);
-
-       list_for_each_entry_from(connector, connector_list, head) {
-               if (connector != from) {
-                       struct drm_encoder *encoder = connector->encoder;
-                       struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
-                       if (crtc && crtc->primary->fb == fb)
-                               return connector;
-
-               }
-       }
-
-       return NULL;
-}
-
 #ifdef CONFIG_DEBUG_FS
 void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m)
 {
-       struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
        int i, n = fb->format->num_planes;
 
        seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height,
                        (char *)&fb->format->format);
 
        for (i = 0; i < n; i++) {
-               struct plane *plane = &omap_fb->planes[i];
                seq_printf(m, "   %d: offset=%d pitch=%d, obj: ",
-                               i, plane->offset, plane->pitch);
-               omap_gem_describe(plane->bo, m);
+                               i, fb->offsets[n], fb->pitches[i]);
+               omap_gem_describe(fb->obj[i], m);
        }
 }
 #endif
@@ -454,9 +395,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
                        goto fail;
                }
 
-               plane->bo     = bos[i];
-               plane->offset = mode_cmd->offsets[i];
-               plane->pitch  = pitch;
+               fb->obj[i]    = bos[i];
                plane->dma_addr  = 0;
        }
 
index 94ad5f9e440490fef9a09333d92ca6ed8f8d85ee..c20cb4bc714da874697c2104097ffee9726eb0a7 100644 (file)
@@ -38,8 +38,6 @@ int omap_framebuffer_pin(struct drm_framebuffer *fb);
 void omap_framebuffer_unpin(struct drm_framebuffer *fb);
 void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
                struct drm_plane_state *state, struct omap_overlay_info *info);
-struct drm_connector *omap_framebuffer_get_next_connector(
-               struct drm_framebuffer *fb, struct drm_connector *from);
 bool omap_framebuffer_supports_rotation(struct drm_framebuffer *fb);
 void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m);
 
index 8e41d649e248dd14ba6a5340c9e24db177088a6d..1a073f9b283494c9e514052de86b912f172ffe4e 100644 (file)
@@ -148,8 +148,6 @@ static const struct dma_buf_ops omap_dmabuf_ops = {
        .release = drm_gem_dmabuf_release,
        .begin_cpu_access = omap_gem_dmabuf_begin_cpu_access,
        .end_cpu_access = omap_gem_dmabuf_end_cpu_access,
-       .map_atomic = omap_gem_dmabuf_kmap_atomic,
-       .unmap_atomic = omap_gem_dmabuf_kunmap_atomic,
        .map = omap_gem_dmabuf_kmap,
        .unmap = omap_gem_dmabuf_kunmap,
        .mmap = omap_gem_dmabuf_mmap,
index 57df39b5c5899cd3caaffb51d8dbf5d7b2a2eea2..bb53e085076435df1376b1fd191a49815841638e 100644 (file)
@@ -292,7 +292,6 @@ static int innolux_panel_remove(struct mipi_dsi_device *dsi)
                DRM_DEV_ERROR(&dsi->dev, "failed to detach from DSI host: %d\n",
                              err);
 
-       drm_panel_detach(&innolux->base);
        innolux_panel_del(innolux);
 
        return 0;
index 0a94ab79a6c0f768227a3c273751913ef5bc512e..99caa7835e7b11d0be01b6aa5a0bbb3268cbd4ba 100644 (file)
@@ -500,7 +500,6 @@ static int jdi_panel_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "failed to detach from DSI host: %d\n",
                        ret);
 
-       drm_panel_detach(&jdi->base);
        jdi_panel_del(jdi);
 
        return 0;
index 5185819c5b797c0d834d64fa4d8951b56c01f4f7..8a1687887ae912f310b7214de6ef779d905179ae 100644 (file)
@@ -282,7 +282,6 @@ static int panel_lvds_remove(struct platform_device *pdev)
 {
        struct panel_lvds *lvds = dev_get_drvdata(&pdev->dev);
 
-       drm_panel_detach(&lvds->panel);
        drm_panel_remove(&lvds->panel);
 
        panel_lvds_disable(&lvds->panel);
index 90f1ae4af93c0d3ec92abe04c38850eafbc16e57..87fa316e1d7b09a60778751acc51972c759a1c84 100644 (file)
@@ -14,8 +14,6 @@
 #include <linux/regulator/consumer.h>
 #include <video/mipi_display.h>
 
-#define DRV_NAME "orisetech_otm8009a"
-
 #define OTM8009A_BACKLIGHT_DEFAULT     240
 #define OTM8009A_BACKLIGHT_MAX         255
 
@@ -98,6 +96,20 @@ static void otm8009a_dcs_write_buf(struct otm8009a *ctx, const void *data,
                DRM_WARN("mipi dsi dcs write buffer failed\n");
 }
 
+static void otm8009a_dcs_write_buf_hs(struct otm8009a *ctx, const void *data,
+                                     size_t len)
+{
+       struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+
+       /* data will be sent in dsi hs mode (ie. no lpm) */
+       dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+       otm8009a_dcs_write_buf(ctx, data, len);
+
+       /* restore back the dsi lpm mode */
+       dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+}
+
 #define dcs_write_seq(ctx, seq...)                     \
 ({                                                     \
        static const u8 d[] = { seq };                  \
@@ -248,11 +260,7 @@ static int otm8009a_disable(struct drm_panel *panel)
        if (!ctx->enabled)
                return 0; /* This is not an issue so we return 0 here */
 
-       /* Power off the backlight. Note: end-user still controls brightness */
-       ctx->bl_dev->props.power = FB_BLANK_POWERDOWN;
-       ret = backlight_update_status(ctx->bl_dev);
-       if (ret)
-               return ret;
+       backlight_disable(ctx->bl_dev);
 
        ret = mipi_dsi_dcs_set_display_off(dsi);
        if (ret)
@@ -316,13 +324,6 @@ static int otm8009a_prepare(struct drm_panel *panel)
 
        ctx->prepared = true;
 
-       /*
-        * Power on the backlight. Note: end-user still controls brightness
-        * Note: ctx->prepared must be true before updating the backlight.
-        */
-       ctx->bl_dev->props.power = FB_BLANK_UNBLANK;
-       backlight_update_status(ctx->bl_dev);
-
        return 0;
 }
 
@@ -330,6 +331,11 @@ static int otm8009a_enable(struct drm_panel *panel)
 {
        struct otm8009a *ctx = panel_to_otm8009a(panel);
 
+       if (ctx->enabled)
+               return 0;
+
+       backlight_enable(ctx->bl_dev);
+
        ctx->enabled = true;
 
        return 0;
@@ -387,7 +393,7 @@ static int otm8009a_backlight_update_status(struct backlight_device *bd)
                 */
                data[0] = MIPI_DCS_SET_DISPLAY_BRIGHTNESS;
                data[1] = bd->props.brightness;
-               otm8009a_dcs_write_buf(ctx, data, ARRAY_SIZE(data));
+               otm8009a_dcs_write_buf_hs(ctx, data, ARRAY_SIZE(data));
 
                /* set Brightness Control & Backlight on */
                data[1] = 0x24;
@@ -399,7 +405,7 @@ static int otm8009a_backlight_update_status(struct backlight_device *bd)
 
        /* Update Brightness Control & Backlight */
        data[0] = MIPI_DCS_WRITE_CONTROL_DISPLAY;
-       otm8009a_dcs_write_buf(ctx, data, ARRAY_SIZE(data));
+       otm8009a_dcs_write_buf_hs(ctx, data, ARRAY_SIZE(data));
 
        return 0;
 }
@@ -444,11 +450,14 @@ static int otm8009a_probe(struct mipi_dsi_device *dsi)
        ctx->panel.dev = dev;
        ctx->panel.funcs = &otm8009a_drm_funcs;
 
-       ctx->bl_dev = backlight_device_register(DRV_NAME "_backlight", dev, ctx,
-                                               &otm8009a_backlight_ops, NULL);
+       ctx->bl_dev = devm_backlight_device_register(dev, dev_name(dev),
+                                                    dsi->host->dev, ctx,
+                                                    &otm8009a_backlight_ops,
+                                                    NULL);
        if (IS_ERR(ctx->bl_dev)) {
-               dev_err(dev, "failed to register backlight device\n");
-               return PTR_ERR(ctx->bl_dev);
+               ret = PTR_ERR(ctx->bl_dev);
+               dev_err(dev, "failed to register backlight: %d\n", ret);
+               return ret;
        }
 
        ctx->bl_dev->props.max_brightness = OTM8009A_BACKLIGHT_MAX;
@@ -466,11 +475,6 @@ static int otm8009a_probe(struct mipi_dsi_device *dsi)
                return ret;
        }
 
-       DRM_INFO(DRV_NAME "_panel %ux%u@%u %ubpp dsi %udl - ready\n",
-                default_mode.hdisplay, default_mode.vdisplay,
-                default_mode.vrefresh,
-                mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);
-
        return 0;
 }
 
@@ -481,8 +485,6 @@ static int otm8009a_remove(struct mipi_dsi_device *dsi)
        mipi_dsi_detach(dsi);
        drm_panel_remove(&ctx->panel);
 
-       backlight_device_unregister(ctx->bl_dev);
-
        return 0;
 }
 
@@ -496,7 +498,7 @@ static struct mipi_dsi_driver orisetech_otm8009a_driver = {
        .probe  = otm8009a_probe,
        .remove = otm8009a_remove,
        .driver = {
-               .name = DRV_NAME "_panel",
+               .name = "panel-orisetech-otm8009a",
                .of_match_table = orisetech_otm8009a_of_match,
        },
 };
index 74a806121f80e58a42149cdd45a2536a1f6d8d70..cb4dfb98be0f11819f27183282f7d713895b1ba9 100644 (file)
@@ -299,7 +299,6 @@ static int wuxga_nt_panel_remove(struct mipi_dsi_device *dsi)
        if (ret < 0)
                dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
 
-       drm_panel_detach(&wuxga_nt->base);
        wuxga_nt_panel_del(wuxga_nt);
 
        return 0;
index 71c09ed436ae46d652e4a7dfe0c51277d57df12f..75f92539055104c14aba1fa9e42f39b71c1f3467 100644 (file)
@@ -292,7 +292,6 @@ static int seiko_panel_remove(struct platform_device *pdev)
 {
        struct seiko_panel *panel = dev_get_drvdata(&pdev->dev);
 
-       drm_panel_detach(&panel->base);
        drm_panel_remove(&panel->base);
 
        seiko_panel_disable(&panel->base);
index 6bf8730f1a2115068e82b5fdc6c4694d9acdb9fb..02fc0f5423d40e585dd8d12002c2bfc98a5c4717 100644 (file)
@@ -418,7 +418,6 @@ static int sharp_panel_remove(struct mipi_dsi_device *dsi)
        if (err < 0)
                dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
 
-       drm_panel_detach(&sharp->base);
        sharp_panel_del(sharp);
 
        return 0;
index 494aa9b1628a7275210e9a657522287a76c0e385..e5cae0050f52d45a1c0c8fd387efb893d521196f 100644 (file)
@@ -327,7 +327,6 @@ static int sharp_nt_panel_remove(struct mipi_dsi_device *dsi)
        if (ret < 0)
                dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
 
-       drm_panel_detach(&sharp_nt->base);
        sharp_nt_panel_del(sharp_nt);
 
        return 0;
index cbf1ab404ee77316ac6edd504df143bdb1cd39ef..ac6aaa174c0b8964da0462953b2a790c3740f31b 100644 (file)
@@ -364,7 +364,6 @@ static int panel_simple_remove(struct device *dev)
 {
        struct panel_simple *panel = dev_get_drvdata(dev);
 
-       drm_panel_detach(&panel->base);
        drm_panel_remove(&panel->base);
 
        panel_simple_disable(&panel->base);
@@ -581,6 +580,34 @@ static const struct panel_desc auo_b133htn01 = {
        },
 };
 
+static const struct display_timing auo_g070vvn01_timings = {
+       .pixelclock = { 33300000, 34209000, 45000000 },
+       .hactive = { 800, 800, 800 },
+       .hfront_porch = { 20, 40, 200 },
+       .hback_porch = { 87, 40, 1 },
+       .hsync_len = { 1, 48, 87 },
+       .vactive = { 480, 480, 480 },
+       .vfront_porch = { 5, 13, 200 },
+       .vback_porch = { 31, 31, 29 },
+       .vsync_len = { 1, 1, 3 },
+};
+
+static const struct panel_desc auo_g070vvn01 = {
+       .timings = &auo_g070vvn01_timings,
+       .num_timings = 1,
+       .bpc = 8,
+       .size = {
+               .width = 152,
+               .height = 91,
+       },
+       .delay = {
+               .prepare = 200,
+               .enable = 50,
+               .disable = 50,
+               .unprepare = 1000,
+       },
+};
+
 static const struct drm_display_mode auo_g104sn02_mode = {
        .clock = 40000,
        .hdisplay = 800,
@@ -687,7 +714,7 @@ static const struct panel_desc auo_p320hvn03 = {
                .enable = 450,
                .unprepare = 500,
        },
-       .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA,
+       .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
 };
 
 static const struct drm_display_mode auo_t215hvn01_mode = {
@@ -1217,6 +1244,30 @@ static const struct panel_desc innolux_n156bge_l21 = {
        },
 };
 
+static const struct drm_display_mode innolux_tv123wam_mode = {
+       .clock = 206016,
+       .hdisplay = 2160,
+       .hsync_start = 2160 + 48,
+       .hsync_end = 2160 + 48 + 32,
+       .htotal = 2160 + 48 + 32 + 80,
+       .vdisplay = 1440,
+       .vsync_start = 1440 + 3,
+       .vsync_end = 1440 + 3 + 10,
+       .vtotal = 1440 + 3 + 10 + 27,
+       .vrefresh = 60,
+       .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC,
+};
+
+static const struct panel_desc innolux_tv123wam = {
+       .modes = &innolux_tv123wam_mode,
+       .num_modes = 1,
+       .bpc = 8,
+       .size = {
+               .width = 259,
+               .height = 173,
+       },
+};
+
 static const struct drm_display_mode innolux_zj070na_01p_mode = {
        .clock = 51501,
        .hdisplay = 1024,
@@ -1247,8 +1298,8 @@ static const struct display_timing koe_tx31d200vm0baa_timing = {
        .hback_porch = { 16, 36, 56 },
        .hsync_len = { 8, 8, 8 },
        .vactive = { 480, 480, 480 },
-       .vfront_porch = { 6, 21, 33.5 },
-       .vback_porch = { 6, 21, 33.5 },
+       .vfront_porch = { 6, 21, 33 },
+       .vback_porch = { 6, 21, 33 },
        .vsync_len = { 8, 8, 8 },
        .flags = DISPLAY_FLAGS_DE_HIGH,
 };
@@ -2094,6 +2145,9 @@ static const struct of_device_id platform_of_match[] = {
        }, {
                .compatible = "auo,b133xtn01",
                .data = &auo_b133xtn01,
+       }, {
+               .compatible = "auo,g070vvn01",
+               .data = &auo_g070vvn01,
        }, {
                .compatible = "auo,g104sn02",
                .data = &auo_g104sn02,
@@ -2169,6 +2223,9 @@ static const struct of_device_id platform_of_match[] = {
        }, {
                .compatible = "innolux,n156bge-l21",
                .data = &innolux_n156bge_l21,
+       }, {
+               .compatible = "innolux,tv123wam",
+               .data = &innolux_tv123wam,
        }, {
                .compatible = "innolux,zj070na-01p",
                .data = &innolux_zj070na_01p,
index 358c64ef192223e40e6a72b27e5b287aab5147ed..74284e5afc5d9f78b6746554ecc124f641b89276 100644 (file)
@@ -419,7 +419,6 @@ static int st7789v_remove(struct spi_device *spi)
 {
        struct st7789v *ctx = spi_get_drvdata(spi);
 
-       drm_panel_detach(&ctx->panel);
        drm_panel_remove(&ctx->panel);
 
        if (ctx->backlight)
index eb3042c6d1b202bb27e2f1b55f6714d4f48b252a..3105965fc26034e921de4c86d39475180e70b03c 100644 (file)
@@ -792,7 +792,6 @@ err_config_video:
 
 int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio)
 {
-       u32 val;
        int ret;
 
        ret = cdn_dp_reg_write(dp, AUDIO_PACK_CONTROL, 0);
@@ -801,11 +800,7 @@ int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio)
                return ret;
        }
 
-       val = SPDIF_AVG_SEL | SPDIF_JITTER_BYPASS;
-       val |= SPDIF_FIFO_MID_RANGE(0xe0);
-       val |= SPDIF_JITTER_THRSH(0xe0);
-       val |= SPDIF_JITTER_AVG_WIN(7);
-       writel(val, dp->regs + SPDIF_CTRL_ADDR);
+       writel(0, dp->regs + SPDIF_CTRL_ADDR);
 
        /* clearn the audio config and reset */
        writel(0, dp->regs + AUDIO_SRC_CNTL);
@@ -929,12 +924,6 @@ static void cdn_dp_audio_config_spdif(struct cdn_dp_device *dp)
 {
        u32 val;
 
-       val = SPDIF_AVG_SEL | SPDIF_JITTER_BYPASS;
-       val |= SPDIF_FIFO_MID_RANGE(0xe0);
-       val |= SPDIF_JITTER_THRSH(0xe0);
-       val |= SPDIF_JITTER_AVG_WIN(7);
-       writel(val, dp->regs + SPDIF_CTRL_ADDR);
-
        writel(SYNC_WR_TO_CH_ZERO, dp->regs + FIFO_CNTL);
 
        val = MAX_NUM_CH(2) | AUDIO_TYPE_LPCM | CFG_SUB_PCKT_NUM(4);
@@ -942,9 +931,6 @@ static void cdn_dp_audio_config_spdif(struct cdn_dp_device *dp)
        writel(SMPL2PKT_EN, dp->regs + SMPL2PKT_CNTL);
 
        val = SPDIF_ENABLE | SPDIF_AVG_SEL | SPDIF_JITTER_BYPASS;
-       val |= SPDIF_FIFO_MID_RANGE(0xe0);
-       val |= SPDIF_JITTER_THRSH(0xe0);
-       val |= SPDIF_JITTER_AVG_WIN(7);
        writel(val, dp->regs + SPDIF_CTRL_ADDR);
 
        clk_prepare_enable(dp->spdif_clk);
index d4f4118b482ddd6f215eba1cb54d1f4dd5c83b3e..ea18cb2a76c0dc7c7e9052307dda301743a607c2 100644 (file)
 #include <drm/drm_atomic.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_fb.h"
 #include "rockchip_drm_gem.h"
 #include "rockchip_drm_psr.h"
 
-#define to_rockchip_fb(x) container_of(x, struct rockchip_drm_fb, fb)
-
-struct rockchip_drm_fb {
-       struct drm_framebuffer fb;
-       struct drm_gem_object *obj[ROCKCHIP_MAX_FB_BUFFER];
-};
-
-struct drm_gem_object *rockchip_fb_get_gem_obj(struct drm_framebuffer *fb,
-                                              unsigned int plane)
-{
-       struct rockchip_drm_fb *rk_fb = to_rockchip_fb(fb);
-
-       if (plane >= ROCKCHIP_MAX_FB_BUFFER)
-               return NULL;
-
-       return rk_fb->obj[plane];
-}
-
-static void rockchip_drm_fb_destroy(struct drm_framebuffer *fb)
-{
-       struct rockchip_drm_fb *rockchip_fb = to_rockchip_fb(fb);
-       int i;
-
-       for (i = 0; i < ROCKCHIP_MAX_FB_BUFFER; i++)
-               drm_gem_object_put_unlocked(rockchip_fb->obj[i]);
-
-       drm_framebuffer_cleanup(fb);
-       kfree(rockchip_fb);
-}
-
-static int rockchip_drm_fb_create_handle(struct drm_framebuffer *fb,
-                                        struct drm_file *file_priv,
-                                        unsigned int *handle)
-{
-       struct rockchip_drm_fb *rockchip_fb = to_rockchip_fb(fb);
-
-       return drm_gem_handle_create(file_priv,
-                                    rockchip_fb->obj[0], handle);
-}
-
 static int rockchip_drm_fb_dirty(struct drm_framebuffer *fb,
                                 struct drm_file *file,
                                 unsigned int flags, unsigned int color,
@@ -75,46 +36,45 @@ static int rockchip_drm_fb_dirty(struct drm_framebuffer *fb,
 }
 
 static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
-       .destroy        = rockchip_drm_fb_destroy,
-       .create_handle  = rockchip_drm_fb_create_handle,
-       .dirty          = rockchip_drm_fb_dirty,
+       .destroy       = drm_gem_fb_destroy,
+       .create_handle = drm_gem_fb_create_handle,
+       .dirty         = rockchip_drm_fb_dirty,
 };
 
-static struct rockchip_drm_fb *
+static struct drm_framebuffer *
 rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd,
                  struct drm_gem_object **obj, unsigned int num_planes)
 {
-       struct rockchip_drm_fb *rockchip_fb;
+       struct drm_framebuffer *fb;
        int ret;
        int i;
 
-       rockchip_fb = kzalloc(sizeof(*rockchip_fb), GFP_KERNEL);
-       if (!rockchip_fb)
+       fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+       if (!fb)
                return ERR_PTR(-ENOMEM);
 
-       drm_helper_mode_fill_fb_struct(dev, &rockchip_fb->fb, mode_cmd);
+       drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
 
        for (i = 0; i < num_planes; i++)
-               rockchip_fb->obj[i] = obj[i];
+               fb->obj[i] = obj[i];
 
-       ret = drm_framebuffer_init(dev, &rockchip_fb->fb,
-                                  &rockchip_drm_fb_funcs);
+       ret = drm_framebuffer_init(dev, fb, &rockchip_drm_fb_funcs);
        if (ret) {
                DRM_DEV_ERROR(dev->dev,
                              "Failed to initialize framebuffer: %d\n",
                              ret);
-               kfree(rockchip_fb);
+               kfree(fb);
                return ERR_PTR(ret);
        }
 
-       return rockchip_fb;
+       return fb;
 }
 
 static struct drm_framebuffer *
 rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
                        const struct drm_mode_fb_cmd2 *mode_cmd)
 {
-       struct rockchip_drm_fb *rockchip_fb;
+       struct drm_framebuffer *fb;
        struct drm_gem_object *objs[ROCKCHIP_MAX_FB_BUFFER];
        struct drm_gem_object *obj;
        unsigned int hsub;
@@ -153,13 +113,13 @@ rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
                objs[i] = obj;
        }
 
-       rockchip_fb = rockchip_fb_alloc(dev, mode_cmd, objs, i);
-       if (IS_ERR(rockchip_fb)) {
-               ret = PTR_ERR(rockchip_fb);
+       fb = rockchip_fb_alloc(dev, mode_cmd, objs, i);
+       if (IS_ERR(fb)) {
+               ret = PTR_ERR(fb);
                goto err_gem_object_unreference;
        }
 
-       return &rockchip_fb->fb;
+       return fb;
 
 err_gem_object_unreference:
        for (i--; i >= 0; i--)
@@ -242,13 +202,13 @@ rockchip_drm_framebuffer_init(struct drm_device *dev,
                              const struct drm_mode_fb_cmd2 *mode_cmd,
                              struct drm_gem_object *obj)
 {
-       struct rockchip_drm_fb *rockchip_fb;
+       struct drm_framebuffer *fb;
 
-       rockchip_fb = rockchip_fb_alloc(dev, mode_cmd, &obj, 1);
-       if (IS_ERR(rockchip_fb))
-               return ERR_CAST(rockchip_fb);
+       fb = rockchip_fb_alloc(dev, mode_cmd, &obj, 1);
+       if (IS_ERR(fb))
+               return ERR_CAST(fb);
 
-       return &rockchip_fb->fb;
+       return fb;
 }
 
 void rockchip_drm_mode_config_init(struct drm_device *dev)
index 2fe47f1ee98fe226e0c893d333023a678d1995a1..f1265cb1aee86b4c302329f5f909b6fa8b45a598 100644 (file)
@@ -22,7 +22,4 @@ rockchip_drm_framebuffer_init(struct drm_device *dev,
 void rockchip_drm_framebuffer_fini(struct drm_framebuffer *fb);
 
 void rockchip_drm_mode_config_init(struct drm_device *dev);
-
-struct drm_gem_object *rockchip_fb_get_gem_obj(struct drm_framebuffer *fb,
-                                              unsigned int plane);
 #endif /* _ROCKCHIP_DRM_FB_H */
index 2121345a61affb3d915b18c583ee86e4864abc64..c9222119767d8c0d7e9ed220040e5c66a2b1905d 100644 (file)
@@ -486,6 +486,31 @@ static void vop_line_flag_irq_disable(struct vop *vop)
        spin_unlock_irqrestore(&vop->irq_lock, flags);
 }
 
+static int vop_core_clks_enable(struct vop *vop)
+{
+       int ret;
+
+       ret = clk_enable(vop->hclk);
+       if (ret < 0)
+               return ret;
+
+       ret = clk_enable(vop->aclk);
+       if (ret < 0)
+               goto err_disable_hclk;
+
+       return 0;
+
+err_disable_hclk:
+       clk_disable(vop->hclk);
+       return ret;
+}
+
+static void vop_core_clks_disable(struct vop *vop)
+{
+       clk_disable(vop->aclk);
+       clk_disable(vop->hclk);
+}
+
 static int vop_enable(struct drm_crtc *crtc)
 {
        struct vop *vop = to_vop(crtc);
@@ -497,17 +522,13 @@ static int vop_enable(struct drm_crtc *crtc)
                return ret;
        }
 
-       ret = clk_enable(vop->hclk);
+       ret = vop_core_clks_enable(vop);
        if (WARN_ON(ret < 0))
                goto err_put_pm_runtime;
 
        ret = clk_enable(vop->dclk);
        if (WARN_ON(ret < 0))
-               goto err_disable_hclk;
-
-       ret = clk_enable(vop->aclk);
-       if (WARN_ON(ret < 0))
-               goto err_disable_dclk;
+               goto err_disable_core;
 
        /*
         * Slave iommu shares power, irq and clock with vop.  It was associated
@@ -519,7 +540,7 @@ static int vop_enable(struct drm_crtc *crtc)
        if (ret) {
                DRM_DEV_ERROR(vop->dev,
                              "failed to attach dma mapping, %d\n", ret);
-               goto err_disable_aclk;
+               goto err_disable_dclk;
        }
 
        spin_lock(&vop->reg_lock);
@@ -552,18 +573,14 @@ static int vop_enable(struct drm_crtc *crtc)
 
        spin_unlock(&vop->reg_lock);
 
-       enable_irq(vop->irq);
-
        drm_crtc_vblank_on(crtc);
 
        return 0;
 
-err_disable_aclk:
-       clk_disable(vop->aclk);
 err_disable_dclk:
        clk_disable(vop->dclk);
-err_disable_hclk:
-       clk_disable(vop->hclk);
+err_disable_core:
+       vop_core_clks_disable(vop);
 err_put_pm_runtime:
        pm_runtime_put_sync(vop->dev);
        return ret;
@@ -599,8 +616,6 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc,
 
        vop_dsp_hold_valid_irq_disable(vop);
 
-       disable_irq(vop->irq);
-
        vop->is_enabled = false;
 
        /*
@@ -609,8 +624,7 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc,
        rockchip_drm_dma_detach_device(vop->drm_dev, vop->dev);
 
        clk_disable(vop->dclk);
-       clk_disable(vop->aclk);
-       clk_disable(vop->hclk);
+       vop_core_clks_disable(vop);
        pm_runtime_put(vop->dev);
        mutex_unlock(&vop->vop_lock);
 
@@ -728,7 +742,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
                return;
        }
 
-       obj = rockchip_fb_get_gem_obj(fb, 0);
+       obj = fb->obj[0];
        rk_obj = to_rockchip_obj(obj);
 
        actual_w = drm_rect_width(src) >> 16;
@@ -758,7 +772,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
                int vsub = drm_format_vert_chroma_subsampling(fb->format->format);
                int bpp = fb->format->cpp[1];
 
-               uv_obj = rockchip_fb_get_gem_obj(fb, 1);
+               uv_obj = fb->obj[1];
                rk_uv_obj = to_rockchip_obj(uv_obj);
 
                offset = (src->x1 >> 16) * bpp / hsub;
@@ -1177,6 +1191,18 @@ static irqreturn_t vop_isr(int irq, void *data)
        uint32_t active_irqs;
        int ret = IRQ_NONE;
 
+       /*
+        * The irq is shared with the iommu. If the runtime-pm state of the
+        * vop-device is disabled the irq has to be targeted at the iommu.
+        */
+       if (!pm_runtime_get_if_in_use(vop->dev))
+               return IRQ_NONE;
+
+       if (vop_core_clks_enable(vop)) {
+               DRM_DEV_ERROR_RATELIMITED(vop->dev, "couldn't enable clocks\n");
+               goto out;
+       }
+
        /*
         * interrupt register has interrupt status, enable and clear bits, we
         * must hold irq_lock to avoid a race with enable/disable_vblank().
@@ -1192,7 +1218,7 @@ static irqreturn_t vop_isr(int irq, void *data)
 
        /* This is expected for vop iommu irqs, since the irq is shared */
        if (!active_irqs)
-               return IRQ_NONE;
+               goto out_disable;
 
        if (active_irqs & DSP_HOLD_VALID_INTR) {
                complete(&vop->dsp_hold_completion);
@@ -1218,6 +1244,10 @@ static irqreturn_t vop_isr(int irq, void *data)
                DRM_DEV_ERROR(vop->dev, "Unknown VOP IRQs: %#02x\n",
                              active_irqs);
 
+out_disable:
+       vop_core_clks_disable(vop);
+out:
+       pm_runtime_put(vop->dev);
        return ret;
 }
 
@@ -1596,9 +1626,6 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
        if (ret)
                goto err_disable_pm_runtime;
 
-       /* IRQ is initially disabled; it gets enabled in power_on */
-       disable_irq(vop->irq);
-
        return 0;
 
 err_disable_pm_runtime:
index e67f4ea28c0e4122e4a4ce5ae48843e2f9b8a847..b3f6f524b4020f21c2e518f1997d6dfa481a1cc0 100644 (file)
@@ -363,8 +363,10 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
                of_property_read_u32(endpoint, "reg", &endpoint_id);
                ret = drm_of_find_panel_or_bridge(dev->of_node, 1, endpoint_id,
                                                  &lvds->panel, &lvds->bridge);
-               if (!ret)
+               if (!ret) {
+                       of_node_put(endpoint);
                        break;
+               }
        }
        if (!child_count) {
                DRM_DEV_ERROR(dev, "lvds port does not have any children\n");
@@ -446,14 +448,12 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
                        goto err_free_connector;
                }
        } else {
-               lvds->bridge->encoder = encoder;
                ret = drm_bridge_attach(encoder, lvds->bridge, NULL);
                if (ret) {
                        DRM_DEV_ERROR(drm_dev->dev,
                                      "failed to attach bridge: %d\n", ret);
                        goto err_free_encoder;
                }
-               encoder->bridge = lvds->bridge;
        }
 
        pm_runtime_enable(dev);
index 54acc117550cfac5fe16e38e753b6067a46ca884..6b943ea1c57daf97143b13f278b6679b6c1d9798 100644 (file)
@@ -19,7 +19,9 @@ selftest(align64, igt_align64)
 selftest(evict, igt_evict)
 selftest(evict_range, igt_evict_range)
 selftest(bottomup, igt_bottomup)
+selftest(lowest, igt_lowest)
 selftest(topdown, igt_topdown)
+selftest(highest, igt_highest)
 selftest(color, igt_color)
 selftest(color_evict, igt_color_evict)
 selftest(color_evict_range, igt_color_evict_range)
index 933af1c253878acc64e05da0b6f73eee01fcc5c9..fbed2c90fd51ea4dcb5aab0ee8d6e5c7dadadfd6 100644 (file)
@@ -1825,6 +1825,77 @@ err:
        return ret;
 }
 
+static int __igt_once(unsigned int mode)
+{
+       struct drm_mm mm;
+       struct drm_mm_node rsvd_lo, rsvd_hi, node;
+       int err;
+
+       drm_mm_init(&mm, 0, 7);
+
+       memset(&rsvd_lo, 0, sizeof(rsvd_lo));
+       rsvd_lo.start = 1;
+       rsvd_lo.size = 1;
+       err = drm_mm_reserve_node(&mm, &rsvd_lo);
+       if (err) {
+               pr_err("Could not reserve low node\n");
+               goto err;
+       }
+
+       memset(&rsvd_hi, 0, sizeof(rsvd_hi));
+       rsvd_hi.start = 5;
+       rsvd_hi.size = 1;
+       err = drm_mm_reserve_node(&mm, &rsvd_hi);
+       if (err) {
+               pr_err("Could not reserve low node\n");
+               goto err_lo;
+       }
+
+       if (!drm_mm_hole_follows(&rsvd_lo) || !drm_mm_hole_follows(&rsvd_hi)) {
+               pr_err("Expected a hole after lo and high nodes!\n");
+               err = -EINVAL;
+               goto err_hi;
+       }
+
+       memset(&node, 0, sizeof(node));
+       err = drm_mm_insert_node_generic(&mm, &node,
+                                        2, 0, 0,
+                                        mode | DRM_MM_INSERT_ONCE);
+       if (!err) {
+               pr_err("Unexpectedly inserted the node into the wrong hole: node.start=%llx\n",
+                      node.start);
+               err = -EINVAL;
+               goto err_node;
+       }
+
+       err = drm_mm_insert_node_generic(&mm, &node, 2, 0, 0, mode);
+       if (err) {
+               pr_err("Could not insert the node into the available hole!\n");
+               err = -EINVAL;
+               goto err_hi;
+       }
+
+err_node:
+       drm_mm_remove_node(&node);
+err_hi:
+       drm_mm_remove_node(&rsvd_hi);
+err_lo:
+       drm_mm_remove_node(&rsvd_lo);
+err:
+       drm_mm_takedown(&mm);
+       return err;
+}
+
+static int igt_lowest(void *ignored)
+{
+       return __igt_once(DRM_MM_INSERT_LOW);
+}
+
+static int igt_highest(void *ignored)
+{
+       return __igt_once(DRM_MM_INSERT_HIGH);
+}
+
 static void separate_adjacent_colors(const struct drm_mm_node *node,
                                     unsigned long color,
                                     u64 *start,
index 9b2c47051b51ed50ce5153f8a33aa15ac2178348..49813d34bdf06b3cd22ff314f7733605c850029e 100644 (file)
@@ -211,7 +211,11 @@ static int gdp_dbg_show(struct seq_file *s, void *data)
        struct drm_info_node *node = s->private;
        struct sti_gdp *gdp = (struct sti_gdp *)node->info_ent->data;
        struct drm_plane *drm_plane = &gdp->plane.drm_plane;
-       struct drm_crtc *crtc = drm_plane->crtc;
+       struct drm_crtc *crtc;
+
+       drm_modeset_lock(&drm_plane->mutex, NULL);
+       crtc = drm_plane->state->crtc;
+       drm_modeset_unlock(&drm_plane->mutex);
 
        seq_printf(s, "%s: (vaddr = 0x%p)",
                   sti_plane_to_str(&gdp->plane), gdp->regs);
index bfbf761f0c1dd899531c149fce4d6828e56a9579..d4e7d16a2514ed441d796d8e7b818599d1f179de 100644 (file)
@@ -1040,7 +1040,7 @@ static int sun6i_dsi_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int sun6i_dsi_runtime_resume(struct device *dev)
+static int __maybe_unused sun6i_dsi_runtime_resume(struct device *dev)
 {
        struct sun6i_dsi *dsi = dev_get_drvdata(dev);
 
@@ -1069,7 +1069,7 @@ static int sun6i_dsi_runtime_resume(struct device *dev)
        return 0;
 }
 
-static int sun6i_dsi_runtime_suspend(struct device *dev)
+static int __maybe_unused sun6i_dsi_runtime_suspend(struct device *dev)
 {
        struct sun6i_dsi *dsi = dev_get_drvdata(dev);
 
index 00a5c9f322543d8fa6a16ec8515dc07bf9e7146d..4f80100ff5f34b7ca997fb5a31a8c3c6788e59cf 100644 (file)
@@ -582,18 +582,6 @@ static int tegra_gem_prime_end_cpu_access(struct dma_buf *buf,
        return 0;
 }
 
-static void *tegra_gem_prime_kmap_atomic(struct dma_buf *buf,
-                                        unsigned long page)
-{
-       return NULL;
-}
-
-static void tegra_gem_prime_kunmap_atomic(struct dma_buf *buf,
-                                         unsigned long page,
-                                         void *addr)
-{
-}
-
 static void *tegra_gem_prime_kmap(struct dma_buf *buf, unsigned long page)
 {
        return NULL;
@@ -634,8 +622,6 @@ static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = {
        .release = tegra_gem_prime_release,
        .begin_cpu_access = tegra_gem_prime_begin_cpu_access,
        .end_cpu_access = tegra_gem_prime_end_cpu_access,
-       .map_atomic = tegra_gem_prime_kmap_atomic,
-       .unmap_atomic = tegra_gem_prime_kunmap_atomic,
        .map = tegra_gem_prime_kmap,
        .unmap = tegra_gem_prime_kunmap,
        .mmap = tegra_gem_prime_mmap,
index 0a20695eb120e80bd448db9bfa540fcc42817c93..556f62662aa92b41fefb738c1036dbd2eef18432 100644 (file)
@@ -29,7 +29,6 @@ struct udl_drm_dmabuf_attachment {
 };
 
 static int udl_attach_dma_buf(struct dma_buf *dmabuf,
-                             struct device *dev,
                              struct dma_buf_attachment *attach)
 {
        struct udl_drm_dmabuf_attachment *udl_attach;
@@ -158,27 +157,12 @@ static void *udl_dmabuf_kmap(struct dma_buf *dma_buf, unsigned long page_num)
        return NULL;
 }
 
-static void *udl_dmabuf_kmap_atomic(struct dma_buf *dma_buf,
-                                   unsigned long page_num)
-{
-       /* TODO */
-
-       return NULL;
-}
-
 static void udl_dmabuf_kunmap(struct dma_buf *dma_buf,
                              unsigned long page_num, void *addr)
 {
        /* TODO */
 }
 
-static void udl_dmabuf_kunmap_atomic(struct dma_buf *dma_buf,
-                                    unsigned long page_num,
-                                    void *addr)
-{
-       /* TODO */
-}
-
 static int udl_dmabuf_mmap(struct dma_buf *dma_buf,
                           struct vm_area_struct *vma)
 {
@@ -193,9 +177,7 @@ static const struct dma_buf_ops udl_dmabuf_ops = {
        .map_dma_buf            = udl_map_dma_buf,
        .unmap_dma_buf          = udl_unmap_dma_buf,
        .map                    = udl_dmabuf_kmap,
-       .map_atomic             = udl_dmabuf_kmap_atomic,
        .unmap                  = udl_dmabuf_kunmap,
-       .unmap_atomic           = udl_dmabuf_kunmap_atomic,
        .mmap                   = udl_dmabuf_mmap,
        .release                = drm_gem_dmabuf_release,
 };
index 55c0cc3091981754d9449a3c7001211f13621ced..072582570a4fa4508a18585fa95c6514f08d64a1 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/usb.h>
 #include <drm/drm_gem.h>
+#include <linux/mm_types.h>
 
 #define DRIVER_NAME            "udl"
 #define DRIVER_DESC            "DisplayLink"
@@ -136,7 +137,7 @@ void udl_gem_put_pages(struct udl_gem_object *obj);
 int udl_gem_vmap(struct udl_gem_object *obj);
 void udl_gem_vunmap(struct udl_gem_object *obj);
 int udl_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
-int udl_gem_fault(struct vm_fault *vmf);
+vm_fault_t udl_gem_fault(struct vm_fault *vmf);
 
 int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
                      int width, int height);
index 9a15cce22ccee8ef2e1d08d6857024e8fd547192..d5a23295dd80c1a9c1f2cc202c4c93048fc163ef 100644 (file)
@@ -100,13 +100,12 @@ int udl_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
        return ret;
 }
 
-int udl_gem_fault(struct vm_fault *vmf)
+vm_fault_t udl_gem_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct udl_gem_object *obj = to_udl_bo(vma->vm_private_data);
        struct page *page;
        unsigned int page_offset;
-       int ret = 0;
 
        page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
 
@@ -114,17 +113,7 @@ int udl_gem_fault(struct vm_fault *vmf)
                return VM_FAULT_SIGBUS;
 
        page = obj->pages[page_offset];
-       ret = vm_insert_page(vma, vmf->address, page);
-       switch (ret) {
-       case -EAGAIN:
-       case 0:
-       case -ERESTARTSYS:
-               return VM_FAULT_NOPAGE;
-       case -ENOMEM:
-               return VM_FAULT_OOM;
-       default:
-               return VM_FAULT_SIGBUS;
-       }
+       return vmf_insert_page(vma, vmf->address, page);
 }
 
 int udl_gem_get_pages(struct udl_gem_object *obj)
index b07bece9417dc6a3a592789dc0684ba930824f5b..808bc901f567f2aaa81acbaa3e64e70640c44317 100644 (file)
@@ -114,8 +114,8 @@ static struct dma_fence *v3d_job_run(struct drm_sched_job *sched_job)
        v3d_invalidate_caches(v3d);
 
        fence = v3d_fence_create(v3d, q);
-       if (!fence)
-               return fence;
+       if (IS_ERR(fence))
+               return NULL;
 
        if (job->done_fence)
                dma_fence_put(job->done_fence);
index c8650bbcbcb3b34898320982137c40a1c19739e4..dcadf793ee80697cae097733eb387470c6423594 100644 (file)
@@ -862,7 +862,6 @@ static int vc4_async_page_flip(struct drm_crtc *crtc,
         * is released.
         */
        drm_atomic_set_fb_for_plane(plane->state, fb);
-       plane->fb = fb;
 
        vc4_queue_seqno_cb(dev, &flip_state->cb, bo->seqno,
                           vc4_async_page_flip_complete);
@@ -1057,7 +1056,6 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
        drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
                                  &vc4_crtc_funcs, NULL);
        drm_crtc_helper_add(crtc, &vc4_crtc_helper_funcs);
-       primary_plane->crtc = crtc;
        vc4_crtc->channel = vc4_crtc->data->hvs_channel;
        drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
        drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
@@ -1093,7 +1091,6 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
        cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR);
        if (!IS_ERR(cursor_plane)) {
                cursor_plane->possible_crtcs = 1 << drm_crtc_index(crtc);
-               cursor_plane->crtc = crtc;
                crtc->cursor = cursor_plane;
        }
 
index 1d34619eb3fe3f57402291e7dbd05c4a193c45e1..8604fd2e7c5aec55d29c1a3ba2ed75e57810e03a 100644 (file)
@@ -467,12 +467,14 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
        struct drm_framebuffer *fb = state->fb;
        u32 ctl0_offset = vc4_state->dlist_count;
        const struct hvs_format *format = vc4_get_hvs_format(fb->format->format);
+       u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier);
        int num_planes = drm_format_num_planes(format->drm);
        bool mix_plane_alpha;
        bool covers_screen;
        u32 scl0, scl1, pitch0;
        u32 lbm_size, tiling;
        unsigned long irqflags;
+       u32 hvs_format = format->hvs;
        int ret, i;
 
        ret = vc4_plane_setup_clipping_and_scaling(state);
@@ -512,7 +514,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
                scl1 = vc4_get_scl_field(state, 0);
        }
 
-       switch (fb->modifier) {
+       switch (base_format_mod) {
        case DRM_FORMAT_MOD_LINEAR:
                tiling = SCALER_CTL0_TILING_LINEAR;
                pitch0 = VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH);
@@ -535,6 +537,49 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
                break;
        }
 
+       case DRM_FORMAT_MOD_BROADCOM_SAND64:
+       case DRM_FORMAT_MOD_BROADCOM_SAND128:
+       case DRM_FORMAT_MOD_BROADCOM_SAND256: {
+               uint32_t param = fourcc_mod_broadcom_param(fb->modifier);
+
+               /* Column-based NV12 or RGBA.
+                */
+               if (fb->format->num_planes > 1) {
+                       if (hvs_format != HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE) {
+                               DRM_DEBUG_KMS("SAND format only valid for NV12/21");
+                               return -EINVAL;
+                       }
+                       hvs_format = HVS_PIXEL_FORMAT_H264;
+               } else {
+                       if (base_format_mod == DRM_FORMAT_MOD_BROADCOM_SAND256) {
+                               DRM_DEBUG_KMS("SAND256 format only valid for H.264");
+                               return -EINVAL;
+                       }
+               }
+
+               switch (base_format_mod) {
+               case DRM_FORMAT_MOD_BROADCOM_SAND64:
+                       tiling = SCALER_CTL0_TILING_64B;
+                       break;
+               case DRM_FORMAT_MOD_BROADCOM_SAND128:
+                       tiling = SCALER_CTL0_TILING_128B;
+                       break;
+               case DRM_FORMAT_MOD_BROADCOM_SAND256:
+                       tiling = SCALER_CTL0_TILING_256B_OR_T;
+                       break;
+               default:
+                       break;
+               }
+
+               if (param > SCALER_TILE_HEIGHT_MASK) {
+                       DRM_DEBUG_KMS("SAND height too large (%d)\n", param);
+                       return -EINVAL;
+               }
+
+               pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT);
+               break;
+       }
+
        default:
                DRM_DEBUG_KMS("Unsupported FB tiling flag 0x%16llx",
                              (long long)fb->modifier);
@@ -544,8 +589,9 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
        /* Control word */
        vc4_dlist_write(vc4_state,
                        SCALER_CTL0_VALID |
+                       VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) |
                        (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) |
-                       (format->hvs << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
+                       (hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
                        VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) |
                        (vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) |
                        VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) |
@@ -607,8 +653,13 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
 
        /* Pitch word 1/2 */
        for (i = 1; i < num_planes; i++) {
-               vc4_dlist_write(vc4_state,
-                               VC4_SET_FIELD(fb->pitches[i], SCALER_SRC_PITCH));
+               if (hvs_format != HVS_PIXEL_FORMAT_H264) {
+                       vc4_dlist_write(vc4_state,
+                                       VC4_SET_FIELD(fb->pitches[i],
+                                                     SCALER_SRC_PITCH));
+               } else {
+                       vc4_dlist_write(vc4_state, pitch0);
+               }
        }
 
        /* Colorspace conversion words */
@@ -810,18 +861,21 @@ static int vc4_prepare_fb(struct drm_plane *plane,
        struct dma_fence *fence;
        int ret;
 
-       if ((plane->state->fb == state->fb) || !state->fb)
+       if (!state->fb)
                return 0;
 
        bo = to_vc4_bo(&drm_fb_cma_get_gem_obj(state->fb, 0)->base);
 
+       fence = reservation_object_get_excl_rcu(bo->resv);
+       drm_atomic_set_fence_for_plane(state, fence);
+
+       if (plane->state->fb == state->fb)
+               return 0;
+
        ret = vc4_bo_inc_usecnt(bo);
        if (ret)
                return ret;
 
-       fence = reservation_object_get_excl_rcu(bo->resv);
-       drm_atomic_set_fence_for_plane(state, fence);
-
        return 0;
 }
 
@@ -866,13 +920,32 @@ static bool vc4_format_mod_supported(struct drm_plane *plane,
        case DRM_FORMAT_BGR565:
        case DRM_FORMAT_ARGB1555:
        case DRM_FORMAT_XRGB1555:
-               return true;
+               switch (fourcc_mod_broadcom_mod(modifier)) {
+               case DRM_FORMAT_MOD_LINEAR:
+               case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
+               case DRM_FORMAT_MOD_BROADCOM_SAND64:
+               case DRM_FORMAT_MOD_BROADCOM_SAND128:
+                       return true;
+               default:
+                       return false;
+               }
+       case DRM_FORMAT_NV12:
+       case DRM_FORMAT_NV21:
+               switch (fourcc_mod_broadcom_mod(modifier)) {
+               case DRM_FORMAT_MOD_LINEAR:
+               case DRM_FORMAT_MOD_BROADCOM_SAND64:
+               case DRM_FORMAT_MOD_BROADCOM_SAND128:
+               case DRM_FORMAT_MOD_BROADCOM_SAND256:
+                       return true;
+               default:
+                       return false;
+               }
        case DRM_FORMAT_YUV422:
        case DRM_FORMAT_YVU422:
        case DRM_FORMAT_YUV420:
        case DRM_FORMAT_YVU420:
-       case DRM_FORMAT_NV12:
        case DRM_FORMAT_NV16:
+       case DRM_FORMAT_NV61:
        default:
                return (modifier == DRM_FORMAT_MOD_LINEAR);
        }
@@ -900,6 +973,9 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
        unsigned i;
        static const uint64_t modifiers[] = {
                DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
+               DRM_FORMAT_MOD_BROADCOM_SAND128,
+               DRM_FORMAT_MOD_BROADCOM_SAND64,
+               DRM_FORMAT_MOD_BROADCOM_SAND256,
                DRM_FORMAT_MOD_LINEAR,
                DRM_FORMAT_MOD_INVALID
        };
index d1fb6fec46eb2c6ee016c59e238c368764ffe8b3..d6864fa4bd141d032a4cfb730841e16e8321d192 100644 (file)
@@ -1031,6 +1031,12 @@ enum hvs_pixel_format {
 #define SCALER_SRC_PITCH_MASK                  VC4_MASK(15, 0)
 #define SCALER_SRC_PITCH_SHIFT                 0
 
+/* PITCH0/1/2 fields for tiled (SAND). */
+#define SCALER_TILE_SKIP_0_MASK                        VC4_MASK(18, 16)
+#define SCALER_TILE_SKIP_0_SHIFT               16
+#define SCALER_TILE_HEIGHT_MASK                        VC4_MASK(15, 0)
+#define SCALER_TILE_HEIGHT_SHIFT               0
+
 /* PITCH0 fields for T-tiled. */
 #define SCALER_PITCH0_TILE_WIDTH_L_MASK                VC4_MASK(22, 16)
 #define SCALER_PITCH0_TILE_WIDTH_L_SHIFT       16
index 2524ff116f00d922267213d1a4f8554172057400..c64a85950c8293fc39e7a42863460d12cb769253 100644 (file)
@@ -61,13 +61,13 @@ static void vgem_gem_free_object(struct drm_gem_object *obj)
        kfree(vgem_obj);
 }
 
-static int vgem_gem_fault(struct vm_fault *vmf)
+static vm_fault_t vgem_gem_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct drm_vgem_gem_object *obj = vma->vm_private_data;
        /* We don't use vmf->pgoff since that has the fake offset */
        unsigned long vaddr = vmf->address;
-       int ret;
+       vm_fault_t ret = VM_FAULT_SIGBUS;
        loff_t num_pages;
        pgoff_t page_offset;
        page_offset = (vaddr - vma->vm_start) >> PAGE_SHIFT;
@@ -77,7 +77,6 @@ static int vgem_gem_fault(struct vm_fault *vmf)
        if (page_offset > num_pages)
                return VM_FAULT_SIGBUS;
 
-       ret = -ENOENT;
        mutex_lock(&obj->pages_lock);
        if (obj->pages) {
                get_page(obj->pages[page_offset]);
index a5edd86603d9ee3321a5cba885f753cc318ff338..ff9933e794169f9af7701569e1fe522bac33a072 100644 (file)
@@ -28,6 +28,7 @@
 #include "virtgpu_drv.h"
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 
 #define XRES_MIN    32
 #define YRES_MIN    32
@@ -48,16 +49,6 @@ static const struct drm_crtc_funcs virtio_gpu_crtc_funcs = {
        .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
 };
 
-static void virtio_gpu_user_framebuffer_destroy(struct drm_framebuffer *fb)
-{
-       struct virtio_gpu_framebuffer *virtio_gpu_fb
-               = to_virtio_gpu_framebuffer(fb);
-
-       drm_gem_object_put_unlocked(virtio_gpu_fb->obj);
-       drm_framebuffer_cleanup(fb);
-       kfree(virtio_gpu_fb);
-}
-
 static int
 virtio_gpu_framebuffer_surface_dirty(struct drm_framebuffer *fb,
                                     struct drm_file *file_priv,
@@ -71,20 +62,9 @@ virtio_gpu_framebuffer_surface_dirty(struct drm_framebuffer *fb,
        return virtio_gpu_surface_dirty(virtio_gpu_fb, clips, num_clips);
 }
 
-static int
-virtio_gpu_framebuffer_create_handle(struct drm_framebuffer *fb,
-                                    struct drm_file *file_priv,
-                                    unsigned int *handle)
-{
-       struct virtio_gpu_framebuffer *virtio_gpu_fb =
-               to_virtio_gpu_framebuffer(fb);
-
-       return drm_gem_handle_create(file_priv, virtio_gpu_fb->obj, handle);
-}
-
 static const struct drm_framebuffer_funcs virtio_gpu_fb_funcs = {
-       .create_handle = virtio_gpu_framebuffer_create_handle,
-       .destroy = virtio_gpu_user_framebuffer_destroy,
+       .create_handle = drm_gem_fb_create_handle,
+       .destroy = drm_gem_fb_destroy,
        .dirty = virtio_gpu_framebuffer_surface_dirty,
 };
 
@@ -97,7 +77,7 @@ virtio_gpu_framebuffer_init(struct drm_device *dev,
        int ret;
        struct virtio_gpu_object *bo;
 
-       vgfb->obj = obj;
+       vgfb->base.obj[0] = obj;
 
        bo = gem_to_virtio_gpu_obj(obj);
 
@@ -105,7 +85,7 @@ virtio_gpu_framebuffer_init(struct drm_device *dev,
 
        ret = drm_framebuffer_init(dev, &vgfb->base, &virtio_gpu_fb_funcs);
        if (ret) {
-               vgfb->obj = NULL;
+               vgfb->base.obj[0] = NULL;
                return ret;
        }
 
@@ -302,8 +282,6 @@ static int vgdev_output_init(struct virtio_gpu_device *vgdev, int index)
        drm_crtc_init_with_planes(dev, crtc, primary, cursor,
                                  &virtio_gpu_crtc_funcs, NULL);
        drm_crtc_helper_add(crtc, &virtio_gpu_crtc_helper_funcs);
-       primary->crtc = crtc;
-       cursor->crtc = crtc;
 
        drm_connector_init(dev, connector, &virtio_gpu_connector_funcs,
                           DRM_MODE_CONNECTOR_VIRTUAL);
index d25c8ca224aa12c58fae5d58a7ac726685d1bacf..65605e207bbe88028c76a19fb2e4eb1e4d216401 100644 (file)
@@ -124,7 +124,6 @@ struct virtio_gpu_output {
 
 struct virtio_gpu_framebuffer {
        struct drm_framebuffer base;
-       struct drm_gem_object *obj;
        int x1, y1, x2, y2; /* dirty rect */
        spinlock_t dirty_lock;
        uint32_t hw_res_handle;
index 8af69ab58b89ffb27fe2ebb27fb2948c7d8b18f5..a121b1c79522fbf37dd79f51b0f2006bbfc517de 100644 (file)
@@ -46,7 +46,7 @@ static int virtio_gpu_dirty_update(struct virtio_gpu_framebuffer *fb,
        int bpp = fb->base.format->cpp[0];
        int x2, y2;
        unsigned long flags;
-       struct virtio_gpu_object *obj = gem_to_virtio_gpu_obj(fb->obj);
+       struct virtio_gpu_object *obj = gem_to_virtio_gpu_obj(fb->base.obj[0]);
 
        if ((width <= 0) ||
            (x + width > fb->base.width) ||
@@ -121,7 +121,7 @@ int virtio_gpu_surface_dirty(struct virtio_gpu_framebuffer *vgfb,
                             unsigned int num_clips)
 {
        struct virtio_gpu_device *vgdev = vgfb->base.dev->dev_private;
-       struct virtio_gpu_object *obj = gem_to_virtio_gpu_obj(vgfb->obj);
+       struct virtio_gpu_object *obj = gem_to_virtio_gpu_obj(vgfb->base.obj[0]);
        struct drm_clip_rect norect;
        struct drm_clip_rect *clips_ptr;
        int left, right, top, bottom;
@@ -305,8 +305,8 @@ static int virtio_gpu_fbdev_destroy(struct drm_device *dev,
 
        drm_fb_helper_unregister_fbi(&vgfbdev->helper);
 
-       if (vgfb->obj)
-               vgfb->obj = NULL;
+       if (vgfb->base.obj[0])
+               vgfb->base.obj[0] = NULL;
        drm_fb_helper_fini(&vgfbdev->helper);
        drm_framebuffer_cleanup(&vgfb->base);
 
index 71ba455af915b78298662ee5daf588bd554984b0..dc5b5b2b7aab3f470ed9c3035cc7edc62790d478 100644 (file)
@@ -154,7 +154,7 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
 
        if (plane->state->fb) {
                vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
-               bo = gem_to_virtio_gpu_obj(vgfb->obj);
+               bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]);
                handle = bo->hw_res_handle;
                if (bo->dumb) {
                        virtio_gpu_cmd_transfer_to_host_2d
@@ -208,7 +208,7 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane *plane,
 
        if (plane->state->fb) {
                vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
-               bo = gem_to_virtio_gpu_obj(vgfb->obj);
+               bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]);
                handle = bo->hw_res_handle;
        } else {
                handle = 0;
index 54e300365a5ccd04b2d5d6173fbb379bde860322..9b7e0aca5f8476597ca139d11f4daf2ae9736ba7 100644 (file)
@@ -439,38 +439,13 @@ static int vmw_fb_compute_depth(struct fb_var_screeninfo *var,
 static int vmwgfx_set_config_internal(struct drm_mode_set *set)
 {
        struct drm_crtc *crtc = set->crtc;
-       struct drm_framebuffer *fb;
-       struct drm_crtc *tmp;
-       struct drm_device *dev = set->crtc->dev;
        struct drm_modeset_acquire_ctx ctx;
        int ret;
 
        drm_modeset_acquire_init(&ctx, 0);
 
 restart:
-       /*
-        * NOTE: ->set_config can also disable other crtcs (if we steal all
-        * connectors from it), hence we need to refcount the fbs across all
-        * crtcs. Atomic modeset will have saner semantics ...
-        */
-       drm_for_each_crtc(tmp, dev)
-               tmp->primary->old_fb = tmp->primary->fb;
-
-       fb = set->fb;
-
        ret = crtc->funcs->set_config(set, &ctx);
-       if (ret == 0) {
-               crtc->primary->crtc = crtc;
-               crtc->primary->fb = fb;
-       }
-
-       drm_for_each_crtc(tmp, dev) {
-               if (tmp->primary->fb)
-                       drm_framebuffer_get(tmp->primary->fb);
-               if (tmp->primary->old_fb)
-                       drm_framebuffer_put(tmp->primary->old_fb);
-               tmp->primary->old_fb = NULL;
-       }
 
        if (ret == -EDEADLK) {
                drm_modeset_backoff(&ctx);
index 01f2dc9e6f52803a92b1ae7c38ef269c458eb732..ef96ba7432aded1b40956f66468d9ab3b9e65fbd 100644 (file)
@@ -1536,9 +1536,13 @@ vmw_kms_atomic_check_modeset(struct drm_device *dev,
                unsigned long requested_bb_mem = 0;
 
                if (dev_priv->active_display_unit == vmw_du_screen_target) {
-                       if (crtc->primary->fb) {
-                               int cpp = crtc->primary->fb->pitches[0] /
-                                         crtc->primary->fb->width;
+                       struct drm_plane *plane = crtc->primary;
+                       struct drm_plane_state *plane_state;
+
+                       plane_state = drm_atomic_get_new_plane_state(state, plane);
+
+                       if (plane_state && plane_state->fb) {
+                               int cpp = plane_state->fb->format->cpp[0];
 
                                requested_bb_mem += crtc->mode.hdisplay * cpp *
                                                    crtc->mode.vdisplay;
@@ -2322,9 +2326,10 @@ int vmw_kms_helper_dirty(struct vmw_private *dev_priv,
        } else {
                list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list,
                                    head) {
-                       if (crtc->primary->fb != &framebuffer->base)
-                               continue;
-                       units[num_units++] = vmw_crtc_to_du(crtc);
+                       struct drm_plane *plane = crtc->primary;
+
+                       if (plane->state->fb == &framebuffer->base)
+                               units[num_units++] = vmw_crtc_to_du(crtc);
                }
        }
 
@@ -2806,6 +2811,7 @@ void vmw_kms_update_implicit_fb(struct vmw_private *dev_priv,
                                struct drm_crtc *crtc)
 {
        struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
+       struct drm_plane *plane = crtc->primary;
        struct vmw_framebuffer *vfb;
 
        mutex_lock(&dev_priv->global_kms_state_mutex);
@@ -2813,7 +2819,7 @@ void vmw_kms_update_implicit_fb(struct vmw_private *dev_priv,
        if (!du->is_implicit)
                goto out_unlock;
 
-       vfb = vmw_framebuffer_to_vfb(crtc->primary->fb);
+       vfb = vmw_framebuffer_to_vfb(plane->state->fb);
        WARN_ON_ONCE(dev_priv->num_implicit != 1 &&
                     dev_priv->implicit_fb != vfb);
 
index 0d42a46521fc1cc5c8083722fe03239d64ae3d87..373bc6da2f843265c763328b453444d665a9acb7 100644 (file)
@@ -40,7 +40,6 @@
  */
 
 static int vmw_prime_map_attach(struct dma_buf *dma_buf,
-                               struct device *target_dev,
                                struct dma_buf_attachment *attach)
 {
        return -ENOSYS;
@@ -72,17 +71,6 @@ static void vmw_prime_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
 {
 }
 
-static void *vmw_prime_dmabuf_kmap_atomic(struct dma_buf *dma_buf,
-               unsigned long page_num)
-{
-       return NULL;
-}
-
-static void vmw_prime_dmabuf_kunmap_atomic(struct dma_buf *dma_buf,
-               unsigned long page_num, void *addr)
-{
-
-}
 static void *vmw_prime_dmabuf_kmap(struct dma_buf *dma_buf,
                unsigned long page_num)
 {
@@ -109,9 +97,7 @@ const struct dma_buf_ops vmw_prime_dmabuf_ops =  {
        .unmap_dma_buf = vmw_prime_unmap_dma_buf,
        .release = NULL,
        .map = vmw_prime_dmabuf_kmap,
-       .map_atomic = vmw_prime_dmabuf_kmap_atomic,
        .unmap = vmw_prime_dmabuf_kunmap,
-       .unmap_atomic = vmw_prime_dmabuf_kunmap_atomic,
        .mmap = vmw_prime_dmabuf_mmap,
        .vmap = vmw_prime_dmabuf_vmap,
        .vunmap = vmw_prime_dmabuf_vunmap,
index 3d667e903beb7bd76d13d8048a26a1763e835709..9798640cbfcd9b18ecd9c71a6248c961c1ed3eeb 100644 (file)
@@ -527,8 +527,6 @@ vmw_sou_primary_plane_atomic_update(struct drm_plane *plane,
                 */
                if (ret != 0)
                        DRM_ERROR("Failed to update screen.\n");
-
-               crtc->primary->fb = plane->state->fb;
        } else {
                /*
                 * When disabling a plane, CRTC and FB should always be NULL
index 67331f01ef32e72ea46f600ebce3479112eeb48e..152e96cb1c01ade533ec7a0f1a83039a0b2c05b6 100644 (file)
@@ -414,6 +414,7 @@ static void vmw_stdu_crtc_helper_prepare(struct drm_crtc *crtc)
 static void vmw_stdu_crtc_atomic_enable(struct drm_crtc *crtc,
                                        struct drm_crtc_state *old_state)
 {
+       struct drm_plane_state *plane_state = crtc->primary->state;
        struct vmw_private *dev_priv;
        struct vmw_screen_target_display_unit *stdu;
        struct vmw_framebuffer *vfb;
@@ -422,7 +423,7 @@ static void vmw_stdu_crtc_atomic_enable(struct drm_crtc *crtc,
 
        stdu     = vmw_crtc_to_stdu(crtc);
        dev_priv = vmw_priv(crtc->dev);
-       fb       = crtc->primary->fb;
+       fb       = plane_state->fb;
 
        vfb = (fb) ? vmw_framebuffer_to_vfb(fb) : NULL;
 
@@ -1285,8 +1286,6 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
                                                         1, 1, NULL, crtc);
                if (ret)
                        DRM_ERROR("Failed to update STDU.\n");
-
-               crtc->primary->fb = plane->state->fb;
        } else {
                crtc = old_state->crtc;
                stdu = vmw_crtc_to_stdu(crtc);
index b3786c1a4e80fdedb4bc1da0a4c046184d4ff250..6b6d5ab82ec3fadf4b46d4e3c3771f9c8d56e143 100644 (file)
@@ -623,7 +623,7 @@ static int displback_initwait(struct xen_drm_front_info *front_info)
        if (ret < 0)
                return ret;
 
-       DRM_INFO("Have %d conector(s)\n", cfg->num_connectors);
+       DRM_INFO("Have %d connector(s)\n", cfg->num_connectors);
        /* Create event channels for all connectors and publish */
        ret = xen_drm_front_evtchnl_create_all(front_info);
        if (ret < 0)
index 2c2479b571ae6baf56c7f736c8f587c51227da0f..5693b4a4b02b1a951d897f30bd60bf2e74a6297d 100644 (file)
@@ -126,12 +126,12 @@ struct xen_drm_front_drm_info {
 
 static inline u64 xen_drm_front_fb_to_cookie(struct drm_framebuffer *fb)
 {
-       return (u64)fb;
+       return (uintptr_t)fb;
 }
 
 static inline u64 xen_drm_front_dbuf_to_cookie(struct drm_gem_object *gem_obj)
 {
-       return (u64)gem_obj;
+       return (uintptr_t)gem_obj;
 }
 
 int xen_drm_front_mode_set(struct xen_drm_front_drm_pipeline *pipeline,
index 8099cb343ae3bef389a2718c1fc34f50c737c73f..d333b67cc1a06b4cbfe838ddf3ab4245c1de3ae1 100644 (file)
@@ -122,7 +122,7 @@ static void guest_calc_num_grefs(struct xen_drm_front_shbuf *buf)
 }
 
 #define xen_page_to_vaddr(page) \
-               ((phys_addr_t)pfn_to_kaddr(page_to_xen_pfn(page)))
+               ((uintptr_t)pfn_to_kaddr(page_to_xen_pfn(page)))
 
 static int backend_unmap(struct xen_drm_front_shbuf *buf)
 {
index f1178f6f434d0f76d419845d8789d87095ed355a..aff0ab7bf83d565e81507e48f9ae793586d2f3fd 100644 (file)
@@ -222,7 +222,7 @@ struct vb2_dc_attachment {
        enum dma_data_direction dma_dir;
 };
 
-static int vb2_dc_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
+static int vb2_dc_dmabuf_ops_attach(struct dma_buf *dbuf,
        struct dma_buf_attachment *dbuf_attach)
 {
        struct vb2_dc_attachment *attach;
@@ -358,7 +358,6 @@ static const struct dma_buf_ops vb2_dc_dmabuf_ops = {
        .map_dma_buf = vb2_dc_dmabuf_ops_map,
        .unmap_dma_buf = vb2_dc_dmabuf_ops_unmap,
        .map = vb2_dc_dmabuf_ops_kmap,
-       .map_atomic = vb2_dc_dmabuf_ops_kmap,
        .vmap = vb2_dc_dmabuf_ops_vmap,
        .mmap = vb2_dc_dmabuf_ops_mmap,
        .release = vb2_dc_dmabuf_ops_release,
index 753ed3138dcc8bd77bacda888fa09ed849e09f69..015e737095cdd6644b4e0332120aa3ee993eb1d0 100644 (file)
@@ -371,7 +371,7 @@ struct vb2_dma_sg_attachment {
        enum dma_data_direction dma_dir;
 };
 
-static int vb2_dma_sg_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
+static int vb2_dma_sg_dmabuf_ops_attach(struct dma_buf *dbuf,
        struct dma_buf_attachment *dbuf_attach)
 {
        struct vb2_dma_sg_attachment *attach;
@@ -507,7 +507,6 @@ static const struct dma_buf_ops vb2_dma_sg_dmabuf_ops = {
        .map_dma_buf = vb2_dma_sg_dmabuf_ops_map,
        .unmap_dma_buf = vb2_dma_sg_dmabuf_ops_unmap,
        .map = vb2_dma_sg_dmabuf_ops_kmap,
-       .map_atomic = vb2_dma_sg_dmabuf_ops_kmap,
        .vmap = vb2_dma_sg_dmabuf_ops_vmap,
        .mmap = vb2_dma_sg_dmabuf_ops_mmap,
        .release = vb2_dma_sg_dmabuf_ops_release,
index 359fb9804d160426ab037133e2102b979833ecff..6dfbd5b0590759e0c712094dffb96518900efa1a 100644 (file)
@@ -209,7 +209,7 @@ struct vb2_vmalloc_attachment {
        enum dma_data_direction dma_dir;
 };
 
-static int vb2_vmalloc_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
+static int vb2_vmalloc_dmabuf_ops_attach(struct dma_buf *dbuf,
        struct dma_buf_attachment *dbuf_attach)
 {
        struct vb2_vmalloc_attachment *attach;
@@ -346,7 +346,6 @@ static const struct dma_buf_ops vb2_vmalloc_dmabuf_ops = {
        .map_dma_buf = vb2_vmalloc_dmabuf_ops_map,
        .unmap_dma_buf = vb2_vmalloc_dmabuf_ops_unmap,
        .map = vb2_vmalloc_dmabuf_ops_kmap,
-       .map_atomic = vb2_vmalloc_dmabuf_ops_kmap,
        .vmap = vb2_vmalloc_dmabuf_ops_vmap,
        .mmap = vb2_vmalloc_dmabuf_ops_mmap,
        .release = vb2_vmalloc_dmabuf_ops_release,
index 9d1109e43ed442e5614568c312ee31e01ca0dd17..99073325b0c00ca8784cbd1ed7849d4cdb09ec8e 100644 (file)
@@ -201,7 +201,7 @@ struct ion_dma_buf_attachment {
        struct list_head list;
 };
 
-static int ion_dma_buf_attach(struct dma_buf *dmabuf, struct device *dev,
+static int ion_dma_buf_attach(struct dma_buf *dmabuf,
                              struct dma_buf_attachment *attachment)
 {
        struct ion_dma_buf_attachment *a;
@@ -219,7 +219,7 @@ static int ion_dma_buf_attach(struct dma_buf *dmabuf, struct device *dev,
        }
 
        a->table = table;
-       a->dev = dev;
+       a->dev = attachment->dev;
        INIT_LIST_HEAD(&a->list);
 
        attachment->priv = a;
@@ -375,8 +375,6 @@ static const struct dma_buf_ops dma_buf_ops = {
        .detach = ion_dma_buf_detatch,
        .begin_cpu_access = ion_dma_buf_begin_cpu_access,
        .end_cpu_access = ion_dma_buf_end_cpu_access,
-       .map_atomic = ion_dma_buf_kmap,
-       .unmap_atomic = ion_dma_buf_kunmap,
        .map = ion_dma_buf_kmap,
        .unmap = ion_dma_buf_kunmap,
 };
index 07d3be6f0780db209ac2be07354ac390c31d6be8..0b9ab1d0dd45dd69046f921e6bf846e7af23fe88 100644 (file)
@@ -80,11 +80,6 @@ static void tee_shm_op_release(struct dma_buf *dmabuf)
        tee_shm_release(shm);
 }
 
-static void *tee_shm_op_map_atomic(struct dma_buf *dmabuf, unsigned long pgnum)
-{
-       return NULL;
-}
-
 static void *tee_shm_op_map(struct dma_buf *dmabuf, unsigned long pgnum)
 {
        return NULL;
@@ -107,7 +102,6 @@ static const struct dma_buf_ops tee_shm_dma_buf_ops = {
        .map_dma_buf = tee_shm_op_map_dma_buf,
        .unmap_dma_buf = tee_shm_op_unmap_dma_buf,
        .release = tee_shm_op_release,
-       .map_atomic = tee_shm_op_map_atomic,
        .map = tee_shm_op_map,
        .mmap = tee_shm_op_mmap,
 };
index a57a8aa90ffb794146ffd46c4a71543da0545596..da9d95a1958096be400a3c4b9a4f5f1977d394e9 100644 (file)
@@ -160,6 +160,14 @@ struct __drm_crtcs_state {
 struct __drm_connnectors_state {
        struct drm_connector *ptr;
        struct drm_connector_state *state, *old_state, *new_state;
+       /**
+        * @out_fence_ptr:
+        *
+        * User-provided pointer which the kernel uses to return a sync_file
+        * file descriptor. Used by writeback connectors to signal completion of
+        * the writeback.
+        */
+       s32 __user *out_fence_ptr;
 };
 
 struct drm_private_obj;
@@ -594,6 +602,9 @@ void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
 int __must_check
 drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
                                  struct drm_crtc *crtc);
+int drm_atomic_set_writeback_fb_for_connector(
+               struct drm_connector_state *conn_state,
+               struct drm_framebuffer *fb);
 int __must_check
 drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
                                   struct drm_crtc *crtc);
@@ -601,9 +612,6 @@ int __must_check
 drm_atomic_add_affected_planes(struct drm_atomic_state *state,
                               struct drm_crtc *crtc);
 
-void
-drm_atomic_clean_old_fb(struct drm_device *dev, unsigned plane_mask, int ret);
-
 int __must_check drm_atomic_check_only(struct drm_atomic_state *state);
 int __must_check drm_atomic_commit(struct drm_atomic_state *state);
 int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state);
index 3270fec469798fc6cdb20c75e96c0be311b0d3e6..70131ab57e8f2bb3af291a6a0f9979377a18bfc7 100644 (file)
@@ -97,7 +97,7 @@ struct drm_bridge_funcs {
        /**
         * @mode_fixup:
         *
-        * This callback is used to validate and adjust a mode. The paramater
+        * This callback is used to validate and adjust a mode. The parameter
         * mode is the display mode that should be fed to the next element in
         * the display chain, either the final &drm_connector or the next
         * &drm_bridge. The parameter adjusted_mode is the input mode the bridge
@@ -178,6 +178,22 @@ struct drm_bridge_funcs {
         * then this would be &drm_encoder_helper_funcs.mode_set. The display
         * pipe (i.e.  clocks and timing signals) is off when this function is
         * called.
+        *
+        * The adjusted_mode parameter is the mode output by the CRTC for the
+        * first bridge in the chain. It can be different from the mode
+        * parameter that contains the desired mode for the connector at the end
+        * of the bridges chain, for instance when the first bridge in the chain
+        * performs scaling. The adjusted mode is mostly useful for the first
+        * bridge in the chain and is likely irrelevant for the other bridges.
+        *
+        * For atomic drivers the adjusted_mode is the mode stored in
+        * &drm_crtc_state.adjusted_mode.
+        *
+        * NOTE:
+        *
+        * If a need arises to store and access modes adjusted for other
+        * locations than the connection between the CRTC and the first bridge,
+        * the DRM framework will have to be extended with DRM bridge states.
         */
        void (*mode_set)(struct drm_bridge *bridge,
                         struct drm_display_mode *mode,
@@ -285,15 +301,15 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
                      struct drm_bridge *previous);
 
 bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
-                       const struct drm_display_mode *mode,
-                       struct drm_display_mode *adjusted_mode);
+                          const struct drm_display_mode *mode,
+                          struct drm_display_mode *adjusted_mode);
 enum drm_mode_status drm_bridge_mode_valid(struct drm_bridge *bridge,
                                           const struct drm_display_mode *mode);
 void drm_bridge_disable(struct drm_bridge *bridge);
 void drm_bridge_post_disable(struct drm_bridge *bridge);
 void drm_bridge_mode_set(struct drm_bridge *bridge,
-                       struct drm_display_mode *mode,
-                       struct drm_display_mode *adjusted_mode);
+                        struct drm_display_mode *mode,
+                        struct drm_display_mode *adjusted_mode);
 void drm_bridge_pre_enable(struct drm_bridge *bridge);
 void drm_bridge_enable(struct drm_bridge *bridge);
 
index 675cc3f8cf85292ce19aadee37d32f1f143771d8..14ab58ade87f641448ae7fa213daa652a000bee8 100644 (file)
@@ -418,6 +418,14 @@ struct drm_connector_state {
         */
        enum hdmi_picture_aspect picture_aspect_ratio;
 
+       /**
+        * @content_type: Connector property to control the
+        * HDMI infoframe content type setting.
+        * The %DRM_MODE_CONTENT_TYPE_\* values much
+        * match the values.
+        */
+       unsigned int content_type;
+
        /**
         * @scaling_mode: Connector property to control the
         * upscaling, mostly used for built-in panels.
@@ -429,6 +437,19 @@ struct drm_connector_state {
         * protection. This is most commonly used for HDCP.
         */
        unsigned int content_protection;
+
+       /**
+        * @writeback_job: Writeback job for writeback connectors
+        *
+        * Holds the framebuffer and out-fence for a writeback connector. As
+        * the writeback completion may be asynchronous to the normal commit
+        * cycle, the writeback job lifetime is managed separately from the
+        * normal atomic state by this object.
+        *
+        * See also: drm_writeback_queue_job() and
+        * drm_writeback_signal_completion()
+        */
+       struct drm_writeback_job *writeback_job;
 };
 
 /**
@@ -608,6 +629,8 @@ struct drm_connector_funcs {
         * cleaned up by calling the @atomic_destroy_state hook in this
         * structure.
         *
+        * This callback is mandatory for atomic drivers.
+        *
         * Atomic drivers which don't subclass &struct drm_connector_state should use
         * drm_atomic_helper_connector_duplicate_state(). Drivers that subclass the
         * state structure to extend it with driver-private state should use
@@ -634,6 +657,8 @@ struct drm_connector_funcs {
         *
         * Destroy a state duplicated with @atomic_duplicate_state and release
         * or unreference all resources it references
+        *
+        * This callback is mandatory for atomic drivers.
         */
        void (*atomic_destroy_state)(struct drm_connector *connector,
                                     struct drm_connector_state *state);
@@ -1089,11 +1114,16 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
                                  unsigned int num_modes,
                                  const char * const modes[]);
 int drm_mode_create_scaling_mode_property(struct drm_device *dev);
+int drm_connector_attach_content_type_property(struct drm_connector *dev);
 int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
                                               u32 scaling_mode_mask);
 int drm_connector_attach_content_protection_property(
                struct drm_connector *connector);
 int drm_mode_create_aspect_ratio_property(struct drm_device *dev);
+int drm_mode_create_content_type_property(struct drm_device *dev);
+void drm_hdmi_avi_infoframe_content_type(struct hdmi_avi_infoframe *frame,
+                                        const struct drm_connector_state *conn_state);
+
 int drm_mode_create_suggested_offset_properties(struct drm_device *dev);
 
 int drm_mode_connector_set_path_property(struct drm_connector *connector,
index a2d81d2907a9377716a8834f89aedb238cc607e2..23eddbccab10fe0847249d115d8ce306453efde0 100644 (file)
@@ -134,10 +134,13 @@ struct drm_crtc_state {
         *
         * Internal display timings which can be used by the driver to handle
         * differences between the mode requested by userspace in @mode and what
-        * is actually programmed into the hardware. It is purely driver
-        * implementation defined what exactly this adjusted mode means. Usually
-        * it is used to store the hardware display timings used between the
-        * CRTC and encoder blocks.
+        * is actually programmed into the hardware.
+        *
+        * For drivers using drm_bridge, this stores hardware display timings
+        * used between the CRTC and the first bridge. For other drivers, the
+        * meaning of the adjusted_mode field is purely driver implementation
+        * defined information, and will usually be used to store the hardware
+        * display timings used between the CRTC and encoder blocks.
         */
        struct drm_display_mode adjusted_mode;
 
@@ -503,6 +506,8 @@ struct drm_crtc_funcs {
         * cleaned up by calling the @atomic_destroy_state hook in this
         * structure.
         *
+        * This callback is mandatory for atomic drivers.
+        *
         * Atomic drivers which don't subclass &struct drm_crtc_state should use
         * drm_atomic_helper_crtc_duplicate_state(). Drivers that subclass the
         * state structure to extend it with driver-private state should use
@@ -529,6 +534,8 @@ struct drm_crtc_funcs {
         *
         * Destroy a state duplicated with @atomic_duplicate_state and release
         * or unreference all resources it references
+        *
+        * This callback is mandatory for atomic drivers.
         */
        void (*atomic_destroy_state)(struct drm_crtc *crtc,
                                     struct drm_crtc_state *state);
index 027ac16da3d15fb99655ad3724562ae8cf222190..26485acc51d7944697ce96f0988c2803f4d8c581 100644 (file)
@@ -192,6 +192,13 @@ struct drm_file {
         */
        unsigned aspect_ratio_allowed:1;
 
+       /**
+        * @writeback_connectors:
+        *
+        * True if client understands writeback connectors
+        */
+       unsigned writeback_connectors:1;
+
        /**
         * @is_master:
         *
index 101f566ae43d01e8d013573501165428aaec92a3..2c3bbb43c7d1a55600c688e08b3abb1a2cdacc83 100644 (file)
@@ -109,6 +109,38 @@ enum drm_mm_insert_mode {
         * Allocates the node from the bottom of the found hole.
         */
        DRM_MM_INSERT_EVICT,
+
+       /**
+        * @DRM_MM_INSERT_ONCE:
+        *
+        * Only check the first hole for suitablity and report -ENOSPC
+        * immediately otherwise, rather than check every hole until a
+        * suitable one is found. Can only be used in conjunction with another
+        * search method such as DRM_MM_INSERT_HIGH or DRM_MM_INSERT_LOW.
+        */
+       DRM_MM_INSERT_ONCE = BIT(31),
+
+       /**
+        * @DRM_MM_INSERT_HIGHEST:
+        *
+        * Only check the highest hole (the hole with the largest address) and
+        * insert the node at the top of the hole or report -ENOSPC if
+        * unsuitable.
+        *
+        * Does not search all holes.
+        */
+       DRM_MM_INSERT_HIGHEST = DRM_MM_INSERT_HIGH | DRM_MM_INSERT_ONCE,
+
+       /**
+        * @DRM_MM_INSERT_LOWEST:
+        *
+        * Only check the lowest hole (the hole with the smallest address) and
+        * insert the node at the bottom of the hole or report -ENOSPC if
+        * unsuitable.
+        *
+        * Does not search all holes.
+        */
+       DRM_MM_INSERT_LOWEST  = DRM_MM_INSERT_LOW | DRM_MM_INSERT_ONCE,
 };
 
 /**
@@ -173,7 +205,7 @@ struct drm_mm {
        struct drm_mm_node head_node;
        /* Keep an interval_tree for fast lookup of drm_mm_nodes by address. */
        struct rb_root_cached interval_tree;
-       struct rb_root holes_size;
+       struct rb_root_cached holes_size;
        struct rb_root holes_addr;
 
        unsigned long scan_active;
index 33b3a96d66d0a4de3dcb0910edb75fa310eb7a4d..f4a173c8d79cac469f740d4c3f14bea39a02e7bf 100644 (file)
@@ -726,6 +726,11 @@ struct drm_mode_config {
         * HDMI infoframe aspect ratio setting.
         */
        struct drm_property *aspect_ratio_property;
+       /**
+        * @content_type_property: Optional connector property to control the
+        * HDMI infoframe content type setting.
+        */
+       struct drm_property *content_type_property;
        /**
         * @degamma_lut_property: Optional CRTC property to set the LUT used to
         * convert the framebuffer's colors to linear gamma.
@@ -779,6 +784,29 @@ struct drm_mode_config {
         */
        struct drm_property *panel_orientation_property;
 
+       /**
+        * @writeback_fb_id_property: Property for writeback connectors, storing
+        * the ID of the output framebuffer.
+        * See also: drm_writeback_connector_init()
+        */
+       struct drm_property *writeback_fb_id_property;
+
+       /**
+        * @writeback_pixel_formats_property: Property for writeback connectors,
+        * storing an array of the supported pixel formats for the writeback
+        * engine (read-only).
+        * See also: drm_writeback_connector_init()
+        */
+       struct drm_property *writeback_pixel_formats_property;
+       /**
+        * @writeback_out_fence_ptr_property: Property for writeback connectors,
+        * fd pointer representing the outgoing fences for a writeback
+        * connector. Userspace should provide a pointer to a value of type s32,
+        * and then cast that pointer to u64.
+        * See also: drm_writeback_connector_init()
+        */
+       struct drm_property *writeback_out_fence_ptr_property;
+
        /* dumb ioctl parameters */
        uint32_t preferred_depth, prefer_shadow;
 
index 35e2a3a79fc56843daa986ec6dc558176b63a2d9..3b289773297c29f04f33808beb7e020bbcd91c1d 100644 (file)
@@ -974,6 +974,17 @@ struct drm_connector_helper_funcs {
         */
        int (*atomic_check)(struct drm_connector *connector,
                            struct drm_connector_state *state);
+
+       /**
+        * @atomic_commit:
+        *
+        * This hook is to be used by drivers implementing writeback connectors
+        * that need a point when to commit the writeback job to the hardware.
+        *
+        * This callback is used by the atomic modeset helpers.
+        */
+       void (*atomic_commit)(struct drm_connector *connector,
+                             struct drm_writeback_job *writeback_job);
 };
 
 /**
index 14ac240a1f646d6253c0a076ecaaa9b8a1a567c3..26a1b5fd8796cb7b4e495ca09b60e49bc06733bc 100644 (file)
@@ -89,6 +89,7 @@ struct drm_panel {
        struct drm_device *drm;
        struct drm_connector *connector;
        struct device *dev;
+       struct device_link *link;
 
        const struct drm_panel_funcs *funcs;
 
index 26fa50c2a50e8cf88c7e5ad6e344ac0ba19de18c..7d4d6c7f0afdb0f3764c9fa6f7644398a3e1bb40 100644 (file)
@@ -288,6 +288,8 @@ struct drm_plane_funcs {
         * cleaned up by calling the @atomic_destroy_state hook in this
         * structure.
         *
+        * This callback is mandatory for atomic drivers.
+        *
         * Atomic drivers which don't subclass &struct drm_plane_state should use
         * drm_atomic_helper_plane_duplicate_state(). Drivers that subclass the
         * state structure to extend it with driver-private state should use
@@ -314,6 +316,8 @@ struct drm_plane_funcs {
         *
         * Destroy a state duplicated with @atomic_duplicate_state and release
         * or unreference all resources it references
+        *
+        * This callback is mandatory for atomic drivers.
         */
        void (*atomic_destroy_state)(struct drm_plane *plane,
                                     struct drm_plane_state *state);
@@ -431,7 +435,10 @@ struct drm_plane_funcs {
         * This optional hook is used for the DRM to determine if the given
         * format/modifier combination is valid for the plane. This allows the
         * DRM to generate the correct format bitmask (which formats apply to
-        * which modifier).
+        * which modifier), and to valdiate modifiers at atomic_check time.
+        *
+        * If not present, then any modifier in the plane's modifier
+        * list is allowed with any of the plane's formats.
         *
         * Returns:
         *
index 4d5f5d6cf6a686d73264baa1e2806c9c71097cb6..d716d653b096465805e0e5c2f26c3bd0e388a708 100644 (file)
@@ -82,7 +82,7 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev,
 struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
                                      struct dma_buf_export_info *exp_info);
 void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
-int drm_gem_map_attach(struct dma_buf *dma_buf, struct device *target_dev,
+int drm_gem_map_attach(struct dma_buf *dma_buf,
                       struct dma_buf_attachment *attach);
 void drm_gem_map_detach(struct dma_buf *dma_buf,
                        struct dma_buf_attachment *attach);
@@ -93,10 +93,6 @@ void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
                           enum dma_data_direction dir);
 void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf);
 void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr);
-void *drm_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf,
-                                unsigned long page_num);
-void drm_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf,
-                                 unsigned long page_num, void *addr);
 void *drm_gem_dmabuf_kmap(struct dma_buf *dma_buf, unsigned long page_num);
 void drm_gem_dmabuf_kunmap(struct dma_buf *dma_buf, unsigned long page_num,
                           void *addr);
diff --git a/include/drm/drm_writeback.h b/include/drm/drm_writeback.h
new file mode 100644 (file)
index 0000000..a10fe55
--- /dev/null
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
+ * Author: Brian Starkey <brian.starkey@arm.com>
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ */
+
+#ifndef __DRM_WRITEBACK_H__
+#define __DRM_WRITEBACK_H__
+#include <drm/drm_connector.h>
+#include <drm/drm_encoder.h>
+#include <linux/workqueue.h>
+
+struct drm_writeback_connector {
+       struct drm_connector base;
+
+       /**
+        * @encoder: Internal encoder used by the connector to fulfill
+        * the DRM framework requirements. The users of the
+        * @drm_writeback_connector control the behaviour of the @encoder
+        * by passing the @enc_funcs parameter to drm_writeback_connector_init()
+        * function.
+        */
+       struct drm_encoder encoder;
+
+       /**
+        * @pixel_formats_blob_ptr:
+        *
+        * DRM blob property data for the pixel formats list on writeback
+        * connectors
+        * See also drm_writeback_connector_init()
+        */
+       struct drm_property_blob *pixel_formats_blob_ptr;
+
+       /** @job_lock: Protects job_queue */
+       spinlock_t job_lock;
+
+       /**
+        * @job_queue:
+        *
+        * Holds a list of a connector's writeback jobs; the last item is the
+        * most recent. The first item may be either waiting for the hardware
+        * to begin writing, or currently being written.
+        *
+        * See also: drm_writeback_queue_job() and
+        * drm_writeback_signal_completion()
+        */
+       struct list_head job_queue;
+
+       /**
+        * @fence_context:
+        *
+        * timeline context used for fence operations.
+        */
+       unsigned int fence_context;
+       /**
+        * @fence_lock:
+        *
+        * spinlock to protect the fences in the fence_context.
+        */
+       spinlock_t fence_lock;
+       /**
+        * @fence_seqno:
+        *
+        * Seqno variable used as monotonic counter for the fences
+        * created on the connector's timeline.
+        */
+       unsigned long fence_seqno;
+       /**
+        * @timeline_name:
+        *
+        * The name of the connector's fence timeline.
+        */
+       char timeline_name[32];
+};
+
+struct drm_writeback_job {
+       /**
+        * @cleanup_work:
+        *
+        * Used to allow drm_writeback_signal_completion to defer dropping the
+        * framebuffer reference to a workqueue
+        */
+       struct work_struct cleanup_work;
+
+       /**
+        * @list_entry:
+        *
+        * List item for the writeback connector's @job_queue
+        */
+       struct list_head list_entry;
+
+       /**
+        * @fb:
+        *
+        * Framebuffer to be written to by the writeback connector. Do not set
+        * directly, use drm_atomic_set_writeback_fb_for_connector()
+        */
+       struct drm_framebuffer *fb;
+
+       /**
+        * @out_fence:
+        *
+        * Fence which will signal once the writeback has completed
+        */
+       struct dma_fence *out_fence;
+};
+
+int drm_writeback_connector_init(struct drm_device *dev,
+                                struct drm_writeback_connector *wb_connector,
+                                const struct drm_connector_funcs *con_funcs,
+                                const struct drm_encoder_helper_funcs *enc_helper_funcs,
+                                const u32 *formats, int n_formats);
+
+void drm_writeback_queue_job(struct drm_writeback_connector *wb_connector,
+                            struct drm_writeback_job *job);
+
+void drm_writeback_cleanup_job(struct drm_writeback_job *job);
+
+void
+drm_writeback_signal_completion(struct drm_writeback_connector *wb_connector,
+                               int status);
+
+struct dma_fence *
+drm_writeback_get_out_fence(struct drm_writeback_connector *wb_connector);
+#endif
index 085db2fee2d71b603bee462dc29c7cccb4010866..58725f890b5b6185cda07d48591d9f1162f78c3d 100644 (file)
@@ -39,12 +39,12 @@ struct dma_buf_attachment;
 
 /**
  * struct dma_buf_ops - operations possible on struct dma_buf
- * @map_atomic: maps a page from the buffer into kernel address
+ * @map_atomic: [optional] maps a page from the buffer into kernel address
  *             space, users may not block until the subsequent unmap call.
  *             This callback must not sleep.
  * @unmap_atomic: [optional] unmaps a atomically mapped page from the buffer.
  *               This Callback must not sleep.
- * @map: maps a page from the buffer into kernel address space.
+ * @map: [optional] maps a page from the buffer into kernel address space.
  * @unmap: [optional] unmaps a page from the buffer.
  * @vmap: [optional] creates a virtual mapping for the buffer into kernel
  *       address space. Same restrictions as for vmap and friends apply.
@@ -55,11 +55,11 @@ struct dma_buf_ops {
         * @attach:
         *
         * This is called from dma_buf_attach() to make sure that a given
-        * &device can access the provided &dma_buf. Exporters which support
-        * buffer objects in special locations like VRAM or device-specific
-        * carveout areas should check whether the buffer could be move to
-        * system memory (or directly accessed by the provided device), and
-        * otherwise need to fail the attach operation.
+        * &dma_buf_attachment.dev can access the provided &dma_buf. Exporters
+        * which support buffer objects in special locations like VRAM or
+        * device-specific carveout areas should check whether the buffer could
+        * be move to system memory (or directly accessed by the provided
+        * device), and otherwise need to fail the attach operation.
         *
         * The exporter should also in general check whether the current
         * allocation fullfills the DMA constraints of the new device. If this
@@ -77,8 +77,7 @@ struct dma_buf_ops {
         * to signal that backing storage is already allocated and incompatible
         * with the requirements of requesting device.
         */
-       int (*attach)(struct dma_buf *, struct device *,
-                     struct dma_buf_attachment *);
+       int (*attach)(struct dma_buf *, struct dma_buf_attachment *);
 
        /**
         * @detach:
@@ -206,8 +205,6 @@ struct dma_buf_ops {
         * to be restarted.
         */
        int (*end_cpu_access)(struct dma_buf *, enum dma_data_direction);
-       void *(*map_atomic)(struct dma_buf *, unsigned long);
-       void (*unmap_atomic)(struct dma_buf *, unsigned long, void *);
        void *(*map)(struct dma_buf *, unsigned long);
        void (*unmap)(struct dma_buf *, unsigned long, void *);
 
@@ -395,8 +392,6 @@ int dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
                             enum dma_data_direction dir);
 int dma_buf_end_cpu_access(struct dma_buf *dma_buf,
                           enum dma_data_direction dir);
-void *dma_buf_kmap_atomic(struct dma_buf *, unsigned long);
-void dma_buf_kunmap_atomic(struct dma_buf *, unsigned long, void *);
 void *dma_buf_kmap(struct dma_buf *, unsigned long);
 void dma_buf_kunmap(struct dma_buf *, unsigned long, void *);
 
index 9c660e1688abe1cd6bf0e22bf709515e8a463e0d..300f336633f28ea20493570f80a73e30d87cd087 100644 (file)
@@ -687,6 +687,15 @@ struct drm_get_cap {
  */
 #define DRM_CLIENT_CAP_ASPECT_RATIO    4
 
+/**
+ * DRM_CLIENT_CAP_WRITEBACK_CONNECTORS
+ *
+ * If set to 1, the DRM core will expose special connectors to be used for
+ * writing back to memory the scene setup in the commit. Depends on client
+ * also supporting DRM_CLIENT_CAP_ATOMIC
+ */
+#define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS    5
+
 /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
 struct drm_set_client_cap {
        __u64 capability;
index e04613d30a134f696f9fa52dc439b57a87ac8f8c..64bf67abff7e3fddd5ae7f558def0fbae40fb755 100644 (file)
@@ -384,6 +384,23 @@ extern "C" {
 #define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB \
        fourcc_mod_code(NVIDIA, 0x15)
 
+/*
+ * Some Broadcom modifiers take parameters, for example the number of
+ * vertical lines in the image. Reserve the lower 32 bits for modifier
+ * type, and the next 24 bits for parameters. Top 8 bits are the
+ * vendor code.
+ */
+#define __fourcc_mod_broadcom_param_shift 8
+#define __fourcc_mod_broadcom_param_bits 48
+#define fourcc_mod_broadcom_code(val, params) \
+       fourcc_mod_code(BROADCOM, ((((__u64)params) << __fourcc_mod_broadcom_param_shift) | val))
+#define fourcc_mod_broadcom_param(m) \
+       ((int)(((m) >> __fourcc_mod_broadcom_param_shift) &     \
+              ((1ULL << __fourcc_mod_broadcom_param_bits) - 1)))
+#define fourcc_mod_broadcom_mod(m) \
+       ((m) & ~(((1ULL << __fourcc_mod_broadcom_param_bits) - 1) <<    \
+                __fourcc_mod_broadcom_param_shift))
+
 /*
  * Broadcom VC4 "T" format
  *
@@ -405,6 +422,48 @@ extern "C" {
  */
 #define DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED fourcc_mod_code(BROADCOM, 1)
 
+/*
+ * Broadcom SAND format
+ *
+ * This is the native format that the H.264 codec block uses.  For VC4
+ * HVS, it is only valid for H.264 (NV12/21) and RGBA modes.
+ *
+ * The image can be considered to be split into columns, and the
+ * columns are placed consecutively into memory.  The width of those
+ * columns can be either 32, 64, 128, or 256 pixels, but in practice
+ * only 128 pixel columns are used.
+ *
+ * The pitch between the start of each column is set to optimally
+ * switch between SDRAM banks. This is passed as the number of lines
+ * of column width in the modifier (we can't use the stride value due
+ * to various core checks that look at it , so you should set the
+ * stride to width*cpp).
+ *
+ * Note that the column height for this format modifier is the same
+ * for all of the planes, assuming that each column contains both Y
+ * and UV.  Some SAND-using hardware stores UV in a separate tiled
+ * image from Y to reduce the column height, which is not supported
+ * with these modifiers.
+ */
+
+#define DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(v) \
+       fourcc_mod_broadcom_code(2, v)
+#define DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(v) \
+       fourcc_mod_broadcom_code(3, v)
+#define DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(v) \
+       fourcc_mod_broadcom_code(4, v)
+#define DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(v) \
+       fourcc_mod_broadcom_code(5, v)
+
+#define DRM_FORMAT_MOD_BROADCOM_SAND32 \
+       DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(0)
+#define DRM_FORMAT_MOD_BROADCOM_SAND64 \
+       DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(0)
+#define DRM_FORMAT_MOD_BROADCOM_SAND128 \
+       DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(0)
+#define DRM_FORMAT_MOD_BROADCOM_SAND256 \
+       DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(0)
+
 #if defined(__cplusplus)
 }
 #endif
index 4b3a1bb58e68053bd880aa373fe5385730baaade..8d67243952f4f104f8b2ca745b4d94aa2565cbcc 100644 (file)
@@ -96,6 +96,13 @@ extern "C" {
 #define DRM_MODE_PICTURE_ASPECT_64_27          3
 #define DRM_MODE_PICTURE_ASPECT_256_135                4
 
+/* Content type options */
+#define DRM_MODE_CONTENT_TYPE_NO_DATA          0
+#define DRM_MODE_CONTENT_TYPE_GRAPHICS         1
+#define DRM_MODE_CONTENT_TYPE_PHOTO            2
+#define DRM_MODE_CONTENT_TYPE_CINEMA           3
+#define DRM_MODE_CONTENT_TYPE_GAME             4
+
 /* Aspect ratio flag bitmask (4 bits 22:19) */
 #define DRM_MODE_FLAG_PIC_AR_MASK              (0x0F<<19)
 #define  DRM_MODE_FLAG_PIC_AR_NONE \
@@ -344,6 +351,7 @@ enum drm_mode_subconnector {
 #define DRM_MODE_CONNECTOR_VIRTUAL      15
 #define DRM_MODE_CONNECTOR_DSI         16
 #define DRM_MODE_CONNECTOR_DPI         17
+#define DRM_MODE_CONNECTOR_WRITEBACK   18
 
 struct drm_mode_get_connector {