diff options
author | Jan-Simon Moeller <jsmoeller@linuxfoundation.org> | 2019-06-09 21:55:28 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@automotivelinux.org> | 2019-06-09 21:55:28 +0000 |
commit | 50a2eecc8e61647a2a5142a154232fe87fdd37f9 (patch) | |
tree | b7784813fdd658322504fd89cb4163f4d34db302 /meta-agl-bsp/meta-raspberrypi/recipes-kernel/linux/linux-raspberrypi/dsi/0003-drm-vc4-Set-up-the-DSI-host-at-pdev-probe-time-not-c.patch | |
parent | df96ae5d6ac1039a228026f76e93a6499d61762a (diff) | |
parent | ccb667c35ffdea7a2bc1304750e6b22368cd55f7 (diff) |
Merge "Fix rpi touchscreen support on master"
Diffstat (limited to 'meta-agl-bsp/meta-raspberrypi/recipes-kernel/linux/linux-raspberrypi/dsi/0003-drm-vc4-Set-up-the-DSI-host-at-pdev-probe-time-not-c.patch')
-rw-r--r-- | meta-agl-bsp/meta-raspberrypi/recipes-kernel/linux/linux-raspberrypi/dsi/0003-drm-vc4-Set-up-the-DSI-host-at-pdev-probe-time-not-c.patch | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/meta-agl-bsp/meta-raspberrypi/recipes-kernel/linux/linux-raspberrypi/dsi/0003-drm-vc4-Set-up-the-DSI-host-at-pdev-probe-time-not-c.patch b/meta-agl-bsp/meta-raspberrypi/recipes-kernel/linux/linux-raspberrypi/dsi/0003-drm-vc4-Set-up-the-DSI-host-at-pdev-probe-time-not-c.patch new file mode 100644 index 000000000..0e6e068fe --- /dev/null +++ b/meta-agl-bsp/meta-raspberrypi/recipes-kernel/linux/linux-raspberrypi/dsi/0003-drm-vc4-Set-up-the-DSI-host-at-pdev-probe-time-not-c.patch @@ -0,0 +1,217 @@ +From 2ccd080392adfb1f077f2f4d289651b6b15e0951 Mon Sep 17 00:00:00 2001 +From: Kevin Quigley <kevin@kquigley.co.uk> +Date: Mon, 24 Sep 2018 18:09:52 +0000 +Subject: [PATCH 3/4] drm/vc4: Set up the DSI host at pdev probe time, not + component bind. bring https://patchwork.kernel.org/patch/9902623/ to Linux + 4.14.y + +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. +--- + drivers/gpu/drm/vc4/vc4_dsi.c | 93 ++++++++++++++++++++--------------- + 1 file changed, 53 insertions(+), 40 deletions(-) + +diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c +index 3fa2db18d70f..faf38f17ec26 100644 +--- a/drivers/gpu/drm/vc4/vc4_dsi.c ++++ b/drivers/gpu/drm/vc4/vc4_dsi.c +@@ -33,6 +33,7 @@ + #include <drm/drm_crtc_helper.h> + #include <drm/drm_edid.h> + #include <drm/drm_mipi_dsi.h> ++#include <drm/drm_of.h> + #include <drm/drm_panel.h> + #include <linux/clk.h> + #include <linux/clk-provider.h> +@@ -504,7 +505,6 @@ struct vc4_dsi { + struct mipi_dsi_host dsi_host; + struct drm_encoder *encoder; + struct drm_bridge *bridge; +- bool is_panel_bridge; + + void __iomem *regs; + +@@ -1300,7 +1300,6 @@ static int vc4_dsi_host_attach(struct mipi_dsi_host *host, + struct mipi_dsi_device *device) + { + struct vc4_dsi *dsi = host_to_dsi(host); +- int ret = 0; + + dsi->lanes = device->lanes; + dsi->channel = device->channel; +@@ -1335,33 +1334,12 @@ static int vc4_dsi_host_attach(struct mipi_dsi_host *host, + return 0; + } + +- dsi->bridge = of_drm_find_bridge(device->dev.of_node); +- if (!dsi->bridge) { +- struct drm_panel *panel = +- of_drm_find_panel(device->dev.of_node); +- +- dsi->bridge = drm_panel_bridge_add(panel, +- DRM_MODE_CONNECTOR_DSI); +- if (IS_ERR(dsi->bridge)) { +- ret = PTR_ERR(dsi->bridge); +- dsi->bridge = NULL; +- return ret; +- } +- dsi->is_panel_bridge = true; +- } +- +- return drm_bridge_attach(dsi->encoder, dsi->bridge, NULL); ++ return 0; + } + + static int vc4_dsi_host_detach(struct mipi_dsi_host *host, + struct mipi_dsi_device *device) + { +- struct vc4_dsi *dsi = host_to_dsi(host); +- +- if (dsi->is_panel_bridge) { +- drm_panel_bridge_remove(dsi->bridge); +- dsi->bridge = NULL; +- } + + return 0; + } +@@ -1525,16 +1503,13 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) + struct platform_device *pdev = to_platform_device(dev); + struct drm_device *drm = dev_get_drvdata(master); + struct vc4_dev *vc4 = to_vc4_dev(drm); +- struct vc4_dsi *dsi; ++ struct vc4_dsi *dsi = dev_get_drvdata(dev); + struct vc4_dsi_encoder *vc4_dsi_encoder; ++ struct drm_panel *panel; + const struct of_device_id *match; + dma_cap_mask_t dma_mask; + int ret; + +- dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); +- if (!dsi) +- return -ENOMEM; +- + match = of_match_device(vc4_dsi_dt_match, dev); + if (!match) + return -ENODEV; +@@ -1549,7 +1524,6 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) + vc4_dsi_encoder->dsi = dsi; + dsi->encoder = &vc4_dsi_encoder->base.base; + +- dsi->pdev = pdev; + dsi->regs = vc4_ioremap_regs(pdev, 0); + if (IS_ERR(dsi->regs)) + return PTR_ERR(dsi->regs); +@@ -1637,6 +1611,18 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) + return ret; + } + ++ ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, ++ &panel, &dsi->bridge); ++ if (ret) ++ return ret; ++ ++ if (panel) { ++ dsi->bridge = devm_drm_panel_bridge_add(dev, panel, ++ DRM_MODE_CONNECTOR_DSI); ++ if (IS_ERR(dsi->bridge)) ++ return PTR_ERR(dsi->bridge); ++ } ++ + /* The esc clock rate is supposed to always be 100Mhz. */ + ret = clk_set_rate(dsi->escape_clock, 100 * 1000000); + if (ret) { +@@ -1655,13 +1641,6 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) + DRM_MODE_ENCODER_DSI, NULL); + drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs); + +- dsi->dsi_host.ops = &vc4_dsi_host_ops; +- dsi->dsi_host.dev = dev; +- +- mipi_dsi_host_register(&dsi->dsi_host); +- +- dev_set_drvdata(dev, dsi); +- + ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL); + if (ret) { + dev_err(dev, "bridge attach failed: %d\n", ret); +@@ -1672,6 +1651,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) + * from our driver, since we need to sequence them within the + * encoder's enable/disable paths. + */ ++ + dsi->encoder->bridge = NULL; + + pm_runtime_enable(dev); +@@ -1690,8 +1670,6 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master, + + vc4_dsi_encoder_destroy(dsi->encoder); + +- mipi_dsi_host_unregister(&dsi->dsi_host); +- + if (dsi->port == 1) + vc4->dsi1 = NULL; + } +@@ -1703,12 +1681,47 @@ static const struct component_ops vc4_dsi_ops = { + + static int vc4_dsi_dev_probe(struct platform_device *pdev) + { +- return component_add(&pdev->dev, &vc4_dsi_ops); ++ struct device *dev = &pdev->dev; ++ struct vc4_dsi *dsi; ++ int ret; ++ ++ dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); ++ if (!dsi) ++ return -ENOMEM; ++ dev_set_drvdata(dev, dsi); ++ ++ dsi->pdev = pdev; ++ ++ /* Note, the initialization sequence for DSI and panels is ++ * tricky. The component bind above won't get past its ++ * -EPROBE_DEFER until the panel/bridge probes. The ++ * panel/bridge will return -EPROBE_DEFER until it has a ++ * mipi_dsi_host to register its device to. So, we register ++ * the host during pdev probe time, so vc4 as a whole can then ++ * -EPROBE_DEFER its component bind process until the panel ++ * successfully attaches. ++ */ ++ dsi->dsi_host.ops = &vc4_dsi_host_ops; ++ dsi->dsi_host.dev = dev; ++ mipi_dsi_host_register(&dsi->dsi_host); ++ ++ ret = component_add(&pdev->dev, &vc4_dsi_ops); ++ if (ret) { ++ mipi_dsi_host_unregister(&dsi->dsi_host); ++ return ret; ++ } ++ ++ return 0; + } + + static int vc4_dsi_dev_remove(struct platform_device *pdev) + { ++ struct device *dev = &pdev->dev; ++ struct vc4_dsi *dsi = dev_get_drvdata(dev); ++ + component_del(&pdev->dev, &vc4_dsi_ops); ++ mipi_dsi_host_unregister(&dsi->dsi_host); ++ + return 0; + } + +-- +2.21.0 + |