Comment out the correct #endif directive.
[mplayer/greg.git] / vidix / pm2_vid.c
blobd1f5de0e5868e653edba2340725bc30410f3b360
1 /*
2 * VIDIX driver for 3DLabs Permedia 2 chipsets.
3 * Copyright (C) 2002 Måns Rullgård
5 * This file is part of MPlayer.
7 * MPlayer is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * MPlayer is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with MPlayer; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <inttypes.h>
27 #include <sys/types.h>
28 #include <unistd.h>
30 #include "vidix.h"
31 #include "vidixlib.h"
32 #include "fourcc.h"
33 #include "dha.h"
34 #include "pci_ids.h"
35 #include "pci_names.h"
36 #include "config.h"
38 #include "glint_regs.h"
40 /* MBytes of video memory to use */
41 #define PM2_VIDMEM 6
43 #if 0
44 #define TRACE_ENTER() fprintf(stderr, "%s: enter\n", __FUNCTION__)
45 #define TRACE_EXIT() fprintf(stderr, "%s: exit\n", __FUNCTION__)
46 #else
47 #define TRACE_ENTER()
48 #define TRACE_EXIT()
49 #endif
51 #define WRITE_REG(offset,val) \
52 *(volatile unsigned long *)(((unsigned char *)(pm2_reg_base)) + offset) = (val)
53 #define READ_REG(offset) \
54 *(volatile unsigned long *)(((unsigned char *)(pm2_reg_base)) + offset)
56 static pciinfo_t pci_info;
58 static void *pm2_reg_base;
59 static void *pm2_mem;
61 static int pm2_vidmem = PM2_VIDMEM;
63 static vidix_capability_t pm2_cap =
65 "3DLabs Permedia2 driver",
66 "Måns Rullgård <mru@users.sf.net>",
67 TYPE_OUTPUT,
68 { 0, 0, 0, 0 },
69 2048,
70 2048,
73 -1,
74 FLAG_UPSCALER|FLAG_DOWNSCALER,
75 VENDOR_3DLABS,
76 -1,
77 { 0, 0, 0, 0 }
80 static unsigned int pm2_card_ids[] =
82 (VENDOR_3DLABS << 16) | DEVICE_3DLABS_PERMEDIA2,
83 (VENDOR_TEXAS << 16) | DEVICE_TEXAS_TVP4020_PERMEDIA_2
86 static int find_chip(unsigned int vendor, uint32_t chip_id)
88 unsigned int vci = (vendor << 16) | chip_id;
89 unsigned i;
90 for(i = 0; i < sizeof(pm2_card_ids)/sizeof(unsigned int); i++){
91 if(vci == pm2_card_ids[i]) return i;
93 return -1;
96 static int pm2_probe(int verbose, int force __attribute__ ((unused)))
98 pciinfo_t lst[MAX_PCI_DEVICES];
99 unsigned i,num_pci;
100 int err;
102 err = pci_scan(lst,&num_pci);
103 if(err)
105 printf("[pm2] Error occurred during pci scan: %s\n",strerror(err));
106 return err;
108 else
110 err = ENXIO;
111 for(i=0; i < num_pci; i++)
113 int idx;
114 const char *dname;
115 idx = find_chip(lst[i].vendor, lst[i].device);
116 if(idx == -1)
117 continue;
118 dname = pci_device_name(lst[i].vendor, lst[i].device);
119 dname = dname ? dname : "Unknown chip";
120 printf("[pm2] Found chip: %s\n", dname);
121 pm2_cap.device_id = lst[i].device;
122 err = 0;
123 memcpy(&pci_info, &lst[i], sizeof(pciinfo_t));
124 break;
127 if(err && verbose) printf("[pm2] Can't find chip.\n");
128 return err;
131 #define PRINT_REG(reg) \
133 long _foo = READ_REG(reg); \
134 printf("[pm2] " #reg " (%x) = %#lx (%li)\n", reg, _foo, _foo); \
137 static int pm2_init(void)
139 char *vm;
140 pm2_reg_base = map_phys_mem(pci_info.base0, 0x10000);
141 pm2_mem = map_phys_mem(pci_info.base1, 1 << 23);
142 if((vm = getenv("PM2_VIDMEM"))){
143 pm2_vidmem = strtol(vm, NULL, 0);
145 return 0;
148 static void pm2_destroy(void)
150 unmap_phys_mem(pm2_reg_base, 0x10000);
151 unmap_phys_mem(pm2_mem, 1 << 23);
154 static int pm2_get_caps(vidix_capability_t *to)
156 memcpy(to, &pm2_cap, sizeof(vidix_capability_t));
157 return 0;
160 static int is_supported_fourcc(uint32_t fourcc)
162 switch(fourcc){
163 case IMGFMT_YUY2:
164 return 1;
165 default:
166 return 0;
170 static int pm2_query_fourcc(vidix_fourcc_t *to)
172 if(is_supported_fourcc(to->fourcc))
174 to->depth = VID_DEPTH_ALL;
175 to->flags = VID_CAP_EXPAND | VID_CAP_SHRINK | VID_CAP_COLORKEY;
176 return 0;
178 else to->depth = to->flags = 0;
179 return ENOSYS;
182 #define FORMAT_YUV422 ((1 << 6) | 3 | (1 << 4))
184 #define PPROD(a,b,c) (a | (b << 3) | (c << 6))
186 static unsigned int ppcodes[][2] = {
187 {0, 0},
188 {32, PPROD(1, 0, 0)},
189 {64, PPROD(1, 1, 0)},
190 {96, PPROD(1, 1, 1)},
191 {128, PPROD(2, 1, 1)},
192 {160, PPROD(2, 2, 1)},
193 {192, PPROD(2, 2, 2)},
194 {224, PPROD(3, 2, 1)},
195 {256, PPROD(3, 2, 2)},
196 {288, PPROD(3, 3, 1)},
197 {320, PPROD(3, 3, 2)},
198 {384, PPROD(3, 3, 3)},
199 {416, PPROD(4, 3, 1)},
200 {448, PPROD(4, 3, 2)},
201 {512, PPROD(4, 3, 3)},
202 {544, PPROD(4, 4, 1)},
203 {576, PPROD(4, 4, 2)},
204 {640, PPROD(4, 4, 3)},
205 {768, PPROD(4, 4, 4)},
206 {800, PPROD(5, 4, 1)},
207 {832, PPROD(5, 4, 2)},
208 {896, PPROD(5, 4, 3)},
209 {1024, PPROD(5, 4, 4)},
210 {1056, PPROD(5, 5, 1)},
211 {1088, PPROD(5, 5, 2)},
212 {1152, PPROD(5, 5, 3)},
213 {1280, PPROD(5, 5, 4)},
214 {1536, PPROD(5, 5, 5)},
215 {1568, PPROD(6, 5, 1)},
216 {1600, PPROD(6, 5, 2)},
217 {1664, PPROD(6, 5, 3)},
218 {1792, PPROD(6, 5, 4)},
219 {2048, PPROD(6, 5, 5)}
222 static int frames[VID_PLAY_MAXFRAMES];
224 static int pm2_config_playback(vidix_playback_t *info)
226 unsigned int src_w, drw_w;
227 unsigned int src_h, drw_h;
228 long base0;
229 unsigned int stride, sstr;
230 unsigned int format;
231 unsigned int i;
232 unsigned int ppcode = 0, sppc = 0;
233 unsigned int pitch = 0;
235 TRACE_ENTER();
237 switch(info->fourcc){
238 case IMGFMT_YUY2:
239 format = FORMAT_YUV422;
240 break;
241 default:
242 return -1;
245 src_w = info->src.w;
246 src_h = info->src.h;
248 drw_w = info->dest.w;
249 drw_h = info->dest.h;
251 sstr = READ_REG(PMScreenStride) * 2;
253 stride = 0;
254 for(i = 1; i < sizeof(ppcodes) / sizeof(ppcodes[0]); i++){
255 if((!stride) && (ppcodes[i][0] >= src_w)){
256 stride = ppcodes[i][0];
257 ppcode = ppcodes[i][1];
258 pitch = ppcodes[i][0] - ppcodes[i-1][0];
260 if(ppcodes[i][0] == sstr)
261 sppc = ppcodes[i][1];
264 if(!stride)
265 return -1;
267 info->num_frames = pm2_vidmem*1024*1024 / (stride * src_h * 2);
268 if(info->num_frames > VID_PLAY_MAXFRAMES)
269 info->num_frames = VID_PLAY_MAXFRAMES;
271 /* Use end of video memory. Assume the card has 8 MB */
272 base0 = (8 - pm2_vidmem)*1024*1024;
273 info->dga_addr = pm2_mem + base0;
275 info->dest.pitch.y = pitch*2;
276 info->dest.pitch.u = 0;
277 info->dest.pitch.v = 0;
278 info->offset.y = 0;
279 info->offset.v = 0;
280 info->offset.u = 0;
281 info->frame_size = stride * src_h * 2;
283 for(i = 0; i < info->num_frames; i++){
284 info->offsets[i] = info->frame_size * i;
285 frames[i] = (base0 + info->offsets[i]) >> 1;
288 WRITE_REG(WindowOrigin, 0);
289 WRITE_REG(dY, 1 << 16);
290 WRITE_REG(RasterizerMode, 0);
291 WRITE_REG(ScissorMode, 0);
292 WRITE_REG(AreaStippleMode, 0);
293 WRITE_REG(StencilMode, 0);
294 WRITE_REG(TextureAddressMode, 1);
296 WRITE_REG(dSdyDom, 0);
297 WRITE_REG(dTdx, 0);
299 WRITE_REG(PMTextureMapFormat, (1 << 19) | ppcode);
300 WRITE_REG(PMTextureDataFormat, format);
301 WRITE_REG(PMTextureReadMode, (1 << 17) | /* FilterMode */
302 (11 << 13) | (11 << 9) /* TextureSize log2 */ | 1);
303 WRITE_REG(ColorDDAMode, 0);
304 WRITE_REG(TextureColorMode, (0 << 4) /* RGB */ | (3 << 1) /* Copy */ | 1);
305 WRITE_REG(AlphaBlendMode, 0);
306 WRITE_REG(DitherMode, (1 << 10) | 1);
307 WRITE_REG(LogicalOpMode, 0);
308 WRITE_REG(FBReadMode, sppc);
309 WRITE_REG(FBHardwareWriteMask, 0xFFFFFFFF);
310 WRITE_REG(FBWriteMode, 1);
311 WRITE_REG(YUVMode, 1);
313 WRITE_REG(SStart, 0);
314 WRITE_REG(TStart, 0);
316 WRITE_REG(dSdx, (src_w << 20) / drw_w);
317 WRITE_REG(dTdyDom, (src_h << 20) / drw_h);
318 WRITE_REG(RectangleOrigin, info->dest.x | (info->dest.y << 16));
319 WRITE_REG(RectangleSize, (drw_h << 16) | drw_w);
321 TRACE_EXIT();
322 return 0;
325 static int pm2_playback_on(void)
327 TRACE_ENTER();
329 TRACE_EXIT();
330 return 0;
333 static int pm2_playback_off(void)
335 WRITE_REG(YUVMode, 0);
336 WRITE_REG(TextureColorMode, 0);
337 WRITE_REG(TextureAddressMode, 0);
338 WRITE_REG(TextureReadMode, 0);
339 return 0;
342 static int pm2_frame_select(unsigned int frame)
344 WRITE_REG(PMTextureBaseAddress, frames[frame]);
345 WRITE_REG(Render, PrimitiveRectangle | XPositive | YPositive |
346 TextureEnable);
347 return 0;
350 VDXDriver pm2_drv = {
351 "pm2",
352 NULL,
353 .probe = pm2_probe,
354 .get_caps = pm2_get_caps,
355 .query_fourcc = pm2_query_fourcc,
356 .init = pm2_init,
357 .destroy = pm2_destroy,
358 .config_playback = pm2_config_playback,
359 .playback_on = pm2_playback_on,
360 .playback_off = pm2_playback_off,
361 .frame_sel = pm2_frame_select,