2 * VIDIX driver for VIA Cyberblade/i1 chipsets.
3 * Brightness/Contrast controls disabled for the time being - they were
4 * seriously degrading picture quality, especially with TV-Out.
6 * Copyright (C) 2002 Alastair M. Robinson
7 * http://www.blackfiveservices.co.uk/EPIAVidix.shtml
8 * based on Permedia 3 driver by Måns Rullgård
9 * thanks to Gilles Frattini for bugfixes
11 * This file is part of MPlayer.
13 * MPlayer is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * MPlayer is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License along
24 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 * Implement Hue/Saturation controls
30 * Support / Test multiple frames
31 * Test colour-key code more extensively
46 #include "pci_names.h"
48 #include "cyberblade_regs.h"
50 static pciinfo_t pci_info
;
52 static char save_colourkey
[6];
53 static char *cyberblade_mem
;
56 static FILE *logfile
=0;
57 #define LOGWRITE(x) {if(logfile) fprintf(logfile,x);}
62 /* Helper functions for reading registers. */
64 static void CROUTW(int reg
,int val
)
67 CROUTB(reg
+1,(val
>>8)&255);
70 static void SROUTW(int reg
,int val
)
73 SROUTB(reg
+1,(val
>>8)&255);
76 static vidix_capability_t cyberblade_cap
=
78 "Trident CyberBlade i1 driver",
79 "Alastair M. Robinson <blackfive@fakenhamweb.co.uk>",
87 FLAG_UPSCALER
|FLAG_DOWNSCALER
,
93 static unsigned short cyberblade_card_ids
[] =
95 DEVICE_TRIDENT_CYBERBLADE_I7
,
96 DEVICE_TRIDENT_CYBERBLADE_I7D
,
97 DEVICE_TRIDENT_CYBERBLADE_I1
,
98 DEVICE_TRIDENT_CYBERBLADE_I12
,
99 DEVICE_TRIDENT_CYBERBLADE_I13
,
100 DEVICE_TRIDENT_CYBERBLADE_XPAI1
104 static int find_chip(unsigned chip_id
)
107 for(i
= 0;i
< sizeof(cyberblade_card_ids
)/sizeof(unsigned short);i
++)
109 if(chip_id
== cyberblade_card_ids
[i
]) return i
;
114 static int cyberblade_probe(int verbose
, int force
)
116 pciinfo_t lst
[MAX_PCI_DEVICES
];
119 err
= pci_scan(lst
,&num_pci
);
122 printf("[cyberblade] Error occurred during pci scan: %s\n",strerror(err
));
128 for(i
=0; i
< num_pci
; i
++)
130 if(lst
[i
].vendor
== VENDOR_TRIDENT
)
134 idx
= find_chip(lst
[i
].device
);
137 dname
= pci_device_name(VENDOR_TRIDENT
, lst
[i
].device
);
138 dname
= dname
? dname
: "Unknown chip";
139 printf("[cyberblade] Found chip: %s\n", dname
);
141 if ((lst
[i
].command
& PCI_COMMAND_IO
) == 0)
143 printf("[cyberblade] Device is disabled, ignoring\n");
147 cyberblade_cap
.device_id
= lst
[i
].device
;
149 memcpy(&pci_info
, &lst
[i
], sizeof(pciinfo_t
));
155 if(err
&& verbose
) printf("[cyberblade] Can't find chip\n");
160 static int cyberblade_init(void)
162 cyberblade_mem
= map_phys_mem(pci_info
.base0
, 0x800000);
164 save_colourkey
[0]=SRINB(0x50);
165 save_colourkey
[1]=SRINB(0x51);
166 save_colourkey
[2]=SRINB(0x52);
167 save_colourkey
[3]=SRINB(0x54);
168 save_colourkey
[4]=SRINB(0x55);
169 save_colourkey
[5]=SRINB(0x56);
171 logfile
=fopen("/tmp/cyberblade_vidix.log","w");
176 static void cyberblade_destroy(void)
185 CROUTB(0x8E, 0xc4); /* Disable overlay */
186 SROUTB(0x50,save_colourkey
[0]);
187 SROUTB(0x51,save_colourkey
[1]);
188 SROUTB(0x52,save_colourkey
[2]);
189 SROUTB(0x54,save_colourkey
[3]);
190 SROUTB(0x55,save_colourkey
[4]);
191 SROUTB(0x56,save_colourkey
[5]);
192 SROUTB(0x11, protect
);
194 unmap_phys_mem(cyberblade_mem
, 0x800000);
198 static int cyberblade_get_caps(vidix_capability_t
*to
)
200 memcpy(to
, &cyberblade_cap
, sizeof(vidix_capability_t
));
205 static int is_supported_fourcc(uint32_t fourcc
)
220 static int cyberblade_query_fourcc(vidix_fourcc_t
*to
)
222 if(is_supported_fourcc(to
->fourcc
))
224 to
->depth
= VID_DEPTH_ALL
;
225 to
->flags
= VID_CAP_EXPAND
| VID_CAP_SHRINK
| VID_CAP_COLORKEY
;
228 to
->depth
= to
->flags
= 0;
233 static int frames
[VID_PLAY_MAXFRAMES
];
235 static vidix_grkey_t cyberblade_grkey
;
237 static int cyberblade_get_gkeys(vidix_grkey_t
*grkey
)
239 memcpy(grkey
, &cyberblade_grkey
, sizeof(vidix_grkey_t
));
243 static int cyberblade_set_gkeys(const vidix_grkey_t
*grkey
)
245 int pixfmt
=CRINB(0x38);
247 memcpy(&cyberblade_grkey
, grkey
, sizeof(vidix_grkey_t
));
252 if(pixfmt
&0x28) /* 32 or 24 bpp */
254 SROUTB(0x50, cyberblade_grkey
.ckey
.blue
); /* Colour Key */
255 SROUTB(0x51, cyberblade_grkey
.ckey
.green
); /* Colour Key */
256 SROUTB(0x52, cyberblade_grkey
.ckey
.red
); /* Colour Key */
257 SROUTB(0x54, 0xff); /* Colour Key Mask */
258 SROUTB(0x55, 0xff); /* Colour Key Mask */
259 SROUTB(0x56, 0xff); /* Colour Key Mask */
263 int tmp
=((cyberblade_grkey
.ckey
.blue
& 0xF8)>>3)
264 | ((cyberblade_grkey
.ckey
.green
& 0xfc)<<3)
265 | ((cyberblade_grkey
.ckey
.red
& 0xf8)<<8);
266 SROUTB(0x50, tmp
&0xff); /* Colour Key */
267 SROUTB(0x51, (tmp
>>8)&0xff); /* Colour Key */
268 SROUTB(0x52, 0); /* Colour Key */
269 SROUTB(0x54, 0xff); /* Colour Key Mask */
270 SROUTB(0x55, 0xff); /* Colour Key Mask */
271 SROUTB(0x56, 0x00); /* Colour Key Mask */
273 SROUTB(0x11,protect
);
278 static vidix_video_eq_t equal
=
280 VEQ_CAP_BRIGHTNESS
| VEQ_CAP_SATURATION
| VEQ_CAP_HUE
,
281 300, 100, 0, 0, 0, 0, 0, 0
284 static int cyberblade_get_eq( vidix_video_eq_t
* eq
)
286 memcpy(eq
,&equal
,sizeof(vidix_video_eq_t
));
290 static int cyberblade_set_eq( const vidix_video_eq_t
* eq
)
292 int br
,sat
,cr
,protect
;
293 if(eq
->cap
& VEQ_CAP_BRIGHTNESS
) equal
.brightness
= eq
->brightness
;
294 if(eq
->cap
& VEQ_CAP_CONTRAST
) equal
.contrast
= eq
->contrast
;
295 if(eq
->cap
& VEQ_CAP_SATURATION
) equal
.saturation
= eq
->saturation
;
296 if(eq
->cap
& VEQ_CAP_HUE
) equal
.hue
= eq
->hue
;
297 if(eq
->cap
& VEQ_CAP_RGB_INTENSITY
)
299 equal
.red_intensity
= eq
->red_intensity
;
300 equal
.green_intensity
= eq
->green_intensity
;
301 equal
.blue_intensity
= eq
->blue_intensity
;
303 equal
.flags
= eq
->flags
;
305 cr
= (equal
.contrast
) * 31 / 2000; cr
+=16;
306 if (cr
< 0) cr
= 0; if(cr
> 7) cr
= 7;
309 br
= (equal
.brightness
+1000) * 63 / 2000;
310 if (br
< 0) br
= 0; if(br
> 63) br
= 63;
311 if(br
>32) br
-=32; else br
+=32;
313 sat
= (equal
.saturation
+ 1000) * 16 / 2000;
314 if (sat
< 0) sat
= 0; if(sat
> 31) sat
= 31;
320 SROUTW(0xB0,(br
<<10)|4);
322 SROUTB(0x11, protect
);
328 static int YOffs
,UOffs
,VOffs
;
330 static int cyberblade_config_playback(vidix_playback_t
*info
)
336 int y_pitch
= 0, uv_pitch
= 0;
341 if(!is_supported_fourcc(info
->fourcc
))
347 drw_w
= info
->dest
.w
;
348 drw_h
= info
->dest
.h
;
354 y_pitch
= (src_w
*2 + 15) & ~15;
356 YOffs
=VOffs
=UOffs
=info
->offset
.y
= info
->offset
.v
= info
->offset
.u
= 0;
357 info
->frame_size
= y_pitch
*src_h
;
358 layout
=0x0; /* packed */
362 y_pitch
= (src_w
+15) & ~15;
363 uv_pitch
= ((src_w
/2)+7) & ~7;
364 YOffs
=info
->offset
.y
= 0;
365 VOffs
=info
->offset
.v
= y_pitch
*src_h
;
366 UOffs
=info
->offset
.u
= info
->offset
.v
+(uv_pitch
)*(src_h
/2);
367 info
->frame_size
= y_pitch
*src_h
+ 2*uv_pitch
*(src_h
/2);
368 layout
=0x1; /* planar, 4:1:1 */
371 y_pitch
= (src_w
+15) & ~15;
372 uv_pitch
= ((src_w
/4)+3) & ~3;
373 YOffs
=info
->offset
.y
= 0;
374 VOffs
=info
->offset
.v
= y_pitch
*src_h
;
375 UOffs
=info
->offset
.u
= info
->offset
.v
+(uv_pitch
)*(src_h
/4);
376 info
->frame_size
= y_pitch
*src_h
+ 2*uv_pitch
*(src_h
/4);
377 layout
=0x51; /* planar, 16:1:1 */
381 /* Assume we have 2 MB to play with */
382 info
->num_frames
= 0x200000 / info
->frame_size
;
383 if(info
->num_frames
> VID_PLAY_MAXFRAMES
)
384 info
->num_frames
= VID_PLAY_MAXFRAMES
;
386 /* Start at 6 MB. Let's hope it's not in use. */
388 info
->dga_addr
= cyberblade_mem
+ base0
;
390 info
->dest
.pitch
.y
= 16;
391 info
->dest
.pitch
.u
= 16;
392 info
->dest
.pitch
.v
= 16;
394 for(i
= 0; i
< info
->num_frames
; i
++)
396 info
->offsets
[i
] = info
->frame_size
* i
;
397 frames
[i
] = base0
+info
->offsets
[i
];
400 OUTPORT8(0x3d4,0x39);
401 OUTPORT8(0x3d5,INPORT(0x3d5)|1);
403 SRINB(0x0b); /* Select new mode */
405 /* Unprotect hardware registers... */
409 SROUTB(0x57, 0xc0); /* Playback key function */
410 SROUTB(0x21, 0x34); /* Signature control */
411 SROUTB(0x37, 0x30); /* Video key mode */
413 cyberblade_set_gkeys(&cyberblade_grkey
);
415 /* compute_scale_factor(&src_w, &drw_w, &shrink, &zoom); */
417 int HTotal
,VTotal
,HSync
,VSync
,Overflow
,HDisp
,VDisp
;
418 int HWinStart
,VWinStart
;
425 Overflow
=CRINB(0x07);
428 VTotal
|= (Overflow
& 1) <<8;
429 VTotal
|= (Overflow
& 0x20) <<4;
431 VSync
|= (Overflow
& 4) <<6;
432 VSync
|= (Overflow
& 0x80) <<2;
436 int TVHTotal
,TVVTotal
,TVHSyncStart
,TVVSyncStart
,TVOverflow
;
437 LOGWRITE("[cyberblade] Using TV-CRTC\n");
439 HDisp
=(1+CRINB(0x01))*8;
441 Overflow
=CRINB(0x07);
442 VDisp
|= (Overflow
& 2) <<7;
443 VDisp
|= (Overflow
& 0x40) << 3;
445 TVHTotal
=CRINB(0xe0)*8;
446 TVVTotal
=CRINB(0xe6);
447 TVOverflow
=CRINB(0xe7);
448 if(TVOverflow
&0x20) TVVTotal
|=512;
449 if(TVOverflow
&0x01) TVVTotal
|=256;
450 TVHTotal
+=40; TVVTotal
+=2;
452 TVHSyncStart
=CRINB(0xe4)*8;
453 TVVSyncStart
=CRINB(0xf0);
454 if(TVOverflow
&0x80) TVVSyncStart
|=512;
455 if(TVOverflow
&0x04) TVVSyncStart
|=256;
457 HWinStart
=(TVHTotal
-HDisp
)&15;
458 HWinStart
|=(HTotal
-HDisp
)&15;
459 HWinStart
+=(TVHTotal
-TVHSyncStart
)-49;
463 LOGWRITE("[cyberblade] Using Standard CRTC\n");
464 HWinStart
=(HTotal
-HSync
)+15;
466 VWinStart
=(VTotal
-VSync
)-8;
468 printf("[cyberblade] HTotal: 0x%x, HSStart: 0x%x\n",HTotal
,HSync
);
469 printf(" VTotal: 0x%x, VStart: 0x%x\n",VTotal
,VSync
);
470 tx1
=HWinStart
+info
->dest
.x
;
471 ty1
=VWinStart
+info
->dest
.y
;
472 tx2
=tx1
+info
->dest
.w
;
473 ty2
=ty1
+info
->dest
.h
;
485 hscale
=((src_w
<<10)/(drw_w
-2)) & 0x1fff;
489 hscale
=0x8000 | ((((src_w
/drw_w
)-1)&7)<<10) | (((drw_w
<<10)/src_w
) & 0x3ff);
492 vscale
=(src_h
<<10)/(drw_h
);
494 vscale
=0x8000|((drw_h
<<10)/(src_h
));
496 /* Write scale factors to hardware */
498 CROUTW(0x80,hscale
); /* Horizontal Scale */
499 CROUTW(0x82,vscale
); /* Vertical Scale */
501 /* Now set the start address and data layout */
503 int lb
= (y_pitch
+2) >> 2;
504 CROUTB(0x95, ((lb
& 0x100)>>1) | 0x08 ); /* Linebuffer level bit 8 & threshold */
505 CROUTB(0x96, (lb
& 0xFF)); /* Linebuffer level */
507 CROUTB(0x97, 0x00); /* VDE Flags */
508 CROUTB(0xBA, 0x00); /* Chroma key */
509 CROUTB(0xBB, 0x00); /* Chroma key */
510 CROUTB(0xBC, 0xFF); /* Chroma key */
511 CROUTB(0xBD, 0xFF); /* Chroma key */
512 CROUTB(0xBE, 0x04); /* Capture control */
515 layout
|=4; /* 2x line buffers */
516 SROUTB(0x97, layout
);
518 CROUTW(0x90,y_pitch
); /* Y Bytes per row */
519 SROUTW(0x9A,uv_pitch
); /* UV Bytes per row */
524 CROUTB(0x8F, 0x24); /* VDE Flags - Edge Recovery & CSC Bypass */
525 CROUTB(0xBF, 0x02); /* Video format - RGB16 */
526 SROUTB(0xBE, 0x0); /* HSCB disabled */
529 CROUTB(0x8F, 0x20); /* VDE Flags - Edge Recovery */
530 CROUTB(0xBF, 0x00); /* Video format - YUV */
531 SROUTB(0xBE, 0x00); /* HSCB disable - was 0x03*/
535 CROUTB(0x92, ((base0
+info
->offset
.y
) >> 3) &0xff); /* Lower 8 bits of start address */
536 CROUTB(0x93, ((base0
+info
->offset
.y
) >> 11) &0xff); /* Mid 8 bits of start address */
537 CROUTB(0x94, ((base0
+info
->offset
.y
) >> 19) &0xf); /* Upper 4 bits of start address */
538 SROUTB(0x80, ((base0
+info
->offset
.v
) >> 3) &0xff); /* Lower 8 bits of start address */
539 SROUTB(0x81, ((base0
+info
->offset
.v
) >> 11) &0xff); /* Mid 8 bits of start address */
540 SROUTB(0x82, ((base0
+info
->offset
.v
) >> 19) &0xf); /* Upper 4 bits of start address */
541 SROUTB(0x83, ((base0
+info
->offset
.u
) >> 3) &0xff); /* Lower 8 bits of start address */
542 SROUTB(0x84, ((base0
+info
->offset
.u
) >> 11) &0xff); /* Mid 8 bits of start address */
543 SROUTB(0x85, ((base0
+info
->offset
.u
) >> 19) &0xf); /* Upper 4 bits of start address */
546 cyberblade_set_eq(&equal
);
548 /* Protect hardware registers again */
549 SROUTB(0x11, protect
);
554 static int cyberblade_playback_on(void)
556 LOGWRITE("Enable overlay\n");
557 CROUTB(0x8E, 0xd4); /* VDE Flags*/
563 static int cyberblade_playback_off(void)
565 LOGWRITE("Disable overlay\n");
566 CROUTB(0x8E, 0xc4); /* VDE Flags*/
572 static int cyberblade_frame_sel(unsigned int frame
)
575 LOGWRITE("Frame select\n");
578 /* Set overlay address to that of selected frame */
579 CROUTB(0x92, ((frames
[frame
]+YOffs
) >> 3) &0xff); /* Lower 8 bits of start address */
580 CROUTB(0x93, ((frames
[frame
]+YOffs
) >> 11) &0xff); /* Mid 8 bits of start address */
581 CROUTB(0x94, ((frames
[frame
]+YOffs
) >> 19) &0xf); /* Upper 4 bits of start address */
582 SROUTB(0x80, ((frames
[frame
]+VOffs
) >> 3) &0xff); /* Lower 8 bits of start address */
583 SROUTB(0x81, ((frames
[frame
]+VOffs
) >> 11) &0xff); /* Mid 8 bits of start address */
584 SROUTB(0x82, ((frames
[frame
]+VOffs
) >> 19) &0xf); /* Upper 4 bits of start address */
585 SROUTB(0x83, ((frames
[frame
]+UOffs
) >> 3) &0xff); /* Lower 8 bits of start address */
586 SROUTB(0x84, ((frames
[frame
]+UOffs
) >> 11) &0xff); /* Mid 8 bits of start address */
587 SROUTB(0x85, ((frames
[frame
]+UOffs
) >> 19) &0xf); /* Upper 4 bits of start address */
588 SROUTB(0x11, protect
);
592 VDXDriver cyberblade_drv
= {
595 .probe
= cyberblade_probe
,
596 .get_caps
= cyberblade_get_caps
,
597 .query_fourcc
= cyberblade_query_fourcc
,
598 .init
= cyberblade_init
,
599 .destroy
= cyberblade_destroy
,
600 .config_playback
= cyberblade_config_playback
,
601 .playback_on
= cyberblade_playback_on
,
602 .playback_off
= cyberblade_playback_off
,
603 .frame_sel
= cyberblade_frame_sel
,
604 .get_eq
= cyberblade_get_eq
,
605 .set_eq
= cyberblade_set_eq
,
606 .get_gkey
= cyberblade_get_gkeys
,
607 .set_gkey
= cyberblade_set_gkeys
,