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 }