From c7b36a773ec08ce7faa59f328b6b56e9c80394df Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Tue, 2 Jul 2019 14:52:06 +0800 Subject: [PATCH] drm/rockchip: dsi: resolved dependency between mipi_tx0 and mipi_tx1 It has a shared pll for mipi_tx0/mipi_tx1 on RK3288/RK3399, so we need to initialize mipi_tx0 as necessary before enabling mipi_tx1. Change-Id: I2cd9ffe576c7a3d1e6c3081c2b174e3e971a0c4a Signed-off-by: Wyon Bi --- .../display/rockchip/dw_mipi_dsi_rockchip.txt | 2 - drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 181 +++++++++++------- 2 files changed, 117 insertions(+), 66 deletions(-) diff --git a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt index 48c059370571..98d99f3456cb 100644 --- a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt +++ b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt @@ -31,7 +31,6 @@ Optional properties - phys: phandle to Non-SNPS PHY node - phy-names: the string "mipi_dphy" when is found in a node, along with "phys" attribute, provides phandle to MIPI PHY node -- rockchip,dual-channel: for dual-channel panel, if not, don't configure - rockchip,lane-rate: manually configure lane-rate, not necessary. [1] Documentation/devicetree/bindings/clock/clock-bindings.txt @@ -52,7 +51,6 @@ For Rockchip RK3288: #address-cells = <1>; #size-cells = <0>; - rockchip,dual-channel = <&dsi1>; rockchip,lane-rate = <900>; status = "okay"; diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index 2d1db3983d40..dba07a352f5d 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c @@ -282,12 +282,11 @@ struct dw_mipi_dsi { struct clk *pclk; struct clk *h2p_clk; int irq; - - /* dual-channel */ struct dw_mipi_dsi *master; struct dw_mipi_dsi *slave; - struct device_node *panel_node; - int id; + struct mutex mutex; + bool prepared; + unsigned int id; unsigned long mode_flags; unsigned int lane_mbps; /* per lane */ @@ -802,6 +801,11 @@ static void dw_mipi_dsi_set_pll(struct dw_mipi_dsi *dsi, unsigned long rate) dsi->slave->dphy.input_div = dsi->dphy.input_div; dsi->slave->dphy.feedback_div = dsi->dphy.feedback_div; } + if (dsi->master) { + dsi->master->lane_mbps = dsi->lane_mbps; + dsi->master->dphy.input_div = dsi->dphy.input_div; + dsi->master->dphy.feedback_div = dsi->dphy.feedback_div; + } } static void dw_mipi_dsi_set_hs_clk(struct dw_mipi_dsi *dsi, unsigned long rate) @@ -816,9 +820,6 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host, { struct dw_mipi_dsi *dsi = host_to_dsi(host); - if (dsi->master) - return 0; - if (device->lanes < 1 || device->lanes > 8) return -EINVAL; @@ -1095,7 +1096,7 @@ static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi) static void mipi_dphy_init(struct dw_mipi_dsi *dsi) { - u32 map[] = {0x1, 0x3, 0x7, 0xf}; + u32 map[] = {0x0, 0x1, 0x3, 0x7, 0xf}; mipi_dphy_enableclk_deassert(dsi); mipi_dphy_shutdownz_assert(dsi); @@ -1121,7 +1122,7 @@ static void mipi_dphy_init(struct dw_mipi_dsi *dsi) dw_mipi_dsi_phy_init(dsi); /* Enable Data Lane Module */ - grf_field_write(dsi, ENABLE_N, map[dsi->lanes - 1]); + grf_field_write(dsi, ENABLE_N, map[dsi->lanes]); /* Enable Clock Lane Module */ grf_field_write(dsi, ENABLECLK, 1); @@ -1186,14 +1187,8 @@ static void dw_mipi_dsi_packet_handler_config(struct dw_mipi_dsi *dsi) static void dw_mipi_dsi_video_packet_config(struct dw_mipi_dsi *dsi, struct drm_display_mode *mode) { - int pkt_size; - - if (dsi->slave || dsi->master) - pkt_size = VID_PKT_SIZE(mode->hdisplay / 2); - else - pkt_size = VID_PKT_SIZE(mode->hdisplay); - - regmap_write(dsi->regmap, DSI_VID_PKT_SIZE, pkt_size); + regmap_write(dsi->regmap, DSI_VID_PKT_SIZE, + VID_PKT_SIZE(mode->hdisplay)); } static void dw_mipi_dsi_command_mode_config(struct dw_mipi_dsi *dsi) @@ -1211,10 +1206,8 @@ static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct dw_mipi_dsi *dsi, lbcc = hcomponent * dsi->lane_mbps * MSEC_PER_SEC / 8; - if (dsi->mode.clock == 0) { - dev_err(dsi->dev, "dsi mode clock is 0!\n"); + if (dsi->mode.clock == 0) return 0; - } return DIV_ROUND_CLOSEST_ULL(lbcc, dsi->mode.clock); } @@ -1288,8 +1281,10 @@ static void dw_mipi_dsi_encoder_mode_set(struct drm_encoder *encoder, drm_mode_copy(&dsi->mode, adjusted_mode); - if (dsi->slave) - drm_mode_copy(&dsi->slave->mode, adjusted_mode); + if (dsi->slave) { + dsi->mode.hdisplay /= 2; + drm_mode_copy(&dsi->slave->mode, &dsi->mode); + } } static void dw_mipi_dsi_disable(struct dw_mipi_dsi *dsi) @@ -1308,14 +1303,28 @@ static void dw_mipi_dsi_disable(struct dw_mipi_dsi *dsi) static void dw_mipi_dsi_post_disable(struct dw_mipi_dsi *dsi) { + if (dsi->slave) + dw_mipi_dsi_post_disable(dsi->slave); + + mutex_lock(&dsi->mutex); + + if (!dsi->prepared) { + mutex_unlock(&dsi->mutex); + return; + } + dw_mipi_dsi_interrupt_disable(dsi); dw_mipi_dsi_host_power_off(dsi); mipi_dphy_power_off(dsi); pm_runtime_put(dsi->dev); - if (dsi->slave) - dw_mipi_dsi_post_disable(dsi->slave); + dsi->prepared = false; + + mutex_unlock(&dsi->mutex); + + if (dsi->master) + dw_mipi_dsi_post_disable(dsi->master); } static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder) @@ -1352,6 +1361,16 @@ static void dw_mipi_dsi_host_init(struct dw_mipi_dsi *dsi) static void dw_mipi_dsi_pre_enable(struct dw_mipi_dsi *dsi) { + if (dsi->master) + dw_mipi_dsi_pre_enable(dsi->master); + + mutex_lock(&dsi->mutex); + + if (dsi->prepared) { + mutex_unlock(&dsi->mutex); + return; + } + pm_runtime_get_sync(dsi->dev); /* MIPI DSI APB software reset request. */ @@ -1365,6 +1384,10 @@ static void dw_mipi_dsi_pre_enable(struct dw_mipi_dsi *dsi) mipi_dphy_power_on(dsi); dw_mipi_dsi_host_power_on(dsi); + dsi->prepared = true; + + mutex_unlock(&dsi->mutex); + if (dsi->slave) dw_mipi_dsi_pre_enable(dsi->slave); } @@ -1489,6 +1512,9 @@ static int dw_mipi_dsi_loader_protect(struct dw_mipi_dsi *dsi, bool on) { u32 int_st1; + if (dsi->master) + dw_mipi_dsi_loader_protect(dsi->master, on); + if (on) { pm_runtime_get_sync(dsi->dev); regmap_read(dsi->regmap, DSI_INT_ST1, &int_st1); @@ -1573,32 +1599,6 @@ static const struct drm_connector_funcs dw_mipi_dsi_atomic_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; -static int dw_mipi_dsi_dual_channel_probe(struct dw_mipi_dsi *dsi) -{ - struct device_node *np; - struct platform_device *secondary; - - np = of_parse_phandle(dsi->dev->of_node, "rockchip,dual-channel", 0); - if (np) { - secondary = of_find_device_by_node(np); - dsi->slave = platform_get_drvdata(secondary); - of_node_put(np); - - if (!dsi->slave) - return -EPROBE_DEFER; - - dsi->slave->master = dsi; - dsi->lanes /= 2; - - dsi->slave->lanes = dsi->lanes; - dsi->slave->channel = dsi->channel; - dsi->slave->format = dsi->format; - dsi->slave->mode_flags = dsi->mode_flags; - } - - return 0; -} - static int dw_mipi_dsi_register(struct drm_device *drm, struct dw_mipi_dsi *dsi) { @@ -1669,6 +1669,50 @@ encoder_cleanup: return ret; } +static int dw_mipi_dsi_match_by_id(struct device *dev, void *data) +{ + struct dw_mipi_dsi *dsi = dev_get_drvdata(dev); + unsigned int *id = data; + + return dsi->id == *id; +} + +static struct dw_mipi_dsi *dw_mipi_dsi_find_by_id(struct device_driver *drv, + unsigned int id) +{ + struct device *dev; + + dev = driver_find_device(drv, NULL, &id, dw_mipi_dsi_match_by_id); + if (!dev) + return NULL; + + return dev_get_drvdata(dev); +} + +static void dw_mipi_dsi_rpm_enable(struct dw_mipi_dsi *dsi) +{ + if (!pm_runtime_enabled(dsi->dev)) + pm_runtime_enable(dsi->dev); + + if (dsi->slave && !pm_runtime_enabled(dsi->slave->dev)) + pm_runtime_enable(dsi->slave->dev); + + if (dsi->master && !pm_runtime_enabled(dsi->master->dev)) + pm_runtime_enable(dsi->master->dev); +} + +static void dw_mipi_dsi_rpm_disable(struct dw_mipi_dsi *dsi) +{ + if (pm_runtime_enabled(dsi->dev)) + pm_runtime_disable(dsi->dev); + + if (dsi->slave && pm_runtime_enabled(dsi->slave->dev)) + pm_runtime_disable(dsi->slave->dev); + + if (dsi->master && pm_runtime_enabled(dsi->master->dev)) + pm_runtime_enable(dsi->master->dev); +} + static int dw_mipi_dsi_bind(struct device *dev, struct device *master, void *data) { @@ -1676,13 +1720,6 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, struct dw_mipi_dsi *dsi = dev_get_drvdata(dev); int ret; - ret = dw_mipi_dsi_dual_channel_probe(dsi); - if (ret) - return ret; - - if (dsi->master) - return 0; - dsi->panel = of_drm_find_panel(dsi->client); if (!dsi->panel) { dsi->bridge = of_drm_find_bridge(dsi->client); @@ -1690,6 +1727,24 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, return -EPROBE_DEFER; } + if (dsi->id) { + dsi->master = dw_mipi_dsi_find_by_id(dev->driver, 0); + if (!dsi->master) + return -EPROBE_DEFER; + } + + if (dsi->lanes > 4) { + dsi->slave = dw_mipi_dsi_find_by_id(dev->driver, 1); + if (!dsi->slave) + return -EPROBE_DEFER; + + dsi->lanes /= 2; + dsi->slave->lanes = dsi->lanes; + dsi->slave->channel = dsi->channel; + dsi->slave->format = dsi->format; + dsi->slave->mode_flags = dsi->mode_flags; + } + ret = dw_mipi_dsi_register(drm, dsi); if (ret) { dev_err(dev, "Failed to register mipi_dsi: %d\n", ret); @@ -1698,9 +1753,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, dev_set_drvdata(dev, dsi); - pm_runtime_enable(dev); - if (dsi->slave) - pm_runtime_enable(dsi->slave->dev); + dw_mipi_dsi_rpm_enable(dsi); return ret; } @@ -1710,12 +1763,10 @@ static void dw_mipi_dsi_unbind(struct device *dev, struct device *master, { struct dw_mipi_dsi *dsi = dev_get_drvdata(dev); + dw_mipi_dsi_rpm_disable(dsi); + if (dsi->panel) drm_panel_detach(dsi->panel); - - pm_runtime_disable(dev); - if (dsi->slave) - pm_runtime_disable(dsi->slave->dev); } static const struct component_ops dw_mipi_dsi_ops = { @@ -1898,6 +1949,8 @@ static int dw_mipi_dsi_probe(struct platform_device *pdev) if (!dsi) return -ENOMEM; + mutex_init(&dsi->mutex); + dsi_id = of_alias_get_id(np, "dsi"); if (dsi_id < 0) dsi_id = 0;