]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Bruce Chang <BruceChang@via.com.tw> |
2 | Subject: via: Unichrome DRM bugfixes | |
3 | ||
4 | 1. Patch the system hang issue caused by multi X support when doing | |
5 | switch user. | |
6 | 2. Patch system hang issue caused by 3D scaling+ACPI | |
7 | 3. Patch segmentation fault issue caused by playing video with AGP after | |
8 | resume from suspend. | |
9 | 4. Reverse the wrong modification we did on the in-line source for | |
10 | coding style only. So ther should no typedef structure... | |
11 | 5. Move private AGP structure into public. | |
12 | 6. Remove the modification we did for bypassing DMA check to improve | |
13 | performance. | |
14 | ||
15 | ||
16 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
17 | ||
18 | --- | |
19 | drivers/gpu/drm/via/via_dma.c | 341 +++++++++++++++++++++++++++++++++++++++++- | |
20 | drivers/gpu/drm/via/via_drv.c | 12 + | |
21 | drivers/gpu/drm/via/via_drv.h | 12 + | |
22 | drivers/gpu/drm/via/via_map.c | 45 +++++ | |
23 | drivers/gpu/drm/via/via_mm.c | 137 +++++++++++++++- | |
24 | include/drm/via_drm.h | 43 +++++ | |
25 | 6 files changed, 576 insertions(+), 14 deletions(-) | |
26 | ||
27 | --- a/drivers/gpu/drm/via/via_dma.c | |
28 | +++ b/drivers/gpu/drm/via/via_dma.c | |
29 | @@ -68,6 +68,15 @@ | |
30 | *vb++ = (w2); \ | |
31 | dev_priv->dma_low += 8; | |
32 | ||
33 | +#define VIA_OUT_VIDEO_AGP_BUFFER(cmd1, cmd2) \ | |
34 | + do { \ | |
35 | + *cur_virtual++ = cmd1; \ | |
36 | + *cur_virtual++ = cmd2; \ | |
37 | + cmdbuf_info.cmd_size += 8; \ | |
38 | + } while (0); | |
39 | + | |
40 | +static void via_cmdbuf_flush(struct drm_via_private *dev_priv, | |
41 | + uint32_t cmd_type); | |
42 | static void via_cmdbuf_start(drm_via_private_t * dev_priv); | |
43 | static void via_cmdbuf_pause(drm_via_private_t * dev_priv); | |
44 | static void via_cmdbuf_reset(drm_via_private_t * dev_priv); | |
45 | @@ -75,6 +84,7 @@ static void via_cmdbuf_rewind(drm_via_pr | |
46 | static int via_wait_idle(drm_via_private_t * dev_priv); | |
47 | static void via_pad_cache(drm_via_private_t * dev_priv, int qwords); | |
48 | ||
49 | + | |
50 | /* | |
51 | * Free space in command buffer. | |
52 | */ | |
53 | @@ -155,17 +165,35 @@ static inline uint32_t *via_check_dma(dr | |
54 | ||
55 | int via_dma_cleanup(struct drm_device * dev) | |
56 | { | |
57 | + struct drm_via_video_save_head *pnode; | |
58 | + int i; | |
59 | + | |
60 | + | |
61 | + for (pnode = via_video_save_head; pnode; pnode = | |
62 | + (struct drm_via_video_save_head *)pnode->next) | |
63 | + memcpy(pnode->psystemmem, pnode->pvideomem, pnode->size); | |
64 | if (dev->dev_private) { | |
65 | drm_via_private_t *dev_priv = | |
66 | (drm_via_private_t *) dev->dev_private; | |
67 | ||
68 | if (dev_priv->ring.virtual_start) { | |
69 | - via_cmdbuf_reset(dev_priv); | |
70 | + if (dev_priv->cr_status == CR_FOR_RINGBUFFER) | |
71 | + via_cmdbuf_flush(dev_priv, HC_HAGPBpID_STOP); | |
72 | + | |
73 | + via_wait_idle(dev_priv); | |
74 | ||
75 | drm_core_ioremapfree(&dev_priv->ring.map, dev); | |
76 | dev_priv->ring.virtual_start = NULL; | |
77 | } | |
78 | ||
79 | + for (i = 0; i < 3; i++) { | |
80 | + if (dev_priv->video_agp_address_map[i].handle && | |
81 | + dev_priv->video_agp_address_map[i].size) | |
82 | + drm_core_ioremapfree(dev_priv-> | |
83 | + video_agp_address_map+i, dev); | |
84 | + /*Fix for suspend reuse video buf*/ | |
85 | + dev_priv->video_agp_address_map[i].handle = NULL; | |
86 | + } | |
87 | } | |
88 | ||
89 | return 0; | |
90 | @@ -175,6 +203,7 @@ static int via_initialize(struct drm_dev | |
91 | drm_via_private_t * dev_priv, | |
92 | drm_via_dma_init_t * init) | |
93 | { | |
94 | + struct drm_via_video_save_head *pnode; | |
95 | if (!dev_priv || !dev_priv->mmio) { | |
96 | DRM_ERROR("via_dma_init called before via_map_init\n"); | |
97 | return -EFAULT; | |
98 | @@ -194,6 +223,9 @@ static int via_initialize(struct drm_dev | |
99 | DRM_ERROR("AGP DMA is not supported on this chip\n"); | |
100 | return -EINVAL; | |
101 | } | |
102 | + | |
103 | + for (pnode = via_video_save_head; pnode; pnode = pnode->next) | |
104 | + memcpy(pnode->pvideomem, pnode->psystemmem, pnode->size); | |
105 | ||
106 | dev_priv->ring.map.offset = dev->agp->base + init->offset; | |
107 | dev_priv->ring.map.size = init->size; | |
108 | @@ -224,6 +256,7 @@ static int via_initialize(struct drm_dev | |
109 | ||
110 | via_cmdbuf_start(dev_priv); | |
111 | ||
112 | + dev_priv->cr_status = CR_FOR_RINGBUFFER; | |
113 | return 0; | |
114 | } | |
115 | ||
116 | @@ -332,12 +365,42 @@ static int via_flush_ioctl(struct drm_de | |
117 | static int via_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) | |
118 | { | |
119 | drm_via_cmdbuffer_t *cmdbuf = data; | |
120 | - int ret; | |
121 | + drm_via_private_t *dev_priv = dev->dev_private; | |
122 | + int ret = 0, count; | |
123 | ||
124 | LOCK_TEST_WITH_RETURN(dev, file_priv); | |
125 | ||
126 | DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size); | |
127 | ||
128 | + if (dev_priv->cr_status == CR_FOR_VIDEO) { | |
129 | + /* Because our driver will hook CR stop cmd behind video cmd, | |
130 | + * all we need to do here is to wait for CR idle, | |
131 | + * and initialize ring buffer. | |
132 | + */ | |
133 | + count = 10000000; | |
134 | + while (count-- && (VIA_READ(VIA_REG_STATUS) & | |
135 | + VIA_CMD_RGTR_BUSY)) | |
136 | + cpu_relax(); | |
137 | + /* Seldom happen */ | |
138 | + if (count < 0) { | |
139 | + DRM_INFO("The CR can't be idle from video agp cmd \ | |
140 | + dispatch when it is needed by ring buffer \n"); | |
141 | + return -1; | |
142 | + } | |
143 | + /* CR has been idle so that we need to initialize ring buffer */ | |
144 | + dev_priv->dma_ptr = dev_priv->ring.virtual_start; | |
145 | + dev_priv->dma_low = 0; | |
146 | + dev_priv->dma_high = 0x1000000; | |
147 | + dev_priv->dma_wrap = 0x1000000; | |
148 | + dev_priv->dma_offset = 0x0; | |
149 | + dev_priv->last_pause_ptr = NULL; | |
150 | + dev_priv->hw_addr_ptr = dev_priv->mmio->handle + 0x418; | |
151 | + | |
152 | + via_cmdbuf_start(dev_priv); | |
153 | + | |
154 | + dev_priv->cr_status = CR_FOR_RINGBUFFER; | |
155 | + | |
156 | + } | |
157 | ret = via_dispatch_cmdbuffer(dev, cmdbuf); | |
158 | if (ret) { | |
159 | return ret; | |
160 | @@ -346,6 +409,134 @@ static int via_cmdbuffer(struct drm_devi | |
161 | return 0; | |
162 | } | |
163 | ||
164 | +int via_cmdbuffer_video_agp(struct drm_device *dev, void *data, | |
165 | + struct drm_file *file_priv) | |
166 | +{ | |
167 | + drm_via_private_t *dev_priv = dev->dev_private; | |
168 | + struct drm_via_video_agp_cmd cmdbuf_info; | |
169 | + int count; | |
170 | + u32 start_addr, start_addr_lo; | |
171 | + u32 end_addr, end_addr_lo; | |
172 | + u32 pause_addr, pause_addr_hi, pause_addr_lo; | |
173 | + u32 *cur_virtual; | |
174 | + u32 command; | |
175 | + int i = 0; | |
176 | + struct drm_map map; | |
177 | + | |
178 | + LOCK_TEST_WITH_RETURN(dev, file_priv); | |
179 | + | |
180 | + /* Check whether CR services for ring buffer or for video engine. */ | |
181 | + if (dev_priv->cr_status == CR_FOR_RINGBUFFER) { | |
182 | + /* Here we need to hook stop cmd in tail of ringbuffer | |
183 | + * in order to stop CR, for we will reset start/end/pause | |
184 | + * address for fetch cmd from video AGP buffer | |
185 | + */ | |
186 | + via_cmdbuf_flush(dev_priv, HC_HAGPBpID_STOP); | |
187 | + } | |
188 | + | |
189 | + /* Set CR status here to avoid ring buffer crush in case we | |
190 | + * can't initialize CR for video properly | |
191 | + */ | |
192 | + dev_priv->cr_status = CR_FOR_VIDEO; | |
193 | + | |
194 | + /* Wait idle since we will reset CR relevant registers. */ | |
195 | + count = 10000000; | |
196 | + while (count-- && (VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY)) | |
197 | + cpu_relax(); | |
198 | + | |
199 | + /* Seldom happen */ | |
200 | + if (count < 0) { | |
201 | + DRM_INFO("The CR can't be idle from video agp cmd dispatch \ | |
202 | + when it is needed by ring buffer \n"); | |
203 | + return -1; | |
204 | + } | |
205 | + | |
206 | + /* Till here, the CR has been idle, all need to here is to initialize | |
207 | + * CR START/END/PAUSE address registers according to video AGP buffer | |
208 | + * location and size. BE LUCKY!!! | |
209 | + */ | |
210 | + cmdbuf_info = *(struct drm_via_video_agp_cmd *)data; | |
211 | + | |
212 | + start_addr = cmdbuf_info.offset + dev->agp->base; | |
213 | + end_addr = cmdbuf_info.buffer_size + start_addr; | |
214 | + | |
215 | + if ((cmdbuf_info.buffer_size & 0xFF) || | |
216 | + (start_addr + 2 * 0xFF > end_addr) || | |
217 | + start_addr & 0xFF) { | |
218 | + DRM_INFO("The video cmd is too large or you didn't set the \ | |
219 | + video cmd 2 DWORD alignment. \n"); | |
220 | + return -1; | |
221 | + } | |
222 | + | |
223 | + map.offset = start_addr; | |
224 | + map.size = cmdbuf_info.buffer_size; | |
225 | + map.type = map.flags = map.mtrr = 0; | |
226 | + map.handle = 0; | |
227 | + | |
228 | + for (i = 0; i < 3; i++) { | |
229 | + if ((dev_priv->video_agp_address_map[i].offset == map.offset) && | |
230 | + (dev_priv->video_agp_address_map[i].size == map.size) && | |
231 | + dev_priv->video_agp_address_map[i].handle) { | |
232 | + map.handle = dev_priv->video_agp_address_map[i].handle; | |
233 | + break; | |
234 | + } | |
235 | + if (!dev_priv->video_agp_address_map[i].handle) | |
236 | + break; | |
237 | + } | |
238 | + | |
239 | + /* Check whether this agp cmd buffer has already been remaped before */ | |
240 | + /* case: Never be remaped before */ | |
241 | + if (!map.handle) { | |
242 | + drm_core_ioremap(&map, dev); | |
243 | + if (!map.handle) | |
244 | + return -1; | |
245 | + /* there is a free hole for filling in this address map */ | |
246 | + if (i < 3) | |
247 | + dev_priv->video_agp_address_map[i] = map; | |
248 | + else { | |
249 | + drm_core_ioremapfree(dev_priv->video_agp_address_map, | |
250 | + dev); | |
251 | + dev_priv->video_agp_address_map[0] = map; | |
252 | + } | |
253 | + } | |
254 | + | |
255 | + cur_virtual = map.handle + cmdbuf_info.cmd_size; | |
256 | + | |
257 | + VIA_OUT_VIDEO_AGP_BUFFER(HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) | | |
258 | + (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16); | |
259 | + | |
260 | + /* pause register need 0xFF alignment */ | |
261 | + do { | |
262 | + VIA_OUT_VIDEO_AGP_BUFFER(HC_DUMMY, HC_DUMMY); | |
263 | + } while (cmdbuf_info.cmd_size & 0xFF); | |
264 | + pause_addr = cmdbuf_info.cmd_size + start_addr - 8; | |
265 | + | |
266 | + pause_addr_lo = ((HC_SubA_HAGPBpL << 24) | HC_HAGPBpID_STOP | | |
267 | + (pause_addr & HC_HAGPBpL_MASK)); | |
268 | + pause_addr_hi = ((HC_SubA_HAGPBpH << 24) | (pause_addr >> 24)); | |
269 | + start_addr_lo = ((HC_SubA_HAGPBstL << 24) | (start_addr & 0xFFFFFF)); | |
270 | + end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF)); | |
271 | + command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) | | |
272 | + ((end_addr & 0xff000000) >> 16)); | |
273 | + *(cur_virtual-2) = pause_addr_hi; | |
274 | + *(cur_virtual-1) = pause_addr_lo; | |
275 | + | |
276 | + via_flush_write_combine(); | |
277 | + | |
278 | + VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); | |
279 | + VIA_WRITE(VIA_REG_TRANSPACE, command); | |
280 | + VIA_WRITE(VIA_REG_TRANSPACE, start_addr_lo); | |
281 | + VIA_WRITE(VIA_REG_TRANSPACE, end_addr_lo); | |
282 | + | |
283 | + VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); | |
284 | + VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); | |
285 | + DRM_WRITEMEMORYBARRIER(); | |
286 | + /* fire */ | |
287 | + VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); | |
288 | + | |
289 | + return 0; | |
290 | +} | |
291 | + | |
292 | static int via_dispatch_pci_cmdbuffer(struct drm_device * dev, | |
293 | drm_via_cmdbuffer_t * cmd) | |
294 | { | |
295 | @@ -735,6 +926,146 @@ static int via_cmdbuf_size(struct drm_de | |
296 | return ret; | |
297 | } | |
298 | ||
299 | +/*The following functions are for ACPI*/ | |
300 | + | |
301 | +static void initialize3Dengine(drm_via_private_t *dev_priv) | |
302 | +{ | |
303 | + int i = 0; | |
304 | + | |
305 | + VIA_WRITE(0x43C, 0x00010000); | |
306 | + | |
307 | + for (i = 0; i <= 0x7D; i++) | |
308 | + VIA_WRITE(0x440, (unsigned long) i << 24); | |
309 | + | |
310 | + VIA_WRITE(0x43C, 0x00020000); | |
311 | + | |
312 | + for (i = 0; i <= 0x94; i++) | |
313 | + VIA_WRITE(0x440, (unsigned long) i << 24); | |
314 | + | |
315 | + VIA_WRITE(0x440, 0x82400000); | |
316 | + VIA_WRITE(0x43C, 0x01020000); | |
317 | + | |
318 | + for (i = 0; i <= 0x94; i++) | |
319 | + VIA_WRITE(0x440, (unsigned long) i << 24); | |
320 | + | |
321 | + VIA_WRITE(0x440, 0x82400000); | |
322 | + VIA_WRITE(0x43C, 0xfe020000); | |
323 | + | |
324 | + for (i = 0; i <= 0x03; i++) | |
325 | + VIA_WRITE(0x440, (unsigned long) i << 24); | |
326 | + | |
327 | + VIA_WRITE(0x43C, 0x00030000); | |
328 | + | |
329 | + for (i = 0; i <= 0xff; i++) | |
330 | + VIA_WRITE(0x440, 0); | |
331 | + | |
332 | + VIA_WRITE(0x43C, 0x00100000); | |
333 | + VIA_WRITE(0x440, 0x00333004); | |
334 | + VIA_WRITE(0x440, 0x10000002); | |
335 | + VIA_WRITE(0x440, 0x60000000); | |
336 | + VIA_WRITE(0x440, 0x61000000); | |
337 | + VIA_WRITE(0x440, 0x62000000); | |
338 | + VIA_WRITE(0x440, 0x63000000); | |
339 | + VIA_WRITE(0x440, 0x64000000); | |
340 | + | |
341 | + VIA_WRITE(0x43C, 0x00fe0000); | |
342 | + VIA_WRITE(0x440, 0x40008c0f); | |
343 | + VIA_WRITE(0x440, 0x44000000); | |
344 | + VIA_WRITE(0x440, 0x45080C04); | |
345 | + VIA_WRITE(0x440, 0x46800408); | |
346 | + VIA_WRITE(0x440, 0x50000000); | |
347 | + VIA_WRITE(0x440, 0x51000000); | |
348 | + VIA_WRITE(0x440, 0x52000000); | |
349 | + VIA_WRITE(0x440, 0x53000000); | |
350 | + | |
351 | + | |
352 | + VIA_WRITE(0x43C, 0x00fe0000); | |
353 | + VIA_WRITE(0x440, 0x08000001); | |
354 | + VIA_WRITE(0x440, 0x0A000183); | |
355 | + VIA_WRITE(0x440, 0x0B00019F); | |
356 | + VIA_WRITE(0x440, 0x0C00018B); | |
357 | + VIA_WRITE(0x440, 0x0D00019B); | |
358 | + VIA_WRITE(0x440, 0x0E000000); | |
359 | + VIA_WRITE(0x440, 0x0F000000); | |
360 | + VIA_WRITE(0x440, 0x10000000); | |
361 | + VIA_WRITE(0x440, 0x11000000); | |
362 | + VIA_WRITE(0x440, 0x20000000); | |
363 | +} | |
364 | +/* For acpi case, when system resume from suspend or hibernate, | |
365 | + * need to re-initialize dma info into HW | |
366 | + */ | |
367 | +int via_drm_resume(struct pci_dev *pci) | |
368 | +{ | |
369 | + struct drm_device *dev = (struct drm_device *)pci_get_drvdata(pci); | |
370 | + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; | |
371 | + struct drm_via_video_save_head *pnode = 0; | |
372 | + | |
373 | + if (!dev_priv->initialize) | |
374 | + return 0; | |
375 | + /* when resume, initialize 3d registers */ | |
376 | + initialize3Dengine(dev_priv); | |
377 | + | |
378 | + /* here we need to restore some video memory content */ | |
379 | + for (pnode = via_video_save_head; pnode; pnode = pnode->next) | |
380 | + memcpy(pnode->pvideomem, pnode->psystemmem, pnode->size); | |
381 | + | |
382 | + /* if pci path, return */ | |
383 | + if (!dev_priv->ring.virtual_start) | |
384 | + return 0; | |
385 | + | |
386 | + dev_priv->dma_ptr = dev_priv->ring.virtual_start; | |
387 | + dev_priv->dma_low = 0; | |
388 | + dev_priv->dma_high = 0x1000000; | |
389 | + dev_priv->dma_wrap = 0x1000000; | |
390 | + dev_priv->dma_offset = 0x0; | |
391 | + dev_priv->last_pause_ptr = NULL; | |
392 | + dev_priv->hw_addr_ptr = dev_priv->mmio->handle + 0x418; | |
393 | + | |
394 | + via_cmdbuf_start(dev_priv); | |
395 | + | |
396 | + return 0; | |
397 | +} | |
398 | + | |
399 | +int via_drm_suspend(struct pci_dev *pci, pm_message_t state) | |
400 | +{ | |
401 | + struct drm_device *dev = (struct drm_device *)pci_get_drvdata(pci); | |
402 | + drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; | |
403 | + | |
404 | + struct drm_via_video_save_head *pnode = 0; | |
405 | + | |
406 | + if (!dev_priv->initialize) | |
407 | + return 0; | |
408 | + /*here we need to save some video mem information into system memory, | |
409 | + to keep the system consistent between suspend *before* and *after* | |
410 | + 1.save only necessary */ | |
411 | + for (pnode = via_video_save_head; pnode; | |
412 | + pnode = (struct drm_via_video_save_head *)pnode->next) | |
413 | + memcpy(pnode->psystemmem, pnode->pvideomem, pnode->size); | |
414 | + | |
415 | + /* Only agp path need to flush the cmd */ | |
416 | + if (dev_priv->ring.virtual_start) | |
417 | + via_cmdbuf_reset(dev_priv); | |
418 | + | |
419 | + return 0; | |
420 | +} | |
421 | +int via_drm_authmagic(struct drm_device *dev, void *data, | |
422 | + struct drm_file *file_priv) | |
423 | +{ | |
424 | + return 0; | |
425 | +} | |
426 | + | |
427 | +int via_drm_init_judge(struct drm_device *dev, void *data, | |
428 | + struct drm_file *file_priv) | |
429 | +{ | |
430 | + struct drm_via_private *dev_priv = dev->dev_private; | |
431 | + | |
432 | + if (dev_priv->initialize) | |
433 | + *(int *)data = 1; | |
434 | + else | |
435 | + *(int *)data = -1; | |
436 | + return 0; | |
437 | +} | |
438 | + | |
439 | struct drm_ioctl_desc via_ioctls[] = { | |
440 | DRM_IOCTL_DEF(DRM_VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH), | |
441 | DRM_IOCTL_DEF(DRM_VIA_FREEMEM, via_mem_free, DRM_AUTH), | |
442 | @@ -742,6 +1073,7 @@ struct drm_ioctl_desc via_ioctls[] = { | |
443 | DRM_IOCTL_DEF(DRM_VIA_FB_INIT, via_fb_init, DRM_AUTH|DRM_MASTER), | |
444 | DRM_IOCTL_DEF(DRM_VIA_MAP_INIT, via_map_init, DRM_AUTH|DRM_MASTER), | |
445 | DRM_IOCTL_DEF(DRM_VIA_DEC_FUTEX, via_decoder_futex, DRM_AUTH), | |
446 | + DRM_IOCTL_DEF(DRM_VIA_GET_INFO, via_get_drm_info, DRM_AUTH), | |
447 | DRM_IOCTL_DEF(DRM_VIA_DMA_INIT, via_dma_init, DRM_AUTH), | |
448 | DRM_IOCTL_DEF(DRM_VIA_CMDBUFFER, via_cmdbuffer, DRM_AUTH), | |
449 | DRM_IOCTL_DEF(DRM_VIA_FLUSH, via_flush_ioctl, DRM_AUTH), | |
450 | @@ -749,7 +1081,10 @@ struct drm_ioctl_desc via_ioctls[] = { | |
451 | DRM_IOCTL_DEF(DRM_VIA_CMDBUF_SIZE, via_cmdbuf_size, DRM_AUTH), | |
452 | DRM_IOCTL_DEF(DRM_VIA_WAIT_IRQ, via_wait_irq, DRM_AUTH), | |
453 | DRM_IOCTL_DEF(DRM_VIA_DMA_BLIT, via_dma_blit, DRM_AUTH), | |
454 | - DRM_IOCTL_DEF(DRM_VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH) | |
455 | + DRM_IOCTL_DEF(DRM_VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH), | |
456 | + DRM_IOCTL_DEF(DRM_VIA_AUTH_MAGIC, via_drm_authmagic, 0), | |
457 | + DRM_IOCTL_DEF(DRM_VIA_FLUSH_VIDEO, via_cmdbuffer_video_agp, 0), | |
458 | + DRM_IOCTL_DEF(DRM_VIA_INIT_JUDGE, via_drm_init_judge, 0) | |
459 | }; | |
460 | ||
461 | int via_max_ioctl = DRM_ARRAY_SIZE(via_ioctls); | |
462 | --- a/drivers/gpu/drm/via/via_drv.c | |
463 | +++ b/drivers/gpu/drm/via/via_drv.c | |
464 | @@ -37,10 +37,16 @@ static struct pci_device_id pciidlist[] | |
465 | viadrv_PCI_IDS | |
466 | }; | |
467 | ||
468 | +int via_driver_open(struct drm_device *dev, struct drm_file *priv) | |
469 | +{ | |
470 | + priv->authenticated = 1; | |
471 | + return 0; | |
472 | +} | |
473 | static struct drm_driver driver = { | |
474 | .driver_features = | |
475 | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ | | |
476 | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, | |
477 | + .open = via_driver_open, | |
478 | .load = via_driver_load, | |
479 | .unload = via_driver_unload, | |
480 | .context_dtor = via_final_context, | |
481 | @@ -68,8 +74,10 @@ static struct drm_driver driver = { | |
482 | .fasync = drm_fasync, | |
483 | }, | |
484 | .pci_driver = { | |
485 | - .name = DRIVER_NAME, | |
486 | - .id_table = pciidlist, | |
487 | + .name = DRIVER_NAME, | |
488 | + .id_table = pciidlist, | |
489 | + .suspend = via_drm_suspend, | |
490 | + .resume = via_drm_resume, | |
491 | }, | |
492 | ||
493 | .name = DRIVER_NAME, | |
494 | --- a/drivers/gpu/drm/via/via_drv.h | |
495 | +++ b/drivers/gpu/drm/via/via_drv.h | |
496 | @@ -62,6 +62,7 @@ typedef struct drm_via_private { | |
497 | drm_local_map_t *sarea; | |
498 | drm_local_map_t *fb; | |
499 | drm_local_map_t *mmio; | |
500 | + enum drm_agp_type agptype; | |
501 | unsigned long agpAddr; | |
502 | wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS]; | |
503 | char *dma_ptr; | |
504 | @@ -93,7 +94,13 @@ typedef struct drm_via_private { | |
505 | unsigned long vram_offset; | |
506 | unsigned long agp_offset; | |
507 | drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES]; | |
508 | + struct drm_map video_agp_address_map[3]; | |
509 | + enum { | |
510 | + CR_FOR_RINGBUFFER, | |
511 | + CR_FOR_VIDEO | |
512 | + } cr_status; | |
513 | uint32_t dma_diff; | |
514 | + int initialize; | |
515 | } drm_via_private_t; | |
516 | ||
517 | enum via_family { | |
518 | @@ -119,6 +126,8 @@ extern int via_mem_free(struct drm_devic | |
519 | extern int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv); | |
520 | extern int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv); | |
521 | extern int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv); | |
522 | +extern int via_get_drm_info(struct drm_device *dev, void *data, | |
523 | + struct drm_file *file_priv); | |
524 | extern int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv); | |
525 | extern int via_dma_blit_sync( struct drm_device *dev, void *data, struct drm_file *file_priv ); | |
526 | extern int via_dma_blit( struct drm_device *dev, void *data, struct drm_file *file_priv ); | |
527 | @@ -150,4 +159,7 @@ extern void via_lastclose(struct drm_dev | |
528 | extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq); | |
529 | extern void via_init_dmablit(struct drm_device *dev); | |
530 | ||
531 | +extern int via_drm_resume(struct pci_dev *dev); | |
532 | +extern int via_drm_suspend(struct pci_dev *dev, pm_message_t state); | |
533 | + | |
534 | #endif | |
535 | --- a/drivers/gpu/drm/via/via_map.c | |
536 | +++ b/drivers/gpu/drm/via/via_map.c | |
537 | @@ -25,6 +25,7 @@ | |
538 | #include "via_drm.h" | |
539 | #include "via_drv.h" | |
540 | ||
541 | +static int associate; | |
542 | static int via_do_init_map(struct drm_device * dev, drm_via_init_t * init) | |
543 | { | |
544 | drm_via_private_t *dev_priv = dev->dev_private; | |
545 | @@ -65,12 +66,35 @@ static int via_do_init_map(struct drm_de | |
546 | via_init_dmablit(dev); | |
547 | ||
548 | dev->dev_private = (void *)dev_priv; | |
549 | + | |
550 | + /* from doing this, we has the stuff in prev data | |
551 | + * structure to manage agp | |
552 | + */ | |
553 | + if (init->agp_type != DISABLED) { | |
554 | + dev->agp_buffer_map = drm_core_findmap(dev, init->agp_offset); | |
555 | + if (!dev->agp_buffer_map) { | |
556 | + DRM_ERROR("failed to find dma buffer region!\n"); | |
557 | + return -EINVAL; | |
558 | + } | |
559 | + if (init->agp_type == AGP_DOUBLE_BUFFER) | |
560 | + dev_priv->agptype = AGP_DOUBLE_BUFFER; | |
561 | + if (init->agp_type == AGP_RING_BUFFER) | |
562 | + dev_priv->agptype = AGP_RING_BUFFER; | |
563 | + } else { | |
564 | + dev_priv->agptype = DISABLED; | |
565 | + dev->agp_buffer_map = 0; | |
566 | + } | |
567 | + /* end */ | |
568 | + dev_priv->initialize = 1; | |
569 | + | |
570 | return 0; | |
571 | } | |
572 | ||
573 | int via_do_cleanup_map(struct drm_device * dev) | |
574 | { | |
575 | + drm_via_private_t *dev_priv = dev->dev_private; | |
576 | via_dma_cleanup(dev); | |
577 | + dev_priv->initialize = 0; | |
578 | ||
579 | return 0; | |
580 | } | |
581 | @@ -95,6 +119,11 @@ int via_driver_load(struct drm_device *d | |
582 | { | |
583 | drm_via_private_t *dev_priv; | |
584 | int ret = 0; | |
585 | + if (!associate) { | |
586 | + pci_set_drvdata(dev->pdev, dev); | |
587 | + dev->pdev->driver = &dev->driver->pci_driver; | |
588 | + associate = 1; | |
589 | + } | |
590 | ||
591 | dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER); | |
592 | if (dev_priv == NULL) | |
593 | @@ -121,3 +150,19 @@ int via_driver_unload(struct drm_device | |
594 | ||
595 | return 0; | |
596 | } | |
597 | +int via_get_drm_info(struct drm_device *dev, void *data, | |
598 | + struct drm_file *file_priv) | |
599 | +{ | |
600 | + drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; | |
601 | + struct drm_via_info *info = data; | |
602 | + | |
603 | + if (!dev_priv->initialize) | |
604 | + return -EINVAL; | |
605 | + | |
606 | + info->RegSize = dev_priv->mmio->size; | |
607 | + info->AgpSize = dev->agp_buffer_map->size; | |
608 | + info->RegHandle = dev_priv->mmio->offset; | |
609 | + info->AgpHandle = dev->agp_buffer_map->offset; | |
610 | + | |
611 | + return 0; | |
612 | +} | |
613 | --- a/drivers/gpu/drm/via/via_mm.c | |
614 | +++ b/drivers/gpu/drm/via/via_mm.c | |
615 | @@ -30,6 +30,7 @@ | |
616 | #include "via_drv.h" | |
617 | #include "drm_sman.h" | |
618 | ||
619 | +struct drm_via_video_save_head *via_video_save_head; | |
620 | #define VIA_MM_ALIGN_SHIFT 4 | |
621 | #define VIA_MM_ALIGN_MASK ( (1 << VIA_MM_ALIGN_SHIFT) - 1) | |
622 | ||
623 | @@ -56,6 +57,8 @@ int via_agp_init(struct drm_device *dev, | |
624 | DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size); | |
625 | return 0; | |
626 | } | |
627 | +static void *global_dev; | |
628 | +static void *global_file_priv; | |
629 | ||
630 | int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv) | |
631 | { | |
632 | @@ -78,6 +81,8 @@ int via_fb_init(struct drm_device *dev, | |
633 | ||
634 | mutex_unlock(&dev->struct_mutex); | |
635 | DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size); | |
636 | + global_dev = dev; | |
637 | + global_file_priv = file_priv; | |
638 | ||
639 | return 0; | |
640 | ||
641 | @@ -115,6 +120,84 @@ void via_lastclose(struct drm_device *de | |
642 | mutex_unlock(&dev->struct_mutex); | |
643 | } | |
644 | ||
645 | +static int via_videomem_presave_ok(drm_via_private_t *dev_priv, | |
646 | + drm_via_mem_t *mem) | |
647 | +{ | |
648 | + void *pvideomem = 0, *psystemmem = 0; | |
649 | + struct drm_via_video_save_head *pnode = 0; | |
650 | + | |
651 | + if (!mem || !mem->size || (mem->type != VIA_MEM_VIDEO_SAVE)) | |
652 | + return 0; | |
653 | + | |
654 | + /* here the mem->offset is the absolute address, | |
655 | + * not the offset within videomem | |
656 | + */ | |
657 | + pvideomem = (void *)ioremap(dev_priv->fb->offset + mem->offset, | |
658 | + mem->size); | |
659 | + if (!pvideomem) | |
660 | + return 0; | |
661 | + | |
662 | + psystemmem = kmalloc(mem->size, GFP_KERNEL); | |
663 | + if (!psystemmem) { | |
664 | + iounmap(pvideomem); | |
665 | + return 0; | |
666 | + } | |
667 | + | |
668 | + /* map success, then save this information into | |
669 | + * a data structure for later saving usage | |
670 | + */ | |
671 | + pnode = kmalloc( | |
672 | + sizeof(struct drm_via_video_save_head), GFP_KERNEL); | |
673 | + if (!pnode) { | |
674 | + iounmap(pvideomem); | |
675 | + kfree(psystemmem); | |
676 | + return 0; | |
677 | + } | |
678 | + | |
679 | + pnode->next = 0; | |
680 | + pnode->psystemmem = psystemmem; | |
681 | + pnode->pvideomem = pvideomem; | |
682 | + pnode->size = mem->size; | |
683 | + pnode->token = mem->offset; | |
684 | + | |
685 | + /* insert this node into list */ | |
686 | + if (!via_video_save_head) { | |
687 | + via_video_save_head = pnode; | |
688 | + } else { | |
689 | + pnode->next = via_video_save_head; | |
690 | + via_video_save_head = pnode; | |
691 | + } | |
692 | + | |
693 | + return 1; | |
694 | +} | |
695 | + | |
696 | +static int via_videomem_housekeep_ok(drm_via_mem_t *mem) | |
697 | +{ | |
698 | + struct drm_via_video_save_head **ppnode = 0; | |
699 | + struct drm_via_video_save_head *tmpnode = 0; | |
700 | + /* if this mem's token match with one node of the list */ | |
701 | + for (ppnode = &via_video_save_head; *ppnode; | |
702 | + ppnode = (struct drm_via_video_save_head **)(&((*ppnode)->next))) { | |
703 | + if ((*ppnode)->token == mem->offset) | |
704 | + break; | |
705 | + } | |
706 | + | |
707 | + if (*ppnode == 0) { | |
708 | + /* not found, the user may specify the wrong mem node to free */ | |
709 | + return 0; | |
710 | + } | |
711 | + | |
712 | + /* delete this node from the list and then | |
713 | + *free all the mem to avoid memory leak | |
714 | + */ | |
715 | + tmpnode = *ppnode; | |
716 | + *ppnode = (*ppnode)->next; | |
717 | + iounmap(tmpnode->pvideomem); | |
718 | + kfree(tmpnode->psystemmem); | |
719 | + kfree(tmpnode); | |
720 | + | |
721 | + return 1; | |
722 | +} | |
723 | int via_mem_alloc(struct drm_device *dev, void *data, | |
724 | struct drm_file *file_priv) | |
725 | { | |
726 | @@ -124,12 +207,13 @@ int via_mem_alloc(struct drm_device *dev | |
727 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; | |
728 | unsigned long tmpSize; | |
729 | ||
730 | - if (mem->type > VIA_MEM_AGP) { | |
731 | + if (mem->type > VIA_MEM_VIDEO_SAVE) { | |
732 | DRM_ERROR("Unknown memory type allocation\n"); | |
733 | return -EINVAL; | |
734 | } | |
735 | mutex_lock(&dev->struct_mutex); | |
736 | - if (0 == ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized : | |
737 | + if (0 == ((mem->type == VIA_MEM_VIDEO || | |
738 | + mem->type == VIA_MEM_VIDEO_SAVE) ? dev_priv->vram_initialized : | |
739 | dev_priv->agp_initialized)) { | |
740 | DRM_ERROR | |
741 | ("Attempt to allocate from uninitialized memory manager.\n"); | |
742 | @@ -138,15 +222,25 @@ int via_mem_alloc(struct drm_device *dev | |
743 | } | |
744 | ||
745 | tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT; | |
746 | - item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, 0, | |
747 | - (unsigned long)file_priv); | |
748 | + item = drm_sman_alloc(&dev_priv->sman, | |
749 | + (mem->type == VIA_MEM_VIDEO_SAVE ? VIA_MEM_VIDEO : mem->type), | |
750 | + tmpSize, 0, (unsigned long)file_priv); | |
751 | mutex_unlock(&dev->struct_mutex); | |
752 | if (item) { | |
753 | - mem->offset = ((mem->type == VIA_MEM_VIDEO) ? | |
754 | - dev_priv->vram_offset : dev_priv->agp_offset) + | |
755 | - (item->mm-> | |
756 | - offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT); | |
757 | + mem->offset = ((mem->type == VIA_MEM_VIDEO || | |
758 | + mem->type == VIA_MEM_VIDEO_SAVE) ? | |
759 | + dev_priv->vram_offset : dev_priv->agp_offset) + | |
760 | + (item->mm->offset(item->mm, item->mm_info) << | |
761 | + VIA_MM_ALIGN_SHIFT); | |
762 | mem->index = item->user_hash.key; | |
763 | + if (mem->type == VIA_MEM_VIDEO_SAVE) { | |
764 | + if (!via_videomem_presave_ok(dev_priv, mem)) { | |
765 | + mutex_lock(&dev->struct_mutex); | |
766 | + drm_sman_free_key(&dev_priv->sman, mem->index); | |
767 | + mutex_unlock(&dev->struct_mutex); | |
768 | + retval = -ENOMEM; | |
769 | + } | |
770 | + } | |
771 | } else { | |
772 | mem->offset = 0; | |
773 | mem->size = 0; | |
774 | @@ -166,6 +260,10 @@ int via_mem_free(struct drm_device *dev, | |
775 | ||
776 | mutex_lock(&dev->struct_mutex); | |
777 | ret = drm_sman_free_key(&dev_priv->sman, mem->index); | |
778 | + if (mem->type == VIA_MEM_VIDEO_SAVE) { | |
779 | + if (!via_videomem_housekeep_ok(mem)) | |
780 | + ret = -EINVAL; | |
781 | + } | |
782 | mutex_unlock(&dev->struct_mutex); | |
783 | DRM_DEBUG("free = 0x%lx\n", mem->index); | |
784 | ||
785 | @@ -192,3 +290,26 @@ void via_reclaim_buffers_locked(struct d | |
786 | mutex_unlock(&dev->struct_mutex); | |
787 | return; | |
788 | } | |
789 | +static int via_fb_alloc(drm_via_mem_t *mem) | |
790 | +{ | |
791 | + struct drm_device *dev = global_dev; | |
792 | + struct drm_file *file_priv = global_file_priv; | |
793 | + | |
794 | + if (dev && file_priv) | |
795 | + return via_mem_alloc(dev, mem, file_priv); | |
796 | + else | |
797 | + return -EINVAL; | |
798 | +} | |
799 | +EXPORT_SYMBOL(via_fb_alloc); | |
800 | + | |
801 | +static int via_fb_free(drm_via_mem_t *mem) | |
802 | +{ | |
803 | + struct drm_device *dev = global_dev; | |
804 | + struct drm_file *file_priv = global_file_priv; | |
805 | + | |
806 | + if (dev && file_priv) | |
807 | + return via_mem_free(dev, mem, file_priv); | |
808 | + else | |
809 | + return -EINVAL; | |
810 | +} | |
811 | +EXPORT_SYMBOL(via_fb_free); | |
812 | --- a/include/drm/via_drm.h | |
813 | +++ b/include/drm/via_drm.h | |
814 | @@ -51,6 +51,12 @@ | |
815 | #define VIA_LOG_MIN_TEX_REGION_SIZE 16 | |
816 | #endif | |
817 | ||
818 | +struct drm_via_info { | |
819 | + unsigned long AgpHandle; | |
820 | + unsigned long AgpSize; | |
821 | + unsigned long RegHandle; | |
822 | + unsigned long RegSize; | |
823 | +} ; | |
824 | #define VIA_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */ | |
825 | #define VIA_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */ | |
826 | #define VIA_UPLOAD_CTX 0x4 | |
827 | @@ -67,7 +73,7 @@ | |
828 | #define DRM_VIA_FB_INIT 0x03 | |
829 | #define DRM_VIA_MAP_INIT 0x04 | |
830 | #define DRM_VIA_DEC_FUTEX 0x05 | |
831 | -#define NOT_USED | |
832 | +#define DRM_VIA_GET_INFO 0x06 | |
833 | #define DRM_VIA_DMA_INIT 0x07 | |
834 | #define DRM_VIA_CMDBUFFER 0x08 | |
835 | #define DRM_VIA_FLUSH 0x09 | |
836 | @@ -77,6 +83,9 @@ | |
837 | #define DRM_VIA_WAIT_IRQ 0x0d | |
838 | #define DRM_VIA_DMA_BLIT 0x0e | |
839 | #define DRM_VIA_BLIT_SYNC 0x0f | |
840 | +#define DRM_VIA_AUTH_MAGIC 0x11 | |
841 | +#define DRM_VIA_FLUSH_VIDEO 0x12 | |
842 | +#define DRM_VIA_INIT_JUDGE 0x16 | |
843 | ||
844 | #define DRM_IOCTL_VIA_ALLOCMEM DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_ALLOCMEM, drm_via_mem_t) | |
845 | #define DRM_IOCTL_VIA_FREEMEM DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_FREEMEM, drm_via_mem_t) | |
846 | @@ -84,6 +93,8 @@ | |
847 | #define DRM_IOCTL_VIA_FB_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_FB_INIT, drm_via_fb_t) | |
848 | #define DRM_IOCTL_VIA_MAP_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_MAP_INIT, drm_via_init_t) | |
849 | #define DRM_IOCTL_VIA_DEC_FUTEX DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_DEC_FUTEX, drm_via_futex_t) | |
850 | +#define DRM_IOCTL_VIA_GET_INFO DRM_IOR(DRM_COMMAND_BASE + \ | |
851 | + DRM_VIA_GET_INFO, struct drm_via_info) | |
852 | #define DRM_IOCTL_VIA_DMA_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_DMA_INIT, drm_via_dma_init_t) | |
853 | #define DRM_IOCTL_VIA_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_CMDBUFFER, drm_via_cmdbuffer_t) | |
854 | #define DRM_IOCTL_VIA_FLUSH DRM_IO( DRM_COMMAND_BASE + DRM_VIA_FLUSH) | |
855 | @@ -91,8 +102,14 @@ | |
856 | #define DRM_IOCTL_VIA_CMDBUF_SIZE DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_CMDBUF_SIZE, \ | |
857 | drm_via_cmdbuf_size_t) | |
858 | #define DRM_IOCTL_VIA_WAIT_IRQ DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_WAIT_IRQ, drm_via_irqwait_t) | |
859 | +#define DRM_IOCTL_VIA_FLUSH_VIDEO DRM_IOW(DRM_COMMAND_BASE + \ | |
860 | + DRM_VIA_FLUSH_VIDEO, struct drm_via_video_agp_cmd) | |
861 | #define DRM_IOCTL_VIA_DMA_BLIT DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_DMA_BLIT, drm_via_dmablit_t) | |
862 | #define DRM_IOCTL_VIA_BLIT_SYNC DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_BLIT_SYNC, drm_via_blitsync_t) | |
863 | +#define DRM_IOCTL_VIA_AUTH_MAGIC DRM_IOW(DRM_COMMAND_BASE + \ | |
864 | + DRM_VIA_AUTH_MAGIC, drm_auth_t) | |
865 | +#define DRM_IOCTL_VIA_INIT_JUDGE DRM_IOR(DRM_COMMAND_BASE + \ | |
866 | + DRM_VIA_INIT_JUDGE, int) | |
867 | ||
868 | /* Indices into buf.Setup where various bits of state are mirrored per | |
869 | * context and per buffer. These can be fired at the card as a unit, | |
870 | @@ -112,6 +129,13 @@ | |
871 | #define VIA_MEM_SYSTEM 2 | |
872 | #define VIA_MEM_MIXED 3 | |
873 | #define VIA_MEM_UNKNOWN 4 | |
874 | +#define VIA_MEM_VIDEO_SAVE 2 /*For video memory need to be saved in ACPI */ | |
875 | + | |
876 | +enum drm_agp_type { | |
877 | + AGP_RING_BUFFER, | |
878 | + AGP_DOUBLE_BUFFER, | |
879 | + DISABLED | |
880 | +}; | |
881 | ||
882 | typedef struct { | |
883 | uint32_t offset; | |
884 | @@ -141,6 +165,8 @@ typedef struct _drm_via_init { | |
885 | unsigned long fb_offset; | |
886 | unsigned long mmio_offset; | |
887 | unsigned long agpAddr; | |
888 | + unsigned long agp_offset; | |
889 | + enum drm_agp_type agp_type; | |
890 | } drm_via_init_t; | |
891 | ||
892 | typedef struct _drm_via_futex { | |
893 | @@ -245,6 +271,12 @@ typedef union drm_via_irqwait { | |
894 | struct drm_wait_vblank_reply reply; | |
895 | } drm_via_irqwait_t; | |
896 | ||
897 | +struct drm_via_video_agp_cmd { | |
898 | + u32 offset; | |
899 | + u32 cmd_size; | |
900 | + u32 buffer_size; | |
901 | +} ; | |
902 | + | |
903 | typedef struct drm_via_blitsync { | |
904 | uint32_t sync_handle; | |
905 | unsigned engine; | |
906 | @@ -272,4 +304,13 @@ typedef struct drm_via_dmablit { | |
907 | drm_via_blitsync_t sync; | |
908 | } drm_via_dmablit_t; | |
909 | ||
910 | +struct drm_via_video_save_head { | |
911 | + void *pvideomem; | |
912 | + void *psystemmem; | |
913 | + int size; | |
914 | + /* token used to identify this video memory */ | |
915 | + unsigned long token; | |
916 | + void *next; | |
917 | +} ; | |
918 | +extern struct drm_via_video_save_head *via_video_save_head; | |
919 | #endif /* _VIA_DRM_H_ */ |