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