aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2013-03-22 10:34:07 -0400
committerThierry Reding <thierry.reding@avionic-design.de>2013-04-22 06:39:59 -0400
commit692e6d7be8099225f04b2d97299bc03479a5fcdb (patch)
tree13e5a72eeaca72c0b73a668f5f683df6e01619d0
parentc89c0ea63fcd045bdc17076fd078676e1da0c41a (diff)
gpu: host1x: Remove second host1x driver
Remove second host1x driver, and bind tegra-drm to the new host1x driver. The logic to parse device tree and track clients is moved to drm.c. Signed-off-by: Arto Merilainen <amerilainen@nvidia.com> Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de> Tested-by: Thierry Reding <thierry.reding@avionic-design.de> Tested-by: Erik Faye-Lund <kusmabite@gmail.com> Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
-rw-r--r--drivers/gpu/host1x/Makefile2
-rw-r--r--drivers/gpu/host1x/dev.c58
-rw-r--r--drivers/gpu/host1x/dev.h6
-rw-r--r--drivers/gpu/host1x/drm/Kconfig2
-rw-r--r--drivers/gpu/host1x/drm/dc.c5
-rw-r--r--drivers/gpu/host1x/drm/drm.c214
-rw-r--r--drivers/gpu/host1x/drm/drm.h3
-rw-r--r--drivers/gpu/host1x/drm/hdmi.c5
-rw-r--r--drivers/gpu/host1x/drm/host1x.c329
-rw-r--r--drivers/gpu/host1x/host1x_client.h35
10 files changed, 317 insertions, 342 deletions
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index 4761e8af7bdc..9a6fc767f6b8 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -13,6 +13,6 @@ host1x-y = \
13ccflags-y += -Iinclude/drm 13ccflags-y += -Iinclude/drm
14ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG 14ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG
15 15
16host1x-$(CONFIG_DRM_TEGRA) += drm/drm.o drm/fb.o drm/dc.o drm/host1x.o 16host1x-$(CONFIG_DRM_TEGRA) += drm/drm.o drm/fb.o drm/dc.o
17host1x-$(CONFIG_DRM_TEGRA) += drm/output.o drm/rgb.o drm/hdmi.o 17host1x-$(CONFIG_DRM_TEGRA) += drm/output.o drm/rgb.o drm/hdmi.o
18obj-$(CONFIG_TEGRA_HOST1X) += host1x.o 18obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index 96897242fcc2..8ce9889cefd5 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -32,6 +32,19 @@
32#include "channel.h" 32#include "channel.h"
33#include "debug.h" 33#include "debug.h"
34#include "hw/host1x01.h" 34#include "hw/host1x01.h"
35#include "host1x_client.h"
36
37void host1x_set_drm_data(struct device *dev, void *data)
38{
39 struct host1x *host1x = dev_get_drvdata(dev);
40 host1x->drm_data = data;
41}
42
43void *host1x_get_drm_data(struct device *dev)
44{
45 struct host1x *host1x = dev_get_drvdata(dev);
46 return host1x->drm_data;
47}
35 48
36void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r) 49void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r)
37{ 50{
@@ -150,6 +163,8 @@ static int host1x_probe(struct platform_device *pdev)
150 163
151 host1x_debug_init(host); 164 host1x_debug_init(host);
152 165
166 host1x_drm_alloc(pdev);
167
153 return 0; 168 return 0;
154 169
155fail_deinit_syncpt: 170fail_deinit_syncpt:
@@ -168,7 +183,7 @@ static int __exit host1x_remove(struct platform_device *pdev)
168 return 0; 183 return 0;
169} 184}
170 185
171static struct platform_driver platform_driver = { 186static struct platform_driver tegra_host1x_driver = {
172 .probe = host1x_probe, 187 .probe = host1x_probe,
173 .remove = __exit_p(host1x_remove), 188 .remove = __exit_p(host1x_remove),
174 .driver = { 189 .driver = {
@@ -178,8 +193,47 @@ static struct platform_driver platform_driver = {
178 }, 193 },
179}; 194};
180 195
181module_platform_driver(platform_driver); 196static int __init tegra_host1x_init(void)
197{
198 int err;
199
200 err = platform_driver_register(&tegra_host1x_driver);
201 if (err < 0)
202 return err;
203
204#ifdef CONFIG_DRM_TEGRA
205 err = platform_driver_register(&tegra_dc_driver);
206 if (err < 0)
207 goto unregister_host1x;
208
209 err = platform_driver_register(&tegra_hdmi_driver);
210 if (err < 0)
211 goto unregister_dc;
212#endif
213
214 return 0;
215
216#ifdef CONFIG_DRM_TEGRA
217unregister_dc:
218 platform_driver_unregister(&tegra_dc_driver);
219unregister_host1x:
220 platform_driver_unregister(&tegra_host1x_driver);
221 return err;
222#endif
223}
224module_init(tegra_host1x_init);
225
226static void __exit tegra_host1x_exit(void)
227{
228#ifdef CONFIG_DRM_TEGRA
229 platform_driver_unregister(&tegra_hdmi_driver);
230 platform_driver_unregister(&tegra_dc_driver);
231#endif
232 platform_driver_unregister(&tegra_host1x_driver);
233}
234module_exit(tegra_host1x_exit);
182 235
236MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
183MODULE_AUTHOR("Terje Bergstrom <tbergstrom@nvidia.com>"); 237MODULE_AUTHOR("Terje Bergstrom <tbergstrom@nvidia.com>");
184MODULE_DESCRIPTION("Host1x driver for Tegra products"); 238MODULE_DESCRIPTION("Host1x driver for Tegra products");
185MODULE_LICENSE("GPL"); 239MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h
index 4d16fe92400a..a1607d6e135b 100644
--- a/drivers/gpu/host1x/dev.h
+++ b/drivers/gpu/host1x/dev.h
@@ -124,6 +124,8 @@ struct host1x {
124 unsigned int num_allocated_channels; 124 unsigned int num_allocated_channels;
125 125
126 struct dentry *debugfs; 126 struct dentry *debugfs;
127
128 void *drm_data;
127}; 129};
128 130
129void host1x_sync_writel(struct host1x *host1x, u32 r, u32 v); 131void host1x_sync_writel(struct host1x *host1x, u32 r, u32 v);
@@ -299,4 +301,8 @@ static inline void host1x_hw_show_mlocks(struct host1x *host, struct output *o)
299 host->debug_op->show_mlocks(host, o); 301 host->debug_op->show_mlocks(host, o);
300} 302}
301 303
304extern struct platform_driver tegra_hdmi_driver;
305extern struct platform_driver tegra_dc_driver;
306extern struct platform_driver tegra_gr2d_driver;
307
302#endif 308#endif
diff --git a/drivers/gpu/host1x/drm/Kconfig b/drivers/gpu/host1x/drm/Kconfig
index 8267691b7aa3..33f8f7a39196 100644
--- a/drivers/gpu/host1x/drm/Kconfig
+++ b/drivers/gpu/host1x/drm/Kconfig
@@ -1,5 +1,5 @@
1config DRM_TEGRA 1config DRM_TEGRA
2 tristate "NVIDIA Tegra DRM" 2 bool "NVIDIA Tegra DRM"
3 depends on DRM && OF 3 depends on DRM && OF
4 select DRM_KMS_HELPER 4 select DRM_KMS_HELPER
5 select DRM_GEM_CMA_HELPER 5 select DRM_GEM_CMA_HELPER
diff --git a/drivers/gpu/host1x/drm/dc.c b/drivers/gpu/host1x/drm/dc.c
index d1f66099826f..29a79b66f36c 100644
--- a/drivers/gpu/host1x/drm/dc.c
+++ b/drivers/gpu/host1x/drm/dc.c
@@ -16,6 +16,7 @@
16 16
17#include "drm.h" 17#include "drm.h"
18#include "dc.h" 18#include "dc.h"
19#include "host1x_client.h"
19 20
20struct tegra_plane { 21struct tegra_plane {
21 struct drm_plane base; 22 struct drm_plane base;
@@ -1097,7 +1098,7 @@ static const struct host1x_client_ops dc_client_ops = {
1097 1098
1098static int tegra_dc_probe(struct platform_device *pdev) 1099static int tegra_dc_probe(struct platform_device *pdev)
1099{ 1100{
1100 struct host1x_drm *host1x = dev_get_drvdata(pdev->dev.parent); 1101 struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent);
1101 struct resource *regs; 1102 struct resource *regs;
1102 struct tegra_dc *dc; 1103 struct tegra_dc *dc;
1103 int err; 1104 int err;
@@ -1160,7 +1161,7 @@ static int tegra_dc_probe(struct platform_device *pdev)
1160 1161
1161static int tegra_dc_remove(struct platform_device *pdev) 1162static int tegra_dc_remove(struct platform_device *pdev)
1162{ 1163{
1163 struct host1x_drm *host1x = dev_get_drvdata(pdev->dev.parent); 1164 struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent);
1164 struct tegra_dc *dc = platform_get_drvdata(pdev); 1165 struct tegra_dc *dc = platform_get_drvdata(pdev);
1165 int err; 1166 int err;
1166 1167
diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c
index 6c59bcdb65e6..901f0b47815c 100644
--- a/drivers/gpu/host1x/drm/drm.c
+++ b/drivers/gpu/host1x/drm/drm.c
@@ -14,6 +14,7 @@
14#include <linux/dma-mapping.h> 14#include <linux/dma-mapping.h>
15#include <asm/dma-iommu.h> 15#include <asm/dma-iommu.h>
16 16
17#include "host1x_client.h"
17#include "drm.h" 18#include "drm.h"
18 19
19#define DRIVER_NAME "tegra" 20#define DRIVER_NAME "tegra"
@@ -23,13 +24,222 @@
23#define DRIVER_MINOR 0 24#define DRIVER_MINOR 0
24#define DRIVER_PATCHLEVEL 0 25#define DRIVER_PATCHLEVEL 0
25 26
27struct host1x_drm_client {
28 struct host1x_client *client;
29 struct device_node *np;
30 struct list_head list;
31};
32
33static int host1x_add_drm_client(struct host1x_drm *host1x,
34 struct device_node *np)
35{
36 struct host1x_drm_client *client;
37
38 client = kzalloc(sizeof(*client), GFP_KERNEL);
39 if (!client)
40 return -ENOMEM;
41
42 INIT_LIST_HEAD(&client->list);
43 client->np = of_node_get(np);
44
45 list_add_tail(&client->list, &host1x->drm_clients);
46
47 return 0;
48}
49
50static int host1x_activate_drm_client(struct host1x_drm *host1x,
51 struct host1x_drm_client *drm,
52 struct host1x_client *client)
53{
54 mutex_lock(&host1x->drm_clients_lock);
55 list_del_init(&drm->list);
56 list_add_tail(&drm->list, &host1x->drm_active);
57 drm->client = client;
58 mutex_unlock(&host1x->drm_clients_lock);
59
60 return 0;
61}
62
63static int host1x_remove_drm_client(struct host1x_drm *host1x,
64 struct host1x_drm_client *client)
65{
66 mutex_lock(&host1x->drm_clients_lock);
67 list_del_init(&client->list);
68 mutex_unlock(&host1x->drm_clients_lock);
69
70 of_node_put(client->np);
71 kfree(client);
72
73 return 0;
74}
75
76static int host1x_parse_dt(struct host1x_drm *host1x)
77{
78 static const char * const compat[] = {
79 "nvidia,tegra20-dc",
80 "nvidia,tegra20-hdmi",
81 "nvidia,tegra30-dc",
82 "nvidia,tegra30-hdmi",
83 };
84 unsigned int i;
85 int err;
86
87 for (i = 0; i < ARRAY_SIZE(compat); i++) {
88 struct device_node *np;
89
90 for_each_child_of_node(host1x->dev->of_node, np) {
91 if (of_device_is_compatible(np, compat[i]) &&
92 of_device_is_available(np)) {
93 err = host1x_add_drm_client(host1x, np);
94 if (err < 0)
95 return err;
96 }
97 }
98 }
99
100 return 0;
101}
102
103int host1x_drm_alloc(struct platform_device *pdev)
104{
105 struct host1x_drm *host1x;
106 int err;
107
108 host1x = devm_kzalloc(&pdev->dev, sizeof(*host1x), GFP_KERNEL);
109 if (!host1x)
110 return -ENOMEM;
111
112 mutex_init(&host1x->drm_clients_lock);
113 INIT_LIST_HEAD(&host1x->drm_clients);
114 INIT_LIST_HEAD(&host1x->drm_active);
115 mutex_init(&host1x->clients_lock);
116 INIT_LIST_HEAD(&host1x->clients);
117 host1x->dev = &pdev->dev;
118
119 err = host1x_parse_dt(host1x);
120 if (err < 0) {
121 dev_err(&pdev->dev, "failed to parse DT: %d\n", err);
122 return err;
123 }
124
125 host1x_set_drm_data(&pdev->dev, host1x);
126
127 return 0;
128}
129
130int host1x_drm_init(struct host1x_drm *host1x, struct drm_device *drm)
131{
132 struct host1x_client *client;
133
134 mutex_lock(&host1x->clients_lock);
135
136 list_for_each_entry(client, &host1x->clients, list) {
137 if (client->ops && client->ops->drm_init) {
138 int err = client->ops->drm_init(client, drm);
139 if (err < 0) {
140 dev_err(host1x->dev,
141 "DRM setup failed for %s: %d\n",
142 dev_name(client->dev), err);
143 return err;
144 }
145 }
146 }
147
148 mutex_unlock(&host1x->clients_lock);
149
150 return 0;
151}
152
153int host1x_drm_exit(struct host1x_drm *host1x)
154{
155 struct platform_device *pdev = to_platform_device(host1x->dev);
156 struct host1x_client *client;
157
158 if (!host1x->drm)
159 return 0;
160
161 mutex_lock(&host1x->clients_lock);
162
163 list_for_each_entry_reverse(client, &host1x->clients, list) {
164 if (client->ops && client->ops->drm_exit) {
165 int err = client->ops->drm_exit(client);
166 if (err < 0) {
167 dev_err(host1x->dev,
168 "DRM cleanup failed for %s: %d\n",
169 dev_name(client->dev), err);
170 return err;
171 }
172 }
173 }
174
175 mutex_unlock(&host1x->clients_lock);
176
177 drm_platform_exit(&tegra_drm_driver, pdev);
178 host1x->drm = NULL;
179
180 return 0;
181}
182
183int host1x_register_client(struct host1x_drm *host1x,
184 struct host1x_client *client)
185{
186 struct host1x_drm_client *drm, *tmp;
187 int err;
188
189 mutex_lock(&host1x->clients_lock);
190 list_add_tail(&client->list, &host1x->clients);
191 mutex_unlock(&host1x->clients_lock);
192
193 list_for_each_entry_safe(drm, tmp, &host1x->drm_clients, list)
194 if (drm->np == client->dev->of_node)
195 host1x_activate_drm_client(host1x, drm, client);
196
197 if (list_empty(&host1x->drm_clients)) {
198 struct platform_device *pdev = to_platform_device(host1x->dev);
199
200 err = drm_platform_init(&tegra_drm_driver, pdev);
201 if (err < 0) {
202 dev_err(host1x->dev, "drm_platform_init(): %d\n", err);
203 return err;
204 }
205 }
206
207 return 0;
208}
209
210int host1x_unregister_client(struct host1x_drm *host1x,
211 struct host1x_client *client)
212{
213 struct host1x_drm_client *drm, *tmp;
214 int err;
215
216 list_for_each_entry_safe(drm, tmp, &host1x->drm_active, list) {
217 if (drm->client == client) {
218 err = host1x_drm_exit(host1x);
219 if (err < 0) {
220 dev_err(host1x->dev, "host1x_drm_exit(): %d\n",
221 err);
222 return err;
223 }
224
225 host1x_remove_drm_client(host1x, drm);
226 break;
227 }
228 }
229
230 mutex_lock(&host1x->clients_lock);
231 list_del_init(&client->list);
232 mutex_unlock(&host1x->clients_lock);
233
234 return 0;
235}
236
26static int tegra_drm_load(struct drm_device *drm, unsigned long flags) 237static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
27{ 238{
28 struct device *dev = drm->dev;
29 struct host1x_drm *host1x; 239 struct host1x_drm *host1x;
30 int err; 240 int err;
31 241
32 host1x = dev_get_drvdata(dev); 242 host1x = host1x_get_drm_data(drm->dev);
33 drm->dev_private = host1x; 243 drm->dev_private = host1x;
34 host1x->drm = drm; 244 host1x->drm = drm;
35 245
diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/host1x/drm/drm.h
index 7fedb6c63191..0b8738fc444c 100644
--- a/drivers/gpu/host1x/drm/drm.h
+++ b/drivers/gpu/host1x/drm/drm.h
@@ -229,9 +229,6 @@ extern int tegra_output_exit(struct tegra_output *output);
229extern int tegra_drm_fb_init(struct drm_device *drm); 229extern int tegra_drm_fb_init(struct drm_device *drm);
230extern void tegra_drm_fb_exit(struct drm_device *drm); 230extern void tegra_drm_fb_exit(struct drm_device *drm);
231 231
232extern struct platform_driver tegra_host1x_driver;
233extern struct platform_driver tegra_hdmi_driver;
234extern struct platform_driver tegra_dc_driver;
235extern struct drm_driver tegra_drm_driver; 232extern struct drm_driver tegra_drm_driver;
236 233
237#endif /* HOST1X_DRM_H */ 234#endif /* HOST1X_DRM_H */
diff --git a/drivers/gpu/host1x/drm/hdmi.c b/drivers/gpu/host1x/drm/hdmi.c
index f438f805b767..01097da09f7f 100644
--- a/drivers/gpu/host1x/drm/hdmi.c
+++ b/drivers/gpu/host1x/drm/hdmi.c
@@ -22,6 +22,7 @@
22#include "hdmi.h" 22#include "hdmi.h"
23#include "drm.h" 23#include "drm.h"
24#include "dc.h" 24#include "dc.h"
25#include "host1x_client.h"
25 26
26struct tegra_hdmi { 27struct tegra_hdmi {
27 struct host1x_client client; 28 struct host1x_client client;
@@ -1189,7 +1190,7 @@ static const struct host1x_client_ops hdmi_client_ops = {
1189 1190
1190static int tegra_hdmi_probe(struct platform_device *pdev) 1191static int tegra_hdmi_probe(struct platform_device *pdev)
1191{ 1192{
1192 struct host1x_drm *host1x = dev_get_drvdata(pdev->dev.parent); 1193 struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent);
1193 struct tegra_hdmi *hdmi; 1194 struct tegra_hdmi *hdmi;
1194 struct resource *regs; 1195 struct resource *regs;
1195 int err; 1196 int err;
@@ -1278,7 +1279,7 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
1278 1279
1279static int tegra_hdmi_remove(struct platform_device *pdev) 1280static int tegra_hdmi_remove(struct platform_device *pdev)
1280{ 1281{
1281 struct host1x_drm *host1x = dev_get_drvdata(pdev->dev.parent); 1282 struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent);
1282 struct tegra_hdmi *hdmi = platform_get_drvdata(pdev); 1283 struct tegra_hdmi *hdmi = platform_get_drvdata(pdev);
1283 int err; 1284 int err;
1284 1285
diff --git a/drivers/gpu/host1x/drm/host1x.c b/drivers/gpu/host1x/drm/host1x.c
deleted file mode 100644
index c3d8ee54d2fd..000000000000
--- a/drivers/gpu/host1x/drm/host1x.c
+++ /dev/null
@@ -1,329 +0,0 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/clk.h>
11#include <linux/err.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/platform_device.h>
15
16#include "drm.h"
17
18struct host1x_drm_client {
19 struct host1x_client *client;
20 struct device_node *np;
21 struct list_head list;
22};
23
24static int host1x_add_drm_client(struct host1x_drm *host1x,
25 struct device_node *np)
26{
27 struct host1x_drm_client *client;
28
29 client = kzalloc(sizeof(*client), GFP_KERNEL);
30 if (!client)
31 return -ENOMEM;
32
33 INIT_LIST_HEAD(&client->list);
34 client->np = of_node_get(np);
35
36 list_add_tail(&client->list, &host1x->drm_clients);
37
38 return 0;
39}
40
41static int host1x_activate_drm_client(struct host1x_drm *host1x,
42 struct host1x_drm_client *drm,
43 struct host1x_client *client)
44{
45 mutex_lock(&host1x->drm_clients_lock);
46 list_del_init(&drm->list);
47 list_add_tail(&drm->list, &host1x->drm_active);
48 drm->client = client;
49 mutex_unlock(&host1x->drm_clients_lock);
50
51 return 0;
52}
53
54static int host1x_remove_drm_client(struct host1x_drm *host1x,
55 struct host1x_drm_client *client)
56{
57 mutex_lock(&host1x->drm_clients_lock);
58 list_del_init(&client->list);
59 mutex_unlock(&host1x->drm_clients_lock);
60
61 of_node_put(client->np);
62 kfree(client);
63
64 return 0;
65}
66
67static int host1x_parse_dt(struct host1x_drm *host1x)
68{
69 static const char * const compat[] = {
70 "nvidia,tegra20-dc",
71 "nvidia,tegra20-hdmi",
72 "nvidia,tegra30-dc",
73 "nvidia,tegra30-hdmi",
74 };
75 unsigned int i;
76 int err;
77
78 for (i = 0; i < ARRAY_SIZE(compat); i++) {
79 struct device_node *np;
80
81 for_each_child_of_node(host1x->dev->of_node, np) {
82 if (of_device_is_compatible(np, compat[i]) &&
83 of_device_is_available(np)) {
84 err = host1x_add_drm_client(host1x, np);
85 if (err < 0)
86 return err;
87 }
88 }
89 }
90
91 return 0;
92}
93
94static int tegra_host1x_probe(struct platform_device *pdev)
95{
96 struct host1x_drm *host1x;
97 struct resource *regs;
98 int err;
99
100 host1x = devm_kzalloc(&pdev->dev, sizeof(*host1x), GFP_KERNEL);
101 if (!host1x)
102 return -ENOMEM;
103
104 mutex_init(&host1x->drm_clients_lock);
105 INIT_LIST_HEAD(&host1x->drm_clients);
106 INIT_LIST_HEAD(&host1x->drm_active);
107 mutex_init(&host1x->clients_lock);
108 INIT_LIST_HEAD(&host1x->clients);
109 host1x->dev = &pdev->dev;
110
111 err = host1x_parse_dt(host1x);
112 if (err < 0) {
113 dev_err(&pdev->dev, "failed to parse DT: %d\n", err);
114 return err;
115 }
116
117 host1x->clk = devm_clk_get(&pdev->dev, NULL);
118 if (IS_ERR(host1x->clk))
119 return PTR_ERR(host1x->clk);
120
121 err = clk_prepare_enable(host1x->clk);
122 if (err < 0)
123 return err;
124
125 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
126 if (!regs) {
127 err = -ENXIO;
128 goto err;
129 }
130
131 err = platform_get_irq(pdev, 0);
132 if (err < 0)
133 goto err;
134
135 host1x->syncpt = err;
136
137 err = platform_get_irq(pdev, 1);
138 if (err < 0)
139 goto err;
140
141 host1x->irq = err;
142
143 host1x->regs = devm_ioremap_resource(&pdev->dev, regs);
144 if (IS_ERR(host1x->regs)) {
145 err = PTR_ERR(host1x->regs);
146 goto err;
147 }
148
149 platform_set_drvdata(pdev, host1x);
150
151 return 0;
152
153err:
154 clk_disable_unprepare(host1x->clk);
155 return err;
156}
157
158static int tegra_host1x_remove(struct platform_device *pdev)
159{
160 struct host1x_drm *host1x = platform_get_drvdata(pdev);
161
162 clk_disable_unprepare(host1x->clk);
163
164 return 0;
165}
166
167int host1x_drm_init(struct host1x_drm *host1x, struct drm_device *drm)
168{
169 struct host1x_client *client;
170
171 mutex_lock(&host1x->clients_lock);
172
173 list_for_each_entry(client, &host1x->clients, list) {
174 if (client->ops && client->ops->drm_init) {
175 int err = client->ops->drm_init(client, drm);
176 if (err < 0) {
177 dev_err(host1x->dev,
178 "DRM setup failed for %s: %d\n",
179 dev_name(client->dev), err);
180 return err;
181 }
182 }
183 }
184
185 mutex_unlock(&host1x->clients_lock);
186
187 return 0;
188}
189
190int host1x_drm_exit(struct host1x_drm *host1x)
191{
192 struct platform_device *pdev = to_platform_device(host1x->dev);
193 struct host1x_client *client;
194
195 if (!host1x->drm)
196 return 0;
197
198 mutex_lock(&host1x->clients_lock);
199
200 list_for_each_entry_reverse(client, &host1x->clients, list) {
201 if (client->ops && client->ops->drm_exit) {
202 int err = client->ops->drm_exit(client);
203 if (err < 0) {
204 dev_err(host1x->dev,
205 "DRM cleanup failed for %s: %d\n",
206 dev_name(client->dev), err);
207 return err;
208 }
209 }
210 }
211
212 mutex_unlock(&host1x->clients_lock);
213
214 drm_platform_exit(&tegra_drm_driver, pdev);
215 host1x->drm = NULL;
216
217 return 0;
218}
219
220int host1x_register_client(struct host1x_drm *host1x,
221 struct host1x_client *client)
222{
223 struct host1x_drm_client *drm, *tmp;
224 int err;
225
226 mutex_lock(&host1x->clients_lock);
227 list_add_tail(&client->list, &host1x->clients);
228 mutex_unlock(&host1x->clients_lock);
229
230 list_for_each_entry_safe(drm, tmp, &host1x->drm_clients, list)
231 if (drm->np == client->dev->of_node)
232 host1x_activate_drm_client(host1x, drm, client);
233
234 if (list_empty(&host1x->drm_clients)) {
235 struct platform_device *pdev = to_platform_device(host1x->dev);
236
237 err = drm_platform_init(&tegra_drm_driver, pdev);
238 if (err < 0) {
239 dev_err(host1x->dev, "drm_platform_init(): %d\n", err);
240 return err;
241 }
242 }
243
244 client->host1x = host1x;
245
246 return 0;
247}
248
249int host1x_unregister_client(struct host1x_drm *host1x,
250 struct host1x_client *client)
251{
252 struct host1x_drm_client *drm, *tmp;
253 int err;
254
255 list_for_each_entry_safe(drm, tmp, &host1x->drm_active, list) {
256 if (drm->client == client) {
257 err = host1x_drm_exit(host1x);
258 if (err < 0) {
259 dev_err(host1x->dev, "host1x_drm_exit(): %d\n",
260 err);
261 return err;
262 }
263
264 host1x_remove_drm_client(host1x, drm);
265 break;
266 }
267 }
268
269 mutex_lock(&host1x->clients_lock);
270 list_del_init(&client->list);
271 mutex_unlock(&host1x->clients_lock);
272
273 return 0;
274}
275
276static struct of_device_id tegra_host1x_of_match[] = {
277 { .compatible = "nvidia,tegra30-host1x", },
278 { .compatible = "nvidia,tegra20-host1x", },
279 { },
280};
281MODULE_DEVICE_TABLE(of, tegra_host1x_of_match);
282
283struct platform_driver tegra_host1x_driver = {
284 .driver = {
285 .name = "tegra-host1x",
286 .owner = THIS_MODULE,
287 .of_match_table = tegra_host1x_of_match,
288 },
289 .probe = tegra_host1x_probe,
290 .remove = tegra_host1x_remove,
291};
292
293static int __init tegra_host1x_init(void)
294{
295 int err;
296
297 err = platform_driver_register(&tegra_host1x_driver);
298 if (err < 0)
299 return err;
300
301 err = platform_driver_register(&tegra_dc_driver);
302 if (err < 0)
303 goto unregister_host1x;
304
305 err = platform_driver_register(&tegra_hdmi_driver);
306 if (err < 0)
307 goto unregister_dc;
308
309 return 0;
310
311unregister_dc:
312 platform_driver_unregister(&tegra_dc_driver);
313unregister_host1x:
314 platform_driver_unregister(&tegra_host1x_driver);
315 return err;
316}
317module_init(tegra_host1x_init);
318
319static void __exit tegra_host1x_exit(void)
320{
321 platform_driver_unregister(&tegra_hdmi_driver);
322 platform_driver_unregister(&tegra_dc_driver);
323 platform_driver_unregister(&tegra_host1x_driver);
324}
325module_exit(tegra_host1x_exit);
326
327MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
328MODULE_DESCRIPTION("NVIDIA Tegra DRM driver");
329MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/host1x/host1x_client.h b/drivers/gpu/host1x/host1x_client.h
new file mode 100644
index 000000000000..9b85f10f4a44
--- /dev/null
+++ b/drivers/gpu/host1x/host1x_client.h
@@ -0,0 +1,35 @@
1/*
2 * Copyright (c) 2013, NVIDIA Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef HOST1X_CLIENT_H
18#define HOST1X_CLIENT_H
19
20struct device;
21struct platform_device;
22
23#ifdef CONFIG_DRM_TEGRA
24int host1x_drm_alloc(struct platform_device *pdev);
25#else
26static inline int host1x_drm_alloc(struct platform_device *pdev)
27{
28 return 0;
29}
30#endif
31
32void host1x_set_drm_data(struct device *dev, void *data);
33void *host1x_get_drm_data(struct device *dev);
34
35#endif