2 * VIDIX driver for 3DLabs Glint R3 and Permedia 3 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
34 #include "pci_names.h"
40 #define TRACE_ENTER() fprintf(stderr, "%s: enter\n", __FUNCTION__)
41 #define TRACE_EXIT() fprintf(stderr, "%s: exit\n", __FUNCTION__)
47 static pciinfo_t pci_info
;
52 static vidix_capability_t pm3_cap
=
54 "3DLabs GLINT R3/Permedia3 driver",
55 "Måns Rullgård <mru@users.sf.net>",
63 FLAG_UPSCALER
|FLAG_DOWNSCALER
,
69 static unsigned short pm3_card_ids
[] =
71 DEVICE_3DLABS_GLINT_R3
74 static int find_chip(unsigned chip_id
)
77 for(i
= 0;i
< sizeof(pm3_card_ids
)/sizeof(unsigned short);i
++)
79 if(chip_id
== pm3_card_ids
[i
]) return i
;
84 static int pm3_probe(int verbose
, int force
)
86 pciinfo_t lst
[MAX_PCI_DEVICES
];
90 err
= pci_scan(lst
,&num_pci
);
93 printf("[pm3] Error occurred during pci scan: %s\n",strerror(err
));
99 for(i
=0; i
< num_pci
; i
++)
101 if(lst
[i
].vendor
== VENDOR_3DLABS
)
105 idx
= find_chip(lst
[i
].device
);
108 dname
= pci_device_name(VENDOR_3DLABS
, lst
[i
].device
);
109 dname
= dname
? dname
: "Unknown chip";
110 printf("[pm3] Found chip: %s\n", dname
);
112 if ((lst
[i
].command
& PCI_COMMAND_IO
) == 0)
114 printf("[pm3] Device is disabled, ignoring\n");
118 pm3_cap
.device_id
= lst
[i
].device
;
120 memcpy(&pci_info
, &lst
[i
], sizeof(pciinfo_t
));
125 if(err
&& verbose
) printf("[pm3] Can't find chip\n");
129 #define PRINT_REG(reg) \
131 long _foo = READ_REG(reg); \
132 printf("[pm3] " #reg " (%x) = %#lx (%li)\n", reg, _foo, _foo); \
135 static int pm3_init(void)
137 pm3_reg_base
= map_phys_mem(pci_info
.base0
, 0x20000);
138 pm3_mem
= map_phys_mem(pci_info
.base2
, 0x2000000);
142 static void pm3_destroy(void)
144 unmap_phys_mem(pm3_reg_base
, 0x20000);
145 unmap_phys_mem(pm3_mem
, 0x2000000);
148 static int pm3_get_caps(vidix_capability_t
*to
)
150 memcpy(to
, &pm3_cap
, sizeof(vidix_capability_t
));
154 static int is_supported_fourcc(uint32_t fourcc
)
165 static int pm3_query_fourcc(vidix_fourcc_t
*to
)
167 if(is_supported_fourcc(to
->fourcc
))
169 to
->depth
= VID_DEPTH_ALL
;
170 to
->flags
= VID_CAP_EXPAND
| VID_CAP_SHRINK
| VID_CAP_COLORKEY
;
173 else to
->depth
= to
->flags
= 0;
177 #define FORMAT_RGB8888 PM3VideoOverlayMode_COLORFORMAT_RGB8888
178 #define FORMAT_RGB4444 PM3VideoOverlayMode_COLORFORMAT_RGB4444
179 #define FORMAT_RGB5551 PM3VideoOverlayMode_COLORFORMAT_RGB5551
180 #define FORMAT_RGB565 PM3VideoOverlayMode_COLORFORMAT_RGB565
181 #define FORMAT_RGB332 PM3VideoOverlayMode_COLORFORMAT_RGB332
182 #define FORMAT_BGR8888 PM3VideoOverlayMode_COLORFORMAT_BGR8888
183 #define FORMAT_BGR4444 PM3VideoOverlayMode_COLORFORMAT_BGR4444
184 #define FORMAT_BGR5551 PM3VideoOverlayMode_COLORFORMAT_BGR5551
185 #define FORMAT_BGR565 PM3VideoOverlayMode_COLORFORMAT_BGR565
186 #define FORMAT_BGR332 PM3VideoOverlayMode_COLORFORMAT_BGR332
187 #define FORMAT_CI8 PM3VideoOverlayMode_COLORFORMAT_CI8
188 #define FORMAT_VUY444 PM3VideoOverlayMode_COLORFORMAT_VUY444
189 #define FORMAT_YUV444 PM3VideoOverlayMode_COLORFORMAT_YUV444
190 #define FORMAT_VUY422 PM3VideoOverlayMode_COLORFORMAT_VUY422
191 #define FORMAT_YUV422 PM3VideoOverlayMode_COLORFORMAT_YUV422
193 /* Notice, have to check that we don't overflow the deltas here ... */
195 compute_scale_factor(
196 short* src_w
, short* dst_w
,
197 uint32_t* shrink_delta
, uint32_t* zoom_delta
)
199 /* NOTE: If we don't return reasonable values here then the video
200 * unit can potential shut off and won't display an image until re-enabled.
201 * Seems as though the zoom_delta is o.k, and I've not had the problem.
202 * The 'shrink_delta' is prone to this the most - FIXME ! */
204 if (*src_w
>= *dst_w
) {
207 *shrink_delta
= (((*src_w
<< 16) / *dst_w
) + 0x0f) & 0x0ffffff0;
209 if ( ((*shrink_delta
* *dst_w
) >> 16) & 0x03 )
210 *shrink_delta
+= 0x10;
214 *zoom_delta
= (((*src_w
<< 16) / *dst_w
) + 0x0f) & 0x0001fff0;
215 *shrink_delta
= 1<<16;
216 if ( ((*zoom_delta
* *dst_w
) >> 16) & 0x03 )
221 static int frames
[VID_PLAY_MAXFRAMES
];
223 static long overlay_mode
, overlay_control
;
225 static int pm3_config_playback(vidix_playback_t
*info
)
227 uint32_t shrink
, zoom
;
237 if(!is_supported_fourcc(info
->fourcc
))
240 switch(info
->fourcc
){
242 format
= FORMAT_YUV422
;
245 format
= FORMAT_VUY422
;
254 drw_w
= info
->dest
.w
;
255 drw_h
= info
->dest
.h
;
259 /* Assume we have 16 MB to play with */
260 info
->num_frames
= 0x1000000 / (pitch
* src_h
* 2);
261 if(info
->num_frames
> VID_PLAY_MAXFRAMES
)
262 info
->num_frames
= VID_PLAY_MAXFRAMES
;
264 /* Start at 16 MB. Let's hope it's not in use. */
266 info
->dga_addr
= pm3_mem
+ base0
;
268 info
->dest
.pitch
.y
= 2;
269 info
->dest
.pitch
.u
= 0;
270 info
->dest
.pitch
.v
= 0;
274 info
->frame_size
= pitch
* src_h
* 2;
275 for(i
= 0; i
< info
->num_frames
; i
++){
276 info
->offsets
[i
] = info
->frame_size
* i
;
277 frames
[i
] = (base0
+ info
->offsets
[i
]) >> 1;
280 compute_scale_factor(&src_w
, &drw_w
, &shrink
, &zoom
);
282 WRITE_REG(PM3VideoOverlayBase0
, base0
>> 1);
283 WRITE_REG(PM3VideoOverlayStride
, PM3VideoOverlayStride_STRIDE(pitch
));
284 WRITE_REG(PM3VideoOverlayWidth
, PM3VideoOverlayWidth_WIDTH(src_w
));
285 WRITE_REG(PM3VideoOverlayHeight
, PM3VideoOverlayHeight_HEIGHT(src_h
));
286 WRITE_REG(PM3VideoOverlayOrigin
, 0);
288 /* Scale the source to the destinationsize */
289 if (src_h
== drw_h
) {
290 WRITE_REG(PM3VideoOverlayYDelta
, PM3VideoOverlayYDelta_NONE
);
292 WRITE_REG(PM3VideoOverlayYDelta
,
293 PM3VideoOverlayYDelta_DELTA(src_h
, drw_h
));
295 if (src_w
== drw_w
) {
296 WRITE_REG(PM3VideoOverlayShrinkXDelta
, 1<<16);
297 WRITE_REG(PM3VideoOverlayZoomXDelta
, 1<<16);
299 WRITE_REG(PM3VideoOverlayShrinkXDelta
, shrink
);
300 WRITE_REG(PM3VideoOverlayZoomXDelta
, zoom
);
302 WRITE_REG(PM3VideoOverlayIndex
, 0);
304 /* Now set the ramdac video overlay region and mode */
305 RAMDAC_SET_REG(PM3RD_VideoOverlayXStartLow
, (info
->dest
.x
& 0xff));
306 RAMDAC_SET_REG(PM3RD_VideoOverlayXStartHigh
, (info
->dest
.x
& 0xf00)>>8);
307 RAMDAC_SET_REG(PM3RD_VideoOverlayXEndLow
, (info
->dest
.x
+drw_w
) & 0xff);
308 RAMDAC_SET_REG(PM3RD_VideoOverlayXEndHigh
,
309 ((info
->dest
.x
+drw_w
) & 0xf00)>>8);
310 RAMDAC_SET_REG(PM3RD_VideoOverlayYStartLow
, (info
->dest
.y
& 0xff));
311 RAMDAC_SET_REG(PM3RD_VideoOverlayYStartHigh
, (info
->dest
.y
& 0xf00)>>8);
312 RAMDAC_SET_REG(PM3RD_VideoOverlayYEndLow
, (info
->dest
.y
+drw_h
) & 0xff);
313 RAMDAC_SET_REG(PM3RD_VideoOverlayYEndHigh
,
314 ((info
->dest
.y
+drw_h
) & 0xf00)>>8);
316 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyR
, 0xff);
317 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyG
, 0x00);
318 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyB
, 0xff);
323 PM3VideoOverlayMode_FILTER_FULL
|
324 PM3VideoOverlayMode_BUFFERSYNC_MANUAL
|
325 PM3VideoOverlayMode_FLIP_VIDEO
;
328 PM3RD_VideoOverlayControl_KEY_COLOR
|
329 PM3RD_VideoOverlayControl_MODE_MAINKEY
|
330 PM3RD_VideoOverlayControl_DIRECTCOLOR_ENABLED
;
336 static int pm3_playback_on(void)
340 WRITE_REG(PM3VideoOverlayMode
,
341 overlay_mode
| PM3VideoOverlayMode_ENABLE
);
342 RAMDAC_SET_REG(PM3RD_VideoOverlayControl
,
343 overlay_control
| PM3RD_VideoOverlayControl_ENABLE
);
344 WRITE_REG(PM3VideoOverlayUpdate
,
345 PM3VideoOverlayUpdate_ENABLE
);
351 static int pm3_playback_off(void)
353 RAMDAC_SET_REG(PM3RD_VideoOverlayControl
,
354 PM3RD_VideoOverlayControl_DISABLE
);
355 WRITE_REG(PM3VideoOverlayMode
,
356 PM3VideoOverlayMode_DISABLE
);
358 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyR
, 0x01);
359 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyG
, 0x01);
360 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyB
, 0xfe);
365 static int pm3_frame_select(unsigned int frame
)
367 WRITE_REG(PM3VideoOverlayBase0
, frames
[frame
]);
371 VDXDriver pm3_drv
= {
375 .get_caps
= pm3_get_caps
,
376 .query_fourcc
= pm3_query_fourcc
,
378 .destroy
= pm3_destroy
,
379 .config_playback
= pm3_config_playback
,
380 .playback_on
= pm3_playback_on
,
381 .playback_off
= pm3_playback_off
,
382 .frame_sel
= pm3_frame_select
,