2 * VIDIX driver for VIA Cyberblade/i1 chipsets.
3 * Copyright (C) 2002 Alastair M. Robinson
4 * http://www.blackfiveservices.co.uk/EPIAVidix.shtml
6 * This file is part of MPlayer.
8 * MPlayer is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * MPlayer is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with MPlayer; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * Based on Permedia 3 driver by Måns Rullgård
23 * Thanks to Gilles Frattini for bugfixes.
27 * MMIO is no longer used, sidestepping cache issues on EPIA-800
28 * TV-Out modes are now better supported - this should be the end
29 * of the magenta stripes :)
30 * Brightness/Contrast controls disabled for the time being - they were
31 * seriously degrading picture quality, especially with TV-Out.
34 * Implement Hue/Saturation controls
35 * Support / Test multiple frames
36 * Test colour-key code more extensively
52 #include "pci_names.h"
54 #include "cyberblade_regs.h"
56 static pciinfo_t pci_info
;
58 static char save_colourkey
[6];
59 static char *cyberblade_mem
;
62 static FILE *logfile
=0;
63 #define LOGWRITE(x) {if(logfile) fprintf(logfile,x);}
68 /* Helper functions for reading registers. */
70 static void CROUTW(int reg
,int val
)
73 CROUTB(reg
+1,(val
>>8)&255);
76 static void SROUTW(int reg
,int val
)
79 SROUTB(reg
+1,(val
>>8)&255);
82 static vidix_capability_t cyberblade_cap
=
84 "Trident CyberBlade i1 driver",
85 "Alastair M. Robinson <blackfive@fakenhamweb.co.uk>",
93 FLAG_UPSCALER
|FLAG_DOWNSCALER
,
99 static unsigned short cyberblade_card_ids
[] =
101 DEVICE_TRIDENT_CYBERBLADE_I7
,
102 DEVICE_TRIDENT_CYBERBLADE_I7D
,
103 DEVICE_TRIDENT_CYBERBLADE_I1
,
104 DEVICE_TRIDENT_CYBERBLADE_I12
,
105 DEVICE_TRIDENT_CYBERBLADE_I13
,
106 DEVICE_TRIDENT_CYBERBLADE_XPAI1
110 static int find_chip(unsigned chip_id
)
113 for(i
= 0;i
< sizeof(cyberblade_card_ids
)/sizeof(unsigned short);i
++)
115 if(chip_id
== cyberblade_card_ids
[i
]) return i
;
120 static int cyberblade_probe(int verbose
, int force
)
122 pciinfo_t lst
[MAX_PCI_DEVICES
];
125 err
= pci_scan(lst
,&num_pci
);
128 printf("[cyberblade] Error occurred during pci scan: %s\n",strerror(err
));
134 for(i
=0; i
< num_pci
; i
++)
136 if(lst
[i
].vendor
== VENDOR_TRIDENT
)
140 idx
= find_chip(lst
[i
].device
);
143 dname
= pci_device_name(VENDOR_TRIDENT
, lst
[i
].device
);
144 dname
= dname
? dname
: "Unknown chip";
145 printf("[cyberblade] Found chip: %s\n", dname
);
147 if ((lst
[i
].command
& PCI_COMMAND_IO
) == 0)
149 printf("[cyberblade] Device is disabled, ignoring\n");
153 cyberblade_cap
.device_id
= lst
[i
].device
;
155 memcpy(&pci_info
, &lst
[i
], sizeof(pciinfo_t
));
161 if(err
&& verbose
) printf("[cyberblade] Can't find chip\n");
166 static int cyberblade_init(void)
168 cyberblade_mem
= map_phys_mem(pci_info
.base0
, 0x800000);
170 save_colourkey
[0]=SRINB(0x50);
171 save_colourkey
[1]=SRINB(0x51);
172 save_colourkey
[2]=SRINB(0x52);
173 save_colourkey
[3]=SRINB(0x54);
174 save_colourkey
[4]=SRINB(0x55);
175 save_colourkey
[5]=SRINB(0x56);
177 logfile
=fopen("/tmp/cyberblade_vidix.log","w");
182 static void cyberblade_destroy(void)
191 CROUTB(0x8E, 0xc4); /* Disable overlay */
192 SROUTB(0x50,save_colourkey
[0]);
193 SROUTB(0x51,save_colourkey
[1]);
194 SROUTB(0x52,save_colourkey
[2]);
195 SROUTB(0x54,save_colourkey
[3]);
196 SROUTB(0x55,save_colourkey
[4]);
197 SROUTB(0x56,save_colourkey
[5]);
198 SROUTB(0x11, protect
);
200 unmap_phys_mem(cyberblade_mem
, 0x800000);
204 static int cyberblade_get_caps(vidix_capability_t
*to
)
206 memcpy(to
, &cyberblade_cap
, sizeof(vidix_capability_t
));
211 static int is_supported_fourcc(uint32_t fourcc
)
226 static int cyberblade_query_fourcc(vidix_fourcc_t
*to
)
228 if(is_supported_fourcc(to
->fourcc
))
230 to
->depth
= VID_DEPTH_ALL
;
231 to
->flags
= VID_CAP_EXPAND
| VID_CAP_SHRINK
| VID_CAP_COLORKEY
;
234 to
->depth
= to
->flags
= 0;
239 static int frames
[VID_PLAY_MAXFRAMES
];
241 static vidix_grkey_t cyberblade_grkey
;
243 static int cyberblade_get_gkeys(vidix_grkey_t
*grkey
)
245 memcpy(grkey
, &cyberblade_grkey
, sizeof(vidix_grkey_t
));
249 static int cyberblade_set_gkeys(const vidix_grkey_t
*grkey
)
251 int pixfmt
=CRINB(0x38);
253 memcpy(&cyberblade_grkey
, grkey
, sizeof(vidix_grkey_t
));
258 if(pixfmt
&0x28) /* 32 or 24 bpp */
260 SROUTB(0x50, cyberblade_grkey
.ckey
.blue
); /* Colour Key */
261 SROUTB(0x51, cyberblade_grkey
.ckey
.green
); /* Colour Key */
262 SROUTB(0x52, cyberblade_grkey
.ckey
.red
); /* Colour Key */
263 SROUTB(0x54, 0xff); /* Colour Key Mask */
264 SROUTB(0x55, 0xff); /* Colour Key Mask */
265 SROUTB(0x56, 0xff); /* Colour Key Mask */
269 int tmp
=((cyberblade_grkey
.ckey
.blue
& 0xF8)>>3)
270 | ((cyberblade_grkey
.ckey
.green
& 0xfc)<<3)
271 | ((cyberblade_grkey
.ckey
.red
& 0xf8)<<8);
272 SROUTB(0x50, tmp
&0xff); /* Colour Key */
273 SROUTB(0x51, (tmp
>>8)&0xff); /* Colour Key */
274 SROUTB(0x52, 0); /* Colour Key */
275 SROUTB(0x54, 0xff); /* Colour Key Mask */
276 SROUTB(0x55, 0xff); /* Colour Key Mask */
277 SROUTB(0x56, 0x00); /* Colour Key Mask */
279 SROUTB(0x11,protect
);
284 static vidix_video_eq_t equal
=
286 VEQ_CAP_BRIGHTNESS
| VEQ_CAP_SATURATION
| VEQ_CAP_HUE
,
287 300, 100, 0, 0, 0, 0, 0, 0
290 static int cyberblade_get_eq( vidix_video_eq_t
* eq
)
292 memcpy(eq
,&equal
,sizeof(vidix_video_eq_t
));
296 static int cyberblade_set_eq( const vidix_video_eq_t
* eq
)
298 int br
,sat
,cr
,protect
;
299 if(eq
->cap
& VEQ_CAP_BRIGHTNESS
) equal
.brightness
= eq
->brightness
;
300 if(eq
->cap
& VEQ_CAP_CONTRAST
) equal
.contrast
= eq
->contrast
;
301 if(eq
->cap
& VEQ_CAP_SATURATION
) equal
.saturation
= eq
->saturation
;
302 if(eq
->cap
& VEQ_CAP_HUE
) equal
.hue
= eq
->hue
;
303 if(eq
->cap
& VEQ_CAP_RGB_INTENSITY
)
305 equal
.red_intensity
= eq
->red_intensity
;
306 equal
.green_intensity
= eq
->green_intensity
;
307 equal
.blue_intensity
= eq
->blue_intensity
;
309 equal
.flags
= eq
->flags
;
311 cr
= (equal
.contrast
) * 31 / 2000; cr
+=16;
312 if (cr
< 0) cr
= 0; if(cr
> 7) cr
= 7;
315 br
= (equal
.brightness
+1000) * 63 / 2000;
316 if (br
< 0) br
= 0; if(br
> 63) br
= 63;
317 if(br
>32) br
-=32; else br
+=32;
319 sat
= (equal
.saturation
+ 1000) * 16 / 2000;
320 if (sat
< 0) sat
= 0; if(sat
> 31) sat
= 31;
326 SROUTW(0xB0,(br
<<10)|4);
328 SROUTB(0x11, protect
);
334 static int YOffs
,UOffs
,VOffs
;
336 static int cyberblade_config_playback(vidix_playback_t
*info
)
342 int y_pitch
= 0, uv_pitch
= 0;
347 if(!is_supported_fourcc(info
->fourcc
))
353 drw_w
= info
->dest
.w
;
354 drw_h
= info
->dest
.h
;
360 y_pitch
= (src_w
*2 + 15) & ~15;
362 YOffs
=VOffs
=UOffs
=info
->offset
.y
= info
->offset
.v
= info
->offset
.u
= 0;
363 info
->frame_size
= y_pitch
*src_h
;
364 layout
=0x0; /* packed */
368 y_pitch
= (src_w
+15) & ~15;
369 uv_pitch
= ((src_w
/2)+7) & ~7;
370 YOffs
=info
->offset
.y
= 0;
371 VOffs
=info
->offset
.v
= y_pitch
*src_h
;
372 UOffs
=info
->offset
.u
= info
->offset
.v
+(uv_pitch
)*(src_h
/2);
373 info
->frame_size
= y_pitch
*src_h
+ 2*uv_pitch
*(src_h
/2);
374 layout
=0x1; /* planar, 4:1:1 */
377 y_pitch
= (src_w
+15) & ~15;
378 uv_pitch
= ((src_w
/4)+3) & ~3;
379 YOffs
=info
->offset
.y
= 0;
380 VOffs
=info
->offset
.v
= y_pitch
*src_h
;
381 UOffs
=info
->offset
.u
= info
->offset
.v
+(uv_pitch
)*(src_h
/4);
382 info
->frame_size
= y_pitch
*src_h
+ 2*uv_pitch
*(src_h
/4);
383 layout
=0x51; /* planar, 16:1:1 */
387 /* Assume we have 2 MB to play with */
388 info
->num_frames
= 0x200000 / info
->frame_size
;
389 if(info
->num_frames
> VID_PLAY_MAXFRAMES
)
390 info
->num_frames
= VID_PLAY_MAXFRAMES
;
392 /* Start at 6 MB. Let's hope it's not in use. */
394 info
->dga_addr
= cyberblade_mem
+ base0
;
396 info
->dest
.pitch
.y
= 16;
397 info
->dest
.pitch
.u
= 16;
398 info
->dest
.pitch
.v
= 16;
400 for(i
= 0; i
< info
->num_frames
; i
++)
402 info
->offsets
[i
] = info
->frame_size
* i
;
403 frames
[i
] = base0
+info
->offsets
[i
];
406 OUTPORT8(0x3d4,0x39);
407 OUTPORT8(0x3d5,INPORT(0x3d5)|1);
409 SRINB(0x0b); /* Select new mode */
411 /* Unprotect hardware registers... */
415 SROUTB(0x57, 0xc0); /* Playback key function */
416 SROUTB(0x21, 0x34); /* Signature control */
417 SROUTB(0x37, 0x30); /* Video key mode */
419 cyberblade_set_gkeys(&cyberblade_grkey
);
421 /* compute_scale_factor(&src_w, &drw_w, &shrink, &zoom); */
423 int HTotal
,VTotal
,HSync
,VSync
,Overflow
,HDisp
,VDisp
;
424 int HWinStart
,VWinStart
;
431 Overflow
=CRINB(0x07);
434 VTotal
|= (Overflow
& 1) <<8;
435 VTotal
|= (Overflow
& 0x20) <<4;
437 VSync
|= (Overflow
& 4) <<6;
438 VSync
|= (Overflow
& 0x80) <<2;
442 int TVHTotal
,TVVTotal
,TVHSyncStart
,TVVSyncStart
,TVOverflow
;
443 LOGWRITE("[cyberblade] Using TV-CRTC\n");
445 HDisp
=(1+CRINB(0x01))*8;
447 Overflow
=CRINB(0x07);
448 VDisp
|= (Overflow
& 2) <<7;
449 VDisp
|= (Overflow
& 0x40) << 3;
451 TVHTotal
=CRINB(0xe0)*8;
452 TVVTotal
=CRINB(0xe6);
453 TVOverflow
=CRINB(0xe7);
454 if(TVOverflow
&0x20) TVVTotal
|=512;
455 if(TVOverflow
&0x01) TVVTotal
|=256;
456 TVHTotal
+=40; TVVTotal
+=2;
458 TVHSyncStart
=CRINB(0xe4)*8;
459 TVVSyncStart
=CRINB(0xf0);
460 if(TVOverflow
&0x80) TVVSyncStart
|=512;
461 if(TVOverflow
&0x04) TVVSyncStart
|=256;
463 HWinStart
=(TVHTotal
-HDisp
)&15;
464 HWinStart
|=(HTotal
-HDisp
)&15;
465 HWinStart
+=(TVHTotal
-TVHSyncStart
)-49;
469 LOGWRITE("[cyberblade] Using Standard CRTC\n");
470 HWinStart
=(HTotal
-HSync
)+15;
472 VWinStart
=(VTotal
-VSync
)-8;
474 printf("[cyberblade] HTotal: 0x%x, HSStart: 0x%x\n",HTotal
,HSync
);
475 printf(" VTotal: 0x%x, VStart: 0x%x\n",VTotal
,VSync
);
476 tx1
=HWinStart
+info
->dest
.x
;
477 ty1
=VWinStart
+info
->dest
.y
;
478 tx2
=tx1
+info
->dest
.w
;
479 ty2
=ty1
+info
->dest
.h
;
491 hscale
=((src_w
<<10)/(drw_w
-2)) & 0x1fff;
495 hscale
=0x8000 | ((((src_w
/drw_w
)-1)&7)<<10) | (((drw_w
<<10)/src_w
) & 0x3ff);
498 vscale
=(src_h
<<10)/(drw_h
);
500 vscale
=0x8000|((drw_h
<<10)/(src_h
));
502 /* Write scale factors to hardware */
504 CROUTW(0x80,hscale
); /* Horizontal Scale */
505 CROUTW(0x82,vscale
); /* Vertical Scale */
507 /* Now set the start address and data layout */
509 int lb
= (y_pitch
+2) >> 2;
510 CROUTB(0x95, ((lb
& 0x100)>>1) | 0x08 ); /* Linebuffer level bit 8 & threshold */
511 CROUTB(0x96, (lb
& 0xFF)); /* Linebuffer level */
513 CROUTB(0x97, 0x00); /* VDE Flags */
514 CROUTB(0xBA, 0x00); /* Chroma key */
515 CROUTB(0xBB, 0x00); /* Chroma key */
516 CROUTB(0xBC, 0xFF); /* Chroma key */
517 CROUTB(0xBD, 0xFF); /* Chroma key */
518 CROUTB(0xBE, 0x04); /* Capture control */
521 layout
|=4; /* 2x line buffers */
522 SROUTB(0x97, layout
);
524 CROUTW(0x90,y_pitch
); /* Y Bytes per row */
525 SROUTW(0x9A,uv_pitch
); /* UV Bytes per row */
530 CROUTB(0x8F, 0x24); /* VDE Flags - Edge Recovery & CSC Bypass */
531 CROUTB(0xBF, 0x02); /* Video format - RGB16 */
532 SROUTB(0xBE, 0x0); /* HSCB disabled */
535 CROUTB(0x8F, 0x20); /* VDE Flags - Edge Recovery */
536 CROUTB(0xBF, 0x00); /* Video format - YUV */
537 SROUTB(0xBE, 0x00); /* HSCB disable - was 0x03*/
541 CROUTB(0x92, ((base0
+info
->offset
.y
) >> 3) &0xff); /* Lower 8 bits of start address */
542 CROUTB(0x93, ((base0
+info
->offset
.y
) >> 11) &0xff); /* Mid 8 bits of start address */
543 CROUTB(0x94, ((base0
+info
->offset
.y
) >> 19) &0xf); /* Upper 4 bits of start address */
544 SROUTB(0x80, ((base0
+info
->offset
.v
) >> 3) &0xff); /* Lower 8 bits of start address */
545 SROUTB(0x81, ((base0
+info
->offset
.v
) >> 11) &0xff); /* Mid 8 bits of start address */
546 SROUTB(0x82, ((base0
+info
->offset
.v
) >> 19) &0xf); /* Upper 4 bits of start address */
547 SROUTB(0x83, ((base0
+info
->offset
.u
) >> 3) &0xff); /* Lower 8 bits of start address */
548 SROUTB(0x84, ((base0
+info
->offset
.u
) >> 11) &0xff); /* Mid 8 bits of start address */
549 SROUTB(0x85, ((base0
+info
->offset
.u
) >> 19) &0xf); /* Upper 4 bits of start address */
552 cyberblade_set_eq(&equal
);
554 /* Protect hardware registers again */
555 SROUTB(0x11, protect
);
560 static int cyberblade_playback_on(void)
562 LOGWRITE("Enable overlay\n");
563 CROUTB(0x8E, 0xd4); /* VDE Flags*/
569 static int cyberblade_playback_off(void)
571 LOGWRITE("Disable overlay\n");
572 CROUTB(0x8E, 0xc4); /* VDE Flags*/
578 static int cyberblade_frame_sel(unsigned int frame
)
581 LOGWRITE("Frame select\n");
584 /* Set overlay address to that of selected frame */
585 CROUTB(0x92, ((frames
[frame
]+YOffs
) >> 3) &0xff); /* Lower 8 bits of start address */
586 CROUTB(0x93, ((frames
[frame
]+YOffs
) >> 11) &0xff); /* Mid 8 bits of start address */
587 CROUTB(0x94, ((frames
[frame
]+YOffs
) >> 19) &0xf); /* Upper 4 bits of start address */
588 SROUTB(0x80, ((frames
[frame
]+VOffs
) >> 3) &0xff); /* Lower 8 bits of start address */
589 SROUTB(0x81, ((frames
[frame
]+VOffs
) >> 11) &0xff); /* Mid 8 bits of start address */
590 SROUTB(0x82, ((frames
[frame
]+VOffs
) >> 19) &0xf); /* Upper 4 bits of start address */
591 SROUTB(0x83, ((frames
[frame
]+UOffs
) >> 3) &0xff); /* Lower 8 bits of start address */
592 SROUTB(0x84, ((frames
[frame
]+UOffs
) >> 11) &0xff); /* Mid 8 bits of start address */
593 SROUTB(0x85, ((frames
[frame
]+UOffs
) >> 19) &0xf); /* Upper 4 bits of start address */
594 SROUTB(0x11, protect
);
598 VDXDriver cyberblade_drv
= {
601 .probe
= cyberblade_probe
,
602 .get_caps
= cyberblade_get_caps
,
603 .query_fourcc
= cyberblade_query_fourcc
,
604 .init
= cyberblade_init
,
605 .destroy
= cyberblade_destroy
,
606 .config_playback
= cyberblade_config_playback
,
607 .playback_on
= cyberblade_playback_on
,
608 .playback_off
= cyberblade_playback_off
,
609 .frame_sel
= cyberblade_frame_sel
,
610 .get_eq
= cyberblade_get_eq
,
611 .set_eq
= cyberblade_set_eq
,
612 .get_gkey
= cyberblade_get_gkeys
,
613 .set_gkey
= cyberblade_set_gkeys
,