Merge tag 'drm-misc-next-2020-01-02' of git://anongit.freedesktop.org/drm/drm-misc...
authorDave Airlie <airlied@redhat.com>
Fri, 3 Jan 2020 01:43:31 +0000 (11:43 +1000)
committerDave Airlie <airlied@redhat.com>
Fri, 3 Jan 2020 01:43:44 +0000 (11:43 +1000)
drm-misc-next for v5.6:

UAPI Changes:
- Commandline parser: Add support for panel orientation, and per-mode options.
- Fix IOCTL naming for dma-buf heaps.

Cross-subsystem Changes:
- Rename DMA_HEAP_IOC_ALLOC to DMA_HEAP_IOCTL_ALLOC before it becomes abi.
- Change DMA-BUF system-heap's name to system.
- Fix leak in error handling in dma_heap_ioctl(), and make a symbol static.
- Fix udma-buf cpu access.
- Fix ti devicetree bindings.

Core Changes:
- Add CTA-861-G modes with VIC >= 193.
- Change error handling and remove bug_on in *drm_dev_init.
- Export drm_panel_of_backlight() correctly once more.
- Add support for lvds decoders.
- Convert drm/client and drm/(gem-,)fb-helper to drm-device based logging and update logging todo.

Driver Changes:
- Add support for dsi/px30 to rockchip.
- Add fb damage support to virtio.
- Use dma_resv locking wrappers in vc4, msm, etnaviv.
- Make functions in virtio static, and perform some simplifications.
- Add suspend support to sun4i.
- Add A64 mipi dsi support to sun4i.
- Add runtime pm suspend to komeda.
- Associated driver fixes.

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/efc11139-1653-86bc-1b0f-0aefde219850@linux.intel.com
67 files changed:
Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt [deleted file]
Documentation/devicetree/bindings/display/bridge/thine,thc63lvdm83d.txt [deleted file]
Documentation/devicetree/bindings/display/bridge/ti,ds90c185.txt [deleted file]
Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt
Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml
Documentation/fb/modedb.rst
Documentation/gpu/todo.rst
drivers/dma-buf/dma-heap.c
drivers/dma-buf/heaps/system_heap.c
drivers/dma-buf/udmabuf.c
drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c
drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h
drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
drivers/gpu/drm/arm/display/komeda/komeda_dev.c
drivers/gpu/drm/arm/display/komeda/komeda_dev.h
drivers/gpu/drm/arm/display/komeda/komeda_drv.c
drivers/gpu/drm/arm/display/komeda/komeda_event.c
drivers/gpu/drm/arm/display/komeda/komeda_kms.c
drivers/gpu/drm/arm/malidp_planes.c
drivers/gpu/drm/bochs/bochs_hw.c
drivers/gpu/drm/bridge/Kconfig
drivers/gpu/drm/bridge/Makefile
drivers/gpu/drm/bridge/lvds-codec.c [new file with mode: 0644]
drivers/gpu/drm/bridge/lvds-encoder.c [deleted file]
drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_atomic_uapi.c
drivers/gpu/drm/drm_client.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_gem_framebuffer_helper.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/drm_panel.c
drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
drivers/gpu/drm/gma500/accel_2d.c
drivers/gpu/drm/mcde/mcde_dsi.c
drivers/gpu/drm/mcde/mcde_dsi_regs.h
drivers/gpu/drm/mediatek/mtk_drm_plane.c
drivers/gpu/drm/msm/msm_gem_submit.c
drivers/gpu/drm/panel/panel-lg-lg4573.c
drivers/gpu/drm/rockchip/Kconfig
drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
drivers/gpu/drm/selftests/drm_cmdline_selftests.h
drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
drivers/gpu/drm/stm/ltdc.c
drivers/gpu/drm/sun4i/sun4i_drv.c
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
drivers/gpu/drm/vc4/vc4_gem.c
drivers/gpu/drm/virtio/virtgpu_display.c
drivers/gpu/drm/virtio/virtgpu_drv.h
drivers/gpu/drm/virtio/virtgpu_fence.c
drivers/gpu/drm/virtio/virtgpu_gem.c
drivers/gpu/drm/virtio/virtgpu_plane.c
drivers/gpu/drm/virtio/virtgpu_vq.c
include/drm/bridge/dw_mipi_dsi.h
include/drm/drm_atomic.h
include/drm/drm_atomic_helper.h
include/drm/drm_connector.h
include/drm/drm_panel.h
include/drm/drm_print.h
include/uapi/linux/dma-heap.h
tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c

index 0f70749..9e90c2b 100644 (file)
@@ -15,7 +15,9 @@ properties:
   "#size-cells": true
 
   compatible:
-    const: allwinner,sun6i-a31-mipi-dsi
+    enum:
+      - allwinner,sun6i-a31-mipi-dsi
+      - allwinner,sun50i-a64-mipi-dsi
 
   reg:
     maxItems: 1
@@ -24,6 +26,8 @@ properties:
     maxItems: 1
 
   clocks:
+    minItems: 1
+    maxItems: 2
     items:
       - description: Bus Clock
       - description: Module Clock
@@ -63,13 +67,38 @@ required:
   - reg
   - interrupts
   - clocks
-  - clock-names
   - phys
   - phy-names
   - resets
   - vcc-dsi-supply
   - port
 
+allOf:
+  - if:
+      properties:
+         compatible:
+           contains:
+             const: allwinner,sun6i-a31-mipi-dsi
+
+    then:
+        properties:
+          clocks:
+            minItems: 2
+
+        required:
+          - clock-names
+
+  - if:
+      properties:
+         compatible:
+           contains:
+             const: allwinner,sun50i-a64-mipi-dsi
+
+    then:
+        properties:
+          clocks:
+            minItems: 1
+
 additionalProperties: false
 
 examples:
diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml
new file mode 100644 (file)
index 0000000..8f37302
--- /dev/null
@@ -0,0 +1,131 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/lvds-codec.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Transparent LVDS encoders and decoders
+
+maintainers:
+  - Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+
+description: |
+  This binding supports transparent LVDS encoders and decoders that don't
+  require any configuration.
+
+  LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple
+  incompatible data link layers have been used over time to transmit image data
+  to LVDS panels. This binding targets devices compatible with the following
+  specifications only.
+
+  [JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February
+  1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA)
+  [LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National
+  Semiconductor
+  [VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video
+  Electronics Standards Association (VESA)
+
+  Those devices have been marketed under the FPD-Link and FlatLink brand names
+  among others.
+
+properties:
+  compatible:
+    oneOf:
+      - items:
+        - enum:
+          - ti,ds90c185       # For the TI DS90C185 FPD-Link Serializer
+          - ti,ds90c187       # For the TI DS90C187 FPD-Link Serializer
+          - ti,sn75lvds83     # For the TI SN75LVDS83 FlatLink transmitter
+        - const: lvds-encoder # Generic LVDS encoder compatible fallback
+      - items:
+        - enum:
+          - ti,ds90cf384a     # For the DS90CF384A FPD-Link LVDS Receiver
+        - const: lvds-decoder # Generic LVDS decoders compatible fallback
+      - enum:
+        - thine,thc63lvdm83d  # For the THC63LVDM83D LVDS serializer
+
+  ports:
+    type: object
+    description: |
+      This device has two video ports. Their connections are modeled using the
+      OF graph bindings specified in Documentation/devicetree/bindings/graph.txt
+    properties:
+      port@0:
+        type: object
+        description: |
+          For LVDS encoders, port 0 is the parallel input
+          For LVDS decoders, port 0 is the LVDS input
+
+      port@1:
+        type: object
+        description: |
+          For LVDS encoders, port 1 is the LVDS output
+          For LVDS decoders, port 1 is the parallel output
+
+    required:
+      - port@0
+      - port@1
+
+  powerdown-gpios:
+    description:
+      The GPIO used to control the power down line of this device.
+    maxItems: 1
+
+required:
+  - compatible
+  - ports
+
+examples:
+  - |
+    lvds-encoder {
+      compatible = "ti,ds90c185", "lvds-encoder";
+
+      ports {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        port@0 {
+          reg = <0>;
+
+          lvds_enc_in: endpoint {
+            remote-endpoint = <&display_out_rgb>;
+          };
+        };
+
+        port@1 {
+          reg = <1>;
+
+          lvds_enc_out: endpoint {
+            remote-endpoint = <&lvds_panel_in>;
+          };
+        };
+      };
+    };
+
+  - |
+    lvds-decoder {
+      compatible = "ti,ds90cf384a", "lvds-decoder";
+
+      ports {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        port@0 {
+          reg = <0>;
+
+          lvds_dec_in: endpoint {
+            remote-endpoint = <&display_out_lvds>;
+          };
+        };
+
+        port@1 {
+          reg = <1>;
+
+          lvds_dec_out: endpoint {
+            remote-endpoint = <&rgb_panel_in>;
+          };
+        };
+      };
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
deleted file mode 100644 (file)
index 60091db..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-Parallel to LVDS Encoder
-------------------------
-
-This binding supports the parallel to LVDS encoders that don't require any
-configuration.
-
-LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple
-incompatible data link layers have been used over time to transmit image data
-to LVDS panels. This binding targets devices compatible with the following
-specifications only.
-
-[JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February
-1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA)
-[LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National
-Semiconductor
-[VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video
-Electronics Standards Association (VESA)
-
-Those devices have been marketed under the FPD-Link and FlatLink brand names
-among others.
-
-
-Required properties:
-
-- compatible: Must be "lvds-encoder"
-
-  Any encoder compatible with this generic binding, but with additional
-  properties not listed here, must list a device specific compatible first
-  followed by this generic compatible.
-
-Required nodes:
-
-This device has two video ports. Their connections are modeled using the OF
-graph bindings specified in Documentation/devicetree/bindings/graph.txt.
-
-- Video port 0 for parallel input
-- Video port 1 for LVDS output
-
-
-Example
--------
-
-lvds-encoder {
-       compatible = "lvds-encoder";
-
-       ports {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               port@0 {
-                       reg = <0>;
-
-                       lvds_enc_in: endpoint {
-                               remote-endpoint = <&display_out_rgb>;
-                       };
-               };
-
-               port@1 {
-                       reg = <1>;
-
-                       lvds_enc_out: endpoint {
-                               remote-endpoint = <&lvds_panel_in>;
-                       };
-               };
-       };
-};
diff --git a/Documentation/devicetree/bindings/display/bridge/thine,thc63lvdm83d.txt b/Documentation/devicetree/bindings/display/bridge/thine,thc63lvdm83d.txt
deleted file mode 100644 (file)
index fee3c88..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-THine Electronics THC63LVDM83D LVDS serializer
-----------------------------------------------
-
-The THC63LVDM83D is an LVDS serializer designed to support pixel data
-transmission between a host and a flat panel.
-
-Required properties:
-
-- compatible: Should be "thine,thc63lvdm83d"
-
-Optional properties:
-
-- powerdown-gpios: Power down control GPIO (the /PWDN pin, active low).
-
-Required nodes:
-
-The THC63LVDM83D has two video ports. Their connections are modeled using the
-OFgraph bindings specified in Documentation/devicetree/bindings/graph.txt.
-
-- Video port 0 for CMOS/TTL input
-- Video port 1 for LVDS output
-
-
-Example
--------
-
-       lvds_enc: encoder@0 {
-               compatible = "thine,thc63lvdm83d";
-
-               ports {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-
-                       port@0 {
-                               reg = <0>;
-
-                               lvds_enc_in: endpoint@0 {
-                                       remote-endpoint = <&rgb_out>;
-                               };
-                       };
-
-                       port@1 {
-                               reg = <1>;
-
-                               lvds_enc_out: endpoint@0 {
-                                       remote-endpoint = <&panel_in>;
-                               };
-                       };
-               };
-       };
diff --git a/Documentation/devicetree/bindings/display/bridge/ti,ds90c185.txt b/Documentation/devicetree/bindings/display/bridge/ti,ds90c185.txt
deleted file mode 100644 (file)
index e575f99..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-Texas Instruments FPD-Link (LVDS) Serializer
---------------------------------------------
-
-The DS90C185 and DS90C187 are low-power serializers for portable
-battery-powered applications that reduces the size of the RGB
-interface between the host GPU and the display.
-
-Required properties:
-
-- compatible: Should be
-  "ti,ds90c185", "lvds-encoder"  for the TI DS90C185 FPD-Link Serializer
-  "ti,ds90c187", "lvds-encoder"  for the TI DS90C187 FPD-Link Serializer
-
-Optional properties:
-
-- powerdown-gpios: Power down control GPIO (the PDB pin, active-low)
-
-Required nodes:
-
-The devices have two video ports. Their connections are modeled using the OF
-graph bindings specified in Documentation/devicetree/bindings/graph.txt.
-
-- Video port 0 for parallel input
-- Video port 1 for LVDS output
-
-
-Example
--------
-
-lvds-encoder {
-       compatible = "ti,ds90c185", "lvds-encoder";
-
-       powerdown-gpios = <&gpio 17 GPIO_ACTIVE_LOW>;
-
-       ports {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               port@0 {
-                       reg = <0>;
-
-                       lvds_enc_in: endpoint {
-                               remote-endpoint = <&lcdc_out_rgb>;
-                       };
-               };
-
-               port@1 {
-                       reg = <1>;
-
-                       lvds_enc_out: endpoint {
-                               remote-endpoint = <&lvds_panel_in>;
-                       };
-               };
-       };
-};
index ce4c1fc..151be3b 100644 (file)
@@ -4,13 +4,16 @@ Rockchip specific extensions to the Synopsys Designware MIPI DSI
 Required properties:
 - #address-cells: Should be <1>.
 - #size-cells: Should be <0>.
-- compatible: "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi".
-             "rockchip,rk3399-mipi-dsi", "snps,dw-mipi-dsi".
+- compatible: one of
+       "rockchip,px30-mipi-dsi", "snps,dw-mipi-dsi"
+       "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi"
+       "rockchip,rk3399-mipi-dsi", "snps,dw-mipi-dsi"
 - reg: Represent the physical address range of the controller.
 - interrupts: Represent the controller's interrupt to the CPU(s).
 - clocks, clock-names: Phandles to the controller's pll reference
-  clock(ref) and APB clock(pclk). For RK3399, a phy config clock
-  (phy_cfg) and a grf clock(grf) are required. As described in [1].
+  clock(ref) when using an internal dphy and APB clock(pclk).
+  For RK3399, a phy config clock (phy_cfg) and a grf clock(grf)
+  are required. As described in [1].
 - rockchip,grf: this soc should set GRF regs to mux vopl/vopb.
 - ports: contain a port node with endpoint definitions as defined in [2].
   For vopb,set the reg = <0> and set the reg = <1> for vopl.
@@ -18,6 +21,8 @@ Required properties:
 - video port 1 for either a panel or subsequent encoder
 
 Optional properties:
+- phys: from general PHY binding: the phandle for the PHY device.
+- phy-names: Should be "dphy" if phys references an external phy.
 - power-domains: a phandle to mipi dsi power domain node.
 - resets: list of phandle + reset specifier pairs, as described in [3].
 - reset-names: string reset name, must be "apb".
index 230d74f..d0b541a 100644 (file)
@@ -15,7 +15,11 @@ properties:
     const: 0
 
   compatible:
-    const: allwinner,sun6i-a31-mipi-dphy
+    oneOf:
+      - const: allwinner,sun6i-a31-mipi-dphy
+      - items:
+          - const: allwinner,sun50i-a64-mipi-dphy
+          - const: allwinner,sun6i-a31-mipi-dphy
 
   reg:
     maxItems: 1
index 9c4e3fd..624d08f 100644 (file)
@@ -65,6 +65,9 @@ Valid options are::
   - reflect_y (boolean): Perform an axial symmetry on the Y axis
   - rotate (integer): Rotate the initial framebuffer by x
     degrees. Valid values are 0, 90, 180 and 270.
+  - panel_orientation, one of "normal", "upside_down", "left_side_up", or
+    "right_side_up". For KMS drivers only, this sets the "panel orientation"
+    property on the kms connector as hint for kms users.
 
 
 -----------------------------------------------------------------------------
index 2d85f37..bc869b2 100644 (file)
@@ -142,14 +142,14 @@ Contact: Daniel Vetter, respective driver maintainers
 
 Level: Advanced
 
-Convert instances of dev_info/dev_err/dev_warn to their DRM_DEV_* equivalent
-----------------------------------------------------------------------------
+Convert logging to drm_* functions with drm_device paramater
+------------------------------------------------------------
 
 For drivers which could have multiple instances, it is necessary to
 differentiate between which is which in the logs. Since DRM_INFO/WARN/ERROR
 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.
+now have drm_* variants of the drm print functions, so we can start to convert
+those drivers back to using drm-formatted 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
index 4f04d10..afd22c9 100644 (file)
@@ -106,8 +106,8 @@ static long dma_heap_ioctl_allocate(struct file *file, void *data)
        return 0;
 }
 
-unsigned int dma_heap_ioctl_cmds[] = {
-       DMA_HEAP_IOC_ALLOC,
+static unsigned int dma_heap_ioctl_cmds[] = {
+       DMA_HEAP_IOCTL_ALLOC,
 };
 
 static long dma_heap_ioctl(struct file *file, unsigned int ucmd,
@@ -153,11 +153,12 @@ static long dma_heap_ioctl(struct file *file, unsigned int ucmd,
                memset(kdata + in_size, 0, ksize - in_size);
 
        switch (kcmd) {
-       case DMA_HEAP_IOC_ALLOC:
+       case DMA_HEAP_IOCTL_ALLOC:
                ret = dma_heap_ioctl_allocate(file, kdata);
                break;
        default:
-               return -ENOTTY;
+               ret = -ENOTTY;
+               goto err;
        }
 
        if (copy_to_user((void __user *)arg, kdata, out_size) != 0)
index 1aa01e9..0bf688e 100644 (file)
@@ -109,7 +109,7 @@ static int system_heap_create(void)
        struct dma_heap_export_info exp_info;
        int ret = 0;
 
-       exp_info.name = "system_heap";
+       exp_info.name = "system";
        exp_info.ops = &system_heap_ops;
        exp_info.priv = NULL;
 
index 61b0a2c..acb26c6 100644 (file)
@@ -122,9 +122,8 @@ static int begin_cpu_udmabuf(struct dma_buf *buf,
                if (IS_ERR(ubuf->sg))
                        return PTR_ERR(ubuf->sg);
        } else {
-               dma_sync_sg_for_device(dev, ubuf->sg->sgl,
-                                      ubuf->sg->nents,
-                                      direction);
+               dma_sync_sg_for_cpu(dev, ubuf->sg->sgl, ubuf->sg->nents,
+                                   direction);
        }
 
        return 0;
@@ -139,7 +138,7 @@ static int end_cpu_udmabuf(struct dma_buf *buf,
        if (!ubuf->sg)
                return -EINVAL;
 
-       dma_sync_sg_for_cpu(dev, ubuf->sg->sgl, ubuf->sg->nents, direction);
+       dma_sync_sg_for_device(dev, ubuf->sg->sgl, ubuf->sg->nents, direction);
        return 0;
 }
 
index dd1ecf4..00fa56c 100644 (file)
@@ -20,8 +20,10 @@ static u64 get_lpu_event(struct d71_pipeline *d71_pipeline)
                evts |= KOMEDA_EVENT_IBSY;
        if (raw_status & LPU_IRQ_EOW)
                evts |= KOMEDA_EVENT_EOW;
+       if (raw_status & LPU_IRQ_OVR)
+               evts |= KOMEDA_EVENT_OVR;
 
-       if (raw_status & (LPU_IRQ_ERR | LPU_IRQ_IBSY)) {
+       if (raw_status & (LPU_IRQ_ERR | LPU_IRQ_IBSY | LPU_IRQ_OVR)) {
                u32 restore = 0, tbu_status;
                /* Check error of LPU status */
                status = malidp_read32(reg, BLK_STATUS);
@@ -45,6 +47,15 @@ static u64 get_lpu_event(struct d71_pipeline *d71_pipeline)
                        restore |= LPU_STATUS_ACE3;
                        evts |= KOMEDA_ERR_ACE3;
                }
+               if (status & LPU_STATUS_FEMPTY) {
+                       restore |= LPU_STATUS_FEMPTY;
+                       evts |= KOMEDA_EVENT_EMPTY;
+               }
+               if (status & LPU_STATUS_FFULL) {
+                       restore |= LPU_STATUS_FFULL;
+                       evts |= KOMEDA_EVENT_FULL;
+               }
+
                if (restore != 0)
                        malidp_write32_mask(reg, BLK_STATUS, restore, 0);
 
index 81de6a2..e80172a 100644 (file)
 #define TBU_DOUTSTDCAPB_MASK   0x3F
 
 /* LPU_IRQ_BITS */
+#define LPU_IRQ_OVR            BIT(9)
 #define LPU_IRQ_IBSY           BIT(10)
 #define LPU_IRQ_ERR            BIT(11)
 #define LPU_IRQ_EOW            BIT(12)
 #define LPU_STATUS_AXIE                BIT(4)
 #define LPU_STATUS_AXIRP       BIT(5)
 #define LPU_STATUS_AXIWP       BIT(6)
+#define LPU_STATUS_FEMPTY      BIT(11)
+#define LPU_STATUS_FFULL       BIT(14)
 #define LPU_STATUS_ACE0                BIT(16)
 #define LPU_STATUS_ACE1                BIT(17)
 #define LPU_STATUS_ACE2                BIT(18)
index 1c452ea..56bd938 100644 (file)
@@ -5,6 +5,7 @@
  *
  */
 #include <linux/clk.h>
+#include <linux/pm_runtime.h>
 #include <linux/spinlock.h>
 
 #include <drm/drm_atomic.h>
@@ -274,6 +275,7 @@ static void
 komeda_crtc_atomic_enable(struct drm_crtc *crtc,
                          struct drm_crtc_state *old)
 {
+       pm_runtime_get_sync(crtc->dev->dev);
        komeda_crtc_prepare(to_kcrtc(crtc));
        drm_crtc_vblank_on(crtc);
        WARN_ON(drm_crtc_vblank_get(crtc));
@@ -372,6 +374,7 @@ komeda_crtc_atomic_disable(struct drm_crtc *crtc,
        drm_crtc_vblank_put(crtc);
        drm_crtc_vblank_off(crtc);
        komeda_crtc_unprepare(kcrtc);
+       pm_runtime_put(crtc->dev->dev);
 }
 
 static void
index 38b8328..1d76747 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/of_graph.h>
 #include <linux/of_reserved_mem.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/dma-mapping.h>
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
@@ -27,12 +28,16 @@ static int komeda_register_show(struct seq_file *sf, void *x)
 
        seq_puts(sf, "\n====== Komeda register dump =========\n");
 
+       pm_runtime_get_sync(mdev->dev);
+
        if (mdev->funcs->dump_register)
                mdev->funcs->dump_register(mdev, sf);
 
        for (i = 0; i < mdev->n_pipelines; i++)
                komeda_pipeline_dump_register(mdev->pipelines[i], sf);
 
+       pm_runtime_put(mdev->dev);
+
        return 0;
 }
 
@@ -263,15 +268,6 @@ struct komeda_dev *komeda_dev_create(struct device *dev)
        if (!mdev->iommu)
                DRM_INFO("continue without IOMMU support!\n");
 
-       if (mdev->iommu && mdev->funcs->connect_iommu) {
-               err = mdev->funcs->connect_iommu(mdev);
-               if (err) {
-                       DRM_ERROR("connect iommu failed.\n");
-                       mdev->iommu = NULL;
-                       goto disable_clk;
-               }
-       }
-
        clk_disable_unprepare(mdev->aclk);
 
        err = sysfs_create_group(&dev->kobj, &komeda_sysfs_attr_group);
@@ -310,11 +306,6 @@ void komeda_dev_destroy(struct komeda_dev *mdev)
        if (mdev->aclk)
                clk_prepare_enable(mdev->aclk);
 
-       if (mdev->iommu && mdev->funcs->disconnect_iommu)
-               if (mdev->funcs->disconnect_iommu(mdev))
-                       DRM_ERROR("disconnect iommu failed.\n");
-       mdev->iommu = NULL;
-
        for (i = 0; i < mdev->n_pipelines; i++) {
                komeda_pipeline_destroy(mdev, mdev->pipelines[i]);
                mdev->pipelines[i] = NULL;
@@ -343,44 +334,26 @@ void komeda_dev_destroy(struct komeda_dev *mdev)
 
 int komeda_dev_resume(struct komeda_dev *mdev)
 {
-       int ret = 0;
-
        clk_prepare_enable(mdev->aclk);
 
-       if (mdev->iommu && mdev->funcs->connect_iommu) {
-               ret = mdev->funcs->connect_iommu(mdev);
-               if (ret < 0) {
-                       DRM_ERROR("connect iommu failed.\n");
-                       goto disable_clk;
-               }
-       }
-
-       ret = mdev->funcs->enable_irq(mdev);
+       mdev->funcs->enable_irq(mdev);
 
-disable_clk:
-       clk_disable_unprepare(mdev->aclk);
+       if (mdev->iommu && mdev->funcs->connect_iommu)
+               if (mdev->funcs->connect_iommu(mdev))
+                       DRM_ERROR("connect iommu failed.\n");
 
-       return ret;
+       return 0;
 }
 
 int komeda_dev_suspend(struct komeda_dev *mdev)
 {
-       int ret = 0;
-
-       clk_prepare_enable(mdev->aclk);
-
-       if (mdev->iommu && mdev->funcs->disconnect_iommu) {
-               ret = mdev->funcs->disconnect_iommu(mdev);
-               if (ret < 0) {
+       if (mdev->iommu && mdev->funcs->disconnect_iommu)
+               if (mdev->funcs->disconnect_iommu(mdev))
                        DRM_ERROR("disconnect iommu failed.\n");
-                       goto disable_clk;
-               }
-       }
 
-       ret = mdev->funcs->disable_irq(mdev);
+       mdev->funcs->disable_irq(mdev);
 
-disable_clk:
        clk_disable_unprepare(mdev->aclk);
 
-       return ret;
+       return 0;
 }
index 4a67a80..ce27f2f 100644 (file)
@@ -20,6 +20,8 @@
 #define KOMEDA_EVENT_OVR               BIT_ULL(4)
 #define KOMEDA_EVENT_EOW               BIT_ULL(5)
 #define KOMEDA_EVENT_MODE              BIT_ULL(6)
+#define KOMEDA_EVENT_FULL              BIT_ULL(7)
+#define KOMEDA_EVENT_EMPTY             BIT_ULL(8)
 
 #define KOMEDA_ERR_TETO                        BIT_ULL(14)
 #define KOMEDA_ERR_TEMR                        BIT_ULL(15)
@@ -49,7 +51,8 @@
        KOMEDA_ERR_ZME          | KOMEDA_ERR_MERR       | KOMEDA_ERR_TCF |\
        KOMEDA_ERR_TTNG         | KOMEDA_ERR_TTF)
 
-#define KOMEDA_WARN_EVENTS     KOMEDA_ERR_CSCE
+#define KOMEDA_WARN_EVENTS     \
+       (KOMEDA_ERR_CSCE | KOMEDA_EVENT_FULL | KOMEDA_EVENT_EMPTY)
 
 #define KOMEDA_INFO_EVENTS (0 \
                            | KOMEDA_EVENT_VSYNC \
index ad38bbc..ea5cd1e 100644 (file)
@@ -33,6 +33,12 @@ static void komeda_unbind(struct device *dev)
                return;
 
        komeda_kms_detach(mdrv->kms);
+
+       if (pm_runtime_enabled(dev))
+               pm_runtime_disable(dev);
+       else
+               komeda_dev_suspend(mdrv->mdev);
+
        komeda_dev_destroy(mdrv->mdev);
 
        dev_set_drvdata(dev, NULL);
@@ -54,6 +60,10 @@ static int komeda_bind(struct device *dev)
                goto free_mdrv;
        }
 
+       pm_runtime_enable(dev);
+       if (!pm_runtime_enabled(dev))
+               komeda_dev_resume(mdrv->mdev);
+
        mdrv->kms = komeda_kms_attach(mdrv->mdev);
        if (IS_ERR(mdrv->kms)) {
                err = PTR_ERR(mdrv->kms);
@@ -65,6 +75,11 @@ static int komeda_bind(struct device *dev)
        return 0;
 
 destroy_mdev:
+       if (pm_runtime_enabled(dev))
+               pm_runtime_disable(dev);
+       else
+               komeda_dev_suspend(mdrv->mdev);
+
        komeda_dev_destroy(mdrv->mdev);
 
 free_mdrv:
@@ -131,15 +146,29 @@ static const struct of_device_id komeda_of_match[] = {
 
 MODULE_DEVICE_TABLE(of, komeda_of_match);
 
+static int komeda_rt_pm_suspend(struct device *dev)
+{
+       struct komeda_drv *mdrv = dev_get_drvdata(dev);
+
+       return komeda_dev_suspend(mdrv->mdev);
+}
+
+static int komeda_rt_pm_resume(struct device *dev)
+{
+       struct komeda_drv *mdrv = dev_get_drvdata(dev);
+
+       return komeda_dev_resume(mdrv->mdev);
+}
+
 static int __maybe_unused komeda_pm_suspend(struct device *dev)
 {
        struct komeda_drv *mdrv = dev_get_drvdata(dev);
-       struct drm_device *drm = &mdrv->kms->base;
        int res;
 
-       res = drm_mode_config_helper_suspend(drm);
+       res = drm_mode_config_helper_suspend(&mdrv->kms->base);
 
-       komeda_dev_suspend(mdrv->mdev);
+       if (!pm_runtime_status_suspended(dev))
+               komeda_dev_suspend(mdrv->mdev);
 
        return res;
 }
@@ -147,15 +176,16 @@ static int __maybe_unused komeda_pm_suspend(struct device *dev)
 static int __maybe_unused komeda_pm_resume(struct device *dev)
 {
        struct komeda_drv *mdrv = dev_get_drvdata(dev);
-       struct drm_device *drm = &mdrv->kms->base;
 
-       komeda_dev_resume(mdrv->mdev);
+       if (!pm_runtime_status_suspended(dev))
+               komeda_dev_resume(mdrv->mdev);
 
-       return drm_mode_config_helper_resume(drm);
+       return drm_mode_config_helper_resume(&mdrv->kms->base);
 }
 
 static const struct dev_pm_ops komeda_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(komeda_pm_suspend, komeda_pm_resume)
+       SET_RUNTIME_PM_OPS(komeda_rt_pm_suspend, komeda_rt_pm_resume, NULL)
 };
 
 static struct platform_driver komeda_platform_driver = {
index 977c38d..53f944e 100644 (file)
@@ -78,6 +78,8 @@ static void evt_str(struct komeda_str *str, u64 events)
 
        /* LPU errors or events */
        evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
+       evt_sprintf(str, events & KOMEDA_EVENT_EMPTY, "EMPTY|");
+       evt_sprintf(str, events & KOMEDA_EVENT_FULL, "FULL|");
        evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
        evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
        evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
index 2368a0a..442d465 100644 (file)
@@ -308,10 +308,6 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
        if (err)
                goto free_component_binding;
 
-       err = mdev->funcs->enable_irq(mdev);
-       if (err)
-               goto free_component_binding;
-
        drm->irq_enabled = true;
 
        drm_kms_helper_poll_init(drm);
@@ -325,7 +321,6 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
 free_interrupts:
        drm_kms_helper_poll_fini(drm);
        drm->irq_enabled = false;
-       mdev->funcs->disable_irq(mdev);
 free_component_binding:
        component_unbind_all(mdev->dev, drm);
 cleanup_mode_config:
@@ -347,7 +342,6 @@ void komeda_kms_detach(struct komeda_kms_dev *kms)
        drm_kms_helper_poll_fini(drm);
        drm_atomic_helper_shutdown(drm);
        drm->irq_enabled = false;
-       mdev->funcs->disable_irq(mdev);
        component_unbind_all(mdev->dev, drm);
        drm_mode_config_cleanup(drm);
        komeda_kms_cleanup_private_objs(kms);
index 3c70a53..37715cc 100644 (file)
@@ -512,7 +512,7 @@ static int malidp_de_plane_check(struct drm_plane *plane,
        int i, ret;
        unsigned int block_w, block_h;
 
-       if (!state->crtc || !state->fb)
+       if (!state->crtc || WARN_ON(!state->fb))
                return 0;
 
        fb = state->fb;
index e567bdf..b615b7d 100644 (file)
@@ -255,7 +255,7 @@ void bochs_hw_setformat(struct bochs_device *bochs,
                DRM_ERROR("%s: Huh? Got framebuffer format 0x%x",
                          __func__, format->format);
                break;
-       };
+       }
 }
 
 void bochs_hw_setbase(struct bochs_device *bochs,
index ccc698c..0b9ca58 100644 (file)
@@ -35,14 +35,14 @@ config DRM_DUMB_VGA_DAC
          Support for non-programmable RGB to VGA DAC bridges, such as ADI
          ADV7123, TI THS8134 and THS8135 or passive resistor ladder DACs.
 
-config DRM_LVDS_ENCODER
-       tristate "Transparent parallel to LVDS encoder support"
+config DRM_LVDS_CODEC
+       tristate "Transparent LVDS encoders and decoders support"
        depends on OF
        select DRM_KMS_HELPER
        select DRM_PANEL_BRIDGE
        help
-         Support for transparent parallel to LVDS encoders that don't require
-         any configuration.
+         Support for transparent LVDS encoders and decoders that don't
+         require any configuration.
 
 config DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW
        tristate "MegaChips stdp4028-ge-b850v3-fw and stdp2690-ge-b850v3-fw"
index a6c7dd7..cd16ce8 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o
 obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
-obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o
+obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o
 obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
 obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
diff --git a/drivers/gpu/drm/bridge/lvds-codec.c b/drivers/gpu/drm/bridge/lvds-codec.c
new file mode 100644 (file)
index 0000000..5f04cc1
--- /dev/null
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2019 Renesas Electronics Corporation
+ * Copyright (C) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+
+#include <drm/drm_bridge.h>
+#include <drm/drm_panel.h>
+
+struct lvds_codec {
+       struct drm_bridge bridge;
+       struct drm_bridge *panel_bridge;
+       struct gpio_desc *powerdown_gpio;
+       u32 connector_type;
+};
+
+static int lvds_codec_attach(struct drm_bridge *bridge)
+{
+       struct lvds_codec *lvds_codec = container_of(bridge,
+                                                    struct lvds_codec, bridge);
+
+       return drm_bridge_attach(bridge->encoder, lvds_codec->panel_bridge,
+                                bridge);
+}
+
+static void lvds_codec_enable(struct drm_bridge *bridge)
+{
+       struct lvds_codec *lvds_codec = container_of(bridge,
+                                                    struct lvds_codec, bridge);
+
+       if (lvds_codec->powerdown_gpio)
+               gpiod_set_value_cansleep(lvds_codec->powerdown_gpio, 0);
+}
+
+static void lvds_codec_disable(struct drm_bridge *bridge)
+{
+       struct lvds_codec *lvds_codec = container_of(bridge,
+                                                    struct lvds_codec, bridge);
+
+       if (lvds_codec->powerdown_gpio)
+               gpiod_set_value_cansleep(lvds_codec->powerdown_gpio, 1);
+}
+
+static struct drm_bridge_funcs funcs = {
+       .attach = lvds_codec_attach,
+       .enable = lvds_codec_enable,
+       .disable = lvds_codec_disable,
+};
+
+static int lvds_codec_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *panel_node;
+       struct drm_panel *panel;
+       struct lvds_codec *lvds_codec;
+
+       lvds_codec = devm_kzalloc(dev, sizeof(*lvds_codec), GFP_KERNEL);
+       if (!lvds_codec)
+               return -ENOMEM;
+
+       lvds_codec->connector_type = (uintptr_t)of_device_get_match_data(dev);
+       lvds_codec->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown",
+                                                            GPIOD_OUT_HIGH);
+       if (IS_ERR(lvds_codec->powerdown_gpio)) {
+               int err = PTR_ERR(lvds_codec->powerdown_gpio);
+
+               if (err != -EPROBE_DEFER)
+                       dev_err(dev, "powerdown GPIO failure: %d\n", err);
+               return err;
+       }
+
+       /* Locate the panel DT node. */
+       panel_node = of_graph_get_remote_node(dev->of_node, 1, 0);
+       if (!panel_node) {
+               dev_dbg(dev, "panel DT node not found\n");
+               return -ENXIO;
+       }
+
+       panel = of_drm_find_panel(panel_node);
+       of_node_put(panel_node);
+       if (IS_ERR(panel)) {
+               dev_dbg(dev, "panel not found, deferring probe\n");
+               return PTR_ERR(panel);
+       }
+
+       lvds_codec->panel_bridge =
+               devm_drm_panel_bridge_add_typed(dev, panel,
+                                               lvds_codec->connector_type);
+       if (IS_ERR(lvds_codec->panel_bridge))
+               return PTR_ERR(lvds_codec->panel_bridge);
+
+       /*
+        * The panel_bridge bridge is attached to the panel's of_node,
+        * but we need a bridge attached to our of_node for our user
+        * to look up.
+        */
+       lvds_codec->bridge.of_node = dev->of_node;
+       lvds_codec->bridge.funcs = &funcs;
+       drm_bridge_add(&lvds_codec->bridge);
+
+       platform_set_drvdata(pdev, lvds_codec);
+
+       return 0;
+}
+
+static int lvds_codec_remove(struct platform_device *pdev)
+{
+       struct lvds_codec *lvds_codec = platform_get_drvdata(pdev);
+
+       drm_bridge_remove(&lvds_codec->bridge);
+
+       return 0;
+}
+
+static const struct of_device_id lvds_codec_match[] = {
+       {
+               .compatible = "lvds-decoder",
+               .data = (void *)DRM_MODE_CONNECTOR_DPI,
+       },
+       {
+               .compatible = "lvds-encoder",
+               .data = (void *)DRM_MODE_CONNECTOR_LVDS,
+       },
+       {
+               .compatible = "thine,thc63lvdm83d",
+               .data = (void *)DRM_MODE_CONNECTOR_LVDS,
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, lvds_codec_match);
+
+static struct platform_driver lvds_codec_driver = {
+       .probe  = lvds_codec_probe,
+       .remove = lvds_codec_remove,
+       .driver         = {
+               .name           = "lvds-codec",
+               .of_match_table = lvds_codec_match,
+       },
+};
+module_platform_driver(lvds_codec_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("LVDS encoders and decoders");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c
deleted file mode 100644 (file)
index e2132a8..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
- */
-
-#include <linux/gpio/consumer.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_graph.h>
-#include <linux/platform_device.h>
-
-#include <drm/drm_bridge.h>
-#include <drm/drm_panel.h>
-
-struct lvds_encoder {
-       struct drm_bridge bridge;
-       struct drm_bridge *panel_bridge;
-       struct gpio_desc *powerdown_gpio;
-};
-
-static int lvds_encoder_attach(struct drm_bridge *bridge)
-{
-       struct lvds_encoder *lvds_encoder = container_of(bridge,
-                                                        struct lvds_encoder,
-                                                        bridge);
-
-       return drm_bridge_attach(bridge->encoder, lvds_encoder->panel_bridge,
-                                bridge);
-}
-
-static void lvds_encoder_enable(struct drm_bridge *bridge)
-{
-       struct lvds_encoder *lvds_encoder = container_of(bridge,
-                                                        struct lvds_encoder,
-                                                        bridge);
-
-       if (lvds_encoder->powerdown_gpio)
-               gpiod_set_value_cansleep(lvds_encoder->powerdown_gpio, 0);
-}
-
-static void lvds_encoder_disable(struct drm_bridge *bridge)
-{
-       struct lvds_encoder *lvds_encoder = container_of(bridge,
-                                                        struct lvds_encoder,
-                                                        bridge);
-
-       if (lvds_encoder->powerdown_gpio)
-               gpiod_set_value_cansleep(lvds_encoder->powerdown_gpio, 1);
-}
-
-static struct drm_bridge_funcs funcs = {
-       .attach = lvds_encoder_attach,
-       .enable = lvds_encoder_enable,
-       .disable = lvds_encoder_disable,
-};
-
-static int lvds_encoder_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *port;
-       struct device_node *endpoint;
-       struct device_node *panel_node;
-       struct drm_panel *panel;
-       struct lvds_encoder *lvds_encoder;
-
-       lvds_encoder = devm_kzalloc(dev, sizeof(*lvds_encoder), GFP_KERNEL);
-       if (!lvds_encoder)
-               return -ENOMEM;
-
-       lvds_encoder->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown",
-                                                              GPIOD_OUT_HIGH);
-       if (IS_ERR(lvds_encoder->powerdown_gpio)) {
-               int err = PTR_ERR(lvds_encoder->powerdown_gpio);
-
-               if (err != -EPROBE_DEFER)
-                       dev_err(dev, "powerdown GPIO failure: %d\n", err);
-               return err;
-       }
-
-       /* Locate the panel DT node. */
-       port = of_graph_get_port_by_id(dev->of_node, 1);
-       if (!port) {
-               dev_dbg(dev, "port 1 not found\n");
-               return -ENXIO;
-       }
-
-       endpoint = of_get_child_by_name(port, "endpoint");
-       of_node_put(port);
-       if (!endpoint) {
-               dev_dbg(dev, "no endpoint for port 1\n");
-               return -ENXIO;
-       }
-
-       panel_node = of_graph_get_remote_port_parent(endpoint);
-       of_node_put(endpoint);
-       if (!panel_node) {
-               dev_dbg(dev, "no remote endpoint for port 1\n");
-               return -ENXIO;
-       }
-
-       panel = of_drm_find_panel(panel_node);
-       of_node_put(panel_node);
-       if (IS_ERR(panel)) {
-               dev_dbg(dev, "panel not found, deferring probe\n");
-               return PTR_ERR(panel);
-       }
-
-       lvds_encoder->panel_bridge =
-               devm_drm_panel_bridge_add_typed(dev, panel,
-                                               DRM_MODE_CONNECTOR_LVDS);
-       if (IS_ERR(lvds_encoder->panel_bridge))
-               return PTR_ERR(lvds_encoder->panel_bridge);
-
-       /* The panel_bridge bridge is attached to the panel's of_node,
-        * but we need a bridge attached to our of_node for our user
-        * to look up.
-        */
-       lvds_encoder->bridge.of_node = dev->of_node;
-       lvds_encoder->bridge.funcs = &funcs;
-       drm_bridge_add(&lvds_encoder->bridge);
-
-       platform_set_drvdata(pdev, lvds_encoder);
-
-       return 0;
-}
-
-static int lvds_encoder_remove(struct platform_device *pdev)
-{
-       struct lvds_encoder *lvds_encoder = platform_get_drvdata(pdev);
-
-       drm_bridge_remove(&lvds_encoder->bridge);
-
-       return 0;
-}
-
-static const struct of_device_id lvds_encoder_match[] = {
-       { .compatible = "lvds-encoder" },
-       { .compatible = "thine,thc63lvdm83d" },
-       {},
-};
-MODULE_DEVICE_TABLE(of, lvds_encoder_match);
-
-static struct platform_driver lvds_encoder_driver = {
-       .probe  = lvds_encoder_probe,
-       .remove = lvds_encoder_remove,
-       .driver         = {
-               .name           = "lvds-encoder",
-               .of_match_table = lvds_encoder_match,
-       },
-};
-module_platform_driver(lvds_encoder_driver);
-
-MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
-MODULE_DESCRIPTION("Transparent parallel to LVDS encoder");
-MODULE_LICENSE("GPL");
index b6e793b..b18351b 100644 (file)
@@ -719,7 +719,15 @@ static void dw_mipi_dsi_vertical_timing_config(struct dw_mipi_dsi *dsi,
 
 static void dw_mipi_dsi_dphy_timing_config(struct dw_mipi_dsi *dsi)
 {
+       const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
+       struct dw_mipi_dsi_dphy_timing timing;
        u32 hw_version;
+       int ret;
+
+       ret = phy_ops->get_timing(dsi->plat_data->priv_data,
+                                 dsi->lane_mbps, &timing);
+       if (ret)
+               DRM_DEV_ERROR(dsi->dev, "Retrieving phy timings failed\n");
 
        /*
         * TODO dw drv improvements
@@ -732,16 +740,20 @@ static void dw_mipi_dsi_dphy_timing_config(struct dw_mipi_dsi *dsi)
        hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
 
        if (hw_version >= HWVER_131) {
-               dsi_write(dsi, DSI_PHY_TMR_CFG, PHY_HS2LP_TIME_V131(0x40) |
-                         PHY_LP2HS_TIME_V131(0x40));
+               dsi_write(dsi, DSI_PHY_TMR_CFG,
+                         PHY_HS2LP_TIME_V131(timing.data_hs2lp) |
+                         PHY_LP2HS_TIME_V131(timing.data_lp2hs));
                dsi_write(dsi, DSI_PHY_TMR_RD_CFG, MAX_RD_TIME_V131(10000));
        } else {
-               dsi_write(dsi, DSI_PHY_TMR_CFG, PHY_HS2LP_TIME(0x40) |
-                         PHY_LP2HS_TIME(0x40) | MAX_RD_TIME(10000));
+               dsi_write(dsi, DSI_PHY_TMR_CFG,
+                         PHY_HS2LP_TIME(timing.data_hs2lp) |
+                         PHY_LP2HS_TIME(timing.data_lp2hs) |
+                         MAX_RD_TIME(10000));
        }
 
-       dsi_write(dsi, DSI_PHY_TMR_LPCLK_CFG, PHY_CLKHS2LP_TIME(0x40)
-                 | PHY_CLKLP2HS_TIME(0x40));
+       dsi_write(dsi, DSI_PHY_TMR_LPCLK_CFG,
+                 PHY_CLKHS2LP_TIME(timing.clk_hs2lp) |
+                 PHY_CLKLP2HS_TIME(timing.clk_lp2hs));
 }
 
 static void dw_mipi_dsi_dphy_interface_config(struct dw_mipi_dsi *dsi)
@@ -798,9 +810,6 @@ static void dw_mipi_dsi_bridge_post_disable(struct drm_bridge *bridge)
        struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
        const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
 
-       if (phy_ops->power_off)
-               phy_ops->power_off(dsi->plat_data->priv_data);
-
        /*
         * Switch to command mode before panel-bridge post_disable &
         * panel unprepare.
@@ -817,6 +826,9 @@ static void dw_mipi_dsi_bridge_post_disable(struct drm_bridge *bridge)
         */
        dsi->panel_bridge->funcs->post_disable(dsi->panel_bridge);
 
+       if (phy_ops->power_off)
+               phy_ops->power_off(dsi->plat_data->priv_data);
+
        if (dsi->slave) {
                dw_mipi_dsi_disable(dsi->slave);
                clk_disable_unprepare(dsi->slave->pclk);
@@ -883,6 +895,9 @@ static void dw_mipi_dsi_mode_set(struct dw_mipi_dsi *dsi,
 
        /* Switch to cmd mode for panel-bridge pre_enable & panel prepare */
        dw_mipi_dsi_set_mode(dsi, 0);
+
+       if (phy_ops->power_on)
+               phy_ops->power_on(dsi->plat_data->priv_data);
 }
 
 static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge,
@@ -899,15 +914,11 @@ static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge,
 static void dw_mipi_dsi_bridge_enable(struct drm_bridge *bridge)
 {
        struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
-       const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
 
        /* Switch to video mode for panel-bridge enable & panel enable */
        dw_mipi_dsi_set_mode(dsi, MIPI_DSI_MODE_VIDEO);
        if (dsi->slave)
                dw_mipi_dsi_set_mode(dsi->slave, MIPI_DSI_MODE_VIDEO);
-
-       if (phy_ops->power_on)
-               phy_ops->power_on(dsi->plat_data->priv_data);
 }
 
 static enum drm_mode_status
@@ -991,7 +1002,8 @@ __dw_mipi_dsi_probe(struct platform_device *pdev,
        dsi->dev = dev;
        dsi->plat_data = plat_data;
 
-       if (!plat_data->phy_ops->init || !plat_data->phy_ops->get_lane_mbps) {
+       if (!plat_data->phy_ops->init || !plat_data->phy_ops->get_lane_mbps ||
+           !plat_data->phy_ops->get_timing) {
                DRM_ERROR("Phy not properly configured\n");
                return ERR_PTR(-ENODEV);
        }
index ab4508f..d336915 100644 (file)
@@ -251,7 +251,7 @@ EXPORT_SYMBOL(drm_atomic_state_clear);
  * @ref: This atomic state to deallocate
  *
  * This frees all memory associated with an atomic state, including all the
- * per-object state for planes, crtcs and connectors.
+ * per-object state for planes, CRTCs and connectors.
  */
 void __drm_atomic_state_free(struct kref *ref)
 {
@@ -272,12 +272,12 @@ void __drm_atomic_state_free(struct kref *ref)
 EXPORT_SYMBOL(__drm_atomic_state_free);
 
 /**
- * drm_atomic_get_crtc_state - get crtc state
+ * drm_atomic_get_crtc_state - get CRTC state
  * @state: global atomic state object
- * @crtc: crtc to get state object for
+ * @crtc: CRTC to get state object for
  *
- * This function returns the crtc state for the given crtc, allocating it if
- * needed. It will also grab the relevant crtc lock to make sure that the state
+ * This function returns the CRTC state for the given CRTC, allocating it if
+ * needed. It will also grab the relevant CRTC lock to make sure that the state
  * is consistent.
  *
  * Returns:
@@ -1018,14 +1018,14 @@ static void drm_atomic_connector_print_state(struct drm_printer *p,
 }
 
 /**
- * drm_atomic_add_affected_connectors - add connectors for crtc
+ * drm_atomic_add_affected_connectors - add connectors for CRTC
  * @state: atomic state
- * @crtc: DRM crtc
+ * @crtc: DRM CRTC
  *
  * This function walks the current configuration and adds all connectors
  * currently using @crtc to the atomic configuration @state. Note that this
  * function must acquire the connection mutex. This can potentially cause
- * unneeded seralization if the update is just for the planes on one crtc. Hence
+ * unneeded seralization if the update is just for the planes on one CRTC. Hence
  * drivers and helpers should only call this when really needed (e.g. when a
  * full modeset needs to happen due to some change).
  *
@@ -1078,9 +1078,9 @@ drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
 EXPORT_SYMBOL(drm_atomic_add_affected_connectors);
 
 /**
- * drm_atomic_add_affected_planes - add planes for crtc
+ * drm_atomic_add_affected_planes - add planes for CRTC
  * @state: atomic state
- * @crtc: DRM crtc
+ * @crtc: DRM CRTC
  *
  * This function walks the current configuration and adds all planes
  * currently used by @crtc to the atomic configuration @state. This is useful
index bcc9ca2..4511c2e 100644 (file)
@@ -150,8 +150,8 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state,
         * is not set, an error is returned. Userspace can provide a solution
         * through the atomic ioctl.
         *
-        * If the flag is set conflicting connectors are removed from the crtc
-        * and the crtc is disabled if no encoder is left. This preserves
+        * If the flag is set conflicting connectors are removed from the CRTC
+        * and the CRTC is disabled if no encoder is left. This preserves
         * compatibility with the legacy set_config behavior.
         */
        drm_connector_list_iter_begin(state->dev, &conn_iter);
@@ -220,7 +220,7 @@ set_best_encoder(struct drm_atomic_state *state,
                crtc = conn_state->connector->state->crtc;
 
                /* A NULL crtc is an error here because we should have
-                *  duplicated a NULL best_encoder when crtc was NULL.
+                * duplicated a NULL best_encoder when crtc was NULL.
                 * As an exception restoring duplicated atomic state
                 * during resume is allowed, so don't warn when
                 * best_encoder is equal to encoder we intend to set.
@@ -561,27 +561,27 @@ mode_valid(struct drm_atomic_state *state)
  * @state: the driver state object
  *
  * Check the state object to see if the requested state is physically possible.
- * This does all the crtc and connector related computations for an atomic
+ * This does all the CRTC and connector related computations for an atomic
  * update and adds any additional connectors needed for full modesets. It calls
  * the various per-object callbacks in the follow order:
  *
  * 1. &drm_connector_helper_funcs.atomic_best_encoder for determining the new encoder.
  * 2. &drm_connector_helper_funcs.atomic_check to validate the connector state.
- * 3. If it's determined a modeset is needed then all connectors on the affected crtc
- *    crtc are added and &drm_connector_helper_funcs.atomic_check is run on them.
+ * 3. If it's determined a modeset is needed then all connectors on the affected
+ *    CRTC are added and &drm_connector_helper_funcs.atomic_check is run on them.
  * 4. &drm_encoder_helper_funcs.mode_valid, &drm_bridge_funcs.mode_valid and
  *    &drm_crtc_helper_funcs.mode_valid are called on the affected components.
  * 5. &drm_bridge_funcs.mode_fixup is called on all encoder bridges.
  * 6. &drm_encoder_helper_funcs.atomic_check is called to validate any encoder state.
- *    This function is only called when the encoder will be part of a configured crtc,
+ *    This function is only called when the encoder will be part of a configured CRTC,
  *    it must not be used for implementing connector property validation.
  *    If this function is NULL, &drm_atomic_encoder_helper_funcs.mode_fixup is called
  *    instead.
- * 7. &drm_crtc_helper_funcs.mode_fixup is called last, to fix up the mode with crtc constraints.
+ * 7. &drm_crtc_helper_funcs.mode_fixup is called last, to fix up the mode with CRTC constraints.
  *
  * &drm_crtc_state.mode_changed is set when the input mode is changed.
  * &drm_crtc_state.connectors_changed is set when a connector is added or
- * removed from the crtc.  &drm_crtc_state.active_changed is set when
+ * removed from the CRTC.  &drm_crtc_state.active_changed is set when
  * &drm_crtc_state.active changes, which is used for DPMS.
  * See also: drm_atomic_crtc_needs_modeset()
  *
@@ -692,7 +692,7 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
 
        /*
         * After all the routing has been prepared we need to add in any
-        * connector which is itself unchanged, but whose crtc changes its
+        * connector which is itself unchanged, but whose CRTC changes its
         * configuration. This must be done before calling mode_fixup in case a
         * crtc only changed its mode but has the same set of connectors.
         */
@@ -741,13 +741,13 @@ 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
+ * @crtc_state: CRTC state to check
  * @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
+ *                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
+ * @can_update_disabled: can the plane be updated while the CRTC
  *                       is disabled?
  *
  * Checks that a desired plane update is valid, and updates various
@@ -844,7 +844,7 @@ EXPORT_SYMBOL(drm_atomic_helper_check_plane_state);
  * &drm_crtc_helper_funcs.atomic_check and &drm_plane_helper_funcs.atomic_check
  * hooks provided by the driver.
  *
- * It also sets &drm_crtc_state.planes_changed to indicate that a crtc has
+ * It also sets &drm_crtc_state.planes_changed to indicate that a CRTC has
  * updated planes.
  *
  * RETURNS:
@@ -908,7 +908,7 @@ EXPORT_SYMBOL(drm_atomic_helper_check_planes);
  * @state: the driver state object
  *
  * Check the state object to see if the requested state is physically possible.
- * Only crtcs and planes have check callbacks, so for any additional (global)
+ * Only CRTCs and planes have check callbacks, so for any additional (global)
  * checking that a driver needs it can simply wrap that around this function.
  * Drivers without such needs can directly use this as their
  * &drm_mode_config_funcs.atomic_check callback.
@@ -961,14 +961,14 @@ crtc_needs_disable(struct drm_crtc_state *old_state,
                   struct drm_crtc_state *new_state)
 {
        /*
-        * No new_state means the crtc is off, so the only criteria is whether
+        * No new_state means the CRTC is off, so the only criteria is whether
         * it's currently active or in self refresh mode.
         */
        if (!new_state)
                return drm_atomic_crtc_effectively_active(old_state);
 
        /*
-        * We need to run through the crtc_funcs->disable() function if the crtc
+        * We need to run through the crtc_funcs->disable() function if the CRTC
         * is currently on, if it's transitioning to self refresh mode, or if
         * it's in self refresh mode and needs to be fully disabled.
         */
@@ -1087,7 +1087,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
  * @old_state: atomic state object with old state structures
  *
  * This function updates all the various legacy modeset state pointers in
- * connectors, encoders and crtcs. It also updates the timestamping constants
+ * connectors, encoders and CRTCs. It also updates the timestamping constants
  * used for precise vblank timestamps by calling
  * drm_calc_timestamping_constants().
  *
@@ -1236,7 +1236,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
  * This function shuts down all the outputs that need to be shut down and
  * prepares them (if required) with the new mode.
  *
- * For compatibility with legacy crtc helpers this should be called before
+ * For compatibility with legacy CRTC helpers this should be called before
  * drm_atomic_helper_commit_planes(), which is what the default commit function
  * does. But drivers with different needs can group the modeset commits together
  * and do the plane commits at the end. This is useful for drivers doing runtime
@@ -1282,7 +1282,7 @@ static void drm_atomic_helper_commit_writebacks(struct drm_device *dev,
  * This function enables all the outputs with the new configuration which had to
  * be turned off for the update.
  *
- * For compatibility with legacy crtc helpers this should be called after
+ * For compatibility with legacy CRTC helpers this should be called after
  * drm_atomic_helper_commit_planes(), which is what the default commit function
  * does. But drivers with different needs can group the modeset commits together
  * and do the plane commits at the end. This is useful for drivers doing runtime
@@ -1414,12 +1414,12 @@ int drm_atomic_helper_wait_for_fences(struct drm_device *dev,
 EXPORT_SYMBOL(drm_atomic_helper_wait_for_fences);
 
 /**
- * drm_atomic_helper_wait_for_vblanks - wait for vblank on crtcs
+ * drm_atomic_helper_wait_for_vblanks - wait for vblank on CRTCs
  * @dev: DRM device
  * @old_state: atomic state object with old state structures
  *
- * Helper to, after atomic commit, wait for vblanks on all effected
- * crtcs (ie. before cleaning up old framebuffers using
+ * Helper to, after atomic commit, wait for vblanks on all affected
+ * CRTCs (ie. before cleaning up old framebuffers using
  * drm_atomic_helper_cleanup_planes()). It will only wait on CRTCs where the
  * framebuffers have actually changed to optimize for the legacy cursor and
  * plane update use-case.
@@ -1478,10 +1478,10 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks);
  * @dev: DRM device
  * @old_state: atomic state object with old state structures
  *
- * Helper to, after atomic commit, wait for page flips on all effected
+ * Helper to, after atomic commit, wait for page flips on all affected
  * crtcs (ie. before cleaning up old framebuffers using
  * drm_atomic_helper_cleanup_planes()). Compared to
- * drm_atomic_helper_wait_for_vblanks() this waits for the completion of on all
+ * drm_atomic_helper_wait_for_vblanks() this waits for the completion on all
  * CRTCs, assuming that cursors-only updates are signalling their completion
  * immediately (or using a different path).
  *
@@ -2208,7 +2208,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies);
  * drm_atomic_helper_fake_vblank - fake VBLANK events if needed
  * @old_state: atomic state object with old state structures
  *
- * This function walks all CRTCs and fake VBLANK events on those with
+ * This function walks all CRTCs and fakes VBLANK events on those with
  * &drm_crtc_state.no_vblank set to true and &drm_crtc_state.event != NULL.
  * The primary use of this function is writeback connectors working in oneshot
  * mode and faking VBLANK events. In this case they only fake the VBLANK event
@@ -2404,7 +2404,7 @@ static bool plane_crtc_active(const struct drm_plane_state *state)
  * @flags: flags for committing plane state
  *
  * This function commits the new plane state using the plane and atomic helper
- * functions for planes and crtcs. It assumes that the atomic state has already
+ * functions for planes and CRTCs. It assumes that the atomic state has already
  * been pushed into the relevant object state pointers, since this step can no
  * longer fail.
  *
@@ -2525,15 +2525,15 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
 EXPORT_SYMBOL(drm_atomic_helper_commit_planes);
 
 /**
- * drm_atomic_helper_commit_planes_on_crtc - commit plane state for a crtc
- * @old_crtc_state: atomic state object with the old crtc state
+ * drm_atomic_helper_commit_planes_on_crtc - commit plane state for a CRTC
+ * @old_crtc_state: atomic state object with the old CRTC state
  *
  * This function commits the new plane state using the plane and atomic helper
- * functions for planes on the specific crtc. It assumes that the atomic state
+ * functions for planes on the specific CRTC. It assumes that the atomic state
  * has already been pushed into the relevant object state pointers, since this
  * step can no longer fail.
  *
- * This function is useful when plane updates should be done crtc-by-crtc
+ * This function is useful when plane updates should be done CRTC-by-CRTC
  * instead of one global step like drm_atomic_helper_commit_planes() does.
  *
  * This function can only be savely used when planes are not allowed to move
@@ -2823,10 +2823,10 @@ EXPORT_SYMBOL(drm_atomic_helper_swap_state);
  * @plane: plane object to update
  * @crtc: owning CRTC of owning plane
  * @fb: framebuffer to flip onto plane
- * @crtc_x: x offset of primary plane on crtc
- * @crtc_y: y offset of primary plane on crtc
- * @crtc_w: width of primary plane rectangle on crtc
- * @crtc_h: height of primary plane rectangle on crtc
+ * @crtc_x: x offset of primary plane on @crtc
+ * @crtc_y: y offset of primary plane on @crtc
+ * @crtc_w: width of primary plane rectangle on @crtc
+ * @crtc_h: height of primary plane rectangle on @crtc
  * @src_x: x offset of @fb for panning
  * @src_y: y offset of @fb for panning
  * @src_w: width of source rectangle in @fb
@@ -2932,7 +2932,7 @@ EXPORT_SYMBOL(drm_atomic_helper_disable_plane);
  * @set: mode set configuration
  * @ctx: lock acquisition context
  *
- * Provides a default crtc set_config handler using the atomic driver interface.
+ * Provides a default CRTC set_config handler using the atomic driver interface.
  *
  * NOTE: For backwards compatibility with old userspace this automatically
  * resets the "link-status" property to GOOD, to force any link
@@ -3345,7 +3345,7 @@ static int page_flip_common(struct drm_atomic_state *state,
 
 /**
  * drm_atomic_helper_page_flip - execute a legacy page flip
- * @crtc: DRM crtc
+ * @crtc: DRM CRTC
  * @fb: DRM framebuffer
  * @event: optional DRM event to signal upon completion
  * @flags: flip flags for non-vblank sync'ed updates
@@ -3389,7 +3389,7 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip);
 
 /**
  * drm_atomic_helper_page_flip_target - do page flip on target vblank period.
- * @crtc: DRM crtc
+ * @crtc: DRM CRTC
  * @fb: DRM framebuffer
  * @event: optional DRM event to signal upon completion
  * @flags: flip flags for non-vblank sync'ed updates
index 0d466d3..a1e5e26 100644 (file)
@@ -160,12 +160,12 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
 EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc);
 
 /**
- * drm_atomic_set_crtc_for_plane - set crtc for plane
+ * drm_atomic_set_crtc_for_plane - set CRTC for plane
  * @plane_state: the plane whose incoming state to update
- * @crtc: crtc to use for the plane
+ * @crtc: CRTC to use for the plane
  *
- * Changing the assigned crtc for a plane requires us to grab the lock and state
- * for the new crtc, as needed. This function takes care of all these details
+ * Changing the assigned CRTC for a plane requires us to grab the lock and state
+ * for the new CRTC, as needed. This function takes care of all these details
  * besides updating the pointer in the state object itself.
  *
  * Returns:
@@ -279,12 +279,12 @@ drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
 EXPORT_SYMBOL(drm_atomic_set_fence_for_plane);
 
 /**
- * drm_atomic_set_crtc_for_connector - set crtc for connector
+ * drm_atomic_set_crtc_for_connector - set CRTC for connector
  * @conn_state: atomic state object for the connector
- * @crtc: crtc to use for the connector
+ * @crtc: CRTC to use for the connector
  *
- * Changing the assigned crtc for a connector requires us to grab the lock and
- * state for the new crtc, as needed. This function takes care of all these
+ * Changing the assigned CRTC for a connector requires us to grab the lock and
+ * state for the new CRTC, as needed. This function takes care of all these
  * details besides updating the pointer in the state object itself.
  *
  * Returns:
index d9a2e36..b031b45 100644 (file)
@@ -150,7 +150,7 @@ void drm_client_release(struct drm_client_dev *client)
 {
        struct drm_device *dev = client->dev;
 
-       DRM_DEV_DEBUG_KMS(dev->dev, "%s\n", client->name);
+       drm_dbg_kms(dev, "%s\n", client->name);
 
        drm_client_modeset_free(client);
        drm_client_close(client);
@@ -203,7 +203,7 @@ void drm_client_dev_hotplug(struct drm_device *dev)
                        continue;
 
                ret = client->funcs->hotplug(client);
-               DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret);
+               drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret);
        }
        mutex_unlock(&dev->clientlist_mutex);
 }
@@ -223,7 +223,7 @@ void drm_client_dev_restore(struct drm_device *dev)
                        continue;
 
                ret = client->funcs->restore(client);
-               DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret);
+               drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret);
                if (!ret) /* The first one to return zero gets the privilege to restore */
                        break;
        }
@@ -351,8 +351,8 @@ static void drm_client_buffer_rmfb(struct drm_client_buffer *buffer)
 
        ret = drm_mode_rmfb(buffer->client->dev, buffer->fb->base.id, buffer->client->file);
        if (ret)
-               DRM_DEV_ERROR(buffer->client->dev->dev,
-                             "Error removing FB:%u (%d)\n", buffer->fb->base.id, ret);
+               drm_err(buffer->client->dev,
+                       "Error removing FB:%u (%d)\n", buffer->fb->base.id, ret);
 
        buffer->fb = NULL;
 }
index 1b9b40a..7c18a98 100644 (file)
@@ -622,7 +622,8 @@ int drm_dev_init(struct drm_device *dev,
                return -ENODEV;
        }
 
-       BUG_ON(!parent);
+       if (WARN_ON(!parent))
+               return -EINVAL;
 
        kref_init(&dev->ref);
        dev->dev = get_device(parent);
@@ -725,7 +726,7 @@ int devm_drm_dev_init(struct device *parent,
 {
        int ret;
 
-       if (WARN_ON(!parent || !driver->release))
+       if (WARN_ON(!driver->release))
                return -EINVAL;
 
        ret = drm_dev_init(dev, driver, parent);
index 5b33b7c..99769d6 100644 (file)
@@ -710,14 +710,11 @@ static const struct minimode extra_modes[] = {
 };
 
 /*
- * Probably taken from CEA-861 spec.
- * This table is converted from xorg's hw/xfree86/modes/xf86EdidModes.c.
+ * From CEA/CTA-861 spec.
  *
- * Index using the VIC.
+ * Do not access directly, instead always use cea_mode_for_vic().
  */
-static const struct drm_display_mode edid_cea_modes[] = {
-       /* 0 - dummy, VICs start at 1 */
-       { },
+static const struct drm_display_mode edid_cea_modes_1[] = {
        /* 1 - 640x480@60Hz 4:3 */
        { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
                   752, 800, 0, 480, 490, 492, 525, 0,
@@ -1381,6 +1378,149 @@ static const struct drm_display_mode edid_cea_modes[] = {
 };
 
 /*
+ * From CEA/CTA-861 spec.
+ *
+ * Do not access directly, instead always use cea_mode_for_vic().
+ */
+static const struct drm_display_mode edid_cea_modes_193[] = {
+       /* 193 - 5120x2160@120Hz 64:27 */
+       { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 1485000, 5120, 5284,
+                  5372, 5500, 0, 2160, 2168, 2178, 2250, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 194 - 7680x4320@24Hz 16:9 */
+       { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 10232,
+                  10408, 11000, 0, 4320, 4336, 4356, 4500, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
+       /* 195 - 7680x4320@25Hz 16:9 */
+       { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 10032,
+                  10208, 10800, 0, 4320, 4336, 4356, 4400, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
+       /* 196 - 7680x4320@30Hz 16:9 */
+       { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 8232,
+                  8408, 9000, 0, 4320, 4336, 4356, 4400, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
+       /* 197 - 7680x4320@48Hz 16:9 */
+       { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 10232,
+                  10408, 11000, 0, 4320, 4336, 4356, 4500, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
+       /* 198 - 7680x4320@50Hz 16:9 */
+       { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 10032,
+                  10208, 10800, 0, 4320, 4336, 4356, 4400, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
+       /* 199 - 7680x4320@60Hz 16:9 */
+       { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 8232,
+                  8408, 9000, 0, 4320, 4336, 4356, 4400, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
+       /* 200 - 7680x4320@100Hz 16:9 */
+       { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 4752000, 7680, 9792,
+                  9968, 10560, 0, 4320, 4336, 4356, 4500, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
+       /* 201 - 7680x4320@120Hz 16:9 */
+       { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 4752000, 7680, 8032,
+                  8208, 8800, 0, 4320, 4336, 4356, 4500, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
+       /* 202 - 7680x4320@24Hz 64:27 */
+       { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 10232,
+                  10408, 11000, 0, 4320, 4336, 4356, 4500, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 203 - 7680x4320@25Hz 64:27 */
+       { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 10032,
+                  10208, 10800, 0, 4320, 4336, 4356, 4400, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 204 - 7680x4320@30Hz 64:27 */
+       { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 8232,
+                  8408, 9000, 0, 4320, 4336, 4356, 4400, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 205 - 7680x4320@48Hz 64:27 */
+       { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 10232,
+                  10408, 11000, 0, 4320, 4336, 4356, 4500, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 206 - 7680x4320@50Hz 64:27 */
+       { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 10032,
+                  10208, 10800, 0, 4320, 4336, 4356, 4400, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 207 - 7680x4320@60Hz 64:27 */
+       { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 8232,
+                  8408, 9000, 0, 4320, 4336, 4356, 4400, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 208 - 7680x4320@100Hz 64:27 */
+       { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 4752000, 7680, 9792,
+                  9968, 10560, 0, 4320, 4336, 4356, 4500, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 209 - 7680x4320@120Hz 64:27 */
+       { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 4752000, 7680, 8032,
+                  8208, 8800, 0, 4320, 4336, 4356, 4500, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 210 - 10240x4320@24Hz 64:27 */
+       { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 1485000, 10240, 11732,
+                  11908, 12500, 0, 4320, 4336, 4356, 4950, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 211 - 10240x4320@25Hz 64:27 */
+       { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 1485000, 10240, 12732,
+                  12908, 13500, 0, 4320, 4336, 4356, 4400, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 212 - 10240x4320@30Hz 64:27 */
+       { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 1485000, 10240, 10528,
+                  10704, 11000, 0, 4320, 4336, 4356, 4500, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 213 - 10240x4320@48Hz 64:27 */
+       { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 2970000, 10240, 11732,
+                  11908, 12500, 0, 4320, 4336, 4356, 4950, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 214 - 10240x4320@50Hz 64:27 */
+       { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 2970000, 10240, 12732,
+                  12908, 13500, 0, 4320, 4336, 4356, 4400, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 215 - 10240x4320@60Hz 64:27 */
+       { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 2970000, 10240, 10528,
+                  10704, 11000, 0, 4320, 4336, 4356, 4500, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 216 - 10240x4320@100Hz 64:27 */
+       { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 5940000, 10240, 12432,
+                  12608, 13200, 0, 4320, 4336, 4356, 4500, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 217 - 10240x4320@120Hz 64:27 */
+       { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 5940000, 10240, 10528,
+                  10704, 11000, 0, 4320, 4336, 4356, 4500, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+       /* 218 - 4096x2160@100Hz 256:135 */
+       { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 1188000, 4096, 4896,
+                  4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
+       /* 219 - 4096x2160@120Hz 256:135 */
+       { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 1188000, 4096, 4184,
+                  4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
+};
+
+/*
  * HDMI 1.4 4k modes. Index using the VIC.
  */
 static const struct drm_display_mode edid_4k_modes[] = {
@@ -3071,6 +3211,30 @@ static u8 *drm_find_cea_extension(const struct edid *edid)
        return cea;
 }
 
+static const struct drm_display_mode *cea_mode_for_vic(u8 vic)
+{
+       BUILD_BUG_ON(1 + ARRAY_SIZE(edid_cea_modes_1) - 1 != 127);
+       BUILD_BUG_ON(193 + ARRAY_SIZE(edid_cea_modes_193) - 1 != 219);
+
+       if (vic >= 1 && vic < 1 + ARRAY_SIZE(edid_cea_modes_1))
+               return &edid_cea_modes_1[vic - 1];
+       if (vic >= 193 && vic < 193 + ARRAY_SIZE(edid_cea_modes_193))
+               return &edid_cea_modes_193[vic - 193];
+       return NULL;
+}
+
+static u8 cea_num_vics(void)
+{
+       return 193 + ARRAY_SIZE(edid_cea_modes_193);
+}
+
+static u8 cea_next_vic(u8 vic)
+{
+       if (++vic == 1 + ARRAY_SIZE(edid_cea_modes_1))
+               vic = 193;
+       return vic;
+}
+
 /*
  * Calculate the alternate clock for the CEA mode
  * (60Hz vs. 59.94Hz etc.)
@@ -3108,14 +3272,14 @@ cea_mode_alternate_timings(u8 vic, struct drm_display_mode *mode)
         * get the other variants by simply increasing the
         * vertical front porch length.
         */
-       BUILD_BUG_ON(edid_cea_modes[8].vtotal != 262 ||
-                    edid_cea_modes[9].vtotal != 262 ||
-                    edid_cea_modes[12].vtotal != 262 ||
-                    edid_cea_modes[13].vtotal != 262 ||
-                    edid_cea_modes[23].vtotal != 312 ||
-                    edid_cea_modes[24].vtotal != 312 ||
-                    edid_cea_modes[27].vtotal != 312 ||
-                    edid_cea_modes[28].vtotal != 312);
+       BUILD_BUG_ON(cea_mode_for_vic(8)->vtotal != 262 ||
+                    cea_mode_for_vic(9)->vtotal != 262 ||
+                    cea_mode_for_vic(12)->vtotal != 262 ||
+                    cea_mode_for_vic(13)->vtotal != 262 ||
+                    cea_mode_for_vic(23)->vtotal != 312 ||
+                    cea_mode_for_vic(24)->vtotal != 312 ||
+                    cea_mode_for_vic(27)->vtotal != 312 ||
+                    cea_mode_for_vic(28)->vtotal != 312);
 
        if (((vic == 8 || vic == 9 ||
              vic == 12 || vic == 13) && mode->vtotal < 263) ||
@@ -3143,8 +3307,8 @@ static u8 drm_match_cea_mode_clock_tolerance(const struct drm_display_mode *to_m
        if (to_match->picture_aspect_ratio)
                match_flags |= DRM_MODE_MATCH_ASPECT_RATIO;
 
-       for (vic = 1; vic < ARRAY_SIZE(edid_cea_modes); vic++) {
-               struct drm_display_mode cea_mode = edid_cea_modes[vic];
+       for (vic = 1; vic < cea_num_vics(); vic = cea_next_vic(vic)) {
+               struct drm_display_mode cea_mode = *cea_mode_for_vic(vic);
                unsigned int clock1, clock2;
 
                /* Check both 60Hz and 59.94Hz */
@@ -3182,8 +3346,8 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
        if (to_match->picture_aspect_ratio)
                match_flags |= DRM_MODE_MATCH_ASPECT_RATIO;
 
-       for (vic = 1; vic < ARRAY_SIZE(edid_cea_modes); vic++) {
-               struct drm_display_mode cea_mode = edid_cea_modes[vic];
+       for (vic = 1; vic < cea_num_vics(); vic = cea_next_vic(vic)) {
+               struct drm_display_mode cea_mode = *cea_mode_for_vic(vic);
                unsigned int clock1, clock2;
 
                /* Check both 60Hz and 59.94Hz */
@@ -3206,12 +3370,17 @@ EXPORT_SYMBOL(drm_match_cea_mode);
 
 static bool drm_valid_cea_vic(u8 vic)
 {
-       return vic > 0 && vic < ARRAY_SIZE(edid_cea_modes);
+       return cea_mode_for_vic(vic) != NULL;
 }
 
 static enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code)
 {
-       return edid_cea_modes[video_code].picture_aspect_ratio;
+       const struct drm_display_mode *mode = cea_mode_for_vic(video_code);
+
+       if (mode)
+               return mode->picture_aspect_ratio;
+
+       return HDMI_PICTURE_ASPECT_NONE;
 }
 
 static enum hdmi_picture_aspect drm_get_hdmi_aspect_ratio(const u8 video_code)
@@ -3323,7 +3492,7 @@ add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid)
                unsigned int clock1, clock2;
 
                if (drm_valid_cea_vic(vic)) {
-                       cea_mode = &edid_cea_modes[vic];
+                       cea_mode = cea_mode_for_vic(vic);
                        clock2 = cea_mode_alternate_clock(cea_mode);
                } else {
                        vic = drm_match_hdmi_mode(mode);
@@ -3398,7 +3567,7 @@ drm_display_mode_from_vic_index(struct drm_connector *connector,
        if (!drm_valid_cea_vic(vic))
                return NULL;
 
-       newmode = drm_mode_duplicate(dev, &edid_cea_modes[vic]);
+       newmode = drm_mode_duplicate(dev, cea_mode_for_vic(vic));
        if (!newmode)
                return NULL;
 
@@ -3432,7 +3601,7 @@ static int do_y420vdb_modes(struct drm_connector *connector,
                if (!drm_valid_cea_vic(vic))
                        continue;
 
-               newmode = drm_mode_duplicate(dev, &edid_cea_modes[vic]);
+               newmode = drm_mode_duplicate(dev, cea_mode_for_vic(vic));
                if (!newmode)
                        break;
                bitmap_set(hdmi->y420_vdb_modes, vic, 1);
@@ -4001,7 +4170,7 @@ static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
        vic = drm_match_cea_mode_clock_tolerance(mode, 5);
        if (drm_valid_cea_vic(vic)) {
                type = "CEA";
-               cea_mode = &edid_cea_modes[vic];
+               cea_mode = cea_mode_for_vic(vic);
                clock1 = cea_mode->clock;
                clock2 = cea_mode_alternate_clock(cea_mode);
        } else {
@@ -4577,7 +4746,7 @@ static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector,
                if (scdc->supported) {
                        scdc->scrambling.supported = true;
 
-                       /* Few sinks support scrambling for cloks < 340M */
+                       /* Few sinks support scrambling for clocks < 340M */
                        if ((hf_vsdb[6] & 0x8))
                                scdc->scrambling.low_rates = true;
                }
index fb9bff0..f8e9051 100644 (file)
@@ -191,6 +191,7 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
 {
        struct drm_fb_helper *helper = info->par;
        struct drm_client_dev *client = &helper->client;
+       struct drm_device *dev = helper->dev;
        struct drm_crtc *crtc;
        const struct drm_crtc_helper_funcs *funcs;
        struct drm_mode_set *mode_set;
@@ -209,7 +210,7 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
                        continue;
 
                if (!fb) {
-                       DRM_ERROR("no fb to restore??\n");
+                       drm_err(dev, "no fb to restore?\n");
                        continue;
                }
 
@@ -1248,12 +1249,13 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
 {
        struct drm_fb_helper *fb_helper = info->par;
        struct drm_framebuffer *fb = fb_helper->fb;
+       struct drm_device *dev = fb_helper->dev;
 
        if (in_dbg_master())
                return -EINVAL;
 
        if (var->pixclock != 0) {
-               DRM_DEBUG("fbdev emulation doesn't support changing the pixel clock, value of pixclock is ignored\n");
+               drm_dbg_kms(dev, "fbdev emulation doesn't support changing the pixel clock, value of pixclock is ignored\n");
                var->pixclock = 0;
        }
 
@@ -1268,7 +1270,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
        if (var->bits_per_pixel != fb->format->cpp[0] * 8 ||
            var->xres > fb->width || var->yres > fb->height ||
            var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
-               DRM_DEBUG("fb requested width/height/bpp can't fit in current fb "
+               drm_dbg_kms(dev, "fb requested width/height/bpp can't fit in current fb "
                          "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n",
                          var->xres, var->yres, var->bits_per_pixel,
                          var->xres_virtual, var->yres_virtual,
@@ -1295,7 +1297,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
         * so reject all pixel format changing requests.
         */
        if (!drm_fb_pixel_format_equal(var, &info->var)) {
-               DRM_DEBUG("fbdev emulation doesn't support changing the pixel format\n");
+               drm_dbg_kms(dev, "fbdev emulation doesn't support changing the pixel format\n");
                return -EINVAL;
        }
 
@@ -1320,7 +1322,7 @@ int drm_fb_helper_set_par(struct fb_info *info)
                return -EBUSY;
 
        if (var->pixclock != 0) {
-               DRM_ERROR("PIXEL CLOCK SET\n");
+               drm_err(fb_helper->dev, "PIXEL CLOCK SET\n");
                return -EINVAL;
        }
 
@@ -1430,6 +1432,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
                                         int preferred_bpp)
 {
        struct drm_client_dev *client = &fb_helper->client;
+       struct drm_device *dev = fb_helper->dev;
        int ret = 0;
        int crtc_count = 0;
        struct drm_connector_list_iter conn_iter;
@@ -1493,7 +1496,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
                struct drm_plane *plane = crtc->primary;
                int j;
 
-               DRM_DEBUG("test CRTC %u primary plane\n", drm_crtc_index(crtc));
+               drm_dbg_kms(dev, "test CRTC %u primary plane\n", drm_crtc_index(crtc));
 
                for (j = 0; j < plane->format_count; j++) {
                        const struct drm_format_info *fmt;
@@ -1526,7 +1529,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
                }
        }
        if (sizes.surface_depth != best_depth && best_depth) {
-               DRM_INFO("requested bpp %d, scaled depth down to %d",
+               drm_info(dev, "requested bpp %d, scaled depth down to %d",
                         sizes.surface_bpp, best_depth);
                sizes.surface_depth = best_depth;
        }
@@ -1574,7 +1577,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
        mutex_unlock(&client->modeset_mutex);
 
        if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
-               DRM_INFO("Cannot find any crtc or sizes\n");
+               drm_info(dev, "Cannot find any crtc or sizes\n");
 
                /* First time: disable all crtc's.. */
                if (!fb_helper->deferred_setup)
@@ -1889,7 +1892,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 
        drm_master_internal_release(fb_helper->dev);
 
-       DRM_DEBUG_KMS("\n");
+       drm_dbg_kms(fb_helper->dev, "\n");
 
        drm_client_modeset_probe(&fb_helper->client, fb_helper->fb->width, fb_helper->fb->height);
        drm_setup_crtcs_fb(fb_helper);
@@ -2026,15 +2029,16 @@ static int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
                                       struct drm_fb_helper_surface_size *sizes)
 {
        struct drm_client_dev *client = &fb_helper->client;
+       struct drm_device *dev = fb_helper->dev;
        struct drm_client_buffer *buffer;
        struct drm_framebuffer *fb;
        struct fb_info *fbi;
        u32 format;
        void *vaddr;
 
-       DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
-                     sizes->surface_width, sizes->surface_height,
-                     sizes->surface_bpp);
+       drm_dbg_kms(dev, "surface width(%d), height(%d) and bpp(%d)\n",
+                   sizes->surface_width, sizes->surface_height,
+                   sizes->surface_bpp);
 
        format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
        buffer = drm_client_framebuffer_create(client, sizes->surface_width,
@@ -2118,7 +2122,7 @@ static int drm_fbdev_client_hotplug(struct drm_client_dev *client)
                return drm_fb_helper_hotplug_event(dev->fb_helper);
 
        if (!dev->mode_config.num_connector) {
-               DRM_DEV_DEBUG(dev->dev, "No connectors found, will not create framebuffer!\n");
+               drm_dbg_kms(dev, "No connectors found, will not create framebuffer!\n");
                return 0;
        }
 
@@ -2143,7 +2147,7 @@ err:
        fb_helper->dev = NULL;
        fb_helper->fbdev = NULL;
 
-       DRM_DEV_ERROR(dev->dev, "fbdev: Failed to setup generic emulation (ret=%d)\n", ret);
+       drm_err(dev, "fbdev: Failed to setup generic emulation (ret=%d)\n", ret);
 
        return ret;
 }
@@ -2200,7 +2204,7 @@ int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
        ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs);
        if (ret) {
                kfree(fb_helper);
-               DRM_DEV_ERROR(dev->dev, "Failed to register client: %d\n", ret);
+               drm_err(dev, "Failed to register client: %d\n", ret);
                return ret;
        }
 
@@ -2212,7 +2216,7 @@ int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
 
        ret = drm_fbdev_client_hotplug(&fb_helper->client);
        if (ret)
-               DRM_DEV_DEBUG(dev->dev, "client hotplug ret=%d\n", ret);
+               drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
 
        drm_client_register(&fb_helper->client);
 
index b9bcd31..3a7ace1 100644 (file)
@@ -74,8 +74,7 @@ drm_gem_fb_alloc(struct drm_device *dev,
 
        ret = drm_framebuffer_init(dev, fb, funcs);
        if (ret) {
-               DRM_DEV_ERROR(dev->dev, "Failed to init framebuffer: %d\n",
-                             ret);
+               drm_err(dev, "Failed to init framebuffer: %d\n", ret);
                kfree(fb);
                return ERR_PTR(ret);
        }
@@ -160,7 +159,7 @@ drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file,
 
                objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
                if (!objs[i]) {
-                       DRM_DEBUG_KMS("Failed to lookup GEM object\n");
+                       drm_dbg_kms(dev, "Failed to lookup GEM object\n");
                        ret = -ENOENT;
                        goto err_gem_object_put;
                }
index 8823269..2a4eb61 100644 (file)
@@ -1568,33 +1568,76 @@ static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
        return 0;
 }
 
-static int drm_mode_parse_cmdline_options(char *str, size_t len,
+static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret)
+{
+       const char *value;
+       char *endp;
+
+       /*
+        * delim must point to the '=', otherwise it is a syntax error and
+        * if delim points to the terminating zero, then delim + 1 wil point
+        * past the end of the string.
+        */
+       if (*delim != '=')
+               return -EINVAL;
+
+       value = delim + 1;
+       *int_ret = simple_strtol(value, &endp, 10);
+
+       /* Make sure we have parsed something */
+       if (endp == value)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int drm_mode_parse_panel_orientation(const char *delim,
+                                           struct drm_cmdline_mode *mode)
+{
+       const char *value;
+
+       if (*delim != '=')
+               return -EINVAL;
+
+       value = delim + 1;
+       delim = strchr(value, ',');
+       if (!delim)
+               delim = value + strlen(value);
+
+       if (!strncmp(value, "normal", delim - value))
+               mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
+       else if (!strncmp(value, "upside_down", delim - value))
+               mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
+       else if (!strncmp(value, "left_side_up", delim - value))
+               mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
+       else if (!strncmp(value, "right_side_up", delim - value))
+               mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+static int drm_mode_parse_cmdline_options(const char *str,
+                                         bool freestanding,
                                          const struct drm_connector *connector,
                                          struct drm_cmdline_mode *mode)
 {
-       unsigned int rotation = 0;
-       char *sep = str;
+       unsigned int deg, margin, rotation = 0;
+       const char *delim, *option, *sep;
 
-       while ((sep = strchr(sep, ','))) {
-               char *delim, *option;
-
-               option = sep + 1;
+       option = str;
+       do {
                delim = strchr(option, '=');
                if (!delim) {
                        delim = strchr(option, ',');
 
                        if (!delim)
-                               delim = str + len;
+                               delim = option + strlen(option);
                }
 
                if (!strncmp(option, "rotate", delim - option)) {
-                       const char *value = delim + 1;
-                       unsigned int deg;
-
-                       deg = simple_strtol(value, &sep, 10);
-
-                       /* Make sure we have parsed something */
-                       if (sep == value)
+                       if (drm_mode_parse_cmdline_int(delim, &deg))
                                return -EINVAL;
 
                        switch (deg) {
@@ -1619,58 +1662,40 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len,
                        }
                } else if (!strncmp(option, "reflect_x", delim - option)) {
                        rotation |= DRM_MODE_REFLECT_X;
-                       sep = delim;
                } else if (!strncmp(option, "reflect_y", delim - option)) {
                        rotation |= DRM_MODE_REFLECT_Y;
-                       sep = delim;
                } else if (!strncmp(option, "margin_right", delim - option)) {
-                       const char *value = delim + 1;
-                       unsigned int margin;
-
-                       margin = simple_strtol(value, &sep, 10);
-
-                       /* Make sure we have parsed something */
-                       if (sep == value)
+                       if (drm_mode_parse_cmdline_int(delim, &margin))
                                return -EINVAL;
 
                        mode->tv_margins.right = margin;
                } else if (!strncmp(option, "margin_left", delim - option)) {
-                       const char *value = delim + 1;
-                       unsigned int margin;
-
-                       margin = simple_strtol(value, &sep, 10);
-
-                       /* Make sure we have parsed something */
-                       if (sep == value)
+                       if (drm_mode_parse_cmdline_int(delim, &margin))
                                return -EINVAL;
 
                        mode->tv_margins.left = margin;
                } else if (!strncmp(option, "margin_top", delim - option)) {
-                       const char *value = delim + 1;
-                       unsigned int margin;
-
-                       margin = simple_strtol(value, &sep, 10);
-
-                       /* Make sure we have parsed something */
-                       if (sep == value)
+                       if (drm_mode_parse_cmdline_int(delim, &margin))
                                return -EINVAL;
 
                        mode->tv_margins.top = margin;
                } else if (!strncmp(option, "margin_bottom", delim - option)) {
-                       const char *value = delim + 1;
-                       unsigned int margin;
-
-                       margin = simple_strtol(value, &sep, 10);
-
-                       /* Make sure we have parsed something */
-                       if (sep == value)
+                       if (drm_mode_parse_cmdline_int(delim, &margin))
                                return -EINVAL;
 
                        mode->tv_margins.bottom = margin;
+               } else if (!strncmp(option, "panel_orientation", delim - option)) {
+                       if (drm_mode_parse_panel_orientation(delim, mode))
+                               return -EINVAL;
                } else {
                        return -EINVAL;
                }
-       }
+               sep = strchr(delim, ',');
+               option = sep + 1;
+       } while (sep);
+
+       if (rotation && freestanding)
+               return -EINVAL;
 
        mode->rotation_reflection = rotation;
 
@@ -1682,17 +1707,6 @@ static const char * const drm_named_modes_whitelist[] = {
        "PAL",
 };
 
-static bool drm_named_mode_is_in_whitelist(const char *mode, unsigned int size)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++)
-               if (!strncmp(mode, drm_named_modes_whitelist[i], size))
-                       return true;
-
-       return false;
-}
-
 /**
  * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
  * @mode_option: optional per connector mode option
@@ -1723,72 +1737,30 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
                                               struct drm_cmdline_mode *mode)
 {
        const char *name;
-       bool named_mode = false, parse_extras = false;
+       bool freestanding = false, parse_extras = false;
        unsigned int bpp_off = 0, refresh_off = 0, options_off = 0;
        unsigned int mode_end = 0;
-       char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
-       char *options_ptr = NULL;
+       const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
+       const char *options_ptr = NULL;
        char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
-       int ret;
+       int i, len, ret;
 
-#ifdef CONFIG_FB
-       if (!mode_option)
-               mode_option = fb_mode_option;
-#endif
+       memset(mode, 0, sizeof(*mode));
+       mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
 
-       if (!mode_option) {
-               mode->specified = false;
+       if (!mode_option)
                return false;
-       }
 
        name = mode_option;
 
-       /*
-        * This is a bit convoluted. To differentiate between the
-        * named modes and poorly formatted resolutions, we need a
-        * bunch of things:
-        *   - We need to make sure that the first character (which
-        *     would be our resolution in X) is a digit.
-        *   - If not, then it's either a named mode or a force on/off.
-        *     To distinguish between the two, we need to run the
-        *     extra parsing function, and if not, then we consider it
-        *     a named mode.
-        *
-        * If this isn't enough, we should add more heuristics here,
-        * and matching unit-tests.
-        */
-       if (!isdigit(name[0]) && name[0] != 'x') {
-               unsigned int namelen = strlen(name);
-
-               /*
-                * Only the force on/off options can be in that case,
-                * and they all take a single character.
-                */
-               if (namelen == 1) {
-                       ret = drm_mode_parse_cmdline_extra(name, namelen, true,
-                                                          connector, mode);
-                       if (!ret)
-                               return true;
-               }
-
-               named_mode = true;
-       }
-
        /* Try to locate the bpp and refresh specifiers, if any */
        bpp_ptr = strchr(name, '-');
-       if (bpp_ptr) {
+       if (bpp_ptr)
                bpp_off = bpp_ptr - name;
-               mode->bpp_specified = true;
-       }
 
        refresh_ptr = strchr(name, '@');
-       if (refresh_ptr) {
-               if (named_mode)
-                       return false;
-
+       if (refresh_ptr)
                refresh_off = refresh_ptr - name;
-               mode->refresh_specified = true;
-       }
 
        /* Locate the start of named options */
        options_ptr = strchr(name, ',');
@@ -1802,33 +1774,58 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
                mode_end = refresh_off;
        } else if (options_ptr) {
                mode_end = options_off;
+               parse_extras = true;
        } else {
                mode_end = strlen(name);
                parse_extras = true;
        }
 
-       if (named_mode) {
-               if (mode_end + 1 > DRM_DISPLAY_MODE_LEN)
-                       return false;
+       /* First check for a named mode */
+       for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
+               ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
+               if (ret == mode_end) {
+                       if (refresh_ptr)
+                               return false; /* named + refresh is invalid */
 
-               if (!drm_named_mode_is_in_whitelist(name, mode_end))
-                       return false;
+                       strcpy(mode->name, drm_named_modes_whitelist[i]);
+                       mode->specified = true;
+                       break;
+               }
+       }
 
-               strscpy(mode->name, name, mode_end + 1);
-       } else {
+       /* No named mode? Check for a normal mode argument, e.g. 1024x768 */
+       if (!mode->specified && isdigit(name[0])) {
                ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
                                                      parse_extras,
                                                      connector,
                                                      mode);
                if (ret)
                        return false;
+
+               mode->specified = true;
+       }
+
+       /* No mode? Check for freestanding extras and/or options */
+       if (!mode->specified) {
+               unsigned int len = strlen(mode_option);
+
+               if (bpp_ptr || refresh_ptr)
+                       return false; /* syntax error */
+
+               if (len == 1 || (len >= 2 && mode_option[1] == ','))
+                       extra_ptr = mode_option;
+               else
+                       options_ptr = mode_option - 1;
+
+               freestanding = true;
        }
-       mode->specified = true;
 
        if (bpp_ptr) {
                ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode);
                if (ret)
                        return false;
+
+               mode->bpp_specified = true;
        }
 
        if (refresh_ptr) {
@@ -1836,6 +1833,8 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
                                                     &refresh_end_ptr, mode);
                if (ret)
                        return false;
+
+               mode->refresh_specified = true;
        }
 
        /*
@@ -1849,20 +1848,21 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
        else if (refresh_ptr)
                extra_ptr = refresh_end_ptr;
 
-       if (extra_ptr &&
-           extra_ptr != options_ptr) {
-               int len = strlen(name) - (extra_ptr - name);
+       if (extra_ptr) {
+               if (options_ptr)
+                       len = options_ptr - extra_ptr;
+               else
+                       len = strlen(extra_ptr);
 
-               ret = drm_mode_parse_cmdline_extra(extra_ptr, len, false,
+               ret = drm_mode_parse_cmdline_extra(extra_ptr, len, freestanding,
                                                   connector, mode);
                if (ret)
                        return false;
        }
 
        if (options_ptr) {
-               int len = strlen(name) - (options_ptr - name);
-
-               ret = drm_mode_parse_cmdline_options(options_ptr, len,
+               ret = drm_mode_parse_cmdline_options(options_ptr + 1,
+                                                    freestanding,
                                                     connector, mode);
                if (ret)
                        return false;
index 79ff3fd..8c7bac8 100644 (file)
@@ -302,7 +302,7 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np)
 EXPORT_SYMBOL(of_drm_find_panel);
 #endif
 
-#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
+#if IS_REACHABLE(CONFIG_BACKLIGHT_CLASS_DEVICE)
 /**
  * drm_panel_of_backlight - use backlight device node for backlight
  * @panel: DRM panel
index aa3e4c3..3b0afa1 100644 (file)
@@ -113,7 +113,7 @@ static void submit_unlock_object(struct etnaviv_gem_submit *submit, int i)
        if (submit->bos[i].flags & BO_LOCKED) {
                struct drm_gem_object *obj = &submit->bos[i].obj->base;
 
-               ww_mutex_unlock(&obj->resv->lock);
+               dma_resv_unlock(obj->resv);
                submit->bos[i].flags &= ~BO_LOCKED;
        }
 }
@@ -133,8 +133,7 @@ retry:
                contended = i;
 
                if (!(submit->bos[i].flags & BO_LOCKED)) {
-                       ret = ww_mutex_lock_interruptible(&obj->resv->lock,
-                                                         ticket);
+                       ret = dma_resv_lock_interruptible(obj->resv, ticket);
                        if (ret == -EALREADY)
                                DRM_ERROR("BO at index %u already on submit list\n",
                                          i);
@@ -161,8 +160,7 @@ fail:
                obj = &submit->bos[contended].obj->base;
 
                /* we lost out in a seqno race, lock and retry.. */
-               ret = ww_mutex_lock_slow_interruptible(&obj->resv->lock,
-                                                      ticket);
+               ret = dma_resv_lock_slow_interruptible(obj->resv, ticket);
                if (!ret) {
                        submit->bos[contended].flags |= BO_LOCKED;
                        slow_locked = contended;
index b9e5a38..adc0507 100644 (file)
@@ -228,8 +228,8 @@ static void psbfb_copyarea_accel(struct fb_info *info,
 {
        struct drm_fb_helper *fb_helper = info->par;
        struct drm_framebuffer *fb = fb_helper->fb;
-       struct drm_device *dev = fb->dev;
-       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct drm_device *dev;
+       struct drm_psb_private *dev_priv;
        uint32_t offset;
        uint32_t stride;
        uint32_t src_format;
@@ -238,6 +238,8 @@ static void psbfb_copyarea_accel(struct fb_info *info,
        if (!fb)
                return;
 
+       dev = fb->dev;
+       dev_priv = dev->dev_private;
        offset = to_gtt_range(fb->obj[0])->offset;
        stride = fb->pitches[0];
 
index d761067..bb6528b 100644 (file)
@@ -388,13 +388,14 @@ void mcde_dsi_te_request(struct mipi_dsi_device *mdsi)
 static void mcde_dsi_setup_video_mode(struct mcde_dsi *d,
                                      const struct drm_display_mode *mode)
 {
-       u8 bpp = mipi_dsi_pixel_format_to_bpp(d->mdsi->format);
+       /* cpp, characters per pixel, number of bytes per pixel */
+       u8 cpp = mipi_dsi_pixel_format_to_bpp(d->mdsi->format) / 8;
+       u64 pclk;
        u64 bpl;
-       u32 hfp;
-       u32 hbp;
-       u32 hsa;
+       int hfp;
+       int hbp;
+       int hsa;
        u32 blkline_pck, line_duration;
-       u32 blkeol_pck, blkeol_duration;
        u32 val;
 
        val = 0;
@@ -431,11 +432,21 @@ static void mcde_dsi_setup_video_mode(struct mcde_dsi *d,
                return;
        }
 
-       /* TODO: TVG could be enabled here */
+       /* TODO: TVG (test video generator) could be enabled here */
 
-       /* Send blanking packet */
+       /*
+        * During vertical blanking: go to LP mode
+        * Like with the EOL setting, if this is not set, the EOL area will be
+        * filled with NULL or blanking packets in the vblank area.
+        * FIXME: some Samsung phones and display panels such as s6e63m0 use
+        * DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_BLANKING here instead,
+        * figure out how to properly configure that from the panel.
+        */
        val |= DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_LP_0;
-       /* Send EOL packet */
+       /*
+        * During EOL: go to LP mode. If this is not set, the EOL area will be
+        * filled with NULL or blanking packets.
+        */
        val |= DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_LP_0;
        /* Recovery mode 1 */
        val |= 1 << DSI_VID_MAIN_CTL_RECOVERY_MODE_SHIFT;
@@ -443,13 +454,13 @@ static void mcde_dsi_setup_video_mode(struct mcde_dsi *d,
        writel(val, d->regs + DSI_VID_MAIN_CTL);
 
        /* Vertical frame parameters are pretty straight-forward */
-       val = mode->vdisplay << DSI_VID_VSIZE_VSA_LENGTH_SHIFT;
+       val = mode->vdisplay << DSI_VID_VSIZE_VACT_LENGTH_SHIFT;
        /* vertical front porch */
        val |= (mode->vsync_start - mode->vdisplay)
                << DSI_VID_VSIZE_VFP_LENGTH_SHIFT;
        /* vertical sync active */
        val |= (mode->vsync_end - mode->vsync_start)
-               << DSI_VID_VSIZE_VACT_LENGTH_SHIFT;
+               << DSI_VID_VSIZE_VSA_LENGTH_SHIFT;
        /* vertical back porch */
        val |= (mode->vtotal - mode->vsync_end)
                << DSI_VID_VSIZE_VBP_LENGTH_SHIFT;
@@ -457,36 +468,54 @@ static void mcde_dsi_setup_video_mode(struct mcde_dsi *d,
 
        /*
         * Horizontal frame parameters:
-        * horizontal resolution is given in pixels and must be re-calculated
-        * into bytes since this is what the hardware expects.
+        * horizontal resolution is given in pixels but must be re-calculated
+        * into bytes since this is what the hardware expects, these registers
+        * define the payload size of the packet.
+        *
+        * hfp = horizontal front porch in bytes
+        * hbp = horizontal back porch in bytes
+        * hsa = horizontal sync active in bytes
         *
         * 6 + 2 is HFP header + checksum
         */
-       hfp = (mode->hsync_start - mode->hdisplay) * bpp - 6 - 2;
+       hfp = (mode->hsync_start - mode->hdisplay) * cpp - 6 - 2;
        if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
                /*
+                * Use sync pulse for sync: explicit HSA time
                 * 6 is HBP header + checksum
                 * 4 is RGB header + checksum
                 */
-               hbp = (mode->htotal - mode->hsync_end) * bpp - 4 - 6;
+               hbp = (mode->htotal - mode->hsync_end) * cpp - 4 - 6;
                /*
                 * 6 is HBP header + checksum
                 * 4 is HSW packet bytes
                 * 4 is RGB header + checksum
                 */
-               hsa = (mode->hsync_end - mode->hsync_start) * bpp - 4 - 4 - 6;
+               hsa = (mode->hsync_end - mode->hsync_start) * cpp - 4 - 4 - 6;
        } else {
                /*
-                * HBP includes both back porch and sync
+                * Use event for sync: HBP includes both back porch and sync
                 * 6 is HBP header + checksum
                 * 4 is HSW packet bytes
                 * 4 is RGB header + checksum
                 */
-               hbp = (mode->htotal - mode->hsync_start) * bpp - 4 - 4 - 6;
-               /* HSA is not considered in this mode and set to 0 */
+               hbp = (mode->htotal - mode->hsync_start) * cpp - 4 - 4 - 6;
+               /* HSA is not present in this mode and set to 0 */
+               hsa = 0;
+       }
+       if (hfp < 0) {
+               dev_info(d->dev, "hfp negative, set to 0\n");
+               hfp = 0;
+       }
+       if (hbp < 0) {
+               dev_info(d->dev, "hbp negative, set to 0\n");
+               hbp = 0;
+       }
+       if (hsa < 0) {
+               dev_info(d->dev, "hsa negative, set to 0\n");
                hsa = 0;
        }
-       dev_dbg(d->dev, "hfp: %u, hbp: %u, hsa: %u\n",
+       dev_dbg(d->dev, "hfp: %u, hbp: %u, hsa: %u bytes\n",
                hfp, hbp, hsa);
 
        /* Frame parameters: horizontal sync active */
@@ -497,71 +526,185 @@ static void mcde_dsi_setup_video_mode(struct mcde_dsi *d,
        val |= hfp << DSI_VID_HSIZE1_HFP_LENGTH_SHIFT;
        writel(val, d->regs + DSI_VID_HSIZE1);
 
-       /* RGB data length (bytes on one scanline) */
-       val = mode->hdisplay * (bpp / 8);
+       /* RGB data length (visible bytes on one scanline) */
+       val = mode->hdisplay * cpp;
        writel(val, d->regs + DSI_VID_HSIZE2);
+       dev_dbg(d->dev, "RGB length, visible area on a line: %u bytes\n", val);
 
-       /* TODO: further adjustments for TVG mode here */
+       /*
+        * Calculate the time between two pixels in picoseconds using
+        * the supplied refresh rate and total resolution including
+        * porches and sync.
+        */
+       /* (ps/s) / (pixels/s) = ps/pixels */
+       pclk = DIV_ROUND_UP_ULL(1000000000000,
+                               (mode->vrefresh * mode->htotal * mode->vtotal));
+       dev_dbg(d->dev, "picoseconds between two pixels: %llu\n",
+               pclk);
 
        /*
-        * EOL packet length from bits per line calculations: pixel clock
-        * is given in kHz, calculate the time between two pixels in
-        * picoseconds.
+        * How many bytes per line will this update frequency yield?
+        *
+        * Calculate the number of picoseconds for one scanline (1), then
+        * divide by 1000000000000 (2) to get in pixels per second we
+        * want to output.
+        *
+        * Multiply with number of bytes per second at this video display
+        * frequency (3) to get number of bytes transferred during this
+        * time. Notice that we use the frequency the display wants,
+        * not what we actually get from the DSI PLL, which is hs_freq.
+        *
+        * These arithmetics are done in a different order to avoid
+        * overflow.
         */
-       bpl = mode->clock * mode->htotal;
-       bpl *= (d->hs_freq / 8);
-       do_div(bpl, 1000000); /* microseconds */
-       do_div(bpl, 1000000); /* seconds */
+       bpl = pclk * mode->htotal; /* (1) picoseconds per line */
+       dev_dbg(d->dev, "picoseconds per line: %llu\n", bpl);
+       /* Multiply with bytes per second (3) */
+       bpl *= (d->mdsi->hs_rate / 8);
+       /* Pixels per second (2) */
+       bpl = DIV_ROUND_DOWN_ULL(bpl, 1000000); /* microseconds */
+       bpl = DIV_ROUND_DOWN_ULL(bpl, 1000000); /* seconds */
+       /* parallel transactions in all lanes */
        bpl *= d->mdsi->lanes;
-       dev_dbg(d->dev, "calculated bytes per line: %llu\n", bpl);
+       dev_dbg(d->dev,
+               "calculated bytes per line: %llu @ %d Hz with HS %lu Hz\n",
+               bpl, mode->vrefresh, d->mdsi->hs_rate);
+
        /*
         * 6 is header + checksum, header = 4 bytes, checksum = 2 bytes
         * 4 is short packet for vsync/hsync
         */
        if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
-               /* Fixme: isn't the hsync width in pixels? */
+               /* Set the event packet size to 0 (not used) */
+               writel(0, d->regs + DSI_VID_BLKSIZE1);
+               /*
+                * FIXME: isn't the hsync width in pixels? The porch and
+                * sync area size is in pixels here, but this -6
+                * seems to be for bytes. It looks like this in the vendor
+                * code though. Is it completely untested?
+                */
                blkline_pck = bpl - (mode->hsync_end - mode->hsync_start) - 6;
                val = blkline_pck << DSI_VID_BLKSIZE2_BLKLINE_PULSE_PCK_SHIFT;
                writel(val, d->regs + DSI_VID_BLKSIZE2);
        } else {
+               /* Set the sync pulse packet size to 0 (not used) */
+               writel(0, d->regs + DSI_VID_BLKSIZE2);
+               /* Specifying payload size in bytes (-4-6 from manual) */
                blkline_pck = bpl - 4 - 6;
+               if (blkline_pck > 0x1FFF)
+                       dev_err(d->dev, "blkline_pck too big %d bytes\n",
+                               blkline_pck);
                val = blkline_pck << DSI_VID_BLKSIZE1_BLKLINE_EVENT_PCK_SHIFT;
+               val &= DSI_VID_BLKSIZE1_BLKLINE_EVENT_PCK_MASK;
                writel(val, d->regs + DSI_VID_BLKSIZE1);
        }
 
-       line_duration = (blkline_pck + 6) / d->mdsi->lanes;
-       dev_dbg(d->dev, "line duration %u\n", line_duration);
+       /*
+        * The line duration is used to scale back the frequency from
+        * the max frequency supported by the HS clock to the desired
+        * update frequency in vrefresh.
+        */
+       line_duration = blkline_pck + 6;
+       /*
+        * The datasheet contains this complex condition to decreasing
+        * the line duration by 1 under very specific circumstances.
+        * Here we also imply that LP is used during burst EOL.
+        */
+       if (d->mdsi->lanes == 2 && (hsa & 0x01) && (hfp & 0x01)
+           && (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST))
+               line_duration--;
+       line_duration = DIV_ROUND_CLOSEST(line_duration, d->mdsi->lanes);
+       dev_dbg(d->dev, "line duration %u bytes\n", line_duration);
        val = line_duration << DSI_VID_DPHY_TIME_REG_LINE_DURATION_SHIFT;
        /*
         * This is the time to perform LP->HS on D-PHY
         * FIXME: nowhere to get this from: DT property on the DSI?
+        * The manual says this is "system dependent".
+        * values like 48 and 72 seen in the vendor code.
         */
-       val |= 0 << DSI_VID_DPHY_TIME_REG_WAKEUP_TIME_SHIFT;
+       val |= 48 << DSI_VID_DPHY_TIME_REG_WAKEUP_TIME_SHIFT;
        writel(val, d->regs + DSI_VID_DPHY_TIME);
 
-       /* Calculate block end of line */
-       blkeol_pck = bpl - mode->hdisplay * bpp - 6;
-       blkeol_duration = (blkeol_pck + 6) / d->mdsi->lanes;
-       dev_dbg(d->dev, "blkeol pck: %u, duration: %u\n",
-                blkeol_pck, blkeol_duration);
-
+       /*
+        * See the manual figure 657 page 2203 for understanding the impact
+        * of the different burst mode settings.
+        */
        if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
-               /* Set up EOL clock for burst mode */
+               int blkeol_pck, blkeol_duration;
+               /*
+                * Packet size at EOL for burst mode, this is only used
+                * if DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_LP_0 is NOT set,
+                * but we instead send NULL or blanking packets at EOL.
+                * This is given in number of bytes.
+                *
+                * See the manual page 2198 for the 13 reg_blkeol_pck bits.
+                */
+               blkeol_pck = bpl - (mode->htotal * cpp) - 6;
+               if (blkeol_pck < 0) {
+                       dev_err(d->dev, "video block does not fit on line!\n");
+                       dev_err(d->dev,
+                               "calculated bytes per line: %llu @ %d Hz\n",
+                               bpl, mode->vrefresh);
+                       dev_err(d->dev,
+                               "bytes per line (blkline_pck) %u bytes\n",
+                               blkline_pck);
+                       dev_err(d->dev,
+                               "blkeol_pck becomes %d bytes\n", blkeol_pck);
+                       return;
+               }
+               dev_dbg(d->dev, "BLKEOL packet: %d bytes\n", blkeol_pck);
+
                val = readl(d->regs + DSI_VID_BLKSIZE1);
+               val &= ~DSI_VID_BLKSIZE1_BLKEOL_PCK_MASK;
                val |= blkeol_pck << DSI_VID_BLKSIZE1_BLKEOL_PCK_SHIFT;
                writel(val, d->regs + DSI_VID_BLKSIZE1);
-               writel(blkeol_pck, d->regs + DSI_VID_VCA_SETTING2);
-
-               writel(blkeol_duration, d->regs + DSI_VID_PCK_TIME);
-               writel(blkeol_duration - 6, d->regs + DSI_VID_VCA_SETTING1);
+               /* Use the same value for exact burst limit */
+               val = blkeol_pck <<
+                       DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT_SHIFT;
+               val &= DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT_MASK;
+               writel(val, d->regs + DSI_VID_VCA_SETTING2);
+               /*
+                * This BLKEOL duration is claimed to be the duration in clock
+                * cycles of the BLLP end-of-line (EOL) period for each line if
+                * DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_LP_0 is set.
+                *
+                * It is hard to trust the manuals' claim that this is in clock
+                * cycles as we mimic the behaviour of the vendor code, which
+                * appears to write a number of bytes that would have been
+                * transferred on a single lane.
+                *
+                * See the manual figure 657 page 2203 and page 2198 for the 13
+                * reg_blkeol_duration bits.
+                *
+                * FIXME: should this also be set up also for non-burst mode
+                * according to figure 565 page 2202?
+                */
+               blkeol_duration = DIV_ROUND_CLOSEST(blkeol_pck + 6,
+                                                   d->mdsi->lanes);
+               dev_dbg(d->dev, "BLKEOL duration: %d clock cycles\n",
+                       blkeol_duration);
+
+               val = readl(d->regs + DSI_VID_PCK_TIME);
+               val &= ~DSI_VID_PCK_TIME_BLKEOL_DURATION_MASK;
+               val |= blkeol_duration <<
+                       DSI_VID_PCK_TIME_BLKEOL_DURATION_SHIFT;
+               writel(val, d->regs + DSI_VID_PCK_TIME);
+
+               /* Max burst limit, this is given in bytes */
+               val = readl(d->regs + DSI_VID_VCA_SETTING1);
+               val &= ~DSI_VID_VCA_SETTING1_MAX_BURST_LIMIT_MASK;
+               val |= (blkeol_pck - 6) <<
+                       DSI_VID_VCA_SETTING1_MAX_BURST_LIMIT_SHIFT;
+               writel(val, d->regs + DSI_VID_VCA_SETTING1);
        }
 
        /* Maximum line limit */
        val = readl(d->regs + DSI_VID_VCA_SETTING2);
-       val |= blkline_pck <<
-               DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT_SHIFT;
+       val &= ~DSI_VID_VCA_SETTING2_MAX_LINE_LIMIT_MASK;
+       val |= (blkline_pck - 6) <<
+               DSI_VID_VCA_SETTING2_MAX_LINE_LIMIT_SHIFT;
        writel(val, d->regs + DSI_VID_VCA_SETTING2);
-
+       dev_dbg(d->dev, "blkline pck: %d bytes\n", blkline_pck - 6);
 }
 
 static void mcde_dsi_start(struct mcde_dsi *d)
index 8089db8..16551af 100644 (file)
 
 #define DSI_VID_PCK_TIME 0x000000A8
 #define DSI_VID_PCK_TIME_BLKEOL_DURATION_SHIFT 0
+#define DSI_VID_PCK_TIME_BLKEOL_DURATION_MASK 0x00000FFF
 
 #define DSI_VID_DPHY_TIME 0x000000AC
 #define DSI_VID_DPHY_TIME_REG_LINE_DURATION_SHIFT 0
index 540ef2f..f0b0325 100644 (file)
@@ -94,7 +94,7 @@ static int mtk_plane_atomic_check(struct drm_plane *plane,
        if (!fb)
                return 0;
 
-       if (!state->crtc)
+       if (WARN_ON(!state->crtc))
                return 0;
 
        ret = mtk_drm_crtc_plane_check(state->crtc, plane,
index 7d04c47..385d496 100644 (file)
@@ -157,7 +157,7 @@ static void submit_unlock_unpin_bo(struct msm_gem_submit *submit,
                msm_gem_unpin_iova(&msm_obj->base, submit->aspace);
 
        if (submit->bos[i].flags & BO_LOCKED)
-               ww_mutex_unlock(&msm_obj->base.resv->lock);
+               dma_resv_unlock(msm_obj->base.resv);
 
        if (backoff && !(submit->bos[i].flags & BO_VALID))
                submit->bos[i].iova = 0;
@@ -180,8 +180,8 @@ retry:
                contended = i;
 
                if (!(submit->bos[i].flags & BO_LOCKED)) {
-                       ret = ww_mutex_lock_interruptible(&msm_obj->base.resv->lock,
-                                       &submit->ticket);
+                       ret = dma_resv_lock_interruptible(msm_obj->base.resv,
+                                                         &submit->ticket);
                        if (ret)
                                goto fail;
                        submit->bos[i].flags |= BO_LOCKED;
@@ -202,8 +202,8 @@ fail:
        if (ret == -EDEADLK) {
                struct msm_gem_object *msm_obj = submit->bos[contended].obj;
                /* we lost out in a seqno race, lock and retry.. */
-               ret = ww_mutex_lock_slow_interruptible(&msm_obj->base.resv->lock,
-                               &submit->ticket);
+               ret = dma_resv_lock_slow_interruptible(msm_obj->base.resv,
+                                                      &submit->ticket);
                if (!ret) {
                        submit->bos[contended].flags |= BO_LOCKED;
                        slow_locked = contended;
index 20235ff..b262b53 100644 (file)
@@ -42,7 +42,7 @@ static int lg4573_spi_write_u16(struct lg4573 *ctx, u16 data)
        struct spi_transfer xfer = {
                .len = 2,
        };
-       u16 temp = cpu_to_be16(data);
+       __be16 temp = cpu_to_be16(data);
        struct spi_message msg;
 
        dev_dbg(ctx->panel.dev, "writing data: %x\n", data);
index 1670a5c..310aa15 100644 (file)
@@ -46,6 +46,7 @@ config ROCKCHIP_DW_HDMI
 
 config ROCKCHIP_DW_MIPI_DSI
        bool "Rockchip specific extensions for Synopsys DW MIPI DSI"
+       select GENERIC_PHY_MIPI_DPHY
        help
          This selects support for Rockchip SoC specific extensions
          for the Synopsys DesignWare HDMI driver. If you want to
index 5f23cf7..6e1270e 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/phy/phy.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 
 #define DW_MIPI_NEEDS_PHY_CFG_CLK      BIT(0)
 #define DW_MIPI_NEEDS_GRF_CLK          BIT(1)
 
+#define PX30_GRF_PD_VO_CON1            0x0438
+#define PX30_DSI_FORCETXSTOPMODE       (0xf << 7)
+#define PX30_DSI_FORCERXMODE           BIT(6)
+#define PX30_DSI_TURNDISABLE           BIT(5)
+#define PX30_DSI_LCDC_SEL              BIT(0)
+
 #define RK3288_GRF_SOC_CON6            0x025c
 #define RK3288_DSI0_LCDC_SEL           BIT(6)
 #define RK3288_DSI1_LCDC_SEL           BIT(9)
@@ -223,6 +230,10 @@ struct dw_mipi_dsi_rockchip {
        bool is_slave;
        struct dw_mipi_dsi_rockchip *slave;
 
+       /* optional external dphy */
+       struct phy *phy;
+       union phy_configure_opts phy_opts;
+
        unsigned int lane_mbps; /* per lane */
        u16 input_div;
        u16 feedback_div;
@@ -359,6 +370,9 @@ static int dw_mipi_dsi_phy_init(void *priv_data)
        struct dw_mipi_dsi_rockchip *dsi = priv_data;
        int ret, i, vco;
 
+       if (dsi->phy)
+               return 0;
+
        /*
         * Get vco from frequency(lane_mbps)
         * vco  frequency table
@@ -467,6 +481,28 @@ static int dw_mipi_dsi_phy_init(void *priv_data)
        return ret;
 }
 
+static void dw_mipi_dsi_phy_power_on(void *priv_data)
+{
+       struct dw_mipi_dsi_rockchip *dsi = priv_data;
+       int ret;
+
+       ret = phy_set_mode(dsi->phy, PHY_MODE_MIPI_DPHY);
+       if (ret) {
+               DRM_DEV_ERROR(dsi->dev, "failed to set phy mode: %d\n", ret);
+               return;
+       }
+
+       phy_configure(dsi->phy, &dsi->phy_opts);
+       phy_power_on(dsi->phy);
+}
+
+static void dw_mipi_dsi_phy_power_off(void *priv_data)
+{
+       struct dw_mipi_dsi_rockchip *dsi = priv_data;
+
+       phy_power_off(dsi->phy);
+}
+
 static int
 dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
                          unsigned long mode_flags, u32 lanes, u32 format,
@@ -504,6 +540,17 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
                                      "DPHY clock frequency is out of range\n");
        }
 
+       /* for external phy only a the mipi_dphy_config is necessary */
+       if (dsi->phy) {
+               phy_mipi_dphy_get_default_config(mode->clock * 1000 * 10 / 8,
+                                                bpp, lanes,
+                                                &dsi->phy_opts.mipi_dphy);
+               dsi->lane_mbps = target_mbps;
+               *lane_mbps = dsi->lane_mbps;
+
+               return 0;
+       }
+
        fin = clk_get_rate(dsi->pllref_clk);
        fout = target_mbps * USEC_PER_SEC;
 
@@ -559,9 +606,89 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
        return 0;
 }
 
+struct hstt {
+       unsigned int maxfreq;
+       struct dw_mipi_dsi_dphy_timing timing;
+};
+
+#define HSTT(_maxfreq, _c_lp2hs, _c_hs2lp, _d_lp2hs, _d_hs2lp) \
+{                                      \
+       .maxfreq = _maxfreq,            \
+       .timing = {                     \
+               .clk_lp2hs = _c_lp2hs,  \
+               .clk_hs2lp = _c_hs2lp,  \
+               .data_lp2hs = _d_lp2hs, \
+               .data_hs2lp = _d_hs2lp, \
+       }                               \
+}
+
+/* Table A-3 High-Speed Transition Times */
+struct hstt hstt_table[] = {
+       HSTT(  90,  32, 20,  26, 13),
+       HSTT( 100,  35, 23,  28, 14),
+       HSTT( 110,  32, 22,  26, 13),
+       HSTT( 130,  31, 20,  27, 13),
+       HSTT( 140,  33, 22,  26, 14),
+       HSTT( 150,  33, 21,  26, 14),
+       HSTT( 170,  32, 20,  27, 13),
+       HSTT( 180,  36, 23,  30, 15),
+       HSTT( 200,  40, 22,  33, 15),
+       HSTT( 220,  40, 22,  33, 15),
+       HSTT( 240,  44, 24,  36, 16),
+       HSTT( 250,  48, 24,  38, 17),
+       HSTT( 270,  48, 24,  38, 17),
+       HSTT( 300,  50, 27,  41, 18),
+       HSTT( 330,  56, 28,  45, 18),
+       HSTT( 360,  59, 28,  48, 19),
+       HSTT( 400,  61, 30,  50, 20),
+       HSTT( 450,  67, 31,  55, 21),
+       HSTT( 500,  73, 31,  59, 22),
+       HSTT( 550,  79, 36,  63, 24),
+       HSTT( 600,  83, 37,  68, 25),
+       HSTT( 650,  90, 38,  73, 27),
+       HSTT( 700,  95, 40,  77, 28),
+       HSTT( 750, 102, 40,  84, 28),
+       HSTT( 800, 106, 42,  87, 30),
+       HSTT( 850, 113, 44,  93, 31),
+       HSTT( 900, 118, 47,  98, 32),
+       HSTT( 950, 124, 47, 102, 34),
+       HSTT(1000, 130, 49, 107, 35),
+       HSTT(1050, 135, 51, 111, 37),
+       HSTT(1100, 139, 51, 114, 38),
+       HSTT(1150, 146, 54, 120, 40),
+       HSTT(1200, 153, 57, 125, 41),
+       HSTT(1250, 158, 58, 130, 42),
+       HSTT(1300, 163, 58, 135, 44),
+       HSTT(1350, 168, 60, 140, 45),
+       HSTT(1400, 172, 64, 144, 47),
+       HSTT(1450, 176, 65, 148, 48),
+       HSTT(1500, 181, 66, 153, 50)
+};
+
+static int
+dw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps,
+                          struct dw_mipi_dsi_dphy_timing *timing)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(hstt_table); i++)
+               if (lane_mbps < hstt_table[i].maxfreq)
+                       break;
+
+       if (i == ARRAY_SIZE(hstt_table))
+               i--;
+
+       *timing = hstt_table[i].timing;
+
+       return 0;
+}
+
 static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_rockchip_phy_ops = {
        .init = dw_mipi_dsi_phy_init,
+       .power_on = dw_mipi_dsi_phy_power_on,
+       .power_off = dw_mipi_dsi_phy_power_off,
        .get_lane_mbps = dw_mipi_dsi_get_lane_mbps,
+       .get_timing = dw_mipi_dsi_phy_get_timing,
 };
 
 static void dw_mipi_dsi_rockchip_config(struct dw_mipi_dsi_rockchip *dsi,
@@ -920,12 +1047,29 @@ static int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
+       /* try to get a possible external dphy */
+       dsi->phy = devm_phy_optional_get(dev, "dphy");
+       if (IS_ERR(dsi->phy)) {
+               ret = PTR_ERR(dsi->phy);
+               DRM_DEV_ERROR(dev, "failed to get mipi dphy: %d\n", ret);
+               return ret;
+       }
+
        dsi->pllref_clk = devm_clk_get(dev, "ref");
        if (IS_ERR(dsi->pllref_clk)) {
-               ret = PTR_ERR(dsi->pllref_clk);
-               DRM_DEV_ERROR(dev,
-                             "Unable to get pll reference clock: %d\n", ret);
-               return ret;
+               if (dsi->phy) {
+                       /*
+                        * if external phy is present, pll will be
+                        * generated there.
+                        */
+                       dsi->pllref_clk = NULL;
+               } else {
+                       ret = PTR_ERR(dsi->pllref_clk);
+                       DRM_DEV_ERROR(dev,
+                                     "Unable to get pll reference clock: %d\n",
+                                     ret);
+                       return ret;
+               }
        }
 
        if (dsi->cdata->flags & DW_MIPI_NEEDS_PHY_CFG_CLK) {
@@ -989,6 +1133,24 @@ static int dw_mipi_dsi_rockchip_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct rockchip_dw_dsi_chip_data px30_chip_data[] = {
+       {
+               .reg = 0xff450000,
+               .lcdsel_grf_reg = PX30_GRF_PD_VO_CON1,
+               .lcdsel_big = HIWORD_UPDATE(0, PX30_DSI_LCDC_SEL),
+               .lcdsel_lit = HIWORD_UPDATE(PX30_DSI_LCDC_SEL,
+                                           PX30_DSI_LCDC_SEL),
+
+               .lanecfg1_grf_reg = PX30_GRF_PD_VO_CON1,
+               .lanecfg1 = HIWORD_UPDATE(0, PX30_DSI_TURNDISABLE |
+                                            PX30_DSI_FORCERXMODE |
+                                            PX30_DSI_FORCETXSTOPMODE),
+
+               .max_data_lanes = 4,
+       },
+       { /* sentinel */ }
+};
+
 static const struct rockchip_dw_dsi_chip_data rk3288_chip_data[] = {
        {
                .reg = 0xff960000,
@@ -1057,6 +1219,9 @@ static const struct rockchip_dw_dsi_chip_data rk3399_chip_data[] = {
 
 static const struct of_device_id dw_mipi_dsi_rockchip_dt_ids[] = {
        {
+        .compatible = "rockchip,px30-mipi-dsi",
+        .data = &px30_chip_data,
+       }, {
         .compatible = "rockchip,rk3288-mipi-dsi",
         .data = &rk3288_chip_data,
        }, {
index 6d61a0e..ceac7af 100644 (file)
@@ -60,3 +60,8 @@ cmdline_test(drm_cmdline_test_vmirror)
 cmdline_test(drm_cmdline_test_margin_options)
 cmdline_test(drm_cmdline_test_multiple_options)
 cmdline_test(drm_cmdline_test_invalid_option)
+cmdline_test(drm_cmdline_test_bpp_extra_and_option)
+cmdline_test(drm_cmdline_test_extra_and_option)
+cmdline_test(drm_cmdline_test_freestanding_options)
+cmdline_test(drm_cmdline_test_freestanding_force_e_and_options)
+cmdline_test(drm_cmdline_test_panel_orientation)
index 013de9d..520f3e6 100644 (file)
@@ -992,6 +992,128 @@ static int drm_cmdline_test_invalid_option(void *ignored)
        return 0;
 }
 
+static int drm_cmdline_test_bpp_extra_and_option(void *ignored)
+{
+       struct drm_cmdline_mode mode = { };
+
+       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24e,rotate=180",
+                                                          &no_connector,
+                                                          &mode));
+       FAIL_ON(!mode.specified);
+       FAIL_ON(mode.xres != 720);
+       FAIL_ON(mode.yres != 480);
+       FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180);
+
+       FAIL_ON(mode.refresh_specified);
+
+       FAIL_ON(!mode.bpp_specified);
+       FAIL_ON(mode.bpp != 24);
+
+       FAIL_ON(mode.rb);
+       FAIL_ON(mode.cvt);
+       FAIL_ON(mode.interlace);
+       FAIL_ON(mode.margins);
+       FAIL_ON(mode.force != DRM_FORCE_ON);
+
+       return 0;
+}
+
+static int drm_cmdline_test_extra_and_option(void *ignored)
+{
+       struct drm_cmdline_mode mode = { };
+
+       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480e,rotate=180",
+                                                          &no_connector,
+                                                          &mode));
+       FAIL_ON(!mode.specified);
+       FAIL_ON(mode.xres != 720);
+       FAIL_ON(mode.yres != 480);
+       FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180);
+
+       FAIL_ON(mode.refresh_specified);
+       FAIL_ON(mode.bpp_specified);
+
+       FAIL_ON(mode.rb);
+       FAIL_ON(mode.cvt);
+       FAIL_ON(mode.interlace);
+       FAIL_ON(mode.margins);
+       FAIL_ON(mode.force != DRM_FORCE_ON);
+
+       return 0;
+}
+
+static int drm_cmdline_test_freestanding_options(void *ignored)
+{
+       struct drm_cmdline_mode mode = { };
+
+       FAIL_ON(!drm_mode_parse_command_line_for_connector("margin_right=14,margin_left=24,margin_bottom=36,margin_top=42",
+                                                          &no_connector,
+                                                          &mode));
+       FAIL_ON(mode.specified);
+       FAIL_ON(mode.refresh_specified);
+       FAIL_ON(mode.bpp_specified);
+
+       FAIL_ON(mode.tv_margins.right != 14);
+       FAIL_ON(mode.tv_margins.left != 24);
+       FAIL_ON(mode.tv_margins.bottom != 36);
+       FAIL_ON(mode.tv_margins.top != 42);
+
+       FAIL_ON(mode.rb);
+       FAIL_ON(mode.cvt);
+       FAIL_ON(mode.interlace);
+       FAIL_ON(mode.margins);
+       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
+
+       return 0;
+}
+
+static int drm_cmdline_test_freestanding_force_e_and_options(void *ignored)
+{
+       struct drm_cmdline_mode mode = { };
+
+       FAIL_ON(!drm_mode_parse_command_line_for_connector("e,margin_right=14,margin_left=24,margin_bottom=36,margin_top=42",
+                                                          &no_connector,
+                                                          &mode));
+       FAIL_ON(mode.specified);
+       FAIL_ON(mode.refresh_specified);
+       FAIL_ON(mode.bpp_specified);
+
+       FAIL_ON(mode.tv_margins.right != 14);
+       FAIL_ON(mode.tv_margins.left != 24);
+       FAIL_ON(mode.tv_margins.bottom != 36);
+       FAIL_ON(mode.tv_margins.top != 42);
+
+       FAIL_ON(mode.rb);
+       FAIL_ON(mode.cvt);
+       FAIL_ON(mode.interlace);
+       FAIL_ON(mode.margins);
+       FAIL_ON(mode.force != DRM_FORCE_ON);
+
+       return 0;
+}
+
+static int drm_cmdline_test_panel_orientation(void *ignored)
+{
+       struct drm_cmdline_mode mode = { };
+
+       FAIL_ON(!drm_mode_parse_command_line_for_connector("panel_orientation=upside_down",
+                                                          &no_connector,
+                                                          &mode));
+       FAIL_ON(mode.specified);
+       FAIL_ON(mode.refresh_specified);
+       FAIL_ON(mode.bpp_specified);
+
+       FAIL_ON(mode.panel_orientation != DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP);
+
+       FAIL_ON(mode.rb);
+       FAIL_ON(mode.cvt);
+       FAIL_ON(mode.interlace);
+       FAIL_ON(mode.margins);
+       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
+
+       return 0;
+}
+
 #include "drm_selftest.c"
 
 static int __init test_drm_cmdline_init(void)
index 514efef..4b16563 100644 (file)
@@ -309,11 +309,24 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
        return 0;
 }
 
+static int
+dw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps,
+                          struct dw_mipi_dsi_dphy_timing *timing)
+{
+       timing->clk_hs2lp = 0x40;
+       timing->clk_lp2hs = 0x40;
+       timing->data_hs2lp = 0x40;
+       timing->data_lp2hs = 0x40;
+
+       return 0;
+}
+
 static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_stm_phy_ops = {
        .init = dw_mipi_dsi_phy_init,
        .power_on = dw_mipi_dsi_phy_power_on,
        .power_off = dw_mipi_dsi_phy_power_off,
        .get_lane_mbps = dw_mipi_dsi_get_lane_mbps,
+       .get_timing = dw_mipi_dsi_phy_get_timing,
 };
 
 static struct dw_mipi_dsi_plat_data dw_mipi_dsi_stm_plat_data = {
index 5b51298..c2815e8 100644 (file)
@@ -437,9 +437,6 @@ static void ltdc_crtc_atomic_enable(struct drm_crtc *crtc,
        /* Commit shadow registers = update planes at next vblank */
        reg_set(ldev->regs, LTDC_SRCR, SRCR_VBR);
 
-       /* Enable LTDC */
-       reg_set(ldev->regs, LTDC_GCR, GCR_LTDCEN);
-
        drm_crtc_vblank_on(crtc);
 }
 
@@ -453,9 +450,6 @@ static void ltdc_crtc_atomic_disable(struct drm_crtc *crtc,
 
        drm_crtc_vblank_off(crtc);
 
-       /* disable LTDC */
-       reg_clear(ldev->regs, LTDC_GCR, GCR_LTDCEN);
-
        /* disable IRQ */
        reg_clear(ldev->regs, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE);
 
@@ -1044,9 +1038,13 @@ static const struct drm_encoder_funcs ltdc_encoder_funcs = {
 static void ltdc_encoder_disable(struct drm_encoder *encoder)
 {
        struct drm_device *ddev = encoder->dev;
+       struct ltdc_device *ldev = ddev->dev_private;
 
        DRM_DEBUG_DRIVER("\n");
 
+       /* Disable LTDC */
+       reg_clear(ldev->regs, LTDC_GCR, GCR_LTDCEN);
+
        /* Set to sleep state the pinctrl whatever type of encoder */
        pinctrl_pm_select_sleep_state(ddev->dev);
 }
@@ -1054,6 +1052,19 @@ static void ltdc_encoder_disable(struct drm_encoder *encoder)
 static void ltdc_encoder_enable(struct drm_encoder *encoder)
 {
        struct drm_device *ddev = encoder->dev;
+       struct ltdc_device *ldev = ddev->dev_private;
+
+       DRM_DEBUG_DRIVER("\n");
+
+       /* Enable LTDC */
+       reg_set(ldev->regs, LTDC_GCR, GCR_LTDCEN);
+}
+
+static void ltdc_encoder_mode_set(struct drm_encoder *encoder,
+                                 struct drm_display_mode *mode,
+                                 struct drm_display_mode *adjusted_mode)
+{
+       struct drm_device *ddev = encoder->dev;
 
        DRM_DEBUG_DRIVER("\n");
 
@@ -1069,6 +1080,7 @@ static void ltdc_encoder_enable(struct drm_encoder *encoder)
 static const struct drm_encoder_helper_funcs ltdc_encoder_helper_funcs = {
        .disable = ltdc_encoder_disable,
        .enable = ltdc_encoder_enable,
+       .mode_set = ltdc_encoder_mode_set,
 };
 
 static int ltdc_encoder_init(struct drm_device *ddev, struct drm_bridge *bridge)
index a5757b1..5ae67d5 100644 (file)
@@ -346,6 +346,27 @@ static int sun4i_drv_add_endpoints(struct device *dev,
        return count;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int sun4i_drv_drm_sys_suspend(struct device *dev)
+{
+       struct drm_device *drm = dev_get_drvdata(dev);
+
+       return drm_mode_config_helper_suspend(drm);
+}
+
+static int sun4i_drv_drm_sys_resume(struct device *dev)
+{
+       struct drm_device *drm = dev_get_drvdata(dev);
+
+       return drm_mode_config_helper_resume(drm);
+}
+#endif
+
+static const struct dev_pm_ops sun4i_drv_drm_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(sun4i_drv_drm_sys_suspend,
+                               sun4i_drv_drm_sys_resume)
+};
+
 static int sun4i_drv_probe(struct platform_device *pdev)
 {
        struct component_match *match = NULL;
@@ -418,6 +439,7 @@ static struct platform_driver sun4i_drv_platform_driver = {
        .driver         = {
                .name           = "sun4i-drm",
                .of_match_table = sun4i_drv_of_table,
+               .pm = &sun4i_drv_drm_pm_ops,
        },
 };
 module_platform_driver(sun4i_drv_platform_driver);
index 4e8f634..a75fcb1 100644 (file)
@@ -1081,6 +1081,7 @@ static const struct component_ops sun6i_dsi_ops = {
 static int sun6i_dsi_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
+       const char *bus_clk_name = NULL;
        struct sun6i_dsi *dsi;
        struct resource *res;
        void __iomem *base;
@@ -1094,6 +1095,10 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
        dsi->host.ops = &sun6i_dsi_host_ops;
        dsi->host.dev = dev;
 
+       if (of_device_is_compatible(dev->of_node,
+                                   "allwinner,sun6i-a31-mipi-dsi"))
+               bus_clk_name = "bus";
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        base = devm_ioremap_resource(dev, res);
        if (IS_ERR(base)) {
@@ -1107,23 +1112,36 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
                return PTR_ERR(dsi->regulator);
        }
 
-       dsi->regs = devm_regmap_init_mmio_clk(dev, "bus", base,
-                                             &sun6i_dsi_regmap_config);
-       if (IS_ERR(dsi->regs)) {
-               dev_err(dev, "Couldn't create the DSI encoder regmap\n");
-               return PTR_ERR(dsi->regs);
-       }
-
        dsi->reset = devm_reset_control_get_shared(dev, NULL);
        if (IS_ERR(dsi->reset)) {
                dev_err(dev, "Couldn't get our reset line\n");
                return PTR_ERR(dsi->reset);
        }
 
-       dsi->mod_clk = devm_clk_get(dev, "mod");
-       if (IS_ERR(dsi->mod_clk)) {
-               dev_err(dev, "Couldn't get the DSI mod clock\n");
-               return PTR_ERR(dsi->mod_clk);
+       dsi->regs = devm_regmap_init_mmio(dev, base, &sun6i_dsi_regmap_config);
+       if (IS_ERR(dsi->regs)) {
+               dev_err(dev, "Couldn't init regmap\n");
+               return PTR_ERR(dsi->regs);
+       }
+
+       dsi->bus_clk = devm_clk_get(dev, bus_clk_name);
+       if (IS_ERR(dsi->bus_clk)) {
+               dev_err(dev, "Couldn't get the DSI bus clock\n");
+               return PTR_ERR(dsi->bus_clk);
+       }
+
+       ret = regmap_mmio_attach_clk(dsi->regs, dsi->bus_clk);
+       if (ret)
+               return ret;
+
+       if (of_device_is_compatible(dev->of_node,
+                                   "allwinner,sun6i-a31-mipi-dsi")) {
+               dsi->mod_clk = devm_clk_get(dev, "mod");
+               if (IS_ERR(dsi->mod_clk)) {
+                       dev_err(dev, "Couldn't get the DSI mod clock\n");
+                       ret = PTR_ERR(dsi->mod_clk);
+                       goto err_attach_clk;
+               }
        }
 
        /*
@@ -1161,6 +1179,9 @@ err_pm_disable:
        pm_runtime_disable(dev);
 err_unprotect_clk:
        clk_rate_exclusive_put(dsi->mod_clk);
+err_attach_clk:
+       if (!IS_ERR(dsi->bus_clk))
+               regmap_mmio_detach_clk(dsi->regs);
        return ret;
 }
 
@@ -1174,6 +1195,9 @@ static int sun6i_dsi_remove(struct platform_device *pdev)
        pm_runtime_disable(dev);
        clk_rate_exclusive_put(dsi->mod_clk);
 
+       if (!IS_ERR(dsi->bus_clk))
+               regmap_mmio_detach_clk(dsi->regs);
+
        return 0;
 }
 
@@ -1232,6 +1256,7 @@ static const struct dev_pm_ops sun6i_dsi_pm_ops = {
 
 static const struct of_device_id sun6i_dsi_of_table[] = {
        { .compatible = "allwinner,sun6i-a31-mipi-dsi" },
+       { .compatible = "allwinner,sun50i-a64-mipi-dsi" },
        { }
 };
 MODULE_DEVICE_TABLE(of, sun6i_dsi_of_table);
index 7a06cb6..e1cfc3c 100644 (file)
@@ -568,7 +568,7 @@ vc4_unlock_bo_reservations(struct drm_device *dev,
        for (i = 0; i < exec->bo_count; i++) {
                struct drm_gem_object *bo = &exec->bo[i]->base;
 
-               ww_mutex_unlock(&bo->resv->lock);
+               dma_resv_unlock(bo->resv);
        }
 
        ww_acquire_fini(acquire_ctx);
@@ -595,8 +595,7 @@ vc4_lock_bo_reservations(struct drm_device *dev,
 retry:
        if (contended_lock != -1) {
                bo = &exec->bo[contended_lock]->base;
-               ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
-                                                      acquire_ctx);
+               ret = dma_resv_lock_slow_interruptible(bo->resv, acquire_ctx);
                if (ret) {
                        ww_acquire_done(acquire_ctx);
                        return ret;
@@ -609,19 +608,19 @@ retry:
 
                bo = &exec->bo[i]->base;
 
-               ret = ww_mutex_lock_interruptible(&bo->resv->lock, acquire_ctx);
+               ret = dma_resv_lock_interruptible(bo->resv, acquire_ctx);
                if (ret) {
                        int j;
 
                        for (j = 0; j < i; j++) {
                                bo = &exec->bo[j]->base;
-                               ww_mutex_unlock(&bo->resv->lock);
+                               dma_resv_unlock(bo->resv);
                        }
 
                        if (contended_lock != -1 && contended_lock >= i) {
                                bo = &exec->bo[contended_lock]->base;
 
-                               ww_mutex_unlock(&bo->resv->lock);
+                               dma_resv_unlock(bo->resv);
                        }
 
                        if (ret == -EDEADLK) {
index e622485..0966208 100644 (file)
@@ -43,6 +43,9 @@
 #define XRES_MAX  8192
 #define YRES_MAX  8192
 
+#define drm_connector_to_virtio_gpu_output(x) \
+       container_of(x, struct virtio_gpu_output, conn)
+
 static const struct drm_crtc_funcs virtio_gpu_crtc_funcs = {
        .set_config             = drm_atomic_helper_set_config,
        .destroy                = drm_crtc_cleanup,
@@ -59,7 +62,7 @@ static const struct drm_framebuffer_funcs virtio_gpu_fb_funcs = {
        .dirty = drm_atomic_helper_dirtyfb,
 };
 
-int
+static int
 virtio_gpu_framebuffer_init(struct drm_device *dev,
                            struct virtio_gpu_framebuffer *vgfb,
                            const struct drm_mode_fb_cmd2 *mode_cmd,
index eedae2a..7e69c06 100644 (file)
@@ -103,8 +103,6 @@ struct virtio_gpu_fence {
        struct virtio_gpu_fence_driver *drv;
        struct list_head node;
 };
-#define to_virtio_fence(x) \
-       container_of(x, struct virtio_gpu_fence, f)
 
 struct virtio_gpu_vbuffer {
        char *buf;
@@ -135,10 +133,6 @@ struct virtio_gpu_output {
 };
 #define drm_crtc_to_virtio_gpu_output(x) \
        container_of(x, struct virtio_gpu_output, crtc)
-#define drm_connector_to_virtio_gpu_output(x) \
-       container_of(x, struct virtio_gpu_output, conn)
-#define drm_encoder_to_virtio_gpu_output(x) \
-       container_of(x, struct virtio_gpu_output, enc)
 
 struct virtio_gpu_framebuffer {
        struct drm_framebuffer base;
@@ -183,6 +177,9 @@ struct virtio_gpu_device {
        struct kmem_cache *vbufs;
        bool vqs_ready;
 
+       bool disable_notify;
+       bool pending_notify;
+
        struct ida      resource_ida;
 
        wait_queue_head_t resp_wq;
@@ -335,11 +332,10 @@ void virtio_gpu_dequeue_ctrl_func(struct work_struct *work);
 void virtio_gpu_dequeue_cursor_func(struct work_struct *work);
 void virtio_gpu_dequeue_fence_func(struct work_struct *work);
 
+void virtio_gpu_disable_notify(struct virtio_gpu_device *vgdev);
+void virtio_gpu_enable_notify(struct virtio_gpu_device *vgdev);
+
 /* virtio_gpu_display.c */
-int virtio_gpu_framebuffer_init(struct drm_device *dev,
-                               struct virtio_gpu_framebuffer *vgfb,
-                               const struct drm_mode_fb_cmd2 *mode_cmd,
-                               struct drm_gem_object *obj);
 void virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev);
 void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev);
 
@@ -350,7 +346,6 @@ struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev,
                                        int index);
 
 /* virtio_gpu_fence.c */
-bool virtio_fence_signaled(struct dma_fence *f);
 struct virtio_gpu_fence *virtio_gpu_fence_alloc(
        struct virtio_gpu_device *vgdev);
 void virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,
@@ -366,18 +361,12 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
                             struct virtio_gpu_object_params *params,
                             struct virtio_gpu_object **bo_ptr,
                             struct virtio_gpu_fence *fence);
-
 /* virtgpu_prime.c */
 struct drm_gem_object *virtgpu_gem_prime_import_sg_table(
        struct drm_device *dev, struct dma_buf_attachment *attach,
        struct sg_table *sgt);
 
-static inline u64 virtio_gpu_object_mmap_offset(struct virtio_gpu_object *bo)
-{
-       return drm_vma_node_offset_addr(&bo->base.base.vma_node);
-}
-
-/* virgl debufs */
+/* virgl debugfs */
 int virtio_gpu_debugfs_init(struct drm_minor *minor);
 
 #endif
index a4b9881..5b2a414 100644 (file)
@@ -27,6 +27,9 @@
 
 #include "virtgpu_drv.h"
 
+#define to_virtio_fence(x) \
+       container_of(x, struct virtio_gpu_fence, f)
+
 static const char *virtio_get_driver_name(struct dma_fence *f)
 {
        return "virtio_gpu";
@@ -37,7 +40,7 @@ static const char *virtio_get_timeline_name(struct dma_fence *f)
        return "controlq";
 }
 
-bool virtio_fence_signaled(struct dma_fence *f)
+static bool virtio_fence_signaled(struct dma_fence *f)
 {
        struct virtio_gpu_fence *fence = to_virtio_fence(f);
 
index 4c1f579..0a2b622 100644 (file)
@@ -96,14 +96,12 @@ int virtio_gpu_mode_dumb_mmap(struct drm_file *file_priv,
                              uint32_t handle, uint64_t *offset_p)
 {
        struct drm_gem_object *gobj;
-       struct virtio_gpu_object *obj;
 
        BUG_ON(!offset_p);
        gobj = drm_gem_object_lookup(file_priv, handle);
        if (gobj == NULL)
                return -ENOENT;
-       obj = gem_to_virtio_gpu_obj(gobj);
-       *offset_p = virtio_gpu_object_mmap_offset(obj);
+       *offset_p = drm_vma_node_offset_addr(&gobj->vma_node);
        drm_gem_object_put_unlocked(gobj);
        return 0;
 }
index bc4bc44..ac42c84 100644 (file)
@@ -24,6 +24,7 @@
  */
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_damage_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_plane_helper.h>
 
@@ -88,7 +89,7 @@ static int virtio_gpu_plane_atomic_check(struct drm_plane *plane,
        struct drm_crtc_state *crtc_state;
        int ret;
 
-       if (!state->fb || !state->crtc)
+       if (!state->fb || WARN_ON(!state->crtc))
                return 0;
 
        crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
@@ -103,22 +104,26 @@ static int virtio_gpu_plane_atomic_check(struct drm_plane *plane,
 }
 
 static void virtio_gpu_update_dumb_bo(struct virtio_gpu_device *vgdev,
-                                     struct virtio_gpu_object *bo,
-                                     struct drm_plane_state *state)
+                                     struct drm_plane_state *state,
+                                     struct drm_rect *rect)
 {
+       struct virtio_gpu_object *bo =
+               gem_to_virtio_gpu_obj(state->fb->obj[0]);
        struct virtio_gpu_object_array *objs;
+       uint32_t w = rect->x2 - rect->x1;
+       uint32_t h = rect->y2 - rect->y1;
+       uint32_t x = rect->x1;
+       uint32_t y = rect->y1;
+       uint32_t off = x * state->fb->format->cpp[0] +
+               y * state->fb->pitches[0];
 
        objs = virtio_gpu_array_alloc(1);
        if (!objs)
                return;
        virtio_gpu_array_add_obj(objs, &bo->base.base);
-       virtio_gpu_cmd_transfer_to_host_2d
-               (vgdev, 0,
-                state->src_w >> 16,
-                state->src_h >> 16,
-                state->src_x >> 16,
-                state->src_y >> 16,
-                objs, NULL);
+
+       virtio_gpu_cmd_transfer_to_host_2d(vgdev, off, w, h, x, y,
+                                          objs, NULL);
 }
 
 static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
@@ -127,8 +132,8 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
        struct drm_device *dev = plane->dev;
        struct virtio_gpu_device *vgdev = dev->dev_private;
        struct virtio_gpu_output *output = NULL;
-       struct virtio_gpu_framebuffer *vgfb;
        struct virtio_gpu_object *bo;
+       struct drm_rect rect;
 
        if (plane->state->crtc)
                output = drm_crtc_to_virtio_gpu_output(plane->state->crtc);
@@ -146,30 +151,43 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
                return;
        }
 
-       vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
-       bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]);
+       if (!drm_atomic_helper_damage_merged(old_state, plane->state, &rect))
+               return;
+
+       virtio_gpu_disable_notify(vgdev);
+
+       bo = gem_to_virtio_gpu_obj(plane->state->fb->obj[0]);
        if (bo->dumb)
-               virtio_gpu_update_dumb_bo(vgdev, bo, plane->state);
-
-       DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n",
-                 bo->hw_res_handle,
-                 plane->state->crtc_w, plane->state->crtc_h,
-                 plane->state->crtc_x, plane->state->crtc_y,
-                 plane->state->src_w >> 16,
-                 plane->state->src_h >> 16,
-                 plane->state->src_x >> 16,
-                 plane->state->src_y >> 16);
-       virtio_gpu_cmd_set_scanout(vgdev, output->index,
-                                  bo->hw_res_handle,
-                                  plane->state->src_w >> 16,
-                                  plane->state->src_h >> 16,
-                                  plane->state->src_x >> 16,
-                                  plane->state->src_y >> 16);
+               virtio_gpu_update_dumb_bo(vgdev, plane->state, &rect);
+
+       if (plane->state->fb != old_state->fb ||
+           plane->state->src_w != old_state->src_w ||
+           plane->state->src_h != old_state->src_h ||
+           plane->state->src_x != old_state->src_x ||
+           plane->state->src_y != old_state->src_y) {
+               DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n",
+                         bo->hw_res_handle,
+                         plane->state->crtc_w, plane->state->crtc_h,
+                         plane->state->crtc_x, plane->state->crtc_y,
+                         plane->state->src_w >> 16,
+                         plane->state->src_h >> 16,
+                         plane->state->src_x >> 16,
+                         plane->state->src_y >> 16);
+               virtio_gpu_cmd_set_scanout(vgdev, output->index,
+                                          bo->hw_res_handle,
+                                          plane->state->src_w >> 16,
+                                          plane->state->src_h >> 16,
+                                          plane->state->src_x >> 16,
+                                          plane->state->src_y >> 16);
+       }
+
        virtio_gpu_cmd_resource_flush(vgdev, bo->hw_res_handle,
-                                     plane->state->src_x >> 16,
-                                     plane->state->src_y >> 16,
-                                     plane->state->src_w >> 16,
-                                     plane->state->src_h >> 16);
+                                     rect.x1,
+                                     rect.y1,
+                                     rect.x2 - rect.x1,
+                                     rect.y2 - rect.y1);
+
+       virtio_gpu_enable_notify(vgdev);
 }
 
 static int virtio_gpu_cursor_prepare_fb(struct drm_plane *plane,
index 9274c40..5914e79 100644 (file)
@@ -404,8 +404,12 @@ again:
        }
        notify = virtio_gpu_queue_ctrl_buffer_locked(vgdev, vbuf, vout);
        spin_unlock(&vgdev->ctrlq.qlock);
-       if (notify)
-               virtqueue_notify(vgdev->ctrlq.vq);
+       if (notify) {
+               if (vgdev->disable_notify)
+                       vgdev->pending_notify = true;
+               else
+                       virtqueue_notify(vgdev->ctrlq.vq);
+       }
 
        if (sgt) {
                sg_free_table(sgt);
@@ -413,6 +417,21 @@ again:
        }
 }
 
+void virtio_gpu_disable_notify(struct virtio_gpu_device *vgdev)
+{
+       vgdev->disable_notify = true;
+}
+
+void virtio_gpu_enable_notify(struct virtio_gpu_device *vgdev)
+{
+       vgdev->disable_notify = false;
+
+       if (!vgdev->pending_notify)
+               return;
+       vgdev->pending_notify = false;
+       virtqueue_notify(vgdev->ctrlq.vq);
+}
+
 static void virtio_gpu_queue_ctrl_buffer(struct virtio_gpu_device *vgdev,
                                         struct virtio_gpu_vbuffer *vbuf)
 {
index 94cc64a..b0e390b 100644 (file)
@@ -19,6 +19,13 @@ struct dw_mipi_dsi;
 struct mipi_dsi_device;
 struct platform_device;
 
+struct dw_mipi_dsi_dphy_timing {
+       u16 data_hs2lp;
+       u16 data_lp2hs;
+       u16 clk_hs2lp;
+       u16 clk_lp2hs;
+};
+
 struct dw_mipi_dsi_phy_ops {
        int (*init)(void *priv_data);
        void (*power_on)(void *priv_data);
@@ -27,6 +34,8 @@ struct dw_mipi_dsi_phy_ops {
                             const struct drm_display_mode *mode,
                             unsigned long mode_flags, u32 lanes, u32 format,
                             unsigned int *lane_mbps);
+       int (*get_timing)(void *priv_data, unsigned int lane_mbps,
+                         struct dw_mipi_dsi_dphy_timing *timing);
 };
 
 struct dw_mipi_dsi_host_ops {
index 5923819..951dfb1 100644 (file)
@@ -35,7 +35,7 @@
  * struct drm_crtc_commit - track modeset commits on a CRTC
  *
  * This structure is used to track pending modeset changes and atomic commit on
- * a per-CRTC basis. Since updating the list should never block this structure
+ * a per-CRTC basis. Since updating the list should never block, this structure
  * is reference counted to allow waiters to safely wait on an event to complete,
  * without holding any locks.
  *
@@ -363,7 +363,7 @@ struct drm_atomic_state {
         * When a connector or plane is not bound to any CRTC, it's still important
         * to preserve linearity to prevent the atomic states from being freed to early.
         *
-        * This commit (if set) is not bound to any crtc, but will be completed when
+        * This commit (if set) is not bound to any CRTC, but will be completed when
         * drm_atomic_helper_commit_hw_done() is called.
         */
        struct drm_crtc_commit *fake_commit;
@@ -476,12 +476,12 @@ drm_atomic_get_new_connector_for_encoder(struct drm_atomic_state *state,
                                         struct drm_encoder *encoder);
 
 /**
- * drm_atomic_get_existing_crtc_state - get crtc state, if it exists
+ * drm_atomic_get_existing_crtc_state - get CRTC state, if it exists
  * @state: global atomic state object
- * @crtc: crtc to grab
+ * @crtc: CRTC to grab
  *
- * This function returns the crtc state for the given crtc, or NULL
- * if the crtc is not part of the global atomic state.
+ * This function returns the CRTC state for the given CRTC, or NULL
+ * if the CRTC is not part of the global atomic state.
  *
  * This function is deprecated, @drm_atomic_get_old_crtc_state or
  * @drm_atomic_get_new_crtc_state should be used instead.
@@ -494,12 +494,12 @@ drm_atomic_get_existing_crtc_state(struct drm_atomic_state *state,
 }
 
 /**
- * drm_atomic_get_old_crtc_state - get old crtc state, if it exists
+ * drm_atomic_get_old_crtc_state - get old CRTC state, if it exists
  * @state: global atomic state object
- * @crtc: crtc to grab
+ * @crtc: CRTC to grab
  *
- * This function returns the old crtc state for the given crtc, or
- * NULL if the crtc is not part of the global atomic state.
+ * This function returns the old CRTC state for the given CRTC, or
+ * NULL if the CRTC is not part of the global atomic state.
  */
 static inline struct drm_crtc_state *
 drm_atomic_get_old_crtc_state(struct drm_atomic_state *state,
@@ -508,12 +508,12 @@ drm_atomic_get_old_crtc_state(struct drm_atomic_state *state,
        return state->crtcs[drm_crtc_index(crtc)].old_state;
 }
 /**
- * drm_atomic_get_new_crtc_state - get new crtc state, if it exists
+ * drm_atomic_get_new_crtc_state - get new CRTC state, if it exists
  * @state: global atomic state object
- * @crtc: crtc to grab
+ * @crtc: CRTC to grab
  *
- * This function returns the new crtc state for the given crtc, or
- * NULL if the crtc is not part of the global atomic state.
+ * This function returns the new CRTC state for the given CRTC, or
+ * NULL if the CRTC is not part of the global atomic state.
  */
 static inline struct drm_crtc_state *
 drm_atomic_get_new_crtc_state(struct drm_atomic_state *state,
@@ -978,11 +978,11 @@ drm_atomic_crtc_needs_modeset(const struct drm_crtc_state *state)
 }
 
 /**
- * drm_atomic_crtc_effectively_active - compute whether crtc is actually active
+ * drm_atomic_crtc_effectively_active - compute whether CRTC is actually active
  * @state: &drm_crtc_state for the CRTC
  *
  * When in self refresh mode, the crtc_state->active value will be false, since
- * the crtc is off. However in some cases we're interested in whether the crtc
+ * the CRTC is off. However in some cases we're interested in whether the CRTC
  * is active, or effectively active (ie: it's connected to an active display).
  * In these cases, use this function instead of just checking active.
  */
index bf4e071..9db3cac 100644 (file)
@@ -152,7 +152,7 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
 /**
  * drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC
  * @plane: the loop cursor
- * @crtc:  the crtc whose planes are iterated
+ * @crtc:  the CRTC whose planes are iterated
  *
  * This iterates over the current state, useful (for example) when applying
  * atomic state after it has been checked and swapped.  To iterate over the
@@ -166,7 +166,7 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
 /**
  * drm_crtc_atomic_state_for_each_plane - iterate over attached planes in new state
  * @plane: the loop cursor
- * @crtc_state: the incoming crtc-state
+ * @crtc_state: the incoming CRTC state
  *
  * Similar to drm_crtc_for_each_plane(), but iterates the planes that will be
  * attached if the specified state is applied.  Useful during for example
@@ -180,7 +180,7 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
  * drm_crtc_atomic_state_for_each_plane_state - iterate over attached planes in new state
  * @plane: the loop cursor
  * @plane_state: loop cursor for the plane's state, must be const
- * @crtc_state: the incoming crtc-state
+ * @crtc_state: the incoming CRTC state
  *
  * Similar to drm_crtc_for_each_plane(), but iterates the planes that will be
  * attached if the specified state is applied.  Useful during for example
@@ -189,7 +189,7 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
  *
  * Compared to just drm_atomic_crtc_state_for_each_plane() this also fills in a
  * const plane_state. This is useful when a driver just wants to peek at other
- * active planes on this crtc, but does not need to change it.
+ * active planes on this CRTC, but does not need to change it.
  */
 #define drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, crtc_state) \
        drm_for_each_plane_mask(plane, (crtc_state)->state->dev, (crtc_state)->plane_mask) \
index 17b728d..2219109 100644 (file)
@@ -1070,6 +1070,14 @@ struct drm_cmdline_mode {
        unsigned int rotation_reflection;
 
        /**
+        * @panel_orientation:
+        *
+        * drm-connector "panel orientation" property override value,
+        * DRM_MODE_PANEL_ORIENTATION_UNKNOWN if not set.
+        */
+       enum drm_panel_orientation panel_orientation;
+
+       /**
         * @tv_margins: TV margins to apply to the mode.
         */
        struct drm_connector_tv_margins tv_margins;
index 5f27b69..121f7aa 100644 (file)
@@ -198,7 +198,7 @@ static inline struct drm_panel *of_drm_find_panel(const struct device_node *np)
 }
 #endif
 
-#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
+#if IS_REACHABLE(CONFIG_BACKLIGHT_CLASS_DEVICE)
 int drm_panel_of_backlight(struct drm_panel *panel);
 #else
 static inline int drm_panel_of_backlight(struct drm_panel *panel)
index 085a968..8f99d38 100644 (file)
@@ -322,6 +322,8 @@ static inline bool drm_debug_enabled(enum drm_debug_category category)
 
 /*
  * struct device based logging
+ *
+ * Prefer drm_device based logging over device or prink based logging.
  */
 
 __printf(3, 4)
@@ -418,7 +420,70 @@ void drm_dev_dbg(const struct device *dev, enum drm_debug_category category,
                                          fmt, ##__VA_ARGS__)
 
 /*
+ * struct drm_device based logging
+ *
+ * Prefer drm_device based logging over device or prink based logging.
+ */
+
+/* Helper for struct drm_device based logging. */
+#define __drm_printk(drm, level, type, fmt, ...)                       \
+       dev_##level##type((drm)->dev, "[drm] " fmt, ##__VA_ARGS__)
+
+
+#define drm_info(drm, fmt, ...)                                        \
+       __drm_printk((drm), info,, fmt, ##__VA_ARGS__)
+
+#define drm_notice(drm, fmt, ...)                              \
+       __drm_printk((drm), notice,, fmt, ##__VA_ARGS__)
+
+#define drm_warn(drm, fmt, ...)                                        \
+       __drm_printk((drm), warn,, fmt, ##__VA_ARGS__)
+
+#define drm_err(drm, fmt, ...)                                 \
+       __drm_printk((drm), err,, "*ERROR* " fmt, ##__VA_ARGS__)
+
+
+#define drm_info_once(drm, fmt, ...)                           \
+       __drm_printk((drm), info, _once, fmt, ##__VA_ARGS__)
+
+#define drm_notice_once(drm, fmt, ...)                         \
+       __drm_printk((drm), notice, _once, fmt, ##__VA_ARGS__)
+
+#define drm_warn_once(drm, fmt, ...)                           \
+       __drm_printk((drm), warn, _once, fmt, ##__VA_ARGS__)
+
+#define drm_err_once(drm, fmt, ...)                            \
+       __drm_printk((drm), err, _once, "*ERROR* " fmt, ##__VA_ARGS__)
+
+
+#define drm_err_ratelimited(drm, fmt, ...)                             \
+       __drm_printk((drm), err, _ratelimited, "*ERROR* " fmt, ##__VA_ARGS__)
+
+
+#define drm_dbg_core(drm, fmt, ...)                                    \
+       drm_dev_dbg((drm)->dev, DRM_UT_CORE, fmt, ##__VA_ARGS__)
+#define drm_dbg(drm, fmt, ...)                                         \
+       drm_dev_dbg((drm)->dev, DRM_UT_DRIVER, fmt, ##__VA_ARGS__)
+#define drm_dbg_kms(drm, fmt, ...)                                     \
+       drm_dev_dbg((drm)->dev, DRM_UT_KMS, fmt, ##__VA_ARGS__)
+#define drm_dbg_prime(drm, fmt, ...)                                   \
+       drm_dev_dbg((drm)->dev, DRM_UT_PRIME, fmt, ##__VA_ARGS__)
+#define drm_dbg_atomic(drm, fmt, ...)                                  \
+       drm_dev_dbg((drm)->dev, DRM_UT_ATOMIC, fmt, ##__VA_ARGS__)
+#define drm_dbg_vbl(drm, fmt, ...)                                     \
+       drm_dev_dbg((drm)->dev, DRM_UT_VBL, fmt, ##__VA_ARGS__)
+#define drm_dbg_state(drm, fmt, ...)                                   \
+       drm_dev_dbg((drm)->dev, DRM_UT_STATE, fmt, ##__VA_ARGS__)
+#define drm_dbg_lease(drm, fmt, ...)                                   \
+       drm_dev_dbg((drm)->dev, DRM_UT_LEASE, fmt, ##__VA_ARGS__)
+#define drm_dbg_dp(drm, fmt, ...)                                      \
+       drm_dev_dbg((drm)->dev, DRM_UT_DP, fmt, ##__VA_ARGS__)
+
+
+/*
  * printk based logging
+ *
+ * Prefer drm_device based logging over device or prink based logging.
  */
 
 __printf(2, 3)
index 73e7f66..6f84fa0 100644 (file)
@@ -42,12 +42,12 @@ struct dma_heap_allocation_data {
 #define DMA_HEAP_IOC_MAGIC             'H'
 
 /**
- * DOC: DMA_HEAP_IOC_ALLOC - allocate memory from pool
+ * DOC: DMA_HEAP_IOCTL_ALLOC - allocate memory from pool
  *
  * Takes a dma_heap_allocation_data struct and returns it with the fd field
  * populated with the dmabuf handle of the allocation.
  */
-#define DMA_HEAP_IOC_ALLOC     _IOWR(DMA_HEAP_IOC_MAGIC, 0x0,\
+#define DMA_HEAP_IOCTL_ALLOC   _IOWR(DMA_HEAP_IOC_MAGIC, 0x0,\
                                      struct dma_heap_allocation_data)
 
 #endif /* _UAPI_LINUX_DMABUF_POOL_H */
index 3e53ad3..cd5e1f6 100644 (file)
@@ -116,7 +116,7 @@ static int dmabuf_heap_alloc_fdflags(int fd, size_t len, unsigned int fd_flags,
        if (!dmabuf_fd)
                return -EINVAL;
 
-       ret = ioctl(fd, DMA_HEAP_IOC_ALLOC, &data);
+       ret = ioctl(fd, DMA_HEAP_IOCTL_ALLOC, &data);
        if (ret < 0)
                return ret;
        *dmabuf_fd = (int)data.fd;