/* * All modifications in this file to the original code are * (C) Copyright 1992, ..., 2004 the "DOSEMU-Development-Team". * * for details see file COPYING in the DOSEMU distribution */ /* * video/cirrus.c * $XConsortium: cir_driver.c,v 1.5 95/01/23 15:35:14 kaleb Exp $ * * $XFree86: xc/programs/Xserver/hw/xfree86/vga256/drivers/cirrus/cir_driver.c,v 3.17 1995/06/02 11:19:47 dawes Exp $ * * * This file contains support for VGA-cards with a Cirrus chip. * */ #define CIRRUS_C #include #include #include "emu.h" /* for v_printf only */ #include "port.h" #include "video.h" #include "vc.h" #include "vga.h" #include "cirrus.h" static int vgaIOBase = 0x3D0; static int cirrusChip; static int cirrusChipRevision; /*static int cirrusBusType;*/ static int cirrus_memsize = 0; static int cirrus_8514_base = BASE_8514_1; #if 0 static char cirrusUseBLTEngine = 0; static char cirrusUseMMIO = 0; static char cirrusMMIOFlag = 0; static unsigned char *cirrusMMIOBase = NULL; static char cirrusUseLinear = 0; static char cirrusFavourBLT = 0; static char cirrusAvoidImageBLT = 0; static int cirrusDRAMBandwidth; static int cirrusDRAMBandwidthLimit; static int cirrusReprogrammedMCLK = 0; #endif #define CLAVGA2_ID 0x06 #define CLGD5420_ID 0x22 #define CLGD5422_ID 0x23 #define CLGD5424_ID 0x25 #define CLGD5426_ID 0x24 #define CLGD5428_ID 0x26 #define CLGD5429_ID 0x27 #define CLGD6205_ID 0x02 #define CLGD6215_ID 0x22 #define CLGD6225_ID 0x32 #define CLGD6235_ID 0x06 #define CLGD5434_OLD_ID 0x29 #define CLGD5434_ID 0x2A #define CLGD5430_ID 0x28 #define CLGD5436_ID 0x2B #define Is_62x5(x) ((x) >= CLGD6205 && (x) <= CLGD6235) #define Has_HWCursor(x) (((x) >= CLGD5422 && (x) <= CLGD5429) || \ (x) == CLGD5430 || (x) == CLGD5434 || (x) == CLGD5436) /* Some information on the accelerated features of the 5426, derived from the Databook. [from svgalib] port index Addresses have 21 bits (2Mb of memory). 0x3ce, 0x28 bits 0-7 of the destination address 0x3ce, 0x29 bits 8-15 0x3ce, 0x2a bits 16-20 0x3ce, 0x2c bits 0-7 of the source address 0x3ce, 0x2d bits 8-15 0x3ce, 0x2e bits 16-20 Maximum pitch is 4095. 0x3ce, 0x24 bits 0-7 of the destination pitch (screen width) 0x3ce, 0x25 bits 8-11 0x3ce, 0x26 bits 0-7 of the source pitch (screen width) 0x3ce, 0x27 bits 8-11 Maximum width is 2047. 0x3ce, 0x20 bits 0-7 of the box width - 1 0x3ce, 0x21 bits 8-10 Maximum height is 1023. 0x3ce, 0x22 bits 0-7 of the box height - 1 0x3ce, 0x23 bits 8-9 0x3ce, 0x30 BLT mode bit 0: direction (0 = down, 1 = up) bit 1: destination bit 2: source (0 = video memory, 1 = system memory) bit 3: enable transparency compare bit 4: 16-bit color expand/transparency bit 6: 8x8 pattern copy bit 7: enable color expand 0x31 BLT status bit 0: busy bit 1: start operation (1)/suspend (0) bit 2: reset bit 3: set while blit busy/suspended 0x32 BLT raster operation 0x00 black 0x01 white 0x0d copy source 0xd0 copy inverted source 0x0b invert destination 0x05 logical AND 0x6d logical OR (paint) 0x59 XOR 0x34 BLT transparent color 0x35 high byte 0x3ce, 0x00 background color (for color expansion) 0x3ce, 0x01 foreground color 0x3ce, 0x10 high byte of background color for 16-bit pixels 0x3ce, 0x11 high byte of foreground color 0x3ce, 0x0b bit 1: enable BY8 addressing 0x3c4, 0x02 8-bit plane mask for BY8 (corresponds to 8 pixels) (write mode 1, 4, 5) 0x3c5, 0x05 bits 0-2: VGA write mode extended write mode 4: write up to 8 pixels in foreground color (BY8) extended write mode 5: write 8 pixels in foreground/ background color (BY8) This may also work in normal non-BY8 packed-pixel mode. When doing blits from system memory to video memory, pixel data can apparently be written to any video address in 16-bit words, with the each scanline padded to 4-byte alignment. This is handy because the chip handles line transitions and alignment automatically (and can do, for example, masking). The pattern copy requires an 8x8 pattern (64 pixels) at the source address in video memory, and fills a box with specified size and destination address with the pattern. This is in fact the way to do solid fills. mode pattern Color Expansion 8 bytes (monochrome bitmap) 8-bit pixels 64 bytes 16-bit pixels 128 bytes */ static inline void wrinx(const ioport_t port, const int index, const u_char value) { port_out(index, port); port_out(value, port+1); } static inline int rdinx(const ioport_t port, const int index) { port_out(index, port); return (port_in(port+1) & 0xff); } #define out_crt(i,v) wrinx(CRT_I,(i),(v)) #define in_crt(i) rdinx(CRT_I,(i)) /* * cirrusEnterLeave -- * enable/disable io-mapping */ static void cirrusEnterLeave(char enter) { static unsigned char temp; if (enter) { /* Are we Mono or Color? */ vgaIOBase = (port_in(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; port_out(0x06,0x3C4); port_out(0x12,0x3C5); /* unlock cirrus special */ /* Put the Vert. Retrace End Reg in temp */ port_out(0x11, vgaIOBase+4); temp = port_in(vgaIOBase + 5); /* Put it back with PR bit set to 0 */ /* This unprotects the 0-7 CRTC regs so */ /* they can be modified, i.e. we can set */ /* the timing. */ port_out(temp & 0x7F, vgaIOBase+5); } else { port_out(0x06,0x3C4); port_out(0x0f,0x3C5); /*relock cirrus special */ } } /* * cirrusProbe -- * check up whether a cirrus based board is installed */ static int cirrusProbe(void) { /* int cirrusClockNo; */ unsigned char lockreg,IdentVal; unsigned char id, rev, partstatus; unsigned char temp; unsigned char old; old = rdinx(0x3c4, 0x06); cirrusEnterLeave(1); /* Make the timing regs writable */ /* Kited the following from the Cirrus */ /* Databook */ /* If it's a Cirrus at all, we should be */ /* able to read back the lock register */ /* we wrote in cirrusEnterLeave() */ port_out(0x06,0x3C4); lockreg = port_in(0x3C5); /* Ok, if it's not 0x12, we're not a Cirrus542X or 62x5. */ if (lockreg != 0x12) { wrinx(0x3c4, 0x06, old); cirrusEnterLeave(0); return(0); } /* OK, it's a Cirrus. Now, what kind of */ /* Cirrus? We read in the ident reg, */ /* CRTC index 27 */ port_out(0x27, vgaIOBase+4); IdentVal = port_in(vgaIOBase+5); cirrusChip = -1; id = (IdentVal & 0xFc) >> 2; rev = (IdentVal & 0x03); port_out(0x25, vgaIOBase+4); partstatus = port_in(vgaIOBase+5); cirrusChipRevision = 0x00; switch( id ) { case CLGD5420_ID: cirrusChip = CLGD5420; /* 5420 or 5402 */ /* Check for CL-GD5420-75QC-B */ /* It has a Hidden-DAC register. */ port_out(0x00, 0x3C6); port_out(0xff, 0x3C6); port_in(0x3C6); port_in(0x3c6); port_in(0x3C6); port_in(0x3C6); if (port_in(0x3C6) != 0xFF) cirrusChipRevision = 0x01; /* 5420-75QC-B */ break; case CLGD5422_ID: cirrusChip = CLGD5422; break; case CLGD5424_ID: cirrusChip = CLGD5424; break; case CLGD5426_ID: cirrusChip = CLGD5426; break; case CLGD5428_ID: cirrusChip = CLGD5428; break; case CLGD5429_ID: if (partstatus >= 0x67) cirrusChipRevision = 0x01; /* >= Rev. B, fixes BLT */ cirrusChip = CLGD5429; break; /* * LCD driver chips... the +1 options are because * these chips have one more bit of chip rev level */ case CLGD6205_ID: case CLGD6205_ID + 1: cirrusChip = CLGD6205; break; case CLGD6225_ID: case CLGD6225_ID + 1: cirrusChip = CLGD6225; break; case CLGD6235_ID: case CLGD6235_ID + 1: cirrusChip = CLGD6235; break; /* 'Alpine' family. */ case CLGD5434_ID: if ((partstatus & 0xC0) == 0xC0) { /* * Better than Rev. ~D/E/F. * Handles 60 MHz MCLK and 135 MHz VCLK. */ cirrusChipRevision = 0x01; /* cirrusClockLimit[CLGD5434] = 135100; */ } else if (partstatus == 0x8E) /* Intermediate revision, supports 135 MHz VCLK. */ /* cirrusClockLimit[CLGD5434] = 135100; */ cirrusChip = CLGD5434; break; case CLGD5430_ID: cirrusChip = CLGD5430; break; case CLGD5436_ID: cirrusChip = CLGD5436; break; case CLGD5434_OLD_ID: default: v_printf("Unknown Cirrus chipset: type 0x%02x, rev %d\n", id, rev); if (id == CLGD5434_OLD_ID) v_printf("Old pre-production ID for clgd5434\n"); cirrusEnterLeave(0); return(0); break; } if (cirrusChip == CLGD5430 || cirrusChip == CLGD5434 || cirrusChip == CLGD5436) { /* Write sane value to Display Compression Control */ /* Register, which may be corrupted by pvga1 driver */ /* probe. */ port_out(0x0f, 0x3ce); temp = port_in(0x3cf) & 0xc0; port_out(temp, 0x3cf); } /* OK, we are a Cirrus */ v_printf("Cirrus chipset: type 0x%02x, rev %d\n", id, rev); #if 0 if (vgaBitsPerPixel == 16 && (Is_62x5(cirrusChip) || cirrusChip == CLGD5420)) { v_printf("%s %s: %s: Cirrus 62x5 and 5420 chipsets not supported " "in 16bpp mode\n", XCONFIG_PROBED, vga256InfoRec.name, vga256InfoRec.chipset); CIRRUS.ChipHas16bpp = 0; } #endif if (!cirrus_memsize) { if (Is_62x5(cirrusChip)) { /* * According to Ed Strauss at Cirrus, the 62x5 has 512k. * That's it. Period. */ cirrus_memsize = 512; } else if (HAVE543X()) { /* The scratch register method does not work on the 543x. */ /* Use the DRAM bandwidth bit and the DRAM bank switching */ /* bit to figure out the amount of memory. */ unsigned char SRF; cirrus_memsize = 512; port_out(0x0f, 0x3c4); SRF = port_in(0x3c5); if (SRF & 0x10) /* 32-bit DRAM bus. */ cirrus_memsize *= 2; if ((SRF & 0x18) == 0x18) /* 64-bit DRAM data bus width; assume 2MB. */ /* Also indicates 2MB memory on the 5430. */ cirrus_memsize *= 2; if (cirrusChip != CLGD5430 && (SRF & 0x80)) /* If DRAM bank switching is enabled, there */ /* must be twice as much memory installed. */ /* (4MB on the 5434) */ cirrus_memsize *= 2; } else { unsigned char memreg; /* Thanks to Brad Hackenson at Cirrus for */ /* this bit of undocumented black art....*/ port_out(0x0a, 0x3C4); memreg = port_in(0x3C5); switch( (memreg & 0x18) >> 3 ) { case 0: cirrus_memsize = 256; break; case 1: cirrus_memsize = 512; break; case 2: cirrus_memsize = 1024; break; case 3: cirrus_memsize = 2048; break; } if (cirrusChip >= CLGD5422 && cirrusChip <= CLGD5429 && cirrus_memsize < 512) { /* Invalid amount for 542x -- scratch register may */ /* not be set by some BIOSes. */ unsigned char SRF; cirrus_memsize = 512; port_out(0x0f, 0x3c4); SRF = port_in(0x3c5); if (SRF & 0x10) /* 32-bit DRAM bus. */ cirrus_memsize *= 2; if ((SRF & 0x18) == 0x18) /* 2MB memory on the 5426/8/9 (not sure). */ cirrus_memsize *= 2; } } } #if 0 if (vgaBitsPerPixel == 32 && ((cirrusChip != CLGD5434 && cirrusChip != CLGD5436) || vga256InfoRec.videoRam < 2048)) { ErrorF("%s %s: %s: Only clgd5434 with 2048K supports 32bpp\n", XCONFIG_PROBED, vga256InfoRec.name, vga256InfoRec.chipset); CIRRUS.ChipHas32bpp = 0; } /* * Banking granularity is 16k for the 5426, 5428 or 5429 * when allowing access to 2MB, and 4k otherwise */ if (vga256InfoRec.videoRam > 1024) { CIRRUS.ChipSetRead = cirrusSetRead2MB; CIRRUS.ChipSetWrite = cirrusSetWrite2MB; CIRRUS.ChipSetReadWrite = cirrusSetReadWrite2MB; cirrusBankShift = 8; } /* ... */ vga256InfoRec.bankedMono = 1; vga256InfoRec.maxClock = cirrusClockLimit[cirrusChip]; /* Initialize option flags allowed for this driver */ OFLG_SET(OPTION_NOACCEL, &CIRRUS.ChipOptionFlags); OFLG_SET(OPTION_PROBE_CLKS, &CIRRUS.ChipOptionFlags); OFLG_SET(OPTION_LINEAR, &CIRRUS.ChipOptionFlags); if ((cirrusChip >= CLGD5424 && cirrusChip <= CLGD5429) || HAVE543X()) { OFLG_SET(OPTION_SLOW_DRAM, &CIRRUS.ChipOptionFlags); OFLG_SET(OPTION_MED_DRAM, &CIRRUS.ChipOptionFlags); OFLG_SET(OPTION_FAST_DRAM, &CIRRUS.ChipOptionFlags); OFLG_SET(OPTION_FIFO_CONSERV, &CIRRUS.ChipOptionFlags); OFLG_SET(OPTION_FIFO_AGGRESSIVE, &CIRRUS.ChipOptionFlags); } if ((cirrusChip >= CLGD5426 && cirrusChip <= CLGD5429) || HAVE543X()) { OFLG_SET(OPTION_NO_2MB_BANKSEL, &CIRRUS.ChipOptionFlags); OFLG_SET(OPTION_NO_BITBLT, &CIRRUS.ChipOptionFlags); OFLG_SET(OPTION_FAVOUR_BITBLT, &CIRRUS.ChipOptionFlags); OFLG_SET(OPTION_NO_IMAGEBLT, &CIRRUS.ChipOptionFlags); } /* * The Hardware cursor, if the chip is capable, can be turned off using * the "sw_cursor" option. */ if (Has_HWCursor(cirrusChip)) { OFLG_SET(OPTION_SW_CURSOR, &CIRRUS.ChipOptionFlags); } #endif v_printf("Cirrus base address: 0x%x\n", cirrus_8514_base); v_printf("Cirrus memory size : %d kbyte\n", cirrus_memsize); config.gfxmemsize = cirrus_memsize; v_8514_base = cirrus_8514_base; return(1); } /* * cirrusRestore -- * restore a video mode */ void cirrus_restore_ext_regs(u_char xregs[], u_short xregs16[]) { /* 00 unsigned char GR9; Graphics Offset1 */ /* 01 unsigned char GRA; Graphics Offset2 */ /* 02 unsigned char GRB; Graphics Extensions Control */ /* 03 unsigned char SR7; Extended Sequencer */ /* 04 unsigned char SRE; VCLK Numerator */ /* 05 unsigned char SRF; DRAM Control */ /* 06 unsigned char SR10; Graphics Cursor X Position [7:0] */ /* 07 unsigned char SR10E; Graphics Cursor X Position [7:5] | 10000 */ /* 08 unsigned char SR11; Graphics Cursor Y Position [7:0] */ /* 09 unsigned char SR11E; Graphics Cursor Y Position [7:5] | 10001 */ /* 10 unsigned char SR12; Graphics Cursor Attributes Register */ /* 11 unsigned char SR13; Graphics Cursor Pattern Address */ /* 12 unsigned char SR1E; VCLK Denominator */ /* 13 unsigned char CR19; Interlace End */ /* 14 unsigned char CR1A; Miscellaneous Control */ /* 15 unsigned char CR1B; Extended Display Control */ /* 16 unsigned char CR1D; Overlay Extended Control Register */ /* 17 unsigned char HIDDENDAC; Hidden DAC register */ /* 18 DACcolourRec FOREGROUND; Hidden DAC cursor foreground colour */ /* 19 DACcolourRec BACKGROUND; Hidden DAC cursor background colour */ emu_video_retrace_off(); port_out_w(0x0009, 0x3CE); /* select bank 0 */ port_out_w(0x000a, 0x3CE); port_out(0x0f, 0x3C4); /* Restoring this registers avoids */ port_out(xregs[5], 0x3C5); /* textmode corruption on 2Mb cards. */ port_out(0x07, 0x3C4); /* This will disable linear addressing */ port_out(xregs[3], 0x3C5); /* if enabled. */ #if 0 if (vgaBitsPerPixel != 8) { /* * Write to DAC. This is very delicate, and the it can lock up * the bus if not done carefully. The access count for the DAC * register can be such that the first write accesses either the * VGA LUT pixel mask register or the Hidden DAC register. */ port_out(0x3c6, 0x00); /* Reset access count. */ port_out(0x3c6, 0xff); /* Write 0xff to pixel mask. */ port_in(0x3c6); port_in(0x3c6); port_in(0x3c6); port_in(0x3c6); port_out(0x3c6, restore->HIDDENDAC); } #endif port_out_w(0x0100, 0x3C4); /* disable timing sequencer */ port_out(0x09, 0x3CE); port_out(xregs[0], 0x3CF); port_out(0x0a, 0x3CE); port_out(xregs[1], 0x3CF); port_out(0x0b, 0x3CE); port_out(xregs[2], 0x3CF); if (HAVE543X()) { port_out(0x0f, 0x3ce); port_out(xregs[20], 0x3cf); } port_out(0x0e, 0x3C4); port_out(xregs[4], 0x3C5); if (Has_HWCursor(cirrusChip)) { /* Restore the hardware cursor */ port_out (0x13, 0x3C4); port_out (xregs[11], 0x3C5); port_out (xregs[7], 0x3C4); port_out (xregs[6], 0x3C5); port_out (xregs[9], 0x3C4); port_out (xregs[8], 0x3C5); port_out (0x12, 0x3C4); port_out (xregs[10], 0x3C5); } if ((cirrusChip >= CLGD5424 && cirrusChip <= CLGD5429) || HAVE543X()) { /* Restore the Performance Tuning Register on these chips only. */ port_out(0x16, 0x3C4); port_out(xregs[21], 0x3C5); } if (HAVE543X()) { port_out(0x17, 0x3c4); port_out(xregs[22], 0x3c5); } port_out(0x1e, 0x3C4); port_out(xregs[12], 0x3C5); if ((cirrusChip >= CLGD5424 && cirrusChip <= CLGD5429) || HAVE543X()) { port_out(0x1f, 0x3c4); /* MCLK register */ port_out(xregs[23], 0x3c5); } port_out(0x19, vgaIOBase+4); port_out(xregs[13], vgaIOBase+5); port_out(0x1a, vgaIOBase+4); port_out(xregs[14], vgaIOBase+5); port_out(0x1b, vgaIOBase+4); port_out(xregs[15], vgaIOBase+5); if (cirrusChip == CLGD5434 || cirrusChip == CLGD5436) { port_out(0x1d, vgaIOBase+4); port_out(xregs[16], vgaIOBase+5); } emu_video_retrace_on(); } /* * cirrusSave -- * save the current video mode */ void cirrus_save_ext_regs(u_char xregs[], u_short xregs16[]) { unsigned char temp1, temp2; emu_video_retrace_off(); vgaIOBase = (port_in(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; port_out(0x09, 0x3CE); temp1 = port_in(0x3CF); port_out(0x00, 0x3CF); /* select bank 0 */ port_out(0x0a, 0x3CE); temp2 = port_in(0x3CF); port_out(0x00, 0x3CF); /* select bank 0 */ /* 00 unsigned char GR9; Graphics Offset1 */ /* 01 unsigned char GRA; Graphics Offset2 */ /* 02 unsigned char GRB; Graphics Extensions Control */ /* 03 unsigned char SR7; Extended Sequencer */ /* 04 unsigned char SRE; VCLK Numerator */ /* 05 unsigned char SRF; DRAM Control */ /* 06 unsigned char SR10; Graphics Cursor X Position [7:0] */ /* 07 unsigned char SR10E; Graphics Cursor X Position [7:5] | 10000 */ /* 08 unsigned char SR11; Graphics Cursor Y Position [7:0] */ /* 09 unsigned char SR11E; Graphics Cursor Y Position [7:5] | 10001 */ /* 10 unsigned char SR12; Graphics Cursor Attributes Register */ /* 11 unsigned char SR13; Graphics Cursor Pattern Address */ /* 12 unsigned char SR1E; VCLK Denominator */ /* 13 unsigned char CR19; Interlace End */ /* 14 unsigned char CR1A; Miscellaneous Control */ /* 15 unsigned char CR1B; Extended Display Control */ /* 16 unsigned char CR1D; Overlay Extended Control Register */ /* 17 unsigned char HIDDENDAC; Hidden DAC register */ /* 18 DACcolourRec FOREGROUND; Hidden DAC cursor foreground colour */ /* 19 DACcolourRec BACKGROUND; Hidden DAC cursor background colour */ xregs[0] = temp1; xregs[1] = temp2; port_out(0x0b, 0x3CE); xregs[2] = port_in(0x3CF); if (HAVE543X()) { port_out(0x0f, 0x3ce); xregs[20] = port_in(0x3cf); } port_out(0x07, 0x3C4); xregs[3] = port_in(0x3C5); port_out(0x0e, 0x3C4); xregs[4] = port_in(0x3C5); port_out(0x0f, 0x3C4); xregs[5] = port_in(0x3C5); if (Has_HWCursor(cirrusChip)) { /* Hardware cursor */ port_out (0x10, 0x3C4); xregs[7] = port_in (0x3C4); xregs[6] = port_in (0x3C5); port_out (0x11, 0x3C4); xregs[9] = port_in (0x3C4); xregs[8] = port_in (0x3C5); port_out (0x12, 0x3C4); xregs[10] = port_in (0x3C5); port_out (0x13, 0x3C4); xregs[11] = port_in (0x3C5); } if ((cirrusChip >= CLGD5424 && cirrusChip <= CLGD5429) || HAVE543X()) { /* Save the Performance Tuning Register on these chips only. */ port_out(0x16, 0x3C4); xregs[21] = port_in(0x3C5); } if (HAVE543X()) { port_out(0x17, 0x3c4); xregs[22] = port_in(0x3c5); } port_out(0x1e, 0x3C4); xregs[12] = port_in(0x3C5); if ((cirrusChip >= CLGD5424 && cirrusChip <= CLGD5429) || HAVE543X()) { port_out(0x1f, 0x3c4); /* Save the MCLK register. */ xregs[23] = port_in(0x3c5); } port_out(0x19, vgaIOBase+4); xregs[13] = port_in(vgaIOBase+5); port_out(0x1a, vgaIOBase+4); xregs[14] = port_in(vgaIOBase+5); port_out(0x1b, vgaIOBase+4); xregs[15] = port_in(vgaIOBase+5); if (cirrusChip == CLGD5434 || cirrusChip == CLGD5436) { port_out(0x1d, vgaIOBase+4); xregs[16] = port_in(vgaIOBase+5); } #if 0 if (vgaBitsPerPixel != 8) { port_out(0x3c6, 0x00); /* Reset access count. */ port_out(0x3c6, 0xff); /* Write 0xff to pixel mask. */ port_in(0x3c6); port_in(0x3c6); port_in(0x3c6); port_in(0x3c6); save->HIDDENDAC = port_in(0x3c6); } #endif emu_video_retrace_on(); } void vga_init_cirrus(void) { if (cirrusProbe()) { save_ext_regs = cirrus_save_ext_regs; restore_ext_regs = cirrus_restore_ext_regs; #if 0 set_bank_read = cirrus_set_bank; set_bank_write = cirrus_set_bank; ext_video_port_in = cirrus_ext_video_port_in; ext_video_port_out = cirrus_ext_video_port_out; #endif } } #undef CIRRUS_C