Mercurial > mplayer.hg
annotate vidix/s3_vid.c @ 26763:c13288eeb9f6
Add support for AppleIR Remote as an input under Linux systems.
This requires Linux 2.6 with evdev and appleir drivers.
The keymapping is done to mimics the one that was done for MacOSX.
WARNING: Most distributions do not seems to bother and only let root
access to the device. Modify udev rules accordingly if you want regular
user to be able to use the remote.
author | ben |
---|---|
date | Sun, 18 May 2008 11:53:00 +0000 |
parents | 3abd1629658b |
children | df448e1248b2 |
rev | line source |
---|---|
26096 | 1 /* |
2 * VIDIX driver for S3 chipsets. | |
26718
051b2632f121
consistency cosmetics: Move some parts of file headers around; typo fixes.
diego
parents:
26203
diff
changeset
|
3 * |
26096 | 4 * Copyright (C) 2004 Reza Jelveh |
26718
051b2632f121
consistency cosmetics: Move some parts of file headers around; typo fixes.
diego
parents:
26203
diff
changeset
|
5 * Thanks to Alex Deucher for Support |
051b2632f121
consistency cosmetics: Move some parts of file headers around; typo fixes.
diego
parents:
26203
diff
changeset
|
6 * Trio/Virge support by Michael Kostylev |
26096 | 7 * |
8 * This file is part of MPlayer. | |
9 * | |
10 * MPlayer is free software; you can redistribute it and/or modify | |
11 * it under the terms of the GNU General Public License as published by | |
12 * the Free Software Foundation; either version 2 of the License, or | |
13 * (at your option) any later version. | |
14 * | |
15 * MPlayer is distributed in the hope that it will be useful, | |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 * GNU General Public License for more details. | |
19 * | |
26719 | 20 * You should have received a copy of the GNU General Public License along |
21 * with MPlayer; if not, write to the Free Software Foundation, Inc., | |
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
26096 | 23 */ |
24 | |
25 #include <errno.h> | |
26 #include <stdio.h> | |
27 #include <stdlib.h> | |
28 #include <string.h> | |
29 #include <inttypes.h> | |
30 #include <unistd.h> | |
31 #include <math.h> | |
32 | |
26203 | 33 #include "config.h" |
26096 | 34 #include "vidix.h" |
35 #include "vidixlib.h" | |
36 #include "fourcc.h" | |
37 #include "dha.h" | |
38 #include "pci_ids.h" | |
39 #include "pci_names.h" | |
40 | |
41 #include "s3_regs.h" | |
42 | |
43 static void S3SetColorKeyOld (void); | |
44 static void S3SetColorKeyNew (void); | |
45 static void S3SetColorKey2000 (void); | |
46 static void (*S3SetColorKey) (void) = NULL; | |
47 | |
48 static void S3SetColorOld (void); | |
49 static void S3SetColorNew (void); | |
50 static void S3SetColor2000 (void); | |
51 static void (*S3SetColor) (void) = NULL; | |
52 | |
53 static void S3DisplayVideoOld (void); | |
54 static void S3DisplayVideoNew (void); | |
55 static void S3DisplayVideo2000 (void); | |
56 static void (*S3DisplayVideo) (void) = NULL; | |
57 | |
58 static void S3InitStreamsOld (void); | |
59 static void S3InitStreamsNew (void); | |
60 static void S3InitStreams2000 (void); | |
61 static void (*S3InitStreams) (void) = NULL; | |
62 | |
63 pciinfo_t pci_info; | |
64 | |
65 struct s3_chip | |
66 { | |
67 int arch; | |
68 unsigned long fbsize; | |
69 void (*lock) (struct s3_chip *, int); | |
70 }; | |
71 typedef struct s3_chip s3_chip; | |
72 | |
73 struct s3_info | |
74 { | |
75 vidix_video_eq_t eq; | |
76 unsigned int use_colorkey; | |
77 unsigned int colorkey; | |
78 unsigned int vidixcolorkey; | |
79 unsigned int depth; | |
80 unsigned int bpp; | |
81 unsigned int format; | |
82 unsigned int pitch; | |
83 unsigned int blendBase; | |
84 unsigned int displayWidth, displayHeight; | |
85 unsigned int src_w, src_h; | |
86 unsigned int drw_w, drw_h; | |
87 unsigned int wx, wy; | |
88 unsigned int screen_x; | |
89 unsigned int screen_y; | |
90 unsigned long frame_size; | |
91 struct s3_chip chip; | |
92 void *video_base; | |
93 void *control_base; | |
94 unsigned long picture_base; | |
95 unsigned long picture_offset; | |
96 unsigned int num_frames; | |
97 int bps; | |
98 }; | |
99 typedef struct s3_info s3_info; | |
100 | |
101 static s3_info *info; | |
102 | |
103 static vidix_capability_t s3_cap = { | |
104 "S3 BES", | |
105 "Reza Jelveh, Michael Kostylev", | |
106 TYPE_OUTPUT, | |
107 {0, 0, 0, 0}, | |
108 4096, | |
109 4096, | |
110 4, | |
111 4, | |
112 -1, | |
113 FLAG_UPSCALER | FLAG_DOWNSCALER, | |
114 VENDOR_S3_INC, | |
115 -1, | |
116 {0, 0, 0, 0} | |
117 }; | |
118 | |
119 struct s3_cards | |
120 { | |
121 unsigned short chip_id; | |
122 unsigned short arch; | |
123 }; | |
124 | |
125 static struct s3_cards s3_card_ids[] = { | |
126 /* Trio64V */ | |
127 {DEVICE_S3_INC_86C764_765_TRIO32_64_64V, S3_TRIO64V}, | |
128 {DEVICE_S3_INC_86C767_TRIO_64UV, S3_TRIO64V}, | |
129 {DEVICE_S3_INC_86C755_TRIO_64V2_DX, S3_TRIO64V}, | |
130 {DEVICE_S3_INC_86C775_86C785_TRIO_64V2_DX, S3_TRIO64V}, | |
131 {DEVICE_S3_INC_TRIO_64V_FAMILY, S3_TRIO64V}, | |
132 {DEVICE_S3_INC_TRIO_64V_FAMILY2, S3_TRIO64V}, | |
133 {DEVICE_S3_INC_TRIO_64V_FAMILY3, S3_TRIO64V}, | |
134 {DEVICE_S3_INC_TRIO_64V_FAMILY4, S3_TRIO64V}, | |
135 {DEVICE_S3_INC_TRIO_64V_FAMILY5, S3_TRIO64V}, | |
136 {DEVICE_S3_INC_TRIO_64V_FAMILY6, S3_TRIO64V}, | |
137 {DEVICE_S3_INC_TRIO_64V_FAMILY7, S3_TRIO64V}, | |
138 {DEVICE_S3_INC_TRIO_64V_FAMILY8, S3_TRIO64V}, | |
139 {DEVICE_S3_INC_TRIO_64V_FAMILY9, S3_TRIO64V}, | |
140 {DEVICE_S3_INC_TRIO_64V_FAMILY10, S3_TRIO64V}, | |
141 {DEVICE_S3_INC_TRIO_64V_FAMILY11, S3_TRIO64V}, | |
142 /* Virge */ | |
143 {DEVICE_S3_INC_86C325_VIRGE, S3_VIRGE}, | |
144 {DEVICE_S3_INC_86C988_VIRGE_VX, S3_VIRGE}, | |
145 {DEVICE_S3_INC_VIRGE_DX_OR_GX, S3_VIRGE}, | |
146 {DEVICE_S3_INC_VIRGE_GX2, S3_VIRGE}, | |
147 {DEVICE_S3_INC_VIRGE_M3, S3_VIRGE}, | |
148 {DEVICE_S3_INC_VIRGE_MX, S3_VIRGE}, | |
149 {DEVICE_S3_INC_VIRGE_MX2, S3_VIRGE}, | |
150 {DEVICE_S3_INC_VIRGE_MX_MV, S3_VIRGE}, | |
151 /* Savage3D */ | |
152 {DEVICE_S3_INC_86C794_SAVAGE_3D, S3_SAVAGE3D}, | |
153 {DEVICE_S3_INC_86C390_SAVAGE_3D_MV, S3_SAVAGE3D}, | |
154 /* Savage4 */ | |
155 {DEVICE_S3_INC_SAVAGE_4, S3_SAVAGE4}, | |
156 {DEVICE_S3_INC_SAVAGE_42, S3_SAVAGE4}, | |
157 /* SavageMX */ | |
158 {DEVICE_S3_INC_86C270_294_SAVAGE_MX_MV, S3_SAVAGE_MX}, | |
159 {DEVICE_S3_INC_82C270_294_SAVAGE_MX, S3_SAVAGE_MX}, | |
160 {DEVICE_S3_INC_86C270_294_SAVAGE_IX_MV, S3_SAVAGE_MX}, | |
161 /* SuperSavage */ | |
162 {DEVICE_S3_INC_SUPERSAVAGE_MX_128, S3_SUPERSAVAGE}, | |
163 {DEVICE_S3_INC_SUPERSAVAGE_MX_64, S3_SUPERSAVAGE}, | |
164 {DEVICE_S3_INC_SUPERSAVAGE_MX_64C, S3_SUPERSAVAGE}, | |
165 {DEVICE_S3_INC_SUPERSAVAGE_IX_128_SDR, S3_SUPERSAVAGE}, | |
166 {DEVICE_S3_INC_SUPERSAVAGE_IX_128_DDR, S3_SUPERSAVAGE}, | |
167 {DEVICE_S3_INC_SUPERSAVAGE_IX_64_SDR, S3_SUPERSAVAGE}, | |
168 {DEVICE_S3_INC_SUPERSAVAGE_IX_64_DDR, S3_SUPERSAVAGE}, | |
169 {DEVICE_S3_INC_SUPERSAVAGE_IX_C_SDR, S3_SUPERSAVAGE}, | |
170 {DEVICE_S3_INC_SUPERSAVAGE_IX_C_DDR, S3_SUPERSAVAGE}, | |
171 /* ProSavage */ | |
172 {DEVICE_S3_INC_PROSAVAGE_PM133, S3_PROSAVAGE}, | |
173 {DEVICE_S3_INC_PROSAVAGE_KM133, S3_PROSAVAGE}, | |
174 {DEVICE_S3_INC_86C380_PROSAVAGEDDR_K4M266, S3_PROSAVAGE}, | |
175 {DEVICE_S3_INC_VT8636A_PROSAVAGE_KN133, S3_PROSAVAGE}, | |
176 {DEVICE_S3_INC_VT8751_PROSAVAGEDDR_P4M266, S3_PROSAVAGE}, | |
177 {DEVICE_S3_INC_VT8375_PROSAVAGE8_KM266_KL266, S3_PROSAVAGE}, | |
178 /* Savage2000 */ | |
179 {DEVICE_S3_INC_86C410_SAVAGE_2000, S3_SAVAGE2000} | |
180 }; | |
181 | |
182 static unsigned int GetBlendForFourCC (int id) | |
183 { | |
184 switch (id) | |
185 { | |
186 case IMGFMT_UYVY: | |
187 return 0; | |
188 case IMGFMT_YUY2: | |
189 return 1; | |
190 case IMGFMT_Y211: | |
191 return 4; | |
192 case IMGFMT_BGR15: | |
193 return 3; | |
194 case IMGFMT_BGR16: | |
195 return 5; | |
196 case IMGFMT_BGR24: | |
197 return 6; | |
198 case IMGFMT_BGR32: | |
199 return 7; | |
200 default: | |
201 return 1; | |
202 } | |
203 } | |
204 | |
205 static void S3SetColorOld (void) | |
206 { | |
207 char sat = (info->eq.saturation + 1000) * 15 / 2000; | |
208 double hue = info->eq.hue * 3.1415926 / 1000.0; | |
209 char hsx = ((char) (sat * cos (hue))) & 0x1f; | |
210 char hsy = ((char) (sat * sin (hue))) & 0x1f; | |
211 | |
212 OUTREG (COLOR_ADJUSTMENT_REG, 0x80008000 | hsy << 24 | hsx << 16 | | |
213 ((info->eq.contrast + 1000) * 31 / 2000) << 8 | | |
214 (info->eq.brightness + 1000) * 255 / 2000); | |
215 } | |
216 | |
217 static void S3SetColorNew (void) | |
218 { | |
219 /* not yet */ | |
220 } | |
221 | |
222 static void S3SetColor2000 (void) | |
223 { | |
224 /* not yet */ | |
225 } | |
226 | |
227 static void S3SetColorKeyOld (void) | |
228 { | |
229 int red, green, blue; | |
230 | |
231 /* Here, we reset the colorkey and all the controls */ | |
232 | |
233 red = (info->vidixcolorkey & 0x00FF0000) >> 16; | |
234 green = (info->vidixcolorkey & 0x0000FF00) >> 8; | |
235 blue = info->vidixcolorkey & 0x000000FF; | |
236 | |
237 if (!info->vidixcolorkey) | |
238 { | |
239 OUTREG (COL_CHROMA_KEY_CONTROL_REG, 0); | |
240 OUTREG (CHROMA_KEY_UPPER_BOUND_REG, 0); | |
241 OUTREG (BLEND_CONTROL_REG, 0); | |
242 } | |
243 else | |
244 { | |
245 switch (info->depth) | |
246 { | |
247 // FIXME: isnt fixed yet | |
248 case 8: | |
249 OUTREG (COL_CHROMA_KEY_CONTROL_REG, 0x37000000 | (info->vidixcolorkey & 0xFF)); | |
250 OUTREG (CHROMA_KEY_UPPER_BOUND_REG, 0x00000000 | (info->vidixcolorkey & 0xFF)); | |
251 break; | |
252 case 15: | |
253 /* 15 bpp 555 */ | |
254 red &= 0x1f; | |
255 green &= 0x1f; | |
256 blue &= 0x1f; | |
257 OUTREG (COL_CHROMA_KEY_CONTROL_REG, 0x05000000 | (red << 19) | (green << 11) | (blue << 3)); | |
258 OUTREG (CHROMA_KEY_UPPER_BOUND_REG, 0x00000000 | (red << 19) | (green << 11) | (blue << 3)); | |
259 break; | |
260 case 16: | |
261 /* 16 bpp 565 */ | |
262 red &= 0x1f; | |
263 green &= 0x3f; | |
264 blue &= 0x1f; | |
265 OUTREG (COL_CHROMA_KEY_CONTROL_REG, 0x16000000 | (red << 19) | (green << 10) | (blue << 3)); | |
266 OUTREG (CHROMA_KEY_UPPER_BOUND_REG, 0x00020002 | (red << 19) | (green << 10) | (blue << 3)); | |
267 break; | |
268 case 24: | |
269 /* 24 bpp 888 */ | |
270 OUTREG (COL_CHROMA_KEY_CONTROL_REG, 0x17000000 | (red << 16) | (green << 8) | (blue)); | |
271 OUTREG (CHROMA_KEY_UPPER_BOUND_REG, 0x00000000 | (red << 16) | (green << 8) | (blue)); | |
272 break; | |
273 } | |
274 | |
275 /* We use destination colorkey */ | |
276 OUTREG (BLEND_CONTROL_REG, 0x05000000); | |
277 } | |
278 } | |
279 | |
280 static void S3SetColorKeyNew (void) | |
281 { | |
282 /* not yet */ | |
283 } | |
284 | |
285 static void S3SetColorKey2000 (void) | |
286 { | |
287 /* not yet */ | |
288 } | |
289 | |
290 static void S3DisplayVideoOld (void) | |
291 { | |
292 unsigned int ssControl; | |
293 int cr92; | |
294 | |
295 /* Set surface location and stride */ | |
296 OUTREG (SSTREAM_FBADDR0_REG, info->picture_offset); | |
297 OUTREG (SSTREAM_FBADDR1_REG, 0); | |
298 OUTREG (SSTREAM_STRIDE_REG, info->pitch); | |
299 /* Set window parameters */ | |
300 OUTREG (SSTREAM_WINDOW_START_REG, OS_XY (info->wx, info->wy)); | |
301 OUTREG (SSTREAM_WINDOW_SIZE_REG, OS_WH (info->drw_w, info->drw_h)); | |
302 | |
303 /* Set surface format and adjust scaling */ | |
304 if (info->chip.arch <= S3_VIRGE) | |
305 { | |
306 ssControl = ((info->src_w - 1) << 1) - ((info->drw_w - 1) & 0xffff); | |
307 ssControl |= GetBlendForFourCC (info->format) << 24; | |
308 if (info->src_w != info->drw_w) | |
309 ssControl |= 2 << 28; | |
310 | |
311 OUTREG (SSTREAM_CONTROL_REG, ssControl); | |
312 OUTREG (SSTREAM_STRETCH_REG, (((info->src_w - info->drw_w) & 0x7ff) << 16) | (info->src_w - 1)); | |
313 /* Calculate vertical scale factor */ | |
314 OUTREG (K1_VSCALE_REG, info->src_h - 1); | |
315 OUTREG (K2_VSCALE_REG, (info->src_h - info->drw_h) & 0x7ff); | |
316 OUTREG (DDA_VERT_REG, (1 - info->drw_h) & 0xfff); | |
317 } | |
318 else | |
319 { | |
320 ssControl = GetBlendForFourCC (info->format) << 24 | info->src_w; | |
321 if (info->src_w > (info->drw_w << 1)) | |
322 { | |
323 /* BUGBUG shouldn't this be >=? */ | |
324 if (info->src_w <= (info->drw_w << 2)) | |
325 ssControl |= HDSCALE_4; | |
326 else if (info->src_w > (info->drw_w << 3)) | |
327 ssControl |= HDSCALE_8; | |
328 else if (info->src_w > (info->drw_w << 4)) | |
329 ssControl |= HDSCALE_16; | |
330 else if (info->src_w > (info->drw_w << 5)) | |
331 ssControl |= HDSCALE_32; | |
332 else if (info->src_w > (info->drw_w << 6)) | |
333 ssControl |= HDSCALE_64; | |
334 } | |
335 | |
336 OUTREG (SSTREAM_CONTROL_REG, ssControl); | |
337 OUTREG (SSTREAM_STRETCH_REG, (info->src_w << 15) / info->drw_w); | |
338 OUTREG (SSTREAM_LINES_REG, info->src_h); | |
339 /* Calculate vertical scale factor. */ | |
340 OUTREG (SSTREAM_VSCALE_REG, VSCALING (info->src_h, info->drw_h)); | |
341 } | |
342 | |
343 if (info->chip.arch == S3_TRIO64V) | |
344 OUTREG (STREAMS_FIFO_REG, (6 << 10) | (14 << 5) | 16); | |
345 else | |
346 { | |
347 // FIXME: this should actually be enabled | |
348 info->pitch = (info->pitch + 7) / 8; | |
349 VGAOUT8 (vgaCRIndex, 0x92); | |
350 cr92 = VGAIN8 (vgaCRReg); | |
351 VGAOUT8 (vgaCRReg, (cr92 & 0x40) | (info->pitch >> 8) | 0x80); | |
352 VGAOUT8 (vgaCRIndex, 0x93); | |
353 VGAOUT8 (vgaCRReg, info->pitch); | |
354 OUTREG (STREAMS_FIFO_REG, 2 | 25 << 5 | 32 << 11); | |
355 } | |
356 } | |
357 | |
358 static void S3DisplayVideoNew (void) | |
359 { | |
360 /* not yet */ | |
361 } | |
362 | |
363 static void S3DisplayVideo2000 (void) | |
364 { | |
365 /* not yet */ | |
366 } | |
367 | |
368 static void S3InitStreamsOld (void) | |
369 { | |
370 /*unsigned long jDelta; */ | |
371 unsigned long format = 0; | |
372 | |
373 /*jDelta = pScrn->displayWidth * (pScrn->bitsPerPixel + 7) / 8; */ | |
374 switch (info->depth) | |
375 { | |
376 case 8: | |
377 format = 0 << 24; | |
378 break; | |
379 case 15: | |
380 format = 3 << 24; | |
381 break; | |
382 case 16: | |
383 format = 5 << 24; | |
384 break; | |
385 case 24: | |
386 format = 7 << 24; | |
387 break; | |
388 } | |
389 //#warning enable this again | |
390 OUTREG (PSTREAM_FBSIZE_REG, info->screen_y * info->screen_x * (info->bpp >> 3)); | |
391 OUTREG (PSTREAM_WINDOW_START_REG, OS_XY (0, 0)); | |
392 OUTREG (PSTREAM_WINDOW_SIZE_REG, OS_WH (info->screen_x, info->screen_y)); | |
393 OUTREG (PSTREAM_FBADDR1_REG, 0); | |
394 /*OUTREG( PSTREAM_STRIDE_REG, jDelta ); */ | |
395 OUTREG (PSTREAM_CONTROL_REG, format); | |
396 OUTREG (PSTREAM_FBADDR0_REG, 0); | |
397 | |
398 OUTREG (COL_CHROMA_KEY_CONTROL_REG, 0); | |
399 OUTREG (SSTREAM_CONTROL_REG, 0); | |
400 OUTREG (CHROMA_KEY_UPPER_BOUND_REG, 0); | |
401 OUTREG (SSTREAM_STRETCH_REG, 0); | |
402 OUTREG (COLOR_ADJUSTMENT_REG, 0); | |
403 OUTREG (BLEND_CONTROL_REG, 1 << 24); | |
404 OUTREG (DOUBLE_BUFFER_REG, 0); | |
405 OUTREG (SSTREAM_FBADDR0_REG, 0); | |
406 OUTREG (SSTREAM_FBADDR1_REG, 0); | |
407 OUTREG (SSTREAM_FBADDR2_REG, 0); | |
408 OUTREG (SSTREAM_FBSIZE_REG, 0); | |
409 OUTREG (SSTREAM_STRIDE_REG, 0); | |
410 OUTREG (SSTREAM_VSCALE_REG, 0); | |
411 OUTREG (SSTREAM_LINES_REG, 0); | |
412 OUTREG (SSTREAM_VINITIAL_REG, 0); | |
413 } | |
414 | |
415 static void S3InitStreamsNew (void) | |
416 { | |
417 /* not yet */ | |
418 } | |
419 | |
420 static void S3InitStreams2000 (void) | |
421 { | |
422 /* not yet */ | |
423 } | |
424 | |
425 static void S3StreamsOn (void) | |
426 { | |
427 unsigned char jStreamsControl; | |
428 | |
429 VGAOUT8 (vgaCRIndex, EXT_MISC_CTRL2); | |
430 | |
431 if (S3_SAVAGE_MOBILE_SERIES (info->chip.arch)) | |
432 { | |
433 jStreamsControl = VGAIN8 (vgaCRReg) | ENABLE_STREAM1; | |
434 VerticalRetraceWait (); | |
435 VGAOUT16 (vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2); | |
436 | |
437 S3InitStreams = S3InitStreamsNew; | |
438 S3SetColor = S3SetColorNew; | |
439 S3SetColorKey = S3SetColorKeyNew; | |
440 S3DisplayVideo = S3DisplayVideoNew; | |
441 } | |
442 else if (info->chip.arch == S3_SAVAGE2000) | |
443 { | |
444 jStreamsControl = VGAIN8 (vgaCRReg) | ENABLE_STREAM1; | |
445 VerticalRetraceWait (); | |
446 VGAOUT16 (vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2); | |
447 | |
448 S3InitStreams = S3InitStreams2000; | |
449 S3SetColor = S3SetColor2000; | |
450 S3SetColorKey = S3SetColorKey2000; | |
451 S3DisplayVideo = S3DisplayVideo2000; | |
452 } | |
453 else | |
454 { | |
455 jStreamsControl = VGAIN8 (vgaCRReg) | ENABLE_STREAMS_OLD; | |
456 VerticalRetraceWait (); | |
457 VGAOUT16 (vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2); | |
458 | |
459 S3InitStreams = S3InitStreamsOld; | |
460 S3SetColor = S3SetColorOld; | |
461 S3SetColorKey = S3SetColorKeyOld; | |
462 S3DisplayVideo = S3DisplayVideoOld; | |
463 } | |
464 | |
465 S3InitStreams (); | |
466 | |
467 VerticalRetraceWait (); | |
468 /* Turn on secondary stream TV flicker filter, once we support TV. */ | |
469 /* SR70 |= 0x10 */ | |
470 } | |
471 | |
472 static void S3GetScrProp (struct s3_info *info) | |
473 { | |
474 unsigned char bpp = 0; | |
475 | |
476 VGAOUT8 (vgaCRIndex, EXT_MISC_CTRL2); | |
477 bpp = VGAIN8 (vgaCRReg); | |
478 | |
479 switch (bpp & 0xf0) | |
480 { | |
481 case 0x00: | |
482 case 0x10: | |
483 info->depth = 8; | |
484 info->bpp = 8; | |
485 break; | |
486 case 0x20: | |
487 case 0x30: | |
488 info->depth = 15; | |
489 info->bpp = 16; | |
490 break; | |
491 case 0x40: | |
492 case 0x50: | |
493 info->depth = 16; | |
494 info->bpp = 16; | |
495 break; | |
496 case 0x70: | |
497 case 0xd0: | |
498 info->depth = 24; | |
499 info->bpp = 32; | |
500 break; | |
501 } | |
502 | |
503 VGAOUT8 (vgaCRIndex, 0x1); | |
504 info->screen_x = (1 + VGAIN8 (vgaCRReg)) << 3; | |
505 VGAOUT8 (vgaCRIndex, 0x12); | |
506 info->screen_y = VGAIN8 (vgaCRReg); | |
507 VGAOUT8 (vgaCRIndex, 0x07); | |
508 info->screen_y |= (VGAIN8 (vgaCRReg) & 0x02) << 7; | |
509 info->screen_y |= (VGAIN8 (vgaCRReg) & 0x40) << 3; | |
510 ++info->screen_y; | |
511 | |
512 printf ("[s3_vid] x = %d, y = %d, bpp = %d\n", info->screen_x, info->screen_y, info->bpp); | |
513 } | |
514 | |
515 static void S3StreamsOff (void) | |
516 { | |
517 unsigned char jStreamsControl; | |
518 | |
519 if (info->chip.arch == S3_TRIO64V) | |
520 OUTREG (STREAMS_FIFO_REG, (20 << 10)); | |
521 | |
522 VGAOUT8 (vgaCRIndex, EXT_MISC_CTRL2); | |
523 if (S3_SAVAGE_MOBILE_SERIES (info->chip.arch) || | |
524 (info->chip.arch == S3_SUPERSAVAGE) || (info->chip.arch == S3_SAVAGE2000)) | |
525 jStreamsControl = VGAIN8 (vgaCRReg) & NO_STREAMS; | |
526 else | |
527 jStreamsControl = VGAIN8 (vgaCRReg) & NO_STREAMS_OLD; | |
528 | |
529 VerticalRetraceWait (); | |
530 VGAOUT16 (vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2); | |
531 | |
532 if (S3_SAVAGE_SERIES (info->chip.arch)) | |
533 { | |
534 VGAOUT16 (vgaCRIndex, 0x0093); | |
535 VGAOUT8 (vgaCRIndex, 0x92); | |
536 VGAOUT8 (vgaCRReg, VGAIN8 (vgaCRReg) & 0x40); | |
537 } | |
538 } | |
539 | |
540 static int find_chip (unsigned chip_id) | |
541 { | |
542 unsigned i; | |
543 | |
544 for (i = 0; i < sizeof (s3_card_ids) / sizeof (struct s3_cards); i++) | |
545 if (chip_id == s3_card_ids[i].chip_id) | |
546 return i; | |
547 return -1; | |
548 } | |
549 | |
550 static int s3_probe (int verbose, int force) | |
551 { | |
552 pciinfo_t lst[MAX_PCI_DEVICES]; | |
553 unsigned i, num_pci; | |
554 int err; | |
555 | |
556 if (force) | |
557 printf ("[s3_vid] Warning: forcing not supported yet!\n"); | |
558 err = pci_scan (lst, &num_pci); | |
559 if (err) | |
560 { | |
561 printf ("[s3_vid] Error occurred during pci scan: %s\n", strerror (err)); | |
562 return err; | |
563 } | |
564 else | |
565 { | |
566 err = ENXIO; | |
567 for (i = 0; i < num_pci; i++) | |
568 { | |
569 if (lst[i].vendor == VENDOR_S3_INC) | |
570 { | |
571 int idx; | |
572 const char *dname; | |
573 idx = find_chip (lst[i].device); | |
574 if (idx == -1) | |
575 continue; | |
576 dname = pci_device_name (lst[i].vendor, lst[i].device); | |
577 dname = dname ? dname : "Unknown chip"; | |
578 printf ("[s3_vid] Found chip: %s\n", dname); | |
579 // FIXME: whats wrong here? | |
580 if ((lst[i].command & PCI_COMMAND_IO) == 0) | |
581 { | |
582 printf ("[s3_vid] Device is disabled, ignoring\n"); | |
583 continue; | |
584 } | |
585 s3_cap.device_id = lst[i].device; | |
586 err = 0; | |
587 memcpy (&pci_info, &lst[i], sizeof (pciinfo_t)); | |
588 break; | |
589 } | |
590 } | |
591 } | |
592 if (err && verbose) | |
593 printf ("[s3_vid] Can't find chip\n"); | |
594 return err; | |
595 } | |
596 | |
26099 | 597 static int s3_init (void) |
26096 | 598 { |
599 unsigned char cr36; | |
600 int mtrr, videoRam; | |
601 static unsigned char RamTrioVirge[] = { 4, 0, 3, 8, 2, 6, 1, 0 }; | |
602 static unsigned char RamSavage3D[] = { 8, 4, 4, 2 }; | |
603 static unsigned char RamSavage4[] = { 2, 4, 8, 12, 16, 32, 64, 32 }; | |
604 static unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 }; | |
605 static unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 16, 2 }; | |
606 | |
607 enable_app_io (); | |
608 | |
609 info = calloc (1, sizeof (s3_info)); | |
610 | |
611 info->chip.arch = s3_card_ids[find_chip (pci_info.device)].arch; | |
612 | |
613 /* Switch to vga registers */ | |
614 OUTPORT8 (0x3c3, INPORT8 (0x3c3) | 0x01); | |
615 OUTPORT8 (0x3c2, INPORT8 (0x3cc) | 0x01); | |
616 /* Unlock extended registers */ | |
617 OUTPORT8 (vgaCRIndex, 0x38); | |
618 OUTPORT8 (vgaCRReg, 0x48); | |
619 OUTPORT8 (vgaCRIndex, 0x39); | |
620 OUTPORT8 (vgaCRReg, 0xa0); | |
621 | |
622 if (info->chip.arch <= S3_VIRGE) | |
623 { | |
624 /* TODO: Improve detecting code */ | |
625 | |
626 /* Enable LFB */ | |
627 OUTPORT8 (vgaCRIndex, LIN_ADDR_CTRL); | |
628 OUTPORT8 (vgaCRReg, INPORT8 (vgaCRReg) | ENABLE_LFB); | |
629 /* Enable NewMMIO */ | |
630 OUTPORT8 (vgaCRIndex, EXT_MEM_CTRL1); | |
631 OUTPORT8 (vgaCRReg, INPORT8 (vgaCRReg) | ENABLE_NEWMMIO); | |
632 } | |
633 | |
634 if (info->chip.arch < S3_SAVAGE3D) | |
635 info->control_base = map_phys_mem (pci_info.base0 + S3_NEWMMIO_REGBASE, S3_NEWMMIO_REGSIZE); | |
636 else if (info->chip.arch == S3_SAVAGE3D) | |
637 info->control_base = map_phys_mem (pci_info.base0 + S3_NEWMMIO_REGBASE, S3_NEWMMIO_REGSIZE_SAVAGE); | |
638 else | |
639 info->control_base = map_phys_mem (pci_info.base0, S3_NEWMMIO_REGSIZE_SAVAGE); | |
640 | |
641 /* Unlock CRTC[0-7] */ | |
642 VGAOUT8 (vgaCRIndex, 0x11); | |
643 VGAOUT8 (vgaCRReg, VGAIN8 (vgaCRReg) & 0x7f); | |
644 /* Unlock sequencer */ | |
645 VGAOUT16 (0x3c4, 0x0608); | |
646 /* Detect amount of installed ram */ | |
647 VGAOUT8 (vgaCRIndex, 0x36); | |
648 cr36 = VGAIN8 (vgaCRReg); | |
649 | |
650 switch (info->chip.arch) | |
651 { | |
652 case S3_TRIO64V: | |
653 case S3_VIRGE: | |
654 videoRam = RamTrioVirge[(cr36 & 0xE0) >> 5] * 1024; | |
655 break; | |
656 | |
657 case S3_SAVAGE3D: | |
658 videoRam = RamSavage3D[(cr36 & 0xC0) >> 6] * 1024; | |
659 break; | |
660 | |
661 case S3_SAVAGE4: | |
662 /* | |
663 * The Savage4 has one ugly special case to consider. On | |
664 * systems with 4 banks of 2Mx32 SDRAM, the BIOS says 4MB | |
665 * when it really means 8MB. Why do it the same when you | |
666 * can do it different... | |
667 */ | |
668 VGAOUT8 (vgaCRIndex, 0x68); | |
669 if ((VGAIN8 (vgaCRReg) & 0xC0) == (0x01 << 6)) | |
670 RamSavage4[1] = 8; | |
671 | |
672 case S3_SAVAGE2000: | |
673 videoRam = RamSavage4[(cr36 & 0xE0) >> 5] * 1024; | |
674 break; | |
675 | |
676 case S3_SAVAGE_MX: | |
677 videoRam = RamSavageMX[(cr36 & 0x0E) >> 1] * 1024; | |
678 break; | |
679 | |
680 case S3_PROSAVAGE: | |
681 videoRam = RamSavageNB[(cr36 & 0xE0) >> 5] * 1024; | |
682 break; | |
683 | |
684 default: | |
685 /* How did we get here? */ | |
686 videoRam = 0; | |
687 break; | |
688 } | |
689 | |
690 printf ("[s3_vid] VideoRam = %d\n", videoRam); | |
691 info->chip.fbsize = videoRam * 1024; | |
692 | |
693 if (info->chip.arch <= S3_SAVAGE3D) | |
694 mtrr = mtrr_set_type (pci_info.base0, info->chip.fbsize, MTRR_TYPE_WRCOMB); | |
695 else | |
696 mtrr = mtrr_set_type (pci_info.base1, info->chip.fbsize, MTRR_TYPE_WRCOMB); | |
697 | |
698 if (mtrr != 0) | |
699 printf ("[s3_vid] Unable to setup MTRR: %s\n", strerror (mtrr)); | |
700 else | |
701 printf ("[s3_vid] MTRR set up\n"); | |
702 | |
703 S3GetScrProp (info); | |
704 S3StreamsOn (); | |
705 | |
706 return 0; | |
707 } | |
708 | |
709 static void s3_destroy (void) | |
710 { | |
711 unmap_phys_mem (info->video_base, info->chip.fbsize); | |
712 if (S3_SAVAGE_SERIES (info->chip.arch)) | |
713 unmap_phys_mem (info->control_base, S3_NEWMMIO_REGSIZE_SAVAGE); | |
714 else | |
715 unmap_phys_mem (info->control_base, S3_NEWMMIO_REGSIZE); | |
716 | |
717 free (info); | |
718 } | |
719 | |
720 static int s3_get_caps (vidix_capability_t * to) | |
721 { | |
722 memcpy (to, &s3_cap, sizeof (vidix_capability_t)); | |
723 return 0; | |
724 } | |
725 | |
726 static int is_supported_fourcc (uint32_t fourcc) | |
727 { | |
728 switch (fourcc) | |
729 { | |
730 //FIXME: Burst Command Interface should be used | |
731 // for planar to packed conversion | |
732 // case IMGFMT_YV12: | |
733 // case IMGFMT_I420: | |
734 case IMGFMT_UYVY: | |
735 case IMGFMT_YUY2: | |
736 case IMGFMT_Y211: | |
737 case IMGFMT_BGR15: | |
738 case IMGFMT_BGR16: | |
739 case IMGFMT_BGR24: | |
740 case IMGFMT_BGR32: | |
741 return 1; | |
742 default: | |
743 return 0; | |
744 } | |
745 } | |
746 | |
747 static int s3_query_fourcc (vidix_fourcc_t * to) | |
748 { | |
749 if (is_supported_fourcc (to->fourcc)) | |
750 { | |
751 to->depth = VID_DEPTH_ALL; | |
752 to->flags = VID_CAP_EXPAND | VID_CAP_SHRINK | VID_CAP_COLORKEY; | |
753 return 0; | |
754 } | |
755 else | |
756 to->depth = to->flags = 0; | |
757 | |
758 return ENOSYS; | |
759 } | |
760 | |
761 #if 0 | |
762 static int s3_get_gkeys (vidix_grkey_t * grkey) | |
763 { | |
764 return 0; | |
765 } | |
766 #endif | |
767 | |
768 static int s3_set_gkeys (const vidix_grkey_t * grkey) | |
769 { | |
770 if (grkey->ckey.op == CKEY_FALSE) | |
771 { | |
772 info->use_colorkey = 0; | |
773 info->vidixcolorkey = 0; | |
774 printf ("[s3_vid] Colorkeying disabled\n"); | |
775 } | |
776 else | |
777 { | |
778 info->use_colorkey = 1; | |
779 info->vidixcolorkey = ((grkey->ckey.red << 16) | (grkey->ckey.green << 8) | grkey->ckey.blue); | |
780 printf ("[s3_vid] Set colorkey 0x%x\n", info->vidixcolorkey); | |
781 } | |
782 if (S3SetColorKey) | |
783 S3SetColorKey (); | |
784 return 0; | |
785 } | |
786 | |
787 static int s3_get_eq (vidix_video_eq_t * eq) | |
788 { | |
789 memcpy (eq, &(info->eq), sizeof (vidix_video_eq_t)); | |
790 return 0; | |
791 } | |
792 | |
793 static int s3_set_eq (const vidix_video_eq_t * eq) | |
794 { | |
795 if (eq->cap & VEQ_CAP_BRIGHTNESS) | |
796 info->eq.brightness = eq->brightness; | |
797 if (eq->cap & VEQ_CAP_CONTRAST) | |
798 info->eq.contrast = eq->contrast; | |
799 if (eq->cap & VEQ_CAP_SATURATION) | |
800 info->eq.saturation = eq->saturation; | |
801 if (eq->cap & VEQ_CAP_HUE) | |
802 info->eq.hue = eq->hue; | |
803 if (S3SetColor) | |
804 S3SetColor (); | |
805 return 0; | |
806 } | |
807 | |
808 static int s3_config_playback (vidix_playback_t * vinfo) | |
809 { | |
810 unsigned int i, bpp; | |
811 | |
812 if (!is_supported_fourcc (vinfo->fourcc)) | |
813 return -1; | |
814 | |
815 info->src_w = vinfo->src.w; | |
816 info->src_h = vinfo->src.h; | |
817 | |
818 info->drw_w = vinfo->dest.w; | |
819 info->drw_h = vinfo->dest.h; | |
820 | |
821 info->wx = vinfo->dest.x; | |
822 info->wy = vinfo->dest.y; | |
823 info->format = vinfo->fourcc; | |
824 | |
825 info->eq.cap = VEQ_CAP_BRIGHTNESS | VEQ_CAP_CONTRAST | | |
826 VEQ_CAP_SATURATION | VEQ_CAP_HUE; | |
827 info->eq.brightness = 0; | |
828 info->eq.contrast = 0; | |
829 info->eq.saturation = 0; | |
830 info->eq.hue = 0; | |
831 | |
832 vinfo->offset.y = 0; | |
833 vinfo->offset.v = 0; | |
834 vinfo->offset.u = 0; | |
835 | |
836 vinfo->dest.pitch.y = 32; | |
837 vinfo->dest.pitch.u = 32; | |
838 vinfo->dest.pitch.v = 32; | |
839 | |
840 switch (vinfo->fourcc) | |
841 { | |
842 case IMGFMT_Y211: | |
843 bpp = 1; | |
844 break; | |
845 case IMGFMT_BGR24: | |
846 bpp = 3; | |
847 break; | |
848 case IMGFMT_BGR32: | |
849 bpp = 4; | |
850 break; | |
851 default: | |
852 bpp = 2; | |
853 break; | |
854 } | |
855 | |
856 info->pitch = ((info->src_w * bpp) + 15) & ~15; | |
857 info->pitch |= ((info->pitch / bpp) << 16); | |
858 | |
859 vinfo->frame_size = (info->pitch & 0xffff) * info->src_h; | |
860 info->frame_size = vinfo->frame_size; | |
861 | |
862 info->picture_offset = info->screen_x * info->screen_y * (info->bpp >> 3); | |
863 if (info->picture_offset > (info->chip.fbsize - vinfo->frame_size)) | |
864 { | |
865 printf ("[s3_vid] Not enough memory for overlay\n"); | |
866 return -1; | |
867 } | |
868 | |
869 if (info->chip.arch <= S3_SAVAGE3D) | |
870 info->video_base = map_phys_mem (pci_info.base0, info->chip.fbsize); | |
871 else | |
872 info->video_base = map_phys_mem (pci_info.base1, info->chip.fbsize); | |
873 | |
874 if (info->video_base == NULL) | |
875 { | |
876 printf ("[s3_vid] errno = %s\n", strerror (errno)); | |
877 return -1; | |
878 } | |
879 | |
880 info->picture_base = (uint32_t) info->video_base + info->picture_offset; | |
881 | |
882 vinfo->dga_addr = (void *) (info->picture_base); | |
883 | |
884 vinfo->num_frames = (info->chip.fbsize - info->picture_offset) / vinfo->frame_size; | |
885 if (vinfo->num_frames > VID_PLAY_MAXFRAMES) | |
886 vinfo->num_frames = VID_PLAY_MAXFRAMES; | |
887 | |
888 for (i = 0; i < vinfo->num_frames; i++) | |
889 vinfo->offsets[i] = vinfo->frame_size * i; | |
890 | |
891 return 0; | |
892 } | |
893 | |
894 static int s3_playback_on (void) | |
895 { | |
896 S3DisplayVideo (); | |
897 return 0; | |
898 } | |
899 | |
900 static int s3_playback_off (void) | |
901 { | |
902 S3StreamsOff (); | |
903 return 0; | |
904 } | |
905 | |
906 static int s3_frame_sel (unsigned int frame) | |
907 { | |
908 OUTREG (SSTREAM_FBADDR0_REG, info->picture_offset + (info->frame_size * frame)); | |
909 return 0; | |
910 } | |
911 | |
912 VDXDriver s3_drv = { | |
913 "s3", | |
914 NULL, | |
915 .probe = s3_probe, | |
916 .get_caps = s3_get_caps, | |
917 .query_fourcc = s3_query_fourcc, | |
918 .init = s3_init, | |
919 .destroy = s3_destroy, | |
920 .config_playback = s3_config_playback, | |
921 .playback_on = s3_playback_on, | |
922 .playback_off = s3_playback_off, | |
923 .frame_sel = s3_frame_sel, | |
924 .get_eq = s3_get_eq, | |
925 .set_eq = s3_set_eq, | |
926 .set_gkey = s3_set_gkeys, | |
927 }; |