Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 5077 → Rev 5078

/drivers/video/drm/radeon/radeon_connectors.c
31,18 → 31,8
#include "radeon.h"
#include "atom.h"
 
#define DISABLE_DP 0
 
 
extern void
radeon_combios_connected_scratch_regs(struct drm_connector *connector,
struct drm_encoder *encoder,
bool connected);
extern void
radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
struct drm_encoder *encoder,
bool connected);
 
void radeon_connector_hotplug(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
58,6 → 48,7
radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
 
/* if the connector is already off, don't turn it back on */
/* FIXME: This access isn't protected by any locks. */
if (connector->dpms != DRM_MODE_DPMS_ON)
return;
 
99,7 → 90,7
 
if (crtc && crtc->enabled) {
drm_crtc_helper_set_mode(crtc, &crtc->mode,
crtc->x, crtc->y, crtc->fb);
crtc->x, crtc->y, crtc->primary->fb);
}
}
 
110,12 → 101,13
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct radeon_connector_atom_dig *dig_connector;
int bpc = 8;
int mode_clock, max_tmds_clock;
 
switch (connector->connector_type) {
case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_HDMIB:
if (radeon_connector->use_digital) {
if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
if (connector->display_info.bpc)
bpc = connector->display_info.bpc;
}
123,7 → 115,7
break;
case DRM_MODE_CONNECTOR_DVID:
case DRM_MODE_CONNECTOR_HDMIA:
if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
if (connector->display_info.bpc)
bpc = connector->display_info.bpc;
}
132,7 → 124,7
dig_connector = radeon_connector->con_priv;
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) ||
drm_detect_hdmi_monitor(radeon_connector->edid)) {
drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
if (connector->display_info.bpc)
bpc = connector->display_info.bpc;
}
155,6 → 147,73
}
break;
}
 
if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
/* hdmi deep color only implemented on DCE4+ */
if ((bpc > 8) && !ASIC_IS_DCE4(rdev)) {
DRM_DEBUG("%s: HDMI deep color %d bpc unsupported. Using 8 bpc.\n",
connector->name, bpc);
bpc = 8;
}
 
/*
* Pre DCE-8 hw can't handle > 12 bpc, and more than 12 bpc doesn't make
* much sense without support for > 12 bpc framebuffers. RGB 4:4:4 at
* 12 bpc is always supported on hdmi deep color sinks, as this is
* required by the HDMI-1.3 spec. Clamp to a safe 12 bpc maximum.
*/
if (bpc > 12) {
DRM_DEBUG("%s: HDMI deep color %d bpc unsupported. Using 12 bpc.\n",
connector->name, bpc);
bpc = 12;
}
 
/* Any defined maximum tmds clock limit we must not exceed? */
if (connector->max_tmds_clock > 0) {
/* mode_clock is clock in kHz for mode to be modeset on this connector */
mode_clock = radeon_connector->pixelclock_for_modeset;
 
/* Maximum allowable input clock in kHz */
max_tmds_clock = connector->max_tmds_clock * 1000;
 
DRM_DEBUG("%s: hdmi mode dotclock %d kHz, max tmds input clock %d kHz.\n",
connector->name, mode_clock, max_tmds_clock);
 
/* Check if bpc is within clock limit. Try to degrade gracefully otherwise */
if ((bpc == 12) && (mode_clock * 3/2 > max_tmds_clock)) {
if ((connector->display_info.edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30) &&
(mode_clock * 5/4 <= max_tmds_clock))
bpc = 10;
else
bpc = 8;
 
DRM_DEBUG("%s: HDMI deep color 12 bpc exceeds max tmds clock. Using %d bpc.\n",
connector->name, bpc);
}
 
if ((bpc == 10) && (mode_clock * 5/4 > max_tmds_clock)) {
bpc = 8;
DRM_DEBUG("%s: HDMI deep color 10 bpc exceeds max tmds clock. Using %d bpc.\n",
connector->name, bpc);
}
}
else if (bpc > 8) {
/* max_tmds_clock missing, but hdmi spec mandates it for deep color. */
DRM_DEBUG("%s: Required max tmds clock for HDMI deep color missing. Using 8 bpc.\n",
connector->name);
bpc = 8;
}
}
 
if ((radeon_deep_color == 0) && (bpc > 8)) {
DRM_DEBUG("%s: Deep color disabled. Set radeon module param deep_color=1 to enable.\n",
connector->name);
bpc = 8;
}
 
DRM_DEBUG("%s: Display bpc=%d, returned bpc=%d\n",
connector->name, connector->display_info.bpc, bpc);
 
return bpc;
}
 
166,7 → 225,6
struct drm_encoder *best_encoder = NULL;
struct drm_encoder *encoder = NULL;
struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
struct drm_mode_object *obj;
bool connected;
int i;
 
176,14 → 234,11
if (connector->encoder_ids[i] == 0)
break;
 
obj = drm_mode_object_find(connector->dev,
connector->encoder_ids[i],
DRM_MODE_OBJECT_ENCODER);
if (!obj)
encoder = drm_encoder_find(connector->dev,
connector->encoder_ids[i]);
if (!encoder)
continue;
 
encoder = obj_to_encoder(obj);
 
if ((encoder == best_encoder) && (status == connector_status_connected))
connected = true;
else
199,7 → 254,6
 
static struct drm_encoder *radeon_find_encoder(struct drm_connector *connector, int encoder_type)
{
struct drm_mode_object *obj;
struct drm_encoder *encoder;
int i;
 
207,11 → 261,10
if (connector->encoder_ids[i] == 0)
break;
 
obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
if (!obj)
encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
if (!encoder)
continue;
 
encoder = obj_to_encoder(obj);
if (encoder->encoder_type == encoder_type)
return encoder;
}
218,22 → 271,123
return NULL;
}
 
struct edid *radeon_connector_edid(struct drm_connector *connector)
{
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct drm_property_blob *edid_blob = connector->edid_blob_ptr;
 
if (radeon_connector->edid) {
return radeon_connector->edid;
} else if (edid_blob) {
struct edid *edid = kmemdup(edid_blob->data, edid_blob->length, GFP_KERNEL);
if (edid)
radeon_connector->edid = edid;
}
return radeon_connector->edid;
}
 
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];
struct drm_mode_object *obj;
struct drm_encoder *encoder;
 
/* pick the encoder ids */
if (enc_id) {
obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
if (!obj)
if (enc_id)
return drm_encoder_find(connector->dev, enc_id);
return NULL;
encoder = obj_to_encoder(obj);
return encoder;
}
return NULL;
 
static void radeon_get_native_mode(struct drm_connector *connector)
{
struct drm_encoder *encoder = radeon_best_single_encoder(connector);
struct radeon_encoder *radeon_encoder;
 
if (encoder == NULL)
return;
 
radeon_encoder = to_radeon_encoder(encoder);
 
if (!list_empty(&connector->probed_modes)) {
struct drm_display_mode *preferred_mode =
list_first_entry(&connector->probed_modes,
struct drm_display_mode, head);
 
radeon_encoder->native_mode = *preferred_mode;
} else {
radeon_encoder->native_mode.clock = 0;
}
}
 
/*
* radeon_connector_analog_encoder_conflict_solve
270,13 → 424,17
continue;
 
if (priority == true) {
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));
DRM_DEBUG_KMS("1: conflicting encoders switching off %s\n",
conflict->name);
DRM_DEBUG_KMS("in favor of %s\n",
connector->name);
conflict->status = connector_status_disconnected;
radeon_connector_update_scratch_regs(conflict, connector_status_disconnected);
} else {
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));
DRM_DEBUG_KMS("2: conflicting encoders switching off %s\n",
connector->name);
DRM_DEBUG_KMS("in favor of %s\n",
conflict->name);
current_status = connector_status_disconnected;
}
break;
399,6 → 557,36
}
}
 
if (property == rdev->mode_info.audio_property) {
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
/* 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_connector->audio != val) {
radeon_connector->audio = val;
radeon_property_change_mode(&radeon_encoder->base);
}
}
 
if (property == rdev->mode_info.dither_property) {
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
/* 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_connector->dither != val) {
radeon_connector->dither = val;
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);
501,9 → 689,38
radeon_property_change_mode(&radeon_encoder->base);
}
 
if (property == dev->mode_config.scaling_mode_property) {
enum radeon_rmx_type rmx_type;
 
if (connector->encoder)
radeon_encoder = to_radeon_encoder(connector->encoder);
else {
struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
}
 
switch (val) {
default:
case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break;
case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break;
case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break;
case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break;
}
if (radeon_encoder->rmx_type == rmx_type)
return 0;
 
if ((rmx_type != DRM_MODE_SCALE_NONE) &&
(radeon_encoder->native_mode.clock == 0))
return 0;
 
radeon_encoder->rmx_type = rmx_type;
 
radeon_property_change_mode(&radeon_encoder->base);
}
 
return 0;
}
 
static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
struct drm_connector *connector)
{
541,13 → 758,12
 
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);
radeon_connector_get_edid(connector);
ret = radeon_ddc_get_modes(connector);
if (ret > 0) {
encoder = radeon_best_single_encoder(connector);
if (encoder) {
557,7 → 773,6
}
return ret;
}
}
 
encoder = radeon_best_single_encoder(connector);
if (!encoder)
626,16 → 841,9
}
 
/* 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);
646,10 → 854,9
{
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_sysfs_connector_remove(connector);
drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(connector);
}
706,11 → 913,13
 
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);
 
return ret;
}
 
747,29 → 956,27
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",
drm_get_connector_name(connector));
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 {
 
/* if we aren't forcing don't do destructive polling */
778,9 → 985,8
* detected a monitor via load.
*/
if (radeon_connector->detected_by_load)
return connector->status;
else
return ret;
ret = connector->status;
goto out;
}
 
if (radeon_connector->dac_load_detect && encoder) {
805,6 → 1011,8
}
 
radeon_connector_update_scratch_regs(connector, ret);
 
out:
return ret;
}
 
861,6 → 1069,7
struct drm_encoder_helper_funcs *encoder_funcs;
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
enum drm_connector_status ret = connector_status_disconnected;
int r;
 
if (!radeon_connector->dac_load_detect)
return ret;
892,15 → 1101,6
.set_property = radeon_connector_set_property,
};
 
static int radeon_dvi_get_modes(struct drm_connector *connector)
{
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
int ret;
 
ret = radeon_ddc_get_modes(radeon_connector);
return ret;
}
 
static bool radeon_check_hpd_status_unchanged(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
941,32 → 1141,33
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct drm_encoder *encoder = NULL;
struct drm_encoder_helper_funcs *encoder_funcs;
struct drm_mode_object *obj;
int i;
int i, r;
enum drm_connector_status ret = connector_status_disconnected;
bool dret = false, broken_edid = false;
 
if (!force && radeon_check_hpd_status_unchanged(connector))
return connector->status;
 
if (!force && radeon_check_hpd_status_unchanged(connector)) {
ret = connector->status;
goto exit;
}
 
if (radeon_connector->ddc_bus)
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",
drm_get_connector_name(connector));
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", drm_get_connector_name(connector));
DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n",
connector->name);
radeon_connector->ddc_bus = NULL;
} else {
ret = connector_status_connected;
973,18 → 1174,18
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
1004,8 → 1205,7
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;
}
}
1039,14 → 1239,11
if (connector->encoder_ids[i] == 0)
break;
 
obj = drm_mode_object_find(connector->dev,
connector->encoder_ids[i],
DRM_MODE_OBJECT_ENCODER);
if (!obj)
encoder = drm_encoder_find(connector->dev,
connector->encoder_ids[i]);
if (!encoder)
continue;
 
encoder = obj_to_encoder(obj);
 
if (encoder->encoder_type != DRM_MODE_ENCODER_DAC &&
encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
continue;
1098,6 → 1295,8
 
/* updated in get modes as well since we need to know if it's analog or digital */
radeon_connector_update_scratch_regs(connector, ret);
 
exit:
return ret;
}
 
1106,7 → 1305,6
{
int enc_id = connector->encoder_ids[0];
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct drm_mode_object *obj;
struct drm_encoder *encoder;
int i;
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
1113,12 → 1311,10
if (connector->encoder_ids[i] == 0)
break;
 
obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
if (!obj)
encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
if (!encoder)
continue;
 
encoder = obj_to_encoder(obj);
 
if (radeon_connector->use_digital == true) {
if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
return encoder;
1133,15 → 1329,10
 
/* then check use digitial */
/* pick the first one */
if (enc_id) {
obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
if (!obj)
if (enc_id)
return drm_encoder_find(connector->dev, enc_id);
return NULL;
encoder = obj_to_encoder(obj);
return encoder;
}
return NULL;
}
 
static void radeon_dvi_force(struct drm_connector *connector)
{
1172,18 → 1363,16
(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_DCE6(rdev)) {
else if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
/* HDMI 1.3+ supports max clock of 340 Mhz */
if (mode->clock > 340000)
return MODE_CLOCK_HIGH;
else
return MODE_OK;
} else
} 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)
1193,7 → 1382,7
}
 
static const struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = {
.get_modes = radeon_dvi_get_modes,
.get_modes = radeon_vga_get_modes,
.mode_valid = radeon_dvi_mode_valid,
.best_encoder = radeon_dvi_encoder,
};
1207,21 → 1396,6
.force = radeon_dvi_force,
};
 
static void radeon_dp_connector_destroy(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;
 
if (radeon_connector->edid)
kfree(radeon_connector->edid);
if (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);
kfree(connector);
}
 
static int radeon_dp_get_modes(struct drm_connector *connector)
{
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1237,7 → 1411,8
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);
1248,7 → 1423,8
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) {
1281,7 → 1457,10
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);
}
 
return ret;
1289,7 → 1468,6
 
u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector)
{
struct drm_mode_object *obj;
struct drm_encoder *encoder;
struct radeon_encoder *radeon_encoder;
int i;
1298,11 → 1476,10
if (connector->encoder_ids[i] == 0)
break;
 
obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
if (!obj)
encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
if (!encoder)
continue;
 
encoder = obj_to_encoder(obj);
radeon_encoder = to_radeon_encoder(encoder);
 
switch (radeon_encoder->encoder_id) {
1317,9 → 1494,8
return ENCODER_OBJECT_ID_NONE;
}
 
bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector)
static 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;
1329,11 → 1505,10
if (connector->encoder_ids[i] == 0)
break;
 
obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
if (!obj)
encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
if (!encoder)
continue;
 
encoder = obj_to_encoder(obj);
radeon_encoder = to_radeon_encoder(encoder);
if (radeon_encoder->caps & ATOM_ENCODER_CAP_RECORD_HBR2)
found = true;
1348,7 → 1523,7
struct radeon_device *rdev = dev->dev_private;
 
if (ASIC_IS_DCE5(rdev) &&
(rdev->clock.dp_extclk >= 53900) &&
(rdev->clock.default_dispclk >= 53900) &&
radeon_connector_encoder_is_hbr2(connector)) {
return true;
}
1365,21 → 1540,16
enum drm_connector_status ret = connector_status_disconnected;
struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
struct drm_encoder *encoder = radeon_best_single_encoder(connector);
int r;
 
 
#if DISABLE_DP
connector->status = connector_status_disconnected;
return connector->status;
#endif
if (!force && radeon_check_hpd_status_unchanged(connector)) {
ret = connector->status;
goto out;
}
 
if (!force && radeon_check_hpd_status_unchanged(connector))
return connector->status;
radeon_connector_free_edid(connector);
 
if (radeon_connector->edid) {
kfree(radeon_connector->edid);
radeon_connector->edid = NULL;
}
 
if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
(connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
if (encoder) {
1429,7 → 1599,7
if (radeon_dp_getdpcd(radeon_connector))
ret = connector_status_connected;
} else {
/* try non-aux ddc (DP to DVI/HMDI/etc. adapter) */
/* try non-aux ddc (DP to DVI/HDMI/etc. adapter) */
if (radeon_ddc_probe(radeon_connector, false))
ret = connector_status_connected;
}
1437,6 → 1607,7
}
 
radeon_connector_update_scratch_regs(connector, ret);
out:
return ret;
}
 
1443,6 → 1614,8
static int radeon_dp_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct drm_device *dev = connector->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
 
1473,16 → 1646,25
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))
(radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
return radeon_dp_mode_valid_helper(connector, mode);
else
return MODE_OK;
} else {
if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
/* HDMI 1.3+ supports max clock of 340 Mhz */
if (mode->clock > 340000)
return MODE_CLOCK_HIGH;
} else {
if (mode->clock > 165000)
return MODE_CLOCK_HIGH;
}
}
}
 
return MODE_OK;
}
 
static const struct drm_connector_helper_funcs radeon_dp_connector_helper_funcs = {
.get_modes = radeon_dp_get_modes,
.mode_valid = radeon_dp_mode_valid,
1494,10 → 1676,28
.detect = radeon_dp_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = radeon_connector_set_property,
.destroy = radeon_dp_connector_destroy,
.destroy = radeon_connector_destroy,
.force = radeon_dvi_force,
};
 
static const struct drm_connector_funcs radeon_edp_connector_funcs = {
.dpms = drm_helper_connector_dpms,
.detect = radeon_dp_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = radeon_lvds_set_property,
.destroy = radeon_connector_destroy,
.force = radeon_dvi_force,
};
 
static const struct drm_connector_funcs radeon_lvds_bridge_connector_funcs = {
.dpms = drm_helper_connector_dpms,
.detect = radeon_dp_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = radeon_lvds_set_property,
.destroy = radeon_connector_destroy,
.force = radeon_dvi_force,
};
 
void
radeon_add_atom_connector(struct drm_device *dev,
uint32_t connector_id,
1518,6 → 1718,7
uint32_t subpixel_order = SubPixelNone;
bool shared_ddc = false;
bool is_dp_bridge = false;
bool has_aux = false;
 
if (connector_type == DRM_MODE_CONNECTOR_Unknown)
return;
1589,18 → 1790,11
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");
radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
if (radeon_connector->ddc_bus)
has_aux = true;
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) {
1607,6 → 1801,10
case DRM_MODE_CONNECTOR_VGA:
case DRM_MODE_CONNECTOR_DVIA:
default:
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);
connector->interlace_allowed = true;
connector->doublescan_allowed = true;
radeon_connector->dac_load_detect = true;
1613,6 → 1811,9
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property,
1);
drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_NONE);
break;
case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_DVID:
1619,6 → 1820,10
case DRM_MODE_CONNECTOR_HDMIA:
case DRM_MODE_CONNECTOR_HDMIB:
case DRM_MODE_CONNECTOR_DisplayPort:
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);
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_property,
UNDERSCAN_OFF);
1628,6 → 1833,20
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_vborder_property,
0);
 
drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_NONE);
 
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.dither_property,
RADEON_FMT_DITHER_DISABLE);
 
if (radeon_audio != 0)
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.audio_property,
RADEON_AUDIO_AUTO);
 
subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = true;
if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
1643,6 → 1862,10
break;
case DRM_MODE_CONNECTOR_LVDS:
case DRM_MODE_CONNECTOR_eDP:
drm_connector_init(dev, &radeon_connector->base,
&radeon_lvds_bridge_connector_funcs, connector_type);
drm_connector_helper_add(&radeon_connector->base,
&radeon_dp_connector_helper_funcs);
drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_FULLSCREEN);
1665,6 → 1888,10
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property,
1);
if (ASIC_IS_AVIVO(rdev))
drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_NONE);
/* no HPD on analog connectors */
radeon_connector->hpd.hpd = RADEON_HPD_NONE;
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
1683,6 → 1910,10
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property,
1);
if (ASIC_IS_AVIVO(rdev))
drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_NONE);
/* no HPD on analog connectors */
radeon_connector->hpd.hpd = RADEON_HPD_NONE;
connector->interlace_allowed = true;
1716,7 → 1947,18
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_vborder_property,
0);
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.dither_property,
RADEON_FMT_DITHER_DISABLE);
drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_NONE);
}
if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.audio_property,
RADEON_AUDIO_AUTO);
}
if (connector_type == DRM_MODE_CONNECTOR_DVII) {
radeon_connector->dac_load_detect = true;
drm_object_attach_property(&radeon_connector->base.base,
1756,7 → 1998,18
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_vborder_property,
0);
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.dither_property,
RADEON_FMT_DITHER_DISABLE);
drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_NONE);
}
if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.audio_property,
RADEON_AUDIO_AUTO);
}
subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = true;
if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
1773,12 → 2026,10
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, "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)
if (radeon_connector->ddc_bus)
has_aux = true;
else
DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
}
subpixel_order = SubPixelHorizontalRGB;
1795,7 → 2046,18
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_vborder_property,
0);
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.dither_property,
RADEON_FMT_DITHER_DISABLE);
drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_NONE);
}
if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.audio_property,
RADEON_AUDIO_AUTO);
}
connector->interlace_allowed = true;
/* in theory with a DP to VGA converter... */
connector->doublescan_allowed = false;
1806,15 → 2068,13
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_init(dev, &radeon_connector->base, &radeon_edp_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)
if (radeon_connector->ddc_bus)
has_aux = true;
else
DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
}
drm_object_attach_property(&radeon_connector->base.base,
1871,7 → 2131,11
connector->polled = DRM_CONNECTOR_POLL_HPD;
 
connector->display_info.subpixel_order = subpixel_order;
drm_sysfs_connector_add(connector);
drm_connector_register(connector);
 
if (has_aux)
radeon_dp_aux_init(radeon_connector);
 
return;
 
failed:
2028,5 → 2292,5
} else
connector->polled = DRM_CONNECTOR_POLL_HPD;
connector->display_info.subpixel_order = subpixel_order;
drm_sysfs_connector_add(connector);
drm_connector_register(connector);
}