diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2014-07-15 18:38:10 +0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2014-08-05 16:53:29 +0400 |
commit | 72a5c970a57b51f20f8876816869c937340176b5 (patch) | |
tree | 0ec8f5432e14015b29ee2198f030ba6b45d6d887 /drivers/gpu/drm/radeon/radeon_connectors.c | |
parent | 88fd4789cdc403a5fb0839fbb8ea8899d21c56bd (diff) | |
download | linux-72a5c970a57b51f20f8876816869c937340176b5.tar.xz |
drm/radeon: restructure edid fetching
Split radeon_ddc_get_modes() and move it into
radeon_connectors.c since that is the only place
that uses it.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_connectors.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_connectors.c | 162 |
1 files changed, 110 insertions, 52 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index ce50ea629c71..5b5d28ad9ba5 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -262,6 +262,79 @@ static struct drm_encoder *radeon_find_encoder(struct drm_connector *connector, return NULL; } +static void radeon_connector_get_edid(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + + if (radeon_connector->edid) + return; + + /* on hw with routers, select right port */ + if (radeon_connector->router.ddc_valid) + radeon_router_select_ddc_port(radeon_connector); + + if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) != + ENCODER_OBJECT_ID_NONE) && + radeon_connector->ddc_bus->has_aux) { + radeon_connector->edid = drm_get_edid(connector, + &radeon_connector->ddc_bus->aux.ddc); + } else if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) || + (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) { + struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; + + if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT || + dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && + radeon_connector->ddc_bus->has_aux) + radeon_connector->edid = drm_get_edid(&radeon_connector->base, + &radeon_connector->ddc_bus->aux.ddc); + else if (radeon_connector->ddc_bus) + radeon_connector->edid = drm_get_edid(&radeon_connector->base, + &radeon_connector->ddc_bus->adapter); + } else if (radeon_connector->ddc_bus) { + radeon_connector->edid = drm_get_edid(&radeon_connector->base, + &radeon_connector->ddc_bus->adapter); + } + + if (!radeon_connector->edid) { + if (rdev->is_atom_bios) { + /* some laptops provide a hardcoded edid in rom for LCDs */ + if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) || + (connector->connector_type == DRM_MODE_CONNECTOR_eDP))) + radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev); + } else { + /* some servers provide a hardcoded edid in rom for KVMs */ + radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev); + } + } +} + +static void radeon_connector_free_edid(struct drm_connector *connector) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + + if (radeon_connector->edid) { + kfree(radeon_connector->edid); + radeon_connector->edid = NULL; + } +} + +static int radeon_ddc_get_modes(struct drm_connector *connector) +{ + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + int ret; + + if (radeon_connector->edid) { + drm_mode_connector_update_edid_property(connector, radeon_connector->edid); + ret = drm_add_edid_modes(connector, radeon_connector->edid); + drm_edid_to_eld(connector, radeon_connector->edid); + return ret; + } + drm_mode_connector_update_edid_property(connector, NULL); + return 0; +} + static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector) { int enc_id = connector->encoder_ids[0]; @@ -661,22 +734,20 @@ static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder, static int radeon_lvds_get_modes(struct drm_connector *connector) { - struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct drm_encoder *encoder; int ret = 0; struct drm_display_mode *mode; - if (radeon_connector->ddc_bus) { - ret = radeon_ddc_get_modes(radeon_connector); - if (ret > 0) { - encoder = radeon_best_single_encoder(connector); - if (encoder) { - radeon_fixup_lvds_native_mode(encoder, connector); - /* add scaled modes */ - radeon_add_common_modes(encoder, connector); - } - return ret; + radeon_connector_get_edid(connector); + ret = radeon_ddc_get_modes(connector); + if (ret > 0) { + encoder = radeon_best_single_encoder(connector); + if (encoder) { + radeon_fixup_lvds_native_mode(encoder, connector); + /* add scaled modes */ + radeon_add_common_modes(encoder, connector); } + return ret; } encoder = radeon_best_single_encoder(connector); @@ -751,16 +822,9 @@ radeon_lvds_detect(struct drm_connector *connector, bool force) } /* check for edid as well */ + radeon_connector_get_edid(connector); if (radeon_connector->edid) ret = connector_status_connected; - else { - if (radeon_connector->ddc_bus) { - radeon_connector->edid = drm_get_edid(&radeon_connector->base, - &radeon_connector->ddc_bus->adapter); - if (radeon_connector->edid) - ret = connector_status_connected; - } - } /* check acpi lid status ??? */ radeon_connector_update_scratch_regs(connector, ret); @@ -773,8 +837,7 @@ static void radeon_connector_destroy(struct drm_connector *connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); - if (radeon_connector->edid) - kfree(radeon_connector->edid); + radeon_connector_free_edid(connector); kfree(radeon_connector->con_priv); drm_connector_unregister(connector); drm_connector_cleanup(connector); @@ -833,10 +896,10 @@ static const struct drm_connector_funcs radeon_lvds_connector_funcs = { static int radeon_vga_get_modes(struct drm_connector *connector) { - struct radeon_connector *radeon_connector = to_radeon_connector(connector); int ret; - ret = radeon_ddc_get_modes(radeon_connector); + radeon_connector_get_edid(connector); + ret = radeon_ddc_get_modes(connector); radeon_get_native_mode(connector); @@ -881,28 +944,26 @@ radeon_vga_detect(struct drm_connector *connector, bool force) dret = radeon_ddc_probe(radeon_connector, false); if (dret) { radeon_connector->detected_by_load = false; - if (radeon_connector->edid) { - kfree(radeon_connector->edid); - radeon_connector->edid = NULL; - } - radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); + radeon_connector_free_edid(connector); + radeon_connector_get_edid(connector); if (!radeon_connector->edid) { DRM_ERROR("%s: probed a monitor but no|invalid EDID\n", connector->name); ret = connector_status_connected; } else { - radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); + radeon_connector->use_digital = + !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); /* some oems have boards with separate digital and analog connectors * with a shared ddc line (often vga + hdmi) */ if (radeon_connector->use_digital && radeon_connector->shared_ddc) { - kfree(radeon_connector->edid); - radeon_connector->edid = NULL; + radeon_connector_free_edid(connector); ret = connector_status_disconnected; - } else + } else { ret = connector_status_connected; + } } } else { @@ -1094,18 +1155,16 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) dret = radeon_ddc_probe(radeon_connector, false); if (dret) { radeon_connector->detected_by_load = false; - if (radeon_connector->edid) { - kfree(radeon_connector->edid); - radeon_connector->edid = NULL; - } - radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); + radeon_connector_free_edid(connector); + radeon_connector_get_edid(connector); if (!radeon_connector->edid) { DRM_ERROR("%s: probed a monitor but no|invalid EDID\n", connector->name); /* rs690 seems to have a problem with connectors not existing and always * return a block of 0's. If we see this just stop polling on this output */ - if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) && radeon_connector->base.null_edid_counter) { + if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) && + radeon_connector->base.null_edid_counter) { ret = connector_status_disconnected; DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", connector->name); @@ -1115,18 +1174,18 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) broken_edid = true; /* defer use_digital to later */ } } else { - radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); + radeon_connector->use_digital = + !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); /* some oems have boards with separate digital and analog connectors * with a shared ddc line (often vga + hdmi) */ if ((!radeon_connector->use_digital) && radeon_connector->shared_ddc) { - kfree(radeon_connector->edid); - radeon_connector->edid = NULL; + radeon_connector_free_edid(connector); ret = connector_status_disconnected; - } else + } else { ret = connector_status_connected; - + } /* This gets complicated. We have boards with VGA + HDMI with a * shared DDC line and we have boards with DVI-D + HDMI with a shared * DDC line. The latter is more complex because with DVI<->HDMI adapters @@ -1146,8 +1205,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) if (list_connector->connector_type != DRM_MODE_CONNECTOR_VGA) { /* hpd is our only option in this case */ if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { - kfree(radeon_connector->edid); - radeon_connector->edid = NULL; + radeon_connector_free_edid(connector); ret = connector_status_disconnected; } } @@ -1356,7 +1414,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector) if (!radeon_dig_connector->edp_on) atombios_set_edp_panel_power(connector, ATOM_TRANSMITTER_ACTION_POWER_ON); - ret = radeon_ddc_get_modes(radeon_connector); + radeon_connector_get_edid(connector); + ret = radeon_ddc_get_modes(connector); if (!radeon_dig_connector->edp_on) atombios_set_edp_panel_power(connector, ATOM_TRANSMITTER_ACTION_POWER_OFF); @@ -1367,7 +1426,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector) if (encoder) radeon_atom_ext_encoder_setup_ddc(encoder); } - ret = radeon_ddc_get_modes(radeon_connector); + radeon_connector_get_edid(connector); + ret = radeon_ddc_get_modes(connector); } if (ret > 0) { @@ -1400,7 +1460,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector) if (encoder) radeon_atom_ext_encoder_setup_ddc(encoder); } - ret = radeon_ddc_get_modes(radeon_connector); + radeon_connector_get_edid(connector); + ret = radeon_ddc_get_modes(connector); radeon_get_native_mode(connector); } @@ -1493,10 +1554,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force) goto out; } - if (radeon_connector->edid) { - kfree(radeon_connector->edid); - radeon_connector->edid = NULL; - } + radeon_connector_free_edid(connector); if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) || (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) { |