summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDhaval Patel <pdhaval@quicinc.com>2016-11-29 09:24:31 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2016-11-29 09:24:31 -0800
commit5449d1253e573af97fa895c19883bf10e29b672a (patch)
treebca7f1ebcc3604c320f5e2f6668b9a58facdf2da /drivers/gpu
parent07b6d2ceb7c3fbc1a8dca2c811ea7bbd9717eb3e (diff)
parentaa82c5fad3573f9f36f392c4d4c03ac010f672a6 (diff)
Merge "drm/msm/sde: fixup sde_kms shutdown sequence and naming" into dev/msm-4.4-drm_kms
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c24
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h2
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.c150
3 files changed, 138 insertions, 38 deletions
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 46e262f09780..dcfb6842df15 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -50,6 +50,29 @@ int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu)
return idx;
}
+void msm_unregister_mmu(struct drm_device *dev, struct msm_mmu *mmu)
+{
+ struct msm_drm_private *priv = dev->dev_private;
+ int idx;
+
+ if (priv->num_mmus <= 0) {
+ dev_err(dev->dev, "invalid num mmus %d\n", priv->num_mmus);
+ return;
+ }
+
+ idx = priv->num_mmus - 1;
+
+ /* only support reverse-order deallocation */
+ if (priv->mmus[idx] != mmu) {
+ dev_err(dev->dev, "unexpected mmu at idx %d\n", idx);
+ return;
+ }
+
+ --priv->num_mmus;
+ priv->mmus[idx] = 0;
+}
+
+
#ifdef CONFIG_DRM_MSM_REGISTER_LOGGING
static bool reglog = false;
MODULE_PARM_DESC(reglog, "Enable register read/write logging");
@@ -421,6 +444,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
* and (for example) use dmabuf/prime to share buffers with
* imx drm driver on iMX5
*/
+ priv->kms = NULL;
dev_err(dev->dev, "failed to load kms\n");
ret = PTR_ERR(kms);
goto fail;
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index ed19330f91bc..9c824655a954 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -352,7 +352,7 @@ int msm_atomic_commit(struct drm_device *dev,
struct drm_atomic_state *state, bool async);
int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
-void msm_unregister_all_mmu(struct drm_device *dev);
+void msm_unregister_mmu(struct drm_device *dev, struct msm_mmu *mmu);
int msm_wait_fence(struct drm_device *dev, uint32_t fence,
ktime_t *timeout, bool interruptible);
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index e60d6c2ab789..f4da57db6e21 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -25,9 +25,6 @@
#include "sde_kms.h"
#include "sde_core_irq.h"
#include "sde_formats.h"
-#include "sde_hw_mdss.h"
-#include "sde_hw_util.h"
-#include "sde_hw_intf.h"
#include "sde_hw_vbif.h"
#include "sde_vbif.h"
#include "sde_encoder.h"
@@ -78,7 +75,7 @@ bool sde_is_custom_client(void)
return sdecustom;
}
-static int sde_debugfs_show_regset32(struct seq_file *s, void *data)
+static int _sde_debugfs_show_regset32(struct seq_file *s, void *data)
{
struct sde_debugfs_regset32 *regset;
struct sde_kms *sde_kms;
@@ -132,9 +129,10 @@ static int sde_debugfs_show_regset32(struct seq_file *s, void *data)
return 0;
}
-static int sde_debugfs_open_regset32(struct inode *inode, struct file *file)
+static int sde_debugfs_open_regset32(struct inode *inode,
+ struct file *file)
{
- return single_open(file, sde_debugfs_show_regset32, inode->i_private);
+ return single_open(file, _sde_debugfs_show_regset32, inode->i_private);
}
static const struct file_operations sde_fops_regset32 = {
@@ -172,7 +170,7 @@ void *sde_debugfs_get_root(struct sde_kms *sde_kms)
return sde_kms ? sde_kms->debugfs_root : 0;
}
-static int sde_debugfs_init(struct sde_kms *sde_kms)
+static int _sde_debugfs_init(struct sde_kms *sde_kms)
{
void *p;
@@ -199,7 +197,7 @@ static int sde_debugfs_init(struct sde_kms *sde_kms)
return 0;
}
-static void sde_debugfs_destroy(struct sde_kms *sde_kms)
+static void _sde_debugfs_destroy(struct sde_kms *sde_kms)
{
/* don't need to NULL check debugfs_root */
if (sde_kms) {
@@ -232,7 +230,7 @@ static void sde_kms_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
}
-static void sde_prepare_commit(struct msm_kms *kms,
+static void sde_kms_prepare_commit(struct msm_kms *kms,
struct drm_atomic_state *state)
{
struct sde_kms *sde_kms = to_sde_kms(kms);
@@ -242,7 +240,8 @@ static void sde_prepare_commit(struct msm_kms *kms,
sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
}
-static void sde_commit(struct msm_kms *kms, struct drm_atomic_state *old_state)
+static void sde_kms_commit(struct msm_kms *kms,
+ struct drm_atomic_state *old_state)
{
struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state;
@@ -256,7 +255,7 @@ static void sde_commit(struct msm_kms *kms, struct drm_atomic_state *old_state)
}
}
-static void sde_complete_commit(struct msm_kms *kms,
+static void sde_kms_complete_commit(struct msm_kms *kms,
struct drm_atomic_state *old_state)
{
struct sde_kms *sde_kms = to_sde_kms(kms);
@@ -273,7 +272,7 @@ static void sde_complete_commit(struct msm_kms *kms,
SDE_EVT32(SDE_EVTLOG_FUNC_EXIT);
}
-static void sde_wait_for_commit_done(struct msm_kms *kms,
+static void sde_kms_wait_for_commit_done(struct msm_kms *kms,
struct drm_crtc *crtc)
{
struct drm_encoder *encoder;
@@ -549,7 +548,37 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
return 0;
}
-static int modeset_init(struct sde_kms *sde_kms)
+static void _sde_kms_drm_obj_destroy(struct sde_kms *sde_kms)
+{
+ struct msm_drm_private *priv;
+ int i;
+
+ if (!sde_kms) {
+ SDE_ERROR("invalid sde_kms\n");
+ return;
+ } else if (!sde_kms->dev) {
+ SDE_ERROR("invalid dev\n");
+ return;
+ } else if (!sde_kms->dev->dev_private) {
+ SDE_ERROR("invalid dev_private\n");
+ return;
+ }
+ priv = sde_kms->dev->dev_private;
+
+ for (i = 0; i < priv->num_crtcs; i++)
+ priv->crtcs[i]->funcs->destroy(priv->crtcs[i]);
+
+ for (i = 0; i < priv->num_planes; i++)
+ priv->planes[i]->funcs->destroy(priv->planes[i]);
+
+ for (i = 0; i < priv->num_connectors; i++)
+ priv->connectors[i]->funcs->destroy(priv->connectors[i]);
+
+ for (i = 0; i < priv->num_encoders; i++)
+ priv->encoders[i]->funcs->destroy(priv->encoders[i]);
+}
+
+static int _sde_kms_drm_obj_init(struct sde_kms *sde_kms)
{
struct drm_device *dev;
struct drm_plane *primary_planes[MAX_PLANES], *plane;
@@ -627,10 +656,11 @@ static int modeset_init(struct sde_kms *sde_kms)
return 0;
fail:
+ _sde_kms_drm_obj_destroy(sde_kms);
return ret;
}
-static int sde_hw_init(struct msm_kms *kms)
+static int sde_kms_hw_init(struct msm_kms *kms)
{
return 0;
}
@@ -655,13 +685,13 @@ static int sde_kms_postinit(struct msm_kms *kms)
return 0;
}
-static long sde_round_pixclk(struct msm_kms *kms, unsigned long rate,
+static long sde_kms_round_pixclk(struct msm_kms *kms, unsigned long rate,
struct drm_encoder *encoder)
{
return rate;
}
-static void sde_destroy(struct msm_kms *kms)
+static void sde_kms_destroy(struct msm_kms *kms)
{
struct sde_kms *sde_kms = to_sde_kms(kms);
int i;
@@ -674,7 +704,7 @@ static void sde_destroy(struct msm_kms *kms)
}
_sde_kms_release_displays(sde_kms);
- sde_debugfs_destroy(sde_kms);
+ _sde_debugfs_destroy(sde_kms);
sde_hw_intr_destroy(sde_kms->hw_intr);
sde_rm_destroy(&sde_kms->rm);
kfree(sde_kms);
@@ -692,7 +722,7 @@ static void sde_kms_preclose(struct msm_kms *kms, struct drm_file *file)
}
static const struct msm_kms_funcs kms_funcs = {
- .hw_init = sde_hw_init,
+ .hw_init = sde_kms_hw_init,
.postinit = sde_kms_postinit,
.irq_preinstall = sde_irq_preinstall,
.irq_postinstall = sde_irq_postinstall,
@@ -700,25 +730,46 @@ static const struct msm_kms_funcs kms_funcs = {
.irq = sde_irq,
.preclose = sde_kms_preclose,
.prepare_fence = sde_kms_prepare_fence,
- .prepare_commit = sde_prepare_commit,
- .commit = sde_commit,
- .complete_commit = sde_complete_commit,
- .wait_for_crtc_commit_done = sde_wait_for_commit_done,
+ .prepare_commit = sde_kms_prepare_commit,
+ .commit = sde_kms_commit,
+ .complete_commit = sde_kms_complete_commit,
+ .wait_for_crtc_commit_done = sde_kms_wait_for_commit_done,
.enable_vblank = sde_kms_enable_vblank,
.disable_vblank = sde_kms_disable_vblank,
.check_modified_format = sde_format_check_modified_format,
.get_format = sde_get_msm_format,
- .round_pixclk = sde_round_pixclk,
- .destroy = sde_destroy,
+ .round_pixclk = sde_kms_round_pixclk,
+ .destroy = sde_kms_destroy,
};
/* the caller api needs to turn on clock before calling it */
-static void core_hw_rev_init(struct sde_kms *sde_kms)
+static void _sde_kms_core_hw_rev_init(struct sde_kms *sde_kms)
{
sde_kms->core_rev = readl_relaxed(sde_kms->mmio + 0x0);
}
-int sde_mmu_init(struct sde_kms *sde_kms)
+static int _sde_kms_mmu_destroy(struct sde_kms *sde_kms)
+{
+ struct msm_mmu *mmu;
+ int i;
+
+ for (i = ARRAY_SIZE(sde_kms->mmu_id) - 1; i >= 0; i--) {
+ if (sde_kms->mmu_id[i] <= 0 || !sde_kms->mmu[i])
+ continue;
+
+ mmu = sde_kms->mmu[i];
+ msm_unregister_mmu(sde_kms->dev, mmu);
+ mmu->funcs->detach(mmu, (const char **)iommu_ports,
+ ARRAY_SIZE(iommu_ports));
+ mmu->funcs->destroy(mmu);
+ sde_kms->mmu[i] = 0;
+ sde_kms->mmu_id[i] = 0;
+ }
+
+ return 0;
+}
+
+static int _sde_kms_mmu_init(struct sde_kms *sde_kms)
{
struct msm_mmu *mmu;
int i, ret;
@@ -753,11 +804,12 @@ int sde_mmu_init(struct sde_kms *sde_kms)
return 0;
fail:
- return ret;
+ _sde_kms_mmu_destroy(sde_kms);
+ return ret;
}
-struct sde_kms *sde_hw_setup(struct platform_device *pdev)
+static struct sde_kms *_sde_kms_hw_setup(struct platform_device *pdev)
{
struct sde_kms *sde_kms;
int ret = 0;
@@ -809,7 +861,7 @@ err:
return ERR_PTR(ret);
}
-static void sde_hw_destroy(struct sde_kms *sde_kms)
+static void _sde_kms_hw_destroy(struct sde_kms *sde_kms)
{
if (sde_kms->vbif[VBIF_NRT])
iounmap(sde_kms->vbif[VBIF_NRT]);
@@ -832,7 +884,7 @@ struct msm_kms *sde_kms_init(struct drm_device *dev)
}
priv = dev->dev_private;
- sde_kms = sde_hw_setup(dev->platformdev);
+ sde_kms = _sde_kms_hw_setup(dev->platformdev);
if (IS_ERR_OR_NULL(sde_kms)) {
SDE_ERROR("sde hw setup failed\n");
rc = PTR_ERR(sde_kms);
@@ -856,7 +908,7 @@ struct msm_kms *sde_kms_init(struct drm_device *dev)
goto clk_rate_err;
}
- core_hw_rev_init(sde_kms);
+ _sde_kms_core_hw_rev_init(sde_kms);
pr_info("sde hardware revision:0x%x\n", sde_kms->core_rev);
@@ -899,19 +951,31 @@ struct msm_kms *sde_kms_init(struct drm_device *dev)
* Now we need to read the HW catalog and initialize resources such as
* clocks, regulators, GDSC/MMAGIC, ioremap the register ranges etc
*/
- sde_mmu_init(sde_kms);
+ rc = _sde_kms_mmu_init(sde_kms);
+ if (rc) {
+ SDE_ERROR("sde_kms_mmu_init failed: %d\n", rc);
+ goto mmu_init_err;
+ }
/*
* NOTE: Calling sde_debugfs_init here so that the drm_minor device for
* 'primary' is already created.
*/
- sde_debugfs_init(sde_kms);
+ rc = _sde_debugfs_init(sde_kms);
+ if (rc) {
+ SDE_ERROR("sde_debugfs init failed: %d\n", rc);
+ goto debugfs_init_err;
+ }
/*
- * modeset_init should create the DRM related objects i.e. CRTCs,
- * planes, encoders, connectors and so forth
+ * _sde_kms_drm_obj_init should create the DRM related objects
+ * i.e. CRTCs, planes, encoders, connectors and so forth
*/
- modeset_init(sde_kms);
+ rc = _sde_kms_drm_obj_init(sde_kms);
+ if (rc) {
+ SDE_ERROR("modeset init failed: %d\n", rc);
+ goto drm_obj_init_err;
+ }
dev->mode_config.min_width = 0;
dev->mode_config.min_height = 0;
@@ -928,16 +992,28 @@ struct msm_kms *sde_kms_init(struct drm_device *dev)
*/
dev->mode_config.allow_fb_modifiers = true;
+ sde_kms->hw_intr = sde_hw_intr_init(sde_kms->mmio, sde_kms->catalog);
+ if (IS_ERR_OR_NULL(sde_kms->hw_intr))
+ goto hw_intr_init_err;
+
sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
return &sde_kms->base;
+hw_intr_init_err:
+ _sde_kms_drm_obj_destroy(sde_kms);
+drm_obj_init_err:
+ _sde_debugfs_destroy(sde_kms);
+debugfs_init_err:
+ _sde_kms_mmu_destroy(sde_kms);
+mmu_init_err:
+ sde_rm_destroy(&sde_kms->rm);
catalog_err:
sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
clk_rate_err:
sde_power_client_destroy(&priv->phandle, sde_kms->core_client);
kms_destroy:
- sde_hw_destroy(sde_kms);
+ _sde_kms_hw_destroy(sde_kms);
end:
return ERR_PTR(rc);
}