Remove pwclient and add patches to tree

This commit is contained in:
David Derby 2018-04-20 10:14:56 -05:00 committed by Ivan J
parent 6718f5d504
commit 4505896aba
20 changed files with 1836 additions and 748 deletions

View File

@ -39,20 +39,6 @@ custmodules=()
gitkernel="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git"
gitbranch="linux-4.16.y"
# patch series from linux-omap patchwork
# [PATCHv2 0/8] omapdrm: DSI command mode panel support
patchids=(
10207753 # [PATCHv2,1/8] drm/omap: add framedone interrupt support
10207763 # [PATCHv2,2/8] drm/omap: add manual update detection helper
10207759 # [PATCHv2,3/8] drm/omap: add support for manually updated displays
10207749 # [PATCHv2,4/8] dt-bindings: panel: common: document orientation property
10207733 # [PATCHv2,5/8] drm/omap: add support for orientation hints from display drivers
10207747 # [PATCHv2,6/8] drm/omap: panel-dsi-cm: add orientation support
10207755 # [PATCHv2,7/8] ARM: dts: omap4-droid4: Add LCD panel orientation property
10207743 # [PATCHv2,8/8] drm/omap: plane: update fifo size on ovl setup
)
pwclient=$R/extra/pwclient/pwclient
postbuild() {
fn postbuild
@ -77,11 +63,7 @@ build_kernel_${arch}() {
git checkout -- .
copy-kernel-config
notice "applying patches from patchwork"
cp $R/extra/pwclient/.pwclientrc ~
$pwclient git-am -p linux-omap $patchids
notice "applying addtional patches"
notice "applying patches"
_patchdir="$R/extra/patches/linux-n9-patches"
_patchset="$(find ${_patchdir} -name '*.patch' | sort)"
for i in "${=_patchset}"; do

View File

@ -39,20 +39,6 @@ custmodules=()
gitkernel="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git"
gitbranch="linux-4.16.y"
# patch series from linux-omap patchwork
# [PATCHv2 0/8] omapdrm: DSI command mode panel support
patchids=(
10207753 # [PATCHv2,1/8] drm/omap: add framedone interrupt support
10207763 # [PATCHv2,2/8] drm/omap: add manual update detection helper
10207759 # [PATCHv2,3/8] drm/omap: add support for manually updated displays
10207749 # [PATCHv2,4/8] dt-bindings: panel: common: document orientation property
10207733 # [PATCHv2,5/8] drm/omap: add support for orientation hints from display drivers
10207747 # [PATCHv2,6/8] drm/omap: panel-dsi-cm: add orientation support
10207755 # [PATCHv2,7/8] ARM: dts: omap4-droid4: Add LCD panel orientation property
10207743 # [PATCHv2,8/8] drm/omap: plane: update fifo size on ovl setup
)
pwclient=$R/extra/pwclient/pwclient
postbuild() {
fn postbuild
@ -77,11 +63,7 @@ build_kernel_${arch}() {
git checkout -- .
copy-kernel-config
notice "applying patches from patchwork"
cp $R/extra/pwclient/.pwclientrc ~
$pwclient git-am -p linux-omap $patchids
notice "applying addtional patches"
notice "applying patches"
_patchdir="$R/extra/patches/linux-n950-patches"
_patchset="$(find ${_patchdir} -name '*.patch' | sort)"
for i in "${=_patchset}"; do

View File

@ -0,0 +1,175 @@
From patchwork Thu Feb 8 18:30:28 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv2,1/8] drm/omap: add framedone interrupt support
From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
X-Patchwork-Id: 10207753
Message-Id: <20180208183035.8461-2-sebastian.reichel@collabora.co.uk>
To: Sebastian Reichel <sre@kernel.org>,
Tomi Valkeinen <tomi.valkeinen@ti.com>, Tony Lindgren <tony@atomide.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Hans de Goede <hdegoede@redhat.com>, Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Date: Thu, 8 Feb 2018 19:30:28 +0100
This prepares framedone interrupt handling for
manual display update support.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Tested-by: Tony Lindgren <tony@atomide.com>
---
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);

View File

@ -0,0 +1,59 @@
From patchwork Thu Feb 8 18:30:29 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv2,2/8] drm/omap: add manual update detection helper
From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
X-Patchwork-Id: 10207763
Message-Id: <20180208183035.8461-3-sebastian.reichel@collabora.co.uk>
To: Sebastian Reichel <sre@kernel.org>,
Tomi Valkeinen <tomi.valkeinen@ti.com>, Tony Lindgren <tony@atomide.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Hans de Goede <hdegoede@redhat.com>, Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Date: Thu, 8 Feb 2018 19:30:29 +0100
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>
Tested-by: Tony Lindgren <tony@atomide.com>
---
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__ */

View File

@ -0,0 +1,273 @@
From patchwork Thu Feb 8 18:30:30 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv2,3/8] drm/omap: add support for manually updated displays
From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
X-Patchwork-Id: 10207759
Message-Id: <20180208183035.8461-4-sebastian.reichel@collabora.co.uk>
To: Sebastian Reichel <sre@kernel.org>,
Tomi Valkeinen <tomi.valkeinen@ti.com>, Tony Lindgren <tony@atomide.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Hans de Goede <hdegoede@redhat.com>, Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Date: Thu, 8 Feb 2018 19:30:30 +0100
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>
Tested-by: Tony Lindgren <tony@atomide.com>
---
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,
};

View File

@ -0,0 +1,74 @@
From patchwork Thu Feb 8 18:30:31 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv2,
4/8] dt-bindings: panel: common: document orientation property
From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
X-Patchwork-Id: 10207749
Message-Id: <20180208183035.8461-5-sebastian.reichel@collabora.co.uk>
To: Sebastian Reichel <sre@kernel.org>,
Tomi Valkeinen <tomi.valkeinen@ti.com>, Tony Lindgren <tony@atomide.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Hans de Goede <hdegoede@redhat.com>, Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Date: Thu, 8 Feb 2018 19:30:31 +0100
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@collabora.co.uk>
---
.../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

View File

@ -0,0 +1,76 @@
From patchwork Thu Feb 8 18:30:32 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv2,
5/8] drm/omap: add support for orientation hints from display drivers
From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
X-Patchwork-Id: 10207733
Message-Id: <20180208183035.8461-6-sebastian.reichel@collabora.co.uk>
To: Sebastian Reichel <sre@kernel.org>,
Tomi Valkeinen <tomi.valkeinen@ti.com>, Tony Lindgren <tony@atomide.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Hans de Goede <hdegoede@redhat.com>, Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Date: Thu, 8 Feb 2018 19:30:32 +0100
This adds support for setting DRM panel orientation property
based on information from the display driver.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
---
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:

View File

@ -0,0 +1,71 @@
From patchwork Thu Feb 8 18:30:33 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv2,6/8] drm/omap: panel-dsi-cm: add orientation support
From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
X-Patchwork-Id: 10207747
Message-Id: <20180208183035.8461-7-sebastian.reichel@collabora.co.uk>
To: Sebastian Reichel <sre@kernel.org>,
Tomi Valkeinen <tomi.valkeinen@ti.com>, Tony Lindgren <tony@atomide.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Hans de Goede <hdegoede@redhat.com>, Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Date: Thu, 8 Feb 2018 19:30:33 +0100
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@collabora.co.uk>
---
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");

View File

@ -0,0 +1,48 @@
From patchwork Thu Feb 8 18:30:34 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv2,
7/8] ARM: dts: omap4-droid4: Add LCD panel orientation property
From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
X-Patchwork-Id: 10207755
Message-Id: <20180208183035.8461-8-sebastian.reichel@collabora.co.uk>
To: Sebastian Reichel <sre@kernel.org>,
Tomi Valkeinen <tomi.valkeinen@ti.com>, Tony Lindgren <tony@atomide.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Hans de Goede <hdegoede@redhat.com>, Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Date: Thu, 8 Feb 2018 19:30:34 +0100
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@collabora.co.uk>
---
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 */

View File

@ -0,0 +1,141 @@
From patchwork Thu Feb 8 18:30:35 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv2,8/8] drm/omap: plane: update fifo size on ovl setup
From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
X-Patchwork-Id: 10207743
Message-Id: <20180208183035.8461-9-sebastian.reichel@collabora.co.uk>
To: Sebastian Reichel <sre@kernel.org>,
Tomi Valkeinen <tomi.valkeinen@ti.com>, Tony Lindgren <tony@atomide.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Hans de Goede <hdegoede@redhat.com>, Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Date: Thu, 8 Feb 2018 19:30:35 +0100
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@collabora.co.uk>
---
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)

View File

@ -0,0 +1,175 @@
From patchwork Thu Feb 8 18:30:28 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv2,1/8] drm/omap: add framedone interrupt support
From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
X-Patchwork-Id: 10207753
Message-Id: <20180208183035.8461-2-sebastian.reichel@collabora.co.uk>
To: Sebastian Reichel <sre@kernel.org>,
Tomi Valkeinen <tomi.valkeinen@ti.com>, Tony Lindgren <tony@atomide.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Hans de Goede <hdegoede@redhat.com>, Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Date: Thu, 8 Feb 2018 19:30:28 +0100
This prepares framedone interrupt handling for
manual display update support.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Tested-by: Tony Lindgren <tony@atomide.com>
---
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);

View File

@ -0,0 +1,59 @@
From patchwork Thu Feb 8 18:30:29 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv2,2/8] drm/omap: add manual update detection helper
From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
X-Patchwork-Id: 10207763
Message-Id: <20180208183035.8461-3-sebastian.reichel@collabora.co.uk>
To: Sebastian Reichel <sre@kernel.org>,
Tomi Valkeinen <tomi.valkeinen@ti.com>, Tony Lindgren <tony@atomide.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Hans de Goede <hdegoede@redhat.com>, Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Date: Thu, 8 Feb 2018 19:30:29 +0100
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>
Tested-by: Tony Lindgren <tony@atomide.com>
---
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__ */

View File

@ -0,0 +1,273 @@
From patchwork Thu Feb 8 18:30:30 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv2,3/8] drm/omap: add support for manually updated displays
From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
X-Patchwork-Id: 10207759
Message-Id: <20180208183035.8461-4-sebastian.reichel@collabora.co.uk>
To: Sebastian Reichel <sre@kernel.org>,
Tomi Valkeinen <tomi.valkeinen@ti.com>, Tony Lindgren <tony@atomide.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Hans de Goede <hdegoede@redhat.com>, Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Date: Thu, 8 Feb 2018 19:30:30 +0100
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>
Tested-by: Tony Lindgren <tony@atomide.com>
---
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,
};

View File

@ -0,0 +1,74 @@
From patchwork Thu Feb 8 18:30:31 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv2,
4/8] dt-bindings: panel: common: document orientation property
From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
X-Patchwork-Id: 10207749
Message-Id: <20180208183035.8461-5-sebastian.reichel@collabora.co.uk>
To: Sebastian Reichel <sre@kernel.org>,
Tomi Valkeinen <tomi.valkeinen@ti.com>, Tony Lindgren <tony@atomide.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Hans de Goede <hdegoede@redhat.com>, Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Date: Thu, 8 Feb 2018 19:30:31 +0100
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@collabora.co.uk>
---
.../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

View File

@ -0,0 +1,76 @@
From patchwork Thu Feb 8 18:30:32 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv2,
5/8] drm/omap: add support for orientation hints from display drivers
From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
X-Patchwork-Id: 10207733
Message-Id: <20180208183035.8461-6-sebastian.reichel@collabora.co.uk>
To: Sebastian Reichel <sre@kernel.org>,
Tomi Valkeinen <tomi.valkeinen@ti.com>, Tony Lindgren <tony@atomide.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Hans de Goede <hdegoede@redhat.com>, Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Date: Thu, 8 Feb 2018 19:30:32 +0100
This adds support for setting DRM panel orientation property
based on information from the display driver.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
---
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:

View File

@ -0,0 +1,71 @@
From patchwork Thu Feb 8 18:30:33 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv2,6/8] drm/omap: panel-dsi-cm: add orientation support
From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
X-Patchwork-Id: 10207747
Message-Id: <20180208183035.8461-7-sebastian.reichel@collabora.co.uk>
To: Sebastian Reichel <sre@kernel.org>,
Tomi Valkeinen <tomi.valkeinen@ti.com>, Tony Lindgren <tony@atomide.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Hans de Goede <hdegoede@redhat.com>, Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Date: Thu, 8 Feb 2018 19:30:33 +0100
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@collabora.co.uk>
---
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");

View File

@ -0,0 +1,48 @@
From patchwork Thu Feb 8 18:30:34 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv2,
7/8] ARM: dts: omap4-droid4: Add LCD panel orientation property
From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
X-Patchwork-Id: 10207755
Message-Id: <20180208183035.8461-8-sebastian.reichel@collabora.co.uk>
To: Sebastian Reichel <sre@kernel.org>,
Tomi Valkeinen <tomi.valkeinen@ti.com>, Tony Lindgren <tony@atomide.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Hans de Goede <hdegoede@redhat.com>, Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Date: Thu, 8 Feb 2018 19:30:34 +0100
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@collabora.co.uk>
---
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 */

View File

@ -0,0 +1,141 @@
From patchwork Thu Feb 8 18:30:35 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv2,8/8] drm/omap: plane: update fifo size on ovl setup
From: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
X-Patchwork-Id: 10207743
Message-Id: <20180208183035.8461-9-sebastian.reichel@collabora.co.uk>
To: Sebastian Reichel <sre@kernel.org>,
Tomi Valkeinen <tomi.valkeinen@ti.com>, Tony Lindgren <tony@atomide.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Hans de Goede <hdegoede@redhat.com>, Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Date: Thu, 8 Feb 2018 19:30:35 +0100
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@collabora.co.uk>
---
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)

View File

@ -1,6 +0,0 @@
[options]
default=linux-omap
[linux-omap]
url= https://patchwork.kernel.org/xmlrpc/

View File

@ -1,704 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Patchwork command line client
# Copyright (C) 2008 Nate Case <ncase@xes-inc.com>
#
# This file is part of the Patchwork package.
#
# Patchwork is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Patchwork is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Patchwork; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from __future__ import print_function
import os
import sys
try:
import xmlrpclib
except ImportError:
# Python 3 has merged/renamed things.
import xmlrpc.client as xmlrpclib
import argparse
import string
import tempfile
import subprocess
import base64
try:
import ConfigParser
except ImportError:
# Python 3 has renamed things.
import configparser as ConfigParser
import shutil
import re
# Add a shim for Python 2's unicode() helper.
try:
unicode
except NameError:
# Python 3 does everything by unicode now.
unicode = str
# Default Patchwork remote XML-RPC server URL
# This script will check the PW_XMLRPC_URL environment variable
# for the URL to access. If that is unspecified, it will fallback to
# the hardcoded default value specified here.
DEFAULT_URL = "http://patchwork/xmlrpc/"
CONFIG_FILE = os.path.expanduser('~/.pwclientrc')
class Filter(object):
"""Filter for selecting patches."""
def __init__(self):
# These fields refer to specific objects, so they are special
# because we have to resolve them to IDs before passing the
# filter to the server
self.state = ""
self.project = ""
# The dictionary that gets passed to via XML-RPC
self.d = {}
def add(self, field, value):
if field == 'state':
self.state = value
elif field == 'project':
self.project = value
else:
# OK to add directly
self.d[field] = value
def resolve_ids(self, rpc):
"""Resolve State, Project, and Person IDs based on filter strings."""
if self.state != "":
id = state_id_by_name(rpc, self.state)
if id == 0:
sys.stderr.write("Note: No State found matching %s*, " \
"ignoring filter\n" % self.state)
else:
self.d['state_id'] = id
if self.project != None:
id = project_id_by_name(rpc, self.project)
if id == 0:
sys.stderr.write("Note: No Project found matching %s, " \
"ignoring filter\n" % self.project)
else:
self.d['project_id'] = id
def __str__(self):
"""Return human-readable description of the filter."""
return str(self.d)
class BasicHTTPAuthTransport(xmlrpclib.SafeTransport):
def __init__(self, username = None, password = None, use_https = False):
self.username = username
self.password = password
self.use_https = use_https
xmlrpclib.SafeTransport.__init__(self)
def authenticated(self):
return self.username != None and self.password != None
def send_host(self, connection, host):
xmlrpclib.Transport.send_host(self, connection, host)
if not self.authenticated():
return
credentials = '%s:%s' % (self.username, self.password)
auth = 'Basic ' + base64.encodestring(credentials).strip()
connection.putheader('Authorization', auth)
def make_connection(self, host):
if self.use_https:
fn = xmlrpclib.SafeTransport.make_connection
else:
fn = xmlrpclib.Transport.make_connection
return fn(self, host)
def project_id_by_name(rpc, linkname):
"""Given a project short name, look up the Project ID."""
if len(linkname) == 0:
return 0
projects = rpc.project_list(linkname, 0)
for project in projects:
if project['linkname'] == linkname:
return project['id']
return 0
def state_id_by_name(rpc, name):
"""Given a partial state name, look up the state ID."""
if len(name) == 0:
return 0
states = rpc.state_list(name, 0)
for state in states:
if state['name'].lower().startswith(name.lower()):
return state['id']
return 0
def person_ids_by_name(rpc, name):
"""Given a partial name or email address, return a list of the
person IDs that match."""
if len(name) == 0:
return []
people = rpc.person_list(name, 0)
return [x['id'] for x in people]
def list_patches(patches, format_str=None):
"""Dump a list of patches to stdout."""
if format_str:
format_field_re = re.compile("%{([a-z0-9_]+)}")
def patch_field(matchobj):
fieldname = matchobj.group(1)
if fieldname == "_msgid_":
# naive way to strip < and > from message-id
val = string.strip(str(patch["msgid"]), "<>")
else:
val = str(patch[fieldname])
return val
for patch in patches:
print(format_field_re.sub(patch_field, format_str))
else:
print("%-7s %-12s %s" % ("ID", "State", "Name"))
print("%-7s %-12s %s" % ("--", "-----", "----"))
for patch in patches:
print("%-7d %-12s %s" % (patch['id'], patch['state'], patch['name']))
def action_list(rpc, filter, submitter_str, delegate_str, format_str=None):
filter.resolve_ids(rpc)
if submitter_str != None:
ids = person_ids_by_name(rpc, submitter_str)
if len(ids) == 0:
sys.stderr.write("Note: Nobody found matching *%s*\n" % \
submitter_str)
else:
for id in ids:
person = rpc.person_get(id)
print('Patches submitted by %s <%s>:' %
(unicode(person['name']).encode('utf-8'),
unicode(person['email']).encode('utf-8')))
f = filter
f.add("submitter_id", id)
patches = rpc.patch_list(f.d)
list_patches(patches, format_str)
return
if delegate_str != None:
ids = person_ids_by_name(rpc, delegate_str)
if len(ids) == 0:
sys.stderr.write("Note: Nobody found matching *%s*\n" % \
delegate_str)
else:
for id in ids:
person = rpc.person_get(id)
print('Patches delegated to %s <%s>:' %
(person['name'], person['email']))
f = filter
f.add("delegate_id", id)
patches = rpc.patch_list(f.d)
list_patches(patches, format_str)
return
patches = rpc.patch_list(filter.d)
list_patches(patches, format_str)
def action_projects(rpc):
projects = rpc.project_list("", 0)
print("%-5s %-24s %s" % ("ID", "Name", "Description"))
print("%-5s %-24s %s" % ("--", "----", "-----------"))
for project in projects:
print("%-5d %-24s %s" % (project['id'], \
project['linkname'], \
project['name']))
def action_states(rpc):
states = rpc.state_list("", 0)
print("%-5s %s" % ("ID", "Name"))
print("%-5s %s" % ("--", "----"))
for state in states:
print("%-5d %s" % (state['id'], state['name']))
def action_info(rpc, patch_id):
patch = rpc.patch_get(patch_id)
s = "Information for patch id %d" % (patch_id)
print(s)
print('-' * len(s))
for key, value in sorted(patch.items()):
print("- %- 14s: %s" % (key, unicode(value).encode("utf-8")))
def action_get(rpc, patch_id):
patch = rpc.patch_get(patch_id)
s = rpc.patch_get_mbox(patch_id)
if patch == {} or len(s) == 0:
sys.stderr.write("Unable to get patch %d\n" % patch_id)
sys.exit(1)
base_fname = fname = os.path.basename(patch['filename'])
i = 0
while os.path.exists(fname):
fname = "%s.%d" % (base_fname, i)
i += 1
try:
f = open(fname, "w")
except:
sys.stderr.write("Unable to open %s for writing\n" % fname)
sys.exit(1)
try:
f.write(unicode(s).encode("utf-8"))
f.close()
print('Saved patch to %s' % fname)
except:
sys.stderr.write("Failed to write to %s\n" % fname)
sys.exit(1)
def action_apply(rpc, patch_id, apply_cmd=None):
patch = rpc.patch_get(patch_id)
if patch == {}:
sys.stderr.write("Error getting information on patch ID %d\n" % \
patch_id)
sys.exit(1)
if apply_cmd is None:
print('Applying patch #%d to current directory' % patch_id)
apply_cmd = ['patch', '-p1']
else:
print('Applying patch #%d using %s' %
(patch_id, repr(' '.join(apply_cmd))))
print('Description: %s' % patch['name'])
s = rpc.patch_get_mbox(patch_id)
if len(s) > 0:
proc = subprocess.Popen(apply_cmd, stdin = subprocess.PIPE)
proc.communicate(unicode(s).encode('utf-8'))
return proc.returncode
else:
sys.stderr.write("Error: No patch content found\n")
sys.exit(1)
def action_update_patch(rpc, patch_id, state = None, archived = None, commit = None):
patch = rpc.patch_get(patch_id)
if patch == {}:
sys.stderr.write("Error getting information on patch ID %d\n" % \
patch_id)
sys.exit(1)
params = {}
if state:
state_id = state_id_by_name(rpc, state)
if state_id == 0:
sys.stderr.write("Error: No State found matching %s*\n" % state)
sys.exit(1)
params['state'] = state_id
if commit:
params['commit_ref'] = commit
if archived:
params['archived'] = archived == 'yes'
success = False
try:
success = rpc.patch_set(patch_id, params)
except xmlrpclib.Fault as f:
sys.stderr.write("Error updating patch: %s\n" % f.faultString)
if not success:
sys.stderr.write("Patch not updated\n")
def patch_id_from_hash(rpc, project, hash):
try:
patch = rpc.patch_get_by_project_hash(project, hash)
except xmlrpclib.Fault:
# the server may not have the newer patch_get_by_project_hash function,
# so fall back to hash-only.
patch = rpc.patch_get_by_hash(hash)
if patch == {}:
sys.stderr.write("No patch has the hash provided\n")
sys.exit(1)
patch_id = patch['id']
# be super paranoid
try:
patch_id = int(patch_id)
except:
sys.stderr.write("Invalid patch ID obtained from server\n")
sys.exit(1)
return patch_id
auth_actions = ['update']
def main():
hash_parser = argparse.ArgumentParser(add_help=False)
hash_parser.add_argument(
'-h', metavar='HASH', dest='hash', action='store',
help='''Lookup by patch hash'''
)
hash_parser.add_argument(
'id', metavar='ID', nargs='*', action='store', type=int,
help='Patch ID',
)
hash_parser.add_argument(
'-p', metavar='PROJECT',
help='''Lookup patch in project'''
)
filter_parser = argparse.ArgumentParser(add_help=False)
filter_parser.add_argument(
'-s', metavar='STATE',
help='''Filter by patch state (e.g., 'New', 'Accepted', etc.)'''
)
filter_parser.add_argument(
'-a', choices=['yes','no'],
help='''Filter by patch archived state'''
)
filter_parser.add_argument(
'-p', metavar='PROJECT',
help='''Filter by project name (see 'projects' for list)'''
)
filter_parser.add_argument(
'-w', metavar='WHO',
help='''Filter by submitter (name, e-mail substring search)'''
)
filter_parser.add_argument(
'-d', metavar='WHO',
help='''Filter by delegate (name, e-mail substring search)'''
)
filter_parser.add_argument(
'-n', metavar='MAX#',
type=int,
help='''Restrict number of results'''
)
filter_parser.add_argument(
'-m', metavar='MESSAGEID',
help='''Filter by Message-Id'''
)
filter_parser.add_argument(
'-f', metavar='FORMAT',
help='''Print output in the given format. You can use tags matching '''
'''fields, e.g. %%{id}, %%{state}, or %%{msgid}.'''
)
filter_parser.add_argument(
'patch_name', metavar='STR', nargs='?',
help='substring to search for patches by name',
)
action_parser = argparse.ArgumentParser(
prog='pwclient',
epilog='Use \'pwclient <command> --help\' for more info',
)
subparsers = action_parser.add_subparsers(
title='Commands',
)
apply_parser = subparsers.add_parser(
'apply', parents=[hash_parser], conflict_handler='resolve',
help='''Apply a patch (in the current dir, using -p1)'''
)
apply_parser.set_defaults(subcmd='apply')
git_am_parser = subparsers.add_parser(
'git-am', parents=[hash_parser], conflict_handler='resolve',
help='''Apply a patch to current git branch using "git am".'''
)
git_am_parser.set_defaults(subcmd='git_am')
git_am_parser.add_argument(
'-s', '--signoff',
action='store_true',
help='''pass --signoff to git-am'''
)
get_parser = subparsers.add_parser(
'get', parents=[hash_parser], conflict_handler='resolve',
help='''Download a patch and save it locally'''
)
get_parser.set_defaults(subcmd='get')
info_parser = subparsers.add_parser(
'info', parents=[hash_parser], conflict_handler='resolve',
help='''Display patchwork info about a given patch ID'''
)
info_parser.set_defaults(subcmd='info')
projects_parser = subparsers.add_parser(
'projects',
help='''List all projects'''
)
projects_parser.set_defaults(subcmd='projects')
states_parser = subparsers.add_parser(
'states',
help='''Show list of potential patch states'''
)
states_parser.set_defaults(subcmd='states')
view_parser = subparsers.add_parser(
'view', parents=[hash_parser], conflict_handler='resolve',
help='''View a patch'''
)
view_parser.set_defaults(subcmd='view')
update_parser = subparsers.add_parser(
'update', parents=[hash_parser], conflict_handler='resolve',
help='''Update patch''',
epilog='''Using a COMMIT-REF allows for only one ID to be specified''',
)
update_parser.add_argument(
'-c', metavar='COMMIT-REF',
help='''commit reference hash'''
)
update_parser.add_argument(
'-s', metavar='STATE',
help='''Set patch state (e.g., 'Accepted', 'Superseded' etc.)'''
)
update_parser.add_argument(
'-a', choices=['yes', 'no'],
help='''Set patch archived state'''
)
update_parser.set_defaults(subcmd='update')
list_parser = subparsers.add_parser("list",
#aliases=['search'],
parents=[filter_parser],
help='''List patches, using the optional filters specified
below and an optional substring to search for patches
by name'''
)
list_parser.set_defaults(subcmd='list')
search_parser = subparsers.add_parser("search",
parents=[filter_parser],
help='''Alias for "list"'''
)
# Poor man's argparse aliases:
# We register the "search" parser but effectively use "list" for the
# help-text.
search_parser.set_defaults(subcmd='list')
if len(sys.argv) < 2:
action_parser.print_help()
sys.exit(0)
args = action_parser.parse_args()
args = dict(vars(args))
action = args.get('subcmd')
if args.get('hash') and len(args.get('id')):
# mimic mutual exclusive group
locals()[action + '_parser'].error(
"[-h HASH] and [ID [ID ...]] are mutually exlusive")
# set defaults
filt = Filter()
commit_str = None
url = DEFAULT_URL
archived_str = args.get('a')
state_str = args.get('s')
project_str = args.get('p')
submitter_str = args.get('w')
delegate_str = args.get('d')
format_str = args.get('f')
hash_str = args.get('hash')
patch_ids = args.get('id')
msgid_str = args.get('m')
if args.get('c'):
# update multiple IDs with a single commit-hash does not make sense
if action == 'update' and patch_ids and len(patch_ids) > 1:
update_parser.error("Declining update with COMMIT-REF on multiple IDs")
commit_str = args.get('c')
if state_str is None and archived_str is None and action == 'update':
update_parser.error('Must specify one or more update options (-a or -s)')
if args.get('n') != None:
try:
filt.add("max_count", args.get('n'))
except:
action_parser.error("Invalid maximum count '%s'" % args.get('n'))
do_signoff = args.get('signoff')
# grab settings from config files
config = ConfigParser.ConfigParser()
config.read([CONFIG_FILE])
if not config.has_section('options') and os.path.exists(CONFIG_FILE):
sys.stderr.write('~/.pwclientrc is in the old format. Migrating it...')
old_project = config.get('base','project')
new_config = ConfigParser.ConfigParser()
new_config.add_section('options')
new_config.set('options','default',old_project)
new_config.add_section(old_project)
new_config.set(old_project,'url',config.get('base','url'))
if config.has_option('auth', 'username'):
new_config.set(old_project,'username',config.get('auth','username'))
if config.has_option('auth', 'password'):
new_config.set(old_project,'password',config.get('auth','password'))
old_config_file = CONFIG_FILE + '.orig'
shutil.copy2(CONFIG_FILE,old_config_file)
with open(CONFIG_FILE, 'wb') as fd:
new_config.write(fd)
sys.stderr.write(' Done.\n')
sys.stderr.write('Your old ~/.pwclientrc was saved to %s\n' % old_config_file)
sys.stderr.write('and was converted to the new format. You may want to\n')
sys.stderr.write('inspect it before continuing.\n')
sys.exit(1)
if not project_str:
try:
project_str = config.get('options', 'default')
except:
action_parser.error("No default project configured in ~/.pwclientrc")
if not config.has_section(project_str):
sys.stderr.write('No section for project %s in ~/.pwclientrc\n' % project_str)
sys.exit(1)
if not config.has_option(project_str, 'url'):
sys.stderr.write('No URL for project %s in ~/.pwclientrc\n' % project_str)
sys.exit(1)
if not do_signoff and config.has_option('options', 'signoff'):
do_signoff = config.getboolean('options', 'signoff')
if not do_signoff and config.has_option(project_str, 'signoff'):
do_signoff = config.getboolean(project_str, 'signoff')
url = config.get(project_str, 'url')
transport = None
if action in auth_actions:
if config.has_option(project_str, 'username') and \
config.has_option(project_str, 'password'):
use_https = url.startswith('https')
transport = BasicHTTPAuthTransport( \
config.get(project_str, 'username'),
config.get(project_str, 'password'),
use_https)
else:
sys.stderr.write(("The %s action requires authentication, "
"but no username or password\nis configured\n") % action)
sys.exit(1)
if project_str:
filt.add("project", project_str)
if state_str:
filt.add("state", state_str)
if archived_str:
filt.add("archived", archived_str == 'yes')
if msgid_str:
filt.add("msgid", msgid_str)
try:
rpc = xmlrpclib.Server(url, transport = transport)
except:
sys.stderr.write("Unable to connect to %s\n" % url)
sys.exit(1)
# It should be safe to assume hash_str is not zero, but who knows..
if hash_str != None:
patch_ids = [patch_id_from_hash(rpc, project_str, hash_str)]
# helper for non_empty() to print correct helptext
h = locals()[action + '_parser']
# Require either hash_str or IDs for
def non_empty(h, patch_ids):
"""Error out if no patch IDs were specified"""
if patch_ids == None or len(patch_ids) < 1:
sys.stderr.write("Error: Missing Argument! " +
"Either [-h HASH] or [ID [ID ...]] are required\n")
if h:
h.print_help()
sys.exit(1)
return patch_ids
if action == 'list' or action == 'search':
if args.get('patch_name') != None:
filt.add("name__icontains", args.get('patch_name'))
action_list(rpc, filt, submitter_str, delegate_str, format_str)
elif action.startswith('project'):
action_projects(rpc)
elif action.startswith('state'):
action_states(rpc)
elif action == 'view':
pager = os.environ.get('PAGER')
if pager:
pager = subprocess.Popen(
pager.split(), stdin=subprocess.PIPE
)
if pager:
i = list()
for patch_id in non_empty(h, patch_ids):
s = rpc.patch_get_mbox(patch_id)
if len(s) > 0:
i.append(unicode(s).encode("utf-8"))
if len(i) > 0:
pager.communicate(input="\n".join(i))
pager.stdin.close()
else:
for patch_id in non_empty(h, patch_ids):
s = rpc.patch_get_mbox(patch_id)
if len(s) > 0:
print(unicode(s).encode("utf-8"))
elif action == 'info':
for patch_id in non_empty(h, patch_ids):
action_info(rpc, patch_id)
elif action == 'get':
for patch_id in non_empty(h, patch_ids):
action_get(rpc, patch_id)
elif action == 'apply':
for patch_id in non_empty(h, patch_ids):
ret = action_apply(rpc, patch_id)
if ret:
sys.stderr.write("Apply failed with exit status %d\n" % ret)
sys.exit(1)
elif action == 'git_am':
cmd = ['git', 'am']
if do_signoff:
cmd.append('-s')
for patch_id in non_empty(h, patch_ids):
ret = action_apply(rpc, patch_id, cmd)
if ret:
sys.stderr.write("'git am' failed with exit status %d\n" % ret)
sys.exit(1)
elif action == 'update':
for patch_id in non_empty(h, patch_ids):
action_update_patch(rpc, patch_id, state = state_str,
archived = archived_str, commit = commit_str
)
else:
sys.stderr.write("Unknown action '%s'\n" % action)
action_parser.print_help()
sys.exit(1)
if __name__ == "__main__":
main()