|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 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 1.1 (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
12: * this file.
13: *
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
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /*
25: * Copyright (c) 1997 Apple Computer, Inc.
26: *
27: *
28: * HISTORY
29: *
30: * Simon Douglas 22 Oct 97
31: * - first checked in.
32: */
33:
34:
35:
36: #import <driverkit/ppc/IOMacOSTypes.h>
37: #import "IOMacOSVideo.h"
38: #import <driverkit/ppc/IOSmartDisplay.h>
39: #import <mach/mach_types.h>
40: #import <mach/message.h>
41: #import <bsd/dev/ppc/busses.h>
42: #import <bsd/dev/ppc/adb.h>
43:
44: @interface IOSmartDisplay:Object <IOSmartDisplayExported>
45: {
46: // used to query the framebuffer controller
47: id attachedFramebuffer;
48: UInt32 attachedRefCon;
49:
50: @private
51: void * priv;
52:
53: /* Reserved for future expansion. */
54: int _IOSmartDisplay_reserved[2];
55: }
56:
57: @end
58:
59: struct AVDeviceInfo
60: {
61: UInt8 wiggleLADAddr;
62: UInt32 numTimings;
63: const UInt32 * timings;
64: };
65: typedef struct AVDeviceInfo AVDeviceInfo;
66:
67: @interface IOSmartADBDisplay:IOSmartDisplay
68: {
69: @private
70: UInt8 adbAddr;
71: UInt8 waitAckValue;
72: SInt16 avDisplayID;
73: const AVDeviceInfo * deviceInfo;
74: }
75:
76: + probeADBForDisplays; // strictly temporary!
77:
78: @end
79:
80: struct EDID {
81: UInt8 header[8];
82: UInt8 vendorProduct[10];
83: UInt8 version;
84: UInt8 revision;
85: UInt8 displayParams[5];
86: UInt8 colorCharacteristics[10];
87: UInt8 establishedTimings[3];
88: UInt16 standardTimings[8];
89: UInt8 detailedTimings[72];
90: UInt8 extension;
91: UInt8 checksum;
92: };
93: typedef struct EDID EDID;
94:
95: @interface IOSmartDDCDisplay:IOSmartDisplay
96: {
97: @private
98: EDID edid1;
99:
100: }
101:
102: @end
103:
104:
105: static UInt32 smInited = 0; // why does +initialize get called twice?
106: static IOSmartADBDisplay * ADB2SmartDisplay[ ADB_DEVICE_COUNT ];
107:
108: @implementation IOSmartDisplay
109:
110: + findForConnection:framebuffer refCon:(UInt32)refCon
111: {
112: IOSmartADBDisplay * try;
113: IOSmartDisplay * found = nil;
114: UInt32 i;
115:
116: if( !smInited) {
117: smInited = YES;
118: [IOSmartADBDisplay probeADBForDisplays];
119: }
120:
121: if( [framebuffer conformsTo:@protocol( IOFBAppleSense)])
122: {
123: for (i = 0; (found == nil) && (i < ADB_DEVICE_COUNT); i++ ) {
124: try = ADB2SmartDisplay[ i ];
125: found = [try attach:framebuffer refCon:refCon];
126: }
127: }
128:
129: if( (found == nil) && [framebuffer conformsTo:@protocol( IOFBHighLevelDDCSense)])
130: {
131: found = [[[IOSmartDDCDisplay alloc] init] attach:framebuffer refCon:refCon];
132: }
133:
134: if( found == nil)
135: found = [[[IOSmartDisplay alloc] init] attach:framebuffer refCon:refCon];
136:
137: return( found);
138: }
139:
140: - attach:framebuffer refCon:(UInt32)refCon;
141: {
142: attachedFramebuffer = framebuffer;
143: attachedRefCon = refCon;
144: return( self);
145: }
146:
147: - detach
148: {
149: attachedFramebuffer = nil;
150: return( self);
151: }
152:
153: - (BOOL) attached
154: {
155: return( attachedFramebuffer != nil);
156: }
157:
158: - (IOReturn) getDisplayInfoForMode:(IOFBTimingInformation *)mode flags:(UInt32 *)flags
159: {
160: // Pass the existing flags (from framebuffer) thru
161: return( noErr);
162: }
163:
164: - (IOReturn)
165: getGammaTableByIndex:
166: (UInt32 *)channelCount dataCount:(UInt32 *)dataCount
167: dataWidth:(UInt32 *)dataWidth data:(void **)data
168: {
169: return( IO_R_UNSUPPORTED);
170: }
171: @end
172:
173: @implementation IOSmartDDCDisplay
174:
175: - attach:framebuffer refCon:(UInt32)refCon
176: {
177: IOReturn err;
178: IOByteCount length;
179:
180: do {
181: if( NO == [framebuffer hasDDCConnect:refCon])
182: continue;
183:
184: length = sizeof( EDID);
185: err = [framebuffer getDDCBlock:refCon blockNumber:1 blockType:kIOFBDDCBlockTypeEDID
186: options:0 data:(UInt8 *)&edid1 length:&length];
187: if( err || (length != sizeof( EDID)))
188: continue;
189:
190: kprintf("%s EDID Version %d, Revision %d\n", [framebuffer name],
191: edid1.version, edid1.revision );
192: if( edid1.version != 1)
193: continue;
194: #if 1
195: {
196: int i;
197:
198: kprintf("Est: ");
199: for( i=0; i<3; i++)
200: kprintf(" 0x%02x,", edid1.establishedTimings[i] );
201: kprintf("\nStd: " );
202: for( i=0; i<8; i++)
203: kprintf(" 0x%04x,", edid1.standardTimings[i] );
204: kprintf("\n");
205: }
206: #endif
207:
208: kprintf("IOSmartDDCDisplay attach on %s\n", [framebuffer name]);
209: return( [super attach:framebuffer refCon:refCon]);
210:
211: } while( false);
212:
213: return([self free]);
214: }
215:
216:
217: struct TimingToEDID {
218: UInt32 timingID;
219: UInt16 standardTiming;
220: UInt8 establishedBit;
221: UInt8 spare;
222: };
223: typedef struct TimingToEDID TimingToEDID;
224:
225: #define MAKESTD(h,a,r) ( (((h/8)-31)<<8) | (a<<6) | (r-60) )
226:
227: static const TimingToEDID timingToEDID[] = {
228: { timingApple_512x384_60hz, MAKESTD( 512,1,60), 0xff, 0 },
229: { timingApple_640x480_67hz, MAKESTD( 640,1,67), 0x04, 0 },
230: { timingVESA_640x480_60hz, MAKESTD( 640,1,60), 0x05, 0 },
231: { timingVESA_640x480_72hz , MAKESTD( 640,1,72), 0x03, 0 },
232: { timingVESA_640x480_75hz, MAKESTD( 640,1,75), 0x02, 0 },
233: { timingVESA_640x480_85hz, MAKESTD( 640,1,85), 0xff, 0 },
234: { timingApple_832x624_75hz, MAKESTD( 832,1,75), 0x0d, 0 },
235: { timingVESA_800x600_56hz, MAKESTD( 800,1,56), 0x01, 0 },
236: { timingVESA_800x600_60hz, MAKESTD( 800,1,60), 0x00, 0 },
237: { timingVESA_800x600_72hz, MAKESTD( 800,1,72), 0x0f, 0 },
238: { timingVESA_800x600_75hz, MAKESTD( 800,1,75), 0x0e, 0 },
239: { timingVESA_800x600_85hz, MAKESTD( 800,1,85), 0xff, 0 },
240: { timingVESA_1024x768_60hz, MAKESTD( 1024,1,60), 0x0b, 0 },
241: { timingVESA_1024x768_70hz, MAKESTD( 1024,1,70), 0x0a, 0 },
242: { timingVESA_1024x768_75hz, MAKESTD( 1024,1,75), 0x09, 0 },
243: { timingVESA_1024x768_85hz, MAKESTD( 1024,1,85), 0xff, 0 },
244: { timingApple_1024x768_75hz, MAKESTD( 1024,1,75), 0x09, 0 },
245: { timingApple_1152x870_75hz, MAKESTD( 0000,0,00), 0x17, 0 },
246: { timingVESA_1280x960_75hz, MAKESTD( 1280,1,75), 0xff, 0 },
247: { timingVESA_1280x1024_60hz, MAKESTD( 1280,2,60), 0xff, 0 },
248: { timingVESA_1280x1024_75hz, MAKESTD( 1280,2,75), 0x08, 0 },
249: { timingVESA_1280x1024_85hz, MAKESTD( 1280,2,85), 0xff, 0 },
250: { timingVESA_1600x1200_60hz, MAKESTD( 1600,1,60), 0xff, 0 },
251: { timingVESA_1600x1200_65hz, MAKESTD( 1600,1,65), 0xff, 0 },
252: { timingVESA_1600x1200_70hz, MAKESTD( 1600,1,70), 0xff, 0 },
253: { timingVESA_1600x1200_75hz, MAKESTD( 1600,1,75), 0xff, 0 },
254: { timingVESA_1600x1200_80hz, MAKESTD( 1600,1,80), 0xff, 0 }
255: };
256:
257: - (IOReturn) getDisplayInfoForMode:(IOFBTimingInformation *)mode flags:(UInt32 *)flags
258: {
259: const TimingToEDID * lookTiming;
260: UInt32 estBit, i;
261: enum { kSetFlags = (kDisplayModeValidFlag | kDisplayModeSafeFlag) };
262:
263: lookTiming = timingToEDID;
264: while( lookTiming < (timingToEDID + sizeof( timingToEDID) / sizeof( TimingToEDID))) {
265:
266: if( lookTiming->timingID == mode->standardTimingID) {
267: estBit = lookTiming->establishedBit;
268: if( estBit != 0xff) {
269: if( edid1.establishedTimings[ estBit / 8 ] & (1 << (estBit % 8)))
270: *flags = kSetFlags;
271: }
272: for( i = 0; i < 8; i++ ) {
273: if( lookTiming->standardTiming == edid1.standardTimings[ i ]) {
274: *flags = kSetFlags;
275: break;
276: }
277: }
278: break;
279: }
280: lookTiming++;
281: }
282:
283: // Pass the existing flags (from framebuffer) thru
284: return( noErr);
285: }
286:
287: @end
288:
289:
290: #define kOrgDisplayAddr 0x7 // Original display ADB address
291:
292: #define kTelecasterADBHandlerID 0x03
293: #define kSmartDisplayADBHandlerID 0xc0
294:
295: #define kADBReg0 0x0 // Device register zero
296: #define kADBReg1 0x1 // Device register one
297: #define kADBReg2 0x2 // Device register two
298: #define kADBReg3 0x3 // Device register three
299:
300: #define kReg2DataRdy 0xFD // data (to be read) ready
301: #define kReg2DataAck 0xFE // data (just written) OK
302:
303: #define kNoDevice -1
304: #define kTelecaster 0
305: #define kSousaSoundUnit 1
306: #define kHammerhead 2
307: #define kOrca 3
308: #define kWhaler 4
309: #define kWarriorEZ 5
310: #define kManta 6
311: #define kLastDeviceType kManta
312:
313:
314: #define kWiggleLADAddr 0x04 // 0x0f on Telecaster & Sousa?
315: #define kDisplayLocalRemoteLADAddr 0x02 // lad address used in SetDisplayRemoteMode
316: #define kAudioKeypadEnableLADAddr 0x7D
317:
318: #define kUnknown -1
319: #define kLocal 0
320: #define kRemote 1
321:
322: static const UInt32 orcaTimings[] = {
323: timingApple_640x480_67hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
324: timingVESA_640x480_75hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
325: timingVESA_640x480_85hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
326: timingApple_832x624_75hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
327: timingApple_1024x768_75hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
328: timingVESA_1024x768_85hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
329: timingApple_1152x870_75hz, kDisplayModeValidFlag | kDisplayModeSafeFlag | kDisplayModeDefaultFlag,
330: timingVESA_1280x960_75hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
331: timingVESA_1280x1024_75hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
332: timingVESA_1280x1024_85hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
333: timingVESA_1600x1200_60hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
334: timingVESA_1600x1200_65hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
335: timingVESA_1600x1200_70hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
336: timingVESA_1600x1200_75hz, kDisplayModeValidFlag | kDisplayModeSafeFlag
337: };
338:
339: static const UInt32 hammerheadTimings[] = {
340: timingApple_640x480_67hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
341: timingApple_832x624_75hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
342: timingApple_1024x768_75hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
343: timingApple_1152x870_75hz, kDisplayModeValidFlag | kDisplayModeSafeFlag | kDisplayModeDefaultFlag,
344: timingVESA_1280x960_75hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
345: timingVESA_1280x1024_75hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
346: timingVESA_1600x1200_60hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
347: };
348:
349: static const UInt32 mantaTimings[] = {
350: timingApple_640x480_67hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
351: timingApple_832x624_75hz, kDisplayModeValidFlag | kDisplayModeSafeFlag,
352: timingApple_1024x768_75hz, kDisplayModeValidFlag | kDisplayModeSafeFlag | kDisplayModeDefaultFlag,
353: };
354:
355:
356: static const AVDeviceInfo orcaInfo =
357: {
358: kWiggleLADAddr,
359: sizeof( orcaTimings) / sizeof( UInt32) / 2, orcaTimings
360: };
361:
362: static const AVDeviceInfo hammerheadInfo =
363: {
364: kWiggleLADAddr,
365: sizeof( hammerheadTimings) / sizeof( UInt32) / 2, hammerheadTimings
366: };
367:
368: static const AVDeviceInfo mantaInfo =
369: {
370: kWiggleLADAddr,
371: sizeof( mantaTimings) / sizeof( UInt32) / 2, mantaTimings
372: };
373:
374: static const AVDeviceInfo * deviceInfoTable[ kLastDeviceType + 1 ] =
375: {
376: 0, 0, &hammerheadInfo, &orcaInfo, &orcaInfo, &hammerheadInfo, &mantaInfo
377: };
378:
379:
380: @implementation IOSmartADBDisplay
381:
382: - (IOReturn) getDisplayInfoForMode:(IOFBTimingInformation *)mode flags:(UInt32 *)flags
383: {
384: IOReturn err = noErr;
385: UInt32 numTimings;
386: const UInt32 * timings = deviceInfo->timings;
387:
388: *flags = 0;
389: numTimings = deviceInfo->numTimings;
390: while( numTimings--) {
391: if( mode->standardTimingID == *(timings++)) {
392: *flags = *timings;
393: break;
394: }
395: timings++;
396: }
397: return( err);
398: }
399:
400: - (IOReturn) doConnect
401: {
402: IOReturn err;
403: UInt16 value;
404: UInt32 retries = 9;
405:
406: while( retries--) {
407: value = 0x6000 | (adbAddr << 8);
408: err = adb_writereg( adbAddr, kADBReg3, value);
409: if (err != ADB_RET_OK)
410: continue;
411: IOSleep(10);
412: /* IODelay(1000); */
413: err = adb_readreg( adbAddr, kADBReg3, &value);
414: if (err != ADB_RET_OK)
415: continue;
416:
417: if( (value & 0xF000) == 0x6000)
418: break;
419: else
420: err = ADB_RET_UNEXPECTED_RESULT;
421: }
422:
423: if( err)
424: kprintf( "SMDoConnect %d\n", err);
425:
426: return( err);
427: }
428:
429:
430: void SMADBHandler( int number, unsigned char *buffer, int count, void * ssp)
431: {
432: IOSmartADBDisplay * sm;
433:
434: sm = ADB2SmartDisplay[ number ];
435: if( sm && count)
436: if( *buffer == sm->waitAckValue)
437: sm->waitAckValue = 0;
438: }
439:
440: - (IOReturn) writeWithAcknowledge:(UInt8)regNum data:(UInt16)data ackValue:(UInt8)ackValue
441: {
442: IOReturn err;
443: enum { kTimeoutMS = 400 };
444: UInt32 timeout;
445:
446: waitAckValue = ackValue;
447:
448: err = adb_writereg(adbAddr, regNum, data);
449:
450: if( !err) {
451: timeout = kTimeoutMS / 10;
452: while( waitAckValue && timeout--)
453: IOSleep( 10 );
454:
455: if( waitAckValue)
456: err = -3;
457: }
458: waitAckValue = 0;
459: return( err);
460: }
461:
462:
463: - (IOReturn) setLogicalRegister:(UInt16)address data:(UInt16) data
464: {
465: IOReturn err = -1;
466: UInt32 reconnects = 3;
467:
468: while( err && reconnects--)
469: {
470: err = [self writeWithAcknowledge:kADBReg1 data:address ackValue:kReg2DataRdy];
471: if( err == noErr) {
472: err = [self writeWithAcknowledge:kADBReg2 data:data ackValue:kReg2DataAck];
473: }
474: if( err)
475: if( [self doConnect])
476: break;
477: }
478:
479: if( err)
480: kprintf( "SMSetLogicalRegister %x, %d\n", address, err);
481:
482: return( err);
483: }
484:
485:
486: - (IOReturn) getLogicalRegister:(UInt16)address data:(UInt16 *) data
487: {
488: IOReturn err = -1;
489: UInt32 reconnects = 3;
490: UInt16 value;
491:
492: while( err && reconnects--)
493: {
494: err = [self writeWithAcknowledge:kADBReg1 data:address ackValue:kReg2DataRdy];
495: if( err == noErr) {
496: err = adb_readreg( adbAddr, kADBReg2, &value);
497: *data = value & 0xff; // actually only 8 bit
498: }
499: if( err)
500: if( [self doConnect])
501: break;
502: }
503:
504: if( err)
505: kprintf( "SMGetLogicalRegister %x=%x, %d\n", address, *data, err);
506:
507: return( err);
508: }
509:
510: - setWiggle:(BOOL) active
511: {
512: IOReturn err;
513:
514: err = [self setLogicalRegister:deviceInfo->wiggleLADAddr data:(active ? 1 : 0)];
515: return( self);
516: }
517:
518: - initForADB:(UInt8)adbBusAddr
519: {
520: IOReturn err;
521: UInt16 data, deviceType;
522:
523: [super init];
524: adbAddr = adbBusAddr;
525:
526: ADB2SmartDisplay[ adbAddr ] = self;
527:
528: do {
529:
530: err = [self doConnect];
531: if( err)
532: continue;
533: adb_register_dev( adbAddr, SMADBHandler);
534: err = [self setLogicalRegister:0xff data:0xff];
535: if( err)
536: continue;
537: err = [self getLogicalRegister:0xff data:&data];
538: if( err)
539: continue;
540: err = [self getLogicalRegister:0xff data:&deviceType];
541: if( err)
542: continue;
543:
544: kprintf("Found ADBDisplay@%d, AVType %d\n", adbAddr, deviceType );
545:
546: if( (deviceType > kLastDeviceType)
547: || (deviceInfoTable[ deviceType ] == (const AVDeviceInfo *)0) ) {
548: err = -49;
549: continue;
550: }
551:
552: avDisplayID = deviceType;
553: deviceInfo = deviceInfoTable[ deviceType ];
554: [self setWiggle:NO];
555:
556: } while( false);
557:
558: if( err) {
559: return( [self free]);
560: }
561: return( self);
562: }
563:
564: - free
565: {
566:
567: // adb_register_dev( adbAddr, 0); // can't unregister!
568: ADB2SmartDisplay[ adbAddr ] = 0;
569: return( [super free]);
570: }
571:
572: //kprintf( "%s: sense %d, ext sense %d\n", [framebuffer name], info.primarySense, info.extendedSense);
573:
574: - attach:framebuffer refCon:(UInt32)refCon
575: {
576: IOReturn err;
577: IOFBAppleSenseInfo info;
578: id attached = nil;
579:
580: if( [self attached])
581: return( nil);
582:
583: do {
584: err = [framebuffer getAppleSense:refCon info:&info];
585: if( err)
586: continue;
587: if( (info.primarySense != kRSCSix) || (info.extendedSense != kESCSixStandard)) // straight-6
588: continue;
589:
590: [self setWiggle:YES];
591: err = [framebuffer getAppleSense:refCon info:&info];
592: [self setWiggle:NO];
593: if( err)
594: continue;
595: if( (info.primarySense != kRSCFour) || (info.extendedSense != kESCFourNTSC)) // straight-4
596: continue;
597:
598: kprintf("ADBDisplay@%d attached to %s\n", adbAddr, [framebuffer name]);
599: attached = [super attach:framebuffer refCon:refCon];
600:
601: } while( false);
602:
603: return( attached);
604: }
605:
606: + probeADBForDisplays
607: {
608: struct adb_device *devp;
609: int i;
610:
611: devp = adb_devices;
612: for (i = 0; i < ADB_DEVICE_COUNT; i++, devp++) {
613:
614: if ((devp->a_flags & ADB_FLAGS_PRESENT) == 0)
615: continue;
616: // no sense looking for telecaster since its fixed freq
617: // && (devp->a_dev_handler != kTelecasterADBHandlerID) )
618: if( (devp->a_dev_handler != kSmartDisplayADBHandlerID) )
619: continue;
620:
621: [[IOSmartADBDisplay alloc] initForADB:i];
622: }
623: return( self);
624: }
625:
626: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.