aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/msm')
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c59
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c94
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h1
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c7
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c2
-rw-r--r--drivers/gpu/drm/msm/msm_iommu.c43
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,