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