Merge tag 'drm-misc-next-2023-01-12' of git://anongit.freedesktop.org/drm/drm-misc...
authorDave Airlie <airlied@redhat.com>
Mon, 16 Jan 2023 05:33:22 +0000 (15:33 +1000)
committerDave Airlie <airlied@redhat.com>
Mon, 16 Jan 2023 05:33:28 +0000 (15:33 +1000)
drm-misc-next for v6.3:

UAPI Changes:

 * fourcc: Document Open Source user waiver

Cross-subsystem Changes:

 * firmware: fix color-format selection for system framebuffers

Core Changes:

 * format-helper: Add conversion from XRGB8888 to various sysfb formats;
   Make XRGB8888 the only driver-emulated legacy format

 * fb-helper: Avoid blank consoles from selecting an incorrect color format

 * probe-helper: Enable/disable HPD on connectors plus driver updates

 * Use drm_dbg_ helpers in several places

 * docs: Document defaults for CRTC backgrounds; Document use of drm_minor

Driver Changes:

 * arm/hdlcd: Use new debugfs helpers

 * gud: Use new debugfs helpers

 * panel: Support Visionox VTDR6130 AMOLED DSI; Support Himax HX8394; Convert
   many drivers to common generic DSI write-sequence helper

 * v3d: Do not opencode drm_gem_object_lookup()

 * vc4: Various HVS an CRTC fixes

 * vkms: Fix SEGFAULT from incorrect GEM-buffer mapping

 * Convert various drivers to i2c probe_new()

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/Y8ADeSzZDj+tpibF@linux-uq9g
81 files changed:
Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/display/panel/visionox,vtdr6130.yaml [new file with mode: 0644]
Documentation/userspace-api/ioctl/ioctl-number.rst
MAINTAINERS
drivers/firmware/sysfb_simplefb.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/amd/amdgpu/Kconfig
drivers/gpu/drm/arm/hdlcd_drv.c
drivers/gpu/drm/ast/Kconfig
drivers/gpu/drm/bridge/panel.c
drivers/gpu/drm/drm_blend.c
drivers/gpu/drm/drm_bridge_connector.c
drivers/gpu/drm/drm_debugfs.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_file.c
drivers/gpu/drm/drm_format_helper.c
drivers/gpu/drm/drm_gem_dma_helper.c
drivers/gpu/drm/drm_gem_shmem_helper.c
drivers/gpu/drm/drm_ioc32.c
drivers/gpu/drm/drm_ioctl.c
drivers/gpu/drm/drm_lease.c
drivers/gpu/drm/drm_plane.c
drivers/gpu/drm/drm_probe_helper.c
drivers/gpu/drm/gma500/Kconfig
drivers/gpu/drm/gud/gud_drv.c
drivers/gpu/drm/hisilicon/hibmc/Kconfig
drivers/gpu/drm/i2c/ch7006_drv.c
drivers/gpu/drm/i2c/sil164_drv.c
drivers/gpu/drm/i2c/tda9950.c
drivers/gpu/drm/i2c/tda998x_drv.c
drivers/gpu/drm/i915/Kconfig
drivers/gpu/drm/imx/dcss/dcss-dev.c
drivers/gpu/drm/imx/dcss/dcss-drv.c
drivers/gpu/drm/imx/dcss/dcss-kms.c
drivers/gpu/drm/meson/meson_dw_hdmi.c
drivers/gpu/drm/mgag200/Kconfig
drivers/gpu/drm/msm/hdmi/hdmi.c
drivers/gpu/drm/mxsfb/mxsfb_drv.c
drivers/gpu/drm/nouveau/Kconfig
drivers/gpu/drm/omapdrm/omap_drv.c
drivers/gpu/drm/panel/Kconfig
drivers/gpu/drm/panel/Makefile
drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c
drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c
drivers/gpu/drm/panel/panel-edp.c
drivers/gpu/drm/panel/panel-elida-kd35t133.c
drivers/gpu/drm/panel/panel-himax-hx8394.c [new file with mode: 0644]
drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c
drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c
drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c
drivers/gpu/drm/panel/panel-novatek-nt35950.c
drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c
drivers/gpu/drm/panel/panel-samsung-sofef00.c
drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c
drivers/gpu/drm/panel/panel-sitronix-st7703.c
drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c
drivers/gpu/drm/panel/panel-visionox-vtdr6130.c [new file with mode: 0644]
drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c
drivers/gpu/drm/radeon/Kconfig
drivers/gpu/drm/tests/drm_format_helper_test.c
drivers/gpu/drm/tiny/ofdrm.c
drivers/gpu/drm/tiny/simpledrm.c
drivers/gpu/drm/v3d/v3d_gem.c
drivers/gpu/drm/vc4/vc4_crtc.c
drivers/gpu/drm/vc4/vc4_dsi.c
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/gpu/drm/vc4/vc4_hvs.c
drivers/gpu/drm/vc4/vc4_kms.c
drivers/gpu/drm/vc4/vc4_plane.c
drivers/gpu/drm/vc4/vc4_regs.h
drivers/gpu/drm/vc4/vc4_vec.c
drivers/gpu/drm/vkms/vkms_plane.c
include/drm/drm_bridge_connector.h
include/drm/drm_debugfs.h
include/drm/drm_device.h
include/drm/drm_format_helper.h
include/drm/drm_mipi_dsi.h
include/drm/drm_modeset_helper_vtables.h
include/uapi/drm/drm_fourcc.h

diff --git a/Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml b/Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml
new file mode 100644 (file)
index 0000000..1b2a1ba
--- /dev/null
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/himax,hx8394.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Himax HX8394 MIPI-DSI LCD panel controller
+
+maintainers:
+  - Ondrej Jirman <megi@xff.cz>
+  - Javier Martinez Canillas <javierm@redhat.com>
+
+description:
+  Device tree bindings for panels based on the Himax HX8394 controller,
+  such as the HannStar HSD060BHW4 720x1440 TFT LCD panel connected with
+  a MIPI-DSI video interface.
+
+allOf:
+  - $ref: panel-common.yaml#
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - hannstar,hsd060bhw4
+      - const: himax,hx8394
+
+  reg: true
+
+  reset-gpios: true
+
+  backlight: true
+
+  port: true
+
+  vcc-supply:
+    description: Panel power supply
+
+  iovcc-supply:
+    description: I/O voltage supply
+
+required:
+  - compatible
+  - reg
+  - reset-gpios
+  - backlight
+  - port
+  - vcc-supply
+  - iovcc-supply
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    dsi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        panel@0 {
+            compatible = "hannstar,hsd060bhw4", "himax,hx8394";
+            reg = <0>;
+            vcc-supply = <&reg_2v8_p>;
+            iovcc-supply = <&reg_1v8_p>;
+            reset-gpios = <&gpio3 13 GPIO_ACTIVE_LOW>;
+            backlight = <&backlight>;
+
+            port {
+                mipi_in_panel: endpoint {
+                    remote-endpoint = <&mipi_out_panel>;
+                };
+            };
+        };
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/display/panel/visionox,vtdr6130.yaml b/Documentation/devicetree/bindings/display/panel/visionox,vtdr6130.yaml
new file mode 100644 (file)
index 0000000..49e2fd4
--- /dev/null
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/visionox,vtdr6130.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Visionox VTDR6130 AMOLED DSI Panel
+
+maintainers:
+  - Neil Armstrong <neil.armstrong@linaro.org>
+
+allOf:
+  - $ref: panel-common.yaml#
+
+properties:
+  compatible:
+    const: visionox,vtdr6130
+
+  vddio-supply: true
+  vci-supply: true
+  vdd-supply: true
+  port: true
+  reset-gpios: true
+
+additionalProperties: false
+
+required:
+  - compatible
+  - vddio-supply
+  - vci-supply
+  - vdd-supply
+  - reset-gpios
+  - port
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    panel {
+        compatible = "visionox,vtdr6130";
+
+        vddio-supply = <&vreg_l12b_1p8>;
+        vci-supply = <&vreg_l13b_3p0>;
+        vdd-supply = <&vreg_l11b_1p2>;
+
+        reset-gpios = <&tlmm 133 GPIO_ACTIVE_LOW>;
+
+        port {
+            panel0_in: endpoint {
+                remote-endpoint = <&dsi0_out>;
+            };
+        };
+    };
+...
index eb045fc..e48101c 100644 (file)
@@ -222,6 +222,7 @@ Code  Seq#    Include File                                           Comments
 'a'   00-0F  drivers/crypto/qat/qat_common/adf_cfg_common.h          conflict! qat driver
 'b'   00-FF                                                          conflict! bit3 vme host bridge
                                                                      <mailto:natalia@nikhefk.nikhef.nl>
+'b'   00-0F  linux/dma-buf.h                                         conflict!
 'c'   all    linux/cm4000_cs.h                                       conflict!
 'c'   00-7F  linux/comstats.h                                        conflict!
 'c'   00-7F  linux/coda.h                                            conflict!
index a47d963..7fc9e31 100644 (file)
@@ -6550,6 +6550,14 @@ S:       Maintained
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 F:     drivers/gpu/drm/tiny/gm12u320.c
 
+DRM DRIVER FOR HIMAX HX8394 MIPI-DSI LCD panels
+M:     Ondrej Jirman <megi@xff.cz>
+M:     Javier Martinez Canillas <javierm@redhat.com>
+S:     Maintained
+T:     git git://anongit.freedesktop.org/drm/drm-misc
+F:     Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml
+F:     drivers/gpu/drm/panel/panel-himax-hx8394.c
+
 DRM DRIVER FOR HX8357D PANELS
 M:     Emma Anholt <emma@anholt.net>
 S:     Maintained
@@ -7009,7 +7017,6 @@ M:        Xinliang Liu <xinliang.liu@linaro.org>
 M:     Tian Tao  <tiantao6@hisilicon.com>
 R:     John Stultz <jstultz@google.com>
 R:     Xinwei Kong <kong.kongxinwei@hisilicon.com>
-R:     Chen Feng <puck.chen@hisilicon.com>
 L:     dri-devel@lists.freedesktop.org
 S:     Maintained
 T:     git git://anongit.freedesktop.org/drm/drm-misc
index a353e27..ce9c007 100644 (file)
@@ -27,25 +27,56 @@ static const struct simplefb_format formats[] = SIMPLEFB_FORMATS;
 __init bool sysfb_parse_mode(const struct screen_info *si,
                             struct simplefb_platform_data *mode)
 {
-       const struct simplefb_format *f;
        __u8 type;
+       u32 bits_per_pixel;
        unsigned int i;
 
        type = si->orig_video_isVGA;
        if (type != VIDEO_TYPE_VLFB && type != VIDEO_TYPE_EFI)
                return false;
 
+       /*
+        * The meaning of depth and bpp for direct-color formats is
+        * inconsistent:
+        *
+        *  - DRM format info specifies depth as the number of color
+        *    bits; including alpha, but not including filler bits.
+        *  - Linux' EFI platform code computes lfb_depth from the
+        *    individual color channels, including the reserved bits.
+        *  - VBE 1.1 defines lfb_depth for XRGB1555 as 16, but later
+        *    versions use 15.
+        *  - On the kernel command line, 'bpp' of 32 is usually
+        *    XRGB8888 including the filler bits, but 15 is XRGB1555
+        *    not including the filler bit.
+        *
+        * It's not easily possible to fix this in struct screen_info,
+        * as this could break UAPI. The best solution is to compute
+        * bits_per_pixel here and ignore lfb_depth. In the loop below,
+        * ignore simplefb formats with alpha bits, as EFI and VESA
+        * don't specify alpha channels.
+        */
+       if (si->lfb_depth > 8) {
+               bits_per_pixel = max(max3(si->red_size + si->red_pos,
+                                         si->green_size + si->green_pos,
+                                         si->blue_size + si->blue_pos),
+                                    si->rsvd_size + si->rsvd_pos);
+       } else {
+               bits_per_pixel = si->lfb_depth;
+       }
+
        for (i = 0; i < ARRAY_SIZE(formats); ++i) {
-               f = &formats[i];
-               if (si->lfb_depth == f->bits_per_pixel &&
+               const struct simplefb_format *f = &formats[i];
+
+               if (f->transp.length)
+                       continue; /* transparent formats are unsupported by VESA/EFI */
+
+               if (bits_per_pixel == f->bits_per_pixel &&
                    si->red_size == f->red.length &&
                    si->red_pos == f->red.offset &&
                    si->green_size == f->green.length &&
                    si->green_pos == f->green.offset &&
                    si->blue_size == f->blue.length &&
-                   si->blue_pos == f->blue.offset &&
-                   si->rsvd_size == f->transp.length &&
-                   si->rsvd_pos == f->transp.offset) {
+                   si->blue_pos == f->blue.offset) {
                        mode->format = f->name;
                        mode->width = si->lfb_width;
                        mode->height = si->lfb_height;
index 9f019cd..748b93d 100644 (file)
@@ -12,7 +12,6 @@ menuconfig DRM
        select HDMI
        select FB_CMDLINE
        select I2C
-       select I2C_ALGOBIT
        select DMA_SHARED_BUFFER
        select SYNC_FILE
 # gallium uses SYS_kcmp for os_same_file_description() to de-duplicate
index 5fcd510..5341b6b 100644 (file)
@@ -13,6 +13,8 @@ config DRM_AMDGPU
        select DRM_TTM_HELPER
        select POWER_SUPPLY
        select HWMON
+       select I2C
+       select I2C_ALGOBIT
        select BACKLIGHT_CLASS_DEVICE
        select INTERVAL_TREE
        select DRM_BUDDY
index 7043d1c..e3507dd 100644 (file)
@@ -195,8 +195,8 @@ static int hdlcd_setup_mode_config(struct drm_device *drm)
 #ifdef CONFIG_DEBUG_FS
 static int hdlcd_show_underrun_count(struct seq_file *m, void *arg)
 {
-       struct drm_info_node *node = (struct drm_info_node *)m->private;
-       struct drm_device *drm = node->minor->dev;
+       struct drm_debugfs_entry *entry = m->private;
+       struct drm_device *drm = entry->dev;
        struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
 
        seq_printf(m, "underrun : %d\n", atomic_read(&hdlcd->buffer_underrun_count));
@@ -208,8 +208,8 @@ static int hdlcd_show_underrun_count(struct seq_file *m, void *arg)
 
 static int hdlcd_show_pxlclock(struct seq_file *m, void *arg)
 {
-       struct drm_info_node *node = (struct drm_info_node *)m->private;
-       struct drm_device *drm = node->minor->dev;
+       struct drm_debugfs_entry *entry = m->private;
+       struct drm_device *drm = entry->dev;
        struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
        unsigned long clkrate = clk_get_rate(hdlcd->clk);
        unsigned long mode_clock = hdlcd->crtc.mode.crtc_clock * 1000;
@@ -219,17 +219,10 @@ static int hdlcd_show_pxlclock(struct seq_file *m, void *arg)
        return 0;
 }
 
-static struct drm_info_list hdlcd_debugfs_list[] = {
+static struct drm_debugfs_info hdlcd_debugfs_list[] = {
        { "interrupt_count", hdlcd_show_underrun_count, 0 },
        { "clocks", hdlcd_show_pxlclock, 0 },
 };
-
-static void hdlcd_debugfs_init(struct drm_minor *minor)
-{
-       drm_debugfs_create_files(hdlcd_debugfs_list,
-                                ARRAY_SIZE(hdlcd_debugfs_list),
-                                minor->debugfs_root, minor);
-}
 #endif
 
 DEFINE_DRM_GEM_DMA_FOPS(fops);
@@ -237,9 +230,6 @@ DEFINE_DRM_GEM_DMA_FOPS(fops);
 static const struct drm_driver hdlcd_driver = {
        .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        DRM_GEM_DMA_DRIVER_OPS,
-#ifdef CONFIG_DEBUG_FS
-       .debugfs_init = hdlcd_debugfs_init,
-#endif
        .fops = &fops,
        .name = "hdlcd",
        .desc = "ARM HDLCD Controller DRM",
@@ -303,6 +293,10 @@ static int hdlcd_drm_bind(struct device *dev)
        drm_mode_config_reset(drm);
        drm_kms_helper_poll_init(drm);
 
+#ifdef CONFIG_DEBUG_FS
+       drm_debugfs_add_files(drm, hdlcd_debugfs_list, ARRAY_SIZE(hdlcd_debugfs_list));
+#endif
+
        ret = drm_dev_register(drm, 0);
        if (ret)
                goto err_register;
index d367a90..563fa7a 100644 (file)
@@ -4,6 +4,8 @@ config DRM_AST
        depends on DRM && PCI && MMU
        select DRM_GEM_SHMEM_HELPER
        select DRM_KMS_HELPER
+       select I2C
+       select I2C_ALGOBIT
        help
         Say yes for experimental AST GPU driver. Do not enable
         this driver without having a working -modesetting,
index 1708098..e8aae3c 100644 (file)
@@ -357,15 +357,16 @@ struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev,
                return ERR_PTR(-ENOMEM);
 
        bridge = drm_panel_bridge_add_typed(panel, connector_type);
-       if (!IS_ERR(bridge)) {
-               *ptr = bridge;
-               devres_add(dev, ptr);
-       } else {
+       if (IS_ERR(bridge)) {
                devres_free(ptr);
+               return bridge;
        }
 
        bridge->pre_enable_prev_first = panel->prepare_prev_first;
 
+       *ptr = bridge;
+       devres_add(dev, ptr);
+
        return bridge;
 }
 EXPORT_SYMBOL(devm_drm_panel_bridge_add_typed);
index b4c8cab..6e74de8 100644 (file)
@@ -450,8 +450,8 @@ static int drm_atomic_helper_crtc_normalize_zpos(struct drm_crtc *crtc,
        int i, n = 0;
        int ret = 0;
 
-       DRM_DEBUG_ATOMIC("[CRTC:%d:%s] calculating normalized zpos values\n",
-                        crtc->base.id, crtc->name);
+       drm_dbg_atomic(dev, "[CRTC:%d:%s] calculating normalized zpos values\n",
+                      crtc->base.id, crtc->name);
 
        states = kmalloc_array(total_planes, sizeof(*states), GFP_KERNEL);
        if (!states)
@@ -469,9 +469,8 @@ static int drm_atomic_helper_crtc_normalize_zpos(struct drm_crtc *crtc,
                        goto done;
                }
                states[n++] = plane_state;
-               DRM_DEBUG_ATOMIC("[PLANE:%d:%s] processing zpos value %d\n",
-                                plane->base.id, plane->name,
-                                plane_state->zpos);
+               drm_dbg_atomic(dev, "[PLANE:%d:%s] processing zpos value %d\n",
+                              plane->base.id, plane->name, plane_state->zpos);
        }
 
        sort(states, n, sizeof(*states), drm_atomic_state_zpos_cmp, NULL);
@@ -480,8 +479,8 @@ static int drm_atomic_helper_crtc_normalize_zpos(struct drm_crtc *crtc,
                plane = states[i]->plane;
 
                states[i]->normalized_zpos = i;
-               DRM_DEBUG_ATOMIC("[PLANE:%d:%s] normalized zpos value %d\n",
-                                plane->base.id, plane->name, i);
+               drm_dbg_atomic(dev, "[PLANE:%d:%s] normalized zpos value %d\n",
+                              plane->base.id, plane->name, i);
        }
        crtc_state->zpos_changed = true;
 
index 1c7d936..19ae4a1 100644 (file)
@@ -128,14 +128,7 @@ static void drm_bridge_connector_hpd_cb(void *cb_data,
        drm_kms_helper_hotplug_event(dev);
 }
 
-/**
- * drm_bridge_connector_enable_hpd - Enable hot-plug detection for the connector
- * @connector: The DRM bridge connector
- *
- * This function enables hot-plug detection for the given bridge connector.
- * This is typically used by display drivers in their resume handler.
- */
-void drm_bridge_connector_enable_hpd(struct drm_connector *connector)
+static void drm_bridge_connector_enable_hpd(struct drm_connector *connector)
 {
        struct drm_bridge_connector *bridge_connector =
                to_drm_bridge_connector(connector);
@@ -145,17 +138,8 @@ void drm_bridge_connector_enable_hpd(struct drm_connector *connector)
                drm_bridge_hpd_enable(hpd, drm_bridge_connector_hpd_cb,
                                      bridge_connector);
 }
-EXPORT_SYMBOL_GPL(drm_bridge_connector_enable_hpd);
 
-/**
- * drm_bridge_connector_disable_hpd - Disable hot-plug detection for the
- * connector
- * @connector: The DRM bridge connector
- *
- * This function disables hot-plug detection for the given bridge connector.
- * This is typically used by display drivers in their suspend handler.
- */
-void drm_bridge_connector_disable_hpd(struct drm_connector *connector)
+static void drm_bridge_connector_disable_hpd(struct drm_connector *connector)
 {
        struct drm_bridge_connector *bridge_connector =
                to_drm_bridge_connector(connector);
@@ -164,7 +148,6 @@ void drm_bridge_connector_disable_hpd(struct drm_connector *connector)
        if (hpd)
                drm_bridge_hpd_disable(hpd);
 }
-EXPORT_SYMBOL_GPL(drm_bridge_connector_disable_hpd);
 
 /* -----------------------------------------------------------------------------
  * Bridge Connector Functions
@@ -305,6 +288,8 @@ static int drm_bridge_connector_get_modes(struct drm_connector *connector)
 static const struct drm_connector_helper_funcs drm_bridge_connector_helper_funcs = {
        .get_modes = drm_bridge_connector_get_modes,
        /* No need for .mode_valid(), the bridges are checked by the core. */
+       .enable_hpd = drm_bridge_connector_enable_hpd,
+       .disable_hpd = drm_bridge_connector_disable_hpd,
 };
 
 /* -----------------------------------------------------------------------------
@@ -387,10 +372,8 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
                                    connector_type, ddc);
        drm_connector_helper_add(connector, &drm_bridge_connector_helper_funcs);
 
-       if (bridge_connector->bridge_hpd) {
+       if (bridge_connector->bridge_hpd)
                connector->polled = DRM_CONNECTOR_POLL_HPD;
-               drm_bridge_connector_enable_hpd(connector);
-       }
        else if (bridge_connector->bridge_detect)
                connector->polled = DRM_CONNECTOR_POLL_CONNECT
                                  | DRM_CONNECTOR_POLL_DISCONNECT;
index 5ea2378..4f643a4 100644 (file)
@@ -207,7 +207,7 @@ void drm_debugfs_create_files(const struct drm_info_list *files, int count,
 
                tmp->minor = minor;
                tmp->dent = debugfs_create_file(files[i].name,
-                                               S_IFREG | S_IRUGO, root, tmp,
+                                               0444, root, tmp,
                                                &drm_debugfs_fops);
                tmp->info_ent = &files[i];
 
@@ -246,7 +246,7 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id,
                dev->driver->debugfs_init(minor);
 
        list_for_each_entry_safe(entry, tmp, &dev->debugfs_list, list) {
-               debugfs_create_file(entry->file.name, S_IFREG | S_IRUGO,
+               debugfs_create_file(entry->file.name, 0444,
                                    minor->debugfs_root, entry, &drm_debugfs_entry_fops);
                list_del(&entry->list);
        }
@@ -263,7 +263,7 @@ void drm_debugfs_late_register(struct drm_device *dev)
                return;
 
        list_for_each_entry_safe(entry, tmp, &dev->debugfs_list, list) {
-               debugfs_create_file(entry->file.name, S_IFREG | S_IRUGO,
+               debugfs_create_file(entry->file.name, 0444,
                                    minor->debugfs_root, entry, &drm_debugfs_entry_fops);
                list_del(&entry->list);
        }
@@ -508,15 +508,15 @@ void drm_debugfs_connector_add(struct drm_connector *connector)
        connector->debugfs_entry = root;
 
        /* force */
-       debugfs_create_file("force", S_IRUGO | S_IWUSR, root, connector,
+       debugfs_create_file("force", 0644, root, connector,
                            &drm_connector_fops);
 
        /* edid */
-       debugfs_create_file("edid_override", S_IRUGO | S_IWUSR, root, connector,
+       debugfs_create_file("edid_override", 0644, root, connector,
                            &drm_edid_fops);
 
        /* vrr range */
-       debugfs_create_file("vrr_range", S_IRUGO, root, connector,
+       debugfs_create_file("vrr_range", 0444, root, connector,
                            &vrr_range_fops);
 
        /* max bpc */
index b3a731b..4276317 100644 (file)
@@ -1726,117 +1726,132 @@ unlock:
 }
 EXPORT_SYMBOL(drm_fb_helper_pan_display);
 
-/*
- * Allocates the backing storage and sets up the fbdev info structure through
- * the ->fb_probe callback.
- */
-static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
-                                        int preferred_bpp)
+static uint32_t drm_fb_helper_find_format(struct drm_fb_helper *fb_helper, const uint32_t *formats,
+                                         size_t format_count, uint32_t bpp, uint32_t depth)
 {
-       struct drm_client_dev *client = &fb_helper->client;
        struct drm_device *dev = fb_helper->dev;
-       struct drm_mode_config *config = &dev->mode_config;
-       int ret = 0;
-       int crtc_count = 0;
-       struct drm_connector_list_iter conn_iter;
-       struct drm_fb_helper_surface_size sizes;
-       struct drm_connector *connector;
-       struct drm_mode_set *mode_set;
-       int best_depth = 0;
-
-       memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
-       sizes.surface_depth = 24;
-       sizes.surface_bpp = 32;
-       sizes.fb_width = (u32)-1;
-       sizes.fb_height = (u32)-1;
+       uint32_t format;
+       size_t i;
 
        /*
-        * If driver picks 8 or 16 by default use that for both depth/bpp
-        * to begin with
+        * Do not consider YUV or other complicated formats
+        * for framebuffers. This means only legacy formats
+        * are supported (fmt->depth is a legacy field), but
+        * the framebuffer emulation can only deal with such
+        * formats, specifically RGB/BGA formats.
         */
-       if (preferred_bpp != sizes.surface_bpp)
-               sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
+       format = drm_mode_legacy_fb_format(bpp, depth);
+       if (!format)
+               goto err;
 
-       drm_connector_list_iter_begin(fb_helper->dev, &conn_iter);
-       drm_client_for_each_connector_iter(connector, &conn_iter) {
-               struct drm_cmdline_mode *cmdline_mode;
+       for (i = 0; i < format_count; ++i) {
+               if (formats[i] == format)
+                       return format;
+       }
 
-               cmdline_mode = &connector->cmdline_mode;
+err:
+       /* We found nothing. */
+       drm_warn(dev, "bpp/depth value of %u/%u not supported\n", bpp, depth);
 
-               if (cmdline_mode->bpp_specified) {
-                       switch (cmdline_mode->bpp) {
-                       case 8:
-                               sizes.surface_depth = sizes.surface_bpp = 8;
-                               break;
-                       case 15:
-                               sizes.surface_depth = 15;
-                               sizes.surface_bpp = 16;
-                               break;
-                       case 16:
-                               sizes.surface_depth = sizes.surface_bpp = 16;
-                               break;
-                       case 24:
-                               sizes.surface_depth = sizes.surface_bpp = 24;
-                               break;
-                       case 32:
-                               sizes.surface_depth = 24;
-                               sizes.surface_bpp = 32;
-                               break;
-                       }
-                       break;
-               }
+       return DRM_FORMAT_INVALID;
+}
+
+static uint32_t drm_fb_helper_find_color_mode_format(struct drm_fb_helper *fb_helper,
+                                                    const uint32_t *formats, size_t format_count,
+                                                    unsigned int color_mode)
+{
+       struct drm_device *dev = fb_helper->dev;
+       uint32_t bpp, depth;
+
+       switch (color_mode) {
+       case 1:
+       case 2:
+       case 4:
+       case 8:
+       case 16:
+       case 24:
+               bpp = depth = color_mode;
+               break;
+       case 15:
+               bpp = 16;
+               depth = 15;
+               break;
+       case 32:
+               bpp = 32;
+               depth = 24;
+               break;
+       default:
+               drm_info(dev, "unsupported color mode of %d\n", color_mode);
+               return DRM_FORMAT_INVALID;
        }
-       drm_connector_list_iter_end(&conn_iter);
 
-       /*
-        * If we run into a situation where, for example, the primary plane
-        * supports RGBA5551 (16 bpp, depth 15) but not RGB565 (16 bpp, depth
-        * 16) we need to scale down the depth of the sizes we request.
-        */
-       mutex_lock(&client->modeset_mutex);
+       return drm_fb_helper_find_format(fb_helper, formats, format_count, bpp, depth);
+}
+
+static int __drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper, int preferred_bpp,
+                                     struct drm_fb_helper_surface_size *sizes)
+{
+       struct drm_client_dev *client = &fb_helper->client;
+       struct drm_device *dev = fb_helper->dev;
+       int crtc_count = 0;
+       struct drm_connector_list_iter conn_iter;
+       struct drm_connector *connector;
+       struct drm_mode_set *mode_set;
+       uint32_t surface_format = DRM_FORMAT_INVALID;
+       const struct drm_format_info *info;
+
+       memset(sizes, 0, sizeof(*sizes));
+       sizes->fb_width = (u32)-1;
+       sizes->fb_height = (u32)-1;
+
        drm_client_for_each_modeset(mode_set, client) {
                struct drm_crtc *crtc = mode_set->crtc;
                struct drm_plane *plane = crtc->primary;
-               int j;
 
                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;
-
-                       fmt = drm_format_info(plane->format_types[j]);
-
-                       /*
-                        * Do not consider YUV or other complicated formats
-                        * for framebuffers. This means only legacy formats
-                        * are supported (fmt->depth is a legacy field) but
-                        * the framebuffer emulation can only deal with such
-                        * formats, specifically RGB/BGA formats.
-                        */
-                       if (fmt->depth == 0)
-                               continue;
-
-                       /* We found a perfect fit, great */
-                       if (fmt->depth == sizes.surface_depth) {
-                               best_depth = fmt->depth;
-                               break;
-                       }
+               drm_connector_list_iter_begin(fb_helper->dev, &conn_iter);
+               drm_client_for_each_connector_iter(connector, &conn_iter) {
+                       struct drm_cmdline_mode *cmdline_mode = &connector->cmdline_mode;
 
-                       /* Skip depths above what we're looking for */
-                       if (fmt->depth > sizes.surface_depth)
+                       if (!cmdline_mode->bpp_specified)
                                continue;
 
-                       /* Best depth found so far */
-                       if (fmt->depth > best_depth)
-                               best_depth = fmt->depth;
+                       surface_format = drm_fb_helper_find_color_mode_format(fb_helper,
+                                                                             plane->format_types,
+                                                                             plane->format_count,
+                                                                             cmdline_mode->bpp);
+                       if (surface_format != DRM_FORMAT_INVALID)
+                               break; /* found supported format */
                }
+               drm_connector_list_iter_end(&conn_iter);
+
+               if (surface_format != DRM_FORMAT_INVALID)
+                       break; /* found supported format */
+
+               /* try preferred color mode */
+               surface_format = drm_fb_helper_find_color_mode_format(fb_helper,
+                                                                     plane->format_types,
+                                                                     plane->format_count,
+                                                                     preferred_bpp);
+               if (surface_format != DRM_FORMAT_INVALID)
+                       break; /* found supported format */
        }
-       if (sizes.surface_depth != best_depth && best_depth) {
-               drm_info(dev, "requested bpp %d, scaled depth down to %d",
-                        sizes.surface_bpp, best_depth);
-               sizes.surface_depth = best_depth;
+
+       if (surface_format == DRM_FORMAT_INVALID) {
+               /*
+                * If none of the given color modes works, fall back
+                * to XRGB8888. Drivers are expected to provide this
+                * format for compatibility with legacy applications.
+                */
+               drm_warn(dev, "No compatible format found\n");
+               surface_format = drm_driver_legacy_fb_format(dev, 32, 24);
        }
 
+       info = drm_format_info(surface_format);
+       sizes->surface_bpp = drm_format_info_bpp(info, 0);
+       sizes->surface_depth = info->depth;
+
        /* first up get a count of crtcs now in use and new min/maxes width/heights */
        crtc_count = 0;
        drm_client_for_each_modeset(mode_set, client) {
@@ -1858,8 +1873,10 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
                x = mode_set->x;
                y = mode_set->y;
 
-               sizes.surface_width  = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width);
-               sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height);
+               sizes->surface_width  =
+                       max_t(u32, desired_mode->hdisplay + x, sizes->surface_width);
+               sizes->surface_height =
+                       max_t(u32, desired_mode->vdisplay + y, sizes->surface_height);
 
                for (j = 0; j < mode_set->num_connectors; j++) {
                        struct drm_connector *connector = mode_set->connectors[j];
@@ -1875,28 +1892,63 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
                }
 
                if (lasth)
-                       sizes.fb_width  = min_t(u32, desired_mode->hdisplay + x, sizes.fb_width);
+                       sizes->fb_width  = min_t(u32, desired_mode->hdisplay + x, sizes->fb_width);
                if (lastv)
-                       sizes.fb_height = min_t(u32, desired_mode->vdisplay + y, sizes.fb_height);
+                       sizes->fb_height = min_t(u32, desired_mode->vdisplay + y, sizes->fb_height);
        }
-       mutex_unlock(&client->modeset_mutex);
 
-       if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
+       if (crtc_count == 0 || sizes->fb_width == -1 || sizes->fb_height == -1) {
                drm_info(dev, "Cannot find any crtc or sizes\n");
-
-               /* First time: disable all crtc's.. */
-               if (!fb_helper->deferred_setup)
-                       drm_client_modeset_commit(client);
                return -EAGAIN;
        }
 
+       return 0;
+}
+
+static int drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper, int preferred_bpp,
+                                   struct drm_fb_helper_surface_size *sizes)
+{
+       struct drm_client_dev *client = &fb_helper->client;
+       struct drm_device *dev = fb_helper->dev;
+       struct drm_mode_config *config = &dev->mode_config;
+       int ret;
+
+       mutex_lock(&client->modeset_mutex);
+       ret = __drm_fb_helper_find_sizes(fb_helper, preferred_bpp, sizes);
+       mutex_unlock(&client->modeset_mutex);
+
+       if (ret)
+               return ret;
+
        /* Handle our overallocation */
-       sizes.surface_height *= drm_fbdev_overalloc;
-       sizes.surface_height /= 100;
-       if (sizes.surface_height > config->max_height) {
+       sizes->surface_height *= drm_fbdev_overalloc;
+       sizes->surface_height /= 100;
+       if (sizes->surface_height > config->max_height) {
                drm_dbg_kms(dev, "Fbdev over-allocation too large; clamping height to %d\n",
                            config->max_height);
-               sizes.surface_height = config->max_height;
+               sizes->surface_height = config->max_height;
+       }
+
+       return 0;
+}
+
+/*
+ * Allocates the backing storage and sets up the fbdev info structure through
+ * the ->fb_probe callback.
+ */
+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_fb_helper_surface_size sizes;
+       int ret;
+
+       ret = drm_fb_helper_find_sizes(fb_helper, preferred_bpp, &sizes);
+       if (ret) {
+               /* First time: disable all crtc's.. */
+               if (!fb_helper->deferred_setup)
+                       drm_client_modeset_commit(client);
+               return ret;
        }
 
 #if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
index 64b4a3a..a51ff8c 100644 (file)
@@ -245,10 +245,10 @@ void drm_file_free(struct drm_file *file)
 
        dev = file->minor->dev;
 
-       DRM_DEBUG("comm=\"%s\", pid=%d, dev=0x%lx, open_count=%d\n",
-                 current->comm, task_pid_nr(current),
-                 (long)old_encode_dev(file->minor->kdev->devt),
-                 atomic_read(&dev->open_count));
+       drm_dbg_core(dev, "comm=\"%s\", pid=%d, dev=0x%lx, open_count=%d\n",
+                    current->comm, task_pid_nr(current),
+                    (long)old_encode_dev(file->minor->kdev->devt),
+                    atomic_read(&dev->open_count));
 
 #ifdef CONFIG_DRM_LEGACY
        if (drm_core_check_feature(dev, DRIVER_LEGACY) &&
@@ -340,8 +340,8 @@ int drm_open_helper(struct file *filp, struct drm_minor *minor)
            dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF)
                return -EINVAL;
 
-       DRM_DEBUG("comm=\"%s\", pid=%d, minor=%d\n", current->comm,
-                 task_pid_nr(current), minor->index);
+       drm_dbg_core(dev, "comm=\"%s\", pid=%d, minor=%d\n",
+                    current->comm, task_pid_nr(current), minor->index);
 
        priv = drm_file_alloc(minor);
        if (IS_ERR(priv))
@@ -450,11 +450,11 @@ EXPORT_SYMBOL(drm_open);
 
 void drm_lastclose(struct drm_device * dev)
 {
-       DRM_DEBUG("\n");
+       drm_dbg_core(dev, "\n");
 
        if (dev->driver->lastclose)
                dev->driver->lastclose(dev);
-       DRM_DEBUG("driver lastclose completed\n");
+       drm_dbg_core(dev, "driver lastclose completed\n");
 
        if (drm_core_check_feature(dev, DRIVER_LEGACY))
                drm_legacy_dev_reinit(dev);
@@ -485,7 +485,7 @@ int drm_release(struct inode *inode, struct file *filp)
        if (drm_dev_needs_global_mutex(dev))
                mutex_lock(&drm_global_mutex);
 
-       DRM_DEBUG("open_count = %d\n", atomic_read(&dev->open_count));
+       drm_dbg_core(dev, "open_count = %d\n", atomic_read(&dev->open_count));
 
        drm_close_helper(filp);
 
index 74ff33c..994f8fb 100644 (file)
@@ -322,7 +322,7 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb332);
 
 static void drm_fb_xrgb8888_to_rgb565_line(void *dbuf, const void *sbuf, unsigned int pixels)
 {
-       u16 *dbuf16 = dbuf;
+       __le16 *dbuf16 = dbuf;
        const __le32 *sbuf32 = sbuf;
        unsigned int x;
        u16 val16;
@@ -333,14 +333,15 @@ static void drm_fb_xrgb8888_to_rgb565_line(void *dbuf, const void *sbuf, unsigne
                val16 = ((pix & 0x00F80000) >> 8) |
                        ((pix & 0x0000FC00) >> 5) |
                        ((pix & 0x000000F8) >> 3);
-               dbuf16[x] = val16;
+               dbuf16[x] = cpu_to_le16(val16);
        }
 }
 
+/* TODO: implement this helper as conversion to RGB565|BIG_ENDIAN */
 static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf,
                                                unsigned int pixels)
 {
-       u16 *dbuf16 = dbuf;
+       __le16 *dbuf16 = dbuf;
        const __le32 *sbuf32 = sbuf;
        unsigned int x;
        u16 val16;
@@ -351,7 +352,7 @@ static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf,
                val16 = ((pix & 0x00F80000) >> 8) |
                        ((pix & 0x0000FC00) >> 5) |
                        ((pix & 0x000000F8) >> 3);
-               dbuf16[x] = swab16(val16);
+               dbuf16[x] = cpu_to_le16(swab16(val16));
        }
 }
 
@@ -395,6 +396,161 @@ void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pi
 }
 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565);
 
+static void drm_fb_xrgb8888_to_xrgb1555_line(void *dbuf, const void *sbuf, unsigned int pixels)
+{
+       __le16 *dbuf16 = dbuf;
+       const __le32 *sbuf32 = sbuf;
+       unsigned int x;
+       u16 val16;
+       u32 pix;
+
+       for (x = 0; x < pixels; x++) {
+               pix = le32_to_cpu(sbuf32[x]);
+               val16 = ((pix & 0x00f80000) >> 9) |
+                       ((pix & 0x0000f800) >> 6) |
+                       ((pix & 0x000000f8) >> 3);
+               dbuf16[x] = cpu_to_le16(val16);
+       }
+}
+
+/**
+ * drm_fb_xrgb8888_to_xrgb1555 - Convert XRGB8888 to XRGB1555 clip buffer
+ * @dst: Array of XRGB1555 destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
+ *             within @dst; can be NULL if scanlines are stored next to each other.
+ * @src: Array of XRGB8888 source buffer
+ * @fb: DRM framebuffer
+ * @clip: Clip rectangle area to copy
+ *
+ * This function copies parts of a framebuffer to display memory and converts
+ * the color format during the process. The parameters @dst, @dst_pitch and
+ * @src refer to arrays. Each array must have at least as many entries as
+ * there are planes in @fb's format. Each entry stores the value for the
+ * format's respective color plane at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at the
+ * top-left corner).
+ *
+ * Drivers can use this function for XRGB1555 devices that don't support
+ * XRGB8888 natively.
+ */
+void drm_fb_xrgb8888_to_xrgb1555(struct iosys_map *dst, const unsigned int *dst_pitch,
+                                const struct iosys_map *src, const struct drm_framebuffer *fb,
+                                const struct drm_rect *clip)
+{
+       static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
+               2,
+       };
+
+       drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
+                   drm_fb_xrgb8888_to_xrgb1555_line);
+}
+EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb1555);
+
+static void drm_fb_xrgb8888_to_argb1555_line(void *dbuf, const void *sbuf, unsigned int pixels)
+{
+       __le16 *dbuf16 = dbuf;
+       const __le32 *sbuf32 = sbuf;
+       unsigned int x;
+       u16 val16;
+       u32 pix;
+
+       for (x = 0; x < pixels; x++) {
+               pix = le32_to_cpu(sbuf32[x]);
+               val16 = BIT(15) | /* set alpha bit */
+                       ((pix & 0x00f80000) >> 9) |
+                       ((pix & 0x0000f800) >> 6) |
+                       ((pix & 0x000000f8) >> 3);
+               dbuf16[x] = cpu_to_le16(val16);
+       }
+}
+
+/**
+ * drm_fb_xrgb8888_to_argb1555 - Convert XRGB8888 to ARGB1555 clip buffer
+ * @dst: Array of ARGB1555 destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
+ *             within @dst; can be NULL if scanlines are stored next to each other.
+ * @src: Array of XRGB8888 source buffer
+ * @fb: DRM framebuffer
+ * @clip: Clip rectangle area to copy
+ *
+ * This function copies parts of a framebuffer to display memory and converts
+ * the color format during the process. The parameters @dst, @dst_pitch and
+ * @src refer to arrays. Each array must have at least as many entries as
+ * there are planes in @fb's format. Each entry stores the value for the
+ * format's respective color plane at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at the
+ * top-left corner).
+ *
+ * Drivers can use this function for ARGB1555 devices that don't support
+ * XRGB8888 natively. It sets an opaque alpha channel as part of the conversion.
+ */
+void drm_fb_xrgb8888_to_argb1555(struct iosys_map *dst, const unsigned int *dst_pitch,
+                                const struct iosys_map *src, const struct drm_framebuffer *fb,
+                                const struct drm_rect *clip)
+{
+       static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
+               2,
+       };
+
+       drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
+                   drm_fb_xrgb8888_to_argb1555_line);
+}
+EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb1555);
+
+static void drm_fb_xrgb8888_to_rgba5551_line(void *dbuf, const void *sbuf, unsigned int pixels)
+{
+       __le16 *dbuf16 = dbuf;
+       const __le32 *sbuf32 = sbuf;
+       unsigned int x;
+       u16 val16;
+       u32 pix;
+
+       for (x = 0; x < pixels; x++) {
+               pix = le32_to_cpu(sbuf32[x]);
+               val16 = ((pix & 0x00f80000) >> 8) |
+                       ((pix & 0x0000f800) >> 5) |
+                       ((pix & 0x000000f8) >> 2) |
+                       BIT(0); /* set alpha bit */
+               dbuf16[x] = cpu_to_le16(val16);
+       }
+}
+
+/**
+ * drm_fb_xrgb8888_to_rgba5551 - Convert XRGB8888 to RGBA5551 clip buffer
+ * @dst: Array of RGBA5551 destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
+ *             within @dst; can be NULL if scanlines are stored next to each other.
+ * @src: Array of XRGB8888 source buffer
+ * @fb: DRM framebuffer
+ * @clip: Clip rectangle area to copy
+ *
+ * This function copies parts of a framebuffer to display memory and converts
+ * the color format during the process. The parameters @dst, @dst_pitch and
+ * @src refer to arrays. Each array must have at least as many entries as
+ * there are planes in @fb's format. Each entry stores the value for the
+ * format's respective color plane at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at the
+ * top-left corner).
+ *
+ * Drivers can use this function for RGBA5551 devices that don't support
+ * XRGB8888 natively. It sets an opaque alpha channel as part of the conversion.
+ */
+void drm_fb_xrgb8888_to_rgba5551(struct iosys_map *dst, const unsigned int *dst_pitch,
+                                const struct iosys_map *src, const struct drm_framebuffer *fb,
+                                const struct drm_rect *clip)
+{
+       static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
+               2,
+       };
+
+       drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
+                   drm_fb_xrgb8888_to_rgba5551_line);
+}
+EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgba5551);
+
 static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigned int pixels)
 {
        u8 *dbuf8 = dbuf;
@@ -404,6 +560,7 @@ static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigne
 
        for (x = 0; x < pixels; x++) {
                pix = le32_to_cpu(sbuf32[x]);
+               /* write blue-green-red to output in little endianness */
                *dbuf8++ = (pix & 0x000000FF) >>  0;
                *dbuf8++ = (pix & 0x0000FF00) >>  8;
                *dbuf8++ = (pix & 0x00FF0000) >> 16;
@@ -444,64 +601,53 @@ void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pi
 }
 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888);
 
-static void drm_fb_rgb565_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
+static void drm_fb_xrgb8888_to_argb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
 {
        __le32 *dbuf32 = dbuf;
-       const __le16 *sbuf16 = sbuf;
-       unsigned int x;
-
-       for (x = 0; x < pixels; x++) {
-               u16 val16 = le16_to_cpu(sbuf16[x]);
-               u32 val32 = ((val16 & 0xf800) << 8) |
-                           ((val16 & 0x07e0) << 5) |
-                           ((val16 & 0x001f) << 3);
-               val32 = 0xff000000 | val32 |
-                       ((val32 >> 3) & 0x00070007) |
-                       ((val32 >> 2) & 0x00000300);
-               dbuf32[x] = cpu_to_le32(val32);
-       }
-}
-
-static void drm_fb_rgb565_to_xrgb8888(struct iosys_map *dst, const unsigned int *dst_pitch,
-                                     const struct iosys_map *src,
-                                     const struct drm_framebuffer *fb,
-                                     const struct drm_rect *clip)
-{
-       static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
-               4,
-       };
-
-       drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
-                   drm_fb_rgb565_to_xrgb8888_line);
-}
-
-static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
-{
-       __le32 *dbuf32 = dbuf;
-       const u8 *sbuf8 = sbuf;
+       const __le32 *sbuf32 = sbuf;
        unsigned int x;
+       u32 pix;
 
        for (x = 0; x < pixels; x++) {
-               u8 r = *sbuf8++;
-               u8 g = *sbuf8++;
-               u8 b = *sbuf8++;
-               u32 pix = 0xff000000 | (r << 16) | (g << 8) | b;
+               pix = le32_to_cpu(sbuf32[x]);
+               pix |= GENMASK(31, 24); /* fill alpha bits */
                dbuf32[x] = cpu_to_le32(pix);
        }
 }
 
-static void drm_fb_rgb888_to_xrgb8888(struct iosys_map *dst, const unsigned int *dst_pitch,
-                                     const struct iosys_map *src,
-                                     const struct drm_framebuffer *fb,
-                                     const struct drm_rect *clip)
+/**
+ * drm_fb_xrgb8888_to_argb8888 - Convert XRGB8888 to ARGB8888 clip buffer
+ * @dst: Array of ARGB8888 destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
+ *             within @dst; can be NULL if scanlines are stored next to each other.
+ * @src: Array of XRGB8888 source buffer
+ * @fb: DRM framebuffer
+ * @clip: Clip rectangle area to copy
+ *
+ * This function copies parts of a framebuffer to display memory and converts the
+ * color format during the process. The parameters @dst, @dst_pitch and @src refer
+ * to arrays. Each array must have at least as many entries as there are planes in
+ * @fb's format. Each entry stores the value for the format's respective color plane
+ * at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at the
+ * top-left corner).
+ *
+ * Drivers can use this function for ARGB8888 devices that don't support XRGB8888
+ * natively. It sets an opaque alpha channel as part of the conversion.
+ */
+void drm_fb_xrgb8888_to_argb8888(struct iosys_map *dst, const unsigned int *dst_pitch,
+                                const struct iosys_map *src, const struct drm_framebuffer *fb,
+                                const struct drm_rect *clip)
 {
        static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
                4,
        };
 
        drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
-                   drm_fb_rgb888_to_xrgb8888_line);
+                   drm_fb_xrgb8888_to_argb8888_line);
 }
+EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb8888);
 
 static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels)
 {
@@ -555,6 +701,59 @@ void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *d
 }
 EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010);
 
+static void drm_fb_xrgb8888_to_argb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels)
+{
+       __le32 *dbuf32 = dbuf;
+       const __le32 *sbuf32 = sbuf;
+       unsigned int x;
+       u32 val32;
+       u32 pix;
+
+       for (x = 0; x < pixels; x++) {
+               pix = le32_to_cpu(sbuf32[x]);
+               val32 = ((pix & 0x000000ff) << 2) |
+                       ((pix & 0x0000ff00) << 4) |
+                       ((pix & 0x00ff0000) << 6);
+               pix = GENMASK(31, 30) | /* set alpha bits */
+                     val32 | ((val32 >> 8) & 0x00300c03);
+               *dbuf32++ = cpu_to_le32(pix);
+       }
+}
+
+/**
+ * drm_fb_xrgb8888_to_argb2101010 - Convert XRGB8888 to ARGB2101010 clip buffer
+ * @dst: Array of ARGB2101010 destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
+ *             within @dst; can be NULL if scanlines are stored next to each other.
+ * @src: Array of XRGB8888 source buffers
+ * @fb: DRM framebuffer
+ * @clip: Clip rectangle area to copy
+ *
+ * This function copies parts of a framebuffer to display memory and converts
+ * the color format during the process. The parameters @dst, @dst_pitch and
+ * @src refer to arrays. Each array must have at least as many entries as
+ * there are planes in @fb's format. Each entry stores the value for the
+ * format's respective color plane at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at the
+ * top-left corner).
+ *
+ * Drivers can use this function for ARGB2101010 devices that don't support XRGB8888
+ * natively.
+ */
+void drm_fb_xrgb8888_to_argb2101010(struct iosys_map *dst, const unsigned int *dst_pitch,
+                                   const struct iosys_map *src, const struct drm_framebuffer *fb,
+                                   const struct drm_rect *clip)
+{
+       static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
+               4,
+       };
+
+       drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
+                   drm_fb_xrgb8888_to_argb2101010_line);
+}
+EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb2101010);
+
 static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned int pixels)
 {
        u8 *dbuf8 = dbuf;
@@ -641,50 +840,41 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d
 {
        uint32_t fb_format = fb->format->format;
 
-       /* treat alpha channel like filler bits */
-       if (fb_format == DRM_FORMAT_ARGB8888)
-               fb_format = DRM_FORMAT_XRGB8888;
-       if (dst_format == DRM_FORMAT_ARGB8888)
-               dst_format = DRM_FORMAT_XRGB8888;
-       if (fb_format == DRM_FORMAT_ARGB2101010)
-               fb_format = DRM_FORMAT_XRGB2101010;
-       if (dst_format == DRM_FORMAT_ARGB2101010)
-               dst_format = DRM_FORMAT_XRGB2101010;
-
-       if (dst_format == fb_format) {
+       if (fb_format == dst_format) {
                drm_fb_memcpy(dst, dst_pitch, src, fb, clip);
                return 0;
-
-       } else if (dst_format == DRM_FORMAT_RGB565) {
-               if (fb_format == DRM_FORMAT_XRGB8888) {
+       } else if (fb_format == (dst_format | DRM_FORMAT_BIG_ENDIAN)) {
+               drm_fb_swab(dst, dst_pitch, src, fb, clip, false);
+               return 0;
+       } else if (fb_format == (dst_format & ~DRM_FORMAT_BIG_ENDIAN)) {
+               drm_fb_swab(dst, dst_pitch, src, fb, clip, false);
+               return 0;
+       } else if (fb_format == DRM_FORMAT_XRGB8888) {
+               if (dst_format == DRM_FORMAT_RGB565) {
                        drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, false);
                        return 0;
-               }
-       } else if (dst_format == (DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN)) {
-               if (fb_format == DRM_FORMAT_RGB565) {
-                       drm_fb_swab(dst, dst_pitch, src, fb, clip, false);
+               } else if (dst_format == DRM_FORMAT_XRGB1555) {
+                       drm_fb_xrgb8888_to_xrgb1555(dst, dst_pitch, src, fb, clip);
                        return 0;
-               }
-       } else if (dst_format == DRM_FORMAT_RGB888) {
-               if (fb_format == DRM_FORMAT_XRGB8888) {
-                       drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip);
+               } else if (dst_format == DRM_FORMAT_ARGB1555) {
+                       drm_fb_xrgb8888_to_argb1555(dst, dst_pitch, src, fb, clip);
                        return 0;
-               }
-       } else if (dst_format == DRM_FORMAT_XRGB8888) {
-               if (fb_format == DRM_FORMAT_RGB888) {
-                       drm_fb_rgb888_to_xrgb8888(dst, dst_pitch, src, fb, clip);
+               } else if (dst_format == DRM_FORMAT_RGBA5551) {
+                       drm_fb_xrgb8888_to_rgba5551(dst, dst_pitch, src, fb, clip);
+                       return 0;
+               } else if (dst_format == DRM_FORMAT_RGB888) {
+                       drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip);
                        return 0;
-               } else if (fb_format == DRM_FORMAT_RGB565) {
-                       drm_fb_rgb565_to_xrgb8888(dst, dst_pitch, src, fb, clip);
+               } else if (dst_format == DRM_FORMAT_ARGB8888) {
+                       drm_fb_xrgb8888_to_argb8888(dst, dst_pitch, src, fb, clip);
                        return 0;
-               }
-       } else if (dst_format == DRM_FORMAT_XRGB2101010) {
-               if (fb_format == DRM_FORMAT_XRGB8888) {
+               } else if (dst_format == DRM_FORMAT_XRGB2101010) {
                        drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, src, fb, clip);
                        return 0;
-               }
-       } else if (dst_format == DRM_FORMAT_BGRX8888) {
-               if (fb_format == DRM_FORMAT_XRGB8888) {
+               } else if (dst_format == DRM_FORMAT_ARGB2101010) {
+                       drm_fb_xrgb8888_to_argb2101010(dst, dst_pitch, src, fb, clip);
+                       return 0;
+               } else if (dst_format == DRM_FORMAT_BGRX8888) {
                        drm_fb_swab(dst, dst_pitch, src, fb, clip, false);
                        return 0;
                }
@@ -805,6 +995,39 @@ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitc
 }
 EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono);
 
+static uint32_t drm_fb_nonalpha_fourcc(uint32_t fourcc)
+{
+       /* only handle formats with depth != 0 and alpha channel */
+       switch (fourcc) {
+       case DRM_FORMAT_ARGB1555:
+               return DRM_FORMAT_XRGB1555;
+       case DRM_FORMAT_ABGR1555:
+               return DRM_FORMAT_XBGR1555;
+       case DRM_FORMAT_RGBA5551:
+               return DRM_FORMAT_RGBX5551;
+       case DRM_FORMAT_BGRA5551:
+               return DRM_FORMAT_BGRX5551;
+       case DRM_FORMAT_ARGB8888:
+               return DRM_FORMAT_XRGB8888;
+       case DRM_FORMAT_ABGR8888:
+               return DRM_FORMAT_XBGR8888;
+       case DRM_FORMAT_RGBA8888:
+               return DRM_FORMAT_RGBX8888;
+       case DRM_FORMAT_BGRA8888:
+               return DRM_FORMAT_BGRX8888;
+       case DRM_FORMAT_ARGB2101010:
+               return DRM_FORMAT_XRGB2101010;
+       case DRM_FORMAT_ABGR2101010:
+               return DRM_FORMAT_XBGR2101010;
+       case DRM_FORMAT_RGBA1010102:
+               return DRM_FORMAT_RGBX1010102;
+       case DRM_FORMAT_BGRA1010102:
+               return DRM_FORMAT_BGRX1010102;
+       }
+
+       return fourcc;
+}
+
 static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t fourcc)
 {
        const uint32_t *fourccs_end = fourccs + nfourccs;
@@ -817,73 +1040,48 @@ static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t
        return false;
 }
 
-static const uint32_t conv_from_xrgb8888[] = {
-       DRM_FORMAT_XRGB8888,
-       DRM_FORMAT_ARGB8888,
-       DRM_FORMAT_XRGB2101010,
-       DRM_FORMAT_ARGB2101010,
-       DRM_FORMAT_RGB565,
-       DRM_FORMAT_RGB888,
-};
-
-static const uint32_t conv_from_rgb565_888[] = {
-       DRM_FORMAT_XRGB8888,
-       DRM_FORMAT_ARGB8888,
-};
-
-static bool is_conversion_supported(uint32_t from, uint32_t to)
-{
-       switch (from) {
-       case DRM_FORMAT_XRGB8888:
-       case DRM_FORMAT_ARGB8888:
-               return is_listed_fourcc(conv_from_xrgb8888, ARRAY_SIZE(conv_from_xrgb8888), to);
-       case DRM_FORMAT_RGB565:
-       case DRM_FORMAT_RGB888:
-               return is_listed_fourcc(conv_from_rgb565_888, ARRAY_SIZE(conv_from_rgb565_888), to);
-       case DRM_FORMAT_XRGB2101010:
-               return to == DRM_FORMAT_ARGB2101010;
-       case DRM_FORMAT_ARGB2101010:
-               return to == DRM_FORMAT_XRGB2101010;
-       default:
-               return false;
-       }
-}
-
 /**
  * drm_fb_build_fourcc_list - Filters a list of supported color formats against
  *                            the device's native formats
  * @dev: DRM device
  * @native_fourccs: 4CC codes of natively supported color formats
  * @native_nfourccs: The number of entries in @native_fourccs
- * @driver_fourccs: 4CC codes of all driver-supported color formats
- * @driver_nfourccs: The number of entries in @driver_fourccs
  * @fourccs_out: Returns 4CC codes of supported color formats
  * @nfourccs_out: The number of available entries in @fourccs_out
  *
  * This function create a list of supported color format from natively
- * supported formats and the emulated formats.
+ * supported formats and additional emulated formats.
  * At a minimum, most userspace programs expect at least support for
  * XRGB8888 on the primary plane. Devices that have to emulate the
  * format, and possibly others, can use drm_fb_build_fourcc_list() to
  * create a list of supported color formats. The returned list can
  * be handed over to drm_universal_plane_init() et al. Native formats
- * will go before emulated formats. Other heuristics might be applied
+ * will go before emulated formats. Native formats with alpha channel
+ * will be replaced by such without, as primary planes usually don't
+ * support alpha. Other heuristics might be applied
  * to optimize the order. Formats near the beginning of the list are
- * usually preferred over formats near the end of the list. Formats
- * without conversion helpers will be skipped. New drivers should only
- * pass in XRGB8888 and avoid exposing additional emulated formats.
+ * usually preferred over formats near the end of the list.
  *
  * Returns:
  * The number of color-formats 4CC codes returned in @fourccs_out.
  */
 size_t drm_fb_build_fourcc_list(struct drm_device *dev,
                                const u32 *native_fourccs, size_t native_nfourccs,
-                               const u32 *driver_fourccs, size_t driver_nfourccs,
                                u32 *fourccs_out, size_t nfourccs_out)
 {
+       /*
+        * XRGB8888 is the default fallback format for most of userspace
+        * and it's currently the only format that should be emulated for
+        * the primary plane. Only if there's ever another default fallback,
+        * it should be added here.
+        */
+       static const uint32_t extra_fourccs[] = {
+               DRM_FORMAT_XRGB8888,
+       };
+       static const size_t extra_nfourccs = ARRAY_SIZE(extra_fourccs);
+
        u32 *fourccs = fourccs_out;
        const u32 *fourccs_end = fourccs_out + nfourccs_out;
-       uint32_t native_format = 0;
        size_t i;
 
        /*
@@ -891,7 +1089,12 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev,
         */
 
        for (i = 0; i < native_nfourccs; ++i) {
-               u32 fourcc = native_fourccs[i];
+               /*
+                * Several DTs, boot loaders and firmware report native
+                * alpha formats that are non-alpha formats instead. So
+                * replace alpha formats by non-alpha formats.
+                */
+               u32 fourcc = drm_fb_nonalpha_fourcc(native_fourccs[i]);
 
                if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) {
                        continue; /* skip duplicate entries */
@@ -902,14 +1105,6 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev,
 
                drm_dbg_kms(dev, "adding native format %p4cc\n", &fourcc);
 
-               /*
-                * There should only be one native format with the current API.
-                * This API needs to be refactored to correctly support arbitrary
-                * sets of native formats, since it needs to report which native
-                * format to use for each emulated format.
-                */
-               if (!native_format)
-                       native_format = fourcc;
                *fourccs = fourcc;
                ++fourccs;
        }
@@ -918,17 +1113,14 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev,
         * The extra formats, emulated by the driver, go second.
         */
 
-       for (i = 0; (i < driver_nfourccs) && (fourccs < fourccs_end); ++i) {
-               u32 fourcc = driver_fourccs[i];
+       for (i = 0; (i < extra_nfourccs) && (fourccs < fourccs_end); ++i) {
+               u32 fourcc = extra_fourccs[i];
 
                if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) {
                        continue; /* skip duplicate and native entries */
                } else if (fourccs == fourccs_end) {
                        drm_warn(dev, "Ignoring emulated format %p4cc\n", &fourcc);
                        continue; /* end of available output buffer */
-               } else if (!is_conversion_supported(fourcc, native_format)) {
-                       drm_dbg_kms(dev, "Unsupported emulated format %p4cc\n", &fourcc);
-                       continue; /* format is not supported for conversion */
                }
 
                drm_dbg_kms(dev, "adding emulated format %p4cc\n", &fourcc);
index 1e658c4..df89fbd 100644 (file)
@@ -477,8 +477,8 @@ drm_gem_dma_prime_import_sg_table(struct drm_device *dev,
        dma_obj->dma_addr = sg_dma_address(sgt->sgl);
        dma_obj->sgt = sgt;
 
-       DRM_DEBUG_PRIME("dma_addr = %pad, size = %zu\n", &dma_obj->dma_addr,
-                       attach->dmabuf->size);
+       drm_dbg_prime(dev, "dma_addr = %pad, size = %zu\n", &dma_obj->dma_addr,
+                     attach->dmabuf->size);
 
        return &dma_obj->base;
 }
index f21f477..235832a 100644 (file)
@@ -766,7 +766,7 @@ drm_gem_shmem_prime_import_sg_table(struct drm_device *dev,
 
        shmem->sgt = sgt;
 
-       DRM_DEBUG_PRIME("size = %zu\n", size);
+       drm_dbg_prime(dev, "size = %zu\n", size);
 
        return &shmem->base;
 }
index 5d82891..49a743f 100644 (file)
@@ -972,6 +972,7 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        unsigned int nr = DRM_IOCTL_NR(cmd);
        struct drm_file *file_priv = filp->private_data;
+       struct drm_device *dev = file_priv->minor->dev;
        drm_ioctl_compat_t *fn;
        int ret;
 
@@ -986,14 +987,14 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        if (!fn)
                return drm_ioctl(filp, cmd, arg);
 
-       DRM_DEBUG("comm=\"%s\", pid=%d, dev=0x%lx, auth=%d, %s\n",
-                 current->comm, task_pid_nr(current),
-                 (long)old_encode_dev(file_priv->minor->kdev->devt),
-                 file_priv->authenticated,
-                 drm_compat_ioctls[nr].name);
+       drm_dbg_core(dev, "comm=\"%s\", pid=%d, dev=0x%lx, auth=%d, %s\n",
+                    current->comm, task_pid_nr(current),
+                    (long)old_encode_dev(file_priv->minor->kdev->devt),
+                    file_priv->authenticated,
+                    drm_compat_ioctls[nr].name);
        ret = (*fn)(filp, cmd, arg);
        if (ret)
-               DRM_DEBUG("ret = %d\n", ret);
+               drm_dbg_core(dev, "ret = %d\n", ret);
        return ret;
 }
 EXPORT_SYMBOL(drm_compat_ioctl);
index ca2a6e6..7c9d66e 100644 (file)
@@ -440,7 +440,7 @@ done:
 int drm_noop(struct drm_device *dev, void *data,
             struct drm_file *file_priv)
 {
-       DRM_DEBUG("\n");
+       drm_dbg_core(dev, "\n");
        return 0;
 }
 EXPORT_SYMBOL(drm_noop);
@@ -856,16 +856,16 @@ long drm_ioctl(struct file *filp,
                out_size = 0;
        ksize = max(max(in_size, out_size), drv_size);
 
-       DRM_DEBUG("comm=\"%s\" pid=%d, dev=0x%lx, auth=%d, %s\n",
-                 current->comm, task_pid_nr(current),
-                 (long)old_encode_dev(file_priv->minor->kdev->devt),
-                 file_priv->authenticated, ioctl->name);
+       drm_dbg_core(dev, "comm=\"%s\" pid=%d, dev=0x%lx, auth=%d, %s\n",
+                    current->comm, task_pid_nr(current),
+                    (long)old_encode_dev(file_priv->minor->kdev->devt),
+                    file_priv->authenticated, ioctl->name);
 
        /* Do not trust userspace, use our own definition */
        func = ioctl->func;
 
        if (unlikely(!func)) {
-               DRM_DEBUG("no function\n");
+               drm_dbg_core(dev, "no function\n");
                retcode = -EINVAL;
                goto err_i1;
        }
@@ -894,16 +894,17 @@ long drm_ioctl(struct file *filp,
 
       err_i1:
        if (!ioctl)
-               DRM_DEBUG("invalid ioctl: comm=\"%s\", pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
-                         current->comm, task_pid_nr(current),
-                         (long)old_encode_dev(file_priv->minor->kdev->devt),
-                         file_priv->authenticated, cmd, nr);
+               drm_dbg_core(dev,
+                            "invalid ioctl: comm=\"%s\", pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
+                            current->comm, task_pid_nr(current),
+                            (long)old_encode_dev(file_priv->minor->kdev->devt),
+                            file_priv->authenticated, cmd, nr);
 
        if (kdata != stack_kdata)
                kfree(kdata);
        if (retcode)
-               DRM_DEBUG("comm=\"%s\", pid=%d, ret=%d\n", current->comm,
-                         task_pid_nr(current), retcode);
+               drm_dbg_core(dev, "comm=\"%s\", pid=%d, ret=%d\n",
+                            current->comm, task_pid_nr(current), retcode);
        return retcode;
 }
 EXPORT_SYMBOL(drm_ioctl);
index d72c2fa..08ab753 100644 (file)
@@ -213,11 +213,11 @@ static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr
        int id;
        void *entry;
 
-       DRM_DEBUG_LEASE("lessor %d\n", lessor->lessee_id);
+       drm_dbg_lease(dev, "lessor %d\n", lessor->lessee_id);
 
        lessee = drm_master_create(lessor->dev);
        if (!lessee) {
-               DRM_DEBUG_LEASE("drm_master_create failed\n");
+               drm_dbg_lease(dev, "drm_master_create failed\n");
                return ERR_PTR(-ENOMEM);
        }
 
@@ -231,7 +231,7 @@ static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr
                        error = -EBUSY;
 
                if (error != 0) {
-                       DRM_DEBUG_LEASE("object %d failed %d\n", object, error);
+                       drm_dbg_lease(dev, "object %d failed %d\n", object, error);
                        goto out_lessee;
                }
        }
@@ -249,7 +249,8 @@ static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr
 
        /* Move the leases over */
        lessee->leases = *leases;
-       DRM_DEBUG_LEASE("new lessee %d %p, lessor %d %p\n", lessee->lessee_id, lessee, lessor->lessee_id, lessor);
+       drm_dbg_lease(dev, "new lessee %d %p, lessor %d %p\n",
+                     lessee->lessee_id, lessee, lessor->lessee_id, lessor);
 
        mutex_unlock(&dev->mode_config.idr_mutex);
        return lessee;
@@ -268,7 +269,7 @@ void drm_lease_destroy(struct drm_master *master)
 
        mutex_lock(&dev->mode_config.idr_mutex);
 
-       DRM_DEBUG_LEASE("drm_lease_destroy %d\n", master->lessee_id);
+       drm_dbg_lease(dev, "drm_lease_destroy %d\n", master->lessee_id);
 
        /* This master is referenced by all lessees, hence it cannot be destroyed
         * until all of them have been
@@ -277,7 +278,8 @@ void drm_lease_destroy(struct drm_master *master)
 
        /* Remove this master from the lessee idr in the owner */
        if (master->lessee_id != 0) {
-               DRM_DEBUG_LEASE("remove master %d from device list of lessees\n", master->lessee_id);
+               drm_dbg_lease(dev, "remove master %d from device list of lessees\n",
+                             master->lessee_id);
                idr_remove(&(drm_lease_owner(master)->lessee_idr), master->lessee_id);
        }
 
@@ -292,7 +294,7 @@ void drm_lease_destroy(struct drm_master *master)
                drm_master_put(&master->lessor);
        }
 
-       DRM_DEBUG_LEASE("drm_lease_destroy done %d\n", master->lessee_id);
+       drm_dbg_lease(dev, "drm_lease_destroy done %d\n", master->lessee_id);
 }
 
 static void _drm_lease_revoke(struct drm_master *top)
@@ -308,7 +310,8 @@ static void _drm_lease_revoke(struct drm_master *top)
         * the tree is fully connected, we can do this without recursing
         */
        for (;;) {
-               DRM_DEBUG_LEASE("revoke leases for %p %d\n", master, master->lessee_id);
+               drm_dbg_lease(master->dev, "revoke leases for %p %d\n",
+                             master, master->lessee_id);
 
                /* Evacuate the lease */
                idr_for_each_entry(&master->leases, entry, object)
@@ -408,7 +411,7 @@ static int fill_object_idr(struct drm_device *dev,
 
        ret = validate_lease(dev, object_count, objects, universal_planes);
        if (ret) {
-               DRM_DEBUG_LEASE("lease validation failed\n");
+               drm_dbg_lease(dev, "lease validation failed\n");
                goto out_free_objects;
        }
 
@@ -418,7 +421,7 @@ static int fill_object_idr(struct drm_device *dev,
                struct drm_mode_object *obj = objects[o];
                u32 object_id = objects[o]->id;
 
-               DRM_DEBUG_LEASE("Adding object %d to lease\n", object_id);
+               drm_dbg_lease(dev, "Adding object %d to lease\n", object_id);
 
                /*
                 * We're using an IDR to hold the set of leased
@@ -430,8 +433,8 @@ static int fill_object_idr(struct drm_device *dev,
                 */
                ret = idr_alloc(leases, &drm_lease_idr_object , object_id, object_id + 1, GFP_KERNEL);
                if (ret < 0) {
-                       DRM_DEBUG_LEASE("Object %d cannot be inserted into leases (%d)\n",
-                                       object_id, ret);
+                       drm_dbg_lease(dev, "Object %d cannot be inserted into leases (%d)\n",
+                                     object_id, ret);
                        goto out_free_objects;
                }
                if (obj->type == DRM_MODE_OBJECT_CRTC && !universal_planes) {
@@ -439,15 +442,15 @@ static int fill_object_idr(struct drm_device *dev,
 
                        ret = idr_alloc(leases, &drm_lease_idr_object, crtc->primary->base.id, crtc->primary->base.id + 1, GFP_KERNEL);
                        if (ret < 0) {
-                               DRM_DEBUG_LEASE("Object primary plane %d cannot be inserted into leases (%d)\n",
-                                               object_id, ret);
+                               drm_dbg_lease(dev, "Object primary plane %d cannot be inserted into leases (%d)\n",
+                                             object_id, ret);
                                goto out_free_objects;
                        }
                        if (crtc->cursor) {
                                ret = idr_alloc(leases, &drm_lease_idr_object, crtc->cursor->base.id, crtc->cursor->base.id + 1, GFP_KERNEL);
                                if (ret < 0) {
-                                       DRM_DEBUG_LEASE("Object cursor plane %d cannot be inserted into leases (%d)\n",
-                                                       object_id, ret);
+                                       drm_dbg_lease(dev, "Object cursor plane %d cannot be inserted into leases (%d)\n",
+                                                     object_id, ret);
                                        goto out_free_objects;
                                }
                        }
@@ -490,14 +493,14 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
                return -EOPNOTSUPP;
 
        if (cl->flags && (cl->flags & ~(O_CLOEXEC | O_NONBLOCK))) {
-               DRM_DEBUG_LEASE("invalid flags\n");
+               drm_dbg_lease(dev, "invalid flags\n");
                return -EINVAL;
        }
 
        lessor = drm_file_get_master(lessor_priv);
        /* Do not allow sub-leases */
        if (lessor->lessor) {
-               DRM_DEBUG_LEASE("recursive leasing not allowed\n");
+               drm_dbg_lease(dev, "recursive leasing not allowed\n");
                ret = -EINVAL;
                goto out_lessor;
        }
@@ -520,7 +523,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
                                      object_count, object_ids);
                kfree(object_ids);
                if (ret) {
-                       DRM_DEBUG_LEASE("lease object lookup failed: %i\n", ret);
+                       drm_dbg_lease(dev, "lease object lookup failed: %i\n", ret);
                        idr_destroy(&leases);
                        goto out_lessor;
                }
@@ -534,7 +537,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
                goto out_lessor;
        }
 
-       DRM_DEBUG_LEASE("Creating lease\n");
+       drm_dbg_lease(dev, "Creating lease\n");
        /* lessee will take the ownership of leases */
        lessee = drm_lease_create(lessor, &leases);
 
@@ -545,7 +548,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
        }
 
        /* Clone the lessor file to create a new file for us */
-       DRM_DEBUG_LEASE("Allocating lease file\n");
+       drm_dbg_lease(dev, "Allocating lease file\n");
        lessee_file = file_clone_open(lessor_file);
        if (IS_ERR(lessee_file)) {
                ret = PTR_ERR(lessee_file);
@@ -560,7 +563,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
        lessee_priv->authenticated = 1;
 
        /* Pass fd back to userspace */
-       DRM_DEBUG_LEASE("Returning fd %d id %d\n", fd, lessee->lessee_id);
+       drm_dbg_lease(dev, "Returning fd %d id %d\n", fd, lessee->lessee_id);
        cl->fd = fd;
        cl->lessee_id = lessee->lessee_id;
 
@@ -568,7 +571,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
        fd_install(fd, lessee_file);
 
        drm_master_put(&lessor);
-       DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl succeeded\n");
+       drm_dbg_lease(dev, "drm_mode_create_lease_ioctl succeeded\n");
        return 0;
 
 out_lessee:
@@ -579,7 +582,7 @@ out_leases:
 
 out_lessor:
        drm_master_put(&lessor);
-       DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl failed: %d\n", ret);
+       drm_dbg_lease(dev, "drm_mode_create_lease_ioctl failed: %d\n", ret);
        return ret;
 }
 
@@ -601,7 +604,7 @@ int drm_mode_list_lessees_ioctl(struct drm_device *dev,
                return -EOPNOTSUPP;
 
        lessor = drm_file_get_master(lessor_priv);
-       DRM_DEBUG_LEASE("List lessees for %d\n", lessor->lessee_id);
+       drm_dbg_lease(dev, "List lessees for %d\n", lessor->lessee_id);
 
        mutex_lock(&dev->mode_config.idr_mutex);
 
@@ -610,7 +613,8 @@ int drm_mode_list_lessees_ioctl(struct drm_device *dev,
                /* Only list un-revoked leases */
                if (!idr_is_empty(&lessee->leases)) {
                        if (count_lessees > count) {
-                               DRM_DEBUG_LEASE("Add lessee %d\n", lessee->lessee_id);
+                               drm_dbg_lease(dev, "Add lessee %d\n",
+                                             lessee->lessee_id);
                                ret = put_user(lessee->lessee_id, lessee_ids + count);
                                if (ret)
                                        break;
@@ -619,7 +623,7 @@ int drm_mode_list_lessees_ioctl(struct drm_device *dev,
                }
        }
 
-       DRM_DEBUG_LEASE("Lessor leases to %d\n", count);
+       drm_dbg_lease(dev, "Lessor leases to %d\n", count);
        if (ret == 0)
                arg->count_lessees = count;
 
@@ -651,7 +655,7 @@ int drm_mode_get_lease_ioctl(struct drm_device *dev,
                return -EOPNOTSUPP;
 
        lessee = drm_file_get_master(lessee_priv);
-       DRM_DEBUG_LEASE("get lease for %d\n", lessee->lessee_id);
+       drm_dbg_lease(dev, "get lease for %d\n", lessee->lessee_id);
 
        mutex_lock(&dev->mode_config.idr_mutex);
 
@@ -665,7 +669,7 @@ int drm_mode_get_lease_ioctl(struct drm_device *dev,
        count = 0;
        idr_for_each_entry(object_idr, entry, object) {
                if (count_objects > count) {
-                       DRM_DEBUG_LEASE("adding object %d\n", object);
+                       drm_dbg_lease(dev, "adding object %d\n", object);
                        ret = put_user(object, object_ids + count);
                        if (ret)
                                break;
@@ -696,7 +700,7 @@ int drm_mode_revoke_lease_ioctl(struct drm_device *dev,
        struct drm_master *lessee;
        int ret = 0;
 
-       DRM_DEBUG_LEASE("revoke lease for %d\n", arg->lessee_id);
+       drm_dbg_lease(dev, "revoke lease for %d\n", arg->lessee_id);
 
        /* Can't lease without MODESET */
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
index 3335762..24e7998 100644 (file)
  * properties that specify how the pixels are positioned and blended, like
  * rotation or Z-position. All these properties are stored in &drm_plane_state.
  *
+ * Unless explicitly specified (via CRTC property or otherwise), the active area
+ * of a CRTC will be black by default. This means portions of the active area
+ * which are not covered by a plane will be black, and alpha blending of any
+ * planes with the CRTC background will blend with black at the lowest zpos.
+ *
  * To create a plane, a KMS drivers allocates and zeroes an instances of
  * &struct drm_plane (possibly as part of a larger structure) and registers it
  * with a call to drm_universal_plane_init().
index 1ea053c..7973f25 100644 (file)
@@ -250,6 +250,12 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
 
        drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
+               const struct drm_connector_helper_funcs *funcs =
+                       connector->helper_private;
+
+               if (funcs && funcs->enable_hpd)
+                       funcs->enable_hpd(connector);
+
                if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
                                         DRM_CONNECTOR_POLL_DISCONNECT))
                        poll = true;
@@ -802,6 +808,30 @@ bool drm_kms_helper_is_poll_worker(void)
 }
 EXPORT_SYMBOL(drm_kms_helper_is_poll_worker);
 
+static void drm_kms_helper_poll_disable_fini(struct drm_device *dev, bool fini)
+{
+       struct drm_connector *connector;
+       struct drm_connector_list_iter conn_iter;
+
+       if (!dev->mode_config.poll_enabled)
+               return;
+
+       if (fini)
+               dev->mode_config.poll_enabled = false;
+
+       drm_connector_list_iter_begin(dev, &conn_iter);
+       drm_for_each_connector_iter(connector, &conn_iter) {
+               const struct drm_connector_helper_funcs *funcs =
+                       connector->helper_private;
+
+               if (funcs && funcs->disable_hpd)
+                       funcs->disable_hpd(connector);
+       }
+       drm_connector_list_iter_end(&conn_iter);
+
+       cancel_delayed_work_sync(&dev->mode_config.output_poll_work);
+}
+
 /**
  * drm_kms_helper_poll_disable - disable output polling
  * @dev: drm_device
@@ -818,9 +848,7 @@ EXPORT_SYMBOL(drm_kms_helper_is_poll_worker);
  */
 void drm_kms_helper_poll_disable(struct drm_device *dev)
 {
-       if (!dev->mode_config.poll_enabled)
-               return;
-       cancel_delayed_work_sync(&dev->mode_config.output_poll_work);
+       drm_kms_helper_poll_disable_fini(dev, false);
 }
 EXPORT_SYMBOL(drm_kms_helper_poll_disable);
 
@@ -858,11 +886,7 @@ EXPORT_SYMBOL(drm_kms_helper_poll_init);
  */
 void drm_kms_helper_poll_fini(struct drm_device *dev)
 {
-       if (!dev->mode_config.poll_enabled)
-               return;
-
-       dev->mode_config.poll_enabled = false;
-       cancel_delayed_work_sync(&dev->mode_config.output_poll_work);
+       drm_kms_helper_poll_disable_fini(dev, true);
 }
 EXPORT_SYMBOL(drm_kms_helper_poll_fini);
 
index 807b989..2efc0eb 100644 (file)
@@ -3,6 +3,8 @@ config DRM_GMA500
        tristate "Intel GMA500/600/3600/3650 KMS Framebuffer"
        depends on DRM && PCI && X86 && MMU
        select DRM_KMS_HELPER
+       select I2C
+       select I2C_ALGOBIT
        # GMA500 depends on ACPI_VIDEO when ACPI is enabled, just like i915
        select ACPI_VIDEO if ACPI
        select BACKLIGHT_CLASS_DEVICE if ACPI
index 5aac7cd..9d7bf8e 100644 (file)
@@ -325,8 +325,8 @@ static struct drm_gem_object *gud_gem_prime_import(struct drm_device *drm, struc
 
 static int gud_stats_debugfs(struct seq_file *m, void *data)
 {
-       struct drm_info_node *node = m->private;
-       struct gud_device *gdrm = to_gud_device(node->minor->dev);
+       struct drm_debugfs_entry *entry = m->private;
+       struct gud_device *gdrm = to_gud_device(entry->dev);
        char buf[10];
 
        string_get_size(gdrm->bulk_len, 1, STRING_UNITS_2, buf, sizeof(buf));
@@ -352,16 +352,6 @@ static int gud_stats_debugfs(struct seq_file *m, void *data)
        return 0;
 }
 
-static const struct drm_info_list gud_debugfs_list[] = {
-       { "stats", gud_stats_debugfs, 0, NULL },
-};
-
-static void gud_debugfs_init(struct drm_minor *minor)
-{
-       drm_debugfs_create_files(gud_debugfs_list, ARRAY_SIZE(gud_debugfs_list),
-                                minor->debugfs_root, minor);
-}
-
 static const struct drm_simple_display_pipe_funcs gud_pipe_funcs = {
        .check      = gud_pipe_check,
        .update     = gud_pipe_update,
@@ -386,7 +376,6 @@ static const struct drm_driver gud_drm_driver = {
        .fops                   = &gud_fops,
        DRM_GEM_SHMEM_DRIVER_OPS,
        .gem_prime_import       = gud_gem_prime_import,
-       .debugfs_init           = gud_debugfs_init,
 
        .name                   = "gud",
        .desc                   = "Generic USB Display",
@@ -623,6 +612,8 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
        if (!gdrm->dmadev)
                dev_warn(dev, "buffer sharing not supported");
 
+       drm_debugfs_add_file(drm, "stats", gud_stats_debugfs, NULL);
+
        ret = drm_dev_register(drm, 0);
        if (ret) {
                put_device(gdrm->dmadev);
index 4e41c14..1265043 100644 (file)
@@ -7,6 +7,8 @@ config DRM_HISI_HIBMC
        select DRM_VRAM_HELPER
        select DRM_TTM
        select DRM_TTM_HELPER
+       select I2C
+       select I2C_ALGOBIT
        help
          Choose this option if you have a Hisilicon Hibmc soc chipset.
          If M is selected the module will be called hibmc-drm.
index b978821..923389f 100644 (file)
@@ -386,7 +386,7 @@ static const struct drm_encoder_slave_funcs ch7006_encoder_funcs = {
 
 /* I2C driver functions */
 
-static int ch7006_probe(struct i2c_client *client, const struct i2c_device_id *id)
+static int ch7006_probe(struct i2c_client *client)
 {
        uint8_t addr = CH7006_VERSION_ID;
        uint8_t val;
@@ -495,7 +495,7 @@ static const struct dev_pm_ops ch7006_pm_ops = {
 
 static struct drm_i2c_encoder_driver ch7006_driver = {
        .i2c_driver = {
-               .probe = ch7006_probe,
+               .probe_new = ch7006_probe,
                .remove = ch7006_remove,
 
                .driver = {
index 1bc0b5d..f57f9a8 100644 (file)
@@ -350,7 +350,7 @@ static const struct drm_encoder_slave_funcs sil164_encoder_funcs = {
 /* I2C driver functions */
 
 static int
-sil164_probe(struct i2c_client *client, const struct i2c_device_id *id)
+sil164_probe(struct i2c_client *client)
 {
        int vendor = sil164_read(client, SIL164_VENDOR_HI) << 8 |
                sil164_read(client, SIL164_VENDOR_LO);
@@ -420,7 +420,7 @@ MODULE_DEVICE_TABLE(i2c, sil164_ids);
 
 static struct drm_i2c_encoder_driver sil164_driver = {
        .i2c_driver = {
-               .probe = sil164_probe,
+               .probe_new = sil164_probe,
                .driver = {
                        .name = "sil164",
                },
index 9ed54e7..b8c143e 100644 (file)
@@ -375,8 +375,7 @@ static void tda9950_cec_del(void *data)
        cec_delete_adapter(priv->adap);
 }
 
-static int tda9950_probe(struct i2c_client *client,
-                        const struct i2c_device_id *id)
+static int tda9950_probe(struct i2c_client *client)
 {
        struct tda9950_glue *glue = client->dev.platform_data;
        struct device *dev = &client->dev;
@@ -493,7 +492,7 @@ static struct i2c_device_id tda9950_ids[] = {
 MODULE_DEVICE_TABLE(i2c, tda9950_ids);
 
 static struct i2c_driver tda9950_driver = {
-       .probe = tda9950_probe,
+       .probe_new = tda9950_probe,
        .remove = tda9950_remove,
        .driver = {
                .name = "tda9950",
index a14d289..db5c934 100644 (file)
@@ -2059,7 +2059,7 @@ static const struct component_ops tda998x_ops = {
 };
 
 static int
-tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id)
+tda998x_probe(struct i2c_client *client)
 {
        int ret;
 
@@ -2099,7 +2099,7 @@ static const struct i2c_device_id tda998x_ids[] = {
 MODULE_DEVICE_TABLE(i2c, tda998x_ids);
 
 static struct i2c_driver tda998x_driver = {
-       .probe = tda998x_probe,
+       .probe_new = tda998x_probe,
        .remove = tda998x_remove,
        .driver = {
                .name = "tda998x",
index 3efce05..c6e3792 100644 (file)
@@ -18,6 +18,8 @@ config DRM_I915
        select DRM_PANEL
        select DRM_MIPI_DSI
        select RELAY
+       select I2C
+       select I2C_ALGOBIT
        select IRQ_WORK
        # i915 depends on ACPI_VIDEO when ACPI is enabled
        # but for select to work, need to select ACPI_VIDEO's dependencies, ick
index 66d9233..5d1779a 100644 (file)
@@ -253,11 +253,8 @@ static int dcss_dev_suspend(struct device *dev)
 {
        struct dcss_dev *dcss = dcss_drv_dev_to_dcss(dev);
        struct drm_device *ddev = dcss_drv_dev_to_drm(dev);
-       struct dcss_kms_dev *kms = container_of(ddev, struct dcss_kms_dev, base);
        int ret;
 
-       drm_bridge_connector_disable_hpd(kms->connector);
-
        drm_mode_config_helper_suspend(ddev);
 
        if (pm_runtime_suspended(dev))
@@ -276,7 +273,6 @@ static int dcss_dev_resume(struct device *dev)
 {
        struct dcss_dev *dcss = dcss_drv_dev_to_dcss(dev);
        struct drm_device *ddev = dcss_drv_dev_to_drm(dev);
-       struct dcss_kms_dev *kms = container_of(ddev, struct dcss_kms_dev, base);
 
        if (pm_runtime_suspended(dev)) {
                drm_mode_config_helper_resume(ddev);
@@ -291,8 +287,6 @@ static int dcss_dev_resume(struct device *dev)
 
        drm_mode_config_helper_resume(ddev);
 
-       drm_bridge_connector_enable_hpd(kms->connector);
-
        return 0;
 }
 
index 431510b..4f22916 100644 (file)
@@ -74,8 +74,6 @@ static int dcss_drv_platform_probe(struct platform_device *pdev)
 dcss_shutoff:
        dcss_dev_destroy(mdrv->dcss);
 
-       dev_set_drvdata(dev, NULL);
-
 err:
        kfree(mdrv);
        return err;
@@ -85,14 +83,9 @@ static int dcss_drv_platform_remove(struct platform_device *pdev)
 {
        struct dcss_drv *mdrv = dev_get_drvdata(&pdev->dev);
 
-       if (!mdrv)
-               return 0;
-
        dcss_kms_detach(mdrv->kms);
        dcss_dev_destroy(mdrv->dcss);
 
-       dev_set_drvdata(&pdev->dev, NULL);
-
        kfree(mdrv);
 
        return 0;
index 18df388..dab5e66 100644 (file)
@@ -150,7 +150,6 @@ struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss)
        return kms;
 
 cleanup_crtc:
-       drm_bridge_connector_disable_hpd(kms->connector);
        drm_kms_helper_poll_fini(drm);
        dcss_crtc_deinit(crtc, drm);
 
@@ -166,7 +165,6 @@ void dcss_kms_detach(struct dcss_kms_dev *kms)
        struct drm_device *drm = &kms->base;
 
        drm_dev_unregister(drm);
-       drm_bridge_connector_disable_hpd(kms->connector);
        drm_kms_helper_poll_fini(drm);
        drm_atomic_helper_shutdown(drm);
        drm_crtc_vblank_off(&kms->crtc.base);
index 7642f74..534621a 100644 (file)
@@ -718,7 +718,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
        dw_plat_data = &meson_dw_hdmi->dw_plat_data;
 
        ret = devm_regulator_get_enable_optional(dev, "hdmi");
-       if (ret != -ENODEV)
+       if (ret < 0)
                return ret;
 
        meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev,
index eec5965..b28c5e4 100644 (file)
@@ -4,6 +4,8 @@ config DRM_MGAG200
        depends on DRM && PCI && MMU
        select DRM_GEM_SHMEM_HELPER
        select DRM_KMS_HELPER
+       select I2C
+       select I2C_ALGOBIT
        help
         This is a KMS driver for Matrox G200 chips. It supports the original
         MGA G200 desktop chips and the server variants. It requires 0.3.0
index 4d3fdc8..c373a40 100644 (file)
@@ -203,8 +203,6 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
                goto fail;
        }
 
-       drm_bridge_connector_enable_hpd(hdmi->connector);
-
        ret = msm_hdmi_hpd_enable(hdmi->bridge);
        if (ret < 0) {
                DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);
index 810edea..b3ab86a 100644 (file)
@@ -78,14 +78,12 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
 
 void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb)
 {
-       if (mxsfb->clk_axi)
-               clk_prepare_enable(mxsfb->clk_axi);
+       clk_prepare_enable(mxsfb->clk_axi);
 }
 
 void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb)
 {
-       if (mxsfb->clk_axi)
-               clk_disable_unprepare(mxsfb->clk_axi);
+       clk_disable_unprepare(mxsfb->clk_axi);
 }
 
 static struct drm_framebuffer *
@@ -235,9 +233,9 @@ static int mxsfb_load(struct drm_device *drm,
        if (IS_ERR(mxsfb->clk))
                return PTR_ERR(mxsfb->clk);
 
-       mxsfb->clk_axi = devm_clk_get(drm->dev, "axi");
+       mxsfb->clk_axi = devm_clk_get_optional(drm->dev, "axi");
        if (IS_ERR(mxsfb->clk_axi))
-               mxsfb->clk_axi = NULL;
+               return PTR_ERR(mxsfb->clk_axi);
 
        mxsfb->clk_disp_axi = devm_clk_get(drm->dev, "disp_axi");
        if (IS_ERR(mxsfb->clk_disp_axi))
index 03d12ca..a0bb398 100644 (file)
@@ -10,6 +10,8 @@ config DRM_NOUVEAU
        select DRM_KMS_HELPER
        select DRM_TTM
        select DRM_TTM_HELPER
+       select I2C
+       select I2C_ALGOBIT
        select BACKLIGHT_CLASS_DEVICE if DRM_NOUVEAU_BACKLIGHT
        select X86_PLATFORM_DEVICES if ACPI && X86
        select ACPI_WMI if ACPI && X86
index eaf67b9..699ed81 100644 (file)
@@ -545,44 +545,6 @@ static void omap_modeset_fini(struct drm_device *ddev)
        drm_mode_config_cleanup(ddev);
 }
 
-/*
- * Enable the HPD in external components if supported
- */
-static void omap_modeset_enable_external_hpd(struct drm_device *ddev)
-{
-       struct omap_drm_private *priv = ddev->dev_private;
-       unsigned int i;
-
-       for (i = 0; i < priv->num_pipes; i++) {
-               struct drm_connector *connector = priv->pipes[i].connector;
-
-               if (!connector)
-                       continue;
-
-               if (priv->pipes[i].output->bridge)
-                       drm_bridge_connector_enable_hpd(connector);
-       }
-}
-
-/*
- * Disable the HPD in external components if supported
- */
-static void omap_modeset_disable_external_hpd(struct drm_device *ddev)
-{
-       struct omap_drm_private *priv = ddev->dev_private;
-       unsigned int i;
-
-       for (i = 0; i < priv->num_pipes; i++) {
-               struct drm_connector *connector = priv->pipes[i].connector;
-
-               if (!connector)
-                       continue;
-
-               if (priv->pipes[i].output->bridge)
-                       drm_bridge_connector_disable_hpd(connector);
-       }
-}
-
 /*
  * drm ioctl funcs
  */
@@ -782,7 +744,6 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev)
        omap_fbdev_init(ddev);
 
        drm_kms_helper_poll_init(ddev);
-       omap_modeset_enable_external_hpd(ddev);
 
        /*
         * Register the DRM device with the core and the connectors with
@@ -795,7 +756,6 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev)
        return 0;
 
 err_cleanup_helpers:
-       omap_modeset_disable_external_hpd(ddev);
        drm_kms_helper_poll_fini(ddev);
 
        omap_fbdev_fini(ddev);
@@ -822,7 +782,6 @@ static void omapdrm_cleanup(struct omap_drm_private *priv)
 
        drm_dev_unregister(ddev);
 
-       omap_modeset_disable_external_hpd(ddev);
        drm_kms_helper_poll_fini(ddev);
 
        omap_fbdev_fini(ddev);
index 114758f..dd79928 100644 (file)
@@ -154,6 +154,18 @@ config DRM_PANEL_FEIYANG_FY07024DI26A30D
          Say Y if you want to enable support for panels based on the
          Feiyang FY07024DI26A30-D MIPI-DSI interface.
 
+config DRM_PANEL_HIMAX_HX8394
+       tristate "HIMAX HX8394 MIPI-DSI LCD panels"
+       depends on OF
+       depends on DRM_MIPI_DSI
+       depends on BACKLIGHT_CLASS_DEVICE
+       help
+         Say Y if you want to enable support for panels based on the
+         Himax HX8394 controller, such as the HannStar HSD060BHW4
+         720x1440 TFT LCD panel that uses a MIPI-DSI interface.
+
+         If M is selected the module will be called panel-himax-hx8394.
+
 config DRM_PANEL_ILITEK_IL9322
        tristate "Ilitek ILI9322 320x240 QVGA panels"
        depends on OF && SPI
@@ -726,6 +738,14 @@ config DRM_PANEL_VISIONOX_RM69299
          Say Y here if you want to enable support for Visionox
          RM69299  DSI Video Mode panel.
 
+config DRM_PANEL_VISIONOX_VTDR6130
+       tristate "Visionox VTDR6130"
+       depends on OF
+       depends on DRM_MIPI_DSI
+       help
+         Say Y here if you want to enable support for Visionox
+         VTDR6130 1080x2400 AMOLED DSI panel.
+
 config DRM_PANEL_WIDECHIPS_WS2401
        tristate "Widechips WS2401 DPI panel driver"
        depends on SPI && GPIOLIB
index ddcf8df..d07e6fa 100644 (file)
@@ -13,6 +13,7 @@ obj-$(CONFIG_DRM_PANEL_EBBG_FT8719) += panel-ebbg-ft8719.o
 obj-$(CONFIG_DRM_PANEL_ELIDA_KD35T133) += panel-elida-kd35t133.o
 obj-$(CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02) += panel-feixin-k101-im2ba02.o
 obj-$(CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D) += panel-feiyang-fy07024di26a30d.o
+obj-$(CONFIG_DRM_PANEL_HIMAX_HX8394) += panel-himax-hx8394.o
 obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o
 obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9341) += panel-ilitek-ili9341.o
 obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o
@@ -74,5 +75,6 @@ obj-$(CONFIG_DRM_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
 obj-$(CONFIG_DRM_PANEL_TPO_TPG110) += panel-tpo-tpg110.o
 obj-$(CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA) += panel-truly-nt35597.o
 obj-$(CONFIG_DRM_PANEL_VISIONOX_RM69299) += panel-visionox-rm69299.o
+obj-$(CONFIG_DRM_PANEL_VISIONOX_VTDR6130) += panel-visionox-vtdr6130.o
 obj-$(CONFIG_DRM_PANEL_WIDECHIPS_WS2401) += panel-widechips-ws2401.o
 obj-$(CONFIG_DRM_PANEL_XINPENG_XPP055C272) += panel-xinpeng-xpp055c272.o
index b323578..075a7af 100644 (file)
@@ -24,22 +24,6 @@ static inline struct tm5p5_nt35596 *to_tm5p5_nt35596(struct drm_panel *panel)
        return container_of(panel, struct tm5p5_nt35596, panel);
 }
 
-#define dsi_generic_write_seq(dsi, seq...) do {                                \
-               static const u8 d[] = { seq };                          \
-               int ret;                                                \
-               ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));    \
-               if (ret < 0)                                            \
-                       return ret;                                     \
-       } while (0)
-
-#define dsi_dcs_write_seq(dsi, seq...) do {                            \
-               static const u8 d[] = { seq };                          \
-               int ret;                                                \
-               ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
-               if (ret < 0)                                            \
-                       return ret;                                     \
-       } while (0)
-
 static void tm5p5_nt35596_reset(struct tm5p5_nt35596 *ctx)
 {
        gpiod_set_value_cansleep(ctx->reset_gpio, 1);
@@ -54,46 +38,46 @@ static int tm5p5_nt35596_on(struct tm5p5_nt35596 *ctx)
 {
        struct mipi_dsi_device *dsi = ctx->dsi;
 
-       dsi_generic_write_seq(dsi, 0xff, 0x05);
-       dsi_generic_write_seq(dsi, 0xfb, 0x01);
-       dsi_generic_write_seq(dsi, 0xc5, 0x31);
-       dsi_generic_write_seq(dsi, 0xff, 0x04);
-       dsi_generic_write_seq(dsi, 0x01, 0x84);
-       dsi_generic_write_seq(dsi, 0x05, 0x25);
-       dsi_generic_write_seq(dsi, 0x06, 0x01);
-       dsi_generic_write_seq(dsi, 0x07, 0x20);
-       dsi_generic_write_seq(dsi, 0x08, 0x06);
-       dsi_generic_write_seq(dsi, 0x09, 0x08);
-       dsi_generic_write_seq(dsi, 0x0a, 0x10);
-       dsi_generic_write_seq(dsi, 0x0b, 0x10);
-       dsi_generic_write_seq(dsi, 0x0c, 0x10);
-       dsi_generic_write_seq(dsi, 0x0d, 0x14);
-       dsi_generic_write_seq(dsi, 0x0e, 0x14);
-       dsi_generic_write_seq(dsi, 0x0f, 0x14);
-       dsi_generic_write_seq(dsi, 0x10, 0x14);
-       dsi_generic_write_seq(dsi, 0x11, 0x14);
-       dsi_generic_write_seq(dsi, 0x12, 0x14);
-       dsi_generic_write_seq(dsi, 0x17, 0xf3);
-       dsi_generic_write_seq(dsi, 0x18, 0xc0);
-       dsi_generic_write_seq(dsi, 0x19, 0xc0);
-       dsi_generic_write_seq(dsi, 0x1a, 0xc0);
-       dsi_generic_write_seq(dsi, 0x1b, 0xb3);
-       dsi_generic_write_seq(dsi, 0x1c, 0xb3);
-       dsi_generic_write_seq(dsi, 0x1d, 0xb3);
-       dsi_generic_write_seq(dsi, 0x1e, 0xb3);
-       dsi_generic_write_seq(dsi, 0x1f, 0xb3);
-       dsi_generic_write_seq(dsi, 0x20, 0xb3);
-       dsi_generic_write_seq(dsi, 0xfb, 0x01);
-       dsi_generic_write_seq(dsi, 0xff, 0x00);
-       dsi_generic_write_seq(dsi, 0xfb, 0x01);
-       dsi_generic_write_seq(dsi, 0x35, 0x01);
-       dsi_generic_write_seq(dsi, 0xd3, 0x06);
-       dsi_generic_write_seq(dsi, 0xd4, 0x04);
-       dsi_generic_write_seq(dsi, 0x5e, 0x0d);
-       dsi_generic_write_seq(dsi, 0x11, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xff, 0x05);
+       mipi_dsi_generic_write_seq(dsi, 0xfb, 0x01);
+       mipi_dsi_generic_write_seq(dsi, 0xc5, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xff, 0x04);
+       mipi_dsi_generic_write_seq(dsi, 0x01, 0x84);
+       mipi_dsi_generic_write_seq(dsi, 0x05, 0x25);
+       mipi_dsi_generic_write_seq(dsi, 0x06, 0x01);
+       mipi_dsi_generic_write_seq(dsi, 0x07, 0x20);
+       mipi_dsi_generic_write_seq(dsi, 0x08, 0x06);
+       mipi_dsi_generic_write_seq(dsi, 0x09, 0x08);
+       mipi_dsi_generic_write_seq(dsi, 0x0a, 0x10);
+       mipi_dsi_generic_write_seq(dsi, 0x0b, 0x10);
+       mipi_dsi_generic_write_seq(dsi, 0x0c, 0x10);
+       mipi_dsi_generic_write_seq(dsi, 0x0d, 0x14);
+       mipi_dsi_generic_write_seq(dsi, 0x0e, 0x14);
+       mipi_dsi_generic_write_seq(dsi, 0x0f, 0x14);
+       mipi_dsi_generic_write_seq(dsi, 0x10, 0x14);
+       mipi_dsi_generic_write_seq(dsi, 0x11, 0x14);
+       mipi_dsi_generic_write_seq(dsi, 0x12, 0x14);
+       mipi_dsi_generic_write_seq(dsi, 0x17, 0xf3);
+       mipi_dsi_generic_write_seq(dsi, 0x18, 0xc0);
+       mipi_dsi_generic_write_seq(dsi, 0x19, 0xc0);
+       mipi_dsi_generic_write_seq(dsi, 0x1a, 0xc0);
+       mipi_dsi_generic_write_seq(dsi, 0x1b, 0xb3);
+       mipi_dsi_generic_write_seq(dsi, 0x1c, 0xb3);
+       mipi_dsi_generic_write_seq(dsi, 0x1d, 0xb3);
+       mipi_dsi_generic_write_seq(dsi, 0x1e, 0xb3);
+       mipi_dsi_generic_write_seq(dsi, 0x1f, 0xb3);
+       mipi_dsi_generic_write_seq(dsi, 0x20, 0xb3);
+       mipi_dsi_generic_write_seq(dsi, 0xfb, 0x01);
+       mipi_dsi_generic_write_seq(dsi, 0xff, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xfb, 0x01);
+       mipi_dsi_generic_write_seq(dsi, 0x35, 0x01);
+       mipi_dsi_generic_write_seq(dsi, 0xd3, 0x06);
+       mipi_dsi_generic_write_seq(dsi, 0xd4, 0x04);
+       mipi_dsi_generic_write_seq(dsi, 0x5e, 0x0d);
+       mipi_dsi_generic_write_seq(dsi, 0x11, 0x00);
        msleep(100);
-       dsi_generic_write_seq(dsi, 0x29, 0x00);
-       dsi_generic_write_seq(dsi, 0x53, 0x24);
+       mipi_dsi_generic_write_seq(dsi, 0x29, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0x53, 0x24);
 
        return 0;
 }
@@ -117,7 +101,7 @@ static int tm5p5_nt35596_off(struct tm5p5_nt35596 *ctx)
                return ret;
        }
 
-       dsi_dcs_write_seq(dsi, 0x4f, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x4f, 0x01);
 
        return 0;
 }
index ad58840..90098b7 100644 (file)
@@ -43,14 +43,6 @@ struct boe_bf060y8m_aj0 *to_boe_bf060y8m_aj0(struct drm_panel *panel)
        return container_of(panel, struct boe_bf060y8m_aj0, panel);
 }
 
-#define dsi_dcs_write_seq(dsi, seq...) do {                            \
-               static const u8 d[] = { seq };                          \
-               int ret;                                                \
-               ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
-               if (ret < 0)                                            \
-                       return ret;                                     \
-       } while (0)
-
 static void boe_bf060y8m_aj0_reset(struct boe_bf060y8m_aj0 *boe)
 {
        gpiod_set_value_cansleep(boe->reset_gpio, 0);
@@ -67,12 +59,12 @@ static int boe_bf060y8m_aj0_on(struct boe_bf060y8m_aj0 *boe)
        struct device *dev = &dsi->dev;
        int ret;
 
-       dsi_dcs_write_seq(dsi, 0xb0, 0xa5, 0x00);
-       dsi_dcs_write_seq(dsi, 0xb2, 0x00, 0x4c);
-       dsi_dcs_write_seq(dsi, MIPI_DCS_SET_3D_CONTROL, 0x10);
-       dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, DCS_ALLOW_HBM_RANGE);
-       dsi_dcs_write_seq(dsi, 0xf8,
-                         0x00, 0x08, 0x10, 0x00, 0x22, 0x00, 0x00, 0x2d);
+       mipi_dsi_dcs_write_seq(dsi, 0xb0, 0xa5, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x00, 0x4c);
+       mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_3D_CONTROL, 0x10);
+       mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, DCS_ALLOW_HBM_RANGE);
+       mipi_dsi_dcs_write_seq(dsi, 0xf8,
+                              0x00, 0x08, 0x10, 0x00, 0x22, 0x00, 0x00, 0x2d);
 
        ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
        if (ret < 0) {
@@ -81,17 +73,17 @@ static int boe_bf060y8m_aj0_on(struct boe_bf060y8m_aj0 *boe)
        }
        msleep(30);
 
-       dsi_dcs_write_seq(dsi, 0xb0, 0xa5, 0x00);
-       dsi_dcs_write_seq(dsi, 0xc0,
-                         0x08, 0x48, 0x65, 0x33, 0x33, 0x33,
-                         0x2a, 0x31, 0x39, 0x20, 0x09);
-       dsi_dcs_write_seq(dsi, 0xc1, 0x00, 0x00, 0x00, 0x1f, 0x1f,
-                         0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
-                         0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
-       dsi_dcs_write_seq(dsi, 0xe2, 0x20, 0x04, 0x10, 0x12, 0x92,
-                         0x4f, 0x8f, 0x44, 0x84, 0x83, 0x83, 0x83,
-                         0x5c, 0x5c, 0x5c);
-       dsi_dcs_write_seq(dsi, 0xde, 0x01, 0x2c, 0x00, 0x77, 0x3e);
+       mipi_dsi_dcs_write_seq(dsi, 0xb0, 0xa5, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xc0,
+                              0x08, 0x48, 0x65, 0x33, 0x33, 0x33,
+                              0x2a, 0x31, 0x39, 0x20, 0x09);
+       mipi_dsi_dcs_write_seq(dsi, 0xc1, 0x00, 0x00, 0x00, 0x1f, 0x1f,
+                              0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+                              0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
+       mipi_dsi_dcs_write_seq(dsi, 0xe2, 0x20, 0x04, 0x10, 0x12, 0x92,
+                              0x4f, 0x8f, 0x44, 0x84, 0x83, 0x83, 0x83,
+                              0x5c, 0x5c, 0x5c);
+       mipi_dsi_dcs_write_seq(dsi, 0xde, 0x01, 0x2c, 0x00, 0x77, 0x3e);
 
        msleep(30);
 
index a0a7ab3..01bfe07 100644 (file)
@@ -1891,7 +1891,8 @@ static const struct edp_panel_entry edp_panels[] = {
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x1247, &delay_200_500_e80_d50, "N120ACA-EA1"),
 
        EDP_PANEL_ENTRY('I', 'V', 'O', 0x057d, &delay_200_500_e200, "R140NWF5 RH"),
-       EDP_PANEL_ENTRY('I', 'V', 'O', 0x854b, &delay_200_500_p2e100, "M133NW4J-R3"),
+       EDP_PANEL_ENTRY('I', 'V', 'O', 0x854a, &delay_200_500_p2e100, "M133NW4J"),
+       EDP_PANEL_ENTRY('I', 'V', 'O', 0x854b, &delay_200_500_p2e100, "R133NW4K-R0"),
 
        EDP_PANEL_ENTRY('K', 'D', 'B', 0x0624, &kingdisplay_kd116n21_30nv_a010.delay, "116N21-30NV-A010"),
        EDP_PANEL_ENTRY('K', 'D', 'B', 0x1120, &delay_200_500_e80_d50, "116N29-30NK-C007"),
index eee714c..e7be15b 100644 (file)
@@ -51,14 +51,6 @@ static inline struct kd35t133 *panel_to_kd35t133(struct drm_panel *panel)
        return container_of(panel, struct kd35t133, panel);
 }
 
-#define dsi_dcs_write_seq(dsi, cmd, seq...) do {                       \
-               static const u8 b[] = { cmd, seq };                     \
-               int ret;                                                \
-               ret = mipi_dsi_dcs_write_buffer(dsi, b, ARRAY_SIZE(b)); \
-               if (ret < 0)                                            \
-                       return ret;                                     \
-       } while (0)
-
 static int kd35t133_init_sequence(struct kd35t133 *ctx)
 {
        struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
@@ -68,25 +60,25 @@ static int kd35t133_init_sequence(struct kd35t133 *ctx)
         * Init sequence was supplied by the panel vendor with minimal
         * documentation.
         */
-       dsi_dcs_write_seq(dsi, KD35T133_CMD_POSITIVEGAMMA,
-                         0x00, 0x13, 0x18, 0x04, 0x0f, 0x06, 0x3a, 0x56,
-                         0x4d, 0x03, 0x0a, 0x06, 0x30, 0x3e, 0x0f);
-       dsi_dcs_write_seq(dsi, KD35T133_CMD_NEGATIVEGAMMA,
-                         0x00, 0x13, 0x18, 0x01, 0x11, 0x06, 0x38, 0x34,
-                         0x4d, 0x06, 0x0d, 0x0b, 0x31, 0x37, 0x0f);
-       dsi_dcs_write_seq(dsi, KD35T133_CMD_POWERCONTROL1, 0x18, 0x17);
-       dsi_dcs_write_seq(dsi, KD35T133_CMD_POWERCONTROL2, 0x41);
-       dsi_dcs_write_seq(dsi, KD35T133_CMD_VCOMCONTROL, 0x00, 0x1a, 0x80);
-       dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x48);
-       dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PIXEL_FORMAT, 0x55);
-       dsi_dcs_write_seq(dsi, KD35T133_CMD_INTERFACEMODECTRL, 0x00);
-       dsi_dcs_write_seq(dsi, KD35T133_CMD_FRAMERATECTRL, 0xa0);
-       dsi_dcs_write_seq(dsi, KD35T133_CMD_DISPLAYINVERSIONCTRL, 0x02);
-       dsi_dcs_write_seq(dsi, KD35T133_CMD_DISPLAYFUNCTIONCTRL,
-                         0x20, 0x02);
-       dsi_dcs_write_seq(dsi, KD35T133_CMD_SETIMAGEFUNCTION, 0x00);
-       dsi_dcs_write_seq(dsi, KD35T133_CMD_ADJUSTCONTROL3,
-                         0xa9, 0x51, 0x2c, 0x82);
+       mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_POSITIVEGAMMA,
+                              0x00, 0x13, 0x18, 0x04, 0x0f, 0x06, 0x3a, 0x56,
+                              0x4d, 0x03, 0x0a, 0x06, 0x30, 0x3e, 0x0f);
+       mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_NEGATIVEGAMMA,
+                              0x00, 0x13, 0x18, 0x01, 0x11, 0x06, 0x38, 0x34,
+                              0x4d, 0x06, 0x0d, 0x0b, 0x31, 0x37, 0x0f);
+       mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_POWERCONTROL1, 0x18, 0x17);
+       mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_POWERCONTROL2, 0x41);
+       mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_VCOMCONTROL, 0x00, 0x1a, 0x80);
+       mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x48);
+       mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PIXEL_FORMAT, 0x55);
+       mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_INTERFACEMODECTRL, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_FRAMERATECTRL, 0xa0);
+       mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_DISPLAYINVERSIONCTRL, 0x02);
+       mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_DISPLAYFUNCTIONCTRL,
+                              0x20, 0x02);
+       mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_SETIMAGEFUNCTION, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, KD35T133_CMD_ADJUSTCONTROL3,
+                              0xa9, 0x51, 0x2c, 0x82);
        mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_INVERT_MODE, NULL, 0);
 
        dev_dbg(dev, "Panel init sequence done\n");
diff --git a/drivers/gpu/drm/panel/panel-himax-hx8394.c b/drivers/gpu/drm/panel/panel-himax-hx8394.c
new file mode 100644 (file)
index 0000000..d4fb5d1
--- /dev/null
@@ -0,0 +1,451 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for panels based on Himax HX8394 controller, such as:
+ *
+ * - HannStar HSD060BHW4 5.99" MIPI-DSI panel
+ *
+ * Copyright (C) 2021 Kamil TrzciÅ„ski
+ *
+ * Based on drivers/gpu/drm/panel/panel-sitronix-st7703.c
+ * Copyright (C) Purism SPC 2019
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/media-bus-format.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+#define DRV_NAME "panel-himax-hx8394"
+
+/* Manufacturer specific commands sent via DSI, listed in HX8394-F datasheet */
+#define HX8394_CMD_SETSEQUENCE   0xb0
+#define HX8394_CMD_SETPOWER      0xb1
+#define HX8394_CMD_SETDISP       0xb2
+#define HX8394_CMD_SETCYC        0xb4
+#define HX8394_CMD_SETVCOM       0xb6
+#define HX8394_CMD_SETTE         0xb7
+#define HX8394_CMD_SETSENSOR     0xb8
+#define HX8394_CMD_SETEXTC       0xb9
+#define HX8394_CMD_SETMIPI       0xba
+#define HX8394_CMD_SETOTP        0xbb
+#define HX8394_CMD_SETREGBANK    0xbd
+#define HX8394_CMD_UNKNOWN1      0xc0
+#define HX8394_CMD_SETDGCLUT     0xc1
+#define HX8394_CMD_SETID         0xc3
+#define HX8394_CMD_SETDDB        0xc4
+#define HX8394_CMD_UNKNOWN2      0xc6
+#define HX8394_CMD_SETCABC       0xc9
+#define HX8394_CMD_SETCABCGAIN   0xca
+#define HX8394_CMD_SETPANEL      0xcc
+#define HX8394_CMD_SETOFFSET     0xd2
+#define HX8394_CMD_SETGIP0       0xd3
+#define HX8394_CMD_UNKNOWN3      0xd4
+#define HX8394_CMD_SETGIP1       0xd5
+#define HX8394_CMD_SETGIP2       0xd6
+#define HX8394_CMD_SETGPO        0xd6
+#define HX8394_CMD_SETSCALING    0xdd
+#define HX8394_CMD_SETIDLE       0xdf
+#define HX8394_CMD_SETGAMMA      0xe0
+#define HX8394_CMD_SETCHEMODE_DYN 0xe4
+#define HX8394_CMD_SETCHE        0xe5
+#define HX8394_CMD_SETCESEL      0xe6
+#define HX8394_CMD_SET_SP_CMD    0xe9
+#define HX8394_CMD_SETREADINDEX          0xfe
+#define HX8394_CMD_GETSPIREAD    0xff
+
+struct hx8394 {
+       struct device *dev;
+       struct drm_panel panel;
+       struct gpio_desc *reset_gpio;
+       struct regulator *vcc;
+       struct regulator *iovcc;
+       bool prepared;
+
+       const struct hx8394_panel_desc *desc;
+};
+
+struct hx8394_panel_desc {
+       const struct drm_display_mode *mode;
+       unsigned int lanes;
+       unsigned long mode_flags;
+       enum mipi_dsi_pixel_format format;
+       int (*init_sequence)(struct hx8394 *ctx);
+};
+
+static inline struct hx8394 *panel_to_hx8394(struct drm_panel *panel)
+{
+       return container_of(panel, struct hx8394, panel);
+}
+
+static int hsd060bhw4_init_sequence(struct hx8394 *ctx)
+{
+       struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+
+       /* 5.19.8 SETEXTC: Set extension command (B9h) */
+       mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETEXTC,
+                              0xff, 0x83, 0x94);
+
+       /* 5.19.2 SETPOWER: Set power (B1h) */
+       mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER,
+                              0x48, 0x11, 0x71, 0x09, 0x32, 0x24, 0x71, 0x31, 0x55, 0x30);
+
+       /* 5.19.9 SETMIPI: Set MIPI control (BAh) */
+       mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETMIPI,
+                              0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0);
+
+       /* 5.19.3 SETDISP: Set display related register (B2h) */
+       mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETDISP,
+                              0x00, 0x80, 0x78, 0x0c, 0x07);
+
+       /* 5.19.4 SETCYC: Set display waveform cycles (B4h) */
+       mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETCYC,
+                              0x12, 0x63, 0x12, 0x63, 0x12, 0x63, 0x01, 0x0c, 0x7c, 0x55,
+                              0x00, 0x3f, 0x12, 0x6b, 0x12, 0x6b, 0x12, 0x6b, 0x01, 0x0c,
+                              0x7c);
+
+       /* 5.19.19 SETGIP0: Set GIP Option0 (D3h) */
+       mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP0,
+                              0x00, 0x00, 0x00, 0x00, 0x3c, 0x1c, 0x00, 0x00, 0x32, 0x10,
+                              0x09, 0x00, 0x09, 0x32, 0x15, 0xad, 0x05, 0xad, 0x32, 0x00,
+                              0x00, 0x00, 0x00, 0x37, 0x03, 0x0b, 0x0b, 0x37, 0x00, 0x00,
+                              0x00, 0x0c, 0x40);
+
+       /* 5.19.20 Set GIP Option1 (D5h) */
+       mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP1,
+                              0x19, 0x19, 0x18, 0x18, 0x1b, 0x1b, 0x1a, 0x1a, 0x00, 0x01,
+                              0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21, 0x18, 0x18,
+                              0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+                              0x24, 0x25, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+                              0x18, 0x18, 0x18, 0x18, 0x18, 0x18);
+
+       /* 5.19.21 Set GIP Option2 (D6h) */
+       mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP2,
+                              0x18, 0x18, 0x19, 0x19, 0x1b, 0x1b, 0x1a, 0x1a, 0x07, 0x06,
+                              0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x25, 0x24, 0x18, 0x18,
+                              0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+                              0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+                              0x18, 0x18, 0x18, 0x18, 0x18, 0x18);
+
+       /* 5.19.25 SETGAMMA: Set gamma curve related setting (E0h) */
+       mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGAMMA,
+                              0x00, 0x04, 0x0c, 0x12, 0x14, 0x18, 0x1a, 0x18, 0x31, 0x3f,
+                              0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f, 0x82, 0x7e, 0x8a,
+                              0x99, 0x4a, 0x48, 0x49, 0x4b, 0x4a, 0x4c, 0x4b, 0x7f, 0x00,
+                              0x04, 0x0c, 0x11, 0x13, 0x17, 0x1a, 0x18, 0x31,
+                              0x3f, 0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f,
+                              0x82, 0x7e, 0x8a, 0x99, 0x4a, 0x48, 0x49, 0x4b,
+                              0x4a, 0x4c, 0x4b, 0x7f);
+
+       /* 5.19.17 SETPANEL (CCh) */
+       mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPANEL,
+                              0x0b);
+
+       /* Unknown command, not listed in the HX8394-F datasheet */
+       mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN1,
+                              0x1f, 0x31);
+
+       /* 5.19.5 SETVCOM: Set VCOM voltage (B6h) */
+       mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETVCOM,
+                              0x7d, 0x7d);
+
+       /* Unknown command, not listed in the HX8394-F datasheet */
+       mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN3,
+                              0x02);
+
+       /* 5.19.11 Set register bank (BDh) */
+       mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK,
+                              0x01);
+
+       /* 5.19.2 SETPOWER: Set power (B1h) */
+       mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER,
+                              0x00);
+
+       /* 5.19.11 Set register bank (BDh) */
+       mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK,
+                              0x00);
+
+       /* Unknown command, not listed in the HX8394-F datasheet */
+       mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN3,
+                              0xed);
+
+       return 0;
+}
+
+static const struct drm_display_mode hsd060bhw4_mode = {
+       .hdisplay    = 720,
+       .hsync_start = 720 + 40,
+       .hsync_end   = 720 + 40 + 46,
+       .htotal      = 720 + 40 + 46 + 40,
+       .vdisplay    = 1440,
+       .vsync_start = 1440 + 9,
+       .vsync_end   = 1440 + 9 + 7,
+       .vtotal      = 1440 + 9 + 7 + 7,
+       .clock       = 74250,
+       .flags       = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+       .width_mm    = 68,
+       .height_mm   = 136,
+};
+
+static const struct hx8394_panel_desc hsd060bhw4_desc = {
+       .mode = &hsd060bhw4_mode,
+       .lanes = 4,
+       .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST,
+       .format = MIPI_DSI_FMT_RGB888,
+       .init_sequence = hsd060bhw4_init_sequence,
+};
+
+static int hx8394_enable(struct drm_panel *panel)
+{
+       struct hx8394 *ctx = panel_to_hx8394(panel);
+       struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+       int ret;
+
+       ret = ctx->desc->init_sequence(ctx);
+       if (ret) {
+               dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+       if (ret) {
+               dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
+               return ret;
+       }
+
+       /* Panel is operational 120 msec after reset */
+       msleep(120);
+
+       ret = mipi_dsi_dcs_set_display_on(dsi);
+       if (ret) {
+               dev_err(ctx->dev, "Failed to turn on the display: %d\n", ret);
+               goto sleep_in;
+       }
+
+       return 0;
+
+sleep_in:
+       /* This will probably fail, but let's try orderly power off anyway. */
+       ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+       if (!ret)
+               msleep(50);
+
+       return ret;
+}
+
+static int hx8394_disable(struct drm_panel *panel)
+{
+       struct hx8394 *ctx = panel_to_hx8394(panel);
+       struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+       int ret;
+
+       ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+       if (ret) {
+               dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
+               return ret;
+       }
+
+       msleep(50); /* about 3 frames */
+
+       return 0;
+}
+
+static int hx8394_unprepare(struct drm_panel *panel)
+{
+       struct hx8394 *ctx = panel_to_hx8394(panel);
+
+       if (!ctx->prepared)
+               return 0;
+
+       gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+
+       regulator_disable(ctx->iovcc);
+       regulator_disable(ctx->vcc);
+
+       ctx->prepared = false;
+
+       return 0;
+}
+
+static int hx8394_prepare(struct drm_panel *panel)
+{
+       struct hx8394 *ctx = panel_to_hx8394(panel);
+       int ret;
+
+       if (ctx->prepared)
+               return 0;
+
+       gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+
+       ret = regulator_enable(ctx->vcc);
+       if (ret) {
+               dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
+               return ret;
+       }
+
+       ret = regulator_enable(ctx->iovcc);
+       if (ret) {
+               dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
+               goto disable_vcc;
+       }
+
+       gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+
+       msleep(180);
+
+       ctx->prepared = true;
+
+       return 0;
+
+disable_vcc:
+       gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+       regulator_disable(ctx->vcc);
+       return ret;
+}
+
+static int hx8394_get_modes(struct drm_panel *panel,
+                           struct drm_connector *connector)
+{
+       struct hx8394 *ctx = panel_to_hx8394(panel);
+       struct drm_display_mode *mode;
+
+       mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
+       if (!mode) {
+               dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n",
+                       ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
+                       drm_mode_vrefresh(ctx->desc->mode));
+               return -ENOMEM;
+       }
+
+       drm_mode_set_name(mode);
+
+       mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+       connector->display_info.width_mm = mode->width_mm;
+       connector->display_info.height_mm = mode->height_mm;
+       drm_mode_probed_add(connector, mode);
+
+       return 1;
+}
+
+static const struct drm_panel_funcs hx8394_drm_funcs = {
+       .disable   = hx8394_disable,
+       .unprepare = hx8394_unprepare,
+       .prepare   = hx8394_prepare,
+       .enable    = hx8394_enable,
+       .get_modes = hx8394_get_modes,
+};
+
+static int hx8394_probe(struct mipi_dsi_device *dsi)
+{
+       struct device *dev = &dsi->dev;
+       struct hx8394 *ctx;
+       int ret;
+
+       ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(ctx->reset_gpio))
+               return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+                                    "Failed to get reset gpio\n");
+
+       mipi_dsi_set_drvdata(dsi, ctx);
+
+       ctx->dev = dev;
+       ctx->desc = of_device_get_match_data(dev);
+
+       dsi->mode_flags = ctx->desc->mode_flags;
+       dsi->format = ctx->desc->format;
+       dsi->lanes = ctx->desc->lanes;
+
+       ctx->vcc = devm_regulator_get(dev, "vcc");
+       if (IS_ERR(ctx->vcc))
+               return dev_err_probe(dev, PTR_ERR(ctx->vcc),
+                                    "Failed to request vcc regulator\n");
+
+       ctx->iovcc = devm_regulator_get(dev, "iovcc");
+       if (IS_ERR(ctx->iovcc))
+               return dev_err_probe(dev, PTR_ERR(ctx->iovcc),
+                                    "Failed to request iovcc regulator\n");
+
+       drm_panel_init(&ctx->panel, dev, &hx8394_drm_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
+
+       ret = drm_panel_of_backlight(&ctx->panel);
+       if (ret)
+               return ret;
+
+       drm_panel_add(&ctx->panel);
+
+       ret = mipi_dsi_attach(dsi);
+       if (ret < 0) {
+               dev_err_probe(dev, ret, "mipi_dsi_attach failed\n");
+               drm_panel_remove(&ctx->panel);
+               return ret;
+       }
+
+       dev_dbg(dev, "%ux%u@%u %ubpp dsi %udl - ready\n",
+               ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
+               drm_mode_vrefresh(ctx->desc->mode),
+               mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);
+
+       return 0;
+}
+
+static void hx8394_shutdown(struct mipi_dsi_device *dsi)
+{
+       struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi);
+       int ret;
+
+       ret = drm_panel_disable(&ctx->panel);
+       if (ret < 0)
+               dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
+
+       ret = drm_panel_unprepare(&ctx->panel);
+       if (ret < 0)
+               dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
+}
+
+static void hx8394_remove(struct mipi_dsi_device *dsi)
+{
+       struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi);
+       int ret;
+
+       hx8394_shutdown(dsi);
+
+       ret = mipi_dsi_detach(dsi);
+       if (ret < 0)
+               dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+       drm_panel_remove(&ctx->panel);
+}
+
+static const struct of_device_id hx8394_of_match[] = {
+       { .compatible = "hannstar,hsd060bhw4", .data = &hsd060bhw4_desc },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, hx8394_of_match);
+
+static struct mipi_dsi_driver hx8394_driver = {
+       .probe  = hx8394_probe,
+       .remove = hx8394_remove,
+       .shutdown = hx8394_shutdown,
+       .driver = {
+               .name = DRV_NAME,
+               .of_match_table = hx8394_of_match,
+       },
+};
+module_mipi_dsi_driver(hx8394_driver);
+
+MODULE_AUTHOR("Kamil TrzciÅ„ski <ayufan@ayufan.eu>");
+MODULE_DESCRIPTION("DRM driver for Himax HX8394 based MIPI DSI panels");
+MODULE_LICENSE("GPL");
index d8765b2..8912757 100644 (file)
@@ -29,22 +29,6 @@ static inline struct jdi_fhd_r63452 *to_jdi_fhd_r63452(struct drm_panel *panel)
        return container_of(panel, struct jdi_fhd_r63452, panel);
 }
 
-#define dsi_generic_write_seq(dsi, seq...) do {                                \
-               static const u8 d[] = { seq };                          \
-               int ret;                                                \
-               ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));    \
-               if (ret < 0)                                            \
-                       return ret;                                     \
-       } while (0)
-
-#define dsi_dcs_write_seq(dsi, seq...) do {                            \
-               static const u8 d[] = { seq };                          \
-               int ret;                                                \
-               ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
-               if (ret < 0)                                            \
-                       return ret;                                     \
-       } while (0)
-
 static void jdi_fhd_r63452_reset(struct jdi_fhd_r63452 *ctx)
 {
        gpiod_set_value_cansleep(ctx->reset_gpio, 0);
@@ -63,12 +47,12 @@ static int jdi_fhd_r63452_on(struct jdi_fhd_r63452 *ctx)
 
        dsi->mode_flags |= MIPI_DSI_MODE_LPM;
 
-       dsi_generic_write_seq(dsi, 0xb0, 0x00);
-       dsi_generic_write_seq(dsi, 0xd6, 0x01);
-       dsi_generic_write_seq(dsi, 0xec,
-                             0x64, 0xdc, 0xec, 0x3b, 0x52, 0x00, 0x0b, 0x0b,
-                             0x13, 0x15, 0x68, 0x0b, 0xb5);
-       dsi_generic_write_seq(dsi, 0xb0, 0x03);
+       mipi_dsi_generic_write_seq(dsi, 0xb0, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xd6, 0x01);
+       mipi_dsi_generic_write_seq(dsi, 0xec,
+                                  0x64, 0xdc, 0xec, 0x3b, 0x52, 0x00, 0x0b, 0x0b,
+                                  0x13, 0x15, 0x68, 0x0b, 0xb5);
+       mipi_dsi_generic_write_seq(dsi, 0xb0, 0x03);
 
        ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
        if (ret < 0) {
@@ -76,7 +60,7 @@ static int jdi_fhd_r63452_on(struct jdi_fhd_r63452 *ctx)
                return ret;
        }
 
-       dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
 
        ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x77);
        if (ret < 0) {
@@ -108,10 +92,10 @@ static int jdi_fhd_r63452_on(struct jdi_fhd_r63452 *ctx)
                return ret;
        }
 
-       dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
-       dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
-       dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x00);
-       dsi_dcs_write_seq(dsi, 0x84, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
+       mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x84, 0x00);
 
        ret = mipi_dsi_dcs_set_display_on(dsi);
        if (ret < 0) {
@@ -127,10 +111,10 @@ static int jdi_fhd_r63452_on(struct jdi_fhd_r63452 *ctx)
        }
        msleep(80);
 
-       dsi_generic_write_seq(dsi, 0xb0, 0x04);
-       dsi_dcs_write_seq(dsi, 0x84, 0x00);
-       dsi_generic_write_seq(dsi, 0xc8, 0x11);
-       dsi_generic_write_seq(dsi, 0xb0, 0x03);
+       mipi_dsi_generic_write_seq(dsi, 0xb0, 0x04);
+       mipi_dsi_dcs_write_seq(dsi, 0x84, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xc8, 0x11);
+       mipi_dsi_generic_write_seq(dsi, 0xb0, 0x03);
 
        return 0;
 }
@@ -143,12 +127,12 @@ static int jdi_fhd_r63452_off(struct jdi_fhd_r63452 *ctx)
 
        dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
 
-       dsi_generic_write_seq(dsi, 0xb0, 0x00);
-       dsi_generic_write_seq(dsi, 0xd6, 0x01);
-       dsi_generic_write_seq(dsi, 0xec,
-                             0x64, 0xdc, 0xec, 0x3b, 0x52, 0x00, 0x0b, 0x0b,
-                             0x13, 0x15, 0x68, 0x0b, 0x95);
-       dsi_generic_write_seq(dsi, 0xb0, 0x03);
+       mipi_dsi_generic_write_seq(dsi, 0xb0, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xd6, 0x01);
+       mipi_dsi_generic_write_seq(dsi, 0xec,
+                                  0x64, 0xdc, 0xec, 0x3b, 0x52, 0x00, 0x0b, 0x0b,
+                                  0x13, 0x15, 0x68, 0x0b, 0x95);
+       mipi_dsi_generic_write_seq(dsi, 0xb0, 0x03);
 
        ret = mipi_dsi_dcs_set_display_off(dsi);
        if (ret < 0) {
index 5619f18..d2efd88 100644 (file)
@@ -244,14 +244,6 @@ struct ltk050h3146w *panel_to_ltk050h3146w(struct drm_panel *panel)
        return container_of(panel, struct ltk050h3146w, panel);
 }
 
-#define dsi_dcs_write_seq(dsi, cmd, seq...) do {                       \
-               static const u8 b[] = { cmd, seq };                     \
-               int ret;                                                \
-               ret = mipi_dsi_dcs_write_buffer(dsi, b, ARRAY_SIZE(b)); \
-               if (ret < 0)                                            \
-                       return ret;                                     \
-       } while (0)
-
 static int ltk050h3146w_init_sequence(struct ltk050h3146w *ctx)
 {
        struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
@@ -261,55 +253,55 @@ static int ltk050h3146w_init_sequence(struct ltk050h3146w *ctx)
         * Init sequence was supplied by the panel vendor without much
         * documentation.
         */
-       dsi_dcs_write_seq(dsi, 0xdf, 0x93, 0x65, 0xf8);
-       dsi_dcs_write_seq(dsi, 0xb0, 0x01, 0x03, 0x02, 0x00, 0x64, 0x06,
-                         0x01);
-       dsi_dcs_write_seq(dsi, 0xb2, 0x00, 0xb5);
-       dsi_dcs_write_seq(dsi, 0xb3, 0x00, 0xb5);
-       dsi_dcs_write_seq(dsi, 0xb7, 0x00, 0xbf, 0x00, 0x00, 0xbf, 0x00);
-
-       dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xc4, 0x23, 0x07);
-       dsi_dcs_write_seq(dsi, 0xbb, 0x02, 0x01, 0x24, 0x00, 0x28, 0x0f,
-                         0x28, 0x04, 0xcc, 0xcc, 0xcc);
-       dsi_dcs_write_seq(dsi, 0xbc, 0x0f, 0x04);
-       dsi_dcs_write_seq(dsi, 0xbe, 0x1e, 0xf2);
-       dsi_dcs_write_seq(dsi, 0xc0, 0x26, 0x03);
-       dsi_dcs_write_seq(dsi, 0xc1, 0x00, 0x12);
-       dsi_dcs_write_seq(dsi, 0xc3, 0x04, 0x02, 0x02, 0x76, 0x01, 0x80,
-                         0x80);
-       dsi_dcs_write_seq(dsi, 0xc4, 0x24, 0x80, 0xb4, 0x81, 0x12, 0x0f,
-                         0x16, 0x00, 0x00);
-       dsi_dcs_write_seq(dsi, 0xc8, 0x7f, 0x72, 0x67, 0x5d, 0x5d, 0x50,
-                         0x56, 0x41, 0x59, 0x57, 0x55, 0x70, 0x5b, 0x5f,
-                         0x4f, 0x47, 0x38, 0x23, 0x08, 0x7f, 0x72, 0x67,
-                         0x5d, 0x5d, 0x50, 0x56, 0x41, 0x59, 0x57, 0x55,
-                         0x70, 0x5b, 0x5f, 0x4f, 0x47, 0x38, 0x23, 0x08);
-       dsi_dcs_write_seq(dsi, 0xd0, 0x1e, 0x1f, 0x57, 0x58, 0x48, 0x4a,
-                         0x44, 0x46, 0x40, 0x1f, 0x42, 0x1f, 0x1f, 0x1f,
-                         0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
-       dsi_dcs_write_seq(dsi, 0xd1, 0x1e, 0x1f, 0x57, 0x58, 0x49, 0x4b,
-                         0x45, 0x47, 0x41, 0x1f, 0x43, 0x1f, 0x1f, 0x1f,
-                         0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
-       dsi_dcs_write_seq(dsi, 0xd2, 0x1f, 0x1e, 0x17, 0x18, 0x07, 0x05,
-                         0x0b, 0x09, 0x03, 0x1f, 0x01, 0x1f, 0x1f, 0x1f,
-                         0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
-       dsi_dcs_write_seq(dsi, 0xd3, 0x1f, 0x1e, 0x17, 0x18, 0x06, 0x04,
-                         0x0a, 0x08, 0x02, 0x1f, 0x00, 0x1f, 0x1f, 0x1f,
-                         0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
-       dsi_dcs_write_seq(dsi, 0xd4, 0x00, 0x00, 0x00, 0x0c, 0x06, 0x20,
-                         0x01, 0x02, 0x00, 0x60, 0x15, 0xb0, 0x30, 0x03,
-                         0x04, 0x00, 0x60, 0x72, 0x0a, 0x00, 0x60, 0x08);
-       dsi_dcs_write_seq(dsi, 0xd5, 0x00, 0x06, 0x06, 0x00, 0x30, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0xbc, 0x50, 0x00, 0x05,
-                         0x21, 0x00, 0x60);
-       dsi_dcs_write_seq(dsi, 0xdd, 0x2c, 0xa3, 0x00);
-       dsi_dcs_write_seq(dsi, 0xde, 0x02);
-       dsi_dcs_write_seq(dsi, 0xb2, 0x32, 0x1c);
-       dsi_dcs_write_seq(dsi, 0xb7, 0x3b, 0x70, 0x00, 0x04);
-       dsi_dcs_write_seq(dsi, 0xc1, 0x11);
-       dsi_dcs_write_seq(dsi, 0xbb, 0x21, 0x22, 0x23, 0x24, 0x36, 0x37);
-       dsi_dcs_write_seq(dsi, 0xc2, 0x20, 0x38, 0x1e, 0x84);
-       dsi_dcs_write_seq(dsi, 0xde, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xdf, 0x93, 0x65, 0xf8);
+       mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x01, 0x03, 0x02, 0x00, 0x64, 0x06,
+                              0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x00, 0xb5);
+       mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x00, 0xb5);
+       mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x00, 0xbf, 0x00, 0x00, 0xbf, 0x00);
+
+       mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xc4, 0x23, 0x07);
+       mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x02, 0x01, 0x24, 0x00, 0x28, 0x0f,
+                              0x28, 0x04, 0xcc, 0xcc, 0xcc);
+       mipi_dsi_dcs_write_seq(dsi, 0xbc, 0x0f, 0x04);
+       mipi_dsi_dcs_write_seq(dsi, 0xbe, 0x1e, 0xf2);
+       mipi_dsi_dcs_write_seq(dsi, 0xc0, 0x26, 0x03);
+       mipi_dsi_dcs_write_seq(dsi, 0xc1, 0x00, 0x12);
+       mipi_dsi_dcs_write_seq(dsi, 0xc3, 0x04, 0x02, 0x02, 0x76, 0x01, 0x80,
+                              0x80);
+       mipi_dsi_dcs_write_seq(dsi, 0xc4, 0x24, 0x80, 0xb4, 0x81, 0x12, 0x0f,
+                              0x16, 0x00, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xc8, 0x7f, 0x72, 0x67, 0x5d, 0x5d, 0x50,
+                              0x56, 0x41, 0x59, 0x57, 0x55, 0x70, 0x5b, 0x5f,
+                              0x4f, 0x47, 0x38, 0x23, 0x08, 0x7f, 0x72, 0x67,
+                              0x5d, 0x5d, 0x50, 0x56, 0x41, 0x59, 0x57, 0x55,
+                              0x70, 0x5b, 0x5f, 0x4f, 0x47, 0x38, 0x23, 0x08);
+       mipi_dsi_dcs_write_seq(dsi, 0xd0, 0x1e, 0x1f, 0x57, 0x58, 0x48, 0x4a,
+                              0x44, 0x46, 0x40, 0x1f, 0x42, 0x1f, 0x1f, 0x1f,
+                              0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
+       mipi_dsi_dcs_write_seq(dsi, 0xd1, 0x1e, 0x1f, 0x57, 0x58, 0x49, 0x4b,
+                              0x45, 0x47, 0x41, 0x1f, 0x43, 0x1f, 0x1f, 0x1f,
+                              0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
+       mipi_dsi_dcs_write_seq(dsi, 0xd2, 0x1f, 0x1e, 0x17, 0x18, 0x07, 0x05,
+                              0x0b, 0x09, 0x03, 0x1f, 0x01, 0x1f, 0x1f, 0x1f,
+                              0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
+       mipi_dsi_dcs_write_seq(dsi, 0xd3, 0x1f, 0x1e, 0x17, 0x18, 0x06, 0x04,
+                              0x0a, 0x08, 0x02, 0x1f, 0x00, 0x1f, 0x1f, 0x1f,
+                              0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f);
+       mipi_dsi_dcs_write_seq(dsi, 0xd4, 0x00, 0x00, 0x00, 0x0c, 0x06, 0x20,
+                              0x01, 0x02, 0x00, 0x60, 0x15, 0xb0, 0x30, 0x03,
+                              0x04, 0x00, 0x60, 0x72, 0x0a, 0x00, 0x60, 0x08);
+       mipi_dsi_dcs_write_seq(dsi, 0xd5, 0x00, 0x06, 0x06, 0x00, 0x30, 0x00,
+                              0x00, 0x00, 0x00, 0x00, 0xbc, 0x50, 0x00, 0x05,
+                              0x21, 0x00, 0x60);
+       mipi_dsi_dcs_write_seq(dsi, 0xdd, 0x2c, 0xa3, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xde, 0x02);
+       mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x32, 0x1c);
+       mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x3b, 0x70, 0x00, 0x04);
+       mipi_dsi_dcs_write_seq(dsi, 0xc1, 0x11);
+       mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x21, 0x22, 0x23, 0x24, 0x36, 0x37);
+       mipi_dsi_dcs_write_seq(dsi, 0xc2, 0x20, 0x38, 0x1e, 0x84);
+       mipi_dsi_dcs_write_seq(dsi, 0xde, 0x00);
 
        ret = mipi_dsi_dcs_set_tear_on(dsi, 1);
        if (ret < 0) {
index 772e3b6..9243b2a 100644 (file)
@@ -45,14 +45,6 @@ static inline struct mantix *panel_to_mantix(struct drm_panel *panel)
        return container_of(panel, struct mantix, panel);
 }
 
-#define dsi_generic_write_seq(dsi, seq...) do {                                \
-               static const u8 d[] = { seq };                          \
-               int ret;                                                \
-               ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));    \
-               if (ret < 0)                                            \
-                       return ret;                                     \
-       } while (0)
-
 static int mantix_init_sequence(struct mantix *ctx)
 {
        struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
@@ -61,18 +53,18 @@ static int mantix_init_sequence(struct mantix *ctx)
        /*
         * Init sequence was supplied by the panel vendor.
         */
-       dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A);
+       mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A);
 
-       dsi_generic_write_seq(dsi, MANTIX_CMD_INT_CANCEL, 0x03);
-       dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A, 0x03);
-       dsi_generic_write_seq(dsi, 0x80, 0xA9, 0x00);
+       mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_INT_CANCEL, 0x03);
+       mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A, 0x03);
+       mipi_dsi_generic_write_seq(dsi, 0x80, 0xA9, 0x00);
 
-       dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A, 0x09);
-       dsi_generic_write_seq(dsi, 0x80, 0x64, 0x00, 0x64, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A, 0x09);
+       mipi_dsi_generic_write_seq(dsi, 0x80, 0x64, 0x00, 0x64, 0x00, 0x00);
        msleep(20);
 
-       dsi_generic_write_seq(dsi, MANTIX_CMD_SPI_FINISH, 0xA5);
-       dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x00, 0x2F);
+       mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_SPI_FINISH, 0xA5);
+       mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x00, 0x2F);
        msleep(20);
 
        dev_dbg(dev, "Panel init sequence done\n");
index 3a84491..abf752b 100644 (file)
@@ -89,14 +89,6 @@ static inline struct nt35950 *to_nt35950(struct drm_panel *panel)
        return container_of(panel, struct nt35950, panel);
 }
 
-#define dsi_dcs_write_seq(dsi, seq...) do {                            \
-               static const u8 d[] = { seq };                          \
-               int ret;                                                \
-               ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
-               if (ret < 0)                                            \
-                       return ret;                                     \
-       } while (0)
-
 static void nt35950_reset(struct nt35950 *nt)
 {
        gpiod_set_value_cansleep(nt->reset_gpio, 1);
@@ -338,7 +330,7 @@ static int nt35950_on(struct nt35950 *nt)
                return ret;
 
        /* Unknown command */
-       dsi_dcs_write_seq(dsi, 0xd4, 0x88, 0x88);
+       mipi_dsi_dcs_write_seq(dsi, 0xd4, 0x88, 0x88);
 
        /* CMD2 Page 7 */
        ret = nt35950_set_cmd2_page(nt, 7);
@@ -346,10 +338,10 @@ static int nt35950_on(struct nt35950 *nt)
                return ret;
 
        /* Enable SubPixel Rendering */
-       dsi_dcs_write_seq(dsi, MCS_PARAM_SPR_EN, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, MCS_PARAM_SPR_EN, 0x01);
 
        /* SPR Mode: YYG Rainbow-RGB */
-       dsi_dcs_write_seq(dsi, MCS_PARAM_SPR_MODE, MCS_SPR_MODE_YYG_RAINBOW_RGB);
+       mipi_dsi_dcs_write_seq(dsi, MCS_PARAM_SPR_MODE, MCS_SPR_MODE_YYG_RAINBOW_RGB);
 
        /* CMD3 */
        ret = nt35950_inject_black_image(nt);
index 36a46cb..aba556c 100644 (file)
@@ -202,8 +202,7 @@ static const struct drm_panel_funcs lcd_olinuxino_funcs = {
        .get_modes = lcd_olinuxino_get_modes,
 };
 
-static int lcd_olinuxino_probe(struct i2c_client *client,
-                              const struct i2c_device_id *id)
+static int lcd_olinuxino_probe(struct i2c_client *client)
 {
        struct device *dev = &client->dev;
        struct lcd_olinuxino *lcd;
@@ -309,7 +308,7 @@ static struct i2c_driver lcd_olinuxino_driver = {
                .name = "lcd_olinuxino",
                .of_match_table = lcd_olinuxino_of_ids,
        },
-       .probe = lcd_olinuxino_probe,
+       .probe_new = lcd_olinuxino_probe,
        .remove = lcd_olinuxino_remove,
 };
 
index 79f8524..1ef1cfd 100644 (file)
@@ -362,8 +362,7 @@ static const struct drm_panel_funcs rpi_touchscreen_funcs = {
        .get_modes = rpi_touchscreen_get_modes,
 };
 
-static int rpi_touchscreen_probe(struct i2c_client *i2c,
-                                const struct i2c_device_id *id)
+static int rpi_touchscreen_probe(struct i2c_client *i2c)
 {
        struct device *dev = &i2c->dev;
        struct rpi_touchscreen *ts;
@@ -491,7 +490,7 @@ static struct i2c_driver rpi_touchscreen_driver = {
                .name = "rpi_touchscreen",
                .of_match_table = rpi_touchscreen_of_ids,
        },
-       .probe = rpi_touchscreen_probe,
+       .probe_new = rpi_touchscreen_probe,
        .remove = rpi_touchscreen_remove,
 };
 
index 97ff7a1..7431cae 100644 (file)
@@ -28,14 +28,6 @@ s6e88a0_ams452ef01 *to_s6e88a0_ams452ef01(struct drm_panel *panel)
        return container_of(panel, struct s6e88a0_ams452ef01, panel);
 }
 
-#define dsi_dcs_write_seq(dsi, seq...) do {                            \
-               static const u8 d[] = { seq };                          \
-               int ret;                                                \
-               ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
-               if (ret < 0)                                            \
-                       return ret;                                     \
-       } while (0)
-
 static void s6e88a0_ams452ef01_reset(struct s6e88a0_ams452ef01 *ctx)
 {
        gpiod_set_value_cansleep(ctx->reset_gpio, 1);
@@ -54,8 +46,8 @@ static int s6e88a0_ams452ef01_on(struct s6e88a0_ams452ef01 *ctx)
 
        dsi->mode_flags |= MIPI_DSI_MODE_LPM;
 
-       dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a); // enable LEVEL2 commands
-       dsi_dcs_write_seq(dsi, 0xcc, 0x4c); // set Pixel Clock Divider polarity
+       mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a); // enable LEVEL2 commands
+       mipi_dsi_dcs_write_seq(dsi, 0xcc, 0x4c); // set Pixel Clock Divider polarity
 
        ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
        if (ret < 0) {
@@ -65,23 +57,23 @@ static int s6e88a0_ams452ef01_on(struct s6e88a0_ams452ef01 *ctx)
        msleep(120);
 
        // set default brightness/gama
-       dsi_dcs_write_seq(dsi, 0xca,
-                         0x01, 0x00, 0x01, 0x00, 0x01, 0x00,   // V255 RR,GG,BB
-                         0x80, 0x80, 0x80,                     // V203 R,G,B
-                         0x80, 0x80, 0x80,                     // V151 R,G,B
-                         0x80, 0x80, 0x80,                     // V87  R,G,B
-                         0x80, 0x80, 0x80,                     // V51  R,G,B
-                         0x80, 0x80, 0x80,                     // V35  R,G,B
-                         0x80, 0x80, 0x80,                     // V23  R,G,B
-                         0x80, 0x80, 0x80,                     // V11  R,G,B
-                         0x6b, 0x68, 0x71,                     // V3   R,G,B
-                         0x00, 0x00, 0x00);                    // V1   R,G,B
+       mipi_dsi_dcs_write_seq(dsi, 0xca,
+                              0x01, 0x00, 0x01, 0x00, 0x01, 0x00,      // V255 RR,GG,BB
+                              0x80, 0x80, 0x80,                        // V203 R,G,B
+                              0x80, 0x80, 0x80,                        // V151 R,G,B
+                              0x80, 0x80, 0x80,                        // V87  R,G,B
+                              0x80, 0x80, 0x80,                        // V51  R,G,B
+                              0x80, 0x80, 0x80,                        // V35  R,G,B
+                              0x80, 0x80, 0x80,                        // V23  R,G,B
+                              0x80, 0x80, 0x80,                        // V11  R,G,B
+                              0x6b, 0x68, 0x71,                        // V3   R,G,B
+                              0x00, 0x00, 0x00);                       // V1   R,G,B
        // set default Amoled Off Ratio
-       dsi_dcs_write_seq(dsi, 0xb2, 0x40, 0x0a, 0x17, 0x00, 0x0a);
-       dsi_dcs_write_seq(dsi, 0xb6, 0x2c, 0x0b); // set default elvss voltage
-       dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
-       dsi_dcs_write_seq(dsi, 0xf7, 0x03); // gamma/aor update
-       dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5); // disable LEVEL2 commands
+       mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x40, 0x0a, 0x17, 0x00, 0x0a);
+       mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x2c, 0x0b); // set default elvss voltage
+       mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xf7, 0x03); // gamma/aor update
+       mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5); // disable LEVEL2 commands
 
        ret = mipi_dsi_dcs_set_display_on(dsi);
        if (ret < 0) {
index 1a0d245..9db49a0 100644 (file)
@@ -34,14 +34,6 @@ struct sofef00_panel *to_sofef00_panel(struct drm_panel *panel)
        return container_of(panel, struct sofef00_panel, panel);
 }
 
-#define dsi_dcs_write_seq(dsi, seq...) do {                            \
-               static const u8 d[] = { seq };                          \
-               int ret;                                                \
-               ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
-               if (ret < 0)                                            \
-                       return ret;                                     \
-       } while (0)
-
 static void sofef00_panel_reset(struct sofef00_panel *ctx)
 {
        gpiod_set_value_cansleep(ctx->reset_gpio, 0);
@@ -67,7 +59,7 @@ static int sofef00_panel_on(struct sofef00_panel *ctx)
        }
        usleep_range(10000, 11000);
 
-       dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+       mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
 
        ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
        if (ret < 0) {
@@ -75,13 +67,13 @@ static int sofef00_panel_on(struct sofef00_panel *ctx)
                return ret;
        }
 
-       dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
-       dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
-       dsi_dcs_write_seq(dsi, 0xb0, 0x07);
-       dsi_dcs_write_seq(dsi, 0xb6, 0x12);
-       dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
-       dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
-       dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+       mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+       mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x07);
+       mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x12);
+       mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+       mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
+       mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
 
        ret = mipi_dsi_dcs_set_display_on(dsi);
        if (ret < 0) {
index 8a4e0c1..68f52ea 100644 (file)
@@ -32,12 +32,6 @@ static inline struct sharp_ls060 *to_sharp_ls060(struct drm_panel *panel)
        return container_of(panel, struct sharp_ls060, panel);
 }
 
-#define dsi_dcs_write_seq(dsi, seq...) ({                              \
-               static const u8 d[] = { seq };                          \
-                                                                       \
-               mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));       \
-       })
-
 static void sharp_ls060_reset(struct sharp_ls060 *ctx)
 {
        gpiod_set_value_cansleep(ctx->reset_gpio, 0);
@@ -56,17 +50,8 @@ static int sharp_ls060_on(struct sharp_ls060 *ctx)
 
        dsi->mode_flags |= MIPI_DSI_MODE_LPM;
 
-       ret = dsi_dcs_write_seq(dsi, 0xbb, 0x13);
-       if (ret < 0) {
-               dev_err(dev, "Failed to send command: %d\n", ret);
-               return ret;
-       }
-
-       ret = dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_MEMORY_START);
-       if (ret < 0) {
-               dev_err(dev, "Failed to send command: %d\n", ret);
-               return ret;
-       }
+       mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x13);
+       mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_MEMORY_START);
 
        ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
        if (ret < 0) {
index 86a472b..6747ca2 100644 (file)
@@ -73,14 +73,6 @@ static inline struct st7703 *panel_to_st7703(struct drm_panel *panel)
        return container_of(panel, struct st7703, panel);
 }
 
-#define dsi_generic_write_seq(dsi, seq...) do {                                \
-               static const u8 d[] = { seq };                          \
-               int ret;                                                \
-               ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));    \
-               if (ret < 0)                                            \
-                       return ret;                                     \
-       } while (0)
-
 static int jh057n_init_sequence(struct st7703 *ctx)
 {
        struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
@@ -90,50 +82,50 @@ static int jh057n_init_sequence(struct st7703 *ctx)
         * resemble the ST7703 but the number of parameters often don't match
         * so it's likely a clone.
         */
-       dsi_generic_write_seq(dsi, ST7703_CMD_SETEXTC,
-                             0xF1, 0x12, 0x83);
-       dsi_generic_write_seq(dsi, ST7703_CMD_SETRGBIF,
-                             0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00,
-                             0x00, 0x00);
-       dsi_generic_write_seq(dsi, ST7703_CMD_SETSCR,
-                             0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70,
-                             0x00);
-       dsi_generic_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
-       dsi_generic_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
-       dsi_generic_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
-       dsi_generic_write_seq(dsi, ST7703_CMD_SETDISP, 0xF0, 0x12, 0x30);
-       dsi_generic_write_seq(dsi, ST7703_CMD_SETEQ,
-                             0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00,
-                             0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10);
-       dsi_generic_write_seq(dsi, ST7703_CMD_SETBGP, 0x08, 0x08);
+       mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETEXTC,
+                                  0xF1, 0x12, 0x83);
+       mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETRGBIF,
+                                  0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00,
+                                  0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETSCR,
+                                  0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70,
+                                  0x00);
+       mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
+       mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
+       mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
+       mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETDISP, 0xF0, 0x12, 0x30);
+       mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETEQ,
+                                  0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00,
+                                  0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10);
+       mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETBGP, 0x08, 0x08);
        msleep(20);
 
-       dsi_generic_write_seq(dsi, ST7703_CMD_SETVCOM, 0x3F, 0x3F);
-       dsi_generic_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
-       dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP1,
-                             0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12,
-                             0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
-                             0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
-                             0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
-                             0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
-                             0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
-                             0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP2,
-                             0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                             0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
-                             0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
-                             0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
-                             0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
-                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A,
-                             0xA5, 0x00, 0x00, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, ST7703_CMD_SETGAMMA,
-                             0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37,
-                             0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11,
-                             0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41,
-                             0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10,
-                             0x11, 0x18);
+       mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETVCOM, 0x3F, 0x3F);
+       mipi_dsi_generic_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
+       mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP1,
+                                  0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12,
+                                  0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
+                                  0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
+                                  0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
+                                  0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
+                                  0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+                                  0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP2,
+                                  0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                  0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
+                                  0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
+                                  0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+                                  0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
+                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A,
+                                  0xA5, 0x00, 0x00, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGAMMA,
+                                  0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37,
+                                  0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11,
+                                  0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41,
+                                  0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10,
+                                  0x11, 0x18);
 
        return 0;
 }
@@ -162,15 +154,6 @@ static const struct st7703_panel_desc jh057n00900_panel_desc = {
        .init_sequence = jh057n_init_sequence,
 };
 
-#define dsi_dcs_write_seq(dsi, cmd, seq...) do {                       \
-               static const u8 d[] = { seq };                          \
-               int ret;                                                \
-               ret = mipi_dsi_dcs_write(dsi, cmd, d, ARRAY_SIZE(d));   \
-               if (ret < 0)                                            \
-                       return ret;                                     \
-       } while (0)
-
-
 static int xbd599_init_sequence(struct st7703 *ctx)
 {
        struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
@@ -180,154 +163,154 @@ static int xbd599_init_sequence(struct st7703 *ctx)
         */
 
        /* Magic sequence to unlock user commands below. */
-       dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x83);
-
-       dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI,
-                         0x33, /* VC_main = 0, Lane_Number = 3 (4 lanes) */
-                         0x81, /* DSI_LDO_SEL = 1.7V, RTERM = 90 Ohm */
-                         0x05, /* IHSRX = x6 (Low High Speed driving ability) */
-                         0xF9, /* TX_CLK_SEL = fDSICLK/16 */
-                         0x0E, /* HFP_OSC (min. HFP number in DSI mode) */
-                         0x0E, /* HBP_OSC (min. HBP number in DSI mode) */
-                         /* The rest is undocumented in ST7703 datasheet */
-                         0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02,
-                         0x4F, 0x11, 0x00, 0x00, 0x37);
-
-       dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT,
-                         0x25, /* PCCS = 2, ECP_DC_DIV = 1/4 HSYNC */
-                         0x22, /* DT = 15ms XDK_ECP = x2 */
-                         0x20, /* PFM_DC_DIV = /1 */
-                         0x03  /* ECP_SYNC_EN = 1, VGX_SYNC_EN = 1 */);
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x83);
+
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI,
+                              0x33, /* VC_main = 0, Lane_Number = 3 (4 lanes) */
+                              0x81, /* DSI_LDO_SEL = 1.7V, RTERM = 90 Ohm */
+                              0x05, /* IHSRX = x6 (Low High Speed driving ability) */
+                              0xF9, /* TX_CLK_SEL = fDSICLK/16 */
+                              0x0E, /* HFP_OSC (min. HFP number in DSI mode) */
+                              0x0E, /* HBP_OSC (min. HBP number in DSI mode) */
+                              /* The rest is undocumented in ST7703 datasheet */
+                              0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                              0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02,
+                              0x4F, 0x11, 0x00, 0x00, 0x37);
+
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT,
+                              0x25, /* PCCS = 2, ECP_DC_DIV = 1/4 HSYNC */
+                              0x22, /* DT = 15ms XDK_ECP = x2 */
+                              0x20, /* PFM_DC_DIV = /1 */
+                              0x03  /* ECP_SYNC_EN = 1, VGX_SYNC_EN = 1 */);
 
        /* RGB I/F porch timing */
-       dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF,
-                         0x10, /* VBP_RGB_GEN */
-                         0x10, /* VFP_RGB_GEN */
-                         0x05, /* DE_BP_RGB_GEN */
-                         0x05, /* DE_FP_RGB_GEN */
-                         /* The rest is undocumented in ST7703 datasheet */
-                         0x03, 0xFF,
-                         0x00, 0x00,
-                         0x00, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF,
+                              0x10, /* VBP_RGB_GEN */
+                              0x10, /* VFP_RGB_GEN */
+                              0x05, /* DE_BP_RGB_GEN */
+                              0x05, /* DE_FP_RGB_GEN */
+                              /* The rest is undocumented in ST7703 datasheet */
+                              0x03, 0xFF,
+                              0x00, 0x00,
+                              0x00, 0x00);
 
        /* Source driving settings. */
-       dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR,
-                         0x73, /* N_POPON */
-                         0x73, /* N_NOPON */
-                         0x50, /* I_POPON */
-                         0x50, /* I_NOPON */
-                         0x00, /* SCR[31,24] */
-                         0xC0, /* SCR[23,16] */
-                         0x08, /* SCR[15,8] */
-                         0x70, /* SCR[7,0] */
-                         0x00  /* Undocumented */);
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR,
+                              0x73, /* N_POPON */
+                              0x73, /* N_NOPON */
+                              0x50, /* I_POPON */
+                              0x50, /* I_NOPON */
+                              0x00, /* SCR[31,24] */
+                              0xC0, /* SCR[23,16] */
+                              0x08, /* SCR[15,8] */
+                              0x70, /* SCR[7,0] */
+                              0x00  /* Undocumented */);
 
        /* NVDDD_SEL = -1.8V, VDDD_SEL = out of range (possibly 1.9V?) */
-       dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
 
        /*
         * SS_PANEL = 1 (reverse scan), GS_PANEL = 0 (normal scan)
         * REV_PANEL = 1 (normally black panel), BGR_PANEL = 1 (BGR)
         */
-       dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
 
        /* Zig-Zag Type C column inversion. */
-       dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
 
        /* Set display resolution. */
-       dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP,
-                         0xF0, /* NL = 240 */
-                         0x12, /* RES_V_LSB = 0, BLK_CON = VSSD,
-                                * RESO_SEL = 720RGB
-                                */
-                         0xF0  /* WHITE_GND_EN = 1 (GND),
-                                * WHITE_FRAME_SEL = 7 frames,
-                                * ISC = 0 frames
-                                */);
-
-       dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ,
-                         0x00, /* PNOEQ */
-                         0x00, /* NNOEQ */
-                         0x0B, /* PEQGND */
-                         0x0B, /* NEQGND */
-                         0x10, /* PEQVCI */
-                         0x10, /* NEQVCI */
-                         0x00, /* PEQVCI1 */
-                         0x00, /* NEQVCI1 */
-                         0x00, /* reserved */
-                         0x00, /* reserved */
-                         0xFF, /* reserved */
-                         0x00, /* reserved */
-                         0xC0, /* ESD_DET_DATA_WHITE = 1, ESD_WHITE_EN = 1 */
-                         0x10  /* SLPIN_OPTION = 1 (no need vsync after sleep-in)
-                                * VEDIO_NO_CHECK_EN = 0
-                                * ESD_WHITE_GND_EN = 0
-                                * ESD_DET_TIME_SEL = 0 frames
-                                */);
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP,
+                              0xF0, /* NL = 240 */
+                              0x12, /* RES_V_LSB = 0, BLK_CON = VSSD,
+                                     * RESO_SEL = 720RGB
+                                     */
+                              0xF0  /* WHITE_GND_EN = 1 (GND),
+                                     * WHITE_FRAME_SEL = 7 frames,
+                                     * ISC = 0 frames
+                                     */);
+
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ,
+                              0x00, /* PNOEQ */
+                              0x00, /* NNOEQ */
+                              0x0B, /* PEQGND */
+                              0x0B, /* NEQGND */
+                              0x10, /* PEQVCI */
+                              0x10, /* NEQVCI */
+                              0x00, /* PEQVCI1 */
+                              0x00, /* NEQVCI1 */
+                              0x00, /* reserved */
+                              0x00, /* reserved */
+                              0xFF, /* reserved */
+                              0x00, /* reserved */
+                              0xC0, /* ESD_DET_DATA_WHITE = 1, ESD_WHITE_EN = 1 */
+                              0x10  /* SLPIN_OPTION = 1 (no need vsync after sleep-in)
+                                     * VEDIO_NO_CHECK_EN = 0
+                                     * ESD_WHITE_GND_EN = 0
+                                     * ESD_DET_TIME_SEL = 0 frames
+                                     */);
 
        /* Undocumented command. */
-       dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_C6, 0x01, 0x00, 0xFF, 0xFF, 0x00);
-
-       dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER,
-                         0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */
-                         0x00, /* FBOFF_VGH = 0, FBOFF_VGL = 0 */
-                         0x32, /* VRP  */
-                         0x32, /* VRN */
-                         0x77, /* reserved */
-                         0xF1, /* APS = 1 (small),
-                                * VGL_DET_EN = 1, VGH_DET_EN = 1,
-                                * VGL_TURBO = 1, VGH_TURBO = 1
-                                */
-                         0xFF, /* VGH1_L_DIV, VGL1_L_DIV (1.5MHz) */
-                         0xFF, /* VGH1_R_DIV, VGL1_R_DIV (1.5MHz) */
-                         0xCC, /* VGH2_L_DIV, VGL2_L_DIV (2.6MHz) */
-                         0xCC, /* VGH2_R_DIV, VGL2_R_DIV (2.6MHz) */
-                         0x77, /* VGH3_L_DIV, VGL3_L_DIV (4.5MHz) */
-                         0x77  /* VGH3_R_DIV, VGL3_R_DIV (4.5MHz) */);
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_C6, 0x01, 0x00, 0xFF, 0xFF, 0x00);
+
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER,
+                              0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */
+                              0x00, /* FBOFF_VGH = 0, FBOFF_VGL = 0 */
+                              0x32, /* VRP  */
+                              0x32, /* VRN */
+                              0x77, /* reserved */
+                              0xF1, /* APS = 1 (small),
+                                     * VGL_DET_EN = 1, VGH_DET_EN = 1,
+                                     * VGL_TURBO = 1, VGH_TURBO = 1
+                                     */
+                              0xFF, /* VGH1_L_DIV, VGL1_L_DIV (1.5MHz) */
+                              0xFF, /* VGH1_R_DIV, VGL1_R_DIV (1.5MHz) */
+                              0xCC, /* VGH2_L_DIV, VGL2_L_DIV (2.6MHz) */
+                              0xCC, /* VGH2_R_DIV, VGL2_R_DIV (2.6MHz) */
+                              0x77, /* VGH3_L_DIV, VGL3_L_DIV (4.5MHz) */
+                              0x77  /* VGH3_R_DIV, VGL3_R_DIV (4.5MHz) */);
 
        /* Reference voltage. */
-       dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP,
-                         0x07, /* VREF_SEL = 4.2V */
-                         0x07  /* NVREF_SEL = 4.2V */);
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP,
+                              0x07, /* VREF_SEL = 4.2V */
+                              0x07  /* NVREF_SEL = 4.2V */);
        msleep(20);
 
-       dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM,
-                         0x2C, /* VCOMDC_F = -0.67V */
-                         0x2C  /* VCOMDC_B = -0.67V */);
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM,
+                              0x2C, /* VCOMDC_F = -0.67V */
+                              0x2C  /* VCOMDC_B = -0.67V */);
 
        /* Undocumented command. */
-       dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
 
        /* This command is to set forward GIP timing. */
-       dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1,
-                         0x82, 0x10, 0x06, 0x05, 0xA2, 0x0A, 0xA5, 0x12,
-                         0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
-                         0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
-                         0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
-                         0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
-                         0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
-                         0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1,
+                              0x82, 0x10, 0x06, 0x05, 0xA2, 0x0A, 0xA5, 0x12,
+                              0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
+                              0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
+                              0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
+                              0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
+                              0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+                              0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
 
        /* This command is to set backward GIP timing. */
-       dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2,
-                         0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
-                         0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
-                         0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
-                         0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A,
-                         0xA5, 0x00, 0x00, 0x00, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2,
+                              0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                              0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
+                              0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
+                              0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+                              0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
+                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A,
+                              0xA5, 0x00, 0x00, 0x00, 0x00);
 
        /* Adjust the gamma characteristics of the panel. */
-       dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA,
-                         0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 0x35,
-                         0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 0x12,
-                         0x18, 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41,
-                         0x35, 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12,
-                         0x12, 0x18);
+       mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA,
+                              0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 0x35,
+                              0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 0x12,
+                              0x18, 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41,
+                              0x35, 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12,
+                              0x12, 0x18);
 
        return 0;
 }
@@ -499,7 +482,7 @@ static int allpixelson_set(void *data, u64 val)
        struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 
        dev_dbg(ctx->dev, "Setting all pixels on\n");
-       dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON);
+       mipi_dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON);
        msleep(val * 1000);
        /* Reset the panel to get video back */
        drm_panel_disable(&ctx->panel);
index fa9be3c..ee5d20e 100644 (file)
@@ -33,14 +33,6 @@ struct truly_nt35521 *to_truly_nt35521(struct drm_panel *panel)
        return container_of(panel, struct truly_nt35521, panel);
 }
 
-#define dsi_generic_write_seq(dsi, seq...) do {                                \
-               static const u8 d[] = { seq };                          \
-               int ret;                                                \
-               ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));    \
-               if (ret < 0)                                            \
-                       return ret;                                     \
-       } while (0)
-
 static void truly_nt35521_reset(struct truly_nt35521 *ctx)
 {
        gpiod_set_value_cansleep(ctx->reset_gpio, 1);
@@ -59,200 +51,200 @@ static int truly_nt35521_on(struct truly_nt35521 *ctx)
 
        dsi->mode_flags |= MIPI_DSI_MODE_LPM;
 
-       dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
-       dsi_generic_write_seq(dsi, 0xff, 0xaa, 0x55, 0xa5, 0x80);
-       dsi_generic_write_seq(dsi, 0x6f, 0x11, 0x00);
-       dsi_generic_write_seq(dsi, 0xf7, 0x20, 0x00);
-       dsi_generic_write_seq(dsi, 0x6f, 0x01);
-       dsi_generic_write_seq(dsi, 0xb1, 0x21);
-       dsi_generic_write_seq(dsi, 0xbd, 0x01, 0xa0, 0x10, 0x08, 0x01);
-       dsi_generic_write_seq(dsi, 0xb8, 0x01, 0x02, 0x0c, 0x02);
-       dsi_generic_write_seq(dsi, 0xbb, 0x11, 0x11);
-       dsi_generic_write_seq(dsi, 0xbc, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xb6, 0x02);
-       dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x01);
-       dsi_generic_write_seq(dsi, 0xb0, 0x09, 0x09);
-       dsi_generic_write_seq(dsi, 0xb1, 0x09, 0x09);
-       dsi_generic_write_seq(dsi, 0xbc, 0x8c, 0x00);
-       dsi_generic_write_seq(dsi, 0xbd, 0x8c, 0x00);
-       dsi_generic_write_seq(dsi, 0xca, 0x00);
-       dsi_generic_write_seq(dsi, 0xc0, 0x04);
-       dsi_generic_write_seq(dsi, 0xbe, 0xb5);
-       dsi_generic_write_seq(dsi, 0xb3, 0x35, 0x35);
-       dsi_generic_write_seq(dsi, 0xb4, 0x25, 0x25);
-       dsi_generic_write_seq(dsi, 0xb9, 0x43, 0x43);
-       dsi_generic_write_seq(dsi, 0xba, 0x24, 0x24);
-       dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x02);
-       dsi_generic_write_seq(dsi, 0xee, 0x03);
-       dsi_generic_write_seq(dsi, 0xb0,
-                             0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb6, 0x00, 0xc3,
-                             0x00, 0xce, 0x00, 0xe1, 0x00, 0xf3, 0x01, 0x11);
-       dsi_generic_write_seq(dsi, 0xb1,
-                             0x01, 0x2e, 0x01, 0x5c, 0x01, 0x82, 0x01, 0xc3,
-                             0x01, 0xfe, 0x02, 0x00, 0x02, 0x37, 0x02, 0x77);
-       dsi_generic_write_seq(dsi, 0xb2,
-                             0x02, 0xa1, 0x02, 0xd7, 0x02, 0xfe, 0x03, 0x2c,
-                             0x03, 0x4b, 0x03, 0x63, 0x03, 0x8f, 0x03, 0x90);
-       dsi_generic_write_seq(dsi, 0xb3, 0x03, 0x96, 0x03, 0x98);
-       dsi_generic_write_seq(dsi, 0xb4,
-                             0x00, 0x81, 0x00, 0x8b, 0x00, 0x9c, 0x00, 0xa9,
-                             0x00, 0xb5, 0x00, 0xcb, 0x00, 0xdf, 0x01, 0x02);
-       dsi_generic_write_seq(dsi, 0xb5,
-                             0x01, 0x1f, 0x01, 0x51, 0x01, 0x7a, 0x01, 0xbf,
-                             0x01, 0xfa, 0x01, 0xfc, 0x02, 0x34, 0x02, 0x76);
-       dsi_generic_write_seq(dsi, 0xb6,
-                             0x02, 0x9f, 0x02, 0xd7, 0x02, 0xfc, 0x03, 0x2c,
-                             0x03, 0x4a, 0x03, 0x63, 0x03, 0x8f, 0x03, 0xa2);
-       dsi_generic_write_seq(dsi, 0xb7, 0x03, 0xb8, 0x03, 0xba);
-       dsi_generic_write_seq(dsi, 0xb8,
-                             0x00, 0x01, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x2a,
-                             0x00, 0x41, 0x00, 0x67, 0x00, 0x87, 0x00, 0xb9);
-       dsi_generic_write_seq(dsi, 0xb9,
-                             0x00, 0xe2, 0x01, 0x22, 0x01, 0x54, 0x01, 0xa3,
-                             0x01, 0xe6, 0x01, 0xe7, 0x02, 0x24, 0x02, 0x67);
-       dsi_generic_write_seq(dsi, 0xba,
-                             0x02, 0x93, 0x02, 0xcd, 0x02, 0xf6, 0x03, 0x31,
-                             0x03, 0x6c, 0x03, 0xe9, 0x03, 0xef, 0x03, 0xf4);
-       dsi_generic_write_seq(dsi, 0xbb, 0x03, 0xf6, 0x03, 0xf7);
-       dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03);
-       dsi_generic_write_seq(dsi, 0xb0, 0x22, 0x00);
-       dsi_generic_write_seq(dsi, 0xb1, 0x22, 0x00);
-       dsi_generic_write_seq(dsi, 0xb2, 0x05, 0x00, 0x60, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xb3, 0x05, 0x00, 0x60, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xb4, 0x05, 0x00, 0x60, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xb5, 0x05, 0x00, 0x60, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xba, 0x53, 0x00, 0x60, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xbb, 0x53, 0x00, 0x60, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xbc, 0x53, 0x00, 0x60, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xbd, 0x53, 0x00, 0x60, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xc0, 0x00, 0x34, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xc1, 0x00, 0x00, 0x34, 0x00);
-       dsi_generic_write_seq(dsi, 0xc2, 0x00, 0x00, 0x34, 0x00);
-       dsi_generic_write_seq(dsi, 0xc3, 0x00, 0x00, 0x34, 0x00);
-       dsi_generic_write_seq(dsi, 0xc4, 0x60);
-       dsi_generic_write_seq(dsi, 0xc5, 0xc0);
-       dsi_generic_write_seq(dsi, 0xc6, 0x00);
-       dsi_generic_write_seq(dsi, 0xc7, 0x00);
-       dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05);
-       dsi_generic_write_seq(dsi, 0xb0, 0x17, 0x06);
-       dsi_generic_write_seq(dsi, 0xb1, 0x17, 0x06);
-       dsi_generic_write_seq(dsi, 0xb2, 0x17, 0x06);
-       dsi_generic_write_seq(dsi, 0xb3, 0x17, 0x06);
-       dsi_generic_write_seq(dsi, 0xb4, 0x17, 0x06);
-       dsi_generic_write_seq(dsi, 0xb5, 0x17, 0x06);
-       dsi_generic_write_seq(dsi, 0xb6, 0x17, 0x06);
-       dsi_generic_write_seq(dsi, 0xb7, 0x17, 0x06);
-       dsi_generic_write_seq(dsi, 0xb8, 0x00);
-       dsi_generic_write_seq(dsi, 0xb9, 0x00, 0x03);
-       dsi_generic_write_seq(dsi, 0xba, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xbb, 0x02, 0x03);
-       dsi_generic_write_seq(dsi, 0xbc, 0x02, 0x03);
-       dsi_generic_write_seq(dsi, 0xbd, 0x03, 0x03, 0x00, 0x03, 0x03);
-       dsi_generic_write_seq(dsi, 0xc0, 0x0b);
-       dsi_generic_write_seq(dsi, 0xc1, 0x09);
-       dsi_generic_write_seq(dsi, 0xc2, 0xa6);
-       dsi_generic_write_seq(dsi, 0xc3, 0x05);
-       dsi_generic_write_seq(dsi, 0xc4, 0x00);
-       dsi_generic_write_seq(dsi, 0xc5, 0x02);
-       dsi_generic_write_seq(dsi, 0xc6, 0x22);
-       dsi_generic_write_seq(dsi, 0xc7, 0x03);
-       dsi_generic_write_seq(dsi, 0xc8, 0x07, 0x20);
-       dsi_generic_write_seq(dsi, 0xc9, 0x03, 0x20);
-       dsi_generic_write_seq(dsi, 0xca, 0x01, 0x60);
-       dsi_generic_write_seq(dsi, 0xcb, 0x01, 0x60);
-       dsi_generic_write_seq(dsi, 0xcc, 0x00, 0x00, 0x02);
-       dsi_generic_write_seq(dsi, 0xcd, 0x00, 0x00, 0x02);
-       dsi_generic_write_seq(dsi, 0xce, 0x00, 0x00, 0x02);
-       dsi_generic_write_seq(dsi, 0xcf, 0x00, 0x00, 0x02);
-       dsi_generic_write_seq(dsi, 0xd1, 0x00, 0x05, 0x01, 0x07, 0x10);
-       dsi_generic_write_seq(dsi, 0xd2, 0x10, 0x05, 0x05, 0x03, 0x10);
-       dsi_generic_write_seq(dsi, 0xd3, 0x20, 0x00, 0x43, 0x07, 0x10);
-       dsi_generic_write_seq(dsi, 0xd4, 0x30, 0x00, 0x43, 0x07, 0x10);
-       dsi_generic_write_seq(dsi, 0xd0,
-                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xd5,
-                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                             0x00, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xd6,
-                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                             0x00, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xd7,
-                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                             0x00, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xe5, 0x06);
-       dsi_generic_write_seq(dsi, 0xe6, 0x06);
-       dsi_generic_write_seq(dsi, 0xe7, 0x00);
-       dsi_generic_write_seq(dsi, 0xe8, 0x06);
-       dsi_generic_write_seq(dsi, 0xe9, 0x06);
-       dsi_generic_write_seq(dsi, 0xea, 0x06);
-       dsi_generic_write_seq(dsi, 0xeb, 0x00);
-       dsi_generic_write_seq(dsi, 0xec, 0x00);
-       dsi_generic_write_seq(dsi, 0xed, 0x30);
-       dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x06);
-       dsi_generic_write_seq(dsi, 0xb0, 0x31, 0x31);
-       dsi_generic_write_seq(dsi, 0xb1, 0x31, 0x31);
-       dsi_generic_write_seq(dsi, 0xb2, 0x2d, 0x2e);
-       dsi_generic_write_seq(dsi, 0xb3, 0x31, 0x34);
-       dsi_generic_write_seq(dsi, 0xb4, 0x29, 0x2a);
-       dsi_generic_write_seq(dsi, 0xb5, 0x12, 0x10);
-       dsi_generic_write_seq(dsi, 0xb6, 0x18, 0x16);
-       dsi_generic_write_seq(dsi, 0xb7, 0x00, 0x02);
-       dsi_generic_write_seq(dsi, 0xb8, 0x08, 0x31);
-       dsi_generic_write_seq(dsi, 0xb9, 0x31, 0x31);
-       dsi_generic_write_seq(dsi, 0xba, 0x31, 0x31);
-       dsi_generic_write_seq(dsi, 0xbb, 0x31, 0x08);
-       dsi_generic_write_seq(dsi, 0xbc, 0x03, 0x01);
-       dsi_generic_write_seq(dsi, 0xbd, 0x17, 0x19);
-       dsi_generic_write_seq(dsi, 0xbe, 0x11, 0x13);
-       dsi_generic_write_seq(dsi, 0xbf, 0x2a, 0x29);
-       dsi_generic_write_seq(dsi, 0xc0, 0x34, 0x31);
-       dsi_generic_write_seq(dsi, 0xc1, 0x2e, 0x2d);
-       dsi_generic_write_seq(dsi, 0xc2, 0x31, 0x31);
-       dsi_generic_write_seq(dsi, 0xc3, 0x31, 0x31);
-       dsi_generic_write_seq(dsi, 0xc4, 0x31, 0x31);
-       dsi_generic_write_seq(dsi, 0xc5, 0x31, 0x31);
-       dsi_generic_write_seq(dsi, 0xc6, 0x2e, 0x2d);
-       dsi_generic_write_seq(dsi, 0xc7, 0x31, 0x34);
-       dsi_generic_write_seq(dsi, 0xc8, 0x29, 0x2a);
-       dsi_generic_write_seq(dsi, 0xc9, 0x17, 0x19);
-       dsi_generic_write_seq(dsi, 0xca, 0x11, 0x13);
-       dsi_generic_write_seq(dsi, 0xcb, 0x03, 0x01);
-       dsi_generic_write_seq(dsi, 0xcc, 0x08, 0x31);
-       dsi_generic_write_seq(dsi, 0xcd, 0x31, 0x31);
-       dsi_generic_write_seq(dsi, 0xce, 0x31, 0x31);
-       dsi_generic_write_seq(dsi, 0xcf, 0x31, 0x08);
-       dsi_generic_write_seq(dsi, 0xd0, 0x00, 0x02);
-       dsi_generic_write_seq(dsi, 0xd1, 0x12, 0x10);
-       dsi_generic_write_seq(dsi, 0xd2, 0x18, 0x16);
-       dsi_generic_write_seq(dsi, 0xd3, 0x2a, 0x29);
-       dsi_generic_write_seq(dsi, 0xd4, 0x34, 0x31);
-       dsi_generic_write_seq(dsi, 0xd5, 0x2d, 0x2e);
-       dsi_generic_write_seq(dsi, 0xd6, 0x31, 0x31);
-       dsi_generic_write_seq(dsi, 0xd7, 0x31, 0x31);
-       dsi_generic_write_seq(dsi, 0xe5, 0x31, 0x31);
-       dsi_generic_write_seq(dsi, 0xe6, 0x31, 0x31);
-       dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xe7, 0x00);
-       dsi_generic_write_seq(dsi, 0x6f, 0x02);
-       dsi_generic_write_seq(dsi, 0xf7, 0x47);
-       dsi_generic_write_seq(dsi, 0x6f, 0x0a);
-       dsi_generic_write_seq(dsi, 0xf7, 0x02);
-       dsi_generic_write_seq(dsi, 0x6f, 0x17);
-       dsi_generic_write_seq(dsi, 0xf4, 0x60);
-       dsi_generic_write_seq(dsi, 0x6f, 0x01);
-       dsi_generic_write_seq(dsi, 0xf9, 0x46);
-       dsi_generic_write_seq(dsi, 0x6f, 0x11);
-       dsi_generic_write_seq(dsi, 0xf3, 0x01);
-       dsi_generic_write_seq(dsi, 0x35, 0x00);
-       dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
-       dsi_generic_write_seq(dsi, 0xd9, 0x02, 0x03, 0x00);
-       dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
-       dsi_generic_write_seq(dsi, 0xb1, 0x6c, 0x21);
-       dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, 0x35, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xff, 0xaa, 0x55, 0xa5, 0x80);
+       mipi_dsi_generic_write_seq(dsi, 0x6f, 0x11, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xf7, 0x20, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0x6f, 0x01);
+       mipi_dsi_generic_write_seq(dsi, 0xb1, 0x21);
+       mipi_dsi_generic_write_seq(dsi, 0xbd, 0x01, 0xa0, 0x10, 0x08, 0x01);
+       mipi_dsi_generic_write_seq(dsi, 0xb8, 0x01, 0x02, 0x0c, 0x02);
+       mipi_dsi_generic_write_seq(dsi, 0xbb, 0x11, 0x11);
+       mipi_dsi_generic_write_seq(dsi, 0xbc, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xb6, 0x02);
+       mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x01);
+       mipi_dsi_generic_write_seq(dsi, 0xb0, 0x09, 0x09);
+       mipi_dsi_generic_write_seq(dsi, 0xb1, 0x09, 0x09);
+       mipi_dsi_generic_write_seq(dsi, 0xbc, 0x8c, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xbd, 0x8c, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xca, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xc0, 0x04);
+       mipi_dsi_generic_write_seq(dsi, 0xbe, 0xb5);
+       mipi_dsi_generic_write_seq(dsi, 0xb3, 0x35, 0x35);
+       mipi_dsi_generic_write_seq(dsi, 0xb4, 0x25, 0x25);
+       mipi_dsi_generic_write_seq(dsi, 0xb9, 0x43, 0x43);
+       mipi_dsi_generic_write_seq(dsi, 0xba, 0x24, 0x24);
+       mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x02);
+       mipi_dsi_generic_write_seq(dsi, 0xee, 0x03);
+       mipi_dsi_generic_write_seq(dsi, 0xb0,
+                                  0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb6, 0x00, 0xc3,
+                                  0x00, 0xce, 0x00, 0xe1, 0x00, 0xf3, 0x01, 0x11);
+       mipi_dsi_generic_write_seq(dsi, 0xb1,
+                                  0x01, 0x2e, 0x01, 0x5c, 0x01, 0x82, 0x01, 0xc3,
+                                  0x01, 0xfe, 0x02, 0x00, 0x02, 0x37, 0x02, 0x77);
+       mipi_dsi_generic_write_seq(dsi, 0xb2,
+                                  0x02, 0xa1, 0x02, 0xd7, 0x02, 0xfe, 0x03, 0x2c,
+                                  0x03, 0x4b, 0x03, 0x63, 0x03, 0x8f, 0x03, 0x90);
+       mipi_dsi_generic_write_seq(dsi, 0xb3, 0x03, 0x96, 0x03, 0x98);
+       mipi_dsi_generic_write_seq(dsi, 0xb4,
+                                  0x00, 0x81, 0x00, 0x8b, 0x00, 0x9c, 0x00, 0xa9,
+                                  0x00, 0xb5, 0x00, 0xcb, 0x00, 0xdf, 0x01, 0x02);
+       mipi_dsi_generic_write_seq(dsi, 0xb5,
+                                  0x01, 0x1f, 0x01, 0x51, 0x01, 0x7a, 0x01, 0xbf,
+                                  0x01, 0xfa, 0x01, 0xfc, 0x02, 0x34, 0x02, 0x76);
+       mipi_dsi_generic_write_seq(dsi, 0xb6,
+                                  0x02, 0x9f, 0x02, 0xd7, 0x02, 0xfc, 0x03, 0x2c,
+                                  0x03, 0x4a, 0x03, 0x63, 0x03, 0x8f, 0x03, 0xa2);
+       mipi_dsi_generic_write_seq(dsi, 0xb7, 0x03, 0xb8, 0x03, 0xba);
+       mipi_dsi_generic_write_seq(dsi, 0xb8,
+                                  0x00, 0x01, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x2a,
+                                  0x00, 0x41, 0x00, 0x67, 0x00, 0x87, 0x00, 0xb9);
+       mipi_dsi_generic_write_seq(dsi, 0xb9,
+                                  0x00, 0xe2, 0x01, 0x22, 0x01, 0x54, 0x01, 0xa3,
+                                  0x01, 0xe6, 0x01, 0xe7, 0x02, 0x24, 0x02, 0x67);
+       mipi_dsi_generic_write_seq(dsi, 0xba,
+                                  0x02, 0x93, 0x02, 0xcd, 0x02, 0xf6, 0x03, 0x31,
+                                  0x03, 0x6c, 0x03, 0xe9, 0x03, 0xef, 0x03, 0xf4);
+       mipi_dsi_generic_write_seq(dsi, 0xbb, 0x03, 0xf6, 0x03, 0xf7);
+       mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03);
+       mipi_dsi_generic_write_seq(dsi, 0xb0, 0x22, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xb1, 0x22, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xb2, 0x05, 0x00, 0x60, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xb3, 0x05, 0x00, 0x60, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xb4, 0x05, 0x00, 0x60, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xb5, 0x05, 0x00, 0x60, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xba, 0x53, 0x00, 0x60, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xbb, 0x53, 0x00, 0x60, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xbc, 0x53, 0x00, 0x60, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xbd, 0x53, 0x00, 0x60, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xc0, 0x00, 0x34, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xc1, 0x00, 0x00, 0x34, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xc2, 0x00, 0x00, 0x34, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xc3, 0x00, 0x00, 0x34, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xc4, 0x60);
+       mipi_dsi_generic_write_seq(dsi, 0xc5, 0xc0);
+       mipi_dsi_generic_write_seq(dsi, 0xc6, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xc7, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05);
+       mipi_dsi_generic_write_seq(dsi, 0xb0, 0x17, 0x06);
+       mipi_dsi_generic_write_seq(dsi, 0xb1, 0x17, 0x06);
+       mipi_dsi_generic_write_seq(dsi, 0xb2, 0x17, 0x06);
+       mipi_dsi_generic_write_seq(dsi, 0xb3, 0x17, 0x06);
+       mipi_dsi_generic_write_seq(dsi, 0xb4, 0x17, 0x06);
+       mipi_dsi_generic_write_seq(dsi, 0xb5, 0x17, 0x06);
+       mipi_dsi_generic_write_seq(dsi, 0xb6, 0x17, 0x06);
+       mipi_dsi_generic_write_seq(dsi, 0xb7, 0x17, 0x06);
+       mipi_dsi_generic_write_seq(dsi, 0xb8, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xb9, 0x00, 0x03);
+       mipi_dsi_generic_write_seq(dsi, 0xba, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xbb, 0x02, 0x03);
+       mipi_dsi_generic_write_seq(dsi, 0xbc, 0x02, 0x03);
+       mipi_dsi_generic_write_seq(dsi, 0xbd, 0x03, 0x03, 0x00, 0x03, 0x03);
+       mipi_dsi_generic_write_seq(dsi, 0xc0, 0x0b);
+       mipi_dsi_generic_write_seq(dsi, 0xc1, 0x09);
+       mipi_dsi_generic_write_seq(dsi, 0xc2, 0xa6);
+       mipi_dsi_generic_write_seq(dsi, 0xc3, 0x05);
+       mipi_dsi_generic_write_seq(dsi, 0xc4, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xc5, 0x02);
+       mipi_dsi_generic_write_seq(dsi, 0xc6, 0x22);
+       mipi_dsi_generic_write_seq(dsi, 0xc7, 0x03);
+       mipi_dsi_generic_write_seq(dsi, 0xc8, 0x07, 0x20);
+       mipi_dsi_generic_write_seq(dsi, 0xc9, 0x03, 0x20);
+       mipi_dsi_generic_write_seq(dsi, 0xca, 0x01, 0x60);
+       mipi_dsi_generic_write_seq(dsi, 0xcb, 0x01, 0x60);
+       mipi_dsi_generic_write_seq(dsi, 0xcc, 0x00, 0x00, 0x02);
+       mipi_dsi_generic_write_seq(dsi, 0xcd, 0x00, 0x00, 0x02);
+       mipi_dsi_generic_write_seq(dsi, 0xce, 0x00, 0x00, 0x02);
+       mipi_dsi_generic_write_seq(dsi, 0xcf, 0x00, 0x00, 0x02);
+       mipi_dsi_generic_write_seq(dsi, 0xd1, 0x00, 0x05, 0x01, 0x07, 0x10);
+       mipi_dsi_generic_write_seq(dsi, 0xd2, 0x10, 0x05, 0x05, 0x03, 0x10);
+       mipi_dsi_generic_write_seq(dsi, 0xd3, 0x20, 0x00, 0x43, 0x07, 0x10);
+       mipi_dsi_generic_write_seq(dsi, 0xd4, 0x30, 0x00, 0x43, 0x07, 0x10);
+       mipi_dsi_generic_write_seq(dsi, 0xd0,
+                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xd5,
+                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                  0x00, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xd6,
+                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                  0x00, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xd7,
+                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                  0x00, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xe5, 0x06);
+       mipi_dsi_generic_write_seq(dsi, 0xe6, 0x06);
+       mipi_dsi_generic_write_seq(dsi, 0xe7, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xe8, 0x06);
+       mipi_dsi_generic_write_seq(dsi, 0xe9, 0x06);
+       mipi_dsi_generic_write_seq(dsi, 0xea, 0x06);
+       mipi_dsi_generic_write_seq(dsi, 0xeb, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xec, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xed, 0x30);
+       mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x06);
+       mipi_dsi_generic_write_seq(dsi, 0xb0, 0x31, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xb1, 0x31, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xb2, 0x2d, 0x2e);
+       mipi_dsi_generic_write_seq(dsi, 0xb3, 0x31, 0x34);
+       mipi_dsi_generic_write_seq(dsi, 0xb4, 0x29, 0x2a);
+       mipi_dsi_generic_write_seq(dsi, 0xb5, 0x12, 0x10);
+       mipi_dsi_generic_write_seq(dsi, 0xb6, 0x18, 0x16);
+       mipi_dsi_generic_write_seq(dsi, 0xb7, 0x00, 0x02);
+       mipi_dsi_generic_write_seq(dsi, 0xb8, 0x08, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xb9, 0x31, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xba, 0x31, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xbb, 0x31, 0x08);
+       mipi_dsi_generic_write_seq(dsi, 0xbc, 0x03, 0x01);
+       mipi_dsi_generic_write_seq(dsi, 0xbd, 0x17, 0x19);
+       mipi_dsi_generic_write_seq(dsi, 0xbe, 0x11, 0x13);
+       mipi_dsi_generic_write_seq(dsi, 0xbf, 0x2a, 0x29);
+       mipi_dsi_generic_write_seq(dsi, 0xc0, 0x34, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xc1, 0x2e, 0x2d);
+       mipi_dsi_generic_write_seq(dsi, 0xc2, 0x31, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xc3, 0x31, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xc4, 0x31, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xc5, 0x31, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xc6, 0x2e, 0x2d);
+       mipi_dsi_generic_write_seq(dsi, 0xc7, 0x31, 0x34);
+       mipi_dsi_generic_write_seq(dsi, 0xc8, 0x29, 0x2a);
+       mipi_dsi_generic_write_seq(dsi, 0xc9, 0x17, 0x19);
+       mipi_dsi_generic_write_seq(dsi, 0xca, 0x11, 0x13);
+       mipi_dsi_generic_write_seq(dsi, 0xcb, 0x03, 0x01);
+       mipi_dsi_generic_write_seq(dsi, 0xcc, 0x08, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xcd, 0x31, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xce, 0x31, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xcf, 0x31, 0x08);
+       mipi_dsi_generic_write_seq(dsi, 0xd0, 0x00, 0x02);
+       mipi_dsi_generic_write_seq(dsi, 0xd1, 0x12, 0x10);
+       mipi_dsi_generic_write_seq(dsi, 0xd2, 0x18, 0x16);
+       mipi_dsi_generic_write_seq(dsi, 0xd3, 0x2a, 0x29);
+       mipi_dsi_generic_write_seq(dsi, 0xd4, 0x34, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xd5, 0x2d, 0x2e);
+       mipi_dsi_generic_write_seq(dsi, 0xd6, 0x31, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xd7, 0x31, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xe5, 0x31, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xe6, 0x31, 0x31);
+       mipi_dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xe7, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0x6f, 0x02);
+       mipi_dsi_generic_write_seq(dsi, 0xf7, 0x47);
+       mipi_dsi_generic_write_seq(dsi, 0x6f, 0x0a);
+       mipi_dsi_generic_write_seq(dsi, 0xf7, 0x02);
+       mipi_dsi_generic_write_seq(dsi, 0x6f, 0x17);
+       mipi_dsi_generic_write_seq(dsi, 0xf4, 0x60);
+       mipi_dsi_generic_write_seq(dsi, 0x6f, 0x01);
+       mipi_dsi_generic_write_seq(dsi, 0xf9, 0x46);
+       mipi_dsi_generic_write_seq(dsi, 0x6f, 0x11);
+       mipi_dsi_generic_write_seq(dsi, 0xf3, 0x01);
+       mipi_dsi_generic_write_seq(dsi, 0x35, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xd9, 0x02, 0x03, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0xb1, 0x6c, 0x21);
+       mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
+       mipi_dsi_generic_write_seq(dsi, 0x35, 0x00);
 
        ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
        if (ret < 0) {
@@ -268,7 +260,7 @@ static int truly_nt35521_on(struct truly_nt35521 *ctx)
        }
        usleep_range(1000, 2000);
 
-       dsi_generic_write_seq(dsi, 0x53, 0x24);
+       mipi_dsi_generic_write_seq(dsi, 0x53, 0x24);
 
        return 0;
 }
diff --git a/drivers/gpu/drm/panel/panel-visionox-vtdr6130.c b/drivers/gpu/drm/panel/panel-visionox-vtdr6130.c
new file mode 100644 (file)
index 0000000..f9a6abc
--- /dev/null
@@ -0,0 +1,358 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2023, Linaro Limited
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#include <drm/display/drm_dsc.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+#include <video/mipi_display.h>
+
+struct visionox_vtdr6130 {
+       struct drm_panel panel;
+       struct mipi_dsi_device *dsi;
+       struct gpio_desc *reset_gpio;
+       struct regulator_bulk_data supplies[3];
+       bool prepared;
+};
+
+static inline struct visionox_vtdr6130 *to_visionox_vtdr6130(struct drm_panel *panel)
+{
+       return container_of(panel, struct visionox_vtdr6130, panel);
+}
+
+static void visionox_vtdr6130_reset(struct visionox_vtdr6130 *ctx)
+{
+       gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+       usleep_range(10000, 11000);
+       gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+       usleep_range(10000, 11000);
+       gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+       usleep_range(10000, 11000);
+}
+
+static int visionox_vtdr6130_on(struct visionox_vtdr6130 *ctx)
+{
+       struct mipi_dsi_device *dsi = ctx->dsi;
+       struct device *dev = &dsi->dev;
+       int ret;
+
+       dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+       ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+       if (ret)
+               return ret;
+
+       mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
+       mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, 0x00, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x59, 0x09);
+       mipi_dsi_dcs_write_seq(dsi, 0x6c, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x6f, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0x70,
+                              0x12, 0x00, 0x00, 0xab, 0x30, 0x80, 0x09, 0x60, 0x04,
+                              0x38, 0x00, 0x28, 0x02, 0x1c, 0x02, 0x1c, 0x02, 0x00,
+                              0x02, 0x0e, 0x00, 0x20, 0x03, 0xdd, 0x00, 0x07, 0x00,
+                              0x0c, 0x02, 0x77, 0x02, 0x8b, 0x18, 0x00, 0x10, 0xf0,
+                              0x07, 0x10, 0x20, 0x00, 0x06, 0x0f, 0x0f, 0x33, 0x0e,
+                              0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62, 0x69, 0x70, 0x77,
+                              0x79, 0x7b, 0x7d, 0x7e, 0x02, 0x02, 0x22, 0x00, 0x2a,
+                              0x40, 0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8,
+                              0x3b, 0x38, 0x3b, 0x78, 0x3b, 0xb6, 0x4b, 0xb6, 0x4b,
+                              0xf4, 0x4b, 0xf4, 0x6c, 0x34, 0x84, 0x74, 0x00, 0x00,
+                              0x00, 0x00, 0x00, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xaa, 0x10);
+       mipi_dsi_dcs_write_seq(dsi, 0xb1,
+                              0x01, 0x38, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x01, 0x66,
+                              0x00, 0x14, 0x00, 0x14, 0x00, 0x01, 0x66, 0x00, 0x14,
+                              0x05, 0xcc, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xaa, 0x13);
+       mipi_dsi_dcs_write_seq(dsi, 0xce,
+                              0x09, 0x11, 0x09, 0x11, 0x08, 0xc1, 0x07, 0xfa, 0x05,
+                              0xa4, 0x00, 0x3c, 0x00, 0x34, 0x00, 0x24, 0x00, 0x0c,
+                              0x00, 0x0c, 0x04, 0x00, 0x35);
+       mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xaa, 0x14);
+       mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x03, 0x33);
+       mipi_dsi_dcs_write_seq(dsi, 0xb4,
+                              0x00, 0x33, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
+                              0x3e, 0x00, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xb5,
+                              0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x06, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0x00, 0x08, 0x09, 0x09, 0x09);
+       mipi_dsi_dcs_write_seq(dsi, 0xbc,
+                              0x10, 0x00, 0x00, 0x06, 0x11, 0x09, 0x3b, 0x09, 0x47,
+                              0x09, 0x47, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xbe,
+                              0x10, 0x10, 0x00, 0x08, 0x22, 0x09, 0x19, 0x09, 0x25,
+                              0x09, 0x25, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0x5a, 0x80);
+       mipi_dsi_dcs_write_seq(dsi, 0x65, 0x14);
+       mipi_dsi_dcs_write_seq(dsi, 0xfa, 0x08, 0x08, 0x08);
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0x5a, 0x81);
+       mipi_dsi_dcs_write_seq(dsi, 0x65, 0x05);
+       mipi_dsi_dcs_write_seq(dsi, 0xf3, 0x0f);
+       mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xaa, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0x5a, 0x82);
+       mipi_dsi_dcs_write_seq(dsi, 0xf9, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0x51, 0x83);
+       mipi_dsi_dcs_write_seq(dsi, 0x65, 0x04);
+       mipi_dsi_dcs_write_seq(dsi, 0xf8, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0x5a, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, 0x65, 0x01);
+       mipi_dsi_dcs_write_seq(dsi, 0xf4, 0x9a);
+       mipi_dsi_dcs_write_seq(dsi, 0xff, 0x5a, 0x00);
+
+       ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+       if (ret < 0) {
+               dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+               return ret;
+       }
+       msleep(120);
+
+       ret = mipi_dsi_dcs_set_display_on(dsi);
+       if (ret < 0) {
+               dev_err(dev, "Failed to set display on: %d\n", ret);
+               return ret;
+       }
+       msleep(20);
+
+       return 0;
+}
+
+static int visionox_vtdr6130_off(struct visionox_vtdr6130 *ctx)
+{
+       struct mipi_dsi_device *dsi = ctx->dsi;
+       struct device *dev = &dsi->dev;
+       int ret;
+
+       dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+       ret = mipi_dsi_dcs_set_display_off(dsi);
+       if (ret < 0) {
+               dev_err(dev, "Failed to set display off: %d\n", ret);
+               return ret;
+       }
+       msleep(20);
+
+       ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+       if (ret < 0) {
+               dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+               return ret;
+       }
+       msleep(120);
+
+       return 0;
+}
+
+static int visionox_vtdr6130_prepare(struct drm_panel *panel)
+{
+       struct visionox_vtdr6130 *ctx = to_visionox_vtdr6130(panel);
+       struct device *dev = &ctx->dsi->dev;
+       int ret;
+
+       if (ctx->prepared)
+               return 0;
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies),
+                                   ctx->supplies);
+       if (ret < 0)
+               return ret;
+
+       visionox_vtdr6130_reset(ctx);
+
+       ret = visionox_vtdr6130_on(ctx);
+       if (ret < 0) {
+               dev_err(dev, "Failed to initialize panel: %d\n", ret);
+               gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+               regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+               return ret;
+       }
+
+       ctx->prepared = true;
+       return 0;
+}
+
+static int visionox_vtdr6130_unprepare(struct drm_panel *panel)
+{
+       struct visionox_vtdr6130 *ctx = to_visionox_vtdr6130(panel);
+       struct device *dev = &ctx->dsi->dev;
+       int ret;
+
+       if (!ctx->prepared)
+               return 0;
+
+       ret = visionox_vtdr6130_off(ctx);
+       if (ret < 0)
+               dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+       gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+
+       regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+
+       ctx->prepared = false;
+       return 0;
+}
+
+static const struct drm_display_mode visionox_vtdr6130_mode = {
+       .clock = (1080 + 20 + 2 + 20) * (2400 + 20 + 2 + 18) * 144 / 1000,
+       .hdisplay = 1080,
+       .hsync_start = 1080 + 20,
+       .hsync_end = 1080 + 20 + 2,
+       .htotal = 1080 + 20 + 2 + 20,
+       .vdisplay = 2400,
+       .vsync_start = 2400 + 20,
+       .vsync_end = 2400 + 20 + 2,
+       .vtotal = 2400 + 20 + 2 + 18,
+       .width_mm = 71,
+       .height_mm = 157,
+};
+
+static int visionox_vtdr6130_get_modes(struct drm_panel *panel,
+                                      struct drm_connector *connector)
+{
+       struct drm_display_mode *mode;
+
+       mode = drm_mode_duplicate(connector->dev, &visionox_vtdr6130_mode);
+       if (!mode)
+               return -ENOMEM;
+
+       drm_mode_set_name(mode);
+
+       mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+       connector->display_info.width_mm = mode->width_mm;
+       connector->display_info.height_mm = mode->height_mm;
+       drm_mode_probed_add(connector, mode);
+
+       return 1;
+}
+
+static const struct drm_panel_funcs visionox_vtdr6130_panel_funcs = {
+       .prepare = visionox_vtdr6130_prepare,
+       .unprepare = visionox_vtdr6130_unprepare,
+       .get_modes = visionox_vtdr6130_get_modes,
+};
+
+static int visionox_vtdr6130_bl_update_status(struct backlight_device *bl)
+{
+       struct mipi_dsi_device *dsi = bl_get_data(bl);
+       u16 brightness = backlight_get_brightness(bl);
+       /* Panel needs big-endian order of brightness value */
+       u8 payload[2] = { brightness >> 8, brightness & 0xff };
+       int ret;
+
+       ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
+                                payload, sizeof(payload));
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static const struct backlight_ops visionox_vtdr6130_bl_ops = {
+       .update_status = visionox_vtdr6130_bl_update_status,
+};
+
+static struct backlight_device *
+visionox_vtdr6130_create_backlight(struct mipi_dsi_device *dsi)
+{
+       struct device *dev = &dsi->dev;
+       const struct backlight_properties props = {
+               .type = BACKLIGHT_RAW,
+               .brightness = 4095,
+               .max_brightness = 4095,
+       };
+
+       return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+                                             &visionox_vtdr6130_bl_ops, &props);
+}
+
+static int visionox_vtdr6130_probe(struct mipi_dsi_device *dsi)
+{
+       struct device *dev = &dsi->dev;
+       struct visionox_vtdr6130 *ctx;
+       int ret;
+
+       ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       ctx->supplies[0].supply = "vddio";
+       ctx->supplies[1].supply = "vci";
+       ctx->supplies[2].supply = "vdd";
+
+       ret = devm_regulator_bulk_get(&dsi->dev, ARRAY_SIZE(ctx->supplies),
+                                     ctx->supplies);
+       if (ret < 0)
+               return ret;
+
+       ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+       if (IS_ERR(ctx->reset_gpio))
+               return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+                                    "Failed to get reset-gpios\n");
+
+       ctx->dsi = dsi;
+       mipi_dsi_set_drvdata(dsi, ctx);
+
+       dsi->lanes = 4;
+       dsi->format = MIPI_DSI_FMT_RGB888;
+       dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_NO_EOT_PACKET |
+                         MIPI_DSI_CLOCK_NON_CONTINUOUS;
+
+       drm_panel_init(&ctx->panel, dev, &visionox_vtdr6130_panel_funcs,
+                      DRM_MODE_CONNECTOR_DSI);
+
+       ctx->panel.backlight = visionox_vtdr6130_create_backlight(dsi);
+       if (IS_ERR(ctx->panel.backlight))
+               return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
+                                    "Failed to create backlight\n");
+
+       drm_panel_add(&ctx->panel);
+
+       ret = mipi_dsi_attach(dsi);
+       if (ret < 0) {
+               dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+               drm_panel_remove(&ctx->panel);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void visionox_vtdr6130_remove(struct mipi_dsi_device *dsi)
+{
+       struct visionox_vtdr6130 *ctx = mipi_dsi_get_drvdata(dsi);
+       int ret;
+
+       ret = mipi_dsi_detach(dsi);
+       if (ret < 0)
+               dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+       drm_panel_remove(&ctx->panel);
+}
+
+static const struct of_device_id visionox_vtdr6130_of_match[] = {
+       { .compatible = "visionox,vtdr6130" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, visionox_vtdr6130_of_match);
+
+static struct mipi_dsi_driver visionox_vtdr6130_driver = {
+       .probe = visionox_vtdr6130_probe,
+       .remove = visionox_vtdr6130_remove,
+       .driver = {
+               .name = "panel-visionox-vtdr6130",
+               .of_match_table = visionox_vtdr6130_of_match,
+       },
+};
+module_mipi_dsi_driver(visionox_vtdr6130_driver);
+
+MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>");
+MODULE_DESCRIPTION("Panel driver for the Visionox VTDR6130 AMOLED DSI panel");
+MODULE_LICENSE("GPL");
index 2c54733..8670386 100644 (file)
@@ -60,14 +60,6 @@ static inline struct xpp055c272 *panel_to_xpp055c272(struct drm_panel *panel)
        return container_of(panel, struct xpp055c272, panel);
 }
 
-#define dsi_generic_write_seq(dsi, cmd, seq...) do {                   \
-               static const u8 b[] = { cmd, seq };                     \
-               int ret;                                                \
-               ret = mipi_dsi_dcs_write_buffer(dsi, b, ARRAY_SIZE(b)); \
-               if (ret < 0)                                            \
-                       return ret;                                     \
-       } while (0)
-
 static int xpp055c272_init_sequence(struct xpp055c272 *ctx)
 {
        struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
@@ -77,60 +69,60 @@ static int xpp055c272_init_sequence(struct xpp055c272 *ctx)
         * Init sequence was supplied by the panel vendor without much
         * documentation.
         */
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETEXTC, 0xf1, 0x12, 0x83);
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETMIPI,
-                             0x33, 0x81, 0x05, 0xf9, 0x0e, 0x0e, 0x00, 0x00,
-                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x25,
-                             0x00, 0x91, 0x0a, 0x00, 0x00, 0x02, 0x4f, 0x01,
-                             0x00, 0x00, 0x37);
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETPOWER_EXT, 0x25);
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETPCR, 0x02, 0x11, 0x00);
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETRGBIF,
-                             0x0c, 0x10, 0x0a, 0x50, 0x03, 0xff, 0x00, 0x00,
-                             0x00, 0x00);
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETSCR,
-                             0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70,
-                             0x00);
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETVDC, 0x46);
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETPANEL, 0x0b);
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETCYC, 0x80);
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETDISP, 0xc8, 0x12, 0x30);
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETEQ,
-                             0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00,
-                             0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10);
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETPOWER,
-                             0x53, 0x00, 0x1e, 0x1e, 0x77, 0xe1, 0xcc, 0xdd,
-                             0x67, 0x77, 0x33, 0x33);
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETECO, 0x00, 0x00, 0xff,
-                             0xff, 0x01, 0xff);
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETBGP, 0x09, 0x09);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETEXTC, 0xf1, 0x12, 0x83);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETMIPI,
+                              0x33, 0x81, 0x05, 0xf9, 0x0e, 0x0e, 0x00, 0x00,
+                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x25,
+                              0x00, 0x91, 0x0a, 0x00, 0x00, 0x02, 0x4f, 0x01,
+                              0x00, 0x00, 0x37);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETPOWER_EXT, 0x25);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETPCR, 0x02, 0x11, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETRGBIF,
+                              0x0c, 0x10, 0x0a, 0x50, 0x03, 0xff, 0x00, 0x00,
+                              0x00, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETSCR,
+                              0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70,
+                              0x00);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETVDC, 0x46);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETPANEL, 0x0b);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETCYC, 0x80);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETDISP, 0xc8, 0x12, 0x30);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETEQ,
+                              0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00,
+                              0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETPOWER,
+                              0x53, 0x00, 0x1e, 0x1e, 0x77, 0xe1, 0xcc, 0xdd,
+                              0x67, 0x77, 0x33, 0x33);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETECO, 0x00, 0x00, 0xff,
+                              0xff, 0x01, 0xff);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETBGP, 0x09, 0x09);
        msleep(20);
 
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETVCOM, 0x87, 0x95);
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETGIP1,
-                             0xc2, 0x10, 0x05, 0x05, 0x10, 0x05, 0xa0, 0x12,
-                             0x31, 0x23, 0x3f, 0x81, 0x0a, 0xa0, 0x37, 0x18,
-                             0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
-                             0x01, 0x00, 0x00, 0x00, 0x48, 0xf8, 0x86, 0x42,
-                             0x08, 0x88, 0x88, 0x80, 0x88, 0x88, 0x88, 0x58,
-                             0xf8, 0x87, 0x53, 0x18, 0x88, 0x88, 0x81, 0x88,
-                             0x88, 0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
-                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETGIP2,
-                             0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
-                             0x00, 0x00, 0x00, 0x00, 0x1f, 0x88, 0x81, 0x35,
-                             0x78, 0x88, 0x88, 0x85, 0x88, 0x88, 0x88, 0x0f,
-                             0x88, 0x80, 0x24, 0x68, 0x88, 0x88, 0x84, 0x88,
-                             0x88, 0x88, 0x23, 0x10, 0x00, 0x00, 0x1c, 0x00,
-                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x05,
-                             0xa0, 0x00, 0x00, 0x00, 0x00);
-       dsi_generic_write_seq(dsi, XPP055C272_CMD_SETGAMMA,
-                             0x00, 0x06, 0x08, 0x2a, 0x31, 0x3f, 0x38, 0x36,
-                             0x07, 0x0c, 0x0d, 0x11, 0x13, 0x12, 0x13, 0x11,
-                             0x18, 0x00, 0x06, 0x08, 0x2a, 0x31, 0x3f, 0x38,
-                             0x36, 0x07, 0x0c, 0x0d, 0x11, 0x13, 0x12, 0x13,
-                             0x11, 0x18);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETVCOM, 0x87, 0x95);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETGIP1,
+                              0xc2, 0x10, 0x05, 0x05, 0x10, 0x05, 0xa0, 0x12,
+                              0x31, 0x23, 0x3f, 0x81, 0x0a, 0xa0, 0x37, 0x18,
+                              0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
+                              0x01, 0x00, 0x00, 0x00, 0x48, 0xf8, 0x86, 0x42,
+                              0x08, 0x88, 0x88, 0x80, 0x88, 0x88, 0x88, 0x58,
+                              0xf8, 0x87, 0x53, 0x18, 0x88, 0x88, 0x81, 0x88,
+                              0x88, 0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETGIP2,
+                              0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+                              0x00, 0x00, 0x00, 0x00, 0x1f, 0x88, 0x81, 0x35,
+                              0x78, 0x88, 0x88, 0x85, 0x88, 0x88, 0x88, 0x0f,
+                              0x88, 0x80, 0x24, 0x68, 0x88, 0x88, 0x84, 0x88,
+                              0x88, 0x88, 0x23, 0x10, 0x00, 0x00, 0x1c, 0x00,
+                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x05,
+                              0xa0, 0x00, 0x00, 0x00, 0x00);
+       mipi_dsi_dcs_write_seq(dsi, XPP055C272_CMD_SETGAMMA,
+                              0x00, 0x06, 0x08, 0x2a, 0x31, 0x3f, 0x38, 0x36,
+                              0x07, 0x0c, 0x0d, 0x11, 0x13, 0x12, 0x13, 0x11,
+                              0x18, 0x00, 0x06, 0x08, 0x2a, 0x31, 0x3f, 0x38,
+                              0x36, 0x07, 0x0c, 0x0d, 0x11, 0x13, 0x12, 0x13,
+                              0x11, 0x18);
 
        msleep(60);
 
index 97a277f..62a596d 100644 (file)
@@ -15,6 +15,8 @@ config DRM_RADEON
        select HWMON
        select BACKLIGHT_CLASS_DEVICE
        select INTERVAL_TREE
+       select I2C
+       select I2C_ALGOBIT
        # radeon depends on ACPI_VIDEO when ACPI is enabled, for select to work
        # ACPI_VIDEO's dependencies must also be selected.
        select INPUT if ACPI
index 567c71f..34e80eb 100644 (file)
@@ -32,16 +32,41 @@ struct convert_to_rgb565_result {
        const u16 expected_swab[TEST_BUF_SIZE];
 };
 
+struct convert_to_xrgb1555_result {
+       unsigned int dst_pitch;
+       const u16 expected[TEST_BUF_SIZE];
+};
+
+struct convert_to_argb1555_result {
+       unsigned int dst_pitch;
+       const u16 expected[TEST_BUF_SIZE];
+};
+
+struct convert_to_rgba5551_result {
+       unsigned int dst_pitch;
+       const u16 expected[TEST_BUF_SIZE];
+};
+
 struct convert_to_rgb888_result {
        unsigned int dst_pitch;
        const u8 expected[TEST_BUF_SIZE];
 };
 
+struct convert_to_argb8888_result {
+       unsigned int dst_pitch;
+       const u32 expected[TEST_BUF_SIZE];
+};
+
 struct convert_to_xrgb2101010_result {
        unsigned int dst_pitch;
        const u32 expected[TEST_BUF_SIZE];
 };
 
+struct convert_to_argb2101010_result {
+       unsigned int dst_pitch;
+       const u32 expected[TEST_BUF_SIZE];
+};
+
 struct convert_xrgb8888_case {
        const char *name;
        unsigned int pitch;
@@ -50,8 +75,13 @@ struct convert_xrgb8888_case {
        struct convert_to_gray8_result gray8_result;
        struct convert_to_rgb332_result rgb332_result;
        struct convert_to_rgb565_result rgb565_result;
+       struct convert_to_xrgb1555_result xrgb1555_result;
+       struct convert_to_argb1555_result argb1555_result;
+       struct convert_to_rgba5551_result rgba5551_result;
        struct convert_to_rgb888_result rgb888_result;
+       struct convert_to_argb8888_result argb8888_result;
        struct convert_to_xrgb2101010_result xrgb2101010_result;
+       struct convert_to_argb2101010_result argb2101010_result;
 };
 
 static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
@@ -73,14 +103,34 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
                        .expected = { 0xF800 },
                        .expected_swab = { 0x00F8 },
                },
+               .xrgb1555_result = {
+                       .dst_pitch = 0,
+                       .expected = { 0x7C00 },
+               },
+               .argb1555_result = {
+                       .dst_pitch = 0,
+                       .expected = { 0xFC00 },
+               },
+               .rgba5551_result = {
+                       .dst_pitch = 0,
+                       .expected = { 0xF801 },
+               },
                .rgb888_result = {
                        .dst_pitch = 0,
                        .expected = { 0x00, 0x00, 0xFF },
                },
+               .argb8888_result = {
+                       .dst_pitch = 0,
+                       .expected = { 0xFFFF0000 },
+               },
                .xrgb2101010_result = {
                        .dst_pitch = 0,
                        .expected = { 0x3FF00000 },
                },
+               .argb2101010_result = {
+                       .dst_pitch = 0,
+                       .expected = { 0xFFF00000 },
+               },
        },
        {
                .name = "single_pixel_clip_rectangle",
@@ -103,14 +153,34 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
                        .expected = { 0xF800 },
                        .expected_swab = { 0x00F8 },
                },
+               .xrgb1555_result = {
+                       .dst_pitch = 0,
+                       .expected = { 0x7C00 },
+               },
+               .argb1555_result = {
+                       .dst_pitch = 0,
+                       .expected = { 0xFC00 },
+               },
+               .rgba5551_result = {
+                       .dst_pitch = 0,
+                       .expected = { 0xF801 },
+               },
                .rgb888_result = {
                        .dst_pitch = 0,
                        .expected = { 0x00, 0x00, 0xFF },
                },
+               .argb8888_result = {
+                       .dst_pitch = 0,
+                       .expected = { 0xFFFF0000 },
+               },
                .xrgb2101010_result = {
                        .dst_pitch = 0,
                        .expected = { 0x3FF00000 },
                },
+               .argb2101010_result = {
+                       .dst_pitch = 0,
+                       .expected = { 0xFFF00000 },
+               },
        },
        {
                /* Well known colors: White, black, red, green, blue, magenta,
@@ -160,6 +230,33 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
                                0xE0FF, 0xFF07,
                        },
                },
+               .xrgb1555_result = {
+                       .dst_pitch = 0,
+                       .expected = {
+                               0x7FFF, 0x0000,
+                               0x7C00, 0x03E0,
+                               0x001F, 0x7C1F,
+                               0x7FE0, 0x03FF,
+                       },
+               },
+               .argb1555_result = {
+                       .dst_pitch = 0,
+                       .expected = {
+                               0xFFFF, 0x8000,
+                               0xFC00, 0x83E0,
+                               0x801F, 0xFC1F,
+                               0xFFE0, 0x83FF,
+                       },
+               },
+               .rgba5551_result = {
+                       .dst_pitch = 0,
+                       .expected = {
+                               0xFFFF, 0x0001,
+                               0xF801, 0x07C1,
+                               0x003F, 0xF83F,
+                               0xFFC1, 0x07FF,
+                       },
+               },
                .rgb888_result = {
                        .dst_pitch = 0,
                        .expected = {
@@ -169,6 +266,15 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
                                0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
                        },
                },
+               .argb8888_result = {
+                       .dst_pitch = 0,
+                       .expected = {
+                               0xFFFFFFFF, 0xFF000000,
+                               0xFFFF0000, 0xFF00FF00,
+                               0xFF0000FF, 0xFFFF00FF,
+                               0xFFFFFF00, 0xFF00FFFF,
+                       },
+               },
                .xrgb2101010_result = {
                        .dst_pitch = 0,
                        .expected = {
@@ -178,6 +284,15 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
                                0x3FFFFC00, 0x000FFFFF,
                        },
                },
+               .argb2101010_result = {
+                       .dst_pitch = 0,
+                       .expected = {
+                               0xFFFFFFFF, 0xC0000000,
+                               0xFFF00000, 0xC00FFC00,
+                               0xC00003FF, 0xFFF003FF,
+                               0xFFFFFC00, 0xC00FFFFF,
+                       },
+               },
        },
        {
                /* Randomly picked colors. Full buffer within the clip area. */
@@ -218,6 +333,30 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
                                0x00A8, 0x8E6B, 0x330A, 0x0000, 0x0000,
                        },
                },
+               .xrgb1555_result = {
+                       .dst_pitch = 10,
+                       .expected = {
+                               0x0513, 0x0920, 0x5400, 0x0000, 0x0000,
+                               0x35CE, 0x0513, 0x0920, 0x0000, 0x0000,
+                               0x5400, 0x35CE, 0x0513, 0x0000, 0x0000,
+                       },
+               },
+               .argb1555_result = {
+                       .dst_pitch = 10,
+                       .expected = {
+                               0x8513, 0x8920, 0xD400, 0x0000, 0x0000,
+                               0xB5CE, 0x8513, 0x8920, 0x0000, 0x0000,
+                               0xD400, 0xB5CE, 0x8513, 0x0000, 0x0000,
+                       },
+               },
+               .rgba5551_result = {
+                       .dst_pitch = 10,
+                       .expected = {
+                               0x0A27, 0x1241, 0xA801, 0x0000, 0x0000,
+                               0x6B9D, 0x0A27, 0x1241, 0x0000, 0x0000,
+                               0xA801, 0x6B9D, 0x0A27, 0x0000, 0x0000,
+                       },
+               },
                .rgb888_result = {
                        .dst_pitch = 15,
                        .expected = {
@@ -229,6 +368,14 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                        },
                },
+               .argb8888_result = {
+                       .dst_pitch = 20,
+                       .expected = {
+                               0xFF0E449C, 0xFF114D05, 0xFFA80303, 0x00000000, 0x00000000,
+                               0xFF6C7073, 0xFF0E449C, 0xFF114D05, 0x00000000, 0x00000000,
+                               0xFFA80303, 0xFF6C7073, 0xFF0E449C, 0x00000000, 0x00000000,
+                       },
+               },
                .xrgb2101010_result = {
                        .dst_pitch = 20,
                        .expected = {
@@ -237,6 +384,14 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
                                0x2A20300C, 0x1B1705CD, 0x03844672, 0x00000000, 0x00000000,
                        },
                },
+               .argb2101010_result = {
+                       .dst_pitch = 20,
+                       .expected = {
+                               0xC3844672, 0xC444D414, 0xEA20300C, 0x00000000, 0x00000000,
+                               0xDB1705CD, 0xC3844672, 0xC444D414, 0x00000000, 0x00000000,
+                               0xEA20300C, 0xDB1705CD, 0xC3844672, 0x00000000, 0x00000000,
+                       },
+               },
        },
 };
 
@@ -264,7 +419,22 @@ static size_t conversion_buf_size(u32 dst_format, unsigned int dst_pitch,
        return dst_pitch * drm_rect_height(clip);
 }
 
-static u32 *le32buf_to_cpu(struct kunit *test, const u32 *buf, size_t buf_size)
+static u16 *le16buf_to_cpu(struct kunit *test, const __le16 *buf, size_t buf_size)
+{
+       u16 *dst = NULL;
+       int n;
+
+       dst = kunit_kzalloc(test, sizeof(*dst) * buf_size, GFP_KERNEL);
+       if (!dst)
+               return NULL;
+
+       for (n = 0; n < buf_size; n++)
+               dst[n] = le16_to_cpu(buf[n]);
+
+       return dst;
+}
+
+static u32 *le32buf_to_cpu(struct kunit *test, const __le32 *buf, size_t buf_size)
 {
        u32 *dst = NULL;
        int n;
@@ -279,6 +449,21 @@ static u32 *le32buf_to_cpu(struct kunit *test, const u32 *buf, size_t buf_size)
        return dst;
 }
 
+static __le32 *cpubuf_to_le32(struct kunit *test, const u32 *buf, size_t buf_size)
+{
+       __le32 *dst = NULL;
+       int n;
+
+       dst = kunit_kzalloc(test, sizeof(*dst) * buf_size, GFP_KERNEL);
+       if (!dst)
+               return NULL;
+
+       for (n = 0; n < buf_size; n++)
+               dst[n] = cpu_to_le32(buf[n]);
+
+       return dst;
+}
+
 static void convert_xrgb8888_case_desc(struct convert_xrgb8888_case *t,
                                       char *desc)
 {
@@ -293,8 +478,8 @@ static void drm_test_fb_xrgb8888_to_gray8(struct kunit *test)
        const struct convert_xrgb8888_case *params = test->param_value;
        const struct convert_to_gray8_result *result = &params->gray8_result;
        size_t dst_size;
-       __u8 *buf = NULL;
-       __u32 *xrgb8888 = NULL;
+       u8 *buf = NULL;
+       __le32 *xrgb8888 = NULL;
        struct iosys_map dst, src;
 
        struct drm_framebuffer fb = {
@@ -310,7 +495,7 @@ static void drm_test_fb_xrgb8888_to_gray8(struct kunit *test)
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
        iosys_map_set_vaddr(&dst, buf);
 
-       xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE);
+       xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
        iosys_map_set_vaddr(&src, xrgb8888);
 
@@ -323,8 +508,8 @@ static void drm_test_fb_xrgb8888_to_rgb332(struct kunit *test)
        const struct convert_xrgb8888_case *params = test->param_value;
        const struct convert_to_rgb332_result *result = &params->rgb332_result;
        size_t dst_size;
-       __u8 *buf = NULL;
-       __u32 *xrgb8888 = NULL;
+       u8 *buf = NULL;
+       __le32 *xrgb8888 = NULL;
        struct iosys_map dst, src;
 
        struct drm_framebuffer fb = {
@@ -340,7 +525,7 @@ static void drm_test_fb_xrgb8888_to_rgb332(struct kunit *test)
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
        iosys_map_set_vaddr(&dst, buf);
 
-       xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE);
+       xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
        iosys_map_set_vaddr(&src, xrgb8888);
 
@@ -353,8 +538,8 @@ static void drm_test_fb_xrgb8888_to_rgb565(struct kunit *test)
        const struct convert_xrgb8888_case *params = test->param_value;
        const struct convert_to_rgb565_result *result = &params->rgb565_result;
        size_t dst_size;
-       __u16 *buf = NULL;
-       __u32 *xrgb8888 = NULL;
+       u16 *buf = NULL;
+       __le32 *xrgb8888 = NULL;
        struct iosys_map dst, src;
 
        struct drm_framebuffer fb = {
@@ -370,24 +555,120 @@ static void drm_test_fb_xrgb8888_to_rgb565(struct kunit *test)
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
        iosys_map_set_vaddr(&dst, buf);
 
-       xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE);
+       xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
        iosys_map_set_vaddr(&src, xrgb8888);
 
        drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, &params->clip, false);
+       buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
        KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
 
+       buf = dst.vaddr; /* restore original value of buf */
        drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, &params->clip, true);
+       buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
        KUNIT_EXPECT_MEMEQ(test, buf, result->expected_swab, dst_size);
 }
 
+static void drm_test_fb_xrgb8888_to_xrgb1555(struct kunit *test)
+{
+       const struct convert_xrgb8888_case *params = test->param_value;
+       const struct convert_to_xrgb1555_result *result = &params->xrgb1555_result;
+       size_t dst_size;
+       u16 *buf = NULL;
+       __le32 *xrgb8888 = NULL;
+       struct iosys_map dst, src;
+
+       struct drm_framebuffer fb = {
+               .format = drm_format_info(DRM_FORMAT_XRGB8888),
+               .pitches = { params->pitch, 0, 0 },
+       };
+
+       dst_size = conversion_buf_size(DRM_FORMAT_XRGB1555, result->dst_pitch,
+                                      &params->clip);
+       KUNIT_ASSERT_GT(test, dst_size, 0);
+
+       buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
+       iosys_map_set_vaddr(&dst, buf);
+
+       xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
+       iosys_map_set_vaddr(&src, xrgb8888);
+
+       drm_fb_xrgb8888_to_xrgb1555(&dst, &result->dst_pitch, &src, &fb, &params->clip);
+       buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
+       KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);
+}
+
+static void drm_test_fb_xrgb8888_to_argb1555(struct kunit *test)
+{
+       const struct convert_xrgb8888_case *params = test->param_value;
+       const struct convert_to_argb1555_result *result = &params->argb1555_result;
+       size_t dst_size;
+       u16 *buf = NULL;
+       __le32 *xrgb8888 = NULL;
+       struct iosys_map dst, src;
+
+       struct drm_framebuffer fb = {
+               .format = drm_format_info(DRM_FORMAT_XRGB8888),
+               .pitches = { params->pitch, 0, 0 },
+       };
+
+       dst_size = conversion_buf_size(DRM_FORMAT_ARGB1555, result->dst_pitch,
+                                      &params->clip);
+       KUNIT_ASSERT_GT(test, dst_size, 0);
+
+       buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
+       iosys_map_set_vaddr(&dst, buf);
+
+       xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
+       iosys_map_set_vaddr(&src, xrgb8888);
+
+       drm_fb_xrgb8888_to_argb1555(&dst, &result->dst_pitch, &src, &fb, &params->clip);
+       buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
+       KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);
+}
+
+static void drm_test_fb_xrgb8888_to_rgba5551(struct kunit *test)
+{
+       const struct convert_xrgb8888_case *params = test->param_value;
+       const struct convert_to_rgba5551_result *result = &params->rgba5551_result;
+       size_t dst_size;
+       u16 *buf = NULL;
+       __le32 *xrgb8888 = NULL;
+       struct iosys_map dst, src;
+
+       struct drm_framebuffer fb = {
+               .format = drm_format_info(DRM_FORMAT_XRGB8888),
+               .pitches = { params->pitch, 0, 0 },
+       };
+
+       dst_size = conversion_buf_size(DRM_FORMAT_RGBA5551, result->dst_pitch,
+                                      &params->clip);
+       KUNIT_ASSERT_GT(test, dst_size, 0);
+
+       buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
+       iosys_map_set_vaddr(&dst, buf);
+
+       xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
+       iosys_map_set_vaddr(&src, xrgb8888);
+
+       drm_fb_xrgb8888_to_rgba5551(&dst, &result->dst_pitch, &src, &fb, &params->clip);
+       buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
+       KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);
+}
+
 static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test)
 {
        const struct convert_xrgb8888_case *params = test->param_value;
        const struct convert_to_rgb888_result *result = &params->rgb888_result;
        size_t dst_size;
-       __u8 *buf = NULL;
-       __u32 *xrgb8888 = NULL;
+       u8 *buf = NULL;
+       __le32 *xrgb8888 = NULL;
        struct iosys_map dst, src;
 
        struct drm_framebuffer fb = {
@@ -403,21 +684,56 @@ static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test)
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
        iosys_map_set_vaddr(&dst, buf);
 
-       xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE);
+       xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
        iosys_map_set_vaddr(&src, xrgb8888);
 
+       /*
+        * RGB888 expected results are already in little-endian
+        * order, so there's no need to convert the test output.
+        */
        drm_fb_xrgb8888_to_rgb888(&dst, &result->dst_pitch, &src, &fb, &params->clip);
        KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
 }
 
+static void drm_test_fb_xrgb8888_to_argb8888(struct kunit *test)
+{
+       const struct convert_xrgb8888_case *params = test->param_value;
+       const struct convert_to_argb8888_result *result = &params->argb8888_result;
+       size_t dst_size;
+       u32 *buf = NULL;
+       __le32 *xrgb8888 = NULL;
+       struct iosys_map dst, src;
+
+       struct drm_framebuffer fb = {
+               .format = drm_format_info(DRM_FORMAT_XRGB8888),
+               .pitches = { params->pitch, 0, 0 },
+       };
+
+       dst_size = conversion_buf_size(DRM_FORMAT_ARGB8888,
+                                      result->dst_pitch, &params->clip);
+       KUNIT_ASSERT_GT(test, dst_size, 0);
+
+       buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
+       iosys_map_set_vaddr(&dst, buf);
+
+       xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
+       iosys_map_set_vaddr(&src, xrgb8888);
+
+       drm_fb_xrgb8888_to_argb8888(&dst, &result->dst_pitch, &src, &fb, &params->clip);
+       buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32));
+       KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);
+}
+
 static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test)
 {
        const struct convert_xrgb8888_case *params = test->param_value;
        const struct convert_to_xrgb2101010_result *result = &params->xrgb2101010_result;
        size_t dst_size;
-       __u32 *buf = NULL;
-       __u32 *xrgb8888 = NULL;
+       u32 *buf = NULL;
+       __le32 *xrgb8888 = NULL;
        struct iosys_map dst, src;
 
        struct drm_framebuffer fb = {
@@ -433,7 +749,7 @@ static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test)
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
        iosys_map_set_vaddr(&dst, buf);
 
-       xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE);
+       xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
        iosys_map_set_vaddr(&src, xrgb8888);
 
@@ -442,12 +758,48 @@ static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test)
        KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
 }
 
+static void drm_test_fb_xrgb8888_to_argb2101010(struct kunit *test)
+{
+       const struct convert_xrgb8888_case *params = test->param_value;
+       const struct convert_to_argb2101010_result *result = &params->argb2101010_result;
+       size_t dst_size;
+       u32 *buf = NULL;
+       __le32 *xrgb8888 = NULL;
+       struct iosys_map dst, src;
+
+       struct drm_framebuffer fb = {
+               .format = drm_format_info(DRM_FORMAT_XRGB8888),
+               .pitches = { params->pitch, 0, 0 },
+       };
+
+       dst_size = conversion_buf_size(DRM_FORMAT_ARGB2101010,
+                                      result->dst_pitch, &params->clip);
+       KUNIT_ASSERT_GT(test, dst_size, 0);
+
+       buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
+       iosys_map_set_vaddr(&dst, buf);
+
+       xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
+       iosys_map_set_vaddr(&src, xrgb8888);
+
+       drm_fb_xrgb8888_to_argb2101010(&dst, &result->dst_pitch, &src, &fb, &params->clip);
+       buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32));
+       KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);
+}
+
 static struct kunit_case drm_format_helper_test_cases[] = {
        KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_gray8, convert_xrgb8888_gen_params),
        KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb332, convert_xrgb8888_gen_params),
        KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb565, convert_xrgb8888_gen_params),
+       KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xrgb1555, convert_xrgb8888_gen_params),
+       KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb1555, convert_xrgb8888_gen_params),
+       KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgba5551, convert_xrgb8888_gen_params),
        KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb888, convert_xrgb8888_gen_params),
+       KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb8888, convert_xrgb8888_gen_params),
        KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xrgb2101010, convert_xrgb8888_gen_params),
+       KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb2101010, convert_xrgb8888_gen_params),
        {}
 };
 
index 33eefeb..6e349ca 100644 (file)
@@ -754,24 +754,6 @@ static void ofdrm_crtc_state_destroy(struct ofdrm_crtc_state *ofdrm_crtc_state)
        kfree(ofdrm_crtc_state);
 }
 
-/*
- * Support all formats of OF display and maybe more; in order
- * of preference. The display's update function will do any
- * conversion necessary.
- *
- * TODO: Add blit helpers for remaining formats and uncomment
- *       constants.
- */
-static const uint32_t ofdrm_primary_plane_formats[] = {
-       DRM_FORMAT_XRGB8888,
-       DRM_FORMAT_RGB565,
-       //DRM_FORMAT_XRGB1555,
-       //DRM_FORMAT_C8,
-       /* Big-endian formats below */
-       DRM_FORMAT_BGRX8888,
-       DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN,
-};
-
 static const uint64_t ofdrm_primary_plane_format_modifiers[] = {
        DRM_FORMAT_MOD_LINEAR,
        DRM_FORMAT_MOD_INVALID
@@ -1290,8 +1272,6 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv,
        /* Primary plane */
 
        nformats = drm_fb_build_fourcc_list(dev, &format->format, 1,
-                                           ofdrm_primary_plane_formats,
-                                           ARRAY_SIZE(ofdrm_primary_plane_formats),
                                            odev->formats, ARRAY_SIZE(odev->formats));
 
        primary_plane = &odev->primary_plane;
@@ -1372,6 +1352,7 @@ static int ofdrm_probe(struct platform_device *pdev)
 {
        struct ofdrm_device *odev;
        struct drm_device *dev;
+       unsigned int color_mode;
        int ret;
 
        odev = ofdrm_device_create(&ofdrm_driver, pdev);
@@ -1383,7 +1364,11 @@ static int ofdrm_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       drm_fbdev_generic_setup(dev, drm_format_info_bpp(odev->format, 0));
+       color_mode = drm_format_info_bpp(odev->format, 0);
+       if (color_mode == 16)
+               color_mode = odev->format->depth; // can be 15 or 16
+
+       drm_fbdev_generic_setup(dev, color_mode);
 
        return 0;
 }
index 30e928d..f658b99 100644 (file)
@@ -446,25 +446,6 @@ static int simpledrm_device_init_regulators(struct simpledrm_device *sdev)
  * Modesetting
  */
 
-/*
- * Support all formats of simplefb and maybe more; in order
- * of preference. The display's update function will do any
- * conversion necessary.
- *
- * TODO: Add blit helpers for remaining formats and uncomment
- *       constants.
- */
-static const uint32_t simpledrm_primary_plane_formats[] = {
-       DRM_FORMAT_XRGB8888,
-       DRM_FORMAT_ARGB8888,
-       DRM_FORMAT_RGB565,
-       //DRM_FORMAT_XRGB1555,
-       //DRM_FORMAT_ARGB1555,
-       DRM_FORMAT_RGB888,
-       DRM_FORMAT_XRGB2101010,
-       DRM_FORMAT_ARGB2101010,
-};
-
 static const uint64_t simpledrm_primary_plane_format_modifiers[] = {
        DRM_FORMAT_MOD_LINEAR,
        DRM_FORMAT_MOD_INVALID
@@ -745,8 +726,6 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv,
        /* Primary plane */
 
        nformats = drm_fb_build_fourcc_list(dev, &format->format, 1,
-                                           simpledrm_primary_plane_formats,
-                                           ARRAY_SIZE(simpledrm_primary_plane_formats),
                                            sdev->formats, ARRAY_SIZE(sdev->formats));
 
        primary_plane = &sdev->primary_plane;
@@ -823,6 +802,7 @@ static int simpledrm_probe(struct platform_device *pdev)
 {
        struct simpledrm_device *sdev;
        struct drm_device *dev;
+       unsigned int color_mode;
        int ret;
 
        sdev = simpledrm_device_create(&simpledrm_driver, pdev);
@@ -834,7 +814,11 @@ static int simpledrm_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       drm_fbdev_generic_setup(dev, drm_format_info_bpp(sdev->format, 0));
+       color_mode = drm_format_info_bpp(sdev->format, 0);
+       if (color_mode == 16)
+               color_mode = sdev->format->depth; // can be 15 or 16
+
+       drm_fbdev_generic_setup(dev, color_mode);
 
        return 0;
 }
index 6e152ef..5da1806 100644 (file)
@@ -861,7 +861,6 @@ v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
 
        job->args = *args;
 
-       spin_lock(&file_priv->table_lock);
        for (job->base.bo_count = 0;
             job->base.bo_count < ARRAY_SIZE(args->bo_handles);
             job->base.bo_count++) {
@@ -870,20 +869,16 @@ v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
                if (!args->bo_handles[job->base.bo_count])
                        break;
 
-               bo = idr_find(&file_priv->object_idr,
-                             args->bo_handles[job->base.bo_count]);
+               bo = drm_gem_object_lookup(file_priv, args->bo_handles[job->base.bo_count]);
                if (!bo) {
                        DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
                                  job->base.bo_count,
                                  args->bo_handles[job->base.bo_count]);
                        ret = -ENOENT;
-                       spin_unlock(&file_priv->table_lock);
                        goto fail;
                }
-               drm_gem_object_get(bo);
                job->base.bo[job->base.bo_count] = bo;
        }
-       spin_unlock(&file_priv->table_lock);
 
        ret = v3d_lock_bo_reservations(&job->base, &acquire_ctx);
        if (ret)
index 35a6b59..cdc0559 100644 (file)
@@ -335,8 +335,14 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode
        bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 ||
                       vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
        bool is_dsi1 = vc4_encoder->type == VC4_ENCODER_TYPE_DSI1;
+       bool is_vec = vc4_encoder->type == VC4_ENCODER_TYPE_VEC;
        u32 format = is_dsi1 ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
        u8 ppc = pv_data->pixels_per_clock;
+
+       u16 vert_bp = mode->crtc_vtotal - mode->crtc_vsync_end;
+       u16 vert_sync = mode->crtc_vsync_end - mode->crtc_vsync_start;
+       u16 vert_fp = mode->crtc_vsync_start - mode->crtc_vdisplay;
+
        bool debug_dump_regs = false;
        int idx;
 
@@ -364,49 +370,60 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode
                   VC4_SET_FIELD(mode->hdisplay * pixel_rep / ppc,
                                 PV_HORZB_HACTIVE));
 
-       CRTC_WRITE(PV_VERTA,
-                  VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end +
-                                interlace,
-                                PV_VERTA_VBP) |
-                  VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
-                                PV_VERTA_VSYNC));
-       CRTC_WRITE(PV_VERTB,
-                  VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
-                                PV_VERTB_VFP) |
-                  VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
-
        if (interlace) {
+               bool odd_field_first = false;
+               u32 field_delay = mode->htotal * pixel_rep / (2 * ppc);
+               u16 vert_bp_even = vert_bp;
+               u16 vert_fp_even = vert_fp;
+
+               if (is_vec) {
+                       /* VEC (composite output) */
+                       ++field_delay;
+                       if (mode->htotal == 858) {
+                               /* 525-line mode (NTSC or PAL-M) */
+                               odd_field_first = true;
+                       }
+               }
+
+               if (odd_field_first)
+                       ++vert_fp_even;
+               else
+                       ++vert_bp;
+
                CRTC_WRITE(PV_VERTA_EVEN,
-                          VC4_SET_FIELD(mode->crtc_vtotal -
-                                        mode->crtc_vsync_end,
-                                        PV_VERTA_VBP) |
-                          VC4_SET_FIELD(mode->crtc_vsync_end -
-                                        mode->crtc_vsync_start,
-                                        PV_VERTA_VSYNC));
+                          VC4_SET_FIELD(vert_bp_even, PV_VERTA_VBP) |
+                          VC4_SET_FIELD(vert_sync, PV_VERTA_VSYNC));
                CRTC_WRITE(PV_VERTB_EVEN,
-                          VC4_SET_FIELD(mode->crtc_vsync_start -
-                                        mode->crtc_vdisplay,
-                                        PV_VERTB_VFP) |
+                          VC4_SET_FIELD(vert_fp_even, PV_VERTB_VFP) |
                           VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
 
-               /* We set up first field even mode for HDMI.  VEC's
-                * NTSC mode would want first field odd instead, once
-                * we support it (to do so, set ODD_FIRST and put the
-                * delay in VSYNCD_EVEN instead).
+               /* We set up first field even mode for HDMI and VEC's PAL.
+                * For NTSC, we need first field odd.
                 */
                CRTC_WRITE(PV_V_CONTROL,
                           PV_VCONTROL_CONTINUOUS |
                           (is_dsi ? PV_VCONTROL_DSI : 0) |
                           PV_VCONTROL_INTERLACE |
-                          VC4_SET_FIELD(mode->htotal * pixel_rep / (2 * ppc),
-                                        PV_VCONTROL_ODD_DELAY));
-               CRTC_WRITE(PV_VSYNCD_EVEN, 0);
+                          (odd_field_first
+                                  ? PV_VCONTROL_ODD_FIRST
+                                  : VC4_SET_FIELD(field_delay,
+                                                  PV_VCONTROL_ODD_DELAY)));
+               CRTC_WRITE(PV_VSYNCD_EVEN,
+                          (odd_field_first ? field_delay : 0));
        } else {
                CRTC_WRITE(PV_V_CONTROL,
                           PV_VCONTROL_CONTINUOUS |
                           (is_dsi ? PV_VCONTROL_DSI : 0));
+               CRTC_WRITE(PV_VSYNCD_EVEN, 0);
        }
 
+       CRTC_WRITE(PV_VERTA,
+                  VC4_SET_FIELD(vert_bp, PV_VERTA_VBP) |
+                  VC4_SET_FIELD(vert_sync, PV_VERTA_VSYNC));
+       CRTC_WRITE(PV_VERTB,
+                  VC4_SET_FIELD(vert_fp, PV_VERTB_VFP) |
+                  VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
+
        if (is_dsi)
                CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
 
index e05be9a..2a71321 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/component.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
-#include <linux/i2c.h>
 #include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
index dfb7f41..1462886 100644 (file)
@@ -1307,11 +1307,12 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
                     VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL));
        u32 vertb = (VC4_SET_FIELD(mode->htotal >> (2 - pixel_rep),
                                   VC5_HDMI_VERTB_VSPO) |
-                    VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
+                    VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end +
+                                  interlaced,
                                   VC4_HDMI_VERTB_VBP));
        u32 vertb_even = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
                          VC4_SET_FIELD(mode->crtc_vtotal -
-                                       mode->crtc_vsync_end - interlaced,
+                                       mode->crtc_vsync_end,
                                        VC4_HDMI_VERTB_VBP));
        unsigned long flags;
        unsigned char gcp;
index 024a2cd..4da66ef 100644 (file)
@@ -370,28 +370,30 @@ static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc,
         * mode.
         */
        dispctrl = SCALER_DISPCTRLX_ENABLE;
+       dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan));
 
-       if (!vc4->is_vc5)
+       if (!vc4->is_vc5) {
                dispctrl |= VC4_SET_FIELD(mode->hdisplay,
                                          SCALER_DISPCTRLX_WIDTH) |
                            VC4_SET_FIELD(mode->vdisplay,
                                          SCALER_DISPCTRLX_HEIGHT) |
                            (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
-       else
+               dispbkgndx |= SCALER_DISPBKGND_AUTOHS;
+       } else {
                dispctrl |= VC4_SET_FIELD(mode->hdisplay,
                                          SCALER5_DISPCTRLX_WIDTH) |
                            VC4_SET_FIELD(mode->vdisplay,
                                          SCALER5_DISPCTRLX_HEIGHT) |
                            (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
+               dispbkgndx &= ~SCALER5_DISPBKGND_BCK2BCK;
+       }
 
        HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl);
 
-       dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan));
        dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
        dispbkgndx &= ~SCALER_DISPBKGND_INTERLACE;
 
        HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx |
-                 SCALER_DISPBKGND_AUTOHS |
                  ((!vc4->is_vc5) ? SCALER_DISPBKGND_GAMMA : 0) |
                  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
 
@@ -568,6 +570,8 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
        bool enable_bg_fill = false;
        u32 __iomem *dlist_start = vc4->hvs->dlist + vc4_state->mm.start;
        u32 __iomem *dlist_next = dlist_start;
+       unsigned int zpos = 0;
+       bool found = false;
        int idx;
 
        if (!drm_dev_enter(dev, &idx)) {
@@ -575,29 +579,43 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
                return;
        }
 
+       if (vc4_state->assigned_channel == VC4_HVS_CHANNEL_DISABLED)
+               return;
+
        if (debug_dump_regs) {
                DRM_INFO("CRTC %d HVS before:\n", drm_crtc_index(crtc));
                vc4_hvs_dump_state(hvs);
        }
 
        /* Copy all the active planes' dlist contents to the hardware dlist. */
-       drm_atomic_crtc_for_each_plane(plane, crtc) {
-               /* Is this the first active plane? */
-               if (dlist_next == dlist_start) {
-                       /* We need to enable background fill when a plane
-                        * could be alpha blending from the background, i.e.
-                        * where no other plane is underneath. It suffices to
-                        * consider the first active plane here since we set
-                        * needs_bg_fill such that either the first plane
-                        * already needs it or all planes on top blend from
-                        * the first or a lower plane.
-                        */
-                       vc4_plane_state = to_vc4_plane_state(plane->state);
-                       enable_bg_fill = vc4_plane_state->needs_bg_fill;
+       do {
+               found = false;
+
+               drm_atomic_crtc_for_each_plane(plane, crtc) {
+                       if (plane->state->normalized_zpos != zpos)
+                               continue;
+
+                       /* Is this the first active plane? */
+                       if (dlist_next == dlist_start) {
+                               /* We need to enable background fill when a plane
+                                * could be alpha blending from the background, i.e.
+                                * where no other plane is underneath. It suffices to
+                                * consider the first active plane here since we set
+                                * needs_bg_fill such that either the first plane
+                                * already needs it or all planes on top blend from
+                                * the first or a lower plane.
+                                */
+                               vc4_plane_state = to_vc4_plane_state(plane->state);
+                               enable_bg_fill = vc4_plane_state->needs_bg_fill;
+                       }
+
+                       dlist_next += vc4_plane_write_dlist(plane, dlist_next);
+
+                       found = true;
                }
 
-               dlist_next += vc4_plane_write_dlist(plane, dlist_next);
-       }
+               zpos++;
+       } while (found);
 
        writel(SCALER_CTL0_END, dlist_next);
        dlist_next++;
@@ -658,7 +676,8 @@ void vc4_hvs_mask_underrun(struct vc4_hvs *hvs, int channel)
                return;
 
        dispctrl = HVS_READ(SCALER_DISPCTRL);
-       dispctrl &= ~SCALER_DISPCTRL_DSPEISLUR(channel);
+       dispctrl &= ~(hvs->vc4->is_vc5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) :
+                                        SCALER_DISPCTRL_DSPEISLUR(channel));
 
        HVS_WRITE(SCALER_DISPCTRL, dispctrl);
 
@@ -675,7 +694,8 @@ void vc4_hvs_unmask_underrun(struct vc4_hvs *hvs, int channel)
                return;
 
        dispctrl = HVS_READ(SCALER_DISPCTRL);
-       dispctrl |= SCALER_DISPCTRL_DSPEISLUR(channel);
+       dispctrl |= (hvs->vc4->is_vc5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) :
+                                       SCALER_DISPCTRL_DSPEISLUR(channel));
 
        HVS_WRITE(SCALER_DISPSTAT,
                  SCALER_DISPSTAT_EUFLOW(channel));
@@ -701,6 +721,7 @@ static irqreturn_t vc4_hvs_irq_handler(int irq, void *data)
        int channel;
        u32 control;
        u32 status;
+       u32 dspeislur;
 
        /*
         * NOTE: We don't need to protect the register access using
@@ -717,9 +738,11 @@ static irqreturn_t vc4_hvs_irq_handler(int irq, void *data)
        control = HVS_READ(SCALER_DISPCTRL);
 
        for (channel = 0; channel < SCALER_CHANNELS_COUNT; channel++) {
+               dspeislur = vc4->is_vc5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) :
+                                         SCALER_DISPCTRL_DSPEISLUR(channel);
                /* Interrupt masking is not always honored, so check it here. */
                if (status & SCALER_DISPSTAT_EUFLOW(channel) &&
-                   control & SCALER_DISPCTRL_DSPEISLUR(channel)) {
+                   control & dspeislur) {
                        vc4_hvs_mask_underrun(hvs, channel);
                        vc4_hvs_report_underrun(dev);
 
@@ -806,7 +829,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
        struct vc4_hvs *hvs = NULL;
        int ret;
        u32 dispctrl;
-       u32 reg;
+       u32 reg, top;
 
        hvs = __vc4_hvs_alloc(vc4, NULL);
        if (IS_ERR(hvs))
@@ -899,22 +922,102 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
                    SCALER_DISPCTRL_DISPEIRQ(1) |
                    SCALER_DISPCTRL_DISPEIRQ(2);
 
-       dispctrl &= ~(SCALER_DISPCTRL_DMAEIRQ |
-                     SCALER_DISPCTRL_SLVWREIRQ |
-                     SCALER_DISPCTRL_SLVRDEIRQ |
-                     SCALER_DISPCTRL_DSPEIEOF(0) |
-                     SCALER_DISPCTRL_DSPEIEOF(1) |
-                     SCALER_DISPCTRL_DSPEIEOF(2) |
-                     SCALER_DISPCTRL_DSPEIEOLN(0) |
-                     SCALER_DISPCTRL_DSPEIEOLN(1) |
-                     SCALER_DISPCTRL_DSPEIEOLN(2) |
-                     SCALER_DISPCTRL_DSPEISLUR(0) |
-                     SCALER_DISPCTRL_DSPEISLUR(1) |
-                     SCALER_DISPCTRL_DSPEISLUR(2) |
-                     SCALER_DISPCTRL_SCLEIRQ);
+       if (!vc4->is_vc5)
+               dispctrl &= ~(SCALER_DISPCTRL_DMAEIRQ |
+                             SCALER_DISPCTRL_SLVWREIRQ |
+                             SCALER_DISPCTRL_SLVRDEIRQ |
+                             SCALER_DISPCTRL_DSPEIEOF(0) |
+                             SCALER_DISPCTRL_DSPEIEOF(1) |
+                             SCALER_DISPCTRL_DSPEIEOF(2) |
+                             SCALER_DISPCTRL_DSPEIEOLN(0) |
+                             SCALER_DISPCTRL_DSPEIEOLN(1) |
+                             SCALER_DISPCTRL_DSPEIEOLN(2) |
+                             SCALER_DISPCTRL_DSPEISLUR(0) |
+                             SCALER_DISPCTRL_DSPEISLUR(1) |
+                             SCALER_DISPCTRL_DSPEISLUR(2) |
+                             SCALER_DISPCTRL_SCLEIRQ);
+       else
+               dispctrl &= ~(SCALER_DISPCTRL_DMAEIRQ |
+                             SCALER5_DISPCTRL_SLVEIRQ |
+                             SCALER5_DISPCTRL_DSPEIEOF(0) |
+                             SCALER5_DISPCTRL_DSPEIEOF(1) |
+                             SCALER5_DISPCTRL_DSPEIEOF(2) |
+                             SCALER5_DISPCTRL_DSPEIEOLN(0) |
+                             SCALER5_DISPCTRL_DSPEIEOLN(1) |
+                             SCALER5_DISPCTRL_DSPEIEOLN(2) |
+                             SCALER5_DISPCTRL_DSPEISLUR(0) |
+                             SCALER5_DISPCTRL_DSPEISLUR(1) |
+                             SCALER5_DISPCTRL_DSPEISLUR(2) |
+                             SCALER_DISPCTRL_SCLEIRQ);
+
+
+       /* Set AXI panic mode.
+        * VC4 panics when < 2 lines in FIFO.
+        * VC5 panics when less than 1 line in the FIFO.
+        */
+       dispctrl &= ~(SCALER_DISPCTRL_PANIC0_MASK |
+                     SCALER_DISPCTRL_PANIC1_MASK |
+                     SCALER_DISPCTRL_PANIC2_MASK);
+       dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_PANIC0);
+       dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_PANIC1);
+       dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_PANIC2);
 
        HVS_WRITE(SCALER_DISPCTRL, dispctrl);
 
+       /* Recompute Composite Output Buffer (COB) allocations for the displays
+        */
+       if (!vc4->is_vc5) {
+               /* The COB is 20736 pixels, or just over 10 lines at 2048 wide.
+                * The bottom 2048 pixels are full 32bpp RGBA (intended for the
+                * TXP composing RGBA to memory), whilst the remainder are only
+                * 24bpp RGB.
+                *
+                * Assign 3 lines to channels 1 & 2, and just over 4 lines to
+                * channel 0.
+                */
+               #define VC4_COB_SIZE            20736
+               #define VC4_COB_LINE_WIDTH      2048
+               #define VC4_COB_NUM_LINES       3
+               reg = 0;
+               top = VC4_COB_LINE_WIDTH * VC4_COB_NUM_LINES;
+               reg |= (top - 1) << 16;
+               HVS_WRITE(SCALER_DISPBASE2, reg);
+               reg = top;
+               top += VC4_COB_LINE_WIDTH * VC4_COB_NUM_LINES;
+               reg |= (top - 1) << 16;
+               HVS_WRITE(SCALER_DISPBASE1, reg);
+               reg = top;
+               top = VC4_COB_SIZE;
+               reg |= (top - 1) << 16;
+               HVS_WRITE(SCALER_DISPBASE0, reg);
+       } else {
+               /* The COB is 44416 pixels, or 10.8 lines at 4096 wide.
+                * The bottom 4096 pixels are full RGBA (intended for the TXP
+                * composing RGBA to memory), whilst the remainder are only
+                * RGB. Addressing is always pixel wide.
+                *
+                * Assign 3 lines of 4096 to channels 1 & 2, and just over 4
+                * lines. to channel 0.
+                */
+               #define VC5_COB_SIZE            44416
+               #define VC5_COB_LINE_WIDTH      4096
+               #define VC5_COB_NUM_LINES       3
+               reg = 0;
+               top = VC5_COB_LINE_WIDTH * VC5_COB_NUM_LINES;
+               reg |= top << 16;
+               HVS_WRITE(SCALER_DISPBASE2, reg);
+               top += 16;
+               reg = top;
+               top += VC5_COB_LINE_WIDTH * VC5_COB_NUM_LINES;
+               reg |= top << 16;
+               HVS_WRITE(SCALER_DISPBASE1, reg);
+               top += 16;
+               reg = top;
+               top = VC5_COB_SIZE;
+               reg |= top << 16;
+               HVS_WRITE(SCALER_DISPBASE0, reg);
+       }
+
        ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
                               vc4_hvs_irq_handler, 0, "vc4 hvs", drm);
        if (ret)
index 53d9f30..a7e3d47 100644 (file)
@@ -1074,6 +1074,7 @@ int vc4_kms_load(struct drm_device *dev)
        dev->mode_config.helper_private = &vc4_mode_config_helpers;
        dev->mode_config.preferred_depth = 24;
        dev->mode_config.async_page_flip = true;
+       dev->mode_config.normalize_zpos = true;
 
        ret = vc4_ctm_obj_init(vc4);
        if (ret)
index 8b92a45..dee525b 100644 (file)
@@ -65,78 +65,176 @@ static const struct hvs_format {
                .drm = DRM_FORMAT_RGB565,
                .hvs = HVS_PIXEL_FORMAT_RGB565,
                .pixel_order = HVS_PIXEL_ORDER_XRGB,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_XRGB,
        },
        {
                .drm = DRM_FORMAT_BGR565,
                .hvs = HVS_PIXEL_FORMAT_RGB565,
                .pixel_order = HVS_PIXEL_ORDER_XBGR,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_XBGR,
        },
        {
                .drm = DRM_FORMAT_ARGB1555,
                .hvs = HVS_PIXEL_FORMAT_RGBA5551,
                .pixel_order = HVS_PIXEL_ORDER_ABGR,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
        },
        {
                .drm = DRM_FORMAT_XRGB1555,
                .hvs = HVS_PIXEL_FORMAT_RGBA5551,
                .pixel_order = HVS_PIXEL_ORDER_ABGR,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
        },
        {
                .drm = DRM_FORMAT_RGB888,
                .hvs = HVS_PIXEL_FORMAT_RGB888,
                .pixel_order = HVS_PIXEL_ORDER_XRGB,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_XRGB,
        },
        {
                .drm = DRM_FORMAT_BGR888,
                .hvs = HVS_PIXEL_FORMAT_RGB888,
                .pixel_order = HVS_PIXEL_ORDER_XBGR,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_XBGR,
        },
        {
                .drm = DRM_FORMAT_YUV422,
                .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE,
                .pixel_order = HVS_PIXEL_ORDER_XYCBCR,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR,
        },
        {
                .drm = DRM_FORMAT_YVU422,
                .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE,
                .pixel_order = HVS_PIXEL_ORDER_XYCRCB,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB,
        },
        {
                .drm = DRM_FORMAT_YUV420,
                .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE,
                .pixel_order = HVS_PIXEL_ORDER_XYCBCR,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR,
        },
        {
                .drm = DRM_FORMAT_YVU420,
                .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE,
                .pixel_order = HVS_PIXEL_ORDER_XYCRCB,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB,
        },
        {
                .drm = DRM_FORMAT_NV12,
                .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE,
                .pixel_order = HVS_PIXEL_ORDER_XYCBCR,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR,
        },
        {
                .drm = DRM_FORMAT_NV21,
                .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE,
                .pixel_order = HVS_PIXEL_ORDER_XYCRCB,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB,
        },
        {
                .drm = DRM_FORMAT_NV16,
                .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE,
                .pixel_order = HVS_PIXEL_ORDER_XYCBCR,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR,
        },
        {
                .drm = DRM_FORMAT_NV61,
                .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE,
                .pixel_order = HVS_PIXEL_ORDER_XYCRCB,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB,
        },
        {
                .drm = DRM_FORMAT_P030,
                .hvs = HVS_PIXEL_FORMAT_YCBCR_10BIT,
-               .pixel_order = HVS_PIXEL_ORDER_XYCBCR,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCBCR,
+               .hvs5_only = true,
+       },
+       {
+               .drm = DRM_FORMAT_XRGB2101010,
+               .hvs = HVS_PIXEL_FORMAT_RGBA1010102,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
+               .hvs5_only = true,
+       },
+       {
+               .drm = DRM_FORMAT_ARGB2101010,
+               .hvs = HVS_PIXEL_FORMAT_RGBA1010102,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
+               .hvs5_only = true,
+       },
+       {
+               .drm = DRM_FORMAT_ABGR2101010,
+               .hvs = HVS_PIXEL_FORMAT_RGBA1010102,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
                .hvs5_only = true,
        },
+       {
+               .drm = DRM_FORMAT_XBGR2101010,
+               .hvs = HVS_PIXEL_FORMAT_RGBA1010102,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
+               .hvs5_only = true,
+       },
+       {
+               .drm = DRM_FORMAT_RGB332,
+               .hvs = HVS_PIXEL_FORMAT_RGB332,
+               .pixel_order = HVS_PIXEL_ORDER_ARGB,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
+       },
+       {
+               .drm = DRM_FORMAT_BGR233,
+               .hvs = HVS_PIXEL_FORMAT_RGB332,
+               .pixel_order = HVS_PIXEL_ORDER_ABGR,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
+       },
+       {
+               .drm = DRM_FORMAT_XRGB4444,
+               .hvs = HVS_PIXEL_FORMAT_RGBA4444,
+               .pixel_order = HVS_PIXEL_ORDER_ABGR,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
+       },
+       {
+               .drm = DRM_FORMAT_ARGB4444,
+               .hvs = HVS_PIXEL_FORMAT_RGBA4444,
+               .pixel_order = HVS_PIXEL_ORDER_ABGR,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
+       },
+       {
+               .drm = DRM_FORMAT_XBGR4444,
+               .hvs = HVS_PIXEL_FORMAT_RGBA4444,
+               .pixel_order = HVS_PIXEL_ORDER_ARGB,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
+       },
+       {
+               .drm = DRM_FORMAT_ABGR4444,
+               .hvs = HVS_PIXEL_FORMAT_RGBA4444,
+               .pixel_order = HVS_PIXEL_ORDER_ARGB,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
+       },
+       {
+               .drm = DRM_FORMAT_BGRX4444,
+               .hvs = HVS_PIXEL_FORMAT_RGBA4444,
+               .pixel_order = HVS_PIXEL_ORDER_RGBA,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_BGRA,
+       },
+       {
+               .drm = DRM_FORMAT_BGRA4444,
+               .hvs = HVS_PIXEL_FORMAT_RGBA4444,
+               .pixel_order = HVS_PIXEL_ORDER_RGBA,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_BGRA,
+       },
+       {
+               .drm = DRM_FORMAT_RGBX4444,
+               .hvs = HVS_PIXEL_FORMAT_RGBA4444,
+               .pixel_order = HVS_PIXEL_ORDER_BGRA,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_RGBA,
+       },
+       {
+               .drm = DRM_FORMAT_RGBA4444,
+               .hvs = HVS_PIXEL_FORMAT_RGBA4444,
+               .pixel_order = HVS_PIXEL_ORDER_BGRA,
+               .pixel_order_hvs5 = HVS_PIXEL_ORDER_RGBA,
+       },
 };
 
 static const struct hvs_format *vc4_get_hvs_format(u32 drm_format)
@@ -1001,15 +1099,10 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
                vc4_dlist_write(vc4_state, 0xc0c0c0c0);
 
        } else {
-               u32 hvs_pixel_order = format->pixel_order;
-
-               if (format->pixel_order_hvs5)
-                       hvs_pixel_order = format->pixel_order_hvs5;
-
                /* Control word */
                vc4_dlist_write(vc4_state,
                                SCALER_CTL0_VALID |
-                               (hvs_pixel_order << SCALER_CTL0_ORDER_SHIFT) |
+                               (format->pixel_order_hvs5 << SCALER_CTL0_ORDER_SHIFT) |
                                (hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
                                VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) |
                                (vc4_state->is_unity ?
@@ -1488,6 +1581,16 @@ static bool vc4_format_mod_supported(struct drm_plane *plane,
        case DRM_FORMAT_BGRX1010102:
        case DRM_FORMAT_RGBA1010102:
        case DRM_FORMAT_BGRA1010102:
+       case DRM_FORMAT_XRGB4444:
+       case DRM_FORMAT_ARGB4444:
+       case DRM_FORMAT_XBGR4444:
+       case DRM_FORMAT_ABGR4444:
+       case DRM_FORMAT_RGBX4444:
+       case DRM_FORMAT_RGBA4444:
+       case DRM_FORMAT_BGRX4444:
+       case DRM_FORMAT_BGRA4444:
+       case DRM_FORMAT_RGB332:
+       case DRM_FORMAT_BGR233:
        case DRM_FORMAT_YUV422:
        case DRM_FORMAT_YVU422:
        case DRM_FORMAT_YUV420:
@@ -1568,9 +1671,14 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
                                          DRM_COLOR_YCBCR_BT709,
                                          DRM_COLOR_YCBCR_LIMITED_RANGE);
 
+       if (type == DRM_PLANE_TYPE_PRIMARY)
+               drm_plane_create_zpos_immutable_property(plane, 0);
+
        return plane;
 }
 
+#define VC4_NUM_OVERLAY_PLANES 16
+
 int vc4_plane_create_additional_planes(struct drm_device *drm)
 {
        struct drm_plane *cursor_plane;
@@ -1586,24 +1694,35 @@ int vc4_plane_create_additional_planes(struct drm_device *drm)
         * modest number of planes to expose, that should hopefully
         * still cover any sane usecase.
         */
-       for (i = 0; i < 16; i++) {
+       for (i = 0; i < VC4_NUM_OVERLAY_PLANES; i++) {
                struct drm_plane *plane =
                        vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY,
                                       GENMASK(drm->mode_config.num_crtc - 1, 0));
 
                if (IS_ERR(plane))
                        continue;
+
+               /* Create zpos property. Max of all the overlays + 1 primary +
+                * 1 cursor plane on a crtc.
+                */
+               drm_plane_create_zpos_property(plane, i + 1, 1,
+                                              VC4_NUM_OVERLAY_PLANES + 1);
        }
 
        drm_for_each_crtc(crtc, drm) {
                /* Set up the legacy cursor after overlay initialization,
-                * since we overlay planes on the CRTC in the order they were
-                * initialized.
+                * since the zpos fallback is that planes are rendered by plane
+                * ID order, and that then puts the cursor on top.
                 */
                cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR,
                                              drm_crtc_mask(crtc));
                if (!IS_ERR(cursor_plane)) {
                        crtc->cursor = cursor_plane;
+
+                       drm_plane_create_zpos_property(cursor_plane,
+                                                      VC4_NUM_OVERLAY_PLANES + 1,
+                                                      1,
+                                                      VC4_NUM_OVERLAY_PLANES + 1);
                }
        }
 
index f0290fa..f3763bd 100644 (file)
 #define SCALER_DISPCTRL                         0x00000000
 /* Global register for clock gating the HVS */
 # define SCALER_DISPCTRL_ENABLE                        BIT(31)
+# define SCALER_DISPCTRL_PANIC0_MASK           VC4_MASK(25, 24)
+# define SCALER_DISPCTRL_PANIC0_SHIFT          24
+# define SCALER_DISPCTRL_PANIC1_MASK           VC4_MASK(27, 26)
+# define SCALER_DISPCTRL_PANIC1_SHIFT          26
+# define SCALER_DISPCTRL_PANIC2_MASK           VC4_MASK(29, 28)
+# define SCALER_DISPCTRL_PANIC2_SHIFT          28
 # define SCALER_DISPCTRL_DSP3_MUX_MASK         VC4_MASK(19, 18)
 # define SCALER_DISPCTRL_DSP3_MUX_SHIFT                18
 
  * always enabled.
  */
 # define SCALER_DISPCTRL_DSPEISLUR(x)          BIT(13 + (x))
+# define SCALER5_DISPCTRL_DSPEISLUR(x)         BIT(9 + ((x) * 4))
 /* Enables Display 0 end-of-line-N contribution to
  * SCALER_DISPSTAT_IRQDISP0
  */
 # define SCALER_DISPCTRL_DSPEIEOLN(x)          BIT(8 + ((x) * 2))
+# define SCALER5_DISPCTRL_DSPEIEOLN(x)         BIT(8 + ((x) * 4))
 /* Enables Display 0 EOF contribution to SCALER_DISPSTAT_IRQDISP0 */
 # define SCALER_DISPCTRL_DSPEIEOF(x)           BIT(7 + ((x) * 2))
+# define SCALER5_DISPCTRL_DSPEIEOF(x)          BIT(7 + ((x) * 4))
 
-# define SCALER_DISPCTRL_SLVRDEIRQ             BIT(6)
-# define SCALER_DISPCTRL_SLVWREIRQ             BIT(5)
+# define SCALER5_DISPCTRL_DSPEIVST(x)          BIT(6 + ((x) * 4))
+
+# define SCALER_DISPCTRL_SLVRDEIRQ             BIT(6)  /* HVS4 only */
+# define SCALER_DISPCTRL_SLVWREIRQ             BIT(5)  /* HVS4 only */
+# define SCALER5_DISPCTRL_SLVEIRQ              BIT(5)
 # define SCALER_DISPCTRL_DMAEIRQ               BIT(4)
 /* Enables interrupt generation on the enabled EOF/EOLN/EISLUR
  * bits and short frames..
 
 #define SCALER_DISPBKGND0                       0x00000044
 # define SCALER_DISPBKGND_AUTOHS               BIT(31)
+# define SCALER5_DISPBKGND_BCK2BCK             BIT(31)
 # define SCALER_DISPBKGND_INTERLACE            BIT(30)
 # define SCALER_DISPBKGND_GAMMA                        BIT(29)
 # define SCALER_DISPBKGND_TESTMODE_MASK                VC4_MASK(28, 25)
@@ -835,16 +848,19 @@ enum hvs_pixel_format {
 /* Note: the LSB is the rightmost character shown.  Only valid for
  * HVS_PIXEL_FORMAT_RGB8888, not RGB888.
  */
+/* For modes 332, 4444, 555, 5551, 6666, 8888, 10:10:10:2 */
 #define HVS_PIXEL_ORDER_RGBA                   0
 #define HVS_PIXEL_ORDER_BGRA                   1
 #define HVS_PIXEL_ORDER_ARGB                   2
 #define HVS_PIXEL_ORDER_ABGR                   3
 
+/* For modes 666 and 888 (4 & 5) */
 #define HVS_PIXEL_ORDER_XBRG                   0
 #define HVS_PIXEL_ORDER_XRBG                   1
 #define HVS_PIXEL_ORDER_XRGB                   2
 #define HVS_PIXEL_ORDER_XBGR                   3
 
+/* For YCbCr modes (8-12, and 17) */
 #define HVS_PIXEL_ORDER_XYCBCR                 0
 #define HVS_PIXEL_ORDER_XYCRCB                 1
 #define HVS_PIXEL_ORDER_YXCBCR                 2
index d8bf00b..a3782d0 100644 (file)
@@ -613,7 +613,9 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder,
        VEC_WRITE(VEC_CLMP0_START, 0xac);
        VEC_WRITE(VEC_CLMP0_END, 0xec);
        VEC_WRITE(VEC_CONFIG2,
-                 VEC_CONFIG2_UV_DIG_DIS | VEC_CONFIG2_RGB_DIG_DIS);
+                 VEC_CONFIG2_UV_DIG_DIS |
+                 VEC_CONFIG2_RGB_DIG_DIS |
+                 ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ? 0 : VEC_CONFIG2_PROG_SCAN));
        VEC_WRITE(VEC_CONFIG3, VEC_CONFIG3_HORIZ_LEN_STD);
        VEC_WRITE(VEC_DAC_CONFIG, vec->variant->dac_config);
 
index c3a8452..b3f8a11 100644 (file)
@@ -160,10 +160,44 @@ static int vkms_plane_atomic_check(struct drm_plane *plane,
        return 0;
 }
 
+static int vkms_prepare_fb(struct drm_plane *plane,
+                          struct drm_plane_state *state)
+{
+       struct drm_shadow_plane_state *shadow_plane_state;
+       struct drm_framebuffer *fb = state->fb;
+       int ret;
+
+       if (!fb)
+               return 0;
+
+       shadow_plane_state = to_drm_shadow_plane_state(state);
+
+       ret = drm_gem_plane_helper_prepare_fb(plane, state);
+       if (ret)
+               return ret;
+
+       return drm_gem_fb_vmap(fb, shadow_plane_state->map, shadow_plane_state->data);
+}
+
+static void vkms_cleanup_fb(struct drm_plane *plane,
+                           struct drm_plane_state *state)
+{
+       struct drm_shadow_plane_state *shadow_plane_state;
+       struct drm_framebuffer *fb = state->fb;
+
+       if (!fb)
+               return;
+
+       shadow_plane_state = to_drm_shadow_plane_state(state);
+
+       drm_gem_fb_vunmap(fb, shadow_plane_state->map);
+}
+
 static const struct drm_plane_helper_funcs vkms_primary_helper_funcs = {
        .atomic_update          = vkms_plane_atomic_update,
        .atomic_check           = vkms_plane_atomic_check,
-       DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
+       .prepare_fb             = vkms_prepare_fb,
+       .cleanup_fb             = vkms_cleanup_fb,
 };
 
 struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
index 33f6c3b..6963081 100644 (file)
@@ -10,8 +10,6 @@ struct drm_connector;
 struct drm_device;
 struct drm_encoder;
 
-void drm_bridge_connector_enable_hpd(struct drm_connector *connector);
-void drm_bridge_connector_disable_hpd(struct drm_connector *connector);
 struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
                                                struct drm_encoder *encoder);
 
index 53b7297..7616f45 100644 (file)
@@ -86,9 +86,22 @@ struct drm_info_node {
  * core.
  */
 struct drm_debugfs_info {
+       /** @name: File name */
        const char *name;
+
+       /**
+        * @show:
+        *
+        * Show callback. &seq_file->private will be set to the &struct
+        * drm_debugfs_entry corresponding to the instance of this info
+        * on a given &struct drm_device.
+        */
        int (*show)(struct seq_file*, void*);
+
+       /** @driver_features: Required driver features for this entry. */
        u32 driver_features;
+
+       /** @data: Driver-private data, should not be device-specific. */
        void *data;
 };
 
@@ -99,8 +112,13 @@ struct drm_debugfs_info {
  * drm_debugfs_info on a &struct drm_device.
  */
 struct drm_debugfs_entry {
+       /** @dev: &struct drm_device for this node. */
        struct drm_device *dev;
+
+       /** @file: Template for this node. */
        struct drm_debugfs_info file;
+
+       /** @list: Linked list of all device nodes. */
        struct list_head list;
 };
 
index a68c6a3..7cf4afa 100644 (file)
@@ -87,10 +87,23 @@ struct drm_device {
         */
        void *dev_private;
 
-       /** @primary: Primary node */
+       /**
+        * @primary:
+        *
+        * Primary node. Drivers should not interact with this
+        * directly. debugfs interfaces can be registered with
+        * drm_debugfs_add_file(), and sysfs should be directly added on the
+        * hardware (and not character device node) struct device @dev.
+        */
        struct drm_minor *primary;
 
-       /** @render: Render node */
+       /**
+        * @render:
+        *
+        * Render node. Drivers should not interact with this directly ever.
+        * Drivers should not expose any additional interfaces in debugfs or
+        * sysfs on this node.
+        */
        struct drm_minor *render;
 
        /** @accel: Compute Acceleration node */
index eb5c98c..291deb0 100644 (file)
@@ -30,12 +30,27 @@ void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pi
 void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch,
                               const struct iosys_map *src, const struct drm_framebuffer *fb,
                               const struct drm_rect *clip, bool swab);
+void drm_fb_xrgb8888_to_xrgb1555(struct iosys_map *dst, const unsigned int *dst_pitch,
+                                const struct iosys_map *src, const struct drm_framebuffer *fb,
+                                const struct drm_rect *clip);
+void drm_fb_xrgb8888_to_argb1555(struct iosys_map *dst, const unsigned int *dst_pitch,
+                                const struct iosys_map *src, const struct drm_framebuffer *fb,
+                                const struct drm_rect *clip);
+void drm_fb_xrgb8888_to_rgba5551(struct iosys_map *dst, const unsigned int *dst_pitch,
+                                const struct iosys_map *src, const struct drm_framebuffer *fb,
+                                const struct drm_rect *clip);
 void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch,
                               const struct iosys_map *src, const struct drm_framebuffer *fb,
                               const struct drm_rect *clip);
+void drm_fb_xrgb8888_to_argb8888(struct iosys_map *dst, const unsigned int *dst_pitch,
+                                const struct iosys_map *src, const struct drm_framebuffer *fb,
+                                const struct drm_rect *clip);
 void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch,
                                    const struct iosys_map *src, const struct drm_framebuffer *fb,
                                    const struct drm_rect *clip);
+void drm_fb_xrgb8888_to_argb2101010(struct iosys_map *dst, const unsigned int *dst_pitch,
+                                   const struct iosys_map *src, const struct drm_framebuffer *fb,
+                                   const struct drm_rect *clip);
 void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch,
                              const struct iosys_map *src, const struct drm_framebuffer *fb,
                              const struct drm_rect *clip);
@@ -50,7 +65,6 @@ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitc
 
 size_t drm_fb_build_fourcc_list(struct drm_device *dev,
                                const u32 *native_fourccs, size_t native_nfourccs,
-                               const u32 *extra_fourccs, size_t extra_nfourccs,
                                u32 *fourccs_out, size_t nfourccs_out);
 
 #endif /* __LINUX_DRM_FORMAT_HELPER_H */
index 20b21b5..4f503d9 100644 (file)
@@ -297,21 +297,42 @@ int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi,
 int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi,
                                        u16 *brightness);
 
+/**
+ * mipi_dsi_generic_write_seq - transmit data using a generic write packet
+ * @dsi: DSI peripheral device
+ * @seq: buffer containing the payload
+ */
+#define mipi_dsi_generic_write_seq(dsi, seq...)                                \
+       do {                                                                   \
+               static const u8 d[] = { seq };                                 \
+               struct device *dev = &dsi->dev;                                \
+               int ret;                                                       \
+               ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));           \
+               if (ret < 0) {                                                 \
+                       dev_err_ratelimited(dev, "transmit data failed: %d\n", \
+                                           ret);                              \
+                       return ret;                                            \
+               }                                                              \
+       } while (0)
+
 /**
  * mipi_dsi_dcs_write_seq - transmit a DCS command with payload
  * @dsi: DSI peripheral device
  * @cmd: Command
  * @seq: buffer containing data to be transmitted
  */
-#define mipi_dsi_dcs_write_seq(dsi, cmd, seq...) do {                          \
-               static const u8 d[] = { cmd, seq };                             \
-               struct device *dev = &dsi->dev; \
-               int ret;                                                \
-               ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
-               if (ret < 0) {                                          \
-                       dev_err_ratelimited(dev, "sending command %#02x failed: %d\n", cmd, ret); \
-                       return ret;                                             \
-               }                                               \
+#define mipi_dsi_dcs_write_seq(dsi, cmd, seq...)                           \
+       do {                                                               \
+               static const u8 d[] = { cmd, seq };                        \
+               struct device *dev = &dsi->dev;                            \
+               int ret;                                                   \
+               ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));    \
+               if (ret < 0) {                                             \
+                       dev_err_ratelimited(                               \
+                               dev, "sending command %#02x failed: %d\n", \
+                               cmd, ret);                                 \
+                       return ret;                                        \
+               }                                                          \
        } while (0)
 
 /**
index d9f2254..77a540a 100644 (file)
@@ -1143,6 +1143,28 @@ struct drm_connector_helper_funcs {
         */
        void (*cleanup_writeback_job)(struct drm_writeback_connector *connector,
                                      struct drm_writeback_job *job);
+
+       /**
+        * @enable_hpd:
+        *
+        * Enable hot-plug detection for the connector.
+        *
+        * This operation is optional.
+        *
+        * This callback is used by the drm_kms_helper_poll_enable() helpers.
+        */
+       void (*enable_hpd)(struct drm_connector *connector);
+
+       /**
+        * @disable_hpd:
+        *
+        * Disable hot-plug detection for the connector.
+        *
+        * This operation is optional.
+        *
+        * This callback is used by the drm_kms_helper_poll_disable() helpers.
+        */
+       void (*disable_hpd)(struct drm_connector *connector);
 };
 
 /**
index bc056f2..de703c6 100644 (file)
@@ -88,6 +88,18 @@ extern "C" {
  *
  * The authoritative list of format modifier codes is found in
  * `include/uapi/drm/drm_fourcc.h`
+ *
+ * Open Source User Waiver
+ * -----------------------
+ *
+ * Because this is the authoritative source for pixel formats and modifiers
+ * referenced by GL, Vulkan extensions and other standards and hence used both
+ * by open source and closed source driver stacks, the usual requirement for an
+ * upstream in-kernel or open source userspace user does not apply.
+ *
+ * To ensure, as much as feasible, compatibility across stacks and avoid
+ * confusion with incompatible enumerations stakeholders for all relevant driver
+ * stacks should approve additions.
  */
 
 #define fourcc_code(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \