brcm2708: update linux 4.4 patches to latest version
[openwrt/openwrt.git] / target / linux / brcm2708 / patches-4.4 / 0466-drm-vc4-Enable-runtime-PM.patch
1 From 02a0346c7f8159cb0930ff153bf2cb3b1f1a7a79 Mon Sep 17 00:00:00 2001
2 From: Eric Anholt <eric@anholt.net>
3 Date: Fri, 5 Feb 2016 17:41:49 -0800
4 Subject: [PATCH] drm/vc4: Enable runtime PM.
5
6 This may actually get us a feature that the closed driver didn't have:
7 turning off the GPU in between rendering jobs, while the V3D device is
8 still opened by the client.
9
10 There may be some tuning to be applied here to use autosuspend so that
11 we don't bounce the device's power so much, but in steady-state
12 GPU-bound rendering we keep the power on (since we keep multiple jobs
13 outstanding) and even if we power cycle on every job we can still
14 manage at least 680 fps.
15
16 More importantly, though, runtime PM will allow us to power off the
17 device to do a GPU reset.
18
19 v2: Switch #ifdef to CONFIG_PM not CONFIG_PM_SLEEP (caught by kbuild
20 test robot)
21
22 Signed-off-by: Eric Anholt <eric@anholt.net>
23 (cherry picked from commit 001bdb55d9eb72a9e2d5b623bacfc52da74ae03e)
24 ---
25 drivers/gpu/drm/vc4/vc4_drv.h | 1 +
26 drivers/gpu/drm/vc4/vc4_gem.c | 10 ++++++++
27 drivers/gpu/drm/vc4/vc4_v3d.c | 59 ++++++++++++++++++++++++++-----------------
28 3 files changed, 47 insertions(+), 23 deletions(-)
29
30 --- a/drivers/gpu/drm/vc4/vc4_drv.h
31 +++ b/drivers/gpu/drm/vc4/vc4_drv.h
32 @@ -155,6 +155,7 @@ struct vc4_seqno_cb {
33 };
34
35 struct vc4_v3d {
36 + struct vc4_dev *vc4;
37 struct platform_device *pdev;
38 void __iomem *regs;
39 };
40 --- a/drivers/gpu/drm/vc4/vc4_gem.c
41 +++ b/drivers/gpu/drm/vc4/vc4_gem.c
42 @@ -23,6 +23,7 @@
43
44 #include <linux/module.h>
45 #include <linux/platform_device.h>
46 +#include <linux/pm_runtime.h>
47 #include <linux/device.h>
48 #include <linux/io.h>
49
50 @@ -689,6 +690,7 @@ fail:
51 static void
52 vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec)
53 {
54 + struct vc4_dev *vc4 = to_vc4_dev(dev);
55 unsigned i;
56
57 /* Need the struct lock for drm_gem_object_unreference(). */
58 @@ -707,6 +709,8 @@ vc4_complete_exec(struct drm_device *dev
59 }
60 mutex_unlock(&dev->struct_mutex);
61
62 + pm_runtime_put(&vc4->v3d->pdev->dev);
63 +
64 kfree(exec);
65 }
66
67 @@ -860,6 +864,12 @@ vc4_submit_cl_ioctl(struct drm_device *d
68 return -ENOMEM;
69 }
70
71 + ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
72 + if (ret < 0) {
73 + kfree(exec);
74 + return ret;
75 + }
76 +
77 exec->args = args;
78 INIT_LIST_HEAD(&exec->unref_list);
79
80 --- a/drivers/gpu/drm/vc4/vc4_v3d.c
81 +++ b/drivers/gpu/drm/vc4/vc4_v3d.c
82 @@ -17,7 +17,7 @@
83 */
84
85 #include "linux/component.h"
86 -#include "soc/bcm2835/raspberrypi-firmware.h"
87 +#include "linux/pm_runtime.h"
88 #include "vc4_drv.h"
89 #include "vc4_regs.h"
90
91 @@ -145,22 +145,6 @@ int vc4_v3d_debugfs_ident(struct seq_fil
92 }
93 #endif /* CONFIG_DEBUG_FS */
94
95 -/*
96 - * Asks the firmware to turn on power to the V3D engine.
97 - *
98 - * This may be doable with just the clocks interface, though this
99 - * packet does some other register setup from the firmware, too.
100 - */
101 -int
102 -vc4_v3d_set_power(struct vc4_dev *vc4, bool on)
103 -{
104 - u32 packet = on;
105 -
106 - return rpi_firmware_property(vc4->firmware,
107 - RPI_FIRMWARE_SET_ENABLE_QPU,
108 - &packet, sizeof(packet));
109 -}
110 -
111 static void vc4_v3d_init_hw(struct drm_device *dev)
112 {
113 struct vc4_dev *vc4 = to_vc4_dev(dev);
114 @@ -172,6 +156,29 @@ static void vc4_v3d_init_hw(struct drm_d
115 V3D_WRITE(V3D_VPMBASE, 0);
116 }
117
118 +#ifdef CONFIG_PM
119 +static int vc4_v3d_runtime_suspend(struct device *dev)
120 +{
121 + struct vc4_v3d *v3d = dev_get_drvdata(dev);
122 + struct vc4_dev *vc4 = v3d->vc4;
123 +
124 + vc4_irq_uninstall(vc4->dev);
125 +
126 + return 0;
127 +}
128 +
129 +static int vc4_v3d_runtime_resume(struct device *dev)
130 +{
131 + struct vc4_v3d *v3d = dev_get_drvdata(dev);
132 + struct vc4_dev *vc4 = v3d->vc4;
133 +
134 + vc4_v3d_init_hw(vc4->dev);
135 + vc4_irq_postinstall(vc4->dev);
136 +
137 + return 0;
138 +}
139 +#endif
140 +
141 static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
142 {
143 struct platform_device *pdev = to_platform_device(dev);
144 @@ -184,6 +191,8 @@ static int vc4_v3d_bind(struct device *d
145 if (!v3d)
146 return -ENOMEM;
147
148 + dev_set_drvdata(dev, v3d);
149 +
150 v3d->pdev = pdev;
151
152 v3d->regs = vc4_ioremap_regs(pdev, 0);
153 @@ -191,10 +200,7 @@ static int vc4_v3d_bind(struct device *d
154 return PTR_ERR(v3d->regs);
155
156 vc4->v3d = v3d;
157 -
158 - ret = vc4_v3d_set_power(vc4, true);
159 - if (ret)
160 - return ret;
161 + v3d->vc4 = vc4;
162
163 if (V3D_READ(V3D_IDENT0) != V3D_EXPECTED_IDENT0) {
164 DRM_ERROR("V3D_IDENT0 read 0x%08x instead of 0x%08x\n",
165 @@ -216,6 +222,8 @@ static int vc4_v3d_bind(struct device *d
166 return ret;
167 }
168
169 + pm_runtime_enable(dev);
170 +
171 return 0;
172 }
173
174 @@ -225,6 +233,8 @@ static void vc4_v3d_unbind(struct device
175 struct drm_device *drm = dev_get_drvdata(master);
176 struct vc4_dev *vc4 = to_vc4_dev(drm);
177
178 + pm_runtime_disable(dev);
179 +
180 drm_irq_uninstall(drm);
181
182 /* Disable the binner's overflow memory address, so the next
183 @@ -234,11 +244,13 @@ static void vc4_v3d_unbind(struct device
184 V3D_WRITE(V3D_BPOA, 0);
185 V3D_WRITE(V3D_BPOS, 0);
186
187 - vc4_v3d_set_power(vc4, false);
188 -
189 vc4->v3d = NULL;
190 }
191
192 +static const struct dev_pm_ops vc4_v3d_pm_ops = {
193 + SET_RUNTIME_PM_OPS(vc4_v3d_runtime_suspend, vc4_v3d_runtime_resume, NULL)
194 +};
195 +
196 static const struct component_ops vc4_v3d_ops = {
197 .bind = vc4_v3d_bind,
198 .unbind = vc4_v3d_unbind,
199 @@ -267,5 +279,6 @@ struct platform_driver vc4_v3d_driver =
200 .driver = {
201 .name = "vc4_v3d",
202 .of_match_table = vc4_v3d_dt_match,
203 + .pm = &vc4_v3d_pm_ops,
204 },
205 };