aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/host1x/drm/gr2d.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/host1x/drm/gr2d.c')
-rw-r--r--drivers/gpu/host1x/drm/gr2d.c100
1 files changed, 49 insertions, 51 deletions
diff --git a/drivers/gpu/host1x/drm/gr2d.c b/drivers/gpu/host1x/drm/gr2d.c
index 8d9a10f52d81..e91b184ced30 100644
--- a/drivers/gpu/host1x/drm/gr2d.c
+++ b/drivers/gpu/host1x/drm/gr2d.c
@@ -25,11 +25,14 @@
25#include "host1x_client.h" 25#include "host1x_client.h"
26#include "syncpt.h" 26#include "syncpt.h"
27 27
28#define GR2D_NUM_REGS 0x4d
29
28struct gr2d { 30struct gr2d {
29 struct host1x_client client; 31 struct host1x_client client;
30 struct clk *clk;
31 struct host1x_channel *channel; 32 struct host1x_channel *channel;
32 unsigned long *addr_regs; 33 struct clk *clk;
34
35 DECLARE_BITMAP(addr_regs, GR2D_NUM_REGS);
33}; 36};
34 37
35static inline struct gr2d *to_gr2d(struct host1x_client *client) 38static inline struct gr2d *to_gr2d(struct host1x_client *client)
@@ -37,8 +40,6 @@ static inline struct gr2d *to_gr2d(struct host1x_client *client)
37 return container_of(client, struct gr2d, client); 40 return container_of(client, struct gr2d, client);
38} 41}
39 42
40static int gr2d_is_addr_reg(struct device *dev, u32 class, u32 reg);
41
42static int gr2d_client_init(struct host1x_client *client, 43static int gr2d_client_init(struct host1x_client *client,
43 struct drm_device *drm) 44 struct drm_device *drm)
44{ 45{
@@ -56,7 +57,6 @@ static int gr2d_open_channel(struct host1x_client *client,
56 struct gr2d *gr2d = to_gr2d(client); 57 struct gr2d *gr2d = to_gr2d(client);
57 58
58 context->channel = host1x_channel_get(gr2d->channel); 59 context->channel = host1x_channel_get(gr2d->channel);
59
60 if (!context->channel) 60 if (!context->channel)
61 return -ENOMEM; 61 return -ENOMEM;
62 62
@@ -87,11 +87,35 @@ static struct host1x_bo *host1x_bo_lookup(struct drm_device *drm,
87 return &bo->base; 87 return &bo->base;
88} 88}
89 89
90static int gr2d_is_addr_reg(struct device *dev, u32 class, u32 offset)
91{
92 struct gr2d *gr2d = dev_get_drvdata(dev);
93
94 switch (class) {
95 case HOST1X_CLASS_HOST1X:
96 if (offset == 0x2b)
97 return 1;
98
99 break;
100
101 case HOST1X_CLASS_GR2D:
102 case HOST1X_CLASS_GR2D_SB:
103 if (offset >= GR2D_NUM_REGS)
104 break;
105
106 if (test_bit(offset, gr2d->addr_regs))
107 return 1;
108
109 break;
110 }
111
112 return 0;
113}
114
90static int gr2d_submit(struct tegra_drm_context *context, 115static int gr2d_submit(struct tegra_drm_context *context,
91 struct drm_tegra_submit *args, struct drm_device *drm, 116 struct drm_tegra_submit *args, struct drm_device *drm,
92 struct drm_file *file) 117 struct drm_file *file)
93{ 118{
94 struct host1x_job *job;
95 unsigned int num_cmdbufs = args->num_cmdbufs; 119 unsigned int num_cmdbufs = args->num_cmdbufs;
96 unsigned int num_relocs = args->num_relocs; 120 unsigned int num_relocs = args->num_relocs;
97 unsigned int num_waitchks = args->num_waitchks; 121 unsigned int num_waitchks = args->num_waitchks;
@@ -102,6 +126,7 @@ static int gr2d_submit(struct tegra_drm_context *context,
102 struct drm_tegra_waitchk __user *waitchks = 126 struct drm_tegra_waitchk __user *waitchks =
103 (void * __user)(uintptr_t)args->waitchks; 127 (void * __user)(uintptr_t)args->waitchks;
104 struct drm_tegra_syncpt syncpt; 128 struct drm_tegra_syncpt syncpt;
129 struct host1x_job *job;
105 int err; 130 int err;
106 131
107 /* We don't yet support other than one syncpt_incr struct per submit */ 132 /* We don't yet support other than one syncpt_incr struct per submit */
@@ -205,54 +230,25 @@ static struct host1x_client_ops gr2d_client_ops = {
205 .submit = gr2d_submit, 230 .submit = gr2d_submit,
206}; 231};
207 232
208static void gr2d_init_addr_reg_map(struct device *dev, struct gr2d *gr2d)
209{
210 const u32 gr2d_addr_regs[] = {0x1a, 0x1b, 0x26, 0x2b, 0x2c, 0x2d, 0x31,
211 0x32, 0x48, 0x49, 0x4a, 0x4b, 0x4c};
212 unsigned long *bitmap;
213 int i;
214
215 bitmap = devm_kzalloc(dev, DIV_ROUND_UP(256, BITS_PER_BYTE),
216 GFP_KERNEL);
217
218 for (i = 0; i < ARRAY_SIZE(gr2d_addr_regs); ++i) {
219 u32 reg = gr2d_addr_regs[i];
220 bitmap[BIT_WORD(reg)] |= BIT_MASK(reg);
221 }
222
223 gr2d->addr_regs = bitmap;
224}
225
226static int gr2d_is_addr_reg(struct device *dev, u32 class, u32 reg)
227{
228 struct gr2d *gr2d = dev_get_drvdata(dev);
229
230 switch (class) {
231 case HOST1X_CLASS_HOST1X:
232 return reg == 0x2b;
233 case HOST1X_CLASS_GR2D:
234 case HOST1X_CLASS_GR2D_SB:
235 reg &= 0xff;
236 if (gr2d->addr_regs[BIT_WORD(reg)] & BIT_MASK(reg))
237 return 1;
238 default:
239 return 0;
240 }
241}
242
243static const struct of_device_id gr2d_match[] = { 233static const struct of_device_id gr2d_match[] = {
244 { .compatible = "nvidia,tegra30-gr2d" }, 234 { .compatible = "nvidia,tegra30-gr2d" },
245 { .compatible = "nvidia,tegra20-gr2d" }, 235 { .compatible = "nvidia,tegra20-gr2d" },
246 { }, 236 { },
247}; 237};
248 238
239static const u32 gr2d_addr_regs[] = {
240 0x1a, 0x1b, 0x26, 0x2b, 0x2c, 0x2d, 0x31, 0x32,
241 0x48, 0x49, 0x4a, 0x4b, 0x4c
242};
243
249static int gr2d_probe(struct platform_device *pdev) 244static int gr2d_probe(struct platform_device *pdev)
250{ 245{
246 struct tegra_drm *tegra = host1x_get_drm_data(pdev->dev.parent);
251 struct device *dev = &pdev->dev; 247 struct device *dev = &pdev->dev;
252 struct tegra_drm *tegra = host1x_get_drm_data(dev->parent);
253 int err;
254 struct gr2d *gr2d = NULL;
255 struct host1x_syncpt **syncpts; 248 struct host1x_syncpt **syncpts;
249 struct gr2d *gr2d;
250 unsigned int i;
251 int err;
256 252
257 gr2d = devm_kzalloc(dev, sizeof(*gr2d), GFP_KERNEL); 253 gr2d = devm_kzalloc(dev, sizeof(*gr2d), GFP_KERNEL);
258 if (!gr2d) 254 if (!gr2d)
@@ -296,14 +292,16 @@ static int gr2d_probe(struct platform_device *pdev)
296 return err; 292 return err;
297 } 293 }
298 294
299 gr2d_init_addr_reg_map(dev, gr2d); 295 /* initialize address register map */
296 for (i = 0; i < ARRAY_SIZE(gr2d_addr_regs); i++)
297 set_bit(gr2d_addr_regs[i], gr2d->addr_regs);
300 298
301 platform_set_drvdata(pdev, gr2d); 299 platform_set_drvdata(pdev, gr2d);
302 300
303 return 0; 301 return 0;
304} 302}
305 303
306static int __exit gr2d_remove(struct platform_device *pdev) 304static int gr2d_remove(struct platform_device *pdev)
307{ 305{
308 struct tegra_drm *tegra = host1x_get_drm_data(pdev->dev.parent); 306 struct tegra_drm *tegra = host1x_get_drm_data(pdev->dev.parent);
309 struct gr2d *gr2d = platform_get_drvdata(pdev); 307 struct gr2d *gr2d = platform_get_drvdata(pdev);
@@ -312,7 +310,8 @@ static int __exit gr2d_remove(struct platform_device *pdev)
312 310
313 err = host1x_unregister_client(tegra, &gr2d->client); 311 err = host1x_unregister_client(tegra, &gr2d->client);
314 if (err < 0) { 312 if (err < 0) {
315 dev_err(&pdev->dev, "failed to unregister client: %d\n", err); 313 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
314 err);
316 return err; 315 return err;
317 } 316 }
318 317
@@ -326,11 +325,10 @@ static int __exit gr2d_remove(struct platform_device *pdev)
326} 325}
327 326
328struct platform_driver tegra_gr2d_driver = { 327struct platform_driver tegra_gr2d_driver = {
329 .probe = gr2d_probe,
330 .remove = __exit_p(gr2d_remove),
331 .driver = { 328 .driver = {
332 .owner = THIS_MODULE,
333 .name = "gr2d", 329 .name = "gr2d",
334 .of_match_table = gr2d_match, 330 .of_match_table = gr2d_match,
335 } 331 },
332 .probe = gr2d_probe,
333 .remove = gr2d_remove,
336}; 334};