1 /* 2 * Copyright 2003, Thomas Kurschel. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 /*! 8 Part of DDC driver 9 10 EDID decoder. 11 12 The EDID information is tightly packed; this file takes care of 13 converting it to a usable structure. 14 */ 15 16 17 #include "edid.h" 18 19 #include <KernelExport.h> 20 21 #include <ctype.h> 22 #include <string.h> 23 24 25 // 26 // from hereon a bunch of decoders follow for each EDID section 27 // 28 29 static void 30 decode_vendor(edid1_vendor *vendor, const edid1_vendor_raw *raw) 31 { 32 vendor->manufacturer[0] = raw->c1 + '@'; 33 vendor->manufacturer[1] = ((raw->c2_high << 3) | raw->c2_low) + '@'; 34 vendor->manufacturer[2] = raw->c3 + '@'; 35 vendor->manufacturer[3] = 0; 36 vendor->prod_id = B_LENDIAN_TO_HOST_INT16(raw->prod_id); 37 vendor->serial = B_LENDIAN_TO_HOST_INT32(raw->serial); 38 vendor->week = raw->week; 39 vendor->year = raw->year + 1990; 40 } 41 42 43 static void 44 decode_version(edid1_version *version, const edid1_version_raw *raw) 45 { 46 version->version = raw->version; 47 version->revision = raw->revision; 48 } 49 50 51 static void 52 decode_display(edid1_display *display, const edid1_display_raw *raw) 53 { 54 // We need to dig into one of the union to get the first 55 // bit which should always align. then we can pick the right 56 // data structure to parse. 57 display->input_type = raw->analog_params.input_type; 58 59 if (display->input_type != 0) { 60 // digital 61 display->digital_params.bit_depth = 0; 62 if (raw->digital_params.bit_depth > 0 && raw->digital_params.bit_depth < 7) 63 display->digital_params.bit_depth = raw->digital_params.bit_depth * 2 + 4; 64 display->digital_params.interface = raw->digital_params.interface; 65 } else { 66 // analog 67 display->analog_params.input_voltage = raw->analog_params.input_voltage; 68 display->analog_params.setup = raw->analog_params.setup; 69 display->analog_params.sep_sync = raw->analog_params.sep_sync; 70 display->analog_params.comp_sync = raw->analog_params.comp_sync; 71 display->analog_params.sync_on_green = raw->analog_params.sync_on_green; 72 display->analog_params.sync_serr = raw->analog_params.sync_serr; 73 } 74 75 display->h_size = raw->h_size; 76 display->v_size = raw->v_size; 77 display->gamma = raw->gamma; 78 79 display->dpms_standby = raw->dpms_standby; 80 display->dpms_suspend = raw->dpms_suspend; 81 display->dpms_off = raw->dpms_off; 82 display->display_type = raw->display_type; 83 display->std_colour_space = raw->std_colour_space; 84 display->preferred_timing_mode = raw->preferred_timing_mode; 85 display->gtf_supported = raw->gtf_supported; 86 87 display->red_x = ((uint16)raw->red_x << 2) | raw->red_x_low; 88 display->red_y = ((uint16)raw->red_y << 2) | raw->red_y_low; 89 display->green_x = ((uint16)raw->green_x << 2) | raw->green_x_low; 90 display->green_y = ((uint16)raw->green_y << 2) | raw->green_y_low; 91 display->blue_x = ((uint16)raw->blue_x << 2) | raw->blue_x_low; 92 display->blue_y = ((uint16)raw->blue_y << 2) | raw->blue_y_low; 93 display->white_x = ((uint16)raw->white_x << 2) | raw->white_x_low; 94 display->white_y = ((uint16)raw->white_y << 2) | raw->white_y_low; 95 } 96 97 98 static void 99 decode_std_timing(edid1_std_timing *timing, const edid1_std_timing_raw *raw) 100 { 101 timing->h_size = (raw->timing.h_size + 31) * 8; 102 timing->ratio = raw->timing.ratio; 103 104 switch (raw->timing.ratio) { 105 case 0: 106 timing->v_size = timing->h_size; 107 break; 108 109 case 1: 110 timing->v_size = timing->h_size * 3 / 4; 111 break; 112 113 case 2: 114 timing->v_size = timing->h_size * 4 / 5; 115 break; 116 117 case 3: 118 timing->v_size = timing->h_size * 9 / 16; 119 break; 120 } 121 timing->refresh = raw->timing.refresh + 60; 122 timing->id = raw->id; 123 } 124 125 126 static void 127 decode_whitepoint(edid1_whitepoint *whitepoint, const edid1_whitepoint_raw *raw) 128 { 129 whitepoint[0].index = raw->index1; 130 whitepoint[0].white_x = ((uint16)raw->white_x1 << 2) | raw->white_x1_low; 131 whitepoint[0].white_y = ((uint16)raw->white_y1 << 2) | raw->white_y1_low; 132 whitepoint[0].gamma = raw->gamma1; 133 134 whitepoint[1].index = raw->index2; 135 whitepoint[1].white_x = ((uint16)raw->white_x2 << 2) | raw->white_x2_low; 136 whitepoint[1].white_y = ((uint16)raw->white_y2 << 2) | raw->white_y2_low; 137 whitepoint[1].gamma = raw->gamma2; 138 } 139 140 141 static void 142 decode_detailed_timing(edid1_detailed_timing *timing, 143 const edid1_detailed_timing_raw *raw) 144 { 145 timing->pixel_clock = raw->pixel_clock; 146 timing->h_active = ((uint16)raw->h_active_high << 8) | raw->h_active; 147 timing->h_blank = ((uint16)raw->h_blank_high << 8) | raw->h_blank; 148 timing->v_active = ((uint16)raw->v_active_high << 8) | raw->v_active; 149 timing->v_blank = ((uint16)raw->v_blank_high << 8) | raw->v_blank; 150 timing->h_sync_off = ((uint16)raw->h_sync_off_high << 8) | raw->h_sync_off; 151 timing->h_sync_width = ((uint16)raw->h_sync_width_high << 8) | raw->h_sync_width; 152 timing->v_sync_off = ((uint16)raw->v_sync_off_high << 4) | raw->v_sync_off; 153 timing->v_sync_width = ((uint16)raw->v_sync_width_high << 4) | raw->v_sync_width; 154 timing->h_size = ((uint16)raw->h_size_high << 8) | raw->h_size; 155 timing->v_size = ((uint16)raw->v_size_high << 8) | raw->v_size; 156 timing->h_border = raw->h_border; 157 timing->v_border = raw->v_border; 158 timing->interlaced = raw->interlaced; 159 timing->stereo = raw->stereo; 160 timing->sync = raw->sync; 161 timing->misc = raw->misc; 162 } 163 164 165 //! copy string until 0xa, removing trailing spaces 166 static void 167 copy_str(char *dest, const uint8 *src, size_t len) 168 { 169 uint32 i; 170 171 // copy until 0xa 172 for (i = 0; i < len; i++) { 173 if (*src == 0xa) 174 break; 175 if (!isgraph(*src) && *src != 0x20) 176 break; 177 *dest++ = *src++; 178 } 179 180 // remove trailing spaces 181 while (i-- > 0) { 182 if (*(dest - 1) != ' ') 183 break; 184 185 dest--; 186 } 187 188 *dest = '\0'; 189 } 190 191 192 static void 193 decode_detailed_monitor(edid1_detailed_monitor *monitor, 194 const edid1_detailed_monitor_raw *raw, bool enableExtra) 195 { 196 int i, j; 197 198 for (i = 0; i < EDID1_NUM_DETAILED_MONITOR_DESC; ++i, ++monitor, ++raw) { 199 200 // workaround: normally, all four bytes must be zero for detailed 201 // description, but at least some Formac monitors violate that: 202 // they have some additional info that start at zero_4(!), 203 // so even if only the first two _or_ the other two bytes are 204 // zero, we accept it as a monitor description block 205 if (enableExtra 206 && ((raw->extra.zero_0[0] == 0 && raw->extra.zero_0[1] == 0) 207 || (raw->extra.zero_0[2] == 0 && raw->extra.zero_4 == 0))) { 208 monitor->monitor_desc_type = raw->extra.monitor_desc_type; 209 210 switch (raw->extra.monitor_desc_type) { 211 case EDID1_SERIAL_NUMBER: 212 copy_str(monitor->data.serial_number, 213 raw->extra.data.serial_number, EDID1_EXTRA_STRING_LEN); 214 break; 215 216 case EDID1_ASCII_DATA: 217 copy_str(monitor->data.ascii_data, 218 raw->extra.data.ascii_data, EDID1_EXTRA_STRING_LEN); 219 break; 220 221 case EDID1_MONITOR_RANGES: 222 monitor->data.monitor_range = raw->extra.data.monitor_range; 223 break; 224 225 case EDID1_MONITOR_NAME: 226 copy_str(monitor->data.monitor_name, 227 raw->extra.data.monitor_name, EDID1_EXTRA_STRING_LEN); 228 break; 229 230 case EDID1_ADD_COLOUR_POINTER: 231 decode_whitepoint(monitor->data.whitepoint, 232 &raw->extra.data.whitepoint); 233 break; 234 235 case EDID1_ADD_STD_TIMING: 236 for (j = 0; j < EDID1_NUM_EXTRA_STD_TIMING; ++j) { 237 decode_std_timing(&monitor->data.std_timing[j], 238 &raw->extra.data.std_timing[j]); 239 } 240 break; 241 } 242 } else if (raw->detailed_timing.pixel_clock > 0) { 243 monitor->monitor_desc_type = EDID1_IS_DETAILED_TIMING; 244 decode_detailed_timing(&monitor->data.detailed_timing, 245 &raw->detailed_timing); 246 } 247 } 248 } 249 250 251 static void 252 decode_cta_block(edid1_info *edid, const cta_raw *raw) 253 { 254 unsigned int i, j; 255 256 edid->cta_block.tag = raw->tag; 257 edid->cta_block.revision = raw->revision; 258 edid->cta_block.num_native_detailed = raw->num_native_detailed; 259 edid->cta_block.ycbcr422_supported = raw->ycbcr422; 260 edid->cta_block.ycbcr444_supported = raw->ycbcr444; 261 edid->cta_block.audio_supported = raw->audio; 262 edid->cta_block.underscan = raw->underscan; 263 edid->cta_block.num_data_blocks = 0; 264 265 for (i = 4; i < raw->offset;) { 266 cta_data_block* block = (cta_data_block*)&((uint8*)raw)[i]; 267 memcpy(&edid->cta_block.data_blocks[edid->cta_block.num_data_blocks++], 268 block, block->length + 1); 269 i += block->length + 1; 270 } 271 272 for (i = raw->offset, j = 0; i + sizeof(edid1_detailed_timing_raw) - 1 < 128; 273 i += sizeof(edid1_detailed_timing_raw), j++) { 274 const edid1_detailed_timing_raw* timing = 275 (const edid1_detailed_timing_raw*)&((uint8*)raw)[i]; 276 decode_detailed_timing(&edid->cta_block.detailed_timing[j], timing); 277 } 278 } 279 280 281 static void 282 decode_displayid_block(edid1_info *edid, const displayid_raw *raw) 283 { 284 edid->displayid_block.tag = raw->tag; 285 edid->displayid_block.version = raw->version; 286 edid->displayid_block.extension_count = raw->extension_count; 287 } 288 289 290 // #pragma mark - 291 292 293 //! Main function to decode edid data 294 void 295 edid_decode(edid1_info *edid, const edid1_raw *raw) 296 { 297 int i; 298 memset(edid, 0, sizeof(edid1_info)); 299 300 decode_vendor(&edid->vendor, &raw->vendor); 301 decode_version(&edid->version, &raw->version); 302 decode_display(&edid->display, &raw->display); 303 304 edid->established_timing = raw->established_timing; 305 306 for (i = 0; i < EDID1_NUM_STD_TIMING; ++i) { 307 decode_std_timing(&edid->std_timing[i], &raw->std_timing[i]); 308 } 309 310 decode_detailed_monitor(edid->detailed_monitor, raw->detailed_monitor, 311 edid->version.version == 1 && edid->version.revision >= 1); 312 313 edid->num_sections = raw->num_sections; 314 315 for (i = 1; i < 1 + edid->num_sections; i++) { 316 cta_raw* cta = (cta_raw*)&raw[i]; 317 switch (cta->tag) { 318 case 0x2: 319 decode_cta_block(edid, cta); 320 break; 321 case 0x70: 322 decode_displayid_block(edid, (displayid_raw*)&raw[i]); 323 break; 324 default: 325 //printf("edid_decode unknown tag 0x%x\n", cta->tag); 326 break; 327 } 328 } 329 } 330