1771fe6b9SJerome Glisse /*
2771fe6b9SJerome Glisse  * Copyright 2007-8 Advanced Micro Devices, Inc.
3771fe6b9SJerome Glisse  * Copyright 2008 Red Hat Inc.
4771fe6b9SJerome Glisse  *
5771fe6b9SJerome Glisse  * Permission is hereby granted, free of charge, to any person obtaining a
6771fe6b9SJerome Glisse  * copy of this software and associated documentation files (the "Software"),
7771fe6b9SJerome Glisse  * to deal in the Software without restriction, including without limitation
8771fe6b9SJerome Glisse  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9771fe6b9SJerome Glisse  * and/or sell copies of the Software, and to permit persons to whom the
10771fe6b9SJerome Glisse  * Software is furnished to do so, subject to the following conditions:
11771fe6b9SJerome Glisse  *
12771fe6b9SJerome Glisse  * The above copyright notice and this permission notice shall be included in
13771fe6b9SJerome Glisse  * all copies or substantial portions of the Software.
14771fe6b9SJerome Glisse  *
15771fe6b9SJerome Glisse  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16771fe6b9SJerome Glisse  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17771fe6b9SJerome Glisse  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18771fe6b9SJerome Glisse  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19771fe6b9SJerome Glisse  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20771fe6b9SJerome Glisse  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21771fe6b9SJerome Glisse  * OTHER DEALINGS IN THE SOFTWARE.
22771fe6b9SJerome Glisse  *
23771fe6b9SJerome Glisse  * Authors: Dave Airlie
24771fe6b9SJerome Glisse  *          Alex Deucher
25771fe6b9SJerome Glisse  */
26f9183127SSam Ravnborg 
27da68386dSThomas Zimmermann #include <drm/display/drm_dp_mst_helper.h>
28760285e7SDavid Howells #include <drm/drm_edid.h>
29760285e7SDavid Howells #include <drm/drm_crtc_helper.h>
30f7d17cd4SThomas Zimmermann #include <drm/drm_modeset_helper_vtables.h>
31fcd70cd3SDaniel Vetter #include <drm/drm_probe_helper.h>
32760285e7SDavid Howells #include <drm/radeon_drm.h>
33771fe6b9SJerome Glisse #include "radeon.h"
341a626b68SSlava Grigorev #include "radeon_audio.h"
35923f6848SAlex Deucher #include "atom.h"
36771fe6b9SJerome Glisse 
3710ebc0bcSDave Airlie #include <linux/pm_runtime.h>
3847eb8f73SLukas Wunner #include <linux/vga_switcheroo.h>
3910ebc0bcSDave Airlie 
radeon_connector_hotplug(struct drm_connector * connector)40d4877cf2SAlex Deucher void radeon_connector_hotplug(struct drm_connector *connector)
41d4877cf2SAlex Deucher {
42d4877cf2SAlex Deucher 	struct drm_device *dev = connector->dev;
43d4877cf2SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
44d4877cf2SAlex Deucher 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
45d4877cf2SAlex Deucher 
46cbac9543SAlex Deucher 	/* bail if the connector does not have hpd pin, e.g.,
47cbac9543SAlex Deucher 	 * VGA, TV, etc.
48cbac9543SAlex Deucher 	 */
49cbac9543SAlex Deucher 	if (radeon_connector->hpd.hpd == RADEON_HPD_NONE)
50cbac9543SAlex Deucher 		return;
51cbac9543SAlex Deucher 
52d4877cf2SAlex Deucher 	radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
53d4877cf2SAlex Deucher 
5473104b5cSAlex Deucher 	/* if the connector is already off, don't turn it back on */
556e9f798dSDaniel Vetter 	/* FIXME: This access isn't protected by any locks. */
5673104b5cSAlex Deucher 	if (connector->dpms != DRM_MODE_DPMS_ON)
5773104b5cSAlex Deucher 		return;
5873104b5cSAlex Deucher 
59d5811e87SAlex Deucher 	/* just deal with DP (not eDP) here. */
60d5811e87SAlex Deucher 	if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
61266dcba5SJerome Glisse 		struct radeon_connector_atom_dig *dig_connector =
62266dcba5SJerome Glisse 			radeon_connector->con_priv;
637c3ed0fdSAlex Deucher 
64266dcba5SJerome Glisse 		/* if existing sink type was not DP no need to retrain */
65266dcba5SJerome Glisse 		if (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_DISPLAYPORT)
66266dcba5SJerome Glisse 			return;
67266dcba5SJerome Glisse 
68266dcba5SJerome Glisse 		/* first get sink type as it may be reset after (un)plug */
69266dcba5SJerome Glisse 		dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector);
70266dcba5SJerome Glisse 		/* don't do anything if sink is not display port, i.e.,
71266dcba5SJerome Glisse 		 * passive dp->(dvi|hdmi) adaptor
72266dcba5SJerome Glisse 		 */
732681bc79SMichel Dänzer 		if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT &&
742681bc79SMichel Dänzer 		    radeon_hpd_sense(rdev, radeon_connector->hpd.hpd) &&
752681bc79SMichel Dänzer 		    radeon_dp_needs_link_train(radeon_connector)) {
762681bc79SMichel Dänzer 			/* Don't start link training before we have the DPCD */
77924f92bfSStephen Chandler Paul 			if (!radeon_dp_getdpcd(radeon_connector))
78924f92bfSStephen Chandler Paul 				return;
79924f92bfSStephen Chandler Paul 
802681bc79SMichel Dänzer 			/* Turn the connector off and back on immediately, which
812681bc79SMichel Dänzer 			 * will trigger link training
82ca2ccde5SJerome Glisse 			 */
832681bc79SMichel Dänzer 			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
845ba7ddf8SAlex Deucher 			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
85ca2ccde5SJerome Glisse 		}
86d4877cf2SAlex Deucher 	}
87266dcba5SJerome Glisse }
88d4877cf2SAlex Deucher 
radeon_property_change_mode(struct drm_encoder * encoder)89445282dbSDave Airlie static void radeon_property_change_mode(struct drm_encoder *encoder)
90445282dbSDave Airlie {
91445282dbSDave Airlie 	struct drm_crtc *crtc = encoder->crtc;
92445282dbSDave Airlie 
93445282dbSDave Airlie 	if (crtc && crtc->enabled) {
94445282dbSDave Airlie 		drm_crtc_helper_set_mode(crtc, &crtc->mode,
95f4510a27SMatt Roper 					 crtc->x, crtc->y, crtc->primary->fb);
96445282dbSDave Airlie 	}
97445282dbSDave Airlie }
98eccea792SAlex Deucher 
radeon_get_monitor_bpc(struct drm_connector * connector)99eccea792SAlex Deucher int radeon_get_monitor_bpc(struct drm_connector *connector)
100eccea792SAlex Deucher {
101eccea792SAlex Deucher 	struct drm_device *dev = connector->dev;
102eccea792SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
103eccea792SAlex Deucher 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
104eccea792SAlex Deucher 	struct radeon_connector_atom_dig *dig_connector;
105eccea792SAlex Deucher 	int bpc = 8;
106ea292861SMario Kleiner 	int mode_clock, max_tmds_clock;
107eccea792SAlex Deucher 
108eccea792SAlex Deucher 	switch (connector->connector_type) {
109eccea792SAlex Deucher 	case DRM_MODE_CONNECTOR_DVII:
110eccea792SAlex Deucher 	case DRM_MODE_CONNECTOR_HDMIB:
111eccea792SAlex Deucher 		if (radeon_connector->use_digital) {
112377bd8a9SAlex Deucher 			if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
113eccea792SAlex Deucher 				if (connector->display_info.bpc)
114eccea792SAlex Deucher 					bpc = connector->display_info.bpc;
115eccea792SAlex Deucher 			}
116eccea792SAlex Deucher 		}
117eccea792SAlex Deucher 		break;
118eccea792SAlex Deucher 	case DRM_MODE_CONNECTOR_DVID:
119eccea792SAlex Deucher 	case DRM_MODE_CONNECTOR_HDMIA:
120377bd8a9SAlex Deucher 		if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
121eccea792SAlex Deucher 			if (connector->display_info.bpc)
122eccea792SAlex Deucher 				bpc = connector->display_info.bpc;
123eccea792SAlex Deucher 		}
124eccea792SAlex Deucher 		break;
125eccea792SAlex Deucher 	case DRM_MODE_CONNECTOR_DisplayPort:
126eccea792SAlex Deucher 		dig_connector = radeon_connector->con_priv;
127eccea792SAlex Deucher 		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
128eccea792SAlex Deucher 		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) ||
129377bd8a9SAlex Deucher 		    drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
130eccea792SAlex Deucher 			if (connector->display_info.bpc)
131eccea792SAlex Deucher 				bpc = connector->display_info.bpc;
132eccea792SAlex Deucher 		}
133eccea792SAlex Deucher 		break;
134eccea792SAlex Deucher 	case DRM_MODE_CONNECTOR_eDP:
135eccea792SAlex Deucher 	case DRM_MODE_CONNECTOR_LVDS:
136eccea792SAlex Deucher 		if (connector->display_info.bpc)
137eccea792SAlex Deucher 			bpc = connector->display_info.bpc;
138eccea792SAlex Deucher 		else if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
139319d1e14SJani Nikula 			const struct drm_connector_helper_funcs *connector_funcs =
140eccea792SAlex Deucher 				connector->helper_private;
141eccea792SAlex Deucher 			struct drm_encoder *encoder = connector_funcs->best_encoder(connector);
142eccea792SAlex Deucher 			struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
143eccea792SAlex Deucher 			struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
144eccea792SAlex Deucher 
145eccea792SAlex Deucher 			if (dig->lcd_misc & ATOM_PANEL_MISC_V13_6BIT_PER_COLOR)
146eccea792SAlex Deucher 				bpc = 6;
147eccea792SAlex Deucher 			else if (dig->lcd_misc & ATOM_PANEL_MISC_V13_8BIT_PER_COLOR)
148eccea792SAlex Deucher 				bpc = 8;
149eccea792SAlex Deucher 		}
150eccea792SAlex Deucher 		break;
151eccea792SAlex Deucher 	}
15289b92339SMario Kleiner 
153377bd8a9SAlex Deucher 	if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
15489b92339SMario Kleiner 		/* hdmi deep color only implemented on DCE4+ */
15589b92339SMario Kleiner 		if ((bpc > 8) && !ASIC_IS_DCE4(rdev)) {
15689b92339SMario Kleiner 			DRM_DEBUG("%s: HDMI deep color %d bpc unsupported. Using 8 bpc.\n",
15772082093SJani Nikula 					  connector->name, bpc);
15889b92339SMario Kleiner 			bpc = 8;
15989b92339SMario Kleiner 		}
16089b92339SMario Kleiner 
16189b92339SMario Kleiner 		/*
16289b92339SMario Kleiner 		 * Pre DCE-8 hw can't handle > 12 bpc, and more than 12 bpc doesn't make
16389b92339SMario Kleiner 		 * much sense without support for > 12 bpc framebuffers. RGB 4:4:4 at
16489b92339SMario Kleiner 		 * 12 bpc is always supported on hdmi deep color sinks, as this is
16589b92339SMario Kleiner 		 * required by the HDMI-1.3 spec. Clamp to a safe 12 bpc maximum.
16689b92339SMario Kleiner 		 */
16789b92339SMario Kleiner 		if (bpc > 12) {
16889b92339SMario Kleiner 			DRM_DEBUG("%s: HDMI deep color %d bpc unsupported. Using 12 bpc.\n",
16972082093SJani Nikula 					  connector->name, bpc);
17089b92339SMario Kleiner 			bpc = 12;
17189b92339SMario Kleiner 		}
172ea292861SMario Kleiner 
173ea292861SMario Kleiner 		/* Any defined maximum tmds clock limit we must not exceed? */
1742a272ca9SVille Syrjälä 		if (connector->display_info.max_tmds_clock > 0) {
175ea292861SMario Kleiner 			/* mode_clock is clock in kHz for mode to be modeset on this connector */
176ea292861SMario Kleiner 			mode_clock = radeon_connector->pixelclock_for_modeset;
177ea292861SMario Kleiner 
178ea292861SMario Kleiner 			/* Maximum allowable input clock in kHz */
1792a272ca9SVille Syrjälä 			max_tmds_clock = connector->display_info.max_tmds_clock;
180ea292861SMario Kleiner 
181ea292861SMario Kleiner 			DRM_DEBUG("%s: hdmi mode dotclock %d kHz, max tmds input clock %d kHz.\n",
182ea292861SMario Kleiner 					  connector->name, mode_clock, max_tmds_clock);
183ea292861SMario Kleiner 
184ea292861SMario Kleiner 			/* Check if bpc is within clock limit. Try to degrade gracefully otherwise */
185ea292861SMario Kleiner 			if ((bpc == 12) && (mode_clock * 3/2 > max_tmds_clock)) {
1864adc33f3SMaxime Ripard 				if ((connector->display_info.edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30) &&
187ea292861SMario Kleiner 					(mode_clock * 5/4 <= max_tmds_clock))
188ea292861SMario Kleiner 					bpc = 10;
189ea292861SMario Kleiner 				else
190ea292861SMario Kleiner 					bpc = 8;
191ea292861SMario Kleiner 
192ea292861SMario Kleiner 				DRM_DEBUG("%s: HDMI deep color 12 bpc exceeds max tmds clock. Using %d bpc.\n",
193ea292861SMario Kleiner 						  connector->name, bpc);
194ea292861SMario Kleiner 			}
195ea292861SMario Kleiner 
196ea292861SMario Kleiner 			if ((bpc == 10) && (mode_clock * 5/4 > max_tmds_clock)) {
197ea292861SMario Kleiner 				bpc = 8;
198ea292861SMario Kleiner 				DRM_DEBUG("%s: HDMI deep color 10 bpc exceeds max tmds clock. Using %d bpc.\n",
199ea292861SMario Kleiner 						  connector->name, bpc);
200ea292861SMario Kleiner 			}
201dc200356SRan Sun 		} else if (bpc > 8) {
2029f51e2e0SMario Kleiner 			/* max_tmds_clock missing, but hdmi spec mandates it for deep color. */
2039f51e2e0SMario Kleiner 			DRM_DEBUG("%s: Required max tmds clock for HDMI deep color missing. Using 8 bpc.\n",
2049f51e2e0SMario Kleiner 					  connector->name);
2059f51e2e0SMario Kleiner 			bpc = 8;
2069f51e2e0SMario Kleiner 		}
20789b92339SMario Kleiner 	}
20889b92339SMario Kleiner 
2099f51e2e0SMario Kleiner 	if ((radeon_deep_color == 0) && (bpc > 8)) {
2109f51e2e0SMario Kleiner 		DRM_DEBUG("%s: Deep color disabled. Set radeon module param deep_color=1 to enable.\n",
2119f51e2e0SMario Kleiner 				  connector->name);
212a624f429SAlex Deucher 		bpc = 8;
2139f51e2e0SMario Kleiner 	}
214a624f429SAlex Deucher 
21589b92339SMario Kleiner 	DRM_DEBUG("%s: Display bpc=%d, returned bpc=%d\n",
21672082093SJani Nikula 			  connector->name, connector->display_info.bpc, bpc);
21789b92339SMario Kleiner 
218eccea792SAlex Deucher 	return bpc;
219eccea792SAlex Deucher }
220eccea792SAlex Deucher 
221771fe6b9SJerome Glisse static void
radeon_connector_update_scratch_regs(struct drm_connector * connector,enum drm_connector_status status)222771fe6b9SJerome Glisse radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_connector_status status)
223771fe6b9SJerome Glisse {
224771fe6b9SJerome Glisse 	struct drm_device *dev = connector->dev;
225771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
2267b71ca24SVille Syrjälä 	struct drm_encoder *best_encoder;
2277b71ca24SVille Syrjälä 	struct drm_encoder *encoder;
228319d1e14SJani Nikula 	const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
229771fe6b9SJerome Glisse 	bool connected;
230771fe6b9SJerome Glisse 
231771fe6b9SJerome Glisse 	best_encoder = connector_funcs->best_encoder(connector);
232771fe6b9SJerome Glisse 
23362afb4adSJosé Roberto de Souza 	drm_connector_for_each_possible_encoder(connector, encoder) {
234771fe6b9SJerome Glisse 		if ((encoder == best_encoder) && (status == connector_status_connected))
235771fe6b9SJerome Glisse 			connected = true;
236771fe6b9SJerome Glisse 		else
237771fe6b9SJerome Glisse 			connected = false;
238771fe6b9SJerome Glisse 
239771fe6b9SJerome Glisse 		if (rdev->is_atom_bios)
240771fe6b9SJerome Glisse 			radeon_atombios_connected_scratch_regs(connector, encoder, connected);
241771fe6b9SJerome Glisse 		else
242771fe6b9SJerome Glisse 			radeon_combios_connected_scratch_regs(connector, encoder, connected);
243771fe6b9SJerome Glisse 	}
244771fe6b9SJerome Glisse }
245771fe6b9SJerome Glisse 
radeon_find_encoder(struct drm_connector * connector,int encoder_type)2461109ca09SLauri Kasanen static struct drm_encoder *radeon_find_encoder(struct drm_connector *connector, int encoder_type)
247445282dbSDave Airlie {
248445282dbSDave Airlie 	struct drm_encoder *encoder;
249445282dbSDave Airlie 
25062afb4adSJosé Roberto de Souza 	drm_connector_for_each_possible_encoder(connector, encoder) {
251445282dbSDave Airlie 		if (encoder->encoder_type == encoder_type)
252445282dbSDave Airlie 			return encoder;
253445282dbSDave Airlie 	}
2547b71ca24SVille Syrjälä 
255445282dbSDave Airlie 	return NULL;
256445282dbSDave Airlie }
257445282dbSDave Airlie 
radeon_connector_edid(struct drm_connector * connector)258377bd8a9SAlex Deucher struct edid *radeon_connector_edid(struct drm_connector *connector)
259377bd8a9SAlex Deucher {
260377bd8a9SAlex Deucher 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
261377bd8a9SAlex Deucher 	struct drm_property_blob *edid_blob = connector->edid_blob_ptr;
262377bd8a9SAlex Deucher 
263377bd8a9SAlex Deucher 	if (radeon_connector->edid) {
264377bd8a9SAlex Deucher 		return radeon_connector->edid;
265377bd8a9SAlex Deucher 	} else if (edid_blob) {
266377bd8a9SAlex Deucher 		struct edid *edid = kmemdup(edid_blob->data, edid_blob->length, GFP_KERNEL);
267377bd8a9SAlex Deucher 		if (edid)
268377bd8a9SAlex Deucher 			radeon_connector->edid = edid;
269377bd8a9SAlex Deucher 	}
270377bd8a9SAlex Deucher 	return radeon_connector->edid;
271377bd8a9SAlex Deucher }
272377bd8a9SAlex Deucher 
radeon_connector_get_edid(struct drm_connector * connector)27372a5c970SAlex Deucher static void radeon_connector_get_edid(struct drm_connector *connector)
27472a5c970SAlex Deucher {
27572a5c970SAlex Deucher 	struct drm_device *dev = connector->dev;
27672a5c970SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
27772a5c970SAlex Deucher 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
27872a5c970SAlex Deucher 
27972a5c970SAlex Deucher 	if (radeon_connector->edid)
28072a5c970SAlex Deucher 		return;
28172a5c970SAlex Deucher 
28272a5c970SAlex Deucher 	/* on hw with routers, select right port */
28372a5c970SAlex Deucher 	if (radeon_connector->router.ddc_valid)
28472a5c970SAlex Deucher 		radeon_router_select_ddc_port(radeon_connector);
28572a5c970SAlex Deucher 
28672a5c970SAlex Deucher 	if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
28772a5c970SAlex Deucher 	     ENCODER_OBJECT_ID_NONE) &&
28872a5c970SAlex Deucher 	    radeon_connector->ddc_bus->has_aux) {
28972a5c970SAlex Deucher 		radeon_connector->edid = drm_get_edid(connector,
29072a5c970SAlex Deucher 						      &radeon_connector->ddc_bus->aux.ddc);
29172a5c970SAlex Deucher 	} else if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
29272a5c970SAlex Deucher 		   (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
29372a5c970SAlex Deucher 		struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
29472a5c970SAlex Deucher 
29572a5c970SAlex Deucher 		if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
29672a5c970SAlex Deucher 		     dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) &&
29772a5c970SAlex Deucher 		    radeon_connector->ddc_bus->has_aux)
29872a5c970SAlex Deucher 			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
29972a5c970SAlex Deucher 							      &radeon_connector->ddc_bus->aux.ddc);
30072a5c970SAlex Deucher 		else if (radeon_connector->ddc_bus)
30172a5c970SAlex Deucher 			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
30272a5c970SAlex Deucher 							      &radeon_connector->ddc_bus->adapter);
30347eb8f73SLukas Wunner 	} else if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC &&
30447eb8f73SLukas Wunner 		   connector->connector_type == DRM_MODE_CONNECTOR_LVDS &&
30547eb8f73SLukas Wunner 		   radeon_connector->ddc_bus) {
30647eb8f73SLukas Wunner 		radeon_connector->edid = drm_get_edid_switcheroo(&radeon_connector->base,
30747eb8f73SLukas Wunner 								 &radeon_connector->ddc_bus->adapter);
30872a5c970SAlex Deucher 	} else if (radeon_connector->ddc_bus) {
30972a5c970SAlex Deucher 		radeon_connector->edid = drm_get_edid(&radeon_connector->base,
31072a5c970SAlex Deucher 						      &radeon_connector->ddc_bus->adapter);
31172a5c970SAlex Deucher 	}
31272a5c970SAlex Deucher 
31372a5c970SAlex Deucher 	if (!radeon_connector->edid) {
31413485794SAlex Deucher 		/* don't fetch the edid from the vbios if ddc fails and runpm is
31513485794SAlex Deucher 		 * enabled so we report disconnected.
31613485794SAlex Deucher 		 */
31713485794SAlex Deucher 		if ((rdev->flags & RADEON_IS_PX) && (radeon_runtime_pm != 0))
31813485794SAlex Deucher 			return;
31913485794SAlex Deucher 
32072a5c970SAlex Deucher 		if (rdev->is_atom_bios) {
32172a5c970SAlex Deucher 			/* some laptops provide a hardcoded edid in rom for LCDs */
32272a5c970SAlex Deucher 			if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) ||
32372a5c970SAlex Deucher 			     (connector->connector_type == DRM_MODE_CONNECTOR_eDP)))
32472a5c970SAlex Deucher 				radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
32572a5c970SAlex Deucher 		} else {
32672a5c970SAlex Deucher 			/* some servers provide a hardcoded edid in rom for KVMs */
32772a5c970SAlex Deucher 			radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
32872a5c970SAlex Deucher 		}
32972a5c970SAlex Deucher 	}
33072a5c970SAlex Deucher }
33172a5c970SAlex Deucher 
radeon_connector_free_edid(struct drm_connector * connector)33272a5c970SAlex Deucher static void radeon_connector_free_edid(struct drm_connector *connector)
33372a5c970SAlex Deucher {
33472a5c970SAlex Deucher 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
33572a5c970SAlex Deucher 
33672a5c970SAlex Deucher 	kfree(radeon_connector->edid);
33772a5c970SAlex Deucher 	radeon_connector->edid = NULL;
33872a5c970SAlex Deucher }
33972a5c970SAlex Deucher 
radeon_ddc_get_modes(struct drm_connector * connector)34072a5c970SAlex Deucher static int radeon_ddc_get_modes(struct drm_connector *connector)
34172a5c970SAlex Deucher {
34272a5c970SAlex Deucher 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
34372a5c970SAlex Deucher 	int ret;
34472a5c970SAlex Deucher 
34572a5c970SAlex Deucher 	if (radeon_connector->edid) {
346c555f023SDaniel Vetter 		drm_connector_update_edid_property(connector, radeon_connector->edid);
34772a5c970SAlex Deucher 		ret = drm_add_edid_modes(connector, radeon_connector->edid);
34872a5c970SAlex Deucher 		return ret;
34972a5c970SAlex Deucher 	}
350c555f023SDaniel Vetter 	drm_connector_update_edid_property(connector, NULL);
35172a5c970SAlex Deucher 	return 0;
35272a5c970SAlex Deucher }
35372a5c970SAlex Deucher 
radeon_best_single_encoder(struct drm_connector * connector)3541109ca09SLauri Kasanen static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
355771fe6b9SJerome Glisse {
3567b71ca24SVille Syrjälä 	struct drm_encoder *encoder;
3577b71ca24SVille Syrjälä 
3587b71ca24SVille Syrjälä 	/* pick the first one */
35962afb4adSJosé Roberto de Souza 	drm_connector_for_each_possible_encoder(connector, encoder)
3607b71ca24SVille Syrjälä 		return encoder;
3617b71ca24SVille Syrjälä 
362771fe6b9SJerome Glisse 	return NULL;
363771fe6b9SJerome Glisse }
364771fe6b9SJerome Glisse 
radeon_get_native_mode(struct drm_connector * connector)365da997620SAlex Deucher static void radeon_get_native_mode(struct drm_connector *connector)
366da997620SAlex Deucher {
367da997620SAlex Deucher 	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
368da997620SAlex Deucher 	struct radeon_encoder *radeon_encoder;
369da997620SAlex Deucher 
370da997620SAlex Deucher 	if (encoder == NULL)
371da997620SAlex Deucher 		return;
372da997620SAlex Deucher 
373da997620SAlex Deucher 	radeon_encoder = to_radeon_encoder(encoder);
374da997620SAlex Deucher 
375da997620SAlex Deucher 	if (!list_empty(&connector->probed_modes)) {
376da997620SAlex Deucher 		struct drm_display_mode *preferred_mode =
377da997620SAlex Deucher 			list_first_entry(&connector->probed_modes,
378da997620SAlex Deucher 					 struct drm_display_mode, head);
379da997620SAlex Deucher 
380da997620SAlex Deucher 		radeon_encoder->native_mode = *preferred_mode;
381da997620SAlex Deucher 	} else {
382da997620SAlex Deucher 		radeon_encoder->native_mode.clock = 0;
383da997620SAlex Deucher 	}
384da997620SAlex Deucher }
385da997620SAlex Deucher 
3864ce001abSDave Airlie /*
3874ce001abSDave Airlie  * radeon_connector_analog_encoder_conflict_solve
3884ce001abSDave Airlie  * - search for other connectors sharing this encoder
3894ce001abSDave Airlie  *   if priority is true, then set them disconnected if this is connected
3904ce001abSDave Airlie  *   if priority is false, set us disconnected if they are connected
3914ce001abSDave Airlie  */
3924ce001abSDave Airlie static enum drm_connector_status
radeon_connector_analog_encoder_conflict_solve(struct drm_connector * connector,struct drm_encoder * encoder,enum drm_connector_status current_status,bool priority)3934ce001abSDave Airlie radeon_connector_analog_encoder_conflict_solve(struct drm_connector *connector,
3944ce001abSDave Airlie 					       struct drm_encoder *encoder,
3954ce001abSDave Airlie 					       enum drm_connector_status current_status,
3964ce001abSDave Airlie 					       bool priority)
3974ce001abSDave Airlie {
3984ce001abSDave Airlie 	struct drm_device *dev = connector->dev;
3994ce001abSDave Airlie 	struct drm_connector *conflict;
40008d07511SAlex Deucher 	struct radeon_connector *radeon_conflict;
4014ce001abSDave Airlie 
4024ce001abSDave Airlie 	list_for_each_entry(conflict, &dev->mode_config.connector_list, head) {
4037b71ca24SVille Syrjälä 		struct drm_encoder *enc;
4047b71ca24SVille Syrjälä 
4054ce001abSDave Airlie 		if (conflict == connector)
4064ce001abSDave Airlie 			continue;
4074ce001abSDave Airlie 
40808d07511SAlex Deucher 		radeon_conflict = to_radeon_connector(conflict);
4094ce001abSDave Airlie 
41062afb4adSJosé Roberto de Souza 		drm_connector_for_each_possible_encoder(conflict, enc) {
4114ce001abSDave Airlie 			/* if the IDs match */
4127b71ca24SVille Syrjälä 			if (enc == encoder) {
4134ce001abSDave Airlie 				if (conflict->status != connector_status_connected)
4144ce001abSDave Airlie 					continue;
4154ce001abSDave Airlie 
41608d07511SAlex Deucher 				if (radeon_conflict->use_digital)
41708d07511SAlex Deucher 					continue;
41808d07511SAlex Deucher 
419fbd62354SWambui Karuga 				if (priority) {
42072082093SJani Nikula 					DRM_DEBUG_KMS("1: conflicting encoders switching off %s\n",
42172082093SJani Nikula 						      conflict->name);
42272082093SJani Nikula 					DRM_DEBUG_KMS("in favor of %s\n",
42372082093SJani Nikula 						      connector->name);
4244ce001abSDave Airlie 					conflict->status = connector_status_disconnected;
4254ce001abSDave Airlie 					radeon_connector_update_scratch_regs(conflict, connector_status_disconnected);
4264ce001abSDave Airlie 				} else {
42772082093SJani Nikula 					DRM_DEBUG_KMS("2: conflicting encoders switching off %s\n",
42872082093SJani Nikula 						      connector->name);
42972082093SJani Nikula 					DRM_DEBUG_KMS("in favor of %s\n",
43072082093SJani Nikula 						      conflict->name);
4314ce001abSDave Airlie 					current_status = connector_status_disconnected;
4324ce001abSDave Airlie 				}
4334ce001abSDave Airlie 				break;
4344ce001abSDave Airlie 			}
4354ce001abSDave Airlie 		}
4364ce001abSDave Airlie 	}
4374ce001abSDave Airlie 	return current_status;
4384ce001abSDave Airlie 
4394ce001abSDave Airlie }
4404ce001abSDave Airlie 
radeon_fp_native_mode(struct drm_encoder * encoder)441771fe6b9SJerome Glisse static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encoder)
442771fe6b9SJerome Glisse {
443771fe6b9SJerome Glisse 	struct drm_device *dev = encoder->dev;
444771fe6b9SJerome Glisse 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
445771fe6b9SJerome Glisse 	struct drm_display_mode *mode = NULL;
446de2103e4SAlex Deucher 	struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
447771fe6b9SJerome Glisse 
448de2103e4SAlex Deucher 	if (native_mode->hdisplay != 0 &&
449de2103e4SAlex Deucher 	    native_mode->vdisplay != 0 &&
450de2103e4SAlex Deucher 	    native_mode->clock != 0) {
451fb06ca8fSAlex Deucher 		mode = drm_mode_duplicate(dev, native_mode);
452a2b28708SGong Yuanjun 		if (!mode)
453a2b28708SGong Yuanjun 			return NULL;
454771fe6b9SJerome Glisse 		mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
455771fe6b9SJerome Glisse 		drm_mode_set_name(mode);
456771fe6b9SJerome Glisse 
457d9fdaafbSDave Airlie 		DRM_DEBUG_KMS("Adding native panel mode %s\n", mode->name);
458d2efdf6dSAlex Deucher 	} else if (native_mode->hdisplay != 0 &&
459d2efdf6dSAlex Deucher 		   native_mode->vdisplay != 0) {
460d2efdf6dSAlex Deucher 		/* mac laptops without an edid */
461d2efdf6dSAlex Deucher 		/* Note that this is not necessarily the exact panel mode,
462d2efdf6dSAlex Deucher 		 * but an approximation based on the cvt formula.  For these
463d2efdf6dSAlex Deucher 		 * systems we should ideally read the mode info out of the
464d2efdf6dSAlex Deucher 		 * registers or add a mode table, but this works and is much
465d2efdf6dSAlex Deucher 		 * simpler.
466d2efdf6dSAlex Deucher 		 */
467d2efdf6dSAlex Deucher 		mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay, 60, true, false, false);
468a2b28708SGong Yuanjun 		if (!mode)
469a2b28708SGong Yuanjun 			return NULL;
470d2efdf6dSAlex Deucher 		mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
471d9fdaafbSDave Airlie 		DRM_DEBUG_KMS("Adding cvt approximation of native panel mode %s\n", mode->name);
472771fe6b9SJerome Glisse 	}
473771fe6b9SJerome Glisse 	return mode;
474771fe6b9SJerome Glisse }
475771fe6b9SJerome Glisse 
radeon_add_common_modes(struct drm_encoder * encoder,struct drm_connector * connector)476923f6848SAlex Deucher static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_connector *connector)
477923f6848SAlex Deucher {
478923f6848SAlex Deucher 	struct drm_device *dev = encoder->dev;
479923f6848SAlex Deucher 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
480923f6848SAlex Deucher 	struct drm_display_mode *mode = NULL;
481de2103e4SAlex Deucher 	struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
482923f6848SAlex Deucher 	int i;
483923f6848SAlex Deucher 	struct mode_size {
484923f6848SAlex Deucher 		int w;
485923f6848SAlex Deucher 		int h;
486923f6848SAlex Deucher 	} common_modes[17] = {
487923f6848SAlex Deucher 		{ 640,  480},
488923f6848SAlex Deucher 		{ 720,  480},
489923f6848SAlex Deucher 		{ 800,  600},
490923f6848SAlex Deucher 		{ 848,  480},
491923f6848SAlex Deucher 		{1024,  768},
492923f6848SAlex Deucher 		{1152,  768},
493923f6848SAlex Deucher 		{1280,  720},
494923f6848SAlex Deucher 		{1280,  800},
495923f6848SAlex Deucher 		{1280,  854},
496923f6848SAlex Deucher 		{1280,  960},
497923f6848SAlex Deucher 		{1280, 1024},
498923f6848SAlex Deucher 		{1440,  900},
499923f6848SAlex Deucher 		{1400, 1050},
500923f6848SAlex Deucher 		{1680, 1050},
501923f6848SAlex Deucher 		{1600, 1200},
502923f6848SAlex Deucher 		{1920, 1080},
503923f6848SAlex Deucher 		{1920, 1200}
504923f6848SAlex Deucher 	};
505923f6848SAlex Deucher 
506923f6848SAlex Deucher 	for (i = 0; i < 17; i++) {
507dfdd6467SAlex Deucher 		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) {
508dfdd6467SAlex Deucher 			if (common_modes[i].w > 1024 ||
509dfdd6467SAlex Deucher 			    common_modes[i].h > 768)
510dfdd6467SAlex Deucher 				continue;
511dfdd6467SAlex Deucher 		}
512923f6848SAlex Deucher 		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
513de2103e4SAlex Deucher 			if (common_modes[i].w > native_mode->hdisplay ||
514de2103e4SAlex Deucher 			    common_modes[i].h > native_mode->vdisplay ||
515de2103e4SAlex Deucher 			    (common_modes[i].w == native_mode->hdisplay &&
516de2103e4SAlex Deucher 			     common_modes[i].h == native_mode->vdisplay))
517923f6848SAlex Deucher 				continue;
518923f6848SAlex Deucher 		}
519923f6848SAlex Deucher 		if (common_modes[i].w < 320 || common_modes[i].h < 200)
520923f6848SAlex Deucher 			continue;
521923f6848SAlex Deucher 
522d50ba256SDave Airlie 		mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
523923f6848SAlex Deucher 		drm_mode_probed_add(connector, mode);
524923f6848SAlex Deucher 	}
525923f6848SAlex Deucher }
526923f6848SAlex Deucher 
radeon_connector_set_property(struct drm_connector * connector,struct drm_property * property,uint64_t val)5271109ca09SLauri Kasanen static int radeon_connector_set_property(struct drm_connector *connector, struct drm_property *property,
528771fe6b9SJerome Glisse 				  uint64_t val)
529771fe6b9SJerome Glisse {
530445282dbSDave Airlie 	struct drm_device *dev = connector->dev;
531445282dbSDave Airlie 	struct radeon_device *rdev = dev->dev_private;
532445282dbSDave Airlie 	struct drm_encoder *encoder;
533445282dbSDave Airlie 	struct radeon_encoder *radeon_encoder;
534445282dbSDave Airlie 
535445282dbSDave Airlie 	if (property == rdev->mode_info.coherent_mode_property) {
536445282dbSDave Airlie 		struct radeon_encoder_atom_dig *dig;
537ce227c41SDave Airlie 		bool new_coherent_mode;
538445282dbSDave Airlie 
539445282dbSDave Airlie 		/* need to find digital encoder on connector */
540445282dbSDave Airlie 		encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
541445282dbSDave Airlie 		if (!encoder)
542445282dbSDave Airlie 			return 0;
543445282dbSDave Airlie 
544445282dbSDave Airlie 		radeon_encoder = to_radeon_encoder(encoder);
545445282dbSDave Airlie 
546445282dbSDave Airlie 		if (!radeon_encoder->enc_priv)
547445282dbSDave Airlie 			return 0;
548445282dbSDave Airlie 
549445282dbSDave Airlie 		dig = radeon_encoder->enc_priv;
550ce227c41SDave Airlie 		new_coherent_mode = val ? true : false;
551ce227c41SDave Airlie 		if (dig->coherent_mode != new_coherent_mode) {
552ce227c41SDave Airlie 			dig->coherent_mode = new_coherent_mode;
553445282dbSDave Airlie 			radeon_property_change_mode(&radeon_encoder->base);
554445282dbSDave Airlie 		}
555ce227c41SDave Airlie 	}
556445282dbSDave Airlie 
5578666c076SAlex Deucher 	if (property == rdev->mode_info.audio_property) {
5588666c076SAlex Deucher 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
5598666c076SAlex Deucher 		/* need to find digital encoder on connector */
5608666c076SAlex Deucher 		encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
5618666c076SAlex Deucher 		if (!encoder)
5628666c076SAlex Deucher 			return 0;
5638666c076SAlex Deucher 
5648666c076SAlex Deucher 		radeon_encoder = to_radeon_encoder(encoder);
5658666c076SAlex Deucher 
5668666c076SAlex Deucher 		if (radeon_connector->audio != val) {
5678666c076SAlex Deucher 			radeon_connector->audio = val;
5688666c076SAlex Deucher 			radeon_property_change_mode(&radeon_encoder->base);
5698666c076SAlex Deucher 		}
5708666c076SAlex Deucher 	}
5718666c076SAlex Deucher 
5726214bb74SAlex Deucher 	if (property == rdev->mode_info.dither_property) {
5736214bb74SAlex Deucher 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
5746214bb74SAlex Deucher 		/* need to find digital encoder on connector */
5756214bb74SAlex Deucher 		encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
5766214bb74SAlex Deucher 		if (!encoder)
5776214bb74SAlex Deucher 			return 0;
5786214bb74SAlex Deucher 
5796214bb74SAlex Deucher 		radeon_encoder = to_radeon_encoder(encoder);
5806214bb74SAlex Deucher 
5816214bb74SAlex Deucher 		if (radeon_connector->dither != val) {
5826214bb74SAlex Deucher 			radeon_connector->dither = val;
5836214bb74SAlex Deucher 			radeon_property_change_mode(&radeon_encoder->base);
5846214bb74SAlex Deucher 		}
5856214bb74SAlex Deucher 	}
5866214bb74SAlex Deucher 
5875b1714d3SAlex Deucher 	if (property == rdev->mode_info.underscan_property) {
5885b1714d3SAlex Deucher 		/* need to find digital encoder on connector */
5895b1714d3SAlex Deucher 		encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
5905b1714d3SAlex Deucher 		if (!encoder)
5915b1714d3SAlex Deucher 			return 0;
5925b1714d3SAlex Deucher 
5935b1714d3SAlex Deucher 		radeon_encoder = to_radeon_encoder(encoder);
5945b1714d3SAlex Deucher 
5955b1714d3SAlex Deucher 		if (radeon_encoder->underscan_type != val) {
5965b1714d3SAlex Deucher 			radeon_encoder->underscan_type = val;
5975b1714d3SAlex Deucher 			radeon_property_change_mode(&radeon_encoder->base);
5985b1714d3SAlex Deucher 		}
5995b1714d3SAlex Deucher 	}
6005b1714d3SAlex Deucher 
6015bccf5e3SMarius Gröger 	if (property == rdev->mode_info.underscan_hborder_property) {
6025bccf5e3SMarius Gröger 		/* need to find digital encoder on connector */
6035bccf5e3SMarius Gröger 		encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
6045bccf5e3SMarius Gröger 		if (!encoder)
6055bccf5e3SMarius Gröger 			return 0;
6065bccf5e3SMarius Gröger 
6075bccf5e3SMarius Gröger 		radeon_encoder = to_radeon_encoder(encoder);
6085bccf5e3SMarius Gröger 
6095bccf5e3SMarius Gröger 		if (radeon_encoder->underscan_hborder != val) {
6105bccf5e3SMarius Gröger 			radeon_encoder->underscan_hborder = val;
6115bccf5e3SMarius Gröger 			radeon_property_change_mode(&radeon_encoder->base);
6125bccf5e3SMarius Gröger 		}
6135bccf5e3SMarius Gröger 	}
6145bccf5e3SMarius Gröger 
6155bccf5e3SMarius Gröger 	if (property == rdev->mode_info.underscan_vborder_property) {
6165bccf5e3SMarius Gröger 		/* need to find digital encoder on connector */
6175bccf5e3SMarius Gröger 		encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
6185bccf5e3SMarius Gröger 		if (!encoder)
6195bccf5e3SMarius Gröger 			return 0;
6205bccf5e3SMarius Gröger 
6215bccf5e3SMarius Gröger 		radeon_encoder = to_radeon_encoder(encoder);
6225bccf5e3SMarius Gröger 
6235bccf5e3SMarius Gröger 		if (radeon_encoder->underscan_vborder != val) {
6245bccf5e3SMarius Gröger 			radeon_encoder->underscan_vborder = val;
6255bccf5e3SMarius Gröger 			radeon_property_change_mode(&radeon_encoder->base);
6265bccf5e3SMarius Gröger 		}
6275bccf5e3SMarius Gröger 	}
6285bccf5e3SMarius Gröger 
629445282dbSDave Airlie 	if (property == rdev->mode_info.tv_std_property) {
630445282dbSDave Airlie 		encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TVDAC);
631445282dbSDave Airlie 		if (!encoder) {
632445282dbSDave Airlie 			encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_DAC);
633445282dbSDave Airlie 		}
634445282dbSDave Airlie 
635445282dbSDave Airlie 		if (!encoder)
636445282dbSDave Airlie 			return 0;
637445282dbSDave Airlie 
638445282dbSDave Airlie 		radeon_encoder = to_radeon_encoder(encoder);
639445282dbSDave Airlie 		if (!radeon_encoder->enc_priv)
640445282dbSDave Airlie 			return 0;
641643acacfSAlex Deucher 		if (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom) {
642445282dbSDave Airlie 			struct radeon_encoder_atom_dac *dac_int;
643445282dbSDave Airlie 			dac_int = radeon_encoder->enc_priv;
644445282dbSDave Airlie 			dac_int->tv_std = val;
645445282dbSDave Airlie 		} else {
646445282dbSDave Airlie 			struct radeon_encoder_tv_dac *dac_int;
647445282dbSDave Airlie 			dac_int = radeon_encoder->enc_priv;
648445282dbSDave Airlie 			dac_int->tv_std = val;
649445282dbSDave Airlie 		}
650445282dbSDave Airlie 		radeon_property_change_mode(&radeon_encoder->base);
651445282dbSDave Airlie 	}
652445282dbSDave Airlie 
653445282dbSDave Airlie 	if (property == rdev->mode_info.load_detect_property) {
654445282dbSDave Airlie 		struct radeon_connector *radeon_connector =
655445282dbSDave Airlie 			to_radeon_connector(connector);
656445282dbSDave Airlie 
657445282dbSDave Airlie 		if (val == 0)
658445282dbSDave Airlie 			radeon_connector->dac_load_detect = false;
659445282dbSDave Airlie 		else
660445282dbSDave Airlie 			radeon_connector->dac_load_detect = true;
661445282dbSDave Airlie 	}
662445282dbSDave Airlie 
663445282dbSDave Airlie 	if (property == rdev->mode_info.tmds_pll_property) {
664445282dbSDave Airlie 		struct radeon_encoder_int_tmds *tmds = NULL;
665445282dbSDave Airlie 		bool ret = false;
666445282dbSDave Airlie 		/* need to find digital encoder on connector */
667445282dbSDave Airlie 		encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
668445282dbSDave Airlie 		if (!encoder)
669445282dbSDave Airlie 			return 0;
670445282dbSDave Airlie 
671445282dbSDave Airlie 		radeon_encoder = to_radeon_encoder(encoder);
672445282dbSDave Airlie 
673445282dbSDave Airlie 		tmds = radeon_encoder->enc_priv;
674445282dbSDave Airlie 		if (!tmds)
675445282dbSDave Airlie 			return 0;
676445282dbSDave Airlie 
677445282dbSDave Airlie 		if (val == 0) {
678445282dbSDave Airlie 			if (rdev->is_atom_bios)
679445282dbSDave Airlie 				ret = radeon_atombios_get_tmds_info(radeon_encoder, tmds);
680445282dbSDave Airlie 			else
681445282dbSDave Airlie 				ret = radeon_legacy_get_tmds_info_from_combios(radeon_encoder, tmds);
682445282dbSDave Airlie 		}
6833c20d544SWambui Karuga 		if (val == 1 || !ret)
684445282dbSDave Airlie 			radeon_legacy_get_tmds_info_from_table(radeon_encoder, tmds);
6853c20d544SWambui Karuga 
686445282dbSDave Airlie 		radeon_property_change_mode(&radeon_encoder->base);
687445282dbSDave Airlie 	}
688445282dbSDave Airlie 
689da997620SAlex Deucher 	if (property == dev->mode_config.scaling_mode_property) {
690da997620SAlex Deucher 		enum radeon_rmx_type rmx_type;
691da997620SAlex Deucher 
692da997620SAlex Deucher 		if (connector->encoder)
693da997620SAlex Deucher 			radeon_encoder = to_radeon_encoder(connector->encoder);
694da997620SAlex Deucher 		else {
695319d1e14SJani Nikula 			const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
696da997620SAlex Deucher 			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
697da997620SAlex Deucher 		}
698da997620SAlex Deucher 
699da997620SAlex Deucher 		switch (val) {
700da997620SAlex Deucher 		default:
701da997620SAlex Deucher 		case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break;
702da997620SAlex Deucher 		case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break;
703da997620SAlex Deucher 		case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break;
704da997620SAlex Deucher 		case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break;
705da997620SAlex Deucher 		}
706da997620SAlex Deucher 		if (radeon_encoder->rmx_type == rmx_type)
707da997620SAlex Deucher 			return 0;
708da997620SAlex Deucher 
709da997620SAlex Deucher 		if ((rmx_type != DRM_MODE_SCALE_NONE) &&
710da997620SAlex Deucher 		    (radeon_encoder->native_mode.clock == 0))
711da997620SAlex Deucher 			return 0;
712da997620SAlex Deucher 
713da997620SAlex Deucher 		radeon_encoder->rmx_type = rmx_type;
714da997620SAlex Deucher 
715da997620SAlex Deucher 		radeon_property_change_mode(&radeon_encoder->base);
716da997620SAlex Deucher 	}
717da997620SAlex Deucher 
718643b1f56SAlex Deucher 	if (property == rdev->mode_info.output_csc_property) {
719643b1f56SAlex Deucher 		if (connector->encoder)
720643b1f56SAlex Deucher 			radeon_encoder = to_radeon_encoder(connector->encoder);
721643b1f56SAlex Deucher 		else {
72216bb079eSJani Nikula 			const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
723643b1f56SAlex Deucher 			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
724643b1f56SAlex Deucher 		}
725643b1f56SAlex Deucher 
726643b1f56SAlex Deucher 		if (radeon_encoder->output_csc == val)
727643b1f56SAlex Deucher 			return 0;
728643b1f56SAlex Deucher 
729643b1f56SAlex Deucher 		radeon_encoder->output_csc = val;
730643b1f56SAlex Deucher 
731f3eb9b8fSJia-Ju Bai 		if (connector->encoder && connector->encoder->crtc) {
732643b1f56SAlex Deucher 			struct drm_crtc *crtc  = connector->encoder->crtc;
733643b1f56SAlex Deucher 			struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
734643b1f56SAlex Deucher 
735643b1f56SAlex Deucher 			radeon_crtc->output_csc = radeon_encoder->output_csc;
736643b1f56SAlex Deucher 
73742585395SPeter Rosin 			/*
73842585395SPeter Rosin 			 * Our .gamma_set assumes the .gamma_store has been
73942585395SPeter Rosin 			 * prefilled and don't care about its arguments.
74042585395SPeter Rosin 			 */
74142585395SPeter Rosin 			crtc->funcs->gamma_set(crtc, NULL, NULL, NULL, 0, NULL);
742643b1f56SAlex Deucher 		}
743643b1f56SAlex Deucher 	}
744643b1f56SAlex Deucher 
745771fe6b9SJerome Glisse 	return 0;
746771fe6b9SJerome Glisse }
747771fe6b9SJerome Glisse 
radeon_fixup_lvds_native_mode(struct drm_encoder * encoder,struct drm_connector * connector)7488dfaa8a7SMichel Dänzer static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
7498dfaa8a7SMichel Dänzer 					  struct drm_connector *connector)
7508dfaa8a7SMichel Dänzer {
7518dfaa8a7SMichel Dänzer 	struct radeon_encoder *radeon_encoder =	to_radeon_encoder(encoder);
752de2103e4SAlex Deucher 	struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
75313bb9430SMatthew Garrett 	struct drm_display_mode *t, *mode;
75413bb9430SMatthew Garrett 
75513bb9430SMatthew Garrett 	/* If the EDID preferred mode doesn't match the native mode, use it */
75613bb9430SMatthew Garrett 	list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
75713bb9430SMatthew Garrett 		if (mode->type & DRM_MODE_TYPE_PREFERRED) {
75813bb9430SMatthew Garrett 			if (mode->hdisplay != native_mode->hdisplay ||
75913bb9430SMatthew Garrett 			    mode->vdisplay != native_mode->vdisplay)
760606d5877SVille Syrjälä 				drm_mode_copy(native_mode, mode);
76113bb9430SMatthew Garrett 		}
76213bb9430SMatthew Garrett 	}
7638dfaa8a7SMichel Dänzer 
7648dfaa8a7SMichel Dänzer 	/* Try to get native mode details from EDID if necessary */
765de2103e4SAlex Deucher 	if (!native_mode->clock) {
7668dfaa8a7SMichel Dänzer 		list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
767de2103e4SAlex Deucher 			if (mode->hdisplay == native_mode->hdisplay &&
768de2103e4SAlex Deucher 			    mode->vdisplay == native_mode->vdisplay) {
769606d5877SVille Syrjälä 				drm_mode_copy(native_mode, mode);
770de2103e4SAlex Deucher 				drm_mode_set_crtcinfo(native_mode, CRTC_INTERLACE_HALVE_V);
771c5d46b4eSAlex Deucher 				DRM_DEBUG_KMS("Determined LVDS native mode details from EDID\n");
7728dfaa8a7SMichel Dänzer 				break;
7738dfaa8a7SMichel Dänzer 			}
7748dfaa8a7SMichel Dänzer 		}
7758dfaa8a7SMichel Dänzer 	}
77613bb9430SMatthew Garrett 
777de2103e4SAlex Deucher 	if (!native_mode->clock) {
778c5d46b4eSAlex Deucher 		DRM_DEBUG_KMS("No LVDS native mode details, disabling RMX\n");
7798dfaa8a7SMichel Dänzer 		radeon_encoder->rmx_type = RMX_OFF;
7808dfaa8a7SMichel Dänzer 	}
7818dfaa8a7SMichel Dänzer }
782771fe6b9SJerome Glisse 
radeon_lvds_get_modes(struct drm_connector * connector)783771fe6b9SJerome Glisse static int radeon_lvds_get_modes(struct drm_connector *connector)
784771fe6b9SJerome Glisse {
785771fe6b9SJerome Glisse 	struct drm_encoder *encoder;
786771fe6b9SJerome Glisse 	int ret = 0;
787771fe6b9SJerome Glisse 	struct drm_display_mode *mode;
788771fe6b9SJerome Glisse 
78972a5c970SAlex Deucher 	radeon_connector_get_edid(connector);
79072a5c970SAlex Deucher 	ret = radeon_ddc_get_modes(connector);
791771fe6b9SJerome Glisse 	if (ret > 0) {
7927747b713SAlex Deucher 		encoder = radeon_best_single_encoder(connector);
7938dfaa8a7SMichel Dänzer 		if (encoder) {
7948dfaa8a7SMichel Dänzer 			radeon_fixup_lvds_native_mode(encoder, connector);
7957747b713SAlex Deucher 			/* add scaled modes */
7967747b713SAlex Deucher 			radeon_add_common_modes(encoder, connector);
7978dfaa8a7SMichel Dänzer 		}
798771fe6b9SJerome Glisse 		return ret;
799771fe6b9SJerome Glisse 	}
800771fe6b9SJerome Glisse 
801771fe6b9SJerome Glisse 	encoder = radeon_best_single_encoder(connector);
802771fe6b9SJerome Glisse 	if (!encoder)
803771fe6b9SJerome Glisse 		return 0;
804771fe6b9SJerome Glisse 
805771fe6b9SJerome Glisse 	/* we have no EDID modes */
806771fe6b9SJerome Glisse 	mode = radeon_fp_native_mode(encoder);
807771fe6b9SJerome Glisse 	if (mode) {
808771fe6b9SJerome Glisse 		ret = 1;
809771fe6b9SJerome Glisse 		drm_mode_probed_add(connector, mode);
8107a868e18SAlex Deucher 		/* add the width/height from vbios tables if available */
8117a868e18SAlex Deucher 		connector->display_info.width_mm = mode->width_mm;
8127a868e18SAlex Deucher 		connector->display_info.height_mm = mode->height_mm;
813923f6848SAlex Deucher 		/* add scaled modes */
814923f6848SAlex Deucher 		radeon_add_common_modes(encoder, connector);
8157747b713SAlex Deucher 	}
816923f6848SAlex Deucher 
817771fe6b9SJerome Glisse 	return ret;
818771fe6b9SJerome Glisse }
819771fe6b9SJerome Glisse 
radeon_lvds_mode_valid(struct drm_connector * connector,struct drm_display_mode * mode)8207a47f20eSLuc Van Oostenryck static enum drm_mode_status radeon_lvds_mode_valid(struct drm_connector *connector,
821771fe6b9SJerome Glisse 				  struct drm_display_mode *mode)
822771fe6b9SJerome Glisse {
823a3fa6320SAlex Deucher 	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
824a3fa6320SAlex Deucher 
825a3fa6320SAlex Deucher 	if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
826a3fa6320SAlex Deucher 		return MODE_PANEL;
827a3fa6320SAlex Deucher 
828a3fa6320SAlex Deucher 	if (encoder) {
829a3fa6320SAlex Deucher 		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
830a3fa6320SAlex Deucher 		struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
831a3fa6320SAlex Deucher 
832a3fa6320SAlex Deucher 		/* AVIVO hardware supports downscaling modes larger than the panel
833a3fa6320SAlex Deucher 		 * to the panel size, but I'm not sure this is desirable.
834a3fa6320SAlex Deucher 		 */
835a3fa6320SAlex Deucher 		if ((mode->hdisplay > native_mode->hdisplay) ||
836a3fa6320SAlex Deucher 		    (mode->vdisplay > native_mode->vdisplay))
837a3fa6320SAlex Deucher 			return MODE_PANEL;
838a3fa6320SAlex Deucher 
839a3fa6320SAlex Deucher 		/* if scaling is disabled, block non-native modes */
840a3fa6320SAlex Deucher 		if (radeon_encoder->rmx_type == RMX_OFF) {
841a3fa6320SAlex Deucher 			if ((mode->hdisplay != native_mode->hdisplay) ||
842a3fa6320SAlex Deucher 			    (mode->vdisplay != native_mode->vdisplay))
843a3fa6320SAlex Deucher 				return MODE_PANEL;
844a3fa6320SAlex Deucher 		}
845a3fa6320SAlex Deucher 	}
846a3fa6320SAlex Deucher 
847771fe6b9SJerome Glisse 	return MODE_OK;
848771fe6b9SJerome Glisse }
849771fe6b9SJerome Glisse 
8507b334fcbSChris Wilson static enum drm_connector_status
radeon_lvds_detect(struct drm_connector * connector,bool force)851930a9e28SChris Wilson radeon_lvds_detect(struct drm_connector *connector, bool force)
852771fe6b9SJerome Glisse {
85313485794SAlex Deucher 	struct drm_device *dev = connector->dev;
85413485794SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
8550549a061SAlex Deucher 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
8562ffb8429SAlex Deucher 	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
8570549a061SAlex Deucher 	enum drm_connector_status ret = connector_status_disconnected;
85810ebc0bcSDave Airlie 	int r;
85910ebc0bcSDave Airlie 
86015734fefSLukas Wunner 	if (!drm_kms_helper_is_poll_worker()) {
86110ebc0bcSDave Airlie 		r = pm_runtime_get_sync(connector->dev->dev);
8626f2e8acdSAditya Pakki 		if (r < 0) {
8636f2e8acdSAditya Pakki 			pm_runtime_put_autosuspend(connector->dev->dev);
86410ebc0bcSDave Airlie 			return connector_status_disconnected;
86515734fefSLukas Wunner 		}
8666f2e8acdSAditya Pakki 	}
8672ffb8429SAlex Deucher 
8682ffb8429SAlex Deucher 	if (encoder) {
8692ffb8429SAlex Deucher 		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
870de2103e4SAlex Deucher 		struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
8712ffb8429SAlex Deucher 
8722ffb8429SAlex Deucher 		/* check if panel is valid */
873de2103e4SAlex Deucher 		if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240)
8742ffb8429SAlex Deucher 			ret = connector_status_connected;
87513485794SAlex Deucher 		/* don't fetch the edid from the vbios if ddc fails and runpm is
87613485794SAlex Deucher 		 * enabled so we report disconnected.
87713485794SAlex Deucher 		 */
87813485794SAlex Deucher 		if ((rdev->flags & RADEON_IS_PX) && (radeon_runtime_pm != 0))
87913485794SAlex Deucher 			ret = connector_status_disconnected;
8802ffb8429SAlex Deucher 	}
8810549a061SAlex Deucher 
8820549a061SAlex Deucher 	/* check for edid as well */
88372a5c970SAlex Deucher 	radeon_connector_get_edid(connector);
8840294cf4fSAlex Deucher 	if (radeon_connector->edid)
8850294cf4fSAlex Deucher 		ret = connector_status_connected;
886771fe6b9SJerome Glisse 	/* check acpi lid status ??? */
8872ffb8429SAlex Deucher 
888771fe6b9SJerome Glisse 	radeon_connector_update_scratch_regs(connector, ret);
88915734fefSLukas Wunner 
89015734fefSLukas Wunner 	if (!drm_kms_helper_is_poll_worker()) {
89110ebc0bcSDave Airlie 		pm_runtime_mark_last_busy(connector->dev->dev);
89210ebc0bcSDave Airlie 		pm_runtime_put_autosuspend(connector->dev->dev);
89315734fefSLukas Wunner 	}
89415734fefSLukas Wunner 
895771fe6b9SJerome Glisse 	return ret;
896771fe6b9SJerome Glisse }
897771fe6b9SJerome Glisse 
radeon_connector_unregister(struct drm_connector * connector)898b0c80bd5SAlex Deucher static void radeon_connector_unregister(struct drm_connector *connector)
899b0c80bd5SAlex Deucher {
900b0c80bd5SAlex Deucher 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
901b0c80bd5SAlex Deucher 
9020a6e2105SLarry Finger 	if (radeon_connector->ddc_bus && radeon_connector->ddc_bus->has_aux) {
903b0c80bd5SAlex Deucher 		drm_dp_aux_unregister(&radeon_connector->ddc_bus->aux);
904b0c80bd5SAlex Deucher 		radeon_connector->ddc_bus->has_aux = false;
905b0c80bd5SAlex Deucher 	}
906b0c80bd5SAlex Deucher }
907b0c80bd5SAlex Deucher 
radeon_connector_destroy(struct drm_connector * connector)908771fe6b9SJerome Glisse static void radeon_connector_destroy(struct drm_connector *connector)
909771fe6b9SJerome Glisse {
910771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
911771fe6b9SJerome Glisse 
91272a5c970SAlex Deucher 	radeon_connector_free_edid(connector);
913771fe6b9SJerome Glisse 	kfree(radeon_connector->con_priv);
91434ea3d38SThomas Wood 	drm_connector_unregister(connector);
915771fe6b9SJerome Glisse 	drm_connector_cleanup(connector);
916771fe6b9SJerome Glisse 	kfree(connector);
917771fe6b9SJerome Glisse }
918771fe6b9SJerome Glisse 
radeon_lvds_set_property(struct drm_connector * connector,struct drm_property * property,uint64_t value)919445282dbSDave Airlie static int radeon_lvds_set_property(struct drm_connector *connector,
920445282dbSDave Airlie 				    struct drm_property *property,
921445282dbSDave Airlie 				    uint64_t value)
922445282dbSDave Airlie {
923445282dbSDave Airlie 	struct drm_device *dev = connector->dev;
924445282dbSDave Airlie 	struct radeon_encoder *radeon_encoder;
925445282dbSDave Airlie 	enum radeon_rmx_type rmx_type;
926445282dbSDave Airlie 
927d9fdaafbSDave Airlie 	DRM_DEBUG_KMS("\n");
928445282dbSDave Airlie 	if (property != dev->mode_config.scaling_mode_property)
929445282dbSDave Airlie 		return 0;
930445282dbSDave Airlie 
931445282dbSDave Airlie 	if (connector->encoder)
932445282dbSDave Airlie 		radeon_encoder = to_radeon_encoder(connector->encoder);
933445282dbSDave Airlie 	else {
934319d1e14SJani Nikula 		const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
935445282dbSDave Airlie 		radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
936445282dbSDave Airlie 	}
937445282dbSDave Airlie 
938445282dbSDave Airlie 	switch (value) {
939445282dbSDave Airlie 	case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break;
940445282dbSDave Airlie 	case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break;
941445282dbSDave Airlie 	case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break;
942445282dbSDave Airlie 	default:
943445282dbSDave Airlie 	case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break;
944445282dbSDave Airlie 	}
945445282dbSDave Airlie 	if (radeon_encoder->rmx_type == rmx_type)
946445282dbSDave Airlie 		return 0;
947445282dbSDave Airlie 
948445282dbSDave Airlie 	radeon_encoder->rmx_type = rmx_type;
949445282dbSDave Airlie 
950445282dbSDave Airlie 	radeon_property_change_mode(&radeon_encoder->base);
951445282dbSDave Airlie 	return 0;
952445282dbSDave Airlie }
953445282dbSDave Airlie 
954445282dbSDave Airlie 
9551109ca09SLauri Kasanen static const struct drm_connector_helper_funcs radeon_lvds_connector_helper_funcs = {
956771fe6b9SJerome Glisse 	.get_modes = radeon_lvds_get_modes,
957771fe6b9SJerome Glisse 	.mode_valid = radeon_lvds_mode_valid,
958771fe6b9SJerome Glisse 	.best_encoder = radeon_best_single_encoder,
959771fe6b9SJerome Glisse };
960771fe6b9SJerome Glisse 
9611109ca09SLauri Kasanen static const struct drm_connector_funcs radeon_lvds_connector_funcs = {
962771fe6b9SJerome Glisse 	.dpms = drm_helper_connector_dpms,
963771fe6b9SJerome Glisse 	.detect = radeon_lvds_detect,
964771fe6b9SJerome Glisse 	.fill_modes = drm_helper_probe_single_connector_modes,
965b0c80bd5SAlex Deucher 	.early_unregister = radeon_connector_unregister,
966771fe6b9SJerome Glisse 	.destroy = radeon_connector_destroy,
967445282dbSDave Airlie 	.set_property = radeon_lvds_set_property,
968771fe6b9SJerome Glisse };
969771fe6b9SJerome Glisse 
radeon_vga_get_modes(struct drm_connector * connector)970771fe6b9SJerome Glisse static int radeon_vga_get_modes(struct drm_connector *connector)
971771fe6b9SJerome Glisse {
972771fe6b9SJerome Glisse 	int ret;
973771fe6b9SJerome Glisse 
97472a5c970SAlex Deucher 	radeon_connector_get_edid(connector);
97572a5c970SAlex Deucher 	ret = radeon_ddc_get_modes(connector);
976771fe6b9SJerome Glisse 
977da997620SAlex Deucher 	radeon_get_native_mode(connector);
978da997620SAlex Deucher 
979771fe6b9SJerome Glisse 	return ret;
980771fe6b9SJerome Glisse }
981771fe6b9SJerome Glisse 
radeon_vga_mode_valid(struct drm_connector * connector,struct drm_display_mode * mode)9827a47f20eSLuc Van Oostenryck static enum drm_mode_status radeon_vga_mode_valid(struct drm_connector *connector,
983771fe6b9SJerome Glisse 				  struct drm_display_mode *mode)
984771fe6b9SJerome Glisse {
985b20f9befSAlex Deucher 	struct drm_device *dev = connector->dev;
986b20f9befSAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
987b20f9befSAlex Deucher 
988a3fa6320SAlex Deucher 	/* XXX check mode bandwidth */
989b20f9befSAlex Deucher 
990b20f9befSAlex Deucher 	if ((mode->clock / 10) > rdev->clock.max_pixel_clock)
991b20f9befSAlex Deucher 		return MODE_CLOCK_HIGH;
992b20f9befSAlex Deucher 
993771fe6b9SJerome Glisse 	return MODE_OK;
994771fe6b9SJerome Glisse }
995771fe6b9SJerome Glisse 
9967b334fcbSChris Wilson static enum drm_connector_status
radeon_vga_detect(struct drm_connector * connector,bool force)997930a9e28SChris Wilson radeon_vga_detect(struct drm_connector *connector, bool force)
998771fe6b9SJerome Glisse {
999fafcf94eSAlex Deucher 	struct drm_device *dev = connector->dev;
1000fafcf94eSAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
1001771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1002771fe6b9SJerome Glisse 	struct drm_encoder *encoder;
1003319d1e14SJani Nikula 	const struct drm_encoder_helper_funcs *encoder_funcs;
10044b9d2a21SDave Airlie 	bool dret = false;
1005771fe6b9SJerome Glisse 	enum drm_connector_status ret = connector_status_disconnected;
100610ebc0bcSDave Airlie 	int r;
100710ebc0bcSDave Airlie 
100815734fefSLukas Wunner 	if (!drm_kms_helper_is_poll_worker()) {
100910ebc0bcSDave Airlie 		r = pm_runtime_get_sync(connector->dev->dev);
10106f2e8acdSAditya Pakki 		if (r < 0) {
10116f2e8acdSAditya Pakki 			pm_runtime_put_autosuspend(connector->dev->dev);
101210ebc0bcSDave Airlie 			return connector_status_disconnected;
101315734fefSLukas Wunner 		}
10146f2e8acdSAditya Pakki 	}
1015771fe6b9SJerome Glisse 
10164ce001abSDave Airlie 	encoder = radeon_best_single_encoder(connector);
10174ce001abSDave Airlie 	if (!encoder)
10184ce001abSDave Airlie 		ret = connector_status_disconnected;
10194ce001abSDave Airlie 
1020eb6b6d7cSDave Airlie 	if (radeon_connector->ddc_bus)
10210a9069d3SNiels Ole Salscheider 		dret = radeon_ddc_probe(radeon_connector, false);
10220294cf4fSAlex Deucher 	if (dret) {
1023d0d0a225SAlex Deucher 		radeon_connector->detected_by_load = false;
102472a5c970SAlex Deucher 		radeon_connector_free_edid(connector);
102572a5c970SAlex Deucher 		radeon_connector_get_edid(connector);
10260294cf4fSAlex Deucher 
10270294cf4fSAlex Deucher 		if (!radeon_connector->edid) {
1028f82f5f3aSJerome Glisse 			DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
102972082093SJani Nikula 					connector->name);
1030f82f5f3aSJerome Glisse 			ret = connector_status_connected;
10310294cf4fSAlex Deucher 		} else {
103272a5c970SAlex Deucher 			radeon_connector->use_digital =
103372a5c970SAlex Deucher 				!!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
10340294cf4fSAlex Deucher 
10350294cf4fSAlex Deucher 			/* some oems have boards with separate digital and analog connectors
10360294cf4fSAlex Deucher 			 * with a shared ddc line (often vga + hdmi)
10370294cf4fSAlex Deucher 			 */
10380294cf4fSAlex Deucher 			if (radeon_connector->use_digital && radeon_connector->shared_ddc) {
103972a5c970SAlex Deucher 				radeon_connector_free_edid(connector);
10400294cf4fSAlex Deucher 				ret = connector_status_disconnected;
104172a5c970SAlex Deucher 			} else {
1042771fe6b9SJerome Glisse 				ret = connector_status_connected;
10430294cf4fSAlex Deucher 			}
104472a5c970SAlex Deucher 		}
10450294cf4fSAlex Deucher 	} else {
1046c3cceeddSDave Airlie 
1047c3cceeddSDave Airlie 		/* if we aren't forcing don't do destructive polling */
1048d0d0a225SAlex Deucher 		if (!force) {
1049d0d0a225SAlex Deucher 			/* only return the previous status if we last
1050d0d0a225SAlex Deucher 			 * detected a monitor via load.
1051d0d0a225SAlex Deucher 			 */
1052d0d0a225SAlex Deucher 			if (radeon_connector->detected_by_load)
105310ebc0bcSDave Airlie 				ret = connector->status;
105410ebc0bcSDave Airlie 			goto out;
1055d0d0a225SAlex Deucher 		}
1056c3cceeddSDave Airlie 
1057d8a7f792SDarren Jenkins 		if (radeon_connector->dac_load_detect && encoder) {
1058771fe6b9SJerome Glisse 			encoder_funcs = encoder->helper_private;
1059771fe6b9SJerome Glisse 			ret = encoder_funcs->detect(encoder, connector);
106034076446SJerome Glisse 			if (ret != connector_status_disconnected)
1061d0d0a225SAlex Deucher 				radeon_connector->detected_by_load = true;
1062771fe6b9SJerome Glisse 		}
1063445282dbSDave Airlie 	}
1064771fe6b9SJerome Glisse 
10654ce001abSDave Airlie 	if (ret == connector_status_connected)
10664ce001abSDave Airlie 		ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
1067fafcf94eSAlex Deucher 
1068fafcf94eSAlex Deucher 	/* RN50 and some RV100 asics in servers often have a hardcoded EDID in the
1069fafcf94eSAlex Deucher 	 * vbios to deal with KVMs. If we have one and are not able to detect a monitor
1070fafcf94eSAlex Deucher 	 * by other means, assume the CRT is connected and use that EDID.
1071fafcf94eSAlex Deucher 	 */
1072fafcf94eSAlex Deucher 	if ((!rdev->is_atom_bios) &&
1073fafcf94eSAlex Deucher 	    (ret == connector_status_disconnected) &&
1074fafcf94eSAlex Deucher 	    rdev->mode_info.bios_hardcoded_edid_size) {
1075fafcf94eSAlex Deucher 		ret = connector_status_connected;
1076fafcf94eSAlex Deucher 	}
1077fafcf94eSAlex Deucher 
1078771fe6b9SJerome Glisse 	radeon_connector_update_scratch_regs(connector, ret);
107910ebc0bcSDave Airlie 
108010ebc0bcSDave Airlie out:
108115734fefSLukas Wunner 	if (!drm_kms_helper_is_poll_worker()) {
108210ebc0bcSDave Airlie 		pm_runtime_mark_last_busy(connector->dev->dev);
108310ebc0bcSDave Airlie 		pm_runtime_put_autosuspend(connector->dev->dev);
108415734fefSLukas Wunner 	}
108510ebc0bcSDave Airlie 
1086771fe6b9SJerome Glisse 	return ret;
1087771fe6b9SJerome Glisse }
1088771fe6b9SJerome Glisse 
10891109ca09SLauri Kasanen static const struct drm_connector_helper_funcs radeon_vga_connector_helper_funcs = {
1090771fe6b9SJerome Glisse 	.get_modes = radeon_vga_get_modes,
1091771fe6b9SJerome Glisse 	.mode_valid = radeon_vga_mode_valid,
1092771fe6b9SJerome Glisse 	.best_encoder = radeon_best_single_encoder,
1093771fe6b9SJerome Glisse };
1094771fe6b9SJerome Glisse 
10951109ca09SLauri Kasanen static const struct drm_connector_funcs radeon_vga_connector_funcs = {
1096771fe6b9SJerome Glisse 	.dpms = drm_helper_connector_dpms,
1097771fe6b9SJerome Glisse 	.detect = radeon_vga_detect,
1098771fe6b9SJerome Glisse 	.fill_modes = drm_helper_probe_single_connector_modes,
1099b0c80bd5SAlex Deucher 	.early_unregister = radeon_connector_unregister,
1100771fe6b9SJerome Glisse 	.destroy = radeon_connector_destroy,
1101771fe6b9SJerome Glisse 	.set_property = radeon_connector_set_property,
1102771fe6b9SJerome Glisse };
1103771fe6b9SJerome Glisse 
radeon_tv_get_modes(struct drm_connector * connector)11044ce001abSDave Airlie static int radeon_tv_get_modes(struct drm_connector *connector)
11054ce001abSDave Airlie {
11064ce001abSDave Airlie 	struct drm_device *dev = connector->dev;
1107923f6848SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
11084ce001abSDave Airlie 	struct drm_display_mode *tv_mode;
1109923f6848SAlex Deucher 	struct drm_encoder *encoder;
11104ce001abSDave Airlie 
1111923f6848SAlex Deucher 	encoder = radeon_best_single_encoder(connector);
1112923f6848SAlex Deucher 	if (!encoder)
1113923f6848SAlex Deucher 		return 0;
1114923f6848SAlex Deucher 
1115923f6848SAlex Deucher 	/* avivo chips can scale any mode */
1116923f6848SAlex Deucher 	if (rdev->family >= CHIP_RS600)
1117923f6848SAlex Deucher 		/* add scaled modes */
1118923f6848SAlex Deucher 		radeon_add_common_modes(encoder, connector);
1119923f6848SAlex Deucher 	else {
1120923f6848SAlex Deucher 		/* only 800x600 is supported right now on pre-avivo chips */
1121d50ba256SDave Airlie 		tv_mode = drm_cvt_mode(dev, 800, 600, 60, false, false, false);
1122*c0fe7aacSMa Ke 		if (!tv_mode)
1123*c0fe7aacSMa Ke 			return 0;
11244ce001abSDave Airlie 		tv_mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
11254ce001abSDave Airlie 		drm_mode_probed_add(connector, tv_mode);
1126923f6848SAlex Deucher 	}
11274ce001abSDave Airlie 	return 1;
11284ce001abSDave Airlie }
11294ce001abSDave Airlie 
radeon_tv_mode_valid(struct drm_connector * connector,struct drm_display_mode * mode)11307a47f20eSLuc Van Oostenryck static enum drm_mode_status radeon_tv_mode_valid(struct drm_connector *connector,
11314ce001abSDave Airlie 				struct drm_display_mode *mode)
11324ce001abSDave Airlie {
1133a3fa6320SAlex Deucher 	if ((mode->hdisplay > 1024) || (mode->vdisplay > 768))
1134a3fa6320SAlex Deucher 		return MODE_CLOCK_RANGE;
11354ce001abSDave Airlie 	return MODE_OK;
11364ce001abSDave Airlie }
11374ce001abSDave Airlie 
11387b334fcbSChris Wilson static enum drm_connector_status
radeon_tv_detect(struct drm_connector * connector,bool force)1139930a9e28SChris Wilson radeon_tv_detect(struct drm_connector *connector, bool force)
11404ce001abSDave Airlie {
11414ce001abSDave Airlie 	struct drm_encoder *encoder;
1142319d1e14SJani Nikula 	const struct drm_encoder_helper_funcs *encoder_funcs;
1143445282dbSDave Airlie 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1144445282dbSDave Airlie 	enum drm_connector_status ret = connector_status_disconnected;
114510ebc0bcSDave Airlie 	int r;
1146445282dbSDave Airlie 
1147445282dbSDave Airlie 	if (!radeon_connector->dac_load_detect)
1148445282dbSDave Airlie 		return ret;
11494ce001abSDave Airlie 
115015734fefSLukas Wunner 	if (!drm_kms_helper_is_poll_worker()) {
115110ebc0bcSDave Airlie 		r = pm_runtime_get_sync(connector->dev->dev);
11526f2e8acdSAditya Pakki 		if (r < 0) {
11536f2e8acdSAditya Pakki 			pm_runtime_put_autosuspend(connector->dev->dev);
115410ebc0bcSDave Airlie 			return connector_status_disconnected;
115515734fefSLukas Wunner 		}
11566f2e8acdSAditya Pakki 	}
115710ebc0bcSDave Airlie 
11584ce001abSDave Airlie 	encoder = radeon_best_single_encoder(connector);
11594ce001abSDave Airlie 	if (!encoder)
11604ce001abSDave Airlie 		ret = connector_status_disconnected;
11614ce001abSDave Airlie 	else {
11624ce001abSDave Airlie 		encoder_funcs = encoder->helper_private;
11634ce001abSDave Airlie 		ret = encoder_funcs->detect(encoder, connector);
11644ce001abSDave Airlie 	}
11654ce001abSDave Airlie 	if (ret == connector_status_connected)
11664ce001abSDave Airlie 		ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false);
11674ce001abSDave Airlie 	radeon_connector_update_scratch_regs(connector, ret);
116815734fefSLukas Wunner 
116915734fefSLukas Wunner 	if (!drm_kms_helper_is_poll_worker()) {
117010ebc0bcSDave Airlie 		pm_runtime_mark_last_busy(connector->dev->dev);
117110ebc0bcSDave Airlie 		pm_runtime_put_autosuspend(connector->dev->dev);
117215734fefSLukas Wunner 	}
117315734fefSLukas Wunner 
11744ce001abSDave Airlie 	return ret;
11754ce001abSDave Airlie }
11764ce001abSDave Airlie 
11771109ca09SLauri Kasanen static const struct drm_connector_helper_funcs radeon_tv_connector_helper_funcs = {
11784ce001abSDave Airlie 	.get_modes = radeon_tv_get_modes,
11794ce001abSDave Airlie 	.mode_valid = radeon_tv_mode_valid,
11804ce001abSDave Airlie 	.best_encoder = radeon_best_single_encoder,
11814ce001abSDave Airlie };
11824ce001abSDave Airlie 
11831109ca09SLauri Kasanen static const struct drm_connector_funcs radeon_tv_connector_funcs = {
11844ce001abSDave Airlie 	.dpms = drm_helper_connector_dpms,
11854ce001abSDave Airlie 	.detect = radeon_tv_detect,
11864ce001abSDave Airlie 	.fill_modes = drm_helper_probe_single_connector_modes,
1187b0c80bd5SAlex Deucher 	.early_unregister = radeon_connector_unregister,
11884ce001abSDave Airlie 	.destroy = radeon_connector_destroy,
11894ce001abSDave Airlie 	.set_property = radeon_connector_set_property,
11904ce001abSDave Airlie };
11914ce001abSDave Airlie 
radeon_check_hpd_status_unchanged(struct drm_connector * connector)119211fe1266STvrtko Ursulin static bool radeon_check_hpd_status_unchanged(struct drm_connector *connector)
119311fe1266STvrtko Ursulin {
119411fe1266STvrtko Ursulin 	struct drm_device *dev = connector->dev;
119511fe1266STvrtko Ursulin 	struct radeon_device *rdev = dev->dev_private;
119611fe1266STvrtko Ursulin 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
119711fe1266STvrtko Ursulin 	enum drm_connector_status status;
119811fe1266STvrtko Ursulin 
119911fe1266STvrtko Ursulin 	/* We only trust HPD on R600 and newer ASICS. */
120011fe1266STvrtko Ursulin 	if (rdev->family >= CHIP_R600
120111fe1266STvrtko Ursulin 	  && radeon_connector->hpd.hpd != RADEON_HPD_NONE) {
120211fe1266STvrtko Ursulin 		if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
120311fe1266STvrtko Ursulin 			status = connector_status_connected;
120411fe1266STvrtko Ursulin 		else
120511fe1266STvrtko Ursulin 			status = connector_status_disconnected;
120611fe1266STvrtko Ursulin 		if (connector->status == status)
120711fe1266STvrtko Ursulin 			return true;
120811fe1266STvrtko Ursulin 	}
120911fe1266STvrtko Ursulin 
121011fe1266STvrtko Ursulin 	return false;
121111fe1266STvrtko Ursulin }
121211fe1266STvrtko Ursulin 
12134ce001abSDave Airlie /*
12144ce001abSDave Airlie  * DVI is complicated
12154ce001abSDave Airlie  * Do a DDC probe, if DDC probe passes, get the full EDID so
12164ce001abSDave Airlie  * we can do analog/digital monitor detection at this point.
12174ce001abSDave Airlie  * If the monitor is an analog monitor or we got no DDC,
12184ce001abSDave Airlie  * we need to find the DAC encoder object for this connector.
12194ce001abSDave Airlie  * If we got no DDC, we do load detection on the DAC encoder object.
12204ce001abSDave Airlie  * If we got analog DDC or load detection passes on the DAC encoder
12214ce001abSDave Airlie  * we have to check if this analog encoder is shared with anyone else (TV)
12224ce001abSDave Airlie  * if its shared we have to set the other connector to disconnected.
12234ce001abSDave Airlie  */
12247b334fcbSChris Wilson static enum drm_connector_status
radeon_dvi_detect(struct drm_connector * connector,bool force)1225930a9e28SChris Wilson radeon_dvi_detect(struct drm_connector *connector, bool force)
1226771fe6b9SJerome Glisse {
1227fafcf94eSAlex Deucher 	struct drm_device *dev = connector->dev;
1228fafcf94eSAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
1229771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
12304ce001abSDave Airlie 	struct drm_encoder *encoder = NULL;
1231319d1e14SJani Nikula 	const struct drm_encoder_helper_funcs *encoder_funcs;
12327b71ca24SVille Syrjälä 	int r;
1233771fe6b9SJerome Glisse 	enum drm_connector_status ret = connector_status_disconnected;
1234fc87f13bSEgbert Eich 	bool dret = false, broken_edid = false;
1235771fe6b9SJerome Glisse 
123615734fefSLukas Wunner 	if (!drm_kms_helper_is_poll_worker()) {
123710ebc0bcSDave Airlie 		r = pm_runtime_get_sync(connector->dev->dev);
12386f2e8acdSAditya Pakki 		if (r < 0) {
12396f2e8acdSAditya Pakki 			pm_runtime_put_autosuspend(connector->dev->dev);
124010ebc0bcSDave Airlie 			return connector_status_disconnected;
124115734fefSLukas Wunner 		}
12426f2e8acdSAditya Pakki 	}
124310ebc0bcSDave Airlie 
1244cb5d4166SLyude 	if (radeon_connector->detected_hpd_without_ddc) {
1245cb5d4166SLyude 		force = true;
1246cb5d4166SLyude 		radeon_connector->detected_hpd_without_ddc = false;
1247cb5d4166SLyude 	}
1248cb5d4166SLyude 
124910ebc0bcSDave Airlie 	if (!force && radeon_check_hpd_status_unchanged(connector)) {
125010ebc0bcSDave Airlie 		ret = connector->status;
125110ebc0bcSDave Airlie 		goto exit;
125210ebc0bcSDave Airlie 	}
125311fe1266STvrtko Ursulin 
1254cb5d4166SLyude 	if (radeon_connector->ddc_bus) {
12550a9069d3SNiels Ole Salscheider 		dret = radeon_ddc_probe(radeon_connector, false);
1256cb5d4166SLyude 
1257cb5d4166SLyude 		/* Sometimes the pins required for the DDC probe on DVI
1258cb5d4166SLyude 		 * connectors don't make contact at the same time that the ones
1259cb5d4166SLyude 		 * for HPD do. If the DDC probe fails even though we had an HPD
1260cb5d4166SLyude 		 * signal, try again later */
1261cb5d4166SLyude 		if (!dret && !force &&
1262cb5d4166SLyude 		    connector->status != connector_status_connected) {
1263cb5d4166SLyude 			DRM_DEBUG_KMS("hpd detected without ddc, retrying in 1 second\n");
1264cb5d4166SLyude 			radeon_connector->detected_hpd_without_ddc = true;
1265cb5d4166SLyude 			schedule_delayed_work(&rdev->hotplug_work,
1266cb5d4166SLyude 					      msecs_to_jiffies(1000));
1267cb5d4166SLyude 			goto exit;
1268cb5d4166SLyude 		}
1269cb5d4166SLyude 	}
12704ce001abSDave Airlie 	if (dret) {
1271d0d0a225SAlex Deucher 		radeon_connector->detected_by_load = false;
127272a5c970SAlex Deucher 		radeon_connector_free_edid(connector);
127372a5c970SAlex Deucher 		radeon_connector_get_edid(connector);
12744ce001abSDave Airlie 
12754ce001abSDave Airlie 		if (!radeon_connector->edid) {
1276f82f5f3aSJerome Glisse 			DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
127772082093SJani Nikula 					connector->name);
12784a9a8b71SDave Airlie 			/* rs690 seems to have a problem with connectors not existing and always
12794a9a8b71SDave Airlie 			 * return a block of 0's. If we see this just stop polling on this output */
128072a5c970SAlex Deucher 			if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) &&
128172a5c970SAlex Deucher 			    radeon_connector->base.null_edid_counter) {
12824a9a8b71SDave Airlie 				ret = connector_status_disconnected;
128372082093SJani Nikula 				DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n",
128472082093SJani Nikula 					  connector->name);
12854a9a8b71SDave Airlie 				radeon_connector->ddc_bus = NULL;
1286fc87f13bSEgbert Eich 			} else {
1287fc87f13bSEgbert Eich 				ret = connector_status_connected;
1288fc87f13bSEgbert Eich 				broken_edid = true; /* defer use_digital to later */
12894a9a8b71SDave Airlie 			}
12904ce001abSDave Airlie 		} else {
129172a5c970SAlex Deucher 			radeon_connector->use_digital =
129272a5c970SAlex Deucher 				!!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
12934ce001abSDave Airlie 
12940294cf4fSAlex Deucher 			/* some oems have boards with separate digital and analog connectors
12950294cf4fSAlex Deucher 			 * with a shared ddc line (often vga + hdmi)
12960294cf4fSAlex Deucher 			 */
12970294cf4fSAlex Deucher 			if ((!radeon_connector->use_digital) && radeon_connector->shared_ddc) {
129872a5c970SAlex Deucher 				radeon_connector_free_edid(connector);
12990294cf4fSAlex Deucher 				ret = connector_status_disconnected;
130072a5c970SAlex Deucher 			} else {
1301771fe6b9SJerome Glisse 				ret = connector_status_connected;
130272a5c970SAlex Deucher 			}
130342f14c4bSAlex Deucher 			/* This gets complicated.  We have boards with VGA + HDMI with a
130442f14c4bSAlex Deucher 			 * shared DDC line and we have boards with DVI-D + HDMI with a shared
130542f14c4bSAlex Deucher 			 * DDC line.  The latter is more complex because with DVI<->HDMI adapters
130642f14c4bSAlex Deucher 			 * you don't really know what's connected to which port as both are digital.
130771407c46SAlex Deucher 			 */
1308d3932d6cSAlex Deucher 			if (radeon_connector->shared_ddc && (ret == connector_status_connected)) {
130971407c46SAlex Deucher 				struct drm_connector *list_connector;
131071407c46SAlex Deucher 				struct radeon_connector *list_radeon_connector;
131171407c46SAlex Deucher 				list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) {
131271407c46SAlex Deucher 					if (connector == list_connector)
131371407c46SAlex Deucher 						continue;
131471407c46SAlex Deucher 					list_radeon_connector = to_radeon_connector(list_connector);
1315b2ea4aa6SAlex Deucher 					if (list_radeon_connector->shared_ddc &&
1316b2ea4aa6SAlex Deucher 					    (list_radeon_connector->ddc_bus->rec.i2c_id ==
1317b2ea4aa6SAlex Deucher 					     radeon_connector->ddc_bus->rec.i2c_id)) {
131842f14c4bSAlex Deucher 						/* cases where both connectors are digital */
131942f14c4bSAlex Deucher 						if (list_connector->connector_type != DRM_MODE_CONNECTOR_VGA) {
132042f14c4bSAlex Deucher 							/* hpd is our only option in this case */
132142f14c4bSAlex Deucher 							if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
132272a5c970SAlex Deucher 								radeon_connector_free_edid(connector);
132371407c46SAlex Deucher 								ret = connector_status_disconnected;
132471407c46SAlex Deucher 							}
132571407c46SAlex Deucher 						}
132671407c46SAlex Deucher 					}
132771407c46SAlex Deucher 				}
132871407c46SAlex Deucher 			}
13294ce001abSDave Airlie 		}
13304ce001abSDave Airlie 	}
13314ce001abSDave Airlie 
13324ce001abSDave Airlie 	if ((ret == connector_status_connected) && (radeon_connector->use_digital == true))
13334ce001abSDave Airlie 		goto out;
13344ce001abSDave Airlie 
13355f0a2612SAlex Deucher 	/* DVI-D and HDMI-A are digital only */
13365f0a2612SAlex Deucher 	if ((connector->connector_type == DRM_MODE_CONNECTOR_DVID) ||
13375f0a2612SAlex Deucher 	    (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA))
13385f0a2612SAlex Deucher 		goto out;
13395f0a2612SAlex Deucher 
1340d0d0a225SAlex Deucher 	/* if we aren't forcing don't do destructive polling */
1341c3cceeddSDave Airlie 	if (!force) {
1342d0d0a225SAlex Deucher 		/* only return the previous status if we last
1343d0d0a225SAlex Deucher 		 * detected a monitor via load.
1344d0d0a225SAlex Deucher 		 */
1345d0d0a225SAlex Deucher 		if (radeon_connector->detected_by_load)
1346c3cceeddSDave Airlie 			ret = connector->status;
1347c3cceeddSDave Airlie 		goto out;
1348c3cceeddSDave Airlie 	}
1349c3cceeddSDave Airlie 
13504ce001abSDave Airlie 	/* find analog encoder */
1351445282dbSDave Airlie 	if (radeon_connector->dac_load_detect) {
135262afb4adSJosé Roberto de Souza 		drm_connector_for_each_possible_encoder(connector, encoder) {
1353e3632507STakashi Iwai 			if (encoder->encoder_type != DRM_MODE_ENCODER_DAC &&
1354e00e8b5eSAlex Deucher 			    encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
1355e00e8b5eSAlex Deucher 				continue;
1356e00e8b5eSAlex Deucher 
1357771fe6b9SJerome Glisse 			encoder_funcs = encoder->helper_private;
1358771fe6b9SJerome Glisse 			if (encoder_funcs->detect) {
1359fc87f13bSEgbert Eich 				if (!broken_edid) {
13604ce001abSDave Airlie 					if (ret != connector_status_connected) {
1361fc87f13bSEgbert Eich 						/* deal with analog monitors without DDC */
1362771fe6b9SJerome Glisse 						ret = encoder_funcs->detect(encoder, connector);
1363771fe6b9SJerome Glisse 						if (ret == connector_status_connected) {
13644ce001abSDave Airlie 							radeon_connector->use_digital = false;
13654ce001abSDave Airlie 						}
136634076446SJerome Glisse 						if (ret != connector_status_disconnected)
136734076446SJerome Glisse 							radeon_connector->detected_by_load = true;
13684ce001abSDave Airlie 					}
1369fc87f13bSEgbert Eich 				} else {
1370fc87f13bSEgbert Eich 					enum drm_connector_status lret;
1371fc87f13bSEgbert Eich 					/* assume digital unless load detected otherwise */
1372fc87f13bSEgbert Eich 					radeon_connector->use_digital = true;
1373fc87f13bSEgbert Eich 					lret = encoder_funcs->detect(encoder, connector);
1374fc87f13bSEgbert Eich 					DRM_DEBUG_KMS("load_detect %x returned: %x\n", encoder->encoder_type, lret);
1375fc87f13bSEgbert Eich 					if (lret == connector_status_connected)
1376fc87f13bSEgbert Eich 						radeon_connector->use_digital = false;
1377fc87f13bSEgbert Eich 				}
1378771fe6b9SJerome Glisse 				break;
1379771fe6b9SJerome Glisse 			}
1380771fe6b9SJerome Glisse 		}
1381445282dbSDave Airlie 	}
13824ce001abSDave Airlie 
13834ce001abSDave Airlie 	if ((ret == connector_status_connected) && (radeon_connector->use_digital == false) &&
13844ce001abSDave Airlie 	    encoder) {
13854ce001abSDave Airlie 		ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
1386771fe6b9SJerome Glisse 	}
1387771fe6b9SJerome Glisse 
1388fafcf94eSAlex Deucher 	/* RN50 and some RV100 asics in servers often have a hardcoded EDID in the
1389fafcf94eSAlex Deucher 	 * vbios to deal with KVMs. If we have one and are not able to detect a monitor
1390fafcf94eSAlex Deucher 	 * by other means, assume the DFP is connected and use that EDID.  In most
1391fafcf94eSAlex Deucher 	 * cases the DVI port is actually a virtual KVM port connected to the service
1392fafcf94eSAlex Deucher 	 * processor.
1393fafcf94eSAlex Deucher 	 */
1394a09d431fSDave Airlie out:
1395fafcf94eSAlex Deucher 	if ((!rdev->is_atom_bios) &&
1396fafcf94eSAlex Deucher 	    (ret == connector_status_disconnected) &&
1397fafcf94eSAlex Deucher 	    rdev->mode_info.bios_hardcoded_edid_size) {
1398fafcf94eSAlex Deucher 		radeon_connector->use_digital = true;
1399fafcf94eSAlex Deucher 		ret = connector_status_connected;
1400fafcf94eSAlex Deucher 	}
1401fafcf94eSAlex Deucher 
1402771fe6b9SJerome Glisse 	/* updated in get modes as well since we need to know if it's analog or digital */
1403771fe6b9SJerome Glisse 	radeon_connector_update_scratch_regs(connector, ret);
140410ebc0bcSDave Airlie 
1405d0ea397eSAlex Deucher 	if ((radeon_audio != 0) && radeon_connector->use_digital) {
1406d0ea397eSAlex Deucher 		const struct drm_connector_helper_funcs *connector_funcs =
1407d0ea397eSAlex Deucher 			connector->helper_private;
1408d0ea397eSAlex Deucher 
1409d0ea397eSAlex Deucher 		encoder = connector_funcs->best_encoder(connector);
1410d0ea397eSAlex Deucher 		if (encoder && (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)) {
1411d0ea397eSAlex Deucher 			radeon_connector_get_edid(connector);
1412d0ea397eSAlex Deucher 			radeon_audio_detect(connector, encoder, ret);
1413d0ea397eSAlex Deucher 		}
1414d0ea397eSAlex Deucher 	}
14151a626b68SSlava Grigorev 
141610ebc0bcSDave Airlie exit:
141715734fefSLukas Wunner 	if (!drm_kms_helper_is_poll_worker()) {
141810ebc0bcSDave Airlie 		pm_runtime_mark_last_busy(connector->dev->dev);
141910ebc0bcSDave Airlie 		pm_runtime_put_autosuspend(connector->dev->dev);
142015734fefSLukas Wunner 	}
142110ebc0bcSDave Airlie 
1422771fe6b9SJerome Glisse 	return ret;
1423771fe6b9SJerome Glisse }
1424771fe6b9SJerome Glisse 
1425771fe6b9SJerome Glisse /* okay need to be smart in here about which encoder to pick */
radeon_dvi_encoder(struct drm_connector * connector)14261109ca09SLauri Kasanen static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
1427771fe6b9SJerome Glisse {
1428771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1429771fe6b9SJerome Glisse 	struct drm_encoder *encoder;
1430771fe6b9SJerome Glisse 
143162afb4adSJosé Roberto de Souza 	drm_connector_for_each_possible_encoder(connector, encoder) {
14324ce001abSDave Airlie 		if (radeon_connector->use_digital == true) {
1433771fe6b9SJerome Glisse 			if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
1434771fe6b9SJerome Glisse 				return encoder;
1435771fe6b9SJerome Glisse 		} else {
1436771fe6b9SJerome Glisse 			if (encoder->encoder_type == DRM_MODE_ENCODER_DAC ||
1437771fe6b9SJerome Glisse 			    encoder->encoder_type == DRM_MODE_ENCODER_TVDAC)
1438771fe6b9SJerome Glisse 				return encoder;
1439771fe6b9SJerome Glisse 		}
1440771fe6b9SJerome Glisse 	}
1441771fe6b9SJerome Glisse 
1442771fe6b9SJerome Glisse 	/* see if we have a default encoder  TODO */
1443771fe6b9SJerome Glisse 
1444771fe6b9SJerome Glisse 	/* then check use digitial */
1445771fe6b9SJerome Glisse 	/* pick the first one */
144662afb4adSJosé Roberto de Souza 	drm_connector_for_each_possible_encoder(connector, encoder)
14477b71ca24SVille Syrjälä 		return encoder;
14487b71ca24SVille Syrjälä 
1449771fe6b9SJerome Glisse 	return NULL;
1450771fe6b9SJerome Glisse }
1451771fe6b9SJerome Glisse 
radeon_dvi_force(struct drm_connector * connector)1452d50ba256SDave Airlie static void radeon_dvi_force(struct drm_connector *connector)
1453d50ba256SDave Airlie {
1454d50ba256SDave Airlie 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1455d50ba256SDave Airlie 	if (connector->force == DRM_FORCE_ON)
1456d50ba256SDave Airlie 		radeon_connector->use_digital = false;
1457d50ba256SDave Airlie 	if (connector->force == DRM_FORCE_ON_DIGITAL)
1458d50ba256SDave Airlie 		radeon_connector->use_digital = true;
1459d50ba256SDave Airlie }
1460d50ba256SDave Airlie 
radeon_dvi_mode_valid(struct drm_connector * connector,struct drm_display_mode * mode)14617a47f20eSLuc Van Oostenryck static enum drm_mode_status radeon_dvi_mode_valid(struct drm_connector *connector,
1462a3fa6320SAlex Deucher 				  struct drm_display_mode *mode)
1463a3fa6320SAlex Deucher {
14641b24203eSAlex Deucher 	struct drm_device *dev = connector->dev;
14651b24203eSAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
1466a3fa6320SAlex Deucher 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1467a3fa6320SAlex Deucher 
1468a3fa6320SAlex Deucher 	/* XXX check mode bandwidth */
1469a3fa6320SAlex Deucher 
14701b24203eSAlex Deucher 	/* clocks over 135 MHz have heat issues with DVI on RV100 */
14711b24203eSAlex Deucher 	if (radeon_connector->use_digital &&
14721b24203eSAlex Deucher 	    (rdev->family == CHIP_RV100) &&
14731b24203eSAlex Deucher 	    (mode->clock > 135000))
14741b24203eSAlex Deucher 		return MODE_CLOCK_HIGH;
14751b24203eSAlex Deucher 
1476a3fa6320SAlex Deucher 	if (radeon_connector->use_digital && (mode->clock > 165000)) {
1477a3fa6320SAlex Deucher 		if ((radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I) ||
1478a3fa6320SAlex Deucher 		    (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
1479a3fa6320SAlex Deucher 		    (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B))
1480a3fa6320SAlex Deucher 			return MODE_OK;
1481377bd8a9SAlex Deucher 		else if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
1482e1e84017SAlex Deucher 			/* HDMI 1.3+ supports max clock of 340 Mhz */
1483e1e84017SAlex Deucher 			if (mode->clock > 340000)
1484e1e84017SAlex Deucher 				return MODE_CLOCK_HIGH;
1485a3fa6320SAlex Deucher 			else
1486e1e84017SAlex Deucher 				return MODE_OK;
1487f2263fc7SAlex Deucher 		} else {
1488e1e84017SAlex Deucher 			return MODE_CLOCK_HIGH;
1489f2263fc7SAlex Deucher 		}
1490a3fa6320SAlex Deucher 	}
1491b20f9befSAlex Deucher 
1492b20f9befSAlex Deucher 	/* check against the max pixel clock */
1493b20f9befSAlex Deucher 	if ((mode->clock / 10) > rdev->clock.max_pixel_clock)
1494b20f9befSAlex Deucher 		return MODE_CLOCK_HIGH;
1495b20f9befSAlex Deucher 
1496a3fa6320SAlex Deucher 	return MODE_OK;
1497a3fa6320SAlex Deucher }
1498a3fa6320SAlex Deucher 
14991109ca09SLauri Kasanen static const struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = {
15003e22920fSAlex Deucher 	.get_modes = radeon_vga_get_modes,
1501a3fa6320SAlex Deucher 	.mode_valid = radeon_dvi_mode_valid,
1502771fe6b9SJerome Glisse 	.best_encoder = radeon_dvi_encoder,
1503771fe6b9SJerome Glisse };
1504771fe6b9SJerome Glisse 
15051109ca09SLauri Kasanen static const struct drm_connector_funcs radeon_dvi_connector_funcs = {
1506771fe6b9SJerome Glisse 	.dpms = drm_helper_connector_dpms,
1507771fe6b9SJerome Glisse 	.detect = radeon_dvi_detect,
1508771fe6b9SJerome Glisse 	.fill_modes = drm_helper_probe_single_connector_modes,
1509771fe6b9SJerome Glisse 	.set_property = radeon_connector_set_property,
1510b0c80bd5SAlex Deucher 	.early_unregister = radeon_connector_unregister,
1511771fe6b9SJerome Glisse 	.destroy = radeon_connector_destroy,
1512d50ba256SDave Airlie 	.force = radeon_dvi_force,
1513771fe6b9SJerome Glisse };
1514771fe6b9SJerome Glisse 
radeon_dp_get_modes(struct drm_connector * connector)1515746c1aa4SDave Airlie static int radeon_dp_get_modes(struct drm_connector *connector)
1516746c1aa4SDave Airlie {
1517746c1aa4SDave Airlie 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
15188b834852SAlex Deucher 	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
1519591a10e1SAlex Deucher 	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
1520746c1aa4SDave Airlie 	int ret;
1521746c1aa4SDave Airlie 
1522f89931f3SAlex Deucher 	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
1523f89931f3SAlex Deucher 	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
1524d291767bSAlex Deucher 		struct drm_display_mode *mode;
1525d291767bSAlex Deucher 
15262b69ffb9SAlex Deucher 		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
15278b834852SAlex Deucher 			if (!radeon_dig_connector->edp_on)
15288b834852SAlex Deucher 				atombios_set_edp_panel_power(connector,
15298b834852SAlex Deucher 							     ATOM_TRANSMITTER_ACTION_POWER_ON);
153072a5c970SAlex Deucher 			radeon_connector_get_edid(connector);
153172a5c970SAlex Deucher 			ret = radeon_ddc_get_modes(connector);
15328b834852SAlex Deucher 			if (!radeon_dig_connector->edp_on)
15338b834852SAlex Deucher 				atombios_set_edp_panel_power(connector,
15348b834852SAlex Deucher 							     ATOM_TRANSMITTER_ACTION_POWER_OFF);
15352b69ffb9SAlex Deucher 		} else {
15362b69ffb9SAlex Deucher 			/* need to setup ddc on the bridge */
15372b69ffb9SAlex Deucher 			if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
15382b69ffb9SAlex Deucher 			    ENCODER_OBJECT_ID_NONE) {
15392b69ffb9SAlex Deucher 				if (encoder)
15402b69ffb9SAlex Deucher 					radeon_atom_ext_encoder_setup_ddc(encoder);
15412b69ffb9SAlex Deucher 			}
154272a5c970SAlex Deucher 			radeon_connector_get_edid(connector);
154372a5c970SAlex Deucher 			ret = radeon_ddc_get_modes(connector);
15442b69ffb9SAlex Deucher 		}
1545d291767bSAlex Deucher 
1546d291767bSAlex Deucher 		if (ret > 0) {
1547d291767bSAlex Deucher 			if (encoder) {
1548d291767bSAlex Deucher 				radeon_fixup_lvds_native_mode(encoder, connector);
1549d291767bSAlex Deucher 				/* add scaled modes */
1550d291767bSAlex Deucher 				radeon_add_common_modes(encoder, connector);
15518b834852SAlex Deucher 			}
1552d291767bSAlex Deucher 			return ret;
1553d291767bSAlex Deucher 		}
1554d291767bSAlex Deucher 
1555d291767bSAlex Deucher 		if (!encoder)
1556d291767bSAlex Deucher 			return 0;
1557d291767bSAlex Deucher 
1558d291767bSAlex Deucher 		/* we have no EDID modes */
1559d291767bSAlex Deucher 		mode = radeon_fp_native_mode(encoder);
1560d291767bSAlex Deucher 		if (mode) {
1561d291767bSAlex Deucher 			ret = 1;
1562d291767bSAlex Deucher 			drm_mode_probed_add(connector, mode);
1563d291767bSAlex Deucher 			/* add the width/height from vbios tables if available */
1564d291767bSAlex Deucher 			connector->display_info.width_mm = mode->width_mm;
1565d291767bSAlex Deucher 			connector->display_info.height_mm = mode->height_mm;
1566d291767bSAlex Deucher 			/* add scaled modes */
1567d291767bSAlex Deucher 			radeon_add_common_modes(encoder, connector);
1568d291767bSAlex Deucher 		}
1569591a10e1SAlex Deucher 	} else {
1570591a10e1SAlex Deucher 		/* need to setup ddc on the bridge */
15711d33e1fcSAlex Deucher 		if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
15721d33e1fcSAlex Deucher 			ENCODER_OBJECT_ID_NONE) {
1573591a10e1SAlex Deucher 			if (encoder)
1574591a10e1SAlex Deucher 				radeon_atom_ext_encoder_setup_ddc(encoder);
1575591a10e1SAlex Deucher 		}
157672a5c970SAlex Deucher 		radeon_connector_get_edid(connector);
157772a5c970SAlex Deucher 		ret = radeon_ddc_get_modes(connector);
1578da997620SAlex Deucher 
1579da997620SAlex Deucher 		radeon_get_native_mode(connector);
1580591a10e1SAlex Deucher 	}
15818b834852SAlex Deucher 
1582746c1aa4SDave Airlie 	return ret;
1583746c1aa4SDave Airlie }
1584746c1aa4SDave Airlie 
radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector * connector)15851d33e1fcSAlex Deucher u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector)
1586d7fa8bb3SAlex Deucher {
1587d7fa8bb3SAlex Deucher 	struct drm_encoder *encoder;
1588d7fa8bb3SAlex Deucher 	struct radeon_encoder *radeon_encoder;
1589d7fa8bb3SAlex Deucher 
159062afb4adSJosé Roberto de Souza 	drm_connector_for_each_possible_encoder(connector, encoder) {
1591d7fa8bb3SAlex Deucher 		radeon_encoder = to_radeon_encoder(encoder);
1592d7fa8bb3SAlex Deucher 
1593d7fa8bb3SAlex Deucher 		switch (radeon_encoder->encoder_id) {
1594d7fa8bb3SAlex Deucher 		case ENCODER_OBJECT_ID_TRAVIS:
1595d7fa8bb3SAlex Deucher 		case ENCODER_OBJECT_ID_NUTMEG:
15961d33e1fcSAlex Deucher 			return radeon_encoder->encoder_id;
1597d7fa8bb3SAlex Deucher 		default:
1598d7fa8bb3SAlex Deucher 			break;
1599d7fa8bb3SAlex Deucher 		}
1600d7fa8bb3SAlex Deucher 	}
1601d7fa8bb3SAlex Deucher 
16021d33e1fcSAlex Deucher 	return ENCODER_OBJECT_ID_NONE;
1603d7fa8bb3SAlex Deucher }
1604d7fa8bb3SAlex Deucher 
radeon_connector_encoder_is_hbr2(struct drm_connector * connector)1605ebdea82dSAlex Deucher static bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector)
1606d7fa8bb3SAlex Deucher {
1607d7fa8bb3SAlex Deucher 	struct drm_encoder *encoder;
1608d7fa8bb3SAlex Deucher 	struct radeon_encoder *radeon_encoder;
1609d7fa8bb3SAlex Deucher 	bool found = false;
1610d7fa8bb3SAlex Deucher 
161162afb4adSJosé Roberto de Souza 	drm_connector_for_each_possible_encoder(connector, encoder) {
1612d7fa8bb3SAlex Deucher 		radeon_encoder = to_radeon_encoder(encoder);
1613d7fa8bb3SAlex Deucher 		if (radeon_encoder->caps & ATOM_ENCODER_CAP_RECORD_HBR2)
1614d7fa8bb3SAlex Deucher 			found = true;
1615d7fa8bb3SAlex Deucher 	}
1616d7fa8bb3SAlex Deucher 
1617d7fa8bb3SAlex Deucher 	return found;
1618d7fa8bb3SAlex Deucher }
1619d7fa8bb3SAlex Deucher 
radeon_connector_is_dp12_capable(struct drm_connector * connector)1620d7fa8bb3SAlex Deucher bool radeon_connector_is_dp12_capable(struct drm_connector *connector)
1621d7fa8bb3SAlex Deucher {
1622d7fa8bb3SAlex Deucher 	struct drm_device *dev = connector->dev;
1623d7fa8bb3SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
1624d7fa8bb3SAlex Deucher 
1625d7fa8bb3SAlex Deucher 	if (ASIC_IS_DCE5(rdev) &&
1626af5d3653SAlex Deucher 	    (rdev->clock.default_dispclk >= 53900) &&
1627d7fa8bb3SAlex Deucher 	    radeon_connector_encoder_is_hbr2(connector)) {
1628d7fa8bb3SAlex Deucher 		return true;
1629d7fa8bb3SAlex Deucher 	}
1630d7fa8bb3SAlex Deucher 
1631d7fa8bb3SAlex Deucher 	return false;
1632d7fa8bb3SAlex Deucher }
1633d7fa8bb3SAlex Deucher 
16347b334fcbSChris Wilson static enum drm_connector_status
radeon_dp_detect(struct drm_connector * connector,bool force)1635930a9e28SChris Wilson radeon_dp_detect(struct drm_connector *connector, bool force)
1636746c1aa4SDave Airlie {
1637f8d0eddeSAlex Deucher 	struct drm_device *dev = connector->dev;
1638f8d0eddeSAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
1639746c1aa4SDave Airlie 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
1640746c1aa4SDave Airlie 	enum drm_connector_status ret = connector_status_disconnected;
16414143e919SAlex Deucher 	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
1642591a10e1SAlex Deucher 	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
164310ebc0bcSDave Airlie 	int r;
1644746c1aa4SDave Airlie 
164515734fefSLukas Wunner 	if (!drm_kms_helper_is_poll_worker()) {
164610ebc0bcSDave Airlie 		r = pm_runtime_get_sync(connector->dev->dev);
16476f2e8acdSAditya Pakki 		if (r < 0) {
16486f2e8acdSAditya Pakki 			pm_runtime_put_autosuspend(connector->dev->dev);
164910ebc0bcSDave Airlie 			return connector_status_disconnected;
165015734fefSLukas Wunner 		}
16516f2e8acdSAditya Pakki 	}
165210ebc0bcSDave Airlie 
165310ebc0bcSDave Airlie 	if (!force && radeon_check_hpd_status_unchanged(connector)) {
165410ebc0bcSDave Airlie 		ret = connector->status;
165510ebc0bcSDave Airlie 		goto out;
165610ebc0bcSDave Airlie 	}
165711fe1266STvrtko Ursulin 
165872a5c970SAlex Deucher 	radeon_connector_free_edid(connector);
1659746c1aa4SDave Airlie 
1660f89931f3SAlex Deucher 	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
1661f89931f3SAlex Deucher 	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
1662d291767bSAlex Deucher 		if (encoder) {
1663d291767bSAlex Deucher 			struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1664d291767bSAlex Deucher 			struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
1665d291767bSAlex Deucher 
1666d291767bSAlex Deucher 			/* check if panel is valid */
1667d291767bSAlex Deucher 			if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240)
1668d291767bSAlex Deucher 				ret = connector_status_connected;
166913485794SAlex Deucher 			/* don't fetch the edid from the vbios if ddc fails and runpm is
167013485794SAlex Deucher 			 * enabled so we report disconnected.
167113485794SAlex Deucher 			 */
167213485794SAlex Deucher 			if ((rdev->flags & RADEON_IS_PX) && (radeon_runtime_pm != 0))
167313485794SAlex Deucher 				ret = connector_status_disconnected;
1674d291767bSAlex Deucher 		}
16756f50eae7SAlex Deucher 		/* eDP is always DP */
16766f50eae7SAlex Deucher 		radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT;
16778b834852SAlex Deucher 		if (!radeon_dig_connector->edp_on)
16788b834852SAlex Deucher 			atombios_set_edp_panel_power(connector,
16798b834852SAlex Deucher 						     ATOM_TRANSMITTER_ACTION_POWER_ON);
16806f50eae7SAlex Deucher 		if (radeon_dp_getdpcd(radeon_connector))
16814143e919SAlex Deucher 			ret = connector_status_connected;
16828b834852SAlex Deucher 		if (!radeon_dig_connector->edp_on)
16838b834852SAlex Deucher 			atombios_set_edp_panel_power(connector,
16848b834852SAlex Deucher 						     ATOM_TRANSMITTER_ACTION_POWER_OFF);
16851d33e1fcSAlex Deucher 	} else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
16861d33e1fcSAlex Deucher 		   ENCODER_OBJECT_ID_NONE) {
1687b06947b5SAlex Deucher 		/* DP bridges are always DP */
1688b06947b5SAlex Deucher 		radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT;
1689b06947b5SAlex Deucher 		/* get the DPCD from the bridge */
1690b06947b5SAlex Deucher 		radeon_dp_getdpcd(radeon_connector);
1691b06947b5SAlex Deucher 
16926777a4f6SAlex Deucher 		if (encoder) {
16936777a4f6SAlex Deucher 			/* setup ddc on the bridge */
1694591a10e1SAlex Deucher 			radeon_atom_ext_encoder_setup_ddc(encoder);
16950a9069d3SNiels Ole Salscheider 			/* bridge chips are always aux */
16960a9069d3SNiels Ole Salscheider 			if (radeon_ddc_probe(radeon_connector, true)) /* try DDC */
1697b06947b5SAlex Deucher 				ret = connector_status_connected;
16986777a4f6SAlex Deucher 			else if (radeon_connector->dac_load_detect) { /* try load detection */
1699319d1e14SJani Nikula 				const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
1700b06947b5SAlex Deucher 				ret = encoder_funcs->detect(encoder, connector);
1701b06947b5SAlex Deucher 			}
1702b06947b5SAlex Deucher 		}
1703b06947b5SAlex Deucher 	} else {
17046f50eae7SAlex Deucher 		radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector);
1705f8d0eddeSAlex Deucher 		if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
1706f8d0eddeSAlex Deucher 			ret = connector_status_connected;
170701ad1d9cSLyude Paul 			if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT)
1708f8d0eddeSAlex Deucher 				radeon_dp_getdpcd(radeon_connector);
1709f8d0eddeSAlex Deucher 		} else {
17106f50eae7SAlex Deucher 			if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
171101ad1d9cSLyude Paul 				if (radeon_dp_getdpcd(radeon_connector))
17126f50eae7SAlex Deucher 					ret = connector_status_connected;
17136f50eae7SAlex Deucher 			} else {
1714d592fca9SDamien Lespiau 				/* try non-aux ddc (DP to DVI/HDMI/etc. adapter) */
17150a9069d3SNiels Ole Salscheider 				if (radeon_ddc_probe(radeon_connector, false))
1716746c1aa4SDave Airlie 					ret = connector_status_connected;
1717746c1aa4SDave Airlie 			}
17184143e919SAlex Deucher 		}
1719f8d0eddeSAlex Deucher 	}
17204143e919SAlex Deucher 
172130f44372SAlex Deucher 	radeon_connector_update_scratch_regs(connector, ret);
17221a626b68SSlava Grigorev 
1723d0ea397eSAlex Deucher 	if ((radeon_audio != 0) && encoder) {
1724d0ea397eSAlex Deucher 		radeon_connector_get_edid(connector);
1725d0ea397eSAlex Deucher 		radeon_audio_detect(connector, encoder, ret);
1726d0ea397eSAlex Deucher 	}
17271a626b68SSlava Grigorev 
172810ebc0bcSDave Airlie out:
172915734fefSLukas Wunner 	if (!drm_kms_helper_is_poll_worker()) {
173010ebc0bcSDave Airlie 		pm_runtime_mark_last_busy(connector->dev->dev);
173110ebc0bcSDave Airlie 		pm_runtime_put_autosuspend(connector->dev->dev);
173215734fefSLukas Wunner 	}
173310ebc0bcSDave Airlie 
1734746c1aa4SDave Airlie 	return ret;
1735746c1aa4SDave Airlie }
1736746c1aa4SDave Airlie 
radeon_dp_mode_valid(struct drm_connector * connector,struct drm_display_mode * mode)17377a47f20eSLuc Van Oostenryck static enum drm_mode_status radeon_dp_mode_valid(struct drm_connector *connector,
17385801ead6SAlex Deucher 				  struct drm_display_mode *mode)
17395801ead6SAlex Deucher {
17406536a3a6SAlex Deucher 	struct drm_device *dev = connector->dev;
17416536a3a6SAlex Deucher 	struct radeon_device *rdev = dev->dev_private;
17425801ead6SAlex Deucher 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
17435801ead6SAlex Deucher 	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
17445801ead6SAlex Deucher 
17455801ead6SAlex Deucher 	/* XXX check mode bandwidth */
17465801ead6SAlex Deucher 
1747f89931f3SAlex Deucher 	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
1748f89931f3SAlex Deucher 	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
1749d291767bSAlex Deucher 		struct drm_encoder *encoder = radeon_best_single_encoder(connector);
1750d291767bSAlex Deucher 
1751d291767bSAlex Deucher 		if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
1752d291767bSAlex Deucher 			return MODE_PANEL;
1753d291767bSAlex Deucher 
1754d291767bSAlex Deucher 		if (encoder) {
1755d291767bSAlex Deucher 			struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1756d291767bSAlex Deucher 			struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
1757d291767bSAlex Deucher 
1758d291767bSAlex Deucher 			/* AVIVO hardware supports downscaling modes larger than the panel
1759d291767bSAlex Deucher 			 * to the panel size, but I'm not sure this is desirable.
1760d291767bSAlex Deucher 			 */
1761d291767bSAlex Deucher 			if ((mode->hdisplay > native_mode->hdisplay) ||
1762d291767bSAlex Deucher 			    (mode->vdisplay > native_mode->vdisplay))
1763d291767bSAlex Deucher 				return MODE_PANEL;
1764d291767bSAlex Deucher 
1765d291767bSAlex Deucher 			/* if scaling is disabled, block non-native modes */
1766d291767bSAlex Deucher 			if (radeon_encoder->rmx_type == RMX_OFF) {
1767d291767bSAlex Deucher 				if ((mode->hdisplay != native_mode->hdisplay) ||
1768d291767bSAlex Deucher 				    (mode->vdisplay != native_mode->vdisplay))
1769d291767bSAlex Deucher 					return MODE_PANEL;
1770d291767bSAlex Deucher 			}
1771d291767bSAlex Deucher 		}
1772d291767bSAlex Deucher 	} else {
1773196c58d2SAlex Deucher 		if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
17746536a3a6SAlex Deucher 		    (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
1775224d94b1SAlex Deucher 			return radeon_dp_mode_valid_helper(connector, mode);
17766536a3a6SAlex Deucher 		} else {
1777377bd8a9SAlex Deucher 			if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
17786536a3a6SAlex Deucher 				/* HDMI 1.3+ supports max clock of 340 Mhz */
17796536a3a6SAlex Deucher 				if (mode->clock > 340000)
17806536a3a6SAlex Deucher 					return MODE_CLOCK_HIGH;
17816536a3a6SAlex Deucher 			} else {
17826536a3a6SAlex Deucher 				if (mode->clock > 165000)
17836536a3a6SAlex Deucher 					return MODE_CLOCK_HIGH;
17845801ead6SAlex Deucher 			}
1785d291767bSAlex Deucher 		}
17866536a3a6SAlex Deucher 	}
17876536a3a6SAlex Deucher 
17886536a3a6SAlex Deucher 	return MODE_OK;
17896536a3a6SAlex Deucher }
17905801ead6SAlex Deucher 
17911109ca09SLauri Kasanen static const struct drm_connector_helper_funcs radeon_dp_connector_helper_funcs = {
1792746c1aa4SDave Airlie 	.get_modes = radeon_dp_get_modes,
17935801ead6SAlex Deucher 	.mode_valid = radeon_dp_mode_valid,
1794746c1aa4SDave Airlie 	.best_encoder = radeon_dvi_encoder,
1795746c1aa4SDave Airlie };
1796746c1aa4SDave Airlie 
17971109ca09SLauri Kasanen static const struct drm_connector_funcs radeon_dp_connector_funcs = {
1798746c1aa4SDave Airlie 	.dpms = drm_helper_connector_dpms,
1799746c1aa4SDave Airlie 	.detect = radeon_dp_detect,
1800746c1aa4SDave Airlie 	.fill_modes = drm_helper_probe_single_connector_modes,
1801746c1aa4SDave Airlie 	.set_property = radeon_connector_set_property,
1802b0c80bd5SAlex Deucher 	.early_unregister = radeon_connector_unregister,
1803379dfc25SAlex Deucher 	.destroy = radeon_connector_destroy,
1804746c1aa4SDave Airlie 	.force = radeon_dvi_force,
1805746c1aa4SDave Airlie };
1806746c1aa4SDave Airlie 
1807855f5f1dSAlex Deucher static const struct drm_connector_funcs radeon_edp_connector_funcs = {
1808855f5f1dSAlex Deucher 	.dpms = drm_helper_connector_dpms,
1809855f5f1dSAlex Deucher 	.detect = radeon_dp_detect,
1810855f5f1dSAlex Deucher 	.fill_modes = drm_helper_probe_single_connector_modes,
1811855f5f1dSAlex Deucher 	.set_property = radeon_lvds_set_property,
1812b0c80bd5SAlex Deucher 	.early_unregister = radeon_connector_unregister,
1813379dfc25SAlex Deucher 	.destroy = radeon_connector_destroy,
1814855f5f1dSAlex Deucher 	.force = radeon_dvi_force,
1815855f5f1dSAlex Deucher };
1816855f5f1dSAlex Deucher 
1817855f5f1dSAlex Deucher static const struct drm_connector_funcs radeon_lvds_bridge_connector_funcs = {
1818855f5f1dSAlex Deucher 	.dpms = drm_helper_connector_dpms,
1819855f5f1dSAlex Deucher 	.detect = radeon_dp_detect,
1820855f5f1dSAlex Deucher 	.fill_modes = drm_helper_probe_single_connector_modes,
1821855f5f1dSAlex Deucher 	.set_property = radeon_lvds_set_property,
1822b0c80bd5SAlex Deucher 	.early_unregister = radeon_connector_unregister,
1823379dfc25SAlex Deucher 	.destroy = radeon_connector_destroy,
1824855f5f1dSAlex Deucher 	.force = radeon_dvi_force,
1825855f5f1dSAlex Deucher };
1826855f5f1dSAlex Deucher 
1827771fe6b9SJerome Glisse void
radeon_add_atom_connector(struct drm_device * dev,uint32_t connector_id,uint32_t supported_device,int connector_type,struct radeon_i2c_bus_rec * i2c_bus,uint32_t igp_lane_info,uint16_t connector_object_id,struct radeon_hpd * hpd,struct radeon_router * router)1828771fe6b9SJerome Glisse radeon_add_atom_connector(struct drm_device *dev,
1829771fe6b9SJerome Glisse 			  uint32_t connector_id,
1830771fe6b9SJerome Glisse 			  uint32_t supported_device,
1831771fe6b9SJerome Glisse 			  int connector_type,
1832771fe6b9SJerome Glisse 			  struct radeon_i2c_bus_rec *i2c_bus,
1833b75fad06SAlex Deucher 			  uint32_t igp_lane_info,
1834eed45b30SAlex Deucher 			  uint16_t connector_object_id,
183526b5bc98SAlex Deucher 			  struct radeon_hpd *hpd,
183626b5bc98SAlex Deucher 			  struct radeon_router *router)
1837771fe6b9SJerome Glisse {
1838445282dbSDave Airlie 	struct radeon_device *rdev = dev->dev_private;
1839771fe6b9SJerome Glisse 	struct drm_connector *connector;
1840771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector;
1841771fe6b9SJerome Glisse 	struct radeon_connector_atom_dig *radeon_dig_connector;
1842eac4dff6SAlex Deucher 	struct drm_encoder *encoder;
1843eac4dff6SAlex Deucher 	struct radeon_encoder *radeon_encoder;
1844af0e31abSAndrzej Pietrasiewicz 	struct i2c_adapter *ddc = NULL;
1845771fe6b9SJerome Glisse 	uint32_t subpixel_order = SubPixelNone;
18460294cf4fSAlex Deucher 	bool shared_ddc = false;
1847eac4dff6SAlex Deucher 	bool is_dp_bridge = false;
1848496263bfSAlex Deucher 	bool has_aux = false;
1849771fe6b9SJerome Glisse 
18504ce001abSDave Airlie 	if (connector_type == DRM_MODE_CONNECTOR_Unknown)
1851771fe6b9SJerome Glisse 		return;
1852771fe6b9SJerome Glisse 
1853cf4c12f9SAlex Deucher 	/* if the user selected tv=0 don't try and add the connector */
1854cf4c12f9SAlex Deucher 	if (((connector_type == DRM_MODE_CONNECTOR_SVIDEO) ||
1855cf4c12f9SAlex Deucher 	     (connector_type == DRM_MODE_CONNECTOR_Composite) ||
1856cf4c12f9SAlex Deucher 	     (connector_type == DRM_MODE_CONNECTOR_9PinDIN)) &&
1857cf4c12f9SAlex Deucher 	    (radeon_tv == 0))
1858cf4c12f9SAlex Deucher 		return;
1859cf4c12f9SAlex Deucher 
1860771fe6b9SJerome Glisse 	/* see if we already added it */
1861771fe6b9SJerome Glisse 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1862771fe6b9SJerome Glisse 		radeon_connector = to_radeon_connector(connector);
1863771fe6b9SJerome Glisse 		if (radeon_connector->connector_id == connector_id) {
1864771fe6b9SJerome Glisse 			radeon_connector->devices |= supported_device;
1865771fe6b9SJerome Glisse 			return;
1866771fe6b9SJerome Glisse 		}
18670294cf4fSAlex Deucher 		if (radeon_connector->ddc_bus && i2c_bus->valid) {
1868d3932d6cSAlex Deucher 			if (radeon_connector->ddc_bus->rec.i2c_id == i2c_bus->i2c_id) {
18690294cf4fSAlex Deucher 				radeon_connector->shared_ddc = true;
18700294cf4fSAlex Deucher 				shared_ddc = true;
18710294cf4fSAlex Deucher 			}
1872fb939dfcSAlex Deucher 			if (radeon_connector->router_bus && router->ddc_valid &&
187326b5bc98SAlex Deucher 			    (radeon_connector->router.router_id == router->router_id)) {
187426b5bc98SAlex Deucher 				radeon_connector->shared_ddc = false;
187526b5bc98SAlex Deucher 				shared_ddc = false;
187626b5bc98SAlex Deucher 			}
18770294cf4fSAlex Deucher 		}
1878771fe6b9SJerome Glisse 	}
1879771fe6b9SJerome Glisse 
1880eac4dff6SAlex Deucher 	/* check if it's a dp bridge */
1881eac4dff6SAlex Deucher 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
1882eac4dff6SAlex Deucher 		radeon_encoder = to_radeon_encoder(encoder);
1883eac4dff6SAlex Deucher 		if (radeon_encoder->devices & supported_device) {
1884eac4dff6SAlex Deucher 			switch (radeon_encoder->encoder_id) {
1885eac4dff6SAlex Deucher 			case ENCODER_OBJECT_ID_TRAVIS:
1886eac4dff6SAlex Deucher 			case ENCODER_OBJECT_ID_NUTMEG:
1887eac4dff6SAlex Deucher 				is_dp_bridge = true;
1888eac4dff6SAlex Deucher 				break;
1889eac4dff6SAlex Deucher 			default:
1890eac4dff6SAlex Deucher 				break;
1891eac4dff6SAlex Deucher 			}
1892eac4dff6SAlex Deucher 		}
1893eac4dff6SAlex Deucher 	}
1894eac4dff6SAlex Deucher 
1895771fe6b9SJerome Glisse 	radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL);
1896771fe6b9SJerome Glisse 	if (!radeon_connector)
1897771fe6b9SJerome Glisse 		return;
1898771fe6b9SJerome Glisse 
1899771fe6b9SJerome Glisse 	connector = &radeon_connector->base;
1900771fe6b9SJerome Glisse 
1901771fe6b9SJerome Glisse 	radeon_connector->connector_id = connector_id;
1902771fe6b9SJerome Glisse 	radeon_connector->devices = supported_device;
19030294cf4fSAlex Deucher 	radeon_connector->shared_ddc = shared_ddc;
1904b75fad06SAlex Deucher 	radeon_connector->connector_object_id = connector_object_id;
1905eed45b30SAlex Deucher 	radeon_connector->hpd = *hpd;
1906bc1c4dc3SAlex Deucher 
190726b5bc98SAlex Deucher 	radeon_connector->router = *router;
1908fb939dfcSAlex Deucher 	if (router->ddc_valid || router->cd_valid) {
190926b5bc98SAlex Deucher 		radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
191026b5bc98SAlex Deucher 		if (!radeon_connector->router_bus)
1911a70882aaSAlex Deucher 			DRM_ERROR("Failed to assign router i2c bus! Check dmesg for i2c errors.\n");
191226b5bc98SAlex Deucher 	}
1913eac4dff6SAlex Deucher 
1914eac4dff6SAlex Deucher 	if (is_dp_bridge) {
1915eac4dff6SAlex Deucher 		radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
1916eac4dff6SAlex Deucher 		if (!radeon_dig_connector)
1917eac4dff6SAlex Deucher 			goto failed;
1918eac4dff6SAlex Deucher 		radeon_dig_connector->igp_lane_info = igp_lane_info;
1919eac4dff6SAlex Deucher 		radeon_connector->con_priv = radeon_dig_connector;
1920eac4dff6SAlex Deucher 		if (i2c_bus->valid) {
1921379dfc25SAlex Deucher 			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
1922af0e31abSAndrzej Pietrasiewicz 			if (radeon_connector->ddc_bus) {
1923496263bfSAlex Deucher 				has_aux = true;
1924af0e31abSAndrzej Pietrasiewicz 				ddc = &radeon_connector->ddc_bus->adapter;
1925af0e31abSAndrzej Pietrasiewicz 			} else {
1926eac4dff6SAlex Deucher 				DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
1927eac4dff6SAlex Deucher 			}
1928af0e31abSAndrzej Pietrasiewicz 		}
1929eac4dff6SAlex Deucher 		switch (connector_type) {
1930eac4dff6SAlex Deucher 		case DRM_MODE_CONNECTOR_VGA:
1931eac4dff6SAlex Deucher 		case DRM_MODE_CONNECTOR_DVIA:
1932eac4dff6SAlex Deucher 		default:
1933af0e31abSAndrzej Pietrasiewicz 			drm_connector_init_with_ddc(dev, &radeon_connector->base,
1934af0e31abSAndrzej Pietrasiewicz 						    &radeon_dp_connector_funcs,
1935af0e31abSAndrzej Pietrasiewicz 						    connector_type,
1936af0e31abSAndrzej Pietrasiewicz 						    ddc);
1937855f5f1dSAlex Deucher 			drm_connector_helper_add(&radeon_connector->base,
1938855f5f1dSAlex Deucher 						 &radeon_dp_connector_helper_funcs);
1939eac4dff6SAlex Deucher 			connector->interlace_allowed = true;
1940eac4dff6SAlex Deucher 			connector->doublescan_allowed = true;
1941d629a3ceSAlex Deucher 			radeon_connector->dac_load_detect = true;
1942e35755faSRob Clark 			drm_object_attach_property(&radeon_connector->base.base,
1943d629a3ceSAlex Deucher 						      rdev->mode_info.load_detect_property,
1944d629a3ceSAlex Deucher 						      1);
1945da997620SAlex Deucher 			drm_object_attach_property(&radeon_connector->base.base,
1946da997620SAlex Deucher 						   dev->mode_config.scaling_mode_property,
1947da997620SAlex Deucher 						   DRM_MODE_SCALE_NONE);
1948643b1f56SAlex Deucher 			if (ASIC_IS_DCE5(rdev))
1949643b1f56SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
1950643b1f56SAlex Deucher 							   rdev->mode_info.output_csc_property,
1951643b1f56SAlex Deucher 							   RADEON_OUTPUT_CSC_BYPASS);
1952eac4dff6SAlex Deucher 			break;
1953eac4dff6SAlex Deucher 		case DRM_MODE_CONNECTOR_DVII:
1954eac4dff6SAlex Deucher 		case DRM_MODE_CONNECTOR_DVID:
1955eac4dff6SAlex Deucher 		case DRM_MODE_CONNECTOR_HDMIA:
1956eac4dff6SAlex Deucher 		case DRM_MODE_CONNECTOR_HDMIB:
1957eac4dff6SAlex Deucher 		case DRM_MODE_CONNECTOR_DisplayPort:
1958af0e31abSAndrzej Pietrasiewicz 			drm_connector_init_with_ddc(dev, &radeon_connector->base,
1959af0e31abSAndrzej Pietrasiewicz 						    &radeon_dp_connector_funcs,
1960af0e31abSAndrzej Pietrasiewicz 						    connector_type,
1961af0e31abSAndrzej Pietrasiewicz 						    ddc);
1962855f5f1dSAlex Deucher 			drm_connector_helper_add(&radeon_connector->base,
1963855f5f1dSAlex Deucher 						 &radeon_dp_connector_helper_funcs);
1964e35755faSRob Clark 			drm_object_attach_property(&radeon_connector->base.base,
1965eac4dff6SAlex Deucher 						      rdev->mode_info.underscan_property,
1966eac4dff6SAlex Deucher 						      UNDERSCAN_OFF);
1967e35755faSRob Clark 			drm_object_attach_property(&radeon_connector->base.base,
1968eac4dff6SAlex Deucher 						      rdev->mode_info.underscan_hborder_property,
1969eac4dff6SAlex Deucher 						      0);
1970e35755faSRob Clark 			drm_object_attach_property(&radeon_connector->base.base,
1971eac4dff6SAlex Deucher 						      rdev->mode_info.underscan_vborder_property,
1972eac4dff6SAlex Deucher 						      0);
197391915260SDave Airlie 
19746214bb74SAlex Deucher 			drm_object_attach_property(&radeon_connector->base.base,
1975da997620SAlex Deucher 						      dev->mode_config.scaling_mode_property,
1976da997620SAlex Deucher 						      DRM_MODE_SCALE_NONE);
1977da997620SAlex Deucher 
1978da997620SAlex Deucher 			drm_object_attach_property(&radeon_connector->base.base,
19796214bb74SAlex Deucher 						   rdev->mode_info.dither_property,
19806214bb74SAlex Deucher 						   RADEON_FMT_DITHER_DISABLE);
198191915260SDave Airlie 
19827403c515SAlex Deucher 			if (radeon_audio != 0) {
19838666c076SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
19848666c076SAlex Deucher 							   rdev->mode_info.audio_property,
1985e31fadd3SAlex Deucher 							   RADEON_AUDIO_AUTO);
19867403c515SAlex Deucher 				radeon_connector->audio = RADEON_AUDIO_AUTO;
19877403c515SAlex Deucher 			}
1988643b1f56SAlex Deucher 			if (ASIC_IS_DCE5(rdev))
1989643b1f56SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
1990643b1f56SAlex Deucher 							   rdev->mode_info.output_csc_property,
1991643b1f56SAlex Deucher 							   RADEON_OUTPUT_CSC_BYPASS);
199291915260SDave Airlie 
1993eac4dff6SAlex Deucher 			subpixel_order = SubPixelHorizontalRGB;
1994eac4dff6SAlex Deucher 			connector->interlace_allowed = true;
1995eac4dff6SAlex Deucher 			if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
1996eac4dff6SAlex Deucher 				connector->doublescan_allowed = true;
1997eac4dff6SAlex Deucher 			else
1998eac4dff6SAlex Deucher 				connector->doublescan_allowed = false;
1999d629a3ceSAlex Deucher 			if (connector_type == DRM_MODE_CONNECTOR_DVII) {
2000d629a3ceSAlex Deucher 				radeon_connector->dac_load_detect = true;
2001e35755faSRob Clark 				drm_object_attach_property(&radeon_connector->base.base,
2002d629a3ceSAlex Deucher 							      rdev->mode_info.load_detect_property,
2003d629a3ceSAlex Deucher 							      1);
2004d629a3ceSAlex Deucher 			}
2005eac4dff6SAlex Deucher 			break;
2006eac4dff6SAlex Deucher 		case DRM_MODE_CONNECTOR_LVDS:
2007eac4dff6SAlex Deucher 		case DRM_MODE_CONNECTOR_eDP:
2008af0e31abSAndrzej Pietrasiewicz 			drm_connector_init_with_ddc(dev, &radeon_connector->base,
2009af0e31abSAndrzej Pietrasiewicz 						    &radeon_lvds_bridge_connector_funcs,
2010af0e31abSAndrzej Pietrasiewicz 						    connector_type,
2011af0e31abSAndrzej Pietrasiewicz 						    ddc);
2012855f5f1dSAlex Deucher 			drm_connector_helper_add(&radeon_connector->base,
2013855f5f1dSAlex Deucher 						 &radeon_dp_connector_helper_funcs);
2014e35755faSRob Clark 			drm_object_attach_property(&radeon_connector->base.base,
2015eac4dff6SAlex Deucher 						      dev->mode_config.scaling_mode_property,
2016eac4dff6SAlex Deucher 						      DRM_MODE_SCALE_FULLSCREEN);
2017eac4dff6SAlex Deucher 			subpixel_order = SubPixelHorizontalRGB;
2018eac4dff6SAlex Deucher 			connector->interlace_allowed = false;
2019eac4dff6SAlex Deucher 			connector->doublescan_allowed = false;
2020eac4dff6SAlex Deucher 			break;
2021eac4dff6SAlex Deucher 		}
2022eac4dff6SAlex Deucher 	} else {
2023771fe6b9SJerome Glisse 		switch (connector_type) {
2024771fe6b9SJerome Glisse 		case DRM_MODE_CONNECTOR_VGA:
2025771fe6b9SJerome Glisse 			if (i2c_bus->valid) {
2026f376b94fSAlex Deucher 				radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
2027771fe6b9SJerome Glisse 				if (!radeon_connector->ddc_bus)
2028a70882aaSAlex Deucher 					DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
2029af0e31abSAndrzej Pietrasiewicz 				else
2030af0e31abSAndrzej Pietrasiewicz 					ddc = &radeon_connector->ddc_bus->adapter;
2031771fe6b9SJerome Glisse 			}
2032af0e31abSAndrzej Pietrasiewicz 			drm_connector_init_with_ddc(dev, &radeon_connector->base,
2033af0e31abSAndrzej Pietrasiewicz 						    &radeon_vga_connector_funcs,
2034af0e31abSAndrzej Pietrasiewicz 						    connector_type,
2035af0e31abSAndrzej Pietrasiewicz 						    ddc);
2036af0e31abSAndrzej Pietrasiewicz 			drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
203735e4b7afSDave Airlie 			radeon_connector->dac_load_detect = true;
2038e35755faSRob Clark 			drm_object_attach_property(&radeon_connector->base.base,
2039445282dbSDave Airlie 						      rdev->mode_info.load_detect_property,
2040445282dbSDave Airlie 						      1);
2041da997620SAlex Deucher 			if (ASIC_IS_AVIVO(rdev))
2042da997620SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
2043da997620SAlex Deucher 							   dev->mode_config.scaling_mode_property,
2044da997620SAlex Deucher 							   DRM_MODE_SCALE_NONE);
2045643b1f56SAlex Deucher 			if (ASIC_IS_DCE5(rdev))
2046643b1f56SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
2047643b1f56SAlex Deucher 							   rdev->mode_info.output_csc_property,
2048643b1f56SAlex Deucher 							   RADEON_OUTPUT_CSC_BYPASS);
20492581afccSAlex Deucher 			/* no HPD on analog connectors */
20502581afccSAlex Deucher 			radeon_connector->hpd.hpd = RADEON_HPD_NONE;
2051c49948f4SAlex Deucher 			connector->interlace_allowed = true;
2052c49948f4SAlex Deucher 			connector->doublescan_allowed = true;
2053771fe6b9SJerome Glisse 			break;
2054771fe6b9SJerome Glisse 		case DRM_MODE_CONNECTOR_DVIA:
2055771fe6b9SJerome Glisse 			if (i2c_bus->valid) {
2056f376b94fSAlex Deucher 				radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
2057771fe6b9SJerome Glisse 				if (!radeon_connector->ddc_bus)
2058a70882aaSAlex Deucher 					DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
2059af0e31abSAndrzej Pietrasiewicz 				else
2060af0e31abSAndrzej Pietrasiewicz 					ddc = &radeon_connector->ddc_bus->adapter;
2061771fe6b9SJerome Glisse 			}
2062af0e31abSAndrzej Pietrasiewicz 			drm_connector_init_with_ddc(dev, &radeon_connector->base,
2063af0e31abSAndrzej Pietrasiewicz 						    &radeon_vga_connector_funcs,
2064af0e31abSAndrzej Pietrasiewicz 						    connector_type,
2065af0e31abSAndrzej Pietrasiewicz 						    ddc);
2066af0e31abSAndrzej Pietrasiewicz 			drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
206735e4b7afSDave Airlie 			radeon_connector->dac_load_detect = true;
2068e35755faSRob Clark 			drm_object_attach_property(&radeon_connector->base.base,
2069445282dbSDave Airlie 						      rdev->mode_info.load_detect_property,
2070445282dbSDave Airlie 						      1);
2071da997620SAlex Deucher 			if (ASIC_IS_AVIVO(rdev))
2072da997620SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
2073da997620SAlex Deucher 							   dev->mode_config.scaling_mode_property,
2074da997620SAlex Deucher 							   DRM_MODE_SCALE_NONE);
2075643b1f56SAlex Deucher 			if (ASIC_IS_DCE5(rdev))
2076643b1f56SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
2077643b1f56SAlex Deucher 							   rdev->mode_info.output_csc_property,
2078643b1f56SAlex Deucher 							   RADEON_OUTPUT_CSC_BYPASS);
20792581afccSAlex Deucher 			/* no HPD on analog connectors */
20802581afccSAlex Deucher 			radeon_connector->hpd.hpd = RADEON_HPD_NONE;
2081c49948f4SAlex Deucher 			connector->interlace_allowed = true;
2082c49948f4SAlex Deucher 			connector->doublescan_allowed = true;
2083771fe6b9SJerome Glisse 			break;
2084771fe6b9SJerome Glisse 		case DRM_MODE_CONNECTOR_DVII:
2085771fe6b9SJerome Glisse 		case DRM_MODE_CONNECTOR_DVID:
2086771fe6b9SJerome Glisse 			radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
2087771fe6b9SJerome Glisse 			if (!radeon_dig_connector)
2088771fe6b9SJerome Glisse 				goto failed;
2089771fe6b9SJerome Glisse 			radeon_dig_connector->igp_lane_info = igp_lane_info;
2090771fe6b9SJerome Glisse 			radeon_connector->con_priv = radeon_dig_connector;
2091771fe6b9SJerome Glisse 			if (i2c_bus->valid) {
2092f376b94fSAlex Deucher 				radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
2093771fe6b9SJerome Glisse 				if (!radeon_connector->ddc_bus)
2094a70882aaSAlex Deucher 					DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
2095af0e31abSAndrzej Pietrasiewicz 				else
2096af0e31abSAndrzej Pietrasiewicz 					ddc = &radeon_connector->ddc_bus->adapter;
2097771fe6b9SJerome Glisse 			}
2098af0e31abSAndrzej Pietrasiewicz 			drm_connector_init_with_ddc(dev, &radeon_connector->base,
2099af0e31abSAndrzej Pietrasiewicz 						    &radeon_dvi_connector_funcs,
2100af0e31abSAndrzej Pietrasiewicz 						    connector_type,
2101af0e31abSAndrzej Pietrasiewicz 						    ddc);
2102af0e31abSAndrzej Pietrasiewicz 			drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
2103771fe6b9SJerome Glisse 			subpixel_order = SubPixelHorizontalRGB;
2104e35755faSRob Clark 			drm_object_attach_property(&radeon_connector->base.base,
2105445282dbSDave Airlie 						      rdev->mode_info.coherent_mode_property,
2106445282dbSDave Airlie 						      1);
21075bccf5e3SMarius Gröger 			if (ASIC_IS_AVIVO(rdev)) {
2108e35755faSRob Clark 				drm_object_attach_property(&radeon_connector->base.base,
21095b1714d3SAlex Deucher 							      rdev->mode_info.underscan_property,
211056bec7c0SAlex Deucher 							      UNDERSCAN_OFF);
2111e35755faSRob Clark 				drm_object_attach_property(&radeon_connector->base.base,
21125bccf5e3SMarius Gröger 							      rdev->mode_info.underscan_hborder_property,
21135bccf5e3SMarius Gröger 							      0);
2114e35755faSRob Clark 				drm_object_attach_property(&radeon_connector->base.base,
21155bccf5e3SMarius Gröger 							      rdev->mode_info.underscan_vborder_property,
21165bccf5e3SMarius Gröger 							      0);
2117da997620SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
2118da997620SAlex Deucher 							   rdev->mode_info.dither_property,
2119da997620SAlex Deucher 							   RADEON_FMT_DITHER_DISABLE);
2120da997620SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
2121da997620SAlex Deucher 							   dev->mode_config.scaling_mode_property,
2122da997620SAlex Deucher 							   DRM_MODE_SCALE_NONE);
21235bccf5e3SMarius Gröger 			}
2124108dc8e8SAlex Deucher 			if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
21258666c076SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
21268666c076SAlex Deucher 							   rdev->mode_info.audio_property,
2127e31fadd3SAlex Deucher 							   RADEON_AUDIO_AUTO);
21287403c515SAlex Deucher 				radeon_connector->audio = RADEON_AUDIO_AUTO;
21298666c076SAlex Deucher 			}
2130390d0bbeSAlex Deucher 			if (connector_type == DRM_MODE_CONNECTOR_DVII) {
213135e4b7afSDave Airlie 				radeon_connector->dac_load_detect = true;
2132e35755faSRob Clark 				drm_object_attach_property(&radeon_connector->base.base,
2133445282dbSDave Airlie 							      rdev->mode_info.load_detect_property,
2134445282dbSDave Airlie 							      1);
2135390d0bbeSAlex Deucher 			}
2136643b1f56SAlex Deucher 			if (ASIC_IS_DCE5(rdev))
2137643b1f56SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
2138643b1f56SAlex Deucher 							   rdev->mode_info.output_csc_property,
2139643b1f56SAlex Deucher 							   RADEON_OUTPUT_CSC_BYPASS);
2140c49948f4SAlex Deucher 			connector->interlace_allowed = true;
2141c49948f4SAlex Deucher 			if (connector_type == DRM_MODE_CONNECTOR_DVII)
2142c49948f4SAlex Deucher 				connector->doublescan_allowed = true;
2143c49948f4SAlex Deucher 			else
2144c49948f4SAlex Deucher 				connector->doublescan_allowed = false;
2145771fe6b9SJerome Glisse 			break;
2146771fe6b9SJerome Glisse 		case DRM_MODE_CONNECTOR_HDMIA:
2147771fe6b9SJerome Glisse 		case DRM_MODE_CONNECTOR_HDMIB:
2148771fe6b9SJerome Glisse 			radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
2149771fe6b9SJerome Glisse 			if (!radeon_dig_connector)
2150771fe6b9SJerome Glisse 				goto failed;
2151771fe6b9SJerome Glisse 			radeon_dig_connector->igp_lane_info = igp_lane_info;
2152771fe6b9SJerome Glisse 			radeon_connector->con_priv = radeon_dig_connector;
2153771fe6b9SJerome Glisse 			if (i2c_bus->valid) {
2154f376b94fSAlex Deucher 				radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
2155771fe6b9SJerome Glisse 				if (!radeon_connector->ddc_bus)
2156a70882aaSAlex Deucher 					DRM_ERROR("HDMI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
2157af0e31abSAndrzej Pietrasiewicz 				else
2158af0e31abSAndrzej Pietrasiewicz 					ddc = &radeon_connector->ddc_bus->adapter;
2159771fe6b9SJerome Glisse 			}
2160af0e31abSAndrzej Pietrasiewicz 			drm_connector_init_with_ddc(dev, &radeon_connector->base,
2161af0e31abSAndrzej Pietrasiewicz 						    &radeon_dvi_connector_funcs,
2162af0e31abSAndrzej Pietrasiewicz 						    connector_type,
2163af0e31abSAndrzej Pietrasiewicz 						    ddc);
2164af0e31abSAndrzej Pietrasiewicz 			drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
2165e35755faSRob Clark 			drm_object_attach_property(&radeon_connector->base.base,
2166445282dbSDave Airlie 						      rdev->mode_info.coherent_mode_property,
2167445282dbSDave Airlie 						      1);
21685bccf5e3SMarius Gröger 			if (ASIC_IS_AVIVO(rdev)) {
2169e35755faSRob Clark 				drm_object_attach_property(&radeon_connector->base.base,
21705b1714d3SAlex Deucher 							      rdev->mode_info.underscan_property,
217156bec7c0SAlex Deucher 							      UNDERSCAN_OFF);
2172e35755faSRob Clark 				drm_object_attach_property(&radeon_connector->base.base,
21735bccf5e3SMarius Gröger 							      rdev->mode_info.underscan_hborder_property,
21745bccf5e3SMarius Gröger 							      0);
2175e35755faSRob Clark 				drm_object_attach_property(&radeon_connector->base.base,
21765bccf5e3SMarius Gröger 							      rdev->mode_info.underscan_vborder_property,
21775bccf5e3SMarius Gröger 							      0);
2178da997620SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
2179da997620SAlex Deucher 							   rdev->mode_info.dither_property,
2180da997620SAlex Deucher 							   RADEON_FMT_DITHER_DISABLE);
2181da997620SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
2182da997620SAlex Deucher 							   dev->mode_config.scaling_mode_property,
2183da997620SAlex Deucher 							   DRM_MODE_SCALE_NONE);
21845bccf5e3SMarius Gröger 			}
2185108dc8e8SAlex Deucher 			if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
21868666c076SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
21878666c076SAlex Deucher 							   rdev->mode_info.audio_property,
2188e31fadd3SAlex Deucher 							   RADEON_AUDIO_AUTO);
21897403c515SAlex Deucher 				radeon_connector->audio = RADEON_AUDIO_AUTO;
21908666c076SAlex Deucher 			}
2191643b1f56SAlex Deucher 			if (ASIC_IS_DCE5(rdev))
2192643b1f56SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
2193643b1f56SAlex Deucher 							   rdev->mode_info.output_csc_property,
2194643b1f56SAlex Deucher 							   RADEON_OUTPUT_CSC_BYPASS);
2195771fe6b9SJerome Glisse 			subpixel_order = SubPixelHorizontalRGB;
2196c49948f4SAlex Deucher 			connector->interlace_allowed = true;
2197c49948f4SAlex Deucher 			if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
2198c49948f4SAlex Deucher 				connector->doublescan_allowed = true;
2199c49948f4SAlex Deucher 			else
2200c49948f4SAlex Deucher 				connector->doublescan_allowed = false;
2201771fe6b9SJerome Glisse 			break;
2202771fe6b9SJerome Glisse 		case DRM_MODE_CONNECTOR_DisplayPort:
2203771fe6b9SJerome Glisse 			radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
2204771fe6b9SJerome Glisse 			if (!radeon_dig_connector)
2205771fe6b9SJerome Glisse 				goto failed;
2206771fe6b9SJerome Glisse 			radeon_dig_connector->igp_lane_info = igp_lane_info;
2207771fe6b9SJerome Glisse 			radeon_connector->con_priv = radeon_dig_connector;
2208390d0bbeSAlex Deucher 			if (i2c_bus->valid) {
2209f376b94fSAlex Deucher 				radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
2210af0e31abSAndrzej Pietrasiewicz 				if (radeon_connector->ddc_bus) {
2211496263bfSAlex Deucher 					has_aux = true;
2212af0e31abSAndrzej Pietrasiewicz 					ddc = &radeon_connector->ddc_bus->adapter;
2213af0e31abSAndrzej Pietrasiewicz 				} else {
2214a70882aaSAlex Deucher 					DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
2215771fe6b9SJerome Glisse 				}
2216af0e31abSAndrzej Pietrasiewicz 			}
2217af0e31abSAndrzej Pietrasiewicz 			drm_connector_init_with_ddc(dev, &radeon_connector->base,
2218af0e31abSAndrzej Pietrasiewicz 						    &radeon_dp_connector_funcs,
2219af0e31abSAndrzej Pietrasiewicz 						    connector_type,
2220af0e31abSAndrzej Pietrasiewicz 						    ddc);
2221af0e31abSAndrzej Pietrasiewicz 			drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs);
2222771fe6b9SJerome Glisse 			subpixel_order = SubPixelHorizontalRGB;
2223e35755faSRob Clark 			drm_object_attach_property(&radeon_connector->base.base,
2224390d0bbeSAlex Deucher 						      rdev->mode_info.coherent_mode_property,
2225390d0bbeSAlex Deucher 						      1);
22265bccf5e3SMarius Gröger 			if (ASIC_IS_AVIVO(rdev)) {
2227e35755faSRob Clark 				drm_object_attach_property(&radeon_connector->base.base,
22285b1714d3SAlex Deucher 							      rdev->mode_info.underscan_property,
222956bec7c0SAlex Deucher 							      UNDERSCAN_OFF);
2230e35755faSRob Clark 				drm_object_attach_property(&radeon_connector->base.base,
22315bccf5e3SMarius Gröger 							      rdev->mode_info.underscan_hborder_property,
22325bccf5e3SMarius Gröger 							      0);
2233e35755faSRob Clark 				drm_object_attach_property(&radeon_connector->base.base,
22345bccf5e3SMarius Gröger 							      rdev->mode_info.underscan_vborder_property,
22355bccf5e3SMarius Gröger 							      0);
2236da997620SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
2237da997620SAlex Deucher 							   rdev->mode_info.dither_property,
2238da997620SAlex Deucher 							   RADEON_FMT_DITHER_DISABLE);
2239da997620SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
2240da997620SAlex Deucher 							   dev->mode_config.scaling_mode_property,
2241da997620SAlex Deucher 							   DRM_MODE_SCALE_NONE);
22425bccf5e3SMarius Gröger 			}
2243108dc8e8SAlex Deucher 			if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
22448666c076SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
22458666c076SAlex Deucher 							   rdev->mode_info.audio_property,
2246e31fadd3SAlex Deucher 							   RADEON_AUDIO_AUTO);
22477403c515SAlex Deucher 				radeon_connector->audio = RADEON_AUDIO_AUTO;
22488666c076SAlex Deucher 			}
2249643b1f56SAlex Deucher 			if (ASIC_IS_DCE5(rdev))
2250643b1f56SAlex Deucher 				drm_object_attach_property(&radeon_connector->base.base,
2251643b1f56SAlex Deucher 							   rdev->mode_info.output_csc_property,
2252643b1f56SAlex Deucher 							   RADEON_OUTPUT_CSC_BYPASS);
2253c49948f4SAlex Deucher 			connector->interlace_allowed = true;
2254c49948f4SAlex Deucher 			/* in theory with a DP to VGA converter... */
2255c49948f4SAlex Deucher 			connector->doublescan_allowed = false;
2256771fe6b9SJerome Glisse 			break;
22573a5f4a21SAlex Deucher 		case DRM_MODE_CONNECTOR_eDP:
22583a5f4a21SAlex Deucher 			radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
22593a5f4a21SAlex Deucher 			if (!radeon_dig_connector)
22603a5f4a21SAlex Deucher 				goto failed;
22613a5f4a21SAlex Deucher 			radeon_dig_connector->igp_lane_info = igp_lane_info;
22623a5f4a21SAlex Deucher 			radeon_connector->con_priv = radeon_dig_connector;
22633a5f4a21SAlex Deucher 			if (i2c_bus->valid) {
2264379dfc25SAlex Deucher 				radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
2265af0e31abSAndrzej Pietrasiewicz 				if (radeon_connector->ddc_bus) {
2266496263bfSAlex Deucher 					has_aux = true;
2267af0e31abSAndrzej Pietrasiewicz 					ddc = &radeon_connector->ddc_bus->adapter;
2268af0e31abSAndrzej Pietrasiewicz 				} else {
22693a5f4a21SAlex Deucher 					DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
22703a5f4a21SAlex Deucher 				}
2271af0e31abSAndrzej Pietrasiewicz 			}
2272af0e31abSAndrzej Pietrasiewicz 			drm_connector_init_with_ddc(dev, &radeon_connector->base,
2273af0e31abSAndrzej Pietrasiewicz 						    &radeon_edp_connector_funcs,
2274af0e31abSAndrzej Pietrasiewicz 						    connector_type,
2275af0e31abSAndrzej Pietrasiewicz 						    ddc);
2276af0e31abSAndrzej Pietrasiewicz 			drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs);
2277e35755faSRob Clark 			drm_object_attach_property(&radeon_connector->base.base,
22783a5f4a21SAlex Deucher 						      dev->mode_config.scaling_mode_property,
22793a5f4a21SAlex Deucher 						      DRM_MODE_SCALE_FULLSCREEN);
22803a5f4a21SAlex Deucher 			subpixel_order = SubPixelHorizontalRGB;
22813a5f4a21SAlex Deucher 			connector->interlace_allowed = false;
22823a5f4a21SAlex Deucher 			connector->doublescan_allowed = false;
22833a5f4a21SAlex Deucher 			break;
2284771fe6b9SJerome Glisse 		case DRM_MODE_CONNECTOR_SVIDEO:
2285771fe6b9SJerome Glisse 		case DRM_MODE_CONNECTOR_Composite:
2286771fe6b9SJerome Glisse 		case DRM_MODE_CONNECTOR_9PinDIN:
2287af0e31abSAndrzej Pietrasiewicz 			drm_connector_init_with_ddc(dev, &radeon_connector->base,
2288af0e31abSAndrzej Pietrasiewicz 						    &radeon_tv_connector_funcs,
2289af0e31abSAndrzej Pietrasiewicz 						    connector_type,
2290af0e31abSAndrzej Pietrasiewicz 						    ddc);
22910b4c0f3fSDave Airlie 			drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
229235e4b7afSDave Airlie 			radeon_connector->dac_load_detect = true;
2293e35755faSRob Clark 			drm_object_attach_property(&radeon_connector->base.base,
2294445282dbSDave Airlie 						      rdev->mode_info.load_detect_property,
2295445282dbSDave Airlie 						      1);
2296e35755faSRob Clark 			drm_object_attach_property(&radeon_connector->base.base,
2297ed160143SAlex Deucher 						      rdev->mode_info.tv_std_property,
2298d79766faSAlex Deucher 						      radeon_atombios_get_tv_info(rdev));
22992581afccSAlex Deucher 			/* no HPD on analog connectors */
23002581afccSAlex Deucher 			radeon_connector->hpd.hpd = RADEON_HPD_NONE;
2301c49948f4SAlex Deucher 			connector->interlace_allowed = false;
2302c49948f4SAlex Deucher 			connector->doublescan_allowed = false;
2303771fe6b9SJerome Glisse 			break;
2304771fe6b9SJerome Glisse 		case DRM_MODE_CONNECTOR_LVDS:
2305771fe6b9SJerome Glisse 			radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
2306771fe6b9SJerome Glisse 			if (!radeon_dig_connector)
2307771fe6b9SJerome Glisse 				goto failed;
2308771fe6b9SJerome Glisse 			radeon_dig_connector->igp_lane_info = igp_lane_info;
2309771fe6b9SJerome Glisse 			radeon_connector->con_priv = radeon_dig_connector;
2310771fe6b9SJerome Glisse 			if (i2c_bus->valid) {
2311f376b94fSAlex Deucher 				radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
2312771fe6b9SJerome Glisse 				if (!radeon_connector->ddc_bus)
2313a70882aaSAlex Deucher 					DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
2314af0e31abSAndrzej Pietrasiewicz 				else
2315af0e31abSAndrzej Pietrasiewicz 					ddc = &radeon_connector->ddc_bus->adapter;
2316771fe6b9SJerome Glisse 			}
2317af0e31abSAndrzej Pietrasiewicz 			drm_connector_init_with_ddc(dev, &radeon_connector->base,
2318af0e31abSAndrzej Pietrasiewicz 						    &radeon_lvds_connector_funcs,
2319af0e31abSAndrzej Pietrasiewicz 						    connector_type,
2320af0e31abSAndrzej Pietrasiewicz 						    ddc);
2321af0e31abSAndrzej Pietrasiewicz 			drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
2322e35755faSRob Clark 			drm_object_attach_property(&radeon_connector->base.base,
2323445282dbSDave Airlie 						      dev->mode_config.scaling_mode_property,
2324445282dbSDave Airlie 						      DRM_MODE_SCALE_FULLSCREEN);
2325771fe6b9SJerome Glisse 			subpixel_order = SubPixelHorizontalRGB;
2326c49948f4SAlex Deucher 			connector->interlace_allowed = false;
2327c49948f4SAlex Deucher 			connector->doublescan_allowed = false;
2328771fe6b9SJerome Glisse 			break;
2329771fe6b9SJerome Glisse 		}
2330eac4dff6SAlex Deucher 	}
2331771fe6b9SJerome Glisse 
23322581afccSAlex Deucher 	if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
233314ff8d48SLyude 		if (i2c_bus->valid) {
233414ff8d48SLyude 			connector->polled = DRM_CONNECTOR_POLL_CONNECT |
233514ff8d48SLyude 			                    DRM_CONNECTOR_POLL_DISCONNECT;
233614ff8d48SLyude 		}
2337eb1f8e4fSDave Airlie 	} else
2338eb1f8e4fSDave Airlie 		connector->polled = DRM_CONNECTOR_POLL_HPD;
2339eb1f8e4fSDave Airlie 
2340771fe6b9SJerome Glisse 	connector->display_info.subpixel_order = subpixel_order;
234134ea3d38SThomas Wood 	drm_connector_register(connector);
2342496263bfSAlex Deucher 
2343496263bfSAlex Deucher 	if (has_aux)
2344496263bfSAlex Deucher 		radeon_dp_aux_init(radeon_connector);
2345496263bfSAlex Deucher 
2346771fe6b9SJerome Glisse 	return;
2347771fe6b9SJerome Glisse 
2348771fe6b9SJerome Glisse failed:
2349771fe6b9SJerome Glisse 	drm_connector_cleanup(connector);
2350771fe6b9SJerome Glisse 	kfree(connector);
2351771fe6b9SJerome Glisse }
2352771fe6b9SJerome Glisse 
2353771fe6b9SJerome Glisse void
radeon_add_legacy_connector(struct drm_device * dev,uint32_t connector_id,uint32_t supported_device,int connector_type,struct radeon_i2c_bus_rec * i2c_bus,uint16_t connector_object_id,struct radeon_hpd * hpd)2354771fe6b9SJerome Glisse radeon_add_legacy_connector(struct drm_device *dev,
2355771fe6b9SJerome Glisse 			    uint32_t connector_id,
2356771fe6b9SJerome Glisse 			    uint32_t supported_device,
2357771fe6b9SJerome Glisse 			    int connector_type,
2358b75fad06SAlex Deucher 			    struct radeon_i2c_bus_rec *i2c_bus,
2359eed45b30SAlex Deucher 			    uint16_t connector_object_id,
2360eed45b30SAlex Deucher 			    struct radeon_hpd *hpd)
2361771fe6b9SJerome Glisse {
2362445282dbSDave Airlie 	struct radeon_device *rdev = dev->dev_private;
2363771fe6b9SJerome Glisse 	struct drm_connector *connector;
2364771fe6b9SJerome Glisse 	struct radeon_connector *radeon_connector;
2365af0e31abSAndrzej Pietrasiewicz 	struct i2c_adapter *ddc = NULL;
2366771fe6b9SJerome Glisse 	uint32_t subpixel_order = SubPixelNone;
2367771fe6b9SJerome Glisse 
23684ce001abSDave Airlie 	if (connector_type == DRM_MODE_CONNECTOR_Unknown)
2369771fe6b9SJerome Glisse 		return;
2370771fe6b9SJerome Glisse 
2371cf4c12f9SAlex Deucher 	/* if the user selected tv=0 don't try and add the connector */
2372cf4c12f9SAlex Deucher 	if (((connector_type == DRM_MODE_CONNECTOR_SVIDEO) ||
2373cf4c12f9SAlex Deucher 	     (connector_type == DRM_MODE_CONNECTOR_Composite) ||
2374cf4c12f9SAlex Deucher 	     (connector_type == DRM_MODE_CONNECTOR_9PinDIN)) &&
2375cf4c12f9SAlex Deucher 	    (radeon_tv == 0))
2376cf4c12f9SAlex Deucher 		return;
2377cf4c12f9SAlex Deucher 
2378771fe6b9SJerome Glisse 	/* see if we already added it */
2379771fe6b9SJerome Glisse 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
2380771fe6b9SJerome Glisse 		radeon_connector = to_radeon_connector(connector);
2381771fe6b9SJerome Glisse 		if (radeon_connector->connector_id == connector_id) {
2382771fe6b9SJerome Glisse 			radeon_connector->devices |= supported_device;
2383771fe6b9SJerome Glisse 			return;
2384771fe6b9SJerome Glisse 		}
2385771fe6b9SJerome Glisse 	}
2386771fe6b9SJerome Glisse 
2387771fe6b9SJerome Glisse 	radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL);
2388771fe6b9SJerome Glisse 	if (!radeon_connector)
2389771fe6b9SJerome Glisse 		return;
2390771fe6b9SJerome Glisse 
2391771fe6b9SJerome Glisse 	connector = &radeon_connector->base;
2392771fe6b9SJerome Glisse 
2393771fe6b9SJerome Glisse 	radeon_connector->connector_id = connector_id;
2394771fe6b9SJerome Glisse 	radeon_connector->devices = supported_device;
2395b75fad06SAlex Deucher 	radeon_connector->connector_object_id = connector_object_id;
2396eed45b30SAlex Deucher 	radeon_connector->hpd = *hpd;
2397bc1c4dc3SAlex Deucher 
2398771fe6b9SJerome Glisse 	switch (connector_type) {
2399771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_VGA:
2400771fe6b9SJerome Glisse 		if (i2c_bus->valid) {
2401f376b94fSAlex Deucher 			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
2402771fe6b9SJerome Glisse 			if (!radeon_connector->ddc_bus)
2403a70882aaSAlex Deucher 				DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
2404af0e31abSAndrzej Pietrasiewicz 			else
2405af0e31abSAndrzej Pietrasiewicz 				ddc = &radeon_connector->ddc_bus->adapter;
2406771fe6b9SJerome Glisse 		}
2407af0e31abSAndrzej Pietrasiewicz 		drm_connector_init_with_ddc(dev, &radeon_connector->base,
2408af0e31abSAndrzej Pietrasiewicz 					    &radeon_vga_connector_funcs,
2409af0e31abSAndrzej Pietrasiewicz 					    connector_type,
2410af0e31abSAndrzej Pietrasiewicz 					    ddc);
2411af0e31abSAndrzej Pietrasiewicz 		drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
241235e4b7afSDave Airlie 		radeon_connector->dac_load_detect = true;
2413e35755faSRob Clark 		drm_object_attach_property(&radeon_connector->base.base,
2414445282dbSDave Airlie 					      rdev->mode_info.load_detect_property,
2415445282dbSDave Airlie 					      1);
24162581afccSAlex Deucher 		/* no HPD on analog connectors */
24172581afccSAlex Deucher 		radeon_connector->hpd.hpd = RADEON_HPD_NONE;
2418c49948f4SAlex Deucher 		connector->interlace_allowed = true;
2419c49948f4SAlex Deucher 		connector->doublescan_allowed = true;
2420771fe6b9SJerome Glisse 		break;
2421771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_DVIA:
2422771fe6b9SJerome Glisse 		if (i2c_bus->valid) {
2423f376b94fSAlex Deucher 			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
2424771fe6b9SJerome Glisse 			if (!radeon_connector->ddc_bus)
2425a70882aaSAlex Deucher 				DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
2426af0e31abSAndrzej Pietrasiewicz 			else
2427af0e31abSAndrzej Pietrasiewicz 				ddc = &radeon_connector->ddc_bus->adapter;
2428771fe6b9SJerome Glisse 		}
2429af0e31abSAndrzej Pietrasiewicz 		drm_connector_init_with_ddc(dev, &radeon_connector->base,
2430af0e31abSAndrzej Pietrasiewicz 					    &radeon_vga_connector_funcs,
2431af0e31abSAndrzej Pietrasiewicz 					    connector_type,
2432af0e31abSAndrzej Pietrasiewicz 					    ddc);
2433af0e31abSAndrzej Pietrasiewicz 		drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
243435e4b7afSDave Airlie 		radeon_connector->dac_load_detect = true;
2435e35755faSRob Clark 		drm_object_attach_property(&radeon_connector->base.base,
2436445282dbSDave Airlie 					      rdev->mode_info.load_detect_property,
2437445282dbSDave Airlie 					      1);
24382581afccSAlex Deucher 		/* no HPD on analog connectors */
24392581afccSAlex Deucher 		radeon_connector->hpd.hpd = RADEON_HPD_NONE;
2440c49948f4SAlex Deucher 		connector->interlace_allowed = true;
2441c49948f4SAlex Deucher 		connector->doublescan_allowed = true;
2442771fe6b9SJerome Glisse 		break;
2443771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_DVII:
2444771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_DVID:
2445771fe6b9SJerome Glisse 		if (i2c_bus->valid) {
2446f376b94fSAlex Deucher 			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
2447771fe6b9SJerome Glisse 			if (!radeon_connector->ddc_bus)
2448a70882aaSAlex Deucher 				DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
2449af0e31abSAndrzej Pietrasiewicz 			else
2450af0e31abSAndrzej Pietrasiewicz 				ddc = &radeon_connector->ddc_bus->adapter;
245168b3adb4SAlex Deucher 		}
2452af0e31abSAndrzej Pietrasiewicz 		drm_connector_init_with_ddc(dev, &radeon_connector->base,
2453af0e31abSAndrzej Pietrasiewicz 					    &radeon_dvi_connector_funcs,
2454af0e31abSAndrzej Pietrasiewicz 					    connector_type,
2455af0e31abSAndrzej Pietrasiewicz 					    ddc);
2456af0e31abSAndrzej Pietrasiewicz 		drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
245768b3adb4SAlex Deucher 		if (connector_type == DRM_MODE_CONNECTOR_DVII) {
245835e4b7afSDave Airlie 			radeon_connector->dac_load_detect = true;
2459e35755faSRob Clark 			drm_object_attach_property(&radeon_connector->base.base,
2460445282dbSDave Airlie 						      rdev->mode_info.load_detect_property,
2461445282dbSDave Airlie 						      1);
2462771fe6b9SJerome Glisse 		}
2463771fe6b9SJerome Glisse 		subpixel_order = SubPixelHorizontalRGB;
2464c49948f4SAlex Deucher 		connector->interlace_allowed = true;
2465c49948f4SAlex Deucher 		if (connector_type == DRM_MODE_CONNECTOR_DVII)
2466c49948f4SAlex Deucher 			connector->doublescan_allowed = true;
2467c49948f4SAlex Deucher 		else
2468c49948f4SAlex Deucher 			connector->doublescan_allowed = false;
2469771fe6b9SJerome Glisse 		break;
2470771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_SVIDEO:
2471771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_Composite:
2472771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_9PinDIN:
2473af0e31abSAndrzej Pietrasiewicz 		drm_connector_init_with_ddc(dev, &radeon_connector->base,
2474af0e31abSAndrzej Pietrasiewicz 					    &radeon_tv_connector_funcs,
2475af0e31abSAndrzej Pietrasiewicz 					    connector_type,
2476af0e31abSAndrzej Pietrasiewicz 					    ddc);
24770b4c0f3fSDave Airlie 		drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
247835e4b7afSDave Airlie 		radeon_connector->dac_load_detect = true;
24790beb81abSJerome Glisse 		/* RS400,RC410,RS480 chipset seems to report a lot
24800beb81abSJerome Glisse 		 * of false positive on load detect, we haven't yet
24810beb81abSJerome Glisse 		 * found a way to make load detect reliable on those
24820beb81abSJerome Glisse 		 * chipset, thus just disable it for TV.
24830beb81abSJerome Glisse 		 */
24840beb81abSJerome Glisse 		if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480)
24850beb81abSJerome Glisse 			radeon_connector->dac_load_detect = false;
2486e35755faSRob Clark 		drm_object_attach_property(&radeon_connector->base.base,
2487445282dbSDave Airlie 					      rdev->mode_info.load_detect_property,
2488624ab4f8SDave Airlie 					      radeon_connector->dac_load_detect);
2489e35755faSRob Clark 		drm_object_attach_property(&radeon_connector->base.base,
2490ed160143SAlex Deucher 					      rdev->mode_info.tv_std_property,
2491d79766faSAlex Deucher 					      radeon_combios_get_tv_info(rdev));
24922581afccSAlex Deucher 		/* no HPD on analog connectors */
24932581afccSAlex Deucher 		radeon_connector->hpd.hpd = RADEON_HPD_NONE;
2494c49948f4SAlex Deucher 		connector->interlace_allowed = false;
2495c49948f4SAlex Deucher 		connector->doublescan_allowed = false;
2496771fe6b9SJerome Glisse 		break;
2497771fe6b9SJerome Glisse 	case DRM_MODE_CONNECTOR_LVDS:
2498771fe6b9SJerome Glisse 		if (i2c_bus->valid) {
2499f376b94fSAlex Deucher 			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
2500771fe6b9SJerome Glisse 			if (!radeon_connector->ddc_bus)
2501a70882aaSAlex Deucher 				DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
2502af0e31abSAndrzej Pietrasiewicz 			else
2503af0e31abSAndrzej Pietrasiewicz 				ddc = &radeon_connector->ddc_bus->adapter;
2504771fe6b9SJerome Glisse 		}
2505af0e31abSAndrzej Pietrasiewicz 		drm_connector_init_with_ddc(dev, &radeon_connector->base,
2506af0e31abSAndrzej Pietrasiewicz 					    &radeon_lvds_connector_funcs,
2507af0e31abSAndrzej Pietrasiewicz 					    connector_type,
2508af0e31abSAndrzej Pietrasiewicz 					    ddc);
2509af0e31abSAndrzej Pietrasiewicz 		drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
2510e35755faSRob Clark 		drm_object_attach_property(&radeon_connector->base.base,
2511445282dbSDave Airlie 					      dev->mode_config.scaling_mode_property,
2512445282dbSDave Airlie 					      DRM_MODE_SCALE_FULLSCREEN);
2513771fe6b9SJerome Glisse 		subpixel_order = SubPixelHorizontalRGB;
2514c49948f4SAlex Deucher 		connector->interlace_allowed = false;
2515c49948f4SAlex Deucher 		connector->doublescan_allowed = false;
2516771fe6b9SJerome Glisse 		break;
2517771fe6b9SJerome Glisse 	}
2518771fe6b9SJerome Glisse 
25192581afccSAlex Deucher 	if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
252014ff8d48SLyude 		if (i2c_bus->valid) {
252114ff8d48SLyude 			connector->polled = DRM_CONNECTOR_POLL_CONNECT |
252214ff8d48SLyude 			                    DRM_CONNECTOR_POLL_DISCONNECT;
252314ff8d48SLyude 		}
2524eb1f8e4fSDave Airlie 	} else
2525eb1f8e4fSDave Airlie 		connector->polled = DRM_CONNECTOR_POLL_HPD;
252614ff8d48SLyude 
2527771fe6b9SJerome Glisse 	connector->display_info.subpixel_order = subpixel_order;
252834ea3d38SThomas Wood 	drm_connector_register(connector);
2529771fe6b9SJerome Glisse }
2530