Merge tag 'drm-misc-next-2017-11-30' of git://anongit.freedesktop.org/drm/drm-misc...
authorDave Airlie <airlied@redhat.com>
Sun, 3 Dec 2017 19:38:52 +0000 (05:38 +1000)
committerDave Airlie <airlied@redhat.com>
Sun, 3 Dec 2017 19:42:49 +0000 (05:42 +1000)
Cross-subsystem Changes:

- device tree doc for the Mitsubishi AA070MC01 and Tianma TM070RVHG71
panels (Lukasz Majewski) and for a 2nd endpoint on stm32 (Philippe Cornu)

Core Changes:

The most important changes are:

- Add drm_driver .last_close and .output_poll_changed helpers to reduce
fbdev emulation footprint in drivers (Noralf)
- Fix plane clipping in core and for vmwgfx (Ville)

Then we have a bunch of of improvement for print and debug such as the
addition of a framebuffer debugfs file. ELD connector, HDMI and
improvements.  And a bunch of misc improvements, clean ups and style
changes and doc updates

[airlied: drop eld bits from amdgpu_dm]

Driver Changes:

- sii8620: filter unsupported modes and add DVI mode support (Maciej Purski)
- rockchip: analogix_dp: Remove unnecessary init code (Jeffy Chen)
- virtio, cirrus: add fb create_handle support to enable screenshots(Lepton Wu)
- virtio: replace reference/unreference with get/put (Aastha Gupta)
- vc4, gma500: Convert timers to use timer_setup() (Kees Cook)
- vc4: Reject HDMI modes with too high of clocks (Eric)
- vc4: Add support for more pixel formats (Dave Stevenson)
- stm: dsi: Rename driver name to "stm32-display-dsi" (Philippe Cornu)
- stm: ltdc: add a 2nd endpoint (Philippe Cornu)
- via: use monotonic time for VIA_WAIT_IRQ (Arnd Bergmann)

* tag 'drm-misc-next-2017-11-30' of git://anongit.freedesktop.org/drm/drm-misc: (96 commits)
  drm/bridge: tc358767: add copyright lines
  MAINTAINERS: change maintainer for Rockchip drm drivers
  drm/vblank: Fix vblank timestamp debugs
  drm/via: use monotonic time for VIA_WAIT_IRQ
  dma-buf: Fix ifnullfree.cocci warnings
  drm/printer: Add drm_vprintf()
  drm/edid: Allow HDMI infoframe without VIC or S3D
  video/hdmi: Allow "empty" HDMI infoframes
  dma-buf/fence: Fix lock inversion within dma-fence-array
  drm/sti: Handle return value of platform_get_irq_byname
  drm/vc4: Add support for NV21 and NV61.
  drm/vc4: Use .pixel_order instead of custom .flip_cbcr
  drm/vc4: Add support for DRM_FORMAT_RGB888 and DRM_FORMAT_BGR888
  drm: Move drm_plane_helper_check_state() into drm_atomic_helper.c
  drm: Check crtc_state->enable rather than crtc->enabled in drm_plane_helper_check_state()
  drm/vmwgfx: Try to fix plane clipping
  drm/vmwgfx: Use drm_plane_helper_check_state()
  drm/vmwgfx: Remove bogus crtc coords vs fb size check
  gpu: gma500: remove unneeded DRIVER_LICENSE #define
  drm: don't link DP aux i2c adapter to the hardware device node
  ...

113 files changed:
Documentation/devicetree/bindings/display/panel/mitsubishi,aa070mc01.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/tianma,tm070rvhg71.txt [new file with mode: 0644]
Documentation/devicetree/bindings/display/rockchip/rockchip-vop.txt
Documentation/devicetree/bindings/display/st,stm32-ltdc.txt
Documentation/gpu/todo.rst
MAINTAINERS
drivers/base/Kconfig
drivers/dma-buf/dma-buf.c
drivers/dma-buf/dma-fence-array.c
drivers/dma-buf/reservation.c
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/arc/arcpgu_drv.c
drivers/gpu/drm/arm/hdlcd_crtc.c
drivers/gpu/drm/arm/hdlcd_drv.c
drivers/gpu/drm/arm/malidp_planes.c
drivers/gpu/drm/bridge/analogix-anx78xx.c
drivers/gpu/drm/bridge/sil-sii8620.c
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
drivers/gpu/drm/bridge/tc358767.c
drivers/gpu/drm/cirrus/cirrus_main.c
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_debugfs.c
drivers/gpu/drm/drm_dp_helper.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_fb_cma_helper.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_framebuffer.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_gem_cma_helper.c
drivers/gpu/drm/drm_internal.h
drivers/gpu/drm/drm_mm.c
drivers/gpu/drm/drm_plane_helper.c
drivers/gpu/drm/drm_print.c
drivers/gpu/drm/drm_simple_kms_helper.c
drivers/gpu/drm/drm_syncobj.c
drivers/gpu/drm/drm_vblank.c
drivers/gpu/drm/drm_vma_manager.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/gma500/mmu.c
drivers/gpu/drm/gma500/psb_drv.c
drivers/gpu/drm/gma500/psb_drv.h
drivers/gpu/drm/i2c/tda998x_drv.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_modes.c
drivers/gpu/drm/imx/ipuv3-plane.c
drivers/gpu/drm/mediatek/mtk_drm_plane.c
drivers/gpu/drm/mediatek/mtk_hdmi.c
drivers/gpu/drm/meson/meson_plane.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
drivers/gpu/drm/panel/panel-simple.c
drivers/gpu/drm/qxl/qxl_ttm.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_dp_mst.c
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
drivers/gpu/drm/rockchip/cdn-dp-core.c
drivers/gpu/drm/rockchip/inno_hdmi.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/rockchip/rockchip_vop_reg.c
drivers/gpu/drm/rockchip/rockchip_vop_reg.h
drivers/gpu/drm/selftests/test-drm_mm.c
drivers/gpu/drm/sti/Kconfig
drivers/gpu/drm/sti/sti_hdmi.c
drivers/gpu/drm/sti/sti_vtg.c
drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
drivers/gpu/drm/stm/ltdc.c
drivers/gpu/drm/tegra/dc.c
drivers/gpu/drm/tegra/output.c
drivers/gpu/drm/tilcdc/tilcdc_drv.c
drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
drivers/gpu/drm/tinydrm/mipi-dbi.c
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/gpu/drm/vc4/vc4_plane.c
drivers/gpu/drm/via/via_drv.h
drivers/gpu/drm/via/via_irq.c
drivers/gpu/drm/virtio/virtgpu_display.c
drivers/gpu/drm/virtio/virtgpu_ioctl.c
drivers/gpu/drm/virtio/virtgpu_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/zte/zx_hdmi.c
drivers/gpu/drm/zte/zx_plane.c
drivers/video/hdmi.c
include/drm/drmP.h
include/drm/drm_atomic_helper.h
include/drm/drm_connector.h
include/drm/drm_device.h
include/drm/drm_dp_helper.h
include/drm/drm_drv.h
include/drm/drm_edid.h
include/drm/drm_encoder.h
include/drm/drm_fb_cma_helper.h
include/drm/drm_fb_helper.h
include/drm/drm_framebuffer.h
include/drm/drm_gem_cma_helper.h
include/drm/drm_mm.h
include/drm/drm_mode_config.h
include/drm/drm_modeset_helper_vtables.h
include/drm/drm_plane.h
include/drm/drm_plane_helper.h
include/drm/drm_print.h
include/drm/drm_syncobj.h
include/drm/drm_vma_manager.h
include/drm/tinydrm/tinydrm.h
include/linux/dma-fence-array.h
include/linux/dma-fence.h
include/linux/reservation.h

diff --git a/Documentation/devicetree/bindings/display/panel/mitsubishi,aa070mc01.txt b/Documentation/devicetree/bindings/display/panel/mitsubishi,aa070mc01.txt
new file mode 100644 (file)
index 0000000..7d8f6ee
--- /dev/null
@@ -0,0 +1,7 @@
+Mitsubishi "AA070MC01 7.0" WVGA TFT LCD panel
+
+Required properties:
+- compatible: should be "mitsubishi,aa070mc01-ca1"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/display/panel/tianma,tm070rvhg71.txt b/Documentation/devicetree/bindings/display/panel/tianma,tm070rvhg71.txt
new file mode 100644 (file)
index 0000000..b25261e
--- /dev/null
@@ -0,0 +1,29 @@
+Tianma Micro-electronics TM070RVHG71 7.0" WXGA TFT LCD panel
+
+Required properties:
+- compatible: should be "tianma,tm070rvhg71"
+- power-supply: single regulator to provide the supply voltage
+- backlight: phandle of the backlight device attached to the panel
+
+Required nodes:
+- port: LVDS 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
+
+       panel: panel-lvds0 {
+               compatible = "tianma,tm070rvhg71";
+               backlight = <&backlight_lvds>;
+               power-supply = <&reg_lvds>;
+
+               port {
+                       panel_in_lvds0: endpoint {
+                               remote-endpoint = <&lvds0_out>;
+                       };
+               };
+       };
index 5d835d9..eeda359 100644 (file)
@@ -7,6 +7,7 @@ buffer to an external LCD interface.
 Required properties:
 - compatible: value should be one of the following
                "rockchip,rk3036-vop";
+               "rockchip,rk3126-vop";
                "rockchip,rk3288-vop";
                "rockchip,rk3368-vop";
                "rockchip,rk3366-vop";
index 74b5ac7..0292522 100644 (file)
       - "lcd" for the clock feeding the output pixel clock & IP clock.
   - resets: reset to be used by the device (defined by use of RCC macro).
   Required nodes:
-    - Video port for RGB output.
+  - Video port for DPI RGB output: ltdc has one video port with up to 2
+    endpoints:
+      - for external dpi rgb panel or bridge, using gpios.
+      - for internal dpi input of the MIPI DSI host controller.
+      Note: These 2 endpoints cannot be activated simultaneously.
 
 * STMicroelectronics STM32 DSI controller specific extensions to Synopsys
   DesignWare MIPI DSI host controller
index 36625aa..01eaa40 100644 (file)
@@ -179,6 +179,10 @@ don't do this, drivers used dev_info/warn/err to make this differentiation. We
 now have DRM_DEV_* variants of the drm print macros, so we can start to convert
 those drivers back to using drm-formwatted specific log messages.
 
+Before you start this conversion please contact the relevant maintainers to make
+sure your work will be merged - not everyone agrees that the DRM dmesg macros
+are better.
+
 Contact: Sean Paul, Maintainer of the driver you plan to convert
 
 Core refactorings
index d4fdcb1..d7eedb1 100644 (file)
@@ -4587,6 +4587,7 @@ F:        include/linux/vga*
 DRM DRIVERS AND MISC GPU PATCHES
 M:     Daniel Vetter <daniel.vetter@intel.com>
 M:     Jani Nikula <jani.nikula@linux.intel.com>
+M:     Gustavo Padovan <gustavo@padovan.org>
 M:     Sean Paul <seanpaul@chromium.org>
 W:     https://01.org/linuxgraphics/gfx-docs/maintainer-tools/drm-misc.html
 S:     Maintained
@@ -4715,7 +4716,8 @@ F:        Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt
 F:     Documentation/devicetree/bindings/display/renesas,du.txt
 
 DRM DRIVERS FOR ROCKCHIP
-M:     Mark Yao <mark.yao@rock-chips.com>
+M:     Sandy Huang <hjc@rock-chips.com>
+M:     Heiko Stübner <heiko@sntech.de>
 L:     dri-devel@lists.freedesktop.org
 S:     Maintained
 F:     drivers/gpu/drm/rockchip/
index 2f6614c..2c3cab0 100644 (file)
@@ -245,6 +245,7 @@ config DMA_SHARED_BUFFER
        bool
        default n
        select ANON_INODES
+       select IRQ_WORK
        help
          This option enables the framework for buffer-sharing between
          multiple drivers. A buffer is associated with a file using driver
index bc1cb28..058805b 100644 (file)
@@ -351,13 +351,13 @@ static inline int is_dma_buf_file(struct file *file)
  *
  * 2. Userspace passes this file-descriptors to all drivers it wants this buffer
  *    to share with: First the filedescriptor is converted to a &dma_buf using
- *    dma_buf_get(). The the buffer is attached to the device using
+ *    dma_buf_get(). Then the buffer is attached to the device using
  *    dma_buf_attach().
  *
  *    Up to this stage the exporter is still free to migrate or reallocate the
  *    backing storage.
  *
- * 3. Once the buffer is attached to all devices userspace can inniate DMA
+ * 3. Once the buffer is attached to all devices userspace can initiate DMA
  *    access to the shared buffer. In the kernel this is done by calling
  *    dma_buf_map_attachment() and dma_buf_unmap_attachment().
  *
@@ -617,7 +617,7 @@ EXPORT_SYMBOL_GPL(dma_buf_detach);
  * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR
  * on error. May return -EINTR if it is interrupted by a signal.
  *
- * A mapping must be unmapped again using dma_buf_map_attachment(). Note that
+ * A mapping must be unmapped by using dma_buf_unmap_attachment(). Note that
  * the underlying backing storage is pinned for as long as a mapping exists,
  * therefore users/importers should not hold onto a mapping for undue amounts of
  * time.
@@ -1179,8 +1179,7 @@ static int dma_buf_init_debugfs(void)
 
 static void dma_buf_uninit_debugfs(void)
 {
-       if (dma_buf_debugfs_dir)
-               debugfs_remove_recursive(dma_buf_debugfs_dir);
+       debugfs_remove_recursive(dma_buf_debugfs_dir);
 }
 #else
 static inline int dma_buf_init_debugfs(void)
index 0350829..dd1edfb 100644 (file)
@@ -31,6 +31,14 @@ static const char *dma_fence_array_get_timeline_name(struct dma_fence *fence)
        return "unbound";
 }
 
+static void irq_dma_fence_array_work(struct irq_work *wrk)
+{
+       struct dma_fence_array *array = container_of(wrk, typeof(*array), work);
+
+       dma_fence_signal(&array->base);
+       dma_fence_put(&array->base);
+}
+
 static void dma_fence_array_cb_func(struct dma_fence *f,
                                    struct dma_fence_cb *cb)
 {
@@ -39,8 +47,9 @@ static void dma_fence_array_cb_func(struct dma_fence *f,
        struct dma_fence_array *array = array_cb->array;
 
        if (atomic_dec_and_test(&array->num_pending))
-               dma_fence_signal(&array->base);
-       dma_fence_put(&array->base);
+               irq_work_queue(&array->work);
+       else
+               dma_fence_put(&array->base);
 }
 
 static bool dma_fence_array_enable_signaling(struct dma_fence *fence)
@@ -136,6 +145,7 @@ struct dma_fence_array *dma_fence_array_create(int num_fences,
        spin_lock_init(&array->lock);
        dma_fence_init(&array->base, &dma_fence_array_ops, &array->lock,
                       context, seqno);
+       init_irq_work(&array->work, irq_dma_fence_array_work);
 
        array->num_fences = num_fences;
        atomic_set(&array->num_pending, signal_on_any ? 1 : num_fences);
index b44d9d7..b759a56 100644 (file)
@@ -104,7 +104,8 @@ reservation_object_add_shared_inplace(struct reservation_object *obj,
                                      struct reservation_object_list *fobj,
                                      struct dma_fence *fence)
 {
-       u32 i;
+       struct dma_fence *signaled = NULL;
+       u32 i, signaled_idx;
 
        dma_fence_get(fence);
 
@@ -126,17 +127,28 @@ reservation_object_add_shared_inplace(struct reservation_object *obj,
                        dma_fence_put(old_fence);
                        return;
                }
+
+               if (!signaled && dma_fence_is_signaled(old_fence)) {
+                       signaled = old_fence;
+                       signaled_idx = i;
+               }
        }
 
        /*
         * memory barrier is added by write_seqcount_begin,
         * fobj->shared_count is protected by this lock too
         */
-       RCU_INIT_POINTER(fobj->shared[fobj->shared_count], fence);
-       fobj->shared_count++;
+       if (signaled) {
+               RCU_INIT_POINTER(fobj->shared[signaled_idx], fence);
+       } else {
+               RCU_INIT_POINTER(fobj->shared[fobj->shared_count], fence);
+               fobj->shared_count++;
+       }
 
        write_seqcount_end(&obj->seq);
        preempt_enable();
+
+       dma_fence_put(signaled);
 }
 
 static void
@@ -145,8 +157,7 @@ reservation_object_add_shared_replace(struct reservation_object *obj,
                                      struct reservation_object_list *fobj,
                                      struct dma_fence *fence)
 {
-       unsigned i;
-       struct dma_fence *old_fence = NULL;
+       unsigned i, j, k;
 
        dma_fence_get(fence);
 
@@ -162,24 +173,21 @@ reservation_object_add_shared_replace(struct reservation_object *obj,
         * references from the old struct are carried over to
         * the new.
         */
-       fobj->shared_count = old->shared_count;
-
-       for (i = 0; i < old->shared_count; ++i) {
+       for (i = 0, j = 0, k = fobj->shared_max; i < old->shared_count; ++i) {
                struct dma_fence *check;
 
                check = rcu_dereference_protected(old->shared[i],
                                                reservation_object_held(obj));
 
-               if (!old_fence && check->context == fence->context) {
-                       old_fence = check;
-                       RCU_INIT_POINTER(fobj->shared[i], fence);
-               } else
-                       RCU_INIT_POINTER(fobj->shared[i], check);
-       }
-       if (!old_fence) {
-               RCU_INIT_POINTER(fobj->shared[fobj->shared_count], fence);
-               fobj->shared_count++;
+               if (check->context == fence->context ||
+                   dma_fence_is_signaled(check))
+                       RCU_INIT_POINTER(fobj->shared[--k], check);
+               else
+                       RCU_INIT_POINTER(fobj->shared[j++], check);
        }
+       fobj->shared_count = j;
+       RCU_INIT_POINTER(fobj->shared[fobj->shared_count], fence);
+       fobj->shared_count++;
 
 done:
        preempt_disable();
@@ -192,10 +200,18 @@ done:
        write_seqcount_end(&obj->seq);
        preempt_enable();
 
-       if (old)
-               kfree_rcu(old, rcu);
+       if (!old)
+               return;
 
-       dma_fence_put(old_fence);
+       /* Drop the references to the signaled fences */
+       for (i = k; i < fobj->shared_max; ++i) {
+               struct dma_fence *f;
+
+               f = rcu_dereference_protected(fobj->shared[i],
+                                             reservation_object_held(obj));
+               dma_fence_put(f);
+       }
+       kfree_rcu(old, rcu);
 }
 
 /**
@@ -318,7 +334,7 @@ retry:
                                continue;
                        }
 
-                       dst_list->shared[dst_list->shared_count++] = fence;
+                       rcu_assign_pointer(dst_list->shared[dst_list->shared_count++], fence);
                }
        } else {
                dst_list = NULL;
index df9cbc7..8ca3783 100644 (file)
@@ -358,7 +358,6 @@ static int amdgpu_connector_ddc_get_modes(struct drm_connector *connector)
        if (amdgpu_connector->edid) {
                drm_mode_connector_update_edid_property(connector, amdgpu_connector->edid);
                ret = drm_add_edid_modes(connector, amdgpu_connector->edid);
-               drm_edid_to_eld(connector, amdgpu_connector->edid);
                return ret;
        }
        drm_mode_connector_update_edid_property(connector, NULL);
index f71fe6d..c324c3b 100644 (file)
@@ -3333,8 +3333,6 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector,
                amdgpu_dm_connector->num_modes =
                                drm_add_edid_modes(connector, edid);
 
-               drm_edid_to_eld(connector, edid);
-
                amdgpu_dm_get_native_mode(connector);
        } else {
                amdgpu_dm_connector->num_modes = 0;
index f8efb98..707928b 100644 (file)
@@ -177,12 +177,7 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
 static int dm_connector_update_modes(struct drm_connector *connector,
                                struct edid *edid)
 {
-       int ret;
-
-       ret = drm_add_edid_modes(connector, edid);
-       drm_edid_to_eld(connector, edid);
-
-       return ret;
+       return drm_add_edid_modes(connector, edid);
 }
 
 static int dm_dp_mst_get_modes(struct drm_connector *connector)
index 074fd4e..f067de4 100644 (file)
@@ -155,7 +155,6 @@ static int arcpgu_show_pxlclock(struct seq_file *m, void *arg)
 
 static struct drm_info_list arcpgu_debugfs_list[] = {
        { "clocks", arcpgu_show_pxlclock, 0 },
-       { "fb", drm_fb_cma_debugfs_show, 0 },
 };
 
 static int arcpgu_debugfs_init(struct drm_minor *minor)
@@ -180,6 +179,7 @@ static struct drm_driver arcpgu_drm_driver = {
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
+       .gem_print_info = drm_gem_cma_print_info,
        .gem_vm_ops = &drm_gem_cma_vm_ops,
        .gem_prime_export = drm_gem_prime_export,
        .gem_prime_import = drm_gem_prime_import,
index 5a5427b..630721f 100644 (file)
@@ -252,10 +252,10 @@ static int hdlcd_plane_atomic_check(struct drm_plane *plane,
        clip.x2 = crtc_state->adjusted_mode.hdisplay;
        clip.y2 = crtc_state->adjusted_mode.vdisplay;
 
-       return drm_plane_helper_check_state(state, &clip,
-                                           DRM_PLANE_HELPER_NO_SCALING,
-                                           DRM_PLANE_HELPER_NO_SCALING,
-                                           false, true);
+       return drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
+                                                  DRM_PLANE_HELPER_NO_SCALING,
+                                                  DRM_PLANE_HELPER_NO_SCALING,
+                                                  false, true);
 }
 
 static void hdlcd_plane_atomic_update(struct drm_plane *plane,
index 0afb53b..feaa8bc 100644 (file)
@@ -231,7 +231,6 @@ static int hdlcd_show_pxlclock(struct seq_file *m, void *arg)
 static struct drm_info_list hdlcd_debugfs_list[] = {
        { "interrupt_count", hdlcd_show_underrun_count, 0 },
        { "clocks", hdlcd_show_pxlclock, 0 },
-       { "fb", drm_fb_cma_debugfs_show, 0 },
 };
 
 static int hdlcd_debugfs_init(struct drm_minor *minor)
@@ -253,6 +252,7 @@ static struct drm_driver hdlcd_driver = {
        .irq_postinstall = hdlcd_irq_postinstall,
        .irq_uninstall = hdlcd_irq_uninstall,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
+       .gem_print_info = drm_gem_cma_print_info,
        .gem_vm_ops = &drm_gem_cma_vm_ops,
        .dumb_create = drm_gem_cma_dumb_create,
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
index e741979..33c5ef9 100644 (file)
@@ -150,7 +150,8 @@ static int malidp_se_check_scaling(struct malidp_plane *mp,
 
        clip.x2 = crtc_state->adjusted_mode.hdisplay;
        clip.y2 = crtc_state->adjusted_mode.vdisplay;
-       ret = drm_plane_helper_check_state(state, &clip, 0, INT_MAX, true, true);
+       ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
+                                                 0, INT_MAX, true, true);
        if (ret)
                return ret;
 
index 9385eb0..ed12a7d 100644 (file)
@@ -977,8 +977,6 @@ static int anx78xx_get_modes(struct drm_connector *connector)
        }
 
        num_modes = drm_add_edid_modes(connector, anx78xx->edid);
-       /* Store the ELD */
-       drm_edid_to_eld(connector, anx78xx->edid);
 
 unlock:
        mutex_unlock(&anx78xx->lock);
index b7eb704..86789f8 100644 (file)
@@ -1169,8 +1169,18 @@ static void sii8620_set_infoframes(struct sii8620 *ctx)
        sii8620_write_buf(ctx, REG_TPI_INFO_B0, buf, ret);
 }
 
-static void sii8620_start_hdmi(struct sii8620 *ctx)
+static void sii8620_start_video(struct sii8620 *ctx)
 {
+       if (!sii8620_is_mhl3(ctx))
+               sii8620_stop_video(ctx);
+
+       if (ctx->sink_type == SINK_DVI && !sii8620_is_mhl3(ctx)) {
+               sii8620_write(ctx, REG_RX_HDMI_CTRL2,
+                             VAL_RX_HDMI_CTRL2_DEFVAL);
+               sii8620_write(ctx, REG_TPI_SC, 0);
+               return;
+       }
+
        sii8620_write_seq_static(ctx,
                REG_RX_HDMI_CTRL2, VAL_RX_HDMI_CTRL2_DEFVAL
                        | BIT_RX_HDMI_CTRL2_USE_AV_MUTE,
@@ -1229,21 +1239,6 @@ static void sii8620_start_hdmi(struct sii8620 *ctx)
        sii8620_set_infoframes(ctx);
 }
 
-static void sii8620_start_video(struct sii8620 *ctx)
-{
-       if (!sii8620_is_mhl3(ctx))
-               sii8620_stop_video(ctx);
-
-       switch (ctx->sink_type) {
-       case SINK_HDMI:
-               sii8620_start_hdmi(ctx);
-               break;
-       case SINK_DVI:
-       default:
-               break;
-       }
-}
-
 static void sii8620_disable_hpd(struct sii8620 *ctx)
 {
        sii8620_setbits(ctx, REG_EDID_CTRL, BIT_EDID_CTRL_EDID_PRIME_VALID, 0);
@@ -1945,8 +1940,13 @@ static void sii8620_irq_scdt(struct sii8620 *ctx)
        if (stat & BIT_INTR_SCDT_CHANGE) {
                u8 cstat = sii8620_readb(ctx, REG_TMDS_CSTAT_P3);
 
-               if (cstat & BIT_TMDS_CSTAT_P3_SCDT)
-                       sii8620_scdt_high(ctx);
+               if (cstat & BIT_TMDS_CSTAT_P3_SCDT) {
+                       if (ctx->sink_type == SINK_HDMI)
+                               /* enable infoframe interrupt */
+                               sii8620_scdt_high(ctx);
+                       else
+                               sii8620_start_video(ctx);
+               }
        }
 
        sii8620_write(ctx, REG_INTR5, stat);
@@ -2191,6 +2191,19 @@ static void sii8620_detach(struct drm_bridge *bridge)
        rc_unregister_device(ctx->rc_dev);
 }
 
+static enum drm_mode_status sii8620_mode_valid(struct drm_bridge *bridge,
+                                        const struct drm_display_mode *mode)
+{
+       struct sii8620 *ctx = bridge_to_sii8620(bridge);
+       bool can_pack = ctx->devcap[MHL_DCAP_VID_LINK_MODE] &
+                       MHL_DCAP_VID_LINK_PPIXEL;
+       unsigned int max_pclk = sii8620_is_mhl3(ctx) ? MHL3_MAX_LCLK :
+                                                      MHL1_MAX_LCLK;
+       max_pclk /= can_pack ? 2 : 3;
+
+       return (mode->clock > max_pclk) ? MODE_CLOCK_HIGH : MODE_OK;
+}
+
 static bool sii8620_mode_fixup(struct drm_bridge *bridge,
                               const struct drm_display_mode *mode,
                               struct drm_display_mode *adjusted_mode)
@@ -2220,8 +2233,9 @@ end:
                        union hdmi_infoframe frm;
                        u8 mhl_vic[] = { 0, 95, 94, 93, 98 };
 
+                       /* FIXME: We need the connector here */
                        drm_hdmi_vendor_infoframe_from_display_mode(
-                               &frm.vendor.hdmi, adjusted_mode);
+                               &frm.vendor.hdmi, NULL, adjusted_mode);
                        vic = frm.vendor.hdmi.vic;
                        if (vic >= ARRAY_SIZE(mhl_vic))
                                vic = 0;
@@ -2238,6 +2252,7 @@ static const struct drm_bridge_funcs sii8620_bridge_funcs = {
        .attach = sii8620_attach,
        .detach = sii8620_detach,
        .mode_fixup = sii8620_mode_fixup,
+       .mode_valid = sii8620_mode_valid,
 };
 
 static int sii8620_probe(struct i2c_client *client,
index b72259b..a38db40 100644 (file)
@@ -1438,7 +1438,9 @@ static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi,
        u8 buffer[10];
        ssize_t err;
 
-       err = drm_hdmi_vendor_infoframe_from_display_mode(&frame, mode);
+       err = drm_hdmi_vendor_infoframe_from_display_mode(&frame,
+                                                         &hdmi->connector,
+                                                         mode);
        if (err < 0)
                /*
                 * Going into that statement does not means vendor infoframe
@@ -1911,8 +1913,6 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
                drm_mode_connector_update_edid_property(connector, edid);
                cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid);
                ret = drm_add_edid_modes(connector, edid);
-               /* Store the ELD */
-               drm_edid_to_eld(connector, edid);
                kfree(edid);
        } else {
                dev_dbg(hdmi->dev, "failed to get edid\n");
index 8636e7e..08ab7d6 100644 (file)
@@ -6,6 +6,8 @@
  *
  * Copyright (C) 2016 Pengutronix, Philipp Zabel <p.zabel@pengutronix.de>
  *
+ * Copyright (C) 2016 Zodiac Inflight Innovations
+ *
  * Initially based on: drivers/gpu/drm/i2c/tda998x_drv.c
  *
  * Copyright (C) 2012 Texas Instruments
index b5f5285..26df1e8 100644 (file)
 
 #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)
 {
@@ -24,6 +32,7 @@ static void cirrus_user_framebuffer_destroy(struct drm_framebuffer *fb)
 }
 
 static const struct drm_framebuffer_funcs cirrus_fb_funcs = {
+       .create_handle = cirrus_create_handle,
        .destroy = cirrus_user_framebuffer_destroy,
 };
 
index c2da558..37445d5 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/sync_file.h>
 
 #include "drm_crtc_internal.h"
+#include "drm_internal.h"
 
 void __drm_crtc_commit_free(struct kref *kref)
 {
@@ -907,11 +908,12 @@ static int drm_atomic_plane_check(struct drm_plane *plane,
            state->src_h > fb_height ||
            state->src_y > fb_height - state->src_h) {
                DRM_DEBUG_ATOMIC("Invalid source coordinates "
-                                "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
+                                "%u.%06ux%u.%06u+%u.%06u+%u.%06u (fb %ux%u)\n",
                                 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,
-                                state->src_y >> 16, ((state->src_y & 0xffff) * 15625) >> 10);
+                                state->src_y >> 16, ((state->src_y & 0xffff) * 15625) >> 10,
+                                state->fb->width, state->fb->height);
                return -ENOSPC;
        }
 
@@ -934,21 +936,8 @@ static void drm_atomic_plane_print_state(struct drm_printer *p,
        drm_printf(p, "plane[%u]: %s\n", plane->base.id, plane->name);
        drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)");
        drm_printf(p, "\tfb=%u\n", state->fb ? state->fb->base.id : 0);
-       if (state->fb) {
-               struct drm_framebuffer *fb = state->fb;
-               int i, n = fb->format->num_planes;
-               struct drm_format_name_buf format_name;
-
-               drm_printf(p, "\t\tformat=%s\n",
-                             drm_get_format_name(fb->format->format, &format_name));
-               drm_printf(p, "\t\t\tmodifier=0x%llx\n", fb->modifier);
-               drm_printf(p, "\t\tsize=%dx%d\n", fb->width, fb->height);
-               drm_printf(p, "\t\tlayers:\n");
-               for (i = 0; i < n; i++) {
-                       drm_printf(p, "\t\t\tpitch[%d]=%u\n", i, fb->pitches[i]);
-                       drm_printf(p, "\t\t\toffset[%d]=%u\n", i, fb->offsets[i]);
-               }
-       }
+       if (state->fb)
+               drm_framebuffer_print_info(p, 2, state->fb);
        drm_printf(p, "\tcrtc-pos=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&dest));
        drm_printf(p, "\tsrc-pos=" DRM_RECT_FP_FMT "\n", DRM_RECT_FP_ARG(&src));
        drm_printf(p, "\trotation=%x\n", state->rotation);
@@ -1808,7 +1797,7 @@ int drm_atomic_debugfs_init(struct drm_minor *minor)
 #endif
 
 /*
- * The big monstor ioctl
+ * The big monster ioctl
  */
 
 static struct drm_pending_vblank_event *create_vblank_event(
index b16f1d6..ab40321 100644 (file)
@@ -695,6 +695,100 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
 
+/**
+ * drm_atomic_helper_check_plane_state() - Check plane state for validity
+ * @plane_state: plane state to check
+ * @crtc_state: crtc state to check
+ * @clip: integer clipping coordinates
+ * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
+ * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
+ * @can_position: is it legal to position the plane such that it
+ *                doesn't cover the entire crtc?  This will generally
+ *                only be false for primary planes.
+ * @can_update_disabled: can the plane be updated while the crtc
+ *                       is disabled?
+ *
+ * Checks that a desired plane update is valid, and updates various
+ * bits of derived state (clipped coordinates etc.). Drivers that provide
+ * their own plane handling rather than helper-provided implementations may
+ * still wish to call this function to avoid duplication of error checking
+ * code.
+ *
+ * RETURNS:
+ * Zero if update appears valid, error code on failure
+ */
+int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
+                                       const struct drm_crtc_state *crtc_state,
+                                       const struct drm_rect *clip,
+                                       int min_scale,
+                                       int max_scale,
+                                       bool can_position,
+                                       bool can_update_disabled)
+{
+       struct drm_framebuffer *fb = plane_state->fb;
+       struct drm_rect *src = &plane_state->src;
+       struct drm_rect *dst = &plane_state->dst;
+       unsigned int rotation = plane_state->rotation;
+       int hscale, vscale;
+
+       WARN_ON(plane_state->crtc && plane_state->crtc != crtc_state->crtc);
+
+       *src = drm_plane_state_src(plane_state);
+       *dst = drm_plane_state_dest(plane_state);
+
+       if (!fb) {
+               plane_state->visible = false;
+               return 0;
+       }
+
+       /* crtc should only be NULL when disabling (i.e., !fb) */
+       if (WARN_ON(!plane_state->crtc)) {
+               plane_state->visible = false;
+               return 0;
+       }
+
+       if (!crtc_state->enable && !can_update_disabled) {
+               DRM_DEBUG_KMS("Cannot update plane of a disabled CRTC.\n");
+               return -EINVAL;
+       }
+
+       drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation);
+
+       /* Check scaling */
+       hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
+       vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
+       if (hscale < 0 || vscale < 0) {
+               DRM_DEBUG_KMS("Invalid scaling of plane\n");
+               drm_rect_debug_print("src: ", &plane_state->src, true);
+               drm_rect_debug_print("dst: ", &plane_state->dst, false);
+               return -ERANGE;
+       }
+
+       plane_state->visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale);
+
+       drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation);
+
+       if (!plane_state->visible)
+               /*
+                * Plane isn't visible; some drivers can handle this
+                * so we just return success here.  Drivers that can't
+                * (including those that use the primary plane helper's
+                * update function) will return an error from their
+                * update_plane handler.
+                */
+               return 0;
+
+       if (!can_position && !drm_rect_equals(dst, clip)) {
+               DRM_DEBUG_KMS("Plane must cover entire CRTC\n");
+               drm_rect_debug_print("dst: ", dst, false);
+               drm_rect_debug_print("clip: ", clip, false);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_atomic_helper_check_plane_state);
+
 /**
  * drm_atomic_helper_check_planes - validate state object for planes changes
  * @dev: DRM device
@@ -907,6 +1001,12 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
  *
  * Drivers can use this for building their own atomic commit if they don't have
  * a pure helper-based modeset implementation.
+ *
+ * Since these updates are not synchronized with lockings, only code paths
+ * called from &drm_mode_config_helper_funcs.atomic_commit_tail can look at the
+ * legacy state filled out by this helper. Defacto this means this helper and
+ * the legacy state pointers are only really useful for transitioning an
+ * existing driver to the atomic world.
  */
 void
 drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev,
@@ -1787,11 +1887,8 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
                    !try_wait_for_completion(&old_conn_state->commit->flip_done))
                        return -EBUSY;
 
-               /* commit tracked through new_crtc_state->commit, no need to do it explicitly */
-               if (new_conn_state->crtc)
-                       continue;
-
-               commit = crtc_or_fake_commit(state, old_conn_state->crtc);
+               /* Always track connectors explicitly for e.g. link retraining. */
+               commit = crtc_or_fake_commit(state, new_conn_state->crtc ?: old_conn_state->crtc);
                if (!commit)
                        return -ENOMEM;
 
@@ -1805,10 +1902,7 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
                    !try_wait_for_completion(&old_plane_state->commit->flip_done))
                        return -EBUSY;
 
-               /*
-                * Unlike connectors, always track planes explicitly for
-                * async pageflip support.
-                */
+               /* Always track planes explicitly for async pageflip support. */
                commit = crtc_or_fake_commit(state, new_plane_state->crtc ?: old_plane_state->crtc);
                if (!commit)
                        return -ENOMEM;
index c1807d5..b248281 100644 (file)
@@ -158,6 +158,14 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id,
                }
        }
 
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+               ret = drm_framebuffer_debugfs_init(minor);
+               if (ret) {
+                       DRM_ERROR("Failed to create framebuffer debugfs file\n");
+                       return ret;
+               }
+       }
+
        if (dev->driver->debugfs_init) {
                ret = dev->driver->debugfs_init(minor);
                if (ret) {
index b3d6896..adf79be 100644 (file)
@@ -1097,7 +1097,6 @@ int drm_dp_aux_register(struct drm_dp_aux *aux)
        aux->ddc.class = I2C_CLASS_DDC;
        aux->ddc.owner = THIS_MODULE;
        aux->ddc.dev.parent = aux->dev;
-       aux->ddc.dev.of_node = aux->dev->of_node;
 
        strlcpy(aux->ddc.name, aux->name ? aux->name : dev_name(aux->dev),
                sizeof(aux->ddc.name));
index a934fd5..9acc1e1 100644 (file)
@@ -75,53 +75,6 @@ static bool drm_core_init_complete = false;
 
 static struct dentry *drm_debugfs_root;
 
-#define DRM_PRINTK_FMT "[" DRM_NAME ":%s]%s %pV"
-
-void drm_dev_printk(const struct device *dev, const char *level,
-                   unsigned int category, const char *function_name,
-                   const char *prefix, const char *format, ...)
-{
-       struct va_format vaf;
-       va_list args;
-
-       if (category != DRM_UT_NONE && !(drm_debug & category))
-               return;
-
-       va_start(args, format);
-       vaf.fmt = format;
-       vaf.va = &args;
-
-       if (dev)
-               dev_printk(level, dev, DRM_PRINTK_FMT, function_name, prefix,
-                          &vaf);
-       else
-               printk("%s" DRM_PRINTK_FMT, level, function_name, prefix, &vaf);
-
-       va_end(args);
-}
-EXPORT_SYMBOL(drm_dev_printk);
-
-void drm_printk(const char *level, unsigned int category,
-               const char *format, ...)
-{
-       struct va_format vaf;
-       va_list args;
-
-       if (category != DRM_UT_NONE && !(drm_debug & category))
-               return;
-
-       va_start(args, format);
-       vaf.fmt = format;
-       vaf.va = &args;
-
-       printk("%s" "[" DRM_NAME ":%ps]%s %pV",
-              level, __builtin_return_address(0),
-              strcmp(level, KERN_ERR) == 0 ? " *ERROR*" : "", &vaf);
-
-       va_end(args);
-}
-EXPORT_SYMBOL(drm_printk);
-
 /*
  * DRM Minors
  * A DRM device can provide several char-dev interfaces on the DRM-Major. Each
index 5dfe147..524eace 100644 (file)
@@ -3398,6 +3398,7 @@ static int
 do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
                   const u8 *video_db, u8 video_len)
 {
+       struct drm_display_info *info = &connector->display_info;
        int modes = 0, offset = 0, i, multi_present = 0, multi_len;
        u8 vic_len, hdmi_3d_len = 0;
        u16 mask;
@@ -3525,6 +3526,8 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
        }
 
 out:
+       if (modes > 0)
+               info->has_hdmi_infoframe = true;
        return modes;
 }
 
@@ -3761,8 +3764,8 @@ drm_parse_hdmi_vsdb_audio(struct drm_connector *connector, const u8 *db)
 {
        u8 len = cea_db_payload_len(db);
 
-       if (len >= 6)
-               connector->eld[5] |= (db[6] >> 7) << 1;  /* Supports_AI */
+       if (len >= 6 && (db[6] & (1 << 7)))
+               connector->eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= DRM_ELD_SUPPORTS_AI;
        if (len >= 8) {
                connector->latency_present[0] = db[8] >> 7;
                connector->latency_present[1] = (db[8] >> 6) & 1;
@@ -3834,16 +3837,27 @@ void drm_edid_get_monitor_name(struct edid *edid, char *name, int bufsize)
 }
 EXPORT_SYMBOL(drm_edid_get_monitor_name);
 
-/**
+static void clear_eld(struct drm_connector *connector)
+{
+       memset(connector->eld, 0, sizeof(connector->eld));
+
+       connector->latency_present[0] = false;
+       connector->latency_present[1] = false;
+       connector->video_latency[0] = 0;
+       connector->audio_latency[0] = 0;
+       connector->video_latency[1] = 0;
+       connector->audio_latency[1] = 0;
+}
+
+/*
  * drm_edid_to_eld - build ELD from EDID
  * @connector: connector corresponding to the HDMI/DP sink
  * @edid: EDID to parse
  *
  * Fill the ELD (EDID-Like Data) buffer for passing to the audio driver. The
- * Conn_Type, HDCP and Port_ID ELD fields are left for the graphics driver to
- * fill in.
+ * HDCP and Port_ID ELD fields are left for the graphics driver to fill in.
  */
-void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
+static void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
 {
        uint8_t *eld = connector->eld;
        u8 *cea;
@@ -3852,14 +3866,7 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
        int mnl;
        int dbl;
 
-       memset(eld, 0, sizeof(connector->eld));
-
-       connector->latency_present[0] = false;
-       connector->latency_present[1] = false;
-       connector->video_latency[0] = 0;
-       connector->audio_latency[0] = 0;
-       connector->video_latency[1] = 0;
-       connector->audio_latency[1] = 0;
+       clear_eld(connector);
 
        if (!edid)
                return;
@@ -3870,17 +3877,18 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
                return;
        }
 
-       mnl = get_monitor_name(edid, eld + 20);
+       mnl = get_monitor_name(edid, &eld[DRM_ELD_MONITOR_NAME_STRING]);
+       DRM_DEBUG_KMS("ELD monitor %s\n", &eld[DRM_ELD_MONITOR_NAME_STRING]);
 
-       eld[4] = (cea[1] << 5) | mnl;
-       DRM_DEBUG_KMS("ELD monitor %s\n", eld + 20);
+       eld[DRM_ELD_CEA_EDID_VER_MNL] = cea[1] << DRM_ELD_CEA_EDID_VER_SHIFT;
+       eld[DRM_ELD_CEA_EDID_VER_MNL] |= mnl;
 
-       eld[0] = 2 << 3;                /* ELD version: 2 */
+       eld[DRM_ELD_VER] = DRM_ELD_VER_CEA861D;
 
-       eld[16] = edid->mfg_id[0];
-       eld[17] = edid->mfg_id[1];
-       eld[18] = edid->prod_code[0];
-       eld[19] = edid->prod_code[1];
+       eld[DRM_ELD_MANUFACTURER_NAME0] = edid->mfg_id[0];
+       eld[DRM_ELD_MANUFACTURER_NAME1] = edid->mfg_id[1];
+       eld[DRM_ELD_PRODUCT_CODE0] = edid->prod_code[0];
+       eld[DRM_ELD_PRODUCT_CODE1] = edid->prod_code[1];
 
        if (cea_revision(cea) >= 3) {
                int i, start, end;
@@ -3901,14 +3909,14 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
                                /* Audio Data Block, contains SADs */
                                sad_count = min(dbl / 3, 15 - total_sad_count);
                                if (sad_count >= 1)
-                                       memcpy(eld + 20 + mnl + total_sad_count * 3,
+                                       memcpy(&eld[DRM_ELD_CEA_SAD(mnl, total_sad_count)],
                                               &db[1], sad_count * 3);
                                total_sad_count += sad_count;
                                break;
                        case SPEAKER_BLOCK:
                                /* Speaker Allocation Data Block */
                                if (dbl >= 1)
-                                       eld[7] = db[1];
+                                       eld[DRM_ELD_SPEAKER] = db[1];
                                break;
                        case VENDOR_BLOCK:
                                /* HDMI Vendor-Specific Data Block */
@@ -3920,7 +3928,13 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
                        }
                }
        }
-       eld[5] |= total_sad_count << 4;
+       eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= total_sad_count << DRM_ELD_SAD_COUNT_SHIFT;
+
+       if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
+           connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+               eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= DRM_ELD_CONN_TYPE_DP;
+       else
+               eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= DRM_ELD_CONN_TYPE_HDMI;
 
        eld[DRM_ELD_BASELINE_ELD_LEN] =
                DIV_ROUND_UP(drm_eld_calc_baseline_block_size(eld), 4);
@@ -3928,7 +3942,6 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
        DRM_DEBUG_KMS("ELD size %d, SAD count %d\n",
                      drm_eld_size(eld), total_sad_count);
 }
-EXPORT_SYMBOL(drm_edid_to_eld);
 
 /**
  * drm_edid_to_sad - extracts SADs from EDID
@@ -4238,6 +4251,8 @@ static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector,
        struct drm_display_info *display = &connector->display_info;
        struct drm_hdmi_info *hdmi = &display->hdmi;
 
+       display->has_hdmi_infoframe = true;
+
        if (hf_vsdb[6] & 0x80) {
                hdmi->scdc.supported = true;
                if (hf_vsdb[6] & 0x40)
@@ -4411,6 +4426,7 @@ static void drm_add_display_info(struct drm_connector *connector,
        info->cea_rev = 0;
        info->max_tmds_clock = 0;
        info->dvi_dual = false;
+       info->has_hdmi_infoframe = false;
 
        info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP);
 
@@ -4608,8 +4624,8 @@ static int add_displayid_detailed_modes(struct drm_connector *connector,
  * @edid: EDID data
  *
  * Add the specified modes to the connector's mode list. Also fills out the
- * &drm_display_info structure in @connector with any information which can be
- * derived from the edid.
+ * &drm_display_info structure and ELD in @connector with any information which
+ * can be derived from the edid.
  *
  * Return: The number of modes added or 0 if we couldn't find any.
  */
@@ -4619,9 +4635,11 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
        u32 quirks;
 
        if (edid == NULL) {
+               clear_eld(connector);
                return 0;
        }
        if (!drm_edid_is_valid(edid)) {
+               clear_eld(connector);
                dev_warn(connector->dev->dev, "%s: EDID invalid.\n",
                         connector->name);
                return 0;
@@ -4629,6 +4647,8 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
 
        quirks = edid_get_quirks(edid);
 
+       drm_edid_to_eld(connector, edid);
+
        /*
         * CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks.
         * To avoid multiple parsing of same block, lets parse that map
@@ -4904,6 +4924,7 @@ s3d_structure_from_display_mode(const struct drm_display_mode *mode)
  * drm_hdmi_vendor_infoframe_from_display_mode() - fill an HDMI infoframe with
  * data from a DRM display mode
  * @frame: HDMI vendor infoframe
+ * @connector: the connector
  * @mode: DRM display mode
  *
  * Note that there's is a need to send HDMI vendor infoframes only when using a
@@ -4914,8 +4935,15 @@ s3d_structure_from_display_mode(const struct drm_display_mode *mode)
  */
 int
 drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
+                                           struct drm_connector *connector,
                                            const struct drm_display_mode *mode)
 {
+       /*
+        * FIXME: sil-sii8620 doesn't have a connector around when
+        * we need one, so we have to be prepared for a NULL connector.
+        */
+       bool has_hdmi_infoframe = connector ?
+               connector->display_info.has_hdmi_infoframe : false;
        int err;
        u32 s3d_flags;
        u8 vic;
@@ -4923,11 +4951,21 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
        if (!frame || !mode)
                return -EINVAL;
 
+       if (!has_hdmi_infoframe)
+               return -EINVAL;
+
        vic = drm_match_hdmi_mode(mode);
        s3d_flags = mode->flags & DRM_MODE_FLAG_3D_MASK;
 
-       if (!vic && !s3d_flags)
-               return -EINVAL;
+       /*
+        * Even if it's not absolutely necessary to send the infoframe
+        * (ie.vic==0 and s3d_struct==0) we will still send it if we
+        * know that the sink can handle it. This is based on a
+        * suggestion in HDMI 2.0 Appendix F. Apparently some sinks
+        * have trouble realizing that they shuld switch from 3D to 2D
+        * mode if the source simply stops sending the infoframe when
+        * it wants to switch from 3D to 2D.
+        */
 
        if (vic && s3d_flags)
                return -EINVAL;
@@ -4936,10 +4974,8 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
        if (err < 0)
                return err;
 
-       if (vic)
-               frame->vic = vic;
-       else
-               frame->s3d_struct = s3d_structure_from_display_mode(mode);
+       frame->vic = vic;
+       frame->s3d_struct = s3d_structure_from_display_mode(mode);
 
        return 0;
 }
index 0e3c141..35b56df 100644 (file)
@@ -130,43 +130,6 @@ dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
 }
 EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr);
 
-#ifdef CONFIG_DEBUG_FS
-static void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m)
-{
-       int i;
-
-       seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height,
-                       (char *)&fb->format->format);
-
-       for (i = 0; i < fb->format->num_planes; i++) {
-               seq_printf(m, "   %d: offset=%d pitch=%d, obj: ",
-                               i, fb->offsets[i], fb->pitches[i]);
-               drm_gem_cma_describe(drm_fb_cma_get_gem_obj(fb, i), m);
-       }
-}
-
-/**
- * drm_fb_cma_debugfs_show() - Helper to list CMA framebuffer objects
- *                            in debugfs.
- * @m: output file
- * @arg: private data for the callback
- */
-int drm_fb_cma_debugfs_show(struct seq_file *m, void *arg)
-{
-       struct drm_info_node *node = (struct drm_info_node *) m->private;
-       struct drm_device *dev = node->minor->dev;
-       struct drm_framebuffer *fb;
-
-       mutex_lock(&dev->mode_config.fb_lock);
-       drm_for_each_fb(fb, dev)
-               drm_fb_cma_describe(fb, m);
-       mutex_unlock(&dev->mode_config.fb_lock);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(drm_fb_cma_debugfs_show);
-#endif
-
 static int drm_fb_cma_mmap(struct fb_info *info, struct vm_area_struct *vma)
 {
        return dma_mmap_writecombine(info->device, vma, info->screen_base,
index e561663..09919e8 100644 (file)
@@ -150,6 +150,9 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
 {
        int err;
 
+       if (!fb_helper)
+               return 0;
+
        mutex_lock(&fb_helper->lock);
        err = __drm_fb_helper_add_one_connector(fb_helper, connector);
        mutex_unlock(&fb_helper->lock);
@@ -161,7 +164,7 @@ EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
 /**
  * drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev
  *                                            emulation helper
- * @fb_helper: fbdev initialized with drm_fb_helper_init
+ * @fb_helper: fbdev initialized with drm_fb_helper_init, can be NULL
  *
  * This functions adds all the available connectors for use with the given
  * fb_helper. This is a separate step to allow drivers to freely assign
@@ -179,7 +182,7 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
        struct drm_connector_list_iter conn_iter;
        int i, ret = 0;
 
-       if (!drm_fbdev_emulation)
+       if (!drm_fbdev_emulation || !fb_helper)
                return 0;
 
        mutex_lock(&fb_helper->lock);
@@ -245,6 +248,9 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
 {
        int err;
 
+       if (!fb_helper)
+               return 0;
+
        mutex_lock(&fb_helper->lock);
        err = __drm_fb_helper_remove_one_connector(fb_helper, connector);
        mutex_unlock(&fb_helper->lock);
@@ -484,7 +490,7 @@ static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
 
 /**
  * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
- * @fb_helper: fbcon to restore
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
  *
  * This should be called from driver's drm &drm_driver.lastclose callback
  * when implementing an fbcon on top of kms using this helper. This ensures that
@@ -498,7 +504,7 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
        bool do_delayed;
        int ret;
 
-       if (!drm_fbdev_emulation)
+       if (!drm_fbdev_emulation || !fb_helper)
                return -ENODEV;
 
        if (READ_ONCE(fb_helper->deferred_setup))
@@ -793,8 +799,10 @@ int drm_fb_helper_init(struct drm_device *dev,
        struct drm_mode_config *config = &dev->mode_config;
        int i;
 
-       if (!drm_fbdev_emulation)
+       if (!drm_fbdev_emulation) {
+               dev->fb_helper = fb_helper;
                return 0;
+       }
 
        if (!max_conn_count)
                return -EINVAL;
@@ -829,6 +837,8 @@ int drm_fb_helper_init(struct drm_device *dev,
                i++;
        }
 
+       dev->fb_helper = fb_helper;
+
        return 0;
 out_free:
        drm_fb_helper_crtc_free(fb_helper);
@@ -883,7 +893,7 @@ EXPORT_SYMBOL(drm_fb_helper_alloc_fbi);
 
 /**
  * drm_fb_helper_unregister_fbi - unregister fb_info framebuffer device
- * @fb_helper: driver-allocated fbdev helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
  *
  * A wrapper around unregister_framebuffer, to release the fb_info
  * framebuffer device. This must be called before releasing all resources for
@@ -898,7 +908,7 @@ EXPORT_SYMBOL(drm_fb_helper_unregister_fbi);
 
 /**
  * drm_fb_helper_fini - finialize a &struct drm_fb_helper
- * @fb_helper: driver-allocated fbdev helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
  *
  * This cleans up all remaining resources associated with @fb_helper. Must be
  * called after drm_fb_helper_unlink_fbi() was called.
@@ -907,7 +917,12 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
 {
        struct fb_info *info;
 
-       if (!drm_fbdev_emulation || !fb_helper)
+       if (!fb_helper)
+               return;
+
+       fb_helper->dev->fb_helper = NULL;
+
+       if (!drm_fbdev_emulation)
                return;
 
        cancel_work_sync(&fb_helper->resume_work);
@@ -937,7 +952,7 @@ EXPORT_SYMBOL(drm_fb_helper_fini);
 
 /**
  * drm_fb_helper_unlink_fbi - wrapper around unlink_framebuffer
- * @fb_helper: driver-allocated fbdev helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
  *
  * A wrapper around unlink_framebuffer implemented by fbdev core
  */
@@ -1138,7 +1153,7 @@ EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit);
 
 /**
  * drm_fb_helper_set_suspend - wrapper around fb_set_suspend
- * @fb_helper: driver-allocated fbdev helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
  * @suspend: whether to suspend or resume
  *
  * A wrapper around fb_set_suspend implemented by fbdev core.
@@ -1155,7 +1170,7 @@ EXPORT_SYMBOL(drm_fb_helper_set_suspend);
 /**
  * drm_fb_helper_set_suspend_unlocked - wrapper around fb_set_suspend that also
  *                                      takes the console lock
- * @fb_helper: driver-allocated fbdev helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
  * @suspend: whether to suspend or resume
  *
  * A wrapper around fb_set_suspend() that takes the console lock. If the lock
@@ -2576,7 +2591,7 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config);
 /**
  * drm_fb_helper_hotplug_event - respond to a hotplug notification by
  *                               probing all the outputs attached to the fb
- * @fb_helper: the drm_fb_helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
  *
  * Scan the connectors attached to the fb_helper and try to put together a
  * setup after notification of a change in output configuration.
@@ -2598,7 +2613,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 {
        int err = 0;
 
-       if (!drm_fbdev_emulation)
+       if (!drm_fbdev_emulation || !fb_helper)
                return 0;
 
        mutex_lock(&fb_helper->lock);
@@ -2626,6 +2641,34 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 }
 EXPORT_SYMBOL(drm_fb_helper_hotplug_event);
 
+/**
+ * drm_fb_helper_lastclose - DRM driver lastclose helper for fbdev emulation
+ * @dev: DRM device
+ *
+ * This function can be used as the &drm_driver->lastclose callback for drivers
+ * that only need to call drm_fb_helper_restore_fbdev_mode_unlocked().
+ */
+void drm_fb_helper_lastclose(struct drm_device *dev)
+{
+       drm_fb_helper_restore_fbdev_mode_unlocked(dev->fb_helper);
+}
+EXPORT_SYMBOL(drm_fb_helper_lastclose);
+
+/**
+ * drm_fb_helper_output_poll_changed - DRM mode config \.output_poll_changed
+ *                                     helper for fbdev emulation
+ * @dev: DRM device
+ *
+ * This function can be used as the
+ * &drm_mode_config_funcs.output_poll_changed callback for drivers that only
+ * need to call drm_fb_helper_hotplug_event().
+ */
+void drm_fb_helper_output_poll_changed(struct drm_device *dev)
+{
+       drm_fb_helper_hotplug_event(dev->fb_helper);
+}
+EXPORT_SYMBOL(drm_fb_helper_output_poll_changed);
+
 /* The Kconfig DRM_KMS_HELPER selects FRAMEBUFFER_CONSOLE (if !EXPERT)
  * but the module doesn't depend on any fb console symbols.  At least
  * attempt to load fbcon to avoid leaving the system without a usable console.
index 279c103..d63d4c2 100644 (file)
@@ -25,7 +25,9 @@
 #include <drm/drm_auth.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_atomic.h>
+#include <drm/drm_print.h>
 
+#include "drm_internal.h"
 #include "drm_crtc_internal.h"
 
 /**
@@ -78,11 +80,12 @@ int drm_framebuffer_check_src_coords(uint32_t src_x, uint32_t src_y,
            src_h > fb_height ||
            src_y > fb_height - src_h) {
                DRM_DEBUG_KMS("Invalid source coordinates "
-                             "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
+                             "%u.%06ux%u.%06u+%u.%06u+%u.%06u (fb %ux%u)\n",
                              src_w >> 16, ((src_w & 0xffff) * 15625) >> 10,
                              src_h >> 16, ((src_h & 0xffff) * 15625) >> 10,
                              src_x >> 16, ((src_x & 0xffff) * 15625) >> 10,
-                             src_y >> 16, ((src_y & 0xffff) * 15625) >> 10);
+                             src_y >> 16, ((src_y & 0xffff) * 15625) >> 10,
+                             fb->width, fb->height);
                return -ENOSPC;
        }
 
@@ -766,14 +769,18 @@ static int atomic_remove_fb(struct drm_framebuffer *fb)
        struct drm_plane *plane;
        struct drm_connector *conn;
        struct drm_connector_state *conn_state;
-       int i, ret = 0;
+       int i, ret;
        unsigned plane_mask;
+       bool disable_crtcs = false;
 
-       state = drm_atomic_state_alloc(dev);
-       if (!state)
-               return -ENOMEM;
-
+retry_disable:
        drm_modeset_acquire_init(&ctx, 0);
+
+       state = drm_atomic_state_alloc(dev);
+       if (!state) {
+               ret = -ENOMEM;
+               goto out;
+       }
        state->acquire_ctx = &ctx;
 
 retry:
@@ -794,7 +801,7 @@ retry:
                        goto unlock;
                }
 
-               if (plane_state->crtc->primary == plane) {
+               if (disable_crtcs && plane_state->crtc->primary == plane) {
                        struct drm_crtc_state *crtc_state;
 
                        crtc_state = drm_atomic_get_existing_crtc_state(state, plane_state->crtc);
@@ -819,6 +826,7 @@ retry:
                plane->old_fb = plane->fb;
        }
 
+       /* This list is only filled when disable_crtcs is set. */
        for_each_new_connector_in_state(state, conn, conn_state, i) {
                ret = drm_atomic_set_crtc_for_connector(conn_state, NULL);
 
@@ -841,9 +849,15 @@ unlock:
 
        drm_atomic_state_put(state);
 
+out:
        drm_modeset_drop_locks(&ctx);
        drm_modeset_acquire_fini(&ctx);
 
+       if (ret == -EINVAL && !disable_crtcs) {
+               disable_crtcs = true;
+               goto retry_disable;
+       }
+
        return ret;
 }
 
@@ -957,3 +971,60 @@ int drm_framebuffer_plane_height(int height,
        return fb_plane_height(height, fb->format, plane);
 }
 EXPORT_SYMBOL(drm_framebuffer_plane_height);
+
+void drm_framebuffer_print_info(struct drm_printer *p, unsigned int indent,
+                               const struct drm_framebuffer *fb)
+{
+       struct drm_format_name_buf format_name;
+       unsigned int i;
+
+       drm_printf_indent(p, indent, "refcount=%u\n",
+                         drm_framebuffer_read_refcount(fb));
+       drm_printf_indent(p, indent, "format=%s\n",
+                         drm_get_format_name(fb->format->format, &format_name));
+       drm_printf_indent(p, indent, "modifier=0x%llx\n", fb->modifier);
+       drm_printf_indent(p, indent, "size=%ux%u\n", fb->width, fb->height);
+       drm_printf_indent(p, indent, "layers:\n");
+
+       for (i = 0; i < fb->format->num_planes; i++) {
+               drm_printf_indent(p, indent + 1, "size[%u]=%dx%d\n", i,
+                                 drm_framebuffer_plane_width(fb->width, fb, i),
+                                 drm_framebuffer_plane_height(fb->height, fb, i));
+               drm_printf_indent(p, indent + 1, "pitch[%u]=%u\n", i, fb->pitches[i]);
+               drm_printf_indent(p, indent + 1, "offset[%u]=%u\n", i, fb->offsets[i]);
+               drm_printf_indent(p, indent + 1, "obj[%u]:%s\n", i,
+                                 fb->obj[i] ? "" : "(null)");
+               if (fb->obj[i])
+                       drm_gem_print_info(p, indent + 2, fb->obj[i]);
+       }
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int drm_framebuffer_info(struct seq_file *m, void *data)
+{
+       struct drm_info_node *node = m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct drm_printer p = drm_seq_file_printer(m);
+       struct drm_framebuffer *fb;
+
+       mutex_lock(&dev->mode_config.fb_lock);
+       drm_for_each_fb(fb, dev) {
+               drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
+               drm_framebuffer_print_info(&p, 1, fb);
+       }
+       mutex_unlock(&dev->mode_config.fb_lock);
+
+       return 0;
+}
+
+static const struct drm_info_list drm_framebuffer_debugfs_list[] = {
+       { "framebuffer", drm_framebuffer_info, 0 },
+};
+
+int drm_framebuffer_debugfs_init(struct drm_minor *minor)
+{
+       return drm_debugfs_create_files(drm_framebuffer_debugfs_list,
+                               ARRAY_SIZE(drm_framebuffer_debugfs_list),
+                               minor->debugfs_root, minor);
+}
+#endif
index 55d6182..01f8d94 100644 (file)
@@ -40,6 +40,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_vma_manager.h>
 #include <drm/drm_gem.h>
+#include <drm/drm_print.h>
 #include "drm_internal.h"
 
 /** @file drm_gem.c
@@ -348,7 +349,7 @@ EXPORT_SYMBOL_GPL(drm_gem_dumb_map_offset);
  * @file: drm file-private structure to remove the dumb handle from
  * @dev: corresponding drm_device
  * @handle: the dumb handle to remove
- * 
+ *
  * This implements the &drm_driver.dumb_destroy kms driver callback for drivers
  * which use gem to manage their backing storage.
  */
@@ -365,7 +366,7 @@ EXPORT_SYMBOL(drm_gem_dumb_destroy);
  * @file_priv: drm file-private structure to register the handle for
  * @obj: object to register
  * @handlep: pointer to return the created handle to the caller
- * 
+ *
  * This expects the &drm_device.object_name_lock to be held already and will
  * drop it before returning. Used to avoid races in establishing new handles
  * when importing an object from either an flink name or a dma-buf.
@@ -1040,3 +1041,19 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
        return ret;
 }
 EXPORT_SYMBOL(drm_gem_mmap);
+
+void drm_gem_print_info(struct drm_printer *p, unsigned int indent,
+                       const struct drm_gem_object *obj)
+{
+       drm_printf_indent(p, indent, "name=%d\n", obj->name);
+       drm_printf_indent(p, indent, "refcount=%u\n",
+                         kref_read(&obj->refcount));
+       drm_printf_indent(p, indent, "start=%08lx\n",
+                         drm_vma_node_start(&obj->vma_node));
+       drm_printf_indent(p, indent, "size=%zu\n", obj->size);
+       drm_printf_indent(p, indent, "imported=%s\n",
+                         obj->import_attach ? "yes" : "no");
+
+       if (obj->dev->driver->gem_print_info)
+               obj->dev->driver->gem_print_info(p, indent, obj);
+}
index 020e766..80a5115 100644 (file)
@@ -397,31 +397,24 @@ unsigned long drm_gem_cma_get_unmapped_area(struct file *filp,
 EXPORT_SYMBOL_GPL(drm_gem_cma_get_unmapped_area);
 #endif
 
-#ifdef CONFIG_DEBUG_FS
 /**
- * drm_gem_cma_describe - describe a CMA GEM object for debugfs
- * @cma_obj: CMA GEM object
- * @m: debugfs file handle
+ * drm_gem_cma_print_info() - Print &drm_gem_cma_object info for debugfs
+ * @p: DRM printer
+ * @indent: Tab indentation level
+ * @obj: GEM object
  *
- * This function can be used to dump a human-readable representation of the
- * CMA GEM object into a synthetic file.
+ * This function can be used as the &drm_driver->gem_print_info callback.
+ * It prints paddr and vaddr for use in e.g. debugfs output.
  */
-void drm_gem_cma_describe(struct drm_gem_cma_object *cma_obj,
-                         struct seq_file *m)
+void drm_gem_cma_print_info(struct drm_printer *p, unsigned int indent,
+                           const struct drm_gem_object *obj)
 {
-       struct drm_gem_object *obj = &cma_obj->base;
-       uint64_t off;
-
-       off = drm_vma_node_start(&obj->vma_node);
-
-       seq_printf(m, "%2d (%2d) %08llx %pad %p %zu",
-                       obj->name, kref_read(&obj->refcount),
-                       off, &cma_obj->paddr, cma_obj->vaddr, obj->size);
+       const struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj);
 
-       seq_printf(m, "\n");
+       drm_printf_indent(p, indent, "paddr=%pad\n", &cma_obj->paddr);
+       drm_printf_indent(p, indent, "vaddr=%p\n", cma_obj->vaddr);
 }
-EXPORT_SYMBOL_GPL(drm_gem_cma_describe);
-#endif
+EXPORT_SYMBOL(drm_gem_cma_print_info);
 
 /**
  * drm_gem_cma_prime_get_sg_table - provide a scatter/gather table of pinned
@@ -482,8 +475,26 @@ drm_gem_cma_prime_import_sg_table(struct drm_device *dev,
 {
        struct drm_gem_cma_object *cma_obj;
 
-       if (sgt->nents != 1)
-               return ERR_PTR(-EINVAL);
+       if (sgt->nents != 1) {
+               /* check if the entries in the sg_table are contiguous */
+               dma_addr_t next_addr = sg_dma_address(sgt->sgl);
+               struct scatterlist *s;
+               unsigned int i;
+
+               for_each_sg(sgt->sgl, s, sgt->nents, i) {
+                       /*
+                        * sg_dma_address(s) is only valid for entries
+                        * that have sg_dma_len(s) != 0
+                        */
+                       if (!sg_dma_len(s))
+                               continue;
+
+                       if (sg_dma_address(s) != next_addr)
+                               return ERR_PTR(-EINVAL);
+
+                       next_addr = sg_dma_address(s) + sg_dma_len(s);
+               }
+       }
 
        /* Create a CMA GEM buffer. */
        cma_obj = __drm_gem_cma_create(dev, attach->dmabuf->size);
index c9d5a6c..b72242e 100644 (file)
@@ -111,6 +111,8 @@ int drm_gem_open_ioctl(struct drm_device *dev, void *data,
                       struct drm_file *file_priv);
 void drm_gem_open(struct drm_device *dev, struct drm_file *file_private);
 void drm_gem_release(struct drm_device *dev, struct drm_file *file_private);
+void drm_gem_print_info(struct drm_printer *p, unsigned int indent,
+                       const struct drm_gem_object *obj);
 
 /* drm_debugfs.c drm_debugfs_crc.c */
 #if defined(CONFIG_DEBUG_FS)
@@ -178,3 +180,8 @@ int drm_syncobj_reset_ioctl(struct drm_device *dev, void *data,
                            struct drm_file *file_private);
 int drm_syncobj_signal_ioctl(struct drm_device *dev, void *data,
                             struct drm_file *file_private);
+
+/* drm_framebuffer.c */
+void drm_framebuffer_print_info(struct drm_printer *p, unsigned int indent,
+                               const struct drm_framebuffer *fb);
+int drm_framebuffer_debugfs_init(struct drm_minor *minor);
index 61a1c8e..eb86bc3 100644 (file)
@@ -92,7 +92,7 @@
  * some basic allocator dumpers for debugging.
  *
  * Note that this range allocator is not thread-safe, drivers need to protect
- * modifications with their on locking. The idea behind this is that for a full
+ * modifications with their own locking. The idea behind this is that for a full
  * memory manager additional data needs to be protected anyway, hence internal
  * locking would be fully redundant.
  */
index 759ed93..f1be8cd 100644 (file)
@@ -99,97 +99,6 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc,
        return count;
 }
 
-/**
- * drm_plane_helper_check_state() - Check plane state for validity
- * @state: plane state to check
- * @clip: integer clipping coordinates
- * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
- * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
- * @can_position: is it legal to position the plane such that it
- *                doesn't cover the entire crtc?  This will generally
- *                only be false for primary planes.
- * @can_update_disabled: can the plane be updated while the crtc
- *                       is disabled?
- *
- * Checks that a desired plane update is valid, and updates various
- * bits of derived state (clipped coordinates etc.). Drivers that provide
- * their own plane handling rather than helper-provided implementations may
- * still wish to call this function to avoid duplication of error checking
- * code.
- *
- * RETURNS:
- * Zero if update appears valid, error code on failure
- */
-int drm_plane_helper_check_state(struct drm_plane_state *state,
-                                const struct drm_rect *clip,
-                                int min_scale,
-                                int max_scale,
-                                bool can_position,
-                                bool can_update_disabled)
-{
-       struct drm_crtc *crtc = state->crtc;
-       struct drm_framebuffer *fb = state->fb;
-       struct drm_rect *src = &state->src;
-       struct drm_rect *dst = &state->dst;
-       unsigned int rotation = state->rotation;
-       int hscale, vscale;
-
-       *src = drm_plane_state_src(state);
-       *dst = drm_plane_state_dest(state);
-
-       if (!fb) {
-               state->visible = false;
-               return 0;
-       }
-
-       /* crtc should only be NULL when disabling (i.e., !fb) */
-       if (WARN_ON(!crtc)) {
-               state->visible = false;
-               return 0;
-       }
-
-       if (!crtc->enabled && !can_update_disabled) {
-               DRM_DEBUG_KMS("Cannot update plane of a disabled CRTC.\n");
-               return -EINVAL;
-       }
-
-       drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation);
-
-       /* Check scaling */
-       hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
-       vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
-       if (hscale < 0 || vscale < 0) {
-               DRM_DEBUG_KMS("Invalid scaling of plane\n");
-               drm_rect_debug_print("src: ", &state->src, true);
-               drm_rect_debug_print("dst: ", &state->dst, false);
-               return -ERANGE;
-       }
-
-       state->visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale);
-
-       drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation);
-
-       if (!state->visible)
-               /*
-                * Plane isn't visible; some drivers can handle this
-                * so we just return success here.  Drivers that can't
-                * (including those that use the primary plane helper's
-                * update function) will return an error from their
-                * update_plane handler.
-                */
-               return 0;
-
-       if (!can_position && !drm_rect_equals(dst, clip)) {
-               DRM_DEBUG_KMS("Plane must cover entire CRTC\n");
-               drm_rect_debug_print("dst: ", dst, false);
-               drm_rect_debug_print("clip: ", clip, false);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(drm_plane_helper_check_state);
-
 /**
  * drm_plane_helper_check_update() - Check plane update for validity
  * @plane: plane object to update
@@ -230,7 +139,7 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
                                  bool can_update_disabled,
                                  bool *visible)
 {
-       struct drm_plane_state state = {
+       struct drm_plane_state plane_state = {
                .plane = plane,
                .crtc = crtc,
                .fb = fb,
@@ -245,18 +154,22 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
                .rotation = rotation,
                .visible = *visible,
        };
+       struct drm_crtc_state crtc_state = {
+               .crtc = crtc,
+               .enable = crtc->enabled,
+       };
        int ret;
 
-       ret = drm_plane_helper_check_state(&state, clip,
-                                          min_scale, max_scale,
-                                          can_position,
-                                          can_update_disabled);
+       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
+                                                 clip, min_scale, max_scale,
+                                                 can_position,
+                                                 can_update_disabled);
        if (ret)
                return ret;
 
-       *src = state.src;
-       *dst = state.dst;
-       *visible = state.visible;
+       *src = plane_state.src;
+       *dst = plane_state.dst;
+       *visible = plane_state.visible;
 
        return 0;
 }
index 74c466a..781518f 100644 (file)
@@ -23,6 +23,8 @@
  * Rob Clark <robdclark@gmail.com>
  */
 
+#define DEBUG /* for pr_debug() */
+
 #include <stdarg.h>
 #include <linux/seq_file.h>
 #include <drm/drmP.h>
@@ -53,13 +55,57 @@ EXPORT_SYMBOL(__drm_printfn_debug);
  */
 void drm_printf(struct drm_printer *p, const char *f, ...)
 {
-       struct va_format vaf;
        va_list args;
 
        va_start(args, f);
-       vaf.fmt = f;
-       vaf.va = &args;
-       p->printfn(p, &vaf);
+       drm_vprintf(p, f, &args);
        va_end(args);
 }
 EXPORT_SYMBOL(drm_printf);
+
+#define DRM_PRINTK_FMT "[" DRM_NAME ":%s]%s %pV"
+
+void drm_dev_printk(const struct device *dev, const char *level,
+                   unsigned int category, const char *function_name,
+                   const char *prefix, const char *format, ...)
+{
+       struct va_format vaf;
+       va_list args;
+
+       if (category != DRM_UT_NONE && !(drm_debug & category))
+               return;
+
+       va_start(args, format);
+       vaf.fmt = format;
+       vaf.va = &args;
+
+       if (dev)
+               dev_printk(level, dev, DRM_PRINTK_FMT, function_name, prefix,
+                          &vaf);
+       else
+               printk("%s" DRM_PRINTK_FMT, level, function_name, prefix, &vaf);
+
+       va_end(args);
+}
+EXPORT_SYMBOL(drm_dev_printk);
+
+void drm_printk(const char *level, unsigned int category,
+               const char *format, ...)
+{
+       struct va_format vaf;
+       va_list args;
+
+       if (category != DRM_UT_NONE && !(drm_debug & category))
+               return;
+
+       va_start(args, format);
+       vaf.fmt = format;
+       vaf.va = &args;
+
+       printk("%s" "[" DRM_NAME ":%ps]%s %pV",
+              level, __builtin_return_address(0),
+              strcmp(level, KERN_ERR) == 0 ? " *ERROR*" : "", &vaf);
+
+       va_end(args);
+}
+EXPORT_SYMBOL(drm_printk);
index dc9fd10..9f3b1c9 100644 (file)
@@ -103,10 +103,11 @@ static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane,
        clip.x2 = crtc_state->adjusted_mode.hdisplay;
        clip.y2 = crtc_state->adjusted_mode.vdisplay;
 
-       ret = drm_plane_helper_check_state(plane_state, &clip,
-                                          DRM_PLANE_HELPER_NO_SCALING,
-                                          DRM_PLANE_HELPER_NO_SCALING,
-                                          false, true);
+       ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state,
+                                                 &clip,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 false, true);
        if (ret)
                return ret;
 
index f776fc1..9b733c5 100644 (file)
@@ -106,7 +106,8 @@ static int drm_syncobj_fence_get_or_add_callback(struct drm_syncobj *syncobj,
         * callback when a fence has already been set.
         */
        if (syncobj->fence) {
-               *fence = dma_fence_get(syncobj->fence);
+               *fence = dma_fence_get(rcu_dereference_protected(syncobj->fence,
+                                                                lockdep_is_held(&syncobj->lock)));
                ret = 1;
        } else {
                *fence = NULL;
@@ -168,8 +169,9 @@ void drm_syncobj_replace_fence(struct drm_syncobj *syncobj,
 
        spin_lock(&syncobj->lock);
 
-       old_fence = syncobj->fence;
-       syncobj->fence = fence;
+       old_fence = rcu_dereference_protected(syncobj->fence,
+                                             lockdep_is_held(&syncobj->lock));
+       rcu_assign_pointer(syncobj->fence, fence);
 
        if (fence != old_fence) {
                list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) {
@@ -659,7 +661,8 @@ static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj,
                container_of(cb, struct syncobj_wait_entry, syncobj_cb);
 
        /* This happens inside the syncobj lock */
-       wait->fence = dma_fence_get(syncobj->fence);
+       wait->fence = dma_fence_get(rcu_dereference_protected(syncobj->fence,
+                                                             lockdep_is_held(&syncobj->lock)));
        wake_up_process(wait->task);
 }
 
index 3717b3d..32d9bcf 100644 (file)
@@ -663,14 +663,16 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
        delta_ns = div_s64(1000000LL * (vpos * mode->crtc_htotal + hpos),
                           mode->crtc_clock);
 
-       /* save this only for debugging purposes */
-       ts_etime = ktime_to_timespec64(etime);
-       ts_vblank_time = ktime_to_timespec64(*vblank_time);
        /* Subtract time delta from raw timestamp to get final
         * vblank_time timestamp for end of vblank.
         */
-       etime = ktime_sub_ns(etime, delta_ns);
-       *vblank_time = etime;
+       *vblank_time = ktime_sub_ns(etime, delta_ns);
+
+       if ((drm_debug & DRM_UT_VBL) == 0)
+               return true;
+
+       ts_etime = ktime_to_timespec64(etime);
+       ts_vblank_time = ktime_to_timespec64(*vblank_time);
 
        DRM_DEBUG_VBL("crtc %u : v p(%d,%d)@ %lld.%06ld -> %lld.%06ld [e %d us, %d rep]\n",
                      pipe, hpos, vpos,
index 28f1226..23c749c 100644 (file)
@@ -203,21 +203,16 @@ EXPORT_SYMBOL(drm_vma_offset_lookup_locked);
 int drm_vma_offset_add(struct drm_vma_offset_manager *mgr,
                       struct drm_vma_offset_node *node, unsigned long pages)
 {
-       int ret;
+       int ret = 0;
 
        write_lock(&mgr->vm_lock);
 
-       if (drm_mm_node_allocated(&node->vm_node)) {
-               ret = 0;
-               goto out_unlock;
-       }
+       if (!drm_mm_node_allocated(&node->vm_node))
+               ret = drm_mm_insert_node(&mgr->vm_addr_space_mm,
+                                        &node->vm_node, pages);
 
-       ret = drm_mm_insert_node(&mgr->vm_addr_space_mm, &node->vm_node, pages);
-       if (ret)
-               goto out_unlock;
-
-out_unlock:
        write_unlock(&mgr->vm_lock);
+
        return ret;
 }
 EXPORT_SYMBOL(drm_vma_offset_add);
index 82d1b7e..a4b75a4 100644 (file)
@@ -829,7 +829,8 @@ static void hdmi_reg_infoframes(struct hdmi_context *hdata)
                DRM_INFO("%s: invalid AVI infoframe (%d)\n", __func__, ret);
        }
 
-       ret = drm_hdmi_vendor_infoframe_from_display_mode(&frm.vendor.hdmi, m);
+       ret = drm_hdmi_vendor_infoframe_from_display_mode(&frm.vendor.hdmi,
+                                                         &hdata->connector, m);
        if (!ret)
                ret = hdmi_vendor_infoframe_pack(&frm.vendor.hdmi, buf,
                                sizeof(buf));
index 0eaf11c..ccb161c 100644 (file)
@@ -395,7 +395,7 @@ static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
                        psb_mmu_clflush(pd->driver, (void *)&v[pt->index]);
                        atomic_set(&pd->driver->needs_tlbflush, 1);
                }
-               kunmap_atomic(pt->v);
+               kunmap_atomic(v);
                spin_unlock(&pd->driver->lock);
                psb_mmu_free_pt(pt);
                return;
index 37a3be7..8f5cc1f 100644 (file)
@@ -527,4 +527,4 @@ module_exit(psb_exit);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
+MODULE_LICENSE("GPL");
index 821497d..4918efc 100644 (file)
@@ -36,7 +36,6 @@
 #include "mmu.h"
 
 #define DRIVER_AUTHOR "Alan Cox <alan@linux.intel.com> and others"
-#define DRIVER_LICENSE "GPL"
 
 #define DRIVER_NAME "gma500"
 #define DRIVER_DESC "DRM driver for the Intel GMA500, GMA600, GMA3600, GMA3650"
index 1278152..cd3f087 100644 (file)
@@ -1100,7 +1100,6 @@ static int tda998x_connector_get_modes(struct drm_connector *connector)
 
        drm_mode_connector_update_edid_property(connector, edid);
        n = drm_add_edid_modes(connector, edid);
-       drm_edid_to_eld(connector, edid);
 
        kfree(edid);
 
index 878acc4..e0fffd8 100644 (file)
@@ -9314,11 +9314,12 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state,
        u32 offset;
        int ret;
 
-       ret = drm_plane_helper_check_state(&plane_state->base,
-                                          &plane_state->clip,
-                                          DRM_PLANE_HELPER_NO_SCALING,
-                                          DRM_PLANE_HELPER_NO_SCALING,
-                                          true, true);
+       ret = drm_atomic_helper_check_plane_state(&plane_state->base,
+                                                 &crtc_state->base,
+                                                 &plane_state->clip,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 true, true);
        if (ret)
                return ret;
 
@@ -12794,10 +12795,11 @@ intel_check_primary_plane(struct intel_plane *plane,
                can_position = true;
        }
 
-       ret = drm_plane_helper_check_state(&state->base,
-                                          &state->clip,
-                                          min_scale, max_scale,
-                                          can_position, true);
+       ret = drm_atomic_helper_check_plane_state(&state->base,
+                                                 &crtc_state->base,
+                                                 &state->clip,
+                                                 min_scale, max_scale,
+                                                 can_position, true);
        if (ret)
                return ret;
 
index 158438b..65260fb 100644 (file)
@@ -5868,7 +5868,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
                if (drm_add_edid_modes(connector, edid)) {
                        drm_mode_connector_update_edid_property(connector,
                                                                edid);
-                       drm_edid_to_eld(connector, edid);
                } else {
                        kfree(edid);
                        edid = ERR_PTR(-EINVAL);
index 4dea833..e039702 100644 (file)
@@ -513,12 +513,14 @@ static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder,
 
 static void
 intel_hdmi_set_hdmi_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)
 {
        union hdmi_infoframe frame;
        int ret;
 
        ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
+                                                         conn_state->connector,
                                                          &crtc_state->base.adjusted_mode);
        if (ret < 0)
                return;
@@ -585,7 +587,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder,
 
        intel_hdmi_set_avi_infoframe(encoder, crtc_state);
        intel_hdmi_set_spd_infoframe(encoder, crtc_state);
-       intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
+       intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
 }
 
 static bool hdmi_sink_is_deep_color(const struct drm_connector_state *conn_state)
@@ -726,7 +728,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder,
 
        intel_hdmi_set_avi_infoframe(encoder, crtc_state);
        intel_hdmi_set_spd_infoframe(encoder, crtc_state);
-       intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
+       intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
 }
 
 static void cpt_set_infoframes(struct drm_encoder *encoder,
@@ -769,7 +771,7 @@ static void cpt_set_infoframes(struct drm_encoder *encoder,
 
        intel_hdmi_set_avi_infoframe(encoder, crtc_state);
        intel_hdmi_set_spd_infoframe(encoder, crtc_state);
-       intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
+       intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
 }
 
 static void vlv_set_infoframes(struct drm_encoder *encoder,
@@ -822,7 +824,7 @@ static void vlv_set_infoframes(struct drm_encoder *encoder,
 
        intel_hdmi_set_avi_infoframe(encoder, crtc_state);
        intel_hdmi_set_spd_infoframe(encoder, crtc_state);
-       intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
+       intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
 }
 
 static void hsw_set_infoframes(struct drm_encoder *encoder,
@@ -855,7 +857,7 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
 
        intel_hdmi_set_avi_infoframe(encoder, crtc_state);
        intel_hdmi_set_spd_infoframe(encoder, crtc_state);
-       intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
+       intel_hdmi_set_hdmi_infoframe(encoder, crtc_state, conn_state);
 }
 
 void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable)
index 28a778b..4e43f87 100644 (file)
@@ -57,7 +57,6 @@ int intel_connector_update_modes(struct drm_connector *connector,
 
        drm_mode_connector_update_edid_property(connector, edid);
        ret = drm_add_edid_modes(connector, edid);
-       drm_edid_to_eld(connector, edid);
 
        intel_connector_update_eld_conn_type(connector);
 
index 247c60e..5a67dae 100644 (file)
@@ -342,10 +342,10 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
        clip.y1 = 0;
        clip.x2 = crtc_state->adjusted_mode.hdisplay;
        clip.y2 = crtc_state->adjusted_mode.vdisplay;
-       ret = drm_plane_helper_check_state(state, &clip,
-                                          DRM_PLANE_HELPER_NO_SCALING,
-                                          DRM_PLANE_HELPER_NO_SCALING,
-                                          can_position, true);
+       ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 can_position, true);
        if (ret)
                return ret;
 
index 6f12189..5ef898b 100644 (file)
@@ -111,10 +111,10 @@ static int mtk_plane_atomic_check(struct drm_plane *plane,
        clip.x2 = crtc_state->mode.hdisplay;
        clip.y2 = crtc_state->mode.vdisplay;
 
-       return drm_plane_helper_check_state(state, &clip,
-                                           DRM_PLANE_HELPER_NO_SCALING,
-                                           DRM_PLANE_HELPER_NO_SCALING,
-                                           true, true);
+       return drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
+                                                  DRM_PLANE_HELPER_NO_SCALING,
+                                                  DRM_PLANE_HELPER_NO_SCALING,
+                                                  true, true);
 }
 
 static void mtk_plane_atomic_update(struct drm_plane *plane,
index 3ff5027..59a1102 100644 (file)
@@ -1054,7 +1054,8 @@ static int mtk_hdmi_setup_vendor_specific_infoframe(struct mtk_hdmi *hdmi,
        u8 buffer[10];
        ssize_t err;
 
-       err = drm_hdmi_vendor_infoframe_from_display_mode(&frame, mode);
+       err = drm_hdmi_vendor_infoframe_from_display_mode(&frame,
+                                                         &hdmi->conn, mode);
        if (err) {
                dev_err(hdmi->dev,
                        "Failed to get vendor infoframe from mode: %zd\n", err);
@@ -1222,7 +1223,6 @@ static int mtk_hdmi_conn_get_modes(struct drm_connector *conn)
        drm_mode_connector_update_edid_property(conn, edid);
 
        ret = drm_add_edid_modes(conn, edid);
-       drm_edid_to_eld(conn, edid);
        kfree(edid);
        return ret;
 }
index 17e96fa..d0a6ac8 100644 (file)
@@ -61,10 +61,10 @@ static int meson_plane_atomic_check(struct drm_plane *plane,
        clip.x2 = crtc_state->mode.hdisplay;
        clip.y2 = crtc_state->mode.vdisplay;
 
-       return drm_plane_helper_check_state(state, &clip,
-                                           DRM_PLANE_HELPER_NO_SCALING,
-                                           DRM_PLANE_HELPER_NO_SCALING,
-                                           true, true);
+       return drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
+                                                  DRM_PLANE_HELPER_NO_SCALING,
+                                                  DRM_PLANE_HELPER_NO_SCALING,
+                                                  true, true);
 }
 
 /* Takes a fixed 16.16 number and converts it to integer. */
index be50445..ee41423 100644 (file)
@@ -327,8 +327,9 @@ static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state,
        min_scale = FRAC_16_16(1, 8);
        max_scale = FRAC_16_16(8, 1);
 
-       ret = drm_plane_helper_check_state(state, &clip, min_scale,
-                                          max_scale, true, true);
+       ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
+                                                 min_scale, max_scale,
+                                                 true, true);
        if (ret)
                return ret;
 
@@ -505,8 +506,9 @@ static int mdp5_plane_atomic_async_check(struct drm_plane *plane,
        min_scale = FRAC_16_16(1, 8);
        max_scale = FRAC_16_16(8, 1);
 
-       ret = drm_plane_helper_check_state(state, &clip, min_scale,
-                                          max_scale, true, true);
+       ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
+                                                 min_scale, max_scale,
+                                                 true, true);
        if (ret)
                return ret;
 
index 584466e..6533694 100644 (file)
@@ -1143,10 +1143,11 @@ nv50_curs_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
 {
        int ret;
 
-       ret = drm_plane_helper_check_state(&asyw->state, &asyw->clip,
-                                          DRM_PLANE_HELPER_NO_SCALING,
-                                          DRM_PLANE_HELPER_NO_SCALING,
-                                          true, true);
+       ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
+                                                 &asyw->clip,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 true, true);
        asyh->curs.visible = asyw->state.visible;
        if (ret || !asyh->curs.visible)
                return ret;
@@ -1432,10 +1433,11 @@ nv50_base_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
        if (!fb->format->depth)
                return -EINVAL;
 
-       ret = drm_plane_helper_check_state(&asyw->state, &asyw->clip,
-                                          DRM_PLANE_HELPER_NO_SCALING,
-                                          DRM_PLANE_HELPER_NO_SCALING,
-                                          false, true);
+       ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
+                                                 &asyw->clip,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 false, true);
        if (ret)
                return ret;
 
@@ -2688,7 +2690,6 @@ nv50_audio_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
        if (!drm_detect_monitor_audio(nv_connector->edid))
                return;
 
-       drm_edid_to_eld(&nv_connector->base, nv_connector->edid);
        memcpy(args.data, nv_connector->base.eld, sizeof(args.data));
 
        nvif_mthd(disp->disp, 0, &args,
@@ -2755,7 +2756,8 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
                        = hdmi_infoframe_pack(&avi_frame, args.infoframes, 17);
        }
 
-       ret = drm_hdmi_vendor_infoframe_from_display_mode(&vendor_frame.vendor.hdmi, mode);
+       ret = drm_hdmi_vendor_infoframe_from_display_mode(&vendor_frame.vendor.hdmi,
+                                                         &nv_connector->base, mode);
        if (!ret) {
                /* We have a Vendor InfoFrame, populate it to the display */
                args.pwr.vendor_infoframe_length
@@ -3064,10 +3066,8 @@ nv50_mstc_get_modes(struct drm_connector *connector)
 
        mstc->edid = drm_dp_mst_get_edid(&mstc->connector, mstc->port->mgr, mstc->port);
        drm_mode_connector_update_edid_property(&mstc->connector, mstc->edid);
-       if (mstc->edid) {
+       if (mstc->edid)
                ret = drm_add_edid_modes(&mstc->connector, mstc->edid);
-               drm_edid_to_eld(&mstc->connector, mstc->edid);
-       }
 
        if (!mstc->connector.display_info.bpc)
                mstc->connector.display_info.bpc = 8;
index 890fd6f..d964d45 100644 (file)
@@ -221,7 +221,7 @@ static struct rpi_touchscreen *panel_to_ts(struct drm_panel *panel)
        return container_of(panel, struct rpi_touchscreen, base);
 }
 
-static u8 rpi_touchscreen_i2c_read(struct rpi_touchscreen *ts, u8 reg)
+static int rpi_touchscreen_i2c_read(struct rpi_touchscreen *ts, u8 reg)
 {
        return i2c_smbus_read_byte_data(ts->i2c, reg);
 }
index b7c4709..5591984 100644 (file)
@@ -1356,6 +1356,38 @@ static const struct panel_desc lg_lp129qe = {
        },
 };
 
+static const struct drm_display_mode mitsubishi_aa070mc01_mode = {
+       .clock = 30400,
+       .hdisplay = 800,
+       .hsync_start = 800 + 0,
+       .hsync_end = 800 + 1,
+       .htotal = 800 + 0 + 1 + 160,
+       .vdisplay = 480,
+       .vsync_start = 480 + 0,
+       .vsync_end = 480 + 48 + 1,
+       .vtotal = 480 + 48 + 1 + 0,
+       .vrefresh = 60,
+       .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+};
+
+static const struct panel_desc mitsubishi_aa070mc01 = {
+       .modes = &mitsubishi_aa070mc01_mode,
+       .num_modes = 1,
+       .bpc = 8,
+       .size = {
+               .width = 152,
+               .height = 91,
+       },
+
+       .delay = {
+               .enable = 200,
+               .unprepare = 200,
+               .disable = 400,
+       },
+       .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .bus_flags = DRM_BUS_FLAG_DE_HIGH,
+};
+
 static const struct display_timing nec_nl12880bc20_05_timing = {
        .pixelclock = { 67000000, 71000000, 75000000 },
        .hactive = { 1280, 1280, 1280 },
@@ -1837,6 +1869,30 @@ static const struct panel_desc tianma_tm070jdhg30 = {
        .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
 };
 
+static const struct display_timing tianma_tm070rvhg71_timing = {
+       .pixelclock = { 27700000, 29200000, 39600000 },
+       .hactive = { 800, 800, 800 },
+       .hfront_porch = { 12, 40, 212 },
+       .hback_porch = { 88, 88, 88 },
+       .hsync_len = { 1, 1, 40 },
+       .vactive = { 480, 480, 480 },
+       .vfront_porch = { 1, 13, 88 },
+       .vback_porch = { 32, 32, 32 },
+       .vsync_len = { 1, 1, 3 },
+       .flags = DISPLAY_FLAGS_DE_HIGH,
+};
+
+static const struct panel_desc tianma_tm070rvhg71 = {
+       .timings = &tianma_tm070rvhg71_timing,
+       .num_timings = 1,
+       .bpc = 8,
+       .size = {
+               .width = 154,
+               .height = 86,
+       },
+       .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+};
+
 static const struct drm_display_mode toshiba_lt089ac29000_mode = {
        .clock = 79500,
        .hdisplay = 1280,
@@ -2085,6 +2141,9 @@ static const struct of_device_id platform_of_match[] = {
        }, {
                .compatible = "lg,lp129qe",
                .data = &lg_lp129qe,
+       }, {
+               .compatible = "mitsubishi,aa070mc01-ca1",
+               .data = &mitsubishi_aa070mc01,
        }, {
                .compatible = "nec,nl12880bc20-05",
                .data = &nec_nl12880bc20_05,
@@ -2142,6 +2201,9 @@ static const struct of_device_id platform_of_match[] = {
        }, {
                .compatible = "tianma,tm070jdhg30",
                .data = &tianma_tm070jdhg30,
+       }, {
+               .compatible = "tianma,tm070rvhg71",
+               .data = &tianma_tm070rvhg71,
        }, {
                .compatible = "toshiba,lt089ac29000",
                .data = &toshiba_lt089ac29000,
index ab48238..586ecd6 100644 (file)
@@ -123,11 +123,8 @@ int qxl_mmap(struct file *filp, struct vm_area_struct *vma)
        struct qxl_device *qdev;
        int r;
 
-       if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) {
-               pr_info("%s: vma->vm_pgoff (%ld) < DRM_FILE_PAGE_OFFSET\n",
-                       __func__, vma->vm_pgoff);
+       if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
                return -EINVAL;
-       }
 
        file_priv = filp->private_data;
        qdev = file_priv->minor->dev->dev_private;
index 59dcefb..5012f5e 100644 (file)
@@ -392,7 +392,6 @@ static int radeon_ddc_get_modes(struct drm_connector *connector)
        if (radeon_connector->edid) {
                drm_mode_connector_update_edid_property(connector, radeon_connector->edid);
                ret = drm_add_edid_modes(connector, radeon_connector->edid);
-               drm_edid_to_eld(connector, radeon_connector->edid);
                return ret;
        }
        drm_mode_connector_update_edid_property(connector, NULL);
index 2917ea1..183b4b4 100644 (file)
@@ -197,7 +197,6 @@ static int radeon_dp_mst_get_ddc_modes(struct drm_connector *connector)
        if (radeon_connector->edid) {
                drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
                ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
-               drm_edid_to_eld(&radeon_connector->base, radeon_connector->edid);
                return ret;
        }
        drm_mode_connector_update_edid_property(&radeon_connector->base, NULL);
index 93b7102..1262120 100644 (file)
@@ -267,11 +267,10 @@ static struct drm_encoder_funcs rockchip_dp_encoder_funcs = {
        .destroy = rockchip_dp_drm_encoder_destroy,
 };
 
-static int rockchip_dp_init(struct rockchip_dp_device *dp)
+static int rockchip_dp_of_probe(struct rockchip_dp_device *dp)
 {
        struct device *dev = dp->dev;
        struct device_node *np = dev->of_node;
-       int ret;
 
        dp->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
        if (IS_ERR(dp->grf)) {
@@ -301,19 +300,6 @@ static int rockchip_dp_init(struct rockchip_dp_device *dp)
                return PTR_ERR(dp->rst);
        }
 
-       ret = clk_prepare_enable(dp->pclk);
-       if (ret < 0) {
-               DRM_DEV_ERROR(dp->dev, "failed to enable pclk %d\n", ret);
-               return ret;
-       }
-
-       ret = rockchip_dp_pre_init(dp);
-       if (ret < 0) {
-               DRM_DEV_ERROR(dp->dev, "failed to pre init %d\n", ret);
-               clk_disable_unprepare(dp->pclk);
-               return ret;
-       }
-
        return 0;
 }
 
@@ -359,10 +345,6 @@ static int rockchip_dp_bind(struct device *dev, struct device *master,
        if (!dp_data)
                return -ENODEV;
 
-       ret = rockchip_dp_init(dp);
-       if (ret < 0)
-               return ret;
-
        dp->data = dp_data;
        dp->drm_dev = drm_dev;
 
@@ -396,7 +378,6 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master,
        rockchip_drm_psr_unregister(&dp->encoder);
 
        analogix_dp_unbind(dev, master, data);
-       clk_disable_unprepare(dp->pclk);
 }
 
 static const struct component_ops rockchip_dp_component_ops = {
@@ -412,7 +393,7 @@ static int rockchip_dp_probe(struct platform_device *pdev)
        int ret;
 
        ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL);
-       if (ret)
+       if (ret < 0)
                return ret;
 
        dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
@@ -420,9 +401,12 @@ static int rockchip_dp_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        dp->dev = dev;
-
        dp->plat_data.panel = panel;
 
+       ret = rockchip_dp_of_probe(dp);
+       if (ret < 0)
+               return ret;
+
        /*
         * We just use the drvdata until driver run into component
         * add function, and then we would set drvdata to null, so
index 275844d..ec999d9 100644 (file)
@@ -276,11 +276,9 @@ static int cdn_dp_connector_get_modes(struct drm_connector *connector)
 
                dp->sink_has_audio = drm_detect_monitor_audio(edid);
                ret = drm_add_edid_modes(connector, edid);
-               if (ret) {
+               if (ret)
                        drm_mode_connector_update_edid_property(connector,
                                                                edid);
-                       drm_edid_to_eld(connector, edid);
-               }
        }
        mutex_unlock(&dp->lock);
 
index ee584d8..fab3092 100644 (file)
@@ -282,6 +282,7 @@ static int inno_hdmi_config_video_vsi(struct inno_hdmi *hdmi,
        int rc;
 
        rc = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
+                                                        &hdmi->connector,
                                                         mode);
 
        return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_VSI,
index 19128b4..ba75052 100644 (file)
@@ -659,9 +659,9 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
        clip.x2 = crtc_state->adjusted_mode.hdisplay;
        clip.y2 = crtc_state->adjusted_mode.vdisplay;
 
-       ret = drm_plane_helper_check_state(state, &clip,
-                                          min_scale, max_scale,
-                                          true, true);
+       ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
+                                                 min_scale, max_scale,
+                                                 true, true);
        if (ret)
                return ret;
 
index 4a39049..2e4eea3 100644 (file)
@@ -149,6 +149,34 @@ static const struct vop_data rk3036_vop = {
        .win_size = ARRAY_SIZE(rk3036_vop_win_data),
 };
 
+static const struct vop_win_phy rk3126_win1_data = {
+       .data_formats = formats_win_lite,
+       .nformats = ARRAY_SIZE(formats_win_lite),
+       .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
+       .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
+       .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
+       .dsp_info = VOP_REG(RK3126_WIN1_DSP_INFO, 0x0fff0fff, 0),
+       .dsp_st = VOP_REG(RK3126_WIN1_DSP_ST, 0x1fff1fff, 0),
+       .yrgb_mst = VOP_REG(RK3126_WIN1_MST, 0xffffffff, 0),
+       .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
+};
+
+static const struct vop_win_data rk3126_vop_win_data[] = {
+       { .base = 0x00, .phy = &rk3036_win0_data,
+         .type = DRM_PLANE_TYPE_PRIMARY },
+       { .base = 0x00, .phy = &rk3126_win1_data,
+         .type = DRM_PLANE_TYPE_CURSOR },
+};
+
+static const struct vop_data rk3126_vop = {
+       .intr = &rk3036_intr,
+       .common = &rk3036_common,
+       .modeset = &rk3036_modeset,
+       .output = &rk3036_output,
+       .win = rk3126_vop_win_data,
+       .win_size = ARRAY_SIZE(rk3126_vop_win_data),
+};
+
 static const struct vop_scl_extension rk3288_win_full_scl_ext = {
        .cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31),
        .cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30),
@@ -510,6 +538,8 @@ static const struct vop_data rk3328_vop = {
 static const struct of_device_id vop_driver_dt_match[] = {
        { .compatible = "rockchip,rk3036-vop",
          .data = &rk3036_vop },
+       { .compatible = "rockchip,rk3126-vop",
+         .data = &rk3126_vop },
        { .compatible = "rockchip,rk3288-vop",
          .data = &rk3288_vop },
        { .compatible = "rockchip,rk3368-vop",
index 4a4799f..f81b510 100644 (file)
 #define RK3036_HWC_LUT_ADDR            0x800
 /* rk3036 register definition end */
 
+/* rk3126 register definition */
+#define RK3126_WIN1_MST                        0x4c
+#define RK3126_WIN1_DSP_INFO           0x50
+#define RK3126_WIN1_DSP_ST             0x54
+/* rk3126 register definition end */
+
 #endif /* _ROCKCHIP_VOP_REG_H */
index 86eb4c1..7cc935d 100644 (file)
@@ -682,6 +682,8 @@ static int __igt_insert(unsigned int count, u64 size, bool replace)
                drm_mm_for_each_node_safe(node, next, &mm)
                        drm_mm_remove_node(node);
                DRM_MM_BUG_ON(!drm_mm_clean(&mm));
+
+               cond_resched();
        }
 
        ret = 0;
@@ -944,6 +946,8 @@ static int __igt_insert_range(unsigned int count, u64 size, u64 start, u64 end)
                drm_mm_for_each_node_safe(node, next, &mm)
                        drm_mm_remove_node(node);
                DRM_MM_BUG_ON(!drm_mm_clean(&mm));
+
+               cond_resched();
        }
 
        ret = 0;
@@ -1068,6 +1072,7 @@ static int igt_align(void *ignored)
                drm_mm_for_each_node_safe(node, next, &mm)
                        drm_mm_remove_node(node);
                DRM_MM_BUG_ON(!drm_mm_clean(&mm));
+
                cond_resched();
        }
 
index acd7286..cca4b3c 100644 (file)
@@ -8,5 +8,6 @@ config DRM_STI
        select DRM_PANEL
        select FW_LOADER
        select SND_SOC_HDMI_CODEC if SND_SOC
+       select OF
        help
          Choose this option to enable DRM on STM stiH4xx chipset
index 30f02d2..4ea1cc1 100644 (file)
@@ -515,7 +515,9 @@ static int hdmi_vendor_infoframe_config(struct sti_hdmi *hdmi)
 
        DRM_DEBUG_DRIVER("\n");
 
-       ret = drm_hdmi_vendor_infoframe_from_display_mode(&infoframe, mode);
+       ret = drm_hdmi_vendor_infoframe_from_display_mode(&infoframe,
+                                                         hdmi->drm_connector,
+                                                         mode);
        if (ret < 0) {
                /*
                 * Going into that statement does not means vendor infoframe
@@ -976,7 +978,6 @@ static int sti_hdmi_connector_get_modes(struct drm_connector *connector)
 
        count = drm_add_edid_modes(connector, edid);
        drm_mode_connector_update_edid_property(connector, edid);
-       drm_edid_to_eld(connector, edid);
 
        kfree(edid);
        return count;
@@ -1414,6 +1415,11 @@ static int sti_hdmi_probe(struct platform_device *pdev)
        init_waitqueue_head(&hdmi->wait_event);
 
        hdmi->irq = platform_get_irq_byname(pdev, "irq");
+       if (hdmi->irq < 0) {
+               DRM_ERROR("Cannot get HDMI irq\n");
+               ret = hdmi->irq;
+               goto release_adapter;
+       }
 
        ret = devm_request_threaded_irq(dev, hdmi->irq, hdmi_irq,
                        hdmi_irq_thread, IRQF_ONESHOT, dev_name(dev), hdmi);
index 2dcba1d..3aa2fa6 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/module.h>
 #include <linux/notifier.h>
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
 
 #include <drm/drmP.h>
@@ -72,8 +73,6 @@
 #define AWG_DELAY_ED        (-8)
 #define AWG_DELAY_SD        (-7)
 
-static LIST_HEAD(vtg_lookup);
-
 /*
  * STI VTG register offset structure
  *
@@ -123,42 +122,31 @@ struct sti_vtg_sync_params {
 /**
  * STI VTG structure
  *
- * @dev: pointer to device driver
- * @np: device node
  * @regs: register mapping
  * @sync_params: synchronisation parameters used to generate timings
  * @irq: VTG irq
  * @irq_status: store the IRQ status value
  * @notifier_list: notifier callback
  * @crtc: the CRTC for vblank event
- * @link: List node to link the structure in lookup list
  */
 struct sti_vtg {
-       struct device *dev;
-       struct device_node *np;
        void __iomem *regs;
        struct sti_vtg_sync_params sync_params[VTG_MAX_SYNC_OUTPUT];
        int irq;
        u32 irq_status;
        struct raw_notifier_head notifier_list;
        struct drm_crtc *crtc;
-       struct list_head link;
 };
 
-static void vtg_register(struct sti_vtg *vtg)
-{
-       list_add_tail(&vtg->link, &vtg_lookup);
-}
-
 struct sti_vtg *of_vtg_find(struct device_node *np)
 {
-       struct sti_vtg *vtg;
+       struct platform_device *pdev;
 
-       list_for_each_entry(vtg, &vtg_lookup, link) {
-               if (vtg->np == np)
-                       return vtg;
-       }
-       return NULL;
+       pdev = of_find_device_by_node(np);
+       if (!pdev)
+               return NULL;
+
+       return (struct sti_vtg *)platform_get_drvdata(pdev);
 }
 
 static void vtg_reset(struct sti_vtg *vtg)
@@ -397,9 +385,6 @@ static int vtg_probe(struct platform_device *pdev)
        if (!vtg)
                return -ENOMEM;
 
-       vtg->dev = dev;
-       vtg->np = pdev->dev.of_node;
-
        /* Get Memory ressources */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
@@ -428,16 +413,10 @@ static int vtg_probe(struct platform_device *pdev)
                return ret;
        }
 
-       vtg_register(vtg);
        platform_set_drvdata(pdev, vtg);
 
-       DRM_INFO("%s %s\n", __func__, dev_name(vtg->dev));
-
-       return 0;
-}
+       DRM_INFO("%s %s\n", __func__, dev_name(dev));
 
-static int vtg_remove(struct platform_device *pdev)
-{
        return 0;
 }
 
@@ -454,7 +433,6 @@ struct platform_driver sti_vtg_driver = {
                .of_match_table = vtg_of_match,
        },
        .probe  = vtg_probe,
-       .remove = vtg_remove,
 };
 
 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
index e5b6310..3e8b9ed 100644 (file)
@@ -129,7 +129,7 @@ static int dsi_pll_get_params(int clkin_khz, int clkout_khz,
        int fvco_min, fvco_max, delta, best_delta; /* all in khz */
 
        /* Early checks preventing division by 0 & odd results */
-       if ((clkin_khz <= 0) || (clkout_khz <= 0))
+       if (clkin_khz <= 0 || clkout_khz <= 0)
                return -EINVAL;
 
        fvco_min = LANE_MIN_KBPS * 2 * ODF_MAX;
@@ -155,7 +155,7 @@ static int dsi_pll_get_params(int clkin_khz, int clkout_khz,
                for (o = ODF_MIN; o <= ODF_MAX; o *= 2) {
                        n = DIV_ROUND_CLOSEST(i * o * clkout_khz, clkin_khz);
                        /* Check ndiv according to vco range */
-                       if ((n < n_min) || (n > n_max))
+                       if (n < n_min || n > n_max)
                                continue;
                        /* Check if new delta is better & saves parameters */
                        delta = dsi_pll_get_clkout_khz(clkin_khz, i, n, o) -
@@ -342,7 +342,7 @@ static struct platform_driver dw_mipi_dsi_stm_driver = {
        .remove         = dw_mipi_dsi_stm_remove,
        .driver         = {
                .of_match_table = dw_mipi_dsi_stm_dt_ids,
-               .name   = "dw_mipi_dsi-stm",
+               .name   = "stm32-display-dsi",
        },
 };
 
index 735c908..35e8842 100644 (file)
@@ -33,6 +33,8 @@
 
 #define MAX_IRQ 4
 
+#define MAX_ENDPOINTS 2
+
 #define HWVER_10200 0x010200
 #define HWVER_10300 0x010300
 #define HWVER_20101 0x020101
@@ -556,7 +558,7 @@ static int ltdc_plane_atomic_check(struct drm_plane *plane,
        src_h = state->src_h >> 16;
 
        /* Reject scaling */
-       if ((src_w != state->crtc_w) || (src_h != state->crtc_h)) {
+       if (src_w != state->crtc_w || src_h != state->crtc_h) {
                DRM_ERROR("Scaling is not supported");
                return -EINVAL;
        }
@@ -856,18 +858,33 @@ int ltdc_load(struct drm_device *ddev)
        struct ltdc_device *ldev = ddev->dev_private;
        struct device *dev = ddev->dev;
        struct device_node *np = dev->of_node;
-       struct drm_bridge *bridge;
-       struct drm_panel *panel;
+       struct drm_bridge *bridge[MAX_ENDPOINTS] = {NULL};
+       struct drm_panel *panel[MAX_ENDPOINTS] = {NULL};
        struct drm_crtc *crtc;
        struct reset_control *rstc;
        struct resource *res;
-       int irq, ret, i;
+       int irq, ret, i, endpoint_not_ready = -ENODEV;
 
        DRM_DEBUG_DRIVER("\n");
 
-       ret = drm_of_find_panel_or_bridge(np, 0, 0, &panel, &bridge);
-       if (ret)
-               return ret;
+       /* Get endpoints if any */
+       for (i = 0; i < MAX_ENDPOINTS; i++) {
+               ret = drm_of_find_panel_or_bridge(np, 0, i, &panel[i],
+                                                 &bridge[i]);
+
+               /*
+                * If at least one endpoint is ready, continue probing,
+                * else if at least one endpoint is -EPROBE_DEFER and
+                * there is no previous ready endpoints, defer probing.
+                */
+               if (!ret)
+                       endpoint_not_ready = 0;
+               else if (ret == -EPROBE_DEFER && endpoint_not_ready)
+                       endpoint_not_ready = -EPROBE_DEFER;
+       }
+
+       if (endpoint_not_ready)
+               return endpoint_not_ready;
 
        rstc = devm_reset_control_get_exclusive(dev, NULL);
 
@@ -928,19 +945,25 @@ int ltdc_load(struct drm_device *ddev)
 
        DRM_INFO("ltdc hw version 0x%08x - ready\n", ldev->caps.hw_version);
 
-       if (panel) {
-               bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DPI);
-               if (IS_ERR(bridge)) {
-                       DRM_ERROR("Failed to create panel-bridge\n");
-                       ret = PTR_ERR(bridge);
-                       goto err;
+       /* Add endpoints panels or bridges if any */
+       for (i = 0; i < MAX_ENDPOINTS; i++) {
+               if (panel[i]) {
+                       bridge[i] = drm_panel_bridge_add(panel[i],
+                                                       DRM_MODE_CONNECTOR_DPI);
+                       if (IS_ERR(bridge[i])) {
+                               DRM_ERROR("panel-bridge endpoint %d\n", i);
+                               ret = PTR_ERR(bridge[i]);
+                               goto err;
+                       }
                }
-       }
 
-       ret = ltdc_encoder_init(ddev, bridge);
-       if (ret) {
-               DRM_ERROR("Failed to init encoder\n");
-               goto err;
+               if (bridge[i]) {
+                       ret = ltdc_encoder_init(ddev, bridge[i]);
+                       if (ret) {
+                               DRM_ERROR("init encoder endpoint %d\n", i);
+                               goto err;
+                       }
+               }
        }
 
        crtc = devm_kzalloc(dev, sizeof(*crtc), GFP_KERNEL);
@@ -968,7 +991,8 @@ int ltdc_load(struct drm_device *ddev)
        return 0;
 
 err:
-       drm_panel_bridge_remove(bridge);
+       for (i = 0; i < MAX_ENDPOINTS; i++)
+               drm_panel_bridge_remove(bridge[i]);
 
        clk_disable_unprepare(ldev->pixel_clk);
 
@@ -978,10 +1002,12 @@ err:
 void ltdc_unload(struct drm_device *ddev)
 {
        struct ltdc_device *ldev = ddev->dev_private;
+       int i;
 
        DRM_DEBUG_DRIVER("\n");
 
-       drm_of_panel_bridge_remove(ddev->dev->of_node, 0, 0);
+       for (i = 0; i < MAX_ENDPOINTS; i++)
+               drm_of_panel_bridge_remove(ddev->dev->of_node, 0, i);
 
        clk_disable_unprepare(ldev->pixel_clk);
 }
index 24a5ef4..fc70351 100644 (file)
@@ -491,8 +491,8 @@ static int tegra_plane_state_add(struct tegra_plane *plane,
        clip.y2 = crtc_state->mode.vdisplay;
 
        /* Check plane state for visibility and calculate clipping bounds */
-       err = drm_plane_helper_check_state(state, &clip, 0, INT_MAX,
-                                          true, true);
+       err = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
+                                                 0, INT_MAX, true, true);
        if (err < 0)
                return err;
 
index 1cfbace..24f8a3b 100644 (file)
@@ -39,7 +39,6 @@ int tegra_output_connector_get_modes(struct drm_connector *connector)
 
        if (edid) {
                err = drm_add_edid_modes(connector, edid);
-               drm_edid_to_eld(connector, edid);
                kfree(edid);
        }
 
index 72ce063..bc4feb3 100644 (file)
@@ -507,7 +507,6 @@ static int tilcdc_mm_show(struct seq_file *m, void *arg)
 static struct drm_info_list tilcdc_debugfs_list[] = {
                { "regs", tilcdc_regs_show, 0 },
                { "mm",   tilcdc_mm_show,   0 },
-               { "fb",   drm_fb_cma_debugfs_show, 0 },
 };
 
 static int tilcdc_debugfs_init(struct drm_minor *minor)
@@ -541,6 +540,7 @@ static struct drm_driver tilcdc_driver = {
        .lastclose          = tilcdc_lastclose,
        .irq_handler        = tilcdc_irq,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
+       .gem_print_info     = drm_gem_cma_print_info,
        .gem_vm_ops         = &drm_gem_cma_vm_ops,
        .dumb_create        = drm_gem_cma_dumb_create,
 
index bd6cce0..bf96072 100644 (file)
@@ -414,11 +414,9 @@ tinydrm_dbg_spi_print(struct spi_device *spi, struct spi_transfer *tr,
 void _tinydrm_dbg_spi_message(struct spi_device *spi, struct spi_message *m)
 {
        struct spi_transfer *tmp;
-       struct list_head *pos;
        int i = 0;
 
-       list_for_each(pos, &m->transfers) {
-               tmp = list_entry(pos, struct spi_transfer, transfer_list);
+       list_for_each_entry(tmp, &m->transfers, transfer_list) {
 
                if (tmp->tx_buf)
                        tinydrm_dbg_spi_print(spi, tmp, tmp->tx_buf, i, true);
index d43e992..347f9b2 100644 (file)
@@ -961,10 +961,6 @@ static const struct file_operations mipi_dbi_debugfs_command_fops = {
        .write = mipi_dbi_debugfs_command_write,
 };
 
-static const struct drm_info_list mipi_dbi_debugfs_list[] = {
-       { "fb",   drm_fb_cma_debugfs_show, 0 },
-};
-
 /**
  * mipi_dbi_debugfs_init - Create debugfs entries
  * @minor: DRM minor
@@ -987,9 +983,7 @@ int mipi_dbi_debugfs_init(struct drm_minor *minor)
        debugfs_create_file("command", mode, minor->debugfs_root, mipi,
                            &mipi_dbi_debugfs_command_fops);
 
-       return drm_debugfs_create_files(mipi_dbi_debugfs_list,
-                                       ARRAY_SIZE(mipi_dbi_debugfs_list),
-                                       minor->debugfs_root, minor);
+       return 0;
 }
 EXPORT_SYMBOL(mipi_dbi_debugfs_init);
 
index 0b20882..984501e 100644 (file)
@@ -287,7 +287,6 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
 
        drm_mode_connector_update_edid_property(connector, edid);
        ret = drm_add_edid_modes(connector, edid);
-       drm_edid_to_eld(connector, edid);
        kfree(edid);
 
        return ret;
@@ -695,7 +694,22 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
        }
 }
 
+static enum drm_mode_status
+vc4_hdmi_encoder_mode_valid(struct drm_encoder *crtc,
+                           const struct drm_display_mode *mode)
+{
+       /* HSM clock must be 108% of the pixel clock.  Additionally,
+        * the AXI clock needs to be at least 25% of pixel clock, but
+        * HSM ends up being the limiting factor.
+        */
+       if (mode->clock > HSM_CLOCK_FREQ / (1000 * 108 / 100))
+               return MODE_CLOCK_HIGH;
+
+       return MODE_OK;
+}
+
 static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
+       .mode_valid = vc4_hdmi_encoder_mode_valid,
        .disable = vc4_hdmi_encoder_disable,
        .enable = vc4_hdmi_encoder_enable,
 };
index 423a23e..515f979 100644 (file)
@@ -86,7 +86,6 @@ static const struct hvs_format {
        u32 hvs; /* HVS_FORMAT_* */
        u32 pixel_order;
        bool has_alpha;
-       bool flip_cbcr;
 } hvs_formats[] = {
        {
                .drm = DRM_FORMAT_XRGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
@@ -120,31 +119,53 @@ static const struct hvs_format {
                .drm = DRM_FORMAT_XRGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551,
                .pixel_order = HVS_PIXEL_ORDER_ABGR, .has_alpha = false,
        },
+       {
+               .drm = DRM_FORMAT_RGB888, .hvs = HVS_PIXEL_FORMAT_RGB888,
+               .pixel_order = HVS_PIXEL_ORDER_XRGB, .has_alpha = false,
+       },
+       {
+               .drm = DRM_FORMAT_BGR888, .hvs = HVS_PIXEL_FORMAT_RGB888,
+               .pixel_order = HVS_PIXEL_ORDER_XBGR, .has_alpha = false,
+       },
        {
                .drm = DRM_FORMAT_YUV422,
                .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE,
+               .pixel_order = HVS_PIXEL_ORDER_XYCBCR,
        },
        {
                .drm = DRM_FORMAT_YVU422,
                .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE,
-               .flip_cbcr = true,
+               .pixel_order = HVS_PIXEL_ORDER_XYCRCB,
        },
        {
                .drm = DRM_FORMAT_YUV420,
                .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE,
+               .pixel_order = HVS_PIXEL_ORDER_XYCBCR,
        },
        {
                .drm = DRM_FORMAT_YVU420,
                .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE,
-               .flip_cbcr = true,
+               .pixel_order = HVS_PIXEL_ORDER_XYCRCB,
        },
        {
                .drm = DRM_FORMAT_NV12,
                .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE,
+               .pixel_order = HVS_PIXEL_ORDER_XYCBCR,
+       },
+       {
+               .drm = DRM_FORMAT_NV21,
+               .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE,
+               .pixel_order = HVS_PIXEL_ORDER_XYCRCB,
        },
        {
                .drm = DRM_FORMAT_NV16,
                .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE,
+               .pixel_order = HVS_PIXEL_ORDER_XYCBCR,
+       },
+       {
+               .drm = DRM_FORMAT_NV61,
+               .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE,
+               .pixel_order = HVS_PIXEL_ORDER_XYCRCB,
        },
 };
 
@@ -617,15 +638,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
         * The pointers may be any byte address.
         */
        vc4_state->ptr0_offset = vc4_state->dlist_count;
-       if (!format->flip_cbcr) {
-               for (i = 0; i < num_planes; i++)
-                       vc4_dlist_write(vc4_state, vc4_state->offsets[i]);
-       } else {
-               WARN_ON_ONCE(num_planes != 3);
-               vc4_dlist_write(vc4_state, vc4_state->offsets[0]);
-               vc4_dlist_write(vc4_state, vc4_state->offsets[2]);
-               vc4_dlist_write(vc4_state, vc4_state->offsets[1]);
-       }
+       for (i = 0; i < num_planes; i++)
+               vc4_dlist_write(vc4_state, vc4_state->offsets[i]);
 
        /* Pointer Context Word 0/1/2: Written by the HVS */
        for (i = 0; i < num_planes; i++)
index 9873942..6d1ae83 100644 (file)
@@ -74,9 +74,9 @@ typedef struct drm_via_private {
        volatile uint32_t *last_pause_ptr;
        volatile uint32_t *hw_addr_ptr;
        drm_via_ring_buffer_t ring;
-       struct timeval last_vblank;
+       ktime_t last_vblank;
        int last_vblank_valid;
-       unsigned usec_per_vblank;
+       ktime_t nsec_per_vblank;
        atomic_t vbl_received;
        drm_via_state_t hc_state;
        char pci_buf[VIA_PCI_BUF_SIZE];
index ea8172c..c96830c 100644 (file)
@@ -88,13 +88,6 @@ static int via_num_unichrome = ARRAY_SIZE(via_unichrome_irqs);
 static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
 
 
-static unsigned time_diff(struct timeval *now, struct timeval *then)
-{
-       return (now->tv_usec >= then->tv_usec) ?
-               now->tv_usec - then->tv_usec :
-               1000000 - (then->tv_usec - now->tv_usec);
-}
-
 u32 via_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
 {
        drm_via_private_t *dev_priv = dev->dev_private;
@@ -111,7 +104,7 @@ irqreturn_t via_driver_irq_handler(int irq, void *arg)
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
        u32 status;
        int handled = 0;
-       struct timeval cur_vblank;
+       ktime_t cur_vblank;
        drm_via_irq_t *cur_irq = dev_priv->via_irqs;
        int i;
 
@@ -119,18 +112,18 @@ irqreturn_t via_driver_irq_handler(int irq, void *arg)
        if (status & VIA_IRQ_VBLANK_PENDING) {
                atomic_inc(&dev_priv->vbl_received);
                if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) {
-                       do_gettimeofday(&cur_vblank);
+                       cur_vblank = ktime_get();
                        if (dev_priv->last_vblank_valid) {
-                               dev_priv->usec_per_vblank =
-                                       time_diff(&cur_vblank,
-                                                 &dev_priv->last_vblank) >> 4;
+                               dev_priv->nsec_per_vblank =
+                                       ktime_sub(cur_vblank,
+                                               dev_priv->last_vblank) >> 4;
                        }
                        dev_priv->last_vblank = cur_vblank;
                        dev_priv->last_vblank_valid = 1;
                }
                if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) {
-                       DRM_DEBUG("US per vblank is: %u\n",
-                                 dev_priv->usec_per_vblank);
+                       DRM_DEBUG("nsec per vblank is: %llu\n",
+                                 ktime_to_ns(dev_priv->nsec_per_vblank));
                }
                drm_handle_vblank(dev, 0);
                handled = 1;
@@ -350,7 +343,7 @@ void via_driver_irq_uninstall(struct drm_device *dev)
 int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        drm_via_irqwait_t *irqwait = data;
-       struct timeval now;
+       struct timespec64 now;
        int ret = 0;
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
        drm_via_irq_t *cur_irq = dev_priv->via_irqs;
@@ -384,9 +377,9 @@ int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv)
 
        ret = via_driver_irq_wait(dev, irqwait->request.irq, force_sequence,
                                  &irqwait->request.sequence);
-       do_gettimeofday(&now);
+       ktime_get_ts64(&now);
        irqwait->reply.tval_sec = now.tv_sec;
-       irqwait->reply.tval_usec = now.tv_usec;
+       irqwait->reply.tval_usec = now.tv_nsec / NSEC_PER_USEC;
 
        return ret;
 }
index 41b0930..19114a3 100644 (file)
@@ -71,7 +71,19 @@ 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,
        .dirty = virtio_gpu_framebuffer_surface_dirty,
 };
index 0528edb..461f81a 100644 (file)
@@ -261,7 +261,7 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
                ret = virtio_gpu_object_attach(vgdev, qobj, res_id, NULL);
        } else {
                /* use a gem reference since unref list undoes them */
-               drm_gem_object_reference(&qobj->gem_base);
+               drm_gem_object_get(&qobj->gem_base);
                mainbuf.bo = &qobj->tbo;
                list_add(&mainbuf.head, &validate_list);
 
index 6400506..65060c0 100644 (file)
@@ -272,20 +272,18 @@ int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file)
        struct virtio_gpu_device *vgdev = dev->dev_private;
        struct virtio_gpu_fpriv *vfpriv;
        uint32_t id;
-       char dbgname[64], tmpname[TASK_COMM_LEN];
+       char dbgname[TASK_COMM_LEN];
 
        /* can't create contexts without 3d renderer */
        if (!vgdev->has_virgl_3d)
                return 0;
 
-       get_task_comm(tmpname, current);
-       snprintf(dbgname, sizeof(dbgname), "%s", tmpname);
-       dbgname[63] = 0;
        /* allocate a virt GPU context for this opener */
        vfpriv = kzalloc(sizeof(*vfpriv), GFP_KERNEL);
        if (!vfpriv)
                return -ENOMEM;
 
+       get_task_comm(dbgname, current);
        virtio_gpu_context_create(vgdev, strlen(dbgname), dbgname, &id);
 
        vfpriv->ctx_id = id;
index 0545740..a2a93d7 100644 (file)
@@ -441,31 +441,23 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
 int vmw_du_primary_plane_atomic_check(struct drm_plane *plane,
                                      struct drm_plane_state *state)
 {
+       struct drm_crtc_state *crtc_state = NULL;
        struct drm_framebuffer *new_fb = state->fb;
-       bool visible;
-
-       struct drm_rect src = {
-               .x1 = state->src_x,
-               .y1 = state->src_y,
-               .x2 = state->src_x + state->src_w,
-               .y2 = state->src_y + state->src_h,
-       };
-       struct drm_rect dest = {
-               .x1 = state->crtc_x,
-               .y1 = state->crtc_y,
-               .x2 = state->crtc_x + state->crtc_w,
-               .y2 = state->crtc_y + state->crtc_h,
-       };
-       struct drm_rect clip = dest;
+       struct drm_rect clip = {};
        int ret;
 
-       ret = drm_plane_helper_check_update(plane, state->crtc, new_fb,
-                                           &src, &dest, &clip,
-                                           DRM_MODE_ROTATE_0,
-                                           DRM_PLANE_HELPER_NO_SCALING,
-                                           DRM_PLANE_HELPER_NO_SCALING,
-                                           false, true, &visible);
+       if (state->crtc)
+               crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc);
+
+       if (crtc_state && crtc_state->enable) {
+               clip.x2 = crtc_state->adjusted_mode.hdisplay;
+               clip.y2 = crtc_state->adjusted_mode.vdisplay;
+       }
 
+       ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 false, true);
 
        if (!ret && new_fb) {
                struct drm_crtc *crtc = state->crtc;
@@ -476,12 +468,6 @@ int vmw_du_primary_plane_atomic_check(struct drm_plane *plane,
 
                vcs = vmw_connector_state_to_vcs(du->connector.state);
 
-               if ((dest.x2 > new_fb->width ||
-                    dest.y2 > new_fb->height)) {
-                       DRM_ERROR("CRTC area outside of framebuffer\n");
-                       return -EINVAL;
-               }
-
                /* Only one active implicit framebuffer at a time. */
                mutex_lock(&dev_priv->global_kms_state_mutex);
                if (vcs->is_implicit && dev_priv->implicit_fb &&
index b8abb1b..13ea90f 100644 (file)
@@ -108,6 +108,7 @@ static int zx_hdmi_config_video_vsi(struct zx_hdmi *hdmi,
        int ret;
 
        ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
+                                                         &hdmi->connector,
                                                          mode);
        if (ret) {
                DRM_DEV_ERROR(hdmi->dev, "failed to get vendor infoframe: %d\n",
index 18e7634..68fd2e2 100644 (file)
@@ -80,9 +80,9 @@ static int zx_vl_plane_atomic_check(struct drm_plane *plane,
        clip.x2 = crtc_state->adjusted_mode.hdisplay;
        clip.y2 = crtc_state->adjusted_mode.vdisplay;
 
-       return drm_plane_helper_check_state(plane_state, &clip,
-                                           min_scale, max_scale,
-                                           true, true);
+       return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
+                                                  &clip, min_scale, max_scale,
+                                                  true, true);
 }
 
 static int zx_vl_get_fmt(uint32_t format)
@@ -315,10 +315,11 @@ static int zx_gl_plane_atomic_check(struct drm_plane *plane,
        clip.x2 = crtc_state->adjusted_mode.hdisplay;
        clip.y2 = crtc_state->adjusted_mode.vdisplay;
 
-       return drm_plane_helper_check_state(plane_state, &clip,
-                                           DRM_PLANE_HELPER_NO_SCALING,
-                                           DRM_PLANE_HELPER_NO_SCALING,
-                                           false, true);
+       return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
+                                                  &clip,
+                                                  DRM_PLANE_HELPER_NO_SCALING,
+                                                  DRM_PLANE_HELPER_NO_SCALING,
+                                                  false, true);
 }
 
 static int zx_gl_get_fmt(uint32_t format)
index 1cf907e..111a0ab 100644 (file)
@@ -321,6 +321,17 @@ int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame)
 }
 EXPORT_SYMBOL(hdmi_vendor_infoframe_init);
 
+static int hdmi_vendor_infoframe_length(const struct hdmi_vendor_infoframe *frame)
+{
+       /* for side by side (half) we also need to provide 3D_Ext_Data */
+       if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
+               return 6;
+       else if (frame->vic != 0 || frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID)
+               return 5;
+       else
+               return 4;
+}
+
 /**
  * hdmi_vendor_infoframe_pack() - write a HDMI vendor infoframe to binary buffer
  * @frame: HDMI infoframe
@@ -341,19 +352,11 @@ ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
        u8 *ptr = buffer;
        size_t length;
 
-       /* empty info frame */
-       if (frame->vic == 0 && frame->s3d_struct == HDMI_3D_STRUCTURE_INVALID)
-               return -EINVAL;
-
        /* only one of those can be supplied */
        if (frame->vic != 0 && frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID)
                return -EINVAL;
 
-       /* for side by side (half) we also need to provide 3D_Ext_Data */
-       if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
-               frame->length = 6;
-       else
-               frame->length = 5;
+       frame->length = hdmi_vendor_infoframe_length(frame);
 
        length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
 
@@ -372,14 +375,16 @@ ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
        ptr[5] = 0x0c;
        ptr[6] = 0x00;
 
-       if (frame->vic) {
-               ptr[7] = 0x1 << 5;      /* video format */
-               ptr[8] = frame->vic;
-       } else {
+       if (frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID) {
                ptr[7] = 0x2 << 5;      /* video format */
                ptr[8] = (frame->s3d_struct & 0xf) << 4;
                if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
                        ptr[9] = (frame->s3d_ext_data & 0xf) << 4;
+       } else if (frame->vic) {
+               ptr[7] = 0x1 << 5;      /* video format */
+               ptr[8] = frame->vic;
+       } else {
+               ptr[7] = 0x0 << 5;      /* video format */
        }
 
        hdmi_infoframe_set_checksum(buffer, length);
@@ -1165,7 +1170,7 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
 
        if (ptr[0] != HDMI_INFOFRAME_TYPE_VENDOR ||
            ptr[1] != 1 ||
-           (ptr[2] != 5 && ptr[2] != 6))
+           (ptr[2] != 4 && ptr[2] != 5 && ptr[2] != 6))
                return -EINVAL;
 
        length = ptr[2];
@@ -1193,16 +1198,22 @@ hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
 
        hvf->length = length;
 
-       if (hdmi_video_format == 0x1) {
-               hvf->vic = ptr[4];
-       } else if (hdmi_video_format == 0x2) {
+       if (hdmi_video_format == 0x2) {
+               if (length != 5 && length != 6)
+                       return -EINVAL;
                hvf->s3d_struct = ptr[4] >> 4;
                if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) {
-                       if (length == 6)
-                               hvf->s3d_ext_data = ptr[5] >> 4;
-                       else
+                       if (length != 6)
                                return -EINVAL;
+                       hvf->s3d_ext_data = ptr[5] >> 4;
                }
+       } else if (hdmi_video_format == 0x1) {
+               if (length != 5)
+                       return -EINVAL;
+               hvf->vic = ptr[4];
+       } else {
+               if (length != 4)
+                       return -EINVAL;
        }
 
        return 0;
index 59be123..c6666cd 100644 (file)
@@ -75,6 +75,7 @@
 #include <drm/drm_sarea.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_prime.h>
+#include <drm/drm_print.h>
 #include <drm/drm_pci.h>
 #include <drm/drm_file.h>
 #include <drm/drm_debugfs.h>
@@ -94,212 +95,16 @@ struct dma_buf_attachment;
 struct pci_dev;
 struct pci_controller;
 
-/*
- * The following categories are defined:
- *
- * CORE: Used in the generic drm code: drm_ioctl.c, drm_mm.c, drm_memory.c, ...
- *      This is the category used by the DRM_DEBUG() macro.
- *
- * DRIVER: Used in the vendor specific part of the driver: i915, radeon, ...
- *        This is the category used by the DRM_DEBUG_DRIVER() macro.
- *
- * KMS: used in the modesetting code.
- *     This is the category used by the DRM_DEBUG_KMS() macro.
- *
- * PRIME: used in the prime code.
- *       This is the category used by the DRM_DEBUG_PRIME() macro.
- *
- * ATOMIC: used in the atomic code.
- *       This is the category used by the DRM_DEBUG_ATOMIC() macro.
- *
- * VBL: used for verbose debug message in the vblank code
- *       This is the category used by the DRM_DEBUG_VBL() macro.
- *
- * Enabling verbose debug messages is done through the drm.debug parameter,
- * each category being enabled by a bit.
- *
- * drm.debug=0x1 will enable CORE messages
- * drm.debug=0x2 will enable DRIVER messages
- * drm.debug=0x3 will enable CORE and DRIVER messages
- * ...
- * drm.debug=0x3f will enable all messages
- *
- * An interesting feature is that it's possible to enable verbose logging at
- * run-time by echoing the debug value in its sysfs node:
- *   # echo 0xf > /sys/module/drm/parameters/debug
- */
-#define DRM_UT_NONE            0x00
-#define DRM_UT_CORE            0x01
-#define DRM_UT_DRIVER          0x02
-#define DRM_UT_KMS             0x04
-#define DRM_UT_PRIME           0x08
-#define DRM_UT_ATOMIC          0x10
-#define DRM_UT_VBL             0x20
-#define DRM_UT_STATE           0x40
-#define DRM_UT_LEASE           0x80
-
 /***********************************************************************/
 /** \name DRM template customization defaults */
 /*@{*/
 
-/***********************************************************************/
-/** \name Macros to make printk easier */
-/*@{*/
-
-#define _DRM_PRINTK(once, level, fmt, ...)                             \
-       do {                                                            \
-               printk##once(KERN_##level "[" DRM_NAME "] " fmt,        \
-                            ##__VA_ARGS__);                            \
-       } while (0)
-
-#define DRM_INFO(fmt, ...)                                             \
-       _DRM_PRINTK(, INFO, fmt, ##__VA_ARGS__)
-#define DRM_NOTE(fmt, ...)                                             \
-       _DRM_PRINTK(, NOTICE, fmt, ##__VA_ARGS__)
-#define DRM_WARN(fmt, ...)                                             \
-       _DRM_PRINTK(, WARNING, fmt, ##__VA_ARGS__)
-
-#define DRM_INFO_ONCE(fmt, ...)                                                \
-       _DRM_PRINTK(_once, INFO, fmt, ##__VA_ARGS__)
-#define DRM_NOTE_ONCE(fmt, ...)                                                \
-       _DRM_PRINTK(_once, NOTICE, fmt, ##__VA_ARGS__)
-#define DRM_WARN_ONCE(fmt, ...)                                                \
-       _DRM_PRINTK(_once, WARNING, fmt, ##__VA_ARGS__)
-
-/**
- * Error output.
- *
- * \param fmt printf() like format string.
- * \param arg arguments
- */
-#define DRM_DEV_ERROR(dev, fmt, ...)                                   \
-       drm_dev_printk(dev, KERN_ERR, DRM_UT_NONE, __func__, " *ERROR*",\
-                      fmt, ##__VA_ARGS__)
-#define DRM_ERROR(fmt, ...)                                            \
-       drm_printk(KERN_ERR, DRM_UT_NONE, fmt,  ##__VA_ARGS__)
-
-/**
- * Rate limited error output.  Like DRM_ERROR() but won't flood the log.
- *
- * \param fmt printf() like format string.
- * \param arg arguments
- */
-#define DRM_DEV_ERROR_RATELIMITED(dev, fmt, ...)                       \
-({                                                                     \
-       static DEFINE_RATELIMIT_STATE(_rs,                              \
-                                     DEFAULT_RATELIMIT_INTERVAL,       \
-                                     DEFAULT_RATELIMIT_BURST);         \
-                                                                       \
-       if (__ratelimit(&_rs))                                          \
-               DRM_DEV_ERROR(dev, fmt, ##__VA_ARGS__);                 \
-})
-#define DRM_ERROR_RATELIMITED(fmt, ...)                                        \
-       DRM_DEV_ERROR_RATELIMITED(NULL, fmt, ##__VA_ARGS__)
-
-#define DRM_DEV_INFO(dev, fmt, ...)                                    \
-       drm_dev_printk(dev, KERN_INFO, DRM_UT_NONE, __func__, "", fmt,  \
-                      ##__VA_ARGS__)
-
-#define DRM_DEV_INFO_ONCE(dev, fmt, ...)                               \
-({                                                                     \
-       static bool __print_once __read_mostly;                         \
-       if (!__print_once) {                                            \
-               __print_once = true;                                    \
-               DRM_DEV_INFO(dev, fmt, ##__VA_ARGS__);                  \
-       }                                                               \
-})
-
-/**
- * Debug output.
- *
- * \param fmt printf() like format string.
- * \param arg arguments
- */
-#define DRM_DEV_DEBUG(dev, fmt, args...)                               \
-       drm_dev_printk(dev, KERN_DEBUG, DRM_UT_CORE, __func__, "", fmt, \
-                      ##args)
-#define DRM_DEBUG(fmt, ...)                                            \
-       drm_printk(KERN_DEBUG, DRM_UT_CORE, fmt, ##__VA_ARGS__)
-
-#define DRM_DEV_DEBUG_DRIVER(dev, fmt, args...)                                \
-       drm_dev_printk(dev, KERN_DEBUG, DRM_UT_DRIVER, __func__, "",    \
-                      fmt, ##args)
-#define DRM_DEBUG_DRIVER(fmt, ...)                                     \
-       drm_printk(KERN_DEBUG, DRM_UT_DRIVER, fmt, ##__VA_ARGS__)
-
-#define DRM_DEV_DEBUG_KMS(dev, fmt, args...)                           \
-       drm_dev_printk(dev, KERN_DEBUG, DRM_UT_KMS, __func__, "", fmt,  \
-                      ##args)
-#define DRM_DEBUG_KMS(fmt, ...)                                        \
-       drm_printk(KERN_DEBUG, DRM_UT_KMS, fmt, ##__VA_ARGS__)
-
-#define DRM_DEV_DEBUG_PRIME(dev, fmt, args...)                         \
-       drm_dev_printk(dev, KERN_DEBUG, DRM_UT_PRIME, __func__, "",     \
-                      fmt, ##args)
-#define DRM_DEBUG_PRIME(fmt, ...)                                      \
-       drm_printk(KERN_DEBUG, DRM_UT_PRIME, fmt, ##__VA_ARGS__)
-
-#define DRM_DEV_DEBUG_ATOMIC(dev, fmt, args...)                                \
-       drm_dev_printk(dev, KERN_DEBUG, DRM_UT_ATOMIC, __func__, "",    \
-                      fmt, ##args)
-#define DRM_DEBUG_ATOMIC(fmt, ...)                                     \
-       drm_printk(KERN_DEBUG, DRM_UT_ATOMIC, fmt, ##__VA_ARGS__)
-
-#define DRM_DEV_DEBUG_VBL(dev, fmt, args...)                           \
-       drm_dev_printk(dev, KERN_DEBUG, DRM_UT_VBL, __func__, "", fmt,  \
-                      ##args)
-#define DRM_DEBUG_VBL(fmt, ...)                                        \
-       drm_printk(KERN_DEBUG, DRM_UT_VBL, fmt, ##__VA_ARGS__)
-
-#define DRM_DEBUG_LEASE(fmt, ...)                                      \
-       drm_printk(KERN_DEBUG, DRM_UT_LEASE, fmt, ##__VA_ARGS__)
-
-#define _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, level, fmt, args...)    \
-({                                                                     \
-       static DEFINE_RATELIMIT_STATE(_rs,                              \
-                                     DEFAULT_RATELIMIT_INTERVAL,       \
-                                     DEFAULT_RATELIMIT_BURST);         \
-       if (__ratelimit(&_rs))                                          \
-               drm_dev_printk(dev, KERN_DEBUG, DRM_UT_ ## level,       \
-                              __func__, "", fmt, ##args);              \
-})
-
-/**
- * Rate limited debug output. Like DRM_DEBUG() but won't flood the log.
- *
- * \param fmt printf() like format string.
- * \param arg arguments
- */
-#define DRM_DEV_DEBUG_RATELIMITED(dev, fmt, args...)                   \
-       DEV__DRM_DEFINE_DEBUG_RATELIMITED(dev, CORE, fmt, ##args)
-#define DRM_DEBUG_RATELIMITED(fmt, args...)                            \
-       DRM_DEV_DEBUG_RATELIMITED(NULL, fmt, ##args)
-#define DRM_DEV_DEBUG_DRIVER_RATELIMITED(dev, fmt, args...)            \
-       _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, DRIVER, fmt, ##args)
-#define DRM_DEBUG_DRIVER_RATELIMITED(fmt, args...)                     \
-       DRM_DEV_DEBUG_DRIVER_RATELIMITED(NULL, fmt, ##args)
-#define DRM_DEV_DEBUG_KMS_RATELIMITED(dev, fmt, args...)               \
-       _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, KMS, fmt, ##args)
-#define DRM_DEBUG_KMS_RATELIMITED(fmt, args...)                                \
-       DRM_DEV_DEBUG_KMS_RATELIMITED(NULL, fmt, ##args)
-#define DRM_DEV_DEBUG_PRIME_RATELIMITED(dev, fmt, args...)             \
-       _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, PRIME, fmt, ##args)
-#define DRM_DEBUG_PRIME_RATELIMITED(fmt, args...)                      \
-       DRM_DEV_DEBUG_PRIME_RATELIMITED(NULL, fmt, ##args)
-
-/* Format strings and argument splitters to simplify printing
- * various "complex" objects
- */
-
-/*@}*/
-
 /***********************************************************************/
 /** \name Internal types and structures */
 /*@{*/
 
 #define DRM_IF_VERSION(maj, min) (maj << 16 | min)
 
-
 /**
  * drm_drv_uses_atomic_modeset - check if the driver implements
  * atomic_commit()
index d2b56cc..4842ee9 100644 (file)
@@ -38,6 +38,13 @@ struct drm_private_state;
 
 int drm_atomic_helper_check_modeset(struct drm_device *dev,
                                struct drm_atomic_state *state);
+int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
+                                       const struct drm_crtc_state *crtc_state,
+                                       const struct drm_rect *clip,
+                                       int min_scale,
+                                       int max_scale,
+                                       bool can_position,
+                                       bool can_update_disabled);
 int drm_atomic_helper_check_planes(struct drm_device *dev,
                               struct drm_atomic_state *state);
 int drm_atomic_helper_check(struct drm_device *dev,
index df9807a..66d6c99 100644 (file)
@@ -269,6 +269,11 @@ struct drm_display_info {
         */
        bool dvi_dual;
 
+       /**
+        * @has_hdmi_infoframe: Does the sink support the HDMI infoframe?
+        */
+       bool has_hdmi_infoframe;
+
        /**
         * @edid_hdmi_dc_modes: Mask of supported hdmi deep color modes. Even
         * more stuff redundant with @bus_formats.
@@ -704,7 +709,6 @@ struct drm_cmdline_mode {
  * @force: a DRM_FORCE_<foo> state for forced mode sets
  * @override_edid: has the EDID been overwritten through debugfs for testing?
  * @encoder_ids: valid encoders for this connector
- * @encoder: encoder driving this connector, if any
  * @eld: EDID-like data, if present
  * @latency_present: AV delay info from ELD, if found
  * @video_latency: video latency info from ELD, if found
@@ -874,7 +878,13 @@ struct drm_connector {
 
 #define DRM_CONNECTOR_MAX_ENCODER 3
        uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
-       struct drm_encoder *encoder; /* currently active encoder */
+       /**
+        * @encoder: Currently bound encoder driving this connector, if any.
+        * Only really meaningful for non-atomic drivers. Atomic drivers should
+        * instead look at &drm_connector_state.best_encoder, and in case they
+        * need the CRTC driving this output, &drm_connector_state.crtc.
+        */
+       struct drm_encoder *encoder;
 
 #define MAX_ELD_BYTES  128
        /* EDID bits */
index e21af87..7c4fa32 100644 (file)
@@ -17,6 +17,7 @@ struct drm_vblank_crtc;
 struct drm_sg_mem;
 struct drm_local_map;
 struct drm_vma_offset_manager;
+struct drm_fb_helper;
 
 struct inode;
 
@@ -185,6 +186,14 @@ struct drm_device {
        struct drm_vma_offset_manager *vma_offset_manager;
        /*@} */
        int switch_power_state;
+
+       /**
+        * @fb_helper:
+        *
+        * Pointer to the fbdev emulation structure.
+        * Set by drm_fb_helper_init() and cleared by drm_fb_helper_fini().
+        */
+       struct drm_fb_helper *fb_helper;
 };
 
 #endif
index 2623a12..da58a42 100644 (file)
 # define DP_SET_POWER_D0                    0x1
 # define DP_SET_POWER_D3                    0x2
 # define DP_SET_POWER_MASK                  0x3
+# define DP_SET_POWER_D3_AUX_ON             0x5
 
 #define DP_EDP_DPCD_REV                            0x700    /* eDP 1.2 */
 # define DP_EDP_11                         0x00
index 412e83a..d32b688 100644 (file)
@@ -39,6 +39,7 @@ struct drm_minor;
 struct dma_buf_attachment;
 struct drm_display_mode;
 struct drm_mode_create_dumb;
+struct drm_printer;
 
 /* driver capabilities and requirements mask */
 #define DRIVER_USE_AGP                 0x1
@@ -428,6 +429,20 @@ struct drm_driver {
         */
        void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);
 
+       /**
+        * @gem_print_info:
+        *
+        * If driver subclasses struct &drm_gem_object, it can implement this
+        * optional hook for printing additional driver specific info.
+        *
+        * drm_printf_indent() should be used in the callback passing it the
+        * indent argument.
+        *
+        * This callback is called from drm_gem_print_info().
+        */
+       void (*gem_print_info)(struct drm_printer *p, unsigned int indent,
+                              const struct drm_gem_object *obj);
+
        /**
         * @gem_create_object: constructor for gem objects
         *
@@ -592,13 +607,6 @@ struct drm_driver {
        int dev_priv_size;
 };
 
-__printf(6, 7)
-void drm_dev_printk(const struct device *dev, const char *level,
-                   unsigned int category, const char *function_name,
-                   const char *prefix, const char *format, ...);
-__printf(3, 4)
-void drm_printk(const char *level, unsigned int category,
-               const char *format, ...);
 extern unsigned int drm_debug;
 
 int drm_dev_init(struct drm_device *dev,
index 2ec41d0..b25d12e 100644 (file)
@@ -333,7 +333,6 @@ struct drm_encoder;
 struct drm_connector;
 struct drm_display_mode;
 
-void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid);
 int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads);
 int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb);
 int drm_av_sync_delay(struct drm_connector *connector,
@@ -357,6 +356,7 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
                                         bool is_hdmi2_sink);
 int
 drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
+                                           struct drm_connector *connector,
                                            const struct drm_display_mode *mode);
 void
 drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame,
index ee4cfbe..fb29969 100644 (file)
@@ -88,7 +88,6 @@ struct drm_encoder_funcs {
  * @head: list management
  * @base: base KMS object
  * @name: human readable name, can be overwritten by the driver
- * @crtc: currently bound CRTC
  * @bridge: bridge associated to the encoder
  * @funcs: control functions
  * @helper_private: mid-layer private data
@@ -166,6 +165,11 @@ struct drm_encoder {
         */
        uint32_t possible_clones;
 
+       /**
+        * @crtc: Currently bound CRTC, only really meaningful for non-atomic
+        * drivers.  Atomic drivers should instead check
+        * &drm_connector_state.crtc.
+        */
        struct drm_crtc *crtc;
        struct drm_bridge *bridge;
        const struct drm_encoder_funcs *funcs;
index faf56c5..65def43 100644 (file)
@@ -36,11 +36,5 @@ dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
                                   struct drm_plane_state *state,
                                   unsigned int plane);
 
-#ifdef CONFIG_DEBUG_FS
-struct seq_file;
-
-int drm_fb_cma_debugfs_show(struct seq_file *m, void *arg);
-#endif
-
 #endif
 
index 33fe959..877e5b3 100644 (file)
@@ -310,6 +310,9 @@ drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn);
 int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector);
 int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
                                       struct drm_connector *connector);
+
+void drm_fb_helper_lastclose(struct drm_device *dev);
+void drm_fb_helper_output_poll_changed(struct drm_device *dev);
 #else
 static inline void drm_fb_helper_prepare(struct drm_device *dev,
                                        struct drm_fb_helper *helper,
@@ -507,6 +510,14 @@ drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
        return 0;
 }
 
+static inline void drm_fb_helper_lastclose(struct drm_device *dev)
+{
+}
+
+static inline void drm_fb_helper_output_poll_changed(struct drm_device *dev)
+{
+}
+
 #endif
 
 static inline int
index 4c5ee4a..dccb897 100644 (file)
@@ -264,7 +264,7 @@ static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb)
  *
  * This functions returns the framebuffer's reference count.
  */
-static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb)
+static inline uint32_t drm_framebuffer_read_refcount(const struct drm_framebuffer *fb)
 {
        return kref_read(&fb->base.refcount);
 }
index 520e3fe..1977714 100644 (file)
@@ -9,7 +9,9 @@
  * struct drm_gem_cma_object - GEM object backed by CMA memory allocations
  * @base: base GEM object
  * @paddr: physical address of the backing memory
- * @sgt: scatter/gather table for imported PRIME buffers
+ * @sgt: scatter/gather table for imported PRIME buffers. The table can have
+ *       more than one entry but they are guaranteed to have contiguous
+ *       DMA addresses.
  * @vaddr: kernel virtual address of the backing memory
  */
 struct drm_gem_cma_object {
@@ -21,11 +23,8 @@ struct drm_gem_cma_object {
        void *vaddr;
 };
 
-static inline struct drm_gem_cma_object *
-to_drm_gem_cma_obj(struct drm_gem_object *gem_obj)
-{
-       return container_of(gem_obj, struct drm_gem_cma_object, base);
-}
+#define to_drm_gem_cma_obj(gem_obj) \
+       container_of(gem_obj, struct drm_gem_cma_object, base)
 
 #ifndef CONFIG_MMU
 #define DRM_GEM_CMA_UNMAPPED_AREA_FOPS \
@@ -91,9 +90,8 @@ unsigned long drm_gem_cma_get_unmapped_area(struct file *filp,
                                            unsigned long flags);
 #endif
 
-#ifdef CONFIG_DEBUG_FS
-void drm_gem_cma_describe(struct drm_gem_cma_object *obj, struct seq_file *m);
-#endif
+void drm_gem_cma_print_info(struct drm_printer *p, unsigned int indent,
+                           const struct drm_gem_object *obj);
 
 struct sg_table *drm_gem_cma_prime_get_sg_table(struct drm_gem_object *obj);
 struct drm_gem_object *
index 8d10fc9..101f566 100644 (file)
@@ -386,7 +386,7 @@ int drm_mm_insert_node_in_range(struct drm_mm *mm,
  * @color: opaque tag value to use for this node
  * @mode: fine-tune the allocation search and placement
  *
- * This is a simplified version of drm_mm_insert_node_in_range_generic() with no
+ * This is a simplified version of drm_mm_insert_node_in_range() with no
  * range restrictions applied.
  *
  * The preallocated node must be cleared to 0.
index b21e827..5306ebd 100644 (file)
@@ -752,7 +752,7 @@ struct drm_mode_config {
        bool allow_fb_modifiers;
 
        /**
-        * @modifiers: Plane property to list support modifier/format
+        * @modifiers_property: Plane property to list support modifier/format
         * combination.
         */
        struct drm_property *modifiers_property;
index 16646c4..3e76ca8 100644 (file)
@@ -801,9 +801,6 @@ struct drm_connector_helper_funcs {
         * resolution can call drm_add_modes_noedid(), and mark the preferred
         * one using drm_set_preferred_mode().
         *
-        * Finally drivers that support audio probably want to update the ELD
-        * data, too, using drm_edid_to_eld().
-        *
         * This function is only called after the @detect hook has indicated
         * that a sink is connected and when the EDID isn't overridden through
         * sysfs or the kernel commandline.
index 5716150..8185e34 100644 (file)
@@ -474,8 +474,8 @@ enum drm_plane_type {
  * @format_types: array of formats supported by this plane
  * @format_count: number of formats supported
  * @format_default: driver hasn't supplied supported formats for the plane
- * @crtc: currently bound CRTC
- * @fb: currently bound fb
+ * @modifiers: array of modifiers supported by this plane
+ * @modifier_count: number of modifiers supported
  * @old_fb: Temporary tracking of the old fb while a modeset is ongoing. Used by
  *     drm_mode_set_config_internal() to implement correct refcounting.
  * @funcs: helper functions
@@ -512,7 +512,17 @@ struct drm_plane {
        uint64_t *modifiers;
        unsigned int modifier_count;
 
+       /**
+        * @crtc: Currently bound CRTC, only really meaningful for non-atomic
+        * drivers.  Atomic drivers should instead check &drm_plane_state.crtc.
+        */
        struct drm_crtc *crtc;
+
+       /**
+        * @fb: Currently bound framebuffer, only really meaningful for
+        * non-atomic drivers.  Atomic drivers should instead check
+        * &drm_plane_state.fb.
+        */
        struct drm_framebuffer *fb;
 
        struct drm_framebuffer *old_fb;
index 7c8a00c..8aa49c0 100644 (file)
  */
 #define DRM_PLANE_HELPER_NO_SCALING (1<<16)
 
-int drm_plane_helper_check_state(struct drm_plane_state *state,
-                                const struct drm_rect *clip,
-                                int min_scale, int max_scale,
-                                bool can_position,
-                                bool can_update_disabled);
 int drm_plane_helper_check_update(struct drm_plane *plane,
                                  struct drm_crtc *crtc,
                                  struct drm_framebuffer *fb,
index ca4d7c6..5f9932e 100644 (file)
@@ -80,6 +80,29 @@ void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf);
 __printf(2, 3)
 void drm_printf(struct drm_printer *p, const char *f, ...);
 
+/**
+ * drm_vprintf - print to a &drm_printer stream
+ * @p: the &drm_printer
+ * @fmt: format string
+ * @va: the va_list
+ */
+__printf(2, 0)
+static inline void
+drm_vprintf(struct drm_printer *p, const char *fmt, va_list *va)
+{
+       struct va_format vaf = { .fmt = fmt, .va = va };
+
+       p->printfn(p, &vaf);
+}
+
+/**
+ * drm_printf_indent - Print to a &drm_printer stream with indentation
+ * @printer: DRM printer
+ * @indent: Tab indentation level (max 5)
+ * @fmt: Format string
+ */
+#define drm_printf_indent(printer, indent, fmt, ...) \
+       drm_printf((printer), "%.*s" fmt, (indent), "\t\t\t\t\tX", ##__VA_ARGS__)
 
 /**
  * drm_seq_file_printer - construct a &drm_printer that outputs to &seq_file
@@ -128,4 +151,200 @@ static inline struct drm_printer drm_debug_printer(const char *prefix)
        };
        return p;
 }
+
+/*
+ * The following categories are defined:
+ *
+ * CORE: Used in the generic drm code: drm_ioctl.c, drm_mm.c, drm_memory.c, ...
+ *      This is the category used by the DRM_DEBUG() macro.
+ *
+ * DRIVER: Used in the vendor specific part of the driver: i915, radeon, ...
+ *        This is the category used by the DRM_DEBUG_DRIVER() macro.
+ *
+ * KMS: used in the modesetting code.
+ *     This is the category used by the DRM_DEBUG_KMS() macro.
+ *
+ * PRIME: used in the prime code.
+ *       This is the category used by the DRM_DEBUG_PRIME() macro.
+ *
+ * ATOMIC: used in the atomic code.
+ *       This is the category used by the DRM_DEBUG_ATOMIC() macro.
+ *
+ * VBL: used for verbose debug message in the vblank code
+ *       This is the category used by the DRM_DEBUG_VBL() macro.
+ *
+ * Enabling verbose debug messages is done through the drm.debug parameter,
+ * each category being enabled by a bit.
+ *
+ * drm.debug=0x1 will enable CORE messages
+ * drm.debug=0x2 will enable DRIVER messages
+ * drm.debug=0x3 will enable CORE and DRIVER messages
+ * ...
+ * drm.debug=0x3f will enable all messages
+ *
+ * An interesting feature is that it's possible to enable verbose logging at
+ * run-time by echoing the debug value in its sysfs node:
+ *   # echo 0xf > /sys/module/drm/parameters/debug
+ */
+#define DRM_UT_NONE            0x00
+#define DRM_UT_CORE            0x01
+#define DRM_UT_DRIVER          0x02
+#define DRM_UT_KMS             0x04
+#define DRM_UT_PRIME           0x08
+#define DRM_UT_ATOMIC          0x10
+#define DRM_UT_VBL             0x20
+#define DRM_UT_STATE           0x40
+#define DRM_UT_LEASE           0x80
+
+__printf(6, 7)
+void drm_dev_printk(const struct device *dev, const char *level,
+                   unsigned int category, const char *function_name,
+                   const char *prefix, const char *format, ...);
+__printf(3, 4)
+void drm_printk(const char *level, unsigned int category,
+               const char *format, ...);
+
+/* Macros to make printk easier */
+
+#define _DRM_PRINTK(once, level, fmt, ...)                             \
+       do {                                                            \
+               printk##once(KERN_##level "[" DRM_NAME "] " fmt,        \
+                            ##__VA_ARGS__);                            \
+       } while (0)
+
+#define DRM_INFO(fmt, ...)                                             \
+       _DRM_PRINTK(, INFO, fmt, ##__VA_ARGS__)
+#define DRM_NOTE(fmt, ...)                                             \
+       _DRM_PRINTK(, NOTICE, fmt, ##__VA_ARGS__)
+#define DRM_WARN(fmt, ...)                                             \
+       _DRM_PRINTK(, WARNING, fmt, ##__VA_ARGS__)
+
+#define DRM_INFO_ONCE(fmt, ...)                                                \
+       _DRM_PRINTK(_once, INFO, fmt, ##__VA_ARGS__)
+#define DRM_NOTE_ONCE(fmt, ...)                                                \
+       _DRM_PRINTK(_once, NOTICE, fmt, ##__VA_ARGS__)
+#define DRM_WARN_ONCE(fmt, ...)                                                \
+       _DRM_PRINTK(_once, WARNING, fmt, ##__VA_ARGS__)
+
+/**
+ * Error output.
+ *
+ * @dev: device pointer
+ * @fmt: printf() like format string.
+ */
+#define DRM_DEV_ERROR(dev, fmt, ...)                                   \
+       drm_dev_printk(dev, KERN_ERR, DRM_UT_NONE, __func__, " *ERROR*",\
+                      fmt, ##__VA_ARGS__)
+#define DRM_ERROR(fmt, ...)                                            \
+       drm_printk(KERN_ERR, DRM_UT_NONE, fmt,  ##__VA_ARGS__)
+
+/**
+ * Rate limited error output.  Like DRM_ERROR() but won't flood the log.
+ *
+ * @dev: device pointer
+ * @fmt: printf() like format string.
+ */
+#define DRM_DEV_ERROR_RATELIMITED(dev, fmt, ...)                       \
+({                                                                     \
+       static DEFINE_RATELIMIT_STATE(_rs,                              \
+                                     DEFAULT_RATELIMIT_INTERVAL,       \
+                                     DEFAULT_RATELIMIT_BURST);         \
+                                                                       \
+       if (__ratelimit(&_rs))                                          \
+               DRM_DEV_ERROR(dev, fmt, ##__VA_ARGS__);                 \
+})
+#define DRM_ERROR_RATELIMITED(fmt, ...)                                        \
+       DRM_DEV_ERROR_RATELIMITED(NULL, fmt, ##__VA_ARGS__)
+
+#define DRM_DEV_INFO(dev, fmt, ...)                                    \
+       drm_dev_printk(dev, KERN_INFO, DRM_UT_NONE, __func__, "", fmt,  \
+                      ##__VA_ARGS__)
+
+#define DRM_DEV_INFO_ONCE(dev, fmt, ...)                               \
+({                                                                     \
+       static bool __print_once __read_mostly;                         \
+       if (!__print_once) {                                            \
+               __print_once = true;                                    \
+               DRM_DEV_INFO(dev, fmt, ##__VA_ARGS__);                  \
+       }                                                               \
+})
+
+/**
+ * Debug output.
+ *
+ * @dev: device pointer
+ * @fmt: printf() like format string.
+ */
+#define DRM_DEV_DEBUG(dev, fmt, args...)                               \
+       drm_dev_printk(dev, KERN_DEBUG, DRM_UT_CORE, __func__, "", fmt, \
+                      ##args)
+#define DRM_DEBUG(fmt, ...)                                            \
+       drm_printk(KERN_DEBUG, DRM_UT_CORE, fmt, ##__VA_ARGS__)
+
+#define DRM_DEV_DEBUG_DRIVER(dev, fmt, args...)                                \
+       drm_dev_printk(dev, KERN_DEBUG, DRM_UT_DRIVER, __func__, "",    \
+                      fmt, ##args)
+#define DRM_DEBUG_DRIVER(fmt, ...)                                     \
+       drm_printk(KERN_DEBUG, DRM_UT_DRIVER, fmt, ##__VA_ARGS__)
+
+#define DRM_DEV_DEBUG_KMS(dev, fmt, args...)                           \
+       drm_dev_printk(dev, KERN_DEBUG, DRM_UT_KMS, __func__, "", fmt,  \
+                      ##args)
+#define DRM_DEBUG_KMS(fmt, ...)                                        \
+       drm_printk(KERN_DEBUG, DRM_UT_KMS, fmt, ##__VA_ARGS__)
+
+#define DRM_DEV_DEBUG_PRIME(dev, fmt, args...)                         \
+       drm_dev_printk(dev, KERN_DEBUG, DRM_UT_PRIME, __func__, "",     \
+                      fmt, ##args)
+#define DRM_DEBUG_PRIME(fmt, ...)                                      \
+       drm_printk(KERN_DEBUG, DRM_UT_PRIME, fmt, ##__VA_ARGS__)
+
+#define DRM_DEV_DEBUG_ATOMIC(dev, fmt, args...)                                \
+       drm_dev_printk(dev, KERN_DEBUG, DRM_UT_ATOMIC, __func__, "",    \
+                      fmt, ##args)
+#define DRM_DEBUG_ATOMIC(fmt, ...)                                     \
+       drm_printk(KERN_DEBUG, DRM_UT_ATOMIC, fmt, ##__VA_ARGS__)
+
+#define DRM_DEV_DEBUG_VBL(dev, fmt, args...)                           \
+       drm_dev_printk(dev, KERN_DEBUG, DRM_UT_VBL, __func__, "", fmt,  \
+                      ##args)
+#define DRM_DEBUG_VBL(fmt, ...)                                        \
+       drm_printk(KERN_DEBUG, DRM_UT_VBL, fmt, ##__VA_ARGS__)
+
+#define DRM_DEBUG_LEASE(fmt, ...)                                      \
+       drm_printk(KERN_DEBUG, DRM_UT_LEASE, fmt, ##__VA_ARGS__)
+
+#define _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, level, fmt, args...)    \
+({                                                                     \
+       static DEFINE_RATELIMIT_STATE(_rs,                              \
+                                     DEFAULT_RATELIMIT_INTERVAL,       \
+                                     DEFAULT_RATELIMIT_BURST);         \
+       if (__ratelimit(&_rs))                                          \
+               drm_dev_printk(dev, KERN_DEBUG, DRM_UT_ ## level,       \
+                              __func__, "", fmt, ##args);              \
+})
+
+/**
+ * Rate limited debug output. Like DRM_DEBUG() but won't flood the log.
+ *
+ * @dev: device pointer
+ * @fmt: printf() like format string.
+ */
+#define DRM_DEV_DEBUG_RATELIMITED(dev, fmt, args...)                   \
+       DEV__DRM_DEFINE_DEBUG_RATELIMITED(dev, CORE, fmt, ##args)
+#define DRM_DEBUG_RATELIMITED(fmt, args...)                            \
+       DRM_DEV_DEBUG_RATELIMITED(NULL, fmt, ##args)
+#define DRM_DEV_DEBUG_DRIVER_RATELIMITED(dev, fmt, args...)            \
+       _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, DRIVER, fmt, ##args)
+#define DRM_DEBUG_DRIVER_RATELIMITED(fmt, args...)                     \
+       DRM_DEV_DEBUG_DRIVER_RATELIMITED(NULL, fmt, ##args)
+#define DRM_DEV_DEBUG_KMS_RATELIMITED(dev, fmt, args...)               \
+       _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, KMS, fmt, ##args)
+#define DRM_DEBUG_KMS_RATELIMITED(fmt, args...)                                \
+       DRM_DEV_DEBUG_KMS_RATELIMITED(NULL, fmt, ##args)
+#define DRM_DEV_DEBUG_PRIME_RATELIMITED(dev, fmt, args...)             \
+       _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, PRIME, fmt, ##args)
+#define DRM_DEBUG_PRIME_RATELIMITED(fmt, args...)                      \
+       DRM_DEV_DEBUG_PRIME_RATELIMITED(NULL, fmt, ##args)
+
 #endif /* DRM_PRINT_H_ */
index 43e2f38..9e8ba90 100644 (file)
@@ -49,7 +49,7 @@ struct drm_syncobj {
         * This field should not be used directly.  Use drm_syncobj_fence_get
         * and drm_syncobj_replace_fence instead.
         */
-       struct dma_fence *fence;
+       struct dma_fence __rcu *fence;
        /**
         * @cb_list:
         * List of callbacks to call when the fence gets replaced
index d84d52f..8758df9 100644 (file)
@@ -152,7 +152,7 @@ static inline void drm_vma_node_reset(struct drm_vma_offset_node *node)
  * Start address of @node for page-based addressing. 0 if the node does not
  * have an offset allocated.
  */
-static inline unsigned long drm_vma_node_start(struct drm_vma_offset_node *node)
+static inline unsigned long drm_vma_node_start(const struct drm_vma_offset_node *node)
 {
        return node->vm_node.start;
 }
index 4774fe3..4238289 100644 (file)
@@ -46,6 +46,7 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe)
  */
 #define TINYDRM_GEM_DRIVER_OPS \
        .gem_free_object        = tinydrm_gem_cma_free_object, \
+       .gem_print_info         = drm_gem_cma_print_info, \
        .gem_vm_ops             = &drm_gem_cma_vm_ops, \
        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd, \
        .prime_fd_to_handle     = drm_gem_prime_fd_to_handle, \
index 332a542..bc8940c 100644 (file)
@@ -21,6 +21,7 @@
 #define __LINUX_DMA_FENCE_ARRAY_H
 
 #include <linux/dma-fence.h>
+#include <linux/irq_work.h>
 
 /**
  * struct dma_fence_array_cb - callback helper for fence array
@@ -47,6 +48,8 @@ struct dma_fence_array {
        unsigned num_fences;
        atomic_t num_pending;
        struct dma_fence **fences;
+
+       struct irq_work work;
 };
 
 extern const struct dma_fence_ops dma_fence_array_ops;
index efdabbb..4c00817 100644 (file)
@@ -242,7 +242,7 @@ static inline struct dma_fence *dma_fence_get_rcu(struct dma_fence *fence)
  * The caller is required to hold the RCU read lock.
  */
 static inline struct dma_fence *
-dma_fence_get_rcu_safe(struct dma_fence * __rcu *fencep)
+dma_fence_get_rcu_safe(struct dma_fence __rcu **fencep)
 {
        do {
                struct dma_fence *fence;
index 21fc84d..02166e8 100644 (file)
@@ -166,6 +166,29 @@ reservation_object_lock(struct reservation_object *obj,
        return ww_mutex_lock(&obj->lock, ctx);
 }
 
+/**
+ * reservation_object_lock_interruptible - lock the reservation object
+ * @obj: the reservation object
+ * @ctx: the locking context
+ *
+ * Locks the reservation object interruptible for exclusive access and
+ * modification. Note, that the lock is only against other writers, readers
+ * will run concurrently with a writer under RCU. The seqlock is used to
+ * notify readers if they overlap with a writer.
+ *
+ * As the reservation object may be locked by multiple parties in an
+ * undefined order, a #ww_acquire_ctx is passed to unwind if a cycle
+ * is detected. See ww_mutex_lock() and ww_acquire_init(). A reservation
+ * object may be locked by itself by passing NULL as @ctx.
+ */
+static inline int
+reservation_object_lock_interruptible(struct reservation_object *obj,
+                                     struct ww_acquire_ctx *ctx)
+{
+       return ww_mutex_lock_interruptible(&obj->lock, ctx);
+}
+
+
 /**
  * reservation_object_trylock - trylock the reservation object
  * @obj: the reservation object