40,6 → 40,10 |
struct drm_encoder *encoder, |
bool connected); |
|
extern void |
radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder, |
struct drm_connector *drm_connector); |
|
void radeon_connector_hotplug(struct drm_connector *connector) |
{ |
struct drm_device *dev = connector->dev; |
46,22 → 50,23 |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
|
if (radeon_connector->hpd.hpd != RADEON_HPD_NONE) |
radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); |
|
if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) || |
(connector->connector_type == DRM_MODE_CONNECTOR_eDP)) { |
if ((radeon_dp_getsinktype(radeon_connector) == CONNECTOR_OBJECT_ID_DISPLAYPORT) || |
(radeon_dp_getsinktype(radeon_connector) == CONNECTOR_OBJECT_ID_eDP)) { |
if (radeon_dp_needs_link_train(radeon_connector)) { |
if (connector->encoder) |
dp_link_train(connector->encoder, connector); |
/* powering up/down the eDP panel generates hpd events which |
* can interfere with modesetting. |
*/ |
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) |
return; |
|
/* pre-r600 did not always have the hpd pins mapped accurately to connectors */ |
if (rdev->family >= CHIP_R600) { |
if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) |
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); |
else |
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); |
} |
} |
} |
|
} |
|
static void radeon_property_change_mode(struct drm_encoder *encoder) |
{ |
struct drm_crtc *crtc = encoder->crtc; |
162,6 → 167,7 |
{ |
struct drm_device *dev = connector->dev; |
struct drm_connector *conflict; |
struct radeon_connector *radeon_conflict; |
int i; |
|
list_for_each_entry(conflict, &dev->mode_config.connector_list, head) { |
168,6 → 174,7 |
if (conflict == connector) |
continue; |
|
radeon_conflict = to_radeon_connector(conflict); |
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
if (conflict->encoder_ids[i] == 0) |
break; |
177,14 → 184,17 |
if (conflict->status != connector_status_connected) |
continue; |
|
if (radeon_conflict->use_digital) |
continue; |
|
if (priority == true) { |
DRM_INFO("1: conflicting encoders switching off %s\n", drm_get_connector_name(conflict)); |
DRM_INFO("in favor of %s\n", drm_get_connector_name(connector)); |
DRM_DEBUG_KMS("1: conflicting encoders switching off %s\n", drm_get_connector_name(conflict)); |
DRM_DEBUG_KMS("in favor of %s\n", drm_get_connector_name(connector)); |
conflict->status = connector_status_disconnected; |
radeon_connector_update_scratch_regs(conflict, connector_status_disconnected); |
} else { |
DRM_INFO("2: conflicting encoders switching off %s\n", drm_get_connector_name(connector)); |
DRM_INFO("in favor of %s\n", drm_get_connector_name(conflict)); |
DRM_DEBUG_KMS("2: conflicting encoders switching off %s\n", drm_get_connector_name(connector)); |
DRM_DEBUG_KMS("in favor of %s\n", drm_get_connector_name(conflict)); |
current_status = connector_status_disconnected; |
} |
break; |
209,7 → 219,7 |
mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; |
drm_mode_set_name(mode); |
|
DRM_DEBUG("Adding native panel mode %s\n", mode->name); |
DRM_DEBUG_KMS("Adding native panel mode %s\n", mode->name); |
} else if (native_mode->hdisplay != 0 && |
native_mode->vdisplay != 0) { |
/* mac laptops without an edid */ |
221,7 → 231,7 |
*/ |
mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay, 60, true, false, false); |
mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; |
DRM_DEBUG("Adding cvt approximation of native panel mode %s\n", mode->name); |
DRM_DEBUG_KMS("Adding cvt approximation of native panel mode %s\n", mode->name); |
} |
return mode; |
} |
287,6 → 297,7 |
|
if (property == rdev->mode_info.coherent_mode_property) { |
struct radeon_encoder_atom_dig *dig; |
bool new_coherent_mode; |
|
/* need to find digital encoder on connector */ |
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); |
299,10 → 310,55 |
return 0; |
|
dig = radeon_encoder->enc_priv; |
dig->coherent_mode = val ? true : false; |
new_coherent_mode = val ? true : false; |
if (dig->coherent_mode != new_coherent_mode) { |
dig->coherent_mode = new_coherent_mode; |
radeon_property_change_mode(&radeon_encoder->base); |
} |
} |
|
if (property == rdev->mode_info.underscan_property) { |
/* need to find digital encoder on connector */ |
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); |
if (!encoder) |
return 0; |
|
radeon_encoder = to_radeon_encoder(encoder); |
|
if (radeon_encoder->underscan_type != val) { |
radeon_encoder->underscan_type = val; |
radeon_property_change_mode(&radeon_encoder->base); |
} |
} |
|
if (property == rdev->mode_info.underscan_hborder_property) { |
/* need to find digital encoder on connector */ |
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); |
if (!encoder) |
return 0; |
|
radeon_encoder = to_radeon_encoder(encoder); |
|
if (radeon_encoder->underscan_hborder != val) { |
radeon_encoder->underscan_hborder = val; |
radeon_property_change_mode(&radeon_encoder->base); |
} |
} |
|
if (property == rdev->mode_info.underscan_vborder_property) { |
/* need to find digital encoder on connector */ |
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); |
if (!encoder) |
return 0; |
|
radeon_encoder = to_radeon_encoder(encoder); |
|
if (radeon_encoder->underscan_vborder != val) { |
radeon_encoder->underscan_vborder = val; |
radeon_property_change_mode(&radeon_encoder->base); |
} |
} |
|
if (property == rdev->mode_info.tv_std_property) { |
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TVDAC); |
if (!encoder) { |
315,7 → 371,7 |
radeon_encoder = to_radeon_encoder(encoder); |
if (!radeon_encoder->enc_priv) |
return 0; |
if (rdev->is_atom_bios) { |
if (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom) { |
struct radeon_encoder_atom_dac *dac_int; |
dac_int = radeon_encoder->enc_priv; |
dac_int->tv_std = val; |
381,13 → 437,13 |
mode->vdisplay == native_mode->vdisplay) { |
*native_mode = *mode; |
drm_mode_set_crtcinfo(native_mode, CRTC_INTERLACE_HALVE_V); |
DRM_INFO("Determined LVDS native mode details from EDID\n"); |
DRM_DEBUG_KMS("Determined LVDS native mode details from EDID\n"); |
break; |
} |
} |
} |
if (!native_mode->clock) { |
DRM_INFO("No LVDS native mode details, disabling RMX\n"); |
DRM_DEBUG_KMS("No LVDS native mode details, disabling RMX\n"); |
radeon_encoder->rmx_type = RMX_OFF; |
} |
} |
421,6 → 477,9 |
if (mode) { |
ret = 1; |
drm_mode_probed_add(connector, mode); |
/* add the width/height from vbios tables if available */ |
connector->display_info.width_mm = mode->width_mm; |
connector->display_info.height_mm = mode->height_mm; |
/* add scaled modes */ |
radeon_add_common_modes(encoder, connector); |
} |
458,7 → 517,8 |
return MODE_OK; |
} |
|
static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector) |
static enum drm_connector_status |
radeon_lvds_detect(struct drm_connector *connector, bool force) |
{ |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
struct drm_encoder *encoder = radeon_best_single_encoder(connector); |
495,8 → 555,6 |
{ |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
|
if (radeon_connector->ddc_bus) |
radeon_i2c_destroy(radeon_connector->ddc_bus); |
if (radeon_connector->edid) |
kfree(radeon_connector->edid); |
kfree(radeon_connector->con_priv); |
513,7 → 571,7 |
struct radeon_encoder *radeon_encoder; |
enum radeon_rmx_type rmx_type; |
|
DRM_DEBUG("\n"); |
DRM_DEBUG_KMS("\n"); |
if (property != dev->mode_config.scaling_mode_property) |
return 0; |
|
568,13 → 626,22 |
static int radeon_vga_mode_valid(struct drm_connector *connector, |
struct drm_display_mode *mode) |
{ |
struct drm_device *dev = connector->dev; |
struct radeon_device *rdev = dev->dev_private; |
|
/* XXX check mode bandwidth */ |
/* XXX verify against max DAC output frequency */ |
|
if ((mode->clock / 10) > rdev->clock.max_pixel_clock) |
return MODE_CLOCK_HIGH; |
|
return MODE_OK; |
} |
|
static enum drm_connector_status radeon_vga_detect(struct drm_connector *connector) |
static enum drm_connector_status |
radeon_vga_detect(struct drm_connector *connector, bool force) |
{ |
struct drm_device *dev = connector->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
struct drm_encoder *encoder; |
struct drm_encoder_helper_funcs *encoder_funcs; |
612,6 → 679,11 |
ret = connector_status_connected; |
} |
} else { |
|
/* if we aren't forcing don't do destructive polling */ |
if (!force) |
return connector->status; |
|
if (radeon_connector->dac_load_detect && encoder) { |
encoder_funcs = encoder->helper_private; |
ret = encoder_funcs->detect(encoder, connector); |
620,6 → 692,17 |
|
if (ret == connector_status_connected) |
ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true); |
|
/* RN50 and some RV100 asics in servers often have a hardcoded EDID in the |
* vbios to deal with KVMs. If we have one and are not able to detect a monitor |
* by other means, assume the CRT is connected and use that EDID. |
*/ |
if ((!rdev->is_atom_bios) && |
(ret == connector_status_disconnected) && |
rdev->mode_info.bios_hardcoded_edid_size) { |
ret = connector_status_connected; |
} |
|
radeon_connector_update_scratch_regs(connector, ret); |
return ret; |
} |
670,7 → 753,8 |
return MODE_OK; |
} |
|
static enum drm_connector_status radeon_tv_detect(struct drm_connector *connector) |
static enum drm_connector_status |
radeon_tv_detect(struct drm_connector *connector, bool force) |
{ |
struct drm_encoder *encoder; |
struct drm_encoder_helper_funcs *encoder_funcs; |
727,8 → 811,11 |
* we have to check if this analog encoder is shared with anyone else (TV) |
* if its shared we have to set the other connector to disconnected. |
*/ |
static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector) |
static enum drm_connector_status |
radeon_dvi_detect(struct drm_connector *connector, bool force) |
{ |
struct drm_device *dev = connector->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
struct drm_encoder *encoder = NULL; |
struct drm_encoder_helper_funcs *encoder_funcs; |
762,14 → 849,12 |
} else |
ret = connector_status_connected; |
|
/* multiple connectors on the same encoder with the same ddc line |
* This tends to be HDMI and DVI on the same encoder with the |
* same ddc line. If the edid says HDMI, consider the HDMI port |
* connected and the DVI port disconnected. If the edid doesn't |
* say HDMI, vice versa. |
/* 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 |
* you don't really know what's connected to which port as both are digital. |
*/ |
if (radeon_connector->shared_ddc && (ret == connector_status_connected)) { |
struct drm_device *dev = connector->dev; |
struct drm_connector *list_connector; |
struct radeon_connector *list_radeon_connector; |
list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) { |
776,19 → 861,17 |
if (connector == list_connector) |
continue; |
list_radeon_connector = to_radeon_connector(list_connector); |
if (radeon_connector->devices == list_radeon_connector->devices) { |
if (drm_detect_hdmi_monitor(radeon_connector->edid)) { |
if (connector->connector_type == DRM_MODE_CONNECTOR_DVID) { |
if (list_radeon_connector->shared_ddc && |
(list_radeon_connector->ddc_bus->rec.i2c_id == |
radeon_connector->ddc_bus->rec.i2c_id)) { |
/* cases where both connectors are digital */ |
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; |
ret = connector_status_disconnected; |
} |
} else { |
if ((connector->connector_type == DRM_MODE_CONNECTOR_HDMIA) || |
(connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)) { |
kfree(radeon_connector->edid); |
radeon_connector->edid = NULL; |
ret = connector_status_disconnected; |
} |
} |
} |
795,11 → 878,15 |
} |
} |
} |
} |
|
if ((ret == connector_status_connected) && (radeon_connector->use_digital == true)) |
goto out; |
|
if (!force) { |
ret = connector->status; |
goto out; |
} |
|
/* find analog encoder */ |
if (radeon_connector->dac_load_detect) { |
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
832,6 → 919,19 |
ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true); |
} |
|
/* RN50 and some RV100 asics in servers often have a hardcoded EDID in the |
* vbios to deal with KVMs. If we have one and are not able to detect a monitor |
* by other means, assume the DFP is connected and use that EDID. In most |
* cases the DVI port is actually a virtual KVM port connected to the service |
* processor. |
*/ |
if ((!rdev->is_atom_bios) && |
(ret == connector_status_disconnected) && |
rdev->mode_info.bios_hardcoded_edid_size) { |
radeon_connector->use_digital = true; |
ret = connector_status_connected; |
} |
|
out: |
/* updated in get modes as well since we need to know if it's analog or digital */ |
radeon_connector_update_scratch_regs(connector, ret); |
909,9 → 1009,23 |
(radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) || |
(radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B)) |
return MODE_OK; |
else if (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_A) { |
if (ASIC_IS_DCE3(rdev)) { |
/* HDMI 1.3+ supports max clock of 340 Mhz */ |
if (mode->clock > 340000) |
return MODE_CLOCK_HIGH; |
else |
return MODE_OK; |
} else |
return MODE_CLOCK_HIGH; |
} else |
return MODE_CLOCK_HIGH; |
} |
|
/* check against the max pixel clock */ |
if ((mode->clock / 10) > rdev->clock.max_pixel_clock) |
return MODE_CLOCK_HIGH; |
|
return MODE_OK; |
} |
|
935,12 → 1049,10 |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; |
|
if (radeon_connector->ddc_bus) |
radeon_i2c_destroy(radeon_connector->ddc_bus); |
if (radeon_connector->edid) |
kfree(radeon_connector->edid); |
if (radeon_dig_connector->dp_i2c_bus) |
radeon_i2c_destroy_dp(radeon_dig_connector->dp_i2c_bus); |
radeon_i2c_destroy(radeon_dig_connector->dp_i2c_bus); |
kfree(radeon_connector->con_priv); |
drm_sysfs_connector_remove(connector); |
drm_connector_cleanup(connector); |
950,18 → 1062,131 |
static int radeon_dp_get_modes(struct drm_connector *connector) |
{ |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; |
int ret; |
|
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { |
struct drm_encoder *encoder; |
struct drm_display_mode *mode; |
|
if (!radeon_dig_connector->edp_on) |
atombios_set_edp_panel_power(connector, |
ATOM_TRANSMITTER_ACTION_POWER_ON); |
ret = radeon_ddc_get_modes(radeon_connector); |
if (!radeon_dig_connector->edp_on) |
atombios_set_edp_panel_power(connector, |
ATOM_TRANSMITTER_ACTION_POWER_OFF); |
|
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; |
} |
|
static enum drm_connector_status radeon_dp_detect(struct drm_connector *connector) |
encoder = radeon_best_single_encoder(connector); |
if (!encoder) |
return 0; |
|
/* we have no EDID modes */ |
mode = radeon_fp_native_mode(encoder); |
if (mode) { |
ret = 1; |
drm_mode_probed_add(connector, mode); |
/* add the width/height from vbios tables if available */ |
connector->display_info.width_mm = mode->width_mm; |
connector->display_info.height_mm = mode->height_mm; |
/* add scaled modes */ |
radeon_add_common_modes(encoder, connector); |
} |
} else |
ret = radeon_ddc_get_modes(radeon_connector); |
|
return ret; |
} |
|
bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector) |
{ |
struct drm_mode_object *obj; |
struct drm_encoder *encoder; |
struct radeon_encoder *radeon_encoder; |
int i; |
bool found = false; |
|
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
if (connector->encoder_ids[i] == 0) |
break; |
|
obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER); |
if (!obj) |
continue; |
|
encoder = obj_to_encoder(obj); |
radeon_encoder = to_radeon_encoder(encoder); |
|
switch (radeon_encoder->encoder_id) { |
case ENCODER_OBJECT_ID_TRAVIS: |
case ENCODER_OBJECT_ID_NUTMEG: |
found = true; |
break; |
default: |
break; |
} |
} |
|
return found; |
} |
|
bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector) |
{ |
struct drm_mode_object *obj; |
struct drm_encoder *encoder; |
struct radeon_encoder *radeon_encoder; |
int i; |
bool found = false; |
|
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
if (connector->encoder_ids[i] == 0) |
break; |
|
obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER); |
if (!obj) |
continue; |
|
encoder = obj_to_encoder(obj); |
radeon_encoder = to_radeon_encoder(encoder); |
if (radeon_encoder->caps & ATOM_ENCODER_CAP_RECORD_HBR2) |
found = true; |
} |
|
return found; |
} |
|
bool radeon_connector_is_dp12_capable(struct drm_connector *connector) |
{ |
struct drm_device *dev = connector->dev; |
struct radeon_device *rdev = dev->dev_private; |
|
if (ASIC_IS_DCE5(rdev) && |
(rdev->clock.dp_extclk >= 53900) && |
radeon_connector_encoder_is_hbr2(connector)) { |
return true; |
} |
|
return false; |
} |
|
static enum drm_connector_status |
radeon_dp_detect(struct drm_connector *connector, bool force) |
{ |
struct drm_device *dev = connector->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
enum drm_connector_status ret = connector_status_disconnected; |
struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; |
u8 sink_type; |
|
if (radeon_connector->edid) { |
kfree(radeon_connector->edid); |
968,20 → 1193,44 |
radeon_connector->edid = NULL; |
} |
|
sink_type = radeon_dp_getsinktype(radeon_connector); |
if ((sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || |
(sink_type == CONNECTOR_OBJECT_ID_eDP)) { |
if (radeon_dp_getdpcd(radeon_connector)) { |
radeon_dig_connector->dp_sink_type = sink_type; |
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { |
struct drm_encoder *encoder = radeon_best_single_encoder(connector); |
if (encoder) { |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct drm_display_mode *native_mode = &radeon_encoder->native_mode; |
|
/* check if panel is valid */ |
if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240) |
ret = connector_status_connected; |
} |
/* eDP is always DP */ |
radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT; |
if (!radeon_dig_connector->edp_on) |
atombios_set_edp_panel_power(connector, |
ATOM_TRANSMITTER_ACTION_POWER_ON); |
if (radeon_dp_getdpcd(radeon_connector)) |
ret = connector_status_connected; |
if (!radeon_dig_connector->edp_on) |
atombios_set_edp_panel_power(connector, |
ATOM_TRANSMITTER_ACTION_POWER_OFF); |
} else { |
if (radeon_ddc_probe(radeon_connector)) { |
radeon_dig_connector->dp_sink_type = sink_type; |
radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector); |
if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { |
ret = connector_status_connected; |
if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) |
radeon_dp_getdpcd(radeon_connector); |
} else { |
if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { |
if (radeon_dp_getdpcd(radeon_connector)) |
ret = connector_status_connected; |
} else { |
if (radeon_ddc_probe(radeon_connector)) |
ret = connector_status_connected; |
} |
} |
} |
|
radeon_connector_update_scratch_regs(connector, ret); |
return ret; |
} |
|
993,12 → 1242,39 |
|
/* XXX check mode bandwidth */ |
|
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { |
struct drm_encoder *encoder = radeon_best_single_encoder(connector); |
|
if ((mode->hdisplay < 320) || (mode->vdisplay < 240)) |
return MODE_PANEL; |
|
if (encoder) { |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct drm_display_mode *native_mode = &radeon_encoder->native_mode; |
|
/* AVIVO hardware supports downscaling modes larger than the panel |
* to the panel size, but I'm not sure this is desirable. |
*/ |
if ((mode->hdisplay > native_mode->hdisplay) || |
(mode->vdisplay > native_mode->vdisplay)) |
return MODE_PANEL; |
|
/* if scaling is disabled, block non-native modes */ |
if (radeon_encoder->rmx_type == RMX_OFF) { |
if ((mode->hdisplay != native_mode->hdisplay) || |
(mode->vdisplay != native_mode->vdisplay)) |
return MODE_PANEL; |
} |
} |
return MODE_OK; |
} else { |
if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || |
(radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) |
return radeon_dp_mode_valid_helper(radeon_connector, mode); |
return radeon_dp_mode_valid_helper(connector, mode); |
else |
return MODE_OK; |
} |
} |
|
struct drm_connector_helper_funcs radeon_dp_connector_helper_funcs = { |
.get_modes = radeon_dp_get_modes, |
1021,23 → 1297,31 |
uint32_t supported_device, |
int connector_type, |
struct radeon_i2c_bus_rec *i2c_bus, |
bool linkb, |
uint32_t igp_lane_info, |
uint16_t connector_object_id, |
struct radeon_hpd *hpd) |
struct radeon_hpd *hpd, |
struct radeon_router *router) |
{ |
struct radeon_device *rdev = dev->dev_private; |
struct drm_connector *connector; |
struct radeon_connector *radeon_connector; |
struct radeon_connector_atom_dig *radeon_dig_connector; |
struct drm_encoder *encoder; |
struct radeon_encoder *radeon_encoder; |
uint32_t subpixel_order = SubPixelNone; |
bool shared_ddc = false; |
int ret; |
bool is_dp_bridge = false; |
|
/* fixme - tv/cv/din */ |
if (connector_type == DRM_MODE_CONNECTOR_Unknown) |
return; |
|
/* if the user selected tv=0 don't try and add the connector */ |
if (((connector_type == DRM_MODE_CONNECTOR_SVIDEO) || |
(connector_type == DRM_MODE_CONNECTOR_Composite) || |
(connector_type == DRM_MODE_CONNECTOR_9PinDIN)) && |
(radeon_tv == 0)) |
return; |
|
/* see if we already added it */ |
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
radeon_connector = to_radeon_connector(connector); |
1050,9 → 1334,29 |
radeon_connector->shared_ddc = true; |
shared_ddc = true; |
} |
if (radeon_connector->router_bus && router->ddc_valid && |
(radeon_connector->router.router_id == router->router_id)) { |
radeon_connector->shared_ddc = false; |
shared_ddc = false; |
} |
} |
} |
|
/* check if it's a dp bridge */ |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
radeon_encoder = to_radeon_encoder(encoder); |
if (radeon_encoder->devices & supported_device) { |
switch (radeon_encoder->encoder_id) { |
case ENCODER_OBJECT_ID_TRAVIS: |
case ENCODER_OBJECT_ID_NUTMEG: |
is_dp_bridge = true; |
break; |
default: |
break; |
} |
} |
} |
|
radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL); |
if (!radeon_connector) |
return; |
1064,36 → 1368,107 |
radeon_connector->shared_ddc = shared_ddc; |
radeon_connector->connector_object_id = connector_object_id; |
radeon_connector->hpd = *hpd; |
radeon_connector->router = *router; |
if (router->ddc_valid || router->cd_valid) { |
radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info); |
if (!radeon_connector->router_bus) |
DRM_ERROR("Failed to assign router i2c bus! Check dmesg for i2c errors.\n"); |
} |
|
if (is_dp_bridge) { |
radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
if (!radeon_dig_connector) |
goto failed; |
radeon_dig_connector->igp_lane_info = igp_lane_info; |
radeon_connector->con_priv = radeon_dig_connector; |
drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); |
drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); |
if (i2c_bus->valid) { |
/* add DP i2c bus */ |
if (connector_type == DRM_MODE_CONNECTOR_eDP) |
radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); |
else |
radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); |
if (!radeon_dig_connector->dp_i2c_bus) |
DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); |
radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
if (!radeon_connector->ddc_bus) |
DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); |
} |
switch (connector_type) { |
case DRM_MODE_CONNECTOR_VGA: |
case DRM_MODE_CONNECTOR_DVIA: |
default: |
connector->interlace_allowed = true; |
connector->doublescan_allowed = true; |
break; |
case DRM_MODE_CONNECTOR_DVII: |
case DRM_MODE_CONNECTOR_DVID: |
case DRM_MODE_CONNECTOR_HDMIA: |
case DRM_MODE_CONNECTOR_HDMIB: |
case DRM_MODE_CONNECTOR_DisplayPort: |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.underscan_property, |
UNDERSCAN_OFF); |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.underscan_hborder_property, |
0); |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.underscan_vborder_property, |
0); |
subpixel_order = SubPixelHorizontalRGB; |
connector->interlace_allowed = true; |
if (connector_type == DRM_MODE_CONNECTOR_HDMIB) |
connector->doublescan_allowed = true; |
else |
connector->doublescan_allowed = false; |
break; |
case DRM_MODE_CONNECTOR_LVDS: |
case DRM_MODE_CONNECTOR_eDP: |
drm_connector_attach_property(&radeon_connector->base, |
dev->mode_config.scaling_mode_property, |
DRM_MODE_SCALE_FULLSCREEN); |
subpixel_order = SubPixelHorizontalRGB; |
connector->interlace_allowed = false; |
connector->doublescan_allowed = false; |
break; |
} |
} else { |
switch (connector_type) { |
case DRM_MODE_CONNECTOR_VGA: |
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
if (ret) |
goto failed; |
drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
if (i2c_bus->valid) { |
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); |
radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
if (!radeon_connector->ddc_bus) |
goto failed; |
DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); |
} |
radeon_connector->dac_load_detect = true; |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.load_detect_property, |
1); |
/* no HPD on analog connectors */ |
radeon_connector->hpd.hpd = RADEON_HPD_NONE; |
connector->polled = DRM_CONNECTOR_POLL_CONNECT; |
connector->interlace_allowed = true; |
connector->doublescan_allowed = true; |
break; |
case DRM_MODE_CONNECTOR_DVIA: |
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
if (ret) |
goto failed; |
drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
if (i2c_bus->valid) { |
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); |
radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
if (!radeon_connector->ddc_bus) |
goto failed; |
DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); |
} |
radeon_connector->dac_load_detect = true; |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.load_detect_property, |
1); |
/* no HPD on analog connectors */ |
radeon_connector->hpd.hpd = RADEON_HPD_NONE; |
connector->interlace_allowed = true; |
connector->doublescan_allowed = true; |
break; |
case DRM_MODE_CONNECTOR_DVII: |
case DRM_MODE_CONNECTOR_DVID: |
1100,22 → 1475,30 |
radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
if (!radeon_dig_connector) |
goto failed; |
radeon_dig_connector->linkb = linkb; |
radeon_dig_connector->igp_lane_info = igp_lane_info; |
radeon_connector->con_priv = radeon_dig_connector; |
drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
if (ret) |
goto failed; |
drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
if (i2c_bus->valid) { |
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); |
radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
if (!radeon_connector->ddc_bus) |
goto failed; |
DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); |
} |
subpixel_order = SubPixelHorizontalRGB; |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.coherent_mode_property, |
1); |
if (ASIC_IS_AVIVO(rdev)) { |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.underscan_property, |
UNDERSCAN_OFF); |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.underscan_hborder_property, |
0); |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.underscan_vborder_property, |
0); |
} |
if (connector_type == DRM_MODE_CONNECTOR_DVII) { |
radeon_connector->dac_load_detect = true; |
drm_connector_attach_property(&radeon_connector->base, |
1122,6 → 1505,11 |
rdev->mode_info.load_detect_property, |
1); |
} |
connector->interlace_allowed = true; |
if (connector_type == DRM_MODE_CONNECTOR_DVII) |
connector->doublescan_allowed = true; |
else |
connector->doublescan_allowed = false; |
break; |
case DRM_MODE_CONNECTOR_HDMIA: |
case DRM_MODE_CONNECTOR_HDMIB: |
1128,63 → 1516,101 |
radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
if (!radeon_dig_connector) |
goto failed; |
radeon_dig_connector->linkb = linkb; |
radeon_dig_connector->igp_lane_info = igp_lane_info; |
radeon_connector->con_priv = radeon_dig_connector; |
drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
if (ret) |
goto failed; |
drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
if (i2c_bus->valid) { |
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI"); |
radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
if (!radeon_connector->ddc_bus) |
goto failed; |
DRM_ERROR("HDMI: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); |
} |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.coherent_mode_property, |
1); |
if (ASIC_IS_AVIVO(rdev)) { |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.underscan_property, |
UNDERSCAN_OFF); |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.underscan_hborder_property, |
0); |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.underscan_vborder_property, |
0); |
} |
subpixel_order = SubPixelHorizontalRGB; |
connector->interlace_allowed = true; |
if (connector_type == DRM_MODE_CONNECTOR_HDMIB) |
connector->doublescan_allowed = true; |
else |
connector->doublescan_allowed = false; |
break; |
case DRM_MODE_CONNECTOR_DisplayPort: |
case DRM_MODE_CONNECTOR_eDP: |
radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
if (!radeon_dig_connector) |
goto failed; |
radeon_dig_connector->linkb = linkb; |
radeon_dig_connector->igp_lane_info = igp_lane_info; |
radeon_connector->con_priv = radeon_dig_connector; |
drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); |
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); |
if (ret) |
goto failed; |
drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); |
if (i2c_bus->valid) { |
/* add DP i2c bus */ |
if (connector_type == DRM_MODE_CONNECTOR_eDP) |
radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); |
else |
radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); |
if (!radeon_dig_connector->dp_i2c_bus) |
goto failed; |
if (connector_type == DRM_MODE_CONNECTOR_eDP) |
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "eDP"); |
else |
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP"); |
DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); |
radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
if (!radeon_connector->ddc_bus) |
goto failed; |
DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); |
} |
subpixel_order = SubPixelHorizontalRGB; |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.coherent_mode_property, |
1); |
if (ASIC_IS_AVIVO(rdev)) { |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.underscan_property, |
UNDERSCAN_OFF); |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.underscan_hborder_property, |
0); |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.underscan_vborder_property, |
0); |
} |
connector->interlace_allowed = true; |
/* in theory with a DP to VGA converter... */ |
connector->doublescan_allowed = false; |
break; |
case DRM_MODE_CONNECTOR_eDP: |
radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
if (!radeon_dig_connector) |
goto failed; |
radeon_dig_connector->igp_lane_info = igp_lane_info; |
radeon_connector->con_priv = radeon_dig_connector; |
drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); |
drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); |
if (i2c_bus->valid) { |
/* add DP i2c bus */ |
radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); |
if (!radeon_dig_connector->dp_i2c_bus) |
DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); |
radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
if (!radeon_connector->ddc_bus) |
DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); |
} |
drm_connector_attach_property(&radeon_connector->base, |
dev->mode_config.scaling_mode_property, |
DRM_MODE_SCALE_FULLSCREEN); |
subpixel_order = SubPixelHorizontalRGB; |
connector->interlace_allowed = false; |
connector->doublescan_allowed = false; |
break; |
case DRM_MODE_CONNECTOR_SVIDEO: |
case DRM_MODE_CONNECTOR_Composite: |
case DRM_MODE_CONNECTOR_9PinDIN: |
if (radeon_tv == 1) { |
drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); |
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); |
if (ret) |
goto failed; |
drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); |
radeon_connector->dac_load_detect = true; |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.load_detect_property, |
1192,38 → 1618,45 |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.tv_std_property, |
radeon_atombios_get_tv_info(rdev)); |
} |
/* no HPD on analog connectors */ |
radeon_connector->hpd.hpd = RADEON_HPD_NONE; |
connector->interlace_allowed = false; |
connector->doublescan_allowed = false; |
break; |
case DRM_MODE_CONNECTOR_LVDS: |
radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
if (!radeon_dig_connector) |
goto failed; |
radeon_dig_connector->linkb = linkb; |
radeon_dig_connector->igp_lane_info = igp_lane_info; |
radeon_connector->con_priv = radeon_dig_connector; |
drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); |
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); |
if (ret) |
goto failed; |
drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); |
if (i2c_bus->valid) { |
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); |
radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
if (!radeon_connector->ddc_bus) |
goto failed; |
DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); |
} |
drm_connector_attach_property(&radeon_connector->base, |
dev->mode_config.scaling_mode_property, |
DRM_MODE_SCALE_FULLSCREEN); |
subpixel_order = SubPixelHorizontalRGB; |
connector->interlace_allowed = false; |
connector->doublescan_allowed = false; |
break; |
} |
} |
|
if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) { |
if (i2c_bus->valid) |
connector->polled = DRM_CONNECTOR_POLL_CONNECT; |
} else |
connector->polled = DRM_CONNECTOR_POLL_HPD; |
|
connector->display_info.subpixel_order = subpixel_order; |
drm_sysfs_connector_add(connector); |
return; |
|
failed: |
if (radeon_connector->ddc_bus) |
radeon_i2c_destroy(radeon_connector->ddc_bus); |
drm_connector_cleanup(connector); |
kfree(connector); |
} |
1241,12 → 1674,17 |
struct drm_connector *connector; |
struct radeon_connector *radeon_connector; |
uint32_t subpixel_order = SubPixelNone; |
int ret; |
|
/* fixme - tv/cv/din */ |
if (connector_type == DRM_MODE_CONNECTOR_Unknown) |
return; |
|
/* if the user selected tv=0 don't try and add the connector */ |
if (((connector_type == DRM_MODE_CONNECTOR_SVIDEO) || |
(connector_type == DRM_MODE_CONNECTOR_Composite) || |
(connector_type == DRM_MODE_CONNECTOR_9PinDIN)) && |
(radeon_tv == 0)) |
return; |
|
/* see if we already added it */ |
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
radeon_connector = to_radeon_connector(connector); |
1269,44 → 1707,49 |
switch (connector_type) { |
case DRM_MODE_CONNECTOR_VGA: |
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
if (ret) |
goto failed; |
drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
if (i2c_bus->valid) { |
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); |
radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
if (!radeon_connector->ddc_bus) |
goto failed; |
DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); |
} |
radeon_connector->dac_load_detect = true; |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.load_detect_property, |
1); |
/* no HPD on analog connectors */ |
radeon_connector->hpd.hpd = RADEON_HPD_NONE; |
connector->polled = DRM_CONNECTOR_POLL_CONNECT; |
connector->interlace_allowed = true; |
connector->doublescan_allowed = true; |
break; |
case DRM_MODE_CONNECTOR_DVIA: |
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
if (ret) |
goto failed; |
drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
if (i2c_bus->valid) { |
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); |
radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
if (!radeon_connector->ddc_bus) |
goto failed; |
DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); |
} |
radeon_connector->dac_load_detect = true; |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.load_detect_property, |
1); |
/* no HPD on analog connectors */ |
radeon_connector->hpd.hpd = RADEON_HPD_NONE; |
connector->interlace_allowed = true; |
connector->doublescan_allowed = true; |
break; |
case DRM_MODE_CONNECTOR_DVII: |
case DRM_MODE_CONNECTOR_DVID: |
drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
if (ret) |
goto failed; |
drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
if (i2c_bus->valid) { |
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); |
radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
if (!radeon_connector->ddc_bus) |
goto failed; |
DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); |
} |
if (connector_type == DRM_MODE_CONNECTOR_DVII) { |
radeon_connector->dac_load_detect = true; |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.load_detect_property, |
1313,15 → 1756,17 |
1); |
} |
subpixel_order = SubPixelHorizontalRGB; |
connector->interlace_allowed = true; |
if (connector_type == DRM_MODE_CONNECTOR_DVII) |
connector->doublescan_allowed = true; |
else |
connector->doublescan_allowed = false; |
break; |
case DRM_MODE_CONNECTOR_SVIDEO: |
case DRM_MODE_CONNECTOR_Composite: |
case DRM_MODE_CONNECTOR_9PinDIN: |
if (radeon_tv == 1) { |
drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); |
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); |
if (ret) |
goto failed; |
drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); |
radeon_connector->dac_load_detect = true; |
/* RS400,RC410,RS480 chipset seems to report a lot |
* of false positive on load detect, we haven't yet |
1336,32 → 1781,44 |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.tv_std_property, |
radeon_combios_get_tv_info(rdev)); |
} |
/* no HPD on analog connectors */ |
radeon_connector->hpd.hpd = RADEON_HPD_NONE; |
connector->interlace_allowed = false; |
connector->doublescan_allowed = false; |
break; |
case DRM_MODE_CONNECTOR_LVDS: |
drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); |
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); |
if (ret) |
goto failed; |
drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); |
if (i2c_bus->valid) { |
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); |
radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
if (!radeon_connector->ddc_bus) |
goto failed; |
DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); |
} |
drm_connector_attach_property(&radeon_connector->base, |
dev->mode_config.scaling_mode_property, |
DRM_MODE_SCALE_FULLSCREEN); |
subpixel_order = SubPixelHorizontalRGB; |
connector->interlace_allowed = false; |
connector->doublescan_allowed = false; |
break; |
} |
|
if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) { |
if (i2c_bus->valid) |
connector->polled = DRM_CONNECTOR_POLL_CONNECT; |
} else |
connector->polled = DRM_CONNECTOR_POLL_HPD; |
connector->display_info.subpixel_order = subpixel_order; |
drm_sysfs_connector_add(connector); |
return; |
if (connector_type == DRM_MODE_CONNECTOR_LVDS) { |
struct drm_encoder *drm_encoder; |
|
failed: |
if (radeon_connector->ddc_bus) |
radeon_i2c_destroy(radeon_connector->ddc_bus); |
drm_connector_cleanup(connector); |
kfree(connector); |
list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) { |
struct radeon_encoder *radeon_encoder; |
|
radeon_encoder = to_radeon_encoder(drm_encoder); |
if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_LVDS) |
radeon_legacy_backlight_init(radeon_encoder, connector); |
} |
} |
} |