On R-Car D3 and E3, the LVDS encoders provide the pixel clock to the DU,
even when LVDS outputs are not used. For this reason, the rcar-lvds
driver probes successfully on those platforms even if no further bridge
or panel is connected to the LVDS output, in order to provide the
rcar_lvds_clk_enable() and rcar_lvds_clk_disable() functions to the DU
driver.
If an LVDS output isn't connected, trying to create a DRM connector for
the output will fail. Fix this by skipping connector creation in …
[View More]that
case, and also skip creation of the DRM encoder as there's no point in
an encoder without a connector.
Fixes: e9e056949c92 ("drm: rcar-du: lvds: Convert to DRM panel bridge helper")
Reported-by: Geert Uytterhoeven <geert(a)linux-m68k.org>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas(a)ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 16 ++++++++++++----
drivers/gpu/drm/rcar-du/rcar_lvds.c | 11 +++++++++++
drivers/gpu/drm/rcar-du/rcar_lvds.h | 5 +++++
3 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index 0daa8bba50f5..4bf4e25d7f01 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -86,12 +86,20 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
}
/*
- * Create and initialize the encoder. On Gen3 skip the LVDS1 output if
+ * Create and initialize the encoder. On Gen3, skip the LVDS1 output if
* the LVDS1 encoder is used as a companion for LVDS0 in dual-link
- * mode.
+ * mode, or any LVDS output if it isn't connected. The latter may happen
+ * on D3 or E3 as the LVDS encoders are needed to provide the pixel
+ * clock to the DU, even when the LVDS outputs are not used.
*/
- if (rcdu->info->gen >= 3 && output == RCAR_DU_OUTPUT_LVDS1) {
- if (rcar_lvds_dual_link(bridge))
+ if (rcdu->info->gen >= 3) {
+ if (output == RCAR_DU_OUTPUT_LVDS1 &&
+ rcar_lvds_dual_link(bridge))
+ return -ENOLINK;
+
+ if ((output == RCAR_DU_OUTPUT_LVDS0 ||
+ output == RCAR_DU_OUTPUT_LVDS1) &&
+ !rcar_lvds_is_connected(bridge))
return -ENOLINK;
}
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
index d061b8de748f..b672c5bd72ee 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
@@ -576,6 +576,9 @@ static int rcar_lvds_attach(struct drm_bridge *bridge,
{
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
+ if (!lvds->next_bridge)
+ return 0;
+
return drm_bridge_attach(bridge->encoder, lvds->next_bridge, bridge,
flags);
}
@@ -598,6 +601,14 @@ bool rcar_lvds_dual_link(struct drm_bridge *bridge)
}
EXPORT_SYMBOL_GPL(rcar_lvds_dual_link);
+bool rcar_lvds_is_connected(struct drm_bridge *bridge)
+{
+ struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
+
+ return lvds->next_bridge != NULL;
+}
+EXPORT_SYMBOL_GPL(rcar_lvds_is_connected);
+
/* -----------------------------------------------------------------------------
* Probe & Remove
*/
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.h b/drivers/gpu/drm/rcar-du/rcar_lvds.h
index 222ec0e60785..eb7c6ef03b00 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.h
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.h
@@ -16,6 +16,7 @@ struct drm_bridge;
int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq);
void rcar_lvds_clk_disable(struct drm_bridge *bridge);
bool rcar_lvds_dual_link(struct drm_bridge *bridge);
+bool rcar_lvds_is_connected(struct drm_bridge *bridge);
#else
static inline int rcar_lvds_clk_enable(struct drm_bridge *bridge,
unsigned long freq)
@@ -27,6 +28,10 @@ static inline bool rcar_lvds_dual_link(struct drm_bridge *bridge)
{
return false;
}
+static inline bool rcar_lvds_is_connected(struct drm_bridge *bridge)
+{
+ return false;
+}
#endif /* CONFIG_DRM_RCAR_LVDS */
#endif /* __RCAR_LVDS_H__ */
--
Regards,
Laurent Pinchart
[View Less]
This patch series brings back several patches targeting assigning dispcc
clock parents, that were removed from the massive dsi rework patchset
earlier.
Few notes:
- assign-clock-parents is a mandatory proprety according to the current
dsi.txt description.
- There is little point in duplicating this functionality with the ad-hoc
implementation in the dsi code.
On top of that come few minor cleanups for the DSI PHY drivers.
I'd kindly ask to bring all dts changes also through the drm …
[View More]tree, so
that there won't be any breakage of the functionality.
The patchset was tested on RB3 (single DSI), RB5 (single DSI, two
independent DSI, bonded DSI, two last configs require additional patches
which do not concern the DSI timings code).
Changes since v1:
- add dt-bindings change
- drop the patch removing msm_dsi_dphy_timing
The following changes since commit e88bbc91849b2bf57683119c339e52916d34433f:
Revert "drm/msm/mdp5: provide dynamic bandwidth management" (2021-06-23 14:06:20 -0700)
are available in the Git repository at:
https://git.linaro.org/people/dmitry.baryshkov/kernel.git dsi-phy-update
for you to fetch changes up to a79d84d8eac721a7ebaf3cfc65b200077b1d6947:
drm/msm/dsi: drop msm_dsi_phy_get_shared_timings (2021-07-10 00:02:18 +0300)
----------------------------------------------------------------
Dmitry Baryshkov (8):
dt-bindings: display: msm: dsi-controller-main: restore assigned-clocks
arm64: dts: qcom: sc7180: assign DSI clock source parents
arm64: dts: qcom: sdm845: assign DSI clock source parents
arm64: dts: qcom: sdm845-mtp: assign DSI clock source parents
arm64: dts: qcom: sm8250: assign DSI clock source parents
drm/msm/dsi: stop setting clock parents manually
drm/msm/dsi: phy: use of_device_get_match_data
drm/msm/dsi: drop msm_dsi_phy_get_shared_timings
.../bindings/display/msm/dsi-controller-main.yaml | 17 ++++++++
arch/arm64/boot/dts/qcom/sc7180.dtsi | 3 ++
arch/arm64/boot/dts/qcom/sdm845-mtp.dts | 3 ++
arch/arm64/boot/dts/qcom/sdm845.dtsi | 6 +++
arch/arm64/boot/dts/qcom/sm8250.dtsi | 6 +++
drivers/gpu/drm/msm/dsi/dsi.h | 7 +--
drivers/gpu/drm/msm/dsi/dsi_host.c | 51 ----------------------
drivers/gpu/drm/msm/dsi/dsi_manager.c | 8 +---
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 34 ++++-----------
9 files changed, 47 insertions(+), 88 deletions(-)
[View Less]
Hans de Goede asked me to take a topic from a private discussion here.
I must also preface that I'm not a graphics person and my knowledge of
DRI/DRM is cursory at best.
I initiated the conversation with de Goede after learning that the X
server now supports being started with an open DRM file descriptor
(this was added for Keith Packard's xlease project). I wondered if
that could be used to smoothen the Plymouth->X transition somehow and
asked de Goede if there were any such plans. He …
[View More]denied, but mentioned
that a new ioctl is in the works to prevent the kernel from wiping the
contents of a frame buffer after a device is closed, and that this
would help to keep transitions smooth.
I am a bit disappointed with this being considered a desirable way of
handling that transfer of control over a shared DRM device as it shows
a lack of ambition. Sure, it's probably easy to implement, but it
will also greatly limit how such transitions can be presented to the
user. In practice it would mean plymouthd closing the DRM device and
exiting so that systemd can start the display manager which then
starts an X server to present the login screen. If for that several
shared libraries have to first be loaded and relocated while the
system is under heavy load then there will be a noticeable delay
manifesting as a frozen screen. After that the best you can hope for
is blending the still-frame over into the login screen (or whatever
comes then). The VT-API-based switching mechanism currently en vogue
suffers from similar limitations.
If the approach to transferring control were to be changed to a scheme
that involves both donor and recipient process connecting to each
other on a unix socket and actively coordinating the transfer
(i.e. the calls to drmSetMaster and drmDropMaster) then this would
open the door to a host of possibilities. Not only could the
transition be kept infinitesimally short since both processes are
already up, but it could also involve e.g. the recipient continuing an
animation the donor had going reusing state that is transferred as a
memfd. This way there wouldn't be any noticeable freezes on the
display making for a far more polished, and thus impressive
experience. It would be a feat a program alone cannot achieve on its
own. Another option made possible would be implementing a watchdog.
If the recipient transfers e.g. file descriptors for a pipe and a
pidfd of itself, then the donor could monitor those for a
heartbeat/process termination and take back control over the device if
something goes awry (deadlock/crash) and initiate a recovery
mechanism. With the other approach implementing such features is
simply not possible.
Making processes talk to each other and work together like this would
also be a far more accurate software representation of what is
actually going on: different subsystems passing control over a shared
device around to work towards the common goal of a good user
experience.
A bit of context: The idea underlying this came from my experience
with accessibility technology under Linux where uncoordinated fighting
over the audio device among all kinds of processes led to countless
ways in which things would break with no hope of ever fixing anything.
It instilled in me the conviction that user-facing programs are broken
if they are not written to talk to each other to coordinate access to
shared resources for the goal of rendering a good user experience, but
instead leave it to the distro maintainer/user to set things up into a
static, brittle working order. Seeing a much-needed cultural shift
begin somewhere would be nice. The Plymouth->X transition would lend
itself well as a starting point since many building blocks are already
there.
Regards
[View Less]
The DSI host might be left in some state by the bootloader. If this
state generates an IRQ, it might hang the system by holding the
interrupt line before the driver sets up the DSI host to the known
state.
Move the request/free_irq calls into msm_dsi_host_power_on/_off calls,
so that we can be sure that the interrupt is delivered when the host is
in the known state.
Fixes: a689554ba6ed ("drm/msm: Initial add DSI connector support")
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov(a)linaro.…
[View More]org>
---
drivers/gpu/drm/msm/dsi/dsi_host.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index e269df285136..cd842347a6b1 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1951,15 +1951,6 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host,
return ret;
}
- ret = devm_request_irq(&pdev->dev, msm_host->irq,
- dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
- "dsi_isr", msm_host);
- if (ret < 0) {
- DRM_DEV_ERROR(&pdev->dev, "failed to request IRQ%u: %d\n",
- msm_host->irq, ret);
- return ret;
- }
-
msm_host->dev = dev;
ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K);
if (ret) {
@@ -2413,6 +2404,16 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host,
if (msm_host->disp_en_gpio)
gpiod_set_value(msm_host->disp_en_gpio, 1);
+ ret = devm_request_irq(&msm_host->pdev->dev, msm_host->irq,
+ dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "dsi_isr", msm_host);
+ if (ret < 0) {
+ DRM_DEV_ERROR(&msm_host->pdev->dev, "failed to request IRQ%u: %d\n",
+ msm_host->irq, ret);
+ return ret;
+ }
+
+
msm_host->power_on = true;
mutex_unlock(&msm_host->dev_mutex);
@@ -2439,6 +2440,8 @@ int msm_dsi_host_power_off(struct mipi_dsi_host *host)
goto unlock_ret;
}
+ devm_free_irq(&msm_host->pdev->dev, msm_host->irq, msm_host);
+
dsi_ctrl_config(msm_host, false, NULL, NULL);
if (msm_host->disp_en_gpio)
--
2.30.2
[View Less]