DRM page flip vblank events requested by page flips or atomic commits
are created by the DRM core and then passed to driver through CRTC
states (for atomic commit) or directly to the page flip handler (for
legacy page flips). The events are then kept aside until the page flip
completes, at which point drivers queue them for delivery with a call to
drm_send_vblank_event().
When a DRM file handle is closed events pending for delivery are cleaned
up automatically by the DRM core. Events that have been passed to the
driver but haven't completed yet, however, are not handled by the DRM
core. Drivers are responsible for destroying them and must not attempt
to queue them for delivery. This is usually handled by drivers'
preclose() handlers that cancel and destroy page flip events that
reference the file handle being closed.
With asynchronous atomic updates the story becomes more complex. Several
asynchronous atomic updates can be pending, each of them carrying
per-CRTC events. As the atomic_commit() operation doesn't receive a file
handle context, drivers can't know which file handle a pending update
refers to, making it difficult to cancel or wait for completion of
updates related to the file handle being closed.
It should be noted that cancelling page flips or waiting for atomic
updates completion isn't required by the DRM core when closing a file
handle. The only requirement is that no event gets queued for delivery
after the preclose() operation returns. This can easily be achieved by
storing events for atomic commits in a list, unlinking events from the
file handle being closed by setting the file_priv field to NULL, and
skipping delivery of unlinked events.
This logic replaces the page flip cancellation completely.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
When performing asynchronous atomic updates the modeset lock isn't taken
around the callers of omap_crtc_flush(). This isn't an issue though, as
access to the CRTC is properly serialized. Just drop the warning.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The omap_crtc_flush() function is always called with a reference to the
dispc held. Remove unnecessary calls to dispc_runtime_get() and
dispc_runtime_put().
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The function isn't used outside of its compilation unit, make it static.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The field tracks the plane state to avoid double-enable or -disable.
This isn't required anymore, as
- the DRM atomic core guarantees that the plane atomic_update and
atomic_disable functions will never be called on an enabled/disabled
plane
- the CRTC enable/disable operations that enable/disable the plane are
already guarded against double enable/disable
We can thus remove the enabled field completely. The
omap_plane_set_enable() function then becomes a wrapper around
omap_plane_setup() which can be called directly.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The field tracks the CRTC state to avoid double-enable or -disable. As
the DRM atomic core guarantees that the CRTC enable and disable
functions won't be called on an already enabled or disabled CRTC, such
tracking isn't needed. Remove the enabled field.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The crtc info structure is only used to setup the crtc through the DSS
API. Move it from the crtc structure to local variables in
omap_crtc_dss_enable().
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The plane info and win structures are only used to setup the plane
through the DSS API. Move them from the plane structure to local
variables in omap_plane_setup().
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Allow setting up plane properties atomically using the plane
set_property atomic helper. The properties are now stored in the plane
state (requiring subclassing it) and applied when updating the planes.
The CRTC exposes the properties of its primary plane for legacy reason.
We can't get rid of that API, so simply delegate it to the primary
plane.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Since the removal of omap_plane_mode_set(), framebuffers are now pinned
exclusively through the plane .prepare_fb() and .cleanup_fb() operations
as the remaining callers of omap_plane_setup() don't modify the
framebuffer. Remove the manual pin/unpin infrastructure.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The atomic page flip helper implements the page flip operation using
asynchronous commits.
As the legacy page flip was the last caller of omap_plane_mode_set(),
remove the function.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Implement a custom .atomic_commit() handler that supports asynchronous
commits using a work queue. This can be used for userspace-driven
asynchronous commits, as well as for an atomic page flip implementation.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The encoder .mode_fixup() operation is legacy, atomic updates uses the
new .atomic_check() operation. Convert the encoder driver.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The atomic connector DPMS helper implements the connector DPMS operation
using atomic commit, removing the need for DPMS helper operations on
CRTCs and encoders.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
This removes the legacy mode config code. The CRTC and encoder prepare
and commit operations are not used anymore, remove them.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
This removes the legacy plane update code. Wire up the default atomic
check and atomic commit mode config helpers as needed by the plane
update atomic helpers.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Use the new CRTC atomic transitional helpers drm_helper_crtc_mode_set()
and drm_helper_crtc_mode_set_base() to implement the CRTC .mode_set and
.mode_set_base operations. This delegates primary plane configuration to
the plane .atomic_update and .atomic_disable operations, removing
duplicate code from the CRTC implementation.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Implement the CRTC .atomic_begin() and .atomic_flush() operations, the
plane .atomic_check(), .atomic_update() and operations, and use the
transitional atomic helpers to implement the plane update and disable
operations on top of the new atomic operations.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Hook up the default .reset(), .atomic_duplicate_state() and
.atomic_free_state() helpers to ensure that state objects are properly
created and destroyed, and call drm_mode_config_reset() at init time to
create the initial state objects.
Framebuffer reference count also gets maintained automatically by the
transitional helpers except for the legacy page flip operation. Maintain
it explicitly there.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The operations are required by the atomic helpers, implement them.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
When using atomic updates the CRTC .enable() and .disable() helper
operations are preferred over the (then legacy) .prepare() and .commit()
operations. Implement .enable() and rework .disable() to not depend on
DPMS, easing DPMS removal later on.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The omap_crtc_enable() and omap_crtc_disable() DSS operations functions
will clash with the new CRTC enable and disable helpers. Rename them to
omap_crtc_dss_*, as well as the other DSS operations for consistency.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Use the <...> include style instead of "..." for DRM headers and sort
the headers alphabetically to ease detection of duplicates.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
We can't rely on crtc->primary->fb in the page flip worker, as a racing
CRTC disable (due for instance to an explicit framebuffer deletion from
userspace) would set that field to NULL before the worker gets a change
to run. Store the framebuffer queued for page flip in a new field of
omap_crtc instead, and hold a reference to it.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The DRM core vblank handling mechanism requires drivers to forcefully
turn vblank reporting off when disabling the CRTC, and to restore the
vblank reporting status when enabling the CRTC.
Implement this using the drm_crtc_vblank_on/off helpers. When disabling
vblank we must first wait for page flips to complete, so implement page
flip completion wait as well.
Finally, drm_crtc_vblank_off() must be called at startup to synchronize
the state of the vblank core code with the hardware, which is initially
disabled. An interesting side effect is that the .disable_vblank()
operation will now be called for the first time with the CRTC disabled
and the DISPC runtime suspended. The dispc_runtime_get() call in
.disable_vblank() is supposed to take care of that, but the operation is
called with a spinlock held, which prevents it from sleeping.
To fix that move DISPC runtime PM handling out of the vblank operations
to the CRTC code, ensuring that the display controller will always be
powered when enabling or disabling vblank interrupts.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
To implement proper vblank control the driver will need to wait for page
flip completion before disabling the vblank interrupt. This is made
complex by the page flip implementation which queues and submits page
flips to the hardware in two separate steps between which DRM locks are
released. We thus need to avoid waiting on a page flip that has been
queued but not submitted as submission and wait are covered by the same
lock.
Rework page flip handling as a first step by splitting the flip_pending
boolean variable into an enumerated state and moving between states
based on flip queue, submission and completion. The CANCELLED state will
be used in a second step.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Pending page flips must be cancelled when closing the device, otherwise
their completion at next vblank will result in nasty effects, including
possible oopses due to resources required to complete the page flip
being freed.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The omapdrm can't use drm_irq_install() and drm_irq_uninstall() as it
delegates IRQ handling to the omapdss driver. However, the code still
declares IRQ-related operations used by the DRM IRQ helpers, and calls
them indirectly.
Simplify the implementation by calling the functions directly or
inlining them. The irq_enabled checks can then also be simplified as
the call stacks guarantees that omap_drm_irq_install() and
omap_drm_irq_uninstall() will never run concurrently.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The old_fb field is only used to indicate whether a page flip is
pending. Turn it into a bool named flip_pending. Rename event and
page_flip_work to flip_event and flip_work for consistency.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The operation is called page_flip, rename its implementation
accordingly.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The omapdrm driver implements a mechanism to apply new settings (due to
plane update, plane disable, plane property set, CRTC mode set or CRTC
DPMS) asynchronously. While this improves performance, it adds a level
of complexity that makes transition to the atomic update API close to
impossible. Furthermore the atomic update API requires part of the apply
operations to be synchronous (such as pinning the framebuffers), so the
current implementation needs to be changed.
Simplify the CRTC and plane code by making updates synchronous to
prepare for the switch to the atomic update API. Asynchronous update
will be implemented in a second step.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Rotation is a standard property, store it in
dev->mode_config.rotation_property. While at it, extract the properties
initialization code to a separate function instead of running it for
every plane.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
At present, dma_buf_export() takes a series of parameters, which
makes it difficult to add any new parameters for exporters, if required.
Make it simpler by moving all these parameters into a struct, and pass
the struct * as parameter to dma_buf_export().
While at it, unite dma_buf_export_named() with dma_buf_export(), and
change all callers accordingly.
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
Reviewed-by: Daniel Thompson <daniel.thompson@linaro.org>
Acked-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Acked-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
Setting a dev_pm_ops resume callback but not a set of hibernation
handler means that pm function will not be called upon hibernation.
Fix this by using SIMPLE_DEV_PM_OPS, which appropriately assigns the
suspend and hibernation handlers and move omap_dmm_resume under
CONFIG_PM_SLEEP to avoid build warnings.
Signed-off-by: Grygorii Strashko <grygorii.strashko@linaro.org>
Reviewed-by: Rob Clark <robdclark@gmail.com>
[tomi valkeinen: add missing 'static']
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Setting a dev_pm_ops suspend/resume pair but not a set of hibernation
functions means those pm functions will not be called upon hibernation.
Fix this by using SIMPLE_DEV_PM_OPS, which appropriately assigns the
suspend and hibernation handlers and move
omap_drm_suspend/omap_drm_resume under CONFIG_PM_SLEEP to avoid build
warnings.
Signed-off-by: Grygorii Strashko <Grygorii.Strashko@linaro.org>
[tomi.valkeinen@ti.com: fix conflict, clean up description]
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
We store the fb being page-flipped to 'old_fb' field, but we don't
increase the ref count of the fb when doing that. While I am not
sure if it can cause problem in practice, it's still safer to keep a ref
when storing a pointer to a fb.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The omapdrm DMM code sometimes crashes with:
WARNING: CPU: 0 PID: 1235 at lib/list_debug.c:36 __list_add+0x8c/0xbc()
list_add double add: new=e9265368, prev=e90139c4, next=e9265368.
This is caused by the code calling release_engine() twice for the same
engine.
dmm_txn_commit(wait=true) call is supposed to wait until the DMM
transaction has been finished. And it does that, but it does not wait
for the irq handler to finish.
What happens is that the irq handler is triggered, and it either wakes
up the thread that called dmm_txn_commit(), or that thread never even
slept because the transaction was finished in the HW very quickly. That
thread then continues executing, even if the irq handler is not yet
finished, and a new transaction may be initiated. If that transaction is
async (i.e. wait=false), a 'async' flag is set to true. The original irq
handler, which has yet not finished, then sees the transaction as
'async', even if it was supposed to be 'sync'.
When that happens, the irq handler does an extra release_engine() call
because it thinks it need to release the engine, leading to the crash.
This patch fixes the issue by using completion to ensure that the irq
handler has finished before a dmm_txn_commit(wait=true) may continue.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
omap_gem_objects are added to dev->obj_list in omap_gem_new, and removed
in omap_gem_free_object. Unfortunately there's no locking for
dev->obj_list, which eventually leads to a crash:
WARNING: CPU: 1 PID: 1123 at lib/list_debug.c:59 __list_del_entry+0xa4/0xe0()
list_del corruption. prev->next should be e9281344, but was ea722b84
Add a spinlock to protect dev->obj_list.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
spin_is_locked(x) returns always 0 on uniprocessor, triggering BUG() in
omapdrm.
Change it to use assert_spin_locked() to fix the issue.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
We need to ignore DIGIT SYNC LOST error when enabling/disabling TV
output. The code does that, but it ignores the DIGI SYNC LOST when
enabling any output. Normally this does no harm, but it could make us
miss DIGIT SYNC LOST on some rare occasions.
Fix the code to only ignore DIGIT SYNC LOST when enabling/disabling TV.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
omapdrm tries to avoid error floods by unregistering the error irq when
an error happens, and then registering the error irq again later.
However, the code is racy, as it sometimes tries to unregister the error
irq when it's already unregistered, leading to WARN().
Also, the code only registers the error irq again when something is done
on that particular output, i.e. if only TV is used to flip the buffers,
and LCD is showing a same buffer, an error on LCD will cause the LCD
error irq to be unregistered and never registered again.
To fix this, let's keep the error irqs always enabled and trust the
DRM_ERROR_RATELIMITED to limit the flood.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
omapdrm uses normal DRM_ERROR() print when the HW reports an error. As
we sometimes may get a flood of errors, let's rather use
DRM_ERROR_RATELIMITED().
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
When not using proper hotplug detection, DRM polls periodically the
connectors to find out if a cable is connected. This polling can happen
at any time, even very late in the suspend process.
This causes a problem with omapdrm, when the poll happens during the
suspend process after GPIOs have been disabled, leading to a crash in
gpio_get().
This patch fixes the issue by adding suspend and resume hooks to
omapdrm, in which we disable and enable, respectively, the polling.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
omapdrm has dummy functions for platform_device's
suspend/resume/shutdown. The functions don't do anything, and those
platform device functions are deprecated, so remove them from omapdrm.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
The tiler irq handler uses engine->async value, but the code that sets
engine->async and enables the interrupt does not have a barrier. This
may cause the irq handler to see the old value of engine->async, causing
memory corruption.
Reported-by: Harinarayan Bhatta <harinarayan@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
omap_plane_pre_apply() sets the plane's output channel too late, only
after the plane has already been otherwise configured and enabled. This
causes problems, as at the configuration stage we need to make decisions
based on the output channel.
This may lead to bad plane settings or failing to setup the plane.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
On OMAP5 it is not possible to use TILER buffer with CPU when caching or
write-combining is used. Doing so leads to errors from the memory
manager.
However, on OMAP4, write-combining works fine.
This patch adds platform specific data for the TILER, and a function
tiler_get_cpu_cache_flags() which can be used to get the caching mode to
be used.
Note that without write-combining the use of the TILER buffer with CPU
is unusably slow. It's still good to have it operational for testing
purposes.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
omapdrm doesn't check if the pitch of the framebuffer and the color
format's bits-per-pixel are compatible. omapdss requires that the stride
of a buffer is an integer number of pixels
For example, when using modetest with a display that has x resolution of
1280, and using packed 24 RGB mode (3 bytes per pixel), modetest
allocates a buffer with a byte stride of 4 * 1280 = 5120. But 5120 / 3 =
1706.666... pixels, which causes wrong colors and a tilt on the screen.
Add a check into omapdrm to return an error if the user tries to use
such a combination.
Note: this is not a HW requirement at least for non-rotation use cases,
but a SW driver requirement. In the future we should study if also
rotation use cases are fine with any stride size, and if so, change the
driver to allow these strides.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
When an error happens in omap_framebuffer_create(),
omap_framebuffer_create() calls omap_framebuffer_destroy() if the fb
struct has been allocated. However, that crashes, as
omap_framebuffer_destroy(), which calls drm_framebuffer_cleanup(),
should only be called after drm_framebuffer_init()
Fix this by just calling kfree() for the allocated fb when an error
happens.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>