Convert m_config.c to use talloc
[mplayer.git] / vidix / pm3_vid.c
bloba2a30875603eb620335d298e29d3955b17b6ca8e
1 /*
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
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <inttypes.h>
27 #include <unistd.h>
29 #include "config.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"
37 #include "pm3_regs.h"
39 #if 0
40 #define TRACE_ENTER() fprintf(stderr, "%s: enter\n", __FUNCTION__)
41 #define TRACE_EXIT() fprintf(stderr, "%s: exit\n", __FUNCTION__)
42 #else
43 #define TRACE_ENTER()
44 #define TRACE_EXIT()
45 #endif
47 static pciinfo_t pci_info;
49 void *pm3_reg_base;
50 static void *pm3_mem;
52 static vidix_capability_t pm3_cap =
54 "3DLabs GLINT R3/Permedia3 driver",
55 "Måns Rullgård <mru@users.sf.net>",
56 TYPE_OUTPUT,
57 { 0, 0, 0, 0 },
58 2048,
59 2048,
62 -1,
63 FLAG_UPSCALER|FLAG_DOWNSCALER,
64 VENDOR_3DLABS,
65 -1,
66 { 0, 0, 0, 0 }
69 static unsigned short pm3_card_ids[] =
71 DEVICE_3DLABS_GLINT_R3
74 static int find_chip(unsigned chip_id)
76 unsigned i;
77 for(i = 0;i < sizeof(pm3_card_ids)/sizeof(unsigned short);i++)
79 if(chip_id == pm3_card_ids[i]) return i;
81 return -1;
84 static int pm3_probe(int verbose, int force)
86 pciinfo_t lst[MAX_PCI_DEVICES];
87 unsigned i,num_pci;
88 int err;
90 err = pci_scan(lst,&num_pci);
91 if(err)
93 printf("[pm3] Error occurred during pci scan: %s\n",strerror(err));
94 return err;
96 else
98 err = ENXIO;
99 for(i=0; i < num_pci; i++)
101 if(lst[i].vendor == VENDOR_3DLABS)
103 int idx;
104 const char *dname;
105 idx = find_chip(lst[i].device);
106 if(idx == -1)
107 continue;
108 dname = pci_device_name(VENDOR_3DLABS, lst[i].device);
109 dname = dname ? dname : "Unknown chip";
110 printf("[pm3] Found chip: %s\n", dname);
111 #if 0
112 if ((lst[i].command & PCI_COMMAND_IO) == 0)
114 printf("[pm3] Device is disabled, ignoring\n");
115 continue;
117 #endif
118 pm3_cap.device_id = lst[i].device;
119 err = 0;
120 memcpy(&pci_info, &lst[i], sizeof(pciinfo_t));
121 break;
125 if(err && verbose) printf("[pm3] Can't find chip\n");
126 return err;
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);
139 return 0;
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));
151 return 0;
154 static int is_supported_fourcc(uint32_t fourcc)
156 switch(fourcc){
157 case IMGFMT_YUY2:
158 case IMGFMT_UYVY:
159 return 1;
160 default:
161 return 0;
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;
171 return 0;
173 else to->depth = to->flags = 0;
174 return ENOSYS;
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 ... */
194 static void
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) {
205 *src_w &= ~0x3;
206 *dst_w &= ~0x3;
207 *shrink_delta = (((*src_w << 16) / *dst_w) + 0x0f) & 0x0ffffff0;
208 *zoom_delta = 1<<16;
209 if ( ((*shrink_delta * *dst_w) >> 16) & 0x03 )
210 *shrink_delta += 0x10;
211 } else {
212 *src_w &= ~0x3;
213 *dst_w &= ~0x3;
214 *zoom_delta = (((*src_w << 16) / *dst_w) + 0x0f) & 0x0001fff0;
215 *shrink_delta = 1<<16;
216 if ( ((*zoom_delta * *dst_w) >> 16) & 0x03 )
217 *zoom_delta += 0x10;
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;
228 short src_w, drw_w;
229 short src_h, drw_h;
230 long base0;
231 int pitch;
232 int format;
233 unsigned int i;
235 TRACE_ENTER();
237 if(!is_supported_fourcc(info->fourcc))
238 return -1;
240 switch(info->fourcc){
241 case IMGFMT_YUY2:
242 format = FORMAT_YUV422;
243 break;
244 case IMGFMT_UYVY:
245 format = FORMAT_VUY422;
246 break;
247 default:
248 return -1;
251 src_w = info->src.w;
252 src_h = info->src.h;
254 drw_w = info->dest.w;
255 drw_h = info->dest.h;
257 pitch = src_w;
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. */
265 base0 = 0x1000000;
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;
271 info->offset.y = 0;
272 info->offset.v = 0;
273 info->offset.u = 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);
291 } else {
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);
298 } else {
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);
320 overlay_mode =
321 1 << 5 |
322 format |
323 PM3VideoOverlayMode_FILTER_FULL |
324 PM3VideoOverlayMode_BUFFERSYNC_MANUAL |
325 PM3VideoOverlayMode_FLIP_VIDEO;
327 overlay_control =
328 PM3RD_VideoOverlayControl_KEY_COLOR |
329 PM3RD_VideoOverlayControl_MODE_MAINKEY |
330 PM3RD_VideoOverlayControl_DIRECTCOLOR_ENABLED;
332 TRACE_EXIT();
333 return 0;
336 static int pm3_playback_on(void)
338 TRACE_ENTER();
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);
347 TRACE_EXIT();
348 return 0;
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);
362 return 0;
365 static int pm3_frame_select(unsigned int frame)
367 WRITE_REG(PM3VideoOverlayBase0, frames[frame]);
368 return 0;
371 VDXDriver pm3_drv = {
372 "pm3",
373 NULL,
374 .probe = pm3_probe,
375 .get_caps = pm3_get_caps,
376 .query_fourcc = pm3_query_fourcc,
377 .init = pm3_init,
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,