summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorClarence Ip <cip@codeaurora.org>2016-11-24 17:06:29 -0500
committerClarence Ip <cip@codeaurora.org>2016-11-25 13:33:39 -0500
commit3537e5234a9cc8ce5a0dc970e2db87d06f423074 (patch)
treefeccda09187f0c658ca589ccf79c5b0b7a17d21d /drivers/gpu
parent857addaf00d0b9ead743bd434e8785fd41f20c19 (diff)
drm/msm/sde: move sde hw init to hw_init callback
Callbacks from the upper layer expect hardware initialization logic to reside within the hw_init callback. Consolidate all hw initialization to the hw_init callback and update the deinit and destroy callbacks to match it. Change-Id: I2ab32edae0e8586ddb4701b3d8c5cfde9e611cad Signed-off-by: Clarence Ip <cip@codeaurora.org>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c18
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_catalog.c4
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_catalog.h8
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.c271
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.h1
5 files changed, 171 insertions, 131 deletions
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index fb03350e0132..7ed00ea06b2a 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -490,6 +490,15 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
}
priv->kms = kms;
+ pm_runtime_enable(dev->dev);
+
+ if (kms && kms->funcs && kms->funcs->hw_init) {
+ ret = kms->funcs->hw_init(kms);
+ if (ret) {
+ dev_err(dev->dev, "kms hw init failed: %d\n", ret);
+ goto fail;
+ }
+ }
/* initialize commit thread structure */
for (i = 0; i < priv->num_crtcs; i++) {
@@ -514,15 +523,6 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
}
}
- if (kms) {
- pm_runtime_enable(dev->dev);
- ret = kms->funcs->hw_init(kms);
- if (ret) {
- dev_err(dev->dev, "kms hw init failed: %d\n", ret);
- goto fail;
- }
- }
-
dev->mode_config.funcs = &mode_config_funcs;
ret = drm_vblank_init(dev, priv->num_crtcs);
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
index f8c753d2a8dd..cc2bf7234999 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
@@ -1822,7 +1822,7 @@ static void sde_hardware_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
}
}
-static void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg)
+void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg)
{
int i;
@@ -1848,6 +1848,7 @@ static void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg)
kfree(sde_cfg->vbif[i].dynamic_ot_rd_tbl.cfg);
kfree(sde_cfg->vbif[i].dynamic_ot_wr_tbl.cfg);
}
+ kfree(sde_cfg);
}
/*************************************************************
@@ -1913,6 +1914,5 @@ struct sde_mdss_cfg *sde_hw_catalog_init(struct drm_device *dev, u32 hw_rev)
end:
sde_hw_catalog_deinit(sde_cfg);
- kfree(sde_cfg);
return NULL;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
index 5ca297a46b26..26bb832b5fa3 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
@@ -681,7 +681,7 @@ struct sde_mdss_hw_cfg_handler {
#define BLK_AD(s) ((s)->ad)
/**
- * sde_hw_catalog_init() - sde hardware catalog init API parses dtsi property
+ * sde_hw_catalog_init - sde hardware catalog init API parses dtsi property
* and stores all parsed offset, hardware capabilities in config structure.
* @dev: drm device node.
* @hw_rev: caller needs provide the hardware revision before parsing.
@@ -690,4 +690,10 @@ struct sde_mdss_hw_cfg_handler {
*/
struct sde_mdss_cfg *sde_hw_catalog_init(struct drm_device *dev, u32 hw_rev);
+/**
+ * sde_hw_catalog_deinit - sde hardware catalog cleanup
+ * @sde_cfg: pointer returned from init function
+ */
+void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg);
+
#endif /* _SDE_HW_CATALOG_H */
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index c834f6dad83a..1b523767f523 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -70,6 +70,9 @@ static bool sdecustom = true;
module_param(sdecustom, bool, 0400);
MODULE_PARM_DESC(sdecustom, "Enable customizations for sde clients");
+static int sde_kms_hw_init(struct msm_kms *kms);
+static int _sde_kms_mmu_destroy(struct sde_kms *sde_kms);
+
bool sde_is_custom_client(void)
{
return sdecustom;
@@ -567,15 +570,21 @@ static void _sde_kms_drm_obj_destroy(struct sde_kms *sde_kms)
for (i = 0; i < priv->num_crtcs; i++)
priv->crtcs[i]->funcs->destroy(priv->crtcs[i]);
+ priv->num_crtcs = 0;
for (i = 0; i < priv->num_planes; i++)
priv->planes[i]->funcs->destroy(priv->planes[i]);
+ priv->num_planes = 0;
for (i = 0; i < priv->num_connectors; i++)
priv->connectors[i]->funcs->destroy(priv->connectors[i]);
+ priv->num_connectors = 0;
for (i = 0; i < priv->num_encoders; i++)
priv->encoders[i]->funcs->destroy(priv->encoders[i]);
+ priv->num_encoders = 0;
+
+ _sde_kms_release_displays(sde_kms);
}
static int _sde_kms_drm_obj_init(struct sde_kms *sde_kms)
@@ -660,11 +669,6 @@ fail:
return ret;
}
-static int sde_kms_hw_init(struct msm_kms *kms)
-{
- return 0;
-}
-
static int sde_kms_postinit(struct msm_kms *kms)
{
struct sde_kms *sde_kms = to_sde_kms(kms);
@@ -691,11 +695,34 @@ static long sde_kms_round_pixclk(struct msm_kms *kms, unsigned long rate,
return rate;
}
-static void sde_kms_destroy(struct msm_kms *kms)
+static void _sde_kms_hw_destroy(struct sde_kms *sde_kms,
+ struct platform_device *pdev)
{
- struct sde_kms *sde_kms = to_sde_kms(kms);
+ struct drm_device *dev;
+ struct msm_drm_private *priv;
int i;
+ if (!sde_kms || !pdev)
+ return;
+
+ dev = sde_kms->dev;
+ if (!dev)
+ return;
+
+ priv = dev->dev_private;
+ if (!priv)
+ return;
+
+ if (sde_kms->hw_intr)
+ sde_hw_intr_destroy(sde_kms->hw_intr);
+ sde_kms->hw_intr = NULL;
+
+ _sde_kms_release_displays(sde_kms);
+
+ /* safe to call these more than once during shutdown */
+ _sde_debugfs_destroy(sde_kms);
+ _sde_kms_mmu_destroy(sde_kms);
+
for (i = 0; i < sde_kms->catalog->vbif_count; i++) {
u32 vbif_idx = sde_kms->catalog->vbif[i].id;
@@ -703,10 +730,49 @@ static void sde_kms_destroy(struct msm_kms *kms)
sde_hw_vbif_destroy(sde_kms->hw_vbif[vbif_idx]);
}
- _sde_kms_release_displays(sde_kms);
- _sde_debugfs_destroy(sde_kms);
- sde_hw_intr_destroy(sde_kms->hw_intr);
- sde_rm_destroy(&sde_kms->rm);
+ if (sde_kms->rm_init)
+ sde_rm_destroy(&sde_kms->rm);
+ sde_kms->rm_init = false;
+
+ if (sde_kms->catalog)
+ sde_hw_catalog_deinit(sde_kms->catalog);
+ sde_kms->catalog = NULL;
+
+ if (sde_kms->core_client)
+ sde_power_client_destroy(&priv->phandle, sde_kms->core_client);
+ sde_kms->core_client = NULL;
+
+ if (sde_kms->vbif[VBIF_NRT])
+ msm_iounmap(pdev, sde_kms->vbif[VBIF_NRT]);
+ sde_kms->vbif[VBIF_NRT] = NULL;
+
+ if (sde_kms->vbif[VBIF_RT])
+ msm_iounmap(pdev, sde_kms->vbif[VBIF_RT]);
+ sde_kms->vbif[VBIF_RT] = NULL;
+
+ if (sde_kms->mmio)
+ msm_iounmap(pdev, sde_kms->mmio);
+ sde_kms->mmio = NULL;
+}
+
+static void sde_kms_destroy(struct msm_kms *kms)
+{
+ struct sde_kms *sde_kms;
+ struct drm_device *dev;
+
+ if (!kms) {
+ SDE_ERROR("invalid kms\n");
+ return;
+ }
+
+ sde_kms = to_sde_kms(kms);
+ dev = sde_kms->dev;
+ if (!dev) {
+ SDE_ERROR("invalid device\n");
+ return;
+ }
+
+ _sde_kms_hw_destroy(sde_kms, dev->platformdev);
kfree(sde_kms);
}
@@ -743,7 +809,7 @@ static const struct msm_kms_funcs kms_funcs = {
};
/* the caller api needs to turn on clock before calling it */
-static void _sde_kms_core_hw_rev_init(struct sde_kms *sde_kms)
+static inline void _sde_kms_core_hw_rev_init(struct sde_kms *sde_kms)
{
sde_kms->core_rev = readl_relaxed(sde_kms->mmio + 0x0);
}
@@ -811,112 +877,69 @@ fail:
return ret;
}
-static struct sde_kms *_sde_kms_hw_setup(struct platform_device *pdev)
+static int sde_kms_hw_init(struct msm_kms *kms)
{
struct sde_kms *sde_kms;
- int ret = 0;
+ struct drm_device *dev;
+ struct msm_drm_private *priv;
+ int i, rc = -EINVAL;
- sde_kms = kzalloc(sizeof(*sde_kms), GFP_KERNEL);
- if (!sde_kms)
- return ERR_PTR(-ENOMEM);
+ if (!kms) {
+ SDE_ERROR("invalid kms\n");
+ goto end;
+ }
- sde_kms->mmio = msm_ioremap(pdev, "mdp_phys", "SDE");
+ sde_kms = to_sde_kms(kms);
+ dev = sde_kms->dev;
+ if (!dev || !dev->platformdev) {
+ SDE_ERROR("invalid device\n");
+ goto end;
+ }
+
+ priv = dev->dev_private;
+ if (!priv) {
+ SDE_ERROR("invalid private data\n");
+ goto end;
+ }
+
+ sde_kms->mmio = msm_ioremap(dev->platformdev, "mdp_phys", "SDE");
if (IS_ERR(sde_kms->mmio)) {
- ret = PTR_ERR(sde_kms->mmio);
- SDE_ERROR("mdp register memory map failed: %d\n", ret);
+ rc = PTR_ERR(sde_kms->mmio);
+ SDE_ERROR("mdp register memory map failed: %d\n", rc);
sde_kms->mmio = NULL;
- goto err;
+ goto error;
}
DRM_INFO("mapped mdp address space @%p\n", sde_kms->mmio);
- sde_kms->vbif[VBIF_RT] = msm_ioremap(pdev, "vbif_phys", "VBIF");
+ sde_kms->vbif[VBIF_RT] = msm_ioremap(dev->platformdev,
+ "vbif_phys", "VBIF");
if (IS_ERR(sde_kms->vbif[VBIF_RT])) {
- ret = PTR_ERR(sde_kms->vbif[VBIF_RT]);
- SDE_ERROR("vbif register memory map failed: %d\n", ret);
+ rc = PTR_ERR(sde_kms->vbif[VBIF_RT]);
+ SDE_ERROR("vbif register memory map failed: %d\n", rc);
sde_kms->vbif[VBIF_RT] = NULL;
- goto vbif_map_err;
+ goto error;
}
- sde_kms->vbif[VBIF_NRT] = msm_ioremap(pdev, "vbif_nrt_phys",
- "VBIF_NRT");
+ sde_kms->vbif[VBIF_NRT] = msm_ioremap(dev->platformdev,
+ "vbif_nrt_phys", "VBIF_NRT");
if (IS_ERR(sde_kms->vbif[VBIF_NRT])) {
sde_kms->vbif[VBIF_NRT] = NULL;
SDE_DEBUG("VBIF NRT is not defined");
}
- /* junk API - no error return for init api */
- msm_kms_init(&sde_kms->base, &kms_funcs);
- if (ret) {
- SDE_ERROR("mdp/kms hw init failed\n");
- goto kms_init_err;
- }
-
- SDE_DEBUG("sde hw setup successful\n");
-
- return sde_kms;
-
-kms_init_err:
- if (sde_kms->vbif[VBIF_NRT])
- msm_iounmap(pdev, sde_kms->vbif[VBIF_NRT]);
- if (sde_kms->vbif[VBIF_RT])
- msm_iounmap(pdev, sde_kms->vbif[VBIF_RT]);
-vbif_map_err:
- if (sde_kms->mmio)
- msm_iounmap(pdev, sde_kms->mmio);
-err:
- kfree(sde_kms);
- return ERR_PTR(ret);
-}
-
-static void _sde_kms_hw_destroy(struct sde_kms *sde_kms,
- struct platform_device *pdev)
-{
- if (sde_kms->vbif[VBIF_NRT])
- msm_iounmap(pdev, sde_kms->vbif[VBIF_NRT]);
- if (sde_kms->vbif[VBIF_RT])
- msm_iounmap(pdev, sde_kms->vbif[VBIF_RT]);
- if (sde_kms->mmio)
- msm_iounmap(pdev, sde_kms->mmio);
- kfree(sde_kms);
-}
-
-struct msm_kms *sde_kms_init(struct drm_device *dev)
-{
- struct msm_drm_private *priv;
- struct sde_kms *sde_kms;
- int i;
- int rc;
-
- if (!dev) {
- SDE_ERROR("drm device node invalid\n");
- rc = -EINVAL;
- goto end;
- }
-
- priv = dev->dev_private;
- sde_kms = _sde_kms_hw_setup(dev->platformdev);
- if (IS_ERR_OR_NULL(sde_kms)) {
- rc = PTR_ERR(sde_kms);
- SDE_ERROR("sde hw setup failed: %d\n", rc);
- goto end;
- }
-
- sde_kms->dev = dev;
- priv->kms = &sde_kms->base;
-
sde_kms->core_client = sde_power_client_create(&priv->phandle, "core");
if (IS_ERR_OR_NULL(sde_kms->core_client)) {
rc = PTR_ERR(sde_kms->core_client);
SDE_ERROR("sde power client create failed: %d\n", rc);
sde_kms->core_client = NULL;
- goto kms_destroy;
+ goto error;
}
rc = sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
true);
if (rc) {
SDE_ERROR("resource enable failed: %d\n", rc);
- goto clk_enable_err;
+ goto error;
}
_sde_kms_core_hw_rev_init(sde_kms);
@@ -928,20 +951,24 @@ struct msm_kms *sde_kms_init(struct drm_device *dev)
rc = PTR_ERR(sde_kms->catalog);
SDE_ERROR("catalog init failed: %d\n", rc);
sde_kms->catalog = NULL;
- goto catalog_err;
+ goto power_error;
}
rc = sde_rm_init(&sde_kms->rm, sde_kms->catalog, sde_kms->mmio,
sde_kms->dev);
- if (rc)
- goto rm_init_err;
+ if (rc) {
+ SDE_ERROR("rm init failed: %d\n", rc);
+ goto power_error;
+ }
+
+ sde_kms->rm_init = true;
sde_kms->hw_mdp = sde_rm_get_mdp(&sde_kms->rm);
if (IS_ERR_OR_NULL(sde_kms->hw_mdp)) {
rc = PTR_ERR(sde_kms->hw_mdp);
SDE_ERROR("failed to get hw_mdp: %d\n", rc);
sde_kms->hw_mdp = NULL;
- goto mdp_top_init_err;
+ goto power_error;
}
for (i = 0; i < sde_kms->catalog->vbif_count; i++) {
@@ -953,7 +980,7 @@ struct msm_kms *sde_kms_init(struct drm_device *dev)
rc = PTR_ERR(sde_kms->hw_vbif[vbif_idx]);
SDE_ERROR("failed to init vbif %d: %d\n", vbif_idx, rc);
sde_kms->hw_vbif[vbif_idx] = NULL;
- goto vbif_init_err;
+ goto power_error;
}
}
@@ -964,7 +991,7 @@ struct msm_kms *sde_kms_init(struct drm_device *dev)
rc = _sde_kms_mmu_init(sde_kms);
if (rc) {
SDE_ERROR("sde_kms_mmu_init failed: %d\n", rc);
- goto mmu_init_err;
+ goto power_error;
}
/*
@@ -974,7 +1001,7 @@ struct msm_kms *sde_kms_init(struct drm_device *dev)
rc = _sde_debugfs_init(sde_kms);
if (rc) {
SDE_ERROR("sde_debugfs init failed: %d\n", rc);
- goto debugfs_init_err;
+ goto power_error;
}
/*
@@ -984,7 +1011,7 @@ struct msm_kms *sde_kms_init(struct drm_device *dev)
rc = _sde_kms_drm_obj_init(sde_kms);
if (rc) {
SDE_ERROR("modeset init failed: %d\n", rc);
- goto drm_obj_init_err;
+ goto power_error;
}
dev->mode_config.min_width = 0;
@@ -1011,32 +1038,38 @@ struct msm_kms *sde_kms_init(struct drm_device *dev)
}
sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
-
- return &sde_kms->base;
+ return 0;
hw_intr_init_err:
_sde_kms_drm_obj_destroy(sde_kms);
-drm_obj_init_err:
- _sde_debugfs_destroy(sde_kms);
-debugfs_init_err:
-mmu_init_err:
- _sde_kms_mmu_destroy(sde_kms);
-vbif_init_err:
- for (i = 0; i < sde_kms->catalog->vbif_count; i++) {
- u32 vbif_idx = sde_kms->catalog->vbif[i].id;
-
- if ((vbif_idx < VBIF_MAX) && sde_kms->hw_vbif[vbif_idx])
- sde_hw_vbif_destroy(sde_kms->hw_vbif[vbif_idx]);
- }
-mdp_top_init_err:
- sde_rm_destroy(&sde_kms->rm);
-rm_init_err:
-catalog_err:
+power_error:
sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
-clk_enable_err:
- sde_power_client_destroy(&priv->phandle, sde_kms->core_client);
-kms_destroy:
+error:
_sde_kms_hw_destroy(sde_kms, dev->platformdev);
end:
- return ERR_PTR(rc);
+ return rc;
+}
+
+struct msm_kms *sde_kms_init(struct drm_device *dev)
+{
+ struct msm_drm_private *priv;
+ struct sde_kms *sde_kms;
+
+ if (!dev || !dev->dev_private) {
+ SDE_ERROR("drm device node invalid\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ priv = dev->dev_private;
+
+ sde_kms = kzalloc(sizeof(*sde_kms), GFP_KERNEL);
+ if (!sde_kms) {
+ SDE_ERROR("failed to allocate sde kms\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ msm_kms_init(&sde_kms->base, &kms_funcs);
+ sde_kms->dev = dev;
+
+ return &sde_kms->base;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
index af5c9538f75b..ea2d6841d11c 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ b/drivers/gpu/drm/msm/sde/sde_kms.h
@@ -135,6 +135,7 @@ struct sde_kms {
struct sde_irq irq_obj;
struct sde_rm rm;
+ bool rm_init;
struct sde_hw_vbif *hw_vbif[VBIF_MAX];
struct sde_hw_mdp *hw_mdp;