aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2010-02-05 04:21:19 -0500
committerDave Airlie <airlied@redhat.com>2010-02-08 18:31:20 -0500
commit3c537889e17232e9073f75ae8710ea0f008c5a29 (patch)
tree9d3c25825b466b8ddc3fdc8224d4484c99173b08 /drivers
parent2739d49cd7f1f44876cad614b072da698967b370 (diff)
drm/radeon/kms: add support for hardcoded edids in rom (v2)
Some servers hardcode an edid in rom so that they will work properly with KVMs. This is a port of the relevant code from the ddx. [airlied: reworked to validate edid at boot stage - and remove special quirk, if there is a valid EDID in the BIOS rom we'll just try and use it.] Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/drm_edid.c30
-rw-r--r--drivers/gpu/drm/radeon/radeon_combios.c33
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c14
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h6
4 files changed, 66 insertions, 17 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index f665b05592f3..f41e91ceaea6 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -60,8 +60,7 @@
60#define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5) 60#define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5)
61/* use +hsync +vsync for detailed mode */ 61/* use +hsync +vsync for detailed mode */
62#define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) 62#define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6)
63/* define the number of Extension EDID block */ 63
64#define MAX_EDID_EXT_NUM 4
65 64
66#define LEVEL_DMT 0 65#define LEVEL_DMT 0
67#define LEVEL_GTF 1 66#define LEVEL_GTF 1
@@ -114,14 +113,14 @@ static const u8 edid_header[] = {
114}; 113};
115 114
116/** 115/**
117 * edid_is_valid - sanity check EDID data 116 * drm_edid_is_valid - sanity check EDID data
118 * @edid: EDID data 117 * @edid: EDID data
119 * 118 *
120 * Sanity check the EDID block by looking at the header, the version number 119 * Sanity check the EDID block by looking at the header, the version number
121 * and the checksum. Return 0 if the EDID doesn't check out, or 1 if it's 120 * and the checksum. Return 0 if the EDID doesn't check out, or 1 if it's
122 * valid. 121 * valid.
123 */ 122 */
124static bool edid_is_valid(struct edid *edid) 123bool drm_edid_is_valid(struct edid *edid)
125{ 124{
126 int i, score = 0; 125 int i, score = 0;
127 u8 csum = 0; 126 u8 csum = 0;
@@ -163,6 +162,7 @@ bad:
163 } 162 }
164 return 0; 163 return 0;
165} 164}
165EXPORT_SYMBOL(drm_edid_is_valid);
166 166
167/** 167/**
168 * edid_vendor - match a string against EDID's obfuscated vendor field 168 * edid_vendor - match a string against EDID's obfuscated vendor field
@@ -1069,8 +1069,8 @@ static int add_detailed_info_eedid(struct drm_connector *connector,
1069 } 1069 }
1070 1070
1071 /* Chose real EDID extension number */ 1071 /* Chose real EDID extension number */
1072 edid_ext_num = edid->extensions > MAX_EDID_EXT_NUM ? 1072 edid_ext_num = edid->extensions > DRM_MAX_EDID_EXT_NUM ?
1073 MAX_EDID_EXT_NUM : edid->extensions; 1073 DRM_MAX_EDID_EXT_NUM : edid->extensions;
1074 1074
1075 /* Find CEA extension */ 1075 /* Find CEA extension */
1076 for (i = 0; i < edid_ext_num; i++) { 1076 for (i = 0; i < edid_ext_num; i++) {
@@ -1152,7 +1152,7 @@ static int drm_ddc_read_edid(struct drm_connector *connector,
1152 for (i = 0; i < 4; i++) { 1152 for (i = 0; i < 4; i++) {
1153 if (drm_do_probe_ddc_edid(adapter, buf, len)) 1153 if (drm_do_probe_ddc_edid(adapter, buf, len))
1154 return -1; 1154 return -1;
1155 if (edid_is_valid((struct edid *)buf)) 1155 if (drm_edid_is_valid((struct edid *)buf))
1156 return 0; 1156 return 0;
1157 } 1157 }
1158 1158
@@ -1177,7 +1177,7 @@ struct edid *drm_get_edid(struct drm_connector *connector,
1177 int ret; 1177 int ret;
1178 struct edid *edid; 1178 struct edid *edid;
1179 1179
1180 edid = kmalloc(EDID_LENGTH * (MAX_EDID_EXT_NUM + 1), 1180 edid = kmalloc(EDID_LENGTH * (DRM_MAX_EDID_EXT_NUM + 1),
1181 GFP_KERNEL); 1181 GFP_KERNEL);
1182 if (edid == NULL) { 1182 if (edid == NULL) {
1183 dev_warn(&connector->dev->pdev->dev, 1183 dev_warn(&connector->dev->pdev->dev,
@@ -1195,14 +1195,14 @@ struct edid *drm_get_edid(struct drm_connector *connector,
1195 if (edid->extensions != 0) { 1195 if (edid->extensions != 0) {
1196 int edid_ext_num = edid->extensions; 1196 int edid_ext_num = edid->extensions;
1197 1197
1198 if (edid_ext_num > MAX_EDID_EXT_NUM) { 1198 if (edid_ext_num > DRM_MAX_EDID_EXT_NUM) {
1199 dev_warn(&connector->dev->pdev->dev, 1199 dev_warn(&connector->dev->pdev->dev,
1200 "The number of extension(%d) is " 1200 "The number of extension(%d) is "
1201 "over max (%d), actually read number (%d)\n", 1201 "over max (%d), actually read number (%d)\n",
1202 edid_ext_num, MAX_EDID_EXT_NUM, 1202 edid_ext_num, DRM_MAX_EDID_EXT_NUM,
1203 MAX_EDID_EXT_NUM); 1203 DRM_MAX_EDID_EXT_NUM);
1204 /* Reset EDID extension number to be read */ 1204 /* Reset EDID extension number to be read */
1205 edid_ext_num = MAX_EDID_EXT_NUM; 1205 edid_ext_num = DRM_MAX_EDID_EXT_NUM;
1206 } 1206 }
1207 /* Read EDID including extensions too */ 1207 /* Read EDID including extensions too */
1208 ret = drm_ddc_read_edid(connector, adapter, (char *)edid, 1208 ret = drm_ddc_read_edid(connector, adapter, (char *)edid,
@@ -1245,8 +1245,8 @@ bool drm_detect_hdmi_monitor(struct edid *edid)
1245 goto end; 1245 goto end;
1246 1246
1247 /* Chose real EDID extension number */ 1247 /* Chose real EDID extension number */
1248 edid_ext_num = edid->extensions > MAX_EDID_EXT_NUM ? 1248 edid_ext_num = edid->extensions > DRM_MAX_EDID_EXT_NUM ?
1249 MAX_EDID_EXT_NUM : edid->extensions; 1249 DRM_MAX_EDID_EXT_NUM : edid->extensions;
1250 1250
1251 /* Find CEA extension */ 1251 /* Find CEA extension */
1252 for (i = 0; i < edid_ext_num; i++) { 1252 for (i = 0; i < edid_ext_num; i++) {
@@ -1303,7 +1303,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
1303 if (edid == NULL) { 1303 if (edid == NULL) {
1304 return 0; 1304 return 0;
1305 } 1305 }
1306 if (!edid_is_valid(edid)) { 1306 if (!drm_edid_is_valid(edid)) {
1307 dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", 1307 dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
1308 drm_get_connector_name(connector)); 1308 drm_get_connector_name(connector));
1309 return 0; 1309 return 0;
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index e208d730f514..257ce1774e40 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -443,6 +443,39 @@ static uint16_t combios_get_table_offset(struct drm_device *dev,
443 443
444} 444}
445 445
446bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
447{
448 int edid_info;
449 struct edid *edid;
450 edid_info = combios_get_table_offset(rdev->ddev, COMBIOS_HARDCODED_EDID_TABLE);
451 if (!edid_info)
452 return false;
453
454 edid = kmalloc(EDID_LENGTH * (DRM_MAX_EDID_EXT_NUM + 1),
455 GFP_KERNEL);
456 if (edid == NULL)
457 return false;
458
459 memcpy((unsigned char *)edid,
460 (unsigned char *)(rdev->bios + edid_info), EDID_LENGTH);
461
462 if (!drm_edid_is_valid(edid)) {
463 kfree(edid);
464 return false;
465 }
466
467 rdev->mode_info.bios_hardcoded_edid = edid;
468 return true;
469}
470
471struct edid *
472radeon_combios_get_hardcoded_edid(struct radeon_device *rdev)
473{
474 if (rdev->mode_info.bios_hardcoded_edid)
475 return rdev->mode_info.bios_hardcoded_edid;
476 return NULL;
477}
478
446static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev, 479static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev,
447 int ddc_line) 480 int ddc_line)
448{ 481{
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index ec3166bfaa49..79634da7c311 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -352,6 +352,8 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
352 352
353int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) 353int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
354{ 354{
355 struct drm_device *dev = radeon_connector->base.dev;
356 struct radeon_device *rdev = dev->dev_private;
355 int ret = 0; 357 int ret = 0;
356 358
357 if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || 359 if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
@@ -366,7 +368,9 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
366 if (!radeon_connector->edid) { 368 if (!radeon_connector->edid) {
367 radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); 369 radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
368 } 370 }
369 371 /* some servers provide a hardcoded edid in rom for KVMs */
372 if (!radeon_connector->edid)
373 radeon_connector->edid = radeon_combios_get_hardcoded_edid(rdev);
370 if (radeon_connector->edid) { 374 if (radeon_connector->edid) {
371 drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid); 375 drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
372 ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid); 376 ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
@@ -829,6 +833,12 @@ int radeon_modeset_init(struct radeon_device *rdev)
829 return ret; 833 return ret;
830 } 834 }
831 835
836 /* check combios for a valid hardcoded EDID - Sun servers */
837 if (!rdev->is_atom_bios) {
838 /* check for hardcoded EDID in BIOS */
839 radeon_combios_check_hardcoded_edid(rdev);
840 }
841
832 if (rdev->flags & RADEON_SINGLE_CRTC) 842 if (rdev->flags & RADEON_SINGLE_CRTC)
833 num_crtc = 1; 843 num_crtc = 1;
834 844
@@ -850,6 +860,8 @@ int radeon_modeset_init(struct radeon_device *rdev)
850 860
851void radeon_modeset_fini(struct radeon_device *rdev) 861void radeon_modeset_fini(struct radeon_device *rdev)
852{ 862{
863 kfree(rdev->mode_info.bios_hardcoded_edid);
864
853 if (rdev->mode_info.mode_config_initialized) { 865 if (rdev->mode_info.mode_config_initialized) {
854 radeon_hpd_fini(rdev); 866 radeon_hpd_fini(rdev);
855 drm_mode_config_cleanup(rdev->ddev); 867 drm_mode_config_cleanup(rdev->ddev);
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index b884bacf09ff..71439ba2feeb 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -207,7 +207,8 @@ struct radeon_mode_info {
207 struct drm_property *tv_std_property; 207 struct drm_property *tv_std_property;
208 /* legacy TMDS PLL detect */ 208 /* legacy TMDS PLL detect */
209 struct drm_property *tmds_pll_property; 209 struct drm_property *tmds_pll_property;
210 210 /* hardcoded DFP edid from BIOS */
211 struct edid *bios_hardcoded_edid;
211}; 212};
212 213
213#define MAX_H_CODE_TIMING_LEN 32 214#define MAX_H_CODE_TIMING_LEN 32
@@ -479,6 +480,9 @@ extern int radeon_crtc_cursor_set(struct drm_crtc *crtc,
479extern int radeon_crtc_cursor_move(struct drm_crtc *crtc, 480extern int radeon_crtc_cursor_move(struct drm_crtc *crtc,
480 int x, int y); 481 int x, int y);
481 482
483extern bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev);
484extern struct edid *
485radeon_combios_get_hardcoded_edid(struct radeon_device *rdev);
482extern bool radeon_atom_get_clock_info(struct drm_device *dev); 486extern bool radeon_atom_get_clock_info(struct drm_device *dev);
483extern bool radeon_combios_get_clock_info(struct drm_device *dev); 487extern bool radeon_combios_get_clock_info(struct drm_device *dev);
484extern struct radeon_encoder_atom_dig * 488extern struct radeon_encoder_atom_dig *