1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2012-2013, NVIDIA Corporation.
7 #include <linux/iommu.h>
8 #include <linux/module.h>
9 #include <linux/of_device.h>
20 struct tegra_drm_client client
;
21 struct host1x_channel
*channel
;
24 const struct gr2d_soc
*soc
;
26 DECLARE_BITMAP(addr_regs
, GR2D_NUM_REGS
);
29 static inline struct gr2d
*to_gr2d(struct tegra_drm_client
*client
)
31 return container_of(client
, struct gr2d
, client
);
34 static int gr2d_init(struct host1x_client
*client
)
36 struct tegra_drm_client
*drm
= host1x_to_drm_client(client
);
37 struct drm_device
*dev
= dev_get_drvdata(client
->host
);
38 unsigned long flags
= HOST1X_SYNCPT_HAS_BASE
;
39 struct gr2d
*gr2d
= to_gr2d(drm
);
42 gr2d
->channel
= host1x_channel_request(client
);
46 client
->syncpts
[0] = host1x_syncpt_request(client
, flags
);
47 if (!client
->syncpts
[0]) {
49 dev_err(client
->dev
, "failed to request syncpoint: %d\n", err
);
53 err
= host1x_client_iommu_attach(client
);
55 dev_err(client
->dev
, "failed to attach to domain: %d\n", err
);
59 err
= tegra_drm_register_client(dev
->dev_private
, drm
);
61 dev_err(client
->dev
, "failed to register client: %d\n", err
);
68 host1x_client_iommu_detach(client
);
70 host1x_syncpt_free(client
->syncpts
[0]);
72 host1x_channel_put(gr2d
->channel
);
76 static int gr2d_exit(struct host1x_client
*client
)
78 struct tegra_drm_client
*drm
= host1x_to_drm_client(client
);
79 struct drm_device
*dev
= dev_get_drvdata(client
->host
);
80 struct tegra_drm
*tegra
= dev
->dev_private
;
81 struct gr2d
*gr2d
= to_gr2d(drm
);
84 err
= tegra_drm_unregister_client(tegra
, drm
);
88 host1x_client_iommu_detach(client
);
89 host1x_syncpt_free(client
->syncpts
[0]);
90 host1x_channel_put(gr2d
->channel
);
95 static const struct host1x_client_ops gr2d_client_ops
= {
100 static int gr2d_open_channel(struct tegra_drm_client
*client
,
101 struct tegra_drm_context
*context
)
103 struct gr2d
*gr2d
= to_gr2d(client
);
105 context
->channel
= host1x_channel_get(gr2d
->channel
);
106 if (!context
->channel
)
112 static void gr2d_close_channel(struct tegra_drm_context
*context
)
114 host1x_channel_put(context
->channel
);
117 static int gr2d_is_addr_reg(struct device
*dev
, u32
class, u32 offset
)
119 struct gr2d
*gr2d
= dev_get_drvdata(dev
);
122 case HOST1X_CLASS_HOST1X
:
128 case HOST1X_CLASS_GR2D
:
129 case HOST1X_CLASS_GR2D_SB
:
130 if (offset
>= GR2D_NUM_REGS
)
133 if (test_bit(offset
, gr2d
->addr_regs
))
142 static int gr2d_is_valid_class(u32
class)
144 return (class == HOST1X_CLASS_GR2D
||
145 class == HOST1X_CLASS_GR2D_SB
);
148 static const struct tegra_drm_client_ops gr2d_ops
= {
149 .open_channel
= gr2d_open_channel
,
150 .close_channel
= gr2d_close_channel
,
151 .is_addr_reg
= gr2d_is_addr_reg
,
152 .is_valid_class
= gr2d_is_valid_class
,
153 .submit
= tegra_drm_submit
,
156 static const struct gr2d_soc tegra20_gr2d_soc
= {
160 static const struct gr2d_soc tegra30_gr2d_soc
= {
164 static const struct of_device_id gr2d_match
[] = {
165 { .compatible
= "nvidia,tegra30-gr2d", .data
= &tegra20_gr2d_soc
},
166 { .compatible
= "nvidia,tegra20-gr2d", .data
= &tegra30_gr2d_soc
},
169 MODULE_DEVICE_TABLE(of
, gr2d_match
);
171 static const u32 gr2d_addr_regs
[] = {
181 GR2D_SRC_BASE_ADDR_SB
,
182 GR2D_DSTA_BASE_ADDR_SB
,
183 GR2D_DSTB_BASE_ADDR_SB
,
184 GR2D_UA_BASE_ADDR_SB
,
185 GR2D_VA_BASE_ADDR_SB
,
188 static int gr2d_probe(struct platform_device
*pdev
)
190 struct device
*dev
= &pdev
->dev
;
191 struct host1x_syncpt
**syncpts
;
196 gr2d
= devm_kzalloc(dev
, sizeof(*gr2d
), GFP_KERNEL
);
200 gr2d
->soc
= of_device_get_match_data(dev
);
202 syncpts
= devm_kzalloc(dev
, sizeof(*syncpts
), GFP_KERNEL
);
206 gr2d
->clk
= devm_clk_get(dev
, NULL
);
207 if (IS_ERR(gr2d
->clk
)) {
208 dev_err(dev
, "cannot get clock\n");
209 return PTR_ERR(gr2d
->clk
);
212 err
= clk_prepare_enable(gr2d
->clk
);
214 dev_err(dev
, "cannot turn on clock\n");
218 INIT_LIST_HEAD(&gr2d
->client
.base
.list
);
219 gr2d
->client
.base
.ops
= &gr2d_client_ops
;
220 gr2d
->client
.base
.dev
= dev
;
221 gr2d
->client
.base
.class = HOST1X_CLASS_GR2D
;
222 gr2d
->client
.base
.syncpts
= syncpts
;
223 gr2d
->client
.base
.num_syncpts
= 1;
225 INIT_LIST_HEAD(&gr2d
->client
.list
);
226 gr2d
->client
.version
= gr2d
->soc
->version
;
227 gr2d
->client
.ops
= &gr2d_ops
;
229 err
= host1x_client_register(&gr2d
->client
.base
);
231 dev_err(dev
, "failed to register host1x client: %d\n", err
);
232 clk_disable_unprepare(gr2d
->clk
);
236 /* initialize address register map */
237 for (i
= 0; i
< ARRAY_SIZE(gr2d_addr_regs
); i
++)
238 set_bit(gr2d_addr_regs
[i
], gr2d
->addr_regs
);
240 platform_set_drvdata(pdev
, gr2d
);
245 static int gr2d_remove(struct platform_device
*pdev
)
247 struct gr2d
*gr2d
= platform_get_drvdata(pdev
);
250 err
= host1x_client_unregister(&gr2d
->client
.base
);
252 dev_err(&pdev
->dev
, "failed to unregister host1x client: %d\n",
257 clk_disable_unprepare(gr2d
->clk
);
262 struct platform_driver tegra_gr2d_driver
= {
264 .name
= "tegra-gr2d",
265 .of_match_table
= gr2d_match
,
268 .remove
= gr2d_remove
,