OSDN Git Service

r300: Use the defined names for known registers.
[android-x86/external-libdrm.git] / shared-core / nouveau_state.c
1 /* 
2  * Copyright 2005 Stephane Marchesin
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24
25 #include "drmP.h"
26 #include "drm.h"
27 #include "drm_sarea.h"
28 #include "nouveau_drv.h"
29 #include "nouveau_drm.h"
30
31 static int nouveau_init_card_mappings(drm_device_t *dev)
32 {
33         drm_nouveau_private_t *dev_priv = dev->dev_private;
34         int ret;
35
36         /* resource 0 is mmio regs */
37         /* resource 1 is linear FB */
38         /* resource 2 is RAMIN (mmio regs + 0x1000000) */
39         /* resource 6 is bios */
40
41         /* map the mmio regs */
42         ret = drm_addmap(dev, drm_get_resource_start(dev, 0),
43                               drm_get_resource_len(dev, 0), 
44                               _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio);
45         if (ret) {
46                 DRM_ERROR("Unable to initialize the mmio mapping (%d). "
47                           "Please report your setup to " DRIVER_EMAIL "\n",
48                           ret);
49                 return 1;
50         }
51         DRM_DEBUG("regs mapped ok at 0x%lx\n", dev_priv->mmio->offset);
52
53         /* map larger RAMIN aperture on NV40 cards */
54         if (dev_priv->card_type >= NV_40) {
55                 int ramin_resource = 2;
56                 if (drm_get_resource_len(dev, ramin_resource) == 0)
57                         ramin_resource = 3;
58
59                 ret = drm_addmap(dev,
60                                  drm_get_resource_start(dev, ramin_resource),
61                                  drm_get_resource_len(dev, ramin_resource),
62                                  _DRM_REGISTERS, _DRM_READ_ONLY,
63                                  &dev_priv->ramin);
64                 if (ret) {
65                         DRM_ERROR("Failed to init RAMIN mapping, "
66                                   "limited instance memory available\n");
67                         dev_priv->ramin = NULL;
68                 }
69         } else
70                 dev_priv->ramin = NULL;
71
72         return 0;
73 }
74
75 static void nouveau_stub_takedown(drm_device_t *dev) {}
76 static int nouveau_init_engine_ptrs(drm_device_t *dev)
77 {
78         drm_nouveau_private_t *dev_priv = dev->dev_private;
79         struct nouveau_engine_func *engine = &dev_priv->Engine;
80
81         switch (dev_priv->chipset & 0xf0) {
82         case 0x00:
83                 engine->Mc.Init         = nv04_mc_init;
84                 engine->Mc.Takedown     = nv04_mc_takedown;
85                 engine->Timer.Init      = nv04_timer_init;
86                 engine->Timer.Takedown  = nv04_timer_takedown;
87                 engine->Fb.Init         = nv04_fb_init;
88                 engine->Fb.Takedown     = nv04_fb_takedown;
89                 engine->Graph.Init      = nv04_graph_init;
90                 engine->Graph.Takedown  = nv04_graph_takedown;
91                 engine->Fifo.Init       = nouveau_fifo_init;
92                 engine->Fifo.Takedown   = nouveau_stub_takedown;
93                 break;
94         case 0x10:
95                 engine->Mc.Init         = nv04_mc_init;
96                 engine->Mc.Takedown     = nv04_mc_takedown;
97                 engine->Timer.Init      = nv04_timer_init;
98                 engine->Timer.Takedown  = nv04_timer_takedown;
99                 engine->Fb.Init         = nv10_fb_init;
100                 engine->Fb.Takedown     = nv10_fb_takedown;
101                 engine->Graph.Init      = nv10_graph_init;
102                 engine->Graph.Takedown  = nv10_graph_takedown;
103                 engine->Fifo.Init       = nouveau_fifo_init;
104                 engine->Fifo.Takedown   = nouveau_stub_takedown;
105                 break;
106         case 0x20:
107                 engine->Mc.Init         = nv04_mc_init;
108                 engine->Mc.Takedown     = nv04_mc_takedown;
109                 engine->Timer.Init      = nv04_timer_init;
110                 engine->Timer.Takedown  = nv04_timer_takedown;
111                 engine->Fb.Init         = nv10_fb_init;
112                 engine->Fb.Takedown     = nv10_fb_takedown;
113                 engine->Graph.Init      = nv20_graph_init;
114                 engine->Graph.Takedown  = nv20_graph_takedown;
115                 engine->Fifo.Init       = nouveau_fifo_init;
116                 engine->Fifo.Takedown   = nouveau_stub_takedown;
117                 break;
118         case 0x30:
119                 engine->Mc.Init         = nv04_mc_init;
120                 engine->Mc.Takedown     = nv04_mc_takedown;
121                 engine->Timer.Init      = nv04_timer_init;
122                 engine->Timer.Takedown  = nv04_timer_takedown;
123                 engine->Fb.Init         = nv10_fb_init;
124                 engine->Fb.Takedown     = nv10_fb_takedown;
125                 engine->Graph.Init      = nv30_graph_init;
126                 engine->Graph.Takedown  = nv30_graph_takedown;
127                 engine->Fifo.Init       = nouveau_fifo_init;
128                 engine->Fifo.Takedown   = nouveau_stub_takedown;
129                 break;
130         case 0x40:
131                 engine->Mc.Init         = nv40_mc_init;
132                 engine->Mc.Takedown     = nv40_mc_takedown;
133                 engine->Timer.Init      = nv04_timer_init;
134                 engine->Timer.Takedown  = nv04_timer_takedown;
135                 engine->Fb.Init         = nv40_fb_init;
136                 engine->Fb.Takedown     = nv40_fb_takedown;
137                 engine->Graph.Init      = nv40_graph_init;
138                 engine->Graph.Takedown  = nv40_graph_takedown;
139                 engine->Fifo.Init       = nouveau_fifo_init;
140                 engine->Fifo.Takedown   = nouveau_stub_takedown;
141                 break;
142         case 0x50:
143         default:
144                 DRM_ERROR("NV%02x unsupported\n", dev_priv->chipset);
145                 return 1;
146         }
147
148         return 0;
149 }
150
151 static int nouveau_card_init(drm_device_t *dev)
152 {
153         drm_nouveau_private_t *dev_priv = dev->dev_private;
154         struct nouveau_engine_func *engine;
155         int ret;
156
157         /* Map any PCI resources we need on the card */
158         ret = nouveau_init_card_mappings(dev);
159         if (ret) return ret;
160
161         /* Determine exact chipset we're running on */
162         if (dev_priv->card_type < NV_10)
163                 dev_priv->chipset = dev_priv->card_type;
164         else
165                 dev_priv->chipset =
166                         (NV_READ(NV03_PMC_BOOT_0) & 0x0ff00000) >> 20;
167
168         /* Initialise internal driver API hooks */
169         ret = nouveau_init_engine_ptrs(dev);
170         if (ret) return ret;
171         engine = &dev_priv->Engine;
172
173         /* Initialise instance memory, must happen before mem_init so we
174          * know exactly how much VRAM we're able to use for "normal"
175          * purposes.
176          */
177         ret = nouveau_instmem_init(dev);
178         if (ret) return ret;
179
180         /* Setup the memory manager */
181         ret = nouveau_mem_init(dev);
182         if (ret) return ret;
183
184         /* Parse BIOS tables / Run init tables? */
185
186         /* PMC */
187         ret = engine->Mc.Init(dev);
188         if (ret) return ret;
189
190         /* PTIMER */
191         ret = engine->Timer.Init(dev);
192         if (ret) return ret;
193
194         /* PFB */
195         ret = engine->Fb.Init(dev);
196         if (ret) return ret;
197
198         /* PGRAPH */
199         ret = engine->Graph.Init(dev);
200         if (ret) return ret;
201
202         /* PFIFO */
203         ret = engine->Fifo.Init(dev);
204         if (ret) return ret;
205
206         /* what about PVIDEO/PCRTC/PRAMDAC etc? */
207
208         return 0;
209 }
210
211 /* here a client dies, release the stuff that was allocated for its filp */
212 void nouveau_preclose(drm_device_t * dev, DRMFILE filp)
213 {
214         drm_nouveau_private_t *dev_priv = dev->dev_private;
215
216         nouveau_mem_release(filp,dev_priv->fb_heap);
217         nouveau_mem_release(filp,dev_priv->agp_heap);
218         nouveau_fifo_cleanup(dev, filp);
219 }
220
221 /* first module load, setup the mmio/fb mapping */
222 int nouveau_firstopen(struct drm_device *dev)
223 {
224         int ret;
225
226         ret = nouveau_card_init(dev);
227         if (ret) {
228                 DRM_ERROR("nouveau_card_init() failed! (%d)\n", ret);
229                 return ret;
230         }
231
232         return 0;
233 }
234
235 int nouveau_load(struct drm_device *dev, unsigned long flags)
236 {
237         drm_nouveau_private_t *dev_priv;
238         int ret;
239
240         if (flags==NV_UNKNOWN)
241                 return DRM_ERR(EINVAL);
242
243         dev_priv = drm_alloc(sizeof(drm_nouveau_private_t), DRM_MEM_DRIVER);
244         if (!dev_priv)                   
245                 return DRM_ERR(ENOMEM);
246
247         memset(dev_priv, 0, sizeof(drm_nouveau_private_t));
248         dev_priv->card_type=flags&NOUVEAU_FAMILY;
249         dev_priv->flags=flags&NOUVEAU_FLAGS;
250
251         dev->dev_private = (void *)dev_priv;
252
253 #if 0
254         ret = nouveau_card_init(dev);
255         if (ret) {
256                 DRM_ERROR("nouveau_card_init() failed! (%d)\n", ret);
257                 return ret;
258         }
259 #endif
260
261         return 0;
262 }
263
264 void nouveau_lastclose(struct drm_device *dev)
265 {
266         drm_nouveau_private_t *dev_priv = dev->dev_private;
267         if(dev_priv->fb_mtrr>0)
268         {
269                 drm_mtrr_del(dev_priv->fb_mtrr, drm_get_resource_start(dev, 1),nouveau_mem_fb_amount(dev), DRM_MTRR_WC);
270                 dev_priv->fb_mtrr=0;
271         }
272 }
273
274 int nouveau_unload(struct drm_device *dev)
275 {
276         drm_free(dev->dev_private, sizeof(*dev->dev_private), DRM_MEM_DRIVER);
277         dev->dev_private = NULL;
278         return 0;
279 }
280
281 int nouveau_ioctl_getparam(DRM_IOCTL_ARGS)
282 {
283         DRM_DEVICE;
284         drm_nouveau_private_t *dev_priv = dev->dev_private;
285         drm_nouveau_getparam_t getparam;
286
287         DRM_COPY_FROM_USER_IOCTL(getparam, (drm_nouveau_getparam_t __user *)data,
288                         sizeof(getparam));
289
290         switch (getparam.param) {
291         case NOUVEAU_GETPARAM_PCI_VENDOR:
292                 getparam.value=dev->pci_vendor;
293                 break;
294         case NOUVEAU_GETPARAM_PCI_DEVICE:
295                 getparam.value=dev->pci_device;
296                 break;
297         case NOUVEAU_GETPARAM_BUS_TYPE:
298                 if (drm_device_is_agp(dev))
299                         getparam.value=NV_AGP;
300                 else if (drm_device_is_pcie(dev))
301                         getparam.value=NV_PCIE;
302                 else
303                         getparam.value=NV_PCI;
304                 break;
305         case NOUVEAU_GETPARAM_FB_PHYSICAL:
306                 getparam.value=dev_priv->fb_phys;
307                 break;
308         case NOUVEAU_GETPARAM_AGP_PHYSICAL:
309                 getparam.value=dev_priv->agp_phys;
310                 break;
311         case NOUVEAU_GETPARAM_FB_SIZE:
312                 getparam.value=dev_priv->fb_available_size;
313                 break;
314         case NOUVEAU_GETPARAM_AGP_SIZE:
315                 getparam.value=dev_priv->agp_available_size;
316                 break;
317         default:
318                 DRM_ERROR("unknown parameter %lld\n", getparam.param);
319                 return DRM_ERR(EINVAL);
320         }
321
322         DRM_COPY_TO_USER_IOCTL((drm_nouveau_getparam_t __user *)data, getparam,
323                         sizeof(getparam));
324         return 0;
325 }
326
327 int nouveau_ioctl_setparam(DRM_IOCTL_ARGS)
328 {
329         DRM_DEVICE;
330         drm_nouveau_private_t *dev_priv = dev->dev_private;
331         drm_nouveau_setparam_t setparam;
332
333         DRM_COPY_FROM_USER_IOCTL(setparam, (drm_nouveau_setparam_t __user *)data,
334                         sizeof(setparam));
335
336         switch (setparam.param) {
337         case NOUVEAU_SETPARAM_CMDBUF_LOCATION:
338                 switch (setparam.value) {
339                 case NOUVEAU_MEM_AGP:
340                 case NOUVEAU_MEM_FB:
341                         break;
342                 default:
343                         DRM_ERROR("invalid CMDBUF_LOCATION value=%lld\n",
344                                         setparam.value);
345                         return DRM_ERR(EINVAL);
346                 }
347                 dev_priv->config.cmdbuf.location = setparam.value;
348                 break;
349         case NOUVEAU_SETPARAM_CMDBUF_SIZE:
350                 dev_priv->config.cmdbuf.size = setparam.value;
351                 break;
352         default:
353                 DRM_ERROR("unknown parameter %lld\n", setparam.param);
354                 return DRM_ERR(EINVAL);
355         }
356
357         return 0;
358 }
359
360 /* waits for idle */
361 void nouveau_wait_for_idle(struct drm_device *dev)
362 {
363         drm_nouveau_private_t *dev_priv=dev->dev_private;
364         switch(dev_priv->card_type)
365         {
366                 case NV_03:
367                         while(NV_READ(NV03_PGRAPH_STATUS));
368                         break;
369                 default:
370                         while(NV_READ(NV04_PGRAPH_STATUS));
371                         break;
372         }
373 }
374
375