OSDN Git Service

libkms/radeon: Add backend
[android-x86/external-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 int
30 nouveau_device_open_existing(struct nouveau_device **dev, int close,
31                              int fd, drm_context_t ctx)
32 {
33         struct nouveau_device_priv *nvdev;
34         drmVersionPtr ver;
35         uint64_t value;
36         int ret;
37
38         if (!dev || *dev)
39             return -EINVAL;
40
41         nvdev = calloc(1, sizeof(*nvdev));
42         if (!nvdev)
43             return -ENOMEM;
44         nvdev->fd = fd;
45         nvdev->ctx = ctx;
46         nvdev->needs_close = close;
47
48         ver = drmGetVersion(fd);
49         if (!ver)
50                 return -EINVAL;
51
52         if ((ver->version_major == 0 && ver->version_patchlevel != 16) ||
53              ver->version_major > 1) {
54                 nouveau_device_close((void *)&nvdev);
55                 return -EINVAL;
56         }
57
58         drmFreeVersion(ver);
59
60         ret = nouveau_device_get_param(&nvdev->base,
61                                        NOUVEAU_GETPARAM_VM_VRAM_BASE, &value);
62         if (ret) {
63                 nouveau_device_close((void *)&nvdev);
64                 return ret;
65         }
66         nvdev->base.vm_vram_base = value;
67
68         ret = nouveau_device_get_param(&nvdev->base,
69                                        NOUVEAU_GETPARAM_FB_SIZE, &value);
70         if (ret) {
71                 nouveau_device_close((void *)&nvdev);
72                 return ret;
73         }
74         nvdev->base.vm_vram_size = value;
75
76         ret = nouveau_device_get_param(&nvdev->base,
77                                        NOUVEAU_GETPARAM_AGP_SIZE, &value);
78         if (ret) {
79                 nouveau_device_close((void *)&nvdev);
80                 return ret;
81         }
82         nvdev->base.vm_gart_size = value;
83
84         ret = nouveau_bo_init(&nvdev->base);
85         if (ret) {
86                 nouveau_device_close((void *)&nvdev);
87                 return ret;
88         }
89
90         ret = nouveau_device_get_param(&nvdev->base,
91                                        NOUVEAU_GETPARAM_CHIPSET_ID, &value);
92         if (ret) {
93                 nouveau_device_close((void *)&nvdev);
94                 return ret;
95         }
96         nvdev->base.chipset = value;
97
98         ret = nouveau_device_get_param(&nvdev->base,
99                                        NOUVEAU_GETPARAM_HAS_BO_USAGE, &value);
100         if (!ret)
101                 nvdev->has_bo_usage = value;
102
103         *dev = &nvdev->base;
104         return 0;
105 }
106
107 int
108 nouveau_device_open(struct nouveau_device **dev, const char *busid)
109 {
110         drm_context_t ctx;
111         int fd, ret;
112
113         if (!dev || *dev)
114                 return -EINVAL;
115
116         fd = drmOpen("nouveau", busid);
117         if (fd < 0)
118                 return -EINVAL;
119
120         ret = drmCreateContext(fd, &ctx);
121         if (ret) {
122                 drmClose(fd);
123                 return ret;
124         }
125
126         ret = nouveau_device_open_existing(dev, 1, fd, ctx);
127         if (ret) {
128             drmDestroyContext(fd, ctx);
129             drmClose(fd);
130             return ret;
131         }
132
133         return 0;
134 }
135
136 void
137 nouveau_device_close(struct nouveau_device **dev)
138 {
139         struct nouveau_device_priv *nvdev;
140
141         if (!dev || !*dev)
142                 return;
143         nvdev = nouveau_device(*dev);
144         *dev = NULL;
145
146         nouveau_bo_takedown(&nvdev->base);
147
148         if (nvdev->needs_close) {
149                 drmDestroyContext(nvdev->fd, nvdev->ctx);
150                 drmClose(nvdev->fd);
151         }
152         free(nvdev);
153 }
154
155 int
156 nouveau_device_get_param(struct nouveau_device *dev,
157                          uint64_t param, uint64_t *value)
158 {
159         struct nouveau_device_priv *nvdev = nouveau_device(dev);
160         struct drm_nouveau_getparam g;
161         int ret;
162
163         if (!nvdev || !value)
164                 return -EINVAL;
165
166         g.param = param;
167         ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GETPARAM,
168                                   &g, sizeof(g));
169         if (ret)
170                 return ret;
171
172         *value = g.value;
173         return 0;
174 }
175
176 int
177 nouveau_device_set_param(struct nouveau_device *dev,
178                          uint64_t param, uint64_t value)
179 {
180         struct nouveau_device_priv *nvdev = nouveau_device(dev);
181         struct drm_nouveau_setparam s;
182         int ret;
183
184         if (!nvdev)
185                 return -EINVAL;
186
187         s.param = param;
188         s.value = value;
189         ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_SETPARAM,
190                                   &s, sizeof(s));
191         if (ret)
192                 return ret;
193
194         return 0;
195 }
196