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