URI:
       tAdd and rebase sre's droid4 patches for linux 4.16-rc1. - arm-sdk - os build toolkit for various embedded devices
  HTML git clone https://git.parazyd.org/arm-sdk
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
   DIR commit 3f9238ed77bf41b1bbdde75b9d16fdd670b79c8c
   DIR parent 5771ad298c4c4432eff5a5a258183c2e03c2c15c
  HTML Author: parazyd <parazyd@dyne.org>
       Date:   Wed, 14 Feb 2018 15:13:25 +0100
       
       Add and rebase sre's droid4 patches for linux 4.16-rc1.
       
       Diffstat:
         D extra/patches/linux-droid4-patches… |      31 -------------------------------
         A extra/patches/linux-droid4-patches… |     158 +++++++++++++++++++++++++++++++
         D extra/patches/linux-droid4-patches… |      33 -------------------------------
         A extra/patches/linux-droid4-patches… |      42 +++++++++++++++++++++++++++++++
         D extra/patches/linux-droid4-patches… |      52 -------------------------------
         A extra/patches/linux-droid4-patches… |     256 +++++++++++++++++++++++++++++++
         D extra/patches/linux-droid4-patches… |     160 -------------------------------
         A extra/patches/linux-droid4-patches… |      57 +++++++++++++++++++++++++++++++
         D extra/patches/linux-droid4-patches… |      49 -------------------------------
         A extra/patches/linux-droid4-patches… |      59 +++++++++++++++++++++++++++++++
         D extra/patches/linux-droid4-patches… |     263 -------------------------------
         A extra/patches/linux-droid4-patches… |      55 +++++++++++++++++++++++++++++++
         D extra/patches/linux-droid4-patches… |      50 -------------------------------
         A extra/patches/linux-droid4-patches… |      31 +++++++++++++++++++++++++++++++
         D extra/patches/linux-droid4-patches… |     124 -------------------------------
         A extra/patches/linux-droid4-patches… |     125 +++++++++++++++++++++++++++++++
         D extra/patches/linux-droid4-patches… |     135 -------------------------------
         A extra/patches/linux-droid4-patches… |      67 +++++++++++++++++++++++++++++++
         D extra/patches/linux-droid4-patches… |      67 -------------------------------
         D extra/patches/linux-droid4-patches… |     247 -------------------------------
         D extra/patches/linux-droid4-patches… |     172 ------------------------------
         D extra/patches/linux-droid4-patches… |      39 -------------------------------
         D extra/patches/linux-droid4-patches… |     122 -------------------------------
         D extra/patches/linux-droid4-patches… |      89 -------------------------------
         D extra/patches/linux-droid4-patches… |    1222 -------------------------------
         D extra/patches/linux-droid4-patches… |     102 -------------------------------
         A extra/patches/linux-droid4-patches… |      61 +++++++++++++++++++++++++++++++
       
       27 files changed, 911 insertions(+), 2957 deletions(-)
       ---
   DIR diff --git a/extra/patches/linux-droid4-patches/0001-drm-omap-remove-unused-function-defines.patch b/extra/patches/linux-droid4-patches/0001-drm-omap-remove-unused-function-defines.patch
       t@@ -1,31 +0,0 @@
       -From a7129365bbffa136d3987e9ae8480337882f753a Mon Sep 17 00:00:00 2001
       -From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       -Date: Mon, 24 Jul 2017 19:32:58 +0200
       -Subject: [PATCH 01/17] drm/omap: remove unused function defines
       -
       -Remove driver (un)register API defines. They do not even exist
       -anymore.
       -
       -Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       -Acked-by: Pavel Machek <pavel@ucw.cz>
       ----
       - drivers/gpu/drm/omapdrm/dss/omapdss.h | 3 ---
       - 1 file changed, 3 deletions(-)
       -
       -diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
       -index 47a3316..3d25359 100644
       ---- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
       -+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
       -@@ -584,9 +584,6 @@ struct omap_dss_driver {
       - 
       - bool omapdss_is_initialized(void);
       - 
       --int omap_dss_register_driver(struct omap_dss_driver *);
       --void omap_dss_unregister_driver(struct omap_dss_driver *);
       --
       - int omapdss_register_display(struct omap_dss_device *dssdev);
       - void omapdss_unregister_display(struct omap_dss_device *dssdev);
       - 
       --- 
       -2.1.4
       -
   DIR diff --git a/extra/patches/linux-droid4-patches/0001_drm-omap-add-framedone-interrupt-support.patch b/extra/patches/linux-droid4-patches/0001_drm-omap-add-framedone-interrupt-support.patch
       t@@ -0,0 +1,158 @@
       +This prepares framedone interrupt handling for
       +manual display update support.
       +
       +Signed-off-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxxxx>
       +---
       + drivers/gpu/drm/omapdrm/omap_crtc.c | 48 +++++++++++++++++++++++++++++++++++++
       + drivers/gpu/drm/omapdrm/omap_crtc.h |  1 +
       + drivers/gpu/drm/omapdrm/omap_irq.c  | 24 +++++++++++++++++++
       + drivers/gpu/drm/omapdrm/omap_irq.h  |  1 +
       + 4 files changed, 74 insertions(+)
       +
       +diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
       +index 1b8154e58d18..2278e3433008 100644
       +--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
       ++++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
       +@@ -51,6 +51,9 @@ struct omap_crtc {
       +         bool pending;
       +         wait_queue_head_t pending_wait;
       +         struct drm_pending_vblank_event *event;
       ++
       ++        void (*framedone_handler)(void *);
       ++        void *framedone_handler_data;
       + };
       + 
       + /* -----------------------------------------------------------------------------
       +@@ -247,6 +250,17 @@ static int omap_crtc_dss_register_framedone(
       +                 enum omap_channel channel,
       +                 void (*handler)(void *), void *data)
       + {
       ++        struct omap_crtc *omap_crtc = omap_crtcs[channel];
       ++        struct drm_device *dev = omap_crtc->base.dev;
       ++
       ++        if (omap_crtc->framedone_handler)
       ++                return -EBUSY;
       ++
       ++        dev_dbg(dev->dev, "register framedone %s", omap_crtc->name);
       ++
       ++        omap_crtc->framedone_handler = handler;
       ++        omap_crtc->framedone_handler_data = data;
       ++
       +         return 0;
       + }
       + 
       +@@ -254,6 +268,16 @@ static void omap_crtc_dss_unregister_framedone(
       +                 enum omap_channel channel,
       +                 void (*handler)(void *), void *data)
       + {
       ++        struct omap_crtc *omap_crtc = omap_crtcs[channel];
       ++        struct drm_device *dev = omap_crtc->base.dev;
       ++
       ++        dev_dbg(dev->dev, "unregister framedone %s", omap_crtc->name);
       ++
       ++        WARN_ON(omap_crtc->framedone_handler != handler);
       ++        WARN_ON(omap_crtc->framedone_handler_data != data);
       ++
       ++        omap_crtc->framedone_handler = NULL;
       ++        omap_crtc->framedone_handler_data = NULL;
       + }
       + 
       + static const struct dss_mgr_ops mgr_ops = {
       +@@ -321,6 +345,30 @@ void omap_crtc_vblank_irq(struct drm_crtc *crtc)
       +         DBG("%s: apply done", omap_crtc->name);
       + }
       + 
       ++void omap_crtc_framedone_irq(struct drm_crtc *crtc, uint32_t irqstatus)
       ++{
       ++        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
       ++
       ++        if (!omap_crtc->framedone_handler) {
       ++                dev_warn(omap_crtc->base.dev->dev, "no framedone handler?");
       ++                return;
       ++        }
       ++
       ++        omap_crtc->framedone_handler(omap_crtc->framedone_handler_data);
       ++
       ++        spin_lock(&crtc->dev->event_lock);
       ++        /* Send the vblank event if one has been requested. */
       ++        if (omap_crtc->event) {
       ++                drm_crtc_send_vblank_event(crtc, omap_crtc->event);
       ++                omap_crtc->event = NULL;
       ++        }
       ++        omap_crtc->pending = false;
       ++        spin_unlock(&crtc->dev->event_lock);
       ++
       ++        /* Wake up omap_atomic_complete. */
       ++        wake_up(&omap_crtc->pending_wait);
       ++}
       ++
       + static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc)
       + {
       +         struct omap_drm_private *priv = crtc->dev->dev_private;
       +diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.h b/drivers/gpu/drm/omapdrm/omap_crtc.h
       +index ad7b007c6174..bd316bc0b6f4 100644
       +--- a/drivers/gpu/drm/omapdrm/omap_crtc.h
       ++++ b/drivers/gpu/drm/omapdrm/omap_crtc.h
       +@@ -39,5 +39,6 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
       + int omap_crtc_wait_pending(struct drm_crtc *crtc);
       + void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus);
       + void omap_crtc_vblank_irq(struct drm_crtc *crtc);
       ++void omap_crtc_framedone_irq(struct drm_crtc *crtc, uint32_t irqstatus);
       + 
       + #endif /* __OMAPDRM_CRTC_H__ */
       +diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
       +index 53ba424823b2..354df3583229 100644
       +--- a/drivers/gpu/drm/omapdrm/omap_irq.c
       ++++ b/drivers/gpu/drm/omapdrm/omap_irq.c
       +@@ -85,6 +85,27 @@ int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
       +         return ret == 0 ? -1 : 0;
       + }
       + 
       ++int omap_irq_enable_framedone(struct drm_crtc *crtc, bool enable)
       ++{
       ++        struct drm_device *dev = crtc->dev;
       ++        struct omap_drm_private *priv = dev->dev_private;
       ++        unsigned long flags;
       ++        enum omap_channel channel = omap_crtc_channel(crtc);
       ++        int framedone_irq = priv->dispc_ops->mgr_get_framedone_irq(channel);
       ++
       ++        DBG("dev=%p, crtc=%u, enable=%d", dev, channel, enable);
       ++
       ++        spin_lock_irqsave(&priv->wait_lock, flags);
       ++        if (enable)
       ++                priv->irq_mask |= framedone_irq;
       ++        else
       ++                priv->irq_mask &= ~framedone_irq;
       ++        omap_irq_update(dev);
       ++        spin_unlock_irqrestore(&priv->wait_lock, flags);
       ++
       ++        return 0;
       ++}
       ++
       + /**
       +  * enable_vblank - enable vblank interrupt events
       +  * @dev: DRM device
       +@@ -215,6 +236,9 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
       + 
       +                 if (irqstatus & priv->dispc_ops->mgr_get_sync_lost_irq(channel))
       +                         omap_crtc_error_irq(crtc, irqstatus);
       ++
       ++                if (irqstatus & priv->dispc_ops->mgr_get_framedone_irq(channel))
       ++                        omap_crtc_framedone_irq(crtc, irqstatus);
       +         }
       + 
       +         omap_irq_ocp_error_handler(dev, irqstatus);
       +diff --git a/drivers/gpu/drm/omapdrm/omap_irq.h b/drivers/gpu/drm/omapdrm/omap_irq.h
       +index 606c09932bc0..69f4ff80a0e4 100644
       +--- a/drivers/gpu/drm/omapdrm/omap_irq.h
       ++++ b/drivers/gpu/drm/omapdrm/omap_irq.h
       +@@ -27,6 +27,7 @@ struct drm_device;
       + struct omap_irq_wait;
       + 
       + int omap_irq_enable_vblank(struct drm_crtc *crtc);
       ++int omap_irq_enable_framedone(struct drm_crtc *crtc, bool enable);
       + void omap_irq_disable_vblank(struct drm_crtc *crtc);
       + void omap_drm_irq_uninstall(struct drm_device *dev);
       + int omap_drm_irq_install(struct drm_device *dev);
       +-- 
       +2.15.1
   DIR diff --git a/extra/patches/linux-droid4-patches/0002-drm-omap-drop-incorrect-comment.patch b/extra/patches/linux-droid4-patches/0002-drm-omap-drop-incorrect-comment.patch
       t@@ -1,33 +0,0 @@
       -From faf0e2475147bd8e755dbce7f9f1a0fb8e731e4f Mon Sep 17 00:00:00 2001
       -From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       -Date: Mon, 24 Jul 2017 19:32:59 +0200
       -Subject: [PATCH 02/17] drm/omap: drop incorrect comment
       -
       -The wrappers have been removed in commit 5a35876e2830
       -(drm: omapdrm: Remove manual update display support)
       -and will not be reintroduced, since the normal sys
       -functions properly call the dirty callback.
       -
       -Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       -Acked-by: Pavel Machek <pavel@ucw.cz>
       ----
       - drivers/gpu/drm/omapdrm/omap_fbdev.c | 3 ---
       - 1 file changed, 3 deletions(-)
       -
       -diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c
       -index 9273118..e037818 100644
       ---- a/drivers/gpu/drm/omapdrm/omap_fbdev.c
       -+++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c
       -@@ -84,9 +84,6 @@ static struct fb_ops omap_fb_ops = {
       -         .owner = THIS_MODULE,
       -         DRM_FB_HELPER_DEFAULT_OPS,
       - 
       --        /* Note: to properly handle manual update displays, we wrap the
       --         * basic fbdev ops which write to the framebuffer
       --         */
       -         .fb_read = drm_fb_helper_sys_read,
       -         .fb_write = drm_fb_helper_sys_write,
       -         .fb_fillrect = drm_fb_helper_sys_fillrect,
       --- 
       -2.1.4
       -
   DIR diff --git a/extra/patches/linux-droid4-patches/0002_drm-omap-add-manual-update-detection-helper.patch b/extra/patches/linux-droid4-patches/0002_drm-omap-add-manual-update-detection-helper.patch
       t@@ -0,0 +1,42 @@
       +In preparation for manually updated display support, such as DSI
       +command mode panels, this adds a simple helper to see if a connector
       +is manually updated.
       +
       +Signed-off-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxxxx>
       +---
       + drivers/gpu/drm/omapdrm/omap_connector.c | 8 ++++++++
       + drivers/gpu/drm/omapdrm/omap_connector.h | 1 +
       + 2 files changed, 9 insertions(+)
       +
       +diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
       +index a0d7b1d905e8..a33b51484b2d 100644
       +--- a/drivers/gpu/drm/omapdrm/omap_connector.c
       ++++ b/drivers/gpu/drm/omapdrm/omap_connector.c
       +@@ -57,6 +57,14 @@ bool omap_connector_get_hdmi_mode(struct drm_connector *connector)
       +         return omap_connector->hdmi_mode;
       + }
       + 
       ++bool omap_connector_get_manually_updated(struct drm_connector *connector)
       ++{
       ++        struct omap_connector *omap_connector = to_omap_connector(connector);
       ++
       ++        return !!(omap_connector->dssdev->caps &
       ++                  OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE);
       ++}
       ++
       + static enum drm_connector_status omap_connector_detect(
       +                 struct drm_connector *connector, bool force)
       + {
       +diff --git a/drivers/gpu/drm/omapdrm/omap_connector.h b/drivers/gpu/drm/omapdrm/omap_connector.h
       +index 98bbc779b302..652136d167f5 100644
       +--- a/drivers/gpu/drm/omapdrm/omap_connector.h
       ++++ b/drivers/gpu/drm/omapdrm/omap_connector.h
       +@@ -33,5 +33,6 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
       + struct drm_encoder *omap_connector_attached_encoder(
       +                 struct drm_connector *connector);
       + bool omap_connector_get_hdmi_mode(struct drm_connector *connector);
       ++bool omap_connector_get_manually_updated(struct drm_connector *connector);
       + 
       + #endif /* __OMAPDRM_CONNECTOR_H__ */
       +-- 
       +2.15.1
   DIR diff --git a/extra/patches/linux-droid4-patches/0003-drm-omap-plane-update-fifo-size-on-ovl-setup.patch b/extra/patches/linux-droid4-patches/0003-drm-omap-plane-update-fifo-size-on-ovl-setup.patch
       t@@ -1,52 +0,0 @@
       -From 8bb3dd3ffe60be576bd6a843ebb65979e49e3e25 Mon Sep 17 00:00:00 2001
       -From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       -Date: Mon, 24 Jul 2017 19:33:00 +0200
       -Subject: [PATCH 03/17] drm/omap: plane: update fifo size on ovl setup
       -
       -This is a workaround for a hardware bug occuring on OMAP3
       -with manually updated panels. Details about the HW bug are
       -unknown to me, but without this fix the panel refresh does
       -not work at all on Nokia N950.
       -
       -Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       ----
       - drivers/gpu/drm/omapdrm/dss/dispc.c | 16 ++++++++++++++++
       - 1 file changed, 16 insertions(+)
       -
       -diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c
       -index 0f4fdb2..d5d2d3c 100644
       ---- a/drivers/gpu/drm/omapdrm/dss/dispc.c
       -+++ b/drivers/gpu/drm/omapdrm/dss/dispc.c
       -@@ -1491,6 +1491,18 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane_id plane,
       -         }
       - }
       - 
       -+void dispc_ovl_set_manual_fifo_threshold(enum omap_plane_id plane)
       -+{
       -+        u32 fifo_low, fifo_high;
       -+        bool use_fifo_merge = false;
       -+        bool use_manual_update = true;
       -+
       -+        dispc_ovl_compute_fifo_thresholds(plane, &fifo_low, &fifo_high,
       -+                                          use_fifo_merge, use_manual_update);
       -+
       -+        dispc_ovl_set_fifo_threshold(plane, fifo_low, fifo_high);
       -+}
       -+
       - static void dispc_ovl_set_mflag(enum omap_plane_id plane, bool enable)
       - {
       -         int bit;
       -@@ -2654,6 +2666,10 @@ static int dispc_ovl_setup(enum omap_plane_id plane,
       -                 oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
       -                 oi->rotation_type, replication, vm, mem_to_mem);
       - 
       -+        /* manual mode needs other fifo thresholds */
       -+        if (mgr_fld_read(channel, DISPC_MGR_FLD_STALLMODE))
       -+                dispc_ovl_set_manual_fifo_threshold(plane);
       -+
       -         return r;
       - }
       - 
       --- 
       -2.1.4
       -
   DIR diff --git a/extra/patches/linux-droid4-patches/0003_drm-omap-add-support-for-manually-updated-displays.patch b/extra/patches/linux-droid4-patches/0003_drm-omap-add-support-for-manually-updated-displays.patch
       t@@ -0,0 +1,256 @@
       +This adds the required infrastructure for manually
       +updated displays, such as DSI command mode panels.
       +
       +While those panels often support partial updates
       +we currently always do a full refresh. Display
       +will be refreshed when something calls the dirty
       +callback, such as libdrm's drmModeDirtyFB().
       +
       +This is currently being implemented for the kernel
       +console and for Xorg. Weston currently does not
       +implement this and is known not to work on manually
       +updated displays.
       +
       +Signed-off-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxxxx>
       +---
       + drivers/gpu/drm/omapdrm/omap_crtc.c | 110 +++++++++++++++++++++++++++++++++---
       + drivers/gpu/drm/omapdrm/omap_crtc.h |   1 +
       + drivers/gpu/drm/omapdrm/omap_fb.c   |  20 +++++++
       + 3 files changed, 123 insertions(+), 8 deletions(-)
       +
       +diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
       +index 2278e3433008..c2defb514b9f 100644
       +--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
       ++++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
       +@@ -51,6 +51,7 @@ struct omap_crtc {
       +         bool pending;
       +         wait_queue_head_t pending_wait;
       +         struct drm_pending_vblank_event *event;
       ++        struct delayed_work update_work;
       + 
       +         void (*framedone_handler)(void *);
       +         void *framedone_handler_data;
       +@@ -142,6 +143,28 @@ static void omap_crtc_dss_disconnect(enum omap_channel channel,
       + 
       + static void omap_crtc_dss_start_update(enum omap_channel channel)
       + {
       ++        struct omap_crtc *omap_crtc = omap_crtcs[channel];
       ++        struct omap_drm_private *priv = omap_crtc->base.dev->dev_private;
       ++
       ++        priv->dispc_ops->mgr_enable(channel, true);
       ++}
       ++
       ++static bool omap_crtc_is_manually_updated(struct drm_crtc *crtc)
       ++{
       ++        struct drm_connector *connector;
       ++        struct drm_connector_list_iter conn_iter;
       ++        bool result = false;
       ++
       ++        drm_connector_list_iter_begin(crtc->dev, &conn_iter);
       ++        drm_for_each_connector_iter(connector, &conn_iter) {
       ++                if (connector->state->crtc != crtc)
       ++                        continue;
       ++                result = omap_connector_get_manually_updated(connector);
       ++                break;
       ++        }
       ++        drm_connector_list_iter_end(&conn_iter);
       ++
       ++        return result;
       + }
       + 
       + /* Called only from the encoder enable/disable and suspend/resume handlers. */
       +@@ -153,12 +176,17 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
       +         enum omap_channel channel = omap_crtc->channel;
       +         struct omap_irq_wait *wait;
       +         u32 framedone_irq, vsync_irq;
       ++        bool is_manual = omap_crtc_is_manually_updated(crtc);
       ++        enum omap_display_type type = omap_crtc_output[channel]->output_type;
       +         int ret;
       + 
       +         if (WARN_ON(omap_crtc->enabled == enable))
       +                 return;
       + 
       +-        if (omap_crtc_output[channel]->output_type == OMAP_DISPLAY_TYPE_HDMI) {
       ++        if (is_manual)
       ++                omap_irq_enable_framedone(crtc, enable);
       ++
       ++        if (is_manual || type == OMAP_DISPLAY_TYPE_HDMI) {
       +                 priv->dispc_ops->mgr_enable(channel, enable);
       +                 omap_crtc->enabled = enable;
       +                 return;
       +@@ -209,7 +237,6 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
       +         }
       + }
       + 
       +-
       + static int omap_crtc_dss_enable(enum omap_channel channel)
       + {
       +         struct omap_crtc *omap_crtc = omap_crtcs[channel];
       +@@ -369,6 +396,53 @@ void omap_crtc_framedone_irq(struct drm_crtc *crtc, uint32_t irqstatus)
       +         wake_up(&omap_crtc->pending_wait);
       + }
       + 
       ++void omap_crtc_flush(struct drm_crtc *crtc)
       ++{
       ++        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
       ++
       ++        if (!omap_crtc_is_manually_updated(crtc))
       ++                return;
       ++
       ++        if (!delayed_work_pending(&omap_crtc->update_work))
       ++                schedule_delayed_work(&omap_crtc->update_work, 0);
       ++}
       ++
       ++static void omap_crtc_manual_display_update(struct work_struct *data)
       ++{
       ++        struct omap_crtc *omap_crtc =
       ++                        container_of(data, struct omap_crtc, update_work.work);
       ++        struct omap_dss_device *dssdev = omap_crtc_output[omap_crtc->channel];
       ++        struct drm_device *dev = omap_crtc->base.dev;
       ++        struct omap_dss_driver *dssdrv;
       ++        int ret, width, height;
       ++
       ++        if (!dssdev || !dssdev->dst) {
       ++                dev_err_once(dev->dev, "missing dssdev!");
       ++                return;
       ++        }
       ++
       ++        dssdev = dssdev->dst;
       ++        dssdrv = dssdev->driver;
       ++
       ++        if (!dssdrv || !dssdrv->update) {
       ++                dev_err_once(dev->dev, "incorrect dssdrv!");
       ++                return;
       ++        }
       ++
       ++        if (dssdrv->sync)
       ++                dssdrv->sync(dssdev);
       ++
       ++        width = dssdev->panel.vm.hactive;
       ++        height = dssdev->panel.vm.vactive;
       ++        ret = dssdrv->update(dssdev, 0, 0, width, height);
       ++        if (ret < 0) {
       ++                spin_lock_irq(&dev->event_lock);
       ++                omap_crtc->pending = false;
       ++                spin_unlock_irq(&dev->event_lock);
       ++                wake_up(&omap_crtc->pending_wait);
       ++        }
       ++}
       ++
       + static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc)
       + {
       +         struct omap_drm_private *priv = crtc->dev->dev_private;
       +@@ -421,6 +495,10 @@ static void omap_crtc_atomic_enable(struct drm_crtc *crtc,
       + 
       +         DBG("%s", omap_crtc->name);
       + 
       ++        /* manual updated display will not trigger vsync irq */
       ++        if (omap_crtc_is_manually_updated(crtc))
       ++                return;
       ++
       +         spin_lock_irq(&crtc->dev->event_lock);
       +         drm_crtc_vblank_on(crtc);
       +         ret = drm_crtc_vblank_get(crtc);
       +@@ -434,6 +512,7 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc,
       +                                      struct drm_crtc_state *old_state)
       + {
       +         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
       ++        struct drm_device *dev = crtc->dev;
       + 
       +         DBG("%s", omap_crtc->name);
       + 
       +@@ -444,6 +523,11 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc,
       +         }
       +         spin_unlock_irq(&crtc->dev->event_lock);
       + 
       ++        cancel_delayed_work(&omap_crtc->update_work);
       ++
       ++        if (!omap_crtc_wait_pending(crtc))
       ++                dev_warn(dev->dev, "manual display update did not finish!");
       ++
       +         drm_crtc_vblank_off(crtc);
       + }
       + 
       +@@ -593,13 +677,20 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
       + 
       +         DBG("%s: GO", omap_crtc->name);
       + 
       +-        ret = drm_crtc_vblank_get(crtc);
       +-        WARN_ON(ret != 0);
       ++        if (!omap_crtc_is_manually_updated(crtc)) {
       ++                ret = drm_crtc_vblank_get(crtc);
       ++                WARN_ON(ret != 0);
       + 
       +-        spin_lock_irq(&crtc->dev->event_lock);
       +-        priv->dispc_ops->mgr_go(omap_crtc->channel);
       +-        omap_crtc_arm_event(crtc);
       +-        spin_unlock_irq(&crtc->dev->event_lock);
       ++                spin_lock_irq(&crtc->dev->event_lock);
       ++                priv->dispc_ops->mgr_go(omap_crtc->channel);
       ++                omap_crtc_arm_event(crtc);
       ++                spin_unlock_irq(&crtc->dev->event_lock);
       ++        } else {
       ++                spin_lock_irq(&crtc->dev->event_lock);
       ++                omap_crtc_flush(crtc);
       ++                omap_crtc_arm_event(crtc);
       ++                spin_unlock_irq(&crtc->dev->event_lock);
       ++        }
       + }
       + 
       + static int omap_crtc_atomic_set_property(struct drm_crtc *crtc,
       +@@ -761,6 +852,9 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
       +         omap_crtc->channel = channel;
       +         omap_crtc->name = channel_names[channel];
       + 
       ++        INIT_DELAYED_WORK(&omap_crtc->update_work,
       ++                          omap_crtc_manual_display_update);
       ++
       +         ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
       +                                         &omap_crtc_funcs, NULL);
       +         if (ret < 0) {
       +diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.h b/drivers/gpu/drm/omapdrm/omap_crtc.h
       +index bd316bc0b6f4..b61c94b34f04 100644
       +--- a/drivers/gpu/drm/omapdrm/omap_crtc.h
       ++++ b/drivers/gpu/drm/omapdrm/omap_crtc.h
       +@@ -40,5 +40,6 @@ int omap_crtc_wait_pending(struct drm_crtc *crtc);
       + void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus);
       + void omap_crtc_vblank_irq(struct drm_crtc *crtc);
       + void omap_crtc_framedone_irq(struct drm_crtc *crtc, uint32_t irqstatus);
       ++void omap_crtc_flush(struct drm_crtc *crtc);
       + 
       + #endif /* __OMAPDRM_CRTC_H__ */
       +diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
       +index b2539a90e1a4..57b1767bef09 100644
       +--- a/drivers/gpu/drm/omapdrm/omap_fb.c
       ++++ b/drivers/gpu/drm/omapdrm/omap_fb.c
       +@@ -95,8 +95,28 @@ static void omap_framebuffer_destroy(struct drm_framebuffer *fb)
       +         kfree(omap_fb);
       + }
       + 
       ++static int omap_framebuffer_dirty(struct drm_framebuffer *fb,
       ++                                  struct drm_file *file_priv,
       ++                                  unsigned flags, unsigned color,
       ++                                  struct drm_clip_rect *clips,
       ++                                  unsigned num_clips)
       ++{
       ++        struct drm_connector *connector = NULL;
       ++
       ++        drm_modeset_lock_all(fb->dev);
       ++
       ++        while ((connector = omap_framebuffer_get_next_connector(fb, connector)))
       ++                if (connector->encoder && connector->encoder->crtc)
       ++                        omap_crtc_flush(connector->encoder->crtc);
       ++
       ++        drm_modeset_unlock_all(fb->dev);
       ++
       ++        return 0;
       ++}
       ++
       + static const struct drm_framebuffer_funcs omap_framebuffer_funcs = {
       +         .create_handle = omap_framebuffer_create_handle,
       ++        .dirty = omap_framebuffer_dirty,
       +         .destroy = omap_framebuffer_destroy,
       + };
       + 
       +-- 
       +2.15.1
   DIR diff --git a/extra/patches/linux-droid4-patches/0004-drm-omap-add-framedone-interrupt-support.patch b/extra/patches/linux-droid4-patches/0004-drm-omap-add-framedone-interrupt-support.patch
       t@@ -1,160 +0,0 @@
       -From 8af6ec6efc7607cc5af52af895ac7f8e63820f80 Mon Sep 17 00:00:00 2001
       -From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       -Date: Mon, 24 Jul 2017 19:33:01 +0200
       -Subject: [PATCH 04/17] drm/omap: add framedone interrupt support
       -
       -This prepares framedone interrupt handling for
       -manual display update support.
       -
       -Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       ----
       - drivers/gpu/drm/omapdrm/omap_crtc.c | 48 +++++++++++++++++++++++++++++++++++++
       - drivers/gpu/drm/omapdrm/omap_drv.h  |  2 ++
       - drivers/gpu/drm/omapdrm/omap_irq.c  | 24 +++++++++++++++++++
       - 3 files changed, 74 insertions(+)
       -
       -diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
       -index cc85c16..dee9b6e 100644
       ---- a/drivers/gpu/drm/omapdrm/omap_crtc.c
       -+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
       -@@ -52,6 +52,9 @@ struct omap_crtc {
       -         bool pending;
       -         wait_queue_head_t pending_wait;
       -         struct drm_pending_vblank_event *event;
       -+
       -+        void (*framedone_handler)(void *);
       -+        void *framedone_handler_data;
       - };
       - 
       - /* -----------------------------------------------------------------------------
       -@@ -248,6 +251,17 @@ static int omap_crtc_dss_register_framedone(
       -                 enum omap_channel channel,
       -                 void (*handler)(void *), void *data)
       - {
       -+        struct omap_crtc *omap_crtc = omap_crtcs[channel];
       -+        struct drm_device *dev = omap_crtc->base.dev;
       -+
       -+        if (omap_crtc->framedone_handler)
       -+                return -EBUSY;
       -+
       -+        dev_dbg(dev->dev, "register framedone %s", omap_crtc->name);
       -+
       -+        omap_crtc->framedone_handler = handler;
       -+        omap_crtc->framedone_handler_data = data;
       -+
       -         return 0;
       - }
       - 
       -@@ -255,6 +269,16 @@ static void omap_crtc_dss_unregister_framedone(
       -                 enum omap_channel channel,
       -                 void (*handler)(void *), void *data)
       - {
       -+        struct omap_crtc *omap_crtc = omap_crtcs[channel];
       -+        struct drm_device *dev = omap_crtc->base.dev;
       -+
       -+        dev_dbg(dev->dev, "unregister framedone %s", omap_crtc->name);
       -+
       -+        WARN_ON(omap_crtc->framedone_handler != handler);
       -+        WARN_ON(omap_crtc->framedone_handler_data != data);
       -+
       -+        omap_crtc->framedone_handler = NULL;
       -+        omap_crtc->framedone_handler_data = NULL;
       - }
       - 
       - static const struct dss_mgr_ops mgr_ops = {
       -@@ -322,6 +346,30 @@ void omap_crtc_vblank_irq(struct drm_crtc *crtc)
       -         DBG("%s: apply done", omap_crtc->name);
       - }
       - 
       -+void omap_crtc_framedone_irq(struct drm_crtc *crtc, uint32_t irqstatus)
       -+{
       -+        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
       -+
       -+        if (!omap_crtc->framedone_handler) {
       -+                dev_warn(omap_crtc->base.dev->dev, "no framedone handler?");
       -+                return;
       -+        }
       -+
       -+        omap_crtc->framedone_handler(omap_crtc->framedone_handler_data);
       -+
       -+        spin_lock(&crtc->dev->event_lock);
       -+        /* Send the vblank event if one has been requested. */
       -+        if (omap_crtc->event) {
       -+                drm_crtc_send_vblank_event(crtc, omap_crtc->event);
       -+                omap_crtc->event = NULL;
       -+        }
       -+        omap_crtc->pending = false;
       -+        spin_unlock(&crtc->dev->event_lock);
       -+
       -+        /* Wake up omap_atomic_complete. */
       -+        wake_up(&omap_crtc->pending_wait);
       -+}
       -+
       - static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc)
       - {
       -         struct omap_drm_private *priv = crtc->dev->dev_private;
       -diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
       -index 4bd1e90..22f3d94 100644
       ---- a/drivers/gpu/drm/omapdrm/omap_drv.h
       -+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
       -@@ -97,6 +97,7 @@ void omap_gem_describe_objects(struct list_head *list, struct seq_file *m);
       - int omap_gem_resume(struct device *dev);
       - #endif
       - 
       -+int omap_irq_enable_framedone(struct drm_crtc *crtc, bool enable);
       - int omap_irq_enable_vblank(struct drm_crtc *crtc);
       - void omap_irq_disable_vblank(struct drm_crtc *crtc);
       - void omap_drm_irq_uninstall(struct drm_device *dev);
       -@@ -124,6 +125,7 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
       - int omap_crtc_wait_pending(struct drm_crtc *crtc);
       - void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus);
       - void omap_crtc_vblank_irq(struct drm_crtc *crtc);
       -+void omap_crtc_framedone_irq(struct drm_crtc *crtc, uint32_t irqstatus);
       - 
       - struct drm_plane *omap_plane_init(struct drm_device *dev,
       -                 int idx, enum drm_plane_type type,
       -diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
       -index 013b0bb..301c0e7 100644
       ---- a/drivers/gpu/drm/omapdrm/omap_irq.c
       -+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
       -@@ -87,6 +87,27 @@ int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
       -         return ret == 0 ? -1 : 0;
       - }
       - 
       -+int omap_irq_enable_framedone(struct drm_crtc *crtc, bool enable)
       -+{
       -+        struct drm_device *dev = crtc->dev;
       -+        struct omap_drm_private *priv = dev->dev_private;
       -+        unsigned long flags;
       -+        enum omap_channel channel = omap_crtc_channel(crtc);
       -+        int framedone_irq = priv->dispc_ops->mgr_get_framedone_irq(channel);
       -+
       -+        DBG("dev=%p, crtc=%u, enable=%d", dev, channel, enable);
       -+
       -+        spin_lock_irqsave(&priv->wait_lock, flags);
       -+        if (enable)
       -+                priv->irq_mask |= framedone_irq;
       -+        else
       -+                priv->irq_mask &= ~framedone_irq;
       -+        omap_irq_update(dev);
       -+        spin_unlock_irqrestore(&priv->wait_lock, flags);
       -+
       -+        return 0;
       -+}
       -+
       - /**
       -  * enable_vblank - enable vblank interrupt events
       -  * @dev: DRM device
       -@@ -217,6 +238,9 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
       - 
       -                 if (irqstatus & priv->dispc_ops->mgr_get_sync_lost_irq(channel))
       -                         omap_crtc_error_irq(crtc, irqstatus);
       -+
       -+                if (irqstatus & priv->dispc_ops->mgr_get_framedone_irq(channel))
       -+                        omap_crtc_framedone_irq(crtc, irqstatus);
       -         }
       - 
       -         omap_irq_ocp_error_handler(dev, irqstatus);
       --- 
       -2.1.4
       -
   DIR diff --git a/extra/patches/linux-droid4-patches/0004_dt-bindings-panel-common-document-orientation-property.patch b/extra/patches/linux-droid4-patches/0004_dt-bindings-panel-common-document-orientation-property.patch
       t@@ -0,0 +1,57 @@
       +Introduce new "orientation" property for describing in which
       +orientation a panel has been mounted to the device. This can
       +be used by the operating system to automatically rotate the
       +display correctly.
       +
       +Signed-off-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxxxx>
       +---
       + .../devicetree/bindings/display/panel/panel-common.txt     | 12 ++++++++++++
       + include/dt-bindings/display/common.h                       | 14 ++++++++++++++
       + 2 files changed, 26 insertions(+)
       + create mode 100644 include/dt-bindings/display/common.h
       +
       +diff --git a/Documentation/devicetree/bindings/display/panel/panel-common.txt b/Documentation/devicetree/bindings/display/panel/panel-common.txt
       +index 557fa765adcb..c646b8908458 100644
       +--- a/Documentation/devicetree/bindings/display/panel/panel-common.txt
       ++++ b/Documentation/devicetree/bindings/display/panel/panel-common.txt
       +@@ -18,6 +18,18 @@ Descriptive Properties
       +   physical area where images are displayed. These properties are expressed in
       +   millimeters and rounded to the closest unit.
       + 
       ++- orientation: The orientation property specifies the panel orientation
       ++  in relation to the device's casing. The following values are possible:
       ++
       ++   * 0 = The top side of the panel matches the top side of the device's
       ++         casing.
       ++   * 1 = The top side of the panel matches the bottom side of the device's
       ++         casing. In other words the panel is mounted upside-down.
       ++   * 2 = The left side of the panel matches the top side of the device's
       ++         casing.
       ++   * 3 = The right side of the panel matches the top side of the device's
       ++         casing.
       ++
       + - label: The label property specifies a symbolic name for the panel as a
       +   string suitable for use by humans. It typically contains a name inscribed on
       +   the system (e.g. as an affixed label) or specified in the system's
       +diff --git a/include/dt-bindings/display/common.h b/include/dt-bindings/display/common.h
       +new file mode 100644
       +index 000000000000..a864775445a0
       +--- /dev/null
       ++++ b/include/dt-bindings/display/common.h
       +@@ -0,0 +1,14 @@
       ++/* SPDX-License-Identifier: GPL-2.0 */
       ++/*
       ++ * This header provides common constants for displays
       ++ */
       ++
       ++#ifndef _DT_BINDINGS_DISPLAY_COMMON_H
       ++#define _DT_BINDINGS_DISPLAY_COMMON_H
       ++
       ++#define PANEL_ORIENTATION_NORMAL 0
       ++#define PANEL_ORIENTATION_BOTTOM_UP 1
       ++#define PANEL_ORIENTATION_LEFT_UP 2
       ++#define PANEL_ORIENTATION_RIGHT_UP 3
       ++
       ++#endif
       +-- 
       +2.15.1
   DIR diff --git a/extra/patches/linux-droid4-patches/0005-drm-omap-add-manual-update-detection-helper.patch b/extra/patches/linux-droid4-patches/0005-drm-omap-add-manual-update-detection-helper.patch
       t@@ -1,49 +0,0 @@
       -From 6dae0575adf3b15c51832bfa8c0320e8526e9b8e Mon Sep 17 00:00:00 2001
       -From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       -Date: Mon, 24 Jul 2017 19:33:02 +0200
       -Subject: [PATCH 05/17] drm/omap: add manual update detection helper
       -
       -In preparation for manually updated display support, such as DSI
       -command mode panels, this adds a simple helper to see if a connector
       -is manually updated.
       -
       -Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       ----
       - drivers/gpu/drm/omapdrm/omap_connector.c | 8 ++++++++
       - drivers/gpu/drm/omapdrm/omap_drv.h       | 1 +
       - 2 files changed, 9 insertions(+)
       -
       -diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
       -index aa5ba9a..4f4c7ef 100644
       ---- a/drivers/gpu/drm/omapdrm/omap_connector.c
       -+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
       -@@ -59,6 +59,14 @@ bool omap_connector_get_hdmi_mode(struct drm_connector *connector)
       -         return omap_connector->hdmi_mode;
       - }
       - 
       -+bool omap_connector_get_manually_updated(struct drm_connector *connector)
       -+{
       -+        struct omap_connector *omap_connector = to_omap_connector(connector);
       -+
       -+        return !!(omap_connector->dssdev->caps &
       -+                  OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE);
       -+}
       -+
       - static enum drm_connector_status omap_connector_detect(
       -                 struct drm_connector *connector, bool force)
       - {
       -diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
       -index 22f3d94..f6c48f2 100644
       ---- a/drivers/gpu/drm/omapdrm/omap_drv.h
       -+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
       -@@ -142,6 +142,7 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
       - struct drm_encoder *omap_connector_attached_encoder(
       -                 struct drm_connector *connector);
       - bool omap_connector_get_hdmi_mode(struct drm_connector *connector);
       -+bool omap_connector_get_manually_updated(struct drm_connector *connector);
       - 
       - struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
       -                 struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd);
       --- 
       -2.1.4
       -
   DIR diff --git a/extra/patches/linux-droid4-patches/0005_drm-omap-add-support-for-orientation-hints-from-display-drivers.patch b/extra/patches/linux-droid4-patches/0005_drm-omap-add-support-for-orientation-hints-from-display-drivers.patch
       t@@ -0,0 +1,59 @@
       +This adds support for setting DRM panel orientation property
       +based on information from the display driver.
       +
       +Signed-off-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxxxx>
       +---
       + drivers/gpu/drm/omapdrm/dss/omapdss.h    |  2 ++
       + drivers/gpu/drm/omapdrm/omap_connector.c | 10 +++++++++-
       + 2 files changed, 11 insertions(+), 1 deletion(-)
       +
       +diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
       +index f8f83e826a56..72ebd82409d3 100644
       +--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
       ++++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
       +@@ -565,6 +565,8 @@ struct omap_dss_driver {
       +                             struct videomode *vm);
       +         void (*get_size)(struct omap_dss_device *dssdev,
       +                          unsigned int *width, unsigned int *height);
       ++        void (*get_orientation)(struct omap_dss_device *dssdev,
       ++                                int *orientation);
       + 
       +         int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
       +         u32 (*get_wss)(struct omap_dss_device *dssdev);
       +diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
       +index a33b51484b2d..2f296d29b74b 100644
       +--- a/drivers/gpu/drm/omapdrm/omap_connector.c
       ++++ b/drivers/gpu/drm/omapdrm/omap_connector.c
       +@@ -249,6 +249,7 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
       +         struct drm_connector *connector = NULL;
       +         struct omap_connector *omap_connector;
       +         bool hpd_supported = false;
       ++        int ret;
       + 
       +         DBG("%s", dssdev->name);
       + 
       +@@ -267,7 +268,7 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
       +         drm_connector_helper_add(connector, &omap_connector_helper_funcs);
       + 
       +         if (dssdev->driver->register_hpd_cb) {
       +-                int ret = dssdev->driver->register_hpd_cb(dssdev,
       ++                ret = dssdev->driver->register_hpd_cb(dssdev,
       +                                                           omap_connector_hpd_cb,
       +                                                           omap_connector);
       +                 if (!ret)
       +@@ -288,6 +289,13 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
       +         connector->interlace_allowed = 1;
       +         connector->doublescan_allowed = 0;
       + 
       ++        if (dssdev->driver->get_orientation)
       ++                dssdev->driver->get_orientation(dssdev, &connector->display_info.panel_orientation);
       ++
       ++        ret = drm_connector_init_panel_orientation_property(connector, 0, 0);
       ++        if (ret)
       ++                DBG("%s: Failed to init orientation property (%d)", dssdev->name, ret);
       ++
       +         return connector;
       + 
       + fail:
       +-- 
       +2.15.1
   DIR diff --git a/extra/patches/linux-droid4-patches/0006-drm-omap-add-support-for-manually-updated-displays.patch b/extra/patches/linux-droid4-patches/0006-drm-omap-add-support-for-manually-updated-displays.patch
       t@@ -1,263 +0,0 @@
       -From 2a51a11e2f2705bbf7642e2e08ae6b2f1372d79c Mon Sep 17 00:00:00 2001
       -From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       -Date: Mon, 24 Jul 2017 19:33:03 +0200
       -Subject: [PATCH 06/17] drm/omap: add support for manually updated displays
       -
       -This adds the required infrastructure for manually
       -updated displays, such as DSI command mode panels.
       -
       -While those panels often support partial updates
       -we currently always do a full refresh. Display
       -will be refreshed when something calls the dirty
       -callback, such as libdrm's drmModeDirtyFB().
       -
       -This is currently being implemented for the kernel
       -console and for Xorg. Weston currently does not
       -implement this and is known not to work on manually
       -updated displays.
       -
       -Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       ----
       - drivers/gpu/drm/omapdrm/omap_crtc.c | 110 +++++++++++++++++++++++++++++++++---
       - drivers/gpu/drm/omapdrm/omap_drv.h  |   1 +
       - drivers/gpu/drm/omapdrm/omap_fb.c   |  20 +++++++
       - 3 files changed, 123 insertions(+), 8 deletions(-)
       -
       -diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
       -index dee9b6e..8255241 100644
       ---- a/drivers/gpu/drm/omapdrm/omap_crtc.c
       -+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
       -@@ -52,6 +52,7 @@ struct omap_crtc {
       -         bool pending;
       -         wait_queue_head_t pending_wait;
       -         struct drm_pending_vblank_event *event;
       -+        struct delayed_work update_work;
       - 
       -         void (*framedone_handler)(void *);
       -         void *framedone_handler_data;
       -@@ -143,6 +144,28 @@ static void omap_crtc_dss_disconnect(enum omap_channel channel,
       - 
       - static void omap_crtc_dss_start_update(enum omap_channel channel)
       - {
       -+        struct omap_crtc *omap_crtc = omap_crtcs[channel];
       -+        struct omap_drm_private *priv = omap_crtc->base.dev->dev_private;
       -+
       -+        priv->dispc_ops->mgr_enable(channel, true);
       -+}
       -+
       -+static bool omap_crtc_is_manually_updated(struct drm_crtc *crtc)
       -+{
       -+        struct drm_connector *connector;
       -+        struct drm_connector_list_iter conn_iter;
       -+        bool result = false;
       -+
       -+        drm_connector_list_iter_begin(crtc->dev, &conn_iter);
       -+        drm_for_each_connector_iter(connector, &conn_iter) {
       -+                if (connector->state->crtc != crtc)
       -+                        continue;
       -+                result = omap_connector_get_manually_updated(connector);
       -+                break;
       -+        }
       -+        drm_connector_list_iter_end(&conn_iter);
       -+
       -+        return result;
       - }
       - 
       - /* Called only from the encoder enable/disable and suspend/resume handlers. */
       -@@ -154,12 +177,17 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
       -         enum omap_channel channel = omap_crtc->channel;
       -         struct omap_irq_wait *wait;
       -         u32 framedone_irq, vsync_irq;
       -+        bool is_manual = omap_crtc_is_manually_updated(crtc);
       -+        enum omap_display_type type = omap_crtc_output[channel]->output_type;
       -         int ret;
       - 
       -         if (WARN_ON(omap_crtc->enabled == enable))
       -                 return;
       - 
       --        if (omap_crtc_output[channel]->output_type == OMAP_DISPLAY_TYPE_HDMI) {
       -+        if (is_manual)
       -+                omap_irq_enable_framedone(crtc, enable);
       -+
       -+        if (is_manual || type == OMAP_DISPLAY_TYPE_HDMI) {
       -                 priv->dispc_ops->mgr_enable(channel, enable);
       -                 omap_crtc->enabled = enable;
       -                 return;
       -@@ -210,7 +238,6 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
       -         }
       - }
       - 
       --
       - static int omap_crtc_dss_enable(enum omap_channel channel)
       - {
       -         struct omap_crtc *omap_crtc = omap_crtcs[channel];
       -@@ -370,6 +397,53 @@ void omap_crtc_framedone_irq(struct drm_crtc *crtc, uint32_t irqstatus)
       -         wake_up(&omap_crtc->pending_wait);
       - }
       - 
       -+void omap_crtc_flush(struct drm_crtc *crtc)
       -+{
       -+        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
       -+
       -+        if (!omap_crtc_is_manually_updated(crtc))
       -+                return;
       -+
       -+        if (!delayed_work_pending(&omap_crtc->update_work))
       -+                schedule_delayed_work(&omap_crtc->update_work, 0);
       -+}
       -+
       -+static void omap_crtc_manual_display_update(struct work_struct *data)
       -+{
       -+        struct omap_crtc *omap_crtc =
       -+                        container_of(data, struct omap_crtc, update_work.work);
       -+        struct omap_dss_device *dssdev = omap_crtc_output[omap_crtc->channel];
       -+        struct drm_device *dev = omap_crtc->base.dev;
       -+        struct omap_dss_driver *dssdrv;
       -+        int ret, width, height;
       -+
       -+        if (!dssdev || !dssdev->dst) {
       -+                dev_err_once(dev->dev, "missing dssdev!");
       -+                return;
       -+        }
       -+
       -+        dssdev = dssdev->dst;
       -+        dssdrv = dssdev->driver;
       -+
       -+        if (!dssdrv || !dssdrv->update) {
       -+                dev_err_once(dev->dev, "incorrect dssdrv!");
       -+                return;
       -+        }
       -+
       -+        if (dssdrv->sync)
       -+                dssdrv->sync(dssdev);
       -+
       -+        width = dssdev->panel.vm.hactive;
       -+        height = dssdev->panel.vm.vactive;
       -+        ret = dssdrv->update(dssdev, 0, 0, width, height);
       -+        if (ret < 0) {
       -+                spin_lock_irq(&dev->event_lock);
       -+                omap_crtc->pending = false;
       -+                spin_unlock_irq(&dev->event_lock);
       -+                wake_up(&omap_crtc->pending_wait);
       -+        }
       -+}
       -+
       - static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc)
       - {
       -         struct omap_drm_private *priv = crtc->dev->dev_private;
       -@@ -422,6 +496,10 @@ static void omap_crtc_atomic_enable(struct drm_crtc *crtc,
       - 
       -         DBG("%s", omap_crtc->name);
       - 
       -+        /* manual updated display will not trigger vsync irq */
       -+        if (omap_crtc_is_manually_updated(crtc))
       -+                return;
       -+
       -         spin_lock_irq(&crtc->dev->event_lock);
       -         drm_crtc_vblank_on(crtc);
       -         ret = drm_crtc_vblank_get(crtc);
       -@@ -435,6 +513,7 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc,
       -                                      struct drm_crtc_state *old_state)
       - {
       -         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
       -+        struct drm_device *dev = crtc->dev;
       - 
       -         DBG("%s", omap_crtc->name);
       - 
       -@@ -445,6 +524,11 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc,
       -         }
       -         spin_unlock_irq(&crtc->dev->event_lock);
       - 
       -+        cancel_delayed_work(&omap_crtc->update_work);
       -+
       -+        if (!omap_crtc_wait_pending(crtc))
       -+                dev_warn(dev->dev, "manual display update did not finish!");
       -+
       -         drm_crtc_vblank_off(crtc);
       - }
       - 
       -@@ -559,13 +643,20 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
       - 
       -         DBG("%s: GO", omap_crtc->name);
       - 
       --        ret = drm_crtc_vblank_get(crtc);
       --        WARN_ON(ret != 0);
       -+        if (!omap_crtc_is_manually_updated(crtc)) {
       -+                ret = drm_crtc_vblank_get(crtc);
       -+                WARN_ON(ret != 0);
       - 
       --        spin_lock_irq(&crtc->dev->event_lock);
       --        priv->dispc_ops->mgr_go(omap_crtc->channel);
       --        omap_crtc_arm_event(crtc);
       --        spin_unlock_irq(&crtc->dev->event_lock);
       -+                spin_lock_irq(&crtc->dev->event_lock);
       -+                priv->dispc_ops->mgr_go(omap_crtc->channel);
       -+                omap_crtc_arm_event(crtc);
       -+                spin_unlock_irq(&crtc->dev->event_lock);
       -+        } else {
       -+                spin_lock_irq(&crtc->dev->event_lock);
       -+                omap_crtc_flush(crtc);
       -+                omap_crtc_arm_event(crtc);
       -+                spin_unlock_irq(&crtc->dev->event_lock);
       -+        }
       - }
       - 
       - static int omap_crtc_atomic_set_property(struct drm_crtc *crtc,
       -@@ -726,6 +817,9 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
       -         omap_crtc->channel = channel;
       -         omap_crtc->name = channel_names[channel];
       - 
       -+        INIT_DELAYED_WORK(&omap_crtc->update_work,
       -+                          omap_crtc_manual_display_update);
       -+
       -         ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
       -                                         &omap_crtc_funcs, NULL);
       -         if (ret < 0) {
       -diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
       -index f6c48f2..3cb9f9a 100644
       ---- a/drivers/gpu/drm/omapdrm/omap_drv.h
       -+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
       -@@ -126,6 +126,7 @@ int omap_crtc_wait_pending(struct drm_crtc *crtc);
       - void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus);
       - void omap_crtc_vblank_irq(struct drm_crtc *crtc);
       - void omap_crtc_framedone_irq(struct drm_crtc *crtc, uint32_t irqstatus);
       -+void omap_crtc_flush(struct drm_crtc *crtc);
       - 
       - struct drm_plane *omap_plane_init(struct drm_device *dev,
       -                 int idx, enum drm_plane_type type,
       -diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
       -index b1a762b..9492be6 100644
       ---- a/drivers/gpu/drm/omapdrm/omap_fb.c
       -+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
       -@@ -97,8 +97,28 @@ static void omap_framebuffer_destroy(struct drm_framebuffer *fb)
       -         kfree(omap_fb);
       - }
       - 
       -+static int omap_framebuffer_dirty(struct drm_framebuffer *fb,
       -+                                  struct drm_file *file_priv,
       -+                                  unsigned flags, unsigned color,
       -+                                  struct drm_clip_rect *clips,
       -+                                  unsigned num_clips)
       -+{
       -+        struct drm_connector *connector = NULL;
       -+
       -+        drm_modeset_lock_all(fb->dev);
       -+
       -+        while ((connector = omap_framebuffer_get_next_connector(fb, connector)))
       -+                if (connector->encoder && connector->encoder->crtc)
       -+                        omap_crtc_flush(connector->encoder->crtc);
       -+
       -+        drm_modeset_unlock_all(fb->dev);
       -+
       -+        return 0;
       -+}
       -+
       - static const struct drm_framebuffer_funcs omap_framebuffer_funcs = {
       -         .create_handle = omap_framebuffer_create_handle,
       -+        .dirty = omap_framebuffer_dirty,
       -         .destroy = omap_framebuffer_destroy,
       - };
       - 
       --- 
       -2.1.4
       -
   DIR diff --git a/extra/patches/linux-droid4-patches/0006_drm-omap-panel-dsi-cm-add-orientation-support.patch b/extra/patches/linux-droid4-patches/0006_drm-omap-panel-dsi-cm-add-orientation-support.patch
       t@@ -0,0 +1,55 @@
       +Add support to inform the DRM subsystem about the orientation
       +the display has been mounted to the casing.
       +
       +Signed-off-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxxxx>
       +---
       + drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 13 +++++++++++++
       + 1 file changed, 13 insertions(+)
       +
       +diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       +index 15399a1a666b..7a63d6775a27 100644
       +--- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       ++++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       +@@ -68,6 +68,7 @@ struct panel_drv_data {
       + 
       +         int width_mm;
       +         int height_mm;
       ++        int orientation;
       + 
       +         struct omap_dsi_pin_config pin_config;
       + 
       +@@ -1198,6 +1199,14 @@ static void dsicm_get_size(struct omap_dss_device *dssdev,
       +         *height = ddata->height_mm;
       + }
       + 
       ++static void dsicm_get_orientation(struct omap_dss_device *dssdev,
       ++                                  int *orientation)
       ++{
       ++        struct panel_drv_data *ddata = to_panel_data(dssdev);
       ++
       ++        *orientation = ddata->orientation;
       ++}
       ++
       + static struct omap_dss_driver dsicm_ops = {
       +         .connect        = dsicm_connect,
       +         .disconnect        = dsicm_disconnect,
       +@@ -1211,6 +1220,7 @@ static struct omap_dss_driver dsicm_ops = {
       +         .get_timings        = dsicm_get_timings,
       +         .check_timings        = dsicm_check_timings,
       +         .get_size        = dsicm_get_size,
       ++        .get_orientation = dsicm_get_orientation,
       + 
       +         .enable_te        = dsicm_enable_te,
       +         .get_te                = dsicm_get_te,
       +@@ -1259,6 +1269,9 @@ static int dsicm_probe_of(struct platform_device *pdev)
       +         ddata->height_mm = 0;
       +         of_property_read_u32(node, "height-mm", &ddata->height_mm);
       + 
       ++        ddata->orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
       ++        of_property_read_u32(node, "orientation", &ddata->orientation);
       ++
       +         in = omapdss_of_find_source_for_first_ep(node);
       +         if (IS_ERR(in)) {
       +                 dev_err(&pdev->dev, "failed to find video source\n");
       +-- 
       +2.15.1
   DIR diff --git a/extra/patches/linux-droid4-patches/0007-drm-omap-add-support-for-physical-size-hints-from-di.patch b/extra/patches/linux-droid4-patches/0007-drm-omap-add-support-for-physical-size-hints-from-di.patch
       t@@ -1,50 +0,0 @@
       -From 1e66c0a2f776d6054c2324daf55fc3e3df126c33 Mon Sep 17 00:00:00 2001
       -From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       -Date: Mon, 24 Jul 2017 19:33:04 +0200
       -Subject: [PATCH 07/17] drm/omap: add support for physical size hints from
       - display drivers
       -
       -While physical size information is automatically parsed for EDID
       -based displays, we need to provide it manually for displays providing
       -one fixed mode.
       -
       -Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       -Acked-by: Pavel Machek <pavel@ucw.cz>
       ----
       - drivers/gpu/drm/omapdrm/dss/omapdss.h    | 2 ++
       - drivers/gpu/drm/omapdrm/omap_connector.c | 6 ++++++
       - 2 files changed, 8 insertions(+)
       -
       -diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
       -index 3d25359..5be6ff8 100644
       ---- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
       -+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
       -@@ -562,6 +562,8 @@ struct omap_dss_driver {
       -                             struct videomode *vm);
       -         void (*get_timings)(struct omap_dss_device *dssdev,
       -                             struct videomode *vm);
       -+        void (*get_size)(struct omap_dss_device *dssdev,
       -+                         unsigned int *width, unsigned int *height);
       - 
       -         int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
       -         u32 (*get_wss)(struct omap_dss_device *dssdev);
       -diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
       -index 4f4c7ef..8874f55 100644
       ---- a/drivers/gpu/drm/omapdrm/omap_connector.c
       -+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
       -@@ -157,6 +157,12 @@ static int omap_connector_get_modes(struct drm_connector *connector)
       -                 drm_mode_set_name(mode);
       -                 drm_mode_probed_add(connector, mode);
       - 
       -+                if (dssdrv->get_size) {
       -+                        dssdrv->get_size(dssdev,
       -+                                         &connector->display_info.width_mm,
       -+                                         &connector->display_info.height_mm);
       -+                }
       -+
       -                 n = 1;
       -         }
       - 
       --- 
       -2.1.4
       -
   DIR diff --git a/extra/patches/linux-droid4-patches/0007_arm-dts-omap4-droid4-add-lcd-panel-orientation-property.patch b/extra/patches/linux-droid4-patches/0007_arm-dts-omap4-droid4-add-lcd-panel-orientation-property.patch
       t@@ -0,0 +1,31 @@
       +This adds a LCD panel orientation hint to the Droid 4. If the
       +display is rotated this way the keyboard can be used properly.
       +
       +Signed-off-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxxxx>
       +---
       + arch/arm/boot/dts/omap4-droid4-xt894.dts | 3 +++
       + 1 file changed, 3 insertions(+)
       +
       +diff --git a/arch/arm/boot/dts/omap4-droid4-xt894.dts b/arch/arm/boot/dts/omap4-droid4-xt894.dts
       +index b21084da490b..e11a24397163 100644
       +--- a/arch/arm/boot/dts/omap4-droid4-xt894.dts
       ++++ b/arch/arm/boot/dts/omap4-droid4-xt894.dts
       +@@ -6,6 +6,7 @@
       + /dts-v1/;
       + 
       + #include <dt-bindings/input/input.h>
       ++#include <dt-bindings/display/common.h>
       + #include "omap443x.dtsi"
       + #include "motorola-cpcap-mapphone.dtsi"
       + 
       +@@ -181,6 +182,8 @@
       +                 height-mm = <89>;
       +                 backlight = <&lcd_backlight>;
       + 
       ++                orientation = <PANEL_ORIENTATION_RIGHT_UP>;
       ++
       +                 panel-timing {
       +                         clock-frequency = <0>;                /* Calculated by dsi */
       + 
       +-- 
       +2.15.1
   DIR diff --git a/extra/patches/linux-droid4-patches/0008-drm-omap-panel-dsi-cm-fix-driver.patch b/extra/patches/linux-droid4-patches/0008-drm-omap-panel-dsi-cm-fix-driver.patch
       t@@ -1,124 +0,0 @@
       -From 328a31aeb9e4cb56f312be7722010ede59ef96be Mon Sep 17 00:00:00 2001
       -From: Tony Lindgren <tony@atomide.com>
       -Date: Mon, 24 Jul 2017 19:33:05 +0200
       -Subject: [PATCH 08/17] drm/omap: panel-dsi-cm: fix driver
       -
       -This adds support for get_timings() and check_timings()
       -to get the driver working and properly initializes the
       -timing information from DT.
       -
       -Signed-off-by: Tony Lindgren <tony@atomide.com>
       -Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       ----
       - drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 56 ++++++++++++++++++++++---
       - 1 file changed, 51 insertions(+), 5 deletions(-)
       -
       -diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       -index 92c556a..905b717 100644
       ---- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       -+++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       -@@ -25,6 +25,7 @@
       - #include <linux/of_gpio.h>
       - 
       - #include <video/mipi_display.h>
       -+#include <video/of_display_timing.h>
       - 
       - #include "../dss/omapdss.h"
       - 
       -@@ -1099,6 +1100,36 @@ static void dsicm_ulps_work(struct work_struct *work)
       -         mutex_unlock(&ddata->lock);
       - }
       - 
       -+static void dsicm_get_timings(struct omap_dss_device *dssdev,
       -+                              struct videomode *vm)
       -+{
       -+        struct panel_drv_data *ddata = to_panel_data(dssdev);
       -+
       -+        *vm = ddata->vm;
       -+}
       -+
       -+static int dsicm_check_timings(struct omap_dss_device *dssdev,
       -+                               struct videomode *vm)
       -+{
       -+        struct panel_drv_data *ddata = to_panel_data(dssdev);
       -+        int ret = 0;
       -+
       -+        if (vm->hactive != ddata->vm.hactive)
       -+                ret = -EINVAL;
       -+
       -+        if (vm->vactive != ddata->vm.vactive)
       -+                ret = -EINVAL;
       -+
       -+        if (ret) {
       -+                dev_warn(dssdev->dev, "wrong resolution: %d x %d",
       -+                         vm->hactive, vm->vactive);
       -+                dev_warn(dssdev->dev, "panel resolution: %d x %d",
       -+                         ddata->vm.hactive, ddata->vm.vactive);
       -+        }
       -+
       -+        return ret;
       -+}
       -+
       - static struct omap_dss_driver dsicm_ops = {
       -         .connect        = dsicm_connect,
       -         .disconnect        = dsicm_disconnect,
       -@@ -1109,6 +1140,9 @@ static struct omap_dss_driver dsicm_ops = {
       -         .update                = dsicm_update,
       -         .sync                = dsicm_sync,
       - 
       -+        .get_timings        = dsicm_get_timings,
       -+        .check_timings        = dsicm_check_timings,
       -+
       -         .enable_te        = dsicm_enable_te,
       -         .get_te                = dsicm_get_te,
       - 
       -@@ -1120,7 +1154,8 @@ static int dsicm_probe_of(struct platform_device *pdev)
       -         struct device_node *node = pdev->dev.of_node;
       -         struct panel_drv_data *ddata = platform_get_drvdata(pdev);
       -         struct omap_dss_device *in;
       --        int gpio;
       -+        struct display_timing timing;
       -+        int gpio, err;
       - 
       -         gpio = of_get_named_gpio(node, "reset-gpios", 0);
       -         if (!gpio_is_valid(gpio)) {
       -@@ -1137,6 +1172,17 @@ static int dsicm_probe_of(struct platform_device *pdev)
       -                 return gpio;
       -         }
       - 
       -+        err = of_get_display_timing(node, "panel-timing", &timing);
       -+        if (!err) {
       -+                videomode_from_timing(&timing, &ddata->vm);
       -+                if (!ddata->vm.pixelclock)
       -+                        ddata->vm.pixelclock =
       -+                                ddata->vm.hactive * ddata->vm.vactive * 60;
       -+        } else {
       -+                dev_warn(&pdev->dev,
       -+                         "failed to get video timing, using defaults\n");
       -+        }
       -+
       -         in = omapdss_of_find_source_for_first_ep(node);
       -         if (IS_ERR(in)) {
       -                 dev_err(&pdev->dev, "failed to find video source\n");
       -@@ -1171,14 +1217,14 @@ static int dsicm_probe(struct platform_device *pdev)
       -         if (!pdev->dev.of_node)
       -                 return -ENODEV;
       - 
       --        r = dsicm_probe_of(pdev);
       --        if (r)
       --                return r;
       --
       -         ddata->vm.hactive = 864;
       -         ddata->vm.vactive = 480;
       -         ddata->vm.pixelclock = 864 * 480 * 60;
       - 
       -+        r = dsicm_probe_of(pdev);
       -+        if (r)
       -+                return r;
       -+
       -         dssdev = &ddata->dssdev;
       -         dssdev->dev = dev;
       -         dssdev->driver = &dsicm_ops;
       --- 
       -2.1.4
       -
   DIR diff --git a/extra/patches/linux-droid4-patches/0008_drm-omap-plane-update-fifo-size-on-ovl-setup.patch b/extra/patches/linux-droid4-patches/0008_drm-omap-plane-update-fifo-size-on-ovl-setup.patch
       t@@ -0,0 +1,125 @@
       +This is a workaround for a hardware bug occuring on OMAP3
       +with manually updated panels. Details about the HW bug are
       +unknown to me, but without this fix the panel refresh does
       +not work at all on Nokia N950. This is not the case for the
       +OMAP4 based Droid 4, which works perfectly fine with default
       +settings.
       +
       +Signed-off-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxxxx>
       +---
       + drivers/gpu/drm/omapdrm/dss/dispc.c | 36 +++++++++++++++++++++++++++++++++++-
       + 1 file changed, 35 insertions(+), 1 deletion(-)
       +
       +diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c
       +index 4e8f68efd169..0904c3201914 100644
       +--- a/drivers/gpu/drm/omapdrm/dss/dispc.c
       ++++ b/drivers/gpu/drm/omapdrm/dss/dispc.c
       +@@ -157,6 +157,8 @@ struct dispc_features {
       +         bool has_gamma_table:1;
       + 
       +         bool has_gamma_i734_bug:1;
       ++
       ++        bool has_fifo_stallmode_bug:1;
       + };
       + 
       + #define DISPC_MAX_NR_FIFOS 5
       +@@ -1489,6 +1491,18 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane_id plane,
       +         }
       + }
       + 
       ++static void dispc_ovl_set_manual_fifo_threshold(enum omap_plane_id plane)
       ++{
       ++        u32 fifo_low, fifo_high;
       ++        bool use_fifo_merge = false;
       ++        bool use_manual_update = true;
       ++
       ++        dispc_ovl_compute_fifo_thresholds(plane, &fifo_low, &fifo_high,
       ++                                          use_fifo_merge, use_manual_update);
       ++
       ++        dispc_ovl_set_fifo_threshold(plane, fifo_low, fifo_high);
       ++}
       ++
       + static void dispc_ovl_set_mflag(enum omap_plane_id plane, bool enable)
       + {
       +         int bit;
       +@@ -2651,8 +2665,21 @@ static int dispc_ovl_setup(enum omap_plane_id plane,
       +                 oi->out_width, oi->out_height, oi->fourcc, oi->rotation,
       +                 oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
       +                 oi->rotation_type, replication, vm, mem_to_mem);
       ++        if (r)
       ++                return r;
       + 
       +-        return r;
       ++        /*
       ++         * OMAP3 chips have non-working FIFO thresholds for manually updated
       ++         * displays. The issue is not fully understood, but this workaround
       ++         * fixes the issue. OMAP4 is known to work with default thresholds.
       ++         */
       ++        if (mgr_fld_read(channel, DISPC_MGR_FLD_STALLMODE) &&
       ++            dispc.feat->has_fifo_stallmode_bug) {
       ++                DSSDBG("Enable OMAP3 FIFO stallmode bug workaround!\n");
       ++                dispc_ovl_set_manual_fifo_threshold(plane);
       ++        }
       ++
       ++        return 0;
       + }
       + 
       + int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
       +@@ -4067,6 +4094,7 @@ static const struct dispc_features omap24xx_dispc_feats = {
       +         .no_framedone_tv        =        true,
       +         .set_max_preload        =        false,
       +         .last_pixel_inc_missing        =        true,
       ++        .has_fifo_stallmode_bug        =        true,
       + };
       + 
       + static const struct dispc_features omap34xx_rev1_0_dispc_feats = {
       +@@ -4101,6 +4129,7 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats = {
       +         .no_framedone_tv        =        true,
       +         .set_max_preload        =        false,
       +         .last_pixel_inc_missing        =        true,
       ++        .has_fifo_stallmode_bug        =        true,
       + };
       + 
       + static const struct dispc_features omap34xx_rev3_0_dispc_feats = {
       +@@ -4135,6 +4164,7 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats = {
       +         .no_framedone_tv        =        true,
       +         .set_max_preload        =        false,
       +         .last_pixel_inc_missing        =        true,
       ++        .has_fifo_stallmode_bug        =        true,
       + };
       + 
       + static const struct dispc_features omap36xx_dispc_feats = {
       +@@ -4169,6 +4199,7 @@ static const struct dispc_features omap36xx_dispc_feats = {
       +         .no_framedone_tv        =        true,
       +         .set_max_preload        =        false,
       +         .last_pixel_inc_missing        =        true,
       ++        .has_fifo_stallmode_bug        =        true,
       + };
       + 
       + static const struct dispc_features am43xx_dispc_feats = {
       +@@ -4203,6 +4234,7 @@ static const struct dispc_features am43xx_dispc_feats = {
       +         .no_framedone_tv        =        true,
       +         .set_max_preload        =        false,
       +         .last_pixel_inc_missing        =        true,
       ++        .has_fifo_stallmode_bug        =        false,
       + };
       + 
       + static const struct dispc_features omap44xx_dispc_feats = {
       +@@ -4242,6 +4274,7 @@ static const struct dispc_features omap44xx_dispc_feats = {
       +         .reverse_ilace_field_order =        true,
       +         .has_gamma_table        =        true,
       +         .has_gamma_i734_bug        =        true,
       ++        .has_fifo_stallmode_bug        =        false,
       + };
       + 
       + static const struct dispc_features omap54xx_dispc_feats = {
       +@@ -4282,6 +4315,7 @@ static const struct dispc_features omap54xx_dispc_feats = {
       +         .reverse_ilace_field_order =        true,
       +         .has_gamma_table        =        true,
       +         .has_gamma_i734_bug        =        true,
       ++        .has_fifo_stallmode_bug        =        false,
       + };
       + 
       + static irqreturn_t dispc_irq_handler(int irq, void *arg)
       +-- 
       +2.15.1
   DIR diff --git a/extra/patches/linux-droid4-patches/0009-drm-omap-panel-dsi-cm-add-regulator-support.patch b/extra/patches/linux-droid4-patches/0009-drm-omap-panel-dsi-cm-add-regulator-support.patch
       t@@ -1,135 +0,0 @@
       -From 594f7f466237d32323f63c04e92f7ce7be2f2a4f Mon Sep 17 00:00:00 2001
       -From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       -Date: Mon, 24 Jul 2017 19:33:06 +0200
       -Subject: [PATCH 09/17] drm/omap: panel-dsi-cm: add regulator support
       -
       -Add support for regulators used by panels found inside
       -of the Nokia N950, N9 and Motorola Droid 4.
       -
       -Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       ----
       - drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 57 +++++++++++++++++++++++--
       - 1 file changed, 53 insertions(+), 4 deletions(-)
       -
       -diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       -index 905b717..b98ea9e 100644
       ---- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       -+++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       -@@ -23,6 +23,7 @@
       - #include <linux/workqueue.h>
       - #include <linux/of_device.h>
       - #include <linux/of_gpio.h>
       -+#include <linux/regulator/consumer.h>
       - 
       - #include <video/mipi_display.h>
       - #include <video/of_display_timing.h>
       -@@ -60,6 +61,9 @@ struct panel_drv_data {
       -         int reset_gpio;
       -         int ext_te_gpio;
       - 
       -+        struct regulator *vpnl;
       -+        struct regulator *vddi;
       -+
       -         bool use_dsi_backlight;
       - 
       -         struct omap_dsi_pin_config pin_config;
       -@@ -590,25 +594,43 @@ static int dsicm_power_on(struct panel_drv_data *ddata)
       -                 .lp_clk_max = 10000000,
       -         };
       - 
       -+        if (ddata->vpnl) {
       -+                r = regulator_enable(ddata->vpnl);
       -+                if (r) {
       -+                        dev_err(&ddata->pdev->dev,
       -+                                "failed to enable VPNL: %d\n", r);
       -+                        return r;
       -+                }
       -+        }
       -+
       -+        if (ddata->vddi) {
       -+                r = regulator_enable(ddata->vddi);
       -+                if (r) {
       -+                        dev_err(&ddata->pdev->dev,
       -+                                "failed to enable VDDI: %d\n", r);
       -+                        goto err_vpnl;
       -+                }
       -+        }
       -+
       -         if (ddata->pin_config.num_pins > 0) {
       -                 r = in->ops.dsi->configure_pins(in, &ddata->pin_config);
       -                 if (r) {
       -                         dev_err(&ddata->pdev->dev,
       -                                 "failed to configure DSI pins\n");
       --                        goto err0;
       -+                        goto err_vddi;
       -                 }
       -         }
       - 
       -         r = in->ops.dsi->set_config(in, &dsi_config);
       -         if (r) {
       -                 dev_err(&ddata->pdev->dev, "failed to configure DSI\n");
       --                goto err0;
       -+                goto err_vddi;
       -         }
       - 
       -         r = in->ops.dsi->enable(in);
       -         if (r) {
       -                 dev_err(&ddata->pdev->dev, "failed to enable DSI\n");
       --                goto err0;
       -+                goto err_vddi;
       -         }
       - 
       -         dsicm_hw_reset(ddata);
       -@@ -666,7 +688,13 @@ static int dsicm_power_on(struct panel_drv_data *ddata)
       -         dsicm_hw_reset(ddata);
       - 
       -         in->ops.dsi->disable(in, true, false);
       --err0:
       -+err_vddi:
       -+        if (ddata->vddi)
       -+                regulator_disable(ddata->vddi);
       -+err_vpnl:
       -+        if (ddata->vpnl)
       -+                regulator_disable(ddata->vpnl);
       -+
       -         return r;
       - }
       - 
       -@@ -689,6 +717,11 @@ static void dsicm_power_off(struct panel_drv_data *ddata)
       - 
       -         in->ops.dsi->disable(in, true, false);
       - 
       -+        if (ddata->vddi)
       -+                regulator_disable(ddata->vddi);
       -+        if (ddata->vpnl)
       -+                regulator_disable(ddata->vpnl);
       -+
       -         ddata->enabled = 0;
       - }
       - 
       -@@ -1189,6 +1222,22 @@ static int dsicm_probe_of(struct platform_device *pdev)
       -                 return PTR_ERR(in);
       -         }
       - 
       -+        ddata->vpnl = devm_regulator_get_optional(&pdev->dev, "vpnl");
       -+        if (IS_ERR(ddata->vpnl)) {
       -+                err = PTR_ERR(ddata->vpnl);
       -+                if (err == -EPROBE_DEFER)
       -+                        return err;
       -+                ddata->vpnl = NULL;
       -+        }
       -+
       -+        ddata->vddi = devm_regulator_get_optional(&pdev->dev, "vddi");
       -+        if (IS_ERR(ddata->vddi)) {
       -+                err = PTR_ERR(ddata->vddi);
       -+                if (err == -EPROBE_DEFER)
       -+                        return err;
       -+                ddata->vddi = NULL;
       -+        }
       -+
       -         ddata->in = in;
       - 
       -         /* TODO: ulps, backlight */
       --- 
       -2.1.4
       -
   DIR diff --git a/extra/patches/linux-droid4-patches/0009_arm-dts-omap4-droid4-update-touchscreen.patch b/extra/patches/linux-droid4-patches/0009_arm-dts-omap4-droid4-update-touchscreen.patch
       t@@ -0,0 +1,67 @@
       +From: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxxxx>
       +
       +Update the Droid 4 devicetree to properly describe the reset
       +GPIO. Also rename the node to touchscreen instead of tsp,
       +which seems to be commonly used for touchscreens.
       +
       +Signed-off-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxxxx>
       +---
       + arch/arm/boot/dts/omap4-droid4-xt894.dts | 22 ++++++----------------
       + 1 file changed, 6 insertions(+), 16 deletions(-)
       +
       +diff --git a/arch/arm/boot/dts/omap4-droid4-xt894.dts b/arch/arm/boot/dts/omap4-droid4-xt894.dts
       +index 81c701929c70..40df997fc453 100644
       +--- a/arch/arm/boot/dts/omap4-droid4-xt894.dts
       ++++ b/arch/arm/boot/dts/omap4-droid4-xt894.dts
       +@@ -145,13 +145,6 @@
       + };
       + 
       + &gpio6 {
       +-        touchscreen_reset {
       +-                gpio-hog;
       +-                gpios = <13 0>;
       +-                output-high;
       +-                line-name = "touchscreen-reset";
       +-        };
       +-
       +         pwm8: dmtimer-pwm-8 {
       +                 pinctrl-names = "default";
       +                 pinctrl-0 = <&vibrator_direction_pin>;
       +@@ -385,22 +378,18 @@
       +         };
       + };
       + 
       +-/*
       +- * REVISIT: Add gpio173 reset pin handling to the driver, see gpio-hog above.
       +- * If the GPIO reset is used, we probably need to have /lib/firmware/maxtouch.fw
       +- * available. See "mxt-app" and "droid4-touchscreen-firmware" tools for more
       +- * information.
       +- */
       + &i2c2 {
       +-        tsp@4a {
       ++        touchscreen@4a {
       +                 compatible = "atmel,maxtouch";
       +                 reg = <0x4a>;
       +                 pinctrl-names = "default";
       +                 pinctrl-0 = <&touchscreen_pins>;
       + 
       ++                reset-gpios = <&gpio6 13 GPIO_ACTIVE_HIGH>; /* gpio173 */
       ++
       +                 /* gpio_183 with sys_nirq2 pad as wakeup */
       +-                interrupts-extended = <&gpio6 23 IRQ_TYPE_EDGE_FALLING
       +-                                       &omap4_pmx_core 0x160>;
       ++                interrupts-extended = <&gpio6 23 IRQ_TYPE_EDGE_FALLING>,
       ++                                      <&omap4_pmx_core 0x160>;
       +                 interrupt-names = "irq", "wakeup";
       +                 wakeup-source;
       +         };
       +@@ -484,6 +473,7 @@
       + 
       +         touchscreen_pins: pinmux_touchscreen_pins {
       +                 pinctrl-single,pins = <
       ++                OMAP4_IOPAD(0x180, PIN_OUTPUT | MUX_MODE3)
       +                 OMAP4_IOPAD(0x1a0, PIN_INPUT_PULLUP | MUX_MODE3)
       +                 >;
       +         };
       +-- 
       +2.15.1
   DIR diff --git a/extra/patches/linux-droid4-patches/0010-drm-omap-panel-dsi-cm-add-physical-size-support.patch b/extra/patches/linux-droid4-patches/0010-drm-omap-panel-dsi-cm-add-physical-size-support.patch
       t@@ -1,67 +0,0 @@
       -From 7561ba59ec083593412b8794dd3221fdca2ab49e Mon Sep 17 00:00:00 2001
       -From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       -Date: Mon, 24 Jul 2017 19:33:07 +0200
       -Subject: [PATCH 10/17] drm/omap: panel-dsi-cm: add physical size support
       -
       -Add support to load physical size information from DT using
       -the properties defined by the common panel binding.
       -
       -Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       ----
       - drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 19 +++++++++++++++++++
       - 1 file changed, 19 insertions(+)
       -
       -diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       -index b98ea9e..8459139 100644
       ---- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       -+++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       -@@ -66,6 +66,9 @@ struct panel_drv_data {
       - 
       -         bool use_dsi_backlight;
       - 
       -+        int width_mm;
       -+        int height_mm;
       -+
       -         struct omap_dsi_pin_config pin_config;
       - 
       -         /* runtime variables */
       -@@ -1163,6 +1166,15 @@ static int dsicm_check_timings(struct omap_dss_device *dssdev,
       -         return ret;
       - }
       - 
       -+static void dsicm_get_size(struct omap_dss_device *dssdev,
       -+                          unsigned int *width, unsigned int *height)
       -+{
       -+        struct panel_drv_data *ddata = to_panel_data(dssdev);
       -+
       -+        *width = ddata->width_mm;
       -+        *height = ddata->height_mm;
       -+}
       -+
       - static struct omap_dss_driver dsicm_ops = {
       -         .connect        = dsicm_connect,
       -         .disconnect        = dsicm_disconnect,
       -@@ -1175,6 +1187,7 @@ static struct omap_dss_driver dsicm_ops = {
       - 
       -         .get_timings        = dsicm_get_timings,
       -         .check_timings        = dsicm_check_timings,
       -+        .get_size        = dsicm_get_size,
       - 
       -         .enable_te        = dsicm_enable_te,
       -         .get_te                = dsicm_get_te,
       -@@ -1216,6 +1229,12 @@ static int dsicm_probe_of(struct platform_device *pdev)
       -                          "failed to get video timing, using defaults\n");
       -         }
       - 
       -+        ddata->width_mm = 0;
       -+        of_property_read_u32(node, "width-mm", &ddata->width_mm);
       -+
       -+        ddata->height_mm = 0;
       -+        of_property_read_u32(node, "height-mm", &ddata->height_mm);
       -+
       -         in = omapdss_of_find_source_for_first_ep(node);
       -         if (IS_ERR(in)) {
       -                 dev_err(&pdev->dev, "failed to find video source\n");
       --- 
       -2.1.4
       -
   DIR diff --git a/extra/patches/linux-droid4-patches/0011-drm-omap-panel-dsi-cm-add-external-backlight-support.patch b/extra/patches/linux-droid4-patches/0011-drm-omap-panel-dsi-cm-add-external-backlight-support.patch
       t@@ -1,247 +0,0 @@
       -From ed924fc352d6e2caa0d3fc1be1f1c65a35c9343b Mon Sep 17 00:00:00 2001
       -From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       -Date: Mon, 24 Jul 2017 19:33:08 +0200
       -Subject: [PATCH 11/17] drm/omap: panel-dsi-cm: add external backlight support
       -
       -Droid 4 has a command mode DSI panel, which does not have/use
       -DSI based backlight support. This adds proper support for this
       -using a backlight phandle property, which follows the common
       -panel binding.
       -
       -If no backlight phandle is found, it is assumed, that the
       -native backlight should be used instead. This is used by
       -the Nokia N950.
       -
       -Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       ----
       - drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 91 ++++++++++++++++---------
       - 1 file changed, 60 insertions(+), 31 deletions(-)
       -
       -diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       -index 8459139..d139bb7 100644
       ---- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       -+++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       -@@ -51,6 +51,7 @@ struct panel_drv_data {
       -         struct mutex lock;
       - 
       -         struct backlight_device *bldev;
       -+        struct backlight_device *extbldev;
       - 
       -         unsigned long        hw_guard_end;        /* next value of jiffies when we can
       -                                          * issue the next sleep in/out command
       -@@ -100,6 +101,30 @@ static int dsicm_panel_reset(struct panel_drv_data *ddata);
       - 
       - static void dsicm_ulps_work(struct work_struct *work);
       - 
       -+static void dsicm_bl_power(struct panel_drv_data *ddata, bool enable)
       -+{
       -+        struct backlight_device *backlight;
       -+
       -+        if (ddata->bldev)
       -+                backlight = ddata->bldev;
       -+        else if (ddata->extbldev)
       -+                backlight = ddata->extbldev;
       -+        else
       -+                return;
       -+
       -+        if (enable) {
       -+                backlight->props.fb_blank = FB_BLANK_UNBLANK;
       -+                backlight->props.state = ~(BL_CORE_FBBLANK | BL_CORE_SUSPENDED);
       -+                backlight->props.power = FB_BLANK_UNBLANK;
       -+        } else {
       -+                backlight->props.fb_blank = FB_BLANK_NORMAL;
       -+                backlight->props.power = FB_BLANK_POWERDOWN;
       -+                backlight->props.state |= BL_CORE_FBBLANK | BL_CORE_SUSPENDED;
       -+        }
       -+
       -+        backlight_update_status(backlight);
       -+}
       -+
       - static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec)
       - {
       -         ddata->hw_guard_wait = msecs_to_jiffies(guard_msec);
       -@@ -343,7 +368,7 @@ static int dsicm_bl_update_status(struct backlight_device *dev)
       - {
       -         struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
       -         struct omap_dss_device *in = ddata->in;
       --        int r;
       -+        int r = 0;
       -         int level;
       - 
       -         if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
       -@@ -364,8 +389,6 @@ static int dsicm_bl_update_status(struct backlight_device *dev)
       -                         r = dsicm_dcs_write_1(ddata, DCS_BRIGHTNESS, level);
       - 
       -                 in->ops.dsi->bus_unlock(in);
       --        } else {
       --                r = 0;
       -         }
       - 
       -         mutex_unlock(&ddata->lock);
       -@@ -819,6 +842,8 @@ static int dsicm_enable(struct omap_dss_device *dssdev)
       - 
       -         mutex_unlock(&ddata->lock);
       - 
       -+        dsicm_bl_power(ddata, true);
       -+
       -         return 0;
       - err:
       -         dev_dbg(&ddata->pdev->dev, "enable failed\n");
       -@@ -834,6 +859,8 @@ static void dsicm_disable(struct omap_dss_device *dssdev)
       - 
       -         dev_dbg(&ddata->pdev->dev, "disable\n");
       - 
       -+        dsicm_bl_power(ddata, false);
       -+
       -         mutex_lock(&ddata->lock);
       - 
       -         dsicm_cancel_ulps_work(ddata);
       -@@ -1198,6 +1225,7 @@ static struct omap_dss_driver dsicm_ops = {
       - static int dsicm_probe_of(struct platform_device *pdev)
       - {
       -         struct device_node *node = pdev->dev.of_node;
       -+        struct device_node *backlight;
       -         struct panel_drv_data *ddata = platform_get_drvdata(pdev);
       -         struct omap_dss_device *in;
       -         struct display_timing timing;
       -@@ -1259,14 +1287,25 @@ static int dsicm_probe_of(struct platform_device *pdev)
       - 
       -         ddata->in = in;
       - 
       --        /* TODO: ulps, backlight */
       -+        backlight = of_parse_phandle(node, "backlight", 0);
       -+        if (backlight) {
       -+                ddata->extbldev = of_find_backlight_by_node(backlight);
       -+                of_node_put(backlight);
       -+
       -+                if (!ddata->extbldev)
       -+                        return -EPROBE_DEFER;
       -+        } else {
       -+                /* assume native backlight support */
       -+                ddata->use_dsi_backlight = true;
       -+        }
       -+
       -+        /* TODO: ulps */
       - 
       -         return 0;
       - }
       - 
       - static int dsicm_probe(struct platform_device *pdev)
       - {
       --        struct backlight_properties props;
       -         struct panel_drv_data *ddata;
       -         struct backlight_device *bldev = NULL;
       -         struct device *dev = &pdev->dev;
       -@@ -1319,7 +1358,7 @@ static int dsicm_probe(struct platform_device *pdev)
       -                                 GPIOF_OUT_INIT_LOW, "taal rst");
       -                 if (r) {
       -                         dev_err(dev, "failed to request reset gpio\n");
       --                        return r;
       -+                        goto err_reg;
       -                 }
       -         }
       - 
       -@@ -1328,7 +1367,7 @@ static int dsicm_probe(struct platform_device *pdev)
       -                                 GPIOF_IN, "taal irq");
       -                 if (r) {
       -                         dev_err(dev, "GPIO request failed\n");
       --                        return r;
       -+                        goto err_reg;
       -                 }
       - 
       -                 r = devm_request_irq(dev, gpio_to_irq(ddata->ext_te_gpio),
       -@@ -1338,7 +1377,7 @@ static int dsicm_probe(struct platform_device *pdev)
       - 
       -                 if (r) {
       -                         dev_err(dev, "IRQ request failed\n");
       --                        return r;
       -+                        goto err_reg;
       -                 }
       - 
       -                 INIT_DEFERRABLE_WORK(&ddata->te_timeout_work,
       -@@ -1348,48 +1387,43 @@ static int dsicm_probe(struct platform_device *pdev)
       -         }
       - 
       -         ddata->workqueue = create_singlethread_workqueue("dsicm_wq");
       --        if (ddata->workqueue == NULL) {
       --                dev_err(dev, "can't create workqueue\n");
       --                return -ENOMEM;
       -+        if (!ddata->workqueue) {
       -+                r = -ENOMEM;
       -+                goto err_reg;
       -         }
       -         INIT_DELAYED_WORK(&ddata->ulps_work, dsicm_ulps_work);
       - 
       -         dsicm_hw_reset(ddata);
       - 
       -         if (ddata->use_dsi_backlight) {
       --                memset(&props, 0, sizeof(props));
       -+                struct backlight_properties props = { 0 };
       -                 props.max_brightness = 255;
       --
       -                 props.type = BACKLIGHT_RAW;
       --                bldev = backlight_device_register(dev_name(dev),
       --                                dev, ddata, &dsicm_bl_ops, &props);
       -+
       -+                bldev = devm_backlight_device_register(dev, dev_name(dev),
       -+                        dev, ddata, &dsicm_bl_ops, &props);
       -                 if (IS_ERR(bldev)) {
       -                         r = PTR_ERR(bldev);
       -                         goto err_bl;
       -                 }
       - 
       -                 ddata->bldev = bldev;
       --
       --                bldev->props.fb_blank = FB_BLANK_UNBLANK;
       --                bldev->props.power = FB_BLANK_UNBLANK;
       --                bldev->props.brightness = 255;
       --
       --                dsicm_bl_update_status(bldev);
       -         }
       - 
       -         r = sysfs_create_group(&dev->kobj, &dsicm_attr_group);
       -         if (r) {
       -                 dev_err(dev, "failed to create sysfs files\n");
       --                goto err_sysfs_create;
       -+                goto err_bl;
       -         }
       - 
       -         return 0;
       - 
       --err_sysfs_create:
       --        backlight_device_unregister(bldev);
       - err_bl:
       -         destroy_workqueue(ddata->workqueue);
       - err_reg:
       -+        if (ddata->extbldev)
       -+                put_device(&ddata->extbldev->dev);
       -+
       -         return r;
       - }
       - 
       -@@ -1397,7 +1431,6 @@ static int __exit dsicm_remove(struct platform_device *pdev)
       - {
       -         struct panel_drv_data *ddata = platform_get_drvdata(pdev);
       -         struct omap_dss_device *dssdev = &ddata->dssdev;
       --        struct backlight_device *bldev;
       - 
       -         dev_dbg(&pdev->dev, "remove\n");
       - 
       -@@ -1408,12 +1441,8 @@ static int __exit dsicm_remove(struct platform_device *pdev)
       - 
       -         sysfs_remove_group(&pdev->dev.kobj, &dsicm_attr_group);
       - 
       --        bldev = ddata->bldev;
       --        if (bldev != NULL) {
       --                bldev->props.power = FB_BLANK_POWERDOWN;
       --                dsicm_bl_update_status(bldev);
       --                backlight_device_unregister(bldev);
       --        }
       -+        if (ddata->extbldev)
       -+                put_device(&ddata->extbldev->dev);
       - 
       -         omap_dss_put_device(ddata->in);
       - 
       --- 
       -2.1.4
       -
   DIR diff --git a/extra/patches/linux-droid4-patches/0012-drm-omap-panel-dsi-cm-switch-to-gpiod.patch b/extra/patches/linux-droid4-patches/0012-drm-omap-panel-dsi-cm-switch-to-gpiod.patch
       t@@ -1,172 +0,0 @@
       -From d4b696beecee6b132c024e847dc54efee05f3ccc Mon Sep 17 00:00:00 2001
       -From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       -Date: Mon, 24 Jul 2017 19:33:09 +0200
       -Subject: [PATCH 12/17] drm/omap: panel-dsi-cm: switch to gpiod
       -
       -Use the new descriptor based GPIO API instead of
       -the legacy one, which results in cleaner code
       -with less lines of code.
       -
       -Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       ----
       - drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 74 +++++++++----------------
       - 1 file changed, 27 insertions(+), 47 deletions(-)
       -
       -diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       -index d139bb7..996991d 100644
       ---- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       -+++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
       -@@ -22,7 +22,6 @@
       - #include <linux/slab.h>
       - #include <linux/workqueue.h>
       - #include <linux/of_device.h>
       --#include <linux/of_gpio.h>
       - #include <linux/regulator/consumer.h>
       - 
       - #include <video/mipi_display.h>
       -@@ -59,8 +58,8 @@ struct panel_drv_data {
       -         unsigned long        hw_guard_wait;        /* max guard time in jiffies */
       - 
       -         /* panel HW configuration from DT or platform data */
       --        int reset_gpio;
       --        int ext_te_gpio;
       -+        struct gpio_desc *reset_gpio;
       -+        struct gpio_desc *ext_te_gpio;
       - 
       -         struct regulator *vpnl;
       -         struct regulator *vddi;
       -@@ -288,8 +287,8 @@ static int dsicm_enter_ulps(struct panel_drv_data *ddata)
       -         if (r)
       -                 goto err;
       - 
       --        if (gpio_is_valid(ddata->ext_te_gpio))
       --                disable_irq(gpio_to_irq(ddata->ext_te_gpio));
       -+        if (ddata->ext_te_gpio)
       -+                disable_irq(gpiod_to_irq(ddata->ext_te_gpio));
       - 
       -         in->ops.dsi->disable(in, false, true);
       - 
       -@@ -330,8 +329,8 @@ static int dsicm_exit_ulps(struct panel_drv_data *ddata)
       -                 goto err2;
       -         }
       - 
       --        if (gpio_is_valid(ddata->ext_te_gpio))
       --                enable_irq(gpio_to_irq(ddata->ext_te_gpio));
       -+        if (ddata->ext_te_gpio)
       -+                enable_irq(gpiod_to_irq(ddata->ext_te_gpio));
       - 
       -         dsicm_queue_ulps_work(ddata);
       - 
       -@@ -344,8 +343,8 @@ static int dsicm_exit_ulps(struct panel_drv_data *ddata)
       - 
       -         r = dsicm_panel_reset(ddata);
       -         if (!r) {
       --                if (gpio_is_valid(ddata->ext_te_gpio))
       --                        enable_irq(gpio_to_irq(ddata->ext_te_gpio));
       -+                if (ddata->ext_te_gpio)
       -+                        enable_irq(gpiod_to_irq(ddata->ext_te_gpio));
       -                 ddata->ulps_enabled = false;
       -         }
       - err1:
       -@@ -591,16 +590,13 @@ static const struct attribute_group dsicm_attr_group = {
       - 
       - static void dsicm_hw_reset(struct panel_drv_data *ddata)
       - {
       --        if (!gpio_is_valid(ddata->reset_gpio))
       --                return;
       --
       --        gpio_set_value(ddata->reset_gpio, 1);
       -+        gpiod_set_value(ddata->reset_gpio, 1);
       -         udelay(10);
       -         /* reset the panel */
       --        gpio_set_value(ddata->reset_gpio, 0);
       -+        gpiod_set_value(ddata->reset_gpio, 0);
       -         /* assert reset */
       -         udelay(10);
       --        gpio_set_value(ddata->reset_gpio, 1);
       -+        gpiod_set_value(ddata->reset_gpio, 1);
       -         /* wait after releasing reset */
       -         usleep_range(5000, 10000);
       - }
       -@@ -954,7 +950,7 @@ static int dsicm_update(struct omap_dss_device *dssdev,
       -         if (r)
       -                 goto err;
       - 
       --        if (ddata->te_enabled && gpio_is_valid(ddata->ext_te_gpio)) {
       -+        if (ddata->te_enabled && ddata->ext_te_gpio) {
       -                 schedule_delayed_work(&ddata->te_timeout_work,
       -                                 msecs_to_jiffies(250));
       -                 atomic_set(&ddata->do_update, 1);
       -@@ -1001,7 +997,7 @@ static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable)
       -         else
       -                 r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_TEAR_OFF);
       - 
       --        if (!gpio_is_valid(ddata->ext_te_gpio))
       -+        if (!ddata->ext_te_gpio)
       -                 in->ops.dsi->enable_te(in, enable);
       - 
       -         /* possible panel bug */
       -@@ -1229,21 +1225,21 @@ static int dsicm_probe_of(struct platform_device *pdev)
       -         struct panel_drv_data *ddata = platform_get_drvdata(pdev);
       -         struct omap_dss_device *in;
       -         struct display_timing timing;
       --        int gpio, err;
       -+        int err;
       - 
       --        gpio = of_get_named_gpio(node, "reset-gpios", 0);
       --        if (!gpio_is_valid(gpio)) {
       --                dev_err(&pdev->dev, "failed to parse reset gpio\n");
       --                return gpio;
       -+        ddata->reset_gpio = devm_gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW);
       -+        if (IS_ERR(ddata->reset_gpio)) {
       -+                err = PTR_ERR(ddata->reset_gpio);
       -+                dev_err(&pdev->dev, "reset gpio request failed: %d", err);
       -+                return err;
       -         }
       --        ddata->reset_gpio = gpio;
       - 
       --        gpio = of_get_named_gpio(node, "te-gpios", 0);
       --        if (gpio_is_valid(gpio) || gpio == -ENOENT) {
       --                ddata->ext_te_gpio = gpio;
       --        } else {
       --                dev_err(&pdev->dev, "failed to parse TE gpio\n");
       --                return gpio;
       -+        ddata->ext_te_gpio = devm_gpiod_get_optional(&pdev->dev, "te",
       -+                                                     GPIOD_IN);
       -+        if (IS_ERR(ddata->ext_te_gpio)) {
       -+                err = PTR_ERR(ddata->ext_te_gpio);
       -+                dev_err(&pdev->dev, "TE gpio request failed: %d", err);
       -+                return err;
       -         }
       - 
       -         err = of_get_display_timing(node, "panel-timing", &timing);
       -@@ -1353,24 +1349,8 @@ static int dsicm_probe(struct platform_device *pdev)
       - 
       -         atomic_set(&ddata->do_update, 0);
       - 
       --        if (gpio_is_valid(ddata->reset_gpio)) {
       --                r = devm_gpio_request_one(dev, ddata->reset_gpio,
       --                                GPIOF_OUT_INIT_LOW, "taal rst");
       --                if (r) {
       --                        dev_err(dev, "failed to request reset gpio\n");
       --                        goto err_reg;
       --                }
       --        }
       --
       --        if (gpio_is_valid(ddata->ext_te_gpio)) {
       --                r = devm_gpio_request_one(dev, ddata->ext_te_gpio,
       --                                GPIOF_IN, "taal irq");
       --                if (r) {
       --                        dev_err(dev, "GPIO request failed\n");
       --                        goto err_reg;
       --                }
       --
       --                r = devm_request_irq(dev, gpio_to_irq(ddata->ext_te_gpio),
       -+        if (ddata->ext_te_gpio) {
       -+                r = devm_request_irq(dev, gpiod_to_irq(ddata->ext_te_gpio),
       -                                 dsicm_te_isr,
       -                                 IRQF_TRIGGER_RISING,
       -                                 "taal vsync", ddata);
       --- 
       -2.1.4
       -
   DIR diff --git a/extra/patches/linux-droid4-patches/0013-ARM-dts-omap4-droid4-improve-LCD-description.patch b/extra/patches/linux-droid4-patches/0013-ARM-dts-omap4-droid4-improve-LCD-description.patch
       t@@ -1,39 +0,0 @@
       -From caebc72b95edde23e564f221f09d11148c8526fd Mon Sep 17 00:00:00 2001
       -From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       -Date: Mon, 24 Jul 2017 19:33:10 +0200
       -Subject: [PATCH 13/17] ARM: dts: omap4-droid4: improve LCD description
       -
       -This improves LCD support for the Droid 4.
       -
       -Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       ----
       - arch/arm/boot/dts/omap4-droid4-xt894.dts | 6 +++++-
       - 1 file changed, 5 insertions(+), 1 deletion(-)
       -
       -diff --git a/arch/arm/boot/dts/omap4-droid4-xt894.dts b/arch/arm/boot/dts/omap4-droid4-xt894.dts
       -index 8b93d37..4620b20 100644
       ---- a/arch/arm/boot/dts/omap4-droid4-xt894.dts
       -+++ b/arch/arm/boot/dts/omap4-droid4-xt894.dts
       -@@ -176,6 +176,10 @@
       -                 vddi-supply = <&lcd_regulator>;
       -                 reset-gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>;        /* gpio101 */
       - 
       -+                width-mm = <50>;
       -+                height-mm = <89>;
       -+                backlight = <&lcd_backlight>;
       -+
       -                 panel-timing {
       -                         clock-frequency = <0>;                /* Calculated by dsi */
       - 
       -@@ -345,7 +349,7 @@
       - 
       -                 enable-gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>;
       - 
       --                backlight {
       -+                lcd_backlight: backlight {
       -                         compatible = "ti,lm3532-backlight";
       - 
       -                         lcd {
       --- 
       -2.1.4
       -
   DIR diff --git a/extra/patches/linux-droid4-patches/0014-ARM-dts-n950-add-display-support.patch b/extra/patches/linux-droid4-patches/0014-ARM-dts-n950-add-display-support.patch
       t@@ -1,122 +0,0 @@
       -From e2e3c533158df1e24c6172a2d5f83d7a4b96db16 Mon Sep 17 00:00:00 2001
       -From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       -Date: Mon, 24 Jul 2017 19:33:11 +0200
       -Subject: [PATCH 14/17] ARM: dts: n950: add display support
       -
       -Add basic panel support for the Nokia N950. It must be tweaked a
       -little bit later, since the panel was built into the device
       -upside-down. Also the first 5 and the last 5 pixels are covered
       -by plastic.
       -
       -Signed-off-By: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       -Acked-by: Pavel Machek <pavel@ucw.cz>
       ----
       - arch/arm/boot/dts/omap3-n950.dts | 88 ++++++++++++++++++++++++++++++++++++++++
       - 1 file changed, 88 insertions(+)
       -
       -diff --git a/arch/arm/boot/dts/omap3-n950.dts b/arch/arm/boot/dts/omap3-n950.dts
       -index 646601a..ef70aae 100644
       ---- a/arch/arm/boot/dts/omap3-n950.dts
       -+++ b/arch/arm/boot/dts/omap3-n950.dts
       -@@ -51,6 +51,26 @@
       -         };
       - };
       - 
       -+&omap3_pmx_core {
       -+        dsi_pins: pinmux_dsi_pins {
       -+                pinctrl-single,pins = <
       -+                        OMAP3_CORE1_IOPAD(0x20dc, PIN_OUTPUT | MUX_MODE1) /* dsi_dx0 - data0+ */
       -+                        OMAP3_CORE1_IOPAD(0x20de, PIN_OUTPUT | MUX_MODE1) /* dsi_dy0 - data0- */
       -+                        OMAP3_CORE1_IOPAD(0x20e0, PIN_OUTPUT | MUX_MODE1) /* dsi_dx1 - clk+   */
       -+                        OMAP3_CORE1_IOPAD(0x20e2, PIN_OUTPUT | MUX_MODE1) /* dsi_dy1 - clk-   */
       -+                        OMAP3_CORE1_IOPAD(0x20e4, PIN_OUTPUT | MUX_MODE1) /* dsi_dx2 - data1+ */
       -+                        OMAP3_CORE1_IOPAD(0x20e6, PIN_OUTPUT | MUX_MODE1) /* dsi_dy2 - data1- */
       -+                >;
       -+        };
       -+
       -+        display_pins: pinmux_display_pins {
       -+                pinctrl-single,pins = <
       -+                        OMAP3_CORE1_IOPAD(0x20ca, PIN_INPUT | MUX_MODE4) /* gpio 62 - display te */
       -+                        OMAP3_CORE1_IOPAD(0x20fe, PIN_OUTPUT | MUX_MODE4) /* gpio 87 - display reset */
       -+                >;
       -+        };
       -+};
       -+
       - &i2c2 {
       -         smia_1: camera@10 {
       -                 compatible = "nokia,smia";
       -@@ -185,3 +205,71 @@
       -         st,max-limit-y = <32>;
       -         st,max-limit-z = <32>;
       - };
       -+
       -+&dss {
       -+        status = "ok";
       -+
       -+        vdda_video-supply = <&vdac>;
       -+};
       -+
       -+&dsi {
       -+        status = "ok";
       -+
       -+        pinctrl-names = "default";
       -+        pinctrl-0 = <&dsi_pins>;
       -+
       -+        vdd-supply = <&vpll2>;
       -+
       -+        port {
       -+                dsi_out_ep: endpoint {
       -+                        remote-endpoint = <&lcd0_in>;
       -+                        lanes = <2 3 0 1 4 5>;
       -+                };
       -+        };
       -+
       -+        lcd0: display {
       -+                compatible = "nokia,himalaya", "panel-dsi-cm";
       -+                label = "lcd0";
       -+
       -+                pinctrl-names = "default";
       -+                pinctrl-0 = <&display_pins>;
       -+
       -+                vpnl-supply = <&vmmc2>;
       -+                vddi-supply = <&vio>;
       -+
       -+                reset-gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;        /* 87 */
       -+                te-gpios = <&gpio2 30 GPIO_ACTIVE_HIGH>;        /* 62 */
       -+
       -+                width-mm = <49>; /* 48.960 mm */
       -+                height-mm = <88>; /* 88.128 mm */
       -+
       -+                /* TODO:
       -+                 * - panel is upside-down
       -+                 * - top + bottom 5px are not visible
       -+                 */
       -+                panel-timing {
       -+                        clock-frequency = <0>;          /* Calculated by dsi */
       -+
       -+                        hback-porch = <2>;
       -+                        hactive = <480>;
       -+                        hfront-porch = <0>;
       -+                        hsync-len = <2>;
       -+
       -+                        vback-porch = <1>;
       -+                        vactive = <864>;
       -+                        vfront-porch = <0>;
       -+                        vsync-len = <1>;
       -+
       -+                        hsync-active = <0>;
       -+                        vsync-active = <0>;
       -+                        de-active = <1>;
       -+                        pixelclk-active = <1>;
       -+                };
       -+
       -+                port {
       -+                        lcd0_in: endpoint {
       -+                                remote-endpoint = <&dsi_out_ep>;
       -+                        };
       -+                };
       -+        };
       -+};
       --- 
       -2.1.4
       -
   DIR diff --git a/extra/patches/linux-droid4-patches/0015-dt-bindings-backlight-add-ti-lmu-backlight-binding.patch b/extra/patches/linux-droid4-patches/0015-dt-bindings-backlight-add-ti-lmu-backlight-binding.patch
       t@@ -1,89 +0,0 @@
       -From ce34e7400299f5130f4f78bf3e894905373bc3c3 Mon Sep 17 00:00:00 2001
       -From: Milo Kim <Milo.Kim@ti.com>
       -Date: Mon, 17 Jul 2017 15:39:55 +0200
       -Subject: [PATCH 15/17] dt-bindings: backlight: add ti-lmu-backlight binding
       -
       -Add DT binding for ti-lmu devices.
       -
       -Signed-off-by: Milo Kim <milo.kim@ti.com>
       -Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       ----
       - .../bindings/leds/backlight/ti-lmu-backlight.txt   | 66 ++++++++++++++++++++++
       - 1 file changed, 66 insertions(+)
       - create mode 100644 Documentation/devicetree/bindings/leds/backlight/ti-lmu-backlight.txt
       -
       -diff --git a/Documentation/devicetree/bindings/leds/backlight/ti-lmu-backlight.txt b/Documentation/devicetree/bindings/leds/backlight/ti-lmu-backlight.txt
       -new file mode 100644
       -index 0000000..5fb1458
       ---- /dev/null
       -+++ b/Documentation/devicetree/bindings/leds/backlight/ti-lmu-backlight.txt
       -@@ -0,0 +1,66 @@
       -+TI LMU backlight device tree bindings
       -+
       -+Required property:
       -+ - compatible: Should be one of:
       -+        "ti,lm3532-backlight"
       -+        "ti,lm3631-backlight"
       -+        "ti,lm3632-backlight"
       -+        "ti,lm3633-backlight"
       -+        "ti,lm3695-backlight"
       -+        "ti,lm3697-backlight"
       -+
       -+Optional properties:
       -+ There are two backlight control mode. One is I2C, the other is PWM mode.
       -+ Following properties are only specified in PWM mode.
       -+ Please note that LMU backlight device can have only one PWM channel.
       -+
       -+ - pwms: OF device-tree PWM specification.
       -+ - pwm-names: a list of names for the PWM devices specified in the "pwms"
       -+              property.
       -+
       -+ For the PWM user nodes, please refer to [1].
       -+
       -+Child nodes:
       -+ LMU backlight is represented as sub-nodes of the TI LMU device [2].
       -+ So, LMU backlight should have more than one backlight child node.
       -+ Each node exactly matches with backlight control bank configuration.
       -+ Maximum numbers of child nodes depend on the device.
       -+
       -+ 1 = LM3631, LM3632, LM3695
       -+ 2 = LM3633, LM3697
       -+ 3 = LM3532
       -+
       -+ Required property of a child node:
       -+ - led-sources: List of enabled channels from 0 to 2.
       -+                Please refer to LED binding [3].
       -+                For output channels, please refer to the datasheets [4].
       -+
       -+ Optional properties of a child node:
       -+ - label: Backlight channel identification.
       -+          Please refer to LED binding [3].
       -+ - default-brightness-level: Backlight initial brightness value.
       -+                             Type is <u32>. It is set as soon as backlight
       -+                             device is created.
       -+                             0 ~ 2047 = LM3631, LM3632, LM3633, LM3695 and
       -+                                        LM3697
       -+                             0 ~ 255  = LM3532
       -+ - ramp-up-msec, ramp-down-msec: Light dimming effect properties.
       -+                                 Type is <u32>. Unit is millisecond.
       -+                                 0 ~ 65 msec    = LM3532
       -+                                 0 ~ 4000 msec  = LM3631
       -+                                 0 ~ 16000 msec = LM3633 and LM3697
       -+ - pwm-period: PWM period. Only valid in PWM brightness mode.
       -+               Type is <u32>. If this property is missing, then control
       -+               mode is set to I2C by default.
       -+
       -+Examples: Please refer to ti-lmu dt-bindings. [2].
       -+
       -+[1] ../pwm/pwm.txt
       -+[2] ../mfd/ti-lmu.txt
       -+[3] ../leds/common.txt
       -+[4] LM3532: http://www.ti.com/product/LM3532/datasheet
       -+    LM3631: http://www.ti.com/product/LM3631/datasheet
       -+    LM3632: http://www.ti.com/product/LM3632A/datasheet
       -+    LM3633: http://www.ti.com/product/LM3633/datasheet
       -+    LM3695: Datasheet is not opened yet, but only two strings are used.
       -+    LM3697: http://www.ti.com/product/LM3697/datasheet
       --- 
       -2.1.4
       -
   DIR diff --git a/extra/patches/linux-droid4-patches/0016-backlight-add-TI-LMU-backlight-driver.patch b/extra/patches/linux-droid4-patches/0016-backlight-add-TI-LMU-backlight-driver.patch
       t@@ -1,1222 +0,0 @@
       -From 102ad25228f75277c9f023a121c073c906034d13 Mon Sep 17 00:00:00 2001
       -From: Milo Kim <Milo.Kim@ti.com>
       -Date: Mon, 17 Jul 2017 15:39:56 +0200
       -Subject: [PATCH 16/17] backlight: add TI LMU backlight driver
       -
       -This is consolidated driver which supports the following
       -backlight devices: LM3532, LM3631, LM3632, LM3633, LM3695
       -and LM3697.
       -
       -Structure
       ----------
       -  It consists of two parts - core and data.
       -
       -  Core part supports features below.
       -    - Backlight subsystem control
       -    - Channel configuration from DT properties
       -    - Light dimming effect control: ramp up and down.
       -    - LMU fault monitor notifier handling
       -    - PWM brightness control
       -
       -  Data part describes device specific data.
       -    - Register value configuration for each LMU device
       -      : initialization, channel configuration, control mode, enable and
       -        brightness.
       -    - PWM action configuration
       -    - Light dimming effect table
       -    - Option for LMU fault monitor support
       -
       -Signed-off-by: Milo Kim <milo.kim@ti.com>
       -Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
       ----
       - drivers/video/backlight/Kconfig                 |   7 +
       - drivers/video/backlight/Makefile                |   3 +
       - drivers/video/backlight/ti-lmu-backlight-core.c | 729 ++++++++++++++++++++++++
       - drivers/video/backlight/ti-lmu-backlight-data.c | 304 ++++++++++
       - drivers/video/backlight/ti-lmu-backlight-data.h |  95 +++
       - 5 files changed, 1138 insertions(+)
       - create mode 100644 drivers/video/backlight/ti-lmu-backlight-core.c
       - create mode 100644 drivers/video/backlight/ti-lmu-backlight-data.c
       - create mode 100644 drivers/video/backlight/ti-lmu-backlight-data.h
       -
       -diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
       -index 4e1d2ad..c3cc833 100644
       ---- a/drivers/video/backlight/Kconfig
       -+++ b/drivers/video/backlight/Kconfig
       -@@ -427,6 +427,13 @@ config BACKLIGHT_SKY81452
       -           To compile this driver as a module, choose M here: the module will
       -           be called sky81452-backlight
       - 
       -+config BACKLIGHT_TI_LMU
       -+        tristate "Backlight driver for TI LMU"
       -+        depends on BACKLIGHT_CLASS_DEVICE && MFD_TI_LMU
       -+        help
       -+          Say Y to enable the backlight driver for TI LMU devices.
       -+          This supports LM3532, LM3631, LM3632, LM3633, LM3695 and LM3697.
       -+
       - config BACKLIGHT_TPS65217
       -         tristate "TPS65217 Backlight"
       -         depends on BACKLIGHT_CLASS_DEVICE && MFD_TPS65217
       -diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
       -index 8905129..c532e43 100644
       ---- a/drivers/video/backlight/Makefile
       -+++ b/drivers/video/backlight/Makefile
       -@@ -52,6 +52,9 @@ obj-$(CONFIG_BACKLIGHT_PM8941_WLED)        += pm8941-wled.o
       - obj-$(CONFIG_BACKLIGHT_PWM)                += pwm_bl.o
       - obj-$(CONFIG_BACKLIGHT_SAHARA)                += kb3886_bl.o
       - obj-$(CONFIG_BACKLIGHT_SKY81452)        += sky81452-backlight.o
       -+ti-lmu-backlight-objs                        := ti-lmu-backlight-core.o \
       -+                                           ti-lmu-backlight-data.o
       -+obj-$(CONFIG_BACKLIGHT_TI_LMU)                += ti-lmu-backlight.o
       - obj-$(CONFIG_BACKLIGHT_TOSA)                += tosa_bl.o
       - obj-$(CONFIG_BACKLIGHT_TPS65217)        += tps65217_bl.o
       - obj-$(CONFIG_BACKLIGHT_WM831X)                += wm831x_bl.o
       -diff --git a/drivers/video/backlight/ti-lmu-backlight-core.c b/drivers/video/backlight/ti-lmu-backlight-core.c
       -new file mode 100644
       -index 0000000..fca9508
       ---- /dev/null
       -+++ b/drivers/video/backlight/ti-lmu-backlight-core.c
       -@@ -0,0 +1,729 @@
       -+/*
       -+ * TI LMU (Lighting Management Unit) Backlight Driver
       -+ *
       -+ * Copyright 2015 Texas Instruments
       -+ *
       -+ * Author: Milo Kim <milo.kim@ti.com>
       -+ *
       -+ * This program is free software; you can redistribute it and/or modify
       -+ * it under the terms of the GNU General Public License version 2 as
       -+ * published by the Free Software Foundation.
       -+ */
       -+
       -+#include <linux/backlight.h>
       -+#include <linux/bitops.h>
       -+#include <linux/device.h>
       -+#include <linux/delay.h>
       -+#include <linux/err.h>
       -+#include <linux/kernel.h>
       -+#include <linux/mfd/ti-lmu.h>
       -+#include <linux/mfd/ti-lmu-register.h>
       -+#include <linux/module.h>
       -+#include <linux/notifier.h>
       -+#include <linux/of.h>
       -+#include <linux/of_device.h>
       -+#include <linux/platform_device.h>
       -+#include <linux/pwm.h>
       -+#include <linux/slab.h>
       -+
       -+#include "ti-lmu-backlight-data.h"
       -+
       -+enum ti_lmu_bl_ctrl_mode {
       -+        BL_REGISTER_BASED,
       -+        BL_PWM_BASED,
       -+};
       -+
       -+enum ti_lmu_bl_ramp_mode {
       -+        BL_RAMP_UP,
       -+        BL_RAMP_DOWN,
       -+};
       -+
       -+struct ti_lmu_bl;
       -+
       -+/**
       -+ * struct ti_lmu_bl_chip
       -+ *
       -+ * @dev:                Parent device pointer
       -+ * @lmu:                LMU structure.
       -+ *                        Used for register R/W access and notification.
       -+ * @cfg:                Device configuration data
       -+ * @lmu_bl:                Multiple backlight channels
       -+ * @num_backlights:        Number of backlight channels
       -+ * @nb:                        Notifier block for handling LMU fault monitor event
       -+ *
       -+ * One backlight chip can have multiple backlight channels, 'ti_lmu_bl'.
       -+ */
       -+struct ti_lmu_bl_chip {
       -+        struct device *dev;
       -+        struct ti_lmu *lmu;
       -+        const struct ti_lmu_bl_cfg *cfg;
       -+        struct ti_lmu_bl *lmu_bl;
       -+        int num_backlights;
       -+        struct notifier_block nb;
       -+};
       -+
       -+/**
       -+ * struct ti_lmu_bl
       -+ *
       -+ * @chip:                Pointer to parent backlight device
       -+ * @bl_dev:                Backlight subsystem device structure
       -+ * @bank_id:                Backlight bank ID
       -+ * @name:                Backlight channel name
       -+ * @mode:                Backlight control mode
       -+ * @led_sources:        Backlight output channel configuration.
       -+ *                        Bit mask is set on parsing DT.
       -+ * @default_brightness:        [Optional] Initial brightness value
       -+ * @ramp_up_msec:        [Optional] Ramp up time
       -+ * @ramp_down_msec:        [Optional] Ramp down time
       -+ * @pwm_period:                [Optional] PWM period
       -+ * @pwm:                [Optional] PWM subsystem structure
       -+ *
       -+ * Each backlight device has its own channel configuration.
       -+ * For chip control, parent chip data structure is used.
       -+ */
       -+struct ti_lmu_bl {
       -+        struct ti_lmu_bl_chip *chip;
       -+        struct backlight_device *bl_dev;
       -+
       -+        int bank_id;
       -+        const char *name;
       -+        enum ti_lmu_bl_ctrl_mode mode;
       -+        unsigned long led_sources;
       -+
       -+        unsigned int default_brightness;
       -+
       -+        /* Used for lighting effect */
       -+        unsigned int ramp_up_msec;
       -+        unsigned int ramp_down_msec;
       -+
       -+        /* Only valid in PWM mode */
       -+        unsigned int pwm_period;
       -+        struct pwm_device *pwm;
       -+};
       -+
       -+#define NUM_DUAL_CHANNEL                        2
       -+#define LMU_BACKLIGHT_DUAL_CHANNEL_USED                (BIT(0) | BIT(1))
       -+#define LMU_BACKLIGHT_11BIT_LSB_MASK                (BIT(0) | BIT(1) | BIT(2))
       -+#define LMU_BACKLIGHT_11BIT_MSB_SHIFT                3
       -+#define DEFAULT_PWM_NAME                        "lmu-backlight"
       -+
       -+static int ti_lmu_backlight_enable(struct ti_lmu_bl *lmu_bl, bool enable)
       -+{
       -+        struct ti_lmu_bl_chip *chip = lmu_bl->chip;
       -+        struct regmap *regmap = chip->lmu->regmap;
       -+        unsigned long enable_time = chip->cfg->reginfo->enable_usec;
       -+        u8 *reg = chip->cfg->reginfo->enable;
       -+        u8 mask = BIT(lmu_bl->bank_id);
       -+        u8 val = (enable == true) ? mask : 0;
       -+        int ret;
       -+
       -+        if (!reg)
       -+                return -EINVAL;
       -+
       -+        ret = regmap_update_bits(regmap, *reg, mask, val);
       -+        if (ret)
       -+                return ret;
       -+
       -+        if (enable_time > 0)
       -+                usleep_range(enable_time, enable_time + 100);
       -+
       -+        return 0;
       -+}
       -+
       -+static int ti_lmu_backlight_pwm_ctrl(struct ti_lmu_bl *lmu_bl, int brightness,
       -+                                      int max_brightness)
       -+{
       -+        struct pwm_state state = { };
       -+        int ret;
       -+
       -+        if (!lmu_bl->pwm) {
       -+                lmu_bl->pwm = devm_pwm_get(lmu_bl->chip->dev, DEFAULT_PWM_NAME);
       -+                if (IS_ERR(lmu_bl->pwm)) {
       -+                        ret = PTR_ERR(lmu_bl->pwm);
       -+                        lmu_bl->pwm = NULL;
       -+                        dev_err(lmu_bl->chip->dev,
       -+                                "Can not get PWM device, err: %d\n", ret);
       -+                        return ret;
       -+                }
       -+        }
       -+
       -+        pwm_init_state(lmu_bl->pwm, &state);
       -+        state.period = lmu_bl->pwm_period;
       -+        state.duty_cycle = brightness * state.period / max_brightness;
       -+
       -+        if (state.duty_cycle)
       -+                state.enabled = true;
       -+        else
       -+                state.enabled = false;
       -+
       -+        ret = pwm_apply_state(lmu_bl->pwm, &state);
       -+        if (ret)
       -+                dev_err(lmu_bl->chip->dev, "Failed to configure PWM: %d", ret);
       -+
       -+        return ret;
       -+}
       -+
       -+static int ti_lmu_backlight_update_brightness_register(struct ti_lmu_bl *lmu_bl,
       -+                                                       int brightness)
       -+{
       -+        const struct ti_lmu_bl_cfg *cfg = lmu_bl->chip->cfg;
       -+        const struct ti_lmu_bl_reg *reginfo = cfg->reginfo;
       -+        struct regmap *regmap = lmu_bl->chip->lmu->regmap;
       -+        u8 reg, val;
       -+        int ret;
       -+
       -+        /*
       -+         * Brightness register update
       -+         *
       -+         * 11 bit dimming: update LSB bits and write MSB byte.
       -+         *                   MSB brightness should be shifted.
       -+         *  8 bit dimming: write MSB byte.
       -+         */
       -+        if (cfg->max_brightness == MAX_BRIGHTNESS_11BIT) {
       -+                reg = reginfo->brightness_lsb[lmu_bl->bank_id];
       -+                ret = regmap_update_bits(regmap, reg,
       -+                                         LMU_BACKLIGHT_11BIT_LSB_MASK,
       -+                                         brightness);
       -+                if (ret)
       -+                        return ret;
       -+
       -+                val = brightness >> LMU_BACKLIGHT_11BIT_MSB_SHIFT;
       -+        } else {
       -+                val = brightness;
       -+        }
       -+
       -+        reg = reginfo->brightness_msb[lmu_bl->bank_id];
       -+        return regmap_write(regmap, reg, val);
       -+}
       -+
       -+static int ti_lmu_backlight_update_status(struct backlight_device *bl_dev)
       -+{
       -+        struct ti_lmu_bl *lmu_bl = bl_get_data(bl_dev);
       -+        const struct ti_lmu_bl_cfg *cfg = lmu_bl->chip->cfg;
       -+        int brightness = bl_dev->props.brightness;
       -+        bool enable = brightness > 0;
       -+        int ret;
       -+
       -+        if (bl_dev->props.state & BL_CORE_SUSPENDED)
       -+                brightness = 0;
       -+
       -+        ret = ti_lmu_backlight_enable(lmu_bl, enable);
       -+        if (ret)
       -+                return ret;
       -+
       -+        if (lmu_bl->mode == BL_PWM_BASED) {
       -+                ti_lmu_backlight_pwm_ctrl(lmu_bl, brightness,
       -+                                          bl_dev->props.max_brightness);
       -+
       -+                switch (cfg->pwm_action) {
       -+                case UPDATE_PWM_ONLY:
       -+                        /* No register update is required */
       -+                        return 0;
       -+                case UPDATE_MAX_BRT:
       -+                        /*
       -+                         * PWM can start from any non-zero code and dim down
       -+                         * to zero. So, brightness register should be updated
       -+                         * even in PWM mode.
       -+                         */
       -+                        if (brightness > 0)
       -+                                brightness = MAX_BRIGHTNESS_11BIT;
       -+                        else
       -+                                brightness = 0;
       -+                        break;
       -+                default:
       -+                        break;
       -+                }
       -+        }
       -+
       -+        return ti_lmu_backlight_update_brightness_register(lmu_bl, brightness);
       -+}
       -+
       -+static const struct backlight_ops lmu_backlight_ops = {
       -+        .options = BL_CORE_SUSPENDRESUME,
       -+        .update_status = ti_lmu_backlight_update_status,
       -+};
       -+
       -+static int ti_lmu_backlight_of_get_ctrl_bank(struct device_node *np,
       -+                                             struct ti_lmu_bl *lmu_bl)
       -+{
       -+        const char *name;
       -+        u32 *sources;
       -+        int num_channels = lmu_bl->chip->cfg->num_channels;
       -+        int ret, num_sources;
       -+
       -+        sources = devm_kzalloc(lmu_bl->chip->dev, num_channels, GFP_KERNEL);
       -+        if (!sources)
       -+                return -ENOMEM;
       -+
       -+        if (!of_property_read_string(np, "label", &name))
       -+                lmu_bl->name = name;
       -+        else
       -+                lmu_bl->name = np->name;
       -+
       -+        ret = of_property_count_u32_elems(np, "led-sources");
       -+        if (ret < 0 || ret > num_channels)
       -+                return -EINVAL;
       -+
       -+        num_sources = ret;
       -+        ret = of_property_read_u32_array(np, "led-sources", sources,
       -+                                         num_sources);
       -+        if (ret)
       -+                return ret;
       -+
       -+        lmu_bl->led_sources = 0;
       -+        while (num_sources--)
       -+                set_bit(sources[num_sources], &lmu_bl->led_sources);
       -+
       -+        return 0;
       -+}
       -+
       -+static void ti_lmu_backlight_of_get_light_properties(struct device_node *np,
       -+                                                     struct ti_lmu_bl *lmu_bl)
       -+{
       -+        of_property_read_u32(np, "default-brightness-level",
       -+                             &lmu_bl->default_brightness);
       -+
       -+        of_property_read_u32(np, "ramp-up-msec",  &lmu_bl->ramp_up_msec);
       -+        of_property_read_u32(np, "ramp-down-msec", &lmu_bl->ramp_down_msec);
       -+}
       -+
       -+static void ti_lmu_backlight_of_get_brightness_mode(struct device_node *np,
       -+                                                    struct ti_lmu_bl *lmu_bl)
       -+{
       -+        of_property_read_u32(np, "pwm-period", &lmu_bl->pwm_period);
       -+
       -+        if (lmu_bl->pwm_period > 0)
       -+                lmu_bl->mode = BL_PWM_BASED;
       -+        else
       -+                lmu_bl->mode = BL_REGISTER_BASED;
       -+}
       -+
       -+static int ti_lmu_backlight_of_create(struct ti_lmu_bl_chip *chip,
       -+                                      struct device_node *np)
       -+{
       -+        struct device_node *child;
       -+        struct ti_lmu_bl *lmu_bl, *each;
       -+        int ret, num_backlights;
       -+        int i = 0;
       -+
       -+        num_backlights = of_get_child_count(np);
       -+        if (num_backlights == 0) {
       -+                dev_err(chip->dev, "No backlight strings\n");
       -+                return -ENODEV;
       -+        }
       -+
       -+        /* One chip can have mulitple backlight strings */
       -+        lmu_bl = devm_kzalloc(chip->dev, sizeof(*lmu_bl) * num_backlights,
       -+                              GFP_KERNEL);
       -+        if (!lmu_bl)
       -+                return -ENOMEM;
       -+
       -+        /* Child is mapped to LMU backlight control bank */
       -+        for_each_child_of_node(np, child) {
       -+                each = lmu_bl + i;
       -+                each->bank_id = i;
       -+                each->chip = chip;
       -+
       -+                ret = ti_lmu_backlight_of_get_ctrl_bank(child, each);
       -+                if (ret) {
       -+                        of_node_put(np);
       -+                        return ret;
       -+                }
       -+
       -+                ti_lmu_backlight_of_get_light_properties(child, each);
       -+                ti_lmu_backlight_of_get_brightness_mode(child, each);
       -+
       -+                i++;
       -+        }
       -+
       -+        chip->lmu_bl = lmu_bl;
       -+        chip->num_backlights = num_backlights;
       -+
       -+        return 0;
       -+}
       -+
       -+static int ti_lmu_backlight_check_channel(struct ti_lmu_bl *lmu_bl)
       -+{
       -+        const struct ti_lmu_bl_cfg *cfg = lmu_bl->chip->cfg;
       -+        const struct ti_lmu_bl_reg *reginfo = lmu_bl->chip->cfg->reginfo;
       -+
       -+        if (!reginfo->brightness_msb)
       -+                return -EINVAL;
       -+
       -+        if (cfg->max_brightness > MAX_BRIGHTNESS_8BIT) {
       -+                if (!reginfo->brightness_lsb)
       -+                        return -EINVAL;
       -+        }
       -+
       -+        return 0;
       -+}
       -+
       -+static int ti_lmu_backlight_create_channel(struct ti_lmu_bl *lmu_bl)
       -+{
       -+        struct regmap *regmap = lmu_bl->chip->lmu->regmap;
       -+        const struct lmu_bl_reg_data *regdata =
       -+                lmu_bl->chip->cfg->reginfo->channel;
       -+        int num_channels = lmu_bl->chip->cfg->num_channels;
       -+        int i, ret;
       -+        u8 shift;
       -+
       -+        /*
       -+         * How to create backlight output channels:
       -+         *   Check 'led_sources' bit and update registers.
       -+         *
       -+         *   1) Dual channel configuration
       -+         *     The 1st register data is used for single channel.
       -+         *     The 2nd register data is used for dual channel.
       -+         *
       -+         *   2) Multiple channel configuration
       -+         *     Each register data is mapped to bank ID.
       -+         *     Bit shift operation is defined in channel registers.
       -+         *
       -+         * Channel register data consists of address, mask, value.
       -+         */
       -+
       -+        if (num_channels == NUM_DUAL_CHANNEL) {
       -+                if (lmu_bl->led_sources == LMU_BACKLIGHT_DUAL_CHANNEL_USED)
       -+                        regdata++;
       -+
       -+                return regmap_update_bits(regmap, regdata->reg, regdata->mask,
       -+                                          regdata->val);
       -+        }
       -+
       -+        for (i = 0; regdata && i < num_channels; i++) {
       -+                /*
       -+                 * Note that the result of regdata->val is shift bit.
       -+                 * The bank_id should be shifted for the channel configuration.
       -+                 */
       -+                if (test_bit(i, &lmu_bl->led_sources)) {
       -+                        shift = regdata->val;
       -+                        ret = regmap_update_bits(regmap, regdata->reg,
       -+                                                 regdata->mask,
       -+                                                 lmu_bl->bank_id << shift);
       -+                        if (ret)
       -+                                return ret;
       -+                }
       -+
       -+                regdata++;
       -+        }
       -+
       -+        return 0;
       -+}
       -+
       -+static int ti_lmu_backlight_update_ctrl_mode(struct ti_lmu_bl *lmu_bl)
       -+{
       -+        struct regmap *regmap = lmu_bl->chip->lmu->regmap;
       -+        const struct lmu_bl_reg_data *regdata =
       -+                lmu_bl->chip->cfg->reginfo->mode + lmu_bl->bank_id;
       -+        u8 val = regdata->val;
       -+
       -+        if (!regdata)
       -+                return 0;
       -+
       -+        /*
       -+         * Update PWM configuration register.
       -+         * If the mode is register based, then clear the bit.
       -+         */
       -+        if (lmu_bl->mode != BL_PWM_BASED)
       -+                val = 0;
       -+
       -+        return regmap_update_bits(regmap, regdata->reg, regdata->mask, val);
       -+}
       -+
       -+static int ti_lmu_backlight_convert_ramp_to_index(struct ti_lmu_bl *lmu_bl,
       -+                                                  enum ti_lmu_bl_ramp_mode mode)
       -+{
       -+        const int *ramp_table = lmu_bl->chip->cfg->ramp_table;
       -+        const int size = lmu_bl->chip->cfg->size_ramp;
       -+        unsigned int msec;
       -+        int i;
       -+
       -+        if (!ramp_table)
       -+                return -EINVAL;
       -+
       -+        switch (mode) {
       -+        case BL_RAMP_UP:
       -+                msec = lmu_bl->ramp_up_msec;
       -+                break;
       -+        case BL_RAMP_DOWN:
       -+                msec = lmu_bl->ramp_down_msec;
       -+                break;
       -+        default:
       -+                return -EINVAL;
       -+        }
       -+
       -+        if (msec <= ramp_table[0])
       -+                return 0;
       -+
       -+        if (msec > ramp_table[size - 1])
       -+                return size - 1;
       -+
       -+        for (i = 1; i < size; i++) {
       -+                if (msec == ramp_table[i])
       -+                        return i;
       -+
       -+                /* Find an approximate index by looking up the table */
       -+                if (msec > ramp_table[i - 1] && msec < ramp_table[i]) {
       -+                        if (msec - ramp_table[i - 1] < ramp_table[i] - msec)
       -+                                return i - 1;
       -+                        else
       -+                                return i;
       -+                }
       -+        }
       -+
       -+        return -EINVAL;
       -+}
       -+
       -+static int ti_lmu_backlight_set_ramp(struct ti_lmu_bl *lmu_bl)
       -+{
       -+        struct regmap *regmap = lmu_bl->chip->lmu->regmap;
       -+        const struct ti_lmu_bl_reg *reginfo = lmu_bl->chip->cfg->reginfo;
       -+        int offset = reginfo->ramp_reg_offset;
       -+        int i, ret, index;
       -+        struct lmu_bl_reg_data regdata;
       -+
       -+        for (i = BL_RAMP_UP; i <= BL_RAMP_DOWN; i++) {
       -+                index = ti_lmu_backlight_convert_ramp_to_index(lmu_bl, i);
       -+                if (index > 0) {
       -+                        if (!reginfo->ramp)
       -+                                break;
       -+
       -+                        regdata = reginfo->ramp[i];
       -+                        if (lmu_bl->bank_id != 0)
       -+                                regdata.val += offset;
       -+
       -+                        /* regdata.val is shift bit */
       -+                        ret = regmap_update_bits(regmap, regdata.reg,
       -+                                                 regdata.mask,
       -+                                                 index << regdata.val);
       -+                        if (ret)
       -+                                return ret;
       -+                }
       -+        }
       -+
       -+        return 0;
       -+}
       -+
       -+static int ti_lmu_backlight_configure(struct ti_lmu_bl *lmu_bl)
       -+{
       -+        int ret;
       -+
       -+        ret = ti_lmu_backlight_check_channel(lmu_bl);
       -+        if (ret)
       -+                return ret;
       -+
       -+        ret = ti_lmu_backlight_create_channel(lmu_bl);
       -+        if (ret)
       -+                return ret;
       -+
       -+        ret = ti_lmu_backlight_update_ctrl_mode(lmu_bl);
       -+        if (ret)
       -+                return ret;
       -+
       -+        return ti_lmu_backlight_set_ramp(lmu_bl);
       -+}
       -+
       -+static int ti_lmu_backlight_init(struct ti_lmu_bl_chip *chip)
       -+{
       -+        struct regmap *regmap = chip->lmu->regmap;
       -+        const struct lmu_bl_reg_data *regdata =
       -+                chip->cfg->reginfo->init;
       -+        int num_init = chip->cfg->reginfo->num_init;
       -+        int i, ret;
       -+
       -+        for (i = 0; regdata && i < num_init; i++) {
       -+                ret = regmap_update_bits(regmap, regdata->reg, regdata->mask,
       -+                                         regdata->val);
       -+                if (ret)
       -+                        return ret;
       -+
       -+                regdata++;
       -+        }
       -+
       -+        return 0;
       -+}
       -+
       -+static int ti_lmu_backlight_reload(struct ti_lmu_bl_chip *chip)
       -+{
       -+        struct ti_lmu_bl *each;
       -+        int i, ret;
       -+
       -+        ret = ti_lmu_backlight_init(chip);
       -+        if (ret)
       -+                return ret;
       -+
       -+        for (i = 0; i < chip->num_backlights; i++) {
       -+                each = chip->lmu_bl + i;
       -+                ret = ti_lmu_backlight_configure(each);
       -+                if (ret)
       -+                        return ret;
       -+
       -+                ret = backlight_update_status(each->bl_dev);
       -+                if (ret)
       -+                        return ret;
       -+        }
       -+
       -+        return 0;
       -+}
       -+
       -+static int ti_lmu_backlight_add_device(struct device *dev,
       -+                                       struct ti_lmu_bl *lmu_bl)
       -+{
       -+        struct backlight_device *bl_dev;
       -+        struct backlight_properties props;
       -+
       -+        memset(&props, 0, sizeof(struct backlight_properties));
       -+        props.type = BACKLIGHT_PLATFORM;
       -+        props.brightness = lmu_bl->default_brightness;
       -+        props.max_brightness = lmu_bl->chip->cfg->max_brightness;
       -+
       -+        bl_dev = devm_backlight_device_register(dev, lmu_bl->name,
       -+                                                lmu_bl->chip->dev, lmu_bl,
       -+                                                &lmu_backlight_ops, &props);
       -+        if (IS_ERR(bl_dev))
       -+                return PTR_ERR(bl_dev);
       -+
       -+        lmu_bl->bl_dev = bl_dev;
       -+
       -+        return 0;
       -+}
       -+
       -+static struct ti_lmu_bl_chip *
       -+ti_lmu_backlight_register(struct device *dev, struct ti_lmu *lmu,
       -+                          const struct ti_lmu_bl_cfg *cfg)
       -+{
       -+        struct ti_lmu_bl_chip *chip;
       -+        struct ti_lmu_bl *each;
       -+        int i, ret;
       -+
       -+        if (!cfg) {
       -+                dev_err(dev, "Operation is not configured\n");
       -+                return ERR_PTR(-EINVAL);
       -+        }
       -+
       -+        chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
       -+        if (!chip)
       -+                return ERR_PTR(-ENOMEM);
       -+
       -+        chip->dev = dev;
       -+        chip->lmu = lmu;
       -+        chip->cfg = cfg;
       -+
       -+        ret = ti_lmu_backlight_of_create(chip, dev->of_node);
       -+        if (ret)
       -+                return ERR_PTR(ret);
       -+
       -+        ret = ti_lmu_backlight_init(chip);
       -+        if (ret) {
       -+                dev_err(dev, "Backlight init err: %d\n", ret);
       -+                return ERR_PTR(ret);
       -+        }
       -+
       -+        for (i = 0; i < chip->num_backlights; i++) {
       -+                each = chip->lmu_bl + i;
       -+
       -+                ret = ti_lmu_backlight_configure(each);
       -+                if (ret) {
       -+                        dev_err(dev, "Backlight config err: %d\n", ret);
       -+                        return ERR_PTR(ret);
       -+                }
       -+
       -+                ret = ti_lmu_backlight_add_device(dev, each);
       -+                if (ret) {
       -+                        dev_err(dev, "Backlight device err: %d\n", ret);
       -+                        return ERR_PTR(ret);
       -+                }
       -+
       -+                ret = backlight_update_status(each->bl_dev);
       -+                if (ret) {
       -+                        dev_err(dev, "Backlight update err: %d\n", ret);
       -+                        return ERR_PTR(ret);
       -+                }
       -+        }
       -+
       -+        return chip;
       -+}
       -+
       -+static void ti_lmu_backlight_unregister(struct ti_lmu_bl_chip *chip)
       -+{
       -+        struct ti_lmu_bl *each;
       -+        int i;
       -+
       -+        /* Turn off the brightness */
       -+        for (i = 0; i < chip->num_backlights; i++) {
       -+                each = chip->lmu_bl + i;
       -+                each->bl_dev->props.brightness = 0;
       -+                backlight_update_status(each->bl_dev);
       -+        }
       -+}
       -+
       -+static int ti_lmu_backlight_monitor_notifier(struct notifier_block *nb,
       -+                                             unsigned long action, void *unused)
       -+{
       -+        struct ti_lmu_bl_chip *chip = container_of(nb, struct ti_lmu_bl_chip,
       -+                                                   nb);
       -+
       -+        if (action == LMU_EVENT_MONITOR_DONE) {
       -+                if (ti_lmu_backlight_reload(chip))
       -+                        return NOTIFY_STOP;
       -+        }
       -+
       -+        return NOTIFY_OK;
       -+}
       -+
       -+static int ti_lmu_backlight_probe(struct platform_device *pdev)
       -+{
       -+        struct device *dev = &pdev->dev;
       -+        struct ti_lmu *lmu = dev_get_drvdata(dev->parent);
       -+        struct ti_lmu_bl_chip *chip;
       -+        int ret;
       -+
       -+        chip = ti_lmu_backlight_register(dev, lmu, &lmu_bl_cfg[pdev->id]);
       -+        if (IS_ERR(chip))
       -+                return PTR_ERR(chip);
       -+
       -+        /*
       -+         * Notifier callback is required because backlight device needs
       -+         * reconfiguration after fault detection procedure is done by
       -+         * ti-lmu-fault-monitor driver.
       -+         */
       -+        if (chip->cfg->fault_monitor_used) {
       -+                chip->nb.notifier_call = ti_lmu_backlight_monitor_notifier;
       -+                ret = blocking_notifier_chain_register(&chip->lmu->notifier,
       -+                                                       &chip->nb);
       -+                if (ret)
       -+                        return ret;
       -+        }
       -+
       -+        platform_set_drvdata(pdev, chip);
       -+
       -+        return 0;
       -+}
       -+
       -+static int ti_lmu_backlight_remove(struct platform_device *pdev)
       -+{
       -+        struct ti_lmu_bl_chip *chip = platform_get_drvdata(pdev);
       -+
       -+        if (chip->cfg->fault_monitor_used)
       -+                blocking_notifier_chain_unregister(&chip->lmu->notifier,
       -+                                                   &chip->nb);
       -+
       -+        ti_lmu_backlight_unregister(chip);
       -+
       -+        return 0;
       -+}
       -+
       -+static struct platform_driver ti_lmu_backlight_driver = {
       -+        .probe  = ti_lmu_backlight_probe,
       -+        .remove = ti_lmu_backlight_remove,
       -+        .driver = {
       -+                .name = "ti-lmu-backlight",
       -+        },
       -+};
       -+
       -+module_platform_driver(ti_lmu_backlight_driver)
       -+
       -+MODULE_DESCRIPTION("TI LMU Backlight Driver");
       -+MODULE_AUTHOR("Milo Kim");
       -+MODULE_LICENSE("GPL v2");
       -+MODULE_ALIAS("platform:ti-lmu-backlight");
       -diff --git a/drivers/video/backlight/ti-lmu-backlight-data.c b/drivers/video/backlight/ti-lmu-backlight-data.c
       -new file mode 100644
       -index 0000000..583136c
       ---- /dev/null
       -+++ b/drivers/video/backlight/ti-lmu-backlight-data.c
       -@@ -0,0 +1,304 @@
       -+/*
       -+ * TI LMU (Lighting Management Unit) Backlight Device Data
       -+ *
       -+ * Copyright 2015 Texas Instruments
       -+ *
       -+ * Author: Milo Kim <milo.kim@ti.com>
       -+ *
       -+ * This program is free software; you can redistribute it and/or modify
       -+ * it under the terms of the GNU General Public License version 2 as
       -+ * published by the Free Software Foundation.
       -+ */
       -+
       -+#include "ti-lmu-backlight-data.h"
       -+
       -+/* LM3532 */
       -+static const struct lmu_bl_reg_data lm3532_init_data[] = {
       -+        { LM3532_REG_ZONE_CFG_A, LM3532_ZONE_MASK, LM3532_ZONE_0 },
       -+        { LM3532_REG_ZONE_CFG_B, LM3532_ZONE_MASK, LM3532_ZONE_1 },
       -+        { LM3532_REG_ZONE_CFG_C, LM3532_ZONE_MASK, LM3532_ZONE_2 },
       -+};
       -+
       -+static const struct lmu_bl_reg_data lm3532_channel_data[] = {
       -+        { LM3532_REG_OUTPUT_CFG, LM3532_ILED1_CFG_MASK,
       -+          LM3532_ILED1_CFG_SHIFT },
       -+        { LM3532_REG_OUTPUT_CFG, LM3532_ILED2_CFG_MASK,
       -+          LM3532_ILED2_CFG_SHIFT },
       -+        { LM3532_REG_OUTPUT_CFG, LM3532_ILED3_CFG_MASK,
       -+          LM3532_ILED3_CFG_SHIFT },
       -+};
       -+
       -+static const struct lmu_bl_reg_data lm3532_mode_data[] = {
       -+        { LM3532_REG_PWM_A_CFG, LM3532_PWM_A_MASK, LM3532_PWM_ZONE_0 },
       -+        { LM3532_REG_PWM_B_CFG, LM3532_PWM_B_MASK, LM3532_PWM_ZONE_1 },
       -+        { LM3532_REG_PWM_C_CFG, LM3532_PWM_C_MASK, LM3532_PWM_ZONE_2 },
       -+};
       -+
       -+static const struct lmu_bl_reg_data lm3532_ramp_data[] = {
       -+        { LM3532_REG_RAMPUP, LM3532_RAMPUP_MASK, LM3532_RAMPUP_SHIFT },
       -+        { LM3532_REG_RAMPDN, LM3532_RAMPDN_MASK, LM3532_RAMPDN_SHIFT },
       -+};
       -+
       -+static u8 lm3532_enable_reg = LM3532_REG_ENABLE;
       -+
       -+static u8 lm3532_brightness_regs[] = {
       -+        LM3532_REG_BRT_A,
       -+        LM3532_REG_BRT_B,
       -+        LM3532_REG_BRT_C,
       -+};
       -+
       -+static const struct ti_lmu_bl_reg lm3532_reg_info = {
       -+        .init                = lm3532_init_data,
       -+        .num_init        = ARRAY_SIZE(lm3532_init_data),
       -+        .channel        = lm3532_channel_data,
       -+        .mode                = lm3532_mode_data,
       -+        .ramp                = lm3532_ramp_data,
       -+        .enable                = &lm3532_enable_reg,
       -+        .brightness_msb        = lm3532_brightness_regs,
       -+};
       -+
       -+/* LM3631 */
       -+static const struct lmu_bl_reg_data lm3631_init_data[] = {
       -+        { LM3631_REG_BRT_MODE, LM3631_MODE_MASK, LM3631_DEFAULT_MODE },
       -+        { LM3631_REG_BL_CFG, LM3631_MAP_MASK, LM3631_EXPONENTIAL_MAP },
       -+};
       -+
       -+static const struct lmu_bl_reg_data lm3631_channel_data[] = {
       -+        { LM3631_REG_BL_CFG, LM3631_BL_CHANNEL_MASK, LM3631_BL_SINGLE_CHANNEL },
       -+        { LM3631_REG_BL_CFG, LM3631_BL_CHANNEL_MASK, LM3631_BL_DUAL_CHANNEL },
       -+};
       -+
       -+static const struct lmu_bl_reg_data lm3631_ramp_data[] = {
       -+        { LM3631_REG_SLOPE, LM3631_SLOPE_MASK, LM3631_SLOPE_SHIFT },
       -+};
       -+
       -+static u8 lm3631_enable_reg = LM3631_REG_DEVCTRL;
       -+static u8 lm3631_brightness_msb_reg = LM3631_REG_BRT_MSB;
       -+static u8 lm3631_brightness_lsb_reg = LM3631_REG_BRT_LSB;
       -+
       -+static const struct ti_lmu_bl_reg lm3631_reg_info = {
       -+        .init                = lm3631_init_data,
       -+        .num_init        = ARRAY_SIZE(lm3631_init_data),
       -+        .channel        = lm3631_channel_data,
       -+        .ramp                = lm3631_ramp_data,
       -+        .enable                = &lm3631_enable_reg,
       -+        .brightness_msb        = &lm3631_brightness_msb_reg,
       -+        .brightness_lsb        = &lm3631_brightness_lsb_reg,
       -+};
       -+
       -+/* LM3632 */
       -+static const struct lmu_bl_reg_data lm3632_init_data[] = {
       -+        { LM3632_REG_CONFIG1, LM3632_OVP_MASK, LM3632_OVP_25V },
       -+        { LM3632_REG_CONFIG2, LM3632_SWFREQ_MASK, LM3632_SWFREQ_1MHZ },
       -+};
       -+
       -+static const struct lmu_bl_reg_data lm3632_channel_data[] = {
       -+        { LM3632_REG_ENABLE, LM3632_BL_CHANNEL_MASK, LM3632_BL_SINGLE_CHANNEL },
       -+        { LM3632_REG_ENABLE, LM3632_BL_CHANNEL_MASK, LM3632_BL_DUAL_CHANNEL },
       -+};
       -+
       -+static const struct lmu_bl_reg_data lm3632_mode_data[] = {
       -+        { LM3632_REG_IO_CTRL, LM3632_PWM_MASK, LM3632_PWM_MODE },
       -+};
       -+
       -+static u8 lm3632_enable_reg = LM3632_REG_ENABLE;
       -+static u8 lm3632_brightness_msb_reg = LM3632_REG_BRT_MSB;
       -+static u8 lm3632_brightness_lsb_reg = LM3632_REG_BRT_LSB;
       -+
       -+static const struct ti_lmu_bl_reg lm3632_reg_info = {
       -+        .init                = lm3632_init_data,
       -+        .num_init        = ARRAY_SIZE(lm3632_init_data),
       -+        .channel        = lm3632_channel_data,
       -+        .mode                = lm3632_mode_data,
       -+        .enable                = &lm3632_enable_reg,
       -+        .brightness_msb        = &lm3632_brightness_msb_reg,
       -+        .brightness_lsb        = &lm3632_brightness_lsb_reg,
       -+};
       -+
       -+/* LM3633 */
       -+static const struct lmu_bl_reg_data lm3633_init_data[] = {
       -+        { LM3633_REG_BOOST_CFG, LM3633_OVP_MASK, LM3633_OVP_40V },
       -+        { LM3633_REG_BL_RAMP_CONF, LM3633_BL_RAMP_MASK, LM3633_BL_RAMP_EACH },
       -+};
       -+
       -+static const struct lmu_bl_reg_data lm3633_channel_data[] = {
       -+        { LM3633_REG_HVLED_OUTPUT_CFG, LM3633_HVLED1_CFG_MASK,
       -+          LM3633_HVLED1_CFG_SHIFT },
       -+        { LM3633_REG_HVLED_OUTPUT_CFG, LM3633_HVLED2_CFG_MASK,
       -+          LM3633_HVLED2_CFG_SHIFT },
       -+        { LM3633_REG_HVLED_OUTPUT_CFG, LM3633_HVLED3_CFG_MASK,
       -+          LM3633_HVLED3_CFG_SHIFT },
       -+};
       -+
       -+static const struct lmu_bl_reg_data lm3633_mode_data[] = {
       -+        { LM3633_REG_PWM_CFG, LM3633_PWM_A_MASK, LM3633_PWM_A_MASK },
       -+        { LM3633_REG_PWM_CFG, LM3633_PWM_B_MASK, LM3633_PWM_B_MASK },
       -+};
       -+
       -+static const struct lmu_bl_reg_data lm3633_ramp_data[] = {
       -+        { LM3633_REG_BL0_RAMP, LM3633_BL_RAMPUP_MASK, LM3633_BL_RAMPUP_SHIFT },
       -+        { LM3633_REG_BL0_RAMP, LM3633_BL_RAMPDN_MASK, LM3633_BL_RAMPDN_SHIFT },
       -+};
       -+
       -+static u8 lm3633_enable_reg = LM3633_REG_ENABLE;
       -+
       -+static u8 lm3633_brightness_msb_regs[] = {
       -+        LM3633_REG_BRT_HVLED_A_MSB,
       -+        LM3633_REG_BRT_HVLED_B_MSB,
       -+};
       -+
       -+static u8 lm3633_brightness_lsb_regs[] = {
       -+        LM3633_REG_BRT_HVLED_A_LSB,
       -+        LM3633_REG_BRT_HVLED_B_LSB,
       -+};
       -+
       -+static const struct ti_lmu_bl_reg lm3633_reg_info = {
       -+        .init                 = lm3633_init_data,
       -+        .num_init         = ARRAY_SIZE(lm3633_init_data),
       -+        .channel         = lm3633_channel_data,
       -+        .mode                 = lm3633_mode_data,
       -+        .ramp                 = lm3633_ramp_data,
       -+        .ramp_reg_offset = 1, /* For LM3633_REG_BL1_RAMPUP/DN */
       -+        .enable                 = &lm3633_enable_reg,
       -+        .brightness_msb         = lm3633_brightness_msb_regs,
       -+        .brightness_lsb         = lm3633_brightness_lsb_regs,
       -+};
       -+
       -+/* LM3695 */
       -+static const struct lmu_bl_reg_data lm3695_init_data[] = {
       -+        { LM3695_REG_GP, LM3695_BRT_RW_MASK, LM3695_BRT_RW_MASK },
       -+};
       -+
       -+static const struct lmu_bl_reg_data lm3695_channel_data[] = {
       -+        { LM3695_REG_GP, LM3695_BL_CHANNEL_MASK, LM3695_BL_SINGLE_CHANNEL },
       -+        { LM3695_REG_GP, LM3695_BL_CHANNEL_MASK, LM3695_BL_DUAL_CHANNEL },
       -+};
       -+
       -+static u8 lm3695_enable_reg = LM3695_REG_GP;
       -+static u8 lm3695_brightness_msb_reg = LM3695_REG_BRT_MSB;
       -+static u8 lm3695_brightness_lsb_reg = LM3695_REG_BRT_LSB;
       -+
       -+static const struct ti_lmu_bl_reg lm3695_reg_info = {
       -+        .init                = lm3695_init_data,
       -+        .num_init        = ARRAY_SIZE(lm3695_init_data),
       -+        .channel        = lm3695_channel_data,
       -+        .enable                = &lm3695_enable_reg,
       -+        .enable_usec        = 600,
       -+        .brightness_msb        = &lm3695_brightness_msb_reg,
       -+        .brightness_lsb        = &lm3695_brightness_lsb_reg,
       -+};
       -+
       -+/* LM3697 */
       -+static const struct lmu_bl_reg_data lm3697_init_data[] = {
       -+        { LM3697_REG_RAMP_CONF, LM3697_RAMP_MASK, LM3697_RAMP_EACH },
       -+};
       -+
       -+static const struct lmu_bl_reg_data lm3697_channel_data[] = {
       -+        { LM3697_REG_HVLED_OUTPUT_CFG, LM3697_HVLED1_CFG_MASK,
       -+          LM3697_HVLED1_CFG_SHIFT },
       -+        { LM3697_REG_HVLED_OUTPUT_CFG, LM3697_HVLED2_CFG_MASK,
       -+          LM3697_HVLED2_CFG_SHIFT },
       -+        { LM3697_REG_HVLED_OUTPUT_CFG, LM3697_HVLED3_CFG_MASK,
       -+          LM3697_HVLED3_CFG_SHIFT },
       -+};
       -+
       -+static const struct lmu_bl_reg_data lm3697_mode_data[] = {
       -+        { LM3697_REG_PWM_CFG, LM3697_PWM_A_MASK, LM3697_PWM_A_MASK },
       -+        { LM3697_REG_PWM_CFG, LM3697_PWM_B_MASK, LM3697_PWM_B_MASK },
       -+};
       -+
       -+static const struct lmu_bl_reg_data lm3697_ramp_data[] = {
       -+        { LM3697_REG_BL0_RAMP, LM3697_RAMPUP_MASK, LM3697_RAMPUP_SHIFT },
       -+        { LM3697_REG_BL0_RAMP, LM3697_RAMPDN_MASK, LM3697_RAMPDN_SHIFT },
       -+};
       -+
       -+static u8 lm3697_enable_reg = LM3697_REG_ENABLE;
       -+
       -+static u8 lm3697_brightness_msb_regs[] = {
       -+        LM3697_REG_BRT_A_MSB,
       -+        LM3697_REG_BRT_B_MSB,
       -+};
       -+
       -+static u8 lm3697_brightness_lsb_regs[] = {
       -+        LM3697_REG_BRT_A_LSB,
       -+        LM3697_REG_BRT_B_LSB,
       -+};
       -+
       -+static const struct ti_lmu_bl_reg lm3697_reg_info = {
       -+        .init                 = lm3697_init_data,
       -+        .num_init         = ARRAY_SIZE(lm3697_init_data),
       -+        .channel         = lm3697_channel_data,
       -+        .mode                 = lm3697_mode_data,
       -+        .ramp                 = lm3697_ramp_data,
       -+        .ramp_reg_offset = 1, /* For LM3697_REG_BL1_RAMPUP/DN */
       -+        .enable                 = &lm3697_enable_reg,
       -+        .brightness_msb         = lm3697_brightness_msb_regs,
       -+        .brightness_lsb         = lm3697_brightness_lsb_regs,
       -+};
       -+
       -+static int lm3532_ramp_table[] = { 0, 1, 2, 4, 8, 16, 32, 65 };
       -+
       -+static int lm3631_ramp_table[] = {
       -+           0,   1,   2,    5,   10,   20,   50,  100,
       -+         250, 500, 750, 1000, 1500, 2000, 3000, 4000,
       -+};
       -+
       -+static int common_ramp_table[] = {
       -+           2, 250, 500, 1000, 2000, 4000, 8000, 16000,
       -+};
       -+
       -+#define LM3532_MAX_CHANNELS                3
       -+#define LM3631_MAX_CHANNELS                2
       -+#define LM3632_MAX_CHANNELS                2
       -+#define LM3633_MAX_CHANNELS                3
       -+#define LM3695_MAX_CHANNELS                2
       -+#define LM3697_MAX_CHANNELS                3
       -+
       -+const struct ti_lmu_bl_cfg lmu_bl_cfg[LMU_MAX_ID] = {
       -+        {
       -+                .reginfo                = &lm3532_reg_info,
       -+                .num_channels                = LM3532_MAX_CHANNELS,
       -+                .max_brightness                = MAX_BRIGHTNESS_8BIT,
       -+                .pwm_action                = UPDATE_PWM_AND_BRT_REGISTER,
       -+                .ramp_table                = lm3532_ramp_table,
       -+                .size_ramp                = ARRAY_SIZE(lm3532_ramp_table),
       -+        },
       -+        {
       -+                .reginfo                = &lm3631_reg_info,
       -+                .num_channels                = LM3631_MAX_CHANNELS,
       -+                .max_brightness                = MAX_BRIGHTNESS_11BIT,
       -+                .pwm_action                = UPDATE_PWM_ONLY,
       -+                .ramp_table                = lm3631_ramp_table,
       -+                .size_ramp                = ARRAY_SIZE(lm3631_ramp_table),
       -+        },
       -+        {
       -+                .reginfo                = &lm3632_reg_info,
       -+                .num_channels                = LM3632_MAX_CHANNELS,
       -+                .max_brightness                = MAX_BRIGHTNESS_11BIT,
       -+                .pwm_action                = UPDATE_PWM_ONLY,
       -+        },
       -+        {
       -+                .reginfo                = &lm3633_reg_info,
       -+                .num_channels                = LM3633_MAX_CHANNELS,
       -+                .max_brightness                = MAX_BRIGHTNESS_11BIT,
       -+                .pwm_action                = UPDATE_MAX_BRT,
       -+                .ramp_table                = common_ramp_table,
       -+                .size_ramp                = ARRAY_SIZE(common_ramp_table),
       -+                .fault_monitor_used        = true,
       -+        },
       -+        {
       -+                .reginfo                = &lm3695_reg_info,
       -+                .num_channels                = LM3695_MAX_CHANNELS,
       -+                .max_brightness                = MAX_BRIGHTNESS_11BIT,
       -+                .pwm_action                = UPDATE_PWM_AND_BRT_REGISTER,
       -+        },
       -+        {
       -+                .reginfo                = &lm3697_reg_info,
       -+                .num_channels                = LM3697_MAX_CHANNELS,
       -+                .max_brightness                = MAX_BRIGHTNESS_11BIT,
       -+                .pwm_action                = UPDATE_PWM_AND_BRT_REGISTER,
       -+                .ramp_table                = common_ramp_table,
       -+                .size_ramp                = ARRAY_SIZE(common_ramp_table),
       -+                .fault_monitor_used        = true,
       -+        },
       -+};
       -diff --git a/drivers/video/backlight/ti-lmu-backlight-data.h b/drivers/video/backlight/ti-lmu-backlight-data.h
       -new file mode 100644
       -index 0000000..c64e8e6
       ---- /dev/null
       -+++ b/drivers/video/backlight/ti-lmu-backlight-data.h
       -@@ -0,0 +1,95 @@
       -+/*
       -+ * TI LMU (Lighting Management Unit) Backlight Device Data Definitions
       -+ *
       -+ * Copyright 2015 Texas Instruments
       -+ *
       -+ * Author: Milo Kim <milo.kim@ti.com>
       -+ *
       -+ * This program is free software; you can redistribute it and/or modify
       -+ * it under the terms of the GNU General Public License version 2 as
       -+ * published by the Free Software Foundation.
       -+ */
       -+
       -+#ifndef __TI_LMU_BACKLIGHT_H__
       -+#define __TI_LMU_BACKLIGHT_H__
       -+
       -+#include <linux/mfd/ti-lmu.h>
       -+#include <linux/mfd/ti-lmu-register.h>
       -+
       -+#define MAX_BRIGHTNESS_8BIT                255
       -+#define MAX_BRIGHTNESS_11BIT                2047
       -+
       -+enum ti_lmu_bl_pwm_action {
       -+        /* Update PWM duty, no brightness register update is required */
       -+        UPDATE_PWM_ONLY,
       -+        /* Update not only duty but also brightness register */
       -+        UPDATE_PWM_AND_BRT_REGISTER,
       -+        /* Update max value in brightness registers */
       -+        UPDATE_MAX_BRT,
       -+};
       -+
       -+struct lmu_bl_reg_data {
       -+        u8 reg;
       -+        u8 mask;
       -+        u8 val;
       -+};
       -+
       -+/**
       -+ * struct ti_lmu_bl_reg
       -+ *
       -+ * @init:                Device initialization registers
       -+ * @num_init:                Numbers of initialization registers
       -+ * @channel:                Backlight channel configuration registers
       -+ * @mode:                Brightness control mode registers
       -+ * @ramp:                Ramp registers for lighting effect
       -+ * @ramp_reg_offset:        Ramp register offset.
       -+ *                        Only used for multiple ramp registers.
       -+ * @enable:                Enable control register address
       -+ * @enable_usec:        Delay time for updating enable register.
       -+ *                        Unit is microsecond.
       -+ * @brightness_msb:        Brightness MSB(Upper 8 bits) registers.
       -+ *                        Concatenated with LSB in 11 bit dimming mode.
       -+ *                        In 8 bit dimming, only MSB is used.
       -+ * @brightness_lsb:        Brightness LSB(Lower 3 bits) registers.
       -+ *                        Only valid in 11 bit dimming mode.
       -+ */
       -+struct ti_lmu_bl_reg {
       -+        const struct lmu_bl_reg_data *init;
       -+        int num_init;
       -+        const struct lmu_bl_reg_data *channel;
       -+        const struct lmu_bl_reg_data *mode;
       -+        const struct lmu_bl_reg_data *ramp;
       -+        int ramp_reg_offset;
       -+        u8 *enable;
       -+        unsigned long enable_usec;
       -+        u8 *brightness_msb;
       -+        u8 *brightness_lsb;
       -+};
       -+
       -+/**
       -+ * struct ti_lmu_bl_cfg
       -+ *
       -+ * @reginfo:                Device register configuration
       -+ * @num_channels:        Number of backlight channels
       -+ * @max_brightness:        Max brightness value of backlight device
       -+ * @pwm_action:                How to control brightness registers in PWM mode
       -+ * @ramp_table:                [Optional] Ramp time table for lighting effect.
       -+ *                        It's used for searching approximate register index.
       -+ * @size_ramp:                [Optional] Size of ramp table
       -+ * @fault_monitor_used:        [Optional] Set true if the device needs to handle
       -+ *                        LMU fault monitor event.
       -+ *
       -+ * This structure is used for device specific data configuration.
       -+ */
       -+struct ti_lmu_bl_cfg {
       -+        const struct ti_lmu_bl_reg *reginfo;
       -+        int num_channels;
       -+        int max_brightness;
       -+        enum ti_lmu_bl_pwm_action pwm_action;
       -+        int *ramp_table;
       -+        int size_ramp;
       -+        bool fault_monitor_used;
       -+};
       -+
       -+extern const struct ti_lmu_bl_cfg lmu_bl_cfg[LMU_MAX_ID];
       -+#endif
       --- 
       -2.1.4
       -
   DIR diff --git a/extra/patches/linux-droid4-patches/0017-droid4-hdmi-on-4.14-rc4.patch b/extra/patches/linux-droid4-patches/0017-droid4-hdmi-on-4.14-rc4.patch
       t@@ -1,102 +0,0 @@
       -From 4f23bc7bf13c779f3640a3bf68ce688a98d434b8 Mon Sep 17 00:00:00 2001
       -From: Tony Lindgren <tony@atomide.com>
       -Date: Wed, 25 Oct 2017 15:07:32 -0700
       -Subject: [PATCH 17/17] droid4 hdmi on 4.14-rc4+
       -
       -* Merlijn Wajer <merlijn@wizzup.org> [171025 14:54]:
       -> Hi,
       ->
       -> I have been trying to get HDMI to work on the Motorola Droid4, as I saw
       -> that it should be supported. When I enable DRM_OMAP, OMAP4_DSS_HDMI and
       -> DRM_OMAP_CONNECTOR_HDMI, I don't get any output on HDMI (Full config
       -> here [1], for Linux 4.14-rc4). I see this in dmesg (repeatedly) [2]:
       ->
       -> [   21.360321] of_get_named_gpiod_flags: parsed 'hpd-gpios' property of
       -> node '/connector[0]' - status (0)
       -> [   21.370147] connector-hdmi connector: failed to find video source
       ->
       -> My hunch is that perhaps something is missing in the device tree, but
       -> after looking for time in the omapdrm code I cannot figure it out. Am I
       -> perhaps missing some configuration options?
       ->
       -> I also do not seem to have any /dev/dri entries, although I did expect
       -> to see them.
       -
       -Hmm I've been using it a lot over past six months with lapdock with
       -typically updating to Linux next about once a week or every few weeks.
       -I'm just using pending LCD and backlight patches, and omap2plus_defconfig
       -with following patch. Maybe see if you're missing something from that
       -patch?
       -
       -Also Tomi pointed out earlier that n900 needed the analog tv module
       -loaded for LCD output.. I wonder if you need also the pending LCD
       -patches applied?
       -
       -Cheers,
       -
       -Tony
       -
       -> [1] http://sprunge.us/GIhC
       -> [2] http://sprunge.us/bXWf
       -
       -8< -------------------------
       ----
       - arch/arm/configs/omap2plus_defconfig | 38 ++++++++++++++++++++----------------
       - 1 file changed, 21 insertions(+), 17 deletions(-)
       -
       -diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
       -index 7b97200..59d8c14 100644
       ---- a/arch/arm/configs/omap2plus_defconfig
       -+++ b/arch/arm/configs/omap2plus_defconfig
       -@@ -318,27 +318,31 @@ CONFIG_V4L_PLATFORM_DRIVERS=y
       - CONFIG_VIDEO_OMAP3=m
       - # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
       - CONFIG_VIDEO_TVP5150=m
       -+CONFIG_DRM=m
       -+CONFIG_DRM_OMAP=m
       -+CONFIG_DRM_OMAP_NUM_CRTCS=2
       -+CONFIG_OMAP5_DSS_HDMI=y
       -+CONFIG_OMAP2_DSS_SDI=y
       -+CONFIG_OMAP2_DSS_DSI=y
       -+CONFIG_DRM_OMAP_ENCODER_OPA362=m
       -+CONFIG_DRM_OMAP_ENCODER_TFP410=m
       -+CONFIG_DRM_OMAP_ENCODER_TPD12S015=m
       -+CONFIG_DRM_OMAP_CONNECTOR_DVI=m
       -+CONFIG_DRM_OMAP_CONNECTOR_HDMI=m
       -+CONFIG_DRM_OMAP_CONNECTOR_ANALOG_TV=m
       -+CONFIG_DRM_OMAP_PANEL_DPI=m
       -+CONFIG_DRM_OMAP_PANEL_DSI_CM=m
       -+CONFIG_DRM_OMAP_PANEL_SONY_ACX565AKM=m
       -+CONFIG_DRM_OMAP_PANEL_LGPHILIPS_LB035Q02=m
       -+CONFIG_DRM_OMAP_PANEL_SHARP_LS037V7DW01=m
       -+CONFIG_DRM_OMAP_PANEL_TPO_TD028TTEC1=m
       -+CONFIG_DRM_OMAP_PANEL_TPO_TD043MTEA1=m
       -+CONFIG_DRM_OMAP_PANEL_NEC_NL8048HL11=m
       -+CONFIG_DRM_TILCDC=m
       - CONFIG_FB=y
       - CONFIG_FIRMWARE_EDID=y
       - CONFIG_FB_MODE_HELPERS=y
       - CONFIG_FB_TILEBLITTING=y
       --CONFIG_FB_OMAP2=m
       --CONFIG_FB_OMAP5_DSS_HDMI=y
       --CONFIG_FB_OMAP2_DSS_SDI=y
       --CONFIG_FB_OMAP2_DSS_DSI=y
       --CONFIG_FB_OMAP2_ENCODER_TFP410=m
       --CONFIG_FB_OMAP2_ENCODER_TPD12S015=m
       --CONFIG_FB_OMAP2_CONNECTOR_DVI=m
       --CONFIG_FB_OMAP2_CONNECTOR_HDMI=m
       --CONFIG_FB_OMAP2_CONNECTOR_ANALOG_TV=m
       --CONFIG_FB_OMAP2_PANEL_DPI=m
       --CONFIG_FB_OMAP2_PANEL_DSI_CM=m
       --CONFIG_FB_OMAP2_PANEL_SONY_ACX565AKM=m
       --CONFIG_FB_OMAP2_PANEL_LGPHILIPS_LB035Q02=m
       --CONFIG_FB_OMAP2_PANEL_SHARP_LS037V7DW01=m
       --CONFIG_FB_OMAP2_PANEL_TPO_TD028TTEC1=m
       --CONFIG_FB_OMAP2_PANEL_TPO_TD043MTEA1=m
       --CONFIG_FB_OMAP2_PANEL_NEC_NL8048HL11=m
       - CONFIG_BACKLIGHT_LCD_SUPPORT=y
       - CONFIG_LCD_CLASS_DEVICE=y
       - CONFIG_LCD_PLATFORM=y
       --- 
       -2.1.4
       -
   DIR diff --git a/extra/patches/linux-droid4-patches/README b/extra/patches/linux-droid4-patches/README
       t@@ -0,0 +1,61 @@
       +https://www.spinics.net/lists/linux-omap/msg141500.html
       +
       +Hi,
       +
       +These are the remaining patches from my previous patchset to get
       +Droid 4 (omap4) display working. The patches have been rebased to
       +current master branch from Torvalds (581e400ff935). Since N950
       +(omap3) is broken even with the workaround I moved it to the end,
       +so that it can be skipped.
       +
       +Working on Droid 4:
       + * Framebuffer Console, updated at 1Hz due to blinking cursor
       + * kmstest (static image)
       + * Display blanking
       + * Xorg with omap and modesetting driver
       + * No updates send when nothing needs to be sent
       + * Orientation DRM property is attached to the DSI panel
       +
       +Known issues:
       + * N950 (omap3) is broken. I have updated the omap3 fifo workaround,
       +   but it's not enough to fix omap3.
       + * N950 (and N9) has first and last few lines covered by plastic, so
       +   we should expose a smaller screen
       +
       +Changes since PATCHv1:
       + * Drop patches, that were queued by Tomi
       + * Rebase to current master
       + * Rework the omap3 workaround patch to only affect omap3
       + * Add orientation DRM property support
       +
       +-- Sebastian
       +
       +
       +Sebastian Reichel (8):
       +  drm/omap: add framedone interrupt support
       +  drm/omap: add manual update detection helper
       +  drm/omap: add support for manually updated displays
       +  dt-bindings: panel: common: document orientation property
       +  drm/omap: add support for orientation hints from display drivers
       +  drm/omap: panel-dsi-cm: add orientation support
       +  ARM: dts: omap4-droid4: Add LCD panel orientation property
       +  drm/omap: plane: update fifo size on ovl setup
       +
       + .../bindings/display/panel/panel-common.txt        |  12 ++
       + arch/arm/boot/dts/omap4-droid4-xt894.dts           |   3 +
       + drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c    |  13 ++
       + drivers/gpu/drm/omapdrm/dss/dispc.c                |  36 ++++-
       + drivers/gpu/drm/omapdrm/dss/omapdss.h              |   2 +
       + drivers/gpu/drm/omapdrm/omap_connector.c           |  18 ++-
       + drivers/gpu/drm/omapdrm/omap_connector.h           |   1 +
       + drivers/gpu/drm/omapdrm/omap_crtc.c                | 158 +++++++++++++++++++--
       + drivers/gpu/drm/omapdrm/omap_crtc.h                |   2 +
       + drivers/gpu/drm/omapdrm/omap_fb.c                  |  20 +++
       + drivers/gpu/drm/omapdrm/omap_irq.c                 |  24 ++++
       + drivers/gpu/drm/omapdrm/omap_irq.h                 |   1 +
       + include/dt-bindings/display/common.h               |  14 ++
       + 13 files changed, 294 insertions(+), 10 deletions(-)
       + create mode 100644 include/dt-bindings/display/common.h
       +
       +-- 
       +2.15.1