2 * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 2.0 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright 1993 NeXT, Inc.
26 * All rights reserved.
33 * Various inline routines for video I/O
36 outi (int port
, int index
, int val
)
38 outw (port
, (val
<< 8) | index
);
42 outib (int port
, int index
, int val
)
49 ini (int port
, int index
)
52 return inb (port
+ 1);
56 rmwi (int port
, int index
, int clear
, int set
)
59 outb (port
+ 1, (inb (port
+ 1) & ~clear
) | set
);
67 int getVBEInfo( void * infoBlock
)
70 bb
.eax
.rr
= funcGetControllerInfo
;
71 bb
.es
= SEG( infoBlock
);
72 bb
.edi
.rr
= OFF( infoBlock
);
77 int getVBEModeInfo( int mode
, void * minfo_p
)
80 bb
.eax
.rr
= funcGetModeInfo
;
83 bb
.edi
.rr
= OFF(minfo_p
);
88 int getVBEDACFormat(unsigned char *format
)
91 bb
.eax
.rr
= funcGetSetPaletteFormat
;
92 bb
.ebx
.r
.l
= subfuncGet
;
98 int setVBEDACFormat(unsigned char format
)
101 bb
.eax
.rr
= funcGetSetPaletteFormat
;
102 bb
.ebx
.r
.l
= subfuncSet
;
109 * Default GTF parameter values.
111 #define kCellGranularity 8.0 // character cell granularity
112 #define kMinVSyncPlusBP 550.0 // min VSync + BP interval (us)
113 #define kMinFrontPorch 1.0 // minimum front porch in lines(V)/cells(H)
114 #define kVSyncLines 3.0 // width of VSync in lines
115 #define kHSyncWidth 8.0 // HSync as a percent of total line width
116 #define kC 30.0 // C = (C'-J) * (K/256) + J
117 #define kM 300.0 // M = K/256 * M'
119 static inline double Round( double f
)
121 asm volatile ("frndint" : "=t" (f
) : "0" (f
));
125 static inline double Sqrt( double f
)
127 asm volatile ("fsqrt" : "=t" (f
) : "0" (f
));
131 int generateCRTCTiming( unsigned short width
,
132 unsigned short height
,
133 unsigned long paramValue
,
135 VBECRTCInfoBlock
* timing
)
137 double h_period_est
, h_freq
, h_period
, h_total_pixels
, h_sync_pixels
;
138 double h_active_pixels
, h_ideal_duty_cycle
, h_blank_pixels
, pixel_freq
= 0;
139 double v_sync_plus_bp
= 0, v_total_lines
= 0, v_field_rate_est
, v_frame_rate
= 0;
140 const double h_pixels
= (double) width
;
141 const double v_lines
= (double) height
;
144 left_margin_pixels
= 0,
145 right_margin_pixels
= 0,
146 top_margin_lines
= 0,
147 bot_margin_lines
= 0,
151 // Total number of active pixels in image and both margins
152 h_active_pixels
= h_pixels
+ left_margin_pixels
+ right_margin_pixels
;
154 if (paramType
== kCRTCParamPixelClock
)
156 // Pixel clock provided in MHz
157 pixel_freq
= (double) paramValue
/ 1000000;
159 // Ideal horizontal period from the blanking duty cycle equation
160 h_period
= ((kC
- 100) + (Sqrt(((100 - kC
) * (100 - kC
)) + (0.4 * kM
*
161 (h_active_pixels
+ right_margin_pixels
+ left_margin_pixels
) /
162 pixel_freq
)))) / 2.0 / kM
* 1000;
164 else /* kCRTCParamRefreshRate */
166 double v_field_rate_in
= (double) paramValue
;
168 // Estimate the horizontal period
169 h_period_est
= ((1 / v_field_rate_in
) - kMinVSyncPlusBP
/ 1000000) /
170 (v_lines
+ (2 * top_margin_lines
) + kMinFrontPorch
+ interlace
) *
173 // Number of lines in Vsync + back porch
174 v_sync_plus_bp
= Round(kMinVSyncPlusBP
/ h_period_est
);
176 // Total number of lines in Vetical field period
177 v_total_lines
= v_lines
+ top_margin_lines
+ bot_margin_lines
+
178 v_sync_plus_bp
+ interlace
+ kMinFrontPorch
;
180 // Estimate the vertical field frequency
181 v_field_rate_est
= 1 / h_period_est
/ v_total_lines
* 1000000;
183 // Find the actual horizontal period
184 h_period
= h_period_est
/ (v_field_rate_in
/ v_field_rate_est
);
186 // Find the vertical frame rate (no interlace)
187 v_frame_rate
= 1 / h_period
/ v_total_lines
* 1000000;
190 // Ideal blanking duty cycle from the blanking duty cycle equation
191 h_ideal_duty_cycle
= kC
- (kM
* h_period
/ 1000);
193 // Number of pixels in the blanking time to the nearest double character cell
194 h_blank_pixels
= Round(h_active_pixels
* h_ideal_duty_cycle
/
195 (100 - h_ideal_duty_cycle
) / (2 * kCellGranularity
)) *
196 (2 * kCellGranularity
);
198 // Total number of horizontal pixels
199 h_total_pixels
= h_active_pixels
+ h_blank_pixels
;
201 if (paramType
== kCRTCParamPixelClock
)
203 // Horizontal frequency
204 h_freq
= pixel_freq
/ h_total_pixels
* 1000;
206 // Number of lines in V sync + back porch
207 v_sync_plus_bp
= Round(kMinVSyncPlusBP
* h_freq
/ 1000);
209 // Total number of lines in vertical field period
210 v_total_lines
= v_lines
+ top_margin_lines
+ bot_margin_lines
+
211 interlace
+ v_sync_plus_bp
+ kMinFrontPorch
;
213 // Vertical frame frequency
214 v_frame_rate
= Round(h_freq
/ v_total_lines
* 1000);
218 // Find pixel clock frequency
219 pixel_freq
= Round(h_total_pixels
/ h_period
);
222 h_sync_pixels
= Round(h_total_pixels
* kHSyncWidth
/ 100 / kCellGranularity
) *
225 timing
->HTotal
= h_total_pixels
;
226 timing
->HSyncStart
= h_active_pixels
+ (h_blank_pixels
/ 2) - h_sync_pixels
;
227 timing
->HSyncEnd
= timing
->HSyncStart
+ h_sync_pixels
;
228 timing
->VTotal
= v_total_lines
;
229 timing
->VSyncStart
= v_total_lines
- v_sync_plus_bp
;
230 timing
->VSyncEnd
= timing
->VSyncStart
+ kVSyncLines
;
231 timing
->Flags
= kCRTCNegativeHorizontalSync
;
232 timing
->PixelClock
= pixel_freq
* 1000000;
233 timing
->RefreshRate
= v_frame_rate
* 100;
238 int setVBEMode(unsigned short mode
, const VBECRTCInfoBlock
* timing
)
241 bb
.eax
.rr
= funcSetMode
;
245 bb
.edi
.rr
= OFF(timing
);
251 int setVBEPalette(void *palette
)
254 bb
.eax
.rr
= funcGetSetPaletteData
;
255 bb
.ebx
.r
.l
= subfuncSet
;
258 bb
.es
= SEG(palette
);
259 bb
.edi
.rr
= OFF(palette
);
264 int getVBEPalette(void *palette
)
267 bb
.eax
.rr
= funcGetSetPaletteData
;
268 bb
.ebx
.r
.l
= subfuncGet
;
271 bb
.es
= SEG(palette
);
272 bb
.edi
.rr
= OFF(palette
);
277 int getVBECurrentMode(unsigned short *mode
)
280 bb
.eax
.rr
= funcGetCurrentMode
;
286 int getVBEPixelClock(unsigned short mode
, unsigned long * pixelClock
)
289 bb
.eax
.rr
= funcGetSetPixelClock
;
291 bb
.ecx
.rx
= *pixelClock
;
294 *pixelClock
= bb
.ecx
.rx
;