aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/host1x
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/host1x')
-rw-r--r--drivers/gpu/host1x/Kconfig2
-rw-r--r--drivers/gpu/host1x/Makefile13
-rw-r--r--drivers/gpu/host1x/bus.c550
-rw-r--r--drivers/gpu/host1x/bus.h (renamed from drivers/gpu/host1x/host1x_client.h)24
-rw-r--r--drivers/gpu/host1x/cdma.c2
-rw-r--r--drivers/gpu/host1x/channel.h6
-rw-r--r--drivers/gpu/host1x/dev.c82
-rw-r--r--drivers/gpu/host1x/dev.h11
-rw-r--r--drivers/gpu/host1x/drm/Kconfig29
-rw-r--r--drivers/gpu/host1x/drm/dc.c1200
-rw-r--r--drivers/gpu/host1x/drm/dc.h400
-rw-r--r--drivers/gpu/host1x/drm/drm.c647
-rw-r--r--drivers/gpu/host1x/drm/drm.h271
-rw-r--r--drivers/gpu/host1x/drm/fb.c374
-rw-r--r--drivers/gpu/host1x/drm/gem.c258
-rw-r--r--drivers/gpu/host1x/drm/gem.h56
-rw-r--r--drivers/gpu/host1x/drm/gr2d.c343
-rw-r--r--drivers/gpu/host1x/drm/hdmi.c1304
-rw-r--r--drivers/gpu/host1x/drm/hdmi.h386
-rw-r--r--drivers/gpu/host1x/drm/output.c272
-rw-r--r--drivers/gpu/host1x/drm/rgb.c228
-rw-r--r--drivers/gpu/host1x/host1x.h30
-rw-r--r--drivers/gpu/host1x/host1x_bo.h87
-rw-r--r--drivers/gpu/host1x/hw/Makefile6
-rw-r--r--drivers/gpu/host1x/hw/cdma_hw.c8
-rw-r--r--drivers/gpu/host1x/hw/channel_hw.c32
-rw-r--r--drivers/gpu/host1x/hw/debug_hw.c16
-rw-r--r--drivers/gpu/host1x/hw/host1x01.c16
-rw-r--r--drivers/gpu/host1x/hw/host1x02.c42
-rw-r--r--drivers/gpu/host1x/hw/host1x02.h26
-rw-r--r--drivers/gpu/host1x/hw/hw_host1x01_uclass.h6
-rw-r--r--drivers/gpu/host1x/hw/hw_host1x02_channel.h121
-rw-r--r--drivers/gpu/host1x/hw/hw_host1x02_sync.h243
-rw-r--r--drivers/gpu/host1x/hw/hw_host1x02_uclass.h175
-rw-r--r--drivers/gpu/host1x/hw/intr_hw.c4
-rw-r--r--drivers/gpu/host1x/hw/syncpt_hw.c4
-rw-r--r--drivers/gpu/host1x/job.c73
-rw-r--r--drivers/gpu/host1x/job.h108
-rw-r--r--drivers/gpu/host1x/syncpt.c92
-rw-r--r--drivers/gpu/host1x/syncpt.h46
40 files changed, 1391 insertions, 6202 deletions
diff --git a/drivers/gpu/host1x/Kconfig b/drivers/gpu/host1x/Kconfig
index ccfd42b23606..7d6bed222542 100644
--- a/drivers/gpu/host1x/Kconfig
+++ b/drivers/gpu/host1x/Kconfig
@@ -19,6 +19,4 @@ config TEGRA_HOST1X_FIREWALL
19 19
20 If unsure, choose Y. 20 If unsure, choose Y.
21 21
22source "drivers/gpu/host1x/drm/Kconfig"
23
24endif 22endif
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index 3b037b6e0298..afa1e9e4e512 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -1,6 +1,5 @@
1ccflags-y = -Idrivers/gpu/host1x
2
3host1x-y = \ 1host1x-y = \
2 bus.o \
4 syncpt.o \ 3 syncpt.o \
5 dev.o \ 4 dev.o \
6 intr.o \ 5 intr.o \
@@ -8,13 +7,7 @@ host1x-y = \
8 channel.o \ 7 channel.o \
9 job.o \ 8 job.o \
10 debug.o \ 9 debug.o \
11 hw/host1x01.o 10 hw/host1x01.o \
12 11 hw/host1x02.o
13ccflags-y += -Iinclude/drm
14ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG
15 12
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
18host1x-$(CONFIG_DRM_TEGRA) += drm/gem.o
19host1x-$(CONFIG_DRM_TEGRA) += drm/gr2d.o
20obj-$(CONFIG_TEGRA_HOST1X) += host1x.o 13obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c
new file mode 100644
index 000000000000..509383f8be03
--- /dev/null
+++ b/drivers/gpu/host1x/bus.c
@@ -0,0 +1,550 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012-2013, NVIDIA Corporation
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <linux/host1x.h>
19#include <linux/of.h>
20#include <linux/slab.h>
21
22#include "dev.h"
23
24static DEFINE_MUTEX(clients_lock);
25static LIST_HEAD(clients);
26
27static DEFINE_MUTEX(drivers_lock);
28static LIST_HEAD(drivers);
29
30static DEFINE_MUTEX(devices_lock);
31static LIST_HEAD(devices);
32
33struct host1x_subdev {
34 struct host1x_client *client;
35 struct device_node *np;
36 struct list_head list;
37};
38
39/**
40 * host1x_subdev_add() - add a new subdevice with an associated device node
41 */
42static int host1x_subdev_add(struct host1x_device *device,
43 struct device_node *np)
44{
45 struct host1x_subdev *subdev;
46
47 subdev = kzalloc(sizeof(*subdev), GFP_KERNEL);
48 if (!subdev)
49 return -ENOMEM;
50
51 INIT_LIST_HEAD(&subdev->list);
52 subdev->np = of_node_get(np);
53
54 mutex_lock(&device->subdevs_lock);
55 list_add_tail(&subdev->list, &device->subdevs);
56 mutex_unlock(&device->subdevs_lock);
57
58 return 0;
59}
60
61/**
62 * host1x_subdev_del() - remove subdevice
63 */
64static void host1x_subdev_del(struct host1x_subdev *subdev)
65{
66 list_del(&subdev->list);
67 of_node_put(subdev->np);
68 kfree(subdev);
69}
70
71/**
72 * host1x_device_parse_dt() - scan device tree and add matching subdevices
73 */
74static int host1x_device_parse_dt(struct host1x_device *device)
75{
76 struct device_node *np;
77 int err;
78
79 for_each_child_of_node(device->dev.parent->of_node, np) {
80 if (of_match_node(device->driver->subdevs, np) &&
81 of_device_is_available(np)) {
82 err = host1x_subdev_add(device, np);
83 if (err < 0)
84 return err;
85 }
86 }
87
88 return 0;
89}
90
91static void host1x_subdev_register(struct host1x_device *device,
92 struct host1x_subdev *subdev,
93 struct host1x_client *client)
94{
95 int err;
96
97 /*
98 * Move the subdevice to the list of active (registered) subdevices
99 * and associate it with a client. At the same time, associate the
100 * client with its parent device.
101 */
102 mutex_lock(&device->subdevs_lock);
103 mutex_lock(&device->clients_lock);
104 list_move_tail(&client->list, &device->clients);
105 list_move_tail(&subdev->list, &device->active);
106 client->parent = &device->dev;
107 subdev->client = client;
108 mutex_unlock(&device->clients_lock);
109 mutex_unlock(&device->subdevs_lock);
110
111 /*
112 * When all subdevices have been registered, the composite device is
113 * ready to be probed.
114 */
115 if (list_empty(&device->subdevs)) {
116 err = device->driver->probe(device);
117 if (err < 0)
118 dev_err(&device->dev, "probe failed: %d\n", err);
119 }
120}
121
122static void __host1x_subdev_unregister(struct host1x_device *device,
123 struct host1x_subdev *subdev)
124{
125 struct host1x_client *client = subdev->client;
126 int err;
127
128 /*
129 * If all subdevices have been activated, we're about to remove the
130 * first active subdevice, so unload the driver first.
131 */
132 if (list_empty(&device->subdevs)) {
133 err = device->driver->remove(device);
134 if (err < 0)
135 dev_err(&device->dev, "remove failed: %d\n", err);
136 }
137
138 /*
139 * Move the subdevice back to the list of idle subdevices and remove
140 * it from list of clients.
141 */
142 mutex_lock(&device->clients_lock);
143 subdev->client = NULL;
144 client->parent = NULL;
145 list_move_tail(&subdev->list, &device->subdevs);
146 /*
147 * XXX: Perhaps don't do this here, but rather explicitly remove it
148 * when the device is about to be deleted.
149 *
150 * This is somewhat complicated by the fact that this function is
151 * used to remove the subdevice when a client is unregistered but
152 * also when the composite device is about to be removed.
153 */
154 list_del_init(&client->list);
155 mutex_unlock(&device->clients_lock);
156}
157
158static void host1x_subdev_unregister(struct host1x_device *device,
159 struct host1x_subdev *subdev)
160{
161 mutex_lock(&device->subdevs_lock);
162 __host1x_subdev_unregister(device, subdev);
163 mutex_unlock(&device->subdevs_lock);
164}
165
166int host1x_device_init(struct host1x_device *device)
167{
168 struct host1x_client *client;
169 int err;
170
171 mutex_lock(&device->clients_lock);
172
173 list_for_each_entry(client, &device->clients, list) {
174 if (client->ops && client->ops->init) {
175 err = client->ops->init(client);
176 if (err < 0) {
177 dev_err(&device->dev,
178 "failed to initialize %s: %d\n",
179 dev_name(client->dev), err);
180 mutex_unlock(&device->clients_lock);
181 return err;
182 }
183 }
184 }
185
186 mutex_unlock(&device->clients_lock);
187
188 return 0;
189}
190
191int host1x_device_exit(struct host1x_device *device)
192{
193 struct host1x_client *client;
194 int err;
195
196 mutex_lock(&device->clients_lock);
197
198 list_for_each_entry_reverse(client, &device->clients, list) {
199 if (client->ops && client->ops->exit) {
200 err = client->ops->exit(client);
201 if (err < 0) {
202 dev_err(&device->dev,
203 "failed to cleanup %s: %d\n",
204 dev_name(client->dev), err);
205 mutex_unlock(&device->clients_lock);
206 return err;
207 }
208 }
209 }
210
211 mutex_unlock(&device->clients_lock);
212
213 return 0;
214}
215
216static int host1x_register_client(struct host1x *host1x,
217 struct host1x_client *client)
218{
219 struct host1x_device *device;
220 struct host1x_subdev *subdev;
221
222 mutex_lock(&host1x->devices_lock);
223
224 list_for_each_entry(device, &host1x->devices, list) {
225 list_for_each_entry(subdev, &device->subdevs, list) {
226 if (subdev->np == client->dev->of_node) {
227 host1x_subdev_register(device, subdev, client);
228 mutex_unlock(&host1x->devices_lock);
229 return 0;
230 }
231 }
232 }
233
234 mutex_unlock(&host1x->devices_lock);
235 return -ENODEV;
236}
237
238static int host1x_unregister_client(struct host1x *host1x,
239 struct host1x_client *client)
240{
241 struct host1x_device *device, *dt;
242 struct host1x_subdev *subdev;
243
244 mutex_lock(&host1x->devices_lock);
245
246 list_for_each_entry_safe(device, dt, &host1x->devices, list) {
247 list_for_each_entry(subdev, &device->active, list) {
248 if (subdev->client == client) {
249 host1x_subdev_unregister(device, subdev);
250 mutex_unlock(&host1x->devices_lock);
251 return 0;
252 }
253 }
254 }
255
256 mutex_unlock(&host1x->devices_lock);
257 return -ENODEV;
258}
259
260struct bus_type host1x_bus_type = {
261 .name = "host1x",
262};
263
264int host1x_bus_init(void)
265{
266 return bus_register(&host1x_bus_type);
267}
268
269void host1x_bus_exit(void)
270{
271 bus_unregister(&host1x_bus_type);
272}
273
274static void host1x_device_release(struct device *dev)
275{
276 struct host1x_device *device = to_host1x_device(dev);
277
278 kfree(device);
279}
280
281static int host1x_device_add(struct host1x *host1x,
282 struct host1x_driver *driver)
283{
284 struct host1x_client *client, *tmp;
285 struct host1x_subdev *subdev;
286 struct host1x_device *device;
287 int err;
288
289 device = kzalloc(sizeof(*device), GFP_KERNEL);
290 if (!device)
291 return -ENOMEM;
292
293 mutex_init(&device->subdevs_lock);
294 INIT_LIST_HEAD(&device->subdevs);
295 INIT_LIST_HEAD(&device->active);
296 mutex_init(&device->clients_lock);
297 INIT_LIST_HEAD(&device->clients);
298 INIT_LIST_HEAD(&device->list);
299 device->driver = driver;
300
301 device->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask;
302 device->dev.dma_mask = &device->dev.coherent_dma_mask;
303 device->dev.release = host1x_device_release;
304 dev_set_name(&device->dev, driver->name);
305 device->dev.bus = &host1x_bus_type;
306 device->dev.parent = host1x->dev;
307
308 err = device_register(&device->dev);
309 if (err < 0)
310 return err;
311
312 err = host1x_device_parse_dt(device);
313 if (err < 0) {
314 device_unregister(&device->dev);
315 return err;
316 }
317
318 mutex_lock(&host1x->devices_lock);
319 list_add_tail(&device->list, &host1x->devices);
320 mutex_unlock(&host1x->devices_lock);
321
322 mutex_lock(&clients_lock);
323
324 list_for_each_entry_safe(client, tmp, &clients, list) {
325 list_for_each_entry(subdev, &device->subdevs, list) {
326 if (subdev->np == client->dev->of_node) {
327 host1x_subdev_register(device, subdev, client);
328 break;
329 }
330 }
331 }
332
333 mutex_unlock(&clients_lock);
334
335 return 0;
336}
337
338/*
339 * Removes a device by first unregistering any subdevices and then removing
340 * itself from the list of devices.
341 *
342 * This function must be called with the host1x->devices_lock held.
343 */
344static void host1x_device_del(struct host1x *host1x,
345 struct host1x_device *device)
346{
347 struct host1x_subdev *subdev, *sd;
348 struct host1x_client *client, *cl;
349
350 mutex_lock(&device->subdevs_lock);
351
352 /* unregister subdevices */
353 list_for_each_entry_safe(subdev, sd, &device->active, list) {
354 /*
355 * host1x_subdev_unregister() will remove the client from
356 * any lists, so we'll need to manually add it back to the
357 * list of idle clients.
358 *
359 * XXX: Alternatively, perhaps don't remove the client from
360 * any lists in host1x_subdev_unregister() and instead do
361 * that explicitly from host1x_unregister_client()?
362 */
363 client = subdev->client;
364
365 __host1x_subdev_unregister(device, subdev);
366
367 /* add the client to the list of idle clients */
368 mutex_lock(&clients_lock);
369 list_add_tail(&client->list, &clients);
370 mutex_unlock(&clients_lock);
371 }
372
373 /* remove subdevices */
374 list_for_each_entry_safe(subdev, sd, &device->subdevs, list)
375 host1x_subdev_del(subdev);
376
377 mutex_unlock(&device->subdevs_lock);
378
379 /* move clients to idle list */
380 mutex_lock(&clients_lock);
381 mutex_lock(&device->clients_lock);
382
383 list_for_each_entry_safe(client, cl, &device->clients, list)
384 list_move_tail(&client->list, &clients);
385
386 mutex_unlock(&device->clients_lock);
387 mutex_unlock(&clients_lock);
388
389 /* finally remove the device */
390 list_del_init(&device->list);
391 device_unregister(&device->dev);
392}
393
394static void host1x_attach_driver(struct host1x *host1x,
395 struct host1x_driver *driver)
396{
397 struct host1x_device *device;
398 int err;
399
400 mutex_lock(&host1x->devices_lock);
401
402 list_for_each_entry(device, &host1x->devices, list) {
403 if (device->driver == driver) {
404 mutex_unlock(&host1x->devices_lock);
405 return;
406 }
407 }
408
409 mutex_unlock(&host1x->devices_lock);
410
411 err = host1x_device_add(host1x, driver);
412 if (err < 0)
413 dev_err(host1x->dev, "failed to allocate device: %d\n", err);
414}
415
416static void host1x_detach_driver(struct host1x *host1x,
417 struct host1x_driver *driver)
418{
419 struct host1x_device *device, *tmp;
420
421 mutex_lock(&host1x->devices_lock);
422
423 list_for_each_entry_safe(device, tmp, &host1x->devices, list)
424 if (device->driver == driver)
425 host1x_device_del(host1x, device);
426
427 mutex_unlock(&host1x->devices_lock);
428}
429
430int host1x_register(struct host1x *host1x)
431{
432 struct host1x_driver *driver;
433
434 mutex_lock(&devices_lock);
435 list_add_tail(&host1x->list, &devices);
436 mutex_unlock(&devices_lock);
437
438 mutex_lock(&drivers_lock);
439
440 list_for_each_entry(driver, &drivers, list)
441 host1x_attach_driver(host1x, driver);
442
443 mutex_unlock(&drivers_lock);
444
445 return 0;
446}
447
448int host1x_unregister(struct host1x *host1x)
449{
450 struct host1x_driver *driver;
451
452 mutex_lock(&drivers_lock);
453
454 list_for_each_entry(driver, &drivers, list)
455 host1x_detach_driver(host1x, driver);
456
457 mutex_unlock(&drivers_lock);
458
459 mutex_lock(&devices_lock);
460 list_del_init(&host1x->list);
461 mutex_unlock(&devices_lock);
462
463 return 0;
464}
465
466int host1x_driver_register(struct host1x_driver *driver)
467{
468 struct host1x *host1x;
469
470 INIT_LIST_HEAD(&driver->list);
471
472 mutex_lock(&drivers_lock);
473 list_add_tail(&driver->list, &drivers);
474 mutex_unlock(&drivers_lock);
475
476 mutex_lock(&devices_lock);
477
478 list_for_each_entry(host1x, &devices, list)
479 host1x_attach_driver(host1x, driver);
480
481 mutex_unlock(&devices_lock);
482
483 return 0;
484}
485EXPORT_SYMBOL(host1x_driver_register);
486
487void host1x_driver_unregister(struct host1x_driver *driver)
488{
489 mutex_lock(&drivers_lock);
490 list_del_init(&driver->list);
491 mutex_unlock(&drivers_lock);
492}
493EXPORT_SYMBOL(host1x_driver_unregister);
494
495int host1x_client_register(struct host1x_client *client)
496{
497 struct host1x *host1x;
498 int err;
499
500 mutex_lock(&devices_lock);
501
502 list_for_each_entry(host1x, &devices, list) {
503 err = host1x_register_client(host1x, client);
504 if (!err) {
505 mutex_unlock(&devices_lock);
506 return 0;
507 }
508 }
509
510 mutex_unlock(&devices_lock);
511
512 mutex_lock(&clients_lock);
513 list_add_tail(&client->list, &clients);
514 mutex_unlock(&clients_lock);
515
516 return 0;
517}
518EXPORT_SYMBOL(host1x_client_register);
519
520int host1x_client_unregister(struct host1x_client *client)
521{
522 struct host1x_client *c;
523 struct host1x *host1x;
524 int err;
525
526 mutex_lock(&devices_lock);
527
528 list_for_each_entry(host1x, &devices, list) {
529 err = host1x_unregister_client(host1x, client);
530 if (!err) {
531 mutex_unlock(&devices_lock);
532 return 0;
533 }
534 }
535
536 mutex_unlock(&devices_lock);
537 mutex_lock(&clients_lock);
538
539 list_for_each_entry(c, &clients, list) {
540 if (c == client) {
541 list_del_init(&c->list);
542 break;
543 }
544 }
545
546 mutex_unlock(&clients_lock);
547
548 return 0;
549}
550EXPORT_SYMBOL(host1x_client_unregister);
diff --git a/drivers/gpu/host1x/host1x_client.h b/drivers/gpu/host1x/bus.h
index 9b85f10f4a44..4099e99212c8 100644
--- a/drivers/gpu/host1x/host1x_client.h
+++ b/drivers/gpu/host1x/bus.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2013, NVIDIA Corporation. 2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012-2013, NVIDIA Corporation
3 * 4 *
4 * This program is free software; you can redistribute it and/or modify it 5 * 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 * under the terms and conditions of the GNU General Public License,
@@ -14,22 +15,15 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */ 16 */
16 17
17#ifndef HOST1X_CLIENT_H 18#ifndef HOST1X_BUS_H
18#define HOST1X_CLIENT_H 19#define HOST1X_BUS_H
19 20
20struct device; 21struct host1x;
21struct platform_device;
22 22
23#ifdef CONFIG_DRM_TEGRA 23int host1x_bus_init(void);
24int host1x_drm_alloc(struct platform_device *pdev); 24void host1x_bus_exit(void);
25#else
26static inline int host1x_drm_alloc(struct platform_device *pdev)
27{
28 return 0;
29}
30#endif
31 25
32void host1x_set_drm_data(struct device *dev, void *data); 26int host1x_register(struct host1x *host1x);
33void *host1x_get_drm_data(struct device *dev); 27int host1x_unregister(struct host1x *host1x);
34 28
35#endif 29#endif
diff --git a/drivers/gpu/host1x/cdma.c b/drivers/gpu/host1x/cdma.c
index de72172d3b5f..3995255b16c7 100644
--- a/drivers/gpu/host1x/cdma.c
+++ b/drivers/gpu/host1x/cdma.c
@@ -20,6 +20,7 @@
20#include <asm/cacheflush.h> 20#include <asm/cacheflush.h>
21#include <linux/device.h> 21#include <linux/device.h>
22#include <linux/dma-mapping.h> 22#include <linux/dma-mapping.h>
23#include <linux/host1x.h>
23#include <linux/interrupt.h> 24#include <linux/interrupt.h>
24#include <linux/kernel.h> 25#include <linux/kernel.h>
25#include <linux/kfifo.h> 26#include <linux/kfifo.h>
@@ -30,7 +31,6 @@
30#include "channel.h" 31#include "channel.h"
31#include "dev.h" 32#include "dev.h"
32#include "debug.h" 33#include "debug.h"
33#include "host1x_bo.h"
34#include "job.h" 34#include "job.h"
35 35
36/* 36/*
diff --git a/drivers/gpu/host1x/channel.h b/drivers/gpu/host1x/channel.h
index 48723b8eea42..df767cf90d51 100644
--- a/drivers/gpu/host1x/channel.h
+++ b/drivers/gpu/host1x/channel.h
@@ -40,12 +40,6 @@ struct host1x_channel {
40/* channel list operations */ 40/* channel list operations */
41int host1x_channel_list_init(struct host1x *host); 41int host1x_channel_list_init(struct host1x *host);
42 42
43struct host1x_channel *host1x_channel_request(struct device *dev);
44void host1x_channel_free(struct host1x_channel *channel);
45struct host1x_channel *host1x_channel_get(struct host1x_channel *channel);
46void host1x_channel_put(struct host1x_channel *channel);
47int host1x_job_submit(struct host1x_job *job);
48
49#define host1x_for_each_channel(host, channel) \ 43#define host1x_for_each_channel(host, channel) \
50 list_for_each_entry(channel, &host->chlist.list, list) 44 list_for_each_entry(channel, &host->chlist.list, list)
51 45
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index 471630299878..80da003d63de 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -27,24 +27,13 @@
27#define CREATE_TRACE_POINTS 27#define CREATE_TRACE_POINTS
28#include <trace/events/host1x.h> 28#include <trace/events/host1x.h>
29 29
30#include "bus.h"
30#include "dev.h" 31#include "dev.h"
31#include "intr.h" 32#include "intr.h"
32#include "channel.h" 33#include "channel.h"
33#include "debug.h" 34#include "debug.h"
34#include "hw/host1x01.h" 35#include "hw/host1x01.h"
35#include "host1x_client.h" 36#include "hw/host1x02.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 ? host1x->drm_data : NULL;
47}
48 37
49void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r) 38void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r)
50{ 39{
@@ -79,7 +68,17 @@ static const struct host1x_info host1x01_info = {
79 .sync_offset = 0x3000, 68 .sync_offset = 0x3000,
80}; 69};
81 70
71static const struct host1x_info host1x02_info = {
72 .nb_channels = 9,
73 .nb_pts = 32,
74 .nb_mlocks = 16,
75 .nb_bases = 12,
76 .init = host1x02_init,
77 .sync_offset = 0x3000,
78};
79
82static struct of_device_id host1x_of_match[] = { 80static struct of_device_id host1x_of_match[] = {
81 { .compatible = "nvidia,tegra114-host1x", .data = &host1x02_info, },
83 { .compatible = "nvidia,tegra30-host1x", .data = &host1x01_info, }, 82 { .compatible = "nvidia,tegra30-host1x", .data = &host1x01_info, },
84 { .compatible = "nvidia,tegra20-host1x", .data = &host1x01_info, }, 83 { .compatible = "nvidia,tegra20-host1x", .data = &host1x01_info, },
85 { }, 84 { },
@@ -114,6 +113,9 @@ static int host1x_probe(struct platform_device *pdev)
114 if (!host) 113 if (!host)
115 return -ENOMEM; 114 return -ENOMEM;
116 115
116 mutex_init(&host->devices_lock);
117 INIT_LIST_HEAD(&host->devices);
118 INIT_LIST_HEAD(&host->list);
117 host->dev = &pdev->dev; 119 host->dev = &pdev->dev;
118 host->info = id->data; 120 host->info = id->data;
119 121
@@ -152,7 +154,7 @@ static int host1x_probe(struct platform_device *pdev)
152 err = host1x_syncpt_init(host); 154 err = host1x_syncpt_init(host);
153 if (err) { 155 if (err) {
154 dev_err(&pdev->dev, "failed to initialize syncpts\n"); 156 dev_err(&pdev->dev, "failed to initialize syncpts\n");
155 return err; 157 goto fail_unprepare_disable;
156 } 158 }
157 159
158 err = host1x_intr_init(host, syncpt_irq); 160 err = host1x_intr_init(host, syncpt_irq);
@@ -163,19 +165,26 @@ static int host1x_probe(struct platform_device *pdev)
163 165
164 host1x_debug_init(host); 166 host1x_debug_init(host);
165 167
166 host1x_drm_alloc(pdev); 168 err = host1x_register(host);
169 if (err < 0)
170 goto fail_deinit_intr;
167 171
168 return 0; 172 return 0;
169 173
174fail_deinit_intr:
175 host1x_intr_deinit(host);
170fail_deinit_syncpt: 176fail_deinit_syncpt:
171 host1x_syncpt_deinit(host); 177 host1x_syncpt_deinit(host);
178fail_unprepare_disable:
179 clk_disable_unprepare(host->clk);
172 return err; 180 return err;
173} 181}
174 182
175static int __exit host1x_remove(struct platform_device *pdev) 183static int host1x_remove(struct platform_device *pdev)
176{ 184{
177 struct host1x *host = platform_get_drvdata(pdev); 185 struct host1x *host = platform_get_drvdata(pdev);
178 186
187 host1x_unregister(host);
179 host1x_intr_deinit(host); 188 host1x_intr_deinit(host);
180 host1x_syncpt_deinit(host); 189 host1x_syncpt_deinit(host);
181 clk_disable_unprepare(host->clk); 190 clk_disable_unprepare(host->clk);
@@ -184,59 +193,36 @@ static int __exit host1x_remove(struct platform_device *pdev)
184} 193}
185 194
186static struct platform_driver tegra_host1x_driver = { 195static struct platform_driver tegra_host1x_driver = {
187 .probe = host1x_probe,
188 .remove = __exit_p(host1x_remove),
189 .driver = { 196 .driver = {
190 .owner = THIS_MODULE,
191 .name = "tegra-host1x", 197 .name = "tegra-host1x",
192 .of_match_table = host1x_of_match, 198 .of_match_table = host1x_of_match,
193 }, 199 },
200 .probe = host1x_probe,
201 .remove = host1x_remove,
194}; 202};
195 203
196static int __init tegra_host1x_init(void) 204static int __init tegra_host1x_init(void)
197{ 205{
198 int err; 206 int err;
199 207
200 err = platform_driver_register(&tegra_host1x_driver); 208 err = host1x_bus_init();
201 if (err < 0) 209 if (err < 0)
202 return err; 210 return err;
203 211
204#ifdef CONFIG_DRM_TEGRA 212 err = platform_driver_register(&tegra_host1x_driver);
205 err = platform_driver_register(&tegra_dc_driver); 213 if (err < 0) {
206 if (err < 0) 214 host1x_bus_exit();
207 goto unregister_host1x; 215 return err;
208 216 }
209 err = platform_driver_register(&tegra_hdmi_driver);
210 if (err < 0)
211 goto unregister_dc;
212
213 err = platform_driver_register(&tegra_gr2d_driver);
214 if (err < 0)
215 goto unregister_hdmi;
216#endif
217 217
218 return 0; 218 return 0;
219
220#ifdef CONFIG_DRM_TEGRA
221unregister_hdmi:
222 platform_driver_unregister(&tegra_hdmi_driver);
223unregister_dc:
224 platform_driver_unregister(&tegra_dc_driver);
225unregister_host1x:
226 platform_driver_unregister(&tegra_host1x_driver);
227 return err;
228#endif
229} 219}
230module_init(tegra_host1x_init); 220module_init(tegra_host1x_init);
231 221
232static void __exit tegra_host1x_exit(void) 222static void __exit tegra_host1x_exit(void)
233{ 223{
234#ifdef CONFIG_DRM_TEGRA
235 platform_driver_unregister(&tegra_gr2d_driver);
236 platform_driver_unregister(&tegra_hdmi_driver);
237 platform_driver_unregister(&tegra_dc_driver);
238#endif
239 platform_driver_unregister(&tegra_host1x_driver); 224 platform_driver_unregister(&tegra_host1x_driver);
225 host1x_bus_exit();
240} 226}
241module_exit(tegra_host1x_exit); 227module_exit(tegra_host1x_exit);
242 228
diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h
index bed90a8131be..a61a976e7a42 100644
--- a/drivers/gpu/host1x/dev.h
+++ b/drivers/gpu/host1x/dev.h
@@ -27,6 +27,7 @@
27#include "job.h" 27#include "job.h"
28 28
29struct host1x_syncpt; 29struct host1x_syncpt;
30struct host1x_syncpt_base;
30struct host1x_channel; 31struct host1x_channel;
31struct host1x_cdma; 32struct host1x_cdma;
32struct host1x_job; 33struct host1x_job;
@@ -102,6 +103,7 @@ struct host1x {
102 103
103 void __iomem *regs; 104 void __iomem *regs;
104 struct host1x_syncpt *syncpt; 105 struct host1x_syncpt *syncpt;
106 struct host1x_syncpt_base *bases;
105 struct device *dev; 107 struct device *dev;
106 struct clk *clk; 108 struct clk *clk;
107 109
@@ -125,7 +127,10 @@ struct host1x {
125 127
126 struct dentry *debugfs; 128 struct dentry *debugfs;
127 129
128 void *drm_data; 130 struct mutex devices_lock;
131 struct list_head devices;
132
133 struct list_head list;
129}; 134};
130 135
131void host1x_sync_writel(struct host1x *host1x, u32 r, u32 v); 136void host1x_sync_writel(struct host1x *host1x, u32 r, u32 v);
@@ -301,8 +306,4 @@ static inline void host1x_hw_show_mlocks(struct host1x *host, struct output *o)
301 host->debug_op->show_mlocks(host, o); 306 host->debug_op->show_mlocks(host, o);
302} 307}
303 308
304extern struct platform_driver tegra_dc_driver;
305extern struct platform_driver tegra_hdmi_driver;
306extern struct platform_driver tegra_gr2d_driver;
307
308#endif 309#endif
diff --git a/drivers/gpu/host1x/drm/Kconfig b/drivers/gpu/host1x/drm/Kconfig
deleted file mode 100644
index 69853a4de40a..000000000000
--- a/drivers/gpu/host1x/drm/Kconfig
+++ /dev/null
@@ -1,29 +0,0 @@
1config DRM_TEGRA
2 bool "NVIDIA Tegra DRM"
3 depends on DRM
4 select DRM_KMS_HELPER
5 select FB_SYS_FILLRECT
6 select FB_SYS_COPYAREA
7 select FB_SYS_IMAGEBLIT
8 help
9 Choose this option if you have an NVIDIA Tegra SoC.
10
11 To compile this driver as a module, choose M here: the module
12 will be called tegra-drm.
13
14if DRM_TEGRA
15
16config DRM_TEGRA_STAGING
17 bool "Enable HOST1X interface"
18 depends on STAGING
19 help
20 Say yes if HOST1X should be available for userspace DRM users.
21
22 If unsure, choose N.
23
24config DRM_TEGRA_DEBUG
25 bool "NVIDIA Tegra DRM debug support"
26 help
27 Say yes here to enable debugging support.
28
29endif
diff --git a/drivers/gpu/host1x/drm/dc.c b/drivers/gpu/host1x/drm/dc.c
deleted file mode 100644
index b1a05ad901c3..000000000000
--- a/drivers/gpu/host1x/drm/dc.c
+++ /dev/null
@@ -1,1200 +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/debugfs.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/platform_device.h>
15#include <linux/clk/tegra.h>
16
17#include "host1x_client.h"
18#include "dc.h"
19#include "drm.h"
20#include "gem.h"
21
22struct tegra_plane {
23 struct drm_plane base;
24 unsigned int index;
25};
26
27static inline struct tegra_plane *to_tegra_plane(struct drm_plane *plane)
28{
29 return container_of(plane, struct tegra_plane, base);
30}
31
32static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
33 struct drm_framebuffer *fb, int crtc_x,
34 int crtc_y, unsigned int crtc_w,
35 unsigned int crtc_h, uint32_t src_x,
36 uint32_t src_y, uint32_t src_w, uint32_t src_h)
37{
38 struct tegra_plane *p = to_tegra_plane(plane);
39 struct tegra_dc *dc = to_tegra_dc(crtc);
40 struct tegra_dc_window window;
41 unsigned int i;
42
43 memset(&window, 0, sizeof(window));
44 window.src.x = src_x >> 16;
45 window.src.y = src_y >> 16;
46 window.src.w = src_w >> 16;
47 window.src.h = src_h >> 16;
48 window.dst.x = crtc_x;
49 window.dst.y = crtc_y;
50 window.dst.w = crtc_w;
51 window.dst.h = crtc_h;
52 window.format = tegra_dc_format(fb->pixel_format);
53 window.bits_per_pixel = fb->bits_per_pixel;
54
55 for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
56 struct tegra_bo *bo = tegra_fb_get_plane(fb, i);
57
58 window.base[i] = bo->paddr + fb->offsets[i];
59
60 /*
61 * Tegra doesn't support different strides for U and V planes
62 * so we display a warning if the user tries to display a
63 * framebuffer with such a configuration.
64 */
65 if (i >= 2) {
66 if (fb->pitches[i] != window.stride[1])
67 DRM_ERROR("unsupported UV-plane configuration\n");
68 } else {
69 window.stride[i] = fb->pitches[i];
70 }
71 }
72
73 return tegra_dc_setup_window(dc, p->index, &window);
74}
75
76static int tegra_plane_disable(struct drm_plane *plane)
77{
78 struct tegra_dc *dc = to_tegra_dc(plane->crtc);
79 struct tegra_plane *p = to_tegra_plane(plane);
80 unsigned long value;
81
82 if (!plane->crtc)
83 return 0;
84
85 value = WINDOW_A_SELECT << p->index;
86 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
87
88 value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
89 value &= ~WIN_ENABLE;
90 tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
91
92 tegra_dc_writel(dc, WIN_A_UPDATE << p->index, DC_CMD_STATE_CONTROL);
93 tegra_dc_writel(dc, WIN_A_ACT_REQ << p->index, DC_CMD_STATE_CONTROL);
94
95 return 0;
96}
97
98static void tegra_plane_destroy(struct drm_plane *plane)
99{
100 tegra_plane_disable(plane);
101 drm_plane_cleanup(plane);
102}
103
104static const struct drm_plane_funcs tegra_plane_funcs = {
105 .update_plane = tegra_plane_update,
106 .disable_plane = tegra_plane_disable,
107 .destroy = tegra_plane_destroy,
108};
109
110static const uint32_t plane_formats[] = {
111 DRM_FORMAT_XBGR8888,
112 DRM_FORMAT_XRGB8888,
113 DRM_FORMAT_RGB565,
114 DRM_FORMAT_UYVY,
115 DRM_FORMAT_YUV420,
116 DRM_FORMAT_YUV422,
117};
118
119static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc)
120{
121 unsigned int i;
122 int err = 0;
123
124 for (i = 0; i < 2; i++) {
125 struct tegra_plane *plane;
126
127 plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
128 if (!plane)
129 return -ENOMEM;
130
131 plane->index = 1 + i;
132
133 err = drm_plane_init(drm, &plane->base, 1 << dc->pipe,
134 &tegra_plane_funcs, plane_formats,
135 ARRAY_SIZE(plane_formats), false);
136 if (err < 0)
137 return err;
138 }
139
140 return 0;
141}
142
143static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
144 struct drm_framebuffer *fb)
145{
146 unsigned int format = tegra_dc_format(fb->pixel_format);
147 struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
148 unsigned long value;
149
150 tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER);
151
152 value = fb->offsets[0] + y * fb->pitches[0] +
153 x * fb->bits_per_pixel / 8;
154
155 tegra_dc_writel(dc, bo->paddr + value, DC_WINBUF_START_ADDR);
156 tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE);
157 tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH);
158
159 value = GENERAL_UPDATE | WIN_A_UPDATE;
160 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
161
162 value = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
163 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
164
165 return 0;
166}
167
168void tegra_dc_enable_vblank(struct tegra_dc *dc)
169{
170 unsigned long value, flags;
171
172 spin_lock_irqsave(&dc->lock, flags);
173
174 value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
175 value |= VBLANK_INT;
176 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
177
178 spin_unlock_irqrestore(&dc->lock, flags);
179}
180
181void tegra_dc_disable_vblank(struct tegra_dc *dc)
182{
183 unsigned long value, flags;
184
185 spin_lock_irqsave(&dc->lock, flags);
186
187 value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
188 value &= ~VBLANK_INT;
189 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
190
191 spin_unlock_irqrestore(&dc->lock, flags);
192}
193
194static void tegra_dc_finish_page_flip(struct tegra_dc *dc)
195{
196 struct drm_device *drm = dc->base.dev;
197 struct drm_crtc *crtc = &dc->base;
198 unsigned long flags, base;
199 struct tegra_bo *bo;
200
201 if (!dc->event)
202 return;
203
204 bo = tegra_fb_get_plane(crtc->fb, 0);
205
206 /* check if new start address has been latched */
207 tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);
208 base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR);
209 tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS);
210
211 if (base == bo->paddr + crtc->fb->offsets[0]) {
212 spin_lock_irqsave(&drm->event_lock, flags);
213 drm_send_vblank_event(drm, dc->pipe, dc->event);
214 drm_vblank_put(drm, dc->pipe);
215 dc->event = NULL;
216 spin_unlock_irqrestore(&drm->event_lock, flags);
217 }
218}
219
220void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
221{
222 struct tegra_dc *dc = to_tegra_dc(crtc);
223 struct drm_device *drm = crtc->dev;
224 unsigned long flags;
225
226 spin_lock_irqsave(&drm->event_lock, flags);
227
228 if (dc->event && dc->event->base.file_priv == file) {
229 dc->event->base.destroy(&dc->event->base);
230 drm_vblank_put(drm, dc->pipe);
231 dc->event = NULL;
232 }
233
234 spin_unlock_irqrestore(&drm->event_lock, flags);
235}
236
237static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
238 struct drm_pending_vblank_event *event, uint32_t page_flip_flags)
239{
240 struct tegra_dc *dc = to_tegra_dc(crtc);
241 struct drm_device *drm = crtc->dev;
242
243 if (dc->event)
244 return -EBUSY;
245
246 if (event) {
247 event->pipe = dc->pipe;
248 dc->event = event;
249 drm_vblank_get(drm, dc->pipe);
250 }
251
252 tegra_dc_set_base(dc, 0, 0, fb);
253 crtc->fb = fb;
254
255 return 0;
256}
257
258static const struct drm_crtc_funcs tegra_crtc_funcs = {
259 .page_flip = tegra_dc_page_flip,
260 .set_config = drm_crtc_helper_set_config,
261 .destroy = drm_crtc_cleanup,
262};
263
264static void tegra_crtc_disable(struct drm_crtc *crtc)
265{
266 struct drm_device *drm = crtc->dev;
267 struct drm_plane *plane;
268
269 list_for_each_entry(plane, &drm->mode_config.plane_list, head) {
270 if (plane->crtc == crtc) {
271 tegra_plane_disable(plane);
272 plane->crtc = NULL;
273
274 if (plane->fb) {
275 drm_framebuffer_unreference(plane->fb);
276 plane->fb = NULL;
277 }
278 }
279 }
280}
281
282static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc,
283 const struct drm_display_mode *mode,
284 struct drm_display_mode *adjusted)
285{
286 return true;
287}
288
289static inline u32 compute_dda_inc(unsigned int in, unsigned int out, bool v,
290 unsigned int bpp)
291{
292 fixed20_12 outf = dfixed_init(out);
293 fixed20_12 inf = dfixed_init(in);
294 u32 dda_inc;
295 int max;
296
297 if (v)
298 max = 15;
299 else {
300 switch (bpp) {
301 case 2:
302 max = 8;
303 break;
304
305 default:
306 WARN_ON_ONCE(1);
307 /* fallthrough */
308 case 4:
309 max = 4;
310 break;
311 }
312 }
313
314 outf.full = max_t(u32, outf.full - dfixed_const(1), dfixed_const(1));
315 inf.full -= dfixed_const(1);
316
317 dda_inc = dfixed_div(inf, outf);
318 dda_inc = min_t(u32, dda_inc, dfixed_const(max));
319
320 return dda_inc;
321}
322
323static inline u32 compute_initial_dda(unsigned int in)
324{
325 fixed20_12 inf = dfixed_init(in);
326 return dfixed_frac(inf);
327}
328
329static int tegra_dc_set_timings(struct tegra_dc *dc,
330 struct drm_display_mode *mode)
331{
332 /* TODO: For HDMI compliance, h & v ref_to_sync should be set to 1 */
333 unsigned int h_ref_to_sync = 0;
334 unsigned int v_ref_to_sync = 0;
335 unsigned long value;
336
337 tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
338
339 value = (v_ref_to_sync << 16) | h_ref_to_sync;
340 tegra_dc_writel(dc, value, DC_DISP_REF_TO_SYNC);
341
342 value = ((mode->vsync_end - mode->vsync_start) << 16) |
343 ((mode->hsync_end - mode->hsync_start) << 0);
344 tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH);
345
346 value = ((mode->vtotal - mode->vsync_end) << 16) |
347 ((mode->htotal - mode->hsync_end) << 0);
348 tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH);
349
350 value = ((mode->vsync_start - mode->vdisplay) << 16) |
351 ((mode->hsync_start - mode->hdisplay) << 0);
352 tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH);
353
354 value = (mode->vdisplay << 16) | mode->hdisplay;
355 tegra_dc_writel(dc, value, DC_DISP_ACTIVE);
356
357 return 0;
358}
359
360static int tegra_crtc_setup_clk(struct drm_crtc *crtc,
361 struct drm_display_mode *mode,
362 unsigned long *div)
363{
364 unsigned long pclk = mode->clock * 1000, rate;
365 struct tegra_dc *dc = to_tegra_dc(crtc);
366 struct tegra_output *output = NULL;
367 struct drm_encoder *encoder;
368 long err;
369
370 list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list, head)
371 if (encoder->crtc == crtc) {
372 output = encoder_to_output(encoder);
373 break;
374 }
375
376 if (!output)
377 return -ENODEV;
378
379 /*
380 * This assumes that the display controller will divide its parent
381 * clock by 2 to generate the pixel clock.
382 */
383 err = tegra_output_setup_clock(output, dc->clk, pclk * 2);
384 if (err < 0) {
385 dev_err(dc->dev, "failed to setup clock: %ld\n", err);
386 return err;
387 }
388
389 rate = clk_get_rate(dc->clk);
390 *div = (rate * 2 / pclk) - 2;
391
392 DRM_DEBUG_KMS("rate: %lu, div: %lu\n", rate, *div);
393
394 return 0;
395}
396
397static bool tegra_dc_format_is_yuv(unsigned int format, bool *planar)
398{
399 switch (format) {
400 case WIN_COLOR_DEPTH_YCbCr422:
401 case WIN_COLOR_DEPTH_YUV422:
402 if (planar)
403 *planar = false;
404
405 return true;
406
407 case WIN_COLOR_DEPTH_YCbCr420P:
408 case WIN_COLOR_DEPTH_YUV420P:
409 case WIN_COLOR_DEPTH_YCbCr422P:
410 case WIN_COLOR_DEPTH_YUV422P:
411 case WIN_COLOR_DEPTH_YCbCr422R:
412 case WIN_COLOR_DEPTH_YUV422R:
413 case WIN_COLOR_DEPTH_YCbCr422RA:
414 case WIN_COLOR_DEPTH_YUV422RA:
415 if (planar)
416 *planar = true;
417
418 return true;
419 }
420
421 return false;
422}
423
424int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
425 const struct tegra_dc_window *window)
426{
427 unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp;
428 unsigned long value;
429 bool yuv, planar;
430
431 /*
432 * For YUV planar modes, the number of bytes per pixel takes into
433 * account only the luma component and therefore is 1.
434 */
435 yuv = tegra_dc_format_is_yuv(window->format, &planar);
436 if (!yuv)
437 bpp = window->bits_per_pixel / 8;
438 else
439 bpp = planar ? 1 : 2;
440
441 value = WINDOW_A_SELECT << index;
442 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
443
444 tegra_dc_writel(dc, window->format, DC_WIN_COLOR_DEPTH);
445 tegra_dc_writel(dc, 0, DC_WIN_BYTE_SWAP);
446
447 value = V_POSITION(window->dst.y) | H_POSITION(window->dst.x);
448 tegra_dc_writel(dc, value, DC_WIN_POSITION);
449
450 value = V_SIZE(window->dst.h) | H_SIZE(window->dst.w);
451 tegra_dc_writel(dc, value, DC_WIN_SIZE);
452
453 h_offset = window->src.x * bpp;
454 v_offset = window->src.y;
455 h_size = window->src.w * bpp;
456 v_size = window->src.h;
457
458 value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size);
459 tegra_dc_writel(dc, value, DC_WIN_PRESCALED_SIZE);
460
461 /*
462 * For DDA computations the number of bytes per pixel for YUV planar
463 * modes needs to take into account all Y, U and V components.
464 */
465 if (yuv && planar)
466 bpp = 2;
467
468 h_dda = compute_dda_inc(window->src.w, window->dst.w, false, bpp);
469 v_dda = compute_dda_inc(window->src.h, window->dst.h, true, bpp);
470
471 value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda);
472 tegra_dc_writel(dc, value, DC_WIN_DDA_INC);
473
474 h_dda = compute_initial_dda(window->src.x);
475 v_dda = compute_initial_dda(window->src.y);
476
477 tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
478 tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
479
480 tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
481 tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
482
483 tegra_dc_writel(dc, window->base[0], DC_WINBUF_START_ADDR);
484
485 if (yuv && planar) {
486 tegra_dc_writel(dc, window->base[1], DC_WINBUF_START_ADDR_U);
487 tegra_dc_writel(dc, window->base[2], DC_WINBUF_START_ADDR_V);
488 value = window->stride[1] << 16 | window->stride[0];
489 tegra_dc_writel(dc, value, DC_WIN_LINE_STRIDE);
490 } else {
491 tegra_dc_writel(dc, window->stride[0], DC_WIN_LINE_STRIDE);
492 }
493
494 tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
495 tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
496
497 value = WIN_ENABLE;
498
499 if (yuv) {
500 /* setup default colorspace conversion coefficients */
501 tegra_dc_writel(dc, 0x00f0, DC_WIN_CSC_YOF);
502 tegra_dc_writel(dc, 0x012a, DC_WIN_CSC_KYRGB);
503 tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KUR);
504 tegra_dc_writel(dc, 0x0198, DC_WIN_CSC_KVR);
505 tegra_dc_writel(dc, 0x039b, DC_WIN_CSC_KUG);
506 tegra_dc_writel(dc, 0x032f, DC_WIN_CSC_KVG);
507 tegra_dc_writel(dc, 0x0204, DC_WIN_CSC_KUB);
508 tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KVB);
509
510 value |= CSC_ENABLE;
511 } else if (window->bits_per_pixel < 24) {
512 value |= COLOR_EXPAND;
513 }
514
515 tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
516
517 /*
518 * Disable blending and assume Window A is the bottom-most window,
519 * Window C is the top-most window and Window B is in the middle.
520 */
521 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_NOKEY);
522 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_1WIN);
523
524 switch (index) {
525 case 0:
526 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_X);
527 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
528 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
529 break;
530
531 case 1:
532 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
533 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
534 tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
535 break;
536
537 case 2:
538 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
539 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_Y);
540 tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_3WIN_XY);
541 break;
542 }
543
544 tegra_dc_writel(dc, WIN_A_UPDATE << index, DC_CMD_STATE_CONTROL);
545 tegra_dc_writel(dc, WIN_A_ACT_REQ << index, DC_CMD_STATE_CONTROL);
546
547 return 0;
548}
549
550unsigned int tegra_dc_format(uint32_t format)
551{
552 switch (format) {
553 case DRM_FORMAT_XBGR8888:
554 return WIN_COLOR_DEPTH_R8G8B8A8;
555
556 case DRM_FORMAT_XRGB8888:
557 return WIN_COLOR_DEPTH_B8G8R8A8;
558
559 case DRM_FORMAT_RGB565:
560 return WIN_COLOR_DEPTH_B5G6R5;
561
562 case DRM_FORMAT_UYVY:
563 return WIN_COLOR_DEPTH_YCbCr422;
564
565 case DRM_FORMAT_YUV420:
566 return WIN_COLOR_DEPTH_YCbCr420P;
567
568 case DRM_FORMAT_YUV422:
569 return WIN_COLOR_DEPTH_YCbCr422P;
570
571 default:
572 break;
573 }
574
575 WARN(1, "unsupported pixel format %u, using default\n", format);
576 return WIN_COLOR_DEPTH_B8G8R8A8;
577}
578
579static int tegra_crtc_mode_set(struct drm_crtc *crtc,
580 struct drm_display_mode *mode,
581 struct drm_display_mode *adjusted,
582 int x, int y, struct drm_framebuffer *old_fb)
583{
584 struct tegra_bo *bo = tegra_fb_get_plane(crtc->fb, 0);
585 struct tegra_dc *dc = to_tegra_dc(crtc);
586 struct tegra_dc_window window;
587 unsigned long div, value;
588 int err;
589
590 drm_vblank_pre_modeset(crtc->dev, dc->pipe);
591
592 err = tegra_crtc_setup_clk(crtc, mode, &div);
593 if (err) {
594 dev_err(dc->dev, "failed to setup clock for CRTC: %d\n", err);
595 return err;
596 }
597
598 /* program display mode */
599 tegra_dc_set_timings(dc, mode);
600
601 value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL;
602 tegra_dc_writel(dc, value, DC_DISP_DATA_ENABLE_OPTIONS);
603
604 value = tegra_dc_readl(dc, DC_COM_PIN_OUTPUT_POLARITY(1));
605 value &= ~LVS_OUTPUT_POLARITY_LOW;
606 value &= ~LHS_OUTPUT_POLARITY_LOW;
607 tegra_dc_writel(dc, value, DC_COM_PIN_OUTPUT_POLARITY(1));
608
609 value = DISP_DATA_FORMAT_DF1P1C | DISP_ALIGNMENT_MSB |
610 DISP_ORDER_RED_BLUE;
611 tegra_dc_writel(dc, value, DC_DISP_DISP_INTERFACE_CONTROL);
612
613 tegra_dc_writel(dc, 0x00010001, DC_DISP_SHIFT_CLOCK_OPTIONS);
614
615 value = SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER_PCD1;
616 tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
617
618 /* setup window parameters */
619 memset(&window, 0, sizeof(window));
620 window.src.x = 0;
621 window.src.y = 0;
622 window.src.w = mode->hdisplay;
623 window.src.h = mode->vdisplay;
624 window.dst.x = 0;
625 window.dst.y = 0;
626 window.dst.w = mode->hdisplay;
627 window.dst.h = mode->vdisplay;
628 window.format = tegra_dc_format(crtc->fb->pixel_format);
629 window.bits_per_pixel = crtc->fb->bits_per_pixel;
630 window.stride[0] = crtc->fb->pitches[0];
631 window.base[0] = bo->paddr;
632
633 err = tegra_dc_setup_window(dc, 0, &window);
634 if (err < 0)
635 dev_err(dc->dev, "failed to enable root plane\n");
636
637 return 0;
638}
639
640static int tegra_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
641 struct drm_framebuffer *old_fb)
642{
643 struct tegra_dc *dc = to_tegra_dc(crtc);
644
645 return tegra_dc_set_base(dc, x, y, crtc->fb);
646}
647
648static void tegra_crtc_prepare(struct drm_crtc *crtc)
649{
650 struct tegra_dc *dc = to_tegra_dc(crtc);
651 unsigned int syncpt;
652 unsigned long value;
653
654 /* hardware initialization */
655 tegra_periph_reset_deassert(dc->clk);
656 usleep_range(10000, 20000);
657
658 if (dc->pipe)
659 syncpt = SYNCPT_VBLANK1;
660 else
661 syncpt = SYNCPT_VBLANK0;
662
663 /* initialize display controller */
664 tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
665 tegra_dc_writel(dc, 0x100 | syncpt, DC_CMD_CONT_SYNCPT_VSYNC);
666
667 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | WIN_A_OF_INT;
668 tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
669
670 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
671 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
672 tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
673
674 value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
675 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
676 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
677
678 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
679 value |= DISP_CTRL_MODE_C_DISPLAY;
680 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
681
682 /* initialize timer */
683 value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |
684 WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);
685 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY);
686
687 value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(1) |
688 WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1);
689 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
690
691 value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
692 tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
693
694 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
695 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
696}
697
698static void tegra_crtc_commit(struct drm_crtc *crtc)
699{
700 struct tegra_dc *dc = to_tegra_dc(crtc);
701 unsigned long value;
702
703 value = GENERAL_UPDATE | WIN_A_UPDATE;
704 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
705
706 value = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
707 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
708
709 drm_vblank_post_modeset(crtc->dev, dc->pipe);
710}
711
712static void tegra_crtc_load_lut(struct drm_crtc *crtc)
713{
714}
715
716static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
717 .disable = tegra_crtc_disable,
718 .mode_fixup = tegra_crtc_mode_fixup,
719 .mode_set = tegra_crtc_mode_set,
720 .mode_set_base = tegra_crtc_mode_set_base,
721 .prepare = tegra_crtc_prepare,
722 .commit = tegra_crtc_commit,
723 .load_lut = tegra_crtc_load_lut,
724};
725
726static irqreturn_t tegra_dc_irq(int irq, void *data)
727{
728 struct tegra_dc *dc = data;
729 unsigned long status;
730
731 status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
732 tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
733
734 if (status & FRAME_END_INT) {
735 /*
736 dev_dbg(dc->dev, "%s(): frame end\n", __func__);
737 */
738 }
739
740 if (status & VBLANK_INT) {
741 /*
742 dev_dbg(dc->dev, "%s(): vertical blank\n", __func__);
743 */
744 drm_handle_vblank(dc->base.dev, dc->pipe);
745 tegra_dc_finish_page_flip(dc);
746 }
747
748 if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) {
749 /*
750 dev_dbg(dc->dev, "%s(): underflow\n", __func__);
751 */
752 }
753
754 return IRQ_HANDLED;
755}
756
757static int tegra_dc_show_regs(struct seq_file *s, void *data)
758{
759 struct drm_info_node *node = s->private;
760 struct tegra_dc *dc = node->info_ent->data;
761
762#define DUMP_REG(name) \
763 seq_printf(s, "%-40s %#05x %08lx\n", #name, name, \
764 tegra_dc_readl(dc, name))
765
766 DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT);
767 DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
768 DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_ERROR);
769 DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT);
770 DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_CNTRL);
771 DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_ERROR);
772 DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT);
773 DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_CNTRL);
774 DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_ERROR);
775 DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT);
776 DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_CNTRL);
777 DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_ERROR);
778 DUMP_REG(DC_CMD_CONT_SYNCPT_VSYNC);
779 DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0);
780 DUMP_REG(DC_CMD_DISPLAY_COMMAND);
781 DUMP_REG(DC_CMD_SIGNAL_RAISE);
782 DUMP_REG(DC_CMD_DISPLAY_POWER_CONTROL);
783 DUMP_REG(DC_CMD_INT_STATUS);
784 DUMP_REG(DC_CMD_INT_MASK);
785 DUMP_REG(DC_CMD_INT_ENABLE);
786 DUMP_REG(DC_CMD_INT_TYPE);
787 DUMP_REG(DC_CMD_INT_POLARITY);
788 DUMP_REG(DC_CMD_SIGNAL_RAISE1);
789 DUMP_REG(DC_CMD_SIGNAL_RAISE2);
790 DUMP_REG(DC_CMD_SIGNAL_RAISE3);
791 DUMP_REG(DC_CMD_STATE_ACCESS);
792 DUMP_REG(DC_CMD_STATE_CONTROL);
793 DUMP_REG(DC_CMD_DISPLAY_WINDOW_HEADER);
794 DUMP_REG(DC_CMD_REG_ACT_CONTROL);
795 DUMP_REG(DC_COM_CRC_CONTROL);
796 DUMP_REG(DC_COM_CRC_CHECKSUM);
797 DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(0));
798 DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(1));
799 DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(2));
800 DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(3));
801 DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(0));
802 DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(1));
803 DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(2));
804 DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(3));
805 DUMP_REG(DC_COM_PIN_OUTPUT_DATA(0));
806 DUMP_REG(DC_COM_PIN_OUTPUT_DATA(1));
807 DUMP_REG(DC_COM_PIN_OUTPUT_DATA(2));
808 DUMP_REG(DC_COM_PIN_OUTPUT_DATA(3));
809 DUMP_REG(DC_COM_PIN_INPUT_ENABLE(0));
810 DUMP_REG(DC_COM_PIN_INPUT_ENABLE(1));
811 DUMP_REG(DC_COM_PIN_INPUT_ENABLE(2));
812 DUMP_REG(DC_COM_PIN_INPUT_ENABLE(3));
813 DUMP_REG(DC_COM_PIN_INPUT_DATA(0));
814 DUMP_REG(DC_COM_PIN_INPUT_DATA(1));
815 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(0));
816 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(1));
817 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(2));
818 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(3));
819 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(4));
820 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(5));
821 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(6));
822 DUMP_REG(DC_COM_PIN_MISC_CONTROL);
823 DUMP_REG(DC_COM_PIN_PM0_CONTROL);
824 DUMP_REG(DC_COM_PIN_PM0_DUTY_CYCLE);
825 DUMP_REG(DC_COM_PIN_PM1_CONTROL);
826 DUMP_REG(DC_COM_PIN_PM1_DUTY_CYCLE);
827 DUMP_REG(DC_COM_SPI_CONTROL);
828 DUMP_REG(DC_COM_SPI_START_BYTE);
829 DUMP_REG(DC_COM_HSPI_WRITE_DATA_AB);
830 DUMP_REG(DC_COM_HSPI_WRITE_DATA_CD);
831 DUMP_REG(DC_COM_HSPI_CS_DC);
832 DUMP_REG(DC_COM_SCRATCH_REGISTER_A);
833 DUMP_REG(DC_COM_SCRATCH_REGISTER_B);
834 DUMP_REG(DC_COM_GPIO_CTRL);
835 DUMP_REG(DC_COM_GPIO_DEBOUNCE_COUNTER);
836 DUMP_REG(DC_COM_CRC_CHECKSUM_LATCHED);
837 DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS0);
838 DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS1);
839 DUMP_REG(DC_DISP_DISP_WIN_OPTIONS);
840 DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY);
841 DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
842 DUMP_REG(DC_DISP_DISP_TIMING_OPTIONS);
843 DUMP_REG(DC_DISP_REF_TO_SYNC);
844 DUMP_REG(DC_DISP_SYNC_WIDTH);
845 DUMP_REG(DC_DISP_BACK_PORCH);
846 DUMP_REG(DC_DISP_ACTIVE);
847 DUMP_REG(DC_DISP_FRONT_PORCH);
848 DUMP_REG(DC_DISP_H_PULSE0_CONTROL);
849 DUMP_REG(DC_DISP_H_PULSE0_POSITION_A);
850 DUMP_REG(DC_DISP_H_PULSE0_POSITION_B);
851 DUMP_REG(DC_DISP_H_PULSE0_POSITION_C);
852 DUMP_REG(DC_DISP_H_PULSE0_POSITION_D);
853 DUMP_REG(DC_DISP_H_PULSE1_CONTROL);
854 DUMP_REG(DC_DISP_H_PULSE1_POSITION_A);
855 DUMP_REG(DC_DISP_H_PULSE1_POSITION_B);
856 DUMP_REG(DC_DISP_H_PULSE1_POSITION_C);
857 DUMP_REG(DC_DISP_H_PULSE1_POSITION_D);
858 DUMP_REG(DC_DISP_H_PULSE2_CONTROL);
859 DUMP_REG(DC_DISP_H_PULSE2_POSITION_A);
860 DUMP_REG(DC_DISP_H_PULSE2_POSITION_B);
861 DUMP_REG(DC_DISP_H_PULSE2_POSITION_C);
862 DUMP_REG(DC_DISP_H_PULSE2_POSITION_D);
863 DUMP_REG(DC_DISP_V_PULSE0_CONTROL);
864 DUMP_REG(DC_DISP_V_PULSE0_POSITION_A);
865 DUMP_REG(DC_DISP_V_PULSE0_POSITION_B);
866 DUMP_REG(DC_DISP_V_PULSE0_POSITION_C);
867 DUMP_REG(DC_DISP_V_PULSE1_CONTROL);
868 DUMP_REG(DC_DISP_V_PULSE1_POSITION_A);
869 DUMP_REG(DC_DISP_V_PULSE1_POSITION_B);
870 DUMP_REG(DC_DISP_V_PULSE1_POSITION_C);
871 DUMP_REG(DC_DISP_V_PULSE2_CONTROL);
872 DUMP_REG(DC_DISP_V_PULSE2_POSITION_A);
873 DUMP_REG(DC_DISP_V_PULSE3_CONTROL);
874 DUMP_REG(DC_DISP_V_PULSE3_POSITION_A);
875 DUMP_REG(DC_DISP_M0_CONTROL);
876 DUMP_REG(DC_DISP_M1_CONTROL);
877 DUMP_REG(DC_DISP_DI_CONTROL);
878 DUMP_REG(DC_DISP_PP_CONTROL);
879 DUMP_REG(DC_DISP_PP_SELECT_A);
880 DUMP_REG(DC_DISP_PP_SELECT_B);
881 DUMP_REG(DC_DISP_PP_SELECT_C);
882 DUMP_REG(DC_DISP_PP_SELECT_D);
883 DUMP_REG(DC_DISP_DISP_CLOCK_CONTROL);
884 DUMP_REG(DC_DISP_DISP_INTERFACE_CONTROL);
885 DUMP_REG(DC_DISP_DISP_COLOR_CONTROL);
886 DUMP_REG(DC_DISP_SHIFT_CLOCK_OPTIONS);
887 DUMP_REG(DC_DISP_DATA_ENABLE_OPTIONS);
888 DUMP_REG(DC_DISP_SERIAL_INTERFACE_OPTIONS);
889 DUMP_REG(DC_DISP_LCD_SPI_OPTIONS);
890 DUMP_REG(DC_DISP_BORDER_COLOR);
891 DUMP_REG(DC_DISP_COLOR_KEY0_LOWER);
892 DUMP_REG(DC_DISP_COLOR_KEY0_UPPER);
893 DUMP_REG(DC_DISP_COLOR_KEY1_LOWER);
894 DUMP_REG(DC_DISP_COLOR_KEY1_UPPER);
895 DUMP_REG(DC_DISP_CURSOR_FOREGROUND);
896 DUMP_REG(DC_DISP_CURSOR_BACKGROUND);
897 DUMP_REG(DC_DISP_CURSOR_START_ADDR);
898 DUMP_REG(DC_DISP_CURSOR_START_ADDR_NS);
899 DUMP_REG(DC_DISP_CURSOR_POSITION);
900 DUMP_REG(DC_DISP_CURSOR_POSITION_NS);
901 DUMP_REG(DC_DISP_INIT_SEQ_CONTROL);
902 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_A);
903 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_B);
904 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_C);
905 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_D);
906 DUMP_REG(DC_DISP_DC_MCCIF_FIFOCTRL);
907 DUMP_REG(DC_DISP_MCCIF_DISPLAY0A_HYST);
908 DUMP_REG(DC_DISP_MCCIF_DISPLAY0B_HYST);
909 DUMP_REG(DC_DISP_MCCIF_DISPLAY1A_HYST);
910 DUMP_REG(DC_DISP_MCCIF_DISPLAY1B_HYST);
911 DUMP_REG(DC_DISP_DAC_CRT_CTRL);
912 DUMP_REG(DC_DISP_DISP_MISC_CONTROL);
913 DUMP_REG(DC_DISP_SD_CONTROL);
914 DUMP_REG(DC_DISP_SD_CSC_COEFF);
915 DUMP_REG(DC_DISP_SD_LUT(0));
916 DUMP_REG(DC_DISP_SD_LUT(1));
917 DUMP_REG(DC_DISP_SD_LUT(2));
918 DUMP_REG(DC_DISP_SD_LUT(3));
919 DUMP_REG(DC_DISP_SD_LUT(4));
920 DUMP_REG(DC_DISP_SD_LUT(5));
921 DUMP_REG(DC_DISP_SD_LUT(6));
922 DUMP_REG(DC_DISP_SD_LUT(7));
923 DUMP_REG(DC_DISP_SD_LUT(8));
924 DUMP_REG(DC_DISP_SD_FLICKER_CONTROL);
925 DUMP_REG(DC_DISP_DC_PIXEL_COUNT);
926 DUMP_REG(DC_DISP_SD_HISTOGRAM(0));
927 DUMP_REG(DC_DISP_SD_HISTOGRAM(1));
928 DUMP_REG(DC_DISP_SD_HISTOGRAM(2));
929 DUMP_REG(DC_DISP_SD_HISTOGRAM(3));
930 DUMP_REG(DC_DISP_SD_HISTOGRAM(4));
931 DUMP_REG(DC_DISP_SD_HISTOGRAM(5));
932 DUMP_REG(DC_DISP_SD_HISTOGRAM(6));
933 DUMP_REG(DC_DISP_SD_HISTOGRAM(7));
934 DUMP_REG(DC_DISP_SD_BL_TF(0));
935 DUMP_REG(DC_DISP_SD_BL_TF(1));
936 DUMP_REG(DC_DISP_SD_BL_TF(2));
937 DUMP_REG(DC_DISP_SD_BL_TF(3));
938 DUMP_REG(DC_DISP_SD_BL_CONTROL);
939 DUMP_REG(DC_DISP_SD_HW_K_VALUES);
940 DUMP_REG(DC_DISP_SD_MAN_K_VALUES);
941 DUMP_REG(DC_WIN_WIN_OPTIONS);
942 DUMP_REG(DC_WIN_BYTE_SWAP);
943 DUMP_REG(DC_WIN_BUFFER_CONTROL);
944 DUMP_REG(DC_WIN_COLOR_DEPTH);
945 DUMP_REG(DC_WIN_POSITION);
946 DUMP_REG(DC_WIN_SIZE);
947 DUMP_REG(DC_WIN_PRESCALED_SIZE);
948 DUMP_REG(DC_WIN_H_INITIAL_DDA);
949 DUMP_REG(DC_WIN_V_INITIAL_DDA);
950 DUMP_REG(DC_WIN_DDA_INC);
951 DUMP_REG(DC_WIN_LINE_STRIDE);
952 DUMP_REG(DC_WIN_BUF_STRIDE);
953 DUMP_REG(DC_WIN_UV_BUF_STRIDE);
954 DUMP_REG(DC_WIN_BUFFER_ADDR_MODE);
955 DUMP_REG(DC_WIN_DV_CONTROL);
956 DUMP_REG(DC_WIN_BLEND_NOKEY);
957 DUMP_REG(DC_WIN_BLEND_1WIN);
958 DUMP_REG(DC_WIN_BLEND_2WIN_X);
959 DUMP_REG(DC_WIN_BLEND_2WIN_Y);
960 DUMP_REG(DC_WIN_BLEND_3WIN_XY);
961 DUMP_REG(DC_WIN_HP_FETCH_CONTROL);
962 DUMP_REG(DC_WINBUF_START_ADDR);
963 DUMP_REG(DC_WINBUF_START_ADDR_NS);
964 DUMP_REG(DC_WINBUF_START_ADDR_U);
965 DUMP_REG(DC_WINBUF_START_ADDR_U_NS);
966 DUMP_REG(DC_WINBUF_START_ADDR_V);
967 DUMP_REG(DC_WINBUF_START_ADDR_V_NS);
968 DUMP_REG(DC_WINBUF_ADDR_H_OFFSET);
969 DUMP_REG(DC_WINBUF_ADDR_H_OFFSET_NS);
970 DUMP_REG(DC_WINBUF_ADDR_V_OFFSET);
971 DUMP_REG(DC_WINBUF_ADDR_V_OFFSET_NS);
972 DUMP_REG(DC_WINBUF_UFLOW_STATUS);
973 DUMP_REG(DC_WINBUF_AD_UFLOW_STATUS);
974 DUMP_REG(DC_WINBUF_BD_UFLOW_STATUS);
975 DUMP_REG(DC_WINBUF_CD_UFLOW_STATUS);
976
977#undef DUMP_REG
978
979 return 0;
980}
981
982static struct drm_info_list debugfs_files[] = {
983 { "regs", tegra_dc_show_regs, 0, NULL },
984};
985
986static int tegra_dc_debugfs_init(struct tegra_dc *dc, struct drm_minor *minor)
987{
988 unsigned int i;
989 char *name;
990 int err;
991
992 name = kasprintf(GFP_KERNEL, "dc.%d", dc->pipe);
993 dc->debugfs = debugfs_create_dir(name, minor->debugfs_root);
994 kfree(name);
995
996 if (!dc->debugfs)
997 return -ENOMEM;
998
999 dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
1000 GFP_KERNEL);
1001 if (!dc->debugfs_files) {
1002 err = -ENOMEM;
1003 goto remove;
1004 }
1005
1006 for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
1007 dc->debugfs_files[i].data = dc;
1008
1009 err = drm_debugfs_create_files(dc->debugfs_files,
1010 ARRAY_SIZE(debugfs_files),
1011 dc->debugfs, minor);
1012 if (err < 0)
1013 goto free;
1014
1015 dc->minor = minor;
1016
1017 return 0;
1018
1019free:
1020 kfree(dc->debugfs_files);
1021 dc->debugfs_files = NULL;
1022remove:
1023 debugfs_remove(dc->debugfs);
1024 dc->debugfs = NULL;
1025
1026 return err;
1027}
1028
1029static int tegra_dc_debugfs_exit(struct tegra_dc *dc)
1030{
1031 drm_debugfs_remove_files(dc->debugfs_files, ARRAY_SIZE(debugfs_files),
1032 dc->minor);
1033 dc->minor = NULL;
1034
1035 kfree(dc->debugfs_files);
1036 dc->debugfs_files = NULL;
1037
1038 debugfs_remove(dc->debugfs);
1039 dc->debugfs = NULL;
1040
1041 return 0;
1042}
1043
1044static int tegra_dc_drm_init(struct host1x_client *client,
1045 struct drm_device *drm)
1046{
1047 struct tegra_dc *dc = host1x_client_to_dc(client);
1048 int err;
1049
1050 dc->pipe = drm->mode_config.num_crtc;
1051
1052 drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs);
1053 drm_mode_crtc_set_gamma_size(&dc->base, 256);
1054 drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
1055
1056 err = tegra_dc_rgb_init(drm, dc);
1057 if (err < 0 && err != -ENODEV) {
1058 dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
1059 return err;
1060 }
1061
1062 err = tegra_dc_add_planes(drm, dc);
1063 if (err < 0)
1064 return err;
1065
1066 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1067 err = tegra_dc_debugfs_init(dc, drm->primary);
1068 if (err < 0)
1069 dev_err(dc->dev, "debugfs setup failed: %d\n", err);
1070 }
1071
1072 err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0,
1073 dev_name(dc->dev), dc);
1074 if (err < 0) {
1075 dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq,
1076 err);
1077 return err;
1078 }
1079
1080 return 0;
1081}
1082
1083static int tegra_dc_drm_exit(struct host1x_client *client)
1084{
1085 struct tegra_dc *dc = host1x_client_to_dc(client);
1086 int err;
1087
1088 devm_free_irq(dc->dev, dc->irq, dc);
1089
1090 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1091 err = tegra_dc_debugfs_exit(dc);
1092 if (err < 0)
1093 dev_err(dc->dev, "debugfs cleanup failed: %d\n", err);
1094 }
1095
1096 err = tegra_dc_rgb_exit(dc);
1097 if (err) {
1098 dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err);
1099 return err;
1100 }
1101
1102 return 0;
1103}
1104
1105static const struct host1x_client_ops dc_client_ops = {
1106 .drm_init = tegra_dc_drm_init,
1107 .drm_exit = tegra_dc_drm_exit,
1108};
1109
1110static int tegra_dc_probe(struct platform_device *pdev)
1111{
1112 struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent);
1113 struct resource *regs;
1114 struct tegra_dc *dc;
1115 int err;
1116
1117 dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
1118 if (!dc)
1119 return -ENOMEM;
1120
1121 spin_lock_init(&dc->lock);
1122 INIT_LIST_HEAD(&dc->list);
1123 dc->dev = &pdev->dev;
1124
1125 dc->clk = devm_clk_get(&pdev->dev, NULL);
1126 if (IS_ERR(dc->clk)) {
1127 dev_err(&pdev->dev, "failed to get clock\n");
1128 return PTR_ERR(dc->clk);
1129 }
1130
1131 err = clk_prepare_enable(dc->clk);
1132 if (err < 0)
1133 return err;
1134
1135 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1136 dc->regs = devm_ioremap_resource(&pdev->dev, regs);
1137 if (IS_ERR(dc->regs))
1138 return PTR_ERR(dc->regs);
1139
1140 dc->irq = platform_get_irq(pdev, 0);
1141 if (dc->irq < 0) {
1142 dev_err(&pdev->dev, "failed to get IRQ\n");
1143 return -ENXIO;
1144 }
1145
1146 INIT_LIST_HEAD(&dc->client.list);
1147 dc->client.ops = &dc_client_ops;
1148 dc->client.dev = &pdev->dev;
1149
1150 err = tegra_dc_rgb_probe(dc);
1151 if (err < 0 && err != -ENODEV) {
1152 dev_err(&pdev->dev, "failed to probe RGB output: %d\n", err);
1153 return err;
1154 }
1155
1156 err = host1x_register_client(host1x, &dc->client);
1157 if (err < 0) {
1158 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1159 err);
1160 return err;
1161 }
1162
1163 platform_set_drvdata(pdev, dc);
1164
1165 return 0;
1166}
1167
1168static int tegra_dc_remove(struct platform_device *pdev)
1169{
1170 struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent);
1171 struct tegra_dc *dc = platform_get_drvdata(pdev);
1172 int err;
1173
1174 err = host1x_unregister_client(host1x, &dc->client);
1175 if (err < 0) {
1176 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1177 err);
1178 return err;
1179 }
1180
1181 clk_disable_unprepare(dc->clk);
1182
1183 return 0;
1184}
1185
1186static struct of_device_id tegra_dc_of_match[] = {
1187 { .compatible = "nvidia,tegra30-dc", },
1188 { .compatible = "nvidia,tegra20-dc", },
1189 { },
1190};
1191
1192struct platform_driver tegra_dc_driver = {
1193 .driver = {
1194 .name = "tegra-dc",
1195 .owner = THIS_MODULE,
1196 .of_match_table = tegra_dc_of_match,
1197 },
1198 .probe = tegra_dc_probe,
1199 .remove = tegra_dc_remove,
1200};
diff --git a/drivers/gpu/host1x/drm/dc.h b/drivers/gpu/host1x/drm/dc.h
deleted file mode 100644
index 79eaec9aac77..000000000000
--- a/drivers/gpu/host1x/drm/dc.h
+++ /dev/null
@@ -1,400 +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#ifndef TEGRA_DC_H
11#define TEGRA_DC_H 1
12
13#define DC_CMD_GENERAL_INCR_SYNCPT 0x000
14#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x001
15#define DC_CMD_GENERAL_INCR_SYNCPT_ERROR 0x002
16#define DC_CMD_WIN_A_INCR_SYNCPT 0x008
17#define DC_CMD_WIN_A_INCR_SYNCPT_CNTRL 0x009
18#define DC_CMD_WIN_A_INCR_SYNCPT_ERROR 0x00a
19#define DC_CMD_WIN_B_INCR_SYNCPT 0x010
20#define DC_CMD_WIN_B_INCR_SYNCPT_CNTRL 0x011
21#define DC_CMD_WIN_B_INCR_SYNCPT_ERROR 0x012
22#define DC_CMD_WIN_C_INCR_SYNCPT 0x018
23#define DC_CMD_WIN_C_INCR_SYNCPT_CNTRL 0x019
24#define DC_CMD_WIN_C_INCR_SYNCPT_ERROR 0x01a
25#define DC_CMD_CONT_SYNCPT_VSYNC 0x028
26#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031
27#define DC_CMD_DISPLAY_COMMAND 0x032
28#define DISP_CTRL_MODE_STOP (0 << 5)
29#define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
30#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
31#define DC_CMD_SIGNAL_RAISE 0x033
32#define DC_CMD_DISPLAY_POWER_CONTROL 0x036
33#define PW0_ENABLE (1 << 0)
34#define PW1_ENABLE (1 << 2)
35#define PW2_ENABLE (1 << 4)
36#define PW3_ENABLE (1 << 6)
37#define PW4_ENABLE (1 << 8)
38#define PM0_ENABLE (1 << 16)
39#define PM1_ENABLE (1 << 18)
40
41#define DC_CMD_INT_STATUS 0x037
42#define DC_CMD_INT_MASK 0x038
43#define DC_CMD_INT_ENABLE 0x039
44#define DC_CMD_INT_TYPE 0x03a
45#define DC_CMD_INT_POLARITY 0x03b
46#define CTXSW_INT (1 << 0)
47#define FRAME_END_INT (1 << 1)
48#define VBLANK_INT (1 << 2)
49#define WIN_A_UF_INT (1 << 8)
50#define WIN_B_UF_INT (1 << 9)
51#define WIN_C_UF_INT (1 << 10)
52#define WIN_A_OF_INT (1 << 14)
53#define WIN_B_OF_INT (1 << 15)
54#define WIN_C_OF_INT (1 << 16)
55
56#define DC_CMD_SIGNAL_RAISE1 0x03c
57#define DC_CMD_SIGNAL_RAISE2 0x03d
58#define DC_CMD_SIGNAL_RAISE3 0x03e
59
60#define DC_CMD_STATE_ACCESS 0x040
61#define READ_MUX (1 << 0)
62#define WRITE_MUX (1 << 2)
63
64#define DC_CMD_STATE_CONTROL 0x041
65#define GENERAL_ACT_REQ (1 << 0)
66#define WIN_A_ACT_REQ (1 << 1)
67#define WIN_B_ACT_REQ (1 << 2)
68#define WIN_C_ACT_REQ (1 << 3)
69#define GENERAL_UPDATE (1 << 8)
70#define WIN_A_UPDATE (1 << 9)
71#define WIN_B_UPDATE (1 << 10)
72#define WIN_C_UPDATE (1 << 11)
73#define NC_HOST_TRIG (1 << 24)
74
75#define DC_CMD_DISPLAY_WINDOW_HEADER 0x042
76#define WINDOW_A_SELECT (1 << 4)
77#define WINDOW_B_SELECT (1 << 5)
78#define WINDOW_C_SELECT (1 << 6)
79
80#define DC_CMD_REG_ACT_CONTROL 0x043
81
82#define DC_COM_CRC_CONTROL 0x300
83#define DC_COM_CRC_CHECKSUM 0x301
84#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x))
85#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
86#define LVS_OUTPUT_POLARITY_LOW (1 << 28)
87#define LHS_OUTPUT_POLARITY_LOW (1 << 30)
88#define DC_COM_PIN_OUTPUT_DATA(x) (0x30a + (x))
89#define DC_COM_PIN_INPUT_ENABLE(x) (0x30e + (x))
90#define DC_COM_PIN_INPUT_DATA(x) (0x312 + (x))
91#define DC_COM_PIN_OUTPUT_SELECT(x) (0x314 + (x))
92
93#define DC_COM_PIN_MISC_CONTROL 0x31b
94#define DC_COM_PIN_PM0_CONTROL 0x31c
95#define DC_COM_PIN_PM0_DUTY_CYCLE 0x31d
96#define DC_COM_PIN_PM1_CONTROL 0x31e
97#define DC_COM_PIN_PM1_DUTY_CYCLE 0x31f
98
99#define DC_COM_SPI_CONTROL 0x320
100#define DC_COM_SPI_START_BYTE 0x321
101#define DC_COM_HSPI_WRITE_DATA_AB 0x322
102#define DC_COM_HSPI_WRITE_DATA_CD 0x323
103#define DC_COM_HSPI_CS_DC 0x324
104#define DC_COM_SCRATCH_REGISTER_A 0x325
105#define DC_COM_SCRATCH_REGISTER_B 0x326
106#define DC_COM_GPIO_CTRL 0x327
107#define DC_COM_GPIO_DEBOUNCE_COUNTER 0x328
108#define DC_COM_CRC_CHECKSUM_LATCHED 0x329
109
110#define DC_DISP_DISP_SIGNAL_OPTIONS0 0x400
111#define H_PULSE_0_ENABLE (1 << 8)
112#define H_PULSE_1_ENABLE (1 << 10)
113#define H_PULSE_2_ENABLE (1 << 12)
114
115#define DC_DISP_DISP_SIGNAL_OPTIONS1 0x401
116
117#define DC_DISP_DISP_WIN_OPTIONS 0x402
118#define HDMI_ENABLE (1 << 30)
119
120#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
121#define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24)
122#define WINDOW_A_THRESHOLD(x) (((x) & 0x7f) << 16)
123#define WINDOW_B_THRESHOLD(x) (((x) & 0x7f) << 8)
124#define WINDOW_C_THRESHOLD(x) (((x) & 0xff) << 0)
125
126#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404
127#define CURSOR_DELAY(x) (((x) & 0x3f) << 24)
128#define WINDOW_A_DELAY(x) (((x) & 0x3f) << 16)
129#define WINDOW_B_DELAY(x) (((x) & 0x3f) << 8)
130#define WINDOW_C_DELAY(x) (((x) & 0x3f) << 0)
131
132#define DC_DISP_DISP_TIMING_OPTIONS 0x405
133#define VSYNC_H_POSITION(x) ((x) & 0xfff)
134
135#define DC_DISP_REF_TO_SYNC 0x406
136#define DC_DISP_SYNC_WIDTH 0x407
137#define DC_DISP_BACK_PORCH 0x408
138#define DC_DISP_ACTIVE 0x409
139#define DC_DISP_FRONT_PORCH 0x40a
140#define DC_DISP_H_PULSE0_CONTROL 0x40b
141#define DC_DISP_H_PULSE0_POSITION_A 0x40c
142#define DC_DISP_H_PULSE0_POSITION_B 0x40d
143#define DC_DISP_H_PULSE0_POSITION_C 0x40e
144#define DC_DISP_H_PULSE0_POSITION_D 0x40f
145#define DC_DISP_H_PULSE1_CONTROL 0x410
146#define DC_DISP_H_PULSE1_POSITION_A 0x411
147#define DC_DISP_H_PULSE1_POSITION_B 0x412
148#define DC_DISP_H_PULSE1_POSITION_C 0x413
149#define DC_DISP_H_PULSE1_POSITION_D 0x414
150#define DC_DISP_H_PULSE2_CONTROL 0x415
151#define DC_DISP_H_PULSE2_POSITION_A 0x416
152#define DC_DISP_H_PULSE2_POSITION_B 0x417
153#define DC_DISP_H_PULSE2_POSITION_C 0x418
154#define DC_DISP_H_PULSE2_POSITION_D 0x419
155#define DC_DISP_V_PULSE0_CONTROL 0x41a
156#define DC_DISP_V_PULSE0_POSITION_A 0x41b
157#define DC_DISP_V_PULSE0_POSITION_B 0x41c
158#define DC_DISP_V_PULSE0_POSITION_C 0x41d
159#define DC_DISP_V_PULSE1_CONTROL 0x41e
160#define DC_DISP_V_PULSE1_POSITION_A 0x41f
161#define DC_DISP_V_PULSE1_POSITION_B 0x420
162#define DC_DISP_V_PULSE1_POSITION_C 0x421
163#define DC_DISP_V_PULSE2_CONTROL 0x422
164#define DC_DISP_V_PULSE2_POSITION_A 0x423
165#define DC_DISP_V_PULSE3_CONTROL 0x424
166#define DC_DISP_V_PULSE3_POSITION_A 0x425
167#define DC_DISP_M0_CONTROL 0x426
168#define DC_DISP_M1_CONTROL 0x427
169#define DC_DISP_DI_CONTROL 0x428
170#define DC_DISP_PP_CONTROL 0x429
171#define DC_DISP_PP_SELECT_A 0x42a
172#define DC_DISP_PP_SELECT_B 0x42b
173#define DC_DISP_PP_SELECT_C 0x42c
174#define DC_DISP_PP_SELECT_D 0x42d
175
176#define PULSE_MODE_NORMAL (0 << 3)
177#define PULSE_MODE_ONE_CLOCK (1 << 3)
178#define PULSE_POLARITY_HIGH (0 << 4)
179#define PULSE_POLARITY_LOW (1 << 4)
180#define PULSE_QUAL_ALWAYS (0 << 6)
181#define PULSE_QUAL_VACTIVE (2 << 6)
182#define PULSE_QUAL_VACTIVE1 (3 << 6)
183#define PULSE_LAST_START_A (0 << 8)
184#define PULSE_LAST_END_A (1 << 8)
185#define PULSE_LAST_START_B (2 << 8)
186#define PULSE_LAST_END_B (3 << 8)
187#define PULSE_LAST_START_C (4 << 8)
188#define PULSE_LAST_END_C (5 << 8)
189#define PULSE_LAST_START_D (6 << 8)
190#define PULSE_LAST_END_D (7 << 8)
191
192#define PULSE_START(x) (((x) & 0xfff) << 0)
193#define PULSE_END(x) (((x) & 0xfff) << 16)
194
195#define DC_DISP_DISP_CLOCK_CONTROL 0x42e
196#define PIXEL_CLK_DIVIDER_PCD1 (0 << 8)
197#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8)
198#define PIXEL_CLK_DIVIDER_PCD2 (2 << 8)
199#define PIXEL_CLK_DIVIDER_PCD3 (3 << 8)
200#define PIXEL_CLK_DIVIDER_PCD4 (4 << 8)
201#define PIXEL_CLK_DIVIDER_PCD6 (5 << 8)
202#define PIXEL_CLK_DIVIDER_PCD8 (6 << 8)
203#define PIXEL_CLK_DIVIDER_PCD9 (7 << 8)
204#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8)
205#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8)
206#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8)
207#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8)
208#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8)
209#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff)
210
211#define DC_DISP_DISP_INTERFACE_CONTROL 0x42f
212#define DISP_DATA_FORMAT_DF1P1C (0 << 0)
213#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0)
214#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0)
215#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0)
216#define DISP_DATA_FORMAT_DF2S (4 << 0)
217#define DISP_DATA_FORMAT_DF3S (5 << 0)
218#define DISP_DATA_FORMAT_DFSPI (6 << 0)
219#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0)
220#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0)
221#define DISP_ALIGNMENT_MSB (0 << 8)
222#define DISP_ALIGNMENT_LSB (1 << 8)
223#define DISP_ORDER_RED_BLUE (0 << 9)
224#define DISP_ORDER_BLUE_RED (1 << 9)
225
226#define DC_DISP_DISP_COLOR_CONTROL 0x430
227#define BASE_COLOR_SIZE666 (0 << 0)
228#define BASE_COLOR_SIZE111 (1 << 0)
229#define BASE_COLOR_SIZE222 (2 << 0)
230#define BASE_COLOR_SIZE333 (3 << 0)
231#define BASE_COLOR_SIZE444 (4 << 0)
232#define BASE_COLOR_SIZE555 (5 << 0)
233#define BASE_COLOR_SIZE565 (6 << 0)
234#define BASE_COLOR_SIZE332 (7 << 0)
235#define BASE_COLOR_SIZE888 (8 << 0)
236#define DITHER_CONTROL_DISABLE (0 << 8)
237#define DITHER_CONTROL_ORDERED (2 << 8)
238#define DITHER_CONTROL_ERRDIFF (3 << 8)
239
240#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
241
242#define DC_DISP_DATA_ENABLE_OPTIONS 0x432
243#define DE_SELECT_ACTIVE_BLANK (0 << 0)
244#define DE_SELECT_ACTIVE (1 << 0)
245#define DE_SELECT_ACTIVE_IS (2 << 0)
246#define DE_CONTROL_ONECLK (0 << 2)
247#define DE_CONTROL_NORMAL (1 << 2)
248#define DE_CONTROL_EARLY_EXT (2 << 2)
249#define DE_CONTROL_EARLY (3 << 2)
250#define DE_CONTROL_ACTIVE_BLANK (4 << 2)
251
252#define DC_DISP_SERIAL_INTERFACE_OPTIONS 0x433
253#define DC_DISP_LCD_SPI_OPTIONS 0x434
254#define DC_DISP_BORDER_COLOR 0x435
255#define DC_DISP_COLOR_KEY0_LOWER 0x436
256#define DC_DISP_COLOR_KEY0_UPPER 0x437
257#define DC_DISP_COLOR_KEY1_LOWER 0x438
258#define DC_DISP_COLOR_KEY1_UPPER 0x439
259
260#define DC_DISP_CURSOR_FOREGROUND 0x43c
261#define DC_DISP_CURSOR_BACKGROUND 0x43d
262
263#define DC_DISP_CURSOR_START_ADDR 0x43e
264#define DC_DISP_CURSOR_START_ADDR_NS 0x43f
265
266#define DC_DISP_CURSOR_POSITION 0x440
267#define DC_DISP_CURSOR_POSITION_NS 0x441
268
269#define DC_DISP_INIT_SEQ_CONTROL 0x442
270#define DC_DISP_SPI_INIT_SEQ_DATA_A 0x443
271#define DC_DISP_SPI_INIT_SEQ_DATA_B 0x444
272#define DC_DISP_SPI_INIT_SEQ_DATA_C 0x445
273#define DC_DISP_SPI_INIT_SEQ_DATA_D 0x446
274
275#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480
276#define DC_DISP_MCCIF_DISPLAY0A_HYST 0x481
277#define DC_DISP_MCCIF_DISPLAY0B_HYST 0x482
278#define DC_DISP_MCCIF_DISPLAY1A_HYST 0x483
279#define DC_DISP_MCCIF_DISPLAY1B_HYST 0x484
280
281#define DC_DISP_DAC_CRT_CTRL 0x4c0
282#define DC_DISP_DISP_MISC_CONTROL 0x4c1
283#define DC_DISP_SD_CONTROL 0x4c2
284#define DC_DISP_SD_CSC_COEFF 0x4c3
285#define DC_DISP_SD_LUT(x) (0x4c4 + (x))
286#define DC_DISP_SD_FLICKER_CONTROL 0x4cd
287#define DC_DISP_DC_PIXEL_COUNT 0x4ce
288#define DC_DISP_SD_HISTOGRAM(x) (0x4cf + (x))
289#define DC_DISP_SD_BL_PARAMETERS 0x4d7
290#define DC_DISP_SD_BL_TF(x) (0x4d8 + (x))
291#define DC_DISP_SD_BL_CONTROL 0x4dc
292#define DC_DISP_SD_HW_K_VALUES 0x4dd
293#define DC_DISP_SD_MAN_K_VALUES 0x4de
294
295#define DC_WIN_CSC_YOF 0x611
296#define DC_WIN_CSC_KYRGB 0x612
297#define DC_WIN_CSC_KUR 0x613
298#define DC_WIN_CSC_KVR 0x614
299#define DC_WIN_CSC_KUG 0x615
300#define DC_WIN_CSC_KVG 0x616
301#define DC_WIN_CSC_KUB 0x617
302#define DC_WIN_CSC_KVB 0x618
303
304#define DC_WIN_WIN_OPTIONS 0x700
305#define COLOR_EXPAND (1 << 6)
306#define CSC_ENABLE (1 << 18)
307#define WIN_ENABLE (1 << 30)
308
309#define DC_WIN_BYTE_SWAP 0x701
310#define BYTE_SWAP_NOSWAP (0 << 0)
311#define BYTE_SWAP_SWAP2 (1 << 0)
312#define BYTE_SWAP_SWAP4 (2 << 0)
313#define BYTE_SWAP_SWAP4HW (3 << 0)
314
315#define DC_WIN_BUFFER_CONTROL 0x702
316#define BUFFER_CONTROL_HOST (0 << 0)
317#define BUFFER_CONTROL_VI (1 << 0)
318#define BUFFER_CONTROL_EPP (2 << 0)
319#define BUFFER_CONTROL_MPEGE (3 << 0)
320#define BUFFER_CONTROL_SB2D (4 << 0)
321
322#define DC_WIN_COLOR_DEPTH 0x703
323#define WIN_COLOR_DEPTH_P1 0
324#define WIN_COLOR_DEPTH_P2 1
325#define WIN_COLOR_DEPTH_P4 2
326#define WIN_COLOR_DEPTH_P8 3
327#define WIN_COLOR_DEPTH_B4G4R4A4 4
328#define WIN_COLOR_DEPTH_B5G5R5A 5
329#define WIN_COLOR_DEPTH_B5G6R5 6
330#define WIN_COLOR_DEPTH_AB5G5R5 7
331#define WIN_COLOR_DEPTH_B8G8R8A8 12
332#define WIN_COLOR_DEPTH_R8G8B8A8 13
333#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 14
334#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 15
335#define WIN_COLOR_DEPTH_YCbCr422 16
336#define WIN_COLOR_DEPTH_YUV422 17
337#define WIN_COLOR_DEPTH_YCbCr420P 18
338#define WIN_COLOR_DEPTH_YUV420P 19
339#define WIN_COLOR_DEPTH_YCbCr422P 20
340#define WIN_COLOR_DEPTH_YUV422P 21
341#define WIN_COLOR_DEPTH_YCbCr422R 22
342#define WIN_COLOR_DEPTH_YUV422R 23
343#define WIN_COLOR_DEPTH_YCbCr422RA 24
344#define WIN_COLOR_DEPTH_YUV422RA 25
345
346#define DC_WIN_POSITION 0x704
347#define H_POSITION(x) (((x) & 0x1fff) << 0)
348#define V_POSITION(x) (((x) & 0x1fff) << 16)
349
350#define DC_WIN_SIZE 0x705
351#define H_SIZE(x) (((x) & 0x1fff) << 0)
352#define V_SIZE(x) (((x) & 0x1fff) << 16)
353
354#define DC_WIN_PRESCALED_SIZE 0x706
355#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) << 0)
356#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16)
357
358#define DC_WIN_H_INITIAL_DDA 0x707
359#define DC_WIN_V_INITIAL_DDA 0x708
360#define DC_WIN_DDA_INC 0x709
361#define H_DDA_INC(x) (((x) & 0xffff) << 0)
362#define V_DDA_INC(x) (((x) & 0xffff) << 16)
363
364#define DC_WIN_LINE_STRIDE 0x70a
365#define DC_WIN_BUF_STRIDE 0x70b
366#define DC_WIN_UV_BUF_STRIDE 0x70c
367#define DC_WIN_BUFFER_ADDR_MODE 0x70d
368#define DC_WIN_DV_CONTROL 0x70e
369
370#define DC_WIN_BLEND_NOKEY 0x70f
371#define DC_WIN_BLEND_1WIN 0x710
372#define DC_WIN_BLEND_2WIN_X 0x711
373#define DC_WIN_BLEND_2WIN_Y 0x712
374#define DC_WIN_BLEND_3WIN_XY 0x713
375
376#define DC_WIN_HP_FETCH_CONTROL 0x714
377
378#define DC_WINBUF_START_ADDR 0x800
379#define DC_WINBUF_START_ADDR_NS 0x801
380#define DC_WINBUF_START_ADDR_U 0x802
381#define DC_WINBUF_START_ADDR_U_NS 0x803
382#define DC_WINBUF_START_ADDR_V 0x804
383#define DC_WINBUF_START_ADDR_V_NS 0x805
384
385#define DC_WINBUF_ADDR_H_OFFSET 0x806
386#define DC_WINBUF_ADDR_H_OFFSET_NS 0x807
387#define DC_WINBUF_ADDR_V_OFFSET 0x808
388#define DC_WINBUF_ADDR_V_OFFSET_NS 0x809
389
390#define DC_WINBUF_UFLOW_STATUS 0x80a
391
392#define DC_WINBUF_AD_UFLOW_STATUS 0xbca
393#define DC_WINBUF_BD_UFLOW_STATUS 0xdca
394#define DC_WINBUF_CD_UFLOW_STATUS 0xfca
395
396/* synchronization points */
397#define SYNCPT_VBLANK0 26
398#define SYNCPT_VBLANK1 27
399
400#endif /* TEGRA_DC_H */
diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c
deleted file mode 100644
index 8c61ceeaa12d..000000000000
--- a/drivers/gpu/host1x/drm/drm.c
+++ /dev/null
@@ -1,647 +0,0 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012-2013 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/module.h>
11#include <linux/of_address.h>
12#include <linux/of_platform.h>
13
14#include <linux/dma-mapping.h>
15#include <asm/dma-iommu.h>
16
17#include <drm/drm.h>
18#include <drm/drmP.h>
19
20#include "host1x_client.h"
21#include "dev.h"
22#include "drm.h"
23#include "gem.h"
24#include "syncpt.h"
25
26#define DRIVER_NAME "tegra"
27#define DRIVER_DESC "NVIDIA Tegra graphics"
28#define DRIVER_DATE "20120330"
29#define DRIVER_MAJOR 0
30#define DRIVER_MINOR 0
31#define DRIVER_PATCHLEVEL 0
32
33struct host1x_drm_client {
34 struct host1x_client *client;
35 struct device_node *np;
36 struct list_head list;
37};
38
39static int host1x_add_drm_client(struct host1x_drm *host1x,
40 struct device_node *np)
41{
42 struct host1x_drm_client *client;
43
44 client = kzalloc(sizeof(*client), GFP_KERNEL);
45 if (!client)
46 return -ENOMEM;
47
48 INIT_LIST_HEAD(&client->list);
49 client->np = of_node_get(np);
50
51 list_add_tail(&client->list, &host1x->drm_clients);
52
53 return 0;
54}
55
56static int host1x_activate_drm_client(struct host1x_drm *host1x,
57 struct host1x_drm_client *drm,
58 struct host1x_client *client)
59{
60 mutex_lock(&host1x->drm_clients_lock);
61 list_del_init(&drm->list);
62 list_add_tail(&drm->list, &host1x->drm_active);
63 drm->client = client;
64 mutex_unlock(&host1x->drm_clients_lock);
65
66 return 0;
67}
68
69static int host1x_remove_drm_client(struct host1x_drm *host1x,
70 struct host1x_drm_client *client)
71{
72 mutex_lock(&host1x->drm_clients_lock);
73 list_del_init(&client->list);
74 mutex_unlock(&host1x->drm_clients_lock);
75
76 of_node_put(client->np);
77 kfree(client);
78
79 return 0;
80}
81
82static int host1x_parse_dt(struct host1x_drm *host1x)
83{
84 static const char * const compat[] = {
85 "nvidia,tegra20-dc",
86 "nvidia,tegra20-hdmi",
87 "nvidia,tegra20-gr2d",
88 "nvidia,tegra30-dc",
89 "nvidia,tegra30-hdmi",
90 "nvidia,tegra30-gr2d",
91 };
92 unsigned int i;
93 int err;
94
95 for (i = 0; i < ARRAY_SIZE(compat); i++) {
96 struct device_node *np;
97
98 for_each_child_of_node(host1x->dev->of_node, np) {
99 if (of_device_is_compatible(np, compat[i]) &&
100 of_device_is_available(np)) {
101 err = host1x_add_drm_client(host1x, np);
102 if (err < 0)
103 return err;
104 }
105 }
106 }
107
108 return 0;
109}
110
111int host1x_drm_alloc(struct platform_device *pdev)
112{
113 struct host1x_drm *host1x;
114 int err;
115
116 host1x = devm_kzalloc(&pdev->dev, sizeof(*host1x), GFP_KERNEL);
117 if (!host1x)
118 return -ENOMEM;
119
120 mutex_init(&host1x->drm_clients_lock);
121 INIT_LIST_HEAD(&host1x->drm_clients);
122 INIT_LIST_HEAD(&host1x->drm_active);
123 mutex_init(&host1x->clients_lock);
124 INIT_LIST_HEAD(&host1x->clients);
125 host1x->dev = &pdev->dev;
126
127 err = host1x_parse_dt(host1x);
128 if (err < 0) {
129 dev_err(&pdev->dev, "failed to parse DT: %d\n", err);
130 return err;
131 }
132
133 host1x_set_drm_data(&pdev->dev, host1x);
134
135 return 0;
136}
137
138int host1x_drm_init(struct host1x_drm *host1x, struct drm_device *drm)
139{
140 struct host1x_client *client;
141
142 mutex_lock(&host1x->clients_lock);
143
144 list_for_each_entry(client, &host1x->clients, list) {
145 if (client->ops && client->ops->drm_init) {
146 int err = client->ops->drm_init(client, drm);
147 if (err < 0) {
148 dev_err(host1x->dev,
149 "DRM setup failed for %s: %d\n",
150 dev_name(client->dev), err);
151 mutex_unlock(&host1x->clients_lock);
152 return err;
153 }
154 }
155 }
156
157 mutex_unlock(&host1x->clients_lock);
158
159 return 0;
160}
161
162int host1x_drm_exit(struct host1x_drm *host1x)
163{
164 struct platform_device *pdev = to_platform_device(host1x->dev);
165 struct host1x_client *client;
166
167 if (!host1x->drm)
168 return 0;
169
170 mutex_lock(&host1x->clients_lock);
171
172 list_for_each_entry_reverse(client, &host1x->clients, list) {
173 if (client->ops && client->ops->drm_exit) {
174 int err = client->ops->drm_exit(client);
175 if (err < 0) {
176 dev_err(host1x->dev,
177 "DRM cleanup failed for %s: %d\n",
178 dev_name(client->dev), err);
179 mutex_unlock(&host1x->clients_lock);
180 return err;
181 }
182 }
183 }
184
185 mutex_unlock(&host1x->clients_lock);
186
187 drm_platform_exit(&tegra_drm_driver, pdev);
188 host1x->drm = NULL;
189
190 return 0;
191}
192
193int host1x_register_client(struct host1x_drm *host1x,
194 struct host1x_client *client)
195{
196 struct host1x_drm_client *drm, *tmp;
197 int err;
198
199 mutex_lock(&host1x->clients_lock);
200 list_add_tail(&client->list, &host1x->clients);
201 mutex_unlock(&host1x->clients_lock);
202
203 list_for_each_entry_safe(drm, tmp, &host1x->drm_clients, list)
204 if (drm->np == client->dev->of_node)
205 host1x_activate_drm_client(host1x, drm, client);
206
207 if (list_empty(&host1x->drm_clients)) {
208 struct platform_device *pdev = to_platform_device(host1x->dev);
209
210 err = drm_platform_init(&tegra_drm_driver, pdev);
211 if (err < 0) {
212 dev_err(host1x->dev, "drm_platform_init(): %d\n", err);
213 return err;
214 }
215 }
216
217 return 0;
218}
219
220int host1x_unregister_client(struct host1x_drm *host1x,
221 struct host1x_client *client)
222{
223 struct host1x_drm_client *drm, *tmp;
224 int err;
225
226 list_for_each_entry_safe(drm, tmp, &host1x->drm_active, list) {
227 if (drm->client == client) {
228 err = host1x_drm_exit(host1x);
229 if (err < 0) {
230 dev_err(host1x->dev, "host1x_drm_exit(): %d\n",
231 err);
232 return err;
233 }
234
235 host1x_remove_drm_client(host1x, drm);
236 break;
237 }
238 }
239
240 mutex_lock(&host1x->clients_lock);
241 list_del_init(&client->list);
242 mutex_unlock(&host1x->clients_lock);
243
244 return 0;
245}
246
247static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
248{
249 struct host1x_drm *host1x;
250 int err;
251
252 host1x = host1x_get_drm_data(drm->dev);
253 drm->dev_private = host1x;
254 host1x->drm = drm;
255
256 drm_mode_config_init(drm);
257
258 err = host1x_drm_init(host1x, drm);
259 if (err < 0)
260 return err;
261
262 /*
263 * We don't use the drm_irq_install() helpers provided by the DRM
264 * core, so we need to set this manually in order to allow the
265 * DRM_IOCTL_WAIT_VBLANK to operate correctly.
266 */
267 drm->irq_enabled = 1;
268
269 err = drm_vblank_init(drm, drm->mode_config.num_crtc);
270 if (err < 0)
271 return err;
272
273 err = tegra_drm_fb_init(drm);
274 if (err < 0)
275 return err;
276
277 drm_kms_helper_poll_init(drm);
278
279 return 0;
280}
281
282static int tegra_drm_unload(struct drm_device *drm)
283{
284 drm_kms_helper_poll_fini(drm);
285 tegra_drm_fb_exit(drm);
286
287 drm_mode_config_cleanup(drm);
288
289 return 0;
290}
291
292static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
293{
294 struct host1x_drm_file *fpriv;
295
296 fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
297 if (!fpriv)
298 return -ENOMEM;
299
300 INIT_LIST_HEAD(&fpriv->contexts);
301 filp->driver_priv = fpriv;
302
303 return 0;
304}
305
306static void host1x_drm_context_free(struct host1x_drm_context *context)
307{
308 context->client->ops->close_channel(context);
309 kfree(context);
310}
311
312static void tegra_drm_lastclose(struct drm_device *drm)
313{
314 struct host1x_drm *host1x = drm->dev_private;
315
316 tegra_fbdev_restore_mode(host1x->fbdev);
317}
318
319#ifdef CONFIG_DRM_TEGRA_STAGING
320static bool host1x_drm_file_owns_context(struct host1x_drm_file *file,
321 struct host1x_drm_context *context)
322{
323 struct host1x_drm_context *ctx;
324
325 list_for_each_entry(ctx, &file->contexts, list)
326 if (ctx == context)
327 return true;
328
329 return false;
330}
331
332static int tegra_gem_create(struct drm_device *drm, void *data,
333 struct drm_file *file)
334{
335 struct drm_tegra_gem_create *args = data;
336 struct tegra_bo *bo;
337
338 bo = tegra_bo_create_with_handle(file, drm, args->size,
339 &args->handle);
340 if (IS_ERR(bo))
341 return PTR_ERR(bo);
342
343 return 0;
344}
345
346static int tegra_gem_mmap(struct drm_device *drm, void *data,
347 struct drm_file *file)
348{
349 struct drm_tegra_gem_mmap *args = data;
350 struct drm_gem_object *gem;
351 struct tegra_bo *bo;
352
353 gem = drm_gem_object_lookup(drm, file, args->handle);
354 if (!gem)
355 return -EINVAL;
356
357 bo = to_tegra_bo(gem);
358
359 args->offset = drm_vma_node_offset_addr(&bo->gem.vma_node);
360
361 drm_gem_object_unreference(gem);
362
363 return 0;
364}
365
366static int tegra_syncpt_read(struct drm_device *drm, void *data,
367 struct drm_file *file)
368{
369 struct drm_tegra_syncpt_read *args = data;
370 struct host1x *host = dev_get_drvdata(drm->dev);
371 struct host1x_syncpt *sp = host1x_syncpt_get(host, args->id);
372
373 if (!sp)
374 return -EINVAL;
375
376 args->value = host1x_syncpt_read_min(sp);
377 return 0;
378}
379
380static int tegra_syncpt_incr(struct drm_device *drm, void *data,
381 struct drm_file *file)
382{
383 struct drm_tegra_syncpt_incr *args = data;
384 struct host1x *host = dev_get_drvdata(drm->dev);
385 struct host1x_syncpt *sp = host1x_syncpt_get(host, args->id);
386
387 if (!sp)
388 return -EINVAL;
389
390 return host1x_syncpt_incr(sp);
391}
392
393static int tegra_syncpt_wait(struct drm_device *drm, void *data,
394 struct drm_file *file)
395{
396 struct drm_tegra_syncpt_wait *args = data;
397 struct host1x *host = dev_get_drvdata(drm->dev);
398 struct host1x_syncpt *sp = host1x_syncpt_get(host, args->id);
399
400 if (!sp)
401 return -EINVAL;
402
403 return host1x_syncpt_wait(sp, args->thresh, args->timeout,
404 &args->value);
405}
406
407static int tegra_open_channel(struct drm_device *drm, void *data,
408 struct drm_file *file)
409{
410 struct drm_tegra_open_channel *args = data;
411 struct host1x_client *client;
412 struct host1x_drm_context *context;
413 struct host1x_drm_file *fpriv = file->driver_priv;
414 struct host1x_drm *host1x = drm->dev_private;
415 int err = -ENODEV;
416
417 context = kzalloc(sizeof(*context), GFP_KERNEL);
418 if (!context)
419 return -ENOMEM;
420
421 list_for_each_entry(client, &host1x->clients, list)
422 if (client->class == args->client) {
423 err = client->ops->open_channel(client, context);
424 if (err)
425 break;
426
427 context->client = client;
428 list_add(&context->list, &fpriv->contexts);
429 args->context = (uintptr_t)context;
430 return 0;
431 }
432
433 kfree(context);
434 return err;
435}
436
437static int tegra_close_channel(struct drm_device *drm, void *data,
438 struct drm_file *file)
439{
440 struct drm_tegra_close_channel *args = data;
441 struct host1x_drm_file *fpriv = file->driver_priv;
442 struct host1x_drm_context *context =
443 (struct host1x_drm_context *)(uintptr_t)args->context;
444
445 if (!host1x_drm_file_owns_context(fpriv, context))
446 return -EINVAL;
447
448 list_del(&context->list);
449 host1x_drm_context_free(context);
450
451 return 0;
452}
453
454static int tegra_get_syncpt(struct drm_device *drm, void *data,
455 struct drm_file *file)
456{
457 struct drm_tegra_get_syncpt *args = data;
458 struct host1x_drm_file *fpriv = file->driver_priv;
459 struct host1x_drm_context *context =
460 (struct host1x_drm_context *)(uintptr_t)args->context;
461 struct host1x_syncpt *syncpt;
462
463 if (!host1x_drm_file_owns_context(fpriv, context))
464 return -ENODEV;
465
466 if (args->index >= context->client->num_syncpts)
467 return -EINVAL;
468
469 syncpt = context->client->syncpts[args->index];
470 args->id = host1x_syncpt_id(syncpt);
471
472 return 0;
473}
474
475static int tegra_submit(struct drm_device *drm, void *data,
476 struct drm_file *file)
477{
478 struct drm_tegra_submit *args = data;
479 struct host1x_drm_file *fpriv = file->driver_priv;
480 struct host1x_drm_context *context =
481 (struct host1x_drm_context *)(uintptr_t)args->context;
482
483 if (!host1x_drm_file_owns_context(fpriv, context))
484 return -ENODEV;
485
486 return context->client->ops->submit(context, args, drm, file);
487}
488#endif
489
490static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
491#ifdef CONFIG_DRM_TEGRA_STAGING
492 DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED | DRM_AUTH),
493 DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED),
494 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED),
495 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED),
496 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait, DRM_UNLOCKED),
497 DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel, DRM_UNLOCKED),
498 DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel, DRM_UNLOCKED),
499 DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED),
500 DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED),
501#endif
502};
503
504static const struct file_operations tegra_drm_fops = {
505 .owner = THIS_MODULE,
506 .open = drm_open,
507 .release = drm_release,
508 .unlocked_ioctl = drm_ioctl,
509 .mmap = tegra_drm_mmap,
510 .poll = drm_poll,
511 .read = drm_read,
512#ifdef CONFIG_COMPAT
513 .compat_ioctl = drm_compat_ioctl,
514#endif
515 .llseek = noop_llseek,
516};
517
518static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm, int pipe)
519{
520 struct drm_crtc *crtc;
521
522 list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) {
523 struct tegra_dc *dc = to_tegra_dc(crtc);
524
525 if (dc->pipe == pipe)
526 return crtc;
527 }
528
529 return NULL;
530}
531
532static u32 tegra_drm_get_vblank_counter(struct drm_device *dev, int crtc)
533{
534 /* TODO: implement real hardware counter using syncpoints */
535 return drm_vblank_count(dev, crtc);
536}
537
538static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe)
539{
540 struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe);
541 struct tegra_dc *dc = to_tegra_dc(crtc);
542
543 if (!crtc)
544 return -ENODEV;
545
546 tegra_dc_enable_vblank(dc);
547
548 return 0;
549}
550
551static void tegra_drm_disable_vblank(struct drm_device *drm, int pipe)
552{
553 struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe);
554 struct tegra_dc *dc = to_tegra_dc(crtc);
555
556 if (crtc)
557 tegra_dc_disable_vblank(dc);
558}
559
560static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file)
561{
562 struct host1x_drm_file *fpriv = file->driver_priv;
563 struct host1x_drm_context *context, *tmp;
564 struct drm_crtc *crtc;
565
566 list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
567 tegra_dc_cancel_page_flip(crtc, file);
568
569 list_for_each_entry_safe(context, tmp, &fpriv->contexts, list)
570 host1x_drm_context_free(context);
571
572 kfree(fpriv);
573}
574
575#ifdef CONFIG_DEBUG_FS
576static int tegra_debugfs_framebuffers(struct seq_file *s, void *data)
577{
578 struct drm_info_node *node = (struct drm_info_node *)s->private;
579 struct drm_device *drm = node->minor->dev;
580 struct drm_framebuffer *fb;
581
582 mutex_lock(&drm->mode_config.fb_lock);
583
584 list_for_each_entry(fb, &drm->mode_config.fb_list, head) {
585 seq_printf(s, "%3d: user size: %d x %d, depth %d, %d bpp, refcount %d\n",
586 fb->base.id, fb->width, fb->height, fb->depth,
587 fb->bits_per_pixel,
588 atomic_read(&fb->refcount.refcount));
589 }
590
591 mutex_unlock(&drm->mode_config.fb_lock);
592
593 return 0;
594}
595
596static struct drm_info_list tegra_debugfs_list[] = {
597 { "framebuffers", tegra_debugfs_framebuffers, 0 },
598};
599
600static int tegra_debugfs_init(struct drm_minor *minor)
601{
602 return drm_debugfs_create_files(tegra_debugfs_list,
603 ARRAY_SIZE(tegra_debugfs_list),
604 minor->debugfs_root, minor);
605}
606
607static void tegra_debugfs_cleanup(struct drm_minor *minor)
608{
609 drm_debugfs_remove_files(tegra_debugfs_list,
610 ARRAY_SIZE(tegra_debugfs_list), minor);
611}
612#endif
613
614struct drm_driver tegra_drm_driver = {
615 .driver_features = DRIVER_MODESET | DRIVER_GEM,
616 .load = tegra_drm_load,
617 .unload = tegra_drm_unload,
618 .open = tegra_drm_open,
619 .preclose = tegra_drm_preclose,
620 .lastclose = tegra_drm_lastclose,
621
622 .get_vblank_counter = tegra_drm_get_vblank_counter,
623 .enable_vblank = tegra_drm_enable_vblank,
624 .disable_vblank = tegra_drm_disable_vblank,
625
626#if defined(CONFIG_DEBUG_FS)
627 .debugfs_init = tegra_debugfs_init,
628 .debugfs_cleanup = tegra_debugfs_cleanup,
629#endif
630
631 .gem_free_object = tegra_bo_free_object,
632 .gem_vm_ops = &tegra_bo_vm_ops,
633 .dumb_create = tegra_bo_dumb_create,
634 .dumb_map_offset = tegra_bo_dumb_map_offset,
635 .dumb_destroy = drm_gem_dumb_destroy,
636
637 .ioctls = tegra_drm_ioctls,
638 .num_ioctls = ARRAY_SIZE(tegra_drm_ioctls),
639 .fops = &tegra_drm_fops,
640
641 .name = DRIVER_NAME,
642 .desc = DRIVER_DESC,
643 .date = DRIVER_DATE,
644 .major = DRIVER_MAJOR,
645 .minor = DRIVER_MINOR,
646 .patchlevel = DRIVER_PATCHLEVEL,
647};
diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/host1x/drm/drm.h
deleted file mode 100644
index 02ce020f2575..000000000000
--- a/drivers/gpu/host1x/drm/drm.h
+++ /dev/null
@@ -1,271 +0,0 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012-2013 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#ifndef HOST1X_DRM_H
11#define HOST1X_DRM_H 1
12
13#include <drm/drmP.h>
14#include <drm/drm_crtc_helper.h>
15#include <drm/drm_edid.h>
16#include <drm/drm_fb_helper.h>
17#include <drm/drm_fixed.h>
18#include <uapi/drm/tegra_drm.h>
19
20#include "host1x.h"
21
22struct tegra_fb {
23 struct drm_framebuffer base;
24 struct tegra_bo **planes;
25 unsigned int num_planes;
26};
27
28struct tegra_fbdev {
29 struct drm_fb_helper base;
30 struct tegra_fb *fb;
31};
32
33struct host1x_drm {
34 struct drm_device *drm;
35 struct device *dev;
36 void __iomem *regs;
37 struct clk *clk;
38 int syncpt;
39 int irq;
40
41 struct mutex drm_clients_lock;
42 struct list_head drm_clients;
43 struct list_head drm_active;
44
45 struct mutex clients_lock;
46 struct list_head clients;
47
48 struct tegra_fbdev *fbdev;
49};
50
51struct host1x_client;
52
53struct host1x_drm_context {
54 struct host1x_client *client;
55 struct host1x_channel *channel;
56 struct list_head list;
57};
58
59struct host1x_client_ops {
60 int (*drm_init)(struct host1x_client *client, struct drm_device *drm);
61 int (*drm_exit)(struct host1x_client *client);
62 int (*open_channel)(struct host1x_client *client,
63 struct host1x_drm_context *context);
64 void (*close_channel)(struct host1x_drm_context *context);
65 int (*submit)(struct host1x_drm_context *context,
66 struct drm_tegra_submit *args, struct drm_device *drm,
67 struct drm_file *file);
68};
69
70struct host1x_drm_file {
71 struct list_head contexts;
72};
73
74struct host1x_client {
75 struct host1x_drm *host1x;
76 struct device *dev;
77
78 const struct host1x_client_ops *ops;
79
80 enum host1x_class class;
81 struct host1x_channel *channel;
82
83 struct host1x_syncpt **syncpts;
84 unsigned int num_syncpts;
85
86 struct list_head list;
87};
88
89extern int host1x_drm_init(struct host1x_drm *host1x, struct drm_device *drm);
90extern int host1x_drm_exit(struct host1x_drm *host1x);
91
92extern int host1x_register_client(struct host1x_drm *host1x,
93 struct host1x_client *client);
94extern int host1x_unregister_client(struct host1x_drm *host1x,
95 struct host1x_client *client);
96
97struct tegra_output;
98
99struct tegra_dc {
100 struct host1x_client client;
101 spinlock_t lock;
102
103 struct host1x_drm *host1x;
104 struct device *dev;
105
106 struct drm_crtc base;
107 int pipe;
108
109 struct clk *clk;
110
111 void __iomem *regs;
112 int irq;
113
114 struct tegra_output *rgb;
115
116 struct list_head list;
117
118 struct drm_info_list *debugfs_files;
119 struct drm_minor *minor;
120 struct dentry *debugfs;
121
122 /* page-flip handling */
123 struct drm_pending_vblank_event *event;
124};
125
126static inline struct tegra_dc *host1x_client_to_dc(struct host1x_client *client)
127{
128 return container_of(client, struct tegra_dc, client);
129}
130
131static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc)
132{
133 return container_of(crtc, struct tegra_dc, base);
134}
135
136static inline void tegra_dc_writel(struct tegra_dc *dc, unsigned long value,
137 unsigned long reg)
138{
139 writel(value, dc->regs + (reg << 2));
140}
141
142static inline unsigned long tegra_dc_readl(struct tegra_dc *dc,
143 unsigned long reg)
144{
145 return readl(dc->regs + (reg << 2));
146}
147
148struct tegra_dc_window {
149 struct {
150 unsigned int x;
151 unsigned int y;
152 unsigned int w;
153 unsigned int h;
154 } src;
155 struct {
156 unsigned int x;
157 unsigned int y;
158 unsigned int w;
159 unsigned int h;
160 } dst;
161 unsigned int bits_per_pixel;
162 unsigned int format;
163 unsigned int stride[2];
164 unsigned long base[3];
165};
166
167/* from dc.c */
168extern unsigned int tegra_dc_format(uint32_t format);
169extern int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
170 const struct tegra_dc_window *window);
171extern void tegra_dc_enable_vblank(struct tegra_dc *dc);
172extern void tegra_dc_disable_vblank(struct tegra_dc *dc);
173extern void tegra_dc_cancel_page_flip(struct drm_crtc *crtc,
174 struct drm_file *file);
175
176struct tegra_output_ops {
177 int (*enable)(struct tegra_output *output);
178 int (*disable)(struct tegra_output *output);
179 int (*setup_clock)(struct tegra_output *output, struct clk *clk,
180 unsigned long pclk);
181 int (*check_mode)(struct tegra_output *output,
182 struct drm_display_mode *mode,
183 enum drm_mode_status *status);
184};
185
186enum tegra_output_type {
187 TEGRA_OUTPUT_RGB,
188 TEGRA_OUTPUT_HDMI,
189};
190
191struct tegra_output {
192 struct device_node *of_node;
193 struct device *dev;
194
195 const struct tegra_output_ops *ops;
196 enum tegra_output_type type;
197
198 struct i2c_adapter *ddc;
199 const struct edid *edid;
200 unsigned int hpd_irq;
201 int hpd_gpio;
202
203 struct drm_encoder encoder;
204 struct drm_connector connector;
205};
206
207static inline struct tegra_output *encoder_to_output(struct drm_encoder *e)
208{
209 return container_of(e, struct tegra_output, encoder);
210}
211
212static inline struct tegra_output *connector_to_output(struct drm_connector *c)
213{
214 return container_of(c, struct tegra_output, connector);
215}
216
217static inline int tegra_output_enable(struct tegra_output *output)
218{
219 if (output && output->ops && output->ops->enable)
220 return output->ops->enable(output);
221
222 return output ? -ENOSYS : -EINVAL;
223}
224
225static inline int tegra_output_disable(struct tegra_output *output)
226{
227 if (output && output->ops && output->ops->disable)
228 return output->ops->disable(output);
229
230 return output ? -ENOSYS : -EINVAL;
231}
232
233static inline int tegra_output_setup_clock(struct tegra_output *output,
234 struct clk *clk, unsigned long pclk)
235{
236 if (output && output->ops && output->ops->setup_clock)
237 return output->ops->setup_clock(output, clk, pclk);
238
239 return output ? -ENOSYS : -EINVAL;
240}
241
242static inline int tegra_output_check_mode(struct tegra_output *output,
243 struct drm_display_mode *mode,
244 enum drm_mode_status *status)
245{
246 if (output && output->ops && output->ops->check_mode)
247 return output->ops->check_mode(output, mode, status);
248
249 return output ? -ENOSYS : -EINVAL;
250}
251
252/* from rgb.c */
253extern int tegra_dc_rgb_probe(struct tegra_dc *dc);
254extern int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc);
255extern int tegra_dc_rgb_exit(struct tegra_dc *dc);
256
257/* from output.c */
258extern int tegra_output_parse_dt(struct tegra_output *output);
259extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output);
260extern int tegra_output_exit(struct tegra_output *output);
261
262/* from fb.c */
263struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
264 unsigned int index);
265extern int tegra_drm_fb_init(struct drm_device *drm);
266extern void tegra_drm_fb_exit(struct drm_device *drm);
267extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
268
269extern struct drm_driver tegra_drm_driver;
270
271#endif /* HOST1X_DRM_H */
diff --git a/drivers/gpu/host1x/drm/fb.c b/drivers/gpu/host1x/drm/fb.c
deleted file mode 100644
index 979a3e32b78b..000000000000
--- a/drivers/gpu/host1x/drm/fb.c
+++ /dev/null
@@ -1,374 +0,0 @@
1/*
2 * Copyright (C) 2012-2013 Avionic Design GmbH
3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
4 *
5 * Based on the KMS/FB CMA helpers
6 * Copyright (C) 2012 Analog Device Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14
15#include "drm.h"
16#include "gem.h"
17
18static inline struct tegra_fb *to_tegra_fb(struct drm_framebuffer *fb)
19{
20 return container_of(fb, struct tegra_fb, base);
21}
22
23static inline struct tegra_fbdev *to_tegra_fbdev(struct drm_fb_helper *helper)
24{
25 return container_of(helper, struct tegra_fbdev, base);
26}
27
28struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
29 unsigned int index)
30{
31 struct tegra_fb *fb = to_tegra_fb(framebuffer);
32
33 if (index >= drm_format_num_planes(framebuffer->pixel_format))
34 return NULL;
35
36 return fb->planes[index];
37}
38
39static void tegra_fb_destroy(struct drm_framebuffer *framebuffer)
40{
41 struct tegra_fb *fb = to_tegra_fb(framebuffer);
42 unsigned int i;
43
44 for (i = 0; i < fb->num_planes; i++) {
45 struct tegra_bo *bo = fb->planes[i];
46
47 if (bo)
48 drm_gem_object_unreference_unlocked(&bo->gem);
49 }
50
51 drm_framebuffer_cleanup(framebuffer);
52 kfree(fb->planes);
53 kfree(fb);
54}
55
56static int tegra_fb_create_handle(struct drm_framebuffer *framebuffer,
57 struct drm_file *file, unsigned int *handle)
58{
59 struct tegra_fb *fb = to_tegra_fb(framebuffer);
60
61 return drm_gem_handle_create(file, &fb->planes[0]->gem, handle);
62}
63
64static struct drm_framebuffer_funcs tegra_fb_funcs = {
65 .destroy = tegra_fb_destroy,
66 .create_handle = tegra_fb_create_handle,
67};
68
69static struct tegra_fb *tegra_fb_alloc(struct drm_device *drm,
70 struct drm_mode_fb_cmd2 *mode_cmd,
71 struct tegra_bo **planes,
72 unsigned int num_planes)
73{
74 struct tegra_fb *fb;
75 unsigned int i;
76 int err;
77
78 fb = kzalloc(sizeof(*fb), GFP_KERNEL);
79 if (!fb)
80 return ERR_PTR(-ENOMEM);
81
82 fb->planes = kzalloc(num_planes * sizeof(*planes), GFP_KERNEL);
83 if (!fb->planes)
84 return ERR_PTR(-ENOMEM);
85
86 fb->num_planes = num_planes;
87
88 drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
89
90 for (i = 0; i < fb->num_planes; i++)
91 fb->planes[i] = planes[i];
92
93 err = drm_framebuffer_init(drm, &fb->base, &tegra_fb_funcs);
94 if (err < 0) {
95 dev_err(drm->dev, "failed to initialize framebuffer: %d\n",
96 err);
97 kfree(fb->planes);
98 kfree(fb);
99 return ERR_PTR(err);
100 }
101
102 return fb;
103}
104
105static struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
106 struct drm_file *file,
107 struct drm_mode_fb_cmd2 *cmd)
108{
109 unsigned int hsub, vsub, i;
110 struct tegra_bo *planes[4];
111 struct drm_gem_object *gem;
112 struct tegra_fb *fb;
113 int err;
114
115 hsub = drm_format_horz_chroma_subsampling(cmd->pixel_format);
116 vsub = drm_format_vert_chroma_subsampling(cmd->pixel_format);
117
118 for (i = 0; i < drm_format_num_planes(cmd->pixel_format); i++) {
119 unsigned int width = cmd->width / (i ? hsub : 1);
120 unsigned int height = cmd->height / (i ? vsub : 1);
121 unsigned int size, bpp;
122
123 gem = drm_gem_object_lookup(drm, file, cmd->handles[i]);
124 if (!gem) {
125 err = -ENXIO;
126 goto unreference;
127 }
128
129 bpp = drm_format_plane_cpp(cmd->pixel_format, i);
130
131 size = (height - 1) * cmd->pitches[i] +
132 width * bpp + cmd->offsets[i];
133
134 if (gem->size < size) {
135 err = -EINVAL;
136 goto unreference;
137 }
138
139 planes[i] = to_tegra_bo(gem);
140 }
141
142 fb = tegra_fb_alloc(drm, cmd, planes, i);
143 if (IS_ERR(fb)) {
144 err = PTR_ERR(fb);
145 goto unreference;
146 }
147
148 return &fb->base;
149
150unreference:
151 while (i--)
152 drm_gem_object_unreference_unlocked(&planes[i]->gem);
153
154 return ERR_PTR(err);
155}
156
157static struct fb_ops tegra_fb_ops = {
158 .owner = THIS_MODULE,
159 .fb_fillrect = sys_fillrect,
160 .fb_copyarea = sys_copyarea,
161 .fb_imageblit = sys_imageblit,
162 .fb_check_var = drm_fb_helper_check_var,
163 .fb_set_par = drm_fb_helper_set_par,
164 .fb_blank = drm_fb_helper_blank,
165 .fb_pan_display = drm_fb_helper_pan_display,
166 .fb_setcmap = drm_fb_helper_setcmap,
167};
168
169static int tegra_fbdev_probe(struct drm_fb_helper *helper,
170 struct drm_fb_helper_surface_size *sizes)
171{
172 struct tegra_fbdev *fbdev = to_tegra_fbdev(helper);
173 struct drm_device *drm = helper->dev;
174 struct drm_mode_fb_cmd2 cmd = { 0 };
175 unsigned int bytes_per_pixel;
176 struct drm_framebuffer *fb;
177 unsigned long offset;
178 struct fb_info *info;
179 struct tegra_bo *bo;
180 size_t size;
181 int err;
182
183 bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
184
185 cmd.width = sizes->surface_width;
186 cmd.height = sizes->surface_height;
187 cmd.pitches[0] = sizes->surface_width * bytes_per_pixel;
188 cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
189 sizes->surface_depth);
190
191 size = cmd.pitches[0] * cmd.height;
192
193 bo = tegra_bo_create(drm, size);
194 if (IS_ERR(bo))
195 return PTR_ERR(bo);
196
197 info = framebuffer_alloc(0, drm->dev);
198 if (!info) {
199 dev_err(drm->dev, "failed to allocate framebuffer info\n");
200 tegra_bo_free_object(&bo->gem);
201 return -ENOMEM;
202 }
203
204 fbdev->fb = tegra_fb_alloc(drm, &cmd, &bo, 1);
205 if (IS_ERR(fbdev->fb)) {
206 dev_err(drm->dev, "failed to allocate DRM framebuffer\n");
207 err = PTR_ERR(fbdev->fb);
208 goto release;
209 }
210
211 fb = &fbdev->fb->base;
212 helper->fb = fb;
213 helper->fbdev = info;
214
215 info->par = helper;
216 info->flags = FBINFO_FLAG_DEFAULT;
217 info->fbops = &tegra_fb_ops;
218
219 err = fb_alloc_cmap(&info->cmap, 256, 0);
220 if (err < 0) {
221 dev_err(drm->dev, "failed to allocate color map: %d\n", err);
222 goto destroy;
223 }
224
225 drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
226 drm_fb_helper_fill_var(info, helper, fb->width, fb->height);
227
228 offset = info->var.xoffset * bytes_per_pixel +
229 info->var.yoffset * fb->pitches[0];
230
231 drm->mode_config.fb_base = (resource_size_t)bo->paddr;
232 info->screen_base = bo->vaddr + offset;
233 info->screen_size = size;
234 info->fix.smem_start = (unsigned long)(bo->paddr + offset);
235 info->fix.smem_len = size;
236
237 return 0;
238
239destroy:
240 drm_framebuffer_unregister_private(fb);
241 tegra_fb_destroy(fb);
242release:
243 framebuffer_release(info);
244 return err;
245}
246
247static struct drm_fb_helper_funcs tegra_fb_helper_funcs = {
248 .fb_probe = tegra_fbdev_probe,
249};
250
251static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
252 unsigned int preferred_bpp,
253 unsigned int num_crtc,
254 unsigned int max_connectors)
255{
256 struct drm_fb_helper *helper;
257 struct tegra_fbdev *fbdev;
258 int err;
259
260 fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
261 if (!fbdev) {
262 dev_err(drm->dev, "failed to allocate DRM fbdev\n");
263 return ERR_PTR(-ENOMEM);
264 }
265
266 fbdev->base.funcs = &tegra_fb_helper_funcs;
267 helper = &fbdev->base;
268
269 err = drm_fb_helper_init(drm, &fbdev->base, num_crtc, max_connectors);
270 if (err < 0) {
271 dev_err(drm->dev, "failed to initialize DRM FB helper\n");
272 goto free;
273 }
274
275 err = drm_fb_helper_single_add_all_connectors(&fbdev->base);
276 if (err < 0) {
277 dev_err(drm->dev, "failed to add connectors\n");
278 goto fini;
279 }
280
281 drm_helper_disable_unused_functions(drm);
282
283 err = drm_fb_helper_initial_config(&fbdev->base, preferred_bpp);
284 if (err < 0) {
285 dev_err(drm->dev, "failed to set initial configuration\n");
286 goto fini;
287 }
288
289 return fbdev;
290
291fini:
292 drm_fb_helper_fini(&fbdev->base);
293free:
294 kfree(fbdev);
295 return ERR_PTR(err);
296}
297
298static void tegra_fbdev_free(struct tegra_fbdev *fbdev)
299{
300 struct fb_info *info = fbdev->base.fbdev;
301
302 if (info) {
303 int err;
304
305 err = unregister_framebuffer(info);
306 if (err < 0)
307 DRM_DEBUG_KMS("failed to unregister framebuffer\n");
308
309 if (info->cmap.len)
310 fb_dealloc_cmap(&info->cmap);
311
312 framebuffer_release(info);
313 }
314
315 if (fbdev->fb) {
316 drm_framebuffer_unregister_private(&fbdev->fb->base);
317 tegra_fb_destroy(&fbdev->fb->base);
318 }
319
320 drm_fb_helper_fini(&fbdev->base);
321 kfree(fbdev);
322}
323
324static void tegra_fb_output_poll_changed(struct drm_device *drm)
325{
326 struct host1x_drm *host1x = drm->dev_private;
327
328 if (host1x->fbdev)
329 drm_fb_helper_hotplug_event(&host1x->fbdev->base);
330}
331
332static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
333 .fb_create = tegra_fb_create,
334 .output_poll_changed = tegra_fb_output_poll_changed,
335};
336
337int tegra_drm_fb_init(struct drm_device *drm)
338{
339 struct host1x_drm *host1x = drm->dev_private;
340 struct tegra_fbdev *fbdev;
341
342 drm->mode_config.min_width = 0;
343 drm->mode_config.min_height = 0;
344
345 drm->mode_config.max_width = 4096;
346 drm->mode_config.max_height = 4096;
347
348 drm->mode_config.funcs = &tegra_drm_mode_funcs;
349
350 fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc,
351 drm->mode_config.num_connector);
352 if (IS_ERR(fbdev))
353 return PTR_ERR(fbdev);
354
355 host1x->fbdev = fbdev;
356
357 return 0;
358}
359
360void tegra_drm_fb_exit(struct drm_device *drm)
361{
362 struct host1x_drm *host1x = drm->dev_private;
363
364 tegra_fbdev_free(host1x->fbdev);
365}
366
367void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev)
368{
369 if (fbdev) {
370 drm_modeset_lock_all(fbdev->base.dev);
371 drm_fb_helper_restore_fbdev_mode(&fbdev->base);
372 drm_modeset_unlock_all(fbdev->base.dev);
373 }
374}
diff --git a/drivers/gpu/host1x/drm/gem.c b/drivers/gpu/host1x/drm/gem.c
deleted file mode 100644
index 59623de4ee15..000000000000
--- a/drivers/gpu/host1x/drm/gem.c
+++ /dev/null
@@ -1,258 +0,0 @@
1/*
2 * NVIDIA Tegra DRM GEM helper functions
3 *
4 * Copyright (C) 2012 Sascha Hauer, Pengutronix
5 * Copyright (C) 2013 NVIDIA CORPORATION, All rights reserved.
6 *
7 * Based on the GEM/CMA helpers
8 *
9 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 */
20
21#include <linux/mm.h>
22#include <linux/slab.h>
23#include <linux/mutex.h>
24#include <linux/export.h>
25#include <linux/dma-mapping.h>
26
27#include <drm/drmP.h>
28#include <drm/drm.h>
29
30#include "gem.h"
31
32static inline struct tegra_bo *host1x_to_drm_bo(struct host1x_bo *bo)
33{
34 return container_of(bo, struct tegra_bo, base);
35}
36
37static void tegra_bo_put(struct host1x_bo *bo)
38{
39 struct tegra_bo *obj = host1x_to_drm_bo(bo);
40 struct drm_device *drm = obj->gem.dev;
41
42 mutex_lock(&drm->struct_mutex);
43 drm_gem_object_unreference(&obj->gem);
44 mutex_unlock(&drm->struct_mutex);
45}
46
47static dma_addr_t tegra_bo_pin(struct host1x_bo *bo, struct sg_table **sgt)
48{
49 struct tegra_bo *obj = host1x_to_drm_bo(bo);
50
51 return obj->paddr;
52}
53
54static void tegra_bo_unpin(struct host1x_bo *bo, struct sg_table *sgt)
55{
56}
57
58static void *tegra_bo_mmap(struct host1x_bo *bo)
59{
60 struct tegra_bo *obj = host1x_to_drm_bo(bo);
61
62 return obj->vaddr;
63}
64
65static void tegra_bo_munmap(struct host1x_bo *bo, void *addr)
66{
67}
68
69static void *tegra_bo_kmap(struct host1x_bo *bo, unsigned int page)
70{
71 struct tegra_bo *obj = host1x_to_drm_bo(bo);
72
73 return obj->vaddr + page * PAGE_SIZE;
74}
75
76static void tegra_bo_kunmap(struct host1x_bo *bo, unsigned int page,
77 void *addr)
78{
79}
80
81static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo)
82{
83 struct tegra_bo *obj = host1x_to_drm_bo(bo);
84 struct drm_device *drm = obj->gem.dev;
85
86 mutex_lock(&drm->struct_mutex);
87 drm_gem_object_reference(&obj->gem);
88 mutex_unlock(&drm->struct_mutex);
89
90 return bo;
91}
92
93const struct host1x_bo_ops tegra_bo_ops = {
94 .get = tegra_bo_get,
95 .put = tegra_bo_put,
96 .pin = tegra_bo_pin,
97 .unpin = tegra_bo_unpin,
98 .mmap = tegra_bo_mmap,
99 .munmap = tegra_bo_munmap,
100 .kmap = tegra_bo_kmap,
101 .kunmap = tegra_bo_kunmap,
102};
103
104static void tegra_bo_destroy(struct drm_device *drm, struct tegra_bo *bo)
105{
106 dma_free_writecombine(drm->dev, bo->gem.size, bo->vaddr, bo->paddr);
107}
108
109struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size)
110{
111 struct tegra_bo *bo;
112 int err;
113
114 bo = kzalloc(sizeof(*bo), GFP_KERNEL);
115 if (!bo)
116 return ERR_PTR(-ENOMEM);
117
118 host1x_bo_init(&bo->base, &tegra_bo_ops);
119 size = round_up(size, PAGE_SIZE);
120
121 bo->vaddr = dma_alloc_writecombine(drm->dev, size, &bo->paddr,
122 GFP_KERNEL | __GFP_NOWARN);
123 if (!bo->vaddr) {
124 dev_err(drm->dev, "failed to allocate buffer with size %u\n",
125 size);
126 err = -ENOMEM;
127 goto err_dma;
128 }
129
130 err = drm_gem_object_init(drm, &bo->gem, size);
131 if (err)
132 goto err_init;
133
134 err = drm_gem_create_mmap_offset(&bo->gem);
135 if (err)
136 goto err_mmap;
137
138 return bo;
139
140err_mmap:
141 drm_gem_object_release(&bo->gem);
142err_init:
143 tegra_bo_destroy(drm, bo);
144err_dma:
145 kfree(bo);
146
147 return ERR_PTR(err);
148
149}
150
151struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
152 struct drm_device *drm,
153 unsigned int size,
154 unsigned int *handle)
155{
156 struct tegra_bo *bo;
157 int ret;
158
159 bo = tegra_bo_create(drm, size);
160 if (IS_ERR(bo))
161 return bo;
162
163 ret = drm_gem_handle_create(file, &bo->gem, handle);
164 if (ret)
165 goto err;
166
167 drm_gem_object_unreference_unlocked(&bo->gem);
168
169 return bo;
170
171err:
172 tegra_bo_free_object(&bo->gem);
173 return ERR_PTR(ret);
174}
175
176void tegra_bo_free_object(struct drm_gem_object *gem)
177{
178 struct tegra_bo *bo = to_tegra_bo(gem);
179
180 drm_gem_free_mmap_offset(gem);
181
182 drm_gem_object_release(gem);
183 tegra_bo_destroy(gem->dev, bo);
184
185 kfree(bo);
186}
187
188int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm,
189 struct drm_mode_create_dumb *args)
190{
191 int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
192 struct tegra_bo *bo;
193
194 if (args->pitch < min_pitch)
195 args->pitch = min_pitch;
196
197 if (args->size < args->pitch * args->height)
198 args->size = args->pitch * args->height;
199
200 bo = tegra_bo_create_with_handle(file, drm, args->size,
201 &args->handle);
202 if (IS_ERR(bo))
203 return PTR_ERR(bo);
204
205 return 0;
206}
207
208int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm,
209 uint32_t handle, uint64_t *offset)
210{
211 struct drm_gem_object *gem;
212 struct tegra_bo *bo;
213
214 mutex_lock(&drm->struct_mutex);
215
216 gem = drm_gem_object_lookup(drm, file, handle);
217 if (!gem) {
218 dev_err(drm->dev, "failed to lookup GEM object\n");
219 mutex_unlock(&drm->struct_mutex);
220 return -EINVAL;
221 }
222
223 bo = to_tegra_bo(gem);
224
225 *offset = drm_vma_node_offset_addr(&bo->gem.vma_node);
226
227 drm_gem_object_unreference(gem);
228
229 mutex_unlock(&drm->struct_mutex);
230
231 return 0;
232}
233
234const struct vm_operations_struct tegra_bo_vm_ops = {
235 .open = drm_gem_vm_open,
236 .close = drm_gem_vm_close,
237};
238
239int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma)
240{
241 struct drm_gem_object *gem;
242 struct tegra_bo *bo;
243 int ret;
244
245 ret = drm_gem_mmap(file, vma);
246 if (ret)
247 return ret;
248
249 gem = vma->vm_private_data;
250 bo = to_tegra_bo(gem);
251
252 ret = remap_pfn_range(vma, vma->vm_start, bo->paddr >> PAGE_SHIFT,
253 vma->vm_end - vma->vm_start, vma->vm_page_prot);
254 if (ret)
255 drm_gem_vm_close(vma);
256
257 return ret;
258}
diff --git a/drivers/gpu/host1x/drm/gem.h b/drivers/gpu/host1x/drm/gem.h
deleted file mode 100644
index 492533a2dacb..000000000000
--- a/drivers/gpu/host1x/drm/gem.h
+++ /dev/null
@@ -1,56 +0,0 @@
1/*
2 * Tegra host1x GEM implementation
3 *
4 * Copyright (c) 2012-2013, NVIDIA Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef __HOST1X_GEM_H
20#define __HOST1X_GEM_H
21
22#include <drm/drm.h>
23#include <drm/drmP.h>
24
25#include "host1x_bo.h"
26
27struct tegra_bo {
28 struct drm_gem_object gem;
29 struct host1x_bo base;
30 dma_addr_t paddr;
31 void *vaddr;
32};
33
34static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem)
35{
36 return container_of(gem, struct tegra_bo, gem);
37}
38
39extern const struct host1x_bo_ops tegra_bo_ops;
40
41struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size);
42struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
43 struct drm_device *drm,
44 unsigned int size,
45 unsigned int *handle);
46void tegra_bo_free_object(struct drm_gem_object *gem);
47int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm,
48 struct drm_mode_create_dumb *args);
49int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm,
50 uint32_t handle, uint64_t *offset);
51
52int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma);
53
54extern const struct vm_operations_struct tegra_bo_vm_ops;
55
56#endif
diff --git a/drivers/gpu/host1x/drm/gr2d.c b/drivers/gpu/host1x/drm/gr2d.c
deleted file mode 100644
index 27ffcf15a4b4..000000000000
--- a/drivers/gpu/host1x/drm/gr2d.c
+++ /dev/null
@@ -1,343 +0,0 @@
1/*
2 * drivers/video/tegra/host/gr2d/gr2d.c
3 *
4 * Tegra Graphics 2D
5 *
6 * Copyright (c) 2012-2013, NVIDIA Corporation.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <linux/export.h>
22#include <linux/of.h>
23#include <linux/of_device.h>
24#include <linux/clk.h>
25
26#include "channel.h"
27#include "drm.h"
28#include "gem.h"
29#include "job.h"
30#include "host1x.h"
31#include "host1x_bo.h"
32#include "host1x_client.h"
33#include "syncpt.h"
34
35struct gr2d {
36 struct host1x_client client;
37 struct clk *clk;
38 struct host1x_channel *channel;
39 unsigned long *addr_regs;
40};
41
42static inline struct gr2d *to_gr2d(struct host1x_client *client)
43{
44 return container_of(client, struct gr2d, client);
45}
46
47static int gr2d_is_addr_reg(struct device *dev, u32 class, u32 reg);
48
49static int gr2d_client_init(struct host1x_client *client,
50 struct drm_device *drm)
51{
52 return 0;
53}
54
55static int gr2d_client_exit(struct host1x_client *client)
56{
57 return 0;
58}
59
60static int gr2d_open_channel(struct host1x_client *client,
61 struct host1x_drm_context *context)
62{
63 struct gr2d *gr2d = to_gr2d(client);
64
65 context->channel = host1x_channel_get(gr2d->channel);
66
67 if (!context->channel)
68 return -ENOMEM;
69
70 return 0;
71}
72
73static void gr2d_close_channel(struct host1x_drm_context *context)
74{
75 host1x_channel_put(context->channel);
76}
77
78static struct host1x_bo *host1x_bo_lookup(struct drm_device *drm,
79 struct drm_file *file,
80 u32 handle)
81{
82 struct drm_gem_object *gem;
83 struct tegra_bo *bo;
84
85 gem = drm_gem_object_lookup(drm, file, handle);
86 if (!gem)
87 return NULL;
88
89 mutex_lock(&drm->struct_mutex);
90 drm_gem_object_unreference(gem);
91 mutex_unlock(&drm->struct_mutex);
92
93 bo = to_tegra_bo(gem);
94 return &bo->base;
95}
96
97static int gr2d_submit(struct host1x_drm_context *context,
98 struct drm_tegra_submit *args, struct drm_device *drm,
99 struct drm_file *file)
100{
101 struct host1x_job *job;
102 unsigned int num_cmdbufs = args->num_cmdbufs;
103 unsigned int num_relocs = args->num_relocs;
104 unsigned int num_waitchks = args->num_waitchks;
105 struct drm_tegra_cmdbuf __user *cmdbufs =
106 (void * __user)(uintptr_t)args->cmdbufs;
107 struct drm_tegra_reloc __user *relocs =
108 (void * __user)(uintptr_t)args->relocs;
109 struct drm_tegra_waitchk __user *waitchks =
110 (void * __user)(uintptr_t)args->waitchks;
111 struct drm_tegra_syncpt syncpt;
112 int err;
113
114 /* We don't yet support other than one syncpt_incr struct per submit */
115 if (args->num_syncpts != 1)
116 return -EINVAL;
117
118 job = host1x_job_alloc(context->channel, args->num_cmdbufs,
119 args->num_relocs, args->num_waitchks);
120 if (!job)
121 return -ENOMEM;
122
123 job->num_relocs = args->num_relocs;
124 job->num_waitchk = args->num_waitchks;
125 job->client = (u32)args->context;
126 job->class = context->client->class;
127 job->serialize = true;
128
129 while (num_cmdbufs) {
130 struct drm_tegra_cmdbuf cmdbuf;
131 struct host1x_bo *bo;
132
133 err = copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf));
134 if (err)
135 goto fail;
136
137 bo = host1x_bo_lookup(drm, file, cmdbuf.handle);
138 if (!bo) {
139 err = -ENOENT;
140 goto fail;
141 }
142
143 host1x_job_add_gather(job, bo, cmdbuf.words, cmdbuf.offset);
144 num_cmdbufs--;
145 cmdbufs++;
146 }
147
148 err = copy_from_user(job->relocarray, relocs,
149 sizeof(*relocs) * num_relocs);
150 if (err)
151 goto fail;
152
153 while (num_relocs--) {
154 struct host1x_reloc *reloc = &job->relocarray[num_relocs];
155 struct host1x_bo *cmdbuf, *target;
156
157 cmdbuf = host1x_bo_lookup(drm, file, (u32)reloc->cmdbuf);
158 target = host1x_bo_lookup(drm, file, (u32)reloc->target);
159
160 reloc->cmdbuf = cmdbuf;
161 reloc->target = target;
162
163 if (!reloc->target || !reloc->cmdbuf) {
164 err = -ENOENT;
165 goto fail;
166 }
167 }
168
169 err = copy_from_user(job->waitchk, waitchks,
170 sizeof(*waitchks) * num_waitchks);
171 if (err)
172 goto fail;
173
174 err = copy_from_user(&syncpt, (void * __user)(uintptr_t)args->syncpts,
175 sizeof(syncpt));
176 if (err)
177 goto fail;
178
179 job->syncpt_id = syncpt.id;
180 job->syncpt_incrs = syncpt.incrs;
181 job->timeout = 10000;
182 job->is_addr_reg = gr2d_is_addr_reg;
183
184 if (args->timeout && args->timeout < 10000)
185 job->timeout = args->timeout;
186
187 err = host1x_job_pin(job, context->client->dev);
188 if (err)
189 goto fail;
190
191 err = host1x_job_submit(job);
192 if (err)
193 goto fail_submit;
194
195 args->fence = job->syncpt_end;
196
197 host1x_job_put(job);
198 return 0;
199
200fail_submit:
201 host1x_job_unpin(job);
202fail:
203 host1x_job_put(job);
204 return err;
205}
206
207static struct host1x_client_ops gr2d_client_ops = {
208 .drm_init = gr2d_client_init,
209 .drm_exit = gr2d_client_exit,
210 .open_channel = gr2d_open_channel,
211 .close_channel = gr2d_close_channel,
212 .submit = gr2d_submit,
213};
214
215static void gr2d_init_addr_reg_map(struct device *dev, struct gr2d *gr2d)
216{
217 const u32 gr2d_addr_regs[] = {0x1a, 0x1b, 0x26, 0x2b, 0x2c, 0x2d, 0x31,
218 0x32, 0x48, 0x49, 0x4a, 0x4b, 0x4c};
219 unsigned long *bitmap;
220 int i;
221
222 bitmap = devm_kzalloc(dev, DIV_ROUND_UP(256, BITS_PER_BYTE),
223 GFP_KERNEL);
224
225 for (i = 0; i < ARRAY_SIZE(gr2d_addr_regs); ++i) {
226 u32 reg = gr2d_addr_regs[i];
227 bitmap[BIT_WORD(reg)] |= BIT_MASK(reg);
228 }
229
230 gr2d->addr_regs = bitmap;
231}
232
233static int gr2d_is_addr_reg(struct device *dev, u32 class, u32 reg)
234{
235 struct gr2d *gr2d = dev_get_drvdata(dev);
236
237 switch (class) {
238 case HOST1X_CLASS_HOST1X:
239 return reg == 0x2b;
240 case HOST1X_CLASS_GR2D:
241 case HOST1X_CLASS_GR2D_SB:
242 reg &= 0xff;
243 if (gr2d->addr_regs[BIT_WORD(reg)] & BIT_MASK(reg))
244 return 1;
245 default:
246 return 0;
247 }
248}
249
250static const struct of_device_id gr2d_match[] = {
251 { .compatible = "nvidia,tegra30-gr2d" },
252 { .compatible = "nvidia,tegra20-gr2d" },
253 { },
254};
255
256static int gr2d_probe(struct platform_device *pdev)
257{
258 struct device *dev = &pdev->dev;
259 struct host1x_drm *host1x = host1x_get_drm_data(dev->parent);
260 int err;
261 struct gr2d *gr2d = NULL;
262 struct host1x_syncpt **syncpts;
263
264 gr2d = devm_kzalloc(dev, sizeof(*gr2d), GFP_KERNEL);
265 if (!gr2d)
266 return -ENOMEM;
267
268 syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL);
269 if (!syncpts)
270 return -ENOMEM;
271
272 gr2d->clk = devm_clk_get(dev, NULL);
273 if (IS_ERR(gr2d->clk)) {
274 dev_err(dev, "cannot get clock\n");
275 return PTR_ERR(gr2d->clk);
276 }
277
278 err = clk_prepare_enable(gr2d->clk);
279 if (err) {
280 dev_err(dev, "cannot turn on clock\n");
281 return err;
282 }
283
284 gr2d->channel = host1x_channel_request(dev);
285 if (!gr2d->channel)
286 return -ENOMEM;
287
288 *syncpts = host1x_syncpt_request(dev, false);
289 if (!(*syncpts)) {
290 host1x_channel_free(gr2d->channel);
291 return -ENOMEM;
292 }
293
294 gr2d->client.ops = &gr2d_client_ops;
295 gr2d->client.dev = dev;
296 gr2d->client.class = HOST1X_CLASS_GR2D;
297 gr2d->client.syncpts = syncpts;
298 gr2d->client.num_syncpts = 1;
299
300 err = host1x_register_client(host1x, &gr2d->client);
301 if (err < 0) {
302 dev_err(dev, "failed to register host1x client: %d\n", err);
303 return err;
304 }
305
306 gr2d_init_addr_reg_map(dev, gr2d);
307
308 platform_set_drvdata(pdev, gr2d);
309
310 return 0;
311}
312
313static int __exit gr2d_remove(struct platform_device *pdev)
314{
315 struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent);
316 struct gr2d *gr2d = platform_get_drvdata(pdev);
317 unsigned int i;
318 int err;
319
320 err = host1x_unregister_client(host1x, &gr2d->client);
321 if (err < 0) {
322 dev_err(&pdev->dev, "failed to unregister client: %d\n", err);
323 return err;
324 }
325
326 for (i = 0; i < gr2d->client.num_syncpts; i++)
327 host1x_syncpt_free(gr2d->client.syncpts[i]);
328
329 host1x_channel_free(gr2d->channel);
330 clk_disable_unprepare(gr2d->clk);
331
332 return 0;
333}
334
335struct platform_driver tegra_gr2d_driver = {
336 .probe = gr2d_probe,
337 .remove = __exit_p(gr2d_remove),
338 .driver = {
339 .owner = THIS_MODULE,
340 .name = "gr2d",
341 .of_match_table = gr2d_match,
342 }
343};
diff --git a/drivers/gpu/host1x/drm/hdmi.c b/drivers/gpu/host1x/drm/hdmi.c
deleted file mode 100644
index 644d95c7d489..000000000000
--- a/drivers/gpu/host1x/drm/hdmi.c
+++ /dev/null
@@ -1,1304 +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/debugfs.h>
12#include <linux/gpio.h>
13#include <linux/hdmi.h>
14#include <linux/module.h>
15#include <linux/of.h>
16#include <linux/platform_device.h>
17#include <linux/regulator/consumer.h>
18#include <linux/clk/tegra.h>
19
20#include <drm/drm_edid.h>
21
22#include "hdmi.h"
23#include "drm.h"
24#include "dc.h"
25#include "host1x_client.h"
26
27struct tegra_hdmi {
28 struct host1x_client client;
29 struct tegra_output output;
30 struct device *dev;
31
32 struct regulator *vdd;
33 struct regulator *pll;
34
35 void __iomem *regs;
36 unsigned int irq;
37
38 struct clk *clk_parent;
39 struct clk *clk;
40
41 unsigned int audio_source;
42 unsigned int audio_freq;
43 bool stereo;
44 bool dvi;
45
46 struct drm_info_list *debugfs_files;
47 struct drm_minor *minor;
48 struct dentry *debugfs;
49};
50
51static inline struct tegra_hdmi *
52host1x_client_to_hdmi(struct host1x_client *client)
53{
54 return container_of(client, struct tegra_hdmi, client);
55}
56
57static inline struct tegra_hdmi *to_hdmi(struct tegra_output *output)
58{
59 return container_of(output, struct tegra_hdmi, output);
60}
61
62#define HDMI_AUDIOCLK_FREQ 216000000
63#define HDMI_REKEY_DEFAULT 56
64
65enum {
66 AUTO = 0,
67 SPDIF,
68 HDA,
69};
70
71static inline unsigned long tegra_hdmi_readl(struct tegra_hdmi *hdmi,
72 unsigned long reg)
73{
74 return readl(hdmi->regs + (reg << 2));
75}
76
77static inline void tegra_hdmi_writel(struct tegra_hdmi *hdmi, unsigned long val,
78 unsigned long reg)
79{
80 writel(val, hdmi->regs + (reg << 2));
81}
82
83struct tegra_hdmi_audio_config {
84 unsigned int pclk;
85 unsigned int n;
86 unsigned int cts;
87 unsigned int aval;
88};
89
90static const struct tegra_hdmi_audio_config tegra_hdmi_audio_32k[] = {
91 { 25200000, 4096, 25200, 24000 },
92 { 27000000, 4096, 27000, 24000 },
93 { 74250000, 4096, 74250, 24000 },
94 { 148500000, 4096, 148500, 24000 },
95 { 0, 0, 0, 0 },
96};
97
98static const struct tegra_hdmi_audio_config tegra_hdmi_audio_44_1k[] = {
99 { 25200000, 5880, 26250, 25000 },
100 { 27000000, 5880, 28125, 25000 },
101 { 74250000, 4704, 61875, 20000 },
102 { 148500000, 4704, 123750, 20000 },
103 { 0, 0, 0, 0 },
104};
105
106static const struct tegra_hdmi_audio_config tegra_hdmi_audio_48k[] = {
107 { 25200000, 6144, 25200, 24000 },
108 { 27000000, 6144, 27000, 24000 },
109 { 74250000, 6144, 74250, 24000 },
110 { 148500000, 6144, 148500, 24000 },
111 { 0, 0, 0, 0 },
112};
113
114static const struct tegra_hdmi_audio_config tegra_hdmi_audio_88_2k[] = {
115 { 25200000, 11760, 26250, 25000 },
116 { 27000000, 11760, 28125, 25000 },
117 { 74250000, 9408, 61875, 20000 },
118 { 148500000, 9408, 123750, 20000 },
119 { 0, 0, 0, 0 },
120};
121
122static const struct tegra_hdmi_audio_config tegra_hdmi_audio_96k[] = {
123 { 25200000, 12288, 25200, 24000 },
124 { 27000000, 12288, 27000, 24000 },
125 { 74250000, 12288, 74250, 24000 },
126 { 148500000, 12288, 148500, 24000 },
127 { 0, 0, 0, 0 },
128};
129
130static const struct tegra_hdmi_audio_config tegra_hdmi_audio_176_4k[] = {
131 { 25200000, 23520, 26250, 25000 },
132 { 27000000, 23520, 28125, 25000 },
133 { 74250000, 18816, 61875, 20000 },
134 { 148500000, 18816, 123750, 20000 },
135 { 0, 0, 0, 0 },
136};
137
138static const struct tegra_hdmi_audio_config tegra_hdmi_audio_192k[] = {
139 { 25200000, 24576, 25200, 24000 },
140 { 27000000, 24576, 27000, 24000 },
141 { 74250000, 24576, 74250, 24000 },
142 { 148500000, 24576, 148500, 24000 },
143 { 0, 0, 0, 0 },
144};
145
146struct tmds_config {
147 unsigned int pclk;
148 u32 pll0;
149 u32 pll1;
150 u32 pe_current;
151 u32 drive_current;
152};
153
154static const struct tmds_config tegra2_tmds_config[] = {
155 { /* slow pixel clock modes */
156 .pclk = 27000000,
157 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
158 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
159 SOR_PLL_TX_REG_LOAD(3),
160 .pll1 = SOR_PLL_TMDS_TERM_ENABLE,
161 .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
162 PE_CURRENT1(PE_CURRENT_0_0_mA) |
163 PE_CURRENT2(PE_CURRENT_0_0_mA) |
164 PE_CURRENT3(PE_CURRENT_0_0_mA),
165 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
166 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
167 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
168 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
169 },
170 { /* high pixel clock modes */
171 .pclk = UINT_MAX,
172 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
173 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
174 SOR_PLL_TX_REG_LOAD(3),
175 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
176 .pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) |
177 PE_CURRENT1(PE_CURRENT_6_0_mA) |
178 PE_CURRENT2(PE_CURRENT_6_0_mA) |
179 PE_CURRENT3(PE_CURRENT_6_0_mA),
180 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
181 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
182 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
183 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
184 },
185};
186
187static const struct tmds_config tegra3_tmds_config[] = {
188 { /* 480p modes */
189 .pclk = 27000000,
190 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
191 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
192 SOR_PLL_TX_REG_LOAD(0),
193 .pll1 = SOR_PLL_TMDS_TERM_ENABLE,
194 .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
195 PE_CURRENT1(PE_CURRENT_0_0_mA) |
196 PE_CURRENT2(PE_CURRENT_0_0_mA) |
197 PE_CURRENT3(PE_CURRENT_0_0_mA),
198 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
199 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
200 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
201 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
202 }, { /* 720p modes */
203 .pclk = 74250000,
204 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
205 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
206 SOR_PLL_TX_REG_LOAD(0),
207 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
208 .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
209 PE_CURRENT1(PE_CURRENT_5_0_mA) |
210 PE_CURRENT2(PE_CURRENT_5_0_mA) |
211 PE_CURRENT3(PE_CURRENT_5_0_mA),
212 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
213 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
214 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
215 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
216 }, { /* 1080p modes */
217 .pclk = UINT_MAX,
218 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
219 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(3) |
220 SOR_PLL_TX_REG_LOAD(0),
221 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
222 .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
223 PE_CURRENT1(PE_CURRENT_5_0_mA) |
224 PE_CURRENT2(PE_CURRENT_5_0_mA) |
225 PE_CURRENT3(PE_CURRENT_5_0_mA),
226 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
227 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
228 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
229 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
230 },
231};
232
233static const struct tegra_hdmi_audio_config *
234tegra_hdmi_get_audio_config(unsigned int audio_freq, unsigned int pclk)
235{
236 const struct tegra_hdmi_audio_config *table;
237
238 switch (audio_freq) {
239 case 32000:
240 table = tegra_hdmi_audio_32k;
241 break;
242
243 case 44100:
244 table = tegra_hdmi_audio_44_1k;
245 break;
246
247 case 48000:
248 table = tegra_hdmi_audio_48k;
249 break;
250
251 case 88200:
252 table = tegra_hdmi_audio_88_2k;
253 break;
254
255 case 96000:
256 table = tegra_hdmi_audio_96k;
257 break;
258
259 case 176400:
260 table = tegra_hdmi_audio_176_4k;
261 break;
262
263 case 192000:
264 table = tegra_hdmi_audio_192k;
265 break;
266
267 default:
268 return NULL;
269 }
270
271 while (table->pclk) {
272 if (table->pclk == pclk)
273 return table;
274
275 table++;
276 }
277
278 return NULL;
279}
280
281static void tegra_hdmi_setup_audio_fs_tables(struct tegra_hdmi *hdmi)
282{
283 const unsigned int freqs[] = {
284 32000, 44100, 48000, 88200, 96000, 176400, 192000
285 };
286 unsigned int i;
287
288 for (i = 0; i < ARRAY_SIZE(freqs); i++) {
289 unsigned int f = freqs[i];
290 unsigned int eight_half;
291 unsigned long value;
292 unsigned int delta;
293
294 if (f > 96000)
295 delta = 2;
296 else if (f > 480000)
297 delta = 6;
298 else
299 delta = 9;
300
301 eight_half = (8 * HDMI_AUDIOCLK_FREQ) / (f * 128);
302 value = AUDIO_FS_LOW(eight_half - delta) |
303 AUDIO_FS_HIGH(eight_half + delta);
304 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_FS(i));
305 }
306}
307
308static int tegra_hdmi_setup_audio(struct tegra_hdmi *hdmi, unsigned int pclk)
309{
310 struct device_node *node = hdmi->dev->of_node;
311 const struct tegra_hdmi_audio_config *config;
312 unsigned int offset = 0;
313 unsigned long value;
314
315 switch (hdmi->audio_source) {
316 case HDA:
317 value = AUDIO_CNTRL0_SOURCE_SELECT_HDAL;
318 break;
319
320 case SPDIF:
321 value = AUDIO_CNTRL0_SOURCE_SELECT_SPDIF;
322 break;
323
324 default:
325 value = AUDIO_CNTRL0_SOURCE_SELECT_AUTO;
326 break;
327 }
328
329 if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
330 value |= AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
331 AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0);
332 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0);
333 } else {
334 value |= AUDIO_CNTRL0_INJECT_NULLSMPL;
335 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_AUDIO_CNTRL0);
336
337 value = AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
338 AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0);
339 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0);
340 }
341
342 config = tegra_hdmi_get_audio_config(hdmi->audio_freq, pclk);
343 if (!config) {
344 dev_err(hdmi->dev, "cannot set audio to %u at %u pclk\n",
345 hdmi->audio_freq, pclk);
346 return -EINVAL;
347 }
348
349 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_HDMI_ACR_CTRL);
350
351 value = AUDIO_N_RESETF | AUDIO_N_GENERATE_ALTERNATE |
352 AUDIO_N_VALUE(config->n - 1);
353 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N);
354
355 tegra_hdmi_writel(hdmi, ACR_SUBPACK_N(config->n) | ACR_ENABLE,
356 HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
357
358 value = ACR_SUBPACK_CTS(config->cts);
359 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
360
361 value = SPARE_HW_CTS | SPARE_FORCE_SW_CTS | SPARE_CTS_RESET_VAL(1);
362 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_SPARE);
363
364 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_AUDIO_N);
365 value &= ~AUDIO_N_RESETF;
366 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N);
367
368 if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
369 switch (hdmi->audio_freq) {
370 case 32000:
371 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320;
372 break;
373
374 case 44100:
375 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441;
376 break;
377
378 case 48000:
379 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480;
380 break;
381
382 case 88200:
383 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882;
384 break;
385
386 case 96000:
387 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960;
388 break;
389
390 case 176400:
391 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764;
392 break;
393
394 case 192000:
395 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920;
396 break;
397 }
398
399 tegra_hdmi_writel(hdmi, config->aval, offset);
400 }
401
402 tegra_hdmi_setup_audio_fs_tables(hdmi);
403
404 return 0;
405}
406
407static inline unsigned long tegra_hdmi_subpack(const u8 *ptr, size_t size)
408{
409 unsigned long value = 0;
410 size_t i;
411
412 for (i = size; i > 0; i--)
413 value = (value << 8) | ptr[i - 1];
414
415 return value;
416}
417
418static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi, const void *data,
419 size_t size)
420{
421 const u8 *ptr = data;
422 unsigned long offset;
423 unsigned long value;
424 size_t i, j;
425
426 switch (ptr[0]) {
427 case HDMI_INFOFRAME_TYPE_AVI:
428 offset = HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER;
429 break;
430
431 case HDMI_INFOFRAME_TYPE_AUDIO:
432 offset = HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER;
433 break;
434
435 case HDMI_INFOFRAME_TYPE_VENDOR:
436 offset = HDMI_NV_PDISP_HDMI_GENERIC_HEADER;
437 break;
438
439 default:
440 dev_err(hdmi->dev, "unsupported infoframe type: %02x\n",
441 ptr[0]);
442 return;
443 }
444
445 value = INFOFRAME_HEADER_TYPE(ptr[0]) |
446 INFOFRAME_HEADER_VERSION(ptr[1]) |
447 INFOFRAME_HEADER_LEN(ptr[2]);
448 tegra_hdmi_writel(hdmi, value, offset);
449 offset++;
450
451 /*
452 * Each subpack contains 7 bytes, divided into:
453 * - subpack_low: bytes 0 - 3
454 * - subpack_high: bytes 4 - 6 (with byte 7 padded to 0x00)
455 */
456 for (i = 3, j = 0; i < size; i += 7, j += 8) {
457 size_t rem = size - i, num = min_t(size_t, rem, 4);
458
459 value = tegra_hdmi_subpack(&ptr[i], num);
460 tegra_hdmi_writel(hdmi, value, offset++);
461
462 num = min_t(size_t, rem - num, 3);
463
464 value = tegra_hdmi_subpack(&ptr[i + 4], num);
465 tegra_hdmi_writel(hdmi, value, offset++);
466 }
467}
468
469static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
470 struct drm_display_mode *mode)
471{
472 struct hdmi_avi_infoframe frame;
473 u8 buffer[17];
474 ssize_t err;
475
476 if (hdmi->dvi) {
477 tegra_hdmi_writel(hdmi, 0,
478 HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
479 return;
480 }
481
482 err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
483 if (err < 0) {
484 dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err);
485 return;
486 }
487
488 err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
489 if (err < 0) {
490 dev_err(hdmi->dev, "failed to pack AVI infoframe: %zd\n", err);
491 return;
492 }
493
494 tegra_hdmi_write_infopack(hdmi, buffer, err);
495
496 tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
497 HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
498}
499
500static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi)
501{
502 struct hdmi_audio_infoframe frame;
503 u8 buffer[14];
504 ssize_t err;
505
506 if (hdmi->dvi) {
507 tegra_hdmi_writel(hdmi, 0,
508 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
509 return;
510 }
511
512 err = hdmi_audio_infoframe_init(&frame);
513 if (err < 0) {
514 dev_err(hdmi->dev, "failed to initialize audio infoframe: %d\n",
515 err);
516 return;
517 }
518
519 frame.channels = 2;
520
521 err = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
522 if (err < 0) {
523 dev_err(hdmi->dev, "failed to pack audio infoframe: %zd\n",
524 err);
525 return;
526 }
527
528 /*
529 * The audio infoframe has only one set of subpack registers, so the
530 * infoframe needs to be truncated. One set of subpack registers can
531 * contain 7 bytes. Including the 3 byte header only the first 10
532 * bytes can be programmed.
533 */
534 tegra_hdmi_write_infopack(hdmi, buffer, min(10, err));
535
536 tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
537 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
538}
539
540static void tegra_hdmi_setup_stereo_infoframe(struct tegra_hdmi *hdmi)
541{
542 struct hdmi_vendor_infoframe frame;
543 unsigned long value;
544 u8 buffer[10];
545 ssize_t err;
546
547 if (!hdmi->stereo) {
548 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
549 value &= ~GENERIC_CTRL_ENABLE;
550 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
551 return;
552 }
553
554 hdmi_vendor_infoframe_init(&frame);
555 frame.s3d_struct = HDMI_3D_STRUCTURE_FRAME_PACKING;
556
557 err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer));
558 if (err < 0) {
559 dev_err(hdmi->dev, "failed to pack vendor infoframe: %zd\n",
560 err);
561 return;
562 }
563
564 tegra_hdmi_write_infopack(hdmi, buffer, err);
565
566 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
567 value |= GENERIC_CTRL_ENABLE;
568 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
569}
570
571static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi,
572 const struct tmds_config *tmds)
573{
574 unsigned long value;
575
576 tegra_hdmi_writel(hdmi, tmds->pll0, HDMI_NV_PDISP_SOR_PLL0);
577 tegra_hdmi_writel(hdmi, tmds->pll1, HDMI_NV_PDISP_SOR_PLL1);
578 tegra_hdmi_writel(hdmi, tmds->pe_current, HDMI_NV_PDISP_PE_CURRENT);
579
580 value = tmds->drive_current | DRIVE_CURRENT_FUSE_OVERRIDE;
581 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
582}
583
584static int tegra_output_hdmi_enable(struct tegra_output *output)
585{
586 unsigned int h_sync_width, h_front_porch, h_back_porch, i, rekey;
587 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
588 struct drm_display_mode *mode = &dc->base.mode;
589 struct tegra_hdmi *hdmi = to_hdmi(output);
590 struct device_node *node = hdmi->dev->of_node;
591 unsigned int pulse_start, div82, pclk;
592 const struct tmds_config *tmds;
593 unsigned int num_tmds;
594 unsigned long value;
595 int retries = 1000;
596 int err;
597
598 pclk = mode->clock * 1000;
599 h_sync_width = mode->hsync_end - mode->hsync_start;
600 h_back_porch = mode->htotal - mode->hsync_end;
601 h_front_porch = mode->hsync_start - mode->hdisplay;
602
603 err = regulator_enable(hdmi->vdd);
604 if (err < 0) {
605 dev_err(hdmi->dev, "failed to enable VDD regulator: %d\n", err);
606 return err;
607 }
608
609 err = regulator_enable(hdmi->pll);
610 if (err < 0) {
611 dev_err(hdmi->dev, "failed to enable PLL regulator: %d\n", err);
612 return err;
613 }
614
615 /*
616 * This assumes that the display controller will divide its parent
617 * clock by 2 to generate the pixel clock.
618 */
619 err = tegra_output_setup_clock(output, hdmi->clk, pclk * 2);
620 if (err < 0) {
621 dev_err(hdmi->dev, "failed to setup clock: %d\n", err);
622 return err;
623 }
624
625 err = clk_set_rate(hdmi->clk, pclk);
626 if (err < 0)
627 return err;
628
629 err = clk_enable(hdmi->clk);
630 if (err < 0) {
631 dev_err(hdmi->dev, "failed to enable clock: %d\n", err);
632 return err;
633 }
634
635 tegra_periph_reset_assert(hdmi->clk);
636 usleep_range(1000, 2000);
637 tegra_periph_reset_deassert(hdmi->clk);
638
639 tegra_dc_writel(dc, VSYNC_H_POSITION(1),
640 DC_DISP_DISP_TIMING_OPTIONS);
641 tegra_dc_writel(dc, DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE888,
642 DC_DISP_DISP_COLOR_CONTROL);
643
644 /* video_preamble uses h_pulse2 */
645 pulse_start = 1 + h_sync_width + h_back_porch - 10;
646
647 tegra_dc_writel(dc, H_PULSE_2_ENABLE, DC_DISP_DISP_SIGNAL_OPTIONS0);
648
649 value = PULSE_MODE_NORMAL | PULSE_POLARITY_HIGH | PULSE_QUAL_VACTIVE |
650 PULSE_LAST_END_A;
651 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_CONTROL);
652
653 value = PULSE_START(pulse_start) | PULSE_END(pulse_start + 8);
654 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_POSITION_A);
655
656 value = VSYNC_WINDOW_END(0x210) | VSYNC_WINDOW_START(0x200) |
657 VSYNC_WINDOW_ENABLE;
658 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
659
660 if (dc->pipe)
661 value = HDMI_SRC_DISPLAYB;
662 else
663 value = HDMI_SRC_DISPLAYA;
664
665 if ((mode->hdisplay == 720) && ((mode->vdisplay == 480) ||
666 (mode->vdisplay == 576)))
667 tegra_hdmi_writel(hdmi,
668 value | ARM_VIDEO_RANGE_FULL,
669 HDMI_NV_PDISP_INPUT_CONTROL);
670 else
671 tegra_hdmi_writel(hdmi,
672 value | ARM_VIDEO_RANGE_LIMITED,
673 HDMI_NV_PDISP_INPUT_CONTROL);
674
675 div82 = clk_get_rate(hdmi->clk) / 1000000 * 4;
676 value = SOR_REFCLK_DIV_INT(div82 >> 2) | SOR_REFCLK_DIV_FRAC(div82);
677 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_REFCLK);
678
679 if (!hdmi->dvi) {
680 err = tegra_hdmi_setup_audio(hdmi, pclk);
681 if (err < 0)
682 hdmi->dvi = true;
683 }
684
685 if (of_device_is_compatible(node, "nvidia,tegra20-hdmi")) {
686 /*
687 * TODO: add ELD support
688 */
689 }
690
691 rekey = HDMI_REKEY_DEFAULT;
692 value = HDMI_CTRL_REKEY(rekey);
693 value |= HDMI_CTRL_MAX_AC_PACKET((h_sync_width + h_back_porch +
694 h_front_porch - rekey - 18) / 32);
695
696 if (!hdmi->dvi)
697 value |= HDMI_CTRL_ENABLE;
698
699 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_CTRL);
700
701 if (hdmi->dvi)
702 tegra_hdmi_writel(hdmi, 0x0,
703 HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
704 else
705 tegra_hdmi_writel(hdmi, GENERIC_CTRL_AUDIO,
706 HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
707
708 tegra_hdmi_setup_avi_infoframe(hdmi, mode);
709 tegra_hdmi_setup_audio_infoframe(hdmi);
710 tegra_hdmi_setup_stereo_infoframe(hdmi);
711
712 /* TMDS CONFIG */
713 if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
714 num_tmds = ARRAY_SIZE(tegra3_tmds_config);
715 tmds = tegra3_tmds_config;
716 } else {
717 num_tmds = ARRAY_SIZE(tegra2_tmds_config);
718 tmds = tegra2_tmds_config;
719 }
720
721 for (i = 0; i < num_tmds; i++) {
722 if (pclk <= tmds[i].pclk) {
723 tegra_hdmi_setup_tmds(hdmi, &tmds[i]);
724 break;
725 }
726 }
727
728 tegra_hdmi_writel(hdmi,
729 SOR_SEQ_CTL_PU_PC(0) |
730 SOR_SEQ_PU_PC_ALT(0) |
731 SOR_SEQ_PD_PC(8) |
732 SOR_SEQ_PD_PC_ALT(8),
733 HDMI_NV_PDISP_SOR_SEQ_CTL);
734
735 value = SOR_SEQ_INST_WAIT_TIME(1) |
736 SOR_SEQ_INST_WAIT_UNITS_VSYNC |
737 SOR_SEQ_INST_HALT |
738 SOR_SEQ_INST_PIN_A_LOW |
739 SOR_SEQ_INST_PIN_B_LOW |
740 SOR_SEQ_INST_DRIVE_PWM_OUT_LO;
741
742 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(0));
743 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(8));
744
745 value = 0x1c800;
746 value &= ~SOR_CSTM_ROTCLK(~0);
747 value |= SOR_CSTM_ROTCLK(2);
748 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_CSTM);
749
750 tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, DC_CMD_DISPLAY_COMMAND);
751 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
752 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
753
754 /* start SOR */
755 tegra_hdmi_writel(hdmi,
756 SOR_PWR_NORMAL_STATE_PU |
757 SOR_PWR_NORMAL_START_NORMAL |
758 SOR_PWR_SAFE_STATE_PD |
759 SOR_PWR_SETTING_NEW_TRIGGER,
760 HDMI_NV_PDISP_SOR_PWR);
761 tegra_hdmi_writel(hdmi,
762 SOR_PWR_NORMAL_STATE_PU |
763 SOR_PWR_NORMAL_START_NORMAL |
764 SOR_PWR_SAFE_STATE_PD |
765 SOR_PWR_SETTING_NEW_DONE,
766 HDMI_NV_PDISP_SOR_PWR);
767
768 do {
769 BUG_ON(--retries < 0);
770 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_SOR_PWR);
771 } while (value & SOR_PWR_SETTING_NEW_PENDING);
772
773 value = SOR_STATE_ASY_CRCMODE_COMPLETE |
774 SOR_STATE_ASY_OWNER_HEAD0 |
775 SOR_STATE_ASY_SUBOWNER_BOTH |
776 SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A |
777 SOR_STATE_ASY_DEPOL_POS;
778
779 /* setup sync polarities */
780 if (mode->flags & DRM_MODE_FLAG_PHSYNC)
781 value |= SOR_STATE_ASY_HSYNCPOL_POS;
782
783 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
784 value |= SOR_STATE_ASY_HSYNCPOL_NEG;
785
786 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
787 value |= SOR_STATE_ASY_VSYNCPOL_POS;
788
789 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
790 value |= SOR_STATE_ASY_VSYNCPOL_NEG;
791
792 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE2);
793
794 value = SOR_STATE_ASY_HEAD_OPMODE_AWAKE | SOR_STATE_ASY_ORMODE_NORMAL;
795 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE1);
796
797 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
798 tegra_hdmi_writel(hdmi, SOR_STATE_UPDATE, HDMI_NV_PDISP_SOR_STATE0);
799 tegra_hdmi_writel(hdmi, value | SOR_STATE_ATTACHED,
800 HDMI_NV_PDISP_SOR_STATE1);
801 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
802
803 tegra_dc_writel(dc, HDMI_ENABLE, DC_DISP_DISP_WIN_OPTIONS);
804
805 value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
806 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
807 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
808
809 value = DISP_CTRL_MODE_C_DISPLAY;
810 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
811
812 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
813 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
814
815 /* TODO: add HDCP support */
816
817 return 0;
818}
819
820static int tegra_output_hdmi_disable(struct tegra_output *output)
821{
822 struct tegra_hdmi *hdmi = to_hdmi(output);
823
824 tegra_periph_reset_assert(hdmi->clk);
825 clk_disable(hdmi->clk);
826 regulator_disable(hdmi->pll);
827 regulator_disable(hdmi->vdd);
828
829 return 0;
830}
831
832static int tegra_output_hdmi_setup_clock(struct tegra_output *output,
833 struct clk *clk, unsigned long pclk)
834{
835 struct tegra_hdmi *hdmi = to_hdmi(output);
836 struct clk *base;
837 int err;
838
839 err = clk_set_parent(clk, hdmi->clk_parent);
840 if (err < 0) {
841 dev_err(output->dev, "failed to set parent: %d\n", err);
842 return err;
843 }
844
845 base = clk_get_parent(hdmi->clk_parent);
846
847 /*
848 * This assumes that the parent clock is pll_d_out0 or pll_d2_out
849 * respectively, each of which divides the base pll_d by 2.
850 */
851 err = clk_set_rate(base, pclk * 2);
852 if (err < 0)
853 dev_err(output->dev,
854 "failed to set base clock rate to %lu Hz\n",
855 pclk * 2);
856
857 return 0;
858}
859
860static int tegra_output_hdmi_check_mode(struct tegra_output *output,
861 struct drm_display_mode *mode,
862 enum drm_mode_status *status)
863{
864 struct tegra_hdmi *hdmi = to_hdmi(output);
865 unsigned long pclk = mode->clock * 1000;
866 struct clk *parent;
867 long err;
868
869 parent = clk_get_parent(hdmi->clk_parent);
870
871 err = clk_round_rate(parent, pclk * 4);
872 if (err < 0)
873 *status = MODE_NOCLOCK;
874 else
875 *status = MODE_OK;
876
877 return 0;
878}
879
880static const struct tegra_output_ops hdmi_ops = {
881 .enable = tegra_output_hdmi_enable,
882 .disable = tegra_output_hdmi_disable,
883 .setup_clock = tegra_output_hdmi_setup_clock,
884 .check_mode = tegra_output_hdmi_check_mode,
885};
886
887static int tegra_hdmi_show_regs(struct seq_file *s, void *data)
888{
889 struct drm_info_node *node = s->private;
890 struct tegra_hdmi *hdmi = node->info_ent->data;
891 int err;
892
893 err = clk_enable(hdmi->clk);
894 if (err)
895 return err;
896
897#define DUMP_REG(name) \
898 seq_printf(s, "%-56s %#05x %08lx\n", #name, name, \
899 tegra_hdmi_readl(hdmi, name))
900
901 DUMP_REG(HDMI_CTXSW);
902 DUMP_REG(HDMI_NV_PDISP_SOR_STATE0);
903 DUMP_REG(HDMI_NV_PDISP_SOR_STATE1);
904 DUMP_REG(HDMI_NV_PDISP_SOR_STATE2);
905 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_MSB);
906 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_LSB);
907 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_MSB);
908 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_LSB);
909 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_MSB);
910 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_LSB);
911 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_MSB);
912 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_LSB);
913 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_MSB);
914 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_LSB);
915 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_MSB);
916 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_LSB);
917 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CTRL);
918 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CMODE);
919 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB);
920 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB);
921 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB);
922 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2);
923 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1);
924 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_RI);
925 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_MSB);
926 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_LSB);
927 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU0);
928 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0);
929 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU1);
930 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU2);
931 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
932 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS);
933 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER);
934 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW);
935 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH);
936 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
937 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS);
938 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER);
939 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW);
940 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH);
941 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW);
942 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH);
943 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
944 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_STATUS);
945 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_HEADER);
946 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW);
947 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH);
948 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW);
949 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH);
950 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW);
951 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH);
952 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW);
953 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH);
954 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_CTRL);
955 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW);
956 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH);
957 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
958 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
959 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW);
960 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH);
961 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW);
962 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH);
963 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW);
964 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH);
965 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW);
966 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH);
967 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW);
968 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH);
969 DUMP_REG(HDMI_NV_PDISP_HDMI_CTRL);
970 DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT);
971 DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
972 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_CTRL);
973 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_STATUS);
974 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_SUBPACK);
975 DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1);
976 DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2);
977 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU0);
978 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1);
979 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1_RDATA);
980 DUMP_REG(HDMI_NV_PDISP_HDMI_SPARE);
981 DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1);
982 DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2);
983 DUMP_REG(HDMI_NV_PDISP_HDMI_HDCPRIF_ROM_CTRL);
984 DUMP_REG(HDMI_NV_PDISP_SOR_CAP);
985 DUMP_REG(HDMI_NV_PDISP_SOR_PWR);
986 DUMP_REG(HDMI_NV_PDISP_SOR_TEST);
987 DUMP_REG(HDMI_NV_PDISP_SOR_PLL0);
988 DUMP_REG(HDMI_NV_PDISP_SOR_PLL1);
989 DUMP_REG(HDMI_NV_PDISP_SOR_PLL2);
990 DUMP_REG(HDMI_NV_PDISP_SOR_CSTM);
991 DUMP_REG(HDMI_NV_PDISP_SOR_LVDS);
992 DUMP_REG(HDMI_NV_PDISP_SOR_CRCA);
993 DUMP_REG(HDMI_NV_PDISP_SOR_CRCB);
994 DUMP_REG(HDMI_NV_PDISP_SOR_BLANK);
995 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_CTL);
996 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(0));
997 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(1));
998 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(2));
999 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(3));
1000 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(4));
1001 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(5));
1002 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(6));
1003 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(7));
1004 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(8));
1005 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(9));
1006 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(10));
1007 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(11));
1008 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(12));
1009 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(13));
1010 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(14));
1011 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(15));
1012 DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA0);
1013 DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA1);
1014 DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA0);
1015 DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA1);
1016 DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA0);
1017 DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA1);
1018 DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA0);
1019 DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA1);
1020 DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA0);
1021 DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA1);
1022 DUMP_REG(HDMI_NV_PDISP_SOR_TRIG);
1023 DUMP_REG(HDMI_NV_PDISP_SOR_MSCHECK);
1024 DUMP_REG(HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
1025 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG0);
1026 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG1);
1027 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG2);
1028 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(0));
1029 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(1));
1030 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(2));
1031 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(3));
1032 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(4));
1033 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(5));
1034 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(6));
1035 DUMP_REG(HDMI_NV_PDISP_AUDIO_PULSE_WIDTH);
1036 DUMP_REG(HDMI_NV_PDISP_AUDIO_THRESHOLD);
1037 DUMP_REG(HDMI_NV_PDISP_AUDIO_CNTRL0);
1038 DUMP_REG(HDMI_NV_PDISP_AUDIO_N);
1039 DUMP_REG(HDMI_NV_PDISP_HDCPRIF_ROM_TIMING);
1040 DUMP_REG(HDMI_NV_PDISP_SOR_REFCLK);
1041 DUMP_REG(HDMI_NV_PDISP_CRC_CONTROL);
1042 DUMP_REG(HDMI_NV_PDISP_INPUT_CONTROL);
1043 DUMP_REG(HDMI_NV_PDISP_SCRATCH);
1044 DUMP_REG(HDMI_NV_PDISP_PE_CURRENT);
1045 DUMP_REG(HDMI_NV_PDISP_KEY_CTRL);
1046 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG0);
1047 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG1);
1048 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG2);
1049 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_0);
1050 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_1);
1051 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_2);
1052 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_3);
1053 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG);
1054 DUMP_REG(HDMI_NV_PDISP_KEY_SKEY_INDEX);
1055 DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_CNTRL0);
1056 DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR);
1057 DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE);
1058
1059#undef DUMP_REG
1060
1061 clk_disable(hdmi->clk);
1062
1063 return 0;
1064}
1065
1066static struct drm_info_list debugfs_files[] = {
1067 { "regs", tegra_hdmi_show_regs, 0, NULL },
1068};
1069
1070static int tegra_hdmi_debugfs_init(struct tegra_hdmi *hdmi,
1071 struct drm_minor *minor)
1072{
1073 unsigned int i;
1074 int err;
1075
1076 hdmi->debugfs = debugfs_create_dir("hdmi", minor->debugfs_root);
1077 if (!hdmi->debugfs)
1078 return -ENOMEM;
1079
1080 hdmi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
1081 GFP_KERNEL);
1082 if (!hdmi->debugfs_files) {
1083 err = -ENOMEM;
1084 goto remove;
1085 }
1086
1087 for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
1088 hdmi->debugfs_files[i].data = hdmi;
1089
1090 err = drm_debugfs_create_files(hdmi->debugfs_files,
1091 ARRAY_SIZE(debugfs_files),
1092 hdmi->debugfs, minor);
1093 if (err < 0)
1094 goto free;
1095
1096 hdmi->minor = minor;
1097
1098 return 0;
1099
1100free:
1101 kfree(hdmi->debugfs_files);
1102 hdmi->debugfs_files = NULL;
1103remove:
1104 debugfs_remove(hdmi->debugfs);
1105 hdmi->debugfs = NULL;
1106
1107 return err;
1108}
1109
1110static int tegra_hdmi_debugfs_exit(struct tegra_hdmi *hdmi)
1111{
1112 drm_debugfs_remove_files(hdmi->debugfs_files, ARRAY_SIZE(debugfs_files),
1113 hdmi->minor);
1114 hdmi->minor = NULL;
1115
1116 kfree(hdmi->debugfs_files);
1117 hdmi->debugfs_files = NULL;
1118
1119 debugfs_remove(hdmi->debugfs);
1120 hdmi->debugfs = NULL;
1121
1122 return 0;
1123}
1124
1125static int tegra_hdmi_drm_init(struct host1x_client *client,
1126 struct drm_device *drm)
1127{
1128 struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
1129 int err;
1130
1131 hdmi->output.type = TEGRA_OUTPUT_HDMI;
1132 hdmi->output.dev = client->dev;
1133 hdmi->output.ops = &hdmi_ops;
1134
1135 err = tegra_output_init(drm, &hdmi->output);
1136 if (err < 0) {
1137 dev_err(client->dev, "output setup failed: %d\n", err);
1138 return err;
1139 }
1140
1141 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1142 err = tegra_hdmi_debugfs_init(hdmi, drm->primary);
1143 if (err < 0)
1144 dev_err(client->dev, "debugfs setup failed: %d\n", err);
1145 }
1146
1147 return 0;
1148}
1149
1150static int tegra_hdmi_drm_exit(struct host1x_client *client)
1151{
1152 struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
1153 int err;
1154
1155 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1156 err = tegra_hdmi_debugfs_exit(hdmi);
1157 if (err < 0)
1158 dev_err(client->dev, "debugfs cleanup failed: %d\n",
1159 err);
1160 }
1161
1162 err = tegra_output_disable(&hdmi->output);
1163 if (err < 0) {
1164 dev_err(client->dev, "output failed to disable: %d\n", err);
1165 return err;
1166 }
1167
1168 err = tegra_output_exit(&hdmi->output);
1169 if (err < 0) {
1170 dev_err(client->dev, "output cleanup failed: %d\n", err);
1171 return err;
1172 }
1173
1174 return 0;
1175}
1176
1177static const struct host1x_client_ops hdmi_client_ops = {
1178 .drm_init = tegra_hdmi_drm_init,
1179 .drm_exit = tegra_hdmi_drm_exit,
1180};
1181
1182static int tegra_hdmi_probe(struct platform_device *pdev)
1183{
1184 struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent);
1185 struct tegra_hdmi *hdmi;
1186 struct resource *regs;
1187 int err;
1188
1189 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
1190 if (!hdmi)
1191 return -ENOMEM;
1192
1193 hdmi->dev = &pdev->dev;
1194 hdmi->audio_source = AUTO;
1195 hdmi->audio_freq = 44100;
1196 hdmi->stereo = false;
1197 hdmi->dvi = false;
1198
1199 hdmi->clk = devm_clk_get(&pdev->dev, NULL);
1200 if (IS_ERR(hdmi->clk)) {
1201 dev_err(&pdev->dev, "failed to get clock\n");
1202 return PTR_ERR(hdmi->clk);
1203 }
1204
1205 err = clk_prepare(hdmi->clk);
1206 if (err < 0)
1207 return err;
1208
1209 hdmi->clk_parent = devm_clk_get(&pdev->dev, "parent");
1210 if (IS_ERR(hdmi->clk_parent))
1211 return PTR_ERR(hdmi->clk_parent);
1212
1213 err = clk_prepare(hdmi->clk_parent);
1214 if (err < 0)
1215 return err;
1216
1217 err = clk_set_parent(hdmi->clk, hdmi->clk_parent);
1218 if (err < 0) {
1219 dev_err(&pdev->dev, "failed to setup clocks: %d\n", err);
1220 return err;
1221 }
1222
1223 hdmi->vdd = devm_regulator_get(&pdev->dev, "vdd");
1224 if (IS_ERR(hdmi->vdd)) {
1225 dev_err(&pdev->dev, "failed to get VDD regulator\n");
1226 return PTR_ERR(hdmi->vdd);
1227 }
1228
1229 hdmi->pll = devm_regulator_get(&pdev->dev, "pll");
1230 if (IS_ERR(hdmi->pll)) {
1231 dev_err(&pdev->dev, "failed to get PLL regulator\n");
1232 return PTR_ERR(hdmi->pll);
1233 }
1234
1235 hdmi->output.dev = &pdev->dev;
1236
1237 err = tegra_output_parse_dt(&hdmi->output);
1238 if (err < 0)
1239 return err;
1240
1241 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1242 if (!regs)
1243 return -ENXIO;
1244
1245 hdmi->regs = devm_ioremap_resource(&pdev->dev, regs);
1246 if (IS_ERR(hdmi->regs))
1247 return PTR_ERR(hdmi->regs);
1248
1249 err = platform_get_irq(pdev, 0);
1250 if (err < 0)
1251 return err;
1252
1253 hdmi->irq = err;
1254
1255 hdmi->client.ops = &hdmi_client_ops;
1256 INIT_LIST_HEAD(&hdmi->client.list);
1257 hdmi->client.dev = &pdev->dev;
1258
1259 err = host1x_register_client(host1x, &hdmi->client);
1260 if (err < 0) {
1261 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1262 err);
1263 return err;
1264 }
1265
1266 platform_set_drvdata(pdev, hdmi);
1267
1268 return 0;
1269}
1270
1271static int tegra_hdmi_remove(struct platform_device *pdev)
1272{
1273 struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent);
1274 struct tegra_hdmi *hdmi = platform_get_drvdata(pdev);
1275 int err;
1276
1277 err = host1x_unregister_client(host1x, &hdmi->client);
1278 if (err < 0) {
1279 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1280 err);
1281 return err;
1282 }
1283
1284 clk_unprepare(hdmi->clk_parent);
1285 clk_unprepare(hdmi->clk);
1286
1287 return 0;
1288}
1289
1290static struct of_device_id tegra_hdmi_of_match[] = {
1291 { .compatible = "nvidia,tegra30-hdmi", },
1292 { .compatible = "nvidia,tegra20-hdmi", },
1293 { },
1294};
1295
1296struct platform_driver tegra_hdmi_driver = {
1297 .driver = {
1298 .name = "tegra-hdmi",
1299 .owner = THIS_MODULE,
1300 .of_match_table = tegra_hdmi_of_match,
1301 },
1302 .probe = tegra_hdmi_probe,
1303 .remove = tegra_hdmi_remove,
1304};
diff --git a/drivers/gpu/host1x/drm/hdmi.h b/drivers/gpu/host1x/drm/hdmi.h
deleted file mode 100644
index 52ac36e08ccb..000000000000
--- a/drivers/gpu/host1x/drm/hdmi.h
+++ /dev/null
@@ -1,386 +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#ifndef TEGRA_HDMI_H
11#define TEGRA_HDMI_H 1
12
13/* register definitions */
14#define HDMI_CTXSW 0x00
15
16#define HDMI_NV_PDISP_SOR_STATE0 0x01
17#define SOR_STATE_UPDATE (1 << 0)
18
19#define HDMI_NV_PDISP_SOR_STATE1 0x02
20#define SOR_STATE_ASY_HEAD_OPMODE_AWAKE (2 << 0)
21#define SOR_STATE_ASY_ORMODE_NORMAL (1 << 2)
22#define SOR_STATE_ATTACHED (1 << 3)
23
24#define HDMI_NV_PDISP_SOR_STATE2 0x03
25#define SOR_STATE_ASY_OWNER_NONE (0 << 0)
26#define SOR_STATE_ASY_OWNER_HEAD0 (1 << 0)
27#define SOR_STATE_ASY_SUBOWNER_NONE (0 << 4)
28#define SOR_STATE_ASY_SUBOWNER_SUBHEAD0 (1 << 4)
29#define SOR_STATE_ASY_SUBOWNER_SUBHEAD1 (2 << 4)
30#define SOR_STATE_ASY_SUBOWNER_BOTH (3 << 4)
31#define SOR_STATE_ASY_CRCMODE_ACTIVE (0 << 6)
32#define SOR_STATE_ASY_CRCMODE_COMPLETE (1 << 6)
33#define SOR_STATE_ASY_CRCMODE_NON_ACTIVE (2 << 6)
34#define SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A (1 << 8)
35#define SOR_STATE_ASY_PROTOCOL_CUSTOM (15 << 8)
36#define SOR_STATE_ASY_HSYNCPOL_POS (0 << 12)
37#define SOR_STATE_ASY_HSYNCPOL_NEG (1 << 12)
38#define SOR_STATE_ASY_VSYNCPOL_POS (0 << 13)
39#define SOR_STATE_ASY_VSYNCPOL_NEG (1 << 13)
40#define SOR_STATE_ASY_DEPOL_POS (0 << 14)
41#define SOR_STATE_ASY_DEPOL_NEG (1 << 14)
42
43#define HDMI_NV_PDISP_RG_HDCP_AN_MSB 0x04
44#define HDMI_NV_PDISP_RG_HDCP_AN_LSB 0x05
45#define HDMI_NV_PDISP_RG_HDCP_CN_MSB 0x06
46#define HDMI_NV_PDISP_RG_HDCP_CN_LSB 0x07
47#define HDMI_NV_PDISP_RG_HDCP_AKSV_MSB 0x08
48#define HDMI_NV_PDISP_RG_HDCP_AKSV_LSB 0x09
49#define HDMI_NV_PDISP_RG_HDCP_BKSV_MSB 0x0a
50#define HDMI_NV_PDISP_RG_HDCP_BKSV_LSB 0x0b
51#define HDMI_NV_PDISP_RG_HDCP_CKSV_MSB 0x0c
52#define HDMI_NV_PDISP_RG_HDCP_CKSV_LSB 0x0d
53#define HDMI_NV_PDISP_RG_HDCP_DKSV_MSB 0x0e
54#define HDMI_NV_PDISP_RG_HDCP_DKSV_LSB 0x0f
55#define HDMI_NV_PDISP_RG_HDCP_CTRL 0x10
56#define HDMI_NV_PDISP_RG_HDCP_CMODE 0x11
57#define HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB 0x12
58#define HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB 0x13
59#define HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB 0x14
60#define HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2 0x15
61#define HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1 0x16
62#define HDMI_NV_PDISP_RG_HDCP_RI 0x17
63#define HDMI_NV_PDISP_RG_HDCP_CS_MSB 0x18
64#define HDMI_NV_PDISP_RG_HDCP_CS_LSB 0x19
65#define HDMI_NV_PDISP_HDMI_AUDIO_EMU0 0x1a
66#define HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0 0x1b
67#define HDMI_NV_PDISP_HDMI_AUDIO_EMU1 0x1c
68#define HDMI_NV_PDISP_HDMI_AUDIO_EMU2 0x1d
69
70#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL 0x1e
71#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS 0x1f
72#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER 0x20
73#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW 0x21
74#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH 0x22
75#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL 0x23
76#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS 0x24
77#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER 0x25
78#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW 0x26
79#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH 0x27
80#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW 0x28
81#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH 0x29
82
83#define INFOFRAME_CTRL_ENABLE (1 << 0)
84
85#define INFOFRAME_HEADER_TYPE(x) (((x) & 0xff) << 0)
86#define INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) << 8)
87#define INFOFRAME_HEADER_LEN(x) (((x) & 0x0f) << 16)
88
89#define HDMI_NV_PDISP_HDMI_GENERIC_CTRL 0x2a
90#define GENERIC_CTRL_ENABLE (1 << 0)
91#define GENERIC_CTRL_OTHER (1 << 4)
92#define GENERIC_CTRL_SINGLE (1 << 8)
93#define GENERIC_CTRL_HBLANK (1 << 12)
94#define GENERIC_CTRL_AUDIO (1 << 16)
95
96#define HDMI_NV_PDISP_HDMI_GENERIC_STATUS 0x2b
97#define HDMI_NV_PDISP_HDMI_GENERIC_HEADER 0x2c
98#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW 0x2d
99#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH 0x2e
100#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW 0x2f
101#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH 0x30
102#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW 0x31
103#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH 0x32
104#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW 0x33
105#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH 0x34
106
107#define HDMI_NV_PDISP_HDMI_ACR_CTRL 0x35
108#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW 0x36
109#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH 0x37
110#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW 0x38
111#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH 0x39
112#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW 0x3a
113#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH 0x3b
114#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW 0x3c
115#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH 0x3d
116#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW 0x3e
117#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH 0x3f
118#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW 0x40
119#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH 0x41
120#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW 0x42
121#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH 0x43
122
123#define ACR_SUBPACK_CTS(x) (((x) & 0xffffff) << 8)
124#define ACR_SUBPACK_N(x) (((x) & 0xffffff) << 0)
125#define ACR_ENABLE (1 << 31)
126
127#define HDMI_NV_PDISP_HDMI_CTRL 0x44
128#define HDMI_CTRL_REKEY(x) (((x) & 0x7f) << 0)
129#define HDMI_CTRL_MAX_AC_PACKET(x) (((x) & 0x1f) << 16)
130#define HDMI_CTRL_ENABLE (1 << 30)
131
132#define HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT 0x45
133#define HDMI_NV_PDISP_HDMI_VSYNC_WINDOW 0x46
134#define VSYNC_WINDOW_END(x) (((x) & 0x3ff) << 0)
135#define VSYNC_WINDOW_START(x) (((x) & 0x3ff) << 16)
136#define VSYNC_WINDOW_ENABLE (1 << 31)
137
138#define HDMI_NV_PDISP_HDMI_GCP_CTRL 0x47
139#define HDMI_NV_PDISP_HDMI_GCP_STATUS 0x48
140#define HDMI_NV_PDISP_HDMI_GCP_SUBPACK 0x49
141#define HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1 0x4a
142#define HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2 0x4b
143#define HDMI_NV_PDISP_HDMI_EMU0 0x4c
144#define HDMI_NV_PDISP_HDMI_EMU1 0x4d
145#define HDMI_NV_PDISP_HDMI_EMU1_RDATA 0x4e
146
147#define HDMI_NV_PDISP_HDMI_SPARE 0x4f
148#define SPARE_HW_CTS (1 << 0)
149#define SPARE_FORCE_SW_CTS (1 << 1)
150#define SPARE_CTS_RESET_VAL(x) (((x) & 0x7) << 16)
151
152#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1 0x50
153#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2 0x51
154#define HDMI_NV_PDISP_HDMI_HDCPRIF_ROM_CTRL 0x53
155#define HDMI_NV_PDISP_SOR_CAP 0x54
156#define HDMI_NV_PDISP_SOR_PWR 0x55
157#define SOR_PWR_NORMAL_STATE_PD (0 << 0)
158#define SOR_PWR_NORMAL_STATE_PU (1 << 0)
159#define SOR_PWR_NORMAL_START_NORMAL (0 << 1)
160#define SOR_PWR_NORMAL_START_ALT (1 << 1)
161#define SOR_PWR_SAFE_STATE_PD (0 << 16)
162#define SOR_PWR_SAFE_STATE_PU (1 << 16)
163#define SOR_PWR_SETTING_NEW_DONE (0 << 31)
164#define SOR_PWR_SETTING_NEW_PENDING (1 << 31)
165#define SOR_PWR_SETTING_NEW_TRIGGER (1 << 31)
166
167#define HDMI_NV_PDISP_SOR_TEST 0x56
168#define HDMI_NV_PDISP_SOR_PLL0 0x57
169#define SOR_PLL_PWR (1 << 0)
170#define SOR_PLL_PDBG (1 << 1)
171#define SOR_PLL_VCAPD (1 << 2)
172#define SOR_PLL_PDPORT (1 << 3)
173#define SOR_PLL_RESISTORSEL (1 << 4)
174#define SOR_PLL_PULLDOWN (1 << 5)
175#define SOR_PLL_VCOCAP(x) (((x) & 0xf) << 8)
176#define SOR_PLL_BG_V17_S(x) (((x) & 0xf) << 12)
177#define SOR_PLL_FILTER(x) (((x) & 0xf) << 16)
178#define SOR_PLL_ICHPMP(x) (((x) & 0xf) << 24)
179#define SOR_PLL_TX_REG_LOAD(x) (((x) & 0xf) << 28)
180
181#define HDMI_NV_PDISP_SOR_PLL1 0x58
182#define SOR_PLL_TMDS_TERM_ENABLE (1 << 8)
183#define SOR_PLL_TMDS_TERMADJ(x) (((x) & 0xf) << 9)
184#define SOR_PLL_LOADADJ(x) (((x) & 0xf) << 20)
185#define SOR_PLL_PE_EN (1 << 28)
186#define SOR_PLL_HALF_FULL_PE (1 << 29)
187#define SOR_PLL_S_D_PIN_PE (1 << 30)
188
189#define HDMI_NV_PDISP_SOR_PLL2 0x59
190
191#define HDMI_NV_PDISP_SOR_CSTM 0x5a
192#define SOR_CSTM_ROTCLK(x) (((x) & 0xf) << 24)
193
194#define HDMI_NV_PDISP_SOR_LVDS 0x5b
195#define HDMI_NV_PDISP_SOR_CRCA 0x5c
196#define HDMI_NV_PDISP_SOR_CRCB 0x5d
197#define HDMI_NV_PDISP_SOR_BLANK 0x5e
198#define HDMI_NV_PDISP_SOR_SEQ_CTL 0x5f
199#define SOR_SEQ_CTL_PU_PC(x) (((x) & 0xf) << 0)
200#define SOR_SEQ_PU_PC_ALT(x) (((x) & 0xf) << 4)
201#define SOR_SEQ_PD_PC(x) (((x) & 0xf) << 8)
202#define SOR_SEQ_PD_PC_ALT(x) (((x) & 0xf) << 12)
203#define SOR_SEQ_PC(x) (((x) & 0xf) << 16)
204#define SOR_SEQ_STATUS (1 << 28)
205#define SOR_SEQ_SWITCH (1 << 30)
206
207#define HDMI_NV_PDISP_SOR_SEQ_INST(x) (0x60 + (x))
208
209#define SOR_SEQ_INST_WAIT_TIME(x) (((x) & 0x3ff) << 0)
210#define SOR_SEQ_INST_WAIT_UNITS_VSYNC (2 << 12)
211#define SOR_SEQ_INST_HALT (1 << 15)
212#define SOR_SEQ_INST_PIN_A_LOW (0 << 21)
213#define SOR_SEQ_INST_PIN_A_HIGH (1 << 21)
214#define SOR_SEQ_INST_PIN_B_LOW (0 << 22)
215#define SOR_SEQ_INST_PIN_B_HIGH (1 << 22)
216#define SOR_SEQ_INST_DRIVE_PWM_OUT_LO (1 << 23)
217
218#define HDMI_NV_PDISP_SOR_VCRCA0 0x72
219#define HDMI_NV_PDISP_SOR_VCRCA1 0x73
220#define HDMI_NV_PDISP_SOR_CCRCA0 0x74
221#define HDMI_NV_PDISP_SOR_CCRCA1 0x75
222#define HDMI_NV_PDISP_SOR_EDATAA0 0x76
223#define HDMI_NV_PDISP_SOR_EDATAA1 0x77
224#define HDMI_NV_PDISP_SOR_COUNTA0 0x78
225#define HDMI_NV_PDISP_SOR_COUNTA1 0x79
226#define HDMI_NV_PDISP_SOR_DEBUGA0 0x7a
227#define HDMI_NV_PDISP_SOR_DEBUGA1 0x7b
228#define HDMI_NV_PDISP_SOR_TRIG 0x7c
229#define HDMI_NV_PDISP_SOR_MSCHECK 0x7d
230
231#define HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT 0x7e
232#define DRIVE_CURRENT_LANE0(x) (((x) & 0x3f) << 0)
233#define DRIVE_CURRENT_LANE1(x) (((x) & 0x3f) << 8)
234#define DRIVE_CURRENT_LANE2(x) (((x) & 0x3f) << 16)
235#define DRIVE_CURRENT_LANE3(x) (((x) & 0x3f) << 24)
236#define DRIVE_CURRENT_FUSE_OVERRIDE (1 << 31)
237
238#define DRIVE_CURRENT_1_500_mA 0x00
239#define DRIVE_CURRENT_1_875_mA 0x01
240#define DRIVE_CURRENT_2_250_mA 0x02
241#define DRIVE_CURRENT_2_625_mA 0x03
242#define DRIVE_CURRENT_3_000_mA 0x04
243#define DRIVE_CURRENT_3_375_mA 0x05
244#define DRIVE_CURRENT_3_750_mA 0x06
245#define DRIVE_CURRENT_4_125_mA 0x07
246#define DRIVE_CURRENT_4_500_mA 0x08
247#define DRIVE_CURRENT_4_875_mA 0x09
248#define DRIVE_CURRENT_5_250_mA 0x0a
249#define DRIVE_CURRENT_5_625_mA 0x0b
250#define DRIVE_CURRENT_6_000_mA 0x0c
251#define DRIVE_CURRENT_6_375_mA 0x0d
252#define DRIVE_CURRENT_6_750_mA 0x0e
253#define DRIVE_CURRENT_7_125_mA 0x0f
254#define DRIVE_CURRENT_7_500_mA 0x10
255#define DRIVE_CURRENT_7_875_mA 0x11
256#define DRIVE_CURRENT_8_250_mA 0x12
257#define DRIVE_CURRENT_8_625_mA 0x13
258#define DRIVE_CURRENT_9_000_mA 0x14
259#define DRIVE_CURRENT_9_375_mA 0x15
260#define DRIVE_CURRENT_9_750_mA 0x16
261#define DRIVE_CURRENT_10_125_mA 0x17
262#define DRIVE_CURRENT_10_500_mA 0x18
263#define DRIVE_CURRENT_10_875_mA 0x19
264#define DRIVE_CURRENT_11_250_mA 0x1a
265#define DRIVE_CURRENT_11_625_mA 0x1b
266#define DRIVE_CURRENT_12_000_mA 0x1c
267#define DRIVE_CURRENT_12_375_mA 0x1d
268#define DRIVE_CURRENT_12_750_mA 0x1e
269#define DRIVE_CURRENT_13_125_mA 0x1f
270#define DRIVE_CURRENT_13_500_mA 0x20
271#define DRIVE_CURRENT_13_875_mA 0x21
272#define DRIVE_CURRENT_14_250_mA 0x22
273#define DRIVE_CURRENT_14_625_mA 0x23
274#define DRIVE_CURRENT_15_000_mA 0x24
275#define DRIVE_CURRENT_15_375_mA 0x25
276#define DRIVE_CURRENT_15_750_mA 0x26
277#define DRIVE_CURRENT_16_125_mA 0x27
278#define DRIVE_CURRENT_16_500_mA 0x28
279#define DRIVE_CURRENT_16_875_mA 0x29
280#define DRIVE_CURRENT_17_250_mA 0x2a
281#define DRIVE_CURRENT_17_625_mA 0x2b
282#define DRIVE_CURRENT_18_000_mA 0x2c
283#define DRIVE_CURRENT_18_375_mA 0x2d
284#define DRIVE_CURRENT_18_750_mA 0x2e
285#define DRIVE_CURRENT_19_125_mA 0x2f
286#define DRIVE_CURRENT_19_500_mA 0x30
287#define DRIVE_CURRENT_19_875_mA 0x31
288#define DRIVE_CURRENT_20_250_mA 0x32
289#define DRIVE_CURRENT_20_625_mA 0x33
290#define DRIVE_CURRENT_21_000_mA 0x34
291#define DRIVE_CURRENT_21_375_mA 0x35
292#define DRIVE_CURRENT_21_750_mA 0x36
293#define DRIVE_CURRENT_22_125_mA 0x37
294#define DRIVE_CURRENT_22_500_mA 0x38
295#define DRIVE_CURRENT_22_875_mA 0x39
296#define DRIVE_CURRENT_23_250_mA 0x3a
297#define DRIVE_CURRENT_23_625_mA 0x3b
298#define DRIVE_CURRENT_24_000_mA 0x3c
299#define DRIVE_CURRENT_24_375_mA 0x3d
300#define DRIVE_CURRENT_24_750_mA 0x3e
301
302#define HDMI_NV_PDISP_AUDIO_DEBUG0 0x7f
303#define HDMI_NV_PDISP_AUDIO_DEBUG1 0x80
304#define HDMI_NV_PDISP_AUDIO_DEBUG2 0x81
305
306#define HDMI_NV_PDISP_AUDIO_FS(x) (0x82 + (x))
307#define AUDIO_FS_LOW(x) (((x) & 0xfff) << 0)
308#define AUDIO_FS_HIGH(x) (((x) & 0xfff) << 16)
309
310#define HDMI_NV_PDISP_AUDIO_PULSE_WIDTH 0x89
311#define HDMI_NV_PDISP_AUDIO_THRESHOLD 0x8a
312#define HDMI_NV_PDISP_AUDIO_CNTRL0 0x8b
313#define AUDIO_CNTRL0_ERROR_TOLERANCE(x) (((x) & 0xff) << 0)
314#define AUDIO_CNTRL0_SOURCE_SELECT_AUTO (0 << 20)
315#define AUDIO_CNTRL0_SOURCE_SELECT_SPDIF (1 << 20)
316#define AUDIO_CNTRL0_SOURCE_SELECT_HDAL (2 << 20)
317#define AUDIO_CNTRL0_FRAMES_PER_BLOCK(x) (((x) & 0xff) << 24)
318
319#define HDMI_NV_PDISP_AUDIO_N 0x8c
320#define AUDIO_N_VALUE(x) (((x) & 0xfffff) << 0)
321#define AUDIO_N_RESETF (1 << 20)
322#define AUDIO_N_GENERATE_NORMAL (0 << 24)
323#define AUDIO_N_GENERATE_ALTERNATE (1 << 24)
324
325#define HDMI_NV_PDISP_HDCPRIF_ROM_TIMING 0x94
326#define HDMI_NV_PDISP_SOR_REFCLK 0x95
327#define SOR_REFCLK_DIV_INT(x) (((x) & 0xff) << 8)
328#define SOR_REFCLK_DIV_FRAC(x) (((x) & 0x03) << 6)
329
330#define HDMI_NV_PDISP_CRC_CONTROL 0x96
331#define HDMI_NV_PDISP_INPUT_CONTROL 0x97
332#define HDMI_SRC_DISPLAYA (0 << 0)
333#define HDMI_SRC_DISPLAYB (1 << 0)
334#define ARM_VIDEO_RANGE_FULL (0 << 1)
335#define ARM_VIDEO_RANGE_LIMITED (1 << 1)
336
337#define HDMI_NV_PDISP_SCRATCH 0x98
338#define HDMI_NV_PDISP_PE_CURRENT 0x99
339#define PE_CURRENT0(x) (((x) & 0xf) << 0)
340#define PE_CURRENT1(x) (((x) & 0xf) << 8)
341#define PE_CURRENT2(x) (((x) & 0xf) << 16)
342#define PE_CURRENT3(x) (((x) & 0xf) << 24)
343
344#define PE_CURRENT_0_0_mA 0x0
345#define PE_CURRENT_0_5_mA 0x1
346#define PE_CURRENT_1_0_mA 0x2
347#define PE_CURRENT_1_5_mA 0x3
348#define PE_CURRENT_2_0_mA 0x4
349#define PE_CURRENT_2_5_mA 0x5
350#define PE_CURRENT_3_0_mA 0x6
351#define PE_CURRENT_3_5_mA 0x7
352#define PE_CURRENT_4_0_mA 0x8
353#define PE_CURRENT_4_5_mA 0x9
354#define PE_CURRENT_5_0_mA 0xa
355#define PE_CURRENT_5_5_mA 0xb
356#define PE_CURRENT_6_0_mA 0xc
357#define PE_CURRENT_6_5_mA 0xd
358#define PE_CURRENT_7_0_mA 0xe
359#define PE_CURRENT_7_5_mA 0xf
360
361#define HDMI_NV_PDISP_KEY_CTRL 0x9a
362#define HDMI_NV_PDISP_KEY_DEBUG0 0x9b
363#define HDMI_NV_PDISP_KEY_DEBUG1 0x9c
364#define HDMI_NV_PDISP_KEY_DEBUG2 0x9d
365#define HDMI_NV_PDISP_KEY_HDCP_KEY_0 0x9e
366#define HDMI_NV_PDISP_KEY_HDCP_KEY_1 0x9f
367#define HDMI_NV_PDISP_KEY_HDCP_KEY_2 0xa0
368#define HDMI_NV_PDISP_KEY_HDCP_KEY_3 0xa1
369#define HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG 0xa2
370#define HDMI_NV_PDISP_KEY_SKEY_INDEX 0xa3
371
372#define HDMI_NV_PDISP_SOR_AUDIO_CNTRL0 0xac
373#define AUDIO_CNTRL0_INJECT_NULLSMPL (1 << 29)
374#define HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR 0xbc
375#define HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE 0xbd
376
377#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320 0xbf
378#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441 0xc0
379#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882 0xc1
380#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764 0xc2
381#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480 0xc3
382#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960 0xc4
383#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920 0xc5
384#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_DEFAULT 0xc5
385
386#endif /* TEGRA_HDMI_H */
diff --git a/drivers/gpu/host1x/drm/output.c b/drivers/gpu/host1x/drm/output.c
deleted file mode 100644
index 137ae81ab80e..000000000000
--- a/drivers/gpu/host1x/drm/output.c
+++ /dev/null
@@ -1,272 +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/module.h>
11#include <linux/of_gpio.h>
12#include <linux/i2c.h>
13
14#include "drm.h"
15
16static int tegra_connector_get_modes(struct drm_connector *connector)
17{
18 struct tegra_output *output = connector_to_output(connector);
19 struct edid *edid = NULL;
20 int err = 0;
21
22 if (output->edid)
23 edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL);
24 else if (output->ddc)
25 edid = drm_get_edid(connector, output->ddc);
26
27 drm_mode_connector_update_edid_property(connector, edid);
28
29 if (edid) {
30 err = drm_add_edid_modes(connector, edid);
31 kfree(edid);
32 }
33
34 return err;
35}
36
37static int tegra_connector_mode_valid(struct drm_connector *connector,
38 struct drm_display_mode *mode)
39{
40 struct tegra_output *output = connector_to_output(connector);
41 enum drm_mode_status status = MODE_OK;
42 int err;
43
44 err = tegra_output_check_mode(output, mode, &status);
45 if (err < 0)
46 return MODE_ERROR;
47
48 return status;
49}
50
51static struct drm_encoder *
52tegra_connector_best_encoder(struct drm_connector *connector)
53{
54 struct tegra_output *output = connector_to_output(connector);
55
56 return &output->encoder;
57}
58
59static const struct drm_connector_helper_funcs connector_helper_funcs = {
60 .get_modes = tegra_connector_get_modes,
61 .mode_valid = tegra_connector_mode_valid,
62 .best_encoder = tegra_connector_best_encoder,
63};
64
65static enum drm_connector_status
66tegra_connector_detect(struct drm_connector *connector, bool force)
67{
68 struct tegra_output *output = connector_to_output(connector);
69 enum drm_connector_status status = connector_status_unknown;
70
71 if (gpio_is_valid(output->hpd_gpio)) {
72 if (gpio_get_value(output->hpd_gpio) == 0)
73 status = connector_status_disconnected;
74 else
75 status = connector_status_connected;
76 } else {
77 if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
78 status = connector_status_connected;
79 }
80
81 return status;
82}
83
84static void tegra_connector_destroy(struct drm_connector *connector)
85{
86 drm_sysfs_connector_remove(connector);
87 drm_connector_cleanup(connector);
88}
89
90static const struct drm_connector_funcs connector_funcs = {
91 .dpms = drm_helper_connector_dpms,
92 .detect = tegra_connector_detect,
93 .fill_modes = drm_helper_probe_single_connector_modes,
94 .destroy = tegra_connector_destroy,
95};
96
97static void tegra_encoder_destroy(struct drm_encoder *encoder)
98{
99 drm_encoder_cleanup(encoder);
100}
101
102static const struct drm_encoder_funcs encoder_funcs = {
103 .destroy = tegra_encoder_destroy,
104};
105
106static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode)
107{
108}
109
110static bool tegra_encoder_mode_fixup(struct drm_encoder *encoder,
111 const struct drm_display_mode *mode,
112 struct drm_display_mode *adjusted)
113{
114 return true;
115}
116
117static void tegra_encoder_prepare(struct drm_encoder *encoder)
118{
119}
120
121static void tegra_encoder_commit(struct drm_encoder *encoder)
122{
123}
124
125static void tegra_encoder_mode_set(struct drm_encoder *encoder,
126 struct drm_display_mode *mode,
127 struct drm_display_mode *adjusted)
128{
129 struct tegra_output *output = encoder_to_output(encoder);
130 int err;
131
132 err = tegra_output_enable(output);
133 if (err < 0)
134 dev_err(encoder->dev->dev, "tegra_output_enable(): %d\n", err);
135}
136
137static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
138 .dpms = tegra_encoder_dpms,
139 .mode_fixup = tegra_encoder_mode_fixup,
140 .prepare = tegra_encoder_prepare,
141 .commit = tegra_encoder_commit,
142 .mode_set = tegra_encoder_mode_set,
143};
144
145static irqreturn_t hpd_irq(int irq, void *data)
146{
147 struct tegra_output *output = data;
148
149 drm_helper_hpd_irq_event(output->connector.dev);
150
151 return IRQ_HANDLED;
152}
153
154int tegra_output_parse_dt(struct tegra_output *output)
155{
156 enum of_gpio_flags flags;
157 struct device_node *ddc;
158 size_t size;
159 int err;
160
161 if (!output->of_node)
162 output->of_node = output->dev->of_node;
163
164 output->edid = of_get_property(output->of_node, "nvidia,edid", &size);
165
166 ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0);
167 if (ddc) {
168 output->ddc = of_find_i2c_adapter_by_node(ddc);
169 if (!output->ddc) {
170 err = -EPROBE_DEFER;
171 of_node_put(ddc);
172 return err;
173 }
174
175 of_node_put(ddc);
176 }
177
178 if (!output->edid && !output->ddc)
179 return -ENODEV;
180
181 output->hpd_gpio = of_get_named_gpio_flags(output->of_node,
182 "nvidia,hpd-gpio", 0,
183 &flags);
184
185 return 0;
186}
187
188int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
189{
190 int connector, encoder, err;
191
192 if (gpio_is_valid(output->hpd_gpio)) {
193 unsigned long flags;
194
195 err = gpio_request_one(output->hpd_gpio, GPIOF_DIR_IN,
196 "HDMI hotplug detect");
197 if (err < 0) {
198 dev_err(output->dev, "gpio_request_one(): %d\n", err);
199 return err;
200 }
201
202 err = gpio_to_irq(output->hpd_gpio);
203 if (err < 0) {
204 dev_err(output->dev, "gpio_to_irq(): %d\n", err);
205 goto free_hpd;
206 }
207
208 output->hpd_irq = err;
209
210 flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
211 IRQF_ONESHOT;
212
213 err = request_threaded_irq(output->hpd_irq, NULL, hpd_irq,
214 flags, "hpd", output);
215 if (err < 0) {
216 dev_err(output->dev, "failed to request IRQ#%u: %d\n",
217 output->hpd_irq, err);
218 goto free_hpd;
219 }
220
221 output->connector.polled = DRM_CONNECTOR_POLL_HPD;
222 }
223
224 switch (output->type) {
225 case TEGRA_OUTPUT_RGB:
226 connector = DRM_MODE_CONNECTOR_LVDS;
227 encoder = DRM_MODE_ENCODER_LVDS;
228 break;
229
230 case TEGRA_OUTPUT_HDMI:
231 connector = DRM_MODE_CONNECTOR_HDMIA;
232 encoder = DRM_MODE_ENCODER_TMDS;
233 break;
234
235 default:
236 connector = DRM_MODE_CONNECTOR_Unknown;
237 encoder = DRM_MODE_ENCODER_NONE;
238 break;
239 }
240
241 drm_connector_init(drm, &output->connector, &connector_funcs,
242 connector);
243 drm_connector_helper_add(&output->connector, &connector_helper_funcs);
244
245 drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder);
246 drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs);
247
248 drm_mode_connector_attach_encoder(&output->connector, &output->encoder);
249 drm_sysfs_connector_add(&output->connector);
250
251 output->encoder.possible_crtcs = 0x3;
252
253 return 0;
254
255free_hpd:
256 gpio_free(output->hpd_gpio);
257
258 return err;
259}
260
261int tegra_output_exit(struct tegra_output *output)
262{
263 if (gpio_is_valid(output->hpd_gpio)) {
264 free_irq(output->hpd_irq, output);
265 gpio_free(output->hpd_gpio);
266 }
267
268 if (output->ddc)
269 put_device(&output->ddc->dev);
270
271 return 0;
272}
diff --git a/drivers/gpu/host1x/drm/rgb.c b/drivers/gpu/host1x/drm/rgb.c
deleted file mode 100644
index 5aa66ef7a946..000000000000
--- a/drivers/gpu/host1x/drm/rgb.c
+++ /dev/null
@@ -1,228 +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/module.h>
12#include <linux/of.h>
13#include <linux/platform_device.h>
14
15#include "drm.h"
16#include "dc.h"
17
18struct tegra_rgb {
19 struct tegra_output output;
20 struct clk *clk_parent;
21 struct clk *clk;
22};
23
24static inline struct tegra_rgb *to_rgb(struct tegra_output *output)
25{
26 return container_of(output, struct tegra_rgb, output);
27}
28
29struct reg_entry {
30 unsigned long offset;
31 unsigned long value;
32};
33
34static const struct reg_entry rgb_enable[] = {
35 { DC_COM_PIN_OUTPUT_ENABLE(0), 0x00000000 },
36 { DC_COM_PIN_OUTPUT_ENABLE(1), 0x00000000 },
37 { DC_COM_PIN_OUTPUT_ENABLE(2), 0x00000000 },
38 { DC_COM_PIN_OUTPUT_ENABLE(3), 0x00000000 },
39 { DC_COM_PIN_OUTPUT_POLARITY(0), 0x00000000 },
40 { DC_COM_PIN_OUTPUT_POLARITY(1), 0x01000000 },
41 { DC_COM_PIN_OUTPUT_POLARITY(2), 0x00000000 },
42 { DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000000 },
43 { DC_COM_PIN_OUTPUT_DATA(0), 0x00000000 },
44 { DC_COM_PIN_OUTPUT_DATA(1), 0x00000000 },
45 { DC_COM_PIN_OUTPUT_DATA(2), 0x00000000 },
46 { DC_COM_PIN_OUTPUT_DATA(3), 0x00000000 },
47 { DC_COM_PIN_OUTPUT_SELECT(0), 0x00000000 },
48 { DC_COM_PIN_OUTPUT_SELECT(1), 0x00000000 },
49 { DC_COM_PIN_OUTPUT_SELECT(2), 0x00000000 },
50 { DC_COM_PIN_OUTPUT_SELECT(3), 0x00000000 },
51 { DC_COM_PIN_OUTPUT_SELECT(4), 0x00210222 },
52 { DC_COM_PIN_OUTPUT_SELECT(5), 0x00002200 },
53 { DC_COM_PIN_OUTPUT_SELECT(6), 0x00020000 },
54};
55
56static const struct reg_entry rgb_disable[] = {
57 { DC_COM_PIN_OUTPUT_SELECT(6), 0x00000000 },
58 { DC_COM_PIN_OUTPUT_SELECT(5), 0x00000000 },
59 { DC_COM_PIN_OUTPUT_SELECT(4), 0x00000000 },
60 { DC_COM_PIN_OUTPUT_SELECT(3), 0x00000000 },
61 { DC_COM_PIN_OUTPUT_SELECT(2), 0x00000000 },
62 { DC_COM_PIN_OUTPUT_SELECT(1), 0x00000000 },
63 { DC_COM_PIN_OUTPUT_SELECT(0), 0x00000000 },
64 { DC_COM_PIN_OUTPUT_DATA(3), 0xaaaaaaaa },
65 { DC_COM_PIN_OUTPUT_DATA(2), 0xaaaaaaaa },
66 { DC_COM_PIN_OUTPUT_DATA(1), 0xaaaaaaaa },
67 { DC_COM_PIN_OUTPUT_DATA(0), 0xaaaaaaaa },
68 { DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000000 },
69 { DC_COM_PIN_OUTPUT_POLARITY(2), 0x00000000 },
70 { DC_COM_PIN_OUTPUT_POLARITY(1), 0x00000000 },
71 { DC_COM_PIN_OUTPUT_POLARITY(0), 0x00000000 },
72 { DC_COM_PIN_OUTPUT_ENABLE(3), 0x55555555 },
73 { DC_COM_PIN_OUTPUT_ENABLE(2), 0x55555555 },
74 { DC_COM_PIN_OUTPUT_ENABLE(1), 0x55150005 },
75 { DC_COM_PIN_OUTPUT_ENABLE(0), 0x55555555 },
76};
77
78static void tegra_dc_write_regs(struct tegra_dc *dc,
79 const struct reg_entry *table,
80 unsigned int num)
81{
82 unsigned int i;
83
84 for (i = 0; i < num; i++)
85 tegra_dc_writel(dc, table[i].value, table[i].offset);
86}
87
88static int tegra_output_rgb_enable(struct tegra_output *output)
89{
90 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
91
92 tegra_dc_write_regs(dc, rgb_enable, ARRAY_SIZE(rgb_enable));
93
94 return 0;
95}
96
97static int tegra_output_rgb_disable(struct tegra_output *output)
98{
99 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
100
101 tegra_dc_write_regs(dc, rgb_disable, ARRAY_SIZE(rgb_disable));
102
103 return 0;
104}
105
106static int tegra_output_rgb_setup_clock(struct tegra_output *output,
107 struct clk *clk, unsigned long pclk)
108{
109 struct tegra_rgb *rgb = to_rgb(output);
110
111 return clk_set_parent(clk, rgb->clk_parent);
112}
113
114static int tegra_output_rgb_check_mode(struct tegra_output *output,
115 struct drm_display_mode *mode,
116 enum drm_mode_status *status)
117{
118 /*
119 * FIXME: For now, always assume that the mode is okay. There are
120 * unresolved issues with clk_round_rate(), which doesn't always
121 * reliably report whether a frequency can be set or not.
122 */
123
124 *status = MODE_OK;
125
126 return 0;
127}
128
129static const struct tegra_output_ops rgb_ops = {
130 .enable = tegra_output_rgb_enable,
131 .disable = tegra_output_rgb_disable,
132 .setup_clock = tegra_output_rgb_setup_clock,
133 .check_mode = tegra_output_rgb_check_mode,
134};
135
136int tegra_dc_rgb_probe(struct tegra_dc *dc)
137{
138 struct device_node *np;
139 struct tegra_rgb *rgb;
140 int err;
141
142 np = of_get_child_by_name(dc->dev->of_node, "rgb");
143 if (!np || !of_device_is_available(np))
144 return -ENODEV;
145
146 rgb = devm_kzalloc(dc->dev, sizeof(*rgb), GFP_KERNEL);
147 if (!rgb)
148 return -ENOMEM;
149
150 rgb->output.dev = dc->dev;
151 rgb->output.of_node = np;
152
153 err = tegra_output_parse_dt(&rgb->output);
154 if (err < 0)
155 return err;
156
157 rgb->clk = devm_clk_get(dc->dev, NULL);
158 if (IS_ERR(rgb->clk)) {
159 dev_err(dc->dev, "failed to get clock\n");
160 return PTR_ERR(rgb->clk);
161 }
162
163 rgb->clk_parent = devm_clk_get(dc->dev, "parent");
164 if (IS_ERR(rgb->clk_parent)) {
165 dev_err(dc->dev, "failed to get parent clock\n");
166 return PTR_ERR(rgb->clk_parent);
167 }
168
169 err = clk_set_parent(rgb->clk, rgb->clk_parent);
170 if (err < 0) {
171 dev_err(dc->dev, "failed to set parent clock: %d\n", err);
172 return err;
173 }
174
175 dc->rgb = &rgb->output;
176
177 return 0;
178}
179
180int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc)
181{
182 struct tegra_rgb *rgb = to_rgb(dc->rgb);
183 int err;
184
185 if (!dc->rgb)
186 return -ENODEV;
187
188 rgb->output.type = TEGRA_OUTPUT_RGB;
189 rgb->output.ops = &rgb_ops;
190
191 err = tegra_output_init(dc->base.dev, &rgb->output);
192 if (err < 0) {
193 dev_err(dc->dev, "output setup failed: %d\n", err);
194 return err;
195 }
196
197 /*
198 * By default, outputs can be associated with each display controller.
199 * RGB outputs are an exception, so we make sure they can be attached
200 * to only their parent display controller.
201 */
202 rgb->output.encoder.possible_crtcs = 1 << dc->pipe;
203
204 return 0;
205}
206
207int tegra_dc_rgb_exit(struct tegra_dc *dc)
208{
209 if (dc->rgb) {
210 int err;
211
212 err = tegra_output_disable(dc->rgb);
213 if (err < 0) {
214 dev_err(dc->dev, "output failed to disable: %d\n", err);
215 return err;
216 }
217
218 err = tegra_output_exit(dc->rgb);
219 if (err < 0) {
220 dev_err(dc->dev, "output cleanup failed: %d\n", err);
221 return err;
222 }
223
224 dc->rgb = NULL;
225 }
226
227 return 0;
228}
diff --git a/drivers/gpu/host1x/host1x.h b/drivers/gpu/host1x/host1x.h
deleted file mode 100644
index a2bc1e65e972..000000000000
--- a/drivers/gpu/host1x/host1x.h
+++ /dev/null
@@ -1,30 +0,0 @@
1/*
2 * Tegra host1x driver
3 *
4 * Copyright (c) 2009-2013, NVIDIA Corporation. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21#ifndef __LINUX_HOST1X_H
22#define __LINUX_HOST1X_H
23
24enum host1x_class {
25 HOST1X_CLASS_HOST1X = 0x1,
26 HOST1X_CLASS_GR2D = 0x51,
27 HOST1X_CLASS_GR2D_SB = 0x52
28};
29
30#endif
diff --git a/drivers/gpu/host1x/host1x_bo.h b/drivers/gpu/host1x/host1x_bo.h
deleted file mode 100644
index 4c1f10bd773d..000000000000
--- a/drivers/gpu/host1x/host1x_bo.h
+++ /dev/null
@@ -1,87 +0,0 @@
1/*
2 * Tegra host1x Memory Management Abstraction header
3 *
4 * Copyright (c) 2012-2013, NVIDIA Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef _HOST1X_BO_H
20#define _HOST1X_BO_H
21
22struct host1x_bo;
23
24struct host1x_bo_ops {
25 struct host1x_bo *(*get)(struct host1x_bo *bo);
26 void (*put)(struct host1x_bo *bo);
27 dma_addr_t (*pin)(struct host1x_bo *bo, struct sg_table **sgt);
28 void (*unpin)(struct host1x_bo *bo, struct sg_table *sgt);
29 void *(*mmap)(struct host1x_bo *bo);
30 void (*munmap)(struct host1x_bo *bo, void *addr);
31 void *(*kmap)(struct host1x_bo *bo, unsigned int pagenum);
32 void (*kunmap)(struct host1x_bo *bo, unsigned int pagenum, void *addr);
33};
34
35struct host1x_bo {
36 const struct host1x_bo_ops *ops;
37};
38
39static inline void host1x_bo_init(struct host1x_bo *bo,
40 const struct host1x_bo_ops *ops)
41{
42 bo->ops = ops;
43}
44
45static inline struct host1x_bo *host1x_bo_get(struct host1x_bo *bo)
46{
47 return bo->ops->get(bo);
48}
49
50static inline void host1x_bo_put(struct host1x_bo *bo)
51{
52 bo->ops->put(bo);
53}
54
55static inline dma_addr_t host1x_bo_pin(struct host1x_bo *bo,
56 struct sg_table **sgt)
57{
58 return bo->ops->pin(bo, sgt);
59}
60
61static inline void host1x_bo_unpin(struct host1x_bo *bo, struct sg_table *sgt)
62{
63 bo->ops->unpin(bo, sgt);
64}
65
66static inline void *host1x_bo_mmap(struct host1x_bo *bo)
67{
68 return bo->ops->mmap(bo);
69}
70
71static inline void host1x_bo_munmap(struct host1x_bo *bo, void *addr)
72{
73 bo->ops->munmap(bo, addr);
74}
75
76static inline void *host1x_bo_kmap(struct host1x_bo *bo, unsigned int pagenum)
77{
78 return bo->ops->kmap(bo, pagenum);
79}
80
81static inline void host1x_bo_kunmap(struct host1x_bo *bo,
82 unsigned int pagenum, void *addr)
83{
84 bo->ops->kunmap(bo, pagenum, addr);
85}
86
87#endif
diff --git a/drivers/gpu/host1x/hw/Makefile b/drivers/gpu/host1x/hw/Makefile
deleted file mode 100644
index 9b50863a2236..000000000000
--- a/drivers/gpu/host1x/hw/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
1ccflags-y = -Idrivers/gpu/host1x
2
3host1x-hw-objs = \
4 host1x01.o
5
6obj-$(CONFIG_TEGRA_HOST1X) += host1x-hw.o
diff --git a/drivers/gpu/host1x/hw/cdma_hw.c b/drivers/gpu/host1x/hw/cdma_hw.c
index 2ee4ad55c4db..37e2a63241a9 100644
--- a/drivers/gpu/host1x/hw/cdma_hw.c
+++ b/drivers/gpu/host1x/hw/cdma_hw.c
@@ -20,10 +20,10 @@
20#include <linux/scatterlist.h> 20#include <linux/scatterlist.h>
21#include <linux/dma-mapping.h> 21#include <linux/dma-mapping.h>
22 22
23#include "cdma.h" 23#include "../cdma.h"
24#include "channel.h" 24#include "../channel.h"
25#include "dev.h" 25#include "../dev.h"
26#include "debug.h" 26#include "../debug.h"
27 27
28/* 28/*
29 * Put the restart at the end of pushbuffer memor 29 * Put the restart at the end of pushbuffer memor
diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c
index ee199623e365..4608257ab656 100644
--- a/drivers/gpu/host1x/hw/channel_hw.c
+++ b/drivers/gpu/host1x/hw/channel_hw.c
@@ -16,15 +16,15 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */ 17 */
18 18
19#include <linux/host1x.h>
19#include <linux/slab.h> 20#include <linux/slab.h>
21
20#include <trace/events/host1x.h> 22#include <trace/events/host1x.h>
21 23
22#include "host1x.h" 24#include "../channel.h"
23#include "host1x_bo.h" 25#include "../dev.h"
24#include "channel.h" 26#include "../intr.h"
25#include "dev.h" 27#include "../job.h"
26#include "intr.h"
27#include "job.h"
28 28
29#define HOST1X_CHANNEL_SIZE 16384 29#define HOST1X_CHANNEL_SIZE 16384
30#define TRACE_MAX_LENGTH 128U 30#define TRACE_MAX_LENGTH 128U
@@ -67,6 +67,22 @@ static void submit_gathers(struct host1x_job *job)
67 } 67 }
68} 68}
69 69
70static inline void synchronize_syncpt_base(struct host1x_job *job)
71{
72 struct host1x *host = dev_get_drvdata(job->channel->dev->parent);
73 struct host1x_syncpt *sp = host->syncpt + job->syncpt_id;
74 u32 id, value;
75
76 value = host1x_syncpt_read_max(sp);
77 id = sp->base->id;
78
79 host1x_cdma_push(&job->channel->cdma,
80 host1x_opcode_setclass(HOST1X_CLASS_HOST1X,
81 HOST1X_UCLASS_LOAD_SYNCPT_BASE, 1),
82 HOST1X_UCLASS_LOAD_SYNCPT_BASE_BASE_INDX_F(id) |
83 HOST1X_UCLASS_LOAD_SYNCPT_BASE_VALUE_F(value));
84}
85
70static int channel_submit(struct host1x_job *job) 86static int channel_submit(struct host1x_job *job)
71{ 87{
72 struct host1x_channel *ch = job->channel; 88 struct host1x_channel *ch = job->channel;
@@ -118,6 +134,10 @@ static int channel_submit(struct host1x_job *job)
118 host1x_syncpt_read_max(sp))); 134 host1x_syncpt_read_max(sp)));
119 } 135 }
120 136
137 /* Synchronize base register to allow using it for relative waiting */
138 if (sp->base)
139 synchronize_syncpt_base(job);
140
121 syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs); 141 syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs);
122 142
123 job->syncpt_end = syncval; 143 job->syncpt_end = syncval;
diff --git a/drivers/gpu/host1x/hw/debug_hw.c b/drivers/gpu/host1x/hw/debug_hw.c
index 334c038052f5..640c75ca5a8b 100644
--- a/drivers/gpu/host1x/hw/debug_hw.c
+++ b/drivers/gpu/host1x/hw/debug_hw.c
@@ -15,18 +15,10 @@
15 * 15 *
16 */ 16 */
17 17
18#include <linux/debugfs.h> 18#include "../dev.h"
19#include <linux/seq_file.h> 19#include "../debug.h"
20#include <linux/mm.h> 20#include "../cdma.h"
21#include <linux/scatterlist.h> 21#include "../channel.h"
22
23#include <linux/io.h>
24
25#include "dev.h"
26#include "debug.h"
27#include "cdma.h"
28#include "channel.h"
29#include "host1x_bo.h"
30 22
31#define HOST1X_DEBUG_MAX_PAGE_OFFSET 102400 23#define HOST1X_DEBUG_MAX_PAGE_OFFSET 102400
32 24
diff --git a/drivers/gpu/host1x/hw/host1x01.c b/drivers/gpu/host1x/hw/host1x01.c
index a14e91cd1e58..859b73beb4d0 100644
--- a/drivers/gpu/host1x/hw/host1x01.c
+++ b/drivers/gpu/host1x/hw/host1x01.c
@@ -17,17 +17,17 @@
17 */ 17 */
18 18
19/* include hw specification */ 19/* include hw specification */
20#include "hw/host1x01.h" 20#include "host1x01.h"
21#include "hw/host1x01_hardware.h" 21#include "host1x01_hardware.h"
22 22
23/* include code */ 23/* include code */
24#include "hw/cdma_hw.c" 24#include "cdma_hw.c"
25#include "hw/channel_hw.c" 25#include "channel_hw.c"
26#include "hw/debug_hw.c" 26#include "debug_hw.c"
27#include "hw/intr_hw.c" 27#include "intr_hw.c"
28#include "hw/syncpt_hw.c" 28#include "syncpt_hw.c"
29 29
30#include "dev.h" 30#include "../dev.h"
31 31
32int host1x01_init(struct host1x *host) 32int host1x01_init(struct host1x *host)
33{ 33{
diff --git a/drivers/gpu/host1x/hw/host1x02.c b/drivers/gpu/host1x/hw/host1x02.c
new file mode 100644
index 000000000000..e98caca0ca42
--- /dev/null
+++ b/drivers/gpu/host1x/hw/host1x02.c
@@ -0,0 +1,42 @@
1/*
2 * Host1x init for Tegra114 SoCs
3 *
4 * Copyright (c) 2013 NVIDIA Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/* include hw specification */
20#include "host1x01.h"
21#include "host1x01_hardware.h"
22
23/* include code */
24#include "cdma_hw.c"
25#include "channel_hw.c"
26#include "debug_hw.c"
27#include "intr_hw.c"
28#include "syncpt_hw.c"
29
30#include "../dev.h"
31
32int host1x02_init(struct host1x *host)
33{
34 host->channel_op = &host1x_channel_ops;
35 host->cdma_op = &host1x_cdma_ops;
36 host->cdma_pb_op = &host1x_pushbuffer_ops;
37 host->syncpt_op = &host1x_syncpt_ops;
38 host->intr_op = &host1x_intr_ops;
39 host->debug_op = &host1x_debug_ops;
40
41 return 0;
42}
diff --git a/drivers/gpu/host1x/hw/host1x02.h b/drivers/gpu/host1x/hw/host1x02.h
new file mode 100644
index 000000000000..f7486609a90e
--- /dev/null
+++ b/drivers/gpu/host1x/hw/host1x02.h
@@ -0,0 +1,26 @@
1/*
2 * Host1x init for Tegra114 SoCs
3 *
4 * Copyright (c) 2013 NVIDIA Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef HOST1X_HOST1X02_H
20#define HOST1X_HOST1X02_H
21
22struct host1x;
23
24int host1x02_init(struct host1x *host);
25
26#endif
diff --git a/drivers/gpu/host1x/hw/hw_host1x01_uclass.h b/drivers/gpu/host1x/hw/hw_host1x01_uclass.h
index 42f3ce19ca32..f7553599ee27 100644
--- a/drivers/gpu/host1x/hw/hw_host1x01_uclass.h
+++ b/drivers/gpu/host1x/hw/hw_host1x01_uclass.h
@@ -111,6 +111,12 @@ static inline u32 host1x_uclass_wait_syncpt_base_offset_f(u32 v)
111} 111}
112#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_OFFSET_F(v) \ 112#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_OFFSET_F(v) \
113 host1x_uclass_wait_syncpt_base_offset_f(v) 113 host1x_uclass_wait_syncpt_base_offset_f(v)
114static inline u32 host1x_uclass_load_syncpt_base_r(void)
115{
116 return 0xb;
117}
118#define HOST1X_UCLASS_LOAD_SYNCPT_BASE \
119 host1x_uclass_load_syncpt_base_r()
114static inline u32 host1x_uclass_load_syncpt_base_base_indx_f(u32 v) 120static inline u32 host1x_uclass_load_syncpt_base_base_indx_f(u32 v)
115{ 121{
116 return (v & 0xff) << 24; 122 return (v & 0xff) << 24;
diff --git a/drivers/gpu/host1x/hw/hw_host1x02_channel.h b/drivers/gpu/host1x/hw/hw_host1x02_channel.h
new file mode 100644
index 000000000000..e490bcde33fe
--- /dev/null
+++ b/drivers/gpu/host1x/hw/hw_host1x02_channel.h
@@ -0,0 +1,121 @@
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
18 /*
19 * Function naming determines intended use:
20 *
21 * <x>_r(void) : Returns the offset for register <x>.
22 *
23 * <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
24 *
25 * <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
26 *
27 * <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted
28 * and masked to place it at field <y> of register <x>. This value
29 * can be |'d with others to produce a full register value for
30 * register <x>.
31 *
32 * <x>_<y>_m(void) : Returns a mask for field <y> of register <x>. This
33 * value can be ~'d and then &'d to clear the value of field <y> for
34 * register <x>.
35 *
36 * <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
37 * to place it at field <y> of register <x>. This value can be |'d
38 * with others to produce a full register value for <x>.
39 *
40 * <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register
41 * <x> value 'r' after being shifted to place its LSB at bit 0.
42 * This value is suitable for direct comparison with other unshifted
43 * values appropriate for use in field <y> of register <x>.
44 *
45 * <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
46 * field <y> of register <x>. This value is suitable for direct
47 * comparison with unshifted values appropriate for use in field <y>
48 * of register <x>.
49 */
50
51#ifndef HOST1X_HW_HOST1X02_CHANNEL_H
52#define HOST1X_HW_HOST1X02_CHANNEL_H
53
54static inline u32 host1x_channel_fifostat_r(void)
55{
56 return 0x0;
57}
58#define HOST1X_CHANNEL_FIFOSTAT \
59 host1x_channel_fifostat_r()
60static inline u32 host1x_channel_fifostat_cfempty_v(u32 r)
61{
62 return (r >> 11) & 0x1;
63}
64#define HOST1X_CHANNEL_FIFOSTAT_CFEMPTY_V(r) \
65 host1x_channel_fifostat_cfempty_v(r)
66static inline u32 host1x_channel_dmastart_r(void)
67{
68 return 0x14;
69}
70#define HOST1X_CHANNEL_DMASTART \
71 host1x_channel_dmastart_r()
72static inline u32 host1x_channel_dmaput_r(void)
73{
74 return 0x18;
75}
76#define HOST1X_CHANNEL_DMAPUT \
77 host1x_channel_dmaput_r()
78static inline u32 host1x_channel_dmaget_r(void)
79{
80 return 0x1c;
81}
82#define HOST1X_CHANNEL_DMAGET \
83 host1x_channel_dmaget_r()
84static inline u32 host1x_channel_dmaend_r(void)
85{
86 return 0x20;
87}
88#define HOST1X_CHANNEL_DMAEND \
89 host1x_channel_dmaend_r()
90static inline u32 host1x_channel_dmactrl_r(void)
91{
92 return 0x24;
93}
94#define HOST1X_CHANNEL_DMACTRL \
95 host1x_channel_dmactrl_r()
96static inline u32 host1x_channel_dmactrl_dmastop(void)
97{
98 return 1 << 0;
99}
100#define HOST1X_CHANNEL_DMACTRL_DMASTOP \
101 host1x_channel_dmactrl_dmastop()
102static inline u32 host1x_channel_dmactrl_dmastop_v(u32 r)
103{
104 return (r >> 0) & 0x1;
105}
106#define HOST1X_CHANNEL_DMACTRL_DMASTOP_V(r) \
107 host1x_channel_dmactrl_dmastop_v(r)
108static inline u32 host1x_channel_dmactrl_dmagetrst(void)
109{
110 return 1 << 1;
111}
112#define HOST1X_CHANNEL_DMACTRL_DMAGETRST \
113 host1x_channel_dmactrl_dmagetrst()
114static inline u32 host1x_channel_dmactrl_dmainitget(void)
115{
116 return 1 << 2;
117}
118#define HOST1X_CHANNEL_DMACTRL_DMAINITGET \
119 host1x_channel_dmactrl_dmainitget()
120
121#endif
diff --git a/drivers/gpu/host1x/hw/hw_host1x02_sync.h b/drivers/gpu/host1x/hw/hw_host1x02_sync.h
new file mode 100644
index 000000000000..4495401525e8
--- /dev/null
+++ b/drivers/gpu/host1x/hw/hw_host1x02_sync.h
@@ -0,0 +1,243 @@
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
18 /*
19 * Function naming determines intended use:
20 *
21 * <x>_r(void) : Returns the offset for register <x>.
22 *
23 * <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
24 *
25 * <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
26 *
27 * <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted
28 * and masked to place it at field <y> of register <x>. This value
29 * can be |'d with others to produce a full register value for
30 * register <x>.
31 *
32 * <x>_<y>_m(void) : Returns a mask for field <y> of register <x>. This
33 * value can be ~'d and then &'d to clear the value of field <y> for
34 * register <x>.
35 *
36 * <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
37 * to place it at field <y> of register <x>. This value can be |'d
38 * with others to produce a full register value for <x>.
39 *
40 * <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register
41 * <x> value 'r' after being shifted to place its LSB at bit 0.
42 * This value is suitable for direct comparison with other unshifted
43 * values appropriate for use in field <y> of register <x>.
44 *
45 * <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
46 * field <y> of register <x>. This value is suitable for direct
47 * comparison with unshifted values appropriate for use in field <y>
48 * of register <x>.
49 */
50
51#ifndef HOST1X_HW_HOST1X02_SYNC_H
52#define HOST1X_HW_HOST1X02_SYNC_H
53
54#define REGISTER_STRIDE 4
55
56static inline u32 host1x_sync_syncpt_r(unsigned int id)
57{
58 return 0x400 + id * REGISTER_STRIDE;
59}
60#define HOST1X_SYNC_SYNCPT(id) \
61 host1x_sync_syncpt_r(id)
62static inline u32 host1x_sync_syncpt_thresh_cpu0_int_status_r(unsigned int id)
63{
64 return 0x40 + id * REGISTER_STRIDE;
65}
66#define HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(id) \
67 host1x_sync_syncpt_thresh_cpu0_int_status_r(id)
68static inline u32 host1x_sync_syncpt_thresh_int_disable_r(unsigned int id)
69{
70 return 0x60 + id * REGISTER_STRIDE;
71}
72#define HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(id) \
73 host1x_sync_syncpt_thresh_int_disable_r(id)
74static inline u32 host1x_sync_syncpt_thresh_int_enable_cpu0_r(unsigned int id)
75{
76 return 0x68 + id * REGISTER_STRIDE;
77}
78#define HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0(id) \
79 host1x_sync_syncpt_thresh_int_enable_cpu0_r(id)
80static inline u32 host1x_sync_cf_setup_r(unsigned int channel)
81{
82 return 0x80 + channel * REGISTER_STRIDE;
83}
84#define HOST1X_SYNC_CF_SETUP(channel) \
85 host1x_sync_cf_setup_r(channel)
86static inline u32 host1x_sync_cf_setup_base_v(u32 r)
87{
88 return (r >> 0) & 0x3ff;
89}
90#define HOST1X_SYNC_CF_SETUP_BASE_V(r) \
91 host1x_sync_cf_setup_base_v(r)
92static inline u32 host1x_sync_cf_setup_limit_v(u32 r)
93{
94 return (r >> 16) & 0x3ff;
95}
96#define HOST1X_SYNC_CF_SETUP_LIMIT_V(r) \
97 host1x_sync_cf_setup_limit_v(r)
98static inline u32 host1x_sync_cmdproc_stop_r(void)
99{
100 return 0xac;
101}
102#define HOST1X_SYNC_CMDPROC_STOP \
103 host1x_sync_cmdproc_stop_r()
104static inline u32 host1x_sync_ch_teardown_r(void)
105{
106 return 0xb0;
107}
108#define HOST1X_SYNC_CH_TEARDOWN \
109 host1x_sync_ch_teardown_r()
110static inline u32 host1x_sync_usec_clk_r(void)
111{
112 return 0x1a4;
113}
114#define HOST1X_SYNC_USEC_CLK \
115 host1x_sync_usec_clk_r()
116static inline u32 host1x_sync_ctxsw_timeout_cfg_r(void)
117{
118 return 0x1a8;
119}
120#define HOST1X_SYNC_CTXSW_TIMEOUT_CFG \
121 host1x_sync_ctxsw_timeout_cfg_r()
122static inline u32 host1x_sync_ip_busy_timeout_r(void)
123{
124 return 0x1bc;
125}
126#define HOST1X_SYNC_IP_BUSY_TIMEOUT \
127 host1x_sync_ip_busy_timeout_r()
128static inline u32 host1x_sync_mlock_owner_r(unsigned int id)
129{
130 return 0x340 + id * REGISTER_STRIDE;
131}
132#define HOST1X_SYNC_MLOCK_OWNER(id) \
133 host1x_sync_mlock_owner_r(id)
134static inline u32 host1x_sync_mlock_owner_chid_f(u32 v)
135{
136 return (v & 0xf) << 8;
137}
138#define HOST1X_SYNC_MLOCK_OWNER_CHID_F(v) \
139 host1x_sync_mlock_owner_chid_f(v)
140static inline u32 host1x_sync_mlock_owner_cpu_owns_v(u32 r)
141{
142 return (r >> 1) & 0x1;
143}
144#define HOST1X_SYNC_MLOCK_OWNER_CPU_OWNS_V(r) \
145 host1x_sync_mlock_owner_cpu_owns_v(r)
146static inline u32 host1x_sync_mlock_owner_ch_owns_v(u32 r)
147{
148 return (r >> 0) & 0x1;
149}
150#define HOST1X_SYNC_MLOCK_OWNER_CH_OWNS_V(r) \
151 host1x_sync_mlock_owner_ch_owns_v(r)
152static inline u32 host1x_sync_syncpt_int_thresh_r(unsigned int id)
153{
154 return 0x500 + id * REGISTER_STRIDE;
155}
156#define HOST1X_SYNC_SYNCPT_INT_THRESH(id) \
157 host1x_sync_syncpt_int_thresh_r(id)
158static inline u32 host1x_sync_syncpt_base_r(unsigned int id)
159{
160 return 0x600 + id * REGISTER_STRIDE;
161}
162#define HOST1X_SYNC_SYNCPT_BASE(id) \
163 host1x_sync_syncpt_base_r(id)
164static inline u32 host1x_sync_syncpt_cpu_incr_r(unsigned int id)
165{
166 return 0x700 + id * REGISTER_STRIDE;
167}
168#define HOST1X_SYNC_SYNCPT_CPU_INCR(id) \
169 host1x_sync_syncpt_cpu_incr_r(id)
170static inline u32 host1x_sync_cbread_r(unsigned int channel)
171{
172 return 0x720 + channel * REGISTER_STRIDE;
173}
174#define HOST1X_SYNC_CBREAD(channel) \
175 host1x_sync_cbread_r(channel)
176static inline u32 host1x_sync_cfpeek_ctrl_r(void)
177{
178 return 0x74c;
179}
180#define HOST1X_SYNC_CFPEEK_CTRL \
181 host1x_sync_cfpeek_ctrl_r()
182static inline u32 host1x_sync_cfpeek_ctrl_addr_f(u32 v)
183{
184 return (v & 0x3ff) << 0;
185}
186#define HOST1X_SYNC_CFPEEK_CTRL_ADDR_F(v) \
187 host1x_sync_cfpeek_ctrl_addr_f(v)
188static inline u32 host1x_sync_cfpeek_ctrl_channr_f(u32 v)
189{
190 return (v & 0xf) << 16;
191}
192#define HOST1X_SYNC_CFPEEK_CTRL_CHANNR_F(v) \
193 host1x_sync_cfpeek_ctrl_channr_f(v)
194static inline u32 host1x_sync_cfpeek_ctrl_ena_f(u32 v)
195{
196 return (v & 0x1) << 31;
197}
198#define HOST1X_SYNC_CFPEEK_CTRL_ENA_F(v) \
199 host1x_sync_cfpeek_ctrl_ena_f(v)
200static inline u32 host1x_sync_cfpeek_read_r(void)
201{
202 return 0x750;
203}
204#define HOST1X_SYNC_CFPEEK_READ \
205 host1x_sync_cfpeek_read_r()
206static inline u32 host1x_sync_cfpeek_ptrs_r(void)
207{
208 return 0x754;
209}
210#define HOST1X_SYNC_CFPEEK_PTRS \
211 host1x_sync_cfpeek_ptrs_r()
212static inline u32 host1x_sync_cfpeek_ptrs_cf_rd_ptr_v(u32 r)
213{
214 return (r >> 0) & 0x3ff;
215}
216#define HOST1X_SYNC_CFPEEK_PTRS_CF_RD_PTR_V(r) \
217 host1x_sync_cfpeek_ptrs_cf_rd_ptr_v(r)
218static inline u32 host1x_sync_cfpeek_ptrs_cf_wr_ptr_v(u32 r)
219{
220 return (r >> 16) & 0x3ff;
221}
222#define HOST1X_SYNC_CFPEEK_PTRS_CF_WR_PTR_V(r) \
223 host1x_sync_cfpeek_ptrs_cf_wr_ptr_v(r)
224static inline u32 host1x_sync_cbstat_r(unsigned int channel)
225{
226 return 0x758 + channel * REGISTER_STRIDE;
227}
228#define HOST1X_SYNC_CBSTAT(channel) \
229 host1x_sync_cbstat_r(channel)
230static inline u32 host1x_sync_cbstat_cboffset_v(u32 r)
231{
232 return (r >> 0) & 0xffff;
233}
234#define HOST1X_SYNC_CBSTAT_CBOFFSET_V(r) \
235 host1x_sync_cbstat_cboffset_v(r)
236static inline u32 host1x_sync_cbstat_cbclass_v(u32 r)
237{
238 return (r >> 16) & 0x3ff;
239}
240#define HOST1X_SYNC_CBSTAT_CBCLASS_V(r) \
241 host1x_sync_cbstat_cbclass_v(r)
242
243#endif
diff --git a/drivers/gpu/host1x/hw/hw_host1x02_uclass.h b/drivers/gpu/host1x/hw/hw_host1x02_uclass.h
new file mode 100644
index 000000000000..a3b3c9874413
--- /dev/null
+++ b/drivers/gpu/host1x/hw/hw_host1x02_uclass.h
@@ -0,0 +1,175 @@
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
18 /*
19 * Function naming determines intended use:
20 *
21 * <x>_r(void) : Returns the offset for register <x>.
22 *
23 * <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
24 *
25 * <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
26 *
27 * <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted
28 * and masked to place it at field <y> of register <x>. This value
29 * can be |'d with others to produce a full register value for
30 * register <x>.
31 *
32 * <x>_<y>_m(void) : Returns a mask for field <y> of register <x>. This
33 * value can be ~'d and then &'d to clear the value of field <y> for
34 * register <x>.
35 *
36 * <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
37 * to place it at field <y> of register <x>. This value can be |'d
38 * with others to produce a full register value for <x>.
39 *
40 * <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register
41 * <x> value 'r' after being shifted to place its LSB at bit 0.
42 * This value is suitable for direct comparison with other unshifted
43 * values appropriate for use in field <y> of register <x>.
44 *
45 * <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
46 * field <y> of register <x>. This value is suitable for direct
47 * comparison with unshifted values appropriate for use in field <y>
48 * of register <x>.
49 */
50
51#ifndef HOST1X_HW_HOST1X02_UCLASS_H
52#define HOST1X_HW_HOST1X02_UCLASS_H
53
54static inline u32 host1x_uclass_incr_syncpt_r(void)
55{
56 return 0x0;
57}
58#define HOST1X_UCLASS_INCR_SYNCPT \
59 host1x_uclass_incr_syncpt_r()
60static inline u32 host1x_uclass_incr_syncpt_cond_f(u32 v)
61{
62 return (v & 0xff) << 8;
63}
64#define HOST1X_UCLASS_INCR_SYNCPT_COND_F(v) \
65 host1x_uclass_incr_syncpt_cond_f(v)
66static inline u32 host1x_uclass_incr_syncpt_indx_f(u32 v)
67{
68 return (v & 0xff) << 0;
69}
70#define HOST1X_UCLASS_INCR_SYNCPT_INDX_F(v) \
71 host1x_uclass_incr_syncpt_indx_f(v)
72static inline u32 host1x_uclass_wait_syncpt_r(void)
73{
74 return 0x8;
75}
76#define HOST1X_UCLASS_WAIT_SYNCPT \
77 host1x_uclass_wait_syncpt_r()
78static inline u32 host1x_uclass_wait_syncpt_indx_f(u32 v)
79{
80 return (v & 0xff) << 24;
81}
82#define HOST1X_UCLASS_WAIT_SYNCPT_INDX_F(v) \
83 host1x_uclass_wait_syncpt_indx_f(v)
84static inline u32 host1x_uclass_wait_syncpt_thresh_f(u32 v)
85{
86 return (v & 0xffffff) << 0;
87}
88#define HOST1X_UCLASS_WAIT_SYNCPT_THRESH_F(v) \
89 host1x_uclass_wait_syncpt_thresh_f(v)
90static inline u32 host1x_uclass_wait_syncpt_base_r(void)
91{
92 return 0x9;
93}
94#define HOST1X_UCLASS_WAIT_SYNCPT_BASE \
95 host1x_uclass_wait_syncpt_base_r()
96static inline u32 host1x_uclass_wait_syncpt_base_indx_f(u32 v)
97{
98 return (v & 0xff) << 24;
99}
100#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_INDX_F(v) \
101 host1x_uclass_wait_syncpt_base_indx_f(v)
102static inline u32 host1x_uclass_wait_syncpt_base_base_indx_f(u32 v)
103{
104 return (v & 0xff) << 16;
105}
106#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_BASE_INDX_F(v) \
107 host1x_uclass_wait_syncpt_base_base_indx_f(v)
108static inline u32 host1x_uclass_wait_syncpt_base_offset_f(u32 v)
109{
110 return (v & 0xffff) << 0;
111}
112#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_OFFSET_F(v) \
113 host1x_uclass_wait_syncpt_base_offset_f(v)
114static inline u32 host1x_uclass_load_syncpt_base_base_indx_f(u32 v)
115{
116 return (v & 0xff) << 24;
117}
118#define HOST1X_UCLASS_LOAD_SYNCPT_BASE_BASE_INDX_F(v) \
119 host1x_uclass_load_syncpt_base_base_indx_f(v)
120static inline u32 host1x_uclass_load_syncpt_base_value_f(u32 v)
121{
122 return (v & 0xffffff) << 0;
123}
124#define HOST1X_UCLASS_LOAD_SYNCPT_BASE_VALUE_F(v) \
125 host1x_uclass_load_syncpt_base_value_f(v)
126static inline u32 host1x_uclass_incr_syncpt_base_base_indx_f(u32 v)
127{
128 return (v & 0xff) << 24;
129}
130#define HOST1X_UCLASS_INCR_SYNCPT_BASE_BASE_INDX_F(v) \
131 host1x_uclass_incr_syncpt_base_base_indx_f(v)
132static inline u32 host1x_uclass_incr_syncpt_base_offset_f(u32 v)
133{
134 return (v & 0xffffff) << 0;
135}
136#define HOST1X_UCLASS_INCR_SYNCPT_BASE_OFFSET_F(v) \
137 host1x_uclass_incr_syncpt_base_offset_f(v)
138static inline u32 host1x_uclass_indoff_r(void)
139{
140 return 0x2d;
141}
142#define HOST1X_UCLASS_INDOFF \
143 host1x_uclass_indoff_r()
144static inline u32 host1x_uclass_indoff_indbe_f(u32 v)
145{
146 return (v & 0xf) << 28;
147}
148#define HOST1X_UCLASS_INDOFF_INDBE_F(v) \
149 host1x_uclass_indoff_indbe_f(v)
150static inline u32 host1x_uclass_indoff_autoinc_f(u32 v)
151{
152 return (v & 0x1) << 27;
153}
154#define HOST1X_UCLASS_INDOFF_AUTOINC_F(v) \
155 host1x_uclass_indoff_autoinc_f(v)
156static inline u32 host1x_uclass_indoff_indmodid_f(u32 v)
157{
158 return (v & 0xff) << 18;
159}
160#define HOST1X_UCLASS_INDOFF_INDMODID_F(v) \
161 host1x_uclass_indoff_indmodid_f(v)
162static inline u32 host1x_uclass_indoff_indroffset_f(u32 v)
163{
164 return (v & 0xffff) << 2;
165}
166#define HOST1X_UCLASS_INDOFF_INDROFFSET_F(v) \
167 host1x_uclass_indoff_indroffset_f(v)
168static inline u32 host1x_uclass_indoff_rwn_read_v(void)
169{
170 return 1;
171}
172#define HOST1X_UCLASS_INDOFF_INDROFFSET_F(v) \
173 host1x_uclass_indoff_indroffset_f(v)
174
175#endif
diff --git a/drivers/gpu/host1x/hw/intr_hw.c b/drivers/gpu/host1x/hw/intr_hw.c
index b592eef1efcb..b26dcc83bc1b 100644
--- a/drivers/gpu/host1x/hw/intr_hw.c
+++ b/drivers/gpu/host1x/hw/intr_hw.c
@@ -22,8 +22,8 @@
22#include <linux/io.h> 22#include <linux/io.h>
23#include <asm/mach/irq.h> 23#include <asm/mach/irq.h>
24 24
25#include "intr.h" 25#include "../intr.h"
26#include "dev.h" 26#include "../dev.h"
27 27
28/* 28/*
29 * Sync point threshold interrupt service function 29 * Sync point threshold interrupt service function
diff --git a/drivers/gpu/host1x/hw/syncpt_hw.c b/drivers/gpu/host1x/hw/syncpt_hw.c
index 0cf6095d3367..56e85395ac24 100644
--- a/drivers/gpu/host1x/hw/syncpt_hw.c
+++ b/drivers/gpu/host1x/hw/syncpt_hw.c
@@ -18,8 +18,8 @@
18 18
19#include <linux/io.h> 19#include <linux/io.h>
20 20
21#include "dev.h" 21#include "../dev.h"
22#include "syncpt.h" 22#include "../syncpt.h"
23 23
24/* 24/*
25 * Write the current syncpoint value back to hw. 25 * Write the current syncpoint value back to hw.
diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c
index c4e1050f2252..de5ec333ce1a 100644
--- a/drivers/gpu/host1x/job.c
+++ b/drivers/gpu/host1x/job.c
@@ -18,6 +18,7 @@
18 18
19#include <linux/dma-mapping.h> 19#include <linux/dma-mapping.h>
20#include <linux/err.h> 20#include <linux/err.h>
21#include <linux/host1x.h>
21#include <linux/kref.h> 22#include <linux/kref.h>
22#include <linux/module.h> 23#include <linux/module.h>
23#include <linux/scatterlist.h> 24#include <linux/scatterlist.h>
@@ -27,7 +28,6 @@
27 28
28#include "channel.h" 29#include "channel.h"
29#include "dev.h" 30#include "dev.h"
30#include "host1x_bo.h"
31#include "job.h" 31#include "job.h"
32#include "syncpt.h" 32#include "syncpt.h"
33 33
@@ -264,7 +264,7 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
264} 264}
265 265
266static bool check_reloc(struct host1x_reloc *reloc, struct host1x_bo *cmdbuf, 266static bool check_reloc(struct host1x_reloc *reloc, struct host1x_bo *cmdbuf,
267 unsigned int offset) 267 unsigned int offset)
268{ 268{
269 offset *= sizeof(u32); 269 offset *= sizeof(u32);
270 270
@@ -281,7 +281,7 @@ struct host1x_firewall {
281 unsigned int num_relocs; 281 unsigned int num_relocs;
282 struct host1x_reloc *reloc; 282 struct host1x_reloc *reloc;
283 283
284 struct host1x_bo *cmdbuf_id; 284 struct host1x_bo *cmdbuf;
285 unsigned int offset; 285 unsigned int offset;
286 286
287 u32 words; 287 u32 words;
@@ -291,25 +291,37 @@ struct host1x_firewall {
291 u32 count; 291 u32 count;
292}; 292};
293 293
294static int check_register(struct host1x_firewall *fw, unsigned long offset)
295{
296 if (fw->job->is_addr_reg(fw->dev, fw->class, offset)) {
297 if (!fw->num_relocs)
298 return -EINVAL;
299
300 if (!check_reloc(fw->reloc, fw->cmdbuf, fw->offset))
301 return -EINVAL;
302
303 fw->num_relocs--;
304 fw->reloc++;
305 }
306
307 return 0;
308}
309
294static int check_mask(struct host1x_firewall *fw) 310static int check_mask(struct host1x_firewall *fw)
295{ 311{
296 u32 mask = fw->mask; 312 u32 mask = fw->mask;
297 u32 reg = fw->reg; 313 u32 reg = fw->reg;
314 int ret;
298 315
299 while (mask) { 316 while (mask) {
300 if (fw->words == 0) 317 if (fw->words == 0)
301 return -EINVAL; 318 return -EINVAL;
302 319
303 if (mask & 1) { 320 if (mask & 1) {
304 if (fw->job->is_addr_reg(fw->dev, fw->class, reg)) { 321 ret = check_register(fw, reg);
305 if (!fw->num_relocs) 322 if (ret < 0)
306 return -EINVAL; 323 return ret;
307 if (!check_reloc(fw->reloc, fw->cmdbuf_id, 324
308 fw->offset))
309 return -EINVAL;
310 fw->reloc++;
311 fw->num_relocs--;
312 }
313 fw->words--; 325 fw->words--;
314 fw->offset++; 326 fw->offset++;
315 } 327 }
@@ -324,19 +336,16 @@ static int check_incr(struct host1x_firewall *fw)
324{ 336{
325 u32 count = fw->count; 337 u32 count = fw->count;
326 u32 reg = fw->reg; 338 u32 reg = fw->reg;
339 int ret;
327 340
328 while (count) { 341 while (count) {
329 if (fw->words == 0) 342 if (fw->words == 0)
330 return -EINVAL; 343 return -EINVAL;
331 344
332 if (fw->job->is_addr_reg(fw->dev, fw->class, reg)) { 345 ret = check_register(fw, reg);
333 if (!fw->num_relocs) 346 if (ret < 0)
334 return -EINVAL; 347 return ret;
335 if (!check_reloc(fw->reloc, fw->cmdbuf_id, fw->offset)) 348
336 return -EINVAL;
337 fw->reloc++;
338 fw->num_relocs--;
339 }
340 reg++; 349 reg++;
341 fw->words--; 350 fw->words--;
342 fw->offset++; 351 fw->offset++;
@@ -348,21 +357,17 @@ static int check_incr(struct host1x_firewall *fw)
348 357
349static int check_nonincr(struct host1x_firewall *fw) 358static int check_nonincr(struct host1x_firewall *fw)
350{ 359{
351 int is_addr_reg = fw->job->is_addr_reg(fw->dev, fw->class, fw->reg);
352 u32 count = fw->count; 360 u32 count = fw->count;
361 int ret;
353 362
354 while (count) { 363 while (count) {
355 if (fw->words == 0) 364 if (fw->words == 0)
356 return -EINVAL; 365 return -EINVAL;
357 366
358 if (is_addr_reg) { 367 ret = check_register(fw, fw->reg);
359 if (!fw->num_relocs) 368 if (ret < 0)
360 return -EINVAL; 369 return ret;
361 if (!check_reloc(fw->reloc, fw->cmdbuf_id, fw->offset)) 370
362 return -EINVAL;
363 fw->reloc++;
364 fw->num_relocs--;
365 }
366 fw->words--; 371 fw->words--;
367 fw->offset++; 372 fw->offset++;
368 count--; 373 count--;
@@ -381,7 +386,7 @@ static int validate(struct host1x_firewall *fw, struct host1x_job_gather *g)
381 return 0; 386 return 0;
382 387
383 fw->words = g->words; 388 fw->words = g->words;
384 fw->cmdbuf_id = g->bo; 389 fw->cmdbuf = g->bo;
385 fw->offset = 0; 390 fw->offset = 0;
386 391
387 while (fw->words && !err) { 392 while (fw->words && !err) {
@@ -436,10 +441,6 @@ static int validate(struct host1x_firewall *fw, struct host1x_job_gather *g)
436 } 441 }
437 } 442 }
438 443
439 /* No relocs should remain at this point */
440 if (fw->num_relocs)
441 err = -EINVAL;
442
443out: 444out:
444 return err; 445 return err;
445} 446}
@@ -493,6 +494,10 @@ static inline int copy_gathers(struct host1x_job *job, struct device *dev)
493 offset += g->words * sizeof(u32); 494 offset += g->words * sizeof(u32);
494 } 495 }
495 496
497 /* No relocs should remain at this point */
498 if (fw.num_relocs)
499 return -EINVAL;
500
496 return 0; 501 return 0;
497} 502}
498 503
diff --git a/drivers/gpu/host1x/job.h b/drivers/gpu/host1x/job.h
index fba45f20458e..33a697d6dcef 100644
--- a/drivers/gpu/host1x/job.h
+++ b/drivers/gpu/host1x/job.h
@@ -34,15 +34,6 @@ struct host1x_cmdbuf {
34 u32 pad; 34 u32 pad;
35}; 35};
36 36
37struct host1x_reloc {
38 struct host1x_bo *cmdbuf;
39 u32 cmdbuf_offset;
40 struct host1x_bo *target;
41 u32 target_offset;
42 u32 shift;
43 u32 pad;
44};
45
46struct host1x_waitchk { 37struct host1x_waitchk {
47 struct host1x_bo *bo; 38 struct host1x_bo *bo;
48 u32 offset; 39 u32 offset;
@@ -56,105 +47,6 @@ struct host1x_job_unpin_data {
56}; 47};
57 48
58/* 49/*
59 * Each submit is tracked as a host1x_job.
60 */
61struct host1x_job {
62 /* When refcount goes to zero, job can be freed */
63 struct kref ref;
64
65 /* List entry */
66 struct list_head list;
67
68 /* Channel where job is submitted to */
69 struct host1x_channel *channel;
70
71 u32 client;
72
73 /* Gathers and their memory */
74 struct host1x_job_gather *gathers;
75 unsigned int num_gathers;
76
77 /* Wait checks to be processed at submit time */
78 struct host1x_waitchk *waitchk;
79 unsigned int num_waitchk;
80 u32 waitchk_mask;
81
82 /* Array of handles to be pinned & unpinned */
83 struct host1x_reloc *relocarray;
84 unsigned int num_relocs;
85 struct host1x_job_unpin_data *unpins;
86 unsigned int num_unpins;
87
88 dma_addr_t *addr_phys;
89 dma_addr_t *gather_addr_phys;
90 dma_addr_t *reloc_addr_phys;
91
92 /* Sync point id, number of increments and end related to the submit */
93 u32 syncpt_id;
94 u32 syncpt_incrs;
95 u32 syncpt_end;
96
97 /* Maximum time to wait for this job */
98 unsigned int timeout;
99
100 /* Index and number of slots used in the push buffer */
101 unsigned int first_get;
102 unsigned int num_slots;
103
104 /* Copy of gathers */
105 size_t gather_copy_size;
106 dma_addr_t gather_copy;
107 u8 *gather_copy_mapped;
108
109 /* Check if register is marked as an address reg */
110 int (*is_addr_reg)(struct device *dev, u32 reg, u32 class);
111
112 /* Request a SETCLASS to this class */
113 u32 class;
114
115 /* Add a channel wait for previous ops to complete */
116 bool serialize;
117};
118/*
119 * Allocate memory for a job. Just enough memory will be allocated to
120 * accomodate the submit.
121 */
122struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
123 u32 num_cmdbufs, u32 num_relocs,
124 u32 num_waitchks);
125
126/*
127 * Add a gather to a job.
128 */
129void host1x_job_add_gather(struct host1x_job *job, struct host1x_bo *mem_id,
130 u32 words, u32 offset);
131
132/*
133 * Increment reference going to host1x_job.
134 */
135struct host1x_job *host1x_job_get(struct host1x_job *job);
136
137/*
138 * Decrement reference job, free if goes to zero.
139 */
140void host1x_job_put(struct host1x_job *job);
141
142/*
143 * Pin memory related to job. This handles relocation of addresses to the
144 * host1x address space. Handles both the gather memory and any other memory
145 * referred to from the gather buffers.
146 *
147 * Handles also patching out host waits that would wait for an expired sync
148 * point value.
149 */
150int host1x_job_pin(struct host1x_job *job, struct device *dev);
151
152/*
153 * Unpin memory related to job.
154 */
155void host1x_job_unpin(struct host1x_job *job);
156
157/*
158 * Dump contents of job to debug output. 50 * Dump contents of job to debug output.
159 */ 51 */
160void host1x_job_dump(struct device *dev, struct host1x_job *job); 52void host1x_job_dump(struct device *dev, struct host1x_job *job);
diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c
index 409745b949db..159c479829c9 100644
--- a/drivers/gpu/host1x/syncpt.c
+++ b/drivers/gpu/host1x/syncpt.c
@@ -30,9 +30,32 @@
30#define SYNCPT_CHECK_PERIOD (2 * HZ) 30#define SYNCPT_CHECK_PERIOD (2 * HZ)
31#define MAX_STUCK_CHECK_COUNT 15 31#define MAX_STUCK_CHECK_COUNT 15
32 32
33static struct host1x_syncpt *_host1x_syncpt_alloc(struct host1x *host, 33static struct host1x_syncpt_base *
34 struct device *dev, 34host1x_syncpt_base_request(struct host1x *host)
35 bool client_managed) 35{
36 struct host1x_syncpt_base *bases = host->bases;
37 unsigned int i;
38
39 for (i = 0; i < host->info->nb_bases; i++)
40 if (!bases[i].requested)
41 break;
42
43 if (i >= host->info->nb_bases)
44 return NULL;
45
46 bases[i].requested = true;
47 return &bases[i];
48}
49
50static void host1x_syncpt_base_free(struct host1x_syncpt_base *base)
51{
52 if (base)
53 base->requested = false;
54}
55
56static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host,
57 struct device *dev,
58 unsigned long flags)
36{ 59{
37 int i; 60 int i;
38 struct host1x_syncpt *sp = host->syncpt; 61 struct host1x_syncpt *sp = host->syncpt;
@@ -44,6 +67,12 @@ static struct host1x_syncpt *_host1x_syncpt_alloc(struct host1x *host,
44 if (i >= host->info->nb_pts) 67 if (i >= host->info->nb_pts)
45 return NULL; 68 return NULL;
46 69
70 if (flags & HOST1X_SYNCPT_HAS_BASE) {
71 sp->base = host1x_syncpt_base_request(host);
72 if (!sp->base)
73 return NULL;
74 }
75
47 name = kasprintf(GFP_KERNEL, "%02d-%s", sp->id, 76 name = kasprintf(GFP_KERNEL, "%02d-%s", sp->id,
48 dev ? dev_name(dev) : NULL); 77 dev ? dev_name(dev) : NULL);
49 if (!name) 78 if (!name)
@@ -51,7 +80,11 @@ static struct host1x_syncpt *_host1x_syncpt_alloc(struct host1x *host,
51 80
52 sp->dev = dev; 81 sp->dev = dev;
53 sp->name = name; 82 sp->name = name;
54 sp->client_managed = client_managed; 83
84 if (flags & HOST1X_SYNCPT_CLIENT_MANAGED)
85 sp->client_managed = true;
86 else
87 sp->client_managed = false;
55 88
56 return sp; 89 return sp;
57} 90}
@@ -303,25 +336,35 @@ int host1x_syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr)
303 336
304int host1x_syncpt_init(struct host1x *host) 337int host1x_syncpt_init(struct host1x *host)
305{ 338{
339 struct host1x_syncpt_base *bases;
306 struct host1x_syncpt *syncpt; 340 struct host1x_syncpt *syncpt;
307 int i; 341 int i;
308 342
309 syncpt = devm_kzalloc(host->dev, sizeof(*syncpt) * host->info->nb_pts, 343 syncpt = devm_kzalloc(host->dev, sizeof(*syncpt) * host->info->nb_pts,
310 GFP_KERNEL); 344 GFP_KERNEL);
311 if (!syncpt) 345 if (!syncpt)
312 return -ENOMEM; 346 return -ENOMEM;
313 347
314 for (i = 0; i < host->info->nb_pts; ++i) { 348 bases = devm_kzalloc(host->dev, sizeof(*bases) * host->info->nb_bases,
349 GFP_KERNEL);
350 if (!bases)
351 return -ENOMEM;
352
353 for (i = 0; i < host->info->nb_pts; i++) {
315 syncpt[i].id = i; 354 syncpt[i].id = i;
316 syncpt[i].host = host; 355 syncpt[i].host = host;
317 } 356 }
318 357
358 for (i = 0; i < host->info->nb_bases; i++)
359 bases[i].id = i;
360
319 host->syncpt = syncpt; 361 host->syncpt = syncpt;
362 host->bases = bases;
320 363
321 host1x_syncpt_restore(host); 364 host1x_syncpt_restore(host);
322 365
323 /* Allocate sync point to use for clearing waits for expired fences */ 366 /* Allocate sync point to use for clearing waits for expired fences */
324 host->nop_sp = _host1x_syncpt_alloc(host, NULL, false); 367 host->nop_sp = host1x_syncpt_alloc(host, NULL, 0);
325 if (!host->nop_sp) 368 if (!host->nop_sp)
326 return -ENOMEM; 369 return -ENOMEM;
327 370
@@ -329,10 +372,10 @@ int host1x_syncpt_init(struct host1x *host)
329} 372}
330 373
331struct host1x_syncpt *host1x_syncpt_request(struct device *dev, 374struct host1x_syncpt *host1x_syncpt_request(struct device *dev,
332 bool client_managed) 375 unsigned long flags)
333{ 376{
334 struct host1x *host = dev_get_drvdata(dev->parent); 377 struct host1x *host = dev_get_drvdata(dev->parent);
335 return _host1x_syncpt_alloc(host, dev, client_managed); 378 return host1x_syncpt_alloc(host, dev, flags);
336} 379}
337 380
338void host1x_syncpt_free(struct host1x_syncpt *sp) 381void host1x_syncpt_free(struct host1x_syncpt *sp)
@@ -340,7 +383,9 @@ void host1x_syncpt_free(struct host1x_syncpt *sp)
340 if (!sp) 383 if (!sp)
341 return; 384 return;
342 385
386 host1x_syncpt_base_free(sp->base);
343 kfree(sp->name); 387 kfree(sp->name);
388 sp->base = NULL;
344 sp->dev = NULL; 389 sp->dev = NULL;
345 sp->name = NULL; 390 sp->name = NULL;
346 sp->client_managed = false; 391 sp->client_managed = false;
@@ -354,6 +399,25 @@ void host1x_syncpt_deinit(struct host1x *host)
354 kfree(sp->name); 399 kfree(sp->name);
355} 400}
356 401
402/*
403 * Read max. It indicates how many operations there are in queue, either in
404 * channel or in a software thread.
405 * */
406u32 host1x_syncpt_read_max(struct host1x_syncpt *sp)
407{
408 smp_rmb();
409 return (u32)atomic_read(&sp->max_val);
410}
411
412/*
413 * Read min, which is a shadow of the current sync point value in hardware.
414 */
415u32 host1x_syncpt_read_min(struct host1x_syncpt *sp)
416{
417 smp_rmb();
418 return (u32)atomic_read(&sp->min_val);
419}
420
357int host1x_syncpt_nb_pts(struct host1x *host) 421int host1x_syncpt_nb_pts(struct host1x *host)
358{ 422{
359 return host->info->nb_pts; 423 return host->info->nb_pts;
@@ -375,3 +439,13 @@ struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id)
375 return NULL; 439 return NULL;
376 return host->syncpt + id; 440 return host->syncpt + id;
377} 441}
442
443struct host1x_syncpt_base *host1x_syncpt_get_base(struct host1x_syncpt *sp)
444{
445 return sp ? sp->base : NULL;
446}
447
448u32 host1x_syncpt_base_id(struct host1x_syncpt_base *base)
449{
450 return base->id;
451}
diff --git a/drivers/gpu/host1x/syncpt.h b/drivers/gpu/host1x/syncpt.h
index 267c0b9d3647..9056465ecd3f 100644
--- a/drivers/gpu/host1x/syncpt.h
+++ b/drivers/gpu/host1x/syncpt.h
@@ -20,6 +20,7 @@
20#define __HOST1X_SYNCPT_H 20#define __HOST1X_SYNCPT_H
21 21
22#include <linux/atomic.h> 22#include <linux/atomic.h>
23#include <linux/host1x.h>
23#include <linux/kernel.h> 24#include <linux/kernel.h>
24#include <linux/sched.h> 25#include <linux/sched.h>
25 26
@@ -30,6 +31,11 @@ struct host1x;
30/* Reserved for replacing an expired wait with a NOP */ 31/* Reserved for replacing an expired wait with a NOP */
31#define HOST1X_SYNCPT_RESERVED 0 32#define HOST1X_SYNCPT_RESERVED 0
32 33
34struct host1x_syncpt_base {
35 unsigned int id;
36 bool requested;
37};
38
33struct host1x_syncpt { 39struct host1x_syncpt {
34 int id; 40 int id;
35 atomic_t min_val; 41 atomic_t min_val;
@@ -39,6 +45,7 @@ struct host1x_syncpt {
39 bool client_managed; 45 bool client_managed;
40 struct host1x *host; 46 struct host1x *host;
41 struct device *dev; 47 struct device *dev;
48 struct host1x_syncpt_base *base;
42 49
43 /* interrupt data */ 50 /* interrupt data */
44 struct host1x_syncpt_intr intr; 51 struct host1x_syncpt_intr intr;
@@ -50,25 +57,6 @@ int host1x_syncpt_init(struct host1x *host);
50/* Free sync point array */ 57/* Free sync point array */
51void host1x_syncpt_deinit(struct host1x *host); 58void host1x_syncpt_deinit(struct host1x *host);
52 59
53/*
54 * Read max. It indicates how many operations there are in queue, either in
55 * channel or in a software thread.
56 * */
57static inline u32 host1x_syncpt_read_max(struct host1x_syncpt *sp)
58{
59 smp_rmb();
60 return (u32)atomic_read(&sp->max_val);
61}
62
63/*
64 * Read min, which is a shadow of the current sync point value in hardware.
65 */
66static inline u32 host1x_syncpt_read_min(struct host1x_syncpt *sp)
67{
68 smp_rmb();
69 return (u32)atomic_read(&sp->min_val);
70}
71
72/* Return number of sync point supported. */ 60/* Return number of sync point supported. */
73int host1x_syncpt_nb_pts(struct host1x *host); 61int host1x_syncpt_nb_pts(struct host1x *host);
74 62
@@ -112,9 +100,6 @@ static inline bool host1x_syncpt_idle(struct host1x_syncpt *sp)
112 return (min == max); 100 return (min == max);
113} 101}
114 102
115/* Return pointer to struct denoting sync point id. */
116struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id);
117
118/* Load current value from hardware to the shadow register. */ 103/* Load current value from hardware to the shadow register. */
119u32 host1x_syncpt_load(struct host1x_syncpt *sp); 104u32 host1x_syncpt_load(struct host1x_syncpt *sp);
120 105
@@ -130,16 +115,9 @@ void host1x_syncpt_restore(struct host1x *host);
130/* Read current wait base value into shadow register and return it. */ 115/* Read current wait base value into shadow register and return it. */
131u32 host1x_syncpt_load_wait_base(struct host1x_syncpt *sp); 116u32 host1x_syncpt_load_wait_base(struct host1x_syncpt *sp);
132 117
133/* Request incrementing a sync point. */
134int host1x_syncpt_incr(struct host1x_syncpt *sp);
135
136/* Indicate future operations by incrementing the sync point max. */ 118/* Indicate future operations by incrementing the sync point max. */
137u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs); 119u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs);
138 120
139/* Wait until sync point reaches a threshold value, or a timeout. */
140int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh,
141 long timeout, u32 *value);
142
143/* Check if sync point id is valid. */ 121/* Check if sync point id is valid. */
144static inline int host1x_syncpt_is_valid(struct host1x_syncpt *sp) 122static inline int host1x_syncpt_is_valid(struct host1x_syncpt *sp)
145{ 123{
@@ -149,14 +127,4 @@ static inline int host1x_syncpt_is_valid(struct host1x_syncpt *sp)
149/* Patch a wait by replacing it with a wait for syncpt 0 value 0 */ 127/* Patch a wait by replacing it with a wait for syncpt 0 value 0 */
150int host1x_syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr); 128int host1x_syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr);
151 129
152/* Return id of the sync point */
153u32 host1x_syncpt_id(struct host1x_syncpt *sp);
154
155/* Allocate a sync point for a device. */
156struct host1x_syncpt *host1x_syncpt_request(struct device *dev,
157 bool client_managed);
158
159/* Free a sync point. */
160void host1x_syncpt_free(struct host1x_syncpt *sp);
161
162#endif 130#endif