162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright 2007-8 Advanced Micro Devices, Inc.
362306a36Sopenharmony_ci * Copyright 2008 Red Hat Inc.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
662306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
762306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation
862306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
962306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
1062306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
1362306a36Sopenharmony_ci * all copies or substantial portions of the Software.
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1662306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1762306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1862306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
1962306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2062306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2162306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * Authors: Dave Airlie
2462306a36Sopenharmony_ci *          Alex Deucher
2562306a36Sopenharmony_ci */
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include <drm/display/drm_dp_mst_helper.h>
2862306a36Sopenharmony_ci#include <drm/drm_edid.h>
2962306a36Sopenharmony_ci#include <drm/drm_crtc_helper.h>
3062306a36Sopenharmony_ci#include <drm/drm_modeset_helper_vtables.h>
3162306a36Sopenharmony_ci#include <drm/drm_probe_helper.h>
3262306a36Sopenharmony_ci#include <drm/radeon_drm.h>
3362306a36Sopenharmony_ci#include "radeon.h"
3462306a36Sopenharmony_ci#include "radeon_audio.h"
3562306a36Sopenharmony_ci#include "atom.h"
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#include <linux/pm_runtime.h>
3862306a36Sopenharmony_ci#include <linux/vga_switcheroo.h>
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_civoid radeon_connector_hotplug(struct drm_connector *connector)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	struct drm_device *dev = connector->dev;
4362306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
4462306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	/* bail if the connector does not have hpd pin, e.g.,
4762306a36Sopenharmony_ci	 * VGA, TV, etc.
4862306a36Sopenharmony_ci	 */
4962306a36Sopenharmony_ci	if (radeon_connector->hpd.hpd == RADEON_HPD_NONE)
5062306a36Sopenharmony_ci		return;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	/* if the connector is already off, don't turn it back on */
5562306a36Sopenharmony_ci	/* FIXME: This access isn't protected by any locks. */
5662306a36Sopenharmony_ci	if (connector->dpms != DRM_MODE_DPMS_ON)
5762306a36Sopenharmony_ci		return;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	/* just deal with DP (not eDP) here. */
6062306a36Sopenharmony_ci	if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
6162306a36Sopenharmony_ci		struct radeon_connector_atom_dig *dig_connector =
6262306a36Sopenharmony_ci			radeon_connector->con_priv;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci		/* if existing sink type was not DP no need to retrain */
6562306a36Sopenharmony_ci		if (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_DISPLAYPORT)
6662306a36Sopenharmony_ci			return;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci		/* first get sink type as it may be reset after (un)plug */
6962306a36Sopenharmony_ci		dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector);
7062306a36Sopenharmony_ci		/* don't do anything if sink is not display port, i.e.,
7162306a36Sopenharmony_ci		 * passive dp->(dvi|hdmi) adaptor
7262306a36Sopenharmony_ci		 */
7362306a36Sopenharmony_ci		if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT &&
7462306a36Sopenharmony_ci		    radeon_hpd_sense(rdev, radeon_connector->hpd.hpd) &&
7562306a36Sopenharmony_ci		    radeon_dp_needs_link_train(radeon_connector)) {
7662306a36Sopenharmony_ci			/* Don't start link training before we have the DPCD */
7762306a36Sopenharmony_ci			if (!radeon_dp_getdpcd(radeon_connector))
7862306a36Sopenharmony_ci				return;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci			/* Turn the connector off and back on immediately, which
8162306a36Sopenharmony_ci			 * will trigger link training
8262306a36Sopenharmony_ci			 */
8362306a36Sopenharmony_ci			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
8462306a36Sopenharmony_ci			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
8562306a36Sopenharmony_ci		}
8662306a36Sopenharmony_ci	}
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistatic void radeon_property_change_mode(struct drm_encoder *encoder)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	struct drm_crtc *crtc = encoder->crtc;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	if (crtc && crtc->enabled) {
9462306a36Sopenharmony_ci		drm_crtc_helper_set_mode(crtc, &crtc->mode,
9562306a36Sopenharmony_ci					 crtc->x, crtc->y, crtc->primary->fb);
9662306a36Sopenharmony_ci	}
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ciint radeon_get_monitor_bpc(struct drm_connector *connector)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	struct drm_device *dev = connector->dev;
10262306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
10362306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
10462306a36Sopenharmony_ci	struct radeon_connector_atom_dig *dig_connector;
10562306a36Sopenharmony_ci	int bpc = 8;
10662306a36Sopenharmony_ci	int mode_clock, max_tmds_clock;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	switch (connector->connector_type) {
10962306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_DVII:
11062306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_HDMIB:
11162306a36Sopenharmony_ci		if (radeon_connector->use_digital) {
11262306a36Sopenharmony_ci			if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
11362306a36Sopenharmony_ci				if (connector->display_info.bpc)
11462306a36Sopenharmony_ci					bpc = connector->display_info.bpc;
11562306a36Sopenharmony_ci			}
11662306a36Sopenharmony_ci		}
11762306a36Sopenharmony_ci		break;
11862306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_DVID:
11962306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_HDMIA:
12062306a36Sopenharmony_ci		if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
12162306a36Sopenharmony_ci			if (connector->display_info.bpc)
12262306a36Sopenharmony_ci				bpc = connector->display_info.bpc;
12362306a36Sopenharmony_ci		}
12462306a36Sopenharmony_ci		break;
12562306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_DisplayPort:
12662306a36Sopenharmony_ci		dig_connector = radeon_connector->con_priv;
12762306a36Sopenharmony_ci		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
12862306a36Sopenharmony_ci		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) ||
12962306a36Sopenharmony_ci		    drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
13062306a36Sopenharmony_ci			if (connector->display_info.bpc)
13162306a36Sopenharmony_ci				bpc = connector->display_info.bpc;
13262306a36Sopenharmony_ci		}
13362306a36Sopenharmony_ci		break;
13462306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_eDP:
13562306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_LVDS:
13662306a36Sopenharmony_ci		if (connector->display_info.bpc)
13762306a36Sopenharmony_ci			bpc = connector->display_info.bpc;
13862306a36Sopenharmony_ci		else if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
13962306a36Sopenharmony_ci			const struct drm_connector_helper_funcs *connector_funcs =
14062306a36Sopenharmony_ci				connector->helper_private;
14162306a36Sopenharmony_ci			struct drm_encoder *encoder = connector_funcs->best_encoder(connector);
14262306a36Sopenharmony_ci			struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
14362306a36Sopenharmony_ci			struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci			if (dig->lcd_misc & ATOM_PANEL_MISC_V13_6BIT_PER_COLOR)
14662306a36Sopenharmony_ci				bpc = 6;
14762306a36Sopenharmony_ci			else if (dig->lcd_misc & ATOM_PANEL_MISC_V13_8BIT_PER_COLOR)
14862306a36Sopenharmony_ci				bpc = 8;
14962306a36Sopenharmony_ci		}
15062306a36Sopenharmony_ci		break;
15162306a36Sopenharmony_ci	}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
15462306a36Sopenharmony_ci		/* hdmi deep color only implemented on DCE4+ */
15562306a36Sopenharmony_ci		if ((bpc > 8) && !ASIC_IS_DCE4(rdev)) {
15662306a36Sopenharmony_ci			DRM_DEBUG("%s: HDMI deep color %d bpc unsupported. Using 8 bpc.\n",
15762306a36Sopenharmony_ci					  connector->name, bpc);
15862306a36Sopenharmony_ci			bpc = 8;
15962306a36Sopenharmony_ci		}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci		/*
16262306a36Sopenharmony_ci		 * Pre DCE-8 hw can't handle > 12 bpc, and more than 12 bpc doesn't make
16362306a36Sopenharmony_ci		 * much sense without support for > 12 bpc framebuffers. RGB 4:4:4 at
16462306a36Sopenharmony_ci		 * 12 bpc is always supported on hdmi deep color sinks, as this is
16562306a36Sopenharmony_ci		 * required by the HDMI-1.3 spec. Clamp to a safe 12 bpc maximum.
16662306a36Sopenharmony_ci		 */
16762306a36Sopenharmony_ci		if (bpc > 12) {
16862306a36Sopenharmony_ci			DRM_DEBUG("%s: HDMI deep color %d bpc unsupported. Using 12 bpc.\n",
16962306a36Sopenharmony_ci					  connector->name, bpc);
17062306a36Sopenharmony_ci			bpc = 12;
17162306a36Sopenharmony_ci		}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci		/* Any defined maximum tmds clock limit we must not exceed? */
17462306a36Sopenharmony_ci		if (connector->display_info.max_tmds_clock > 0) {
17562306a36Sopenharmony_ci			/* mode_clock is clock in kHz for mode to be modeset on this connector */
17662306a36Sopenharmony_ci			mode_clock = radeon_connector->pixelclock_for_modeset;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci			/* Maximum allowable input clock in kHz */
17962306a36Sopenharmony_ci			max_tmds_clock = connector->display_info.max_tmds_clock;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci			DRM_DEBUG("%s: hdmi mode dotclock %d kHz, max tmds input clock %d kHz.\n",
18262306a36Sopenharmony_ci					  connector->name, mode_clock, max_tmds_clock);
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci			/* Check if bpc is within clock limit. Try to degrade gracefully otherwise */
18562306a36Sopenharmony_ci			if ((bpc == 12) && (mode_clock * 3/2 > max_tmds_clock)) {
18662306a36Sopenharmony_ci				if ((connector->display_info.edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30) &&
18762306a36Sopenharmony_ci					(mode_clock * 5/4 <= max_tmds_clock))
18862306a36Sopenharmony_ci					bpc = 10;
18962306a36Sopenharmony_ci				else
19062306a36Sopenharmony_ci					bpc = 8;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci				DRM_DEBUG("%s: HDMI deep color 12 bpc exceeds max tmds clock. Using %d bpc.\n",
19362306a36Sopenharmony_ci						  connector->name, bpc);
19462306a36Sopenharmony_ci			}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci			if ((bpc == 10) && (mode_clock * 5/4 > max_tmds_clock)) {
19762306a36Sopenharmony_ci				bpc = 8;
19862306a36Sopenharmony_ci				DRM_DEBUG("%s: HDMI deep color 10 bpc exceeds max tmds clock. Using %d bpc.\n",
19962306a36Sopenharmony_ci						  connector->name, bpc);
20062306a36Sopenharmony_ci			}
20162306a36Sopenharmony_ci		} else if (bpc > 8) {
20262306a36Sopenharmony_ci			/* max_tmds_clock missing, but hdmi spec mandates it for deep color. */
20362306a36Sopenharmony_ci			DRM_DEBUG("%s: Required max tmds clock for HDMI deep color missing. Using 8 bpc.\n",
20462306a36Sopenharmony_ci					  connector->name);
20562306a36Sopenharmony_ci			bpc = 8;
20662306a36Sopenharmony_ci		}
20762306a36Sopenharmony_ci	}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	if ((radeon_deep_color == 0) && (bpc > 8)) {
21062306a36Sopenharmony_ci		DRM_DEBUG("%s: Deep color disabled. Set radeon module param deep_color=1 to enable.\n",
21162306a36Sopenharmony_ci				  connector->name);
21262306a36Sopenharmony_ci		bpc = 8;
21362306a36Sopenharmony_ci	}
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	DRM_DEBUG("%s: Display bpc=%d, returned bpc=%d\n",
21662306a36Sopenharmony_ci			  connector->name, connector->display_info.bpc, bpc);
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	return bpc;
21962306a36Sopenharmony_ci}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cistatic void
22262306a36Sopenharmony_ciradeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_connector_status status)
22362306a36Sopenharmony_ci{
22462306a36Sopenharmony_ci	struct drm_device *dev = connector->dev;
22562306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
22662306a36Sopenharmony_ci	struct drm_encoder *best_encoder;
22762306a36Sopenharmony_ci	struct drm_encoder *encoder;
22862306a36Sopenharmony_ci	const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
22962306a36Sopenharmony_ci	bool connected;
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	best_encoder = connector_funcs->best_encoder(connector);
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	drm_connector_for_each_possible_encoder(connector, encoder) {
23462306a36Sopenharmony_ci		if ((encoder == best_encoder) && (status == connector_status_connected))
23562306a36Sopenharmony_ci			connected = true;
23662306a36Sopenharmony_ci		else
23762306a36Sopenharmony_ci			connected = false;
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci		if (rdev->is_atom_bios)
24062306a36Sopenharmony_ci			radeon_atombios_connected_scratch_regs(connector, encoder, connected);
24162306a36Sopenharmony_ci		else
24262306a36Sopenharmony_ci			radeon_combios_connected_scratch_regs(connector, encoder, connected);
24362306a36Sopenharmony_ci	}
24462306a36Sopenharmony_ci}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_cistatic struct drm_encoder *radeon_find_encoder(struct drm_connector *connector, int encoder_type)
24762306a36Sopenharmony_ci{
24862306a36Sopenharmony_ci	struct drm_encoder *encoder;
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	drm_connector_for_each_possible_encoder(connector, encoder) {
25162306a36Sopenharmony_ci		if (encoder->encoder_type == encoder_type)
25262306a36Sopenharmony_ci			return encoder;
25362306a36Sopenharmony_ci	}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	return NULL;
25662306a36Sopenharmony_ci}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_cistruct edid *radeon_connector_edid(struct drm_connector *connector)
25962306a36Sopenharmony_ci{
26062306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
26162306a36Sopenharmony_ci	struct drm_property_blob *edid_blob = connector->edid_blob_ptr;
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	if (radeon_connector->edid) {
26462306a36Sopenharmony_ci		return radeon_connector->edid;
26562306a36Sopenharmony_ci	} else if (edid_blob) {
26662306a36Sopenharmony_ci		struct edid *edid = kmemdup(edid_blob->data, edid_blob->length, GFP_KERNEL);
26762306a36Sopenharmony_ci		if (edid)
26862306a36Sopenharmony_ci			radeon_connector->edid = edid;
26962306a36Sopenharmony_ci	}
27062306a36Sopenharmony_ci	return radeon_connector->edid;
27162306a36Sopenharmony_ci}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_cistatic void radeon_connector_get_edid(struct drm_connector *connector)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	struct drm_device *dev = connector->dev;
27662306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
27762306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	if (radeon_connector->edid)
28062306a36Sopenharmony_ci		return;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	/* on hw with routers, select right port */
28362306a36Sopenharmony_ci	if (radeon_connector->router.ddc_valid)
28462306a36Sopenharmony_ci		radeon_router_select_ddc_port(radeon_connector);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
28762306a36Sopenharmony_ci	     ENCODER_OBJECT_ID_NONE) &&
28862306a36Sopenharmony_ci	    radeon_connector->ddc_bus->has_aux) {
28962306a36Sopenharmony_ci		radeon_connector->edid = drm_get_edid(connector,
29062306a36Sopenharmony_ci						      &radeon_connector->ddc_bus->aux.ddc);
29162306a36Sopenharmony_ci	} else if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
29262306a36Sopenharmony_ci		   (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
29362306a36Sopenharmony_ci		struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci		if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
29662306a36Sopenharmony_ci		     dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) &&
29762306a36Sopenharmony_ci		    radeon_connector->ddc_bus->has_aux)
29862306a36Sopenharmony_ci			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
29962306a36Sopenharmony_ci							      &radeon_connector->ddc_bus->aux.ddc);
30062306a36Sopenharmony_ci		else if (radeon_connector->ddc_bus)
30162306a36Sopenharmony_ci			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
30262306a36Sopenharmony_ci							      &radeon_connector->ddc_bus->adapter);
30362306a36Sopenharmony_ci	} else if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC &&
30462306a36Sopenharmony_ci		   connector->connector_type == DRM_MODE_CONNECTOR_LVDS &&
30562306a36Sopenharmony_ci		   radeon_connector->ddc_bus) {
30662306a36Sopenharmony_ci		radeon_connector->edid = drm_get_edid_switcheroo(&radeon_connector->base,
30762306a36Sopenharmony_ci								 &radeon_connector->ddc_bus->adapter);
30862306a36Sopenharmony_ci	} else if (radeon_connector->ddc_bus) {
30962306a36Sopenharmony_ci		radeon_connector->edid = drm_get_edid(&radeon_connector->base,
31062306a36Sopenharmony_ci						      &radeon_connector->ddc_bus->adapter);
31162306a36Sopenharmony_ci	}
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	if (!radeon_connector->edid) {
31462306a36Sopenharmony_ci		/* don't fetch the edid from the vbios if ddc fails and runpm is
31562306a36Sopenharmony_ci		 * enabled so we report disconnected.
31662306a36Sopenharmony_ci		 */
31762306a36Sopenharmony_ci		if ((rdev->flags & RADEON_IS_PX) && (radeon_runtime_pm != 0))
31862306a36Sopenharmony_ci			return;
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci		if (rdev->is_atom_bios) {
32162306a36Sopenharmony_ci			/* some laptops provide a hardcoded edid in rom for LCDs */
32262306a36Sopenharmony_ci			if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) ||
32362306a36Sopenharmony_ci			     (connector->connector_type == DRM_MODE_CONNECTOR_eDP)))
32462306a36Sopenharmony_ci				radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
32562306a36Sopenharmony_ci		} else {
32662306a36Sopenharmony_ci			/* some servers provide a hardcoded edid in rom for KVMs */
32762306a36Sopenharmony_ci			radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
32862306a36Sopenharmony_ci		}
32962306a36Sopenharmony_ci	}
33062306a36Sopenharmony_ci}
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_cistatic void radeon_connector_free_edid(struct drm_connector *connector)
33362306a36Sopenharmony_ci{
33462306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	kfree(radeon_connector->edid);
33762306a36Sopenharmony_ci	radeon_connector->edid = NULL;
33862306a36Sopenharmony_ci}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_cistatic int radeon_ddc_get_modes(struct drm_connector *connector)
34162306a36Sopenharmony_ci{
34262306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
34362306a36Sopenharmony_ci	int ret;
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	if (radeon_connector->edid) {
34662306a36Sopenharmony_ci		drm_connector_update_edid_property(connector, radeon_connector->edid);
34762306a36Sopenharmony_ci		ret = drm_add_edid_modes(connector, radeon_connector->edid);
34862306a36Sopenharmony_ci		return ret;
34962306a36Sopenharmony_ci	}
35062306a36Sopenharmony_ci	drm_connector_update_edid_property(connector, NULL);
35162306a36Sopenharmony_ci	return 0;
35262306a36Sopenharmony_ci}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_cistatic struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
35562306a36Sopenharmony_ci{
35662306a36Sopenharmony_ci	struct drm_encoder *encoder;
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	/* pick the first one */
35962306a36Sopenharmony_ci	drm_connector_for_each_possible_encoder(connector, encoder)
36062306a36Sopenharmony_ci		return encoder;
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	return NULL;
36362306a36Sopenharmony_ci}
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_cistatic void radeon_get_native_mode(struct drm_connector *connector)
36662306a36Sopenharmony_ci{
36762306a36Sopenharmony_ci	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
36862306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder;
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	if (encoder == NULL)
37162306a36Sopenharmony_ci		return;
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	radeon_encoder = to_radeon_encoder(encoder);
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	if (!list_empty(&connector->probed_modes)) {
37662306a36Sopenharmony_ci		struct drm_display_mode *preferred_mode =
37762306a36Sopenharmony_ci			list_first_entry(&connector->probed_modes,
37862306a36Sopenharmony_ci					 struct drm_display_mode, head);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci		radeon_encoder->native_mode = *preferred_mode;
38162306a36Sopenharmony_ci	} else {
38262306a36Sopenharmony_ci		radeon_encoder->native_mode.clock = 0;
38362306a36Sopenharmony_ci	}
38462306a36Sopenharmony_ci}
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci/*
38762306a36Sopenharmony_ci * radeon_connector_analog_encoder_conflict_solve
38862306a36Sopenharmony_ci * - search for other connectors sharing this encoder
38962306a36Sopenharmony_ci *   if priority is true, then set them disconnected if this is connected
39062306a36Sopenharmony_ci *   if priority is false, set us disconnected if they are connected
39162306a36Sopenharmony_ci */
39262306a36Sopenharmony_cistatic enum drm_connector_status
39362306a36Sopenharmony_ciradeon_connector_analog_encoder_conflict_solve(struct drm_connector *connector,
39462306a36Sopenharmony_ci					       struct drm_encoder *encoder,
39562306a36Sopenharmony_ci					       enum drm_connector_status current_status,
39662306a36Sopenharmony_ci					       bool priority)
39762306a36Sopenharmony_ci{
39862306a36Sopenharmony_ci	struct drm_device *dev = connector->dev;
39962306a36Sopenharmony_ci	struct drm_connector *conflict;
40062306a36Sopenharmony_ci	struct radeon_connector *radeon_conflict;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	list_for_each_entry(conflict, &dev->mode_config.connector_list, head) {
40362306a36Sopenharmony_ci		struct drm_encoder *enc;
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci		if (conflict == connector)
40662306a36Sopenharmony_ci			continue;
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci		radeon_conflict = to_radeon_connector(conflict);
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci		drm_connector_for_each_possible_encoder(conflict, enc) {
41162306a36Sopenharmony_ci			/* if the IDs match */
41262306a36Sopenharmony_ci			if (enc == encoder) {
41362306a36Sopenharmony_ci				if (conflict->status != connector_status_connected)
41462306a36Sopenharmony_ci					continue;
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci				if (radeon_conflict->use_digital)
41762306a36Sopenharmony_ci					continue;
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci				if (priority) {
42062306a36Sopenharmony_ci					DRM_DEBUG_KMS("1: conflicting encoders switching off %s\n",
42162306a36Sopenharmony_ci						      conflict->name);
42262306a36Sopenharmony_ci					DRM_DEBUG_KMS("in favor of %s\n",
42362306a36Sopenharmony_ci						      connector->name);
42462306a36Sopenharmony_ci					conflict->status = connector_status_disconnected;
42562306a36Sopenharmony_ci					radeon_connector_update_scratch_regs(conflict, connector_status_disconnected);
42662306a36Sopenharmony_ci				} else {
42762306a36Sopenharmony_ci					DRM_DEBUG_KMS("2: conflicting encoders switching off %s\n",
42862306a36Sopenharmony_ci						      connector->name);
42962306a36Sopenharmony_ci					DRM_DEBUG_KMS("in favor of %s\n",
43062306a36Sopenharmony_ci						      conflict->name);
43162306a36Sopenharmony_ci					current_status = connector_status_disconnected;
43262306a36Sopenharmony_ci				}
43362306a36Sopenharmony_ci				break;
43462306a36Sopenharmony_ci			}
43562306a36Sopenharmony_ci		}
43662306a36Sopenharmony_ci	}
43762306a36Sopenharmony_ci	return current_status;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci}
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_cistatic struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encoder)
44262306a36Sopenharmony_ci{
44362306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
44462306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
44562306a36Sopenharmony_ci	struct drm_display_mode *mode = NULL;
44662306a36Sopenharmony_ci	struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	if (native_mode->hdisplay != 0 &&
44962306a36Sopenharmony_ci	    native_mode->vdisplay != 0 &&
45062306a36Sopenharmony_ci	    native_mode->clock != 0) {
45162306a36Sopenharmony_ci		mode = drm_mode_duplicate(dev, native_mode);
45262306a36Sopenharmony_ci		if (!mode)
45362306a36Sopenharmony_ci			return NULL;
45462306a36Sopenharmony_ci		mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
45562306a36Sopenharmony_ci		drm_mode_set_name(mode);
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci		DRM_DEBUG_KMS("Adding native panel mode %s\n", mode->name);
45862306a36Sopenharmony_ci	} else if (native_mode->hdisplay != 0 &&
45962306a36Sopenharmony_ci		   native_mode->vdisplay != 0) {
46062306a36Sopenharmony_ci		/* mac laptops without an edid */
46162306a36Sopenharmony_ci		/* Note that this is not necessarily the exact panel mode,
46262306a36Sopenharmony_ci		 * but an approximation based on the cvt formula.  For these
46362306a36Sopenharmony_ci		 * systems we should ideally read the mode info out of the
46462306a36Sopenharmony_ci		 * registers or add a mode table, but this works and is much
46562306a36Sopenharmony_ci		 * simpler.
46662306a36Sopenharmony_ci		 */
46762306a36Sopenharmony_ci		mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay, 60, true, false, false);
46862306a36Sopenharmony_ci		if (!mode)
46962306a36Sopenharmony_ci			return NULL;
47062306a36Sopenharmony_ci		mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
47162306a36Sopenharmony_ci		DRM_DEBUG_KMS("Adding cvt approximation of native panel mode %s\n", mode->name);
47262306a36Sopenharmony_ci	}
47362306a36Sopenharmony_ci	return mode;
47462306a36Sopenharmony_ci}
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_cistatic void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_connector *connector)
47762306a36Sopenharmony_ci{
47862306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
47962306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
48062306a36Sopenharmony_ci	struct drm_display_mode *mode = NULL;
48162306a36Sopenharmony_ci	struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
48262306a36Sopenharmony_ci	int i;
48362306a36Sopenharmony_ci	struct mode_size {
48462306a36Sopenharmony_ci		int w;
48562306a36Sopenharmony_ci		int h;
48662306a36Sopenharmony_ci	} common_modes[17] = {
48762306a36Sopenharmony_ci		{ 640,  480},
48862306a36Sopenharmony_ci		{ 720,  480},
48962306a36Sopenharmony_ci		{ 800,  600},
49062306a36Sopenharmony_ci		{ 848,  480},
49162306a36Sopenharmony_ci		{1024,  768},
49262306a36Sopenharmony_ci		{1152,  768},
49362306a36Sopenharmony_ci		{1280,  720},
49462306a36Sopenharmony_ci		{1280,  800},
49562306a36Sopenharmony_ci		{1280,  854},
49662306a36Sopenharmony_ci		{1280,  960},
49762306a36Sopenharmony_ci		{1280, 1024},
49862306a36Sopenharmony_ci		{1440,  900},
49962306a36Sopenharmony_ci		{1400, 1050},
50062306a36Sopenharmony_ci		{1680, 1050},
50162306a36Sopenharmony_ci		{1600, 1200},
50262306a36Sopenharmony_ci		{1920, 1080},
50362306a36Sopenharmony_ci		{1920, 1200}
50462306a36Sopenharmony_ci	};
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	for (i = 0; i < 17; i++) {
50762306a36Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) {
50862306a36Sopenharmony_ci			if (common_modes[i].w > 1024 ||
50962306a36Sopenharmony_ci			    common_modes[i].h > 768)
51062306a36Sopenharmony_ci				continue;
51162306a36Sopenharmony_ci		}
51262306a36Sopenharmony_ci		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
51362306a36Sopenharmony_ci			if (common_modes[i].w > native_mode->hdisplay ||
51462306a36Sopenharmony_ci			    common_modes[i].h > native_mode->vdisplay ||
51562306a36Sopenharmony_ci			    (common_modes[i].w == native_mode->hdisplay &&
51662306a36Sopenharmony_ci			     common_modes[i].h == native_mode->vdisplay))
51762306a36Sopenharmony_ci				continue;
51862306a36Sopenharmony_ci		}
51962306a36Sopenharmony_ci		if (common_modes[i].w < 320 || common_modes[i].h < 200)
52062306a36Sopenharmony_ci			continue;
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci		mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
52362306a36Sopenharmony_ci		drm_mode_probed_add(connector, mode);
52462306a36Sopenharmony_ci	}
52562306a36Sopenharmony_ci}
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_cistatic int radeon_connector_set_property(struct drm_connector *connector, struct drm_property *property,
52862306a36Sopenharmony_ci				  uint64_t val)
52962306a36Sopenharmony_ci{
53062306a36Sopenharmony_ci	struct drm_device *dev = connector->dev;
53162306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
53262306a36Sopenharmony_ci	struct drm_encoder *encoder;
53362306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	if (property == rdev->mode_info.coherent_mode_property) {
53662306a36Sopenharmony_ci		struct radeon_encoder_atom_dig *dig;
53762306a36Sopenharmony_ci		bool new_coherent_mode;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci		/* need to find digital encoder on connector */
54062306a36Sopenharmony_ci		encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
54162306a36Sopenharmony_ci		if (!encoder)
54262306a36Sopenharmony_ci			return 0;
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci		radeon_encoder = to_radeon_encoder(encoder);
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci		if (!radeon_encoder->enc_priv)
54762306a36Sopenharmony_ci			return 0;
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci		dig = radeon_encoder->enc_priv;
55062306a36Sopenharmony_ci		new_coherent_mode = val ? true : false;
55162306a36Sopenharmony_ci		if (dig->coherent_mode != new_coherent_mode) {
55262306a36Sopenharmony_ci			dig->coherent_mode = new_coherent_mode;
55362306a36Sopenharmony_ci			radeon_property_change_mode(&radeon_encoder->base);
55462306a36Sopenharmony_ci		}
55562306a36Sopenharmony_ci	}
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	if (property == rdev->mode_info.audio_property) {
55862306a36Sopenharmony_ci		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
55962306a36Sopenharmony_ci		/* need to find digital encoder on connector */
56062306a36Sopenharmony_ci		encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
56162306a36Sopenharmony_ci		if (!encoder)
56262306a36Sopenharmony_ci			return 0;
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci		radeon_encoder = to_radeon_encoder(encoder);
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci		if (radeon_connector->audio != val) {
56762306a36Sopenharmony_ci			radeon_connector->audio = val;
56862306a36Sopenharmony_ci			radeon_property_change_mode(&radeon_encoder->base);
56962306a36Sopenharmony_ci		}
57062306a36Sopenharmony_ci	}
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	if (property == rdev->mode_info.dither_property) {
57362306a36Sopenharmony_ci		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
57462306a36Sopenharmony_ci		/* need to find digital encoder on connector */
57562306a36Sopenharmony_ci		encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
57662306a36Sopenharmony_ci		if (!encoder)
57762306a36Sopenharmony_ci			return 0;
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci		radeon_encoder = to_radeon_encoder(encoder);
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci		if (radeon_connector->dither != val) {
58262306a36Sopenharmony_ci			radeon_connector->dither = val;
58362306a36Sopenharmony_ci			radeon_property_change_mode(&radeon_encoder->base);
58462306a36Sopenharmony_ci		}
58562306a36Sopenharmony_ci	}
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	if (property == rdev->mode_info.underscan_property) {
58862306a36Sopenharmony_ci		/* need to find digital encoder on connector */
58962306a36Sopenharmony_ci		encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
59062306a36Sopenharmony_ci		if (!encoder)
59162306a36Sopenharmony_ci			return 0;
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci		radeon_encoder = to_radeon_encoder(encoder);
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci		if (radeon_encoder->underscan_type != val) {
59662306a36Sopenharmony_ci			radeon_encoder->underscan_type = val;
59762306a36Sopenharmony_ci			radeon_property_change_mode(&radeon_encoder->base);
59862306a36Sopenharmony_ci		}
59962306a36Sopenharmony_ci	}
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	if (property == rdev->mode_info.underscan_hborder_property) {
60262306a36Sopenharmony_ci		/* need to find digital encoder on connector */
60362306a36Sopenharmony_ci		encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
60462306a36Sopenharmony_ci		if (!encoder)
60562306a36Sopenharmony_ci			return 0;
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci		radeon_encoder = to_radeon_encoder(encoder);
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci		if (radeon_encoder->underscan_hborder != val) {
61062306a36Sopenharmony_ci			radeon_encoder->underscan_hborder = val;
61162306a36Sopenharmony_ci			radeon_property_change_mode(&radeon_encoder->base);
61262306a36Sopenharmony_ci		}
61362306a36Sopenharmony_ci	}
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci	if (property == rdev->mode_info.underscan_vborder_property) {
61662306a36Sopenharmony_ci		/* need to find digital encoder on connector */
61762306a36Sopenharmony_ci		encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
61862306a36Sopenharmony_ci		if (!encoder)
61962306a36Sopenharmony_ci			return 0;
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci		radeon_encoder = to_radeon_encoder(encoder);
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci		if (radeon_encoder->underscan_vborder != val) {
62462306a36Sopenharmony_ci			radeon_encoder->underscan_vborder = val;
62562306a36Sopenharmony_ci			radeon_property_change_mode(&radeon_encoder->base);
62662306a36Sopenharmony_ci		}
62762306a36Sopenharmony_ci	}
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	if (property == rdev->mode_info.tv_std_property) {
63062306a36Sopenharmony_ci		encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TVDAC);
63162306a36Sopenharmony_ci		if (!encoder) {
63262306a36Sopenharmony_ci			encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_DAC);
63362306a36Sopenharmony_ci		}
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci		if (!encoder)
63662306a36Sopenharmony_ci			return 0;
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci		radeon_encoder = to_radeon_encoder(encoder);
63962306a36Sopenharmony_ci		if (!radeon_encoder->enc_priv)
64062306a36Sopenharmony_ci			return 0;
64162306a36Sopenharmony_ci		if (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom) {
64262306a36Sopenharmony_ci			struct radeon_encoder_atom_dac *dac_int;
64362306a36Sopenharmony_ci			dac_int = radeon_encoder->enc_priv;
64462306a36Sopenharmony_ci			dac_int->tv_std = val;
64562306a36Sopenharmony_ci		} else {
64662306a36Sopenharmony_ci			struct radeon_encoder_tv_dac *dac_int;
64762306a36Sopenharmony_ci			dac_int = radeon_encoder->enc_priv;
64862306a36Sopenharmony_ci			dac_int->tv_std = val;
64962306a36Sopenharmony_ci		}
65062306a36Sopenharmony_ci		radeon_property_change_mode(&radeon_encoder->base);
65162306a36Sopenharmony_ci	}
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	if (property == rdev->mode_info.load_detect_property) {
65462306a36Sopenharmony_ci		struct radeon_connector *radeon_connector =
65562306a36Sopenharmony_ci			to_radeon_connector(connector);
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci		if (val == 0)
65862306a36Sopenharmony_ci			radeon_connector->dac_load_detect = false;
65962306a36Sopenharmony_ci		else
66062306a36Sopenharmony_ci			radeon_connector->dac_load_detect = true;
66162306a36Sopenharmony_ci	}
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	if (property == rdev->mode_info.tmds_pll_property) {
66462306a36Sopenharmony_ci		struct radeon_encoder_int_tmds *tmds = NULL;
66562306a36Sopenharmony_ci		bool ret = false;
66662306a36Sopenharmony_ci		/* need to find digital encoder on connector */
66762306a36Sopenharmony_ci		encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
66862306a36Sopenharmony_ci		if (!encoder)
66962306a36Sopenharmony_ci			return 0;
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci		radeon_encoder = to_radeon_encoder(encoder);
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci		tmds = radeon_encoder->enc_priv;
67462306a36Sopenharmony_ci		if (!tmds)
67562306a36Sopenharmony_ci			return 0;
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci		if (val == 0) {
67862306a36Sopenharmony_ci			if (rdev->is_atom_bios)
67962306a36Sopenharmony_ci				ret = radeon_atombios_get_tmds_info(radeon_encoder, tmds);
68062306a36Sopenharmony_ci			else
68162306a36Sopenharmony_ci				ret = radeon_legacy_get_tmds_info_from_combios(radeon_encoder, tmds);
68262306a36Sopenharmony_ci		}
68362306a36Sopenharmony_ci		if (val == 1 || !ret)
68462306a36Sopenharmony_ci			radeon_legacy_get_tmds_info_from_table(radeon_encoder, tmds);
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci		radeon_property_change_mode(&radeon_encoder->base);
68762306a36Sopenharmony_ci	}
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	if (property == dev->mode_config.scaling_mode_property) {
69062306a36Sopenharmony_ci		enum radeon_rmx_type rmx_type;
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_ci		if (connector->encoder)
69362306a36Sopenharmony_ci			radeon_encoder = to_radeon_encoder(connector->encoder);
69462306a36Sopenharmony_ci		else {
69562306a36Sopenharmony_ci			const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
69662306a36Sopenharmony_ci			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
69762306a36Sopenharmony_ci		}
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci		switch (val) {
70062306a36Sopenharmony_ci		default:
70162306a36Sopenharmony_ci		case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break;
70262306a36Sopenharmony_ci		case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break;
70362306a36Sopenharmony_ci		case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break;
70462306a36Sopenharmony_ci		case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break;
70562306a36Sopenharmony_ci		}
70662306a36Sopenharmony_ci		if (radeon_encoder->rmx_type == rmx_type)
70762306a36Sopenharmony_ci			return 0;
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci		if ((rmx_type != DRM_MODE_SCALE_NONE) &&
71062306a36Sopenharmony_ci		    (radeon_encoder->native_mode.clock == 0))
71162306a36Sopenharmony_ci			return 0;
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci		radeon_encoder->rmx_type = rmx_type;
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci		radeon_property_change_mode(&radeon_encoder->base);
71662306a36Sopenharmony_ci	}
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	if (property == rdev->mode_info.output_csc_property) {
71962306a36Sopenharmony_ci		if (connector->encoder)
72062306a36Sopenharmony_ci			radeon_encoder = to_radeon_encoder(connector->encoder);
72162306a36Sopenharmony_ci		else {
72262306a36Sopenharmony_ci			const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
72362306a36Sopenharmony_ci			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
72462306a36Sopenharmony_ci		}
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci		if (radeon_encoder->output_csc == val)
72762306a36Sopenharmony_ci			return 0;
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci		radeon_encoder->output_csc = val;
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci		if (connector->encoder && connector->encoder->crtc) {
73262306a36Sopenharmony_ci			struct drm_crtc *crtc  = connector->encoder->crtc;
73362306a36Sopenharmony_ci			struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci			radeon_crtc->output_csc = radeon_encoder->output_csc;
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci			/*
73862306a36Sopenharmony_ci			 * Our .gamma_set assumes the .gamma_store has been
73962306a36Sopenharmony_ci			 * prefilled and don't care about its arguments.
74062306a36Sopenharmony_ci			 */
74162306a36Sopenharmony_ci			crtc->funcs->gamma_set(crtc, NULL, NULL, NULL, 0, NULL);
74262306a36Sopenharmony_ci		}
74362306a36Sopenharmony_ci	}
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci	return 0;
74662306a36Sopenharmony_ci}
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_cistatic void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
74962306a36Sopenharmony_ci					  struct drm_connector *connector)
75062306a36Sopenharmony_ci{
75162306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder =	to_radeon_encoder(encoder);
75262306a36Sopenharmony_ci	struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
75362306a36Sopenharmony_ci	struct drm_display_mode *t, *mode;
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci	/* If the EDID preferred mode doesn't match the native mode, use it */
75662306a36Sopenharmony_ci	list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
75762306a36Sopenharmony_ci		if (mode->type & DRM_MODE_TYPE_PREFERRED) {
75862306a36Sopenharmony_ci			if (mode->hdisplay != native_mode->hdisplay ||
75962306a36Sopenharmony_ci			    mode->vdisplay != native_mode->vdisplay)
76062306a36Sopenharmony_ci				drm_mode_copy(native_mode, mode);
76162306a36Sopenharmony_ci		}
76262306a36Sopenharmony_ci	}
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_ci	/* Try to get native mode details from EDID if necessary */
76562306a36Sopenharmony_ci	if (!native_mode->clock) {
76662306a36Sopenharmony_ci		list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
76762306a36Sopenharmony_ci			if (mode->hdisplay == native_mode->hdisplay &&
76862306a36Sopenharmony_ci			    mode->vdisplay == native_mode->vdisplay) {
76962306a36Sopenharmony_ci				drm_mode_copy(native_mode, mode);
77062306a36Sopenharmony_ci				drm_mode_set_crtcinfo(native_mode, CRTC_INTERLACE_HALVE_V);
77162306a36Sopenharmony_ci				DRM_DEBUG_KMS("Determined LVDS native mode details from EDID\n");
77262306a36Sopenharmony_ci				break;
77362306a36Sopenharmony_ci			}
77462306a36Sopenharmony_ci		}
77562306a36Sopenharmony_ci	}
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	if (!native_mode->clock) {
77862306a36Sopenharmony_ci		DRM_DEBUG_KMS("No LVDS native mode details, disabling RMX\n");
77962306a36Sopenharmony_ci		radeon_encoder->rmx_type = RMX_OFF;
78062306a36Sopenharmony_ci	}
78162306a36Sopenharmony_ci}
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_cistatic int radeon_lvds_get_modes(struct drm_connector *connector)
78462306a36Sopenharmony_ci{
78562306a36Sopenharmony_ci	struct drm_encoder *encoder;
78662306a36Sopenharmony_ci	int ret = 0;
78762306a36Sopenharmony_ci	struct drm_display_mode *mode;
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci	radeon_connector_get_edid(connector);
79062306a36Sopenharmony_ci	ret = radeon_ddc_get_modes(connector);
79162306a36Sopenharmony_ci	if (ret > 0) {
79262306a36Sopenharmony_ci		encoder = radeon_best_single_encoder(connector);
79362306a36Sopenharmony_ci		if (encoder) {
79462306a36Sopenharmony_ci			radeon_fixup_lvds_native_mode(encoder, connector);
79562306a36Sopenharmony_ci			/* add scaled modes */
79662306a36Sopenharmony_ci			radeon_add_common_modes(encoder, connector);
79762306a36Sopenharmony_ci		}
79862306a36Sopenharmony_ci		return ret;
79962306a36Sopenharmony_ci	}
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci	encoder = radeon_best_single_encoder(connector);
80262306a36Sopenharmony_ci	if (!encoder)
80362306a36Sopenharmony_ci		return 0;
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci	/* we have no EDID modes */
80662306a36Sopenharmony_ci	mode = radeon_fp_native_mode(encoder);
80762306a36Sopenharmony_ci	if (mode) {
80862306a36Sopenharmony_ci		ret = 1;
80962306a36Sopenharmony_ci		drm_mode_probed_add(connector, mode);
81062306a36Sopenharmony_ci		/* add the width/height from vbios tables if available */
81162306a36Sopenharmony_ci		connector->display_info.width_mm = mode->width_mm;
81262306a36Sopenharmony_ci		connector->display_info.height_mm = mode->height_mm;
81362306a36Sopenharmony_ci		/* add scaled modes */
81462306a36Sopenharmony_ci		radeon_add_common_modes(encoder, connector);
81562306a36Sopenharmony_ci	}
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	return ret;
81862306a36Sopenharmony_ci}
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_cistatic enum drm_mode_status radeon_lvds_mode_valid(struct drm_connector *connector,
82162306a36Sopenharmony_ci				  struct drm_display_mode *mode)
82262306a36Sopenharmony_ci{
82362306a36Sopenharmony_ci	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
82462306a36Sopenharmony_ci
82562306a36Sopenharmony_ci	if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
82662306a36Sopenharmony_ci		return MODE_PANEL;
82762306a36Sopenharmony_ci
82862306a36Sopenharmony_ci	if (encoder) {
82962306a36Sopenharmony_ci		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
83062306a36Sopenharmony_ci		struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci		/* AVIVO hardware supports downscaling modes larger than the panel
83362306a36Sopenharmony_ci		 * to the panel size, but I'm not sure this is desirable.
83462306a36Sopenharmony_ci		 */
83562306a36Sopenharmony_ci		if ((mode->hdisplay > native_mode->hdisplay) ||
83662306a36Sopenharmony_ci		    (mode->vdisplay > native_mode->vdisplay))
83762306a36Sopenharmony_ci			return MODE_PANEL;
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci		/* if scaling is disabled, block non-native modes */
84062306a36Sopenharmony_ci		if (radeon_encoder->rmx_type == RMX_OFF) {
84162306a36Sopenharmony_ci			if ((mode->hdisplay != native_mode->hdisplay) ||
84262306a36Sopenharmony_ci			    (mode->vdisplay != native_mode->vdisplay))
84362306a36Sopenharmony_ci				return MODE_PANEL;
84462306a36Sopenharmony_ci		}
84562306a36Sopenharmony_ci	}
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	return MODE_OK;
84862306a36Sopenharmony_ci}
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_cistatic enum drm_connector_status
85162306a36Sopenharmony_ciradeon_lvds_detect(struct drm_connector *connector, bool force)
85262306a36Sopenharmony_ci{
85362306a36Sopenharmony_ci	struct drm_device *dev = connector->dev;
85462306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
85562306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
85662306a36Sopenharmony_ci	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
85762306a36Sopenharmony_ci	enum drm_connector_status ret = connector_status_disconnected;
85862306a36Sopenharmony_ci	int r;
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci	if (!drm_kms_helper_is_poll_worker()) {
86162306a36Sopenharmony_ci		r = pm_runtime_get_sync(connector->dev->dev);
86262306a36Sopenharmony_ci		if (r < 0) {
86362306a36Sopenharmony_ci			pm_runtime_put_autosuspend(connector->dev->dev);
86462306a36Sopenharmony_ci			return connector_status_disconnected;
86562306a36Sopenharmony_ci		}
86662306a36Sopenharmony_ci	}
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	if (encoder) {
86962306a36Sopenharmony_ci		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
87062306a36Sopenharmony_ci		struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci		/* check if panel is valid */
87362306a36Sopenharmony_ci		if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240)
87462306a36Sopenharmony_ci			ret = connector_status_connected;
87562306a36Sopenharmony_ci		/* don't fetch the edid from the vbios if ddc fails and runpm is
87662306a36Sopenharmony_ci		 * enabled so we report disconnected.
87762306a36Sopenharmony_ci		 */
87862306a36Sopenharmony_ci		if ((rdev->flags & RADEON_IS_PX) && (radeon_runtime_pm != 0))
87962306a36Sopenharmony_ci			ret = connector_status_disconnected;
88062306a36Sopenharmony_ci	}
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	/* check for edid as well */
88362306a36Sopenharmony_ci	radeon_connector_get_edid(connector);
88462306a36Sopenharmony_ci	if (radeon_connector->edid)
88562306a36Sopenharmony_ci		ret = connector_status_connected;
88662306a36Sopenharmony_ci	/* check acpi lid status ??? */
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_ci	radeon_connector_update_scratch_regs(connector, ret);
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci	if (!drm_kms_helper_is_poll_worker()) {
89162306a36Sopenharmony_ci		pm_runtime_mark_last_busy(connector->dev->dev);
89262306a36Sopenharmony_ci		pm_runtime_put_autosuspend(connector->dev->dev);
89362306a36Sopenharmony_ci	}
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	return ret;
89662306a36Sopenharmony_ci}
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_cistatic void radeon_connector_unregister(struct drm_connector *connector)
89962306a36Sopenharmony_ci{
90062306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci	if (radeon_connector->ddc_bus && radeon_connector->ddc_bus->has_aux) {
90362306a36Sopenharmony_ci		drm_dp_aux_unregister(&radeon_connector->ddc_bus->aux);
90462306a36Sopenharmony_ci		radeon_connector->ddc_bus->has_aux = false;
90562306a36Sopenharmony_ci	}
90662306a36Sopenharmony_ci}
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_cistatic void radeon_connector_destroy(struct drm_connector *connector)
90962306a36Sopenharmony_ci{
91062306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	radeon_connector_free_edid(connector);
91362306a36Sopenharmony_ci	kfree(radeon_connector->con_priv);
91462306a36Sopenharmony_ci	drm_connector_unregister(connector);
91562306a36Sopenharmony_ci	drm_connector_cleanup(connector);
91662306a36Sopenharmony_ci	kfree(connector);
91762306a36Sopenharmony_ci}
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_cistatic int radeon_lvds_set_property(struct drm_connector *connector,
92062306a36Sopenharmony_ci				    struct drm_property *property,
92162306a36Sopenharmony_ci				    uint64_t value)
92262306a36Sopenharmony_ci{
92362306a36Sopenharmony_ci	struct drm_device *dev = connector->dev;
92462306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder;
92562306a36Sopenharmony_ci	enum radeon_rmx_type rmx_type;
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	DRM_DEBUG_KMS("\n");
92862306a36Sopenharmony_ci	if (property != dev->mode_config.scaling_mode_property)
92962306a36Sopenharmony_ci		return 0;
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci	if (connector->encoder)
93262306a36Sopenharmony_ci		radeon_encoder = to_radeon_encoder(connector->encoder);
93362306a36Sopenharmony_ci	else {
93462306a36Sopenharmony_ci		const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
93562306a36Sopenharmony_ci		radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
93662306a36Sopenharmony_ci	}
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	switch (value) {
93962306a36Sopenharmony_ci	case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break;
94062306a36Sopenharmony_ci	case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break;
94162306a36Sopenharmony_ci	case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break;
94262306a36Sopenharmony_ci	default:
94362306a36Sopenharmony_ci	case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break;
94462306a36Sopenharmony_ci	}
94562306a36Sopenharmony_ci	if (radeon_encoder->rmx_type == rmx_type)
94662306a36Sopenharmony_ci		return 0;
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_ci	radeon_encoder->rmx_type = rmx_type;
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	radeon_property_change_mode(&radeon_encoder->base);
95162306a36Sopenharmony_ci	return 0;
95262306a36Sopenharmony_ci}
95362306a36Sopenharmony_ci
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_cistatic const struct drm_connector_helper_funcs radeon_lvds_connector_helper_funcs = {
95662306a36Sopenharmony_ci	.get_modes = radeon_lvds_get_modes,
95762306a36Sopenharmony_ci	.mode_valid = radeon_lvds_mode_valid,
95862306a36Sopenharmony_ci	.best_encoder = radeon_best_single_encoder,
95962306a36Sopenharmony_ci};
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_cistatic const struct drm_connector_funcs radeon_lvds_connector_funcs = {
96262306a36Sopenharmony_ci	.dpms = drm_helper_connector_dpms,
96362306a36Sopenharmony_ci	.detect = radeon_lvds_detect,
96462306a36Sopenharmony_ci	.fill_modes = drm_helper_probe_single_connector_modes,
96562306a36Sopenharmony_ci	.early_unregister = radeon_connector_unregister,
96662306a36Sopenharmony_ci	.destroy = radeon_connector_destroy,
96762306a36Sopenharmony_ci	.set_property = radeon_lvds_set_property,
96862306a36Sopenharmony_ci};
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_cistatic int radeon_vga_get_modes(struct drm_connector *connector)
97162306a36Sopenharmony_ci{
97262306a36Sopenharmony_ci	int ret;
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ci	radeon_connector_get_edid(connector);
97562306a36Sopenharmony_ci	ret = radeon_ddc_get_modes(connector);
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	radeon_get_native_mode(connector);
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	return ret;
98062306a36Sopenharmony_ci}
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_cistatic enum drm_mode_status radeon_vga_mode_valid(struct drm_connector *connector,
98362306a36Sopenharmony_ci				  struct drm_display_mode *mode)
98462306a36Sopenharmony_ci{
98562306a36Sopenharmony_ci	struct drm_device *dev = connector->dev;
98662306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	/* XXX check mode bandwidth */
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci	if ((mode->clock / 10) > rdev->clock.max_pixel_clock)
99162306a36Sopenharmony_ci		return MODE_CLOCK_HIGH;
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci	return MODE_OK;
99462306a36Sopenharmony_ci}
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_cistatic enum drm_connector_status
99762306a36Sopenharmony_ciradeon_vga_detect(struct drm_connector *connector, bool force)
99862306a36Sopenharmony_ci{
99962306a36Sopenharmony_ci	struct drm_device *dev = connector->dev;
100062306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
100162306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
100262306a36Sopenharmony_ci	struct drm_encoder *encoder;
100362306a36Sopenharmony_ci	const struct drm_encoder_helper_funcs *encoder_funcs;
100462306a36Sopenharmony_ci	bool dret = false;
100562306a36Sopenharmony_ci	enum drm_connector_status ret = connector_status_disconnected;
100662306a36Sopenharmony_ci	int r;
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	if (!drm_kms_helper_is_poll_worker()) {
100962306a36Sopenharmony_ci		r = pm_runtime_get_sync(connector->dev->dev);
101062306a36Sopenharmony_ci		if (r < 0) {
101162306a36Sopenharmony_ci			pm_runtime_put_autosuspend(connector->dev->dev);
101262306a36Sopenharmony_ci			return connector_status_disconnected;
101362306a36Sopenharmony_ci		}
101462306a36Sopenharmony_ci	}
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ci	encoder = radeon_best_single_encoder(connector);
101762306a36Sopenharmony_ci	if (!encoder)
101862306a36Sopenharmony_ci		ret = connector_status_disconnected;
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ci	if (radeon_connector->ddc_bus)
102162306a36Sopenharmony_ci		dret = radeon_ddc_probe(radeon_connector, false);
102262306a36Sopenharmony_ci	if (dret) {
102362306a36Sopenharmony_ci		radeon_connector->detected_by_load = false;
102462306a36Sopenharmony_ci		radeon_connector_free_edid(connector);
102562306a36Sopenharmony_ci		radeon_connector_get_edid(connector);
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci		if (!radeon_connector->edid) {
102862306a36Sopenharmony_ci			DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
102962306a36Sopenharmony_ci					connector->name);
103062306a36Sopenharmony_ci			ret = connector_status_connected;
103162306a36Sopenharmony_ci		} else {
103262306a36Sopenharmony_ci			radeon_connector->use_digital =
103362306a36Sopenharmony_ci				!!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci			/* some oems have boards with separate digital and analog connectors
103662306a36Sopenharmony_ci			 * with a shared ddc line (often vga + hdmi)
103762306a36Sopenharmony_ci			 */
103862306a36Sopenharmony_ci			if (radeon_connector->use_digital && radeon_connector->shared_ddc) {
103962306a36Sopenharmony_ci				radeon_connector_free_edid(connector);
104062306a36Sopenharmony_ci				ret = connector_status_disconnected;
104162306a36Sopenharmony_ci			} else {
104262306a36Sopenharmony_ci				ret = connector_status_connected;
104362306a36Sopenharmony_ci			}
104462306a36Sopenharmony_ci		}
104562306a36Sopenharmony_ci	} else {
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci		/* if we aren't forcing don't do destructive polling */
104862306a36Sopenharmony_ci		if (!force) {
104962306a36Sopenharmony_ci			/* only return the previous status if we last
105062306a36Sopenharmony_ci			 * detected a monitor via load.
105162306a36Sopenharmony_ci			 */
105262306a36Sopenharmony_ci			if (radeon_connector->detected_by_load)
105362306a36Sopenharmony_ci				ret = connector->status;
105462306a36Sopenharmony_ci			goto out;
105562306a36Sopenharmony_ci		}
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_ci		if (radeon_connector->dac_load_detect && encoder) {
105862306a36Sopenharmony_ci			encoder_funcs = encoder->helper_private;
105962306a36Sopenharmony_ci			ret = encoder_funcs->detect(encoder, connector);
106062306a36Sopenharmony_ci			if (ret != connector_status_disconnected)
106162306a36Sopenharmony_ci				radeon_connector->detected_by_load = true;
106262306a36Sopenharmony_ci		}
106362306a36Sopenharmony_ci	}
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci	if (ret == connector_status_connected)
106662306a36Sopenharmony_ci		ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ci	/* RN50 and some RV100 asics in servers often have a hardcoded EDID in the
106962306a36Sopenharmony_ci	 * vbios to deal with KVMs. If we have one and are not able to detect a monitor
107062306a36Sopenharmony_ci	 * by other means, assume the CRT is connected and use that EDID.
107162306a36Sopenharmony_ci	 */
107262306a36Sopenharmony_ci	if ((!rdev->is_atom_bios) &&
107362306a36Sopenharmony_ci	    (ret == connector_status_disconnected) &&
107462306a36Sopenharmony_ci	    rdev->mode_info.bios_hardcoded_edid_size) {
107562306a36Sopenharmony_ci		ret = connector_status_connected;
107662306a36Sopenharmony_ci	}
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	radeon_connector_update_scratch_regs(connector, ret);
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ciout:
108162306a36Sopenharmony_ci	if (!drm_kms_helper_is_poll_worker()) {
108262306a36Sopenharmony_ci		pm_runtime_mark_last_busy(connector->dev->dev);
108362306a36Sopenharmony_ci		pm_runtime_put_autosuspend(connector->dev->dev);
108462306a36Sopenharmony_ci	}
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci	return ret;
108762306a36Sopenharmony_ci}
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_cistatic const struct drm_connector_helper_funcs radeon_vga_connector_helper_funcs = {
109062306a36Sopenharmony_ci	.get_modes = radeon_vga_get_modes,
109162306a36Sopenharmony_ci	.mode_valid = radeon_vga_mode_valid,
109262306a36Sopenharmony_ci	.best_encoder = radeon_best_single_encoder,
109362306a36Sopenharmony_ci};
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_cistatic const struct drm_connector_funcs radeon_vga_connector_funcs = {
109662306a36Sopenharmony_ci	.dpms = drm_helper_connector_dpms,
109762306a36Sopenharmony_ci	.detect = radeon_vga_detect,
109862306a36Sopenharmony_ci	.fill_modes = drm_helper_probe_single_connector_modes,
109962306a36Sopenharmony_ci	.early_unregister = radeon_connector_unregister,
110062306a36Sopenharmony_ci	.destroy = radeon_connector_destroy,
110162306a36Sopenharmony_ci	.set_property = radeon_connector_set_property,
110262306a36Sopenharmony_ci};
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_cistatic int radeon_tv_get_modes(struct drm_connector *connector)
110562306a36Sopenharmony_ci{
110662306a36Sopenharmony_ci	struct drm_device *dev = connector->dev;
110762306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
110862306a36Sopenharmony_ci	struct drm_display_mode *tv_mode;
110962306a36Sopenharmony_ci	struct drm_encoder *encoder;
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci	encoder = radeon_best_single_encoder(connector);
111262306a36Sopenharmony_ci	if (!encoder)
111362306a36Sopenharmony_ci		return 0;
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci	/* avivo chips can scale any mode */
111662306a36Sopenharmony_ci	if (rdev->family >= CHIP_RS600)
111762306a36Sopenharmony_ci		/* add scaled modes */
111862306a36Sopenharmony_ci		radeon_add_common_modes(encoder, connector);
111962306a36Sopenharmony_ci	else {
112062306a36Sopenharmony_ci		/* only 800x600 is supported right now on pre-avivo chips */
112162306a36Sopenharmony_ci		tv_mode = drm_cvt_mode(dev, 800, 600, 60, false, false, false);
112262306a36Sopenharmony_ci		if (!tv_mode)
112362306a36Sopenharmony_ci			return 0;
112462306a36Sopenharmony_ci		tv_mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
112562306a36Sopenharmony_ci		drm_mode_probed_add(connector, tv_mode);
112662306a36Sopenharmony_ci	}
112762306a36Sopenharmony_ci	return 1;
112862306a36Sopenharmony_ci}
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_cistatic enum drm_mode_status radeon_tv_mode_valid(struct drm_connector *connector,
113162306a36Sopenharmony_ci				struct drm_display_mode *mode)
113262306a36Sopenharmony_ci{
113362306a36Sopenharmony_ci	if ((mode->hdisplay > 1024) || (mode->vdisplay > 768))
113462306a36Sopenharmony_ci		return MODE_CLOCK_RANGE;
113562306a36Sopenharmony_ci	return MODE_OK;
113662306a36Sopenharmony_ci}
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_cistatic enum drm_connector_status
113962306a36Sopenharmony_ciradeon_tv_detect(struct drm_connector *connector, bool force)
114062306a36Sopenharmony_ci{
114162306a36Sopenharmony_ci	struct drm_encoder *encoder;
114262306a36Sopenharmony_ci	const struct drm_encoder_helper_funcs *encoder_funcs;
114362306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
114462306a36Sopenharmony_ci	enum drm_connector_status ret = connector_status_disconnected;
114562306a36Sopenharmony_ci	int r;
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_ci	if (!radeon_connector->dac_load_detect)
114862306a36Sopenharmony_ci		return ret;
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci	if (!drm_kms_helper_is_poll_worker()) {
115162306a36Sopenharmony_ci		r = pm_runtime_get_sync(connector->dev->dev);
115262306a36Sopenharmony_ci		if (r < 0) {
115362306a36Sopenharmony_ci			pm_runtime_put_autosuspend(connector->dev->dev);
115462306a36Sopenharmony_ci			return connector_status_disconnected;
115562306a36Sopenharmony_ci		}
115662306a36Sopenharmony_ci	}
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci	encoder = radeon_best_single_encoder(connector);
115962306a36Sopenharmony_ci	if (!encoder)
116062306a36Sopenharmony_ci		ret = connector_status_disconnected;
116162306a36Sopenharmony_ci	else {
116262306a36Sopenharmony_ci		encoder_funcs = encoder->helper_private;
116362306a36Sopenharmony_ci		ret = encoder_funcs->detect(encoder, connector);
116462306a36Sopenharmony_ci	}
116562306a36Sopenharmony_ci	if (ret == connector_status_connected)
116662306a36Sopenharmony_ci		ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false);
116762306a36Sopenharmony_ci	radeon_connector_update_scratch_regs(connector, ret);
116862306a36Sopenharmony_ci
116962306a36Sopenharmony_ci	if (!drm_kms_helper_is_poll_worker()) {
117062306a36Sopenharmony_ci		pm_runtime_mark_last_busy(connector->dev->dev);
117162306a36Sopenharmony_ci		pm_runtime_put_autosuspend(connector->dev->dev);
117262306a36Sopenharmony_ci	}
117362306a36Sopenharmony_ci
117462306a36Sopenharmony_ci	return ret;
117562306a36Sopenharmony_ci}
117662306a36Sopenharmony_ci
117762306a36Sopenharmony_cistatic const struct drm_connector_helper_funcs radeon_tv_connector_helper_funcs = {
117862306a36Sopenharmony_ci	.get_modes = radeon_tv_get_modes,
117962306a36Sopenharmony_ci	.mode_valid = radeon_tv_mode_valid,
118062306a36Sopenharmony_ci	.best_encoder = radeon_best_single_encoder,
118162306a36Sopenharmony_ci};
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_cistatic const struct drm_connector_funcs radeon_tv_connector_funcs = {
118462306a36Sopenharmony_ci	.dpms = drm_helper_connector_dpms,
118562306a36Sopenharmony_ci	.detect = radeon_tv_detect,
118662306a36Sopenharmony_ci	.fill_modes = drm_helper_probe_single_connector_modes,
118762306a36Sopenharmony_ci	.early_unregister = radeon_connector_unregister,
118862306a36Sopenharmony_ci	.destroy = radeon_connector_destroy,
118962306a36Sopenharmony_ci	.set_property = radeon_connector_set_property,
119062306a36Sopenharmony_ci};
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_cistatic bool radeon_check_hpd_status_unchanged(struct drm_connector *connector)
119362306a36Sopenharmony_ci{
119462306a36Sopenharmony_ci	struct drm_device *dev = connector->dev;
119562306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
119662306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
119762306a36Sopenharmony_ci	enum drm_connector_status status;
119862306a36Sopenharmony_ci
119962306a36Sopenharmony_ci	/* We only trust HPD on R600 and newer ASICS. */
120062306a36Sopenharmony_ci	if (rdev->family >= CHIP_R600
120162306a36Sopenharmony_ci	  && radeon_connector->hpd.hpd != RADEON_HPD_NONE) {
120262306a36Sopenharmony_ci		if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
120362306a36Sopenharmony_ci			status = connector_status_connected;
120462306a36Sopenharmony_ci		else
120562306a36Sopenharmony_ci			status = connector_status_disconnected;
120662306a36Sopenharmony_ci		if (connector->status == status)
120762306a36Sopenharmony_ci			return true;
120862306a36Sopenharmony_ci	}
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_ci	return false;
121162306a36Sopenharmony_ci}
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ci/*
121462306a36Sopenharmony_ci * DVI is complicated
121562306a36Sopenharmony_ci * Do a DDC probe, if DDC probe passes, get the full EDID so
121662306a36Sopenharmony_ci * we can do analog/digital monitor detection at this point.
121762306a36Sopenharmony_ci * If the monitor is an analog monitor or we got no DDC,
121862306a36Sopenharmony_ci * we need to find the DAC encoder object for this connector.
121962306a36Sopenharmony_ci * If we got no DDC, we do load detection on the DAC encoder object.
122062306a36Sopenharmony_ci * If we got analog DDC or load detection passes on the DAC encoder
122162306a36Sopenharmony_ci * we have to check if this analog encoder is shared with anyone else (TV)
122262306a36Sopenharmony_ci * if its shared we have to set the other connector to disconnected.
122362306a36Sopenharmony_ci */
122462306a36Sopenharmony_cistatic enum drm_connector_status
122562306a36Sopenharmony_ciradeon_dvi_detect(struct drm_connector *connector, bool force)
122662306a36Sopenharmony_ci{
122762306a36Sopenharmony_ci	struct drm_device *dev = connector->dev;
122862306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
122962306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
123062306a36Sopenharmony_ci	struct drm_encoder *encoder = NULL;
123162306a36Sopenharmony_ci	const struct drm_encoder_helper_funcs *encoder_funcs;
123262306a36Sopenharmony_ci	int r;
123362306a36Sopenharmony_ci	enum drm_connector_status ret = connector_status_disconnected;
123462306a36Sopenharmony_ci	bool dret = false, broken_edid = false;
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_ci	if (!drm_kms_helper_is_poll_worker()) {
123762306a36Sopenharmony_ci		r = pm_runtime_get_sync(connector->dev->dev);
123862306a36Sopenharmony_ci		if (r < 0) {
123962306a36Sopenharmony_ci			pm_runtime_put_autosuspend(connector->dev->dev);
124062306a36Sopenharmony_ci			return connector_status_disconnected;
124162306a36Sopenharmony_ci		}
124262306a36Sopenharmony_ci	}
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_ci	if (radeon_connector->detected_hpd_without_ddc) {
124562306a36Sopenharmony_ci		force = true;
124662306a36Sopenharmony_ci		radeon_connector->detected_hpd_without_ddc = false;
124762306a36Sopenharmony_ci	}
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci	if (!force && radeon_check_hpd_status_unchanged(connector)) {
125062306a36Sopenharmony_ci		ret = connector->status;
125162306a36Sopenharmony_ci		goto exit;
125262306a36Sopenharmony_ci	}
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci	if (radeon_connector->ddc_bus) {
125562306a36Sopenharmony_ci		dret = radeon_ddc_probe(radeon_connector, false);
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_ci		/* Sometimes the pins required for the DDC probe on DVI
125862306a36Sopenharmony_ci		 * connectors don't make contact at the same time that the ones
125962306a36Sopenharmony_ci		 * for HPD do. If the DDC probe fails even though we had an HPD
126062306a36Sopenharmony_ci		 * signal, try again later */
126162306a36Sopenharmony_ci		if (!dret && !force &&
126262306a36Sopenharmony_ci		    connector->status != connector_status_connected) {
126362306a36Sopenharmony_ci			DRM_DEBUG_KMS("hpd detected without ddc, retrying in 1 second\n");
126462306a36Sopenharmony_ci			radeon_connector->detected_hpd_without_ddc = true;
126562306a36Sopenharmony_ci			schedule_delayed_work(&rdev->hotplug_work,
126662306a36Sopenharmony_ci					      msecs_to_jiffies(1000));
126762306a36Sopenharmony_ci			goto exit;
126862306a36Sopenharmony_ci		}
126962306a36Sopenharmony_ci	}
127062306a36Sopenharmony_ci	if (dret) {
127162306a36Sopenharmony_ci		radeon_connector->detected_by_load = false;
127262306a36Sopenharmony_ci		radeon_connector_free_edid(connector);
127362306a36Sopenharmony_ci		radeon_connector_get_edid(connector);
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_ci		if (!radeon_connector->edid) {
127662306a36Sopenharmony_ci			DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
127762306a36Sopenharmony_ci					connector->name);
127862306a36Sopenharmony_ci			/* rs690 seems to have a problem with connectors not existing and always
127962306a36Sopenharmony_ci			 * return a block of 0's. If we see this just stop polling on this output */
128062306a36Sopenharmony_ci			if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) &&
128162306a36Sopenharmony_ci			    radeon_connector->base.null_edid_counter) {
128262306a36Sopenharmony_ci				ret = connector_status_disconnected;
128362306a36Sopenharmony_ci				DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n",
128462306a36Sopenharmony_ci					  connector->name);
128562306a36Sopenharmony_ci				radeon_connector->ddc_bus = NULL;
128662306a36Sopenharmony_ci			} else {
128762306a36Sopenharmony_ci				ret = connector_status_connected;
128862306a36Sopenharmony_ci				broken_edid = true; /* defer use_digital to later */
128962306a36Sopenharmony_ci			}
129062306a36Sopenharmony_ci		} else {
129162306a36Sopenharmony_ci			radeon_connector->use_digital =
129262306a36Sopenharmony_ci				!!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
129362306a36Sopenharmony_ci
129462306a36Sopenharmony_ci			/* some oems have boards with separate digital and analog connectors
129562306a36Sopenharmony_ci			 * with a shared ddc line (often vga + hdmi)
129662306a36Sopenharmony_ci			 */
129762306a36Sopenharmony_ci			if ((!radeon_connector->use_digital) && radeon_connector->shared_ddc) {
129862306a36Sopenharmony_ci				radeon_connector_free_edid(connector);
129962306a36Sopenharmony_ci				ret = connector_status_disconnected;
130062306a36Sopenharmony_ci			} else {
130162306a36Sopenharmony_ci				ret = connector_status_connected;
130262306a36Sopenharmony_ci			}
130362306a36Sopenharmony_ci			/* This gets complicated.  We have boards with VGA + HDMI with a
130462306a36Sopenharmony_ci			 * shared DDC line and we have boards with DVI-D + HDMI with a shared
130562306a36Sopenharmony_ci			 * DDC line.  The latter is more complex because with DVI<->HDMI adapters
130662306a36Sopenharmony_ci			 * you don't really know what's connected to which port as both are digital.
130762306a36Sopenharmony_ci			 */
130862306a36Sopenharmony_ci			if (radeon_connector->shared_ddc && (ret == connector_status_connected)) {
130962306a36Sopenharmony_ci				struct drm_connector *list_connector;
131062306a36Sopenharmony_ci				struct radeon_connector *list_radeon_connector;
131162306a36Sopenharmony_ci				list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) {
131262306a36Sopenharmony_ci					if (connector == list_connector)
131362306a36Sopenharmony_ci						continue;
131462306a36Sopenharmony_ci					list_radeon_connector = to_radeon_connector(list_connector);
131562306a36Sopenharmony_ci					if (list_radeon_connector->shared_ddc &&
131662306a36Sopenharmony_ci					    (list_radeon_connector->ddc_bus->rec.i2c_id ==
131762306a36Sopenharmony_ci					     radeon_connector->ddc_bus->rec.i2c_id)) {
131862306a36Sopenharmony_ci						/* cases where both connectors are digital */
131962306a36Sopenharmony_ci						if (list_connector->connector_type != DRM_MODE_CONNECTOR_VGA) {
132062306a36Sopenharmony_ci							/* hpd is our only option in this case */
132162306a36Sopenharmony_ci							if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
132262306a36Sopenharmony_ci								radeon_connector_free_edid(connector);
132362306a36Sopenharmony_ci								ret = connector_status_disconnected;
132462306a36Sopenharmony_ci							}
132562306a36Sopenharmony_ci						}
132662306a36Sopenharmony_ci					}
132762306a36Sopenharmony_ci				}
132862306a36Sopenharmony_ci			}
132962306a36Sopenharmony_ci		}
133062306a36Sopenharmony_ci	}
133162306a36Sopenharmony_ci
133262306a36Sopenharmony_ci	if ((ret == connector_status_connected) && (radeon_connector->use_digital == true))
133362306a36Sopenharmony_ci		goto out;
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_ci	/* DVI-D and HDMI-A are digital only */
133662306a36Sopenharmony_ci	if ((connector->connector_type == DRM_MODE_CONNECTOR_DVID) ||
133762306a36Sopenharmony_ci	    (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA))
133862306a36Sopenharmony_ci		goto out;
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci	/* if we aren't forcing don't do destructive polling */
134162306a36Sopenharmony_ci	if (!force) {
134262306a36Sopenharmony_ci		/* only return the previous status if we last
134362306a36Sopenharmony_ci		 * detected a monitor via load.
134462306a36Sopenharmony_ci		 */
134562306a36Sopenharmony_ci		if (radeon_connector->detected_by_load)
134662306a36Sopenharmony_ci			ret = connector->status;
134762306a36Sopenharmony_ci		goto out;
134862306a36Sopenharmony_ci	}
134962306a36Sopenharmony_ci
135062306a36Sopenharmony_ci	/* find analog encoder */
135162306a36Sopenharmony_ci	if (radeon_connector->dac_load_detect) {
135262306a36Sopenharmony_ci		drm_connector_for_each_possible_encoder(connector, encoder) {
135362306a36Sopenharmony_ci			if (encoder->encoder_type != DRM_MODE_ENCODER_DAC &&
135462306a36Sopenharmony_ci			    encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
135562306a36Sopenharmony_ci				continue;
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_ci			encoder_funcs = encoder->helper_private;
135862306a36Sopenharmony_ci			if (encoder_funcs->detect) {
135962306a36Sopenharmony_ci				if (!broken_edid) {
136062306a36Sopenharmony_ci					if (ret != connector_status_connected) {
136162306a36Sopenharmony_ci						/* deal with analog monitors without DDC */
136262306a36Sopenharmony_ci						ret = encoder_funcs->detect(encoder, connector);
136362306a36Sopenharmony_ci						if (ret == connector_status_connected) {
136462306a36Sopenharmony_ci							radeon_connector->use_digital = false;
136562306a36Sopenharmony_ci						}
136662306a36Sopenharmony_ci						if (ret != connector_status_disconnected)
136762306a36Sopenharmony_ci							radeon_connector->detected_by_load = true;
136862306a36Sopenharmony_ci					}
136962306a36Sopenharmony_ci				} else {
137062306a36Sopenharmony_ci					enum drm_connector_status lret;
137162306a36Sopenharmony_ci					/* assume digital unless load detected otherwise */
137262306a36Sopenharmony_ci					radeon_connector->use_digital = true;
137362306a36Sopenharmony_ci					lret = encoder_funcs->detect(encoder, connector);
137462306a36Sopenharmony_ci					DRM_DEBUG_KMS("load_detect %x returned: %x\n", encoder->encoder_type, lret);
137562306a36Sopenharmony_ci					if (lret == connector_status_connected)
137662306a36Sopenharmony_ci						radeon_connector->use_digital = false;
137762306a36Sopenharmony_ci				}
137862306a36Sopenharmony_ci				break;
137962306a36Sopenharmony_ci			}
138062306a36Sopenharmony_ci		}
138162306a36Sopenharmony_ci	}
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci	if ((ret == connector_status_connected) && (radeon_connector->use_digital == false) &&
138462306a36Sopenharmony_ci	    encoder) {
138562306a36Sopenharmony_ci		ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
138662306a36Sopenharmony_ci	}
138762306a36Sopenharmony_ci
138862306a36Sopenharmony_ci	/* RN50 and some RV100 asics in servers often have a hardcoded EDID in the
138962306a36Sopenharmony_ci	 * vbios to deal with KVMs. If we have one and are not able to detect a monitor
139062306a36Sopenharmony_ci	 * by other means, assume the DFP is connected and use that EDID.  In most
139162306a36Sopenharmony_ci	 * cases the DVI port is actually a virtual KVM port connected to the service
139262306a36Sopenharmony_ci	 * processor.
139362306a36Sopenharmony_ci	 */
139462306a36Sopenharmony_ciout:
139562306a36Sopenharmony_ci	if ((!rdev->is_atom_bios) &&
139662306a36Sopenharmony_ci	    (ret == connector_status_disconnected) &&
139762306a36Sopenharmony_ci	    rdev->mode_info.bios_hardcoded_edid_size) {
139862306a36Sopenharmony_ci		radeon_connector->use_digital = true;
139962306a36Sopenharmony_ci		ret = connector_status_connected;
140062306a36Sopenharmony_ci	}
140162306a36Sopenharmony_ci
140262306a36Sopenharmony_ci	/* updated in get modes as well since we need to know if it's analog or digital */
140362306a36Sopenharmony_ci	radeon_connector_update_scratch_regs(connector, ret);
140462306a36Sopenharmony_ci
140562306a36Sopenharmony_ci	if ((radeon_audio != 0) && radeon_connector->use_digital) {
140662306a36Sopenharmony_ci		const struct drm_connector_helper_funcs *connector_funcs =
140762306a36Sopenharmony_ci			connector->helper_private;
140862306a36Sopenharmony_ci
140962306a36Sopenharmony_ci		encoder = connector_funcs->best_encoder(connector);
141062306a36Sopenharmony_ci		if (encoder && (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)) {
141162306a36Sopenharmony_ci			radeon_connector_get_edid(connector);
141262306a36Sopenharmony_ci			radeon_audio_detect(connector, encoder, ret);
141362306a36Sopenharmony_ci		}
141462306a36Sopenharmony_ci	}
141562306a36Sopenharmony_ci
141662306a36Sopenharmony_ciexit:
141762306a36Sopenharmony_ci	if (!drm_kms_helper_is_poll_worker()) {
141862306a36Sopenharmony_ci		pm_runtime_mark_last_busy(connector->dev->dev);
141962306a36Sopenharmony_ci		pm_runtime_put_autosuspend(connector->dev->dev);
142062306a36Sopenharmony_ci	}
142162306a36Sopenharmony_ci
142262306a36Sopenharmony_ci	return ret;
142362306a36Sopenharmony_ci}
142462306a36Sopenharmony_ci
142562306a36Sopenharmony_ci/* okay need to be smart in here about which encoder to pick */
142662306a36Sopenharmony_cistatic struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
142762306a36Sopenharmony_ci{
142862306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
142962306a36Sopenharmony_ci	struct drm_encoder *encoder;
143062306a36Sopenharmony_ci
143162306a36Sopenharmony_ci	drm_connector_for_each_possible_encoder(connector, encoder) {
143262306a36Sopenharmony_ci		if (radeon_connector->use_digital == true) {
143362306a36Sopenharmony_ci			if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
143462306a36Sopenharmony_ci				return encoder;
143562306a36Sopenharmony_ci		} else {
143662306a36Sopenharmony_ci			if (encoder->encoder_type == DRM_MODE_ENCODER_DAC ||
143762306a36Sopenharmony_ci			    encoder->encoder_type == DRM_MODE_ENCODER_TVDAC)
143862306a36Sopenharmony_ci				return encoder;
143962306a36Sopenharmony_ci		}
144062306a36Sopenharmony_ci	}
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_ci	/* see if we have a default encoder  TODO */
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci	/* then check use digitial */
144562306a36Sopenharmony_ci	/* pick the first one */
144662306a36Sopenharmony_ci	drm_connector_for_each_possible_encoder(connector, encoder)
144762306a36Sopenharmony_ci		return encoder;
144862306a36Sopenharmony_ci
144962306a36Sopenharmony_ci	return NULL;
145062306a36Sopenharmony_ci}
145162306a36Sopenharmony_ci
145262306a36Sopenharmony_cistatic void radeon_dvi_force(struct drm_connector *connector)
145362306a36Sopenharmony_ci{
145462306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
145562306a36Sopenharmony_ci	if (connector->force == DRM_FORCE_ON)
145662306a36Sopenharmony_ci		radeon_connector->use_digital = false;
145762306a36Sopenharmony_ci	if (connector->force == DRM_FORCE_ON_DIGITAL)
145862306a36Sopenharmony_ci		radeon_connector->use_digital = true;
145962306a36Sopenharmony_ci}
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_cistatic enum drm_mode_status radeon_dvi_mode_valid(struct drm_connector *connector,
146262306a36Sopenharmony_ci				  struct drm_display_mode *mode)
146362306a36Sopenharmony_ci{
146462306a36Sopenharmony_ci	struct drm_device *dev = connector->dev;
146562306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
146662306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
146762306a36Sopenharmony_ci
146862306a36Sopenharmony_ci	/* XXX check mode bandwidth */
146962306a36Sopenharmony_ci
147062306a36Sopenharmony_ci	/* clocks over 135 MHz have heat issues with DVI on RV100 */
147162306a36Sopenharmony_ci	if (radeon_connector->use_digital &&
147262306a36Sopenharmony_ci	    (rdev->family == CHIP_RV100) &&
147362306a36Sopenharmony_ci	    (mode->clock > 135000))
147462306a36Sopenharmony_ci		return MODE_CLOCK_HIGH;
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_ci	if (radeon_connector->use_digital && (mode->clock > 165000)) {
147762306a36Sopenharmony_ci		if ((radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I) ||
147862306a36Sopenharmony_ci		    (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
147962306a36Sopenharmony_ci		    (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B))
148062306a36Sopenharmony_ci			return MODE_OK;
148162306a36Sopenharmony_ci		else if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
148262306a36Sopenharmony_ci			/* HDMI 1.3+ supports max clock of 340 Mhz */
148362306a36Sopenharmony_ci			if (mode->clock > 340000)
148462306a36Sopenharmony_ci				return MODE_CLOCK_HIGH;
148562306a36Sopenharmony_ci			else
148662306a36Sopenharmony_ci				return MODE_OK;
148762306a36Sopenharmony_ci		} else {
148862306a36Sopenharmony_ci			return MODE_CLOCK_HIGH;
148962306a36Sopenharmony_ci		}
149062306a36Sopenharmony_ci	}
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_ci	/* check against the max pixel clock */
149362306a36Sopenharmony_ci	if ((mode->clock / 10) > rdev->clock.max_pixel_clock)
149462306a36Sopenharmony_ci		return MODE_CLOCK_HIGH;
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci	return MODE_OK;
149762306a36Sopenharmony_ci}
149862306a36Sopenharmony_ci
149962306a36Sopenharmony_cistatic const struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = {
150062306a36Sopenharmony_ci	.get_modes = radeon_vga_get_modes,
150162306a36Sopenharmony_ci	.mode_valid = radeon_dvi_mode_valid,
150262306a36Sopenharmony_ci	.best_encoder = radeon_dvi_encoder,
150362306a36Sopenharmony_ci};
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_cistatic const struct drm_connector_funcs radeon_dvi_connector_funcs = {
150662306a36Sopenharmony_ci	.dpms = drm_helper_connector_dpms,
150762306a36Sopenharmony_ci	.detect = radeon_dvi_detect,
150862306a36Sopenharmony_ci	.fill_modes = drm_helper_probe_single_connector_modes,
150962306a36Sopenharmony_ci	.set_property = radeon_connector_set_property,
151062306a36Sopenharmony_ci	.early_unregister = radeon_connector_unregister,
151162306a36Sopenharmony_ci	.destroy = radeon_connector_destroy,
151262306a36Sopenharmony_ci	.force = radeon_dvi_force,
151362306a36Sopenharmony_ci};
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_cistatic int radeon_dp_get_modes(struct drm_connector *connector)
151662306a36Sopenharmony_ci{
151762306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
151862306a36Sopenharmony_ci	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
151962306a36Sopenharmony_ci	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
152062306a36Sopenharmony_ci	int ret;
152162306a36Sopenharmony_ci
152262306a36Sopenharmony_ci	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
152362306a36Sopenharmony_ci	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
152462306a36Sopenharmony_ci		struct drm_display_mode *mode;
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_ci		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
152762306a36Sopenharmony_ci			if (!radeon_dig_connector->edp_on)
152862306a36Sopenharmony_ci				atombios_set_edp_panel_power(connector,
152962306a36Sopenharmony_ci							     ATOM_TRANSMITTER_ACTION_POWER_ON);
153062306a36Sopenharmony_ci			radeon_connector_get_edid(connector);
153162306a36Sopenharmony_ci			ret = radeon_ddc_get_modes(connector);
153262306a36Sopenharmony_ci			if (!radeon_dig_connector->edp_on)
153362306a36Sopenharmony_ci				atombios_set_edp_panel_power(connector,
153462306a36Sopenharmony_ci							     ATOM_TRANSMITTER_ACTION_POWER_OFF);
153562306a36Sopenharmony_ci		} else {
153662306a36Sopenharmony_ci			/* need to setup ddc on the bridge */
153762306a36Sopenharmony_ci			if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
153862306a36Sopenharmony_ci			    ENCODER_OBJECT_ID_NONE) {
153962306a36Sopenharmony_ci				if (encoder)
154062306a36Sopenharmony_ci					radeon_atom_ext_encoder_setup_ddc(encoder);
154162306a36Sopenharmony_ci			}
154262306a36Sopenharmony_ci			radeon_connector_get_edid(connector);
154362306a36Sopenharmony_ci			ret = radeon_ddc_get_modes(connector);
154462306a36Sopenharmony_ci		}
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci		if (ret > 0) {
154762306a36Sopenharmony_ci			if (encoder) {
154862306a36Sopenharmony_ci				radeon_fixup_lvds_native_mode(encoder, connector);
154962306a36Sopenharmony_ci				/* add scaled modes */
155062306a36Sopenharmony_ci				radeon_add_common_modes(encoder, connector);
155162306a36Sopenharmony_ci			}
155262306a36Sopenharmony_ci			return ret;
155362306a36Sopenharmony_ci		}
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_ci		if (!encoder)
155662306a36Sopenharmony_ci			return 0;
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_ci		/* we have no EDID modes */
155962306a36Sopenharmony_ci		mode = radeon_fp_native_mode(encoder);
156062306a36Sopenharmony_ci		if (mode) {
156162306a36Sopenharmony_ci			ret = 1;
156262306a36Sopenharmony_ci			drm_mode_probed_add(connector, mode);
156362306a36Sopenharmony_ci			/* add the width/height from vbios tables if available */
156462306a36Sopenharmony_ci			connector->display_info.width_mm = mode->width_mm;
156562306a36Sopenharmony_ci			connector->display_info.height_mm = mode->height_mm;
156662306a36Sopenharmony_ci			/* add scaled modes */
156762306a36Sopenharmony_ci			radeon_add_common_modes(encoder, connector);
156862306a36Sopenharmony_ci		}
156962306a36Sopenharmony_ci	} else {
157062306a36Sopenharmony_ci		/* need to setup ddc on the bridge */
157162306a36Sopenharmony_ci		if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
157262306a36Sopenharmony_ci			ENCODER_OBJECT_ID_NONE) {
157362306a36Sopenharmony_ci			if (encoder)
157462306a36Sopenharmony_ci				radeon_atom_ext_encoder_setup_ddc(encoder);
157562306a36Sopenharmony_ci		}
157662306a36Sopenharmony_ci		radeon_connector_get_edid(connector);
157762306a36Sopenharmony_ci		ret = radeon_ddc_get_modes(connector);
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_ci		radeon_get_native_mode(connector);
158062306a36Sopenharmony_ci	}
158162306a36Sopenharmony_ci
158262306a36Sopenharmony_ci	return ret;
158362306a36Sopenharmony_ci}
158462306a36Sopenharmony_ci
158562306a36Sopenharmony_ciu16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector)
158662306a36Sopenharmony_ci{
158762306a36Sopenharmony_ci	struct drm_encoder *encoder;
158862306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder;
158962306a36Sopenharmony_ci
159062306a36Sopenharmony_ci	drm_connector_for_each_possible_encoder(connector, encoder) {
159162306a36Sopenharmony_ci		radeon_encoder = to_radeon_encoder(encoder);
159262306a36Sopenharmony_ci
159362306a36Sopenharmony_ci		switch (radeon_encoder->encoder_id) {
159462306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_TRAVIS:
159562306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_NUTMEG:
159662306a36Sopenharmony_ci			return radeon_encoder->encoder_id;
159762306a36Sopenharmony_ci		default:
159862306a36Sopenharmony_ci			break;
159962306a36Sopenharmony_ci		}
160062306a36Sopenharmony_ci	}
160162306a36Sopenharmony_ci
160262306a36Sopenharmony_ci	return ENCODER_OBJECT_ID_NONE;
160362306a36Sopenharmony_ci}
160462306a36Sopenharmony_ci
160562306a36Sopenharmony_cistatic bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector)
160662306a36Sopenharmony_ci{
160762306a36Sopenharmony_ci	struct drm_encoder *encoder;
160862306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder;
160962306a36Sopenharmony_ci	bool found = false;
161062306a36Sopenharmony_ci
161162306a36Sopenharmony_ci	drm_connector_for_each_possible_encoder(connector, encoder) {
161262306a36Sopenharmony_ci		radeon_encoder = to_radeon_encoder(encoder);
161362306a36Sopenharmony_ci		if (radeon_encoder->caps & ATOM_ENCODER_CAP_RECORD_HBR2)
161462306a36Sopenharmony_ci			found = true;
161562306a36Sopenharmony_ci	}
161662306a36Sopenharmony_ci
161762306a36Sopenharmony_ci	return found;
161862306a36Sopenharmony_ci}
161962306a36Sopenharmony_ci
162062306a36Sopenharmony_cibool radeon_connector_is_dp12_capable(struct drm_connector *connector)
162162306a36Sopenharmony_ci{
162262306a36Sopenharmony_ci	struct drm_device *dev = connector->dev;
162362306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
162462306a36Sopenharmony_ci
162562306a36Sopenharmony_ci	if (ASIC_IS_DCE5(rdev) &&
162662306a36Sopenharmony_ci	    (rdev->clock.default_dispclk >= 53900) &&
162762306a36Sopenharmony_ci	    radeon_connector_encoder_is_hbr2(connector)) {
162862306a36Sopenharmony_ci		return true;
162962306a36Sopenharmony_ci	}
163062306a36Sopenharmony_ci
163162306a36Sopenharmony_ci	return false;
163262306a36Sopenharmony_ci}
163362306a36Sopenharmony_ci
163462306a36Sopenharmony_cistatic enum drm_connector_status
163562306a36Sopenharmony_ciradeon_dp_detect(struct drm_connector *connector, bool force)
163662306a36Sopenharmony_ci{
163762306a36Sopenharmony_ci	struct drm_device *dev = connector->dev;
163862306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
163962306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
164062306a36Sopenharmony_ci	enum drm_connector_status ret = connector_status_disconnected;
164162306a36Sopenharmony_ci	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
164262306a36Sopenharmony_ci	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
164362306a36Sopenharmony_ci	int r;
164462306a36Sopenharmony_ci
164562306a36Sopenharmony_ci	if (!drm_kms_helper_is_poll_worker()) {
164662306a36Sopenharmony_ci		r = pm_runtime_get_sync(connector->dev->dev);
164762306a36Sopenharmony_ci		if (r < 0) {
164862306a36Sopenharmony_ci			pm_runtime_put_autosuspend(connector->dev->dev);
164962306a36Sopenharmony_ci			return connector_status_disconnected;
165062306a36Sopenharmony_ci		}
165162306a36Sopenharmony_ci	}
165262306a36Sopenharmony_ci
165362306a36Sopenharmony_ci	if (!force && radeon_check_hpd_status_unchanged(connector)) {
165462306a36Sopenharmony_ci		ret = connector->status;
165562306a36Sopenharmony_ci		goto out;
165662306a36Sopenharmony_ci	}
165762306a36Sopenharmony_ci
165862306a36Sopenharmony_ci	radeon_connector_free_edid(connector);
165962306a36Sopenharmony_ci
166062306a36Sopenharmony_ci	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
166162306a36Sopenharmony_ci	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
166262306a36Sopenharmony_ci		if (encoder) {
166362306a36Sopenharmony_ci			struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
166462306a36Sopenharmony_ci			struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
166562306a36Sopenharmony_ci
166662306a36Sopenharmony_ci			/* check if panel is valid */
166762306a36Sopenharmony_ci			if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240)
166862306a36Sopenharmony_ci				ret = connector_status_connected;
166962306a36Sopenharmony_ci			/* don't fetch the edid from the vbios if ddc fails and runpm is
167062306a36Sopenharmony_ci			 * enabled so we report disconnected.
167162306a36Sopenharmony_ci			 */
167262306a36Sopenharmony_ci			if ((rdev->flags & RADEON_IS_PX) && (radeon_runtime_pm != 0))
167362306a36Sopenharmony_ci				ret = connector_status_disconnected;
167462306a36Sopenharmony_ci		}
167562306a36Sopenharmony_ci		/* eDP is always DP */
167662306a36Sopenharmony_ci		radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT;
167762306a36Sopenharmony_ci		if (!radeon_dig_connector->edp_on)
167862306a36Sopenharmony_ci			atombios_set_edp_panel_power(connector,
167962306a36Sopenharmony_ci						     ATOM_TRANSMITTER_ACTION_POWER_ON);
168062306a36Sopenharmony_ci		if (radeon_dp_getdpcd(radeon_connector))
168162306a36Sopenharmony_ci			ret = connector_status_connected;
168262306a36Sopenharmony_ci		if (!radeon_dig_connector->edp_on)
168362306a36Sopenharmony_ci			atombios_set_edp_panel_power(connector,
168462306a36Sopenharmony_ci						     ATOM_TRANSMITTER_ACTION_POWER_OFF);
168562306a36Sopenharmony_ci	} else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
168662306a36Sopenharmony_ci		   ENCODER_OBJECT_ID_NONE) {
168762306a36Sopenharmony_ci		/* DP bridges are always DP */
168862306a36Sopenharmony_ci		radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT;
168962306a36Sopenharmony_ci		/* get the DPCD from the bridge */
169062306a36Sopenharmony_ci		radeon_dp_getdpcd(radeon_connector);
169162306a36Sopenharmony_ci
169262306a36Sopenharmony_ci		if (encoder) {
169362306a36Sopenharmony_ci			/* setup ddc on the bridge */
169462306a36Sopenharmony_ci			radeon_atom_ext_encoder_setup_ddc(encoder);
169562306a36Sopenharmony_ci			/* bridge chips are always aux */
169662306a36Sopenharmony_ci			if (radeon_ddc_probe(radeon_connector, true)) /* try DDC */
169762306a36Sopenharmony_ci				ret = connector_status_connected;
169862306a36Sopenharmony_ci			else if (radeon_connector->dac_load_detect) { /* try load detection */
169962306a36Sopenharmony_ci				const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
170062306a36Sopenharmony_ci				ret = encoder_funcs->detect(encoder, connector);
170162306a36Sopenharmony_ci			}
170262306a36Sopenharmony_ci		}
170362306a36Sopenharmony_ci	} else {
170462306a36Sopenharmony_ci		radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector);
170562306a36Sopenharmony_ci		if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
170662306a36Sopenharmony_ci			ret = connector_status_connected;
170762306a36Sopenharmony_ci			if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT)
170862306a36Sopenharmony_ci				radeon_dp_getdpcd(radeon_connector);
170962306a36Sopenharmony_ci		} else {
171062306a36Sopenharmony_ci			if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
171162306a36Sopenharmony_ci				if (radeon_dp_getdpcd(radeon_connector))
171262306a36Sopenharmony_ci					ret = connector_status_connected;
171362306a36Sopenharmony_ci			} else {
171462306a36Sopenharmony_ci				/* try non-aux ddc (DP to DVI/HDMI/etc. adapter) */
171562306a36Sopenharmony_ci				if (radeon_ddc_probe(radeon_connector, false))
171662306a36Sopenharmony_ci					ret = connector_status_connected;
171762306a36Sopenharmony_ci			}
171862306a36Sopenharmony_ci		}
171962306a36Sopenharmony_ci	}
172062306a36Sopenharmony_ci
172162306a36Sopenharmony_ci	radeon_connector_update_scratch_regs(connector, ret);
172262306a36Sopenharmony_ci
172362306a36Sopenharmony_ci	if ((radeon_audio != 0) && encoder) {
172462306a36Sopenharmony_ci		radeon_connector_get_edid(connector);
172562306a36Sopenharmony_ci		radeon_audio_detect(connector, encoder, ret);
172662306a36Sopenharmony_ci	}
172762306a36Sopenharmony_ci
172862306a36Sopenharmony_ciout:
172962306a36Sopenharmony_ci	if (!drm_kms_helper_is_poll_worker()) {
173062306a36Sopenharmony_ci		pm_runtime_mark_last_busy(connector->dev->dev);
173162306a36Sopenharmony_ci		pm_runtime_put_autosuspend(connector->dev->dev);
173262306a36Sopenharmony_ci	}
173362306a36Sopenharmony_ci
173462306a36Sopenharmony_ci	return ret;
173562306a36Sopenharmony_ci}
173662306a36Sopenharmony_ci
173762306a36Sopenharmony_cistatic enum drm_mode_status radeon_dp_mode_valid(struct drm_connector *connector,
173862306a36Sopenharmony_ci				  struct drm_display_mode *mode)
173962306a36Sopenharmony_ci{
174062306a36Sopenharmony_ci	struct drm_device *dev = connector->dev;
174162306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
174262306a36Sopenharmony_ci	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
174362306a36Sopenharmony_ci	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_ci	/* XXX check mode bandwidth */
174662306a36Sopenharmony_ci
174762306a36Sopenharmony_ci	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
174862306a36Sopenharmony_ci	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
174962306a36Sopenharmony_ci		struct drm_encoder *encoder = radeon_best_single_encoder(connector);
175062306a36Sopenharmony_ci
175162306a36Sopenharmony_ci		if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
175262306a36Sopenharmony_ci			return MODE_PANEL;
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_ci		if (encoder) {
175562306a36Sopenharmony_ci			struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
175662306a36Sopenharmony_ci			struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
175762306a36Sopenharmony_ci
175862306a36Sopenharmony_ci			/* AVIVO hardware supports downscaling modes larger than the panel
175962306a36Sopenharmony_ci			 * to the panel size, but I'm not sure this is desirable.
176062306a36Sopenharmony_ci			 */
176162306a36Sopenharmony_ci			if ((mode->hdisplay > native_mode->hdisplay) ||
176262306a36Sopenharmony_ci			    (mode->vdisplay > native_mode->vdisplay))
176362306a36Sopenharmony_ci				return MODE_PANEL;
176462306a36Sopenharmony_ci
176562306a36Sopenharmony_ci			/* if scaling is disabled, block non-native modes */
176662306a36Sopenharmony_ci			if (radeon_encoder->rmx_type == RMX_OFF) {
176762306a36Sopenharmony_ci				if ((mode->hdisplay != native_mode->hdisplay) ||
176862306a36Sopenharmony_ci				    (mode->vdisplay != native_mode->vdisplay))
176962306a36Sopenharmony_ci					return MODE_PANEL;
177062306a36Sopenharmony_ci			}
177162306a36Sopenharmony_ci		}
177262306a36Sopenharmony_ci	} else {
177362306a36Sopenharmony_ci		if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
177462306a36Sopenharmony_ci		    (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
177562306a36Sopenharmony_ci			return radeon_dp_mode_valid_helper(connector, mode);
177662306a36Sopenharmony_ci		} else {
177762306a36Sopenharmony_ci			if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
177862306a36Sopenharmony_ci				/* HDMI 1.3+ supports max clock of 340 Mhz */
177962306a36Sopenharmony_ci				if (mode->clock > 340000)
178062306a36Sopenharmony_ci					return MODE_CLOCK_HIGH;
178162306a36Sopenharmony_ci			} else {
178262306a36Sopenharmony_ci				if (mode->clock > 165000)
178362306a36Sopenharmony_ci					return MODE_CLOCK_HIGH;
178462306a36Sopenharmony_ci			}
178562306a36Sopenharmony_ci		}
178662306a36Sopenharmony_ci	}
178762306a36Sopenharmony_ci
178862306a36Sopenharmony_ci	return MODE_OK;
178962306a36Sopenharmony_ci}
179062306a36Sopenharmony_ci
179162306a36Sopenharmony_cistatic const struct drm_connector_helper_funcs radeon_dp_connector_helper_funcs = {
179262306a36Sopenharmony_ci	.get_modes = radeon_dp_get_modes,
179362306a36Sopenharmony_ci	.mode_valid = radeon_dp_mode_valid,
179462306a36Sopenharmony_ci	.best_encoder = radeon_dvi_encoder,
179562306a36Sopenharmony_ci};
179662306a36Sopenharmony_ci
179762306a36Sopenharmony_cistatic const struct drm_connector_funcs radeon_dp_connector_funcs = {
179862306a36Sopenharmony_ci	.dpms = drm_helper_connector_dpms,
179962306a36Sopenharmony_ci	.detect = radeon_dp_detect,
180062306a36Sopenharmony_ci	.fill_modes = drm_helper_probe_single_connector_modes,
180162306a36Sopenharmony_ci	.set_property = radeon_connector_set_property,
180262306a36Sopenharmony_ci	.early_unregister = radeon_connector_unregister,
180362306a36Sopenharmony_ci	.destroy = radeon_connector_destroy,
180462306a36Sopenharmony_ci	.force = radeon_dvi_force,
180562306a36Sopenharmony_ci};
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_cistatic const struct drm_connector_funcs radeon_edp_connector_funcs = {
180862306a36Sopenharmony_ci	.dpms = drm_helper_connector_dpms,
180962306a36Sopenharmony_ci	.detect = radeon_dp_detect,
181062306a36Sopenharmony_ci	.fill_modes = drm_helper_probe_single_connector_modes,
181162306a36Sopenharmony_ci	.set_property = radeon_lvds_set_property,
181262306a36Sopenharmony_ci	.early_unregister = radeon_connector_unregister,
181362306a36Sopenharmony_ci	.destroy = radeon_connector_destroy,
181462306a36Sopenharmony_ci	.force = radeon_dvi_force,
181562306a36Sopenharmony_ci};
181662306a36Sopenharmony_ci
181762306a36Sopenharmony_cistatic const struct drm_connector_funcs radeon_lvds_bridge_connector_funcs = {
181862306a36Sopenharmony_ci	.dpms = drm_helper_connector_dpms,
181962306a36Sopenharmony_ci	.detect = radeon_dp_detect,
182062306a36Sopenharmony_ci	.fill_modes = drm_helper_probe_single_connector_modes,
182162306a36Sopenharmony_ci	.set_property = radeon_lvds_set_property,
182262306a36Sopenharmony_ci	.early_unregister = radeon_connector_unregister,
182362306a36Sopenharmony_ci	.destroy = radeon_connector_destroy,
182462306a36Sopenharmony_ci	.force = radeon_dvi_force,
182562306a36Sopenharmony_ci};
182662306a36Sopenharmony_ci
182762306a36Sopenharmony_civoid
182862306a36Sopenharmony_ciradeon_add_atom_connector(struct drm_device *dev,
182962306a36Sopenharmony_ci			  uint32_t connector_id,
183062306a36Sopenharmony_ci			  uint32_t supported_device,
183162306a36Sopenharmony_ci			  int connector_type,
183262306a36Sopenharmony_ci			  struct radeon_i2c_bus_rec *i2c_bus,
183362306a36Sopenharmony_ci			  uint32_t igp_lane_info,
183462306a36Sopenharmony_ci			  uint16_t connector_object_id,
183562306a36Sopenharmony_ci			  struct radeon_hpd *hpd,
183662306a36Sopenharmony_ci			  struct radeon_router *router)
183762306a36Sopenharmony_ci{
183862306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
183962306a36Sopenharmony_ci	struct drm_connector *connector;
184062306a36Sopenharmony_ci	struct radeon_connector *radeon_connector;
184162306a36Sopenharmony_ci	struct radeon_connector_atom_dig *radeon_dig_connector;
184262306a36Sopenharmony_ci	struct drm_encoder *encoder;
184362306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder;
184462306a36Sopenharmony_ci	struct i2c_adapter *ddc = NULL;
184562306a36Sopenharmony_ci	uint32_t subpixel_order = SubPixelNone;
184662306a36Sopenharmony_ci	bool shared_ddc = false;
184762306a36Sopenharmony_ci	bool is_dp_bridge = false;
184862306a36Sopenharmony_ci	bool has_aux = false;
184962306a36Sopenharmony_ci
185062306a36Sopenharmony_ci	if (connector_type == DRM_MODE_CONNECTOR_Unknown)
185162306a36Sopenharmony_ci		return;
185262306a36Sopenharmony_ci
185362306a36Sopenharmony_ci	/* if the user selected tv=0 don't try and add the connector */
185462306a36Sopenharmony_ci	if (((connector_type == DRM_MODE_CONNECTOR_SVIDEO) ||
185562306a36Sopenharmony_ci	     (connector_type == DRM_MODE_CONNECTOR_Composite) ||
185662306a36Sopenharmony_ci	     (connector_type == DRM_MODE_CONNECTOR_9PinDIN)) &&
185762306a36Sopenharmony_ci	    (radeon_tv == 0))
185862306a36Sopenharmony_ci		return;
185962306a36Sopenharmony_ci
186062306a36Sopenharmony_ci	/* see if we already added it */
186162306a36Sopenharmony_ci	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
186262306a36Sopenharmony_ci		radeon_connector = to_radeon_connector(connector);
186362306a36Sopenharmony_ci		if (radeon_connector->connector_id == connector_id) {
186462306a36Sopenharmony_ci			radeon_connector->devices |= supported_device;
186562306a36Sopenharmony_ci			return;
186662306a36Sopenharmony_ci		}
186762306a36Sopenharmony_ci		if (radeon_connector->ddc_bus && i2c_bus->valid) {
186862306a36Sopenharmony_ci			if (radeon_connector->ddc_bus->rec.i2c_id == i2c_bus->i2c_id) {
186962306a36Sopenharmony_ci				radeon_connector->shared_ddc = true;
187062306a36Sopenharmony_ci				shared_ddc = true;
187162306a36Sopenharmony_ci			}
187262306a36Sopenharmony_ci			if (radeon_connector->router_bus && router->ddc_valid &&
187362306a36Sopenharmony_ci			    (radeon_connector->router.router_id == router->router_id)) {
187462306a36Sopenharmony_ci				radeon_connector->shared_ddc = false;
187562306a36Sopenharmony_ci				shared_ddc = false;
187662306a36Sopenharmony_ci			}
187762306a36Sopenharmony_ci		}
187862306a36Sopenharmony_ci	}
187962306a36Sopenharmony_ci
188062306a36Sopenharmony_ci	/* check if it's a dp bridge */
188162306a36Sopenharmony_ci	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
188262306a36Sopenharmony_ci		radeon_encoder = to_radeon_encoder(encoder);
188362306a36Sopenharmony_ci		if (radeon_encoder->devices & supported_device) {
188462306a36Sopenharmony_ci			switch (radeon_encoder->encoder_id) {
188562306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_TRAVIS:
188662306a36Sopenharmony_ci			case ENCODER_OBJECT_ID_NUTMEG:
188762306a36Sopenharmony_ci				is_dp_bridge = true;
188862306a36Sopenharmony_ci				break;
188962306a36Sopenharmony_ci			default:
189062306a36Sopenharmony_ci				break;
189162306a36Sopenharmony_ci			}
189262306a36Sopenharmony_ci		}
189362306a36Sopenharmony_ci	}
189462306a36Sopenharmony_ci
189562306a36Sopenharmony_ci	radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL);
189662306a36Sopenharmony_ci	if (!radeon_connector)
189762306a36Sopenharmony_ci		return;
189862306a36Sopenharmony_ci
189962306a36Sopenharmony_ci	connector = &radeon_connector->base;
190062306a36Sopenharmony_ci
190162306a36Sopenharmony_ci	radeon_connector->connector_id = connector_id;
190262306a36Sopenharmony_ci	radeon_connector->devices = supported_device;
190362306a36Sopenharmony_ci	radeon_connector->shared_ddc = shared_ddc;
190462306a36Sopenharmony_ci	radeon_connector->connector_object_id = connector_object_id;
190562306a36Sopenharmony_ci	radeon_connector->hpd = *hpd;
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci	radeon_connector->router = *router;
190862306a36Sopenharmony_ci	if (router->ddc_valid || router->cd_valid) {
190962306a36Sopenharmony_ci		radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
191062306a36Sopenharmony_ci		if (!radeon_connector->router_bus)
191162306a36Sopenharmony_ci			DRM_ERROR("Failed to assign router i2c bus! Check dmesg for i2c errors.\n");
191262306a36Sopenharmony_ci	}
191362306a36Sopenharmony_ci
191462306a36Sopenharmony_ci	if (is_dp_bridge) {
191562306a36Sopenharmony_ci		radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
191662306a36Sopenharmony_ci		if (!radeon_dig_connector)
191762306a36Sopenharmony_ci			goto failed;
191862306a36Sopenharmony_ci		radeon_dig_connector->igp_lane_info = igp_lane_info;
191962306a36Sopenharmony_ci		radeon_connector->con_priv = radeon_dig_connector;
192062306a36Sopenharmony_ci		if (i2c_bus->valid) {
192162306a36Sopenharmony_ci			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
192262306a36Sopenharmony_ci			if (radeon_connector->ddc_bus) {
192362306a36Sopenharmony_ci				has_aux = true;
192462306a36Sopenharmony_ci				ddc = &radeon_connector->ddc_bus->adapter;
192562306a36Sopenharmony_ci			} else {
192662306a36Sopenharmony_ci				DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
192762306a36Sopenharmony_ci			}
192862306a36Sopenharmony_ci		}
192962306a36Sopenharmony_ci		switch (connector_type) {
193062306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_VGA:
193162306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_DVIA:
193262306a36Sopenharmony_ci		default:
193362306a36Sopenharmony_ci			drm_connector_init_with_ddc(dev, &radeon_connector->base,
193462306a36Sopenharmony_ci						    &radeon_dp_connector_funcs,
193562306a36Sopenharmony_ci						    connector_type,
193662306a36Sopenharmony_ci						    ddc);
193762306a36Sopenharmony_ci			drm_connector_helper_add(&radeon_connector->base,
193862306a36Sopenharmony_ci						 &radeon_dp_connector_helper_funcs);
193962306a36Sopenharmony_ci			connector->interlace_allowed = true;
194062306a36Sopenharmony_ci			connector->doublescan_allowed = true;
194162306a36Sopenharmony_ci			radeon_connector->dac_load_detect = true;
194262306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
194362306a36Sopenharmony_ci						      rdev->mode_info.load_detect_property,
194462306a36Sopenharmony_ci						      1);
194562306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
194662306a36Sopenharmony_ci						   dev->mode_config.scaling_mode_property,
194762306a36Sopenharmony_ci						   DRM_MODE_SCALE_NONE);
194862306a36Sopenharmony_ci			if (ASIC_IS_DCE5(rdev))
194962306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
195062306a36Sopenharmony_ci							   rdev->mode_info.output_csc_property,
195162306a36Sopenharmony_ci							   RADEON_OUTPUT_CSC_BYPASS);
195262306a36Sopenharmony_ci			break;
195362306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_DVII:
195462306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_DVID:
195562306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_HDMIA:
195662306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_HDMIB:
195762306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_DisplayPort:
195862306a36Sopenharmony_ci			drm_connector_init_with_ddc(dev, &radeon_connector->base,
195962306a36Sopenharmony_ci						    &radeon_dp_connector_funcs,
196062306a36Sopenharmony_ci						    connector_type,
196162306a36Sopenharmony_ci						    ddc);
196262306a36Sopenharmony_ci			drm_connector_helper_add(&radeon_connector->base,
196362306a36Sopenharmony_ci						 &radeon_dp_connector_helper_funcs);
196462306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
196562306a36Sopenharmony_ci						      rdev->mode_info.underscan_property,
196662306a36Sopenharmony_ci						      UNDERSCAN_OFF);
196762306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
196862306a36Sopenharmony_ci						      rdev->mode_info.underscan_hborder_property,
196962306a36Sopenharmony_ci						      0);
197062306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
197162306a36Sopenharmony_ci						      rdev->mode_info.underscan_vborder_property,
197262306a36Sopenharmony_ci						      0);
197362306a36Sopenharmony_ci
197462306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
197562306a36Sopenharmony_ci						      dev->mode_config.scaling_mode_property,
197662306a36Sopenharmony_ci						      DRM_MODE_SCALE_NONE);
197762306a36Sopenharmony_ci
197862306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
197962306a36Sopenharmony_ci						   rdev->mode_info.dither_property,
198062306a36Sopenharmony_ci						   RADEON_FMT_DITHER_DISABLE);
198162306a36Sopenharmony_ci
198262306a36Sopenharmony_ci			if (radeon_audio != 0) {
198362306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
198462306a36Sopenharmony_ci							   rdev->mode_info.audio_property,
198562306a36Sopenharmony_ci							   RADEON_AUDIO_AUTO);
198662306a36Sopenharmony_ci				radeon_connector->audio = RADEON_AUDIO_AUTO;
198762306a36Sopenharmony_ci			}
198862306a36Sopenharmony_ci			if (ASIC_IS_DCE5(rdev))
198962306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
199062306a36Sopenharmony_ci							   rdev->mode_info.output_csc_property,
199162306a36Sopenharmony_ci							   RADEON_OUTPUT_CSC_BYPASS);
199262306a36Sopenharmony_ci
199362306a36Sopenharmony_ci			subpixel_order = SubPixelHorizontalRGB;
199462306a36Sopenharmony_ci			connector->interlace_allowed = true;
199562306a36Sopenharmony_ci			if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
199662306a36Sopenharmony_ci				connector->doublescan_allowed = true;
199762306a36Sopenharmony_ci			else
199862306a36Sopenharmony_ci				connector->doublescan_allowed = false;
199962306a36Sopenharmony_ci			if (connector_type == DRM_MODE_CONNECTOR_DVII) {
200062306a36Sopenharmony_ci				radeon_connector->dac_load_detect = true;
200162306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
200262306a36Sopenharmony_ci							      rdev->mode_info.load_detect_property,
200362306a36Sopenharmony_ci							      1);
200462306a36Sopenharmony_ci			}
200562306a36Sopenharmony_ci			break;
200662306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_LVDS:
200762306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_eDP:
200862306a36Sopenharmony_ci			drm_connector_init_with_ddc(dev, &radeon_connector->base,
200962306a36Sopenharmony_ci						    &radeon_lvds_bridge_connector_funcs,
201062306a36Sopenharmony_ci						    connector_type,
201162306a36Sopenharmony_ci						    ddc);
201262306a36Sopenharmony_ci			drm_connector_helper_add(&radeon_connector->base,
201362306a36Sopenharmony_ci						 &radeon_dp_connector_helper_funcs);
201462306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
201562306a36Sopenharmony_ci						      dev->mode_config.scaling_mode_property,
201662306a36Sopenharmony_ci						      DRM_MODE_SCALE_FULLSCREEN);
201762306a36Sopenharmony_ci			subpixel_order = SubPixelHorizontalRGB;
201862306a36Sopenharmony_ci			connector->interlace_allowed = false;
201962306a36Sopenharmony_ci			connector->doublescan_allowed = false;
202062306a36Sopenharmony_ci			break;
202162306a36Sopenharmony_ci		}
202262306a36Sopenharmony_ci	} else {
202362306a36Sopenharmony_ci		switch (connector_type) {
202462306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_VGA:
202562306a36Sopenharmony_ci			if (i2c_bus->valid) {
202662306a36Sopenharmony_ci				radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
202762306a36Sopenharmony_ci				if (!radeon_connector->ddc_bus)
202862306a36Sopenharmony_ci					DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
202962306a36Sopenharmony_ci				else
203062306a36Sopenharmony_ci					ddc = &radeon_connector->ddc_bus->adapter;
203162306a36Sopenharmony_ci			}
203262306a36Sopenharmony_ci			drm_connector_init_with_ddc(dev, &radeon_connector->base,
203362306a36Sopenharmony_ci						    &radeon_vga_connector_funcs,
203462306a36Sopenharmony_ci						    connector_type,
203562306a36Sopenharmony_ci						    ddc);
203662306a36Sopenharmony_ci			drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
203762306a36Sopenharmony_ci			radeon_connector->dac_load_detect = true;
203862306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
203962306a36Sopenharmony_ci						      rdev->mode_info.load_detect_property,
204062306a36Sopenharmony_ci						      1);
204162306a36Sopenharmony_ci			if (ASIC_IS_AVIVO(rdev))
204262306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
204362306a36Sopenharmony_ci							   dev->mode_config.scaling_mode_property,
204462306a36Sopenharmony_ci							   DRM_MODE_SCALE_NONE);
204562306a36Sopenharmony_ci			if (ASIC_IS_DCE5(rdev))
204662306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
204762306a36Sopenharmony_ci							   rdev->mode_info.output_csc_property,
204862306a36Sopenharmony_ci							   RADEON_OUTPUT_CSC_BYPASS);
204962306a36Sopenharmony_ci			/* no HPD on analog connectors */
205062306a36Sopenharmony_ci			radeon_connector->hpd.hpd = RADEON_HPD_NONE;
205162306a36Sopenharmony_ci			connector->interlace_allowed = true;
205262306a36Sopenharmony_ci			connector->doublescan_allowed = true;
205362306a36Sopenharmony_ci			break;
205462306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_DVIA:
205562306a36Sopenharmony_ci			if (i2c_bus->valid) {
205662306a36Sopenharmony_ci				radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
205762306a36Sopenharmony_ci				if (!radeon_connector->ddc_bus)
205862306a36Sopenharmony_ci					DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
205962306a36Sopenharmony_ci				else
206062306a36Sopenharmony_ci					ddc = &radeon_connector->ddc_bus->adapter;
206162306a36Sopenharmony_ci			}
206262306a36Sopenharmony_ci			drm_connector_init_with_ddc(dev, &radeon_connector->base,
206362306a36Sopenharmony_ci						    &radeon_vga_connector_funcs,
206462306a36Sopenharmony_ci						    connector_type,
206562306a36Sopenharmony_ci						    ddc);
206662306a36Sopenharmony_ci			drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
206762306a36Sopenharmony_ci			radeon_connector->dac_load_detect = true;
206862306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
206962306a36Sopenharmony_ci						      rdev->mode_info.load_detect_property,
207062306a36Sopenharmony_ci						      1);
207162306a36Sopenharmony_ci			if (ASIC_IS_AVIVO(rdev))
207262306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
207362306a36Sopenharmony_ci							   dev->mode_config.scaling_mode_property,
207462306a36Sopenharmony_ci							   DRM_MODE_SCALE_NONE);
207562306a36Sopenharmony_ci			if (ASIC_IS_DCE5(rdev))
207662306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
207762306a36Sopenharmony_ci							   rdev->mode_info.output_csc_property,
207862306a36Sopenharmony_ci							   RADEON_OUTPUT_CSC_BYPASS);
207962306a36Sopenharmony_ci			/* no HPD on analog connectors */
208062306a36Sopenharmony_ci			radeon_connector->hpd.hpd = RADEON_HPD_NONE;
208162306a36Sopenharmony_ci			connector->interlace_allowed = true;
208262306a36Sopenharmony_ci			connector->doublescan_allowed = true;
208362306a36Sopenharmony_ci			break;
208462306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_DVII:
208562306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_DVID:
208662306a36Sopenharmony_ci			radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
208762306a36Sopenharmony_ci			if (!radeon_dig_connector)
208862306a36Sopenharmony_ci				goto failed;
208962306a36Sopenharmony_ci			radeon_dig_connector->igp_lane_info = igp_lane_info;
209062306a36Sopenharmony_ci			radeon_connector->con_priv = radeon_dig_connector;
209162306a36Sopenharmony_ci			if (i2c_bus->valid) {
209262306a36Sopenharmony_ci				radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
209362306a36Sopenharmony_ci				if (!radeon_connector->ddc_bus)
209462306a36Sopenharmony_ci					DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
209562306a36Sopenharmony_ci				else
209662306a36Sopenharmony_ci					ddc = &radeon_connector->ddc_bus->adapter;
209762306a36Sopenharmony_ci			}
209862306a36Sopenharmony_ci			drm_connector_init_with_ddc(dev, &radeon_connector->base,
209962306a36Sopenharmony_ci						    &radeon_dvi_connector_funcs,
210062306a36Sopenharmony_ci						    connector_type,
210162306a36Sopenharmony_ci						    ddc);
210262306a36Sopenharmony_ci			drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
210362306a36Sopenharmony_ci			subpixel_order = SubPixelHorizontalRGB;
210462306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
210562306a36Sopenharmony_ci						      rdev->mode_info.coherent_mode_property,
210662306a36Sopenharmony_ci						      1);
210762306a36Sopenharmony_ci			if (ASIC_IS_AVIVO(rdev)) {
210862306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
210962306a36Sopenharmony_ci							      rdev->mode_info.underscan_property,
211062306a36Sopenharmony_ci							      UNDERSCAN_OFF);
211162306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
211262306a36Sopenharmony_ci							      rdev->mode_info.underscan_hborder_property,
211362306a36Sopenharmony_ci							      0);
211462306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
211562306a36Sopenharmony_ci							      rdev->mode_info.underscan_vborder_property,
211662306a36Sopenharmony_ci							      0);
211762306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
211862306a36Sopenharmony_ci							   rdev->mode_info.dither_property,
211962306a36Sopenharmony_ci							   RADEON_FMT_DITHER_DISABLE);
212062306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
212162306a36Sopenharmony_ci							   dev->mode_config.scaling_mode_property,
212262306a36Sopenharmony_ci							   DRM_MODE_SCALE_NONE);
212362306a36Sopenharmony_ci			}
212462306a36Sopenharmony_ci			if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
212562306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
212662306a36Sopenharmony_ci							   rdev->mode_info.audio_property,
212762306a36Sopenharmony_ci							   RADEON_AUDIO_AUTO);
212862306a36Sopenharmony_ci				radeon_connector->audio = RADEON_AUDIO_AUTO;
212962306a36Sopenharmony_ci			}
213062306a36Sopenharmony_ci			if (connector_type == DRM_MODE_CONNECTOR_DVII) {
213162306a36Sopenharmony_ci				radeon_connector->dac_load_detect = true;
213262306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
213362306a36Sopenharmony_ci							      rdev->mode_info.load_detect_property,
213462306a36Sopenharmony_ci							      1);
213562306a36Sopenharmony_ci			}
213662306a36Sopenharmony_ci			if (ASIC_IS_DCE5(rdev))
213762306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
213862306a36Sopenharmony_ci							   rdev->mode_info.output_csc_property,
213962306a36Sopenharmony_ci							   RADEON_OUTPUT_CSC_BYPASS);
214062306a36Sopenharmony_ci			connector->interlace_allowed = true;
214162306a36Sopenharmony_ci			if (connector_type == DRM_MODE_CONNECTOR_DVII)
214262306a36Sopenharmony_ci				connector->doublescan_allowed = true;
214362306a36Sopenharmony_ci			else
214462306a36Sopenharmony_ci				connector->doublescan_allowed = false;
214562306a36Sopenharmony_ci			break;
214662306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_HDMIA:
214762306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_HDMIB:
214862306a36Sopenharmony_ci			radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
214962306a36Sopenharmony_ci			if (!radeon_dig_connector)
215062306a36Sopenharmony_ci				goto failed;
215162306a36Sopenharmony_ci			radeon_dig_connector->igp_lane_info = igp_lane_info;
215262306a36Sopenharmony_ci			radeon_connector->con_priv = radeon_dig_connector;
215362306a36Sopenharmony_ci			if (i2c_bus->valid) {
215462306a36Sopenharmony_ci				radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
215562306a36Sopenharmony_ci				if (!radeon_connector->ddc_bus)
215662306a36Sopenharmony_ci					DRM_ERROR("HDMI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
215762306a36Sopenharmony_ci				else
215862306a36Sopenharmony_ci					ddc = &radeon_connector->ddc_bus->adapter;
215962306a36Sopenharmony_ci			}
216062306a36Sopenharmony_ci			drm_connector_init_with_ddc(dev, &radeon_connector->base,
216162306a36Sopenharmony_ci						    &radeon_dvi_connector_funcs,
216262306a36Sopenharmony_ci						    connector_type,
216362306a36Sopenharmony_ci						    ddc);
216462306a36Sopenharmony_ci			drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
216562306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
216662306a36Sopenharmony_ci						      rdev->mode_info.coherent_mode_property,
216762306a36Sopenharmony_ci						      1);
216862306a36Sopenharmony_ci			if (ASIC_IS_AVIVO(rdev)) {
216962306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
217062306a36Sopenharmony_ci							      rdev->mode_info.underscan_property,
217162306a36Sopenharmony_ci							      UNDERSCAN_OFF);
217262306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
217362306a36Sopenharmony_ci							      rdev->mode_info.underscan_hborder_property,
217462306a36Sopenharmony_ci							      0);
217562306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
217662306a36Sopenharmony_ci							      rdev->mode_info.underscan_vborder_property,
217762306a36Sopenharmony_ci							      0);
217862306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
217962306a36Sopenharmony_ci							   rdev->mode_info.dither_property,
218062306a36Sopenharmony_ci							   RADEON_FMT_DITHER_DISABLE);
218162306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
218262306a36Sopenharmony_ci							   dev->mode_config.scaling_mode_property,
218362306a36Sopenharmony_ci							   DRM_MODE_SCALE_NONE);
218462306a36Sopenharmony_ci			}
218562306a36Sopenharmony_ci			if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
218662306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
218762306a36Sopenharmony_ci							   rdev->mode_info.audio_property,
218862306a36Sopenharmony_ci							   RADEON_AUDIO_AUTO);
218962306a36Sopenharmony_ci				radeon_connector->audio = RADEON_AUDIO_AUTO;
219062306a36Sopenharmony_ci			}
219162306a36Sopenharmony_ci			if (ASIC_IS_DCE5(rdev))
219262306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
219362306a36Sopenharmony_ci							   rdev->mode_info.output_csc_property,
219462306a36Sopenharmony_ci							   RADEON_OUTPUT_CSC_BYPASS);
219562306a36Sopenharmony_ci			subpixel_order = SubPixelHorizontalRGB;
219662306a36Sopenharmony_ci			connector->interlace_allowed = true;
219762306a36Sopenharmony_ci			if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
219862306a36Sopenharmony_ci				connector->doublescan_allowed = true;
219962306a36Sopenharmony_ci			else
220062306a36Sopenharmony_ci				connector->doublescan_allowed = false;
220162306a36Sopenharmony_ci			break;
220262306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_DisplayPort:
220362306a36Sopenharmony_ci			radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
220462306a36Sopenharmony_ci			if (!radeon_dig_connector)
220562306a36Sopenharmony_ci				goto failed;
220662306a36Sopenharmony_ci			radeon_dig_connector->igp_lane_info = igp_lane_info;
220762306a36Sopenharmony_ci			radeon_connector->con_priv = radeon_dig_connector;
220862306a36Sopenharmony_ci			if (i2c_bus->valid) {
220962306a36Sopenharmony_ci				radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
221062306a36Sopenharmony_ci				if (radeon_connector->ddc_bus) {
221162306a36Sopenharmony_ci					has_aux = true;
221262306a36Sopenharmony_ci					ddc = &radeon_connector->ddc_bus->adapter;
221362306a36Sopenharmony_ci				} else {
221462306a36Sopenharmony_ci					DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
221562306a36Sopenharmony_ci				}
221662306a36Sopenharmony_ci			}
221762306a36Sopenharmony_ci			drm_connector_init_with_ddc(dev, &radeon_connector->base,
221862306a36Sopenharmony_ci						    &radeon_dp_connector_funcs,
221962306a36Sopenharmony_ci						    connector_type,
222062306a36Sopenharmony_ci						    ddc);
222162306a36Sopenharmony_ci			drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs);
222262306a36Sopenharmony_ci			subpixel_order = SubPixelHorizontalRGB;
222362306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
222462306a36Sopenharmony_ci						      rdev->mode_info.coherent_mode_property,
222562306a36Sopenharmony_ci						      1);
222662306a36Sopenharmony_ci			if (ASIC_IS_AVIVO(rdev)) {
222762306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
222862306a36Sopenharmony_ci							      rdev->mode_info.underscan_property,
222962306a36Sopenharmony_ci							      UNDERSCAN_OFF);
223062306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
223162306a36Sopenharmony_ci							      rdev->mode_info.underscan_hborder_property,
223262306a36Sopenharmony_ci							      0);
223362306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
223462306a36Sopenharmony_ci							      rdev->mode_info.underscan_vborder_property,
223562306a36Sopenharmony_ci							      0);
223662306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
223762306a36Sopenharmony_ci							   rdev->mode_info.dither_property,
223862306a36Sopenharmony_ci							   RADEON_FMT_DITHER_DISABLE);
223962306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
224062306a36Sopenharmony_ci							   dev->mode_config.scaling_mode_property,
224162306a36Sopenharmony_ci							   DRM_MODE_SCALE_NONE);
224262306a36Sopenharmony_ci			}
224362306a36Sopenharmony_ci			if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
224462306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
224562306a36Sopenharmony_ci							   rdev->mode_info.audio_property,
224662306a36Sopenharmony_ci							   RADEON_AUDIO_AUTO);
224762306a36Sopenharmony_ci				radeon_connector->audio = RADEON_AUDIO_AUTO;
224862306a36Sopenharmony_ci			}
224962306a36Sopenharmony_ci			if (ASIC_IS_DCE5(rdev))
225062306a36Sopenharmony_ci				drm_object_attach_property(&radeon_connector->base.base,
225162306a36Sopenharmony_ci							   rdev->mode_info.output_csc_property,
225262306a36Sopenharmony_ci							   RADEON_OUTPUT_CSC_BYPASS);
225362306a36Sopenharmony_ci			connector->interlace_allowed = true;
225462306a36Sopenharmony_ci			/* in theory with a DP to VGA converter... */
225562306a36Sopenharmony_ci			connector->doublescan_allowed = false;
225662306a36Sopenharmony_ci			break;
225762306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_eDP:
225862306a36Sopenharmony_ci			radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
225962306a36Sopenharmony_ci			if (!radeon_dig_connector)
226062306a36Sopenharmony_ci				goto failed;
226162306a36Sopenharmony_ci			radeon_dig_connector->igp_lane_info = igp_lane_info;
226262306a36Sopenharmony_ci			radeon_connector->con_priv = radeon_dig_connector;
226362306a36Sopenharmony_ci			if (i2c_bus->valid) {
226462306a36Sopenharmony_ci				radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
226562306a36Sopenharmony_ci				if (radeon_connector->ddc_bus) {
226662306a36Sopenharmony_ci					has_aux = true;
226762306a36Sopenharmony_ci					ddc = &radeon_connector->ddc_bus->adapter;
226862306a36Sopenharmony_ci				} else {
226962306a36Sopenharmony_ci					DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
227062306a36Sopenharmony_ci				}
227162306a36Sopenharmony_ci			}
227262306a36Sopenharmony_ci			drm_connector_init_with_ddc(dev, &radeon_connector->base,
227362306a36Sopenharmony_ci						    &radeon_edp_connector_funcs,
227462306a36Sopenharmony_ci						    connector_type,
227562306a36Sopenharmony_ci						    ddc);
227662306a36Sopenharmony_ci			drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs);
227762306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
227862306a36Sopenharmony_ci						      dev->mode_config.scaling_mode_property,
227962306a36Sopenharmony_ci						      DRM_MODE_SCALE_FULLSCREEN);
228062306a36Sopenharmony_ci			subpixel_order = SubPixelHorizontalRGB;
228162306a36Sopenharmony_ci			connector->interlace_allowed = false;
228262306a36Sopenharmony_ci			connector->doublescan_allowed = false;
228362306a36Sopenharmony_ci			break;
228462306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_SVIDEO:
228562306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_Composite:
228662306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_9PinDIN:
228762306a36Sopenharmony_ci			drm_connector_init_with_ddc(dev, &radeon_connector->base,
228862306a36Sopenharmony_ci						    &radeon_tv_connector_funcs,
228962306a36Sopenharmony_ci						    connector_type,
229062306a36Sopenharmony_ci						    ddc);
229162306a36Sopenharmony_ci			drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
229262306a36Sopenharmony_ci			radeon_connector->dac_load_detect = true;
229362306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
229462306a36Sopenharmony_ci						      rdev->mode_info.load_detect_property,
229562306a36Sopenharmony_ci						      1);
229662306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
229762306a36Sopenharmony_ci						      rdev->mode_info.tv_std_property,
229862306a36Sopenharmony_ci						      radeon_atombios_get_tv_info(rdev));
229962306a36Sopenharmony_ci			/* no HPD on analog connectors */
230062306a36Sopenharmony_ci			radeon_connector->hpd.hpd = RADEON_HPD_NONE;
230162306a36Sopenharmony_ci			connector->interlace_allowed = false;
230262306a36Sopenharmony_ci			connector->doublescan_allowed = false;
230362306a36Sopenharmony_ci			break;
230462306a36Sopenharmony_ci		case DRM_MODE_CONNECTOR_LVDS:
230562306a36Sopenharmony_ci			radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
230662306a36Sopenharmony_ci			if (!radeon_dig_connector)
230762306a36Sopenharmony_ci				goto failed;
230862306a36Sopenharmony_ci			radeon_dig_connector->igp_lane_info = igp_lane_info;
230962306a36Sopenharmony_ci			radeon_connector->con_priv = radeon_dig_connector;
231062306a36Sopenharmony_ci			if (i2c_bus->valid) {
231162306a36Sopenharmony_ci				radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
231262306a36Sopenharmony_ci				if (!radeon_connector->ddc_bus)
231362306a36Sopenharmony_ci					DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
231462306a36Sopenharmony_ci				else
231562306a36Sopenharmony_ci					ddc = &radeon_connector->ddc_bus->adapter;
231662306a36Sopenharmony_ci			}
231762306a36Sopenharmony_ci			drm_connector_init_with_ddc(dev, &radeon_connector->base,
231862306a36Sopenharmony_ci						    &radeon_lvds_connector_funcs,
231962306a36Sopenharmony_ci						    connector_type,
232062306a36Sopenharmony_ci						    ddc);
232162306a36Sopenharmony_ci			drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
232262306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
232362306a36Sopenharmony_ci						      dev->mode_config.scaling_mode_property,
232462306a36Sopenharmony_ci						      DRM_MODE_SCALE_FULLSCREEN);
232562306a36Sopenharmony_ci			subpixel_order = SubPixelHorizontalRGB;
232662306a36Sopenharmony_ci			connector->interlace_allowed = false;
232762306a36Sopenharmony_ci			connector->doublescan_allowed = false;
232862306a36Sopenharmony_ci			break;
232962306a36Sopenharmony_ci		}
233062306a36Sopenharmony_ci	}
233162306a36Sopenharmony_ci
233262306a36Sopenharmony_ci	if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
233362306a36Sopenharmony_ci		if (i2c_bus->valid) {
233462306a36Sopenharmony_ci			connector->polled = DRM_CONNECTOR_POLL_CONNECT |
233562306a36Sopenharmony_ci			                    DRM_CONNECTOR_POLL_DISCONNECT;
233662306a36Sopenharmony_ci		}
233762306a36Sopenharmony_ci	} else
233862306a36Sopenharmony_ci		connector->polled = DRM_CONNECTOR_POLL_HPD;
233962306a36Sopenharmony_ci
234062306a36Sopenharmony_ci	connector->display_info.subpixel_order = subpixel_order;
234162306a36Sopenharmony_ci	drm_connector_register(connector);
234262306a36Sopenharmony_ci
234362306a36Sopenharmony_ci	if (has_aux)
234462306a36Sopenharmony_ci		radeon_dp_aux_init(radeon_connector);
234562306a36Sopenharmony_ci
234662306a36Sopenharmony_ci	return;
234762306a36Sopenharmony_ci
234862306a36Sopenharmony_cifailed:
234962306a36Sopenharmony_ci	drm_connector_cleanup(connector);
235062306a36Sopenharmony_ci	kfree(connector);
235162306a36Sopenharmony_ci}
235262306a36Sopenharmony_ci
235362306a36Sopenharmony_civoid
235462306a36Sopenharmony_ciradeon_add_legacy_connector(struct drm_device *dev,
235562306a36Sopenharmony_ci			    uint32_t connector_id,
235662306a36Sopenharmony_ci			    uint32_t supported_device,
235762306a36Sopenharmony_ci			    int connector_type,
235862306a36Sopenharmony_ci			    struct radeon_i2c_bus_rec *i2c_bus,
235962306a36Sopenharmony_ci			    uint16_t connector_object_id,
236062306a36Sopenharmony_ci			    struct radeon_hpd *hpd)
236162306a36Sopenharmony_ci{
236262306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
236362306a36Sopenharmony_ci	struct drm_connector *connector;
236462306a36Sopenharmony_ci	struct radeon_connector *radeon_connector;
236562306a36Sopenharmony_ci	struct i2c_adapter *ddc = NULL;
236662306a36Sopenharmony_ci	uint32_t subpixel_order = SubPixelNone;
236762306a36Sopenharmony_ci
236862306a36Sopenharmony_ci	if (connector_type == DRM_MODE_CONNECTOR_Unknown)
236962306a36Sopenharmony_ci		return;
237062306a36Sopenharmony_ci
237162306a36Sopenharmony_ci	/* if the user selected tv=0 don't try and add the connector */
237262306a36Sopenharmony_ci	if (((connector_type == DRM_MODE_CONNECTOR_SVIDEO) ||
237362306a36Sopenharmony_ci	     (connector_type == DRM_MODE_CONNECTOR_Composite) ||
237462306a36Sopenharmony_ci	     (connector_type == DRM_MODE_CONNECTOR_9PinDIN)) &&
237562306a36Sopenharmony_ci	    (radeon_tv == 0))
237662306a36Sopenharmony_ci		return;
237762306a36Sopenharmony_ci
237862306a36Sopenharmony_ci	/* see if we already added it */
237962306a36Sopenharmony_ci	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
238062306a36Sopenharmony_ci		radeon_connector = to_radeon_connector(connector);
238162306a36Sopenharmony_ci		if (radeon_connector->connector_id == connector_id) {
238262306a36Sopenharmony_ci			radeon_connector->devices |= supported_device;
238362306a36Sopenharmony_ci			return;
238462306a36Sopenharmony_ci		}
238562306a36Sopenharmony_ci	}
238662306a36Sopenharmony_ci
238762306a36Sopenharmony_ci	radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL);
238862306a36Sopenharmony_ci	if (!radeon_connector)
238962306a36Sopenharmony_ci		return;
239062306a36Sopenharmony_ci
239162306a36Sopenharmony_ci	connector = &radeon_connector->base;
239262306a36Sopenharmony_ci
239362306a36Sopenharmony_ci	radeon_connector->connector_id = connector_id;
239462306a36Sopenharmony_ci	radeon_connector->devices = supported_device;
239562306a36Sopenharmony_ci	radeon_connector->connector_object_id = connector_object_id;
239662306a36Sopenharmony_ci	radeon_connector->hpd = *hpd;
239762306a36Sopenharmony_ci
239862306a36Sopenharmony_ci	switch (connector_type) {
239962306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_VGA:
240062306a36Sopenharmony_ci		if (i2c_bus->valid) {
240162306a36Sopenharmony_ci			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
240262306a36Sopenharmony_ci			if (!radeon_connector->ddc_bus)
240362306a36Sopenharmony_ci				DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
240462306a36Sopenharmony_ci			else
240562306a36Sopenharmony_ci				ddc = &radeon_connector->ddc_bus->adapter;
240662306a36Sopenharmony_ci		}
240762306a36Sopenharmony_ci		drm_connector_init_with_ddc(dev, &radeon_connector->base,
240862306a36Sopenharmony_ci					    &radeon_vga_connector_funcs,
240962306a36Sopenharmony_ci					    connector_type,
241062306a36Sopenharmony_ci					    ddc);
241162306a36Sopenharmony_ci		drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
241262306a36Sopenharmony_ci		radeon_connector->dac_load_detect = true;
241362306a36Sopenharmony_ci		drm_object_attach_property(&radeon_connector->base.base,
241462306a36Sopenharmony_ci					      rdev->mode_info.load_detect_property,
241562306a36Sopenharmony_ci					      1);
241662306a36Sopenharmony_ci		/* no HPD on analog connectors */
241762306a36Sopenharmony_ci		radeon_connector->hpd.hpd = RADEON_HPD_NONE;
241862306a36Sopenharmony_ci		connector->interlace_allowed = true;
241962306a36Sopenharmony_ci		connector->doublescan_allowed = true;
242062306a36Sopenharmony_ci		break;
242162306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_DVIA:
242262306a36Sopenharmony_ci		if (i2c_bus->valid) {
242362306a36Sopenharmony_ci			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
242462306a36Sopenharmony_ci			if (!radeon_connector->ddc_bus)
242562306a36Sopenharmony_ci				DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
242662306a36Sopenharmony_ci			else
242762306a36Sopenharmony_ci				ddc = &radeon_connector->ddc_bus->adapter;
242862306a36Sopenharmony_ci		}
242962306a36Sopenharmony_ci		drm_connector_init_with_ddc(dev, &radeon_connector->base,
243062306a36Sopenharmony_ci					    &radeon_vga_connector_funcs,
243162306a36Sopenharmony_ci					    connector_type,
243262306a36Sopenharmony_ci					    ddc);
243362306a36Sopenharmony_ci		drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
243462306a36Sopenharmony_ci		radeon_connector->dac_load_detect = true;
243562306a36Sopenharmony_ci		drm_object_attach_property(&radeon_connector->base.base,
243662306a36Sopenharmony_ci					      rdev->mode_info.load_detect_property,
243762306a36Sopenharmony_ci					      1);
243862306a36Sopenharmony_ci		/* no HPD on analog connectors */
243962306a36Sopenharmony_ci		radeon_connector->hpd.hpd = RADEON_HPD_NONE;
244062306a36Sopenharmony_ci		connector->interlace_allowed = true;
244162306a36Sopenharmony_ci		connector->doublescan_allowed = true;
244262306a36Sopenharmony_ci		break;
244362306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_DVII:
244462306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_DVID:
244562306a36Sopenharmony_ci		if (i2c_bus->valid) {
244662306a36Sopenharmony_ci			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
244762306a36Sopenharmony_ci			if (!radeon_connector->ddc_bus)
244862306a36Sopenharmony_ci				DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
244962306a36Sopenharmony_ci			else
245062306a36Sopenharmony_ci				ddc = &radeon_connector->ddc_bus->adapter;
245162306a36Sopenharmony_ci		}
245262306a36Sopenharmony_ci		drm_connector_init_with_ddc(dev, &radeon_connector->base,
245362306a36Sopenharmony_ci					    &radeon_dvi_connector_funcs,
245462306a36Sopenharmony_ci					    connector_type,
245562306a36Sopenharmony_ci					    ddc);
245662306a36Sopenharmony_ci		drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
245762306a36Sopenharmony_ci		if (connector_type == DRM_MODE_CONNECTOR_DVII) {
245862306a36Sopenharmony_ci			radeon_connector->dac_load_detect = true;
245962306a36Sopenharmony_ci			drm_object_attach_property(&radeon_connector->base.base,
246062306a36Sopenharmony_ci						      rdev->mode_info.load_detect_property,
246162306a36Sopenharmony_ci						      1);
246262306a36Sopenharmony_ci		}
246362306a36Sopenharmony_ci		subpixel_order = SubPixelHorizontalRGB;
246462306a36Sopenharmony_ci		connector->interlace_allowed = true;
246562306a36Sopenharmony_ci		if (connector_type == DRM_MODE_CONNECTOR_DVII)
246662306a36Sopenharmony_ci			connector->doublescan_allowed = true;
246762306a36Sopenharmony_ci		else
246862306a36Sopenharmony_ci			connector->doublescan_allowed = false;
246962306a36Sopenharmony_ci		break;
247062306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_SVIDEO:
247162306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_Composite:
247262306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_9PinDIN:
247362306a36Sopenharmony_ci		drm_connector_init_with_ddc(dev, &radeon_connector->base,
247462306a36Sopenharmony_ci					    &radeon_tv_connector_funcs,
247562306a36Sopenharmony_ci					    connector_type,
247662306a36Sopenharmony_ci					    ddc);
247762306a36Sopenharmony_ci		drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
247862306a36Sopenharmony_ci		radeon_connector->dac_load_detect = true;
247962306a36Sopenharmony_ci		/* RS400,RC410,RS480 chipset seems to report a lot
248062306a36Sopenharmony_ci		 * of false positive on load detect, we haven't yet
248162306a36Sopenharmony_ci		 * found a way to make load detect reliable on those
248262306a36Sopenharmony_ci		 * chipset, thus just disable it for TV.
248362306a36Sopenharmony_ci		 */
248462306a36Sopenharmony_ci		if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480)
248562306a36Sopenharmony_ci			radeon_connector->dac_load_detect = false;
248662306a36Sopenharmony_ci		drm_object_attach_property(&radeon_connector->base.base,
248762306a36Sopenharmony_ci					      rdev->mode_info.load_detect_property,
248862306a36Sopenharmony_ci					      radeon_connector->dac_load_detect);
248962306a36Sopenharmony_ci		drm_object_attach_property(&radeon_connector->base.base,
249062306a36Sopenharmony_ci					      rdev->mode_info.tv_std_property,
249162306a36Sopenharmony_ci					      radeon_combios_get_tv_info(rdev));
249262306a36Sopenharmony_ci		/* no HPD on analog connectors */
249362306a36Sopenharmony_ci		radeon_connector->hpd.hpd = RADEON_HPD_NONE;
249462306a36Sopenharmony_ci		connector->interlace_allowed = false;
249562306a36Sopenharmony_ci		connector->doublescan_allowed = false;
249662306a36Sopenharmony_ci		break;
249762306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_LVDS:
249862306a36Sopenharmony_ci		if (i2c_bus->valid) {
249962306a36Sopenharmony_ci			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
250062306a36Sopenharmony_ci			if (!radeon_connector->ddc_bus)
250162306a36Sopenharmony_ci				DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
250262306a36Sopenharmony_ci			else
250362306a36Sopenharmony_ci				ddc = &radeon_connector->ddc_bus->adapter;
250462306a36Sopenharmony_ci		}
250562306a36Sopenharmony_ci		drm_connector_init_with_ddc(dev, &radeon_connector->base,
250662306a36Sopenharmony_ci					    &radeon_lvds_connector_funcs,
250762306a36Sopenharmony_ci					    connector_type,
250862306a36Sopenharmony_ci					    ddc);
250962306a36Sopenharmony_ci		drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
251062306a36Sopenharmony_ci		drm_object_attach_property(&radeon_connector->base.base,
251162306a36Sopenharmony_ci					      dev->mode_config.scaling_mode_property,
251262306a36Sopenharmony_ci					      DRM_MODE_SCALE_FULLSCREEN);
251362306a36Sopenharmony_ci		subpixel_order = SubPixelHorizontalRGB;
251462306a36Sopenharmony_ci		connector->interlace_allowed = false;
251562306a36Sopenharmony_ci		connector->doublescan_allowed = false;
251662306a36Sopenharmony_ci		break;
251762306a36Sopenharmony_ci	}
251862306a36Sopenharmony_ci
251962306a36Sopenharmony_ci	if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
252062306a36Sopenharmony_ci		if (i2c_bus->valid) {
252162306a36Sopenharmony_ci			connector->polled = DRM_CONNECTOR_POLL_CONNECT |
252262306a36Sopenharmony_ci			                    DRM_CONNECTOR_POLL_DISCONNECT;
252362306a36Sopenharmony_ci		}
252462306a36Sopenharmony_ci	} else
252562306a36Sopenharmony_ci		connector->polled = DRM_CONNECTOR_POLL_HPD;
252662306a36Sopenharmony_ci
252762306a36Sopenharmony_ci	connector->display_info.subpixel_order = subpixel_order;
252862306a36Sopenharmony_ci	drm_connector_register(connector);
252962306a36Sopenharmony_ci}
2530