summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDhaval Patel <pdhaval@codeaurora.org>2016-06-20 16:24:33 -0700
committerDhaval Patel <pdhaval@codeaurora.org>2016-09-12 11:03:26 -0700
commit593f3c3e66f76cc48ad295bcc990396e4e32fe13 (patch)
tree242f63fbce325de07671ba8f55899f1f39ab850b
parentbbe6cf1b0bb73359f135dbe21bcf2fff1c44fcfe (diff)
drm/sde: use power handle api to vote for core clock
Update SDE driver to use the power handle API for voting the core clock and regulator. This change also cleans up bunch of error paths in sde_kms init. Change-Id: I0acdd2308f7e19053d5ec0a8ae148ee6e4bc2433 Signed-off-by: Dhaval Patel <pdhaval@codeaurora.org>
-rw-r--r--drivers/gpu/drm/msm/Makefile1
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c124
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h9
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c11
-rw-r--r--drivers/gpu/drm/msm/sde/sde_irq.c19
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.c450
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.h17
7 files changed, 281 insertions, 350 deletions
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index ddefd7f41bef..ca16fa5b1767 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -54,6 +54,7 @@ msm-y := \
msm_rd.o \
msm_ringbuffer.o \
msm_evtlog.o \
+ sde_power_handle.o \
msm_prop.o \
# use drm gpu driver only if qcom_kgsl driver not available
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index ef0d1949138d..b4af1f6004aa 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -15,6 +15,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <linux/of_address.h>
#include "msm_drv.h"
#include "msm_gpu.h"
#include "msm_kms.h"
@@ -262,8 +263,6 @@ static int get_mdp_ver(struct platform_device *pdev)
return KMS_MDP4;
}
-#include <linux/of_address.h>
-
static int msm_init_vram(struct drm_device *dev)
{
struct msm_drm_private *priv = dev->dev_private;
@@ -339,6 +338,20 @@ static int msm_init_vram(struct drm_device *dev)
return ret;
}
+#ifdef CONFIG_OF
+static int msm_component_bind_all(struct device *dev,
+ struct drm_device *drm_dev)
+{
+ return component_bind_all(dev, drm_dev);
+}
+#else
+static int msm_component_bind_all(struct device *dev,
+ struct drm_device *drm_dev)
+{
+ return 0;
+}
+#endif
+
static int msm_load(struct drm_device *dev, unsigned long flags)
{
struct platform_device *pdev = dev->platformdev;
@@ -346,7 +359,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
struct msm_kms *kms;
int ret;
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ priv = platform_get_drvdata(pdev);
if (!priv) {
dev_err(dev->dev, "failed to allocate private data\n");
return -ENOMEM;
@@ -354,22 +367,11 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
dev->dev_private = priv;
- priv->wq = alloc_ordered_workqueue("msm_drm", 0);
- init_waitqueue_head(&priv->fence_event);
- init_waitqueue_head(&priv->pending_crtcs_event);
-
- INIT_LIST_HEAD(&priv->inactive_list);
- INIT_LIST_HEAD(&priv->fence_cbs);
- INIT_LIST_HEAD(&priv->vblank_ctrl.event_list);
- INIT_WORK(&priv->vblank_ctrl.work, vblank_ctrl_worker);
- spin_lock_init(&priv->vblank_ctrl.lock);
-
drm_mode_config_init(dev);
platform_set_drvdata(pdev, dev);
- /* Bind all our sub-components: */
- ret = component_bind_all(dev->dev, dev);
+ ret = msm_component_bind_all(dev->dev, dev);
if (ret)
return ret;
@@ -1058,6 +1060,21 @@ static const struct dev_pm_ops msm_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(msm_pm_suspend, msm_pm_resume)
};
+static int msm_drm_bind(struct device *dev)
+{
+ return drm_platform_init(&msm_driver, to_platform_device(dev));
+}
+
+static void msm_drm_unbind(struct device *dev)
+{
+ drm_put_dev(platform_get_drvdata(to_platform_device(dev)));
+}
+
+static const struct component_master_ops msm_drm_ops = {
+ .bind = msm_drm_bind,
+ .unbind = msm_drm_unbind,
+};
+
/*
* Componentized driver support:
*/
@@ -1089,27 +1106,30 @@ static int add_components(struct device *dev, struct component_match **matchptr,
return 0;
}
-#else
-static int compare_dev(struct device *dev, void *data)
+
+static int msm_add_master_component(struct device *dev,
+ struct component_match *match)
{
- return dev == data;
+ int ret = component_master_add_with_match(dev, &msm_drm_ops, match);
+
+ if (ret)
+ pr_err("component add match failed\n");
+
+ return ret;
}
-#endif
-static int msm_drm_bind(struct device *dev)
+#else
+static int compare_dev(struct device *dev, void *data)
{
- return drm_platform_init(&msm_driver, to_platform_device(dev));
+ return dev == data;
}
-static void msm_drm_unbind(struct device *dev)
+static int msm_add_master_component(struct device *dev,
+ struct component_match *match)
{
- drm_put_dev(platform_get_drvdata(to_platform_device(dev)));
+ return 0;
}
-
-static const struct component_master_ops msm_drm_ops = {
- .bind = msm_drm_bind,
- .unbind = msm_drm_unbind,
-};
+#endif
/*
* Platform driver:
@@ -1117,7 +1137,10 @@ static const struct component_master_ops msm_drm_ops = {
static int msm_pdev_probe(struct platform_device *pdev)
{
+ int ret;
struct component_match *match = NULL;
+ struct msm_drm_private *priv;
+
#ifdef CONFIG_OF
add_components(&pdev->dev, &match, "connectors");
add_components(&pdev->dev, &match, "gpus");
@@ -1148,14 +1171,55 @@ static int msm_pdev_probe(struct platform_device *pdev)
}
#endif
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->wq = alloc_ordered_workqueue("msm_drm", 0);
+ init_waitqueue_head(&priv->fence_event);
+ init_waitqueue_head(&priv->pending_crtcs_event);
+
+ INIT_LIST_HEAD(&priv->inactive_list);
+ INIT_LIST_HEAD(&priv->fence_cbs);
+ INIT_LIST_HEAD(&priv->vblank_ctrl.event_list);
+ INIT_WORK(&priv->vblank_ctrl.work, vblank_ctrl_worker);
+ spin_lock_init(&priv->vblank_ctrl.lock);
+
+ platform_set_drvdata(pdev, priv);
+
+ ret = sde_power_resource_init(pdev, &priv->phandle);
+ if (ret) {
+ pr_err("sde power resource init failed\n");
+ goto hw_setup_failure;
+ }
+
+ priv->pclient = sde_power_client_create(&priv->phandle, "sde");
+ if (IS_ERR_OR_NULL(priv->pclient)) {
+ pr_err("sde power client create failed\n");
+ ret = -EINVAL;
+ goto client_create_err;
+ }
+
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
- return component_master_add_with_match(&pdev->dev, &msm_drm_ops, match);
+
+ return msm_add_master_component(&pdev->dev, match);
+
+client_create_err:
+ sde_power_resource_deinit(pdev, &priv->phandle);
+hw_setup_failure:
+ kfree(priv);
+
+ return ret;
}
static int msm_pdev_remove(struct platform_device *pdev)
{
- component_master_del(&pdev->dev, &msm_drm_ops);
+ struct drm_device *drm_dev = platform_get_drvdata(pdev);
+ struct msm_drm_private *priv = drm_dev->dev_private;
+ msm_drm_unbind(&pdev->dev);
+ component_master_del(&pdev->dev, &msm_drm_ops);
+ sde_power_resource_deinit(pdev, &priv->phandle);
return 0;
}
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 6873beaa6f87..dccd3ed6eca7 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -31,6 +31,7 @@
#include <linux/iommu.h>
#include <linux/types.h>
#include <linux/of_graph.h>
+#include <linux/mdss_io_util.h>
#include <asm/sizes.h>
#ifndef CONFIG_OF
@@ -49,6 +50,11 @@
#include <drm/drm_gem.h>
#include "msm_evtlog.h"
+#include "sde_power_handle.h"
+
+#define GET_MAJOR_REV(rev) ((rev) >> 28)
+#define GET_MINOR_REV(rev) (((rev) >> 16) & 0xFFF)
+#define GET_STEP_REV(rev) ((rev) & 0xFFFF)
struct msm_kms;
struct msm_gpu;
@@ -205,6 +211,9 @@ struct msm_drm_private {
struct msm_kms *kms;
+ struct sde_power_handle phandle;
+ struct sde_power_client *pclient;
+
/* subordinate devices, if present: */
struct platform_device *gpu_pdev;
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
index 9cb9ecf30600..fb7cc9b30efc 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
@@ -199,6 +199,8 @@ static void sde_encoder_phys_cmd_tearcheck_config(
struct drm_display_mode *mode = &phys_enc->cached_mode;
bool tc_enable = true;
u32 vsync_hz;
+ struct msm_drm_private *priv;
+ struct sde_kms *sde_kms;
DBG("intf %d, pp %d", cmd_enc->intf_idx, cmd_enc->hw_pp->idx);
@@ -208,6 +210,8 @@ static void sde_encoder_phys_cmd_tearcheck_config(
return;
}
+ sde_kms = phys_enc->sde_kms;
+ priv = sde_kms->dev->dev_private;
/*
* TE default: dsi byte clock calculated base on 70 fps;
* around 14 ms to complete a kickoff cycle if te disabled;
@@ -217,7 +221,12 @@ static void sde_encoder_phys_cmd_tearcheck_config(
* vsync_count is ratio of MDP VSYNC clock frequency to LCD panel
* frequency divided by the no. of rows (lines) in the LCDpanel.
*/
- vsync_hz = clk_get_rate(phys_enc->sde_kms->vsync_clk);
+ vsync_hz = sde_power_clk_get_rate(&priv->phandle, "vsync_clk");
+ if (!vsync_hz) {
+ DBG("invalid vsync clock rate");
+ return;
+ }
+
tc_cfg.vsync_count = vsync_hz / (mode->vtotal * mode->vrefresh);
tc_cfg.hw_vsync_mode = 1;
diff --git a/drivers/gpu/drm/msm/sde/sde_irq.c b/drivers/gpu/drm/msm/sde/sde_irq.c
index 967255697dd1..b0bf8dff3190 100644
--- a/drivers/gpu/drm/msm/sde/sde_irq.c
+++ b/drivers/gpu/drm/msm/sde/sde_irq.c
@@ -170,11 +170,13 @@ void sde_disable_all_irqs(struct sde_kms *sde_kms)
void sde_irq_preinstall(struct msm_kms *kms)
{
struct sde_kms *sde_kms = to_sde_kms(kms);
+ struct drm_device *dev = sde_kms->dev;
+ struct msm_drm_private *priv = dev->dev_private;
- sde_enable(sde_kms);
+ sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
sde_clear_all_irqs(sde_kms);
sde_disable_all_irqs(sde_kms);
- sde_disable(sde_kms);
+ sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
spin_lock_init(&sde_kms->irq_obj.cb_lock);
@@ -184,11 +186,14 @@ void sde_irq_preinstall(struct msm_kms *kms)
sizeof(struct sde_irq_callback), GFP_KERNEL);
if (!sde_kms->irq_obj.irq_cb_tbl)
DRM_ERROR("Fail to allocate memory of IRQ callback list\n");
+
}
int sde_irq_postinstall(struct msm_kms *kms)
{
struct sde_kms *sde_kms = to_sde_kms(kms);
+ struct drm_device *dev = sde_kms->dev;
+ struct msm_drm_private *priv = dev->dev_private;
struct sde_irq_callback irq_cb;
int irq_idx;
int i;
@@ -197,14 +202,14 @@ int sde_irq_postinstall(struct msm_kms *kms)
irq_cb.arg = sde_kms;
/* Register interface underrun callback */
- sde_enable(sde_kms);
+ sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
for (i = 0; i < sde_kms->catalog->intf_count; i++) {
irq_idx = sde_irq_idx_lookup(sde_kms,
SDE_IRQ_TYPE_INTF_UNDER_RUN, i+INTF_0);
sde_register_irq_callback(sde_kms, irq_idx, &irq_cb);
sde_enable_irq(sde_kms, &irq_idx, 1);
}
- sde_disable(sde_kms);
+ sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
return 0;
}
@@ -212,11 +217,13 @@ int sde_irq_postinstall(struct msm_kms *kms)
void sde_irq_uninstall(struct msm_kms *kms)
{
struct sde_kms *sde_kms = to_sde_kms(kms);
+ struct drm_device *dev = sde_kms->dev;
+ struct msm_drm_private *priv = dev->dev_private;
- sde_enable(sde_kms);
+ sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
sde_clear_all_irqs(sde_kms);
sde_disable_all_irqs(sde_kms);
- sde_disable(sde_kms);
+ sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
kfree(sde_kms->irq_obj.irq_cb_tbl);
}
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 0e4750bfedce..55f19ce7a337 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -44,34 +44,6 @@ static const char * const iommu_ports[] = {
#define SDE_DEBUGFS_DIR "msm_sde"
#define SDE_DEBUGFS_HWMASKNAME "hw_log_mask"
-int sde_disable(struct sde_kms *sde_kms)
-{
- DBG("");
-
- clk_disable_unprepare(sde_kms->ahb_clk);
- clk_disable_unprepare(sde_kms->axi_clk);
- clk_disable_unprepare(sde_kms->core_clk);
- clk_disable_unprepare(sde_kms->vsync_clk);
- if (sde_kms->lut_clk)
- clk_disable_unprepare(sde_kms->lut_clk);
-
- return 0;
-}
-
-int sde_enable(struct sde_kms *sde_kms)
-{
- DBG("");
-
- clk_prepare_enable(sde_kms->ahb_clk);
- clk_prepare_enable(sde_kms->axi_clk);
- clk_prepare_enable(sde_kms->core_clk);
- clk_prepare_enable(sde_kms->vsync_clk);
- if (sde_kms->lut_clk)
- clk_prepare_enable(sde_kms->lut_clk);
-
- return 0;
-}
-
static int sde_debugfs_show_regset32(struct seq_file *s, void *data)
{
struct sde_debugfs_regset32 *regset = s->private;
@@ -160,7 +132,10 @@ static void sde_prepare_commit(struct msm_kms *kms,
struct drm_atomic_state *state)
{
struct sde_kms *sde_kms = to_sde_kms(kms);
- sde_enable(sde_kms);
+ struct drm_device *dev = sde_kms->dev;
+ struct msm_drm_private *priv = dev->dev_private;
+
+ 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)
@@ -181,6 +156,8 @@ static void sde_complete_commit(struct msm_kms *kms,
struct drm_atomic_state *state)
{
struct sde_kms *sde_kms = to_sde_kms(kms);
+ struct drm_device *dev = sde_kms->dev;
+ struct msm_drm_private *priv = dev->dev_private;
struct drm_crtc *crtc;
struct drm_crtc_state *crtc_state;
struct drm_connector *connector;
@@ -191,7 +168,7 @@ static void sde_complete_commit(struct msm_kms *kms,
sde_crtc_complete_commit(crtc);
for_each_connector_in_state(state, connector, conn_state, i)
sde_connector_complete_commit(connector);
- sde_disable(sde_kms);
+ sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
MSM_EVT(sde_kms->dev, 0, 0);
}
@@ -307,7 +284,6 @@ static int sde_hw_init(struct msm_kms *kms)
{
return 0;
}
-
static long sde_round_pixclk(struct msm_kms *kms, unsigned long rate,
struct drm_encoder *encoder)
{
@@ -316,14 +292,30 @@ static long sde_round_pixclk(struct msm_kms *kms, unsigned long rate,
static void sde_postopen(struct msm_kms *kms, struct drm_file *file)
{
- if (kms)
- sde_enable(to_sde_kms(kms));
+ struct sde_kms *sde_kms;
+ struct msm_drm_private *priv;
+
+ if (!kms)
+ return;
+
+ sde_kms = to_sde_kms(kms);
+ priv = sde_kms->dev->dev_private;
+
+ sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
}
static void sde_preclose(struct msm_kms *kms, struct drm_file *file)
{
- if (kms)
- sde_disable(to_sde_kms(kms));
+ struct sde_kms *sde_kms;
+ struct msm_drm_private *priv;
+
+ if (!kms)
+ return;
+
+ sde_kms = to_sde_kms(kms);
+ priv = sde_kms->dev->dev_private;
+
+ sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
}
static void sde_destroy(struct msm_kms *kms)
@@ -358,227 +350,17 @@ static const struct msm_kms_funcs kms_funcs = {
.destroy = sde_destroy,
};
-static int get_clk(struct platform_device *pdev, struct clk **clkp,
- const char *name, bool mandatory)
+/* the caller api needs to turn on clock before calling it */
+static void core_hw_rev_init(struct sde_kms *sde_kms)
{
- struct device *dev = &pdev->dev;
- struct clk *clk = devm_clk_get(dev, name);
-
- if (IS_ERR(clk) && mandatory) {
- DRM_ERROR("failed to get %s (%ld)\n", name, PTR_ERR(clk));
- return PTR_ERR(clk);
- }
- if (IS_ERR(clk))
- DBG("skipping %s", name);
- else
- *clkp = clk;
-
- return 0;
-}
-
-struct sde_kms *sde_hw_setup(struct platform_device *pdev)
-{
- struct sde_kms *sde_kms;
- struct msm_kms *kms = NULL;
- int ret;
-
- sde_kms = kzalloc(sizeof(*sde_kms), GFP_KERNEL);
- if (!sde_kms)
- return NULL;
-
- msm_kms_init(&sde_kms->base, &kms_funcs);
-
- kms = &sde_kms->base;
-
- sde_kms->mmio = msm_ioremap(pdev, "mdp_phys", "SDE");
- if (IS_ERR(sde_kms->mmio)) {
- ret = PTR_ERR(sde_kms->mmio);
- goto fail;
- }
- DRM_INFO("Mapped Mdp address space @%pK\n", sde_kms->mmio);
-
- sde_kms->vbif[VBIF_RT] = msm_ioremap(pdev, "vbif_phys", "VBIF");
- if (IS_ERR(sde_kms->vbif[VBIF_RT])) {
- ret = PTR_ERR(sde_kms->vbif[VBIF_RT]);
- goto fail;
- }
-
- sde_kms->vbif[VBIF_NRT] = msm_ioremap(pdev, "vbif_nrt_phys",
- "VBIF_NRT");
- if (IS_ERR(sde_kms->vbif[VBIF_NRT])) {
- sde_kms->vbif[VBIF_NRT] = NULL;
- DBG("VBIF NRT is not defined");
- }
-
- sde_kms->venus = devm_regulator_get_optional(&pdev->dev, "gdsc-venus");
- if (IS_ERR(sde_kms->venus)) {
- ret = PTR_ERR(sde_kms->venus);
- DBG("failed to get Venus GDSC regulator: %d", ret);
- sde_kms->venus = NULL;
- }
-
- if (sde_kms->venus) {
- ret = regulator_enable(sde_kms->venus);
- if (ret) {
- DBG("failed to enable venus GDSC: %d", ret);
- goto fail;
- }
- }
-
- sde_kms->vdd = devm_regulator_get(&pdev->dev, "vdd");
- if (IS_ERR(sde_kms->vdd)) {
- ret = PTR_ERR(sde_kms->vdd);
- goto fail;
- }
-
- ret = regulator_enable(sde_kms->vdd);
- if (ret) {
- DBG("failed to enable regulator vdd: %d", ret);
- goto fail;
- }
-
- sde_kms->mmagic = devm_regulator_get_optional(&pdev->dev, "mmagic");
- if (IS_ERR(sde_kms->mmagic)) {
- ret = PTR_ERR(sde_kms->mmagic);
- DBG("failed to get mmagic GDSC regulator: %d", ret);
- sde_kms->mmagic = NULL;
- }
-
- /* mandatory clocks: */
- ret = get_clk(pdev, &sde_kms->axi_clk, "bus_clk", true);
- if (ret)
- goto fail;
- ret = get_clk(pdev, &sde_kms->ahb_clk, "iface_clk", true);
- if (ret)
- goto fail;
- ret = get_clk(pdev, &sde_kms->src_clk, "core_clk_src", true);
- if (ret)
- goto fail;
- ret = get_clk(pdev, &sde_kms->core_clk, "core_clk", true);
- if (ret)
- goto fail;
- ret = get_clk(pdev, &sde_kms->vsync_clk, "vsync_clk", true);
- if (ret)
- goto fail;
-
- /* optional clocks: */
- get_clk(pdev, &sde_kms->lut_clk, "lut_clk", false);
- get_clk(pdev, &sde_kms->mmagic_clk, "mmagic_clk", false);
- get_clk(pdev, &sde_kms->iommu_ahb_clk[MSM_SMMU_DOMAIN_UNSECURE],
- "iommu_mdp_ahb_clk", false);
- get_clk(pdev, &sde_kms->iommu_axi_clk[MSM_SMMU_DOMAIN_UNSECURE],
- "iommu_mdp_axi_clk", false);
- get_clk(pdev, &sde_kms->iommu_ahb_clk[MSM_SMMU_DOMAIN_SECURE],
- "iommu_mdp_ahb_clk", false);
- get_clk(pdev, &sde_kms->iommu_axi_clk[MSM_SMMU_DOMAIN_SECURE],
- "iommu_mdp_axi_clk", false);
- get_clk(pdev, &sde_kms->iommu_ahb_clk[MSM_SMMU_DOMAIN_NRT_UNSECURE],
- "iommu_rot_ahb_clk", false);
- get_clk(pdev, &sde_kms->iommu_axi_clk[MSM_SMMU_DOMAIN_NRT_UNSECURE],
- "iommu_rot_axi_clk", false);
- get_clk(pdev, &sde_kms->iommu_ahb_clk[MSM_SMMU_DOMAIN_NRT_SECURE],
- "iommu_rot_ahb_clk", false);
- get_clk(pdev, &sde_kms->iommu_axi_clk[MSM_SMMU_DOMAIN_NRT_SECURE],
- "iommu_rot_axi_clk", false);
-
- if (sde_kms->mmagic) {
- ret = regulator_enable(sde_kms->mmagic);
- if (ret) {
- DRM_ERROR("failed to enable mmagic GDSC: %d\n", ret);
- goto fail;
- }
- }
- if (sde_kms->mmagic_clk) {
- clk_prepare_enable(sde_kms->mmagic_clk);
- if (ret) {
- DRM_ERROR("failed to enable mmagic_clk\n");
- goto undo_gdsc;
- }
- }
-
- return sde_kms;
-
-undo_gdsc:
- if (sde_kms->mmagic)
- regulator_disable(sde_kms->mmagic);
-fail:
- if (kms)
- sde_destroy(kms);
-
- return ERR_PTR(ret);
+ sde_kms->core_rev = readl_relaxed(sde_kms->mmio + 0x0);
}
-static int sde_translation_ctrl_pwr(struct sde_kms *sde_kms,
- enum msm_mmu_domain_type domain, bool on)
-{
- int ret;
-
- if (on) {
- if (sde_kms->iommu_ahb_clk[domain]) {
- ret = clk_prepare_enable(
- sde_kms->iommu_ahb_clk[domain]);
- if (ret) {
- DRM_ERROR("failed to enable iommu_ahb_clk\n");
- goto undo_mmagic_clk;
- }
- }
- if (sde_kms->iommu_axi_clk[domain]) {
- ret = clk_prepare_enable(
- sde_kms->iommu_axi_clk[domain]);
- if (ret) {
- DRM_ERROR("failed to enable iommu_axi_clk\n");
- if (sde_kms->iommu_ahb_clk[domain])
- clk_disable_unprepare(
- sde_kms->iommu_ahb_clk[domain]);
- goto undo_mmagic_clk;
- }
- }
- } else {
- if (sde_kms->iommu_ahb_clk[domain])
- clk_disable_unprepare(sde_kms->iommu_ahb_clk[domain]);
- if (sde_kms->iommu_axi_clk[domain])
- clk_disable_unprepare(sde_kms->iommu_axi_clk[domain]);
- if (sde_kms->mmagic_clk)
- clk_disable_unprepare(sde_kms->mmagic_clk);
- if (sde_kms->mmagic)
- regulator_disable(sde_kms->mmagic);
- }
-
- return 0;
-
-undo_mmagic_clk:
- if (sde_kms->mmagic_clk)
- clk_disable_unprepare(sde_kms->mmagic_clk);
-
- return ret;
-}
int sde_mmu_init(struct sde_kms *sde_kms)
{
- struct sde_mdss_cfg *catalog = sde_kms->catalog;
- struct sde_hw_intf *intf = NULL;
struct msm_mmu *mmu;
int i, ret;
- /*
- * Make sure things are off before attaching iommu (bootloader could
- * have left things on, in which case we'll start getting faults if
- * we don't disable):
- */
- sde_enable(sde_kms);
- for (i = 0; i < catalog->intf_count; i++) {
- if (catalog->intf[i].type != INTF_NONE) {
- intf = sde_hw_intf_init(catalog->intf[i].id,
- sde_kms->mmio,
- catalog);
- if (!IS_ERR_OR_NULL(intf)) {
- intf->ops.enable_timing(intf, 0x0);
- sde_hw_intf_destroy(intf);
- }
- }
- }
- sde_disable(sde_kms);
- msleep(20);
-
for (i = 0; i < MSM_SMMU_DOMAIN_MAX; i++) {
mmu = msm_smmu_new(sde_kms->dev->dev, i);
if (IS_ERR(mmu)) {
@@ -587,18 +369,10 @@ int sde_mmu_init(struct sde_kms *sde_kms)
goto fail;
}
- ret = sde_translation_ctrl_pwr(sde_kms, i, true);
- if (ret) {
- DRM_ERROR("failed to power iommu: %d\n", ret);
- mmu->funcs->destroy(mmu);
- goto fail;
- }
-
ret = mmu->funcs->attach(mmu, (const char **)iommu_ports,
ARRAY_SIZE(iommu_ports));
if (ret) {
DRM_ERROR("failed to attach iommu: %d\n", ret);
- sde_translation_ctrl_pwr(sde_kms, i, false);
mmu->funcs->destroy(mmu);
goto fail;
}
@@ -609,7 +383,6 @@ int sde_mmu_init(struct sde_kms *sde_kms)
DRM_ERROR("failed to register sde iommu: %d\n", ret);
mmu->funcs->detach(mmu, (const char **)iommu_ports,
ARRAY_SIZE(iommu_ports));
- sde_translation_ctrl_pwr(sde_kms, i, false);
goto fail;
}
@@ -622,53 +395,128 @@ fail:
}
-struct msm_kms *sde_kms_init(struct drm_device *dev)
+struct sde_kms *sde_hw_setup(struct platform_device *pdev)
{
- struct msm_drm_private *priv = dev->dev_private;
- struct platform_device *pdev = dev->platformdev;
- struct sde_mdss_cfg *catalog;
struct sde_kms *sde_kms;
- struct msm_kms *msm_kms;
int ret = 0;
- if (!dev || !dev->dev_private) {
- DRM_ERROR("invalid device\n");
- goto fail;
+ sde_kms = kzalloc(sizeof(*sde_kms), GFP_KERNEL);
+ if (!sde_kms)
+ return ERR_PTR(-ENOMEM);
+
+ sde_kms->mmio = msm_ioremap(pdev, "mdp_phys", "SDE");
+ if (IS_ERR(sde_kms->mmio)) {
+ SDE_ERROR("mdp register memory map failed\n");
+ ret = PTR_ERR(sde_kms->mmio);
+ goto err;
}
+ DRM_INFO("mapped mdp address space @%p\n", sde_kms->mmio);
- sde_kms = sde_hw_setup(pdev);
- if (IS_ERR(sde_kms)) {
- ret = PTR_ERR(sde_kms);
- goto fail;
+ sde_kms->vbif[VBIF_RT] = msm_ioremap(pdev, "vbif_phys", "VBIF");
+ if (IS_ERR(sde_kms->vbif[VBIF_RT])) {
+ SDE_ERROR("vbif register memory map failed\n");
+ ret = PTR_ERR(sde_kms->vbif[VBIF_RT]);
+ goto vbif_map_err;
+ }
+
+ sde_kms->vbif[VBIF_NRT] = msm_ioremap(pdev, "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])
+ iounmap(sde_kms->vbif[VBIF_NRT]);
+ iounmap(sde_kms->vbif[VBIF_RT]);
+vbif_map_err:
+ iounmap(sde_kms->mmio);
+err:
+ kfree(sde_kms);
+ return ERR_PTR(ret);
+}
+
+static void sde_hw_destroy(struct sde_kms *sde_kms)
+{
+ if (sde_kms->vbif[VBIF_NRT])
+ iounmap(sde_kms->vbif[VBIF_NRT]);
+ iounmap(sde_kms->vbif[VBIF_RT]);
+ iounmap(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 rc;
+
+ if (!dev) {
+ SDE_ERROR("drm device node invalid\n");
+ rc = -EINVAL;
+ goto end;
+ }
+
+ priv = dev->dev_private;
+ sde_kms = sde_hw_setup(dev->platformdev);
+ if (IS_ERR_OR_NULL(sde_kms)) {
+ SDE_ERROR("sde hw setup failed\n");
+ rc = PTR_ERR(sde_kms);
+ goto end;
}
sde_kms->dev = dev;
- msm_kms = &sde_kms->base;
- priv->kms = msm_kms;
+ priv->kms = &sde_kms->base;
- /*
- * Currently hardcoding to MDSS version 1.7.0 (8996)
- */
- catalog = sde_hw_catalog_init(1, 7, 0);
- if (!catalog)
- goto fail;
+ sde_kms->core_client = sde_power_client_create(&priv->phandle, "core");
+ if (IS_ERR_OR_NULL(sde_kms->core_client)) {
+ SDE_ERROR("sde power client create failed\n");
+ rc = -EINVAL;
+ goto kms_destroy;
+ }
- sde_kms->catalog = catalog;
+ rc = sde_power_clk_set_rate(&priv->phandle, "core_clk",
+ DEFAULT_MDP_SRC_CLK);
+ if (rc) {
+ SDE_ERROR("core clock set rate failed\n");
+ goto clk_rate_err;
+ }
- /* we need to set a default rate before enabling.
- * Set a safe rate first, before initializing catalog
- * later set more optimal rate based on bandwdith/clock
- * requirements
- */
+ rc = sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
+ true);
+ if (rc) {
+ SDE_ERROR("resource enable failed\n");
+ goto clk_rate_err;
+ }
- clk_set_rate(sde_kms->src_clk, DEFAULT_MDP_SRC_CLK);
+ core_hw_rev_init(sde_kms);
- sde_enable(sde_kms);
- ret = sde_rm_init(&sde_kms->rm, sde_kms->catalog, sde_kms->mmio,
+ sde_kms->catalog = sde_hw_catalog_init(GET_MAJOR_REV(sde_kms->core_rev),
+ GET_MINOR_REV(sde_kms->core_rev),
+ GET_STEP_REV(sde_kms->core_rev));
+ if (IS_ERR_OR_NULL(sde_kms->catalog)) {
+ SDE_ERROR("catalog init failed\n");
+ rc = PTR_ERR(sde_kms->catalog);
+ goto catalog_err;
+ }
+
+ rc = sde_rm_init(&sde_kms->rm, sde_kms->catalog, sde_kms->mmio,
sde_kms->dev);
- sde_disable(sde_kms);
- if (ret)
- goto fail;
+ if (rc)
+ goto catalog_err;
+
+ sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
/*
* Now we need to read the HW catalog and initialize resources such as
@@ -698,7 +546,8 @@ struct msm_kms *sde_kms_init(struct drm_device *dev)
* max crtc width is equal to the max mixer width * 2 and max height is
* is 4K
*/
- dev->mode_config.max_width = catalog->mixer[0].sblk->maxwidth * 2;
+ dev->mode_config.max_width =
+ sde_kms->catalog->mixer[0].sblk->maxwidth * 2;
dev->mode_config.max_height = 4096;
/*
@@ -708,13 +557,16 @@ struct msm_kms *sde_kms_init(struct drm_device *dev)
sde_kms->hw_intr = sde_hw_intr_init(sde_kms->mmio, sde_kms->catalog);
if (IS_ERR_OR_NULL(sde_kms->hw_intr))
- goto fail;
-
- return msm_kms;
-
-fail:
- if (msm_kms)
- sde_destroy(msm_kms);
-
- return ERR_PTR(ret);
+ goto clk_rate_err;
+
+ return &sde_kms->base;
+
+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);
+end:
+ return ERR_PTR(rc);
}
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
index a15e5cd1bddb..460491e5f4c7 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ b/drivers/gpu/drm/msm/sde/sde_kms.h
@@ -25,6 +25,7 @@
#include "sde_hw_top.h"
#include "sde_connector.h"
#include "sde_rm.h"
+#include "sde_power_handle.h"
/**
* SDE_DEBUG - macro for kms/plane/crtc/encoder/connector logs
@@ -113,11 +114,12 @@ struct sde_encoder_hw_resources {
struct sde_kms {
struct msm_kms base;
struct drm_device *dev;
- int rev;
+ int core_rev;
struct sde_mdss_cfg *catalog;
struct msm_mmu *mmu[MSM_SMMU_DOMAIN_MAX];
int mmu_id[MSM_SMMU_DOMAIN_MAX];
+ struct sde_power_client *core_client;
/* directory entry for debugfs */
void *debugfs_root;
@@ -129,16 +131,6 @@ struct sde_kms {
struct regulator *mmagic;
struct regulator *venus;
- struct clk *axi_clk;
- struct clk *ahb_clk;
- struct clk *src_clk;
- struct clk *core_clk;
- struct clk *lut_clk;
- struct clk *mmagic_clk;
- struct clk *iommu_axi_clk[MSM_SMMU_DOMAIN_MAX];
- struct clk *iommu_ahb_clk[MSM_SMMU_DOMAIN_MAX];
- struct clk *vsync_clk;
-
struct {
unsigned long enabled_mask;
struct irq_domain *domain;
@@ -206,9 +198,6 @@ struct sde_plane_state {
((S) && ((X) < PLANE_PROP_COUNT) ? \
(uint32_t)((S)->property_values[(X)]) : 0)
-int sde_disable(struct sde_kms *sde_kms);
-int sde_enable(struct sde_kms *sde_kms);
-
/**
* Debugfs functions - extra helper functions for debugfs support
*