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 along
18 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
34 #include "pci_names.h"
39 #define TRACE_ENTER() fprintf(stderr, "%s: enter\n", __FUNCTION__)
40 #define TRACE_EXIT() fprintf(stderr, "%s: exit\n", __FUNCTION__)
46 static pciinfo_t pci_info
;
51 static vidix_capability_t pm3_cap
=
53 "3DLabs GLINT R3/Permedia3 driver",
54 "Måns Rullgård <mru@users.sf.net>",
62 FLAG_UPSCALER
|FLAG_DOWNSCALER
,
68 static unsigned short pm3_card_ids
[] =
70 DEVICE_3DLABS_GLINT_R3
73 static int find_chip(unsigned chip_id
)
76 for(i
= 0;i
< sizeof(pm3_card_ids
)/sizeof(unsigned short);i
++)
78 if(chip_id
== pm3_card_ids
[i
]) return i
;
83 static int pm3_probe(int verbose
, int force
)
85 pciinfo_t lst
[MAX_PCI_DEVICES
];
89 err
= pci_scan(lst
,&num_pci
);
92 printf("[pm3] Error occurred during pci scan: %s\n",strerror(err
));
98 for(i
=0; i
< num_pci
; i
++)
100 if(lst
[i
].vendor
== VENDOR_3DLABS
)
104 idx
= find_chip(lst
[i
].device
);
107 dname
= pci_device_name(VENDOR_3DLABS
, lst
[i
].device
);
108 dname
= dname
? dname
: "Unknown chip";
109 printf("[pm3] Found chip: %s\n", dname
);
111 if ((lst
[i
].command
& PCI_COMMAND_IO
) == 0)
113 printf("[pm3] Device is disabled, ignoring\n");
117 pm3_cap
.device_id
= lst
[i
].device
;
119 memcpy(&pci_info
, &lst
[i
], sizeof(pciinfo_t
));
124 if(err
&& verbose
) printf("[pm3] Can't find chip\n");
128 #define PRINT_REG(reg) \
130 long _foo = READ_REG(reg); \
131 printf("[pm3] " #reg " (%x) = %#lx (%li)\n", reg, _foo, _foo); \
134 static int pm3_init(void)
136 pm3_reg_base
= map_phys_mem(pci_info
.base0
, 0x20000);
137 pm3_mem
= map_phys_mem(pci_info
.base2
, 0x2000000);
141 static void pm3_destroy(void)
143 unmap_phys_mem(pm3_reg_base
, 0x20000);
144 unmap_phys_mem(pm3_mem
, 0x2000000);
147 static int pm3_get_caps(vidix_capability_t
*to
)
149 memcpy(to
, &pm3_cap
, sizeof(vidix_capability_t
));
153 static int is_supported_fourcc(uint32_t fourcc
)
164 static int pm3_query_fourcc(vidix_fourcc_t
*to
)
166 if(is_supported_fourcc(to
->fourcc
))
168 to
->depth
= VID_DEPTH_ALL
;
169 to
->flags
= VID_CAP_EXPAND
| VID_CAP_SHRINK
| VID_CAP_COLORKEY
;
172 else to
->depth
= to
->flags
= 0;
176 #define FORMAT_RGB8888 PM3VideoOverlayMode_COLORFORMAT_RGB8888
177 #define FORMAT_RGB4444 PM3VideoOverlayMode_COLORFORMAT_RGB4444
178 #define FORMAT_RGB5551 PM3VideoOverlayMode_COLORFORMAT_RGB5551
179 #define FORMAT_RGB565 PM3VideoOverlayMode_COLORFORMAT_RGB565
180 #define FORMAT_RGB332 PM3VideoOverlayMode_COLORFORMAT_RGB332
181 #define FORMAT_BGR8888 PM3VideoOverlayMode_COLORFORMAT_BGR8888
182 #define FORMAT_BGR4444 PM3VideoOverlayMode_COLORFORMAT_BGR4444
183 #define FORMAT_BGR5551 PM3VideoOverlayMode_COLORFORMAT_BGR5551
184 #define FORMAT_BGR565 PM3VideoOverlayMode_COLORFORMAT_BGR565
185 #define FORMAT_BGR332 PM3VideoOverlayMode_COLORFORMAT_BGR332
186 #define FORMAT_CI8 PM3VideoOverlayMode_COLORFORMAT_CI8
187 #define FORMAT_VUY444 PM3VideoOverlayMode_COLORFORMAT_VUY444
188 #define FORMAT_YUV444 PM3VideoOverlayMode_COLORFORMAT_YUV444
189 #define FORMAT_VUY422 PM3VideoOverlayMode_COLORFORMAT_VUY422
190 #define FORMAT_YUV422 PM3VideoOverlayMode_COLORFORMAT_YUV422
192 /* Notice, have to check that we don't overflow the deltas here ... */
194 compute_scale_factor(
195 short* src_w
, short* dst_w
,
196 uint32_t* shrink_delta
, uint32_t* zoom_delta
)
198 /* NOTE: If we don't return reasonable values here then the video
199 * unit can potential shut off and won't display an image until re-enabled.
200 * Seems as though the zoom_delta is o.k, and I've not had the problem.
201 * The 'shrink_delta' is prone to this the most - FIXME ! */
203 if (*src_w
>= *dst_w
) {
206 *shrink_delta
= (((*src_w
<< 16) / *dst_w
) + 0x0f) & 0x0ffffff0;
208 if ( ((*shrink_delta
* *dst_w
) >> 16) & 0x03 )
209 *shrink_delta
+= 0x10;
213 *zoom_delta
= (((*src_w
<< 16) / *dst_w
) + 0x0f) & 0x0001fff0;
214 *shrink_delta
= 1<<16;
215 if ( ((*zoom_delta
* *dst_w
) >> 16) & 0x03 )
220 static int frames
[VID_PLAY_MAXFRAMES
];
222 static long overlay_mode
, overlay_control
;
224 static int pm3_config_playback(vidix_playback_t
*info
)
226 uint32_t shrink
, zoom
;
236 if(!is_supported_fourcc(info
->fourcc
))
239 switch(info
->fourcc
){
241 format
= FORMAT_YUV422
;
244 format
= FORMAT_VUY422
;
253 drw_w
= info
->dest
.w
;
254 drw_h
= info
->dest
.h
;
258 /* Assume we have 16 MB to play with */
259 info
->num_frames
= 0x1000000 / (pitch
* src_h
* 2);
260 if(info
->num_frames
> VID_PLAY_MAXFRAMES
)
261 info
->num_frames
= VID_PLAY_MAXFRAMES
;
263 /* Start at 16 MB. Let's hope it's not in use. */
265 info
->dga_addr
= pm3_mem
+ base0
;
267 info
->dest
.pitch
.y
= 2;
268 info
->dest
.pitch
.u
= 0;
269 info
->dest
.pitch
.v
= 0;
273 info
->frame_size
= pitch
* src_h
* 2;
274 for(i
= 0; i
< info
->num_frames
; i
++){
275 info
->offsets
[i
] = info
->frame_size
* i
;
276 frames
[i
] = (base0
+ info
->offsets
[i
]) >> 1;
279 compute_scale_factor(&src_w
, &drw_w
, &shrink
, &zoom
);
281 WRITE_REG(PM3VideoOverlayBase0
, base0
>> 1);
282 WRITE_REG(PM3VideoOverlayStride
, PM3VideoOverlayStride_STRIDE(pitch
));
283 WRITE_REG(PM3VideoOverlayWidth
, PM3VideoOverlayWidth_WIDTH(src_w
));
284 WRITE_REG(PM3VideoOverlayHeight
, PM3VideoOverlayHeight_HEIGHT(src_h
));
285 WRITE_REG(PM3VideoOverlayOrigin
, 0);
287 /* Scale the source to the destinationsize */
288 if (src_h
== drw_h
) {
289 WRITE_REG(PM3VideoOverlayYDelta
, PM3VideoOverlayYDelta_NONE
);
291 WRITE_REG(PM3VideoOverlayYDelta
,
292 PM3VideoOverlayYDelta_DELTA(src_h
, drw_h
));
294 if (src_w
== drw_w
) {
295 WRITE_REG(PM3VideoOverlayShrinkXDelta
, 1<<16);
296 WRITE_REG(PM3VideoOverlayZoomXDelta
, 1<<16);
298 WRITE_REG(PM3VideoOverlayShrinkXDelta
, shrink
);
299 WRITE_REG(PM3VideoOverlayZoomXDelta
, zoom
);
301 WRITE_REG(PM3VideoOverlayIndex
, 0);
303 /* Now set the ramdac video overlay region and mode */
304 RAMDAC_SET_REG(PM3RD_VideoOverlayXStartLow
, (info
->dest
.x
& 0xff));
305 RAMDAC_SET_REG(PM3RD_VideoOverlayXStartHigh
, (info
->dest
.x
& 0xf00)>>8);
306 RAMDAC_SET_REG(PM3RD_VideoOverlayXEndLow
, (info
->dest
.x
+drw_w
) & 0xff);
307 RAMDAC_SET_REG(PM3RD_VideoOverlayXEndHigh
,
308 ((info
->dest
.x
+drw_w
) & 0xf00)>>8);
309 RAMDAC_SET_REG(PM3RD_VideoOverlayYStartLow
, (info
->dest
.y
& 0xff));
310 RAMDAC_SET_REG(PM3RD_VideoOverlayYStartHigh
, (info
->dest
.y
& 0xf00)>>8);
311 RAMDAC_SET_REG(PM3RD_VideoOverlayYEndLow
, (info
->dest
.y
+drw_h
) & 0xff);
312 RAMDAC_SET_REG(PM3RD_VideoOverlayYEndHigh
,
313 ((info
->dest
.y
+drw_h
) & 0xf00)>>8);
315 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyR
, 0xff);
316 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyG
, 0x00);
317 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyB
, 0xff);
322 PM3VideoOverlayMode_FILTER_FULL
|
323 PM3VideoOverlayMode_BUFFERSYNC_MANUAL
|
324 PM3VideoOverlayMode_FLIP_VIDEO
;
327 PM3RD_VideoOverlayControl_KEY_COLOR
|
328 PM3RD_VideoOverlayControl_MODE_MAINKEY
|
329 PM3RD_VideoOverlayControl_DIRECTCOLOR_ENABLED
;
335 static int pm3_playback_on(void)
339 WRITE_REG(PM3VideoOverlayMode
,
340 overlay_mode
| PM3VideoOverlayMode_ENABLE
);
341 RAMDAC_SET_REG(PM3RD_VideoOverlayControl
,
342 overlay_control
| PM3RD_VideoOverlayControl_ENABLE
);
343 WRITE_REG(PM3VideoOverlayUpdate
,
344 PM3VideoOverlayUpdate_ENABLE
);
350 static int pm3_playback_off(void)
352 RAMDAC_SET_REG(PM3RD_VideoOverlayControl
,
353 PM3RD_VideoOverlayControl_DISABLE
);
354 WRITE_REG(PM3VideoOverlayMode
,
355 PM3VideoOverlayMode_DISABLE
);
357 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyR
, 0x01);
358 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyG
, 0x01);
359 RAMDAC_SET_REG(PM3RD_VideoOverlayKeyB
, 0xfe);
364 static int pm3_frame_select(unsigned int frame
)
366 WRITE_REG(PM3VideoOverlayBase0
, frames
[frame
]);
370 VDXDriver pm3_drv
= {
374 .get_caps
= pm3_get_caps
,
375 .query_fourcc
= pm3_query_fourcc
,
377 .destroy
= pm3_destroy
,
378 .config_playback
= pm3_config_playback
,
379 .playback_on
= pm3_playback_on
,
380 .playback_off
= pm3_playback_off
,
381 .frame_sel
= pm3_frame_select
,