22850
|
1 /*
|
|
2 mach64_vid - VIDIX based video driver for Mach64 and 3DRage chips
|
|
3 Copyrights 2002 Nick Kurshev. This file is based on sources from
|
|
4 GATOS (gatos.sf.net) and X11 (www.xfree86.org)
|
|
5 Licence: GPL
|
|
6 WARNING: THIS DRIVER IS IN BETTA STAGE
|
|
7 */
|
|
8 #include <errno.h>
|
|
9 #include <stdio.h>
|
|
10 #include <stdlib.h>
|
|
11 #include <string.h>
|
|
12 #include <math.h>
|
|
13 #include <inttypes.h>
|
|
14 #include <fcntl.h>
|
|
15
|
|
16 #include "../config.h"
|
|
17 #include "../libavutil/common.h"
|
|
18 #include "../mpbswap.h"
|
|
19 #include "vidix.h"
|
|
20 #include "fourcc.h"
|
|
21 #include "../libdha/libdha.h"
|
|
22 #include "../libdha/pci_ids.h"
|
|
23 #include "../libdha/pci_names.h"
|
|
24
|
|
25 #include "mach64.h"
|
|
26 #include "../version.h"
|
|
27
|
|
28 #define UNUSED(x) ((void)(x)) /**< Removes warning about unused arguments */
|
|
29
|
|
30 static void *mach64_mmio_base = 0;
|
|
31 static void *mach64_mem_base = 0;
|
|
32 static int32_t mach64_overlay_offset = 0;
|
|
33 static uint32_t mach64_ram_size = 0;
|
|
34 static uint32_t mach64_buffer_base[10][3];
|
|
35 static int num_mach64_buffers=-1;
|
|
36 static int supports_planar=0;
|
|
37 static int supports_lcd_v_stretch=0;
|
|
38
|
|
39 pciinfo_t pci_info;
|
|
40 static int probed = 0;
|
|
41 static int __verbose = 0;
|
|
42
|
|
43 #define VERBOSE_LEVEL 1
|
|
44
|
|
45 typedef struct bes_registers_s
|
|
46 {
|
|
47 /* base address of yuv framebuffer */
|
|
48 uint32_t yuv_base;
|
|
49 uint32_t fourcc;
|
|
50 /* YUV BES registers */
|
|
51 uint32_t reg_load_cntl;
|
|
52 uint32_t scale_inc;
|
|
53 uint32_t y_x_start;
|
|
54 uint32_t y_x_end;
|
|
55 uint32_t vid_buf_pitch;
|
|
56 uint32_t height_width;
|
|
57
|
|
58 uint32_t scale_cntl;
|
|
59 uint32_t exclusive_horz;
|
|
60 uint32_t auto_flip_cntl;
|
|
61 uint32_t filter_cntl;
|
|
62 uint32_t key_cntl;
|
|
63 uint32_t test;
|
|
64 /* Configurable stuff */
|
|
65
|
|
66 int brightness;
|
|
67 int saturation;
|
|
68
|
|
69 int ckey_on;
|
|
70 uint32_t graphics_key_clr;
|
|
71 uint32_t graphics_key_msk;
|
|
72
|
|
73 int deinterlace_on;
|
|
74 uint32_t deinterlace_pattern;
|
|
75
|
|
76 } bes_registers_t;
|
|
77
|
|
78 static bes_registers_t besr;
|
|
79
|
|
80 typedef struct video_registers_s
|
|
81 {
|
|
82 const char * sname;
|
|
83 uint32_t name;
|
|
84 uint32_t value;
|
|
85 }video_registers_t;
|
|
86
|
|
87 static bes_registers_t besr;
|
|
88
|
|
89 /* Graphic keys */
|
|
90 static vidix_grkey_t mach64_grkey;
|
|
91
|
|
92 #define DECLARE_VREG(name) { #name, name, 0 }
|
|
93 static video_registers_t vregs[] =
|
|
94 {
|
|
95 DECLARE_VREG(OVERLAY_SCALE_INC),
|
|
96 DECLARE_VREG(OVERLAY_Y_X_START),
|
|
97 DECLARE_VREG(OVERLAY_Y_X_END),
|
|
98 DECLARE_VREG(OVERLAY_SCALE_CNTL),
|
|
99 DECLARE_VREG(OVERLAY_EXCLUSIVE_HORZ),
|
|
100 DECLARE_VREG(OVERLAY_EXCLUSIVE_VERT),
|
|
101 DECLARE_VREG(OVERLAY_TEST),
|
|
102 DECLARE_VREG(SCALER_BUF_PITCH),
|
|
103 DECLARE_VREG(SCALER_HEIGHT_WIDTH),
|
|
104 DECLARE_VREG(SCALER_BUF0_OFFSET),
|
|
105 DECLARE_VREG(SCALER_BUF0_OFFSET_U),
|
|
106 DECLARE_VREG(SCALER_BUF0_OFFSET_V),
|
|
107 DECLARE_VREG(SCALER_BUF1_OFFSET),
|
|
108 DECLARE_VREG(SCALER_BUF1_OFFSET_U),
|
|
109 DECLARE_VREG(SCALER_BUF1_OFFSET_V),
|
|
110 DECLARE_VREG(SCALER_H_COEFF0),
|
|
111 DECLARE_VREG(SCALER_H_COEFF1),
|
|
112 DECLARE_VREG(SCALER_H_COEFF2),
|
|
113 DECLARE_VREG(SCALER_H_COEFF3),
|
|
114 DECLARE_VREG(SCALER_H_COEFF4),
|
|
115 DECLARE_VREG(SCALER_COLOUR_CNTL),
|
|
116 DECLARE_VREG(SCALER_THRESHOLD),
|
|
117 DECLARE_VREG(VIDEO_FORMAT),
|
|
118 DECLARE_VREG(VIDEO_CONFIG),
|
|
119 DECLARE_VREG(VIDEO_SYNC_TEST),
|
|
120 DECLARE_VREG(VIDEO_SYNC_TEST_B)
|
|
121 };
|
|
122
|
|
123 /* have to restore it on exit */
|
|
124 static uint32_t SAVED_OVERLAY_GRAPHICS_KEY_CLR;
|
|
125
|
|
126 /* VIDIX exports */
|
|
127
|
|
128 /* MMIO space*/
|
|
129 #define GETREG(TYPE,PTR,OFFZ) (*((volatile TYPE*)((PTR)+(OFFZ))))
|
|
130 #define SETREG(TYPE,PTR,OFFZ,VAL) (*((volatile TYPE*)((PTR)+(OFFZ))))=VAL
|
|
131
|
|
132 #define INREG8(addr) GETREG(uint8_t,(uint8_t *)mach64_mmio_base,((addr)^0x100)<<2)
|
|
133 #define OUTREG8(addr,val) SETREG(uint8_t,(uint8_t *)mach64_mmio_base,((addr)^0x100)<<2,val)
|
|
134
|
|
135 static inline uint32_t INREG (uint32_t addr) {
|
|
136 uint32_t tmp = GETREG(uint32_t,(uint8_t *)mach64_mmio_base,((addr)^0x100)<<2);
|
|
137 return le2me_32(tmp);
|
|
138 }
|
|
139 #define OUTREG(addr,val) SETREG(uint32_t,(uint8_t *)mach64_mmio_base,((addr)^0x100)<<2,le2me_32(val))
|
|
140
|
|
141 #define OUTREGP(addr,val,mask) \
|
|
142 do { \
|
|
143 unsigned int _tmp = INREG(addr); \
|
|
144 _tmp &= (mask); \
|
|
145 _tmp |= (val); \
|
|
146 OUTREG(addr, _tmp); \
|
|
147 } while (0)
|
|
148
|
|
149 static __inline__ int ATIGetMach64LCDReg(int _Index)
|
|
150 {
|
|
151 OUTREG8(LCD_INDEX, _Index);
|
|
152 return INREG(LCD_DATA);
|
|
153 }
|
|
154
|
|
155 static __inline__ uint32_t INPLL(uint32_t addr)
|
|
156 {
|
|
157 uint32_t res;
|
|
158 uint32_t in;
|
|
159
|
|
160 in= INREG(CLOCK_CNTL);
|
|
161 in &= ~((PLL_WR_EN | PLL_ADDR)); //clean some stuff
|
|
162 OUTREG(CLOCK_CNTL, in | (addr<<10));
|
|
163
|
|
164 /* read the register value */
|
|
165 res = (INREG(CLOCK_CNTL)>>16)&0xFF;
|
|
166 return res;
|
|
167 }
|
|
168
|
|
169 static __inline__ void OUTPLL(uint32_t addr,uint32_t val)
|
|
170 {
|
|
171 //FIXME buggy but its not used
|
|
172 /* write addr byte */
|
|
173 OUTREG8(CLOCK_CNTL + 1, (addr << 2) | PLL_WR_EN);
|
|
174 /* write the register value */
|
|
175 OUTREG(CLOCK_CNTL + 2, val);
|
|
176 OUTREG8(CLOCK_CNTL + 1, (addr << 2) & ~PLL_WR_EN);
|
|
177 }
|
|
178
|
|
179 #define OUTPLLP(addr,val,mask) \
|
|
180 do { \
|
|
181 unsigned int _tmp = INPLL(addr); \
|
|
182 _tmp &= (mask); \
|
|
183 _tmp |= (val); \
|
|
184 OUTPLL(addr, _tmp); \
|
|
185 } while (0)
|
|
186
|
|
187 static void mach64_fifo_wait(unsigned n)
|
|
188 {
|
|
189 while ((INREG(FIFO_STAT) & 0xffff) > ((uint32_t)(0x8000 >> n)));
|
|
190 }
|
|
191
|
|
192 static void mach64_wait_for_idle( void )
|
|
193 {
|
|
194 mach64_fifo_wait(16);
|
|
195 while ((INREG(GUI_STAT) & 1)!= 0);
|
|
196 }
|
|
197
|
|
198 static void mach64_wait_vsync( void )
|
|
199 {
|
|
200 int i;
|
|
201
|
|
202 for(i=0; i<2000000; i++)
|
|
203 if( (INREG(CRTC_INT_CNTL)&CRTC_VBLANK)==0 ) break;
|
|
204 for(i=0; i<2000000; i++)
|
|
205 if( (INREG(CRTC_INT_CNTL)&CRTC_VBLANK) ) break;
|
|
206
|
|
207 }
|
|
208
|
|
209 static vidix_capability_t mach64_cap =
|
|
210 {
|
|
211 "BES driver for Mach64/3DRage cards",
|
|
212 "Nick Kurshev and Michael Niedermayer",
|
|
213 TYPE_OUTPUT,
|
|
214 { 0, 0, 0, 0 },
|
|
215 2048,
|
|
216 2048,
|
|
217 4,
|
|
218 4,
|
|
219 -1,
|
|
220 FLAG_UPSCALER|FLAG_DOWNSCALER,
|
|
221 VENDOR_ATI,
|
|
222 -1,
|
|
223 { 0, 0, 0, 0 }
|
|
224 };
|
|
225
|
|
226 static uint32_t mach64_vid_get_dbpp( void )
|
|
227 {
|
|
228 uint32_t dbpp,retval;
|
|
229 dbpp = (INREG(CRTC_GEN_CNTL)>>8)& 0x7;
|
|
230 switch(dbpp)
|
|
231 {
|
|
232 case 1: retval = 4; break;
|
|
233 case 2: retval = 8; break;
|
|
234 case 3: retval = 15; break;
|
|
235 case 4: retval = 16; break;
|
|
236 case 5: retval = 24; break;
|
|
237 default: retval=32; break;
|
|
238 }
|
|
239 return retval;
|
|
240 }
|
|
241
|
|
242 static int mach64_is_dbl_scan( void )
|
|
243 {
|
|
244 return INREG(CRTC_GEN_CNTL) & CRTC_DBL_SCAN_EN;
|
|
245 }
|
|
246
|
|
247 static int mach64_is_interlace( void )
|
|
248 {
|
|
249 return INREG(CRTC_GEN_CNTL) & CRTC_INTERLACE_EN;
|
|
250 }
|
|
251
|
|
252 static uint32_t mach64_get_xres( void )
|
|
253 {
|
|
254 /* FIXME: currently we extract that from CRTC!!!*/
|
|
255 uint32_t xres,h_total;
|
|
256 h_total = INREG(CRTC_H_TOTAL_DISP);
|
|
257 xres = (h_total >> 16) & 0xffff;
|
|
258 return (xres + 1)*8;
|
|
259 }
|
|
260
|
|
261 static uint32_t mach64_get_yres( void )
|
|
262 {
|
|
263 /* FIXME: currently we extract that from CRTC!!!*/
|
|
264 uint32_t yres,v_total;
|
|
265 v_total = INREG(CRTC_V_TOTAL_DISP);
|
|
266 yres = (v_total >> 16) & 0xffff;
|
|
267 return yres + 1;
|
|
268 }
|
|
269
|
|
270 // returns the verical stretch factor in 16.16
|
|
271 static int mach64_get_vert_stretch(void)
|
|
272 {
|
|
273 int lcd_index;
|
|
274 int vert_stretching;
|
|
275 int ext_vert_stretch;
|
|
276 int ret;
|
|
277 int yres= mach64_get_yres();
|
|
278
|
|
279 if(!supports_lcd_v_stretch){
|
|
280 if(__verbose>0) printf("[mach64] vertical stretching not supported\n");
|
|
281 return 1<<16;
|
|
282 }
|
|
283
|
|
284 lcd_index= INREG(LCD_INDEX);
|
|
285
|
|
286 vert_stretching= ATIGetMach64LCDReg(LCD_VERT_STRETCHING);
|
|
287 if(!(vert_stretching&VERT_STRETCH_EN)) ret= 1<<16;
|
|
288 else
|
|
289 {
|
|
290 int panel_size;
|
|
291
|
|
292 ext_vert_stretch= ATIGetMach64LCDReg(LCD_EXT_VERT_STRETCH);
|
|
293 panel_size= (ext_vert_stretch&VERT_PANEL_SIZE)>>11;
|
|
294 panel_size++;
|
|
295
|
|
296 ret= ((yres<<16) + (panel_size>>1))/panel_size;
|
|
297 }
|
|
298
|
|
299 // lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL);
|
|
300
|
|
301 OUTREG(LCD_INDEX, lcd_index);
|
|
302
|
|
303 if(__verbose>0) printf("[mach64] vertical stretching factor= %d\n", ret);
|
|
304
|
|
305 return ret;
|
|
306 }
|
|
307
|
|
308 static void mach64_vid_make_default(void)
|
|
309 {
|
|
310 mach64_fifo_wait(5);
|
|
311 OUTREG(SCALER_COLOUR_CNTL,0x00101000);
|
|
312
|
|
313 besr.ckey_on=0;
|
|
314 besr.graphics_key_msk=0;
|
|
315 besr.graphics_key_clr=0;
|
|
316
|
|
317 OUTREG(OVERLAY_GRAPHICS_KEY_MSK, besr.graphics_key_msk);
|
|
318 OUTREG(OVERLAY_GRAPHICS_KEY_CLR, besr.graphics_key_clr);
|
|
319 OUTREG(OVERLAY_KEY_CNTL,VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_EQ|CMP_MIX_AND);
|
|
320
|
|
321 }
|
|
322
|
|
323 static void mach64_vid_dump_regs( void )
|
|
324 {
|
|
325 size_t i;
|
|
326 printf("[mach64] *** Begin of DRIVER variables dump ***\n");
|
|
327 printf("[mach64] mach64_mmio_base=%p\n",mach64_mmio_base);
|
|
328 printf("[mach64] mach64_mem_base=%p\n",mach64_mem_base);
|
|
329 printf("[mach64] mach64_overlay_off=%08X\n",mach64_overlay_offset);
|
|
330 printf("[mach64] mach64_ram_size=%08X\n",mach64_ram_size);
|
|
331 printf("[mach64] video mode: %ux%u@%u\n",mach64_get_xres(),mach64_get_yres(),mach64_vid_get_dbpp());
|
|
332 printf("[mach64] *** Begin of OV0 registers dump ***\n");
|
|
333 for(i=0;i<sizeof(vregs)/sizeof(video_registers_t);i++)
|
|
334 {
|
|
335 mach64_wait_for_idle();
|
|
336 printf("[mach64] %s = %08X\n",vregs[i].sname,INREG(vregs[i].name));
|
|
337 }
|
|
338 printf("[mach64] *** End of OV0 registers dump ***\n");
|
|
339 }
|
|
340
|
|
341
|
|
342 unsigned int vixGetVersion(void)
|
|
343 {
|
|
344 return(VIDIX_VERSION);
|
|
345 }
|
|
346
|
|
347 static unsigned short ati_card_ids[] =
|
|
348 {
|
|
349 DEVICE_ATI_215CT_MACH64_CT,
|
|
350 DEVICE_ATI_210888CX_MACH64_CX,
|
|
351 DEVICE_ATI_210888ET_MACH64_ET,
|
|
352 DEVICE_ATI_MACH64_VT,
|
|
353 DEVICE_ATI_210888GX_MACH64_GX,
|
|
354 DEVICE_ATI_264LT_MACH64_LT,
|
|
355 DEVICE_ATI_264VT_MACH64_VT,
|
|
356 DEVICE_ATI_264VT3_MACH64_VT3,
|
|
357 DEVICE_ATI_264VT4_MACH64_VT4,
|
|
358 /**/
|
|
359 DEVICE_ATI_3D_RAGE_PRO,
|
|
360 DEVICE_ATI_3D_RAGE_PRO2,
|
|
361 DEVICE_ATI_3D_RAGE_PRO3,
|
|
362 DEVICE_ATI_3D_RAGE_PRO4,
|
|
363 DEVICE_ATI_RAGE_XC,
|
|
364 DEVICE_ATI_RAGE_XL_AGP,
|
|
365 DEVICE_ATI_RAGE_XC_AGP,
|
|
366 DEVICE_ATI_RAGE_XL,
|
|
367 DEVICE_ATI_3D_RAGE_PRO5,
|
|
368 DEVICE_ATI_3D_RAGE_PRO6,
|
|
369 DEVICE_ATI_RAGE_XL2,
|
|
370 DEVICE_ATI_RAGE_XC2,
|
|
371 DEVICE_ATI_3D_RAGE_I_II,
|
|
372 DEVICE_ATI_3D_RAGE_II,
|
|
373 DEVICE_ATI_3D_RAGE_IIC,
|
|
374 DEVICE_ATI_3D_RAGE_IIC2,
|
|
375 DEVICE_ATI_3D_RAGE_IIC3,
|
|
376 DEVICE_ATI_3D_RAGE_IIC4,
|
|
377 DEVICE_ATI_3D_RAGE_LT,
|
|
378 DEVICE_ATI_3D_RAGE_LT2,
|
|
379 DEVICE_ATI_3D_RAGE_LT_G,
|
|
380 DEVICE_ATI_3D_RAGE_LT3,
|
|
381 DEVICE_ATI_RAGE_MOBILITY_P_M,
|
|
382 DEVICE_ATI_RAGE_MOBILITY_L,
|
|
383 DEVICE_ATI_3D_RAGE_LT4,
|
|
384 DEVICE_ATI_3D_RAGE_LT5,
|
|
385 DEVICE_ATI_RAGE_MOBILITY_P_M2,
|
|
386 DEVICE_ATI_RAGE_MOBILITY_L2
|
|
387 };
|
|
388
|
|
389 static int find_chip(unsigned chip_id)
|
|
390 {
|
|
391 unsigned i;
|
|
392 for(i = 0;i < sizeof(ati_card_ids)/sizeof(unsigned short);i++)
|
|
393 {
|
|
394 if(chip_id == ati_card_ids[i]) return i;
|
|
395 }
|
|
396 return -1;
|
|
397 }
|
|
398
|
|
399 int vixProbe(int verbose,int force)
|
|
400 {
|
|
401 pciinfo_t lst[MAX_PCI_DEVICES];
|
|
402 unsigned i,num_pci;
|
|
403 int err;
|
|
404 __verbose = verbose;
|
|
405 err = pci_scan(lst,&num_pci);
|
|
406 if(err)
|
|
407 {
|
|
408 printf("[mach64] Error occurred during pci scan: %s\n",strerror(err));
|
|
409 return err;
|
|
410 }
|
|
411 else
|
|
412 {
|
|
413 err = ENXIO;
|
|
414 for(i=0;i<num_pci;i++)
|
|
415 {
|
|
416 if(lst[i].vendor == VENDOR_ATI)
|
|
417 {
|
|
418 int idx;
|
|
419 const char *dname;
|
|
420 idx = find_chip(lst[i].device);
|
|
421 if(idx == -1 && force == PROBE_NORMAL) continue;
|
|
422 dname = pci_device_name(VENDOR_ATI,lst[i].device);
|
|
423 dname = dname ? dname : "Unknown chip";
|
|
424 printf("[mach64] Found chip: %s\n",dname);
|
|
425 if ((lst[i].command & PCI_COMMAND_IO) == 0)
|
|
426 {
|
|
427 printf("[mach64] Device is disabled, ignoring\n");
|
|
428 continue;
|
|
429 }
|
|
430 if(force > PROBE_NORMAL)
|
|
431 {
|
|
432 printf("[mach64] Driver was forced. Was found %sknown chip\n",idx == -1 ? "un" : "");
|
|
433 if(idx == -1)
|
|
434 printf("[mach64] Assuming it as Mach64\n");
|
|
435 }
|
|
436 mach64_cap.device_id = lst[i].device;
|
|
437 err = 0;
|
|
438 memcpy(&pci_info,&lst[i],sizeof(pciinfo_t));
|
|
439 probed=1;
|
|
440 break;
|
|
441 }
|
|
442 }
|
|
443 }
|
|
444 if(err && verbose) printf("[mach64] Can't find chip\n");
|
|
445 return err;
|
|
446 }
|
|
447
|
|
448 static void reset_regs( void )
|
|
449 {
|
|
450 size_t i;
|
|
451 for(i=0;i<sizeof(vregs)/sizeof(video_registers_t);i++)
|
|
452 {
|
|
453 mach64_fifo_wait(2);
|
|
454 OUTREG(vregs[i].name,0);
|
|
455 }
|
|
456 }
|
|
457
|
|
458
|
|
459 int vixInit(void)
|
|
460 {
|
|
461 int err;
|
|
462 if(!probed)
|
|
463 {
|
|
464 printf("[mach64] Driver was not probed but is being initializing\n");
|
|
465 return EINTR;
|
|
466 }
|
|
467 if(__verbose>0) printf("[mach64] version %s\n", VERSION);
|
|
468
|
|
469 if((mach64_mmio_base = map_phys_mem(pci_info.base2,0x1000))==(void *)-1) return ENOMEM;
|
|
470 mach64_wait_for_idle();
|
|
471 mach64_ram_size = INREG(MEM_CNTL) & CTL_MEM_SIZEB;
|
|
472 if (mach64_ram_size < 8) mach64_ram_size = (mach64_ram_size + 1) * 512;
|
|
473 else if (mach64_ram_size < 12) mach64_ram_size = (mach64_ram_size - 3) * 1024;
|
|
474 else mach64_ram_size = (mach64_ram_size - 7) * 2048;
|
|
475 mach64_ram_size *= 0x400; /* KB -> bytes */
|
|
476 if((mach64_mem_base = map_phys_mem(pci_info.base0,mach64_ram_size))==(void *)-1) return ENOMEM;
|
|
477 memset(&besr,0,sizeof(bes_registers_t));
|
|
478 printf("[mach64] Video memory = %uMb\n",mach64_ram_size/0x100000);
|
|
479 err = mtrr_set_type(pci_info.base0,mach64_ram_size,MTRR_TYPE_WRCOMB);
|
|
480 if(!err) printf("[mach64] Set write-combining type of video memory\n");
|
|
481
|
|
482 /* save this */
|
|
483 mach64_wait_for_idle();
|
|
484 SAVED_OVERLAY_GRAPHICS_KEY_CLR = INREG(OVERLAY_GRAPHICS_KEY_CLR);
|
|
485
|
|
486 /* check if planar formats are supported */
|
|
487 supports_planar=0;
|
|
488 mach64_wait_for_idle();
|
|
489 mach64_fifo_wait(2);
|
|
490 if(INREG(SCALER_BUF0_OFFSET_U)) supports_planar=1;
|
|
491 else
|
|
492 {
|
|
493 OUTREG(SCALER_BUF0_OFFSET_U, -1);
|
|
494
|
|
495 mach64_wait_vsync();
|
|
496 mach64_wait_for_idle();
|
|
497 mach64_fifo_wait(2);
|
|
498
|
|
499 if(INREG(SCALER_BUF0_OFFSET_U)) supports_planar=1;
|
|
500 }
|
|
501 if(supports_planar) printf("[mach64] Planar YUV formats are supported :)\n");
|
|
502 else printf("[mach64] Planar YUV formats are not supported :(\n");
|
|
503
|
|
504 if( mach64_cap.device_id==DEVICE_ATI_RAGE_MOBILITY_P_M
|
|
505 || mach64_cap.device_id==DEVICE_ATI_RAGE_MOBILITY_P_M2
|
|
506 || mach64_cap.device_id==DEVICE_ATI_RAGE_MOBILITY_L
|
|
507 || mach64_cap.device_id==DEVICE_ATI_RAGE_MOBILITY_L2)
|
|
508 supports_lcd_v_stretch=1;
|
|
509 else
|
|
510 supports_lcd_v_stretch=0;
|
|
511
|
|
512 reset_regs();
|
|
513 mach64_vid_make_default();
|
|
514
|
|
515 if(__verbose > VERBOSE_LEVEL) mach64_vid_dump_regs();
|
|
516 return 0;
|
|
517 }
|
|
518
|
|
519 void vixDestroy(void)
|
|
520 {
|
|
521 /*restore this*/
|
|
522 mach64_wait_for_idle();
|
|
523 OUTREG(OVERLAY_GRAPHICS_KEY_CLR,SAVED_OVERLAY_GRAPHICS_KEY_CLR);
|
|
524
|
|
525 unmap_phys_mem(mach64_mem_base,mach64_ram_size);
|
|
526 unmap_phys_mem(mach64_mmio_base,0x1000);
|
|
527 }
|
|
528
|
|
529 int vixGetCapability(vidix_capability_t *to)
|
|
530 {
|
|
531 memcpy(to, &mach64_cap, sizeof(vidix_capability_t));
|
|
532 return 0;
|
|
533 }
|
|
534
|
|
535 static unsigned mach64_query_pitch(unsigned fourcc,const vidix_yuv_t *spitch)
|
|
536 {
|
|
537 unsigned pitch,spy,spv,spu;
|
|
538 spy = spv = spu = 0;
|
|
539 switch(spitch->y)
|
|
540 {
|
|
541 case 16:
|
|
542 case 32:
|
|
543 case 64:
|
|
544 case 128:
|
|
545 case 256: spy = spitch->y; break;
|
|
546 default: break;
|
|
547 }
|
|
548 switch(spitch->u)
|
|
549 {
|
|
550 case 16:
|
|
551 case 32:
|
|
552 case 64:
|
|
553 case 128:
|
|
554 case 256: spu = spitch->u; break;
|
|
555 default: break;
|
|
556 }
|
|
557 switch(spitch->v)
|
|
558 {
|
|
559 case 16:
|
|
560 case 32:
|
|
561 case 64:
|
|
562 case 128:
|
|
563 case 256: spv = spitch->v; break;
|
|
564 default: break;
|
|
565 }
|
|
566 switch(fourcc)
|
|
567 {
|
|
568 /* 4:2:0 */
|
|
569 case IMGFMT_IYUV:
|
|
570 case IMGFMT_YV12:
|
|
571 case IMGFMT_I420:
|
|
572 if(spy > 16 && spu == spy/2 && spv == spy/2) pitch = spy;
|
|
573 else pitch = 32;
|
|
574 break;
|
|
575 case IMGFMT_YVU9:
|
|
576 if(spy > 32 && spu == spy/4 && spv == spy/4) pitch = spy;
|
|
577 else pitch = 64;
|
|
578 break;
|
|
579 default:
|
|
580 if(spy >= 16) pitch = spy;
|
|
581 else pitch = 16;
|
|
582 break;
|
|
583 }
|
|
584 return pitch;
|
|
585 }
|
|
586
|
|
587 static void mach64_compute_framesize(vidix_playback_t *info)
|
|
588 {
|
|
589 unsigned pitch,awidth;
|
|
590 pitch = mach64_query_pitch(info->fourcc,&info->src.pitch);
|
|
591 switch(info->fourcc)
|
|
592 {
|
|
593 case IMGFMT_I420:
|
|
594 case IMGFMT_YV12:
|
|
595 case IMGFMT_IYUV:
|
|
596 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
|
|
597 info->frame_size = awidth*(info->src.h+info->src.h/2);
|
|
598 break;
|
|
599 case IMGFMT_YVU9:
|
|
600 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
|
|
601 info->frame_size = awidth*(info->src.h+info->src.h/8);
|
|
602 break;
|
|
603 // case IMGFMT_RGB32:
|
|
604 case IMGFMT_BGR32:
|
|
605 awidth = (info->src.w*4 + (pitch-1)) & ~(pitch-1);
|
|
606 info->frame_size = (awidth*info->src.h);
|
|
607 break;
|
|
608 /* YUY2 YVYU, RGB15, RGB16 */
|
|
609 default:
|
|
610 awidth = (info->src.w*2 + (pitch-1)) & ~(pitch-1);
|
|
611 info->frame_size = (awidth*info->src.h);
|
|
612 break;
|
|
613 }
|
|
614 info->frame_size+=256; // so we have some space for alignment & such
|
|
615 info->frame_size&=~16;
|
|
616 }
|
|
617
|
|
618 static void mach64_vid_stop_video( void )
|
|
619 {
|
|
620 mach64_fifo_wait(14);
|
|
621 OUTREG(OVERLAY_SCALE_CNTL, 0x80000000);
|
|
622 OUTREG(OVERLAY_EXCLUSIVE_HORZ, 0);
|
|
623 OUTREG(OVERLAY_EXCLUSIVE_VERT, 0);
|
|
624 OUTREG(SCALER_H_COEFF0, 0x00002000);
|
|
625 OUTREG(SCALER_H_COEFF1, 0x0D06200D);
|
|
626 OUTREG(SCALER_H_COEFF2, 0x0D0A1C0D);
|
|
627 OUTREG(SCALER_H_COEFF3, 0x0C0E1A0C);
|
|
628 OUTREG(SCALER_H_COEFF4, 0x0C14140C);
|
|
629 OUTREG(VIDEO_FORMAT, 0xB000B);
|
|
630 OUTREG(OVERLAY_TEST, 0x0);
|
|
631 }
|
|
632
|
|
633 static void mach64_vid_display_video( void )
|
|
634 {
|
|
635 uint32_t vf;
|
|
636 mach64_fifo_wait(14);
|
|
637
|
|
638 OUTREG(OVERLAY_Y_X_START, besr.y_x_start);
|
|
639 OUTREG(OVERLAY_Y_X_END, besr.y_x_end);
|
|
640 OUTREG(OVERLAY_SCALE_INC, besr.scale_inc);
|
|
641 OUTREG(SCALER_BUF_PITCH, besr.vid_buf_pitch);
|
|
642 OUTREG(SCALER_HEIGHT_WIDTH, besr.height_width);
|
|
643 OUTREG(SCALER_BUF0_OFFSET, mach64_buffer_base[0][0]);
|
|
644 OUTREG(SCALER_BUF0_OFFSET_U, mach64_buffer_base[0][1]);
|
|
645 OUTREG(SCALER_BUF0_OFFSET_V, mach64_buffer_base[0][2]);
|
|
646 OUTREG(SCALER_BUF1_OFFSET, mach64_buffer_base[0][0]);
|
|
647 OUTREG(SCALER_BUF1_OFFSET_U, mach64_buffer_base[0][1]);
|
|
648 OUTREG(SCALER_BUF1_OFFSET_V, mach64_buffer_base[0][2]);
|
|
649 mach64_wait_vsync();
|
|
650
|
|
651 mach64_fifo_wait(4);
|
|
652 OUTREG(OVERLAY_SCALE_CNTL, 0xC4000003);
|
|
653 // OVERLAY_SCALE_CNTL bits & what they seem to affect
|
|
654 // bit 0 no effect
|
|
655 // bit 1 yuv2rgb coeff related
|
|
656 // bit 2 horizontal interpolation if 0
|
|
657 // bit 3 vertical interpolation if 0
|
|
658 // bit 4 chroma encoding (0-> 128=neutral / 1-> 0->neutral)
|
|
659 // bit 5-6 gamma correction
|
|
660 // bit 7 nothing visible if set
|
|
661 // bit 8-27 no effect
|
|
662 // bit 28-31 nothing interresting just crashed my system when i played with them :(
|
|
663
|
|
664 mach64_wait_for_idle();
|
|
665 vf = INREG(VIDEO_FORMAT);
|
|
666
|
|
667 // Bits 16-19 seem to select the format
|
|
668 // 0x0 dunno behaves strange
|
|
669 // 0x1 dunno behaves strange
|
|
670 // 0x2 dunno behaves strange
|
|
671 // 0x3 BGR15
|
|
672 // 0x4 BGR16
|
|
673 // 0x5 BGR16 (hmm, that need investigation, 2 BGR16 formats, i guess 1 will have only 5bits for green)
|
|
674 // 0x6 BGR32
|
|
675 // 0x7 BGR32 with somehow mixed even / odd pixels ?
|
|
676 // 0x8 YYYYUVUV
|
|
677 // 0x9 YVU9
|
|
678 // 0xA YV12
|
|
679 // 0xB YUY2
|
|
680 // 0xC UYVY
|
|
681 // 0xD UYVY (no difference is visible if i switch between C/D for every even/odd frame)
|
|
682 // 0xE dunno behaves strange
|
|
683 // 0xF dunno behaves strange
|
|
684 // Bit 28 all values are assumed to be 7 bit with chroma=64 for black (tested with YV12 & YUY2)
|
|
685 // the remaining bits seem to have no effect
|
|
686
|
|
687
|
|
688 switch(besr.fourcc)
|
|
689 {
|
|
690 /* BGR formats */
|
|
691 case IMGFMT_BGR15: OUTREG(VIDEO_FORMAT, 0x00030000); break;
|
|
692 case IMGFMT_BGR16: OUTREG(VIDEO_FORMAT, 0x00040000); break;
|
|
693 case IMGFMT_BGR32: OUTREG(VIDEO_FORMAT, 0x00060000); break;
|
|
694 /* 4:2:0 */
|
|
695 case IMGFMT_IYUV:
|
|
696 case IMGFMT_I420:
|
|
697 case IMGFMT_YV12: OUTREG(VIDEO_FORMAT, 0x000A0000); break;
|
|
698
|
|
699 case IMGFMT_YVU9: OUTREG(VIDEO_FORMAT, 0x00090000); break;
|
|
700 /* 4:2:2 */
|
|
701 case IMGFMT_YVYU:
|
|
702 case IMGFMT_UYVY: OUTREG(VIDEO_FORMAT, 0x000C0000); break;
|
|
703 case IMGFMT_YUY2:
|
|
704 default: OUTREG(VIDEO_FORMAT, 0x000B0000); break;
|
|
705 }
|
|
706 if(__verbose > VERBOSE_LEVEL) mach64_vid_dump_regs();
|
|
707 }
|
|
708
|
|
709 static int mach64_vid_init_video( vidix_playback_t *config )
|
|
710 {
|
|
711 uint32_t src_w,src_h,dest_w,dest_h,pitch,h_inc,v_inc,left,leftUV,top,ecp,y_pos;
|
|
712 int is_420,best_pitch,mpitch;
|
|
713 int src_offset_y, src_offset_u, src_offset_v;
|
|
714 unsigned int i;
|
|
715
|
|
716 mach64_vid_stop_video();
|
|
717 /* warning, if left or top are != 0 this will fail, as the framesize is too small then */
|
|
718 left = config->src.x;
|
|
719 top = config->src.y;
|
|
720 src_h = config->src.h;
|
|
721 src_w = config->src.w;
|
|
722 is_420 = 0;
|
|
723 if(config->fourcc == IMGFMT_YV12 ||
|
|
724 config->fourcc == IMGFMT_I420 ||
|
|
725 config->fourcc == IMGFMT_IYUV) is_420 = 1;
|
|
726 best_pitch = mach64_query_pitch(config->fourcc,&config->src.pitch);
|
|
727 mpitch = best_pitch-1;
|
|
728 switch(config->fourcc)
|
|
729 {
|
|
730 case IMGFMT_YVU9:
|
|
731 /* 4:2:0 */
|
|
732 case IMGFMT_IYUV:
|
|
733 case IMGFMT_YV12:
|
|
734 case IMGFMT_I420: pitch = (src_w + mpitch) & ~mpitch;
|
|
735 config->dest.pitch.y =
|
|
736 config->dest.pitch.u =
|
|
737 config->dest.pitch.v = best_pitch;
|
|
738 besr.vid_buf_pitch= pitch;
|
|
739 break;
|
|
740 /* RGB 4:4:4:4 */
|
|
741 case IMGFMT_RGB32:
|
|
742 case IMGFMT_BGR32: pitch = (src_w*4 + mpitch) & ~mpitch;
|
|
743 config->dest.pitch.y =
|
|
744 config->dest.pitch.u =
|
|
745 config->dest.pitch.v = best_pitch;
|
|
746 besr.vid_buf_pitch= pitch>>2;
|
|
747 break;
|
|
748 /* 4:2:2 */
|
|
749 default: /* RGB15, RGB16, YVYU, UYVY, YUY2 */
|
|
750 pitch = ((src_w*2) + mpitch) & ~mpitch;
|
|
751 config->dest.pitch.y =
|
|
752 config->dest.pitch.u =
|
|
753 config->dest.pitch.v = best_pitch;
|
|
754 besr.vid_buf_pitch= pitch>>1;
|
|
755 break;
|
|
756 }
|
|
757 dest_w = config->dest.w;
|
|
758 dest_h = config->dest.h;
|
|
759 besr.fourcc = config->fourcc;
|
|
760 ecp = (INPLL(PLL_VCLK_CNTL) & PLL_ECP_DIV) >> 4;
|
|
761 #if 0
|
|
762 {
|
|
763 int i;
|
|
764 for(i=0; i<32; i++){
|
|
765 printf("%X ", INPLL(i));
|
|
766 }
|
|
767 }
|
|
768 #endif
|
|
769 if(__verbose>0) printf("[mach64] ecp: %d\n", ecp);
|
|
770 v_inc = src_h * mach64_get_vert_stretch();
|
|
771
|
|
772 if(mach64_is_interlace()) v_inc<<=1;
|
|
773 if(mach64_is_dbl_scan() ) v_inc>>=1;
|
|
774 v_inc>>=4; // convert 16.16 -> 20.12
|
|
775 v_inc/= dest_h;
|
|
776
|
|
777 h_inc = (src_w << (12+ecp)) / dest_w;
|
|
778 /* keep everything in 16.16 */
|
|
779 config->offsets[0] = 0;
|
|
780 for(i=1; i<config->num_frames; i++)
|
|
781 config->offsets[i] = config->offsets[i-1] + config->frame_size;
|
|
782
|
|
783 /*FIXME the left / top stuff is broken (= zoom a src rectangle from a larger one)
|
|
784 1. the framesize isn't known as the outer src rectangle dimensions aren't known
|
|
785 2. the mach64 needs aligned addresses so it can't work anyway
|
|
786 -> so we could shift the outer buffer to compensate that but that would mean
|
|
787 alignment problems for the code which writes into it
|
|
788 */
|
|
789
|
|
790 if(is_420)
|
|
791 {
|
|
792 config->offset.y= 0;
|
|
793 config->offset.u= (pitch*src_h + 15)&~15;
|
|
794 config->offset.v= (config->offset.u + (pitch*src_h>>2) + 15)&~15;
|
|
795
|
|
796 if(besr.fourcc == IMGFMT_I420 || besr.fourcc == IMGFMT_IYUV)
|
|
797 {
|
|
798 uint32_t tmp;
|
|
799 tmp = config->offset.u;
|
|
800 config->offset.u = config->offset.v;
|
|
801 config->offset.v = tmp;
|
|
802 }
|
|
803
|
|
804 src_offset_y= config->offset.y + top*pitch + left;
|
|
805 src_offset_u= config->offset.u + (top*pitch>>2) + (left>>1);
|
|
806 src_offset_v= config->offset.v + (top*pitch>>2) + (left>>1);
|
|
807 }
|
|
808 else if(besr.fourcc == IMGFMT_YVU9)
|
|
809 {
|
|
810 config->offset.y= 0;
|
|
811 config->offset.u= (pitch*src_h + 15)&~15;
|
|
812 config->offset.v= (config->offset.u + (pitch*src_h>>4) + 15)&~15;
|
|
813
|
|
814 src_offset_y= config->offset.y + top*pitch + left;
|
|
815 src_offset_u= config->offset.u + (top*pitch>>4) + (left>>1);
|
|
816 src_offset_v= config->offset.v + (top*pitch>>4) + (left>>1);
|
|
817 }
|
|
818 else if(besr.fourcc == IMGFMT_BGR32)
|
|
819 {
|
|
820 config->offset.y = config->offset.u = config->offset.v = 0;
|
|
821 src_offset_y= src_offset_u= src_offset_v= top*pitch + (left << 2);
|
|
822 }
|
|
823 else
|
|
824 {
|
|
825 config->offset.y = config->offset.u = config->offset.v = 0;
|
|
826 src_offset_y= src_offset_u= src_offset_v= top*pitch + (left << 1);
|
|
827 }
|
|
828
|
|
829 num_mach64_buffers= config->num_frames;
|
|
830 for(i=0; i<config->num_frames; i++)
|
|
831 {
|
|
832 mach64_buffer_base[i][0]= (mach64_overlay_offset + config->offsets[i] + src_offset_y)&~15;
|
|
833 mach64_buffer_base[i][1]= (mach64_overlay_offset + config->offsets[i] + src_offset_u)&~15;
|
|
834 mach64_buffer_base[i][2]= (mach64_overlay_offset + config->offsets[i] + src_offset_v)&~15;
|
|
835 }
|
|
836
|
|
837 leftUV = (left >> 17) & 15;
|
|
838 left = (left >> 16) & 15;
|
|
839 besr.scale_inc = ( h_inc << 16 ) | v_inc;
|
|
840 y_pos = config->dest.y;
|
|
841 if(mach64_is_dbl_scan()) y_pos*=2;
|
|
842 else
|
|
843 if(mach64_is_interlace()) y_pos/=2;
|
|
844 besr.y_x_start = y_pos | (config->dest.x << 16);
|
|
845 y_pos =config->dest.y + dest_h;
|
|
846 if(mach64_is_dbl_scan()) y_pos*=2;
|
|
847 else
|
|
848 if(mach64_is_interlace()) y_pos/=2;
|
|
849 besr.y_x_end = y_pos | ((config->dest.x + dest_w) << 16);
|
|
850 besr.height_width = ((src_w - left)<<16) | (src_h - top);
|
|
851
|
|
852 return 0;
|
|
853 }
|
|
854
|
|
855 static int is_supported_fourcc(uint32_t fourcc)
|
|
856 {
|
|
857 switch(fourcc)
|
|
858 {
|
|
859 case IMGFMT_YV12:
|
|
860 case IMGFMT_I420:
|
|
861 case IMGFMT_YVU9:
|
|
862 case IMGFMT_IYUV:
|
|
863 return supports_planar;
|
|
864 case IMGFMT_YUY2:
|
|
865 case IMGFMT_UYVY:
|
|
866 case IMGFMT_BGR15:
|
|
867 case IMGFMT_BGR16:
|
|
868 case IMGFMT_BGR32:
|
|
869 return 1;
|
|
870 default:
|
|
871 return 0;
|
|
872 }
|
|
873 }
|
|
874
|
|
875 int vixQueryFourcc(vidix_fourcc_t *to)
|
|
876 {
|
|
877 if(is_supported_fourcc(to->fourcc))
|
|
878 {
|
|
879 to->depth = VID_DEPTH_1BPP | VID_DEPTH_2BPP |
|
|
880 VID_DEPTH_4BPP | VID_DEPTH_8BPP |
|
|
881 VID_DEPTH_12BPP| VID_DEPTH_15BPP|
|
|
882 VID_DEPTH_16BPP| VID_DEPTH_24BPP|
|
|
883 VID_DEPTH_32BPP;
|
|
884 to->flags = VID_CAP_EXPAND | VID_CAP_SHRINK | VID_CAP_COLORKEY;
|
|
885 return 0;
|
|
886 }
|
|
887 else to->depth = to->flags = 0;
|
|
888 return ENOSYS;
|
|
889 }
|
|
890
|
|
891 int vixConfigPlayback(vidix_playback_t *info)
|
|
892 {
|
|
893 if(!is_supported_fourcc(info->fourcc)) return ENOSYS;
|
|
894
|
|
895 mach64_compute_framesize(info);
|
|
896
|
|
897 if(info->num_frames>4) info->num_frames=4;
|
|
898 for(;info->num_frames>0; info->num_frames--)
|
|
899 {
|
|
900 mach64_overlay_offset = mach64_ram_size - info->frame_size*info->num_frames;
|
|
901 mach64_overlay_offset &= 0xffff0000;
|
|
902 if(mach64_overlay_offset>0) break;
|
|
903 }
|
|
904 if(info->num_frames <= 0) return EINVAL;
|
|
905
|
|
906 info->dga_addr = (char *)mach64_mem_base + mach64_overlay_offset;
|
|
907 mach64_vid_init_video(info);
|
|
908 return 0;
|
|
909 }
|
|
910
|
|
911 int vixPlaybackOn(void)
|
|
912 {
|
|
913 mach64_vid_display_video();
|
|
914 return 0;
|
|
915 }
|
|
916
|
|
917 int vixPlaybackOff(void)
|
|
918 {
|
|
919 mach64_vid_stop_video();
|
|
920 return 0;
|
|
921 }
|
|
922
|
|
923 int vixPlaybackFrameSelect(unsigned int frame)
|
|
924 {
|
|
925 uint32_t off[6];
|
|
926 int i;
|
|
927 int last_frame= (frame-1+num_mach64_buffers) % num_mach64_buffers;
|
|
928 //printf("Selecting frame %d\n", frame);
|
|
929 /*
|
|
930 buf3-5 always should point onto second buffer for better
|
|
931 deinterlacing and TV-in
|
|
932 */
|
|
933 if(num_mach64_buffers==1) return 0;
|
|
934
|
|
935 for(i=0; i<3; i++)
|
|
936 {
|
|
937 off[i] = mach64_buffer_base[frame][i];
|
|
938 off[i+3]= mach64_buffer_base[last_frame][i];
|
|
939 }
|
|
940
|
|
941 #if 0 // delay routine so the individual frames can be ssen better
|
|
942 {
|
|
943 volatile int i=0;
|
|
944 for(i=0; i<10000000; i++);
|
|
945 }
|
|
946 #endif
|
|
947
|
|
948 mach64_wait_for_idle();
|
|
949 mach64_fifo_wait(7);
|
|
950
|
|
951 OUTREG(SCALER_BUF0_OFFSET, off[0]);
|
|
952 OUTREG(SCALER_BUF0_OFFSET_U, off[1]);
|
|
953 OUTREG(SCALER_BUF0_OFFSET_V, off[2]);
|
|
954 OUTREG(SCALER_BUF1_OFFSET, off[3]);
|
|
955 OUTREG(SCALER_BUF1_OFFSET_U, off[4]);
|
|
956 OUTREG(SCALER_BUF1_OFFSET_V, off[5]);
|
|
957 if(num_mach64_buffers==2) mach64_wait_vsync(); //only wait for vsync if we do double buffering
|
|
958
|
|
959 if(__verbose > VERBOSE_LEVEL) mach64_vid_dump_regs();
|
|
960 return 0;
|
|
961 }
|
|
962
|
|
963 vidix_video_eq_t equal =
|
|
964 {
|
|
965 VEQ_CAP_BRIGHTNESS | VEQ_CAP_SATURATION
|
|
966 ,
|
|
967 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
968
|
|
969 int vixPlaybackGetEq( vidix_video_eq_t * eq)
|
|
970 {
|
|
971 memcpy(eq,&equal,sizeof(vidix_video_eq_t));
|
|
972 return 0;
|
|
973 }
|
|
974
|
|
975 int vixPlaybackSetEq( const vidix_video_eq_t * eq)
|
|
976 {
|
|
977 int br,sat;
|
|
978 if(eq->cap & VEQ_CAP_BRIGHTNESS) equal.brightness = eq->brightness;
|
|
979 if(eq->cap & VEQ_CAP_CONTRAST) equal.contrast = eq->contrast;
|
|
980 if(eq->cap & VEQ_CAP_SATURATION) equal.saturation = eq->saturation;
|
|
981 if(eq->cap & VEQ_CAP_HUE) equal.hue = eq->hue;
|
|
982 if(eq->cap & VEQ_CAP_RGB_INTENSITY)
|
|
983 {
|
|
984 equal.red_intensity = eq->red_intensity;
|
|
985 equal.green_intensity = eq->green_intensity;
|
|
986 equal.blue_intensity = eq->blue_intensity;
|
|
987 }
|
|
988 equal.flags = eq->flags;
|
|
989 br = equal.brightness * 64 / 1000;
|
|
990 if(br < -64) br = -64; if(br > 63) br = 63;
|
|
991 sat = (equal.saturation + 1000) * 16 / 1000;
|
|
992 if(sat < 0) sat = 0; if(sat > 31) sat = 31;
|
|
993 OUTREG(SCALER_COLOUR_CNTL, (br & 0x7f) | (sat << 8) | (sat << 16));
|
|
994 return 0;
|
|
995 }
|
|
996
|
|
997 int vixGetGrKeys(vidix_grkey_t *grkey)
|
|
998 {
|
|
999 memcpy(grkey, &mach64_grkey, sizeof(vidix_grkey_t));
|
|
1000 return(0);
|
|
1001 }
|
|
1002
|
|
1003 int vixSetGrKeys(const vidix_grkey_t *grkey)
|
|
1004 {
|
|
1005 memcpy(&mach64_grkey, grkey, sizeof(vidix_grkey_t));
|
|
1006
|
|
1007 if(mach64_grkey.ckey.op == CKEY_TRUE)
|
|
1008 {
|
|
1009 besr.ckey_on=1;
|
|
1010
|
|
1011 switch(mach64_vid_get_dbpp())
|
|
1012 {
|
|
1013 case 15:
|
|
1014 besr.graphics_key_msk=0x7FFF;
|
|
1015 besr.graphics_key_clr=
|
|
1016 ((mach64_grkey.ckey.blue &0xF8)>>3)
|
|
1017 | ((mach64_grkey.ckey.green&0xF8)<<2)
|
|
1018 | ((mach64_grkey.ckey.red &0xF8)<<7);
|
|
1019 break;
|
|
1020 case 16:
|
|
1021 besr.graphics_key_msk=0xFFFF;
|
|
1022 besr.graphics_key_clr=
|
|
1023 ((mach64_grkey.ckey.blue &0xF8)>>3)
|
|
1024 | ((mach64_grkey.ckey.green&0xFC)<<3)
|
|
1025 | ((mach64_grkey.ckey.red &0xF8)<<8);
|
|
1026 //besr.graphics_key_clr=le2me_32(besr.graphics_key_clr);
|
|
1027 break;
|
|
1028 case 24:
|
|
1029 besr.graphics_key_msk=0xFFFFFF;
|
|
1030 besr.graphics_key_clr=
|
|
1031 ((mach64_grkey.ckey.blue &0xFF))
|
|
1032 | ((mach64_grkey.ckey.green&0xFF)<<8)
|
|
1033 | ((mach64_grkey.ckey.red &0xFF)<<16);
|
|
1034 break;
|
|
1035 case 32:
|
|
1036 besr.graphics_key_msk=0xFFFFFF;
|
|
1037 besr.graphics_key_clr=
|
|
1038 ((mach64_grkey.ckey.blue &0xFF))
|
|
1039 | ((mach64_grkey.ckey.green&0xFF)<<8)
|
|
1040 | ((mach64_grkey.ckey.red &0xFF)<<16);
|
|
1041 break;
|
|
1042 default:
|
|
1043 besr.ckey_on=0;
|
|
1044 besr.graphics_key_msk=0;
|
|
1045 besr.graphics_key_clr=0;
|
|
1046 }
|
|
1047 }
|
|
1048 else
|
|
1049 {
|
|
1050 besr.ckey_on=0;
|
|
1051 besr.graphics_key_msk=0;
|
|
1052 besr.graphics_key_clr=0;
|
|
1053 }
|
|
1054
|
|
1055 mach64_fifo_wait(4);
|
|
1056 OUTREG(OVERLAY_GRAPHICS_KEY_MSK, besr.graphics_key_msk);
|
|
1057 OUTREG(OVERLAY_GRAPHICS_KEY_CLR, besr.graphics_key_clr);
|
|
1058 // OUTREG(OVERLAY_VIDEO_KEY_MSK, 0);
|
|
1059 // OUTREG(OVERLAY_VIDEO_KEY_CLR, 0);
|
|
1060 if(besr.ckey_on)
|
|
1061 OUTREG(OVERLAY_KEY_CNTL,VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_EQ|CMP_MIX_AND);
|
|
1062 else
|
|
1063 OUTREG(OVERLAY_KEY_CNTL,VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND);
|
|
1064
|
|
1065 return(0);
|
|
1066 }
|