drm/radeon/kms: Get LVDS native mode details from EDID if necessary.
authorMichel Dänzer <daenzer@vmware.com>
Tue, 15 Sep 2009 15:09:27 +0000 (17:09 +0200)
committerDave Airlie <airlied@linux.ie>
Wed, 16 Sep 2009 06:10:19 +0000 (16:10 +1000)
Fixes RMX problems on older Apple laptops which don't have an x86 BIOS ROM.

Signed-off-by: Michel Dänzer <daenzer@vmware.com>
Signed-off-by: Dave Airlie <airlied@linux.ie>
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_connectors.c

index 2a027e0..cb60f55 100644 (file)
@@ -863,8 +863,10 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder
        int tmp, i;
        struct radeon_encoder_lvds *lvds = NULL;
 
-       if (rdev->bios == NULL)
-               return radeon_legacy_get_lvds_info_from_regs(rdev);
+       if (rdev->bios == NULL) {
+               lvds = radeon_legacy_get_lvds_info_from_regs(rdev);
+               goto out;
+       }
 
        lcd_info = combios_get_table_offset(dev, COMBIOS_LCD_INFO_TABLE);
 
@@ -965,11 +967,13 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder
                                lvds->native_mode.flags = 0;
                        }
                }
-               encoder->native_mode = lvds->native_mode;
        } else {
                DRM_INFO("No panel info found in BIOS\n");
-               return radeon_legacy_get_lvds_info_from_regs(rdev);
+               lvds = radeon_legacy_get_lvds_info_from_regs(rdev);
        }
+out:
+       if (lvds)
+               encoder->native_mode = lvds->native_mode;
        return lvds;
 }
 
index d2842da..5ee81b6 100644 (file)
@@ -227,6 +227,36 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr
        return 0;
 }
 
+static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
+                                         struct drm_connector *connector)
+{
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
+
+       /* Try to get native mode details from EDID if necessary */
+       if (!native_mode->dotclock) {
+               struct drm_display_mode *t, *mode;
+
+               list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
+                       if (mode->hdisplay == native_mode->panel_xres &&
+                           mode->vdisplay == native_mode->panel_yres) {
+                               native_mode->hblank = mode->htotal - mode->hdisplay;
+                               native_mode->hoverplus = mode->hsync_start - mode->hdisplay;
+                               native_mode->hsync_width = mode->hsync_end - mode->hsync_start;
+                               native_mode->vblank = mode->vtotal - mode->vdisplay;
+                               native_mode->voverplus = mode->vsync_start - mode->vdisplay;
+                               native_mode->vsync_width = mode->vsync_end - mode->vsync_start;
+                               native_mode->dotclock = mode->clock;
+                               DRM_INFO("Determined LVDS native mode details from EDID\n");
+                               break;
+                       }
+               }
+       }
+       if (!native_mode->dotclock) {
+               DRM_INFO("No LVDS native mode details, disabling RMX\n");
+               radeon_encoder->rmx_type = RMX_OFF;
+       }
+}
 
 static int radeon_lvds_get_modes(struct drm_connector *connector)
 {
@@ -239,9 +269,11 @@ static int radeon_lvds_get_modes(struct drm_connector *connector)
                ret = radeon_ddc_get_modes(radeon_connector);
                if (ret > 0) {
                        encoder = radeon_best_single_encoder(connector);
-                       if (encoder)
+                       if (encoder) {
+                               radeon_fixup_lvds_native_mode(encoder, connector);
                                /* add scaled modes */
                                radeon_add_common_modes(encoder, connector);
+                       }
                        return ret;
                }
        }