On BeagleBone Black if no HDMI monitor is connected and suspend
is requested a kernel panic will result:
root@am335x-evm:~# echo mem > /sys/power/state
[ 65.548710] PM: Syncing filesystems ... done.
[ 65.631311] Freezing user space processes ... (elapsed 0.006 seconds) done.
[ 65.648619] Freezing remaining freezable tasks ... (elapsed 0.005 seconds) done.
[ 65.833500] Unhandled fault: external abort on non-linefetch (0x1028) at 0xfa30e004
[ 65.841692] Internal error: : 1028 [#1] SMP ARM
<snip>
[ 66.105287] [<c03765f0>] (platform_pm_suspend) from [<c037b6d4>] (dpm_run_callback+0x34/0x70)
[ 66.114370] [<c037b6d4>] (dpm_run_callback) from [<c037ba84>] (__device_suspend+0x10c/0x2f4)
[ 66.123357] [<c037ba84>] (__device_suspend) from [<c037d004>] (dpm_suspend+0x58/0x218)
[ 66.131796] [<c037d004>] (dpm_suspend) from [<c008d948>] (suspend_devices_and_enter+0x9c/0x3c0)
[ 66.141055] [<c008d948>] (suspend_devices_and_enter) from [<c008de7c>] (pm_suspend+0x210/0x24c)
[ 66.150312] [<c008de7c>] (pm_suspend) from [<c008cabc>] (state_store+0x68/0xb8)
[ 66.158103] [<c008cabc>] (state_store) from [<c02e9654>] (kobj_attr_store+0x14/0x20)
[ 66.166355] [<c02e9654>] (kobj_attr_store) from [<c0185c70>] (sysfs_kf_write+0x4c/0x50)
[ 66.174883] [<c0185c70>] (sysfs_kf_write) from [<c018926c>] (kernfs_fop_write+0xb4/0x150)
[ 66.183598] [<c018926c>] (kernfs_fop_write) from [<c0122638>] (vfs_write+0xa8/0x180)
[ 66.191846] [<c0122638>] (vfs_write) from [<c01229f8>] (SyS_write+0x40/0x8c)
[ 66.199365] [<c01229f8>] (SyS_write) from [<c000e580>] (ret_fast_syscall+0x0/0x48)
[ 66.207426] Code: e595c210 e5932000 e59cc000 e08c2002 (e592c000)
This is because the lcdc module is not enabled when no monitor is detected
to save power. However the suspend handler just blindly tries to save the
lcdc state by copying out the pertinent registers. However module is off
so no good things happen when you try and access it.
This patch only saves off the registers if the module is enabled, and
then only restores the registers on resume if they were saved off during
suspend.
Signed-off-by: Darren Etheridge <detheridge@ti.com>
Tested-by: Dave Gerlach <d-gerlach@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Jyri Sarha <jsarha@ti.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Update tilcdc driver to set the state of the pins to:
- "default on resume
- "sleep" on suspend
By optionally putting the pins into sleep state in the suspend callback
we can accomplish two things.
- minimize current leakage from pins and thus save power,
- prevent the IP from driving pins output in an uncontrolled manner,
which may happen if the power domain drops the domain regulator.
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
Signed-off-by: Darren Etheridge <detheridge@ti.com>
Signed-off-by: Jyri Sarha <jsarha@ti.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Updating the tilcdc DRM driver code to calculate the LCD controller
pixel clock more accurately. Based on a suggested implementation by
Tomi Valkeinen.
The current code does not work correctly and produces wrong results
with many requested clock rates. It also oddly uses two different
clocks, a display pll clock and a divider clock (child of display
pll), instead of just using the clock coming to the lcdc.
This patch removes the use of the display pll clock, and rewrites the
code to calculate the clock rates. The idea is simply to request a
clock rate of pixelclock*2, as the LCD controller has an internal
divider which we set to 2.
Signed-off-by: Darren Etheridge <detheridge@ti.com>
[Rewrapped description]
Signed-off-by: Jyri Sarha <jsarha@ti.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Again since the drm core takes care of event unlinking/disarming this
is now just needless code.
v2: Fixup misplaced hunks.
Cc: Rob Clark <robdclark@gmail.com>
Acked-by: Daniel Stone <daniels@collabora.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com> (v1)
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1453756616-28942-13-git-send-email-daniel.vetter@ffwll.ch
The drm_fbdev_cma_init function always calls the
drm_helper_disable_unused_functions. Since it's part of the usual probe
process, all the drivers using that helper will end up having their encoder
and CRTC disable functions called at probe if their device has not been
reported as enabled.
This could be fixed by reading out from the registers the current state of
the device if it is enabled, but even that will not handle the case where
the device is actually disabled.
Moreover, the drivers using the atomic modesetting expect that their enable
and disable callback to be called when the device is already enabled or
disabled (respectively).
We can however fix this issue by moving the call to
drm_helper_disable_unused_functions out of drm_fbdev_cma_init and make the
drivers needing it (all the drivers calling drm_fbdev_cma_init and not
using the atomic modesetting) explicitly call it.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1452785109-6172-14-git-send-email-maxime.ripard@free-electrons.com
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Drivers shouldn't clobber the passed in addfb ioctl parameters.
i915 was doing just that. To prevent it from happening again,
pass the struct around as const, starting all the way from
internal_framebuffer_create().
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drm_vblank_count() returns the software counter. We should not pretend
it's the hw counter since we use the hw counter to figuere out what the
software counter value should be. So instead provide a new function
drm_vblank_no_hw_counter() for drivers that don't have a real hw
counter. The new function simply returns 0, which is about the only
thing it can do.
Cc: Vincent Abriou <vincent.abriou@st.com>
Cc: Thierry Reding <treding@nvidia.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Vincent Abriou <vincent.abriou@st.com>
[danvet: s/int pipe/unsigned int pipe/ to follow Thierry's interface
change.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This continues the pattern started in commit cc1ef118fc ("drm/irq:
Make pipe unsigned and name consistent"). This is applied to the public
APIs and driver callbacks, so pretty much all drivers need to be updated
to match the new prototypes.
Cc: Christian König <christian.koenig@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Inki Dae <inki.dae@samsung.com>
Cc: Jianwei Wang <jianwei.wang.chn@gmail.com>
Cc: Alison Wang <alison.wang@freescale.com>
Cc: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: David Airlie <airlied@linux.ie>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Ben Skeggs <bskeggs@redhat.com>
Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Mark Yao <mark.yao@rock-chips.com>
Cc: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Cc: Vincent Abriou <vincent.abriou@st.com>
Cc: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
tilcdc calls runtime PM get/put functions everywhere. Some of those
places will be called in irq context, crashing the driver.
As a quick fix, use pm_runtime_irq_safe() for tilcdc.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Signed-off-by: Jyri Sarha <jsarha@ti.com>
Add support for an external compontised DRM encoder. The external
encoder can be connected to tilcdc trough device tree graph binding.
The binding document for tilcdc has been updated. The current
implementation supports only tda998x encoder.
To be able to filter out the unsupported video modes the tilcdc driver
needs to hijack the external connectors helper functions. The tilcdc
installes new helper functions that are otherwise identical to
orignals, but the mode_valid() call-back check the mode first localy,
before calling the original call-back. The tilcdc dirver restores the
original helper functions before it is unbound from the external
device.
I got the idea and some lines of code from Jean-Francois Moine's
"drm/tilcdc: Change the interface with the tda998x driver"-patch.
Signed-off-by: Jyri Sarha <jsarha@ti.com>
Acked-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Remove tilcdc slave support for tda998x driver. The tilcdc slave
support would conflicts with componentized use of tda998x.
Signed-off-by: Jyri Sarha <jsarha@ti.com>
Acked-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Pull drm updates from Dave Airlie:
"Highlights:
- AMD KFD driver merge
This is the AMD HSA interface for exposing a lowlevel interface for
GPGPU use. They have an open source userspace built on top of this
interface, and the code looks as good as it was going to get out of
tree.
- Initial atomic modesetting work
The need for an atomic modesetting interface to allow userspace to
try and send a complete set of modesetting state to the driver has
arisen, and been suffering from neglect this past year. No more,
the start of the common code and changes for msm driver to use it
are in this tree. Ongoing work to get the userspace ioctl finished
and the code clean will probably wait until next kernel.
- DisplayID 1.3 and tiled monitor exposed to userspace.
Tiled monitor property is now exposed for userspace to make use of.
- Rockchip drm driver merged.
- imx gpu driver moved out of staging
Other stuff:
- core:
panel - MIPI DSI + new panels.
expose suggested x/y properties for virtual GPUs
- i915:
Initial Skylake (SKL) support
gen3/4 reset work
start of dri1/ums removal
infoframe tracking
fixes for lots of things.
- nouveau:
tegra k1 voltage support
GM204 modesetting support
GT21x memory reclocking work
- radeon:
CI dpm fixes
GPUVM improvements
Initial DPM fan control
- rcar-du:
HDMI support added
removed some support for old boards
slave encoder driver for Analog Devices adv7511
- exynos:
Exynos4415 SoC support
- msm:
a4xx gpu support
atomic helper conversion
- tegra:
iommu support
universal plane support
ganged-mode DSI support
- sti:
HDMI i2c improvements
- vmwgfx:
some late fixes.
- qxl:
use suggested x/y properties"
* 'drm-next' of git://people.freedesktop.org/~airlied/linux: (969 commits)
drm: sti: fix module compilation issue
drm/i915: save/restore GMBUS freq across suspend/resume on gen4
drm: sti: correctly cleanup CRTC and planes
drm: sti: add HQVDP plane
drm: sti: add cursor plane
drm: sti: enable auxiliary CRTC
drm: sti: fix delay in VTG programming
drm: sti: prepare sti_tvout to support auxiliary crtc
drm: sti: use drm_crtc_vblank_{on/off} instead of drm_vblank_{on/off}
drm: sti: fix hdmi avi infoframe
drm: sti: remove event lock while disabling vblank
drm: sti: simplify gdp code
drm: sti: clear all mixer control
drm: sti: remove gpio for HDMI hot plug detection
drm: sti: allow to change hdmi ddc i2c adapter
drm/doc: Document drm_add_modes_noedid() usage
drm/i915: Remove '& 0xffff' from the mask given to WA_REG()
drm/i915: Invert the mask and val arguments in wa_add() and WA_REG()
drm: Zero out DRM object memory upon cleanup
drm/i915/bdw: Fix the write setting up the WIZ hashing mode
...
The drm_fbdev_cma_hotplug_event() function tests whether its argument is NULL
and then returns immediately. Thus the test around the call is not needed.
This issue was detected by using the Coccinelle software.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
Reviewed-by: Thierry Reding <thierry.reding@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
The current error path calls tilcdc_unload() in case of an error to release
the resources. However, this is wrong because not all resources have been
allocated by the time an error occurs in tilcdc_load().
To fix it, this commit adds proper labels to bail out at the different
stages in the load function, and release only the resources actually allocated.
Tested-by: Darren Etheridge <detheridge@ti.com>
Tested-by: Johannes Pointner <johannes.pointner@br-automation.com>
Signed-off-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
Signed-off-by: Dave Airlie <airlied@redhat.com>
One step closer to dropping all the drm_bus_* code:
Add a driver->set_busid() callback and make all drivers use the generic
helpers. Nouveau is the only driver that uses two different bus-types with
the same drm_driver. This is totally broken if both buses are available on
the same machine (unlikely, but lets be safe). Therefore, we create two
different drivers for each platform during module_init() and set the
set_busid() callback respectively.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Reviewed-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Use module_init instead of late_initcall, as is the norm for modular
drivers.
module_init was used until 6e8de0bd6a
("drm/tilcdc: add encoder slave (v2)") changed it to a late_initcall,
but it does not explain why. Tests show it's working properly with
module_init.
Signed-off-by: Guido Martínez <guido@vanguardiasur.com.ar>
Tested-by: Darren Etheridge <detheridge@ti.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
The TI tilcdc driver is designed with a notion of submodules. Currently,
at unload time, these submodules are iterated and destroyed.
Now that the tilcdc remove order is fixed, this can be handled perfectly
by the kernel using the device infrastructure, since each submodule
is a kernel driver itself, and they are only destroy()'ed at unload
time. Therefore we move the destroy() functionality to each submodule's
remove().
Also, remove some checks in the unloading process since the new code
guarantees the resources are allocated and need a release.
Signed-off-by: Guido Martínez <guido@vanguardiasur.com.ar>
Tested-by: Darren Etheridge <detheridge@ti.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Unregister resources in the correct order on tilcdc_drm_fini, which is
the reverse order they were registered during tilcdc_drm_init.
This also means unregistering the driver before releasing its resources.
Signed-off-by: Guido Martínez <guido@vanguardiasur.com.ar>
Tested-by: Darren Etheridge <detheridge@ti.com>
Cc: <stable@vger.kernel.org> #v3.9+
Signed-off-by: Dave Airlie <airlied@redhat.com>
The driver did not unregister the allocated framebuffer, which caused
memory leaks (and memory manager WARNs) when unloading. Also, the
framebuffer device under /dev still existed after unloading.
Add a call to drm_fbdev_cma_fini when unloading the module to prevent
both issues.
Signed-off-by: Guido Martínez <guido@vanguardiasur.com.ar>
Tested-by: Darren Etheridge <detheridge@ti.com>
Cc: <stable@vger.kernel.org> #v3.9+
Signed-off-by: Dave Airlie <airlied@redhat.com>
Unfortunately this requires a drm-wide change, and I didn't see a sane
way around that. Luckily it's fairly simple, we just need to inline
the respective get_irq implementation from either drm_pci.c or
drm_platform.c.
With that we can now also remove drm_dev_to_irq from drm_irq.c.
Reviewed-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This was hidden in a generic void * dev->mm_private. But only ever
used for gem. But thanks to this fake generic pretension no one
noticed that Rob's drm drivers are now all broken.
So just give the offset manager a type pointer and fix up msm, omapdrm
and tilcdc.
v2: Fixup compile fail.
v3: Fixup rebase fail that David spotted.
Cc: David Herrmann <dh.herrmann@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Dave Airlie <airlied@redhat.com>
I've killed them a long time ago in drm/i915, let's get rid of this
remnant of shared drm core days for good.
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Dave Airlie <airlied@redhat.com>
tilcdc already stores the drm_device in the driver data pointer. So
use that.
Cc: Rob Clark <robdclark@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
So I've stumbled over drm_fasync and wondered what it does. Digging
that up is quite a story.
First I've had to read up on what this does and ended up being rather
bewildered why peopled loved signals so much back in the days that
they've created SIGIO just for that ...
Then I wondered how this ever works, and what that strange "No-op."
comment right above it should mean. After all calling the core fasync
helper is pretty obviously not a noop. After reading through the
kernels FASYNC implementation I've noticed that signals are only sent
out to the processes attached with FASYNC by calling kill_fasync.
No merged drm driver has ever done that.
After more digging I've found out that the only driver that ever used
this is the so called GAMMA driver. I've frankly never heard of such a
gpu brand ever before. Now FASYNC seems to not have been the only bad
thing with that driver, since Dave Airlie removed it from the drm
driver with prejudice:
commit 1430163b4bbf7b00367ea1066c1c5fe85dbeefed
Author: Dave Airlie <airlied@linux.ie>
Date: Sun Aug 29 12:04:35 2004 +0000
Drop GAMMA DRM from a great height ...
Long story short, the drm fasync support seems to be doing absolutely
nothing. And the only user of it was never merged into the upstream
kernel. And we don't need any fops->fasync callback since the fcntl
implementation in the kernel already implements the noop case
correctly.
So stop this particular cargo-cult and rip it all out.
v2: Kill drm_fasync assignments in rcar (newly added) and imx drivers
(somehow I've missed that one in staging). Also drop the reference in
the drm DocBook. ARM compile-fail reported by Rob Clark.
v3: Move the removal of dev->buf_asnyc assignment in drm_setup to this
patch here.
v4: Actually git add ... tsk.
Cc: Dave Airlie <airlied@linux.ie>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Rob Clark <robdclark@gmail.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
All the gem based kms drivers really want the same function to
destroy a dumb framebuffer backing storage object.
So give it to them and roll it out in all drivers.
This still leaves the option open for kms drivers which don't use GEM
for backing storage, but it does decently simplify matters for gem
drivers.
Acked-by: Inki Dae <inki.dae@samsung.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Intel Graphics Development <intel-gfx@lists.freedesktop.org>
Cc: Ben Skeggs <skeggsb@gmail.com>
Reviwed-by: Rob Clark <robdclark@gmail.com>
Cc: Alex Deucher <alexdeucher@gmail.com>
Acked-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Dave Airlie <airlied@redhat.com>
In certain senarios drm will initialize before i2c this means that i2c
slave devices like the nxp tda998x will fail to be probed. This patch
detects this condition then defers the probe of the slave device and
the tilcdc main driver.
Signed-off-by: Darren Etheridge <detheridge@ti.com>
Acked-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Adding support for max-pixelclock and max-width device tree
entries. As some devices that use the tilcdc hardware module
have restrictions on the allowed/tested values. Also update DT
bindings document to reflect new parameters.
Signed-off-by: Darren Etheridge <detheridge@ti.com>
Acked-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
The preferred_bpp value in currently hard-coded to 16.
This causes color corruption on the am335x-evm lcd panel which
requires 32 bpp instead. This changes attempts to use the configured
bpp value from the DT or built-in panel-info struct.
Signed-off-by: Benoit Parrot <bparrot@ti.com>
Acked-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Silences the following checkpatch warning:
WARNING: please, no space before tabs
Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
Acked-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Silences the following checkpatch warning:
WARNING: braces {} are not necessary for any arm of this statement
if (priv->rev == 1) {
Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
Acked-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Instead of checking if num_encoders is zero, it is being assigned 0.
Convert the assignment to a check.
Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
Acked-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Add an output panel driver for LCD panels. Tested with LCD3 cape on
beaglebone.
v1: original
v2: s/of_find_node_by_name()/of_get_child_by_name()/ from Pantelis
Antoniou
v3: add backlight support
v4: rebase to latest of video timing helpers
v5: remove some unneeded fields from panel-info struct, add DT bindings
docs
Signed-off-by: Rob Clark <robdclark@gmail.com>
Tested-by: Koen Kooi <koen@dominion.thruhere.net>
Add output panel driver for i2c encoder slaves.
v1: original
v2: add DT bindings docs, and minor updates for review comments
Signed-off-by: Rob Clark <robdclark@gmail.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Tested-by: Koen Kooi <koen@dominion.thruhere.net>
A simple DRM/KMS driver for the TI LCD Controller found in various
smaller TI parts (AM33xx, OMAPL138, etc). This driver uses the
CMA helpers. Currently only the TFP410 DVI encoder is supported
(tested with beaglebone + DVI cape). There are also various LCD
displays, for which support can be added (as I get hw to test on),
and an external i2c HDMI encoder found on some boards.
The display controller supports a single CRTC. And the encoder+
connector are split out into sub-devices. Depending on which LCD
or external encoder is actually present, the appropriate output
module(s) will be loaded.
v1: original
v2: fix fb refcnting and few other cleanups
v3: get +/- vsync/hsync from timings rather than panel-info, add
option DT max-bandwidth field so driver doesn't attempt to
pick a display mode with too high memory bandwidth, and other
small cleanups
v4: remove some unneeded stuff from panel-info struct, properly
set high bits for hfp/hsw/hbp for rev 2, add DT bindings docs
Signed-off-by: Rob Clark <robdclark@gmail.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Tested-by: Koen Kooi <koen@dominion.thruhere.net>