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