nouveau: add BEGIN_RING_NI
[profile/ivi/libdrm.git] / nouveau / nouveau_device.c
1 /*
2  * Copyright 2007 Nouveau Project
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <errno.h>
26
27 #include "nouveau_private.h"
28
29 #if NOUVEAU_DRM_HEADER_PATCHLEVEL != 15
30 #error nouveau_drm.h does not match expected patchlevel, update libdrm.
31 #endif
32
33 int
34 nouveau_device_open_existing(struct nouveau_device **dev, int close,
35                              int fd, drm_context_t ctx)
36 {
37         struct nouveau_device_priv *nvdev;
38         drmVersionPtr ver;
39         uint64_t value;
40         int ret;
41
42         if (!dev || *dev)
43             return -EINVAL;
44
45         ver = drmGetVersion(fd);
46         if (!ver || ver->version_patchlevel != NOUVEAU_DRM_HEADER_PATCHLEVEL)
47                 return -EINVAL;
48         drmFreeVersion(ver);
49
50         nvdev = calloc(1, sizeof(*nvdev));
51         if (!nvdev)
52             return -ENOMEM;
53         nvdev->fd = fd;
54         nvdev->ctx = ctx;
55         nvdev->needs_close = close;
56
57         ret = drmCommandNone(nvdev->fd, DRM_NOUVEAU_CARD_INIT);
58         if (ret) {
59                 nouveau_device_close((void *)&nvdev);
60                 return ret;
61         }
62
63         ret = nouveau_device_get_param(&nvdev->base,
64                                        NOUVEAU_GETPARAM_VM_VRAM_BASE, &value);
65         if (ret) {
66                 nouveau_device_close((void *)&nvdev);
67                 return ret;
68         }
69         nvdev->base.vm_vram_base = value;
70
71         ret = nouveau_device_get_param(&nvdev->base,
72                                        NOUVEAU_GETPARAM_FB_SIZE, &value);
73         if (ret) {
74                 nouveau_device_close((void *)&nvdev);
75                 return ret;
76         }
77         nvdev->base.vm_vram_size = value;
78
79         ret = nouveau_device_get_param(&nvdev->base,
80                                        NOUVEAU_GETPARAM_AGP_SIZE, &value);
81         if (ret) {
82                 nouveau_device_close((void *)&nvdev);
83                 return ret;
84         }
85         nvdev->base.vm_gart_size = value;
86
87         ret = nouveau_bo_init(&nvdev->base);
88         if (ret) {
89                 nouveau_device_close((void *)&nvdev);
90                 return ret;
91         }
92
93         ret = nouveau_device_get_param(&nvdev->base,
94                                        NOUVEAU_GETPARAM_CHIPSET_ID, &value);
95         if (ret) {
96                 nouveau_device_close((void *)&nvdev);
97                 return ret;
98         }
99         nvdev->base.chipset = value;
100
101         *dev = &nvdev->base;
102         return 0;
103 }
104
105 int
106 nouveau_device_open(struct nouveau_device **dev, const char *busid)
107 {
108         drm_context_t ctx;
109         int fd, ret;
110
111         if (!dev || *dev)
112                 return -EINVAL;
113
114         fd = drmOpen("nouveau", busid);
115         if (fd < 0)
116                 return -EINVAL;
117
118         ret = drmCreateContext(fd, &ctx);
119         if (ret) {
120                 drmClose(fd);
121                 return ret;
122         }
123
124         ret = nouveau_device_open_existing(dev, 1, fd, ctx);
125         if (ret) {
126             drmDestroyContext(fd, ctx);
127             drmClose(fd);
128             return ret;
129         }
130
131         return 0;
132 }
133
134 void
135 nouveau_device_close(struct nouveau_device **dev)
136 {
137         struct nouveau_device_priv *nvdev;
138
139         if (!dev || !*dev)
140                 return;
141         nvdev = nouveau_device(*dev);
142         *dev = NULL;
143
144         nouveau_bo_takedown(&nvdev->base);
145
146         if (nvdev->needs_close) {
147                 drmDestroyContext(nvdev->fd, nvdev->ctx);
148                 drmClose(nvdev->fd);
149         }
150         free(nvdev);
151 }
152
153 int
154 nouveau_device_get_param(struct nouveau_device *dev,
155                          uint64_t param, uint64_t *value)
156 {
157         struct nouveau_device_priv *nvdev = nouveau_device(dev);
158         struct drm_nouveau_getparam g;
159         int ret;
160
161         if (!nvdev || !value)
162                 return -EINVAL;
163
164         g.param = param;
165         ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GETPARAM,
166                                   &g, sizeof(g));
167         if (ret)
168                 return ret;
169
170         *value = g.value;
171         return 0;
172 }
173
174 int
175 nouveau_device_set_param(struct nouveau_device *dev,
176                          uint64_t param, uint64_t value)
177 {
178         struct nouveau_device_priv *nvdev = nouveau_device(dev);
179         struct drm_nouveau_setparam s;
180         int ret;
181
182         if (!nvdev)
183                 return -EINVAL;
184
185         s.param = param;
186         s.value = value;
187         ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_SETPARAM,
188                                   &s, sizeof(s));
189         if (ret)
190                 return ret;
191
192         return 0;
193 }
194