1f453ba04SDave Airlie /* 2f453ba04SDave Airlie * Copyright © 2007-2008 Intel Corporation 3f453ba04SDave Airlie * Jesse Barnes <jesse.barnes@intel.com> 4f453ba04SDave Airlie * 5f453ba04SDave Airlie * Permission is hereby granted, free of charge, to any person obtaining a 6f453ba04SDave Airlie * copy of this software and associated documentation files (the "Software"), 7f453ba04SDave Airlie * to deal in the Software without restriction, including without limitation 8f453ba04SDave Airlie * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9f453ba04SDave Airlie * and/or sell copies of the Software, and to permit persons to whom the 10f453ba04SDave Airlie * Software is furnished to do so, subject to the following conditions: 11f453ba04SDave Airlie * 12f453ba04SDave Airlie * The above copyright notice and this permission notice shall be included in 13f453ba04SDave Airlie * all copies or substantial portions of the Software. 14f453ba04SDave Airlie * 15f453ba04SDave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16f453ba04SDave Airlie * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17f453ba04SDave Airlie * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18f453ba04SDave Airlie * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19f453ba04SDave Airlie * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20f453ba04SDave Airlie * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21f453ba04SDave Airlie * OTHER DEALINGS IN THE SOFTWARE. 22f453ba04SDave Airlie */ 23f453ba04SDave Airlie #ifndef __DRM_EDID_H__ 24f453ba04SDave Airlie #define __DRM_EDID_H__ 25f453ba04SDave Airlie 26f453ba04SDave Airlie #include <linux/types.h> 2700147934SVille Syrjälä #include <linux/hdmi.h> 28*2cdbfd66SUma Shankar #include <drm/drm_mode.h> 29f453ba04SDave Airlie 30cdc3d09fSDaniel Vetter struct drm_device; 31cdc3d09fSDaniel Vetter struct i2c_adapter; 32cdc3d09fSDaniel Vetter 33f453ba04SDave Airlie #define EDID_LENGTH 128 34f453ba04SDave Airlie #define DDC_ADDR 0x50 35b49b55bdSDave Airlie #define DDC_ADDR2 0x52 /* E-DDC 1.2 - where DisplayID can hide */ 36f453ba04SDave Airlie 374d76a221SAdam Jackson #define CEA_EXT 0x02 384d76a221SAdam Jackson #define VTB_EXT 0x10 394d76a221SAdam Jackson #define DI_EXT 0x40 404d76a221SAdam Jackson #define LS_EXT 0x50 414d76a221SAdam Jackson #define MI_EXT 0x60 42b49b55bdSDave Airlie #define DISPLAYID_EXT 0x70 434d76a221SAdam Jackson 44f453ba04SDave Airlie struct est_timings { 45f453ba04SDave Airlie u8 t1; 46f453ba04SDave Airlie u8 t2; 47f453ba04SDave Airlie u8 mfg_rsvd; 48f453ba04SDave Airlie } __attribute__((packed)); 49f453ba04SDave Airlie 500454beabSMichel Dänzer /* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */ 51e14cbee4SMichel Dänzer #define EDID_TIMING_ASPECT_SHIFT 6 520454beabSMichel Dänzer #define EDID_TIMING_ASPECT_MASK (0x3 << EDID_TIMING_ASPECT_SHIFT) 530454beabSMichel Dänzer 540454beabSMichel Dänzer /* need to add 60 */ 55e14cbee4SMichel Dänzer #define EDID_TIMING_VFREQ_SHIFT 0 560454beabSMichel Dänzer #define EDID_TIMING_VFREQ_MASK (0x3f << EDID_TIMING_VFREQ_SHIFT) 570454beabSMichel Dänzer 58f453ba04SDave Airlie struct std_timing { 59f453ba04SDave Airlie u8 hsize; /* need to multiply by 8 then add 248 */ 600454beabSMichel Dänzer u8 vfreq_aspect; 61f453ba04SDave Airlie } __attribute__((packed)); 62f453ba04SDave Airlie 63e14cbee4SMichel Dänzer #define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1) 64e14cbee4SMichel Dänzer #define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2) 650454beabSMichel Dänzer #define DRM_EDID_PT_SEPARATE_SYNC (3 << 3) 66e14cbee4SMichel Dänzer #define DRM_EDID_PT_STEREO (1 << 5) 67e14cbee4SMichel Dänzer #define DRM_EDID_PT_INTERLACED (1 << 7) 680454beabSMichel Dänzer 69f453ba04SDave Airlie /* If detailed data is pixel timing */ 70f453ba04SDave Airlie struct detailed_pixel_timing { 71f453ba04SDave Airlie u8 hactive_lo; 72f453ba04SDave Airlie u8 hblank_lo; 730454beabSMichel Dänzer u8 hactive_hblank_hi; 74f453ba04SDave Airlie u8 vactive_lo; 75f453ba04SDave Airlie u8 vblank_lo; 760454beabSMichel Dänzer u8 vactive_vblank_hi; 77f453ba04SDave Airlie u8 hsync_offset_lo; 78f453ba04SDave Airlie u8 hsync_pulse_width_lo; 790454beabSMichel Dänzer u8 vsync_offset_pulse_width_lo; 800454beabSMichel Dänzer u8 hsync_vsync_offset_pulse_width_hi; 81f453ba04SDave Airlie u8 width_mm_lo; 82f453ba04SDave Airlie u8 height_mm_lo; 830454beabSMichel Dänzer u8 width_height_mm_hi; 84f453ba04SDave Airlie u8 hborder; 85f453ba04SDave Airlie u8 vborder; 860454beabSMichel Dänzer u8 misc; 87f453ba04SDave Airlie } __attribute__((packed)); 88f453ba04SDave Airlie 89f453ba04SDave Airlie /* If it's not pixel timing, it'll be one of the below */ 90f453ba04SDave Airlie struct detailed_data_string { 91f453ba04SDave Airlie u8 str[13]; 92f453ba04SDave Airlie } __attribute__((packed)); 93f453ba04SDave Airlie 94f453ba04SDave Airlie struct detailed_data_monitor_range { 95f453ba04SDave Airlie u8 min_vfreq; 96f453ba04SDave Airlie u8 max_vfreq; 97f453ba04SDave Airlie u8 min_hfreq_khz; 98f453ba04SDave Airlie u8 max_hfreq_khz; 99f453ba04SDave Airlie u8 pixel_clock_mhz; /* need to multiply by 10 */ 100eeefa4beSAdam Jackson u8 flags; 101eeefa4beSAdam Jackson union { 102eeefa4beSAdam Jackson struct { 103eeefa4beSAdam Jackson u8 reserved; 104f453ba04SDave Airlie u8 hfreq_start_khz; /* need to multiply by 2 */ 105f453ba04SDave Airlie u8 c; /* need to divide by 2 */ 1060454beabSMichel Dänzer __le16 m; 107f453ba04SDave Airlie u8 k; 108f453ba04SDave Airlie u8 j; /* need to divide by 2 */ 1098353e6c6STakashi Iwai } __attribute__((packed)) gtf2; 110eeefa4beSAdam Jackson struct { 111eeefa4beSAdam Jackson u8 version; 112eeefa4beSAdam Jackson u8 data1; /* high 6 bits: extra clock resolution */ 113eeefa4beSAdam Jackson u8 data2; /* plus low 2 of above: max hactive */ 114eeefa4beSAdam Jackson u8 supported_aspects; 115eeefa4beSAdam Jackson u8 flags; /* preferred aspect and blanking support */ 116eeefa4beSAdam Jackson u8 supported_scalings; 117eeefa4beSAdam Jackson u8 preferred_refresh; 1188353e6c6STakashi Iwai } __attribute__((packed)) cvt; 119eeefa4beSAdam Jackson } formula; 120f453ba04SDave Airlie } __attribute__((packed)); 121f453ba04SDave Airlie 122f453ba04SDave Airlie struct detailed_data_wpindex { 123e14cbee4SMichel Dänzer u8 white_yx_lo; /* Lower 2 bits each */ 124f453ba04SDave Airlie u8 white_x_hi; 125f453ba04SDave Airlie u8 white_y_hi; 126f453ba04SDave Airlie u8 gamma; /* need to divide by 100 then add 1 */ 127f453ba04SDave Airlie } __attribute__((packed)); 128f453ba04SDave Airlie 129f453ba04SDave Airlie struct detailed_data_color_point { 130f453ba04SDave Airlie u8 windex1; 131f453ba04SDave Airlie u8 wpindex1[3]; 132f453ba04SDave Airlie u8 windex2; 133f453ba04SDave Airlie u8 wpindex2[3]; 134f453ba04SDave Airlie } __attribute__((packed)); 135f453ba04SDave Airlie 1369340d8cfSAdam Jackson struct cvt_timing { 1379340d8cfSAdam Jackson u8 code[3]; 1389340d8cfSAdam Jackson } __attribute__((packed)); 1399340d8cfSAdam Jackson 140f453ba04SDave Airlie struct detailed_non_pixel { 141f453ba04SDave Airlie u8 pad1; 142f453ba04SDave Airlie u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name 143f453ba04SDave Airlie fb=color point data, fa=standard timing data, 144f453ba04SDave Airlie f9=undefined, f8=mfg. reserved */ 145f453ba04SDave Airlie u8 pad2; 146f453ba04SDave Airlie union { 147f453ba04SDave Airlie struct detailed_data_string str; 148f453ba04SDave Airlie struct detailed_data_monitor_range range; 149f453ba04SDave Airlie struct detailed_data_wpindex color; 15096525a2fSDan Carpenter struct std_timing timings[6]; 1519340d8cfSAdam Jackson struct cvt_timing cvt[4]; 152f453ba04SDave Airlie } data; 153f453ba04SDave Airlie } __attribute__((packed)); 154f453ba04SDave Airlie 1552dbdc52cSAdam Jackson #define EDID_DETAIL_EST_TIMINGS 0xf7 1562dbdc52cSAdam Jackson #define EDID_DETAIL_CVT_3BYTE 0xf8 1572dbdc52cSAdam Jackson #define EDID_DETAIL_COLOR_MGMT_DATA 0xf9 158f453ba04SDave Airlie #define EDID_DETAIL_STD_MODES 0xfa 159f453ba04SDave Airlie #define EDID_DETAIL_MONITOR_CPDATA 0xfb 160f453ba04SDave Airlie #define EDID_DETAIL_MONITOR_NAME 0xfc 161f453ba04SDave Airlie #define EDID_DETAIL_MONITOR_RANGE 0xfd 162f453ba04SDave Airlie #define EDID_DETAIL_MONITOR_STRING 0xfe 163f453ba04SDave Airlie #define EDID_DETAIL_MONITOR_SERIAL 0xff 164f453ba04SDave Airlie 165f453ba04SDave Airlie struct detailed_timing { 1660454beabSMichel Dänzer __le16 pixel_clock; /* need to multiply by 10 KHz */ 167f453ba04SDave Airlie union { 168f453ba04SDave Airlie struct detailed_pixel_timing pixel_data; 169f453ba04SDave Airlie struct detailed_non_pixel other_data; 170f453ba04SDave Airlie } data; 171f453ba04SDave Airlie } __attribute__((packed)); 172f453ba04SDave Airlie 173e14cbee4SMichel Dänzer #define DRM_EDID_INPUT_SERRATION_VSYNC (1 << 0) 174e14cbee4SMichel Dänzer #define DRM_EDID_INPUT_SYNC_ON_GREEN (1 << 1) 175e14cbee4SMichel Dänzer #define DRM_EDID_INPUT_COMPOSITE_SYNC (1 << 2) 1760454beabSMichel Dänzer #define DRM_EDID_INPUT_SEPARATE_SYNCS (1 << 3) 177e14cbee4SMichel Dänzer #define DRM_EDID_INPUT_BLANK_TO_BLACK (1 << 4) 178e14cbee4SMichel Dänzer #define DRM_EDID_INPUT_VIDEO_LEVEL (3 << 5) 1793b11228bSJesse Barnes #define DRM_EDID_INPUT_DIGITAL (1 << 7) 1803b11228bSJesse Barnes #define DRM_EDID_DIGITAL_DEPTH_MASK (7 << 4) 1813b11228bSJesse Barnes #define DRM_EDID_DIGITAL_DEPTH_UNDEF (0 << 4) 1823b11228bSJesse Barnes #define DRM_EDID_DIGITAL_DEPTH_6 (1 << 4) 1833b11228bSJesse Barnes #define DRM_EDID_DIGITAL_DEPTH_8 (2 << 4) 1843b11228bSJesse Barnes #define DRM_EDID_DIGITAL_DEPTH_10 (3 << 4) 1853b11228bSJesse Barnes #define DRM_EDID_DIGITAL_DEPTH_12 (4 << 4) 1863b11228bSJesse Barnes #define DRM_EDID_DIGITAL_DEPTH_14 (5 << 4) 1873b11228bSJesse Barnes #define DRM_EDID_DIGITAL_DEPTH_16 (6 << 4) 1883b11228bSJesse Barnes #define DRM_EDID_DIGITAL_DEPTH_RSVD (7 << 4) 1893b11228bSJesse Barnes #define DRM_EDID_DIGITAL_TYPE_UNDEF (0) 1903b11228bSJesse Barnes #define DRM_EDID_DIGITAL_TYPE_DVI (1) 1913b11228bSJesse Barnes #define DRM_EDID_DIGITAL_TYPE_HDMI_A (2) 1923b11228bSJesse Barnes #define DRM_EDID_DIGITAL_TYPE_HDMI_B (3) 1933b11228bSJesse Barnes #define DRM_EDID_DIGITAL_TYPE_MDDI (4) 1943b11228bSJesse Barnes #define DRM_EDID_DIGITAL_TYPE_DP (5) 1950454beabSMichel Dänzer 196e14cbee4SMichel Dänzer #define DRM_EDID_FEATURE_DEFAULT_GTF (1 << 0) 197e14cbee4SMichel Dänzer #define DRM_EDID_FEATURE_PREFERRED_TIMING (1 << 1) 198e14cbee4SMichel Dänzer #define DRM_EDID_FEATURE_STANDARD_COLOR (1 << 2) 199da05a5a7SJesse Barnes /* If analog */ 2000454beabSMichel Dänzer #define DRM_EDID_FEATURE_DISPLAY_TYPE (3 << 3) /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */ 201da05a5a7SJesse Barnes /* If digital */ 202da05a5a7SJesse Barnes #define DRM_EDID_FEATURE_COLOR_MASK (3 << 3) 203da05a5a7SJesse Barnes #define DRM_EDID_FEATURE_RGB (0 << 3) 204da05a5a7SJesse Barnes #define DRM_EDID_FEATURE_RGB_YCRCB444 (1 << 3) 205da05a5a7SJesse Barnes #define DRM_EDID_FEATURE_RGB_YCRCB422 (2 << 3) 206da05a5a7SJesse Barnes #define DRM_EDID_FEATURE_RGB_YCRCB (3 << 3) /* both 4:4:4 and 4:2:2 */ 207da05a5a7SJesse Barnes 208e14cbee4SMichel Dänzer #define DRM_EDID_FEATURE_PM_ACTIVE_OFF (1 << 5) 209e14cbee4SMichel Dänzer #define DRM_EDID_FEATURE_PM_SUSPEND (1 << 6) 210e14cbee4SMichel Dänzer #define DRM_EDID_FEATURE_PM_STANDBY (1 << 7) 2110454beabSMichel Dänzer 212d0c94692SMario Kleiner #define DRM_EDID_HDMI_DC_48 (1 << 6) 213d0c94692SMario Kleiner #define DRM_EDID_HDMI_DC_36 (1 << 5) 214d0c94692SMario Kleiner #define DRM_EDID_HDMI_DC_30 (1 << 4) 215d0c94692SMario Kleiner #define DRM_EDID_HDMI_DC_Y444 (1 << 3) 216d0c94692SMario Kleiner 217e6a9a2c3SShashank Sharma /* YCBCR 420 deep color modes */ 2189068e02fSClint Taylor #define DRM_EDID_YCBCR420_DC_48 (1 << 2) 2199068e02fSClint Taylor #define DRM_EDID_YCBCR420_DC_36 (1 << 1) 2209068e02fSClint Taylor #define DRM_EDID_YCBCR420_DC_30 (1 << 0) 221e6a9a2c3SShashank Sharma #define DRM_EDID_YCBCR420_DC_MASK (DRM_EDID_YCBCR420_DC_48 | \ 222e6a9a2c3SShashank Sharma DRM_EDID_YCBCR420_DC_36 | \ 223e6a9a2c3SShashank Sharma DRM_EDID_YCBCR420_DC_30) 224e6a9a2c3SShashank Sharma 225babc9493SJani Nikula /* ELD Header Block */ 226babc9493SJani Nikula #define DRM_ELD_HEADER_BLOCK_SIZE 4 227babc9493SJani Nikula 228babc9493SJani Nikula #define DRM_ELD_VER 0 229babc9493SJani Nikula # define DRM_ELD_VER_SHIFT 3 230babc9493SJani Nikula # define DRM_ELD_VER_MASK (0x1f << 3) 2311b54bdb8SJani Nikula # define DRM_ELD_VER_CEA861D (2 << 3) /* supports 861D or below */ 2321b54bdb8SJani Nikula # define DRM_ELD_VER_CANNED (0x1f << 3) 233babc9493SJani Nikula 234babc9493SJani Nikula #define DRM_ELD_BASELINE_ELD_LEN 2 /* in dwords! */ 235babc9493SJani Nikula 236babc9493SJani Nikula /* ELD Baseline Block for ELD_Ver == 2 */ 237babc9493SJani Nikula #define DRM_ELD_CEA_EDID_VER_MNL 4 238babc9493SJani Nikula # define DRM_ELD_CEA_EDID_VER_SHIFT 5 239babc9493SJani Nikula # define DRM_ELD_CEA_EDID_VER_MASK (7 << 5) 240babc9493SJani Nikula # define DRM_ELD_CEA_EDID_VER_NONE (0 << 5) 241babc9493SJani Nikula # define DRM_ELD_CEA_EDID_VER_CEA861 (1 << 5) 242babc9493SJani Nikula # define DRM_ELD_CEA_EDID_VER_CEA861A (2 << 5) 243babc9493SJani Nikula # define DRM_ELD_CEA_EDID_VER_CEA861BCD (3 << 5) 244babc9493SJani Nikula # define DRM_ELD_MNL_SHIFT 0 245babc9493SJani Nikula # define DRM_ELD_MNL_MASK (0x1f << 0) 246babc9493SJani Nikula 247babc9493SJani Nikula #define DRM_ELD_SAD_COUNT_CONN_TYPE 5 248babc9493SJani Nikula # define DRM_ELD_SAD_COUNT_SHIFT 4 249babc9493SJani Nikula # define DRM_ELD_SAD_COUNT_MASK (0xf << 4) 250babc9493SJani Nikula # define DRM_ELD_CONN_TYPE_SHIFT 2 251babc9493SJani Nikula # define DRM_ELD_CONN_TYPE_MASK (3 << 2) 252babc9493SJani Nikula # define DRM_ELD_CONN_TYPE_HDMI (0 << 2) 253babc9493SJani Nikula # define DRM_ELD_CONN_TYPE_DP (1 << 2) 254babc9493SJani Nikula # define DRM_ELD_SUPPORTS_AI (1 << 1) 255babc9493SJani Nikula # define DRM_ELD_SUPPORTS_HDCP (1 << 0) 256babc9493SJani Nikula 257babc9493SJani Nikula #define DRM_ELD_AUD_SYNCH_DELAY 6 /* in units of 2 ms */ 258babc9493SJani Nikula # define DRM_ELD_AUD_SYNCH_DELAY_MAX 0xfa /* 500 ms */ 259babc9493SJani Nikula 260babc9493SJani Nikula #define DRM_ELD_SPEAKER 7 261c82dbe5cSArnaud Pouliquen # define DRM_ELD_SPEAKER_MASK 0x7f 262babc9493SJani Nikula # define DRM_ELD_SPEAKER_RLRC (1 << 6) 263babc9493SJani Nikula # define DRM_ELD_SPEAKER_FLRC (1 << 5) 264babc9493SJani Nikula # define DRM_ELD_SPEAKER_RC (1 << 4) 265babc9493SJani Nikula # define DRM_ELD_SPEAKER_RLR (1 << 3) 266babc9493SJani Nikula # define DRM_ELD_SPEAKER_FC (1 << 2) 267babc9493SJani Nikula # define DRM_ELD_SPEAKER_LFE (1 << 1) 268babc9493SJani Nikula # define DRM_ELD_SPEAKER_FLR (1 << 0) 269babc9493SJani Nikula 270babc9493SJani Nikula #define DRM_ELD_PORT_ID 8 /* offsets 8..15 inclusive */ 271babc9493SJani Nikula # define DRM_ELD_PORT_ID_LEN 8 272babc9493SJani Nikula 273babc9493SJani Nikula #define DRM_ELD_MANUFACTURER_NAME0 16 274babc9493SJani Nikula #define DRM_ELD_MANUFACTURER_NAME1 17 275babc9493SJani Nikula 276babc9493SJani Nikula #define DRM_ELD_PRODUCT_CODE0 18 277babc9493SJani Nikula #define DRM_ELD_PRODUCT_CODE1 19 278babc9493SJani Nikula 279babc9493SJani Nikula #define DRM_ELD_MONITOR_NAME_STRING 20 /* offsets 20..(20+mnl-1) inclusive */ 280babc9493SJani Nikula 281babc9493SJani Nikula #define DRM_ELD_CEA_SAD(mnl, sad) (20 + (mnl) + 3 * (sad)) 282babc9493SJani Nikula 283f453ba04SDave Airlie struct edid { 284f453ba04SDave Airlie u8 header[8]; 285f453ba04SDave Airlie /* Vendor & product info */ 286f453ba04SDave Airlie u8 mfg_id[2]; 287f453ba04SDave Airlie u8 prod_code[2]; 288f453ba04SDave Airlie u32 serial; /* FIXME: byte order */ 289f453ba04SDave Airlie u8 mfg_week; 290f453ba04SDave Airlie u8 mfg_year; 291f453ba04SDave Airlie /* EDID version */ 292f453ba04SDave Airlie u8 version; 293f453ba04SDave Airlie u8 revision; 294f453ba04SDave Airlie /* Display info: */ 2950454beabSMichel Dänzer u8 input; 296f453ba04SDave Airlie u8 width_cm; 297f453ba04SDave Airlie u8 height_cm; 298f453ba04SDave Airlie u8 gamma; 2990454beabSMichel Dänzer u8 features; 300f453ba04SDave Airlie /* Color characteristics */ 301f453ba04SDave Airlie u8 red_green_lo; 302f453ba04SDave Airlie u8 black_white_lo; 303f453ba04SDave Airlie u8 red_x; 304f453ba04SDave Airlie u8 red_y; 305f453ba04SDave Airlie u8 green_x; 306f453ba04SDave Airlie u8 green_y; 307f453ba04SDave Airlie u8 blue_x; 308f453ba04SDave Airlie u8 blue_y; 309f453ba04SDave Airlie u8 white_x; 310f453ba04SDave Airlie u8 white_y; 311f453ba04SDave Airlie /* Est. timings and mfg rsvd timings*/ 312f453ba04SDave Airlie struct est_timings established_timings; 313f453ba04SDave Airlie /* Standard timings 1-8*/ 314f453ba04SDave Airlie struct std_timing standard_timings[8]; 315f453ba04SDave Airlie /* Detailing timings 1-4 */ 316f453ba04SDave Airlie struct detailed_timing detailed_timings[4]; 317f453ba04SDave Airlie /* Number of 128 byte ext. blocks */ 318f453ba04SDave Airlie u8 extensions; 319f453ba04SDave Airlie /* Checksum */ 320f453ba04SDave Airlie u8 checksum; 321f453ba04SDave Airlie } __attribute__((packed)); 322f453ba04SDave Airlie 323f453ba04SDave Airlie #define EDID_PRODUCT_ID(e) ((e)->prod_code[0] | ((e)->prod_code[1] << 8)) 324f453ba04SDave Airlie 325fe214163SRafał Miłecki /* Short Audio Descriptor */ 326fe214163SRafał Miłecki struct cea_sad { 327fe214163SRafał Miłecki u8 format; 328fe214163SRafał Miłecki u8 channels; /* max number of channels - 1 */ 329fe214163SRafał Miłecki u8 freq; 330fe214163SRafał Miłecki u8 byte2; /* meaning depends on format */ 331fe214163SRafał Miłecki }; 332fe214163SRafał Miłecki 33376adaa34SWu Fengguang struct drm_encoder; 33476adaa34SWu Fengguang struct drm_connector; 3350d68b887SUma Shankar struct drm_connector_state; 33676adaa34SWu Fengguang struct drm_display_mode; 33710a85120SThierry Reding 338fe214163SRafał Miłecki int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads); 339d105f476SAlex Deucher int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb); 34076adaa34SWu Fengguang int drm_av_sync_delay(struct drm_connector *connector, 3413a818d35SVille Syrjälä const struct drm_display_mode *mode); 342ba34d58cSEzequiel Garcia 343ba34d58cSEzequiel Garcia #ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE 34407c2b84bSJani Nikula struct edid *drm_load_edid_firmware(struct drm_connector *connector); 345ac6c35a4SJani Nikula int __drm_set_edid_firmware_path(const char *path); 346ac6c35a4SJani Nikula int __drm_get_edid_firmware_path(char *buf, size_t bufsize); 347ba34d58cSEzequiel Garcia #else 34807c2b84bSJani Nikula static inline struct edid * 34907c2b84bSJani Nikula drm_load_edid_firmware(struct drm_connector *connector) 350ba34d58cSEzequiel Garcia { 35107c2b84bSJani Nikula return ERR_PTR(-ENOENT); 352ba34d58cSEzequiel Garcia } 353ba34d58cSEzequiel Garcia #endif 35476adaa34SWu Fengguang 35510a85120SThierry Reding int 35610a85120SThierry Reding drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame, 35713d0add3SVille Syrjälä struct drm_connector *connector, 35813d0add3SVille Syrjälä const struct drm_display_mode *mode); 35983dd0008SLespiau, Damien int 36083dd0008SLespiau, Damien drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, 361f1781e9bSVille Syrjälä struct drm_connector *connector, 36283dd0008SLespiau, Damien const struct drm_display_mode *mode); 3630d68b887SUma Shankar 3640d68b887SUma Shankar void 3650d68b887SUma Shankar drm_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame, 3660d68b887SUma Shankar const struct drm_connector_state *conn_state); 3670d68b887SUma Shankar 368a2ce26f8SVille Syrjälä void 369a2ce26f8SVille Syrjälä drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame, 37013d0add3SVille Syrjälä struct drm_connector *connector, 371779c4c28SVille Syrjälä const struct drm_display_mode *mode, 3721581b2dfSVille Syrjälä enum hdmi_quantization_range rgb_quant_range); 37310a85120SThierry Reding 374*2cdbfd66SUma Shankar int 375*2cdbfd66SUma Shankar drm_hdmi_infoframe_set_hdr_metadata(struct hdmi_drm_infoframe *frame, 376*2cdbfd66SUma Shankar const struct drm_connector_state *conn_state); 377*2cdbfd66SUma Shankar 378babc9493SJani Nikula /** 379babc9493SJani Nikula * drm_eld_mnl - Get ELD monitor name length in bytes. 380babc9493SJani Nikula * @eld: pointer to an eld memory structure with mnl set 381babc9493SJani Nikula */ 382babc9493SJani Nikula static inline int drm_eld_mnl(const uint8_t *eld) 383babc9493SJani Nikula { 384babc9493SJani Nikula return (eld[DRM_ELD_CEA_EDID_VER_MNL] & DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT; 385babc9493SJani Nikula } 386babc9493SJani Nikula 387babc9493SJani Nikula /** 3881c73d3b1SRussell King * drm_eld_sad - Get ELD SAD structures. 3891c73d3b1SRussell King * @eld: pointer to an eld memory structure with sad_count set 3901c73d3b1SRussell King */ 3911c73d3b1SRussell King static inline const uint8_t *drm_eld_sad(const uint8_t *eld) 3921c73d3b1SRussell King { 3931c73d3b1SRussell King unsigned int ver, mnl; 3941c73d3b1SRussell King 3951c73d3b1SRussell King ver = (eld[DRM_ELD_VER] & DRM_ELD_VER_MASK) >> DRM_ELD_VER_SHIFT; 3961c73d3b1SRussell King if (ver != 2 && ver != 31) 3971c73d3b1SRussell King return NULL; 3981c73d3b1SRussell King 3991c73d3b1SRussell King mnl = drm_eld_mnl(eld); 4001c73d3b1SRussell King if (mnl > 16) 4011c73d3b1SRussell King return NULL; 4021c73d3b1SRussell King 4031c73d3b1SRussell King return eld + DRM_ELD_CEA_SAD(mnl, 0); 4041c73d3b1SRussell King } 4051c73d3b1SRussell King 4061c73d3b1SRussell King /** 407babc9493SJani Nikula * drm_eld_sad_count - Get ELD SAD count. 408babc9493SJani Nikula * @eld: pointer to an eld memory structure with sad_count set 409babc9493SJani Nikula */ 410babc9493SJani Nikula static inline int drm_eld_sad_count(const uint8_t *eld) 411babc9493SJani Nikula { 412babc9493SJani Nikula return (eld[DRM_ELD_SAD_COUNT_CONN_TYPE] & DRM_ELD_SAD_COUNT_MASK) >> 413babc9493SJani Nikula DRM_ELD_SAD_COUNT_SHIFT; 414babc9493SJani Nikula } 415babc9493SJani Nikula 416babc9493SJani Nikula /** 417babc9493SJani Nikula * drm_eld_calc_baseline_block_size - Calculate baseline block size in bytes 418babc9493SJani Nikula * @eld: pointer to an eld memory structure with mnl and sad_count set 419babc9493SJani Nikula * 420babc9493SJani Nikula * This is a helper for determining the payload size of the baseline block, in 421babc9493SJani Nikula * bytes, for e.g. setting the Baseline_ELD_Len field in the ELD header block. 422babc9493SJani Nikula */ 423babc9493SJani Nikula static inline int drm_eld_calc_baseline_block_size(const uint8_t *eld) 424babc9493SJani Nikula { 425babc9493SJani Nikula return DRM_ELD_MONITOR_NAME_STRING - DRM_ELD_HEADER_BLOCK_SIZE + 426babc9493SJani Nikula drm_eld_mnl(eld) + drm_eld_sad_count(eld) * 3; 427babc9493SJani Nikula } 428babc9493SJani Nikula 429babc9493SJani Nikula /** 430babc9493SJani Nikula * drm_eld_size - Get ELD size in bytes 431babc9493SJani Nikula * @eld: pointer to a complete eld memory structure 432babc9493SJani Nikula * 433babc9493SJani Nikula * The returned value does not include the vendor block. It's vendor specific, 434babc9493SJani Nikula * and comprises of the remaining bytes in the ELD memory buffer after 435babc9493SJani Nikula * drm_eld_size() bytes of header and baseline block. 436babc9493SJani Nikula * 437babc9493SJani Nikula * The returned value is guaranteed to be a multiple of 4. 438babc9493SJani Nikula */ 439babc9493SJani Nikula static inline int drm_eld_size(const uint8_t *eld) 440babc9493SJani Nikula { 441babc9493SJani Nikula return DRM_ELD_HEADER_BLOCK_SIZE + eld[DRM_ELD_BASELINE_ELD_LEN] * 4; 442babc9493SJani Nikula } 443babc9493SJani Nikula 4441aa8ec25SSubhransu S. Prusty /** 445c82dbe5cSArnaud Pouliquen * drm_eld_get_spk_alloc - Get speaker allocation 446c82dbe5cSArnaud Pouliquen * @eld: pointer to an ELD memory structure 447c82dbe5cSArnaud Pouliquen * 448c82dbe5cSArnaud Pouliquen * The returned value is the speakers mask. User has to use %DRM_ELD_SPEAKER 449c82dbe5cSArnaud Pouliquen * field definitions to identify speakers. 450c82dbe5cSArnaud Pouliquen */ 451c82dbe5cSArnaud Pouliquen static inline u8 drm_eld_get_spk_alloc(const uint8_t *eld) 452c82dbe5cSArnaud Pouliquen { 453c82dbe5cSArnaud Pouliquen return eld[DRM_ELD_SPEAKER] & DRM_ELD_SPEAKER_MASK; 454c82dbe5cSArnaud Pouliquen } 455c82dbe5cSArnaud Pouliquen 456c82dbe5cSArnaud Pouliquen /** 4571aa8ec25SSubhransu S. Prusty * drm_eld_get_conn_type - Get device type hdmi/dp connected 4581aa8ec25SSubhransu S. Prusty * @eld: pointer to an ELD memory structure 4591aa8ec25SSubhransu S. Prusty * 4601aa8ec25SSubhransu S. Prusty * The caller need to use %DRM_ELD_CONN_TYPE_HDMI or %DRM_ELD_CONN_TYPE_DP to 4611aa8ec25SSubhransu S. Prusty * identify the display type connected. 4621aa8ec25SSubhransu S. Prusty */ 4631aa8ec25SSubhransu S. Prusty static inline u8 drm_eld_get_conn_type(const uint8_t *eld) 4641aa8ec25SSubhransu S. Prusty { 4651aa8ec25SSubhransu S. Prusty return eld[DRM_ELD_SAD_COUNT_CONN_TYPE] & DRM_ELD_CONN_TYPE_MASK; 4661aa8ec25SSubhransu S. Prusty } 4671aa8ec25SSubhransu S. Prusty 468cdc3d09fSDaniel Vetter bool drm_probe_ddc(struct i2c_adapter *adapter); 46918df89feSLars-Peter Clausen struct edid *drm_do_get_edid(struct drm_connector *connector, 47018df89feSLars-Peter Clausen int (*get_edid_block)(void *data, u8 *buf, unsigned int block, 47118df89feSLars-Peter Clausen size_t len), 47218df89feSLars-Peter Clausen void *data); 473cdc3d09fSDaniel Vetter struct edid *drm_get_edid(struct drm_connector *connector, 474cdc3d09fSDaniel Vetter struct i2c_adapter *adapter); 475cdc3d09fSDaniel Vetter struct edid *drm_get_edid_switcheroo(struct drm_connector *connector, 476cdc3d09fSDaniel Vetter struct i2c_adapter *adapter); 477cdc3d09fSDaniel Vetter struct edid *drm_edid_duplicate(const struct edid *edid); 478cdc3d09fSDaniel Vetter int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); 479cdc3d09fSDaniel Vetter 480cdc3d09fSDaniel Vetter u8 drm_match_cea_mode(const struct drm_display_mode *to_match); 481cdc3d09fSDaniel Vetter enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code); 482cdc3d09fSDaniel Vetter bool drm_detect_hdmi_monitor(struct edid *edid); 483cdc3d09fSDaniel Vetter bool drm_detect_monitor_audio(struct edid *edid); 484c8127cf0SVille Syrjälä enum hdmi_quantization_range 485c8127cf0SVille Syrjälä drm_default_rgb_quant_range(const struct drm_display_mode *mode); 486cdc3d09fSDaniel Vetter int drm_add_modes_noedid(struct drm_connector *connector, 487cdc3d09fSDaniel Vetter int hdisplay, int vdisplay); 488cdc3d09fSDaniel Vetter void drm_set_preferred_mode(struct drm_connector *connector, 489cdc3d09fSDaniel Vetter int hpref, int vpref); 490cdc3d09fSDaniel Vetter 491cdc3d09fSDaniel Vetter int drm_edid_header_is_valid(const u8 *raw_edid); 492cdc3d09fSDaniel Vetter bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid, 493cdc3d09fSDaniel Vetter bool *edid_corrupt); 494cdc3d09fSDaniel Vetter bool drm_edid_is_valid(struct edid *edid); 495cdc3d09fSDaniel Vetter void drm_edid_get_monitor_name(struct edid *edid, char *name, 496cdc3d09fSDaniel Vetter int buflen); 497cdc3d09fSDaniel Vetter struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, 498cdc3d09fSDaniel Vetter int hsize, int vsize, int fresh, 499cdc3d09fSDaniel Vetter bool rb); 500f453ba04SDave Airlie #endif /* __DRM_EDID_H__ */ 501