1 /* 2 * Copyright © 2019 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 * 23 * Authors: Simon Ser <simon.ser@intel.com> 24 */ 25 26 #ifndef IGT_EDID_H 27 #define IGT_EDID_H 28 29 #include "config.h" 30 31 #include <stdint.h> 32 33 #include <xf86drmMode.h> 34 35 #define EDID_BLOCK_SIZE 128 36 37 /** 38 * est_timings: set of established timings 39 */ 40 struct est_timings { 41 uint8_t t1; 42 uint8_t t2; 43 uint8_t mfg_rsvd; 44 } __attribute__((packed)); 45 46 #define STD_TIMINGS_LEN 8 47 48 enum std_timing_aspect { 49 STD_TIMING_16_10 = 0b00, 50 STD_TIMING_4_3 = 0b01, 51 STD_TIMING_5_4 = 0b10, 52 STD_TIMING_16_9 = 0b11, 53 }; 54 55 /** 56 * std_timing: a standard timing 57 */ 58 struct std_timing { 59 uint8_t hsize; 60 uint8_t vfreq_aspect; 61 } __attribute__((packed)); 62 63 #define DETAILED_TIMINGS_LEN 4 64 65 #define EDID_PT_INTERLACED (1 << 7) 66 #define EDID_PT_STEREO (1 << 5) 67 68 /* Sync type */ 69 #define EDID_PT_SYNC_ANALOG (0b00 << 3) 70 #define EDID_PT_SYNC_DIGITAL_COMPOSITE (0b10 << 3) 71 #define EDID_PT_SYNC_DIGITAL_SEPARATE (0b11 << 3) 72 73 /* Applies to EDID_PT_SYNC_DIGITAL_SEPARATE only */ 74 #define EDID_PT_VSYNC_POSITIVE (1 << 2) 75 #define EDID_PT_HSYNC_POSITIVE (1 << 1) 76 77 struct detailed_pixel_timing { 78 uint8_t hactive_lo; 79 uint8_t hblank_lo; 80 uint8_t hactive_hblank_hi; 81 uint8_t vactive_lo; 82 uint8_t vblank_lo; 83 uint8_t vactive_vblank_hi; 84 uint8_t hsync_offset_lo; 85 uint8_t hsync_pulse_width_lo; 86 uint8_t vsync_offset_pulse_width_lo; 87 uint8_t hsync_vsync_offset_pulse_width_hi; 88 uint8_t width_mm_lo; 89 uint8_t height_mm_lo; 90 uint8_t width_height_mm_hi; 91 uint8_t hborder; 92 uint8_t vborder; 93 uint8_t misc; /* EDID_PT_* */ 94 } __attribute__((packed)); 95 96 struct detailed_data_string { 97 char str[13]; 98 } __attribute__((packed)); 99 100 struct detailed_data_monitor_range { 101 uint8_t min_vfreq; 102 uint8_t max_vfreq; 103 uint8_t min_hfreq_khz; 104 uint8_t max_hfreq_khz; 105 uint8_t pixel_clock_mhz; /* need to multiply by 10 */ 106 uint8_t flags; 107 union { 108 char pad[7]; 109 struct { 110 uint8_t reserved; 111 uint8_t hfreq_start_khz; /* need to multiply by 2 */ 112 uint8_t c; /* need to divide by 2 */ 113 uint8_t m[2]; 114 uint8_t k; 115 uint8_t j; /* need to divide by 2 */ 116 } __attribute__((packed)) gtf2; 117 struct { 118 uint8_t version; 119 uint8_t data1; /* high 6 bits: extra clock resolution */ 120 uint8_t data2; /* plus low 2 of above: max hactive */ 121 uint8_t supported_aspects; 122 uint8_t flags; /* preferred aspect and blanking support */ 123 uint8_t supported_scalings; 124 uint8_t preferred_refresh; 125 } __attribute__((packed)) cvt; 126 } formula; 127 } __attribute__((packed)); 128 129 enum detailed_non_pixel_type { 130 EDID_DETAIL_EST_TIMINGS = 0xf7, 131 EDID_DETAIL_CVT_3BYTE = 0xf8, 132 EDID_DETAIL_COLOR_MGMT_DATA = 0xf9, 133 EDID_DETAIL_STD_MODES = 0xfa, 134 EDID_DETAIL_MONITOR_CPDATA = 0xfb, 135 EDID_DETAIL_MONITOR_NAME = 0xfc, 136 EDID_DETAIL_MONITOR_RANGE = 0xfd, 137 EDID_DETAIL_MONITOR_STRING = 0xfe, 138 EDID_DETAIL_MONITOR_SERIAL = 0xff, 139 }; 140 141 struct detailed_non_pixel { 142 uint8_t pad1; 143 uint8_t type; /* enum detailed_non_pixel_type */ 144 uint8_t pad2; 145 union { 146 struct detailed_data_string str; 147 struct detailed_data_monitor_range range; 148 struct detailed_data_string string; 149 /* TODO: other types */ 150 } data; 151 } __attribute__((packed)); 152 153 struct detailed_timing { 154 uint8_t pixel_clock[2]; /* need to multiply by 10 KHz, zero if not a pixel timing */ 155 union { 156 struct detailed_pixel_timing pixel_data; 157 struct detailed_non_pixel other_data; 158 } data; 159 } __attribute__((packed)); 160 161 enum cea_sad_format { 162 CEA_SAD_FORMAT_PCM = 1, 163 CEA_SAD_FORMAT_AC3 = 2, 164 CEA_SAD_FORMAT_MPEG1 = 3, /* Layers 1 & 2 */ 165 CEA_SAD_FORMAT_MP3 = 4, 166 CEA_SAD_FORMAT_MPEG2 = 5, 167 CEA_SAD_FORMAT_AAC = 6, 168 CEA_SAD_FORMAT_DTS = 7, 169 CEA_SAD_FORMAT_ATRAC = 8, 170 CEA_SAD_FORMAT_SACD = 9, /* One-bit audio */ 171 CEA_SAD_FORMAT_DD_PLUS = 10, 172 CEA_SAD_FORMAT_DTS_HD = 11, 173 CEA_SAD_FORMAT_DOLBY = 12, /* MLP/Dolby TrueHD */ 174 CEA_SAD_FORMAT_DST = 13, 175 CEA_SAD_FORMAT_WMA = 14, /* Microsoft WMA Pro */ 176 }; 177 178 enum cea_sad_sampling_rate { 179 CEA_SAD_SAMPLING_RATE_32KHZ = 1 << 0, 180 CEA_SAD_SAMPLING_RATE_44KHZ = 1 << 1, 181 CEA_SAD_SAMPLING_RATE_48KHZ = 1 << 2, 182 CEA_SAD_SAMPLING_RATE_88KHZ = 1 << 3, 183 CEA_SAD_SAMPLING_RATE_96KHZ = 1 << 4, 184 CEA_SAD_SAMPLING_RATE_176KHZ = 1 << 5, 185 CEA_SAD_SAMPLING_RATE_192KHZ = 1 << 6, 186 }; 187 188 /* for PCM only */ 189 enum cea_sad_pcm_sample_size { 190 CEA_SAD_SAMPLE_SIZE_16 = 1 << 0, 191 CEA_SAD_SAMPLE_SIZE_20 = 1 << 1, 192 CEA_SAD_SAMPLE_SIZE_24 = 1 << 2, 193 }; 194 195 /* Short Audio Descriptor */ 196 struct cea_sad { 197 uint8_t format_channels; 198 uint8_t sampling_rates; 199 uint8_t bitrate; 200 } __attribute__((packed)); 201 202 /* Indicates that a Short Video Descriptor is native */ 203 #define CEA_SVD_NATIVE (1 << 7) 204 205 enum hdmi_vsdb_flags1 { 206 HDMI_VSDB_DVI_DUAL = 1 << 0, 207 HDMI_VSDB_DC_Y444 = 1 << 3, /* supports YCbCr 4:4:4 */ 208 HDMI_VSDB_DC_30BIT = 1 << 4, /* 30 bits per pixel */ 209 HDMI_VSDB_DC_36BIT = 1 << 5, /* 36 bits per pixel */ 210 HDMI_VSDB_DC_48BIT = 1 << 6, /* 48 bits per pixel */ 211 HDMI_VSDB_SUPPORTS_AI = 1 << 7, /* supports ACP, ISRC1 or ISRC2 packets */ 212 }; 213 214 enum hdmi_vsdb_flags2 { 215 HDMI_VSDB_CNC_GRAPHICS = 1 << 0, 216 HDMI_VSDB_CNC_PHOTO = 1 << 1, 217 HDMI_VSDB_CNC_CINEMA = 1 << 2, 218 HDMI_VSDB_CNC_GAME = 1 << 3, 219 HDMI_VSDB_VIDEO_PRESENT = 1 << 5, 220 HDMI_VSDB_INTERLACED_LATENCY_PRESENT = 1 << 6, 221 HDMI_VSDB_LATENCY_PRESENT = 1 << 7, 222 }; 223 224 enum hdmi_vsdb_video_flags { 225 HDMI_VSDB_VIDEO_3D_STRUCT_PRESENT = 0b01 << 5, 226 HDMI_VSDB_VIDEO_3D_STRUCT_MASK_PRESENT = 0b10 << 5, 227 HDMI_VSDB_VIDEO_3D_PRESENT = 1 << 7, 228 }; 229 230 /* HDMI's IEEE Registration Identifier */ 231 extern const uint8_t hdmi_ieee_oui[3]; 232 233 /* HDMI Vendor-Specific Data Block (defined in the HDMI spec) */ 234 struct hdmi_vsdb { 235 uint8_t src_phy_addr[2]; /* source physical address */ 236 237 /* Extension fields */ 238 uint8_t flags1; /* enum hdmi_vsdb_flags1 */ 239 uint8_t max_tdms_clock; /* multiply by 5MHz */ 240 uint8_t flags2; /* enum hdmi_vsdb_flags2 */ 241 uint8_t data[]; /* latency, misc, VIC, 3D */ 242 } __attribute__((packed)); 243 244 #define HDMI_VSDB_MIN_SIZE 2 /* just the source physical address */ 245 #define HDMI_VSDB_MAX_SIZE 28 246 #define CEA_VSDB_HEADER_SIZE 3 /* IEEE OUI */ 247 #define CEA_VSDB_HDMI_MIN_SIZE (CEA_VSDB_HEADER_SIZE + HDMI_VSDB_MIN_SIZE) 248 #define CEA_VSDB_HDMI_MAX_SIZE (CEA_VSDB_HEADER_SIZE + HDMI_VSDB_MAX_SIZE) 249 250 /* Vendor-Specific Data Block */ 251 struct cea_vsdb { 252 uint8_t ieee_oui[3]; /* 24-bit IEEE Registration Identifier, LSB */ 253 union { 254 struct hdmi_vsdb hdmi; 255 } data; 256 } __attribute__((packed)); 257 258 enum cea_speaker_alloc_item { 259 CEA_SPEAKER_FRONT_LEFT_RIGHT = 1 << 0, 260 CEA_SPEAKER_LFE = 1 << 1, 261 CEA_SPEAKER_FRONT_CENTER = 1 << 2, 262 CEA_SPEAKER_REAR_LEFT_RIGHT = 1 << 3, 263 CEA_SPEAKER_REAR_CENTER = 1 << 4, 264 CEA_SPEAKER_FRONT_LEFT_RIGHT_CENTER = 1 << 5, 265 CEA_SPEAKER_REAR_LEFT_RIGHT_CENTER = 1 << 6, 266 }; 267 268 struct cea_speaker_alloc { 269 uint8_t speakers; /* enum cea_speaker_alloc_item */ 270 uint8_t reserved[2]; 271 } __attribute__((packed)); 272 273 enum edid_cea_data_type { 274 EDID_CEA_DATA_AUDIO = 1, 275 EDID_CEA_DATA_VIDEO = 2, 276 EDID_CEA_DATA_VENDOR_SPECIFIC = 3, 277 EDID_CEA_DATA_SPEAKER_ALLOC = 4, 278 }; 279 280 struct edid_cea_data_block { 281 uint8_t type_len; /* type is from enum edid_cea_data_type */ 282 union { 283 struct cea_sad sads[0]; 284 uint8_t svds[0]; /* Short Video Descriptors */ 285 struct cea_vsdb vsdbs[0]; 286 struct cea_speaker_alloc speakers[0]; 287 } data; 288 } __attribute__((packed)); 289 290 enum edid_cea_flag { 291 EDID_CEA_YCBCR422 = 1 << 4, 292 EDID_CEA_YCBCR444 = 1 << 5, 293 EDID_CEA_BASIC_AUDIO = 1 << 6, 294 EDID_CEA_UNDERSCAN = 1 << 7, 295 }; 296 297 struct edid_cea { 298 uint8_t revision; 299 uint8_t dtd_start; 300 uint8_t misc; 301 char data[123]; /* DBC & DTD collection, padded with zeros */ 302 uint8_t checksum; 303 } __attribute__((packed)); 304 305 enum edid_ext_tag { 306 EDID_EXT_CEA = 0x02, 307 }; 308 309 struct edid_ext { 310 uint8_t tag; /* enum edid_ext_tag */ 311 union { 312 struct edid_cea cea; 313 } data; 314 } __attribute__((packed)); 315 316 struct edid { 317 char header[8]; 318 /* Vendor & product info */ 319 uint8_t mfg_id[2]; 320 uint8_t prod_code[2]; 321 uint8_t serial[4]; 322 uint8_t mfg_week; 323 uint8_t mfg_year; 324 /* EDID version */ 325 uint8_t version; 326 uint8_t revision; 327 /* Display info: */ 328 uint8_t input; 329 uint8_t width_cm; 330 uint8_t height_cm; 331 uint8_t gamma; 332 uint8_t features; 333 /* Color characteristics */ 334 uint8_t red_green_lo; 335 uint8_t black_white_lo; 336 uint8_t red_x; 337 uint8_t red_y; 338 uint8_t green_x; 339 uint8_t green_y; 340 uint8_t blue_x; 341 uint8_t blue_y; 342 uint8_t white_x; 343 uint8_t white_y; 344 /* Est. timings and mfg rsvd timings*/ 345 struct est_timings established_timings; 346 /* Standard timings 1-8*/ 347 struct std_timing standard_timings[STD_TIMINGS_LEN]; 348 /* Detailing timings 1-4 */ 349 struct detailed_timing detailed_timings[DETAILED_TIMINGS_LEN]; 350 /* Number of 128 byte ext. blocks */ 351 uint8_t extensions_len; 352 uint8_t checksum; 353 struct edid_ext extensions[]; 354 } __attribute__((packed)); 355 356 void edid_init(struct edid *edid); 357 void edid_init_with_mode(struct edid *edid, drmModeModeInfo *mode); 358 void edid_update_checksum(struct edid *edid); 359 size_t edid_get_size(const struct edid *edid); 360 void edid_get_mfg(const struct edid *edid, char out[static 3]); 361 void detailed_timing_set_mode(struct detailed_timing *dt, drmModeModeInfo *mode, 362 int width_mm, int height_mm); 363 void detailed_timing_set_monitor_range_mode(struct detailed_timing *dt, 364 drmModeModeInfo *mode); 365 void detailed_timing_set_string(struct detailed_timing *dt, 366 enum detailed_non_pixel_type type, 367 const char *str); 368 369 void cea_sad_init_pcm(struct cea_sad *sad, int channels, 370 uint8_t sampling_rates, uint8_t sample_sizes); 371 const struct cea_vsdb *cea_vsdb_get_hdmi_default(size_t *size); 372 size_t edid_cea_data_block_set_sad(struct edid_cea_data_block *block, 373 const struct cea_sad *sads, size_t sads_len); 374 size_t edid_cea_data_block_set_svd(struct edid_cea_data_block *block, 375 const uint8_t *svds, size_t svds_len); 376 size_t edid_cea_data_block_set_vsdb(struct edid_cea_data_block *block, 377 const struct cea_vsdb *vsdb, size_t vsdb_size); 378 size_t edid_cea_data_block_set_hdmi_vsdb(struct edid_cea_data_block *block, 379 const struct hdmi_vsdb *hdmi, 380 size_t hdmi_size); 381 size_t edid_cea_data_block_set_speaker_alloc(struct edid_cea_data_block *block, 382 const struct cea_speaker_alloc *speakers); 383 void edid_ext_set_cea(struct edid_ext *ext, size_t data_blocks_size, 384 uint8_t num_native_dtds, uint8_t flags); 385 386 #endif 387