2 /* interpret_edid.c: interpret a primary EDID block
4 * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
6 #ifdef HAVE_XORG_CONFIG_H
7 #include <xorg-config.h>
12 #include "xf86_OSproc.h"
17 static void get_vendor_section(Uchar
*, struct vendor
*);
18 static void get_version_section(Uchar
*, struct edid_version
*);
19 static void get_display_section(Uchar
*, struct disp_features
*,
20 struct edid_version
*);
21 static void get_established_timing_section(Uchar
*, struct established_timings
*);
22 static void get_std_timing_section(Uchar
*, struct std_timings
*,
23 struct edid_version
*);
24 static void get_dt_md_section(Uchar
*, struct edid_version
*,
25 struct detailed_monitor_section
*det_mon
);
26 static void copy_string(Uchar
*, Uchar
*);
27 static void get_dst_timing_section(Uchar
*, struct std_timings
*,
28 struct edid_version
*);
29 static void get_monitor_ranges(Uchar
*, struct monitor_ranges
*);
30 static void get_whitepoint_section(Uchar
*, struct whitePoints
*);
31 static void get_detailed_timing_section(Uchar
*, struct detailed_timings
*);
32 static Bool
validate_version(int scrnIndex
, struct edid_version
*);
35 handle_edid_quirks(xf86MonPtr m
)
38 struct detailed_timings
*preferred_timing
;
39 struct monitor_ranges
*ranges
;
42 * max_clock is only encoded in EDID in tens of MHz, so occasionally we
43 * find a monitor claiming a max of 160 with a mode requiring 162, or
44 * similar. Strictly we should refuse to round up too far, but let's
45 * see how well this works.
47 for (i
= 0; i
< 4; i
++) {
48 if (m
->det_mon
[i
].type
== DS_RANGES
) {
49 ranges
= &m
->det_mon
[i
].section
.ranges
;
50 for (j
= 0; j
< 4; j
++) {
51 if (m
->det_mon
[j
].type
== DT
) {
52 preferred_timing
= &m
->det_mon
[j
].section
.d_timings
;
53 if (!ranges
->max_clock
) continue; /* zero is legal */
54 if (ranges
->max_clock
* 1000000 < preferred_timing
->clock
) {
56 "EDID preferred timing clock %.2fMHz exceeds "
57 "claimed max %dMHz, fixing\n",
58 preferred_timing
->clock
/ 1.0e6
,
61 (preferred_timing
->clock
+999999)/1000000;
71 xf86InterpretEDID(int scrnIndex
, Uchar
*block
)
75 if (!block
) return NULL
;
76 if (! (m
= xnfcalloc(sizeof(xf86Monitor
),1))) return NULL
;
77 m
->scrnIndex
= scrnIndex
;
80 get_vendor_section(SECTION(VENDOR_SECTION
,block
),&m
->vendor
);
81 get_version_section(SECTION(VERSION_SECTION
,block
),&m
->ver
);
82 if (!validate_version(scrnIndex
, &m
->ver
)) goto error
;
83 get_display_section(SECTION(DISPLAY_SECTION
,block
),&m
->features
,
85 get_established_timing_section(SECTION(ESTABLISHED_TIMING_SECTION
,block
),
87 get_std_timing_section(SECTION(STD_TIMING_SECTION
,block
),m
->timings2
,
89 get_dt_md_section(SECTION(DET_TIMING_SECTION
,block
),&m
->ver
, m
->det_mon
);
90 m
->no_sections
= (int)*(char *)SECTION(NO_EDID
,block
);
92 handle_edid_quirks(m
);
102 get_vendor_section(Uchar
*c
, struct vendor
*r
)
109 r
->prod_id
= PROD_ID
;
110 r
->serial
= SERIAL_NO
;
116 get_version_section(Uchar
*c
, struct edid_version
*r
)
118 r
->version
= VERSION
;
119 r
->revision
= REVISION
;
123 get_display_section(Uchar
*c
, struct disp_features
*r
,
124 struct edid_version
*v
)
126 r
->input_type
= INPUT_TYPE
;
127 if (!DIGITAL(r
->input_type
)) {
128 r
->input_voltage
= INPUT_VOLTAGE
;
129 r
->input_setup
= SETUP
;
130 r
->input_sync
= SYNC
;
131 } else if (v
->version
> 1 || v
->revision
> 2)
133 r
->hsize
= HSIZE_MAX
;
134 r
->vsize
= VSIZE_MAX
;
137 r
->display_type
= DISPLAY_TYPE
;
150 get_established_timing_section(Uchar
*c
, struct established_timings
*r
)
158 get_std_timing_section(Uchar
*c
, struct std_timings
*r
,
159 struct edid_version
*v
)
163 for (i
=0;i
<STD_TIMINGS
;i
++){
167 r
[i
].refresh
= REFRESH_R
;
168 r
[i
].id
= STD_TIMING_ID
;
170 r
[i
].hsize
= r
[i
].vsize
= r
[i
].refresh
= r
[i
].id
= 0;
177 get_dt_md_section(Uchar
*c
, struct edid_version
*ver
,
178 struct detailed_monitor_section
*det_mon
)
182 for (i
=0;i
<DET_TIMINGS
;i
++) {
183 if (ver
->version
== 1 && ver
->revision
>= 1 && IS_MONITOR_DESC
) {
185 switch (MONITOR_DESC_TYPE
) {
187 det_mon
[i
].type
= DS_SERIAL
;
188 copy_string(c
,det_mon
[i
].section
.serial
);
191 det_mon
[i
].type
= DS_ASCII_STR
;
192 copy_string(c
,det_mon
[i
].section
.ascii_data
);
195 det_mon
[i
].type
= DS_RANGES
;
196 get_monitor_ranges(c
,&det_mon
[i
].section
.ranges
);
199 det_mon
[i
].type
= DS_NAME
;
200 copy_string(c
,det_mon
[i
].section
.name
);
202 case ADD_COLOR_POINT
:
203 det_mon
[i
].type
= DS_WHITE_P
;
204 get_whitepoint_section(c
,det_mon
[i
].section
.wp
);
206 case ADD_STD_TIMINGS
:
207 det_mon
[i
].type
= DS_STD_TIMINGS
;
208 get_dst_timing_section(c
,det_mon
[i
].section
.std_t
, ver
);
211 det_mon
[i
].type
= DS_DUMMY
;
214 det_mon
[i
].type
= DS_UNKOWN
;
218 det_mon
[i
].type
= DT
;
219 get_detailed_timing_section(c
,&det_mon
[i
].section
.d_timings
);
226 copy_string(Uchar
*c
, Uchar
*s
)
230 for (i
= 0; (i
< 13 && *c
!= 0x0A); i
++)
233 while (i
-- && (*--s
== 0x20)) *s
= 0;
237 get_dst_timing_section(Uchar
*c
, struct std_timings
*t
,
238 struct edid_version
*v
)
242 for (j
= 0; j
< 5; j
++) {
245 t
[j
].refresh
= REFRESH_R
;
246 t
[j
].id
= STD_TIMING_ID
;
252 get_monitor_ranges(Uchar
*c
, struct monitor_ranges
*r
)
259 if(MAX_CLOCK
!= 0xff) /* is specified? */
260 r
->max_clock
= MAX_CLOCK
* 10;
262 r
->gtf_2nd_f
= F_2ND_GTF
;
263 r
->gtf_2nd_c
= C_2ND_GTF
;
264 r
->gtf_2nd_m
= M_2ND_GTF
;
265 r
->gtf_2nd_k
= K_2ND_GTF
;
266 r
->gtf_2nd_j
= J_2ND_GTF
;
272 get_whitepoint_section(Uchar
*c
, struct whitePoints
*wp
)
274 wp
[1].white_x
= WHITEX1
;
275 wp
[1].white_y
= WHITEY1
;
276 wp
[2].white_x
= WHITEX2
;
277 wp
[2].white_y
= WHITEY2
;
278 wp
[1].index
= WHITE_INDEX1
;
279 wp
[2].index
= WHITE_INDEX2
;
280 wp
[1].white_gamma
= WHITE_GAMMA1
;
281 wp
[2].white_gamma
= WHITE_GAMMA2
;
285 get_detailed_timing_section(Uchar
*c
, struct detailed_timings
*r
)
287 r
->clock
= PIXEL_CLOCK
;
288 r
->h_active
= H_ACTIVE
;
289 r
->h_blanking
= H_BLANK
;
290 r
->v_active
= V_ACTIVE
;
291 r
->v_blanking
= V_BLANK
;
292 r
->h_sync_off
= H_SYNC_OFF
;
293 r
->h_sync_width
= H_SYNC_WIDTH
;
294 r
->v_sync_off
= V_SYNC_OFF
;
295 r
->v_sync_width
= V_SYNC_WIDTH
;
298 r
->h_border
= H_BORDER
;
299 r
->v_border
= V_BORDER
;
300 r
->interlaced
= INTERLACED
;
302 r
->stereo_1
= STEREO1
;
307 #define MAX_EDID_MINOR 3
310 validate_version(int scrnIndex
, struct edid_version
*r
)
315 if (r
->revision
> MAX_EDID_MINOR
)
316 xf86DrvMsg(scrnIndex
, X_WARNING
,
317 "Assuming version 1.%d is compatible with 1.%d\n",
318 r
->revision
, MAX_EDID_MINOR
);