xref: /dflybsd-src/sys/dev/drm/amd/amdgpu/amdgpu_connectors.c (revision b843c749addef9340ee7d4e250b09fdd492602a1)
1*b843c749SSergey Zigachev /*
2*b843c749SSergey Zigachev  * Copyright 2007-8 Advanced Micro Devices, Inc.
3*b843c749SSergey Zigachev  * Copyright 2008 Red Hat Inc.
4*b843c749SSergey Zigachev  *
5*b843c749SSergey Zigachev  * Permission is hereby granted, free of charge, to any person obtaining a
6*b843c749SSergey Zigachev  * copy of this software and associated documentation files (the "Software"),
7*b843c749SSergey Zigachev  * to deal in the Software without restriction, including without limitation
8*b843c749SSergey Zigachev  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*b843c749SSergey Zigachev  * and/or sell copies of the Software, and to permit persons to whom the
10*b843c749SSergey Zigachev  * Software is furnished to do so, subject to the following conditions:
11*b843c749SSergey Zigachev  *
12*b843c749SSergey Zigachev  * The above copyright notice and this permission notice shall be included in
13*b843c749SSergey Zigachev  * all copies or substantial portions of the Software.
14*b843c749SSergey Zigachev  *
15*b843c749SSergey Zigachev  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*b843c749SSergey Zigachev  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*b843c749SSergey Zigachev  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*b843c749SSergey Zigachev  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19*b843c749SSergey Zigachev  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20*b843c749SSergey Zigachev  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21*b843c749SSergey Zigachev  * OTHER DEALINGS IN THE SOFTWARE.
22*b843c749SSergey Zigachev  *
23*b843c749SSergey Zigachev  * Authors: Dave Airlie
24*b843c749SSergey Zigachev  *          Alex Deucher
25*b843c749SSergey Zigachev  */
26*b843c749SSergey Zigachev #include <drm/drmP.h>
27*b843c749SSergey Zigachev #include <drm/drm_edid.h>
28*b843c749SSergey Zigachev #include <drm/drm_crtc_helper.h>
29*b843c749SSergey Zigachev #include <drm/drm_fb_helper.h>
30*b843c749SSergey Zigachev #include <drm/amdgpu_drm.h>
31*b843c749SSergey Zigachev #include "amdgpu.h"
32*b843c749SSergey Zigachev #include "atom.h"
33*b843c749SSergey Zigachev #include "atombios_encoders.h"
34*b843c749SSergey Zigachev #include "atombios_dp.h"
35*b843c749SSergey Zigachev #include "amdgpu_connectors.h"
36*b843c749SSergey Zigachev #include "amdgpu_i2c.h"
37*b843c749SSergey Zigachev 
38*b843c749SSergey Zigachev #include <linux/pm_runtime.h>
39*b843c749SSergey Zigachev 
40*b843c749SSergey Zigachev void amdgpu_connector_hotplug(struct drm_connector *connector)
41*b843c749SSergey Zigachev {
42*b843c749SSergey Zigachev 	struct drm_device *dev = connector->dev;
43*b843c749SSergey Zigachev 	struct amdgpu_device *adev = dev->dev_private;
44*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
45*b843c749SSergey Zigachev 
46*b843c749SSergey Zigachev 	/* bail if the connector does not have hpd pin, e.g.,
47*b843c749SSergey Zigachev 	 * VGA, TV, etc.
48*b843c749SSergey Zigachev 	 */
49*b843c749SSergey Zigachev 	if (amdgpu_connector->hpd.hpd == AMDGPU_HPD_NONE)
50*b843c749SSergey Zigachev 		return;
51*b843c749SSergey Zigachev 
52*b843c749SSergey Zigachev 	amdgpu_display_hpd_set_polarity(adev, amdgpu_connector->hpd.hpd);
53*b843c749SSergey Zigachev 
54*b843c749SSergey Zigachev 	/* if the connector is already off, don't turn it back on */
55*b843c749SSergey Zigachev 	if (connector->dpms != DRM_MODE_DPMS_ON)
56*b843c749SSergey Zigachev 		return;
57*b843c749SSergey Zigachev 
58*b843c749SSergey Zigachev 	/* just deal with DP (not eDP) here. */
59*b843c749SSergey Zigachev 	if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
60*b843c749SSergey Zigachev 		struct amdgpu_connector_atom_dig *dig_connector =
61*b843c749SSergey Zigachev 			amdgpu_connector->con_priv;
62*b843c749SSergey Zigachev 
63*b843c749SSergey Zigachev 		/* if existing sink type was not DP no need to retrain */
64*b843c749SSergey Zigachev 		if (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_DISPLAYPORT)
65*b843c749SSergey Zigachev 			return;
66*b843c749SSergey Zigachev 
67*b843c749SSergey Zigachev 		/* first get sink type as it may be reset after (un)plug */
68*b843c749SSergey Zigachev 		dig_connector->dp_sink_type = amdgpu_atombios_dp_get_sinktype(amdgpu_connector);
69*b843c749SSergey Zigachev 		/* don't do anything if sink is not display port, i.e.,
70*b843c749SSergey Zigachev 		 * passive dp->(dvi|hdmi) adaptor
71*b843c749SSergey Zigachev 		 */
72*b843c749SSergey Zigachev 		if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT &&
73*b843c749SSergey Zigachev 		    amdgpu_display_hpd_sense(adev, amdgpu_connector->hpd.hpd) &&
74*b843c749SSergey Zigachev 		    amdgpu_atombios_dp_needs_link_train(amdgpu_connector)) {
75*b843c749SSergey Zigachev 			/* Don't start link training before we have the DPCD */
76*b843c749SSergey Zigachev 			if (amdgpu_atombios_dp_get_dpcd(amdgpu_connector))
77*b843c749SSergey Zigachev 				return;
78*b843c749SSergey Zigachev 
79*b843c749SSergey Zigachev 			/* Turn the connector off and back on immediately, which
80*b843c749SSergey Zigachev 			 * will trigger link training
81*b843c749SSergey Zigachev 			 */
82*b843c749SSergey Zigachev 			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
83*b843c749SSergey Zigachev 			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
84*b843c749SSergey Zigachev 		}
85*b843c749SSergey Zigachev 	}
86*b843c749SSergey Zigachev }
87*b843c749SSergey Zigachev 
88*b843c749SSergey Zigachev static void amdgpu_connector_property_change_mode(struct drm_encoder *encoder)
89*b843c749SSergey Zigachev {
90*b843c749SSergey Zigachev 	struct drm_crtc *crtc = encoder->crtc;
91*b843c749SSergey Zigachev 
92*b843c749SSergey Zigachev 	if (crtc && crtc->enabled) {
93*b843c749SSergey Zigachev 		drm_crtc_helper_set_mode(crtc, &crtc->mode,
94*b843c749SSergey Zigachev 					 crtc->x, crtc->y, crtc->primary->fb);
95*b843c749SSergey Zigachev 	}
96*b843c749SSergey Zigachev }
97*b843c749SSergey Zigachev 
98*b843c749SSergey Zigachev int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
99*b843c749SSergey Zigachev {
100*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
101*b843c749SSergey Zigachev 	struct amdgpu_connector_atom_dig *dig_connector;
102*b843c749SSergey Zigachev 	int bpc = 8;
103*b843c749SSergey Zigachev 	unsigned mode_clock, max_tmds_clock;
104*b843c749SSergey Zigachev 
105*b843c749SSergey Zigachev 	switch (connector->connector_type) {
106*b843c749SSergey Zigachev 	case DRM_MODE_CONNECTOR_DVII:
107*b843c749SSergey Zigachev 	case DRM_MODE_CONNECTOR_HDMIB:
108*b843c749SSergey Zigachev 		if (amdgpu_connector->use_digital) {
109*b843c749SSergey Zigachev 			if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
110*b843c749SSergey Zigachev 				if (connector->display_info.bpc)
111*b843c749SSergey Zigachev 					bpc = connector->display_info.bpc;
112*b843c749SSergey Zigachev 			}
113*b843c749SSergey Zigachev 		}
114*b843c749SSergey Zigachev 		break;
115*b843c749SSergey Zigachev 	case DRM_MODE_CONNECTOR_DVID:
116*b843c749SSergey Zigachev 	case DRM_MODE_CONNECTOR_HDMIA:
117*b843c749SSergey Zigachev 		if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
118*b843c749SSergey Zigachev 			if (connector->display_info.bpc)
119*b843c749SSergey Zigachev 				bpc = connector->display_info.bpc;
120*b843c749SSergey Zigachev 		}
121*b843c749SSergey Zigachev 		break;
122*b843c749SSergey Zigachev 	case DRM_MODE_CONNECTOR_DisplayPort:
123*b843c749SSergey Zigachev 		dig_connector = amdgpu_connector->con_priv;
124*b843c749SSergey Zigachev 		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
125*b843c749SSergey Zigachev 		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) ||
126*b843c749SSergey Zigachev 		    drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
127*b843c749SSergey Zigachev 			if (connector->display_info.bpc)
128*b843c749SSergey Zigachev 				bpc = connector->display_info.bpc;
129*b843c749SSergey Zigachev 		}
130*b843c749SSergey Zigachev 		break;
131*b843c749SSergey Zigachev 	case DRM_MODE_CONNECTOR_eDP:
132*b843c749SSergey Zigachev 	case DRM_MODE_CONNECTOR_LVDS:
133*b843c749SSergey Zigachev 		if (connector->display_info.bpc)
134*b843c749SSergey Zigachev 			bpc = connector->display_info.bpc;
135*b843c749SSergey Zigachev 		else {
136*b843c749SSergey Zigachev 			const struct drm_connector_helper_funcs *connector_funcs =
137*b843c749SSergey Zigachev 				connector->helper_private;
138*b843c749SSergey Zigachev 			struct drm_encoder *encoder = connector_funcs->best_encoder(connector);
139*b843c749SSergey Zigachev 			struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
140*b843c749SSergey Zigachev 			struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
141*b843c749SSergey Zigachev 
142*b843c749SSergey Zigachev 			if (dig->lcd_misc & ATOM_PANEL_MISC_V13_6BIT_PER_COLOR)
143*b843c749SSergey Zigachev 				bpc = 6;
144*b843c749SSergey Zigachev 			else if (dig->lcd_misc & ATOM_PANEL_MISC_V13_8BIT_PER_COLOR)
145*b843c749SSergey Zigachev 				bpc = 8;
146*b843c749SSergey Zigachev 		}
147*b843c749SSergey Zigachev 		break;
148*b843c749SSergey Zigachev 	}
149*b843c749SSergey Zigachev 
150*b843c749SSergey Zigachev 	if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
151*b843c749SSergey Zigachev 		/*
152*b843c749SSergey Zigachev 		 * Pre DCE-8 hw can't handle > 12 bpc, and more than 12 bpc doesn't make
153*b843c749SSergey Zigachev 		 * much sense without support for > 12 bpc framebuffers. RGB 4:4:4 at
154*b843c749SSergey Zigachev 		 * 12 bpc is always supported on hdmi deep color sinks, as this is
155*b843c749SSergey Zigachev 		 * required by the HDMI-1.3 spec. Clamp to a safe 12 bpc maximum.
156*b843c749SSergey Zigachev 		 */
157*b843c749SSergey Zigachev 		if (bpc > 12) {
158*b843c749SSergey Zigachev 			DRM_DEBUG("%s: HDMI deep color %d bpc unsupported. Using 12 bpc.\n",
159*b843c749SSergey Zigachev 				  connector->name, bpc);
160*b843c749SSergey Zigachev 			bpc = 12;
161*b843c749SSergey Zigachev 		}
162*b843c749SSergey Zigachev 
163*b843c749SSergey Zigachev 		/* Any defined maximum tmds clock limit we must not exceed? */
164*b843c749SSergey Zigachev 		if (connector->display_info.max_tmds_clock > 0) {
165*b843c749SSergey Zigachev 			/* mode_clock is clock in kHz for mode to be modeset on this connector */
166*b843c749SSergey Zigachev 			mode_clock = amdgpu_connector->pixelclock_for_modeset;
167*b843c749SSergey Zigachev 
168*b843c749SSergey Zigachev 			/* Maximum allowable input clock in kHz */
169*b843c749SSergey Zigachev 			max_tmds_clock = connector->display_info.max_tmds_clock;
170*b843c749SSergey Zigachev 
171*b843c749SSergey Zigachev 			DRM_DEBUG("%s: hdmi mode dotclock %d kHz, max tmds input clock %d kHz.\n",
172*b843c749SSergey Zigachev 				  connector->name, mode_clock, max_tmds_clock);
173*b843c749SSergey Zigachev 
174*b843c749SSergey Zigachev 			/* Check if bpc is within clock limit. Try to degrade gracefully otherwise */
175*b843c749SSergey Zigachev 			if ((bpc == 12) && (mode_clock * 3/2 > max_tmds_clock)) {
176*b843c749SSergey Zigachev 				if ((connector->display_info.edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30) &&
177*b843c749SSergey Zigachev 				    (mode_clock * 5/4 <= max_tmds_clock))
178*b843c749SSergey Zigachev 					bpc = 10;
179*b843c749SSergey Zigachev 				else
180*b843c749SSergey Zigachev 					bpc = 8;
181*b843c749SSergey Zigachev 
182*b843c749SSergey Zigachev 				DRM_DEBUG("%s: HDMI deep color 12 bpc exceeds max tmds clock. Using %d bpc.\n",
183*b843c749SSergey Zigachev 					  connector->name, bpc);
184*b843c749SSergey Zigachev 			}
185*b843c749SSergey Zigachev 
186*b843c749SSergey Zigachev 			if ((bpc == 10) && (mode_clock * 5/4 > max_tmds_clock)) {
187*b843c749SSergey Zigachev 				bpc = 8;
188*b843c749SSergey Zigachev 				DRM_DEBUG("%s: HDMI deep color 10 bpc exceeds max tmds clock. Using %d bpc.\n",
189*b843c749SSergey Zigachev 					  connector->name, bpc);
190*b843c749SSergey Zigachev 			}
191*b843c749SSergey Zigachev 		} else if (bpc > 8) {
192*b843c749SSergey Zigachev 			/* max_tmds_clock missing, but hdmi spec mandates it for deep color. */
193*b843c749SSergey Zigachev 			DRM_DEBUG("%s: Required max tmds clock for HDMI deep color missing. Using 8 bpc.\n",
194*b843c749SSergey Zigachev 				  connector->name);
195*b843c749SSergey Zigachev 			bpc = 8;
196*b843c749SSergey Zigachev 		}
197*b843c749SSergey Zigachev 	}
198*b843c749SSergey Zigachev 
199*b843c749SSergey Zigachev 	if ((amdgpu_deep_color == 0) && (bpc > 8)) {
200*b843c749SSergey Zigachev 		DRM_DEBUG("%s: Deep color disabled. Set amdgpu module param deep_color=1 to enable.\n",
201*b843c749SSergey Zigachev 			  connector->name);
202*b843c749SSergey Zigachev 		bpc = 8;
203*b843c749SSergey Zigachev 	}
204*b843c749SSergey Zigachev 
205*b843c749SSergey Zigachev 	DRM_DEBUG("%s: Display bpc=%d, returned bpc=%d\n",
206*b843c749SSergey Zigachev 		  connector->name, connector->display_info.bpc, bpc);
207*b843c749SSergey Zigachev 
208*b843c749SSergey Zigachev 	return bpc;
209*b843c749SSergey Zigachev }
210*b843c749SSergey Zigachev 
211*b843c749SSergey Zigachev static void
212*b843c749SSergey Zigachev amdgpu_connector_update_scratch_regs(struct drm_connector *connector,
213*b843c749SSergey Zigachev 				      enum drm_connector_status status)
214*b843c749SSergey Zigachev {
215*b843c749SSergey Zigachev 	struct drm_encoder *best_encoder;
216*b843c749SSergey Zigachev 	struct drm_encoder *encoder;
217*b843c749SSergey Zigachev 	const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
218*b843c749SSergey Zigachev 	bool connected;
219*b843c749SSergey Zigachev 	int i;
220*b843c749SSergey Zigachev 
221*b843c749SSergey Zigachev 	best_encoder = connector_funcs->best_encoder(connector);
222*b843c749SSergey Zigachev 
223*b843c749SSergey Zigachev 	drm_connector_for_each_possible_encoder(connector, encoder, i) {
224*b843c749SSergey Zigachev 		if ((encoder == best_encoder) && (status == connector_status_connected))
225*b843c749SSergey Zigachev 			connected = true;
226*b843c749SSergey Zigachev 		else
227*b843c749SSergey Zigachev 			connected = false;
228*b843c749SSergey Zigachev 
229*b843c749SSergey Zigachev 		amdgpu_atombios_encoder_set_bios_scratch_regs(connector, encoder, connected);
230*b843c749SSergey Zigachev 	}
231*b843c749SSergey Zigachev }
232*b843c749SSergey Zigachev 
233*b843c749SSergey Zigachev static struct drm_encoder *
234*b843c749SSergey Zigachev amdgpu_connector_find_encoder(struct drm_connector *connector,
235*b843c749SSergey Zigachev 			       int encoder_type)
236*b843c749SSergey Zigachev {
237*b843c749SSergey Zigachev 	struct drm_encoder *encoder;
238*b843c749SSergey Zigachev 	int i;
239*b843c749SSergey Zigachev 
240*b843c749SSergey Zigachev 	drm_connector_for_each_possible_encoder(connector, encoder, i) {
241*b843c749SSergey Zigachev 		if (encoder->encoder_type == encoder_type)
242*b843c749SSergey Zigachev 			return encoder;
243*b843c749SSergey Zigachev 	}
244*b843c749SSergey Zigachev 
245*b843c749SSergey Zigachev 	return NULL;
246*b843c749SSergey Zigachev }
247*b843c749SSergey Zigachev 
248*b843c749SSergey Zigachev struct edid *amdgpu_connector_edid(struct drm_connector *connector)
249*b843c749SSergey Zigachev {
250*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
251*b843c749SSergey Zigachev 	struct drm_property_blob *edid_blob = connector->edid_blob_ptr;
252*b843c749SSergey Zigachev 
253*b843c749SSergey Zigachev 	if (amdgpu_connector->edid) {
254*b843c749SSergey Zigachev 		return amdgpu_connector->edid;
255*b843c749SSergey Zigachev 	} else if (edid_blob) {
256*b843c749SSergey Zigachev 		struct edid *edid = kmemdup(edid_blob->data, edid_blob->length, GFP_KERNEL);
257*b843c749SSergey Zigachev 		if (edid)
258*b843c749SSergey Zigachev 			amdgpu_connector->edid = edid;
259*b843c749SSergey Zigachev 	}
260*b843c749SSergey Zigachev 	return amdgpu_connector->edid;
261*b843c749SSergey Zigachev }
262*b843c749SSergey Zigachev 
263*b843c749SSergey Zigachev static struct edid *
264*b843c749SSergey Zigachev amdgpu_connector_get_hardcoded_edid(struct amdgpu_device *adev)
265*b843c749SSergey Zigachev {
266*b843c749SSergey Zigachev 	struct edid *edid;
267*b843c749SSergey Zigachev 
268*b843c749SSergey Zigachev 	if (adev->mode_info.bios_hardcoded_edid) {
269*b843c749SSergey Zigachev 		edid = kmalloc(adev->mode_info.bios_hardcoded_edid_size, GFP_KERNEL);
270*b843c749SSergey Zigachev 		if (edid) {
271*b843c749SSergey Zigachev 			memcpy((unsigned char *)edid,
272*b843c749SSergey Zigachev 			       (unsigned char *)adev->mode_info.bios_hardcoded_edid,
273*b843c749SSergey Zigachev 			       adev->mode_info.bios_hardcoded_edid_size);
274*b843c749SSergey Zigachev 			return edid;
275*b843c749SSergey Zigachev 		}
276*b843c749SSergey Zigachev 	}
277*b843c749SSergey Zigachev 	return NULL;
278*b843c749SSergey Zigachev }
279*b843c749SSergey Zigachev 
280*b843c749SSergey Zigachev static void amdgpu_connector_get_edid(struct drm_connector *connector)
281*b843c749SSergey Zigachev {
282*b843c749SSergey Zigachev 	struct drm_device *dev = connector->dev;
283*b843c749SSergey Zigachev 	struct amdgpu_device *adev = dev->dev_private;
284*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
285*b843c749SSergey Zigachev 
286*b843c749SSergey Zigachev 	if (amdgpu_connector->edid)
287*b843c749SSergey Zigachev 		return;
288*b843c749SSergey Zigachev 
289*b843c749SSergey Zigachev 	/* on hw with routers, select right port */
290*b843c749SSergey Zigachev 	if (amdgpu_connector->router.ddc_valid)
291*b843c749SSergey Zigachev 		amdgpu_i2c_router_select_ddc_port(amdgpu_connector);
292*b843c749SSergey Zigachev 
293*b843c749SSergey Zigachev 	if ((amdgpu_connector_encoder_get_dp_bridge_encoder_id(connector) !=
294*b843c749SSergey Zigachev 	     ENCODER_OBJECT_ID_NONE) &&
295*b843c749SSergey Zigachev 	    amdgpu_connector->ddc_bus->has_aux) {
296*b843c749SSergey Zigachev 		amdgpu_connector->edid = drm_get_edid(connector,
297*b843c749SSergey Zigachev 						      &amdgpu_connector->ddc_bus->aux.ddc);
298*b843c749SSergey Zigachev 	} else if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
299*b843c749SSergey Zigachev 		   (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
300*b843c749SSergey Zigachev 		struct amdgpu_connector_atom_dig *dig = amdgpu_connector->con_priv;
301*b843c749SSergey Zigachev 
302*b843c749SSergey Zigachev 		if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
303*b843c749SSergey Zigachev 		     dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) &&
304*b843c749SSergey Zigachev 		    amdgpu_connector->ddc_bus->has_aux)
305*b843c749SSergey Zigachev 			amdgpu_connector->edid = drm_get_edid(connector,
306*b843c749SSergey Zigachev 							      &amdgpu_connector->ddc_bus->aux.ddc);
307*b843c749SSergey Zigachev 		else if (amdgpu_connector->ddc_bus)
308*b843c749SSergey Zigachev 			amdgpu_connector->edid = drm_get_edid(connector,
309*b843c749SSergey Zigachev 							      &amdgpu_connector->ddc_bus->adapter);
310*b843c749SSergey Zigachev 	} else if (amdgpu_connector->ddc_bus) {
311*b843c749SSergey Zigachev 		amdgpu_connector->edid = drm_get_edid(connector,
312*b843c749SSergey Zigachev 						      &amdgpu_connector->ddc_bus->adapter);
313*b843c749SSergey Zigachev 	}
314*b843c749SSergey Zigachev 
315*b843c749SSergey Zigachev 	if (!amdgpu_connector->edid) {
316*b843c749SSergey Zigachev 		/* some laptops provide a hardcoded edid in rom for LCDs */
317*b843c749SSergey Zigachev 		if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) ||
318*b843c749SSergey Zigachev 		     (connector->connector_type == DRM_MODE_CONNECTOR_eDP)))
319*b843c749SSergey Zigachev 			amdgpu_connector->edid = amdgpu_connector_get_hardcoded_edid(adev);
320*b843c749SSergey Zigachev 	}
321*b843c749SSergey Zigachev }
322*b843c749SSergey Zigachev 
323*b843c749SSergey Zigachev static void amdgpu_connector_free_edid(struct drm_connector *connector)
324*b843c749SSergey Zigachev {
325*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
326*b843c749SSergey Zigachev 
327*b843c749SSergey Zigachev 	kfree(amdgpu_connector->edid);
328*b843c749SSergey Zigachev 	amdgpu_connector->edid = NULL;
329*b843c749SSergey Zigachev }
330*b843c749SSergey Zigachev 
331*b843c749SSergey Zigachev static int amdgpu_connector_ddc_get_modes(struct drm_connector *connector)
332*b843c749SSergey Zigachev {
333*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
334*b843c749SSergey Zigachev 	int ret;
335*b843c749SSergey Zigachev 
336*b843c749SSergey Zigachev 	if (amdgpu_connector->edid) {
337*b843c749SSergey Zigachev 		drm_connector_update_edid_property(connector, amdgpu_connector->edid);
338*b843c749SSergey Zigachev 		ret = drm_add_edid_modes(connector, amdgpu_connector->edid);
339*b843c749SSergey Zigachev 		return ret;
340*b843c749SSergey Zigachev 	}
341*b843c749SSergey Zigachev 	drm_connector_update_edid_property(connector, NULL);
342*b843c749SSergey Zigachev 	return 0;
343*b843c749SSergey Zigachev }
344*b843c749SSergey Zigachev 
345*b843c749SSergey Zigachev static struct drm_encoder *
346*b843c749SSergey Zigachev amdgpu_connector_best_single_encoder(struct drm_connector *connector)
347*b843c749SSergey Zigachev {
348*b843c749SSergey Zigachev 	struct drm_encoder *encoder;
349*b843c749SSergey Zigachev 	int i;
350*b843c749SSergey Zigachev 
351*b843c749SSergey Zigachev 	/* pick the first one */
352*b843c749SSergey Zigachev 	drm_connector_for_each_possible_encoder(connector, encoder, i)
353*b843c749SSergey Zigachev 		return encoder;
354*b843c749SSergey Zigachev 
355*b843c749SSergey Zigachev 	return NULL;
356*b843c749SSergey Zigachev }
357*b843c749SSergey Zigachev 
358*b843c749SSergey Zigachev static void amdgpu_get_native_mode(struct drm_connector *connector)
359*b843c749SSergey Zigachev {
360*b843c749SSergey Zigachev 	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
361*b843c749SSergey Zigachev 	struct amdgpu_encoder *amdgpu_encoder;
362*b843c749SSergey Zigachev 
363*b843c749SSergey Zigachev 	if (encoder == NULL)
364*b843c749SSergey Zigachev 		return;
365*b843c749SSergey Zigachev 
366*b843c749SSergey Zigachev 	amdgpu_encoder = to_amdgpu_encoder(encoder);
367*b843c749SSergey Zigachev 
368*b843c749SSergey Zigachev 	if (!list_empty(&connector->probed_modes)) {
369*b843c749SSergey Zigachev 		struct drm_display_mode *preferred_mode =
370*b843c749SSergey Zigachev 			list_first_entry(&connector->probed_modes,
371*b843c749SSergey Zigachev 					 struct drm_display_mode, head);
372*b843c749SSergey Zigachev 
373*b843c749SSergey Zigachev 		amdgpu_encoder->native_mode = *preferred_mode;
374*b843c749SSergey Zigachev 	} else {
375*b843c749SSergey Zigachev 		amdgpu_encoder->native_mode.clock = 0;
376*b843c749SSergey Zigachev 	}
377*b843c749SSergey Zigachev }
378*b843c749SSergey Zigachev 
379*b843c749SSergey Zigachev static struct drm_display_mode *
380*b843c749SSergey Zigachev amdgpu_connector_lcd_native_mode(struct drm_encoder *encoder)
381*b843c749SSergey Zigachev {
382*b843c749SSergey Zigachev 	struct drm_device *dev = encoder->dev;
383*b843c749SSergey Zigachev 	struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
384*b843c749SSergey Zigachev 	struct drm_display_mode *mode = NULL;
385*b843c749SSergey Zigachev 	struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
386*b843c749SSergey Zigachev 
387*b843c749SSergey Zigachev 	if (native_mode->hdisplay != 0 &&
388*b843c749SSergey Zigachev 	    native_mode->vdisplay != 0 &&
389*b843c749SSergey Zigachev 	    native_mode->clock != 0) {
390*b843c749SSergey Zigachev 		mode = drm_mode_duplicate(dev, native_mode);
391*b843c749SSergey Zigachev 		mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
392*b843c749SSergey Zigachev 		drm_mode_set_name(mode);
393*b843c749SSergey Zigachev 
394*b843c749SSergey Zigachev 		DRM_DEBUG_KMS("Adding native panel mode %s\n", mode->name);
395*b843c749SSergey Zigachev 	} else if (native_mode->hdisplay != 0 &&
396*b843c749SSergey Zigachev 		   native_mode->vdisplay != 0) {
397*b843c749SSergey Zigachev 		/* mac laptops without an edid */
398*b843c749SSergey Zigachev 		/* Note that this is not necessarily the exact panel mode,
399*b843c749SSergey Zigachev 		 * but an approximation based on the cvt formula.  For these
400*b843c749SSergey Zigachev 		 * systems we should ideally read the mode info out of the
401*b843c749SSergey Zigachev 		 * registers or add a mode table, but this works and is much
402*b843c749SSergey Zigachev 		 * simpler.
403*b843c749SSergey Zigachev 		 */
404*b843c749SSergey Zigachev 		mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay, 60, true, false, false);
405*b843c749SSergey Zigachev 		mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
406*b843c749SSergey Zigachev 		DRM_DEBUG_KMS("Adding cvt approximation of native panel mode %s\n", mode->name);
407*b843c749SSergey Zigachev 	}
408*b843c749SSergey Zigachev 	return mode;
409*b843c749SSergey Zigachev }
410*b843c749SSergey Zigachev 
411*b843c749SSergey Zigachev static void amdgpu_connector_add_common_modes(struct drm_encoder *encoder,
412*b843c749SSergey Zigachev 					       struct drm_connector *connector)
413*b843c749SSergey Zigachev {
414*b843c749SSergey Zigachev 	struct drm_device *dev = encoder->dev;
415*b843c749SSergey Zigachev 	struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
416*b843c749SSergey Zigachev 	struct drm_display_mode *mode = NULL;
417*b843c749SSergey Zigachev 	struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
418*b843c749SSergey Zigachev 	int i;
419*b843c749SSergey Zigachev 	static const struct mode_size {
420*b843c749SSergey Zigachev 		int w;
421*b843c749SSergey Zigachev 		int h;
422*b843c749SSergey Zigachev 	} common_modes[17] = {
423*b843c749SSergey Zigachev 		{ 640,  480},
424*b843c749SSergey Zigachev 		{ 720,  480},
425*b843c749SSergey Zigachev 		{ 800,  600},
426*b843c749SSergey Zigachev 		{ 848,  480},
427*b843c749SSergey Zigachev 		{1024,  768},
428*b843c749SSergey Zigachev 		{1152,  768},
429*b843c749SSergey Zigachev 		{1280,  720},
430*b843c749SSergey Zigachev 		{1280,  800},
431*b843c749SSergey Zigachev 		{1280,  854},
432*b843c749SSergey Zigachev 		{1280,  960},
433*b843c749SSergey Zigachev 		{1280, 1024},
434*b843c749SSergey Zigachev 		{1440,  900},
435*b843c749SSergey Zigachev 		{1400, 1050},
436*b843c749SSergey Zigachev 		{1680, 1050},
437*b843c749SSergey Zigachev 		{1600, 1200},
438*b843c749SSergey Zigachev 		{1920, 1080},
439*b843c749SSergey Zigachev 		{1920, 1200}
440*b843c749SSergey Zigachev 	};
441*b843c749SSergey Zigachev 
442*b843c749SSergey Zigachev 	for (i = 0; i < 17; i++) {
443*b843c749SSergey Zigachev 		if (amdgpu_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) {
444*b843c749SSergey Zigachev 			if (common_modes[i].w > 1024 ||
445*b843c749SSergey Zigachev 			    common_modes[i].h > 768)
446*b843c749SSergey Zigachev 				continue;
447*b843c749SSergey Zigachev 		}
448*b843c749SSergey Zigachev 		if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
449*b843c749SSergey Zigachev 			if (common_modes[i].w > native_mode->hdisplay ||
450*b843c749SSergey Zigachev 			    common_modes[i].h > native_mode->vdisplay ||
451*b843c749SSergey Zigachev 			    (common_modes[i].w == native_mode->hdisplay &&
452*b843c749SSergey Zigachev 			     common_modes[i].h == native_mode->vdisplay))
453*b843c749SSergey Zigachev 				continue;
454*b843c749SSergey Zigachev 		}
455*b843c749SSergey Zigachev 		if (common_modes[i].w < 320 || common_modes[i].h < 200)
456*b843c749SSergey Zigachev 			continue;
457*b843c749SSergey Zigachev 
458*b843c749SSergey Zigachev 		mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
459*b843c749SSergey Zigachev 		drm_mode_probed_add(connector, mode);
460*b843c749SSergey Zigachev 	}
461*b843c749SSergey Zigachev }
462*b843c749SSergey Zigachev 
463*b843c749SSergey Zigachev static int amdgpu_connector_set_property(struct drm_connector *connector,
464*b843c749SSergey Zigachev 					  struct drm_property *property,
465*b843c749SSergey Zigachev 					  uint64_t val)
466*b843c749SSergey Zigachev {
467*b843c749SSergey Zigachev 	struct drm_device *dev = connector->dev;
468*b843c749SSergey Zigachev 	struct amdgpu_device *adev = dev->dev_private;
469*b843c749SSergey Zigachev 	struct drm_encoder *encoder;
470*b843c749SSergey Zigachev 	struct amdgpu_encoder *amdgpu_encoder;
471*b843c749SSergey Zigachev 
472*b843c749SSergey Zigachev 	if (property == adev->mode_info.coherent_mode_property) {
473*b843c749SSergey Zigachev 		struct amdgpu_encoder_atom_dig *dig;
474*b843c749SSergey Zigachev 		bool new_coherent_mode;
475*b843c749SSergey Zigachev 
476*b843c749SSergey Zigachev 		/* need to find digital encoder on connector */
477*b843c749SSergey Zigachev 		encoder = amdgpu_connector_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
478*b843c749SSergey Zigachev 		if (!encoder)
479*b843c749SSergey Zigachev 			return 0;
480*b843c749SSergey Zigachev 
481*b843c749SSergey Zigachev 		amdgpu_encoder = to_amdgpu_encoder(encoder);
482*b843c749SSergey Zigachev 
483*b843c749SSergey Zigachev 		if (!amdgpu_encoder->enc_priv)
484*b843c749SSergey Zigachev 			return 0;
485*b843c749SSergey Zigachev 
486*b843c749SSergey Zigachev 		dig = amdgpu_encoder->enc_priv;
487*b843c749SSergey Zigachev 		new_coherent_mode = val ? true : false;
488*b843c749SSergey Zigachev 		if (dig->coherent_mode != new_coherent_mode) {
489*b843c749SSergey Zigachev 			dig->coherent_mode = new_coherent_mode;
490*b843c749SSergey Zigachev 			amdgpu_connector_property_change_mode(&amdgpu_encoder->base);
491*b843c749SSergey Zigachev 		}
492*b843c749SSergey Zigachev 	}
493*b843c749SSergey Zigachev 
494*b843c749SSergey Zigachev 	if (property == adev->mode_info.audio_property) {
495*b843c749SSergey Zigachev 		struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
496*b843c749SSergey Zigachev 		/* need to find digital encoder on connector */
497*b843c749SSergey Zigachev 		encoder = amdgpu_connector_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
498*b843c749SSergey Zigachev 		if (!encoder)
499*b843c749SSergey Zigachev 			return 0;
500*b843c749SSergey Zigachev 
501*b843c749SSergey Zigachev 		amdgpu_encoder = to_amdgpu_encoder(encoder);
502*b843c749SSergey Zigachev 
503*b843c749SSergey Zigachev 		if (amdgpu_connector->audio != val) {
504*b843c749SSergey Zigachev 			amdgpu_connector->audio = val;
505*b843c749SSergey Zigachev 			amdgpu_connector_property_change_mode(&amdgpu_encoder->base);
506*b843c749SSergey Zigachev 		}
507*b843c749SSergey Zigachev 	}
508*b843c749SSergey Zigachev 
509*b843c749SSergey Zigachev 	if (property == adev->mode_info.dither_property) {
510*b843c749SSergey Zigachev 		struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
511*b843c749SSergey Zigachev 		/* need to find digital encoder on connector */
512*b843c749SSergey Zigachev 		encoder = amdgpu_connector_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
513*b843c749SSergey Zigachev 		if (!encoder)
514*b843c749SSergey Zigachev 			return 0;
515*b843c749SSergey Zigachev 
516*b843c749SSergey Zigachev 		amdgpu_encoder = to_amdgpu_encoder(encoder);
517*b843c749SSergey Zigachev 
518*b843c749SSergey Zigachev 		if (amdgpu_connector->dither != val) {
519*b843c749SSergey Zigachev 			amdgpu_connector->dither = val;
520*b843c749SSergey Zigachev 			amdgpu_connector_property_change_mode(&amdgpu_encoder->base);
521*b843c749SSergey Zigachev 		}
522*b843c749SSergey Zigachev 	}
523*b843c749SSergey Zigachev 
524*b843c749SSergey Zigachev 	if (property == adev->mode_info.underscan_property) {
525*b843c749SSergey Zigachev 		/* need to find digital encoder on connector */
526*b843c749SSergey Zigachev 		encoder = amdgpu_connector_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
527*b843c749SSergey Zigachev 		if (!encoder)
528*b843c749SSergey Zigachev 			return 0;
529*b843c749SSergey Zigachev 
530*b843c749SSergey Zigachev 		amdgpu_encoder = to_amdgpu_encoder(encoder);
531*b843c749SSergey Zigachev 
532*b843c749SSergey Zigachev 		if (amdgpu_encoder->underscan_type != val) {
533*b843c749SSergey Zigachev 			amdgpu_encoder->underscan_type = val;
534*b843c749SSergey Zigachev 			amdgpu_connector_property_change_mode(&amdgpu_encoder->base);
535*b843c749SSergey Zigachev 		}
536*b843c749SSergey Zigachev 	}
537*b843c749SSergey Zigachev 
538*b843c749SSergey Zigachev 	if (property == adev->mode_info.underscan_hborder_property) {
539*b843c749SSergey Zigachev 		/* need to find digital encoder on connector */
540*b843c749SSergey Zigachev 		encoder = amdgpu_connector_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
541*b843c749SSergey Zigachev 		if (!encoder)
542*b843c749SSergey Zigachev 			return 0;
543*b843c749SSergey Zigachev 
544*b843c749SSergey Zigachev 		amdgpu_encoder = to_amdgpu_encoder(encoder);
545*b843c749SSergey Zigachev 
546*b843c749SSergey Zigachev 		if (amdgpu_encoder->underscan_hborder != val) {
547*b843c749SSergey Zigachev 			amdgpu_encoder->underscan_hborder = val;
548*b843c749SSergey Zigachev 			amdgpu_connector_property_change_mode(&amdgpu_encoder->base);
549*b843c749SSergey Zigachev 		}
550*b843c749SSergey Zigachev 	}
551*b843c749SSergey Zigachev 
552*b843c749SSergey Zigachev 	if (property == adev->mode_info.underscan_vborder_property) {
553*b843c749SSergey Zigachev 		/* need to find digital encoder on connector */
554*b843c749SSergey Zigachev 		encoder = amdgpu_connector_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
555*b843c749SSergey Zigachev 		if (!encoder)
556*b843c749SSergey Zigachev 			return 0;
557*b843c749SSergey Zigachev 
558*b843c749SSergey Zigachev 		amdgpu_encoder = to_amdgpu_encoder(encoder);
559*b843c749SSergey Zigachev 
560*b843c749SSergey Zigachev 		if (amdgpu_encoder->underscan_vborder != val) {
561*b843c749SSergey Zigachev 			amdgpu_encoder->underscan_vborder = val;
562*b843c749SSergey Zigachev 			amdgpu_connector_property_change_mode(&amdgpu_encoder->base);
563*b843c749SSergey Zigachev 		}
564*b843c749SSergey Zigachev 	}
565*b843c749SSergey Zigachev 
566*b843c749SSergey Zigachev 	if (property == adev->mode_info.load_detect_property) {
567*b843c749SSergey Zigachev 		struct amdgpu_connector *amdgpu_connector =
568*b843c749SSergey Zigachev 			to_amdgpu_connector(connector);
569*b843c749SSergey Zigachev 
570*b843c749SSergey Zigachev 		if (val == 0)
571*b843c749SSergey Zigachev 			amdgpu_connector->dac_load_detect = false;
572*b843c749SSergey Zigachev 		else
573*b843c749SSergey Zigachev 			amdgpu_connector->dac_load_detect = true;
574*b843c749SSergey Zigachev 	}
575*b843c749SSergey Zigachev 
576*b843c749SSergey Zigachev 	if (property == dev->mode_config.scaling_mode_property) {
577*b843c749SSergey Zigachev 		enum amdgpu_rmx_type rmx_type;
578*b843c749SSergey Zigachev 
579*b843c749SSergey Zigachev 		if (connector->encoder) {
580*b843c749SSergey Zigachev 			amdgpu_encoder = to_amdgpu_encoder(connector->encoder);
581*b843c749SSergey Zigachev 		} else {
582*b843c749SSergey Zigachev 			const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
583*b843c749SSergey Zigachev 			amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector));
584*b843c749SSergey Zigachev 		}
585*b843c749SSergey Zigachev 
586*b843c749SSergey Zigachev 		switch (val) {
587*b843c749SSergey Zigachev 		default:
588*b843c749SSergey Zigachev 		case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break;
589*b843c749SSergey Zigachev 		case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break;
590*b843c749SSergey Zigachev 		case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break;
591*b843c749SSergey Zigachev 		case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break;
592*b843c749SSergey Zigachev 		}
593*b843c749SSergey Zigachev 		if (amdgpu_encoder->rmx_type == rmx_type)
594*b843c749SSergey Zigachev 			return 0;
595*b843c749SSergey Zigachev 
596*b843c749SSergey Zigachev 		if ((rmx_type != DRM_MODE_SCALE_NONE) &&
597*b843c749SSergey Zigachev 		    (amdgpu_encoder->native_mode.clock == 0))
598*b843c749SSergey Zigachev 			return 0;
599*b843c749SSergey Zigachev 
600*b843c749SSergey Zigachev 		amdgpu_encoder->rmx_type = rmx_type;
601*b843c749SSergey Zigachev 
602*b843c749SSergey Zigachev 		amdgpu_connector_property_change_mode(&amdgpu_encoder->base);
603*b843c749SSergey Zigachev 	}
604*b843c749SSergey Zigachev 
605*b843c749SSergey Zigachev 	return 0;
606*b843c749SSergey Zigachev }
607*b843c749SSergey Zigachev 
608*b843c749SSergey Zigachev static void
609*b843c749SSergey Zigachev amdgpu_connector_fixup_lcd_native_mode(struct drm_encoder *encoder,
610*b843c749SSergey Zigachev 					struct drm_connector *connector)
611*b843c749SSergey Zigachev {
612*b843c749SSergey Zigachev 	struct amdgpu_encoder *amdgpu_encoder =	to_amdgpu_encoder(encoder);
613*b843c749SSergey Zigachev 	struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
614*b843c749SSergey Zigachev 	struct drm_display_mode *t, *mode;
615*b843c749SSergey Zigachev 
616*b843c749SSergey Zigachev 	/* If the EDID preferred mode doesn't match the native mode, use it */
617*b843c749SSergey Zigachev 	list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
618*b843c749SSergey Zigachev 		if (mode->type & DRM_MODE_TYPE_PREFERRED) {
619*b843c749SSergey Zigachev 			if (mode->hdisplay != native_mode->hdisplay ||
620*b843c749SSergey Zigachev 			    mode->vdisplay != native_mode->vdisplay)
621*b843c749SSergey Zigachev 				memcpy(native_mode, mode, sizeof(*mode));
622*b843c749SSergey Zigachev 		}
623*b843c749SSergey Zigachev 	}
624*b843c749SSergey Zigachev 
625*b843c749SSergey Zigachev 	/* Try to get native mode details from EDID if necessary */
626*b843c749SSergey Zigachev 	if (!native_mode->clock) {
627*b843c749SSergey Zigachev 		list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
628*b843c749SSergey Zigachev 			if (mode->hdisplay == native_mode->hdisplay &&
629*b843c749SSergey Zigachev 			    mode->vdisplay == native_mode->vdisplay) {
630*b843c749SSergey Zigachev 				*native_mode = *mode;
631*b843c749SSergey Zigachev 				drm_mode_set_crtcinfo(native_mode, CRTC_INTERLACE_HALVE_V);
632*b843c749SSergey Zigachev 				DRM_DEBUG_KMS("Determined LVDS native mode details from EDID\n");
633*b843c749SSergey Zigachev 				break;
634*b843c749SSergey Zigachev 			}
635*b843c749SSergey Zigachev 		}
636*b843c749SSergey Zigachev 	}
637*b843c749SSergey Zigachev 
638*b843c749SSergey Zigachev 	if (!native_mode->clock) {
639*b843c749SSergey Zigachev 		DRM_DEBUG_KMS("No LVDS native mode details, disabling RMX\n");
640*b843c749SSergey Zigachev 		amdgpu_encoder->rmx_type = RMX_OFF;
641*b843c749SSergey Zigachev 	}
642*b843c749SSergey Zigachev }
643*b843c749SSergey Zigachev 
644*b843c749SSergey Zigachev static int amdgpu_connector_lvds_get_modes(struct drm_connector *connector)
645*b843c749SSergey Zigachev {
646*b843c749SSergey Zigachev 	struct drm_encoder *encoder;
647*b843c749SSergey Zigachev 	int ret = 0;
648*b843c749SSergey Zigachev 	struct drm_display_mode *mode;
649*b843c749SSergey Zigachev 
650*b843c749SSergey Zigachev 	amdgpu_connector_get_edid(connector);
651*b843c749SSergey Zigachev 	ret = amdgpu_connector_ddc_get_modes(connector);
652*b843c749SSergey Zigachev 	if (ret > 0) {
653*b843c749SSergey Zigachev 		encoder = amdgpu_connector_best_single_encoder(connector);
654*b843c749SSergey Zigachev 		if (encoder) {
655*b843c749SSergey Zigachev 			amdgpu_connector_fixup_lcd_native_mode(encoder, connector);
656*b843c749SSergey Zigachev 			/* add scaled modes */
657*b843c749SSergey Zigachev 			amdgpu_connector_add_common_modes(encoder, connector);
658*b843c749SSergey Zigachev 		}
659*b843c749SSergey Zigachev 		return ret;
660*b843c749SSergey Zigachev 	}
661*b843c749SSergey Zigachev 
662*b843c749SSergey Zigachev 	encoder = amdgpu_connector_best_single_encoder(connector);
663*b843c749SSergey Zigachev 	if (!encoder)
664*b843c749SSergey Zigachev 		return 0;
665*b843c749SSergey Zigachev 
666*b843c749SSergey Zigachev 	/* we have no EDID modes */
667*b843c749SSergey Zigachev 	mode = amdgpu_connector_lcd_native_mode(encoder);
668*b843c749SSergey Zigachev 	if (mode) {
669*b843c749SSergey Zigachev 		ret = 1;
670*b843c749SSergey Zigachev 		drm_mode_probed_add(connector, mode);
671*b843c749SSergey Zigachev 		/* add the width/height from vbios tables if available */
672*b843c749SSergey Zigachev 		connector->display_info.width_mm = mode->width_mm;
673*b843c749SSergey Zigachev 		connector->display_info.height_mm = mode->height_mm;
674*b843c749SSergey Zigachev 		/* add scaled modes */
675*b843c749SSergey Zigachev 		amdgpu_connector_add_common_modes(encoder, connector);
676*b843c749SSergey Zigachev 	}
677*b843c749SSergey Zigachev 
678*b843c749SSergey Zigachev 	return ret;
679*b843c749SSergey Zigachev }
680*b843c749SSergey Zigachev 
681*b843c749SSergey Zigachev static enum drm_mode_status amdgpu_connector_lvds_mode_valid(struct drm_connector *connector,
682*b843c749SSergey Zigachev 					     struct drm_display_mode *mode)
683*b843c749SSergey Zigachev {
684*b843c749SSergey Zigachev 	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
685*b843c749SSergey Zigachev 
686*b843c749SSergey Zigachev 	if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
687*b843c749SSergey Zigachev 		return MODE_PANEL;
688*b843c749SSergey Zigachev 
689*b843c749SSergey Zigachev 	if (encoder) {
690*b843c749SSergey Zigachev 		struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
691*b843c749SSergey Zigachev 		struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
692*b843c749SSergey Zigachev 
693*b843c749SSergey Zigachev 		/* AVIVO hardware supports downscaling modes larger than the panel
694*b843c749SSergey Zigachev 		 * to the panel size, but I'm not sure this is desirable.
695*b843c749SSergey Zigachev 		 */
696*b843c749SSergey Zigachev 		if ((mode->hdisplay > native_mode->hdisplay) ||
697*b843c749SSergey Zigachev 		    (mode->vdisplay > native_mode->vdisplay))
698*b843c749SSergey Zigachev 			return MODE_PANEL;
699*b843c749SSergey Zigachev 
700*b843c749SSergey Zigachev 		/* if scaling is disabled, block non-native modes */
701*b843c749SSergey Zigachev 		if (amdgpu_encoder->rmx_type == RMX_OFF) {
702*b843c749SSergey Zigachev 			if ((mode->hdisplay != native_mode->hdisplay) ||
703*b843c749SSergey Zigachev 			    (mode->vdisplay != native_mode->vdisplay))
704*b843c749SSergey Zigachev 				return MODE_PANEL;
705*b843c749SSergey Zigachev 		}
706*b843c749SSergey Zigachev 	}
707*b843c749SSergey Zigachev 
708*b843c749SSergey Zigachev 	return MODE_OK;
709*b843c749SSergey Zigachev }
710*b843c749SSergey Zigachev 
711*b843c749SSergey Zigachev static enum drm_connector_status
712*b843c749SSergey Zigachev amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force)
713*b843c749SSergey Zigachev {
714*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
715*b843c749SSergey Zigachev 	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
716*b843c749SSergey Zigachev 	enum drm_connector_status ret = connector_status_disconnected;
717*b843c749SSergey Zigachev 	int r;
718*b843c749SSergey Zigachev 
719*b843c749SSergey Zigachev 	if (!drm_kms_helper_is_poll_worker()) {
720*b843c749SSergey Zigachev 		r = pm_runtime_get_sync(connector->dev->dev);
721*b843c749SSergey Zigachev 		if (r < 0) {
722*b843c749SSergey Zigachev 			pm_runtime_put_autosuspend(connector->dev->dev);
723*b843c749SSergey Zigachev 			return connector_status_disconnected;
724*b843c749SSergey Zigachev 		}
725*b843c749SSergey Zigachev 	}
726*b843c749SSergey Zigachev 
727*b843c749SSergey Zigachev 	if (encoder) {
728*b843c749SSergey Zigachev 		struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
729*b843c749SSergey Zigachev 		struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
730*b843c749SSergey Zigachev 
731*b843c749SSergey Zigachev 		/* check if panel is valid */
732*b843c749SSergey Zigachev 		if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240)
733*b843c749SSergey Zigachev 			ret = connector_status_connected;
734*b843c749SSergey Zigachev 
735*b843c749SSergey Zigachev 	}
736*b843c749SSergey Zigachev 
737*b843c749SSergey Zigachev 	/* check for edid as well */
738*b843c749SSergey Zigachev 	amdgpu_connector_get_edid(connector);
739*b843c749SSergey Zigachev 	if (amdgpu_connector->edid)
740*b843c749SSergey Zigachev 		ret = connector_status_connected;
741*b843c749SSergey Zigachev 	/* check acpi lid status ??? */
742*b843c749SSergey Zigachev 
743*b843c749SSergey Zigachev 	amdgpu_connector_update_scratch_regs(connector, ret);
744*b843c749SSergey Zigachev 
745*b843c749SSergey Zigachev 	if (!drm_kms_helper_is_poll_worker()) {
746*b843c749SSergey Zigachev 		pm_runtime_mark_last_busy(connector->dev->dev);
747*b843c749SSergey Zigachev 		pm_runtime_put_autosuspend(connector->dev->dev);
748*b843c749SSergey Zigachev 	}
749*b843c749SSergey Zigachev 
750*b843c749SSergey Zigachev 	return ret;
751*b843c749SSergey Zigachev }
752*b843c749SSergey Zigachev 
753*b843c749SSergey Zigachev static void amdgpu_connector_unregister(struct drm_connector *connector)
754*b843c749SSergey Zigachev {
755*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
756*b843c749SSergey Zigachev 
757*b843c749SSergey Zigachev 	if (amdgpu_connector->ddc_bus && amdgpu_connector->ddc_bus->has_aux) {
758*b843c749SSergey Zigachev 		drm_dp_aux_unregister(&amdgpu_connector->ddc_bus->aux);
759*b843c749SSergey Zigachev 		amdgpu_connector->ddc_bus->has_aux = false;
760*b843c749SSergey Zigachev 	}
761*b843c749SSergey Zigachev }
762*b843c749SSergey Zigachev 
763*b843c749SSergey Zigachev static void amdgpu_connector_destroy(struct drm_connector *connector)
764*b843c749SSergey Zigachev {
765*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
766*b843c749SSergey Zigachev 
767*b843c749SSergey Zigachev 	amdgpu_connector_free_edid(connector);
768*b843c749SSergey Zigachev 	kfree(amdgpu_connector->con_priv);
769*b843c749SSergey Zigachev 	drm_connector_unregister(connector);
770*b843c749SSergey Zigachev 	drm_connector_cleanup(connector);
771*b843c749SSergey Zigachev 	kfree(connector);
772*b843c749SSergey Zigachev }
773*b843c749SSergey Zigachev 
774*b843c749SSergey Zigachev static int amdgpu_connector_set_lcd_property(struct drm_connector *connector,
775*b843c749SSergey Zigachev 					      struct drm_property *property,
776*b843c749SSergey Zigachev 					      uint64_t value)
777*b843c749SSergey Zigachev {
778*b843c749SSergey Zigachev 	struct drm_device *dev = connector->dev;
779*b843c749SSergey Zigachev 	struct amdgpu_encoder *amdgpu_encoder;
780*b843c749SSergey Zigachev 	enum amdgpu_rmx_type rmx_type;
781*b843c749SSergey Zigachev 
782*b843c749SSergey Zigachev 	DRM_DEBUG_KMS("\n");
783*b843c749SSergey Zigachev 	if (property != dev->mode_config.scaling_mode_property)
784*b843c749SSergey Zigachev 		return 0;
785*b843c749SSergey Zigachev 
786*b843c749SSergey Zigachev 	if (connector->encoder)
787*b843c749SSergey Zigachev 		amdgpu_encoder = to_amdgpu_encoder(connector->encoder);
788*b843c749SSergey Zigachev 	else {
789*b843c749SSergey Zigachev 		const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
790*b843c749SSergey Zigachev 		amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector));
791*b843c749SSergey Zigachev 	}
792*b843c749SSergey Zigachev 
793*b843c749SSergey Zigachev 	switch (value) {
794*b843c749SSergey Zigachev 	case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break;
795*b843c749SSergey Zigachev 	case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break;
796*b843c749SSergey Zigachev 	case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break;
797*b843c749SSergey Zigachev 	default:
798*b843c749SSergey Zigachev 	case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break;
799*b843c749SSergey Zigachev 	}
800*b843c749SSergey Zigachev 	if (amdgpu_encoder->rmx_type == rmx_type)
801*b843c749SSergey Zigachev 		return 0;
802*b843c749SSergey Zigachev 
803*b843c749SSergey Zigachev 	amdgpu_encoder->rmx_type = rmx_type;
804*b843c749SSergey Zigachev 
805*b843c749SSergey Zigachev 	amdgpu_connector_property_change_mode(&amdgpu_encoder->base);
806*b843c749SSergey Zigachev 	return 0;
807*b843c749SSergey Zigachev }
808*b843c749SSergey Zigachev 
809*b843c749SSergey Zigachev 
810*b843c749SSergey Zigachev static const struct drm_connector_helper_funcs amdgpu_connector_lvds_helper_funcs = {
811*b843c749SSergey Zigachev 	.get_modes = amdgpu_connector_lvds_get_modes,
812*b843c749SSergey Zigachev 	.mode_valid = amdgpu_connector_lvds_mode_valid,
813*b843c749SSergey Zigachev 	.best_encoder = amdgpu_connector_best_single_encoder,
814*b843c749SSergey Zigachev };
815*b843c749SSergey Zigachev 
816*b843c749SSergey Zigachev static const struct drm_connector_funcs amdgpu_connector_lvds_funcs = {
817*b843c749SSergey Zigachev 	.dpms = drm_helper_connector_dpms,
818*b843c749SSergey Zigachev 	.detect = amdgpu_connector_lvds_detect,
819*b843c749SSergey Zigachev 	.fill_modes = drm_helper_probe_single_connector_modes,
820*b843c749SSergey Zigachev 	.early_unregister = amdgpu_connector_unregister,
821*b843c749SSergey Zigachev 	.destroy = amdgpu_connector_destroy,
822*b843c749SSergey Zigachev 	.set_property = amdgpu_connector_set_lcd_property,
823*b843c749SSergey Zigachev };
824*b843c749SSergey Zigachev 
825*b843c749SSergey Zigachev static int amdgpu_connector_vga_get_modes(struct drm_connector *connector)
826*b843c749SSergey Zigachev {
827*b843c749SSergey Zigachev 	int ret;
828*b843c749SSergey Zigachev 
829*b843c749SSergey Zigachev 	amdgpu_connector_get_edid(connector);
830*b843c749SSergey Zigachev 	ret = amdgpu_connector_ddc_get_modes(connector);
831*b843c749SSergey Zigachev 
832*b843c749SSergey Zigachev 	return ret;
833*b843c749SSergey Zigachev }
834*b843c749SSergey Zigachev 
835*b843c749SSergey Zigachev static enum drm_mode_status amdgpu_connector_vga_mode_valid(struct drm_connector *connector,
836*b843c749SSergey Zigachev 					    struct drm_display_mode *mode)
837*b843c749SSergey Zigachev {
838*b843c749SSergey Zigachev 	struct drm_device *dev = connector->dev;
839*b843c749SSergey Zigachev 	struct amdgpu_device *adev = dev->dev_private;
840*b843c749SSergey Zigachev 
841*b843c749SSergey Zigachev 	/* XXX check mode bandwidth */
842*b843c749SSergey Zigachev 
843*b843c749SSergey Zigachev 	if ((mode->clock / 10) > adev->clock.max_pixel_clock)
844*b843c749SSergey Zigachev 		return MODE_CLOCK_HIGH;
845*b843c749SSergey Zigachev 
846*b843c749SSergey Zigachev 	return MODE_OK;
847*b843c749SSergey Zigachev }
848*b843c749SSergey Zigachev 
849*b843c749SSergey Zigachev static enum drm_connector_status
850*b843c749SSergey Zigachev amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)
851*b843c749SSergey Zigachev {
852*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
853*b843c749SSergey Zigachev 	struct drm_encoder *encoder;
854*b843c749SSergey Zigachev 	const struct drm_encoder_helper_funcs *encoder_funcs;
855*b843c749SSergey Zigachev 	bool dret = false;
856*b843c749SSergey Zigachev 	enum drm_connector_status ret = connector_status_disconnected;
857*b843c749SSergey Zigachev 	int r;
858*b843c749SSergey Zigachev 
859*b843c749SSergey Zigachev 	if (!drm_kms_helper_is_poll_worker()) {
860*b843c749SSergey Zigachev 		r = pm_runtime_get_sync(connector->dev->dev);
861*b843c749SSergey Zigachev 		if (r < 0) {
862*b843c749SSergey Zigachev 			pm_runtime_put_autosuspend(connector->dev->dev);
863*b843c749SSergey Zigachev 			return connector_status_disconnected;
864*b843c749SSergey Zigachev 		}
865*b843c749SSergey Zigachev 	}
866*b843c749SSergey Zigachev 
867*b843c749SSergey Zigachev 	encoder = amdgpu_connector_best_single_encoder(connector);
868*b843c749SSergey Zigachev 	if (!encoder)
869*b843c749SSergey Zigachev 		ret = connector_status_disconnected;
870*b843c749SSergey Zigachev 
871*b843c749SSergey Zigachev 	if (amdgpu_connector->ddc_bus)
872*b843c749SSergey Zigachev 		dret = amdgpu_display_ddc_probe(amdgpu_connector, false);
873*b843c749SSergey Zigachev 	if (dret) {
874*b843c749SSergey Zigachev 		amdgpu_connector->detected_by_load = false;
875*b843c749SSergey Zigachev 		amdgpu_connector_free_edid(connector);
876*b843c749SSergey Zigachev 		amdgpu_connector_get_edid(connector);
877*b843c749SSergey Zigachev 
878*b843c749SSergey Zigachev 		if (!amdgpu_connector->edid) {
879*b843c749SSergey Zigachev 			DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
880*b843c749SSergey Zigachev 					connector->name);
881*b843c749SSergey Zigachev 			ret = connector_status_connected;
882*b843c749SSergey Zigachev 		} else {
883*b843c749SSergey Zigachev 			amdgpu_connector->use_digital =
884*b843c749SSergey Zigachev 				!!(amdgpu_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
885*b843c749SSergey Zigachev 
886*b843c749SSergey Zigachev 			/* some oems have boards with separate digital and analog connectors
887*b843c749SSergey Zigachev 			 * with a shared ddc line (often vga + hdmi)
888*b843c749SSergey Zigachev 			 */
889*b843c749SSergey Zigachev 			if (amdgpu_connector->use_digital && amdgpu_connector->shared_ddc) {
890*b843c749SSergey Zigachev 				amdgpu_connector_free_edid(connector);
891*b843c749SSergey Zigachev 				ret = connector_status_disconnected;
892*b843c749SSergey Zigachev 			} else {
893*b843c749SSergey Zigachev 				ret = connector_status_connected;
894*b843c749SSergey Zigachev 			}
895*b843c749SSergey Zigachev 		}
896*b843c749SSergey Zigachev 	} else {
897*b843c749SSergey Zigachev 
898*b843c749SSergey Zigachev 		/* if we aren't forcing don't do destructive polling */
899*b843c749SSergey Zigachev 		if (!force) {
900*b843c749SSergey Zigachev 			/* only return the previous status if we last
901*b843c749SSergey Zigachev 			 * detected a monitor via load.
902*b843c749SSergey Zigachev 			 */
903*b843c749SSergey Zigachev 			if (amdgpu_connector->detected_by_load)
904*b843c749SSergey Zigachev 				ret = connector->status;
905*b843c749SSergey Zigachev 			goto out;
906*b843c749SSergey Zigachev 		}
907*b843c749SSergey Zigachev 
908*b843c749SSergey Zigachev 		if (amdgpu_connector->dac_load_detect && encoder) {
909*b843c749SSergey Zigachev 			encoder_funcs = encoder->helper_private;
910*b843c749SSergey Zigachev 			ret = encoder_funcs->detect(encoder, connector);
911*b843c749SSergey Zigachev 			if (ret != connector_status_disconnected)
912*b843c749SSergey Zigachev 				amdgpu_connector->detected_by_load = true;
913*b843c749SSergey Zigachev 		}
914*b843c749SSergey Zigachev 	}
915*b843c749SSergey Zigachev 
916*b843c749SSergey Zigachev 	amdgpu_connector_update_scratch_regs(connector, ret);
917*b843c749SSergey Zigachev 
918*b843c749SSergey Zigachev out:
919*b843c749SSergey Zigachev 	if (!drm_kms_helper_is_poll_worker()) {
920*b843c749SSergey Zigachev 		pm_runtime_mark_last_busy(connector->dev->dev);
921*b843c749SSergey Zigachev 		pm_runtime_put_autosuspend(connector->dev->dev);
922*b843c749SSergey Zigachev 	}
923*b843c749SSergey Zigachev 
924*b843c749SSergey Zigachev 	return ret;
925*b843c749SSergey Zigachev }
926*b843c749SSergey Zigachev 
927*b843c749SSergey Zigachev static const struct drm_connector_helper_funcs amdgpu_connector_vga_helper_funcs = {
928*b843c749SSergey Zigachev 	.get_modes = amdgpu_connector_vga_get_modes,
929*b843c749SSergey Zigachev 	.mode_valid = amdgpu_connector_vga_mode_valid,
930*b843c749SSergey Zigachev 	.best_encoder = amdgpu_connector_best_single_encoder,
931*b843c749SSergey Zigachev };
932*b843c749SSergey Zigachev 
933*b843c749SSergey Zigachev static const struct drm_connector_funcs amdgpu_connector_vga_funcs = {
934*b843c749SSergey Zigachev 	.dpms = drm_helper_connector_dpms,
935*b843c749SSergey Zigachev 	.detect = amdgpu_connector_vga_detect,
936*b843c749SSergey Zigachev 	.fill_modes = drm_helper_probe_single_connector_modes,
937*b843c749SSergey Zigachev 	.early_unregister = amdgpu_connector_unregister,
938*b843c749SSergey Zigachev 	.destroy = amdgpu_connector_destroy,
939*b843c749SSergey Zigachev 	.set_property = amdgpu_connector_set_property,
940*b843c749SSergey Zigachev };
941*b843c749SSergey Zigachev 
942*b843c749SSergey Zigachev static bool
943*b843c749SSergey Zigachev amdgpu_connector_check_hpd_status_unchanged(struct drm_connector *connector)
944*b843c749SSergey Zigachev {
945*b843c749SSergey Zigachev 	struct drm_device *dev = connector->dev;
946*b843c749SSergey Zigachev 	struct amdgpu_device *adev = dev->dev_private;
947*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
948*b843c749SSergey Zigachev 	enum drm_connector_status status;
949*b843c749SSergey Zigachev 
950*b843c749SSergey Zigachev 	if (amdgpu_connector->hpd.hpd != AMDGPU_HPD_NONE) {
951*b843c749SSergey Zigachev 		if (amdgpu_display_hpd_sense(adev, amdgpu_connector->hpd.hpd))
952*b843c749SSergey Zigachev 			status = connector_status_connected;
953*b843c749SSergey Zigachev 		else
954*b843c749SSergey Zigachev 			status = connector_status_disconnected;
955*b843c749SSergey Zigachev 		if (connector->status == status)
956*b843c749SSergey Zigachev 			return true;
957*b843c749SSergey Zigachev 	}
958*b843c749SSergey Zigachev 
959*b843c749SSergey Zigachev 	return false;
960*b843c749SSergey Zigachev }
961*b843c749SSergey Zigachev 
962*b843c749SSergey Zigachev /*
963*b843c749SSergey Zigachev  * DVI is complicated
964*b843c749SSergey Zigachev  * Do a DDC probe, if DDC probe passes, get the full EDID so
965*b843c749SSergey Zigachev  * we can do analog/digital monitor detection at this point.
966*b843c749SSergey Zigachev  * If the monitor is an analog monitor or we got no DDC,
967*b843c749SSergey Zigachev  * we need to find the DAC encoder object for this connector.
968*b843c749SSergey Zigachev  * If we got no DDC, we do load detection on the DAC encoder object.
969*b843c749SSergey Zigachev  * If we got analog DDC or load detection passes on the DAC encoder
970*b843c749SSergey Zigachev  * we have to check if this analog encoder is shared with anyone else (TV)
971*b843c749SSergey Zigachev  * if its shared we have to set the other connector to disconnected.
972*b843c749SSergey Zigachev  */
973*b843c749SSergey Zigachev static enum drm_connector_status
974*b843c749SSergey Zigachev amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
975*b843c749SSergey Zigachev {
976*b843c749SSergey Zigachev 	struct drm_device *dev = connector->dev;
977*b843c749SSergey Zigachev 	struct amdgpu_device *adev = dev->dev_private;
978*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
979*b843c749SSergey Zigachev 	const struct drm_encoder_helper_funcs *encoder_funcs;
980*b843c749SSergey Zigachev 	int r;
981*b843c749SSergey Zigachev 	enum drm_connector_status ret = connector_status_disconnected;
982*b843c749SSergey Zigachev 	bool dret = false, broken_edid = false;
983*b843c749SSergey Zigachev 
984*b843c749SSergey Zigachev 	if (!drm_kms_helper_is_poll_worker()) {
985*b843c749SSergey Zigachev 		r = pm_runtime_get_sync(connector->dev->dev);
986*b843c749SSergey Zigachev 		if (r < 0) {
987*b843c749SSergey Zigachev 			pm_runtime_put_autosuspend(connector->dev->dev);
988*b843c749SSergey Zigachev 			return connector_status_disconnected;
989*b843c749SSergey Zigachev 		}
990*b843c749SSergey Zigachev 	}
991*b843c749SSergey Zigachev 
992*b843c749SSergey Zigachev 	if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) {
993*b843c749SSergey Zigachev 		ret = connector->status;
994*b843c749SSergey Zigachev 		goto exit;
995*b843c749SSergey Zigachev 	}
996*b843c749SSergey Zigachev 
997*b843c749SSergey Zigachev 	if (amdgpu_connector->ddc_bus)
998*b843c749SSergey Zigachev 		dret = amdgpu_display_ddc_probe(amdgpu_connector, false);
999*b843c749SSergey Zigachev 	if (dret) {
1000*b843c749SSergey Zigachev 		amdgpu_connector->detected_by_load = false;
1001*b843c749SSergey Zigachev 		amdgpu_connector_free_edid(connector);
1002*b843c749SSergey Zigachev 		amdgpu_connector_get_edid(connector);
1003*b843c749SSergey Zigachev 
1004*b843c749SSergey Zigachev 		if (!amdgpu_connector->edid) {
1005*b843c749SSergey Zigachev 			DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
1006*b843c749SSergey Zigachev 					connector->name);
1007*b843c749SSergey Zigachev 			ret = connector_status_connected;
1008*b843c749SSergey Zigachev 			broken_edid = true; /* defer use_digital to later */
1009*b843c749SSergey Zigachev 		} else {
1010*b843c749SSergey Zigachev 			amdgpu_connector->use_digital =
1011*b843c749SSergey Zigachev 				!!(amdgpu_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
1012*b843c749SSergey Zigachev 
1013*b843c749SSergey Zigachev 			/* some oems have boards with separate digital and analog connectors
1014*b843c749SSergey Zigachev 			 * with a shared ddc line (often vga + hdmi)
1015*b843c749SSergey Zigachev 			 */
1016*b843c749SSergey Zigachev 			if ((!amdgpu_connector->use_digital) && amdgpu_connector->shared_ddc) {
1017*b843c749SSergey Zigachev 				amdgpu_connector_free_edid(connector);
1018*b843c749SSergey Zigachev 				ret = connector_status_disconnected;
1019*b843c749SSergey Zigachev 			} else {
1020*b843c749SSergey Zigachev 				ret = connector_status_connected;
1021*b843c749SSergey Zigachev 			}
1022*b843c749SSergey Zigachev 
1023*b843c749SSergey Zigachev 			/* This gets complicated.  We have boards with VGA + HDMI with a
1024*b843c749SSergey Zigachev 			 * shared DDC line and we have boards with DVI-D + HDMI with a shared
1025*b843c749SSergey Zigachev 			 * DDC line.  The latter is more complex because with DVI<->HDMI adapters
1026*b843c749SSergey Zigachev 			 * you don't really know what's connected to which port as both are digital.
1027*b843c749SSergey Zigachev 			 */
1028*b843c749SSergey Zigachev 			if (amdgpu_connector->shared_ddc && (ret == connector_status_connected)) {
1029*b843c749SSergey Zigachev 				struct drm_connector *list_connector;
1030*b843c749SSergey Zigachev 				struct amdgpu_connector *list_amdgpu_connector;
1031*b843c749SSergey Zigachev 				list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) {
1032*b843c749SSergey Zigachev 					if (connector == list_connector)
1033*b843c749SSergey Zigachev 						continue;
1034*b843c749SSergey Zigachev 					list_amdgpu_connector = to_amdgpu_connector(list_connector);
1035*b843c749SSergey Zigachev 					if (list_amdgpu_connector->shared_ddc &&
1036*b843c749SSergey Zigachev 					    (list_amdgpu_connector->ddc_bus->rec.i2c_id ==
1037*b843c749SSergey Zigachev 					     amdgpu_connector->ddc_bus->rec.i2c_id)) {
1038*b843c749SSergey Zigachev 						/* cases where both connectors are digital */
1039*b843c749SSergey Zigachev 						if (list_connector->connector_type != DRM_MODE_CONNECTOR_VGA) {
1040*b843c749SSergey Zigachev 							/* hpd is our only option in this case */
1041*b843c749SSergey Zigachev 							if (!amdgpu_display_hpd_sense(adev, amdgpu_connector->hpd.hpd)) {
1042*b843c749SSergey Zigachev 								amdgpu_connector_free_edid(connector);
1043*b843c749SSergey Zigachev 								ret = connector_status_disconnected;
1044*b843c749SSergey Zigachev 							}
1045*b843c749SSergey Zigachev 						}
1046*b843c749SSergey Zigachev 					}
1047*b843c749SSergey Zigachev 				}
1048*b843c749SSergey Zigachev 			}
1049*b843c749SSergey Zigachev 		}
1050*b843c749SSergey Zigachev 	}
1051*b843c749SSergey Zigachev 
1052*b843c749SSergey Zigachev 	if ((ret == connector_status_connected) && (amdgpu_connector->use_digital == true))
1053*b843c749SSergey Zigachev 		goto out;
1054*b843c749SSergey Zigachev 
1055*b843c749SSergey Zigachev 	/* DVI-D and HDMI-A are digital only */
1056*b843c749SSergey Zigachev 	if ((connector->connector_type == DRM_MODE_CONNECTOR_DVID) ||
1057*b843c749SSergey Zigachev 	    (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA))
1058*b843c749SSergey Zigachev 		goto out;
1059*b843c749SSergey Zigachev 
1060*b843c749SSergey Zigachev 	/* if we aren't forcing don't do destructive polling */
1061*b843c749SSergey Zigachev 	if (!force) {
1062*b843c749SSergey Zigachev 		/* only return the previous status if we last
1063*b843c749SSergey Zigachev 		 * detected a monitor via load.
1064*b843c749SSergey Zigachev 		 */
1065*b843c749SSergey Zigachev 		if (amdgpu_connector->detected_by_load)
1066*b843c749SSergey Zigachev 			ret = connector->status;
1067*b843c749SSergey Zigachev 		goto out;
1068*b843c749SSergey Zigachev 	}
1069*b843c749SSergey Zigachev 
1070*b843c749SSergey Zigachev 	/* find analog encoder */
1071*b843c749SSergey Zigachev 	if (amdgpu_connector->dac_load_detect) {
1072*b843c749SSergey Zigachev 		struct drm_encoder *encoder;
1073*b843c749SSergey Zigachev 		int i;
1074*b843c749SSergey Zigachev 
1075*b843c749SSergey Zigachev 		drm_connector_for_each_possible_encoder(connector, encoder, i) {
1076*b843c749SSergey Zigachev 			if (encoder->encoder_type != DRM_MODE_ENCODER_DAC &&
1077*b843c749SSergey Zigachev 			    encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
1078*b843c749SSergey Zigachev 				continue;
1079*b843c749SSergey Zigachev 
1080*b843c749SSergey Zigachev 			encoder_funcs = encoder->helper_private;
1081*b843c749SSergey Zigachev 			if (encoder_funcs->detect) {
1082*b843c749SSergey Zigachev 				if (!broken_edid) {
1083*b843c749SSergey Zigachev 					if (ret != connector_status_connected) {
1084*b843c749SSergey Zigachev 						/* deal with analog monitors without DDC */
1085*b843c749SSergey Zigachev 						ret = encoder_funcs->detect(encoder, connector);
1086*b843c749SSergey Zigachev 						if (ret == connector_status_connected) {
1087*b843c749SSergey Zigachev 							amdgpu_connector->use_digital = false;
1088*b843c749SSergey Zigachev 						}
1089*b843c749SSergey Zigachev 						if (ret != connector_status_disconnected)
1090*b843c749SSergey Zigachev 							amdgpu_connector->detected_by_load = true;
1091*b843c749SSergey Zigachev 					}
1092*b843c749SSergey Zigachev 				} else {
1093*b843c749SSergey Zigachev 					enum drm_connector_status lret;
1094*b843c749SSergey Zigachev 					/* assume digital unless load detected otherwise */
1095*b843c749SSergey Zigachev 					amdgpu_connector->use_digital = true;
1096*b843c749SSergey Zigachev 					lret = encoder_funcs->detect(encoder, connector);
1097*b843c749SSergey Zigachev 					DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret);
1098*b843c749SSergey Zigachev 					if (lret == connector_status_connected)
1099*b843c749SSergey Zigachev 						amdgpu_connector->use_digital = false;
1100*b843c749SSergey Zigachev 				}
1101*b843c749SSergey Zigachev 				break;
1102*b843c749SSergey Zigachev 			}
1103*b843c749SSergey Zigachev 		}
1104*b843c749SSergey Zigachev 	}
1105*b843c749SSergey Zigachev 
1106*b843c749SSergey Zigachev out:
1107*b843c749SSergey Zigachev 	/* updated in get modes as well since we need to know if it's analog or digital */
1108*b843c749SSergey Zigachev 	amdgpu_connector_update_scratch_regs(connector, ret);
1109*b843c749SSergey Zigachev 
1110*b843c749SSergey Zigachev exit:
1111*b843c749SSergey Zigachev 	if (!drm_kms_helper_is_poll_worker()) {
1112*b843c749SSergey Zigachev 		pm_runtime_mark_last_busy(connector->dev->dev);
1113*b843c749SSergey Zigachev 		pm_runtime_put_autosuspend(connector->dev->dev);
1114*b843c749SSergey Zigachev 	}
1115*b843c749SSergey Zigachev 
1116*b843c749SSergey Zigachev 	return ret;
1117*b843c749SSergey Zigachev }
1118*b843c749SSergey Zigachev 
1119*b843c749SSergey Zigachev /* okay need to be smart in here about which encoder to pick */
1120*b843c749SSergey Zigachev static struct drm_encoder *
1121*b843c749SSergey Zigachev amdgpu_connector_dvi_encoder(struct drm_connector *connector)
1122*b843c749SSergey Zigachev {
1123*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
1124*b843c749SSergey Zigachev 	struct drm_encoder *encoder;
1125*b843c749SSergey Zigachev 	int i;
1126*b843c749SSergey Zigachev 
1127*b843c749SSergey Zigachev 	drm_connector_for_each_possible_encoder(connector, encoder, i) {
1128*b843c749SSergey Zigachev 		if (amdgpu_connector->use_digital == true) {
1129*b843c749SSergey Zigachev 			if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
1130*b843c749SSergey Zigachev 				return encoder;
1131*b843c749SSergey Zigachev 		} else {
1132*b843c749SSergey Zigachev 			if (encoder->encoder_type == DRM_MODE_ENCODER_DAC ||
1133*b843c749SSergey Zigachev 			    encoder->encoder_type == DRM_MODE_ENCODER_TVDAC)
1134*b843c749SSergey Zigachev 				return encoder;
1135*b843c749SSergey Zigachev 		}
1136*b843c749SSergey Zigachev 	}
1137*b843c749SSergey Zigachev 
1138*b843c749SSergey Zigachev 	/* see if we have a default encoder  TODO */
1139*b843c749SSergey Zigachev 
1140*b843c749SSergey Zigachev 	/* then check use digitial */
1141*b843c749SSergey Zigachev 	/* pick the first one */
1142*b843c749SSergey Zigachev 	drm_connector_for_each_possible_encoder(connector, encoder, i)
1143*b843c749SSergey Zigachev 		return encoder;
1144*b843c749SSergey Zigachev 
1145*b843c749SSergey Zigachev 	return NULL;
1146*b843c749SSergey Zigachev }
1147*b843c749SSergey Zigachev 
1148*b843c749SSergey Zigachev static void amdgpu_connector_dvi_force(struct drm_connector *connector)
1149*b843c749SSergey Zigachev {
1150*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
1151*b843c749SSergey Zigachev 	if (connector->force == DRM_FORCE_ON)
1152*b843c749SSergey Zigachev 		amdgpu_connector->use_digital = false;
1153*b843c749SSergey Zigachev 	if (connector->force == DRM_FORCE_ON_DIGITAL)
1154*b843c749SSergey Zigachev 		amdgpu_connector->use_digital = true;
1155*b843c749SSergey Zigachev }
1156*b843c749SSergey Zigachev 
1157*b843c749SSergey Zigachev static enum drm_mode_status amdgpu_connector_dvi_mode_valid(struct drm_connector *connector,
1158*b843c749SSergey Zigachev 					    struct drm_display_mode *mode)
1159*b843c749SSergey Zigachev {
1160*b843c749SSergey Zigachev 	struct drm_device *dev = connector->dev;
1161*b843c749SSergey Zigachev 	struct amdgpu_device *adev = dev->dev_private;
1162*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
1163*b843c749SSergey Zigachev 
1164*b843c749SSergey Zigachev 	/* XXX check mode bandwidth */
1165*b843c749SSergey Zigachev 
1166*b843c749SSergey Zigachev 	if (amdgpu_connector->use_digital && (mode->clock > 165000)) {
1167*b843c749SSergey Zigachev 		if ((amdgpu_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I) ||
1168*b843c749SSergey Zigachev 		    (amdgpu_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
1169*b843c749SSergey Zigachev 		    (amdgpu_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B)) {
1170*b843c749SSergey Zigachev 			return MODE_OK;
1171*b843c749SSergey Zigachev 		} else if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
1172*b843c749SSergey Zigachev 			/* HDMI 1.3+ supports max clock of 340 Mhz */
1173*b843c749SSergey Zigachev 			if (mode->clock > 340000)
1174*b843c749SSergey Zigachev 				return MODE_CLOCK_HIGH;
1175*b843c749SSergey Zigachev 			else
1176*b843c749SSergey Zigachev 				return MODE_OK;
1177*b843c749SSergey Zigachev 		} else {
1178*b843c749SSergey Zigachev 			return MODE_CLOCK_HIGH;
1179*b843c749SSergey Zigachev 		}
1180*b843c749SSergey Zigachev 	}
1181*b843c749SSergey Zigachev 
1182*b843c749SSergey Zigachev 	/* check against the max pixel clock */
1183*b843c749SSergey Zigachev 	if ((mode->clock / 10) > adev->clock.max_pixel_clock)
1184*b843c749SSergey Zigachev 		return MODE_CLOCK_HIGH;
1185*b843c749SSergey Zigachev 
1186*b843c749SSergey Zigachev 	return MODE_OK;
1187*b843c749SSergey Zigachev }
1188*b843c749SSergey Zigachev 
1189*b843c749SSergey Zigachev static const struct drm_connector_helper_funcs amdgpu_connector_dvi_helper_funcs = {
1190*b843c749SSergey Zigachev 	.get_modes = amdgpu_connector_vga_get_modes,
1191*b843c749SSergey Zigachev 	.mode_valid = amdgpu_connector_dvi_mode_valid,
1192*b843c749SSergey Zigachev 	.best_encoder = amdgpu_connector_dvi_encoder,
1193*b843c749SSergey Zigachev };
1194*b843c749SSergey Zigachev 
1195*b843c749SSergey Zigachev static const struct drm_connector_funcs amdgpu_connector_dvi_funcs = {
1196*b843c749SSergey Zigachev 	.dpms = drm_helper_connector_dpms,
1197*b843c749SSergey Zigachev 	.detect = amdgpu_connector_dvi_detect,
1198*b843c749SSergey Zigachev 	.fill_modes = drm_helper_probe_single_connector_modes,
1199*b843c749SSergey Zigachev 	.set_property = amdgpu_connector_set_property,
1200*b843c749SSergey Zigachev 	.early_unregister = amdgpu_connector_unregister,
1201*b843c749SSergey Zigachev 	.destroy = amdgpu_connector_destroy,
1202*b843c749SSergey Zigachev 	.force = amdgpu_connector_dvi_force,
1203*b843c749SSergey Zigachev };
1204*b843c749SSergey Zigachev 
1205*b843c749SSergey Zigachev static int amdgpu_connector_dp_get_modes(struct drm_connector *connector)
1206*b843c749SSergey Zigachev {
1207*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
1208*b843c749SSergey Zigachev 	struct amdgpu_connector_atom_dig *amdgpu_dig_connector = amdgpu_connector->con_priv;
1209*b843c749SSergey Zigachev 	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
1210*b843c749SSergey Zigachev 	int ret;
1211*b843c749SSergey Zigachev 
1212*b843c749SSergey Zigachev 	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
1213*b843c749SSergey Zigachev 	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
1214*b843c749SSergey Zigachev 		struct drm_display_mode *mode;
1215*b843c749SSergey Zigachev 
1216*b843c749SSergey Zigachev 		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
1217*b843c749SSergey Zigachev 			if (!amdgpu_dig_connector->edp_on)
1218*b843c749SSergey Zigachev 				amdgpu_atombios_encoder_set_edp_panel_power(connector,
1219*b843c749SSergey Zigachev 								     ATOM_TRANSMITTER_ACTION_POWER_ON);
1220*b843c749SSergey Zigachev 			amdgpu_connector_get_edid(connector);
1221*b843c749SSergey Zigachev 			ret = amdgpu_connector_ddc_get_modes(connector);
1222*b843c749SSergey Zigachev 			if (!amdgpu_dig_connector->edp_on)
1223*b843c749SSergey Zigachev 				amdgpu_atombios_encoder_set_edp_panel_power(connector,
1224*b843c749SSergey Zigachev 								     ATOM_TRANSMITTER_ACTION_POWER_OFF);
1225*b843c749SSergey Zigachev 		} else {
1226*b843c749SSergey Zigachev 			/* need to setup ddc on the bridge */
1227*b843c749SSergey Zigachev 			if (amdgpu_connector_encoder_get_dp_bridge_encoder_id(connector) !=
1228*b843c749SSergey Zigachev 			    ENCODER_OBJECT_ID_NONE) {
1229*b843c749SSergey Zigachev 				if (encoder)
1230*b843c749SSergey Zigachev 					amdgpu_atombios_encoder_setup_ext_encoder_ddc(encoder);
1231*b843c749SSergey Zigachev 			}
1232*b843c749SSergey Zigachev 			amdgpu_connector_get_edid(connector);
1233*b843c749SSergey Zigachev 			ret = amdgpu_connector_ddc_get_modes(connector);
1234*b843c749SSergey Zigachev 		}
1235*b843c749SSergey Zigachev 
1236*b843c749SSergey Zigachev 		if (ret > 0) {
1237*b843c749SSergey Zigachev 			if (encoder) {
1238*b843c749SSergey Zigachev 				amdgpu_connector_fixup_lcd_native_mode(encoder, connector);
1239*b843c749SSergey Zigachev 				/* add scaled modes */
1240*b843c749SSergey Zigachev 				amdgpu_connector_add_common_modes(encoder, connector);
1241*b843c749SSergey Zigachev 			}
1242*b843c749SSergey Zigachev 			return ret;
1243*b843c749SSergey Zigachev 		}
1244*b843c749SSergey Zigachev 
1245*b843c749SSergey Zigachev 		if (!encoder)
1246*b843c749SSergey Zigachev 			return 0;
1247*b843c749SSergey Zigachev 
1248*b843c749SSergey Zigachev 		/* we have no EDID modes */
1249*b843c749SSergey Zigachev 		mode = amdgpu_connector_lcd_native_mode(encoder);
1250*b843c749SSergey Zigachev 		if (mode) {
1251*b843c749SSergey Zigachev 			ret = 1;
1252*b843c749SSergey Zigachev 			drm_mode_probed_add(connector, mode);
1253*b843c749SSergey Zigachev 			/* add the width/height from vbios tables if available */
1254*b843c749SSergey Zigachev 			connector->display_info.width_mm = mode->width_mm;
1255*b843c749SSergey Zigachev 			connector->display_info.height_mm = mode->height_mm;
1256*b843c749SSergey Zigachev 			/* add scaled modes */
1257*b843c749SSergey Zigachev 			amdgpu_connector_add_common_modes(encoder, connector);
1258*b843c749SSergey Zigachev 		}
1259*b843c749SSergey Zigachev 	} else {
1260*b843c749SSergey Zigachev 		/* need to setup ddc on the bridge */
1261*b843c749SSergey Zigachev 		if (amdgpu_connector_encoder_get_dp_bridge_encoder_id(connector) !=
1262*b843c749SSergey Zigachev 			ENCODER_OBJECT_ID_NONE) {
1263*b843c749SSergey Zigachev 			if (encoder)
1264*b843c749SSergey Zigachev 				amdgpu_atombios_encoder_setup_ext_encoder_ddc(encoder);
1265*b843c749SSergey Zigachev 		}
1266*b843c749SSergey Zigachev 		amdgpu_connector_get_edid(connector);
1267*b843c749SSergey Zigachev 		ret = amdgpu_connector_ddc_get_modes(connector);
1268*b843c749SSergey Zigachev 
1269*b843c749SSergey Zigachev 		amdgpu_get_native_mode(connector);
1270*b843c749SSergey Zigachev 	}
1271*b843c749SSergey Zigachev 
1272*b843c749SSergey Zigachev 	return ret;
1273*b843c749SSergey Zigachev }
1274*b843c749SSergey Zigachev 
1275*b843c749SSergey Zigachev u16 amdgpu_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector)
1276*b843c749SSergey Zigachev {
1277*b843c749SSergey Zigachev 	struct drm_encoder *encoder;
1278*b843c749SSergey Zigachev 	struct amdgpu_encoder *amdgpu_encoder;
1279*b843c749SSergey Zigachev 	int i;
1280*b843c749SSergey Zigachev 
1281*b843c749SSergey Zigachev 	drm_connector_for_each_possible_encoder(connector, encoder, i) {
1282*b843c749SSergey Zigachev 		amdgpu_encoder = to_amdgpu_encoder(encoder);
1283*b843c749SSergey Zigachev 
1284*b843c749SSergey Zigachev 		switch (amdgpu_encoder->encoder_id) {
1285*b843c749SSergey Zigachev 		case ENCODER_OBJECT_ID_TRAVIS:
1286*b843c749SSergey Zigachev 		case ENCODER_OBJECT_ID_NUTMEG:
1287*b843c749SSergey Zigachev 			return amdgpu_encoder->encoder_id;
1288*b843c749SSergey Zigachev 		default:
1289*b843c749SSergey Zigachev 			break;
1290*b843c749SSergey Zigachev 		}
1291*b843c749SSergey Zigachev 	}
1292*b843c749SSergey Zigachev 
1293*b843c749SSergey Zigachev 	return ENCODER_OBJECT_ID_NONE;
1294*b843c749SSergey Zigachev }
1295*b843c749SSergey Zigachev 
1296*b843c749SSergey Zigachev static bool amdgpu_connector_encoder_is_hbr2(struct drm_connector *connector)
1297*b843c749SSergey Zigachev {
1298*b843c749SSergey Zigachev 	struct drm_encoder *encoder;
1299*b843c749SSergey Zigachev 	struct amdgpu_encoder *amdgpu_encoder;
1300*b843c749SSergey Zigachev 	int i;
1301*b843c749SSergey Zigachev 	bool found = false;
1302*b843c749SSergey Zigachev 
1303*b843c749SSergey Zigachev 	drm_connector_for_each_possible_encoder(connector, encoder, i) {
1304*b843c749SSergey Zigachev 		amdgpu_encoder = to_amdgpu_encoder(encoder);
1305*b843c749SSergey Zigachev 		if (amdgpu_encoder->caps & ATOM_ENCODER_CAP_RECORD_HBR2)
1306*b843c749SSergey Zigachev 			found = true;
1307*b843c749SSergey Zigachev 	}
1308*b843c749SSergey Zigachev 
1309*b843c749SSergey Zigachev 	return found;
1310*b843c749SSergey Zigachev }
1311*b843c749SSergey Zigachev 
1312*b843c749SSergey Zigachev bool amdgpu_connector_is_dp12_capable(struct drm_connector *connector)
1313*b843c749SSergey Zigachev {
1314*b843c749SSergey Zigachev 	struct drm_device *dev = connector->dev;
1315*b843c749SSergey Zigachev 	struct amdgpu_device *adev = dev->dev_private;
1316*b843c749SSergey Zigachev 
1317*b843c749SSergey Zigachev 	if ((adev->clock.default_dispclk >= 53900) &&
1318*b843c749SSergey Zigachev 	    amdgpu_connector_encoder_is_hbr2(connector)) {
1319*b843c749SSergey Zigachev 		return true;
1320*b843c749SSergey Zigachev 	}
1321*b843c749SSergey Zigachev 
1322*b843c749SSergey Zigachev 	return false;
1323*b843c749SSergey Zigachev }
1324*b843c749SSergey Zigachev 
1325*b843c749SSergey Zigachev static enum drm_connector_status
1326*b843c749SSergey Zigachev amdgpu_connector_dp_detect(struct drm_connector *connector, bool force)
1327*b843c749SSergey Zigachev {
1328*b843c749SSergey Zigachev 	struct drm_device *dev = connector->dev;
1329*b843c749SSergey Zigachev 	struct amdgpu_device *adev = dev->dev_private;
1330*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
1331*b843c749SSergey Zigachev 	enum drm_connector_status ret = connector_status_disconnected;
1332*b843c749SSergey Zigachev 	struct amdgpu_connector_atom_dig *amdgpu_dig_connector = amdgpu_connector->con_priv;
1333*b843c749SSergey Zigachev 	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
1334*b843c749SSergey Zigachev 	int r;
1335*b843c749SSergey Zigachev 
1336*b843c749SSergey Zigachev 	if (!drm_kms_helper_is_poll_worker()) {
1337*b843c749SSergey Zigachev 		r = pm_runtime_get_sync(connector->dev->dev);
1338*b843c749SSergey Zigachev 		if (r < 0) {
1339*b843c749SSergey Zigachev 			pm_runtime_put_autosuspend(connector->dev->dev);
1340*b843c749SSergey Zigachev 			return connector_status_disconnected;
1341*b843c749SSergey Zigachev 		}
1342*b843c749SSergey Zigachev 	}
1343*b843c749SSergey Zigachev 
1344*b843c749SSergey Zigachev 	if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) {
1345*b843c749SSergey Zigachev 		ret = connector->status;
1346*b843c749SSergey Zigachev 		goto out;
1347*b843c749SSergey Zigachev 	}
1348*b843c749SSergey Zigachev 
1349*b843c749SSergey Zigachev 	amdgpu_connector_free_edid(connector);
1350*b843c749SSergey Zigachev 
1351*b843c749SSergey Zigachev 	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
1352*b843c749SSergey Zigachev 	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
1353*b843c749SSergey Zigachev 		if (encoder) {
1354*b843c749SSergey Zigachev 			struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
1355*b843c749SSergey Zigachev 			struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
1356*b843c749SSergey Zigachev 
1357*b843c749SSergey Zigachev 			/* check if panel is valid */
1358*b843c749SSergey Zigachev 			if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240)
1359*b843c749SSergey Zigachev 				ret = connector_status_connected;
1360*b843c749SSergey Zigachev 		}
1361*b843c749SSergey Zigachev 		/* eDP is always DP */
1362*b843c749SSergey Zigachev 		amdgpu_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT;
1363*b843c749SSergey Zigachev 		if (!amdgpu_dig_connector->edp_on)
1364*b843c749SSergey Zigachev 			amdgpu_atombios_encoder_set_edp_panel_power(connector,
1365*b843c749SSergey Zigachev 							     ATOM_TRANSMITTER_ACTION_POWER_ON);
1366*b843c749SSergey Zigachev 		if (!amdgpu_atombios_dp_get_dpcd(amdgpu_connector))
1367*b843c749SSergey Zigachev 			ret = connector_status_connected;
1368*b843c749SSergey Zigachev 		if (!amdgpu_dig_connector->edp_on)
1369*b843c749SSergey Zigachev 			amdgpu_atombios_encoder_set_edp_panel_power(connector,
1370*b843c749SSergey Zigachev 							     ATOM_TRANSMITTER_ACTION_POWER_OFF);
1371*b843c749SSergey Zigachev 	} else if (amdgpu_connector_encoder_get_dp_bridge_encoder_id(connector) !=
1372*b843c749SSergey Zigachev 		   ENCODER_OBJECT_ID_NONE) {
1373*b843c749SSergey Zigachev 		/* DP bridges are always DP */
1374*b843c749SSergey Zigachev 		amdgpu_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT;
1375*b843c749SSergey Zigachev 		/* get the DPCD from the bridge */
1376*b843c749SSergey Zigachev 		amdgpu_atombios_dp_get_dpcd(amdgpu_connector);
1377*b843c749SSergey Zigachev 
1378*b843c749SSergey Zigachev 		if (encoder) {
1379*b843c749SSergey Zigachev 			/* setup ddc on the bridge */
1380*b843c749SSergey Zigachev 			amdgpu_atombios_encoder_setup_ext_encoder_ddc(encoder);
1381*b843c749SSergey Zigachev 			/* bridge chips are always aux */
1382*b843c749SSergey Zigachev 			/* try DDC */
1383*b843c749SSergey Zigachev 			if (amdgpu_display_ddc_probe(amdgpu_connector, true))
1384*b843c749SSergey Zigachev 				ret = connector_status_connected;
1385*b843c749SSergey Zigachev 			else if (amdgpu_connector->dac_load_detect) { /* try load detection */
1386*b843c749SSergey Zigachev 				const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
1387*b843c749SSergey Zigachev 				ret = encoder_funcs->detect(encoder, connector);
1388*b843c749SSergey Zigachev 			}
1389*b843c749SSergey Zigachev 		}
1390*b843c749SSergey Zigachev 	} else {
1391*b843c749SSergey Zigachev 		amdgpu_dig_connector->dp_sink_type =
1392*b843c749SSergey Zigachev 			amdgpu_atombios_dp_get_sinktype(amdgpu_connector);
1393*b843c749SSergey Zigachev 		if (amdgpu_display_hpd_sense(adev, amdgpu_connector->hpd.hpd)) {
1394*b843c749SSergey Zigachev 			ret = connector_status_connected;
1395*b843c749SSergey Zigachev 			if (amdgpu_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT)
1396*b843c749SSergey Zigachev 				amdgpu_atombios_dp_get_dpcd(amdgpu_connector);
1397*b843c749SSergey Zigachev 		} else {
1398*b843c749SSergey Zigachev 			if (amdgpu_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
1399*b843c749SSergey Zigachev 				if (!amdgpu_atombios_dp_get_dpcd(amdgpu_connector))
1400*b843c749SSergey Zigachev 					ret = connector_status_connected;
1401*b843c749SSergey Zigachev 			} else {
1402*b843c749SSergey Zigachev 				/* try non-aux ddc (DP to DVI/HDMI/etc. adapter) */
1403*b843c749SSergey Zigachev 				if (amdgpu_display_ddc_probe(amdgpu_connector,
1404*b843c749SSergey Zigachev 							     false))
1405*b843c749SSergey Zigachev 					ret = connector_status_connected;
1406*b843c749SSergey Zigachev 			}
1407*b843c749SSergey Zigachev 		}
1408*b843c749SSergey Zigachev 	}
1409*b843c749SSergey Zigachev 
1410*b843c749SSergey Zigachev 	amdgpu_connector_update_scratch_regs(connector, ret);
1411*b843c749SSergey Zigachev out:
1412*b843c749SSergey Zigachev 	if (!drm_kms_helper_is_poll_worker()) {
1413*b843c749SSergey Zigachev 		pm_runtime_mark_last_busy(connector->dev->dev);
1414*b843c749SSergey Zigachev 		pm_runtime_put_autosuspend(connector->dev->dev);
1415*b843c749SSergey Zigachev 	}
1416*b843c749SSergey Zigachev 
1417*b843c749SSergey Zigachev 	return ret;
1418*b843c749SSergey Zigachev }
1419*b843c749SSergey Zigachev 
1420*b843c749SSergey Zigachev static enum drm_mode_status amdgpu_connector_dp_mode_valid(struct drm_connector *connector,
1421*b843c749SSergey Zigachev 					   struct drm_display_mode *mode)
1422*b843c749SSergey Zigachev {
1423*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
1424*b843c749SSergey Zigachev 	struct amdgpu_connector_atom_dig *amdgpu_dig_connector = amdgpu_connector->con_priv;
1425*b843c749SSergey Zigachev 
1426*b843c749SSergey Zigachev 	/* XXX check mode bandwidth */
1427*b843c749SSergey Zigachev 
1428*b843c749SSergey Zigachev 	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
1429*b843c749SSergey Zigachev 	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
1430*b843c749SSergey Zigachev 		struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
1431*b843c749SSergey Zigachev 
1432*b843c749SSergey Zigachev 		if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
1433*b843c749SSergey Zigachev 			return MODE_PANEL;
1434*b843c749SSergey Zigachev 
1435*b843c749SSergey Zigachev 		if (encoder) {
1436*b843c749SSergey Zigachev 			struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
1437*b843c749SSergey Zigachev 			struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
1438*b843c749SSergey Zigachev 
1439*b843c749SSergey Zigachev 			/* AVIVO hardware supports downscaling modes larger than the panel
1440*b843c749SSergey Zigachev 			 * to the panel size, but I'm not sure this is desirable.
1441*b843c749SSergey Zigachev 			 */
1442*b843c749SSergey Zigachev 			if ((mode->hdisplay > native_mode->hdisplay) ||
1443*b843c749SSergey Zigachev 			    (mode->vdisplay > native_mode->vdisplay))
1444*b843c749SSergey Zigachev 				return MODE_PANEL;
1445*b843c749SSergey Zigachev 
1446*b843c749SSergey Zigachev 			/* if scaling is disabled, block non-native modes */
1447*b843c749SSergey Zigachev 			if (amdgpu_encoder->rmx_type == RMX_OFF) {
1448*b843c749SSergey Zigachev 				if ((mode->hdisplay != native_mode->hdisplay) ||
1449*b843c749SSergey Zigachev 				    (mode->vdisplay != native_mode->vdisplay))
1450*b843c749SSergey Zigachev 					return MODE_PANEL;
1451*b843c749SSergey Zigachev 			}
1452*b843c749SSergey Zigachev 		}
1453*b843c749SSergey Zigachev 		return MODE_OK;
1454*b843c749SSergey Zigachev 	} else {
1455*b843c749SSergey Zigachev 		if ((amdgpu_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
1456*b843c749SSergey Zigachev 		    (amdgpu_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
1457*b843c749SSergey Zigachev 			return amdgpu_atombios_dp_mode_valid_helper(connector, mode);
1458*b843c749SSergey Zigachev 		} else {
1459*b843c749SSergey Zigachev 			if (drm_detect_hdmi_monitor(amdgpu_connector_edid(connector))) {
1460*b843c749SSergey Zigachev 				/* HDMI 1.3+ supports max clock of 340 Mhz */
1461*b843c749SSergey Zigachev 				if (mode->clock > 340000)
1462*b843c749SSergey Zigachev 					return MODE_CLOCK_HIGH;
1463*b843c749SSergey Zigachev 			} else {
1464*b843c749SSergey Zigachev 				if (mode->clock > 165000)
1465*b843c749SSergey Zigachev 					return MODE_CLOCK_HIGH;
1466*b843c749SSergey Zigachev 			}
1467*b843c749SSergey Zigachev 		}
1468*b843c749SSergey Zigachev 	}
1469*b843c749SSergey Zigachev 
1470*b843c749SSergey Zigachev 	return MODE_OK;
1471*b843c749SSergey Zigachev }
1472*b843c749SSergey Zigachev 
1473*b843c749SSergey Zigachev static const struct drm_connector_helper_funcs amdgpu_connector_dp_helper_funcs = {
1474*b843c749SSergey Zigachev 	.get_modes = amdgpu_connector_dp_get_modes,
1475*b843c749SSergey Zigachev 	.mode_valid = amdgpu_connector_dp_mode_valid,
1476*b843c749SSergey Zigachev 	.best_encoder = amdgpu_connector_dvi_encoder,
1477*b843c749SSergey Zigachev };
1478*b843c749SSergey Zigachev 
1479*b843c749SSergey Zigachev static const struct drm_connector_funcs amdgpu_connector_dp_funcs = {
1480*b843c749SSergey Zigachev 	.dpms = drm_helper_connector_dpms,
1481*b843c749SSergey Zigachev 	.detect = amdgpu_connector_dp_detect,
1482*b843c749SSergey Zigachev 	.fill_modes = drm_helper_probe_single_connector_modes,
1483*b843c749SSergey Zigachev 	.set_property = amdgpu_connector_set_property,
1484*b843c749SSergey Zigachev 	.early_unregister = amdgpu_connector_unregister,
1485*b843c749SSergey Zigachev 	.destroy = amdgpu_connector_destroy,
1486*b843c749SSergey Zigachev 	.force = amdgpu_connector_dvi_force,
1487*b843c749SSergey Zigachev };
1488*b843c749SSergey Zigachev 
1489*b843c749SSergey Zigachev static const struct drm_connector_funcs amdgpu_connector_edp_funcs = {
1490*b843c749SSergey Zigachev 	.dpms = drm_helper_connector_dpms,
1491*b843c749SSergey Zigachev 	.detect = amdgpu_connector_dp_detect,
1492*b843c749SSergey Zigachev 	.fill_modes = drm_helper_probe_single_connector_modes,
1493*b843c749SSergey Zigachev 	.set_property = amdgpu_connector_set_lcd_property,
1494*b843c749SSergey Zigachev 	.early_unregister = amdgpu_connector_unregister,
1495*b843c749SSergey Zigachev 	.destroy = amdgpu_connector_destroy,
1496*b843c749SSergey Zigachev 	.force = amdgpu_connector_dvi_force,
1497*b843c749SSergey Zigachev };
1498*b843c749SSergey Zigachev 
1499*b843c749SSergey Zigachev void
1500*b843c749SSergey Zigachev amdgpu_connector_add(struct amdgpu_device *adev,
1501*b843c749SSergey Zigachev 		      uint32_t connector_id,
1502*b843c749SSergey Zigachev 		      uint32_t supported_device,
1503*b843c749SSergey Zigachev 		      int connector_type,
1504*b843c749SSergey Zigachev 		      struct amdgpu_i2c_bus_rec *i2c_bus,
1505*b843c749SSergey Zigachev 		      uint16_t connector_object_id,
1506*b843c749SSergey Zigachev 		      struct amdgpu_hpd *hpd,
1507*b843c749SSergey Zigachev 		      struct amdgpu_router *router)
1508*b843c749SSergey Zigachev {
1509*b843c749SSergey Zigachev 	struct drm_device *dev = adev->ddev;
1510*b843c749SSergey Zigachev 	struct drm_connector *connector;
1511*b843c749SSergey Zigachev 	struct amdgpu_connector *amdgpu_connector;
1512*b843c749SSergey Zigachev 	struct amdgpu_connector_atom_dig *amdgpu_dig_connector;
1513*b843c749SSergey Zigachev 	struct drm_encoder *encoder;
1514*b843c749SSergey Zigachev 	struct amdgpu_encoder *amdgpu_encoder;
1515*b843c749SSergey Zigachev 	uint32_t subpixel_order = SubPixelNone;
1516*b843c749SSergey Zigachev 	bool shared_ddc = false;
1517*b843c749SSergey Zigachev 	bool is_dp_bridge = false;
1518*b843c749SSergey Zigachev 	bool has_aux = false;
1519*b843c749SSergey Zigachev 
1520*b843c749SSergey Zigachev 	if (connector_type == DRM_MODE_CONNECTOR_Unknown)
1521*b843c749SSergey Zigachev 		return;
1522*b843c749SSergey Zigachev 
1523*b843c749SSergey Zigachev 	/* see if we already added it */
1524*b843c749SSergey Zigachev 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1525*b843c749SSergey Zigachev 		amdgpu_connector = to_amdgpu_connector(connector);
1526*b843c749SSergey Zigachev 		if (amdgpu_connector->connector_id == connector_id) {
1527*b843c749SSergey Zigachev 			amdgpu_connector->devices |= supported_device;
1528*b843c749SSergey Zigachev 			return;
1529*b843c749SSergey Zigachev 		}
1530*b843c749SSergey Zigachev 		if (amdgpu_connector->ddc_bus && i2c_bus->valid) {
1531*b843c749SSergey Zigachev 			if (amdgpu_connector->ddc_bus->rec.i2c_id == i2c_bus->i2c_id) {
1532*b843c749SSergey Zigachev 				amdgpu_connector->shared_ddc = true;
1533*b843c749SSergey Zigachev 				shared_ddc = true;
1534*b843c749SSergey Zigachev 			}
1535*b843c749SSergey Zigachev 			if (amdgpu_connector->router_bus && router->ddc_valid &&
1536*b843c749SSergey Zigachev 			    (amdgpu_connector->router.router_id == router->router_id)) {
1537*b843c749SSergey Zigachev 				amdgpu_connector->shared_ddc = false;
1538*b843c749SSergey Zigachev 				shared_ddc = false;
1539*b843c749SSergey Zigachev 			}
1540*b843c749SSergey Zigachev 		}
1541*b843c749SSergey Zigachev 	}
1542*b843c749SSergey Zigachev 
1543*b843c749SSergey Zigachev 	/* check if it's a dp bridge */
1544*b843c749SSergey Zigachev 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
1545*b843c749SSergey Zigachev 		amdgpu_encoder = to_amdgpu_encoder(encoder);
1546*b843c749SSergey Zigachev 		if (amdgpu_encoder->devices & supported_device) {
1547*b843c749SSergey Zigachev 			switch (amdgpu_encoder->encoder_id) {
1548*b843c749SSergey Zigachev 			case ENCODER_OBJECT_ID_TRAVIS:
1549*b843c749SSergey Zigachev 			case ENCODER_OBJECT_ID_NUTMEG:
1550*b843c749SSergey Zigachev 				is_dp_bridge = true;
1551*b843c749SSergey Zigachev 				break;
1552*b843c749SSergey Zigachev 			default:
1553*b843c749SSergey Zigachev 				break;
1554*b843c749SSergey Zigachev 			}
1555*b843c749SSergey Zigachev 		}
1556*b843c749SSergey Zigachev 	}
1557*b843c749SSergey Zigachev 
1558*b843c749SSergey Zigachev 	amdgpu_connector = kzalloc(sizeof(struct amdgpu_connector), GFP_KERNEL);
1559*b843c749SSergey Zigachev 	if (!amdgpu_connector)
1560*b843c749SSergey Zigachev 		return;
1561*b843c749SSergey Zigachev 
1562*b843c749SSergey Zigachev 	connector = &amdgpu_connector->base;
1563*b843c749SSergey Zigachev 
1564*b843c749SSergey Zigachev 	amdgpu_connector->connector_id = connector_id;
1565*b843c749SSergey Zigachev 	amdgpu_connector->devices = supported_device;
1566*b843c749SSergey Zigachev 	amdgpu_connector->shared_ddc = shared_ddc;
1567*b843c749SSergey Zigachev 	amdgpu_connector->connector_object_id = connector_object_id;
1568*b843c749SSergey Zigachev 	amdgpu_connector->hpd = *hpd;
1569*b843c749SSergey Zigachev 
1570*b843c749SSergey Zigachev 	amdgpu_connector->router = *router;
1571*b843c749SSergey Zigachev 	if (router->ddc_valid || router->cd_valid) {
1572*b843c749SSergey Zigachev 		amdgpu_connector->router_bus = amdgpu_i2c_lookup(adev, &router->i2c_info);
1573*b843c749SSergey Zigachev 		if (!amdgpu_connector->router_bus)
1574*b843c749SSergey Zigachev 			DRM_ERROR("Failed to assign router i2c bus! Check dmesg for i2c errors.\n");
1575*b843c749SSergey Zigachev 	}
1576*b843c749SSergey Zigachev 
1577*b843c749SSergey Zigachev 	if (is_dp_bridge) {
1578*b843c749SSergey Zigachev 		amdgpu_dig_connector = kzalloc(sizeof(struct amdgpu_connector_atom_dig), GFP_KERNEL);
1579*b843c749SSergey Zigachev 		if (!amdgpu_dig_connector)
1580*b843c749SSergey Zigachev 			goto failed;
1581*b843c749SSergey Zigachev 		amdgpu_connector->con_priv = amdgpu_dig_connector;
1582*b843c749SSergey Zigachev 		if (i2c_bus->valid) {
1583*b843c749SSergey Zigachev 			amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus);
1584*b843c749SSergey Zigachev 			if (amdgpu_connector->ddc_bus)
1585*b843c749SSergey Zigachev 				has_aux = true;
1586*b843c749SSergey Zigachev 			else
1587*b843c749SSergey Zigachev 				DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
1588*b843c749SSergey Zigachev 		}
1589*b843c749SSergey Zigachev 		switch (connector_type) {
1590*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_VGA:
1591*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_DVIA:
1592*b843c749SSergey Zigachev 		default:
1593*b843c749SSergey Zigachev 			drm_connector_init(dev, &amdgpu_connector->base,
1594*b843c749SSergey Zigachev 					   &amdgpu_connector_dp_funcs, connector_type);
1595*b843c749SSergey Zigachev 			drm_connector_helper_add(&amdgpu_connector->base,
1596*b843c749SSergey Zigachev 						 &amdgpu_connector_dp_helper_funcs);
1597*b843c749SSergey Zigachev 			connector->interlace_allowed = true;
1598*b843c749SSergey Zigachev 			connector->doublescan_allowed = true;
1599*b843c749SSergey Zigachev 			amdgpu_connector->dac_load_detect = true;
1600*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1601*b843c749SSergey Zigachev 						      adev->mode_info.load_detect_property,
1602*b843c749SSergey Zigachev 						      1);
1603*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1604*b843c749SSergey Zigachev 						   dev->mode_config.scaling_mode_property,
1605*b843c749SSergey Zigachev 						   DRM_MODE_SCALE_NONE);
1606*b843c749SSergey Zigachev 			break;
1607*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_DVII:
1608*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_DVID:
1609*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_HDMIA:
1610*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_HDMIB:
1611*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_DisplayPort:
1612*b843c749SSergey Zigachev 			drm_connector_init(dev, &amdgpu_connector->base,
1613*b843c749SSergey Zigachev 					   &amdgpu_connector_dp_funcs, connector_type);
1614*b843c749SSergey Zigachev 			drm_connector_helper_add(&amdgpu_connector->base,
1615*b843c749SSergey Zigachev 						 &amdgpu_connector_dp_helper_funcs);
1616*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1617*b843c749SSergey Zigachev 						      adev->mode_info.underscan_property,
1618*b843c749SSergey Zigachev 						      UNDERSCAN_OFF);
1619*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1620*b843c749SSergey Zigachev 						      adev->mode_info.underscan_hborder_property,
1621*b843c749SSergey Zigachev 						      0);
1622*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1623*b843c749SSergey Zigachev 						      adev->mode_info.underscan_vborder_property,
1624*b843c749SSergey Zigachev 						      0);
1625*b843c749SSergey Zigachev 
1626*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1627*b843c749SSergey Zigachev 						   dev->mode_config.scaling_mode_property,
1628*b843c749SSergey Zigachev 						   DRM_MODE_SCALE_NONE);
1629*b843c749SSergey Zigachev 
1630*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1631*b843c749SSergey Zigachev 						   adev->mode_info.dither_property,
1632*b843c749SSergey Zigachev 						   AMDGPU_FMT_DITHER_DISABLE);
1633*b843c749SSergey Zigachev 
1634*b843c749SSergey Zigachev 			if (amdgpu_audio != 0)
1635*b843c749SSergey Zigachev 				drm_object_attach_property(&amdgpu_connector->base.base,
1636*b843c749SSergey Zigachev 							   adev->mode_info.audio_property,
1637*b843c749SSergey Zigachev 							   AMDGPU_AUDIO_AUTO);
1638*b843c749SSergey Zigachev 
1639*b843c749SSergey Zigachev 			subpixel_order = SubPixelHorizontalRGB;
1640*b843c749SSergey Zigachev 			connector->interlace_allowed = true;
1641*b843c749SSergey Zigachev 			if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
1642*b843c749SSergey Zigachev 				connector->doublescan_allowed = true;
1643*b843c749SSergey Zigachev 			else
1644*b843c749SSergey Zigachev 				connector->doublescan_allowed = false;
1645*b843c749SSergey Zigachev 			if (connector_type == DRM_MODE_CONNECTOR_DVII) {
1646*b843c749SSergey Zigachev 				amdgpu_connector->dac_load_detect = true;
1647*b843c749SSergey Zigachev 				drm_object_attach_property(&amdgpu_connector->base.base,
1648*b843c749SSergey Zigachev 							      adev->mode_info.load_detect_property,
1649*b843c749SSergey Zigachev 							      1);
1650*b843c749SSergey Zigachev 			}
1651*b843c749SSergey Zigachev 			break;
1652*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_LVDS:
1653*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_eDP:
1654*b843c749SSergey Zigachev 			drm_connector_init(dev, &amdgpu_connector->base,
1655*b843c749SSergey Zigachev 					   &amdgpu_connector_edp_funcs, connector_type);
1656*b843c749SSergey Zigachev 			drm_connector_helper_add(&amdgpu_connector->base,
1657*b843c749SSergey Zigachev 						 &amdgpu_connector_dp_helper_funcs);
1658*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1659*b843c749SSergey Zigachev 						      dev->mode_config.scaling_mode_property,
1660*b843c749SSergey Zigachev 						      DRM_MODE_SCALE_FULLSCREEN);
1661*b843c749SSergey Zigachev 			subpixel_order = SubPixelHorizontalRGB;
1662*b843c749SSergey Zigachev 			connector->interlace_allowed = false;
1663*b843c749SSergey Zigachev 			connector->doublescan_allowed = false;
1664*b843c749SSergey Zigachev 			break;
1665*b843c749SSergey Zigachev 		}
1666*b843c749SSergey Zigachev 	} else {
1667*b843c749SSergey Zigachev 		switch (connector_type) {
1668*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_VGA:
1669*b843c749SSergey Zigachev 			drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_vga_funcs, connector_type);
1670*b843c749SSergey Zigachev 			drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_vga_helper_funcs);
1671*b843c749SSergey Zigachev 			if (i2c_bus->valid) {
1672*b843c749SSergey Zigachev 				amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus);
1673*b843c749SSergey Zigachev 				if (!amdgpu_connector->ddc_bus)
1674*b843c749SSergey Zigachev 					DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
1675*b843c749SSergey Zigachev 			}
1676*b843c749SSergey Zigachev 			amdgpu_connector->dac_load_detect = true;
1677*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1678*b843c749SSergey Zigachev 						      adev->mode_info.load_detect_property,
1679*b843c749SSergey Zigachev 						      1);
1680*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1681*b843c749SSergey Zigachev 						   dev->mode_config.scaling_mode_property,
1682*b843c749SSergey Zigachev 						   DRM_MODE_SCALE_NONE);
1683*b843c749SSergey Zigachev 			/* no HPD on analog connectors */
1684*b843c749SSergey Zigachev 			amdgpu_connector->hpd.hpd = AMDGPU_HPD_NONE;
1685*b843c749SSergey Zigachev 			connector->interlace_allowed = true;
1686*b843c749SSergey Zigachev 			connector->doublescan_allowed = true;
1687*b843c749SSergey Zigachev 			break;
1688*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_DVIA:
1689*b843c749SSergey Zigachev 			drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_vga_funcs, connector_type);
1690*b843c749SSergey Zigachev 			drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_vga_helper_funcs);
1691*b843c749SSergey Zigachev 			if (i2c_bus->valid) {
1692*b843c749SSergey Zigachev 				amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus);
1693*b843c749SSergey Zigachev 				if (!amdgpu_connector->ddc_bus)
1694*b843c749SSergey Zigachev 					DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
1695*b843c749SSergey Zigachev 			}
1696*b843c749SSergey Zigachev 			amdgpu_connector->dac_load_detect = true;
1697*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1698*b843c749SSergey Zigachev 						      adev->mode_info.load_detect_property,
1699*b843c749SSergey Zigachev 						      1);
1700*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1701*b843c749SSergey Zigachev 						   dev->mode_config.scaling_mode_property,
1702*b843c749SSergey Zigachev 						   DRM_MODE_SCALE_NONE);
1703*b843c749SSergey Zigachev 			/* no HPD on analog connectors */
1704*b843c749SSergey Zigachev 			amdgpu_connector->hpd.hpd = AMDGPU_HPD_NONE;
1705*b843c749SSergey Zigachev 			connector->interlace_allowed = true;
1706*b843c749SSergey Zigachev 			connector->doublescan_allowed = true;
1707*b843c749SSergey Zigachev 			break;
1708*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_DVII:
1709*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_DVID:
1710*b843c749SSergey Zigachev 			amdgpu_dig_connector = kzalloc(sizeof(struct amdgpu_connector_atom_dig), GFP_KERNEL);
1711*b843c749SSergey Zigachev 			if (!amdgpu_dig_connector)
1712*b843c749SSergey Zigachev 				goto failed;
1713*b843c749SSergey Zigachev 			amdgpu_connector->con_priv = amdgpu_dig_connector;
1714*b843c749SSergey Zigachev 			drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_dvi_funcs, connector_type);
1715*b843c749SSergey Zigachev 			drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dvi_helper_funcs);
1716*b843c749SSergey Zigachev 			if (i2c_bus->valid) {
1717*b843c749SSergey Zigachev 				amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus);
1718*b843c749SSergey Zigachev 				if (!amdgpu_connector->ddc_bus)
1719*b843c749SSergey Zigachev 					DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
1720*b843c749SSergey Zigachev 			}
1721*b843c749SSergey Zigachev 			subpixel_order = SubPixelHorizontalRGB;
1722*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1723*b843c749SSergey Zigachev 						      adev->mode_info.coherent_mode_property,
1724*b843c749SSergey Zigachev 						      1);
1725*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1726*b843c749SSergey Zigachev 						   adev->mode_info.underscan_property,
1727*b843c749SSergey Zigachev 						   UNDERSCAN_OFF);
1728*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1729*b843c749SSergey Zigachev 						   adev->mode_info.underscan_hborder_property,
1730*b843c749SSergey Zigachev 						   0);
1731*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1732*b843c749SSergey Zigachev 						   adev->mode_info.underscan_vborder_property,
1733*b843c749SSergey Zigachev 						   0);
1734*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1735*b843c749SSergey Zigachev 						   dev->mode_config.scaling_mode_property,
1736*b843c749SSergey Zigachev 						   DRM_MODE_SCALE_NONE);
1737*b843c749SSergey Zigachev 
1738*b843c749SSergey Zigachev 			if (amdgpu_audio != 0) {
1739*b843c749SSergey Zigachev 				drm_object_attach_property(&amdgpu_connector->base.base,
1740*b843c749SSergey Zigachev 							   adev->mode_info.audio_property,
1741*b843c749SSergey Zigachev 							   AMDGPU_AUDIO_AUTO);
1742*b843c749SSergey Zigachev 			}
1743*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1744*b843c749SSergey Zigachev 						   adev->mode_info.dither_property,
1745*b843c749SSergey Zigachev 						   AMDGPU_FMT_DITHER_DISABLE);
1746*b843c749SSergey Zigachev 			if (connector_type == DRM_MODE_CONNECTOR_DVII) {
1747*b843c749SSergey Zigachev 				amdgpu_connector->dac_load_detect = true;
1748*b843c749SSergey Zigachev 				drm_object_attach_property(&amdgpu_connector->base.base,
1749*b843c749SSergey Zigachev 							   adev->mode_info.load_detect_property,
1750*b843c749SSergey Zigachev 							   1);
1751*b843c749SSergey Zigachev 			}
1752*b843c749SSergey Zigachev 			connector->interlace_allowed = true;
1753*b843c749SSergey Zigachev 			if (connector_type == DRM_MODE_CONNECTOR_DVII)
1754*b843c749SSergey Zigachev 				connector->doublescan_allowed = true;
1755*b843c749SSergey Zigachev 			else
1756*b843c749SSergey Zigachev 				connector->doublescan_allowed = false;
1757*b843c749SSergey Zigachev 			break;
1758*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_HDMIA:
1759*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_HDMIB:
1760*b843c749SSergey Zigachev 			amdgpu_dig_connector = kzalloc(sizeof(struct amdgpu_connector_atom_dig), GFP_KERNEL);
1761*b843c749SSergey Zigachev 			if (!amdgpu_dig_connector)
1762*b843c749SSergey Zigachev 				goto failed;
1763*b843c749SSergey Zigachev 			amdgpu_connector->con_priv = amdgpu_dig_connector;
1764*b843c749SSergey Zigachev 			drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_dvi_funcs, connector_type);
1765*b843c749SSergey Zigachev 			drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dvi_helper_funcs);
1766*b843c749SSergey Zigachev 			if (i2c_bus->valid) {
1767*b843c749SSergey Zigachev 				amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus);
1768*b843c749SSergey Zigachev 				if (!amdgpu_connector->ddc_bus)
1769*b843c749SSergey Zigachev 					DRM_ERROR("HDMI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
1770*b843c749SSergey Zigachev 			}
1771*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1772*b843c749SSergey Zigachev 						      adev->mode_info.coherent_mode_property,
1773*b843c749SSergey Zigachev 						      1);
1774*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1775*b843c749SSergey Zigachev 						   adev->mode_info.underscan_property,
1776*b843c749SSergey Zigachev 						   UNDERSCAN_OFF);
1777*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1778*b843c749SSergey Zigachev 						   adev->mode_info.underscan_hborder_property,
1779*b843c749SSergey Zigachev 						   0);
1780*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1781*b843c749SSergey Zigachev 						   adev->mode_info.underscan_vborder_property,
1782*b843c749SSergey Zigachev 						   0);
1783*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1784*b843c749SSergey Zigachev 						   dev->mode_config.scaling_mode_property,
1785*b843c749SSergey Zigachev 						   DRM_MODE_SCALE_NONE);
1786*b843c749SSergey Zigachev 			if (amdgpu_audio != 0) {
1787*b843c749SSergey Zigachev 				drm_object_attach_property(&amdgpu_connector->base.base,
1788*b843c749SSergey Zigachev 							   adev->mode_info.audio_property,
1789*b843c749SSergey Zigachev 							   AMDGPU_AUDIO_AUTO);
1790*b843c749SSergey Zigachev 			}
1791*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1792*b843c749SSergey Zigachev 						   adev->mode_info.dither_property,
1793*b843c749SSergey Zigachev 						   AMDGPU_FMT_DITHER_DISABLE);
1794*b843c749SSergey Zigachev 			subpixel_order = SubPixelHorizontalRGB;
1795*b843c749SSergey Zigachev 			connector->interlace_allowed = true;
1796*b843c749SSergey Zigachev 			if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
1797*b843c749SSergey Zigachev 				connector->doublescan_allowed = true;
1798*b843c749SSergey Zigachev 			else
1799*b843c749SSergey Zigachev 				connector->doublescan_allowed = false;
1800*b843c749SSergey Zigachev 			break;
1801*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_DisplayPort:
1802*b843c749SSergey Zigachev 			amdgpu_dig_connector = kzalloc(sizeof(struct amdgpu_connector_atom_dig), GFP_KERNEL);
1803*b843c749SSergey Zigachev 			if (!amdgpu_dig_connector)
1804*b843c749SSergey Zigachev 				goto failed;
1805*b843c749SSergey Zigachev 			amdgpu_connector->con_priv = amdgpu_dig_connector;
1806*b843c749SSergey Zigachev 			drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_dp_funcs, connector_type);
1807*b843c749SSergey Zigachev 			drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dp_helper_funcs);
1808*b843c749SSergey Zigachev 			if (i2c_bus->valid) {
1809*b843c749SSergey Zigachev 				amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus);
1810*b843c749SSergey Zigachev 				if (amdgpu_connector->ddc_bus)
1811*b843c749SSergey Zigachev 					has_aux = true;
1812*b843c749SSergey Zigachev 				else
1813*b843c749SSergey Zigachev 					DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
1814*b843c749SSergey Zigachev 			}
1815*b843c749SSergey Zigachev 			subpixel_order = SubPixelHorizontalRGB;
1816*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1817*b843c749SSergey Zigachev 						      adev->mode_info.coherent_mode_property,
1818*b843c749SSergey Zigachev 						      1);
1819*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1820*b843c749SSergey Zigachev 						   adev->mode_info.underscan_property,
1821*b843c749SSergey Zigachev 						   UNDERSCAN_OFF);
1822*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1823*b843c749SSergey Zigachev 						   adev->mode_info.underscan_hborder_property,
1824*b843c749SSergey Zigachev 						   0);
1825*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1826*b843c749SSergey Zigachev 						   adev->mode_info.underscan_vborder_property,
1827*b843c749SSergey Zigachev 						   0);
1828*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1829*b843c749SSergey Zigachev 						   dev->mode_config.scaling_mode_property,
1830*b843c749SSergey Zigachev 						   DRM_MODE_SCALE_NONE);
1831*b843c749SSergey Zigachev 			if (amdgpu_audio != 0) {
1832*b843c749SSergey Zigachev 				drm_object_attach_property(&amdgpu_connector->base.base,
1833*b843c749SSergey Zigachev 							   adev->mode_info.audio_property,
1834*b843c749SSergey Zigachev 							   AMDGPU_AUDIO_AUTO);
1835*b843c749SSergey Zigachev 			}
1836*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1837*b843c749SSergey Zigachev 						   adev->mode_info.dither_property,
1838*b843c749SSergey Zigachev 						   AMDGPU_FMT_DITHER_DISABLE);
1839*b843c749SSergey Zigachev 			connector->interlace_allowed = true;
1840*b843c749SSergey Zigachev 			/* in theory with a DP to VGA converter... */
1841*b843c749SSergey Zigachev 			connector->doublescan_allowed = false;
1842*b843c749SSergey Zigachev 			break;
1843*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_eDP:
1844*b843c749SSergey Zigachev 			amdgpu_dig_connector = kzalloc(sizeof(struct amdgpu_connector_atom_dig), GFP_KERNEL);
1845*b843c749SSergey Zigachev 			if (!amdgpu_dig_connector)
1846*b843c749SSergey Zigachev 				goto failed;
1847*b843c749SSergey Zigachev 			amdgpu_connector->con_priv = amdgpu_dig_connector;
1848*b843c749SSergey Zigachev 			drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_edp_funcs, connector_type);
1849*b843c749SSergey Zigachev 			drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dp_helper_funcs);
1850*b843c749SSergey Zigachev 			if (i2c_bus->valid) {
1851*b843c749SSergey Zigachev 				amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus);
1852*b843c749SSergey Zigachev 				if (amdgpu_connector->ddc_bus)
1853*b843c749SSergey Zigachev 					has_aux = true;
1854*b843c749SSergey Zigachev 				else
1855*b843c749SSergey Zigachev 					DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
1856*b843c749SSergey Zigachev 			}
1857*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1858*b843c749SSergey Zigachev 						      dev->mode_config.scaling_mode_property,
1859*b843c749SSergey Zigachev 						      DRM_MODE_SCALE_FULLSCREEN);
1860*b843c749SSergey Zigachev 			subpixel_order = SubPixelHorizontalRGB;
1861*b843c749SSergey Zigachev 			connector->interlace_allowed = false;
1862*b843c749SSergey Zigachev 			connector->doublescan_allowed = false;
1863*b843c749SSergey Zigachev 			break;
1864*b843c749SSergey Zigachev 		case DRM_MODE_CONNECTOR_LVDS:
1865*b843c749SSergey Zigachev 			amdgpu_dig_connector = kzalloc(sizeof(struct amdgpu_connector_atom_dig), GFP_KERNEL);
1866*b843c749SSergey Zigachev 			if (!amdgpu_dig_connector)
1867*b843c749SSergey Zigachev 				goto failed;
1868*b843c749SSergey Zigachev 			amdgpu_connector->con_priv = amdgpu_dig_connector;
1869*b843c749SSergey Zigachev 			drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_lvds_funcs, connector_type);
1870*b843c749SSergey Zigachev 			drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_lvds_helper_funcs);
1871*b843c749SSergey Zigachev 			if (i2c_bus->valid) {
1872*b843c749SSergey Zigachev 				amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus);
1873*b843c749SSergey Zigachev 				if (!amdgpu_connector->ddc_bus)
1874*b843c749SSergey Zigachev 					DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
1875*b843c749SSergey Zigachev 			}
1876*b843c749SSergey Zigachev 			drm_object_attach_property(&amdgpu_connector->base.base,
1877*b843c749SSergey Zigachev 						      dev->mode_config.scaling_mode_property,
1878*b843c749SSergey Zigachev 						      DRM_MODE_SCALE_FULLSCREEN);
1879*b843c749SSergey Zigachev 			subpixel_order = SubPixelHorizontalRGB;
1880*b843c749SSergey Zigachev 			connector->interlace_allowed = false;
1881*b843c749SSergey Zigachev 			connector->doublescan_allowed = false;
1882*b843c749SSergey Zigachev 			break;
1883*b843c749SSergey Zigachev 		}
1884*b843c749SSergey Zigachev 	}
1885*b843c749SSergey Zigachev 
1886*b843c749SSergey Zigachev 	if (amdgpu_connector->hpd.hpd == AMDGPU_HPD_NONE) {
1887*b843c749SSergey Zigachev 		if (i2c_bus->valid) {
1888*b843c749SSergey Zigachev 			connector->polled = DRM_CONNECTOR_POLL_CONNECT |
1889*b843c749SSergey Zigachev 			                    DRM_CONNECTOR_POLL_DISCONNECT;
1890*b843c749SSergey Zigachev 		}
1891*b843c749SSergey Zigachev 	} else
1892*b843c749SSergey Zigachev 		connector->polled = DRM_CONNECTOR_POLL_HPD;
1893*b843c749SSergey Zigachev 
1894*b843c749SSergey Zigachev 	connector->display_info.subpixel_order = subpixel_order;
1895*b843c749SSergey Zigachev 	drm_connector_register(connector);
1896*b843c749SSergey Zigachev 
1897*b843c749SSergey Zigachev 	if (has_aux)
1898*b843c749SSergey Zigachev 		amdgpu_atombios_dp_aux_init(amdgpu_connector);
1899*b843c749SSergey Zigachev 
1900*b843c749SSergey Zigachev 	return;
1901*b843c749SSergey Zigachev 
1902*b843c749SSergey Zigachev failed:
1903*b843c749SSergey Zigachev 	drm_connector_cleanup(connector);
1904*b843c749SSergey Zigachev 	kfree(connector);
1905*b843c749SSergey Zigachev }
1906