summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/msm/Makefile1
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_gpu.c67
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_gpu.h17
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_pm.c203
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c219
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h9
6 files changed, 273 insertions, 243 deletions
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index e24eb5ed1952..cea5b55eebcf 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -7,6 +7,7 @@ msm-y := \
adreno/adreno_gpu.o \
adreno/adreno_ringbuffer.o \
adreno/a3xx_gpu.o \
+ adreno/a3xx_pm.o \
hdmi/hdmi.o \
hdmi/hdmi_bridge.o \
hdmi/hdmi_connector.o \
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index a31360a7ec46..c97f8f41b159 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -254,9 +254,12 @@ static int a3xx_hw_init(struct adreno_gpu *gpu)
static void a3xx_destroy(struct adreno_gpu *gpu)
{
+ struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(gpu);
DBG("%s", adreno_get_name(gpu));
+ a3xx_bs_fini(a3xx_gpu);
+
adreno_gpu_cleanup(gpu);
put_device(&gpu->pdev->dev);
kfree(gpu);
@@ -365,8 +368,8 @@ static void a3xx_show(struct adreno_gpu *gpu, struct seq_file *m)
static const struct adreno_gpu_funcs funcs = {
.get_param = adreno_get_param,
.hw_init = a3xx_hw_init,
- .pm_suspend = msm_gpu_pm_suspend,
- .pm_resume = msm_gpu_pm_resume,
+ .pm_suspend = a3xx_gpu_pm_suspend,
+ .pm_resume = a3xx_gpu_pm_resume,
.recover = adreno_recover,
.last_fence = adreno_last_fence,
.submit = adreno_submit,
@@ -379,14 +382,18 @@ static const struct adreno_gpu_funcs funcs = {
#endif
};
+static const char *clk_names[] = {
+ "src_clk", "core_clk", "iface_clk", "mem_clk", "mem_iface_clk",
+};
+
struct msm_gpu *a3xx_gpu_init(struct drm_device *dev, struct adreno_gem *gem,
struct workqueue_struct *wq, int reglog)
{
- struct adreno_gpu *adreno_gpu = NULL;
+ struct a3xx_gpu *a3xx_gpu = NULL;
struct msm_gpu *gpu;
struct platform_device *pdev = a3xx_pdev;
struct adreno_platform_config *config;
- int ret;
+ int i, ret;
if (!pdev) {
dev_err(dev->dev, "no a3xx device\n");
@@ -395,35 +402,63 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev, struct adreno_gem *gem,
config = pdev->dev.platform_data;
- adreno_gpu = kzalloc(sizeof(*adreno_gpu), GFP_KERNEL);
- if (!adreno_gpu) {
+ a3xx_gpu = kzalloc(sizeof(*a3xx_gpu), GFP_KERNEL);
+ if (!a3xx_gpu) {
ret = -ENOMEM;
goto fail;
}
- gpu = &adreno_gpu->base;
+ gpu = &a3xx_gpu->base.base;
get_device(&pdev->dev);
- adreno_gpu->pdev = pdev;
+ a3xx_gpu->base.pdev = pdev;
- gpu->fast_rate = config->fast_rate;
- gpu->slow_rate = config->slow_rate;
- gpu->bus_freq = config->bus_freq;
+ a3xx_gpu->fast_rate = config->fast_rate;
+ a3xx_gpu->slow_rate = config->slow_rate;
+ a3xx_gpu->bus_freq = config->bus_freq;
DBG("fast_rate=%u, slow_rate=%u, bus_freq=%u",
- gpu->fast_rate, gpu->slow_rate, gpu->bus_freq);
+ a3xx_gpu->fast_rate, a3xx_gpu->slow_rate, a3xx_gpu->bus_freq);
+
+ /* Acquire clocks: */
+ BUG_ON(ARRAY_SIZE(clk_names) != ARRAY_SIZE(a3xx_gpu->grp_clks));
+
+ for (i = 0; i < ARRAY_SIZE(clk_names); i++) {
+ a3xx_gpu->grp_clks[i] = devm_clk_get(&pdev->dev, clk_names[i]);
+ DBG("grp_clks[%s]: %p", clk_names[i], a3xx_gpu->grp_clks[i]);
+ if (IS_ERR(a3xx_gpu->grp_clks[i]))
+ a3xx_gpu->grp_clks[i] = NULL;
+ }
+
+ a3xx_gpu->ebi1_clk = devm_clk_get(&pdev->dev, "bus_clk");
+ DBG("ebi1_clk: %p", a3xx_gpu->ebi1_clk);
+ if (IS_ERR(a3xx_gpu->ebi1_clk))
+ a3xx_gpu->ebi1_clk = NULL;
+
+ /* Acquire regulators: */
+ a3xx_gpu->gpu_reg = devm_regulator_get(&pdev->dev, "vdd");
+ DBG("gpu_reg: %p", a3xx_gpu->gpu_reg);
+ if (IS_ERR(a3xx_gpu->gpu_reg))
+ a3xx_gpu->gpu_reg = NULL;
+
+ a3xx_gpu->gpu_cx = devm_regulator_get(&pdev->dev, "vddcx");
+ DBG("gpu_cx: %p", a3xx_gpu->gpu_cx);
+ if (IS_ERR(a3xx_gpu->gpu_cx))
+ a3xx_gpu->gpu_cx = NULL;
+
+ a3xx_bs_init(a3xx_gpu, pdev);
adreno_reglog = reglog;
- ret = adreno_gpu_init(dev, pdev, adreno_gpu,
+ ret = adreno_gpu_init(dev, pdev, &a3xx_gpu->base,
&funcs, gem, wq, config->rev);
if (ret)
goto fail;
- return &adreno_gpu->base;
+ return &a3xx_gpu->base.base;
fail:
- if (adreno_gpu)
- a3xx_destroy(adreno_gpu);
+ if (a3xx_gpu)
+ a3xx_destroy(&a3xx_gpu->base);
return ERR_PTR(ret);
}
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.h b/drivers/gpu/drm/msm/adreno/a3xx_gpu.h
index 00384e9a439c..0070c54ff2d6 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.h
@@ -21,4 +21,21 @@
#include "adreno_gpu.h"
#include "a3xx.xml.h"
+struct a3xx_gpu {
+ struct adreno_gpu base;
+
+ /* Power Control: */
+ struct regulator *gpu_reg, *gpu_cx;
+ struct clk *ebi1_clk, *grp_clks[5];
+ uint32_t fast_rate, slow_rate, bus_freq;
+ uint32_t bsc;
+};
+#define to_a3xx_gpu(x) container_of(x, struct a3xx_gpu, base)
+
+int a3xx_gpu_pm_suspend(struct adreno_gpu *gpu);
+int a3xx_gpu_pm_resume(struct adreno_gpu *gpu);
+
+void a3xx_bs_init(struct a3xx_gpu *gpu, struct platform_device *pdev);
+void a3xx_bs_fini(struct a3xx_gpu *gpu);
+
#endif /* __A3XX_GPU_H__ */
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_pm.c b/drivers/gpu/drm/msm/adreno/a3xx_pm.c
new file mode 100644
index 000000000000..f11ef116bcea
--- /dev/null
+++ b/drivers/gpu/drm/msm/adreno/a3xx_pm.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2013 Pengutronix
+ * Author: Lucas Stach <l.stach@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <adreno/a3xx_gpu.h>
+
+/*
+ * Power Management:
+ */
+
+#ifdef CONFIG_MSM_BUS_SCALING
+#include <mach/board.h>
+#include <mach/kgsl.h>
+void a3xx_bs_init(struct a3xx_gpu *gpu, struct platform_device *pdev)
+{
+ struct drm_device *dev = gpu->dev;
+ struct kgsl_device_platform_data *pdata = pdev->dev.platform_data;
+
+ if (!pdev) {
+ dev_err(dev->dev, "could not find dtv pdata\n");
+ return;
+ }
+
+ if (pdata->bus_scale_table) {
+ gpu->bsc = msm_bus_scale_register_client(pdata->bus_scale_table);
+ DBG("bus scale client: %08x", gpu->bsc);
+ }
+}
+
+void a3xx_bs_fini(struct a3xx_gpu *gpu)
+{
+ if (gpu->bsc) {
+ msm_bus_scale_unregister_client(gpu->bsc);
+ gpu->bsc = 0;
+ }
+}
+
+static void a3xx_bs_set(struct a3xx_gpu *gpu, int idx)
+{
+ if (gpu->bsc) {
+ DBG("set bus scaling: %d", idx);
+ msm_bus_scale_client_update_request(gpu->bsc, idx);
+ }
+}
+#else
+void a3xx_bs_init(struct a3xx_gpu *gpu, struct platform_device *pdev) {}
+void a3xx_bs_fini(struct a3xx_gpu *gpu) {}
+static void a3xx_bs_set(struct a3xx_gpu *gpu, int idx) {}
+#endif
+
+static int enable_pwrrail(struct a3xx_gpu *gpu)
+{
+ struct drm_device *dev = gpu->base.drm;
+ int ret = 0;
+
+ if (gpu->gpu_reg) {
+ ret = regulator_enable(gpu->gpu_reg);
+ if (ret) {
+ dev_err(dev->dev, "failed to enable 'gpu_reg': %d\n", ret);
+ return ret;
+ }
+ }
+
+ if (gpu->gpu_cx) {
+ ret = regulator_enable(gpu->gpu_cx);
+ if (ret) {
+ dev_err(dev->dev, "failed to enable 'gpu_cx': %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int disable_pwrrail(struct a3xx_gpu *gpu)
+{
+ if (gpu->gpu_cx)
+ regulator_disable(gpu->gpu_cx);
+ if (gpu->gpu_reg)
+ regulator_disable(gpu->gpu_reg);
+ return 0;
+}
+
+static int enable_clk(struct a3xx_gpu *gpu)
+{
+ struct clk *rate_clk = NULL;
+ int i;
+
+ /* NOTE: kgsl_pwrctrl_clk() ignores grp_clks[0].. */
+ for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i > 0; i--) {
+ if (gpu->grp_clks[i]) {
+ clk_prepare(gpu->grp_clks[i]);
+ rate_clk = gpu->grp_clks[i];
+ }
+ }
+
+ if (rate_clk && gpu->fast_rate)
+ clk_set_rate(rate_clk, gpu->fast_rate);
+
+ for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i > 0; i--)
+ if (gpu->grp_clks[i])
+ clk_enable(gpu->grp_clks[i]);
+
+ return 0;
+}
+
+static int disable_clk(struct a3xx_gpu *gpu)
+{
+ struct clk *rate_clk = NULL;
+ int i;
+
+ /* NOTE: kgsl_pwrctrl_clk() ignores grp_clks[0].. */
+ for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i > 0; i--) {
+ if (gpu->grp_clks[i]) {
+ clk_disable(gpu->grp_clks[i]);
+ rate_clk = gpu->grp_clks[i];
+ }
+ }
+
+ if (rate_clk && gpu->slow_rate)
+ clk_set_rate(rate_clk, gpu->slow_rate);
+
+ for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i > 0; i--)
+ if (gpu->grp_clks[i])
+ clk_unprepare(gpu->grp_clks[i]);
+
+ return 0;
+}
+
+static int enable_axi(struct a3xx_gpu *gpu)
+{
+ if (gpu->ebi1_clk)
+ clk_prepare_enable(gpu->ebi1_clk);
+ if (gpu->bus_freq)
+ a3xx_bs_set(gpu, gpu->bus_freq);
+ return 0;
+}
+
+static int disable_axi(struct a3xx_gpu *gpu)
+{
+ if (gpu->ebi1_clk)
+ clk_disable_unprepare(gpu->ebi1_clk);
+ if (gpu->bus_freq)
+ a3xx_bs_set(gpu, 0);
+ return 0;
+}
+
+int a3xx_gpu_pm_resume(struct adreno_gpu *gpu)
+{
+ struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(gpu);
+ int ret;
+
+ DBG("%s", adreno_get_name(gpu));
+
+ ret = enable_pwrrail(a3xx_gpu);
+ if (ret)
+ return ret;
+
+ ret = enable_clk(a3xx_gpu);
+ if (ret)
+ return ret;
+
+ ret = enable_axi(a3xx_gpu);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int a3xx_gpu_pm_suspend(struct adreno_gpu *gpu)
+{
+ struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(gpu);
+ int ret;
+
+ DBG("%s", adreno_get_name(gpu));
+
+ ret = disable_axi(a3xx_gpu);
+ if (ret)
+ return ret;
+
+ ret = disable_clk(a3xx_gpu);
+ if (ret)
+ return ret;
+
+ ret = disable_pwrrail(a3xx_gpu);
+ if (ret)
+ return ret;
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index a319dc1f302b..f8152472ab91 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -20,189 +20,6 @@
#include "adreno/adreno_gpu.h"
/*
- * Power Management:
- */
-
-#ifdef CONFIG_MSM_BUS_SCALING
-#include <mach/board.h>
-#include <mach/kgsl.h>
-static void bs_init(struct msm_gpu *gpu, struct platform_device *pdev)
-{
- struct drm_device *dev = gpu->dev;
- struct kgsl_device_platform_data *pdata = pdev->dev.platform_data;
-
- if (!pdev) {
- dev_err(dev->dev, "could not find dtv pdata\n");
- return;
- }
-
- if (pdata->bus_scale_table) {
- gpu->bsc = msm_bus_scale_register_client(pdata->bus_scale_table);
- DBG("bus scale client: %08x", gpu->bsc);
- }
-}
-
-static void bs_fini(struct msm_gpu *gpu)
-{
- if (gpu->bsc) {
- msm_bus_scale_unregister_client(gpu->bsc);
- gpu->bsc = 0;
- }
-}
-
-static void bs_set(struct msm_gpu *gpu, int idx)
-{
- if (gpu->bsc) {
- DBG("set bus scaling: %d", idx);
- msm_bus_scale_client_update_request(gpu->bsc, idx);
- }
-}
-#else
-static void bs_init(struct msm_gpu *gpu, struct platform_device *pdev) {}
-static void bs_fini(struct msm_gpu *gpu) {}
-static void bs_set(struct msm_gpu *gpu, int idx) {}
-#endif
-
-static int enable_pwrrail(struct msm_gpu *gpu)
-{
- struct drm_device *dev = gpu->dev;
- int ret = 0;
-
- if (gpu->gpu_reg) {
- ret = regulator_enable(gpu->gpu_reg);
- if (ret) {
- dev_err(dev->dev, "failed to enable 'gpu_reg': %d\n", ret);
- return ret;
- }
- }
-
- if (gpu->gpu_cx) {
- ret = regulator_enable(gpu->gpu_cx);
- if (ret) {
- dev_err(dev->dev, "failed to enable 'gpu_cx': %d\n", ret);
- return ret;
- }
- }
-
- return 0;
-}
-
-static int disable_pwrrail(struct msm_gpu *gpu)
-{
- if (gpu->gpu_cx)
- regulator_disable(gpu->gpu_cx);
- if (gpu->gpu_reg)
- regulator_disable(gpu->gpu_reg);
- return 0;
-}
-
-static int enable_clk(struct msm_gpu *gpu)
-{
- struct clk *rate_clk = NULL;
- int i;
-
- /* NOTE: kgsl_pwrctrl_clk() ignores grp_clks[0].. */
- for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i > 0; i--) {
- if (gpu->grp_clks[i]) {
- clk_prepare(gpu->grp_clks[i]);
- rate_clk = gpu->grp_clks[i];
- }
- }
-
- if (rate_clk && gpu->fast_rate)
- clk_set_rate(rate_clk, gpu->fast_rate);
-
- for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i > 0; i--)
- if (gpu->grp_clks[i])
- clk_enable(gpu->grp_clks[i]);
-
- return 0;
-}
-
-static int disable_clk(struct msm_gpu *gpu)
-{
- struct clk *rate_clk = NULL;
- int i;
-
- /* NOTE: kgsl_pwrctrl_clk() ignores grp_clks[0].. */
- for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i > 0; i--) {
- if (gpu->grp_clks[i]) {
- clk_disable(gpu->grp_clks[i]);
- rate_clk = gpu->grp_clks[i];
- }
- }
-
- if (rate_clk && gpu->slow_rate)
- clk_set_rate(rate_clk, gpu->slow_rate);
-
- for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i > 0; i--)
- if (gpu->grp_clks[i])
- clk_unprepare(gpu->grp_clks[i]);
-
- return 0;
-}
-
-static int enable_axi(struct msm_gpu *gpu)
-{
- if (gpu->ebi1_clk)
- clk_prepare_enable(gpu->ebi1_clk);
- if (gpu->bus_freq)
- bs_set(gpu, gpu->bus_freq);
- return 0;
-}
-
-static int disable_axi(struct msm_gpu *gpu)
-{
- if (gpu->ebi1_clk)
- clk_disable_unprepare(gpu->ebi1_clk);
- if (gpu->bus_freq)
- bs_set(gpu, 0);
- return 0;
-}
-
-int msm_gpu_pm_resume(struct adreno_gpu *gpu)
-{
- int ret;
-
- DBG("%s", adreno_get_name(gpu));
-
- ret = enable_pwrrail(&gpu->base);
- if (ret)
- return ret;
-
- ret = enable_clk(&gpu->base);
- if (ret)
- return ret;
-
- ret = enable_axi(&gpu->base);
- if (ret)
- return ret;
-
- return 0;
-}
-
-int msm_gpu_pm_suspend(struct adreno_gpu *gpu)
-{
- int ret;
-
- DBG("%s", adreno_get_name(gpu));
-
- ret = disable_axi(&gpu->base);
- if (ret)
- return ret;
-
- ret = disable_clk(&gpu->base);
- if (ret)
- return ret;
-
- ret = disable_pwrrail(&gpu->base);
- if (ret)
- return ret;
-
- return 0;
-}
-
-/*
* Cmdstream submission/retirement:
*/
@@ -285,15 +102,11 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
* Init/Cleanup:
*/
-static const char *clk_names[] = {
- "src_clk", "core_clk", "iface_clk", "mem_clk", "mem_iface_clk",
-};
-
int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
struct msm_gpu *gpu, const struct adreno_gpu_funcs *funcs,
const char *ioname, const char *irqname, int ringsz)
{
- int i, ret;
+ int ret;
gpu->dev = drm;
gpu->funcs = funcs;
@@ -301,32 +114,6 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
INIT_LIST_HEAD(&gpu->active_list);
INIT_WORK(&gpu->retire_work, retire_worker);
- BUG_ON(ARRAY_SIZE(clk_names) != ARRAY_SIZE(gpu->grp_clks));
-
- /* Acquire clocks: */
- for (i = 0; i < ARRAY_SIZE(clk_names); i++) {
- gpu->grp_clks[i] = devm_clk_get(&pdev->dev, clk_names[i]);
- DBG("grp_clks[%s]: %p", clk_names[i], gpu->grp_clks[i]);
- if (IS_ERR(gpu->grp_clks[i]))
- gpu->grp_clks[i] = NULL;
- }
-
- gpu->ebi1_clk = devm_clk_get(&pdev->dev, "bus_clk");
- DBG("ebi1_clk: %p", gpu->ebi1_clk);
- if (IS_ERR(gpu->ebi1_clk))
- gpu->ebi1_clk = NULL;
-
- /* Acquire regulators: */
- gpu->gpu_reg = devm_regulator_get(&pdev->dev, "vdd");
- DBG("gpu_reg: %p", gpu->gpu_reg);
- if (IS_ERR(gpu->gpu_reg))
- gpu->gpu_reg = NULL;
-
- gpu->gpu_cx = devm_regulator_get(&pdev->dev, "vddcx");
- DBG("gpu_cx: %p", gpu->gpu_cx);
- if (IS_ERR(gpu->gpu_cx))
- gpu->gpu_cx = NULL;
-
/* Setup IOMMU.. eventually we will (I think) do this once per context
* and have separate page tables per context. For now, to keep things
* simple and to get something working, just use a single address space:
@@ -339,8 +126,6 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
}
gpu->id = msm_register_iommu(drm, gpu->iommu);
- bs_init(gpu, pdev);
-
return 0;
fail:
@@ -353,8 +138,6 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
WARN_ON(!list_empty(&gpu->active_list));
- bs_fini(gpu);
-
if (gpu->iommu)
iommu_domain_free(gpu->iommu);
}
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 4d5ccba14853..4487e18ec526 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -51,17 +51,8 @@ struct msm_gpu {
struct iommu_domain *iommu;
int id;
-
- /* Power Control: */
- struct regulator *gpu_reg, *gpu_cx;
- struct clk *ebi1_clk, *grp_clks[5];
- uint32_t fast_rate, slow_rate, bus_freq;
- uint32_t bsc;
};
-int msm_gpu_pm_suspend(struct adreno_gpu *gpu);
-int msm_gpu_pm_resume(struct adreno_gpu *gpu);
-
void msm_gpu_retire(struct msm_gpu *gpu);
struct msm_gem_submit;
int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,