diff options
Diffstat (limited to 'drivers/gpu/drm/msm')
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi_host.c | 59 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c | 94 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_drv.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_iommu.c | 43 |
6 files changed, 148 insertions, 58 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 8d82973fe9db..d62e11eb3a55 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -131,6 +131,7 @@ struct msm_dsi_host { enum mipi_dsi_pixel_format format; unsigned long mode_flags; + u32 dlane_swap; u32 dma_cmd_ctrl_restore; bool registered; @@ -684,19 +685,9 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable, data = DSI_CTRL_CLK_EN; DBG("lane number=%d", msm_host->lanes); - if (msm_host->lanes == 2) { - data |= DSI_CTRL_LANE1 | DSI_CTRL_LANE2; - /* swap lanes for 2-lane panel for better performance */ - dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL, - DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(LANE_SWAP_1230)); - } else { - /* Take 4 lanes as default */ - data |= DSI_CTRL_LANE0 | DSI_CTRL_LANE1 | DSI_CTRL_LANE2 | - DSI_CTRL_LANE3; - /* Do not swap lanes for 4-lane panel */ - dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL, - DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(LANE_SWAP_0123)); - } + data |= ((DSI_CTRL_LANE0 << msm_host->lanes) - DSI_CTRL_LANE0); + dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL, + DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(msm_host->dlane_swap)); if (!(flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)) dsi_write(msm_host, REG_DSI_LANE_CTRL, @@ -765,7 +756,9 @@ static void dsi_sw_reset(struct msm_dsi_host *msm_host) dsi_write(msm_host, REG_DSI_RESET, 1); wmb(); /* make sure reset happen */ + mdelay(100); dsi_write(msm_host, REG_DSI_RESET, 0); + wmb(); } static void dsi_op_mode_config(struct msm_dsi_host *msm_host, @@ -1289,20 +1282,21 @@ static int dsi_host_attach(struct mipi_dsi_host *host, struct msm_dsi_host *msm_host = to_msm_dsi_host(host); int ret; + if (dsi->lanes > 4 || dsi->channel > 3) + return -EINVAL; + msm_host->channel = dsi->channel; msm_host->lanes = dsi->lanes; msm_host->format = dsi->format; msm_host->mode_flags = dsi->mode_flags; - WARN_ON(dsi->dev.of_node != msm_host->device_node); - /* Some gpios defined in panel DT need to be controlled by host */ ret = dsi_host_init_panel_gpios(msm_host, &dsi->dev); if (ret) return ret; DBG("id=%d", msm_host->id); - if (msm_host->dev) + if (msm_host->dev && of_drm_find_panel(msm_host->device_node)) drm_helper_hpd_irq_event(msm_host->dev); return 0; @@ -1316,7 +1310,7 @@ static int dsi_host_detach(struct mipi_dsi_host *host, msm_host->device_node = NULL; DBG("id=%d", msm_host->id); - if (msm_host->dev) + if (msm_host->dev && of_drm_find_panel(msm_host->device_node)) drm_helper_hpd_irq_event(msm_host->dev); return 0; @@ -1344,6 +1338,33 @@ static struct mipi_dsi_host_ops dsi_host_ops = { .transfer = dsi_host_transfer, }; +static void dsi_parse_dlane_swap(struct msm_dsi_host *msm_host, + struct device_node *np) +{ + const char *lane_swap; + + lane_swap = of_get_property(np, "qcom,dsi-logical-lane-swap", NULL); + + if (!lane_swap) + msm_host->dlane_swap = LANE_SWAP_0123; + else if (!strncmp(lane_swap, "3012", 5)) + msm_host->dlane_swap = LANE_SWAP_3012; + else if (!strncmp(lane_swap, "2301", 5)) + msm_host->dlane_swap = LANE_SWAP_2301; + else if (!strncmp(lane_swap, "1230", 5)) + msm_host->dlane_swap = LANE_SWAP_1230; + else if (!strncmp(lane_swap, "0321", 5)) + msm_host->dlane_swap = LANE_SWAP_0321; + else if (!strncmp(lane_swap, "1032", 5)) + msm_host->dlane_swap = LANE_SWAP_1032; + else if (!strncmp(lane_swap, "2103", 5)) + msm_host->dlane_swap = LANE_SWAP_2103; + else if (!strncmp(lane_swap, "3210", 5)) + msm_host->dlane_swap = LANE_SWAP_3210; + else + msm_host->dlane_swap = LANE_SWAP_0123; +} + static int dsi_host_parse_dt(struct msm_dsi_host *msm_host) { struct device *dev = &msm_host->pdev->dev; @@ -1358,6 +1379,8 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host) return ret; } + dsi_parse_dlane_swap(msm_host, np); + /* * Get the first endpoint node. In our case, dsi has one output port * to which the panel is connected. Don't return an error if a port @@ -1862,7 +1885,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host) dsi_phy_sw_reset(msm_host); ret = msm_dsi_manager_phy_enable(msm_host->id, msm_host->byte_clk_rate * 8, - clk_get_rate(msm_host->esc_clk), + 19200000,/*clk_get_rate(msm_host->esc_clk),*/ &clk_pre, &clk_post); dsi_bus_clk_disable(msm_host); if (ret) { diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c index 077f7521a971..5e812b60a69d 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c @@ -182,9 +182,20 @@ static void mdp4_preclose(struct msm_kms *kms, struct drm_file *file) mdp4_crtc_cancel_pending_flip(priv->crtcs[i], file); } +static const char *iommu_ports[] = { + "mdp_port0_cb0", "mdp_port1_cb0", +}; + static void mdp4_destroy(struct msm_kms *kms) { struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms)); + struct msm_mmu *mmu = mdp4_kms->mmu; + + if (mmu) { + mmu->funcs->detach(mmu, iommu_ports, ARRAY_SIZE(iommu_ports)); + mmu->funcs->destroy(mmu); + } + if (mdp4_kms->blank_cursor_iova) msm_gem_put_iova(mdp4_kms->blank_cursor_bo, mdp4_kms->id); if (mdp4_kms->blank_cursor_bo) @@ -262,6 +273,11 @@ static struct drm_panel *detect_panel(struct drm_device *dev) of_node_put(endpoint); + if (!of_device_is_available(panel_node)) { + dev_err(dev->dev, "panel is not enabled in DT\n"); + return ERR_PTR(-ENODEV); + } + panel = of_drm_find_panel(panel_node); if (!panel) { of_node_put(panel_node); @@ -313,45 +329,55 @@ static int modeset_init(struct mdp4_kms *mdp4_kms) if (IS_ERR(panel)) { ret = PTR_ERR(panel); dev_err(dev->dev, "failed to detect LVDS panel: %d\n", ret); - goto fail; - } + /** + * Only fail if there is panel but not ready yet + * continue with other stuff if there is no panel connected. + */ + if (ret == -EPROBE_DEFER) + goto fail; + } else { + plane = mdp4_plane_init(dev, RGB2, true); + if (IS_ERR(plane)) { + dev_err(dev->dev, + "failed to construct plane for RGB2\n"); + ret = PTR_ERR(plane); + goto fail; + } - plane = mdp4_plane_init(dev, RGB2, true); - if (IS_ERR(plane)) { - dev_err(dev->dev, "failed to construct plane for RGB2\n"); - ret = PTR_ERR(plane); - goto fail; - } + crtc = mdp4_crtc_init(dev, plane, priv->num_crtcs, 0, DMA_P); + if (IS_ERR(crtc)) { + dev_err(dev->dev, + "failed to construct crtc for DMA_P\n"); + ret = PTR_ERR(crtc); + goto fail; + } - crtc = mdp4_crtc_init(dev, plane, priv->num_crtcs, 0, DMA_P); - if (IS_ERR(crtc)) { - dev_err(dev->dev, "failed to construct crtc for DMA_P\n"); - ret = PTR_ERR(crtc); - goto fail; - } + encoder = mdp4_lcdc_encoder_init(dev, panel); + if (IS_ERR(encoder)) { + dev_err(dev->dev, + "failed to construct LCDC encoder\n"); + ret = PTR_ERR(encoder); + goto fail; + } - encoder = mdp4_lcdc_encoder_init(dev, panel); - if (IS_ERR(encoder)) { - dev_err(dev->dev, "failed to construct LCDC encoder\n"); - ret = PTR_ERR(encoder); - goto fail; - } + /* LCDC can be hooked to DMA_P: */ + encoder->possible_crtcs = 1 << priv->num_crtcs; - /* LCDC can be hooked to DMA_P: */ - encoder->possible_crtcs = 1 << priv->num_crtcs; + priv->crtcs[priv->num_crtcs++] = crtc; + priv->encoders[priv->num_encoders++] = encoder; - priv->crtcs[priv->num_crtcs++] = crtc; - priv->encoders[priv->num_encoders++] = encoder; + connector = mdp4_lvds_connector_init(dev, panel, encoder); + if (IS_ERR(connector)) { + ret = PTR_ERR(connector); + dev_err(dev->dev, + "failed to initialize LVDS connector: %d\n", + ret); + goto fail; + } - connector = mdp4_lvds_connector_init(dev, panel, encoder); - if (IS_ERR(connector)) { - ret = PTR_ERR(connector); - dev_err(dev->dev, "failed to initialize LVDS connector: %d\n", ret); - goto fail; + priv->connectors[priv->num_connectors++] = connector; } - priv->connectors[priv->num_connectors++] = connector; - /* * Setup DTV/HDMI path: RGB1 -> DMA_E -> DTV -> HDMI: */ @@ -398,10 +424,6 @@ fail: return ret; } -static const char *iommu_ports[] = { - "mdp_port0_cb0", "mdp_port1_cb0", -}; - struct msm_kms *mdp4_kms_init(struct drm_device *dev) { struct platform_device *pdev = dev->platformdev; @@ -506,6 +528,8 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev) ARRAY_SIZE(iommu_ports)); if (ret) goto fail; + + mdp4_kms->mmu = mmu; } else { dev_info(dev->dev, "no iommu, fallback to phys " "contig buffers for scanout\n"); diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h index 8a7f6e1e2bca..b3ab4ea0ecf0 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h @@ -45,6 +45,7 @@ struct mdp4_kms { struct clk *pclk; struct clk *lut_clk; struct clk *axi_clk; + struct msm_mmu *mmu; struct mdp_irq error_handler; diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index 047cb0433ccb..b50cc5c65b65 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c @@ -32,6 +32,7 @@ static int mdp5_hw_init(struct msm_kms *kms) unsigned long flags; pm_runtime_get_sync(dev->dev); + mdp5_enable(mdp5_kms); /* Magic unknown register writes: * @@ -63,7 +64,8 @@ static int mdp5_hw_init(struct msm_kms *kms) mdp5_ctlm_hw_reset(mdp5_kms->ctlm); - pm_runtime_put_sync(dev->dev); + mdp5_disable(mdp5_kms); + //pm_runtime_put_sync(dev->dev); return 0; } @@ -578,7 +580,8 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev) continue; mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(i), 0); } - mdp5_disable(mdp5_kms); + /* TODO: Remove this after runtime pm adaptation */ + //mdp5_disable(mdp5_kms); mdelay(16); if (config->platform.iommu) { diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 0339c5d82d37..28c9a2aeb314 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -415,7 +415,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags) pm_runtime_get_sync(dev->dev); ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0)); - pm_runtime_put_sync(dev->dev); + //pm_runtime_put_sync(dev->dev); if (ret < 0) { dev_err(dev->dev, "failed to install IRQ handler\n"); goto fail; diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index 7ac2f1997e4a..f033d48cd1f3 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -18,6 +18,8 @@ #include "msm_drv.h" #include "msm_mmu.h" +#define DUMMY_CONTEXT 0x1 + struct msm_iommu { struct msm_mmu base; struct iommu_domain *domain; @@ -33,14 +35,51 @@ static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev, static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt) { + struct device *dev = mmu->dev; struct msm_iommu *iommu = to_msm_iommu(mmu); - return iommu_attach_device(iommu->domain, mmu->dev); + int i, ret; + + for (i = 0; i < cnt; i++) { + struct device *msm_iommu_get_ctx(const char *ctx_name); + struct device *ctx = msm_iommu_get_ctx(names[i]); + if (IS_ERR_OR_NULL(ctx)) { + dev_warn(dev, "couldn't get %s context", names[i]); + continue; + } + + if (ctx == (struct device *)DUMMY_CONTEXT) { + return iommu_attach_device(iommu->domain, mmu->dev); + } else { + ret = iommu_attach_device(iommu->domain, ctx); + } + + if (ret) { + dev_warn(dev, "could not attach iommu to %s", names[i]); + return ret; + } + } + + return 0; } static void msm_iommu_detach(struct msm_mmu *mmu, const char **names, int cnt) { struct msm_iommu *iommu = to_msm_iommu(mmu); - iommu_detach_device(iommu->domain, mmu->dev); + int i; + + for (i = 0; i < cnt; i++) { + struct device *msm_iommu_get_ctx(const char *ctx_name); + struct device *ctx = msm_iommu_get_ctx(names[i]); + if (IS_ERR_OR_NULL(ctx)) + continue; + + if (ctx == (struct device *)DUMMY_CONTEXT) { + iommu_detach_device(iommu->domain, mmu->dev); + break; + } else { + iommu_detach_device(iommu->domain, ctx); + } + } } static int msm_iommu_map(struct msm_mmu *mmu, uint32_t iova, |