tRevert "Add 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 6b61bec7be1f2d7efee082c008b7cd5f1ac42432
DIR parent 7efcb3d202487652337722ac2fa40256933be3ef
HTML Author: parazyd <parazyd@dyne.org>
Date: Thu, 15 Feb 2018 20:40:01 +0100
Revert "Add and rebase sre's droid4 patches for linux 4.16-rc1."
This reverts commit 3f9238ed77bf41b1bbdde75b9d16fdd670b79c8c.
Diffstat:
A extra/patches/linux-droid4-patches… | 31 +++++++++++++++++++++++++++++++
D extra/patches/linux-droid4-patches… | 158 -------------------------------
A extra/patches/linux-droid4-patches… | 33 +++++++++++++++++++++++++++++++
D extra/patches/linux-droid4-patches… | 42 -------------------------------
A extra/patches/linux-droid4-patches… | 52 +++++++++++++++++++++++++++++++
D extra/patches/linux-droid4-patches… | 256 -------------------------------
A extra/patches/linux-droid4-patches… | 160 +++++++++++++++++++++++++++++++
D extra/patches/linux-droid4-patches… | 57 -------------------------------
A extra/patches/linux-droid4-patches… | 49 +++++++++++++++++++++++++++++++
D extra/patches/linux-droid4-patches… | 59 -------------------------------
A extra/patches/linux-droid4-patches… | 263 +++++++++++++++++++++++++++++++
D extra/patches/linux-droid4-patches… | 55 -------------------------------
A extra/patches/linux-droid4-patches… | 50 +++++++++++++++++++++++++++++++
D extra/patches/linux-droid4-patches… | 31 -------------------------------
A extra/patches/linux-droid4-patches… | 124 +++++++++++++++++++++++++++++++
D extra/patches/linux-droid4-patches… | 125 -------------------------------
A extra/patches/linux-droid4-patches… | 135 +++++++++++++++++++++++++++++++
D extra/patches/linux-droid4-patches… | 67 -------------------------------
A extra/patches/linux-droid4-patches… | 67 +++++++++++++++++++++++++++++++
A extra/patches/linux-droid4-patches… | 247 +++++++++++++++++++++++++++++++
A extra/patches/linux-droid4-patches… | 172 ++++++++++++++++++++++++++++++
A extra/patches/linux-droid4-patches… | 39 +++++++++++++++++++++++++++++++
A extra/patches/linux-droid4-patches… | 122 +++++++++++++++++++++++++++++++
A extra/patches/linux-droid4-patches… | 89 +++++++++++++++++++++++++++++++
A extra/patches/linux-droid4-patches… | 1222 +++++++++++++++++++++++++++++++
A extra/patches/linux-droid4-patches… | 102 +++++++++++++++++++++++++++++++
D extra/patches/linux-droid4-patches… | 61 -------------------------------
27 files changed, 2957 insertions(+), 911 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@@ -0,0 +1,31 @@
+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@@ -1,158 +0,0 @@
-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@@ -0,0 +1,33 @@
+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@@ -1,42 +0,0 @@
-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@@ -0,0 +1,52 @@
+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@@ -1,256 +0,0 @@
-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@@ -0,0 +1,160 @@
+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@@ -1,57 +0,0 @@
-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@@ -0,0 +1,49 @@
+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@@ -1,59 +0,0 @@
-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@@ -0,0 +1,263 @@
+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@@ -1,55 +0,0 @@
-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@@ -0,0 +1,50 @@
+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@@ -1,31 +0,0 @@
-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@@ -0,0 +1,124 @@
+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@@ -1,125 +0,0 @@
-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@@ -0,0 +1,135 @@
+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@@ -1,67 +0,0 @@
-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@@ -0,0 +1,67 @@
+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@@ -0,0 +1,247 @@
+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@@ -0,0 +1,172 @@
+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@@ -0,0 +1,39 @@
+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@@ -0,0 +1,122 @@
+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@@ -0,0 +1,89 @@
+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@@ -0,0 +1,1222 @@
+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@@ -0,0 +1,102 @@
+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@@ -1,61 +0,0 @@
-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