Most bridge drivers create a DRM connector to model the connector at the
output of the bridge. This model is historical and has worked pretty
well so far, but causes several issues:
- It prevents supporting more complex display pipelines where DRM
connector operations are split over multiple components. For instance a
pipeline with a bridge connected to the DDC signals to read EDID data,
and another one connected to the HPD signal to detect connection and
disconnection, will not be possible to support through this model.
- It requires every bridge driver to implement similar connector
handling code, resulting in code duplication.
- It assumes that a bridge will either be wired to a connector or to
another bridge, but doesn't support bridges that can be used in both
positions very well (although there is some ad-hoc support for this in
the analogix_dp bridge driver).
In order to solve these issues, ownership of the connector should be
moved to the display controller driver (where it can be implemented
using helpers provided by the core).
Extend the bridge API to allow disabling connector creation in bridge
drivers as a first step towards the new model. The new flags argument to
the bridge .attach() operation allows instructing the bridge driver to
skip creating a connector. Unconditionally set the new flags argument to
0 for now to keep the existing behaviour, and modify all existing bridge
drivers to return an error when connector creation is not requested as
they don't support this feature yet.
The change is based on the following semantic patch, with manual review
and edits.
@ rule1 @
identifier funcs;
identifier fn;
@@
struct drm_bridge_funcs funcs = {
...,
.attach = fn
};
@ depends on rule1 @
identifier rule1.fn;
identifier bridge;
statement S, S1;
@@
int fn(
struct drm_bridge *bridge
+ , enum drm_bridge_attach_flags flags
)
{
... when != S
+ if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
+ DRM_ERROR("Fix bridge driver to make connector optional!");
+ return -EINVAL;
+ }
+
S1
...
}
@ depends on rule1 @
identifier rule1.fn;
identifier bridge, flags;
expression E1, E2, E3;
@@
int fn(
struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags
) {
<...
drm_bridge_attach(E1, E2, E3
+ , flags
)
...>
}
@@
expression E1, E2, E3;
@@
drm_bridge_attach(E1, E2, E3
+ , 0
)
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Acked-by: Sam Ravnborg <sam@ravnborg.org>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Tested-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200226112514.12455-10-laurent.pinchart@ideasonboard.com
Commit 05193dc381 ("drm/bridge: Make the bridge chain a double-linked
list") patched the bridge chain logic to use a double-linked list instead
of a single-linked list. This change induced changes to the VC4 driver
which was manually resetting the encoder->bridge element to NULL to
control the enable/disable sequence of the bridge chain. During this
conversion, 2 bugs were introduced:
1/ list_splice() was used to move chain elements to our own internal
chain, but list_splice() does not reset the source list to an empty
state, leading to unexpected bridge hook calls when
drm_bridge_chain_xxx() helpers were called by the core. Replacing
those list_splice() calls by list_splice_init() ones fixes this
problem.
2/ drm_bridge_chain_xxx() helpers operate on the
bridge->encoder->bridge_chain list, which is now empty. When the
helper uses list_for_each_entry_reverse() we end up with no operation
done which is not what we want. But that's even worse when the helper
uses list_for_each_entry_from(), because in that case we end up in
an infinite loop searching for the list head element which is no
longer encoder->bridge_chain but vc4_dsi->bridge_chain. To address
that problem we stop using the bridge chain helpers and call the
hooks directly.
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: Eric Anholt <eric@anholt.net>
Fixes: 05193dc381 ("drm/bridge: Make the bridge chain a double-linked list")
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Acked-by: Eric Anholt <eric@anholt.net>
Link: https://patchwork.freedesktop.org/patch/msgid/20191227144124.210294-2-boris.brezillon@collabora.com
The drm panel bridge creates a connector using a connector type
explicitly passed by the display controller or bridge driver that
instantiates the panel bridge. Now that drm_panel reports its connector
type, we can use it to avoid passing an explicit (and often incorrect)
connector type to drm_panel_bridge_add() and
devm_drm_panel_bridge_add().
Several drivers report incorrect or unknown connector types to
userspace. Reporting a different type may result in a breakage. For that
reason, rename (devm_)drm_panel_bridge_add() to
(devm_)drm_panel_bridge_add_typed(), and add new
(devm_)drm_panel_bridge_add() functions that use the panel connector
type. Update all callers of (devm_)drm_panel_bridge_add() to the _typed
function, they will be converted one by one after testing.
The panel drivers have been updated with the following Coccinelle
semantic patch, with manual inspection and fixes to indentation.
@@
expression bridge;
expression dev;
expression panel;
identifier type;
@@
(
-bridge = drm_panel_bridge_add(panel, type);
+bridge = drm_panel_bridge_add_typed(panel, type);
|
-bridge = devm_drm_panel_bridge_add(dev, panel, type);
+bridge = devm_drm_panel_bridge_add_typed(dev, panel, type);
)
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20190904132804.29680-3-laurent.pinchart@ideasonboard.com
Based on 1 normalized pattern(s):
this program is free software you can redistribute it and or modify
it under the terms of the gnu general public license version 2 as
published by the free software foundation this program 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 this program if not see http www gnu org
licenses
extracted by the scancode license scanner the SPDX license identifier
GPL-2.0-only
has been chosen to replace the boilerplate/reference in 503 file(s).
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Alexios Zavras <alexios.zavras@intel.com>
Reviewed-by: Allison Randal <allison@lohutok.net>
Reviewed-by: Enrico Weigelt <info@metux.net>
Cc: linux-spdx@vger.kernel.org
Link: https://lkml.kernel.org/r/20190602204653.811534538@linutronix.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Pull more clk framework updates from Stephen Boyd:
"One more patch to remove io.h from clk-provider.h.
We used to need this include when we had clk_readl() and clk_writel(),
but those are gone now so this patch pushes the dependency out to the
users of clk-provider.h"
* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux:
clk: Remove io.h from clk-provider.h
The global list of all debugfs entries for the driver was painful: the
list couldn't see into the components' structs, so each component had
its own debugs show function to find the component, then find the
regset and dump it. The components also had to be careful to check
that they were actually registered in vc4 before dereferencing
themselves, in case they weren't probed on a particular platform.
They routinely failed at that.
Instead, we can have the components add their debugfs callbacks to a
little list in vc4 to be registered at drm_dev_register() time, which
gets vc4_debugfs.c out of the business of knowing the whole list of
components.
Thanks to this change, dsi0 (if it existed) would register its node.
v2: Rebase on hvs_underrun addition.
v3: whitespace fixup
Signed-off-by: Eric Anholt <eric@anholt.net>
Link: https://patchwork.freedesktop.org/patch/msgid/20190401183559.3823-1-eric@anholt.net
Reviewed-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
This allows panels or bridges that need to send DSI commands during
pre_enable() to successfully send them. We delay DISP0 (aka the
actual display) enabling until after pre_enable so that pixels aren't
streaming before then.
v2: Just clear out the encoder->bridge value to disable the midlayer
calls (idea by Andrzej Hajda).
Signed-off-by: Eric Anholt <eric@anholt.net>
Cc: Andrzej Hajda <a.hajda@samsung.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180621231759.29604-1-eric@anholt.net
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
VC4's DSI1 has a bug where the AXI connection is broken for 32-bit
writes from the CPU, so we use the DMA engine to DMA 32-bit values
into registers instead. That sleeps, so we can't do it from the top
half.
As a solution, use an interrupt thread so that all our writes happen
when sleeping is is allowed.
v2: Use IRQF_ONESHOT (suggested by Boris)
v3: Style nitpicks.
Signed-off-by: Eric Anholt <eric@anholt.net>
Link: https://patchwork.freedesktop.org/patch/msgid/20171014001255.32005-1-eric@anholt.net
Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com> (v2)
We need the following things to happen in sequence:
DSI host creation
DSI device creation in the panel driver (needs DSI host)
DSI device attach from panel to host.
DSI drm_panel_add()
DSI encoder creation
DSI encoder's DRM panel/bridge attach
Unless we allow device creation while the host isn't up yet, we need
to break the -EPROBE_DEFER deadlock between the panel driver looking
up the host and the host driver looking up the panel. We can do so by
moving the DSI host creation outside of the component bind loop, and
the panel/bridge lookup/attach into the component bind process.
Signed-off-by: Eric Anholt <eric@anholt.net>
Link: https://patchwork.freedesktop.org/patch/msgid/20170815234722.20700-3-eric@anholt.net
Reviewed-by: Archit Taneja <architt@codeaurora.org>
The incoming mode might have a missing vrefresh field if it came from
drmModeSetCrtc(), which the kernel is supposed to calculate using
drm_mode_vrefresh(). We could either use that or the adjusted_mode's
original vrefresh value.
However, we can maintain a more exact vrefresh value (not just the
integer approximation), by scaling by the ratio of our clocks.
v2: Use math suggested by Andrzej Hajda instead.
v3: Simplify math now that adjusted_mode->clock isn't padded.
v4: Drop some parens.
Signed-off-by: Eric Anholt <eric@anholt.net>
Link: https://patchwork.freedesktop.org/patch/msgid/20170815234722.20700-2-eric@anholt.net
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
BCM2835's PLLD_DSI1 divider doesn't give us many choices for our pixel
clocks, so to support panels on the Raspberry Pi we need to set a
higher pixel clock rate than requested and adjust the mode we program
to extend out the HFP so that the refresh rate matches.
v2: Drop an unfinished comment (caught by Noralf)
Signed-off-by: Eric Anholt <eric@anholt.net>
Link: http://patchwork.freedesktop.org/patch/msgid/20170511235625.22427-2-eric@anholt.net
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
If dsi_connector fails to allocate, the exit path via label 'fail'
checks if connector is null, which it always is, so the cleanup
that destroys connector is never going to be called. Hence the
failure path can be more optimally performed by removing this
and just returning ERR_PTR(-ENOMEM). This also removes the need
to initialize connector to NULL, and we can also remove ret too.
Detected by CoverityScan, CID#1399504 ("Logicall Dead Code")
Signed-off-by: Colin Ian King <colin.king@canonical.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170203195624.7189-1-colin.king@canonical.com
The DSI0 and DSI1 blocks on the 2835 are related hardware blocks.
Some registers move around, and the featureset is slightly different,
as DSI1 (the 4-lane DSI) is a later version of the hardware block.
This driver doesn't yet enable DSI0, since we don't have any hardware
to test against, but it does put a lot of the register definitions and
code in place.
v2: Use the clk_hw interfaces, don't set CLK_IS_BASIC (from review by
Stephen Boyd)
Signed-off-by: Eric Anholt <eric@anholt.net>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v1)
Link: http://patchwork.freedesktop.org/patch/msgid/20170131192912.11316-1-eric@anholt.net