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
27 #include <sys/types.h>
35 #include "pci_names.h"
38 #include "glint_regs.h"
40 /* MBytes of video memory to use */
44 #define TRACE_ENTER() fprintf(stderr, "%s: enter\n", __FUNCTION__)
45 #define TRACE_EXIT() fprintf(stderr, "%s: exit\n", __FUNCTION__)
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
;
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>",
74 FLAG_UPSCALER
|FLAG_DOWNSCALER
,
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
;
90 for(i
= 0; i
< sizeof(pm2_card_ids
)/sizeof(unsigned int); i
++){
91 if(vci
== pm2_card_ids
[i
]) return i
;
96 static int pm2_probe(int verbose
, int force
__attribute__ ((unused
)))
98 pciinfo_t lst
[MAX_PCI_DEVICES
];
102 err
= pci_scan(lst
,&num_pci
);
105 printf("[pm2] Error occurred during pci scan: %s\n",strerror(err
));
111 for(i
=0; i
< num_pci
; i
++)
115 idx
= find_chip(lst
[i
].vendor
, lst
[i
].device
);
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
;
123 memcpy(&pci_info
, &lst
[i
], sizeof(pciinfo_t
));
127 if(err
&& verbose
) printf("[pm2] Can't find chip.\n");
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)
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);
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
));
160 static int is_supported_fourcc(uint32_t fourcc
)
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
;
178 else to
->depth
= to
->flags
= 0;
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] = {
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
;
229 unsigned int stride
, sstr
;
232 unsigned int ppcode
= 0, sppc
= 0;
233 unsigned int pitch
= 0;
237 switch(info
->fourcc
){
239 format
= FORMAT_YUV422
;
248 drw_w
= info
->dest
.w
;
249 drw_h
= info
->dest
.h
;
251 sstr
= READ_REG(PMScreenStride
) * 2;
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];
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;
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);
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
);
325 static int pm2_playback_on(void)
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);
342 static int pm2_frame_select(unsigned int frame
)
344 WRITE_REG(PMTextureBaseAddress
, frames
[frame
]);
345 WRITE_REG(Render
, PrimitiveRectangle
| XPositive
| YPositive
|
350 VDXDriver pm2_drv
= {
354 .get_caps
= pm2_get_caps
,
355 .query_fourcc
= pm2_query_fourcc
,
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
,