video: tegra: host: Move device data to nvhost_device
[linux-2.6.git] / drivers / video / tegra / host / nvhost_channel.c
1 /*
2  * drivers/video/tegra/host/nvhost_channel.c
3  *
4  * Tegra Graphics Host Channel
5  *
6  * Copyright (c) 2010-2011, NVIDIA Corporation.
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 as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  * more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  */
22
23 #include "nvhost_channel.h"
24 #include "dev.h"
25 #include "nvhost_hwctx.h"
26 #include "nvhost_job.h"
27 #include <trace/events/nvhost.h>
28 #include <linux/nvhost_ioctl.h>
29 #include <linux/slab.h>
30
31 #include <linux/platform_device.h>
32
33 #define NVHOST_CHANNEL_LOW_PRIO_MAX_WAIT 50
34
35 int nvhost_channel_submit(struct nvhost_job *job)
36 {
37         /* Low priority submits wait until sync queue is empty. Ignores result
38          * from nvhost_cdma_flush, as we submit either when push buffer is
39          * empty or when we reach the timeout. */
40         if (job->priority < NVHOST_PRIORITY_MEDIUM)
41                 (void)nvhost_cdma_flush(&job->ch->cdma,
42                                 NVHOST_CHANNEL_LOW_PRIO_MAX_WAIT);
43
44         return channel_op(job->ch).submit(job);
45 }
46
47 struct nvhost_channel *nvhost_getchannel(struct nvhost_channel *ch)
48 {
49         int err = 0;
50         mutex_lock(&ch->reflock);
51         if (ch->refcount == 0) {
52                 err = nvhost_module_init(ch->dev);
53                 if (!err) {
54                         err = nvhost_cdma_init(&ch->cdma);
55                         if (err)
56                                 nvhost_module_deinit(ch->dev);
57                 }
58         } else if (ch->dev->exclusive) {
59                 err = -EBUSY;
60         }
61         if (!err)
62                 ch->refcount++;
63
64         mutex_unlock(&ch->reflock);
65
66         /* Keep alive modules that needs to be when a channel is open */
67         if (!err && ch->dev->keepalive)
68                 nvhost_module_busy(ch->dev);
69
70         return err ? NULL : ch;
71 }
72
73 void nvhost_putchannel(struct nvhost_channel *ch, struct nvhost_hwctx *ctx)
74 {
75         BUG_ON(!channel_cdma_op(ch).stop);
76
77         if (ctx) {
78                 mutex_lock(&ch->submitlock);
79                 if (ch->cur_ctx == ctx)
80                         ch->cur_ctx = NULL;
81                 mutex_unlock(&ch->submitlock);
82         }
83
84         /* Allow keep-alive'd module to be turned off */
85         if (ch->dev->keepalive)
86                 nvhost_module_idle(ch->dev);
87
88         mutex_lock(&ch->reflock);
89         if (ch->refcount == 1) {
90                 channel_cdma_op(ch).stop(&ch->cdma);
91                 nvhost_cdma_deinit(&ch->cdma);
92                 nvhost_module_deinit(ch->dev);
93         }
94         ch->refcount--;
95         mutex_unlock(&ch->reflock);
96 }
97
98 int nvhost_channel_suspend(struct nvhost_channel *ch)
99 {
100         int ret = 0;
101
102         mutex_lock(&ch->reflock);
103         BUG_ON(!channel_cdma_op(ch).stop);
104
105         if (ch->refcount) {
106                 ret = nvhost_module_suspend(ch->dev, false);
107                 if (!ret)
108                         channel_cdma_op(ch).stop(&ch->cdma);
109         }
110         mutex_unlock(&ch->reflock);
111
112         return ret;
113 }