OSDN Git Service

nouveau: nv20 graph ctx switch.
[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
30 /* here a client dies, release the stuff that was allocated for its filp */
31 void nouveau_preclose(drm_device_t * dev, DRMFILE filp)
32 {
33         drm_nouveau_private_t *dev_priv = dev->dev_private;
34
35         nouveau_mem_release(filp,dev_priv->fb_heap);
36         nouveau_mem_release(filp,dev_priv->agp_heap);
37         nouveau_object_cleanup(dev, filp);
38         nouveau_fifo_cleanup(dev, filp);
39 }
40
41 /* first module load, setup the mmio/fb mapping */
42 int nouveau_firstopen(struct drm_device *dev)
43 {
44         int ret;
45         drm_nouveau_private_t *dev_priv = dev->dev_private;
46
47         /* resource 0 is mmio regs */
48         /* resource 1 is linear FB */
49         /* resource 2 is RAMIN (mmio regs + 0x1000000) */
50         /* resource 6 is bios */
51
52         /* map the mmio regs */
53         ret = drm_addmap(dev, drm_get_resource_start(dev, 0), drm_get_resource_len(dev, 0), 
54                         _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio);
55         if (dev_priv->mmio)
56         {
57                 DRM_INFO("regs mapped ok at 0x%lx\n",dev_priv->mmio->offset);
58         }
59         else
60         {
61                 DRM_ERROR("Unable to initialize the mmio mapping. Please report your setup to " DRIVER_EMAIL "\n");
62                 return 1; 
63         }
64
65         DRM_INFO("%lld MB of video ram detected\n",nouveau_mem_fb_amount(dev)>>20);
66
67         /* map larger RAMIN aperture on NV40 cards */
68         if (dev_priv->card_type >= NV_40) {
69                 int ramin_resource = 2;
70                 if (drm_get_resource_len(dev, ramin_resource) == 0)
71                         ramin_resource = 3;
72
73                 ret = drm_addmap(dev, drm_get_resource_start(dev, ramin_resource),
74                                       drm_get_resource_len(dev, ramin_resource),
75                                       _DRM_REGISTERS,
76                                       _DRM_READ_ONLY,
77                                       &dev_priv->ramin);
78                 if (ret) {
79                         DRM_ERROR("Failed to init RAMIN mapping, "
80                                   "limited instance memory available\n");
81                         dev_priv->ramin = NULL;
82                 }
83         } else
84                 dev_priv->ramin = NULL;
85
86         /* Clear RAMIN
87          * Determine locations for RAMHT/FC/RO
88          * Initialise PFIFO
89          */
90         ret = nouveau_fifo_init(dev);
91         if (ret) return ret;
92
93         /* setup a mtrr over the FB */
94         dev_priv->fb_mtrr=drm_mtrr_add(drm_get_resource_start(dev, 1),nouveau_mem_fb_amount(dev), DRM_MTRR_WC);
95
96         /* FIXME: doesn't belong here, and have no idea what it's for.. */
97         if (dev_priv->card_type >= NV_40)
98                 nv40_graph_init(dev);
99         else if (dev_priv->card_type >= NV_30) {
100         }
101         else if (dev_priv->card_type >= NV_20)
102                 nv20_graph_init(dev);
103         else if (dev_priv->card_type >= NV_10)
104                 nv10_graph_init(dev);
105
106         return 0;
107 }
108
109 int nouveau_load(struct drm_device *dev, unsigned long flags)
110 {
111         drm_nouveau_private_t *dev_priv;
112
113         if (flags==NV_UNKNOWN)
114                 return DRM_ERR(EINVAL);
115
116         dev_priv = drm_alloc(sizeof(drm_nouveau_private_t), DRM_MEM_DRIVER);
117         if (!dev_priv)                   
118                 return DRM_ERR(ENOMEM);
119
120         memset(dev_priv, 0, sizeof(drm_nouveau_private_t));
121         dev_priv->card_type=flags&NOUVEAU_FAMILY;
122         dev_priv->flags=flags&NOUVEAU_FLAGS;
123
124         dev->dev_private = (void *)dev_priv;
125
126         return 0;
127 }
128
129 void nouveau_lastclose(struct drm_device *dev)
130 {
131         drm_nouveau_private_t *dev_priv = dev->dev_private;
132         if(dev_priv->fb_mtrr>0)
133         {
134                 drm_mtrr_del(dev_priv->fb_mtrr, drm_get_resource_start(dev, 1),nouveau_mem_fb_amount(dev), DRM_MTRR_WC);
135                 dev_priv->fb_mtrr=0;
136         }
137 }
138
139 int nouveau_unload(struct drm_device *dev)
140 {
141         drm_free(dev->dev_private, sizeof(*dev->dev_private), DRM_MEM_DRIVER);
142         dev->dev_private = NULL;
143         return 0;
144 }
145
146 int nouveau_ioctl_getparam(DRM_IOCTL_ARGS)
147 {
148         DRM_DEVICE;
149         drm_nouveau_private_t *dev_priv = dev->dev_private;
150         drm_nouveau_getparam_t getparam;
151
152         DRM_COPY_FROM_USER_IOCTL(getparam, (drm_nouveau_getparam_t __user *)data,
153                         sizeof(getparam));
154
155         switch (getparam.param) {
156         case NOUVEAU_GETPARAM_PCI_VENDOR:
157                 getparam.value=dev->pci_vendor;
158                 break;
159         case NOUVEAU_GETPARAM_PCI_DEVICE:
160                 getparam.value=dev->pci_device;
161                 break;
162         case NOUVEAU_GETPARAM_BUS_TYPE:
163                 if (drm_device_is_agp(dev))
164                         getparam.value=NV_AGP;
165                 else if (drm_device_is_pcie(dev))
166                         getparam.value=NV_PCIE;
167                 else
168                         getparam.value=NV_PCI;
169                 break;
170         case NOUVEAU_GETPARAM_FB_PHYSICAL:
171                 getparam.value=dev_priv->fb_phys;
172                 break;
173         case NOUVEAU_GETPARAM_AGP_PHYSICAL:
174                 getparam.value=dev_priv->agp_phys;
175                 break;
176         default:
177                 DRM_ERROR("unknown parameter %d\n", getparam.param);
178                 return DRM_ERR(EINVAL);
179         }
180
181         DRM_COPY_TO_USER_IOCTL((drm_nouveau_getparam_t __user *)data, getparam,
182                         sizeof(getparam));
183         return 0;
184 }
185
186 int nouveau_ioctl_setparam(DRM_IOCTL_ARGS)
187 {
188         DRM_DEVICE;
189         drm_nouveau_private_t *dev_priv = dev->dev_private;
190         drm_nouveau_setparam_t setparam;
191
192         DRM_COPY_FROM_USER_IOCTL(setparam, (drm_nouveau_setparam_t __user *)data,
193                         sizeof(setparam));
194
195         switch (setparam.param) {
196         case NOUVEAU_SETPARAM_CMDBUF_LOCATION:
197                 switch (setparam.value) {
198                 case NOUVEAU_MEM_AGP:
199                 case NOUVEAU_MEM_FB:
200                         break;
201                 default:
202                         DRM_ERROR("invalid CMDBUF_LOCATION value=%d\n", setparam.value);
203                         return DRM_ERR(EINVAL);
204                 }
205                 dev_priv->config.cmdbuf.location = setparam.value;
206                 break;
207         case NOUVEAU_SETPARAM_CMDBUF_SIZE:
208                 dev_priv->config.cmdbuf.size = setparam.value;
209                 break;
210         default:
211                 DRM_ERROR("unknown parameter %d\n", setparam.param);
212                 return DRM_ERR(EINVAL);
213         }
214
215         return 0;
216 }
217
218 /* waits for idle */
219 void nouveau_wait_for_idle(struct drm_device *dev)
220 {
221         drm_nouveau_private_t *dev_priv=dev->dev_private;
222         switch(dev_priv->card_type)
223         {
224                 case NV_03:
225                         while(NV_READ(NV03_PGRAPH_STATUS));
226                         break;
227                 default:
228                         while(NV_READ(NV04_PGRAPH_STATUS));
229                         break;
230         }
231 }
232