Subversion Repositories Kolibri OS

Rev

Rev 1029 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1029 serge 1
/*
2
 * Copyright 2007, 2008  Luc Verhaegen 
3
 * Copyright 2007, 2008  Matthias Hopf 
4
 * Copyright 2007, 2008  Egbert Eich   
5
 * Copyright 2007, 2008  Advanced Micro Devices, Inc.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the "Software"),
9
 * to deal in the Software without restriction, including without limitation
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
 * and/or sell copies of the Software, and to permit persons to whom the
12
 * Software is furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
21
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 */
25
#define _PARSE_EDID_
26
 
27
#include "common.h"
28
#include "rhd.h"
29
 
30
#include "edid.h"
31
 
32
#include "xf86DDC.h"
33
 
34
#include "rhd_connector.h"
35
#include "rhd_modes.h"
36
#include "rhd_monitor.h"
37
#ifdef ATOM_BIOS
38
# include "rhd_atombios.h"
39
#endif
40
 
41
/* From rhd_edid.c */
42
void RHDMonitorEDIDSet(struct rhdMonitor *Monitor, xf86MonPtr EDID);
43
 
44
 
45
/*
46
 *
47
 */
48
 
49
void
50
RHDMonitorPrint(struct rhdMonitor *Monitor)
51
{
52
    int i;
53
 
54
    xf86Msg(X_NONE, "    Bandwidth: %dMHz\n", Monitor->Bandwidth / 1000);
55
    xf86Msg(X_NONE, "    Horizontal timing:\n");
56
    for (i = 0; i < Monitor->numHSync; i++)
57
	xf86Msg(X_NONE, "        %3.1f - %3.1fkHz\n",  Monitor->HSync[i].lo,
58
		Monitor->HSync[i].hi);
59
    xf86Msg(X_NONE, "    Vertical timing:\n");
60
    for (i = 0; i < Monitor->numVRefresh; i++)
61
	xf86Msg(X_NONE, "        %3.1f - %3.1fHz\n",  Monitor->VRefresh[i].lo,
62
		Monitor->VRefresh[i].hi);
63
    xf86Msg(X_NONE, "    DPI: %dx%d\n", Monitor->xDpi, Monitor->yDpi);
64
    if (Monitor->ReducedAllowed)
65
	xf86Msg(X_NONE, "    Allows reduced blanking.\n");
66
    if (Monitor->UseFixedModes)
67
	xf86Msg(X_NONE, "    Uses Fixed Modes.\n");
68
 
69
    if (!Monitor->Modes)
70
	xf86Msg(X_NONE, "    No modes are provided.\n");
71
    else {
72
      DisplayModePtr Mode;
73
 
74
	xf86Msg(X_NONE, "    Attached modes:\n");
75
	for (Mode = Monitor->Modes; Mode; Mode = Mode->next) {
76
	    xf86Msg(X_NONE, "        ");
77
        RHDPrintModeline(Mode);
78
      }
79
    }
80
}
81
 
82
 
83
#if 0
84
 
85
/*
86
 *
87
 */
88
static struct rhdMonitor *
89
rhdMonitorFromConfig(int scrnIndex, MonPtr Config)
90
{
91
    struct rhdMonitor *Monitor;
92
    DisplayModePtr Mode;
93
    int i;
94
 
95
    Monitor = xnfcalloc(sizeof(struct rhdMonitor), 1);
96
 
97
    Monitor->Name = xnfstrdup(Config->id);
98
    Monitor->scrnIndex = scrnIndex;
99
 
100
    if (Config->nHsync) {
101
        Monitor->numHSync = Config->nHsync;
102
        for (i = 0; i < Config->nHsync; i++) {
103
            Monitor->HSync[i].lo = Config->hsync[i].lo;
104
            Monitor->HSync[i].hi = Config->hsync[i].hi;
105
        }
106
    } else if (!Monitor->numHSync) {
107
        Monitor->numHSync = 3;
108
        Monitor->HSync[0].lo = 31.5;
109
        Monitor->HSync[0].hi = 31.5;
110
        Monitor->HSync[1].lo = 35.15;
111
        Monitor->HSync[1].hi = 35.15;
112
        Monitor->HSync[2].lo = 35.5;
113
        Monitor->HSync[2].hi = 35.5;
114
    }
115
 
116
    if (Config->nVrefresh) {
117
        Monitor->numVRefresh = Config->nVrefresh;
118
        for (i = 0; i < Config->nVrefresh; i++) {
119
            Monitor->VRefresh[i].lo = Config->vrefresh[i].lo;
120
            Monitor->VRefresh[i].hi = Config->vrefresh[i].hi;
121
        }
122
    } else if (!Monitor->numVRefresh) {
123
        Monitor->numVRefresh = 1;
124
        Monitor->VRefresh[0].lo = 50;
125
        Monitor->VRefresh[0].hi = 61;
126
    }
127
 
128
#ifdef MONREC_HAS_REDUCED
129
    if (Config->reducedblanking)
130
        Monitor->ReducedAllowed = TRUE;
131
#endif
132
 
133
#ifdef MONREC_HAS_BANDWIDTH
134
    if (Config->maxPixClock)
135
        Monitor->Bandwidth = Config->maxPixClock;
136
#endif
137
 
138
    for (Mode = Config->Modes; Mode; Mode = Mode->next)
139
	Monitor->Modes = RHDModesAdd(Monitor->Modes, RHDModeCopy(Mode));
140
 
141
    return Monitor;
142
}
143
#endif
144
 
145
/*
146
 *
147
 */
148
static struct rhdMonitor *
149
rhdMonitorFromDefault(RHDPtr rhdPtr)
150
{
151
    struct rhdMonitor *Monitor;
152
    DisplayModePtr Mode;
153
 
154
    Monitor = xnfcalloc(sizeof(struct rhdMonitor), 1);
155
 
156
    Monitor->Name = strdup("Default (SVGA)");
157
    Monitor->scrnIndex = rhdPtr->scrnIndex;
158
 
159
    /* timing for pathetic 14" svga monitors */
160
    Monitor->numHSync = 3;
161
    Monitor->HSync[0].lo = 31.5;
162
    Monitor->HSync[0].hi = 31.5;
163
    Monitor->HSync[1].lo = 35.15;
164
    Monitor->HSync[1].hi = 35.15;
165
    Monitor->HSync[2].lo = 35.5;
166
    Monitor->HSync[2].hi = 35.5;
167
 
168
    Monitor->numVRefresh = 1;
169
    Monitor->VRefresh[0].lo = 50;
170
    Monitor->VRefresh[0].hi = 61;
171
 
172
    return Monitor;
173
}
174
 
175
/*
176
 * This function tries to handle a configured monitor correctly.
177
 *
178
 * This either can be forced through the option, or is used when
179
 * no monitors are autodetected.
180
 */
181
void
182
RHDConfigMonitorSet(RHDPtr rhdPtr, Bool UseConfig)
183
{
184
  int i;
185
 
186
  for (i = 0; i < RHD_CONNECTORS_MAX; i++)
187
    if (rhdPtr->Connector[i] && rhdPtr->Connector[i]->Monitor)
188
	    break;
189
 
190
  if (i == RHD_CONNECTORS_MAX)
191
	xf86DrvMsg(scrnIndex, X_INFO, "No monitors autodetected; "
192
		   "attempting to work around this.\n");
193
 
194
  if (i == RHD_CONNECTORS_MAX)
195
  {
196
    rhdPtr->ConfigMonitor = rhdMonitorFromDefault(rhdPtr);
197
 
198
    DBG(dbgprintf("Created monitor from default: \"%s\":\n",
199
               rhdPtr->ConfigMonitor->Name));
200
 
201
    RHDMonitorPrint(rhdPtr->ConfigMonitor);
202
  };
203
}
204
 
205
/*
206
 * Make sure that we keep only a single mode in our list. This mode should
207
 * hopefully match our panel at native resolution correctly.
208
 */
209
static void
210
rhdPanelEDIDModesFilter(struct rhdMonitor *Monitor)
211
{
212
  DisplayModeRec *Best = Monitor->Modes, *Mode, *Temp;
213
 
214
  RHDFUNC(Monitor);
215
 
216
  if (!Best || !Best->next)
217
    return; /* don't bother */
218
 
219
    /* don't go for preferred, just take the biggest */
220
    for (Mode = Best->next; Mode; Mode = Mode->next) {
221
    if (((Best->HDisplay <= Mode->HDisplay) &&
222
         (Best->VDisplay < Mode->VDisplay)) ||
223
        ((Best->HDisplay < Mode->HDisplay) &&
224
         (Best->VDisplay <= Mode->VDisplay)))
225
      Best = Mode;
226
  }
227
 
228
    xf86DrvMsg(Monitor->scrnIndex, X_INFO, "Monitor \"%s\": Using Mode \"%s\""
229
	       " for native resolution.\n", Monitor->Name, Best->name);
230
 
231
    /* kill all other modes */
232
  Mode = Monitor->Modes;
233
    while (Mode) {
234
    Temp = Mode->next;
235
 
236
	if (Mode != Best) {
237
	    RHDDebug(Monitor->scrnIndex, "Monitor \"%s\": Discarding Mode \"%s\"\n",
238
		     Monitor->Name, Mode->name);
239
 
240
	    xfree(Mode->name);
241
	    xfree(Mode);
242
    }
243
    Mode = Temp;
244
  }
245
 
246
  Best->next = NULL;
247
  Best->prev = NULL;
248
  Best->type |= M_T_PREFERRED;
249
    Monitor->NativeMode = Best;
250
    Monitor->Modes = Monitor->NativeMode;
251
  Monitor->numHSync = 1;
252
  Monitor->HSync[0].lo = Best->HSync;
253
  Monitor->HSync[0].hi = Best->HSync;
254
  Monitor->numVRefresh = 1;
255
  Monitor->VRefresh[0].lo = Best->VRefresh;
256
  Monitor->VRefresh[0].hi = Best->VRefresh;
257
  Monitor->Bandwidth = Best->Clock;
258
}
259
 
260
/*
261
 *
262
 */
263
void
264
rhdMonitorPrintEDID(struct rhdMonitor *Monitor, xf86MonPtr EDID)
265
{
266
    xf86DrvMsg(EDID->scrnIndex, X_INFO, "EDID data for %s\n",
267
	       Monitor->Name);
268
  xf86PrintEDID(EDID);
269
}
270
 
271
/*
272
 * Panels are the most complicated case we need to handle here.
273
 * Information can come from several places, and we need to make sure
274
 * that we end up with only the native resolution in our table.
275
 */
276
static struct rhdMonitor *
277
rhdMonitorPanel(struct rhdConnector *Connector)
278
{
279
    struct rhdMonitor *Monitor;
280
    DisplayModeRec *Mode = NULL;
281
    xf86MonPtr EDID = NULL;
282
 
283
    RHDFUNC(Connector);
284
 
285
    /* has priority over AtomBIOS EDID */
286
    if (Connector->DDC)
287
    EDID = xf86DoEDID_DDC2(Connector->scrnIndex, Connector->DDC);
288
 
289
#ifdef ATOM_BIOS
290
    {
291
  RHDPtr rhdPtr = (RHDPtr)Connector->scrnIndex;
292
	AtomBiosArgRec data;
293
	AtomBiosResult Result;
294
 
295
  Result = RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
296
				 ATOMBIOS_GET_PANEL_MODE, &data);
297
	if (Result == ATOM_SUCCESS) {
298
	    Mode = data.mode;
299
	    Mode->type |= M_T_PREFERRED;
300
	}
301
	if (!EDID) {
302
      Result = RHDAtomBiosFunc(rhdPtr,rhdPtr->atomBIOS,
303
				     ATOMBIOS_GET_PANEL_EDID, &data);
304
	    if (Result == ATOM_SUCCESS)
305
    EDID = xf86InterpretEDID(rhdPtr, data.EDIDBlock);
306
	}
307
    }
308
#endif
309
 
310
    Monitor = xnfcalloc(sizeof(struct rhdMonitor), 1);
311
 
312
    Monitor->scrnIndex = Connector->scrnIndex;
313
    Monitor->EDID      = EDID;
314
 
315
    if (Mode) {
316
	Monitor->Name = xstrdup("LVDS Panel");
317
    Monitor->Modes = RHDModesAdd(Monitor->Modes, Mode);
318
	Monitor->NativeMode = Mode;
319
    Monitor->numHSync = 1;
320
    Monitor->HSync[0].lo = Mode->HSync;
321
    Monitor->HSync[0].hi = Mode->HSync;
322
    Monitor->numVRefresh = 1;
323
    Monitor->VRefresh[0].lo = Mode->VRefresh;
324
    Monitor->VRefresh[0].hi = Mode->VRefresh;
325
    Monitor->Bandwidth = Mode->SynthClock;
326
 
327
	/* Clueless atombios does give us a mode, but doesn't give us a
328
	 * DPI or a size. It is just perfect, right? */
329
	if (EDID) {
330
      if (EDID->features.hsize)
331
        Monitor->xDpi = (Mode->HDisplay * 2.54) / ((float) EDID->features.hsize) + 0.5;
332
      if (EDID->features.vsize)
333
        Monitor->yDpi = (Mode->VDisplay * 2.54) / ((float) EDID->features.vsize) + 0.5;
334
    }
335
    } else if (EDID) {
336
      RHDMonitorEDIDSet(Monitor, EDID);
337
      rhdPanelEDIDModesFilter(Monitor);
338
    } else {
339
	xf86DrvMsg(Connector->scrnIndex, X_ERROR,
340
		   "%s: No panel mode information found.\n", __func__);
341
	xfree(Monitor);
342
      return NULL;
343
    }
344
 
345
    /* panel should be driven at native resolution only. */
346
  Monitor->UseFixedModes = TRUE;
347
  Monitor->ReducedAllowed = TRUE;
348
 
349
  if (EDID)
350
    rhdMonitorPrintEDID(Monitor, EDID);
351
 
352
  return Monitor;
353
}
354
 
355
/*
356
 * rhdMonitorTV(): get TV modes. Currently we can only get this from AtomBIOS.
357
 */
358
static struct rhdMonitor *
359
rhdMonitorTV(struct rhdConnector *Connector)
360
{
361
    struct rhdMonitor *Monitor = NULL;
362
#ifdef ATOM_BIOS
363
    RHDPtr rhdPtr = RHDPTRI(Connector);
364
    DisplayModeRec *Mode = NULL;
365
    AtomBiosArgRec arg;
366
 
367
    RHDFUNC(Connector);
368
 
369
    arg.tvMode = rhdPtr->tvMode;
370
    if (RHDAtomBiosFunc(Connector->scrnIndex, rhdPtr->atomBIOS,
371
			ATOM_ANALOG_TV_MODE, &arg)
372
	!= ATOM_SUCCESS)
373
	return NULL;
374
 
375
    Mode = arg.mode;
376
    Mode->type |= M_T_PREFERRED;
377
 
378
    Monitor = xnfcalloc(sizeof(struct rhdMonitor), 1);
379
 
380
    Monitor->scrnIndex = Connector->scrnIndex;
381
    Monitor->EDID      = NULL;
382
 
383
    Monitor->Name      = xstrdup("TV");
384
    Monitor->Modes     = RHDModesAdd(Monitor->Modes, Mode);
385
    Monitor->NativeMode= Mode;
386
    Monitor->numHSync  = 1;
387
    Monitor->HSync[0].lo = Mode->HSync;
388
    Monitor->HSync[0].hi = Mode->HSync;
389
    Monitor->numVRefresh = 1;
390
    Monitor->VRefresh[0].lo = Mode->VRefresh;
391
    Monitor->VRefresh[0].hi = Mode->VRefresh;
392
    Monitor->Bandwidth = Mode->SynthClock;
393
 
394
    /* TV should be driven at native resolution only. */
395
    Monitor->UseFixedModes = TRUE;
396
    Monitor->ReducedAllowed = FALSE;
397
    /*
398
     *  hack: the TV encoder takes care of that.
399
     *  The mode that goes in isn't what comes out.
400
     */
401
    Mode->Flags &= ~(V_INTERLACE);
402
#endif
403
    return Monitor;
404
}
405
 
406
/*
407
 *
408
 */
409
struct rhdMonitor *
410
RHDMonitorInit(struct rhdConnector *Connector)
411
{
412
  struct rhdMonitor *Monitor = NULL;
413
 
414
  RHDFUNC(Connector);
415
 
416
  if (Connector->Type == RHD_CONNECTOR_PANEL)
417
    Monitor = rhdMonitorPanel(Connector);
418
    else if (Connector->Type == RHD_CONNECTOR_TV)
419
	Monitor = rhdMonitorTV(Connector);
420
    else if (Connector->DDC) {
421
    xf86MonPtr EDID = xf86DoEDID_DDC2(Connector->scrnIndex, Connector->DDC);
422
	if (EDID) {
423
	    Monitor = xnfcalloc(sizeof(struct rhdMonitor), 1);
424
        Monitor->scrnIndex = Connector->scrnIndex;
425
        Monitor->EDID   = EDID;
426
	    Monitor->NativeMode = NULL;
427
 
428
        RHDMonitorEDIDSet(Monitor, EDID);
429
        rhdMonitorPrintEDID(Monitor, EDID);
430
      }
431
    }
432
  return Monitor;
433
}
434
 
435
/*
436
 *
437
 */
438
void
439
RHDMonitorDestroy(struct rhdMonitor *Monitor)
440
{
441
    DisplayModePtr Mode, Next;
442
 
443
    for (Mode = Monitor->Modes; Mode;) {
444
	Next = Mode->next;
445
 
446
	xfree(Mode->name);
447
	xfree(Mode);
448
 
449
	Mode = Next;
450
    }
451
 
452
    if (Monitor->EDID)
453
	xfree(Monitor->EDID->rawData);
454
    xfree(Monitor->EDID);
455
    xfree(Monitor->Name);
456
    xfree(Monitor);
457
}
458
 
459
 
460
static unsigned char * VDIFRead(RHDPtr rhdPtr, I2CBusPtr pBus, int start);
461
 
462
#define RETRIES 4
463
 
464
static xf86VdifLimitsPtr* get_limits(CARD8 *c);
465
static xf86VdifGammaPtr* get_gamma(CARD8 *c);
466
static xf86VdifTimingPtr* get_timings(CARD8 *c);
467
 
468
xf86vdifPtr xf86InterpretVdif(CARD8 *c)
469
{
470
  xf86VdifPtr p = (xf86VdifPtr)c;
471
  xf86vdifPtr vdif;
472
  int i;
473
 
474
  unsigned long l = 0;
475
 
476
  if (c == NULL) return NULL;
477
  if (p->VDIFId[0] != 'V' || p->VDIFId[1] != 'D' || p->VDIFId[2] != 'I'
478
      || p->VDIFId[3] != 'F') return NULL;
479
  for ( i = 12; i < p->FileLength; i++)
480
    l += c[i];
481
  if ( l != p->Checksum) return NULL;
482
  vdif = malloc(sizeof(xf86vdif));
483
  vdif->vdif = p;
484
  vdif->limits = get_limits(c);
485
  vdif->timings = get_timings(c);
486
  vdif->gamma = get_gamma(c);
487
  vdif->strings = VDIF_STRING(((xf86VdifPtr)c),0);
488
  free(c);
489
  return vdif;
490
}
491
 
492
static xf86VdifLimitsPtr*
493
get_limits(CARD8 *c)
494
{
495
    int num, i, j;
496
    xf86VdifLimitsPtr *pp;
497
    xf86VdifLimitsPtr p;
498
 
499
    num = ((xf86VdifPtr)c)->NumberOperationalLimits;
500
    pp = malloc(sizeof(xf86VdifLimitsPtr) * (num+1));
501
    p = VDIF_OPERATIONAL_LIMITS(((xf86VdifPtr)c));
502
    j = 0;
503
    for ( i = 0; i
504
	if (p->Header.ScnTag == VDIF_OPERATIONAL_LIMITS_TAG)
505
	    pp[j++] = p;
506
	VDIF_NEXT_OPERATIONAL_LIMITS(p);
507
    }
508
    pp[j] = NULL;
509
    return pp;
510
}
511
 
512
static xf86VdifGammaPtr*
513
get_gamma(CARD8 *c)
514
{
515
    int num, i, j;
516
    xf86VdifGammaPtr *pp;
517
    xf86VdifGammaPtr p;
518
 
519
    num = ((xf86VdifPtr)c)->NumberOptions;
520
    pp = malloc(sizeof(xf86VdifGammaPtr) * (num+1));
521
    p = (xf86VdifGammaPtr)VDIF_OPTIONS(((xf86VdifPtr)c));
522
    j = 0;
523
    for ( i = 0; i
524
    {
525
	if (p->Header.ScnTag == VDIF_GAMMA_TABLE_TAG)
526
	    pp[j++] = p;
527
	VDIF_NEXT_OPTIONS(p);
528
    }
529
    pp[j] = NULL;
530
    return pp;
531
}
532
 
533
static xf86VdifTimingPtr*
534
get_timings(CARD8 *c)
535
{
536
    int num, num_limits;
537
    int i,j,k;
538
    xf86VdifLimitsPtr lp;
539
    xf86VdifTimingPtr *pp;
540
    xf86VdifTimingPtr p;
541
 
542
    num = ((xf86VdifPtr)c)->NumberOperationalLimits;
543
    lp = VDIF_OPERATIONAL_LIMITS(((xf86VdifPtr)c));
544
    num_limits = 0;
545
    for (i = 0; i < num; i++) {
546
	if (lp->Header.ScnTag == VDIF_OPERATIONAL_LIMITS_TAG)
547
	    num_limits += lp->NumberPreadjustedTimings;
548
	VDIF_NEXT_OPERATIONAL_LIMITS(lp);
549
    }
550
    pp = malloc(sizeof(xf86VdifTimingPtr)
551
				      * (num_limits+1));
552
    j = 0;
553
    lp = VDIF_OPERATIONAL_LIMITS(((xf86VdifPtr) c));
554
    for (i = 0; i < num; i++) {
555
	p = VDIF_PREADJUSTED_TIMING(lp);
556
	for (k = 0; k < lp->NumberPreadjustedTimings; k++) {
557
	    if (p->Header.ScnTag == VDIF_PREADJUSTED_TIMING_TAG)
558
		pp[j++] = p;
559
	    VDIF_NEXT_PREADJUSTED_TIMING(p);
560
	}
561
	VDIF_NEXT_OPERATIONAL_LIMITS(lp);
562
    }
563
    pp[j] = NULL;
564
    return pp;
565
}
566
 
567
int DDC_checksum(unsigned char *block, int len)
568
{
569
  int i, result = 0;
570
  int not_null = 0;
571
 
572
  for (i=0;i
573
  {
574
    not_null |= block[i];
575
    result += block[i];
576
  }
577
 
578
  if (result & 0xFF) DBG(dbgprintf("DDC checksum not correct\n"));
579
  if (!not_null) DBG(dbgprintf("DDC read all Null\n"));
580
 
581
    /* catch the trivial case where all bytes are 0 */
582
  if (!not_null) return 1;
583
 
584
  return (result&0xFF);
585
}
586
 
587
static unsigned char *
588
DDCRead_DDC2(RHDPtr rhdPtr, I2CBusPtr pBus, int start, int len)
589
{
590
  I2CDevPtr dev;
591
  unsigned char W_Buffer[2];
592
  int w_bytes;
593
  unsigned char *R_Buffer;
594
  int i;
595
 
596
  RHDFUNC(rhdPtr);
597
 
598
//    xf86LoaderReqSymLists(i2cSymbols, NULL);
599
 
600
  if (!(dev = xf86I2CFindDev(pBus, 0x00A0)))
601
  {
602
    dev = xf86CreateI2CDevRec();
603
    dev->DevName = "ddc2";
604
    dev->SlaveAddr = 0xA0;
605
    dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
606
    dev->StartTimeout = 550;
607
    dev->BitTimeout = 40;
608
    dev->ByteTimeout = 40;
609
    dev->AcknTimeout = 40;
610
 
611
    dev->pI2CBus = pBus;
612
    if (!xf86I2CDevInit(dev))
613
    {
614
      DBG(dbgprintf("No DDC2 device\n"));
615
	    return NULL;
616
    }
617
  }
618
  if (start < 0x100)
619
  {
620
    w_bytes = 1;
621
    W_Buffer[0] = start;
622
  }
623
  else
624
  {
625
    w_bytes = 2;
626
    W_Buffer[0] = start & 0xFF;
627
    W_Buffer[1] = (start & 0xFF00) >> 8;
628
  }
629
 
630
  R_Buffer = calloc(1,sizeof(unsigned char)* (len));
631
 
632
  if( !R_Buffer)
633
  {
634
    DBG(dbgprintf("R_Buffer = NULL\n"));
635
    return NULL;
636
  };
637
 
638
  for (i=0; i
639
  {
640
    if (xf86I2CWriteRead(dev, W_Buffer,w_bytes, R_Buffer,len))
641
    {
642
	    if (!DDC_checksum(R_Buffer,len))
643
        return R_Buffer;
644
      else
645
        DBG(dbgprintf("Checksum error in EDID block\n"));
646
    }
647
    else
648
      DBG(dbgprintf("Error reading EDID block\n"));
649
  }
650
  xf86DestroyI2CDevRec(dev,TRUE);
651
  free(R_Buffer);
652
  return NULL;
653
}
654
 
655
static unsigned char*
656
EDID1Read_DDC2(RHDPtr rhdPtr, I2CBusPtr pBus)
657
{
658
    return  DDCRead_DDC2(rhdPtr, pBus, 0, EDID1_LEN);
659
}
660
 
661
xf86MonPtr
662
xf86DoEDID_DDC2(RHDPtr rhdPtr, I2CBusPtr pBus)
663
{
664
  unsigned char *EDID_block = NULL;
665
  unsigned char *VDIF_Block = NULL;
666
  xf86MonPtr tmp = NULL;
667
 
668
  RHDFUNC(rhdPtr);
669
 
670
  EDID_block = EDID1Read_DDC2(rhdPtr,pBus);
671
 
672
  if (EDID_block)
673
  {
674
    tmp = xf86InterpretEDID(rhdPtr,EDID_block);
675
  }
676
  else
677
  {
678
    DBG(dbgprintf("No EDID block returned\n"));
679
    return NULL;
680
  }
681
 
682
  if (!tmp)
683
  {
684
    DBG(dbgprintf("Cannot interpret EDID block\n"));
685
    return tmp;
686
  }
687
  DBG(dbgprintf("Sections to follow: %d\n",tmp->no_sections));
688
 
689
  VDIF_Block =
690
  VDIFRead(rhdPtr, pBus, EDID1_LEN * (tmp->no_sections + 1));
691
  tmp->vdif = xf86InterpretVdif(VDIF_Block);
692
 
693
  return tmp;
694
}
695
 
696
static unsigned char*
697
VDIFRead(RHDPtr rhdPtr, I2CBusPtr pBus, int start)
698
{
699
  unsigned char * Buffer, *v_buffer = NULL, *v_bufferp = NULL;
700
  int i, num = 0;
701
 
702
    /* read VDIF length in 64 byte blocks */
703
  Buffer = DDCRead_DDC2(rhdPtr, pBus,start,64);
704
  if (Buffer == NULL)
705
    return NULL;
706
 
707
  DBG(dbgprintf("number of 64 bit blocks: %i\n",Buffer[0]));
708
 
709
  if ((num = Buffer[0]) > 0)
710
    v_buffer = v_bufferp = malloc(sizeof(unsigned char) * 64 * num);
711
 
712
  for (i = 0; i < num; i++)
713
  {
714
    Buffer = DDCRead_DDC2(rhdPtr, pBus,start,64);
715
    if (Buffer == NULL)
716
    {
717
      free (v_buffer);
718
	    return NULL;
719
    }
720
    memcpy(v_bufferp,Buffer,63); /* 64th byte is checksum */
721
    free(Buffer);
722
    v_bufferp += 63;
723
  }
724
  return v_buffer;
725
}
726
 
727
 
728
 
729
static void print_vendor(RHDPtr rhdPtr, struct vendor *);
730
static void print_version(RHDPtr rhdPtr, struct edid_version *);
731
static void print_display(RHDPtr rhdPtr, struct disp_features *,
732
			  struct edid_version *);
733
static void print_established_timings(RHDPtr rhdPtr,
734
				      struct established_timings *);
735
static void print_std_timings(RHDPtr rhdPtr, struct std_timings *);
736
static void print_detailed_monitor_section(RHDPtr rhdPtr,
737
					   struct detailed_monitor_section *);
738
static void print_detailed_timings(RHDPtr rhdPtr, struct detailed_timings *);
739
 
740
static void print_input_features(RHDPtr rhdPtr, struct disp_features *);
741
static void print_dpms_features(RHDPtr rhdPtr, struct disp_features *,
742
				struct edid_version *v);
743
static void print_whitepoint(RHDPtr rhdPtr, struct disp_features *);
744
static void print_number_sections(RHDPtr rhdPtr, int);
745
 
746
xf86MonPtr
747
xf86PrintEDID(xf86MonPtr m)
748
{
749
    if (!(m)) return NULL;
750
    print_vendor(m->rhdPtr,&m->vendor);
751
    print_version(m->rhdPtr,&m->ver);
752
    print_display(m->rhdPtr,&m->features, &m->ver);
753
    print_established_timings(m->rhdPtr,&m->timings1);
754
    print_std_timings(m->rhdPtr,m->timings2);
755
    print_detailed_monitor_section(m->rhdPtr,m->det_mon);
756
    print_number_sections(m->rhdPtr,m->no_sections);
757
 
758
    return m;
759
}
760
 
761
static void
762
print_vendor(RHDPtr rhdPtr, struct vendor *c)
763
{
764
  DBG(dbgprintf("Manufacturer: %s  Model: %x  Serial#: %u\n",
765
            (char *)&c->name, c->prod_id, c->serial));
766
  DBG(dbgprintf("Year: %u  Week: %u\n", c->year, c->week));
767
}
768
 
769
static void
770
print_version(RHDPtr rhdPtr, struct edid_version *c)
771
{
772
  DBG(dbgprintf("EDID Version: %u.%u\n",c->version,c->revision));
773
}
774
 
775
static void
776
print_display(RHDPtr rhdPtr, struct disp_features *disp,
777
	      struct edid_version *version)
778
{
779
    print_input_features(rhdPtr,disp);
780
    DBG(dbgprintf("Max H-Image Size [cm]: "));
781
    if (disp->hsize)
782
      DBG(dbgprintf("horiz.: %i  ",disp->hsize));
783
    else
784
      DBG(dbgprintf("H-Size may change,  "));
785
    if (disp->vsize)
786
      DBG(dbgprintf("vert.: %i\n",disp->vsize));
787
    else
788
      DBG(dbgprintf("V-Size may change\n"));
789
    DBG(dbgprintf("Gamma: %.2f\n", (double)disp->gamma));
790
    print_dpms_features(rhdPtr,disp,version);
791
    print_whitepoint(rhdPtr,disp);
792
}
793
 
794
static void
795
print_input_features(RHDPtr rhdPtr, struct disp_features *c)
796
{
797
    if (DIGITAL(c->input_type))
798
    {
799
      DBG(dbgprintf("Digital Display Input\n"));
800
      if (DFP1(c->input_dfp))
801
        DBG(dbgprintf("DFP 1.x compatible TMDS\n"));
802
    }
803
    else
804
    {
805
      DBG(dbgprintf("Analog Display Input,  "));
806
      DBG(dbgprintf("Input Voltage Level: "));
807
      switch (c->input_voltage)
808
      {
809
        case V070:
810
          DBG(dbgprintf("0.700/0.300 V\n"));
811
          break;
812
        case V071:
813
          DBG(dbgprintf("0.714/0.286 V\n"));
814
          break;
815
        case V100:
816
          DBG(dbgprintf("1.000/0.400 V\n"));
817
          break;
818
        case V007:
819
          DBG(dbgprintf("0.700/0.700 V\n"));
820
          break;
821
        default:
822
          DBG(dbgprintf("undefined\n"));
823
      }
824
      if (SIG_SETUP(c->input_setup))
825
        DBG(dbgprintf("Signal levels configurable\n"));
826
      DBG(dbgprintf("Sync:"));
827
      if (SEP_SYNC(c->input_sync))
828
        DBG(dbgprintf("  Separate"));
829
      if (COMP_SYNC(c->input_sync))
830
        DBG(dbgprintf("  Composite"));
831
      if (SYNC_O_GREEN(c->input_sync))
832
        DBG(dbgprintf("  SyncOnGreen"));
833
      if (SYNC_SERR(c->input_sync))
834
        DBG(dbgprintf("Serration on. "
835
         "V.Sync Pulse req. if CompSync or SyncOnGreen\n"));
836
      else
837
        DBG(dbgprintf("\n"));
838
    }
839
}
840
 
841
static void
842
print_dpms_features(RHDPtr rhdPtr, struct disp_features *c,
843
		    struct edid_version *v)
844
{
845
   if (c->dpms)
846
   {
847
     DBG(dbgprintf("DPMS capabilities:"));
848
     if (DPMS_STANDBY(c->dpms))
849
       DBG(dbgprintf(" StandBy"));
850
     if (DPMS_SUSPEND(c->dpms))
851
       DBG(dbgprintf(" Suspend"));
852
     if (DPMS_OFF(c->dpms))
853
       DBG(dbgprintf(" Off"));
854
   }
855
   else
856
     DBG(dbgprintf("No DPMS capabilities specified"));
857
   switch (c->display_type)
858
   {
859
     case DISP_MONO:
860
       DBG(dbgprintf("; Monochorome/GrayScale Display\n"));
861
       break;
862
     case DISP_RGB:
863
       DBG(dbgprintf("; RGB/Color Display\n"));
864
       break;
865
     case DISP_MULTCOLOR:
866
       DBG(dbgprintf("; Non RGB Multicolor Display\n"));
867
       break;
868
     default:
869
       DBG(dbgprintf("\n"));
870
       break;
871
   }
872
   if (STD_COLOR_SPACE(c->msc))
873
     DBG(dbgprintf("Default color space is primary color space\n"));
874
   if (PREFERRED_TIMING_MODE(c->msc))
875
     DBG(dbgprintf("First detailed timing is preferred mode\n"));
876
   else
877
     if (v->version == 1 && v->revision >= 3)
878
       DBG(dbgprintf("First detailed timing not preferred "
879
                 "mode in violation of standard!"));
880
   if (GFT_SUPPORTED(c->msc))
881
     DBG(dbgprintf("GTF timings supported\n"));
882
}
883
 
884
static void
885
print_whitepoint(RHDPtr rhdPtr, struct disp_features *disp)
886
{
887
    DBG(dbgprintf("redX: %.3f redY: %.3f   ",
888
         (double)disp->redx,(double)disp->redy));
889
    DBG(dbgprintf("greenX: %.3f greenY: %.3f\n",
890
         (double)disp->greenx,(double)disp->greeny));
891
    DBG(dbgprintf("blueX: %.3f blueY: %.3f   ",
892
         (double)disp->bluex,(double)disp->bluey));
893
    DBG(dbgprintf("whiteX: %.3f whiteY: %.3f\n",
894
         (double)disp->whitex,(double)disp->whitey));
895
}
896
 
897
static void
898
print_established_timings(RHDPtr rhdPtr, struct established_timings *t)
899
{
900
    unsigned char c;
901
 
902
    if (t->t1 || t->t2 || t->t_manu)
903
      DBG(dbgprintf("Supported VESA Video Modes:\n"));
904
    c=t->t1;
905
    if (c&0x80) DBG(dbgprintf("720x400@70Hz\n"));
906
    if (c&0x40) DBG(dbgprintf("720x400@88Hz\n"));
907
    if (c&0x20) DBG(dbgprintf("640x480@60Hz\n"));
908
    if (c&0x10) DBG(dbgprintf("640x480@67Hz\n"));
909
    if (c&0x08) DBG(dbgprintf("640x480@72Hz\n"));
910
    if (c&0x04) DBG(dbgprintf("640x480@75Hz\n"));
911
    if (c&0x02) DBG(dbgprintf("800x600@56Hz\n"));
912
    if (c&0x01) DBG(dbgprintf("800x600@60Hz\n"));
913
    c=t->t2;
914
    if (c&0x80) DBG(dbgprintf("800x600@72Hz\n"));
915
    if (c&0x40) DBG(dbgprintf("800x600@75Hz\n"));
916
    if (c&0x20) DBG(dbgprintf("832x624@75Hz\n"));
917
    if (c&0x10) DBG(dbgprintf("1024x768@87Hz (interlaced)\n"));
918
    if (c&0x08) DBG(dbgprintf("1024x768@60Hz\n"));
919
    if (c&0x04) DBG(dbgprintf("1024x768@70Hz\n"));
920
    if (c&0x02) DBG(dbgprintf("1024x768@75Hz\n"));
921
    if (c&0x01) DBG(dbgprintf("1280x1024@75Hz\n"));
922
    c=t->t_manu;
923
    if (c&0x80) DBG(dbgprintf("1152x870@75Hz\n"));
924
    DBG(dbgprintf("Manufacturer's mask: %X\n",c&0x7F));
925
}
926
 
927
static void
928
print_std_timings(RHDPtr rhdPtr, struct std_timings *t)
929
{
930
    int i;
931
    char done = 0;
932
    for (i=0;i
933
    {
934
      if (t[i].hsize > 256)   /* sanity check */
935
      {
936
        if (!done)
937
        {
938
          DBG(dbgprintf("Supported Future Video Modes:\n"));
939
          done = 1;
940
        }
941
        DBG(dbgprintf("#%d: hsize: %i  vsize %i  refresh: %i  vid: %i\n",
942
                      i, t[i].hsize, t[i].vsize, t[i].refresh, t[i].id));
943
      }
944
    }
945
}
946
 
947
static void
948
print_detailed_monitor_section(RHDPtr rhdPtr,
949
			       struct detailed_monitor_section *m)
950
{
951
  int i,j;
952
 
953
  for (i=0;i
954
  {
955
    switch (m[i].type)
956
    {
957
      case DT:
958
        print_detailed_timings(rhdPtr,&m[i].section.d_timings);
959
        break;
960
      case DS_SERIAL:
961
        DBG(dbgprintf("Serial No: %s\n",m[i].section.serial));
962
        break;
963
      case DS_ASCII_STR:
964
        DBG(dbgprintf(" %s\n",m[i].section.ascii_data));
965
        break;
966
      case DS_NAME:
967
        DBG(dbgprintf("Monitor name: %s\n",m[i].section.name));
968
        break;
969
      case DS_RANGES:
970
        DBG(dbgprintf("Ranges: V min: %i  V max: %i Hz, H min: %i  H max: %i kHz,",
971
                   m[i].section.ranges.min_v, m[i].section.ranges.max_v,
972
                   m[i].section.ranges.min_h, m[i].section.ranges.max_h));
973
        if (m[i].section.ranges.max_clock != 0)
974
          DBG(dbgprintf(" PixClock max %i MHz\n",m[i].section.ranges.max_clock));
975
        else
976
          DBG(dbgprintf("\n"));
977
        if (m[i].section.ranges.gtf_2nd_f > 0)
978
          DBG(dbgprintf(" 2nd GTF parameters: f: %i kHz "
979
                    "c: %i m: %i k %i j %i\n",
980
                    m[i].section.ranges.gtf_2nd_f,
981
                    m[i].section.ranges.gtf_2nd_c,
982
                    m[i].section.ranges.gtf_2nd_m,
983
                    m[i].section.ranges.gtf_2nd_k,
984
                    m[i].section.ranges.gtf_2nd_j));
985
          break;
986
      case DS_STD_TIMINGS:
987
        for (j = 0; j<5; j++)
988
          DBG(dbgprintf("#%i: hsize: %i  vsize %i  refresh: %i  "
989
                    "vid: %i\n",i,m[i].section.std_t[i].hsize,
990
                    m[i].section.std_t[j].vsize,m[i].section.std_t[j].refresh,
991
                    m[i].section.std_t[j].id));
992
          break;
993
      case DS_WHITE_P:
994
        for (j = 0; j<2; j++)
995
          if (m[i].section.wp[j].index != 0)
996
            DBG(dbgprintf("White point %i: whiteX: %f, whiteY: %f; gamma: %f\n",
997
                      m[i].section.wp[j].index,(double)m[i].section.wp[j].white_x,
998
                      (double)m[i].section.wp[j].white_y,
999
                      (double)m[i].section.wp[j].white_gamma));
1000
            break;
1001
      case DS_DUMMY:
1002
      default:
1003
        break;
1004
    }
1005
  }
1006
}
1007
 
1008
static void
1009
print_detailed_timings(RHDPtr rhdPtr, struct detailed_timings *t)
1010
{
1011
 
1012
    if (t->clock > 15000000)  /* sanity check */
1013
    {
1014
      DBG(dbgprintf("Supported additional Video Mode:\n"));
1015
      DBG(dbgprintf("clock: %.1f MHz   ",(double)t->clock/1000000.0));
1016
      DBG(dbgprintf("Image Size:  %i x %i mm\n",t->h_size,t->v_size));
1017
      DBG(dbgprintf("h_active: %i  h_sync: %i  h_sync_end %i h_blank_end %i ",
1018
                    t->h_active, t->h_sync_off + t->h_active,
1019
                    t->h_sync_off + t->h_sync_width + t->h_active,
1020
                    t->h_active + t->h_blanking));
1021
      DBG(dbgprintf("h_border: %i\n",t->h_border));
1022
      DBG(dbgprintf("v_active: %i  v_sync: %i  v_sync_end %i v_blanking: %i ",
1023
                    t->v_active, t->v_sync_off + t->v_active,
1024
                    t->v_sync_off + t->v_sync_width + t->v_active,
1025
                    t->v_active + t->v_blanking));
1026
      DBG(dbgprintf("v_border: %i\n",t->v_border));
1027
      if (IS_STEREO(t->stereo))
1028
      {
1029
        DBG(dbgprintf("Stereo: "));
1030
        if (IS_RIGHT_STEREO(t->stereo))
1031
        {
1032
          if (!t->stereo_1)
1033
            DBG(dbgprintf("right channel on sync\n"));
1034
          else
1035
            DBG(dbgprintf("left channel on sync\n"));
1036
        }
1037
        else
1038
          if (IS_LEFT_STEREO(t->stereo))
1039
          {
1040
            if (!t->stereo_1)
1041
              DBG(dbgprintf("right channel on even line\n"));
1042
            else
1043
              DBG(dbgprintf("left channel on evel line\n"));
1044
          }
1045
        if (IS_4WAY_STEREO(t->stereo))
1046
        {
1047
          if (!t->stereo_1)
1048
            DBG(dbgprintf("4-way interleaved\n"));
1049
          else
1050
            DBG(dbgprintf("side-by-side interleaved"));
1051
        }
1052
      }
1053
    }
1054
}
1055
 
1056
static void
1057
print_number_sections(RHDPtr rhdPtr, int num)
1058
{
1059
  if (num)
1060
    DBG(dbgprintf("Number of EDID sections to follow: %i\n",num));
1061
}
1062
 
1063
 
1064
 
1065
static void get_vendor_section(Uchar*, struct vendor *);
1066
static void get_version_section(Uchar*, struct edid_version *);
1067
static void get_display_section(Uchar*, struct disp_features *,
1068
				struct edid_version *);
1069
static void get_established_timing_section(Uchar*, struct established_timings *);
1070
static void get_std_timing_section(Uchar*, struct std_timings *,
1071
				   struct edid_version *);
1072
static void get_dt_md_section(Uchar *, struct edid_version *,
1073
			      struct detailed_monitor_section *det_mon);
1074
static void copy_string(Uchar *, Uchar *);
1075
static void get_dst_timing_section(Uchar *, struct std_timings *,
1076
				   struct edid_version *);
1077
static void get_monitor_ranges(Uchar *, struct monitor_ranges *);
1078
static void get_whitepoint_section(Uchar *, struct whitePoints *);
1079
static void get_detailed_timing_section(Uchar*, struct 	detailed_timings *);
1080
static Bool validate_version(RHDPtr rhdPtr, struct edid_version *);
1081
 
1082
 
1083
xf86MonPtr
1084
xf86InterpretEDID(int scrnIndex, Uchar *block)
1085
{
1086
    xf86MonPtr m;
1087
    RHDPtr rhdPtr = (RHDPtr)scrnIndex;
1088
 
1089
    if (!block) return NULL;
1090
    if (! (m = calloc(sizeof(xf86Monitor),1))) return NULL;
1091
    m->rhdPtr = rhdPtr;
1092
    m->rawData = block;
1093
 
1094
    get_vendor_section(SECTION(VENDOR_SECTION,block),&m->vendor);
1095
    get_version_section(SECTION(VERSION_SECTION,block),&m->ver);
1096
    if (!validate_version(rhdPtr, &m->ver)) goto error;
1097
    get_display_section(SECTION(DISPLAY_SECTION,block),&m->features,
1098
			&m->ver);
1099
    get_established_timing_section(SECTION(ESTABLISHED_TIMING_SECTION,block),
1100
				   &m->timings1);
1101
    get_std_timing_section(SECTION(STD_TIMING_SECTION,block),m->timings2,
1102
			   &m->ver);
1103
    get_dt_md_section(SECTION(DET_TIMING_SECTION,block),&m->ver, m->det_mon);
1104
    m->no_sections = (int)*(char *)SECTION(NO_EDID,block);
1105
 
1106
    return (m);
1107
 
1108
 error:
1109
    free(m);
1110
    return NULL;
1111
}
1112
 
1113
static void
1114
get_vendor_section(Uchar *c, struct vendor *r)
1115
{
1116
    r->name[0] = L1;
1117
    r->name[1] = L2;
1118
    r->name[2] = L3;
1119
    r->name[3] = '\0';
1120
 
1121
    r->prod_id = PROD_ID;
1122
    r->serial  = SERIAL_NO;
1123
    r->week    = WEEK;
1124
    r->year    = YEAR;
1125
}
1126
 
1127
static void
1128
get_version_section(Uchar *c, struct edid_version *r)
1129
{
1130
    r->version  = VERSION;
1131
    r->revision = REVISION;
1132
}
1133
 
1134
static void
1135
get_display_section(Uchar *c, struct disp_features *r,
1136
		    struct edid_version *v)
1137
{
1138
    r->input_type = INPUT_TYPE;
1139
    if (!DIGITAL(r->input_type))
1140
    {
1141
      r->input_voltage = INPUT_VOLTAGE;
1142
      r->input_setup = SETUP;
1143
      r->input_sync = SYNC;
1144
    }
1145
    else
1146
      if (v->version > 1 || v->revision > 2)
1147
        r->input_dfp = DFP;
1148
    r->hsize = HSIZE_MAX;
1149
    r->vsize = VSIZE_MAX;
1150
    r->gamma = GAMMA;
1151
    r->dpms =  DPMS;
1152
    r->display_type = DISPLAY_TYPE;
1153
    r->msc = MSC;
1154
    r->redx = REDX;
1155
    r->redy = REDY;
1156
    r->greenx = GREENX;
1157
    r->greeny = GREENY;
1158
    r->bluex = BLUEX;
1159
    r->bluey = BLUEY;
1160
    r->whitex = WHITEX;
1161
    r->whitey = WHITEY;
1162
}
1163
 
1164
static void
1165
get_established_timing_section(Uchar *c, struct established_timings *r)
1166
{
1167
    r->t1 = T1;
1168
    r->t2 = T2;
1169
    r->t_manu = T_MANU;
1170
}
1171
 
1172
static void
1173
get_std_timing_section(Uchar *c, struct std_timings *r,
1174
		       struct edid_version *v)
1175
{
1176
    int i;
1177
 
1178
    for (i=0;i
1179
    {
1180
      if (VALID_TIMING)
1181
      {
1182
        r[i].hsize = HSIZE1;
1183
        VSIZE1(r[i].vsize);
1184
        r[i].refresh = REFRESH_R;
1185
        r[i].id = STD_TIMING_ID;
1186
      }
1187
      else
1188
      {
1189
        r[i].hsize = r[i].vsize = r[i].refresh = r[i].id = 0;
1190
       }
1191
       NEXT_STD_TIMING;
1192
    }
1193
}
1194
 
1195
static void
1196
get_dt_md_section(Uchar *c, struct edid_version *ver,
1197
		  struct detailed_monitor_section *det_mon)
1198
{
1199
  int i;
1200
 
1201
  for (i=0;i
1202
    if (ver->version == 1 && ver->revision >= 1 && IS_MONITOR_DESC) {
1203
 
1204
      switch (MONITOR_DESC_TYPE) {
1205
      case SERIAL_NUMBER:
1206
	det_mon[i].type = DS_SERIAL;
1207
	copy_string(c,det_mon[i].section.serial);
1208
	break;
1209
      case ASCII_STR:
1210
	det_mon[i].type = DS_ASCII_STR;
1211
	copy_string(c,det_mon[i].section.ascii_data);
1212
	break;
1213
      case MONITOR_RANGES:
1214
	det_mon[i].type = DS_RANGES;
1215
	get_monitor_ranges(c,&det_mon[i].section.ranges);
1216
	break;
1217
      case MONITOR_NAME:
1218
	det_mon[i].type = DS_NAME;
1219
	copy_string(c,det_mon[i].section.name);
1220
	break;
1221
      case ADD_COLOR_POINT:
1222
	det_mon[i].type = DS_WHITE_P;
1223
	get_whitepoint_section(c,det_mon[i].section.wp);
1224
	break;
1225
      case ADD_STD_TIMINGS:
1226
	det_mon[i].type = DS_STD_TIMINGS;
1227
	get_dst_timing_section(c,det_mon[i].section.std_t, ver);
1228
	break;
1229
      case ADD_DUMMY:
1230
	det_mon[i].type = DS_DUMMY;
1231
        break;
1232
      }
1233
    } else {
1234
      det_mon[i].type = DT;
1235
      get_detailed_timing_section(c,&det_mon[i].section.d_timings);
1236
    }
1237
    NEXT_DT_MD_SECTION;
1238
  }
1239
}
1240
 
1241
static void
1242
copy_string(Uchar *c, Uchar *s)
1243
{
1244
  int i;
1245
  c = c + 5;
1246
  for (i = 0; (i < 13 && *c != 0x0A); i++)
1247
    *(s++) = *(c++);
1248
  *s = 0;
1249
  while (i-- && (*--s == 0x20)) *s = 0;
1250
}
1251
 
1252
static void
1253
get_dst_timing_section(Uchar *c, struct std_timings *t,
1254
		       struct edid_version *v)
1255
{
1256
  int j;
1257
    c = c + 5;
1258
    for (j = 0; j < 5; j++) {
1259
	t[j].hsize = HSIZE1;
1260
	VSIZE1(t[j].vsize);
1261
	t[j].refresh = REFRESH_R;
1262
	t[j].id = STD_TIMING_ID;
1263
	NEXT_STD_TIMING;
1264
    }
1265
}
1266
 
1267
static void
1268
get_monitor_ranges(Uchar *c, struct monitor_ranges *r)
1269
{
1270
    r->min_v = MIN_V;
1271
    r->max_v = MAX_V;
1272
    r->min_h = MIN_H;
1273
    r->max_h = MAX_H;
1274
    r->max_clock = 0;
1275
    if(MAX_CLOCK != 0xff) /* is specified? */
1276
	r->max_clock = MAX_CLOCK * 10;
1277
    if (HAVE_2ND_GTF) {
1278
	r->gtf_2nd_f = F_2ND_GTF;
1279
	r->gtf_2nd_c = C_2ND_GTF;
1280
	r->gtf_2nd_m = M_2ND_GTF;
1281
	r->gtf_2nd_k = K_2ND_GTF;
1282
	r->gtf_2nd_j = J_2ND_GTF;
1283
    } else
1284
	r->gtf_2nd_f = 0;
1285
}
1286
 
1287
static void
1288
get_whitepoint_section(Uchar *c, struct whitePoints *wp)
1289
{
1290
    wp[1].white_x = WHITEX1;
1291
    wp[1].white_y = WHITEY1;
1292
    wp[2].white_x = WHITEX2;
1293
    wp[2].white_y = WHITEY2;
1294
    wp[1].index  = WHITE_INDEX1;
1295
    wp[2].index  = WHITE_INDEX2;
1296
    wp[1].white_gamma  = WHITE_GAMMA1;
1297
    wp[2].white_gamma  = WHITE_GAMMA2;
1298
}
1299
 
1300
static void
1301
get_detailed_timing_section(Uchar *c, struct detailed_timings *r)
1302
{
1303
  r->clock = PIXEL_CLOCK;
1304
  r->h_active = H_ACTIVE;
1305
  r->h_blanking = H_BLANK;
1306
  r->v_active = V_ACTIVE;
1307
  r->v_blanking = V_BLANK;
1308
  r->h_sync_off = H_SYNC_OFF;
1309
  r->h_sync_width = H_SYNC_WIDTH;
1310
  r->v_sync_off = V_SYNC_OFF;
1311
  r->v_sync_width = V_SYNC_WIDTH;
1312
  r->h_size = H_SIZE;
1313
  r->v_size = V_SIZE;
1314
  r->h_border = H_BORDER;
1315
  r->v_border = V_BORDER;
1316
  r->interlaced = INTERLACED;
1317
  r->stereo = STEREO;
1318
  r->stereo_1 = STEREO1;
1319
  r->sync = SYNC_T;
1320
  r->misc = MISC;
1321
}
1322
 
1323
 
1324
static Bool
1325
validate_version(RHDPtr rhdPtr, struct edid_version *r)
1326
{
1327
    if (r->version != 1)
1328
      return FALSE;
1329
    if (r->revision > 3)
1330
    {
1331
      DBG(dbgprintf("EDID Version 1.%d not yet supported\n",r->revision));
1332
      return FALSE;
1333
    }
1334
    return TRUE;
1335
}