aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_edid.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_edid.c')
-rw-r--r--drivers/gpu/drm/drm_edid.c231
1 files changed, 201 insertions, 30 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 3bf999134bcc..53bc7a628909 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -34,6 +34,7 @@
34#include <linux/module.h> 34#include <linux/module.h>
35#include <drm/drmP.h> 35#include <drm/drmP.h>
36#include <drm/drm_edid.h> 36#include <drm/drm_edid.h>
37#include <drm/drm_displayid.h>
37 38
38#define version_greater(edid, maj, min) \ 39#define version_greater(edid, maj, min) \
39 (((edid)->version > (maj)) || \ 40 (((edid)->version > (maj)) || \
@@ -1014,6 +1015,27 @@ module_param_named(edid_fixup, edid_fixup, int, 0400);
1014MODULE_PARM_DESC(edid_fixup, 1015MODULE_PARM_DESC(edid_fixup,
1015 "Minimum number of valid EDID header bytes (0-8, default 6)"); 1016 "Minimum number of valid EDID header bytes (0-8, default 6)");
1016 1017
1018static void drm_get_displayid(struct drm_connector *connector,
1019 struct edid *edid);
1020
1021static int drm_edid_block_checksum(const u8 *raw_edid)
1022{
1023 int i;
1024 u8 csum = 0;
1025 for (i = 0; i < EDID_LENGTH; i++)
1026 csum += raw_edid[i];
1027
1028 return csum;
1029}
1030
1031static bool drm_edid_is_zero(const u8 *in_edid, int length)
1032{
1033 if (memchr_inv(in_edid, 0, length))
1034 return false;
1035
1036 return true;
1037}
1038
1017/** 1039/**
1018 * drm_edid_block_valid - Sanity check the EDID block (base or extension) 1040 * drm_edid_block_valid - Sanity check the EDID block (base or extension)
1019 * @raw_edid: pointer to raw EDID block 1041 * @raw_edid: pointer to raw EDID block
@@ -1027,8 +1049,7 @@ MODULE_PARM_DESC(edid_fixup,
1027 */ 1049 */
1028bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid) 1050bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid)
1029{ 1051{
1030 int i; 1052 u8 csum;
1031 u8 csum = 0;
1032 struct edid *edid = (struct edid *)raw_edid; 1053 struct edid *edid = (struct edid *)raw_edid;
1033 1054
1034 if (WARN_ON(!raw_edid)) 1055 if (WARN_ON(!raw_edid))
@@ -1048,8 +1069,7 @@ bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid)
1048 } 1069 }
1049 } 1070 }
1050 1071
1051 for (i = 0; i < EDID_LENGTH; i++) 1072 csum = drm_edid_block_checksum(raw_edid);
1052 csum += raw_edid[i];
1053 if (csum) { 1073 if (csum) {
1054 if (print_bad_edid) { 1074 if (print_bad_edid) {
1055 DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum); 1075 DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum);
@@ -1080,9 +1100,13 @@ bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid)
1080 1100
1081bad: 1101bad:
1082 if (print_bad_edid) { 1102 if (print_bad_edid) {
1083 printk(KERN_ERR "Raw EDID:\n"); 1103 if (drm_edid_is_zero(raw_edid, EDID_LENGTH)) {
1084 print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1, 1104 printk(KERN_ERR "EDID block is all zeroes\n");
1105 } else {
1106 printk(KERN_ERR "Raw EDID:\n");
1107 print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1,
1085 raw_edid, EDID_LENGTH, false); 1108 raw_edid, EDID_LENGTH, false);
1109 }
1086 } 1110 }
1087 return false; 1111 return false;
1088} 1112}
@@ -1115,7 +1139,7 @@ EXPORT_SYMBOL(drm_edid_is_valid);
1115#define DDC_SEGMENT_ADDR 0x30 1139#define DDC_SEGMENT_ADDR 0x30
1116/** 1140/**
1117 * drm_do_probe_ddc_edid() - get EDID information via I2C 1141 * drm_do_probe_ddc_edid() - get EDID information via I2C
1118 * @adapter: I2C device adaptor 1142 * @data: I2C device adapter
1119 * @buf: EDID data buffer to be filled 1143 * @buf: EDID data buffer to be filled
1120 * @block: 128 byte EDID block to start fetching from 1144 * @block: 128 byte EDID block to start fetching from
1121 * @len: EDID data buffer length to fetch 1145 * @len: EDID data buffer length to fetch
@@ -1125,9 +1149,9 @@ EXPORT_SYMBOL(drm_edid_is_valid);
1125 * Return: 0 on success or -1 on failure. 1149 * Return: 0 on success or -1 on failure.
1126 */ 1150 */
1127static int 1151static int
1128drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, 1152drm_do_probe_ddc_edid(void *data, u8 *buf, unsigned int block, size_t len)
1129 int block, int len)
1130{ 1153{
1154 struct i2c_adapter *adapter = data;
1131 unsigned char start = block * EDID_LENGTH; 1155 unsigned char start = block * EDID_LENGTH;
1132 unsigned char segment = block >> 1; 1156 unsigned char segment = block >> 1;
1133 unsigned char xfers = segment ? 3 : 2; 1157 unsigned char xfers = segment ? 3 : 2;
@@ -1176,16 +1200,26 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
1176 return ret == xfers ? 0 : -1; 1200 return ret == xfers ? 0 : -1;
1177} 1201}
1178 1202
1179static bool drm_edid_is_zero(u8 *in_edid, int length) 1203/**
1180{ 1204 * drm_do_get_edid - get EDID data using a custom EDID block read function
1181 if (memchr_inv(in_edid, 0, length)) 1205 * @connector: connector we're probing
1182 return false; 1206 * @get_edid_block: EDID block read function
1183 1207 * @data: private data passed to the block read function
1184 return true; 1208 *
1185} 1209 * When the I2C adapter connected to the DDC bus is hidden behind a device that
1186 1210 * exposes a different interface to read EDID blocks this function can be used
1187static u8 * 1211 * to get EDID data using a custom block read function.
1188drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) 1212 *
1213 * As in the general case the DDC bus is accessible by the kernel at the I2C
1214 * level, drivers must make all reasonable efforts to expose it as an I2C
1215 * adapter and use drm_get_edid() instead of abusing this function.
1216 *
1217 * Return: Pointer to valid EDID or NULL if we couldn't find any.
1218 */
1219struct edid *drm_do_get_edid(struct drm_connector *connector,
1220 int (*get_edid_block)(void *data, u8 *buf, unsigned int block,
1221 size_t len),
1222 void *data)
1189{ 1223{
1190 int i, j = 0, valid_extensions = 0; 1224 int i, j = 0, valid_extensions = 0;
1191 u8 *block, *new; 1225 u8 *block, *new;
@@ -1196,7 +1230,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
1196 1230
1197 /* base block fetch */ 1231 /* base block fetch */
1198 for (i = 0; i < 4; i++) { 1232 for (i = 0; i < 4; i++) {
1199 if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH)) 1233 if (get_edid_block(data, block, 0, EDID_LENGTH))
1200 goto out; 1234 goto out;
1201 if (drm_edid_block_valid(block, 0, print_bad_edid)) 1235 if (drm_edid_block_valid(block, 0, print_bad_edid))
1202 break; 1236 break;
@@ -1210,7 +1244,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
1210 1244
1211 /* if there's no extensions, we're done */ 1245 /* if there's no extensions, we're done */
1212 if (block[0x7e] == 0) 1246 if (block[0x7e] == 0)
1213 return block; 1247 return (struct edid *)block;
1214 1248
1215 new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL); 1249 new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL);
1216 if (!new) 1250 if (!new)
@@ -1219,7 +1253,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
1219 1253
1220 for (j = 1; j <= block[0x7e]; j++) { 1254 for (j = 1; j <= block[0x7e]; j++) {
1221 for (i = 0; i < 4; i++) { 1255 for (i = 0; i < 4; i++) {
1222 if (drm_do_probe_ddc_edid(adapter, 1256 if (get_edid_block(data,
1223 block + (valid_extensions + 1) * EDID_LENGTH, 1257 block + (valid_extensions + 1) * EDID_LENGTH,
1224 j, EDID_LENGTH)) 1258 j, EDID_LENGTH))
1225 goto out; 1259 goto out;
@@ -1247,7 +1281,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
1247 block = new; 1281 block = new;
1248 } 1282 }
1249 1283
1250 return block; 1284 return (struct edid *)block;
1251 1285
1252carp: 1286carp:
1253 if (print_bad_edid) { 1287 if (print_bad_edid) {
@@ -1260,6 +1294,7 @@ out:
1260 kfree(block); 1294 kfree(block);
1261 return NULL; 1295 return NULL;
1262} 1296}
1297EXPORT_SYMBOL_GPL(drm_do_get_edid);
1263 1298
1264/** 1299/**
1265 * drm_probe_ddc() - probe DDC presence 1300 * drm_probe_ddc() - probe DDC presence
@@ -1289,11 +1324,14 @@ EXPORT_SYMBOL(drm_probe_ddc);
1289struct edid *drm_get_edid(struct drm_connector *connector, 1324struct edid *drm_get_edid(struct drm_connector *connector,
1290 struct i2c_adapter *adapter) 1325 struct i2c_adapter *adapter)
1291{ 1326{
1292 struct edid *edid = NULL; 1327 struct edid *edid;
1293 1328
1294 if (drm_probe_ddc(adapter)) 1329 if (!drm_probe_ddc(adapter))
1295 edid = (struct edid *)drm_do_get_edid(connector, adapter); 1330 return NULL;
1296 1331
1332 edid = drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter);
1333 if (edid)
1334 drm_get_displayid(connector, edid);
1297 return edid; 1335 return edid;
1298} 1336}
1299EXPORT_SYMBOL(drm_get_edid); 1337EXPORT_SYMBOL(drm_get_edid);
@@ -2389,7 +2427,7 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
2389/* 2427/*
2390 * Search EDID for CEA extension block. 2428 * Search EDID for CEA extension block.
2391 */ 2429 */
2392static u8 *drm_find_cea_extension(struct edid *edid) 2430static u8 *drm_find_edid_extension(struct edid *edid, int ext_id)
2393{ 2431{
2394 u8 *edid_ext = NULL; 2432 u8 *edid_ext = NULL;
2395 int i; 2433 int i;
@@ -2401,7 +2439,7 @@ static u8 *drm_find_cea_extension(struct edid *edid)
2401 /* Find CEA extension */ 2439 /* Find CEA extension */
2402 for (i = 0; i < edid->extensions; i++) { 2440 for (i = 0; i < edid->extensions; i++) {
2403 edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1); 2441 edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1);
2404 if (edid_ext[0] == CEA_EXT) 2442 if (edid_ext[0] == ext_id)
2405 break; 2443 break;
2406 } 2444 }
2407 2445
@@ -2411,6 +2449,16 @@ static u8 *drm_find_cea_extension(struct edid *edid)
2411 return edid_ext; 2449 return edid_ext;
2412} 2450}
2413 2451
2452static u8 *drm_find_cea_extension(struct edid *edid)
2453{
2454 return drm_find_edid_extension(edid, CEA_EXT);
2455}
2456
2457static u8 *drm_find_displayid_extension(struct edid *edid)
2458{
2459 return drm_find_edid_extension(edid, DISPLAYID_EXT);
2460}
2461
2414/* 2462/*
2415 * Calculate the alternate clock for the CEA mode 2463 * Calculate the alternate clock for the CEA mode
2416 * (60Hz vs. 59.94Hz etc.) 2464 * (60Hz vs. 59.94Hz etc.)
@@ -3128,9 +3176,12 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
3128 } 3176 }
3129 } 3177 }
3130 eld[5] |= sad_count << 4; 3178 eld[5] |= sad_count << 4;
3131 eld[2] = (20 + mnl + sad_count * 3 + 3) / 4;
3132 3179
3133 DRM_DEBUG_KMS("ELD size %d, SAD count %d\n", (int)eld[2], sad_count); 3180 eld[DRM_ELD_BASELINE_ELD_LEN] =
3181 DIV_ROUND_UP(drm_eld_calc_baseline_block_size(eld), 4);
3182
3183 DRM_DEBUG_KMS("ELD size %d, SAD count %d\n",
3184 drm_eld_size(eld), sad_count);
3134} 3185}
3135EXPORT_SYMBOL(drm_edid_to_eld); 3186EXPORT_SYMBOL(drm_edid_to_eld);
3136 3187
@@ -3868,3 +3919,123 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
3868 return 0; 3919 return 0;
3869} 3920}
3870EXPORT_SYMBOL(drm_hdmi_vendor_infoframe_from_display_mode); 3921EXPORT_SYMBOL(drm_hdmi_vendor_infoframe_from_display_mode);
3922
3923static int drm_parse_display_id(struct drm_connector *connector,
3924 u8 *displayid, int length,
3925 bool is_edid_extension)
3926{
3927 /* if this is an EDID extension the first byte will be 0x70 */
3928 int idx = 0;
3929 struct displayid_hdr *base;
3930 struct displayid_block *block;
3931 u8 csum = 0;
3932 int i;
3933
3934 if (is_edid_extension)
3935 idx = 1;
3936
3937 base = (struct displayid_hdr *)&displayid[idx];
3938
3939 DRM_DEBUG_KMS("base revision 0x%x, length %d, %d %d\n",
3940 base->rev, base->bytes, base->prod_id, base->ext_count);
3941
3942 if (base->bytes + 5 > length - idx)
3943 return -EINVAL;
3944
3945 for (i = idx; i <= base->bytes + 5; i++) {
3946 csum += displayid[i];
3947 }
3948 if (csum) {
3949 DRM_ERROR("DisplayID checksum invalid, remainder is %d\n", csum);
3950 return -EINVAL;
3951 }
3952
3953 block = (struct displayid_block *)&displayid[idx + 4];
3954 DRM_DEBUG_KMS("block id %d, rev %d, len %d\n",
3955 block->tag, block->rev, block->num_bytes);
3956
3957 switch (block->tag) {
3958 case DATA_BLOCK_TILED_DISPLAY: {
3959 struct displayid_tiled_block *tile = (struct displayid_tiled_block *)block;
3960
3961 u16 w, h;
3962 u8 tile_v_loc, tile_h_loc;
3963 u8 num_v_tile, num_h_tile;
3964 struct drm_tile_group *tg;
3965
3966 w = tile->tile_size[0] | tile->tile_size[1] << 8;
3967 h = tile->tile_size[2] | tile->tile_size[3] << 8;
3968
3969 num_v_tile = (tile->topo[0] & 0xf) | (tile->topo[2] & 0x30);
3970 num_h_tile = (tile->topo[0] >> 4) | ((tile->topo[2] >> 2) & 0x30);
3971 tile_v_loc = (tile->topo[1] & 0xf) | ((tile->topo[2] & 0x3) << 4);
3972 tile_h_loc = (tile->topo[1] >> 4) | (((tile->topo[2] >> 2) & 0x3) << 4);
3973
3974 connector->has_tile = true;
3975 if (tile->tile_cap & 0x80)
3976 connector->tile_is_single_monitor = true;
3977
3978 connector->num_h_tile = num_h_tile + 1;
3979 connector->num_v_tile = num_v_tile + 1;
3980 connector->tile_h_loc = tile_h_loc;
3981 connector->tile_v_loc = tile_v_loc;
3982 connector->tile_h_size = w + 1;
3983 connector->tile_v_size = h + 1;
3984
3985 DRM_DEBUG_KMS("tile cap 0x%x\n", tile->tile_cap);
3986 DRM_DEBUG_KMS("tile_size %d x %d\n", w + 1, h + 1);
3987 DRM_DEBUG_KMS("topo num tiles %dx%d, location %dx%d\n",
3988 num_h_tile + 1, num_v_tile + 1, tile_h_loc, tile_v_loc);
3989 DRM_DEBUG_KMS("vend %c%c%c\n", tile->topology_id[0], tile->topology_id[1], tile->topology_id[2]);
3990
3991 tg = drm_mode_get_tile_group(connector->dev, tile->topology_id);
3992 if (!tg) {
3993 tg = drm_mode_create_tile_group(connector->dev, tile->topology_id);
3994 }
3995 if (!tg)
3996 return -ENOMEM;
3997
3998 if (connector->tile_group != tg) {
3999 /* if we haven't got a pointer,
4000 take the reference, drop ref to old tile group */
4001 if (connector->tile_group) {
4002 drm_mode_put_tile_group(connector->dev, connector->tile_group);
4003 }
4004 connector->tile_group = tg;
4005 } else
4006 /* if same tile group, then release the ref we just took. */
4007 drm_mode_put_tile_group(connector->dev, tg);
4008 }
4009 break;
4010 default:
4011 printk("unknown displayid tag %d\n", block->tag);
4012 break;
4013 }
4014 return 0;
4015}
4016
4017static void drm_get_displayid(struct drm_connector *connector,
4018 struct edid *edid)
4019{
4020 void *displayid = NULL;
4021 int ret;
4022 connector->has_tile = false;
4023 displayid = drm_find_displayid_extension(edid);
4024 if (!displayid) {
4025 /* drop reference to any tile group we had */
4026 goto out_drop_ref;
4027 }
4028
4029 ret = drm_parse_display_id(connector, displayid, EDID_LENGTH, true);
4030 if (ret < 0)
4031 goto out_drop_ref;
4032 if (!connector->has_tile)
4033 goto out_drop_ref;
4034 return;
4035out_drop_ref:
4036 if (connector->tile_group) {
4037 drm_mode_put_tile_group(connector->dev, connector->tile_group);
4038 connector->tile_group = NULL;
4039 }
4040 return;
4041}