Mercurial > mplayer.hg
comparison vidix/drivers/pm3_vid.c @ 6254:034b12194350
rage128/radeon fixes, mach64 mess^H^H^H^Hcleanup, pm3 driver.
sync with mplayerxp
author | arpi |
---|---|
date | Fri, 31 May 2002 23:17:43 +0000 |
parents | |
children | f6d2772efca3 |
comparison
equal
deleted
inserted
replaced
6253:136c061fab12 | 6254:034b12194350 |
---|---|
1 /** | |
2 Driver for 3DLabs GLINT R3 and Permedia3 chips. | |
3 | |
4 Copyright (C) 2002 Måns Rullgård | |
5 | |
6 This program is free software; you can redistribute it and/or modify | |
7 it under the terms of the GNU General Public License as published by | |
8 the Free Software Foundation; either version 2 of the License, or | |
9 (at your option) any later version. | |
10 | |
11 This program is distributed in the hope that it will be useful, | |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 GNU General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with this program; if not, write to the Free Software | |
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 **/ | |
20 | |
21 #include <errno.h> | |
22 #include <stdio.h> | |
23 #include <stdlib.h> | |
24 #include <string.h> | |
25 #include <inttypes.h> | |
26 #include <unistd.h> | |
27 | |
28 #include "../vidix.h" | |
29 #include "../fourcc.h" | |
30 #include "../../libdha/libdha.h" | |
31 #include "../../libdha/pci_ids.h" | |
32 #include "../../libdha/pci_names.h" | |
33 #include "../../config.h" | |
34 | |
35 #include "pm3_regs.h" | |
36 | |
37 #if 0 | |
38 #define TRACE_ENTER() fprintf(stderr, "%s: enter\n", __FUNCTION__) | |
39 #define TRACE_EXIT() fprintf(stderr, "%s: exit\n", __FUNCTION__) | |
40 #else | |
41 #define TRACE_ENTER() | |
42 #define TRACE_EXIT() | |
43 #endif | |
44 | |
45 pciinfo_t pci_info; | |
46 | |
47 void *pm3_reg_base; | |
48 void *pm3_mem; | |
49 | |
50 static vidix_capability_t pm3_cap = | |
51 { | |
52 "3DLabs GLINT R3/Permedia3 driver", | |
53 "Måns Rullgård <mru@users.sf.net>", | |
54 TYPE_OUTPUT, | |
55 { 0, 0, 0, 0 }, | |
56 2048, | |
57 2048, | |
58 4, | |
59 4, | |
60 -1, | |
61 FLAG_UPSCALER|FLAG_DOWNSCALER, | |
62 VENDOR_3DLABS, | |
63 -1, | |
64 { 0, 0, 0, 0 } | |
65 }; | |
66 | |
67 | |
68 unsigned int vixGetVersion(void) | |
69 { | |
70 return(VIDIX_VERSION); | |
71 } | |
72 | |
73 static unsigned short pm3_card_ids[] = | |
74 { | |
75 DEVICE_3DLABS_GLINT_R3 | |
76 }; | |
77 | |
78 static int find_chip(unsigned chip_id) | |
79 { | |
80 unsigned i; | |
81 for(i = 0;i < sizeof(pm3_card_ids)/sizeof(unsigned short);i++) | |
82 { | |
83 if(chip_id == pm3_card_ids[i]) return i; | |
84 } | |
85 return -1; | |
86 } | |
87 | |
88 int vixProbe(int verbose, int force) | |
89 { | |
90 pciinfo_t lst[MAX_PCI_DEVICES]; | |
91 unsigned i,num_pci; | |
92 int err; | |
93 | |
94 err = pci_scan(lst,&num_pci); | |
95 if(err) | |
96 { | |
97 printf("[pm3] Error occured during pci scan: %s\n",strerror(err)); | |
98 return err; | |
99 } | |
100 else | |
101 { | |
102 err = ENXIO; | |
103 for(i=0; i < num_pci; i++) | |
104 { | |
105 if(lst[i].vendor == VENDOR_3DLABS) | |
106 { | |
107 int idx; | |
108 const char *dname; | |
109 idx = find_chip(lst[i].device); | |
110 if(idx == -1) | |
111 continue; | |
112 dname = pci_device_name(VENDOR_3DLABS, lst[i].device); | |
113 dname = dname ? dname : "Unknown chip"; | |
114 printf("[pm3] Found chip: %s\n", dname); | |
115 pm3_cap.device_id = lst[i].device; | |
116 err = 0; | |
117 memcpy(&pci_info, &lst[i], sizeof(pciinfo_t)); | |
118 break; | |
119 } | |
120 } | |
121 } | |
122 if(err && verbose) printf("[pm3] Can't find chip\n"); | |
123 return err; | |
124 } | |
125 | |
126 #define PRINT_REG(reg) \ | |
127 { \ | |
128 long _foo = READ_REG(reg); \ | |
129 printf("[pm3] " #reg " (%x) = %#lx (%li)\n", reg, _foo, _foo); \ | |
130 } | |
131 | |
132 int vixInit(void) | |
133 { | |
134 pm3_reg_base = map_phys_mem(pci_info.base0, 0x20000); | |
135 pm3_mem = map_phys_mem(pci_info.base2, 0x2000000); | |
136 return 0; | |
137 } | |
138 | |
139 void vixDestroy(void) | |
140 { | |
141 unmap_phys_mem(pm3_reg_base, 0x20000); | |
142 unmap_phys_mem(pm3_mem, 0x2000000); | |
143 } | |
144 | |
145 int vixGetCapability(vidix_capability_t *to) | |
146 { | |
147 memcpy(to, &pm3_cap, sizeof(vidix_capability_t)); | |
148 return 0; | |
149 } | |
150 | |
151 static int is_supported_fourcc(uint32_t fourcc) | |
152 { | |
153 switch(fourcc){ | |
154 case IMGFMT_YUY2: | |
155 case IMGFMT_UYVY: | |
156 return 1; | |
157 default: | |
158 return 0; | |
159 } | |
160 } | |
161 | |
162 int vixQueryFourcc(vidix_fourcc_t *to) | |
163 { | |
164 if(is_supported_fourcc(to->fourcc)) | |
165 { | |
166 to->depth = VID_DEPTH_1BPP | VID_DEPTH_2BPP | | |
167 VID_DEPTH_4BPP | VID_DEPTH_8BPP | | |
168 VID_DEPTH_12BPP| VID_DEPTH_15BPP| | |
169 VID_DEPTH_16BPP| VID_DEPTH_24BPP| | |
170 VID_DEPTH_32BPP; | |
171 to->flags = VID_CAP_EXPAND | VID_CAP_SHRINK | VID_CAP_COLORKEY; | |
172 return 0; | |
173 } | |
174 else to->depth = to->flags = 0; | |
175 return ENOSYS; | |
176 } | |
177 | |
178 #define FORMAT_RGB8888 PM3VideoOverlayMode_COLORFORMAT_RGB8888 | |
179 #define FORMAT_RGB4444 PM3VideoOverlayMode_COLORFORMAT_RGB4444 | |
180 #define FORMAT_RGB5551 PM3VideoOverlayMode_COLORFORMAT_RGB5551 | |
181 #define FORMAT_RGB565 PM3VideoOverlayMode_COLORFORMAT_RGB565 | |
182 #define FORMAT_RGB332 PM3VideoOverlayMode_COLORFORMAT_RGB332 | |
183 #define FORMAT_BGR8888 PM3VideoOverlayMode_COLORFORMAT_BGR8888 | |
184 #define FORMAT_BGR4444 PM3VideoOverlayMode_COLORFORMAT_BGR4444 | |
185 #define FORMAT_BGR5551 PM3VideoOverlayMode_COLORFORMAT_BGR5551 | |
186 #define FORMAT_BGR565 PM3VideoOverlayMode_COLORFORMAT_BGR565 | |
187 #define FORMAT_BGR332 PM3VideoOverlayMode_COLORFORMAT_BGR332 | |
188 #define FORMAT_CI8 PM3VideoOverlayMode_COLORFORMAT_CI8 | |
189 #define FORMAT_VUY444 PM3VideoOverlayMode_COLORFORMAT_VUY444 | |
190 #define FORMAT_YUV444 PM3VideoOverlayMode_COLORFORMAT_YUV444 | |
191 #define FORMAT_VUY422 PM3VideoOverlayMode_COLORFORMAT_VUY422 | |
192 #define FORMAT_YUV422 PM3VideoOverlayMode_COLORFORMAT_YUV422 | |
193 | |
194 /* Notice, have to check that we dont overflow the deltas here ... */ | |
195 static void | |
196 compute_scale_factor( | |
197 short* src_w, short* dst_w, | |
198 unsigned int* shrink_delta, unsigned int* zoom_delta) | |
199 { | |
200 /* NOTE: If we don't return reasonable values here then the video | |
201 * unit can potential shut off and won't display an image until re-enabled. | |
202 * Seems as though the zoom_delta is o.k, and I've not had the problem. | |
203 * The 'shrink_delta' is prone to this the most - FIXME ! */ | |
204 | |
205 if (*src_w >= *dst_w) { | |
206 *src_w &= ~0x3; | |
207 *dst_w &= ~0x3; | |
208 *shrink_delta = (((*src_w << 16) / *dst_w) + 0x0f) & 0x0ffffff0; | |
209 *zoom_delta = 1<<16; | |
210 if ( ((*shrink_delta * *dst_w) >> 16) & 0x03 ) | |
211 *shrink_delta += 0x10; | |
212 } else { | |
213 *src_w &= ~0x3; | |
214 *dst_w &= ~0x3; | |
215 *zoom_delta = (((*src_w << 16) / *dst_w) + 0x0f) & 0x0001fff0; | |
216 *shrink_delta = 1<<16; | |
217 if ( ((*zoom_delta * *dst_w) >> 16) & 0x03 ) | |
218 *zoom_delta += 0x10; | |
219 } | |
220 } | |
221 | |
222 static int frames[VID_PLAY_MAXFRAMES]; | |
223 | |
224 static long overlay_mode, overlay_control; | |
225 | |
226 int vixConfigPlayback(vidix_playback_t *info) | |
227 { | |
228 int shrink, zoom; | |
229 short src_w, drw_w; | |
230 short src_h, drw_h; | |
231 long base0; | |
232 int pitch; | |
233 int format; | |
234 unsigned int i; | |
235 | |
236 TRACE_ENTER(); | |
237 | |
238 if(!is_supported_fourcc(info->fourcc)) | |
239 return -1; | |
240 | |
241 switch(info->fourcc){ | |
242 case IMGFMT_YUY2: | |
243 format = FORMAT_YUV422; | |
244 break; | |
245 case IMGFMT_UYVY: | |
246 format = FORMAT_VUY422; | |
247 break; | |
248 default: | |
249 return -1; | |
250 } | |
251 | |
252 src_w = info->src.w; | |
253 src_h = info->src.h; | |
254 | |
255 drw_w = info->dest.w; | |
256 drw_h = info->dest.h; | |
257 | |
258 pitch = src_w; | |
259 | |
260 /* Assume we have 16 MB to play with */ | |
261 info->num_frames = 0x1000000 / (pitch * src_h * 2); | |
262 if(info->num_frames > VID_PLAY_MAXFRAMES) | |
263 info->num_frames = VID_PLAY_MAXFRAMES; | |
264 | |
265 /* Start at 16 MB. Let's hope it's not in use. */ | |
266 base0 = 0x1000000; | |
267 info->dga_addr = pm3_mem + base0; | |
268 | |
269 info->dest.pitch.y = 2; | |
270 info->dest.pitch.u = 0; | |
271 info->dest.pitch.v = 0; | |
272 info->offset.y = 0; | |
273 info->offset.v = 0; | |
274 info->offset.u = 0; | |
275 info->frame_size = pitch * src_h * 2; | |
276 for(i = 0; i < info->num_frames; i++){ | |
277 info->offsets[i] = info->frame_size * i; | |
278 frames[i] = (base0 + info->offsets[i]) >> 1; | |
279 } | |
280 | |
281 compute_scale_factor(&src_w, &drw_w, &shrink, &zoom); | |
282 | |
283 WRITE_REG(PM3VideoOverlayBase0, base0 >> 1); | |
284 WRITE_REG(PM3VideoOverlayStride, PM3VideoOverlayStride_STRIDE(pitch)); | |
285 WRITE_REG(PM3VideoOverlayWidth, PM3VideoOverlayWidth_WIDTH(src_w)); | |
286 WRITE_REG(PM3VideoOverlayHeight, PM3VideoOverlayHeight_HEIGHT(src_h)); | |
287 WRITE_REG(PM3VideoOverlayOrigin, 0); | |
288 | |
289 /* Scale the source to the destinationsize */ | |
290 if (src_h == drw_h) { | |
291 WRITE_REG(PM3VideoOverlayYDelta, PM3VideoOverlayYDelta_NONE); | |
292 } else { | |
293 WRITE_REG(PM3VideoOverlayYDelta, | |
294 PM3VideoOverlayYDelta_DELTA(src_h, drw_h)); | |
295 } | |
296 if (src_w == drw_w) { | |
297 WRITE_REG(PM3VideoOverlayShrinkXDelta, 1<<16); | |
298 WRITE_REG(PM3VideoOverlayZoomXDelta, 1<<16); | |
299 } else { | |
300 WRITE_REG(PM3VideoOverlayShrinkXDelta, shrink); | |
301 WRITE_REG(PM3VideoOverlayZoomXDelta, zoom); | |
302 } | |
303 WRITE_REG(PM3VideoOverlayIndex, 0); | |
304 | |
305 /* Now set the ramdac video overlay region and mode */ | |
306 RAMDAC_SET_REG(PM3RD_VideoOverlayXStartLow, (info->dest.x & 0xff)); | |
307 RAMDAC_SET_REG(PM3RD_VideoOverlayXStartHigh, (info->dest.x & 0xf00)>>8); | |
308 RAMDAC_SET_REG(PM3RD_VideoOverlayXEndLow, (info->dest.x+drw_w) & 0xff); | |
309 RAMDAC_SET_REG(PM3RD_VideoOverlayXEndHigh, | |
310 ((info->dest.x+drw_w) & 0xf00)>>8); | |
311 RAMDAC_SET_REG(PM3RD_VideoOverlayYStartLow, (info->dest.y & 0xff)); | |
312 RAMDAC_SET_REG(PM3RD_VideoOverlayYStartHigh, (info->dest.y & 0xf00)>>8); | |
313 RAMDAC_SET_REG(PM3RD_VideoOverlayYEndLow, (info->dest.y+drw_h) & 0xff); | |
314 RAMDAC_SET_REG(PM3RD_VideoOverlayYEndHigh, | |
315 ((info->dest.y+drw_h) & 0xf00)>>8); | |
316 | |
317 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyR, 0xff); | |
318 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyG, 0x00); | |
319 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyB, 0xff); | |
320 | |
321 overlay_mode = | |
322 1 << 5 | | |
323 format | | |
324 PM3VideoOverlayMode_FILTER_FULL | | |
325 PM3VideoOverlayMode_BUFFERSYNC_MANUAL | | |
326 PM3VideoOverlayMode_FLIP_VIDEO; | |
327 | |
328 overlay_control = | |
329 PM3RD_VideoOverlayControl_KEY_COLOR | | |
330 PM3RD_VideoOverlayControl_MODE_MAINKEY | | |
331 PM3RD_VideoOverlayControl_DIRECTCOLOR_ENABLED; | |
332 | |
333 TRACE_EXIT(); | |
334 return 0; | |
335 } | |
336 | |
337 int vixPlaybackOn(void) | |
338 { | |
339 TRACE_ENTER(); | |
340 | |
341 WRITE_REG(PM3VideoOverlayMode, | |
342 overlay_mode | PM3VideoOverlayMode_ENABLE); | |
343 RAMDAC_SET_REG(PM3RD_VideoOverlayControl, | |
344 overlay_control | PM3RD_VideoOverlayControl_ENABLE); | |
345 WRITE_REG(PM3VideoOverlayUpdate, | |
346 PM3VideoOverlayUpdate_ENABLE); | |
347 | |
348 TRACE_EXIT(); | |
349 return 0; | |
350 } | |
351 | |
352 int vixPlaybackOff(void) | |
353 { | |
354 RAMDAC_SET_REG(PM3RD_VideoOverlayControl, | |
355 PM3RD_VideoOverlayControl_DISABLE); | |
356 WRITE_REG(PM3VideoOverlayMode, | |
357 PM3VideoOverlayMode_DISABLE); | |
358 | |
359 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyR, 0x01); | |
360 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyG, 0x01); | |
361 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyB, 0xfe); | |
362 | |
363 return 0; | |
364 } | |
365 | |
366 int vixPlaybackFrameSelect(unsigned int frame) | |
367 { | |
368 WRITE_REG(PM3VideoOverlayBase0, frames[frame]); | |
369 return 0; | |
370 } |