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 along
18 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include <sys/types.h>
35 #include "pci_names.h"
37 #include "glint_regs.h"
39 /* MBytes of video memory to use */
43 #define TRACE_ENTER() fprintf(stderr, "%s: enter\n", __FUNCTION__)
44 #define TRACE_EXIT() fprintf(stderr, "%s: exit\n", __FUNCTION__)
50 #define WRITE_REG(offset,val) \
51 *(volatile unsigned long *)(((unsigned char *)(pm2_reg_base)) + offset) = (val)
52 #define READ_REG(offset) \
53 *(volatile unsigned long *)(((unsigned char *)(pm2_reg_base)) + offset)
55 static pciinfo_t pci_info
;
57 static void *pm2_reg_base
;
60 static int pm2_vidmem
= PM2_VIDMEM
;
62 static vidix_capability_t pm2_cap
=
64 "3DLabs Permedia2 driver",
65 "Måns Rullgård <mru@users.sf.net>",
73 FLAG_UPSCALER
|FLAG_DOWNSCALER
,
79 static unsigned int pm2_card_ids
[] =
81 (VENDOR_3DLABS
<< 16) | DEVICE_3DLABS_PERMEDIA2
,
82 (VENDOR_TEXAS
<< 16) | DEVICE_TEXAS_TVP4020_PERMEDIA_2
85 static int find_chip(unsigned int vendor
, uint32_t chip_id
)
87 unsigned int vci
= (vendor
<< 16) | chip_id
;
89 for(i
= 0; i
< sizeof(pm2_card_ids
)/sizeof(unsigned int); i
++){
90 if(vci
== pm2_card_ids
[i
]) return i
;
95 static int pm2_probe(int verbose
, int force
)
97 pciinfo_t lst
[MAX_PCI_DEVICES
];
101 err
= pci_scan(lst
,&num_pci
);
104 printf("[pm2] Error occurred during pci scan: %s\n",strerror(err
));
110 for(i
=0; i
< num_pci
; i
++)
114 idx
= find_chip(lst
[i
].vendor
, lst
[i
].device
);
117 dname
= pci_device_name(lst
[i
].vendor
, lst
[i
].device
);
118 dname
= dname
? dname
: "Unknown chip";
119 printf("[pm2] Found chip: %s\n", dname
);
120 pm2_cap
.device_id
= lst
[i
].device
;
122 memcpy(&pci_info
, &lst
[i
], sizeof(pciinfo_t
));
126 if(err
&& verbose
) printf("[pm2] Can't find chip.\n");
130 #define PRINT_REG(reg) \
132 long _foo = READ_REG(reg); \
133 printf("[pm2] " #reg " (%x) = %#lx (%li)\n", reg, _foo, _foo); \
136 static int pm2_init(void)
139 pm2_reg_base
= map_phys_mem(pci_info
.base0
, 0x10000);
140 pm2_mem
= map_phys_mem(pci_info
.base1
, 1 << 23);
141 if((vm
= getenv("PM2_VIDMEM"))){
142 pm2_vidmem
= strtol(vm
, NULL
, 0);
147 static void pm2_destroy(void)
149 unmap_phys_mem(pm2_reg_base
, 0x10000);
150 unmap_phys_mem(pm2_mem
, 1 << 23);
153 static int pm2_get_caps(vidix_capability_t
*to
)
155 memcpy(to
, &pm2_cap
, sizeof(vidix_capability_t
));
159 static int is_supported_fourcc(uint32_t fourcc
)
169 static int pm2_query_fourcc(vidix_fourcc_t
*to
)
171 if(is_supported_fourcc(to
->fourcc
))
173 to
->depth
= VID_DEPTH_ALL
;
174 to
->flags
= VID_CAP_EXPAND
| VID_CAP_SHRINK
| VID_CAP_COLORKEY
;
177 else to
->depth
= to
->flags
= 0;
181 #define FORMAT_YUV422 ((1 << 6) | 3 | (1 << 4))
183 #define PPROD(a,b,c) (a | (b << 3) | (c << 6))
185 static unsigned int ppcodes
[][2] = {
187 {32, PPROD(1, 0, 0)},
188 {64, PPROD(1, 1, 0)},
189 {96, PPROD(1, 1, 1)},
190 {128, PPROD(2, 1, 1)},
191 {160, PPROD(2, 2, 1)},
192 {192, PPROD(2, 2, 2)},
193 {224, PPROD(3, 2, 1)},
194 {256, PPROD(3, 2, 2)},
195 {288, PPROD(3, 3, 1)},
196 {320, PPROD(3, 3, 2)},
197 {384, PPROD(3, 3, 3)},
198 {416, PPROD(4, 3, 1)},
199 {448, PPROD(4, 3, 2)},
200 {512, PPROD(4, 3, 3)},
201 {544, PPROD(4, 4, 1)},
202 {576, PPROD(4, 4, 2)},
203 {640, PPROD(4, 4, 3)},
204 {768, PPROD(4, 4, 4)},
205 {800, PPROD(5, 4, 1)},
206 {832, PPROD(5, 4, 2)},
207 {896, PPROD(5, 4, 3)},
208 {1024, PPROD(5, 4, 4)},
209 {1056, PPROD(5, 5, 1)},
210 {1088, PPROD(5, 5, 2)},
211 {1152, PPROD(5, 5, 3)},
212 {1280, PPROD(5, 5, 4)},
213 {1536, PPROD(5, 5, 5)},
214 {1568, PPROD(6, 5, 1)},
215 {1600, PPROD(6, 5, 2)},
216 {1664, PPROD(6, 5, 3)},
217 {1792, PPROD(6, 5, 4)},
218 {2048, PPROD(6, 5, 5)}
221 static int frames
[VID_PLAY_MAXFRAMES
];
223 static int pm2_config_playback(vidix_playback_t
*info
)
225 unsigned int src_w
, drw_w
;
226 unsigned int src_h
, drw_h
;
228 unsigned int stride
, sstr
;
231 unsigned int ppcode
= 0, sppc
= 0;
232 unsigned int pitch
= 0;
236 switch(info
->fourcc
){
238 format
= FORMAT_YUV422
;
247 drw_w
= info
->dest
.w
;
248 drw_h
= info
->dest
.h
;
250 sstr
= READ_REG(PMScreenStride
) * 2;
253 for(i
= 1; i
< sizeof(ppcodes
) / sizeof(ppcodes
[0]); i
++){
254 if((!stride
) && (ppcodes
[i
][0] >= src_w
)){
255 stride
= ppcodes
[i
][0];
256 ppcode
= ppcodes
[i
][1];
257 pitch
= ppcodes
[i
][0] - ppcodes
[i
-1][0];
259 if(ppcodes
[i
][0] == sstr
)
260 sppc
= ppcodes
[i
][1];
266 info
->num_frames
= pm2_vidmem
*1024*1024 / (stride
* src_h
* 2);
267 if(info
->num_frames
> VID_PLAY_MAXFRAMES
)
268 info
->num_frames
= VID_PLAY_MAXFRAMES
;
270 /* Use end of video memory. Assume the card has 8 MB */
271 base0
= (8 - pm2_vidmem
)*1024*1024;
272 info
->dga_addr
= pm2_mem
+ base0
;
274 info
->dest
.pitch
.y
= pitch
*2;
275 info
->dest
.pitch
.u
= 0;
276 info
->dest
.pitch
.v
= 0;
280 info
->frame_size
= stride
* src_h
* 2;
282 for(i
= 0; i
< info
->num_frames
; i
++){
283 info
->offsets
[i
] = info
->frame_size
* i
;
284 frames
[i
] = (base0
+ info
->offsets
[i
]) >> 1;
287 WRITE_REG(WindowOrigin
, 0);
288 WRITE_REG(dY
, 1 << 16);
289 WRITE_REG(RasterizerMode
, 0);
290 WRITE_REG(ScissorMode
, 0);
291 WRITE_REG(AreaStippleMode
, 0);
292 WRITE_REG(StencilMode
, 0);
293 WRITE_REG(TextureAddressMode
, 1);
295 WRITE_REG(dSdyDom
, 0);
298 WRITE_REG(PMTextureMapFormat
, (1 << 19) | ppcode
);
299 WRITE_REG(PMTextureDataFormat
, format
);
300 WRITE_REG(PMTextureReadMode
, (1 << 17) | /* FilterMode */
301 (11 << 13) | (11 << 9) /* TextureSize log2 */ | 1);
302 WRITE_REG(ColorDDAMode
, 0);
303 WRITE_REG(TextureColorMode
, (0 << 4) /* RGB */ | (3 << 1) /* Copy */ | 1);
304 WRITE_REG(AlphaBlendMode
, 0);
305 WRITE_REG(DitherMode
, (1 << 10) | 1);
306 WRITE_REG(LogicalOpMode
, 0);
307 WRITE_REG(FBReadMode
, sppc
);
308 WRITE_REG(FBHardwareWriteMask
, 0xFFFFFFFF);
309 WRITE_REG(FBWriteMode
, 1);
310 WRITE_REG(YUVMode
, 1);
312 WRITE_REG(SStart
, 0);
313 WRITE_REG(TStart
, 0);
315 WRITE_REG(dSdx
, (src_w
<< 20) / drw_w
);
316 WRITE_REG(dTdyDom
, (src_h
<< 20) / drw_h
);
317 WRITE_REG(RectangleOrigin
, info
->dest
.x
| (info
->dest
.y
<< 16));
318 WRITE_REG(RectangleSize
, (drw_h
<< 16) | drw_w
);
324 static int pm2_playback_on(void)
332 static int pm2_playback_off(void)
334 WRITE_REG(YUVMode
, 0);
335 WRITE_REG(TextureColorMode
, 0);
336 WRITE_REG(TextureAddressMode
, 0);
337 WRITE_REG(TextureReadMode
, 0);
341 static int pm2_frame_select(unsigned int frame
)
343 WRITE_REG(PMTextureBaseAddress
, frames
[frame
]);
344 WRITE_REG(Render
, PrimitiveRectangle
| XPositive
| YPositive
|
349 VDXDriver pm2_drv
= {
353 .get_caps
= pm2_get_caps
,
354 .query_fourcc
= pm2_query_fourcc
,
356 .destroy
= pm2_destroy
,
357 .config_playback
= pm2_config_playback
,
358 .playback_on
= pm2_playback_on
,
359 .playback_off
= pm2_playback_off
,
360 .frame_sel
= pm2_frame_select
,