diff options
Diffstat (limited to 'drivers/gpu/host1x/drm/gr2d.c')
-rw-r--r-- | drivers/gpu/host1x/drm/gr2d.c | 100 |
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 | |||
28 | struct gr2d { | 30 | struct 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 | ||
35 | static inline struct gr2d *to_gr2d(struct host1x_client *client) | 38 | static 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 | ||
40 | static int gr2d_is_addr_reg(struct device *dev, u32 class, u32 reg); | ||
41 | |||
42 | static int gr2d_client_init(struct host1x_client *client, | 43 | static 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 | ||
90 | static 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 | |||
90 | static int gr2d_submit(struct tegra_drm_context *context, | 115 | static 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 | ||
208 | static 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 | |||
226 | static 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 | |||
243 | static const struct of_device_id gr2d_match[] = { | 233 | static 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 | ||
239 | static const u32 gr2d_addr_regs[] = { | ||
240 | 0x1a, 0x1b, 0x26, 0x2b, 0x2c, 0x2d, 0x31, 0x32, | ||
241 | 0x48, 0x49, 0x4a, 0x4b, 0x4c | ||
242 | }; | ||
243 | |||
249 | static int gr2d_probe(struct platform_device *pdev) | 244 | static 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 | ||
306 | static int __exit gr2d_remove(struct platform_device *pdev) | 304 | static 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 | ||
328 | struct platform_driver tegra_gr2d_driver = { | 327 | struct 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 | }; |