1926deccbSFrançois Tigeot /*
2926deccbSFrançois Tigeot * Copyright 2007-8 Advanced Micro Devices, Inc.
3926deccbSFrançois Tigeot * Copyright 2008 Red Hat Inc.
4926deccbSFrançois Tigeot *
5926deccbSFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a
6926deccbSFrançois Tigeot * copy of this software and associated documentation files (the "Software"),
7926deccbSFrançois Tigeot * to deal in the Software without restriction, including without limitation
8926deccbSFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9926deccbSFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the
10926deccbSFrançois Tigeot * Software is furnished to do so, subject to the following conditions:
11926deccbSFrançois Tigeot *
12926deccbSFrançois Tigeot * The above copyright notice and this permission notice shall be included in
13926deccbSFrançois Tigeot * all copies or substantial portions of the Software.
14926deccbSFrançois Tigeot *
15926deccbSFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16926deccbSFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17926deccbSFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18926deccbSFrançois Tigeot * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19926deccbSFrançois Tigeot * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20926deccbSFrançois Tigeot * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21926deccbSFrançois Tigeot * OTHER DEALINGS IN THE SOFTWARE.
22926deccbSFrançois Tigeot *
23926deccbSFrançois Tigeot * Authors: Dave Airlie
24926deccbSFrançois Tigeot * Alex Deucher
25926deccbSFrançois Tigeot */
26926deccbSFrançois Tigeot #include <drm/drmP.h>
27926deccbSFrançois Tigeot #include <drm/drm_crtc_helper.h>
2883b4b9b9SFrançois Tigeot #include <drm/radeon_drm.h>
29926deccbSFrançois Tigeot #include "radeon.h"
30926deccbSFrançois Tigeot #include "atom.h"
31926deccbSFrançois Tigeot
32926deccbSFrançois Tigeot
radeon_encoder_clones(struct drm_encoder * encoder)33926deccbSFrançois Tigeot static uint32_t radeon_encoder_clones(struct drm_encoder *encoder)
34926deccbSFrançois Tigeot {
35926deccbSFrançois Tigeot struct drm_device *dev = encoder->dev;
36926deccbSFrançois Tigeot struct radeon_device *rdev = dev->dev_private;
37926deccbSFrançois Tigeot struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
38926deccbSFrançois Tigeot struct drm_encoder *clone_encoder;
39926deccbSFrançois Tigeot uint32_t index_mask = 0;
40926deccbSFrançois Tigeot int count;
41926deccbSFrançois Tigeot
42926deccbSFrançois Tigeot /* DIG routing gets problematic */
43926deccbSFrançois Tigeot if (rdev->family >= CHIP_R600)
44926deccbSFrançois Tigeot return index_mask;
45926deccbSFrançois Tigeot /* LVDS/TV are too wacky */
46926deccbSFrançois Tigeot if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT)
47926deccbSFrançois Tigeot return index_mask;
48926deccbSFrançois Tigeot /* DVO requires 2x ppll clocks depending on tmds chip */
49926deccbSFrançois Tigeot if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT)
50926deccbSFrançois Tigeot return index_mask;
51926deccbSFrançois Tigeot
52926deccbSFrançois Tigeot count = -1;
53926deccbSFrançois Tigeot list_for_each_entry(clone_encoder, &dev->mode_config.encoder_list, head) {
54926deccbSFrançois Tigeot struct radeon_encoder *radeon_clone = to_radeon_encoder(clone_encoder);
55926deccbSFrançois Tigeot count++;
56926deccbSFrançois Tigeot
57926deccbSFrançois Tigeot if (clone_encoder == encoder)
58926deccbSFrançois Tigeot continue;
59926deccbSFrançois Tigeot if (radeon_clone->devices & (ATOM_DEVICE_LCD_SUPPORT))
60926deccbSFrançois Tigeot continue;
61926deccbSFrançois Tigeot if (radeon_clone->devices & ATOM_DEVICE_DFP2_SUPPORT)
62926deccbSFrançois Tigeot continue;
63926deccbSFrançois Tigeot else
64926deccbSFrançois Tigeot index_mask |= (1 << count);
65926deccbSFrançois Tigeot }
66926deccbSFrançois Tigeot return index_mask;
67926deccbSFrançois Tigeot }
68926deccbSFrançois Tigeot
radeon_setup_encoder_clones(struct drm_device * dev)69926deccbSFrançois Tigeot void radeon_setup_encoder_clones(struct drm_device *dev)
70926deccbSFrançois Tigeot {
71926deccbSFrançois Tigeot struct drm_encoder *encoder;
72926deccbSFrançois Tigeot
73926deccbSFrançois Tigeot list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
74926deccbSFrançois Tigeot encoder->possible_clones = radeon_encoder_clones(encoder);
75926deccbSFrançois Tigeot }
76926deccbSFrançois Tigeot }
77926deccbSFrançois Tigeot
78926deccbSFrançois Tigeot uint32_t
radeon_get_encoder_enum(struct drm_device * dev,uint32_t supported_device,uint8_t dac)79926deccbSFrançois Tigeot radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, uint8_t dac)
80926deccbSFrançois Tigeot {
81926deccbSFrançois Tigeot struct radeon_device *rdev = dev->dev_private;
82926deccbSFrançois Tigeot uint32_t ret = 0;
83926deccbSFrançois Tigeot
84926deccbSFrançois Tigeot switch (supported_device) {
85926deccbSFrançois Tigeot case ATOM_DEVICE_CRT1_SUPPORT:
86926deccbSFrançois Tigeot case ATOM_DEVICE_TV1_SUPPORT:
87926deccbSFrançois Tigeot case ATOM_DEVICE_TV2_SUPPORT:
88926deccbSFrançois Tigeot case ATOM_DEVICE_CRT2_SUPPORT:
89926deccbSFrançois Tigeot case ATOM_DEVICE_CV_SUPPORT:
90926deccbSFrançois Tigeot switch (dac) {
91926deccbSFrançois Tigeot case 1: /* dac a */
92926deccbSFrançois Tigeot if ((rdev->family == CHIP_RS300) ||
93926deccbSFrançois Tigeot (rdev->family == CHIP_RS400) ||
94926deccbSFrançois Tigeot (rdev->family == CHIP_RS480))
95926deccbSFrançois Tigeot ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
96926deccbSFrançois Tigeot else if (ASIC_IS_AVIVO(rdev))
97926deccbSFrançois Tigeot ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1;
98926deccbSFrançois Tigeot else
99926deccbSFrançois Tigeot ret = ENCODER_INTERNAL_DAC1_ENUM_ID1;
100926deccbSFrançois Tigeot break;
101926deccbSFrançois Tigeot case 2: /* dac b */
102926deccbSFrançois Tigeot if (ASIC_IS_AVIVO(rdev))
103926deccbSFrançois Tigeot ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1;
104926deccbSFrançois Tigeot else {
105926deccbSFrançois Tigeot /*if (rdev->family == CHIP_R200)
106926deccbSFrançois Tigeot ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
107926deccbSFrançois Tigeot else*/
108926deccbSFrançois Tigeot ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
109926deccbSFrançois Tigeot }
110926deccbSFrançois Tigeot break;
111926deccbSFrançois Tigeot case 3: /* external dac */
112926deccbSFrançois Tigeot if (ASIC_IS_AVIVO(rdev))
113926deccbSFrançois Tigeot ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
114926deccbSFrançois Tigeot else
115926deccbSFrançois Tigeot ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
116926deccbSFrançois Tigeot break;
117926deccbSFrançois Tigeot }
118926deccbSFrançois Tigeot break;
119926deccbSFrançois Tigeot case ATOM_DEVICE_LCD1_SUPPORT:
120926deccbSFrançois Tigeot if (ASIC_IS_AVIVO(rdev))
121926deccbSFrançois Tigeot ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
122926deccbSFrançois Tigeot else
123926deccbSFrançois Tigeot ret = ENCODER_INTERNAL_LVDS_ENUM_ID1;
124926deccbSFrançois Tigeot break;
125926deccbSFrançois Tigeot case ATOM_DEVICE_DFP1_SUPPORT:
126926deccbSFrançois Tigeot if ((rdev->family == CHIP_RS300) ||
127926deccbSFrançois Tigeot (rdev->family == CHIP_RS400) ||
128926deccbSFrançois Tigeot (rdev->family == CHIP_RS480))
129926deccbSFrançois Tigeot ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
130926deccbSFrançois Tigeot else if (ASIC_IS_AVIVO(rdev))
131926deccbSFrançois Tigeot ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1;
132926deccbSFrançois Tigeot else
133926deccbSFrançois Tigeot ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1;
134926deccbSFrançois Tigeot break;
135926deccbSFrançois Tigeot case ATOM_DEVICE_LCD2_SUPPORT:
136926deccbSFrançois Tigeot case ATOM_DEVICE_DFP2_SUPPORT:
137926deccbSFrançois Tigeot if ((rdev->family == CHIP_RS600) ||
138926deccbSFrançois Tigeot (rdev->family == CHIP_RS690) ||
139926deccbSFrançois Tigeot (rdev->family == CHIP_RS740))
140926deccbSFrançois Tigeot ret = ENCODER_INTERNAL_DDI_ENUM_ID1;
141926deccbSFrançois Tigeot else if (ASIC_IS_AVIVO(rdev))
142926deccbSFrançois Tigeot ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
143926deccbSFrançois Tigeot else
144926deccbSFrançois Tigeot ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
145926deccbSFrançois Tigeot break;
146926deccbSFrançois Tigeot case ATOM_DEVICE_DFP3_SUPPORT:
147926deccbSFrançois Tigeot ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
148926deccbSFrançois Tigeot break;
149926deccbSFrançois Tigeot }
150926deccbSFrançois Tigeot
151926deccbSFrançois Tigeot return ret;
152926deccbSFrançois Tigeot }
153926deccbSFrançois Tigeot
radeon_encoder_add_backlight(struct radeon_encoder * radeon_encoder,struct drm_connector * connector)154c6f73aabSFrançois Tigeot static void radeon_encoder_add_backlight(struct radeon_encoder *radeon_encoder,
155c6f73aabSFrançois Tigeot struct drm_connector *connector)
156c6f73aabSFrançois Tigeot {
157c6f73aabSFrançois Tigeot struct drm_device *dev = radeon_encoder->base.dev;
158c6f73aabSFrançois Tigeot struct radeon_device *rdev = dev->dev_private;
159c6f73aabSFrançois Tigeot bool use_bl = false;
160c6f73aabSFrançois Tigeot
161c6f73aabSFrançois Tigeot if (!(radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)))
162c6f73aabSFrançois Tigeot return;
163c6f73aabSFrançois Tigeot
164c6f73aabSFrançois Tigeot if (radeon_backlight == 0) {
165c6f73aabSFrançois Tigeot return;
166c6f73aabSFrançois Tigeot } else if (radeon_backlight == 1) {
167c6f73aabSFrançois Tigeot use_bl = true;
168c6f73aabSFrançois Tigeot } else if (radeon_backlight == -1) {
169c6f73aabSFrançois Tigeot /* Quirks */
170c6f73aabSFrançois Tigeot /* Amilo Xi 2550 only works with acpi bl */
171c6f73aabSFrançois Tigeot if ((rdev->pdev->device == 0x9583) &&
172c6f73aabSFrançois Tigeot (rdev->pdev->subsystem_vendor == 0x1734) &&
173c6f73aabSFrançois Tigeot (rdev->pdev->subsystem_device == 0x1107))
174c6f73aabSFrançois Tigeot use_bl = false;
1757dcf36dcSFrançois Tigeot /* Older PPC macs use on-GPU backlight controller */
1767dcf36dcSFrançois Tigeot #ifndef CONFIG_PPC_PMAC
177591d5043SFrançois Tigeot /* disable native backlight control on older asics */
178591d5043SFrançois Tigeot else if (rdev->family < CHIP_R600)
179591d5043SFrançois Tigeot use_bl = false;
1807dcf36dcSFrançois Tigeot #endif
181c6f73aabSFrançois Tigeot else
182c6f73aabSFrançois Tigeot use_bl = true;
183c6f73aabSFrançois Tigeot }
184c6f73aabSFrançois Tigeot
185c6f73aabSFrançois Tigeot if (use_bl) {
186c6f73aabSFrançois Tigeot if (rdev->is_atom_bios)
187c6f73aabSFrançois Tigeot radeon_atom_backlight_init(radeon_encoder, connector);
188c6f73aabSFrançois Tigeot else
189c6f73aabSFrançois Tigeot radeon_legacy_backlight_init(radeon_encoder, connector);
190c6f73aabSFrançois Tigeot }
191c6f73aabSFrançois Tigeot }
192c6f73aabSFrançois Tigeot
193926deccbSFrançois Tigeot void
radeon_link_encoder_connector(struct drm_device * dev)194926deccbSFrançois Tigeot radeon_link_encoder_connector(struct drm_device *dev)
195926deccbSFrançois Tigeot {
196926deccbSFrançois Tigeot struct drm_connector *connector;
197926deccbSFrançois Tigeot struct radeon_connector *radeon_connector;
198926deccbSFrançois Tigeot struct drm_encoder *encoder;
199926deccbSFrançois Tigeot struct radeon_encoder *radeon_encoder;
200926deccbSFrançois Tigeot
201926deccbSFrançois Tigeot /* walk the list and link encoders to connectors */
202926deccbSFrançois Tigeot list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
203926deccbSFrançois Tigeot radeon_connector = to_radeon_connector(connector);
204926deccbSFrançois Tigeot list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
205926deccbSFrançois Tigeot radeon_encoder = to_radeon_encoder(encoder);
206926deccbSFrançois Tigeot if (radeon_encoder->devices & radeon_connector->devices) {
207926deccbSFrançois Tigeot drm_mode_connector_attach_encoder(connector, encoder);
208c6f73aabSFrançois Tigeot if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
209c6f73aabSFrançois Tigeot radeon_encoder_add_backlight(radeon_encoder, connector);
210926deccbSFrançois Tigeot }
211926deccbSFrançois Tigeot }
212926deccbSFrançois Tigeot }
213926deccbSFrançois Tigeot }
214926deccbSFrançois Tigeot
radeon_encoder_set_active_device(struct drm_encoder * encoder)215926deccbSFrançois Tigeot void radeon_encoder_set_active_device(struct drm_encoder *encoder)
216926deccbSFrançois Tigeot {
217926deccbSFrançois Tigeot struct drm_device *dev = encoder->dev;
218926deccbSFrançois Tigeot struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
219926deccbSFrançois Tigeot struct drm_connector *connector;
220926deccbSFrançois Tigeot
221926deccbSFrançois Tigeot list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
222926deccbSFrançois Tigeot if (connector->encoder == encoder) {
223926deccbSFrançois Tigeot struct radeon_connector *radeon_connector = to_radeon_connector(connector);
224926deccbSFrançois Tigeot radeon_encoder->active_device = radeon_encoder->devices & radeon_connector->devices;
225926deccbSFrançois Tigeot DRM_DEBUG_KMS("setting active device to %08x from %08x %08x for encoder %d\n",
226926deccbSFrançois Tigeot radeon_encoder->active_device, radeon_encoder->devices,
227926deccbSFrançois Tigeot radeon_connector->devices, encoder->encoder_type);
228926deccbSFrançois Tigeot }
229926deccbSFrançois Tigeot }
230926deccbSFrançois Tigeot }
231926deccbSFrançois Tigeot
232926deccbSFrançois Tigeot struct drm_connector *
radeon_get_connector_for_encoder(struct drm_encoder * encoder)233926deccbSFrançois Tigeot radeon_get_connector_for_encoder(struct drm_encoder *encoder)
234926deccbSFrançois Tigeot {
235926deccbSFrançois Tigeot struct drm_device *dev = encoder->dev;
236926deccbSFrançois Tigeot struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
237926deccbSFrançois Tigeot struct drm_connector *connector;
238926deccbSFrançois Tigeot struct radeon_connector *radeon_connector;
239926deccbSFrançois Tigeot
240926deccbSFrançois Tigeot list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
241926deccbSFrançois Tigeot radeon_connector = to_radeon_connector(connector);
242*c59a5c48SFrançois Tigeot if (radeon_encoder->is_mst_encoder) {
243*c59a5c48SFrançois Tigeot struct radeon_encoder_mst *mst_enc;
244*c59a5c48SFrançois Tigeot
245*c59a5c48SFrançois Tigeot if (!radeon_connector->is_mst_connector)
246*c59a5c48SFrançois Tigeot continue;
247*c59a5c48SFrançois Tigeot
248*c59a5c48SFrançois Tigeot mst_enc = radeon_encoder->enc_priv;
249*c59a5c48SFrançois Tigeot if (mst_enc->connector == radeon_connector->mst_port)
250*c59a5c48SFrançois Tigeot return connector;
251*c59a5c48SFrançois Tigeot } else if (radeon_encoder->active_device & radeon_connector->devices)
252926deccbSFrançois Tigeot return connector;
253926deccbSFrançois Tigeot }
254926deccbSFrançois Tigeot return NULL;
255926deccbSFrançois Tigeot }
256926deccbSFrançois Tigeot
257926deccbSFrançois Tigeot struct drm_connector *
radeon_get_connector_for_encoder_init(struct drm_encoder * encoder)258926deccbSFrançois Tigeot radeon_get_connector_for_encoder_init(struct drm_encoder *encoder)
259926deccbSFrançois Tigeot {
260926deccbSFrançois Tigeot struct drm_device *dev = encoder->dev;
261926deccbSFrançois Tigeot struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
262926deccbSFrançois Tigeot struct drm_connector *connector;
263926deccbSFrançois Tigeot struct radeon_connector *radeon_connector;
264926deccbSFrançois Tigeot
265926deccbSFrançois Tigeot list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
266926deccbSFrançois Tigeot radeon_connector = to_radeon_connector(connector);
267926deccbSFrançois Tigeot if (radeon_encoder->devices & radeon_connector->devices)
268926deccbSFrançois Tigeot return connector;
269926deccbSFrançois Tigeot }
270926deccbSFrançois Tigeot return NULL;
271926deccbSFrançois Tigeot }
272926deccbSFrançois Tigeot
radeon_get_external_encoder(struct drm_encoder * encoder)273926deccbSFrançois Tigeot struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder)
274926deccbSFrançois Tigeot {
275926deccbSFrançois Tigeot struct drm_device *dev = encoder->dev;
276926deccbSFrançois Tigeot struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
277926deccbSFrançois Tigeot struct drm_encoder *other_encoder;
278926deccbSFrançois Tigeot struct radeon_encoder *other_radeon_encoder;
279926deccbSFrançois Tigeot
280926deccbSFrançois Tigeot if (radeon_encoder->is_ext_encoder)
281926deccbSFrançois Tigeot return NULL;
282926deccbSFrançois Tigeot
283926deccbSFrançois Tigeot list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
284926deccbSFrançois Tigeot if (other_encoder == encoder)
285926deccbSFrançois Tigeot continue;
286926deccbSFrançois Tigeot other_radeon_encoder = to_radeon_encoder(other_encoder);
287926deccbSFrançois Tigeot if (other_radeon_encoder->is_ext_encoder &&
288926deccbSFrançois Tigeot (radeon_encoder->devices & other_radeon_encoder->devices))
289926deccbSFrançois Tigeot return other_encoder;
290926deccbSFrançois Tigeot }
291926deccbSFrançois Tigeot return NULL;
292926deccbSFrançois Tigeot }
293926deccbSFrançois Tigeot
radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder * encoder)294926deccbSFrançois Tigeot u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder)
295926deccbSFrançois Tigeot {
296926deccbSFrançois Tigeot struct drm_encoder *other_encoder = radeon_get_external_encoder(encoder);
297926deccbSFrançois Tigeot
298926deccbSFrançois Tigeot if (other_encoder) {
299926deccbSFrançois Tigeot struct radeon_encoder *radeon_encoder = to_radeon_encoder(other_encoder);
300926deccbSFrançois Tigeot
301926deccbSFrançois Tigeot switch (radeon_encoder->encoder_id) {
302926deccbSFrançois Tigeot case ENCODER_OBJECT_ID_TRAVIS:
303926deccbSFrançois Tigeot case ENCODER_OBJECT_ID_NUTMEG:
304926deccbSFrançois Tigeot return radeon_encoder->encoder_id;
305926deccbSFrançois Tigeot default:
306926deccbSFrançois Tigeot return ENCODER_OBJECT_ID_NONE;
307926deccbSFrançois Tigeot }
308926deccbSFrançois Tigeot }
309926deccbSFrançois Tigeot return ENCODER_OBJECT_ID_NONE;
310926deccbSFrançois Tigeot }
311926deccbSFrançois Tigeot
radeon_panel_mode_fixup(struct drm_encoder * encoder,struct drm_display_mode * adjusted_mode)312926deccbSFrançois Tigeot void radeon_panel_mode_fixup(struct drm_encoder *encoder,
313926deccbSFrançois Tigeot struct drm_display_mode *adjusted_mode)
314926deccbSFrançois Tigeot {
315926deccbSFrançois Tigeot struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
316926deccbSFrançois Tigeot struct drm_device *dev = encoder->dev;
317926deccbSFrançois Tigeot struct radeon_device *rdev = dev->dev_private;
318926deccbSFrançois Tigeot struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
319926deccbSFrançois Tigeot unsigned hblank = native_mode->htotal - native_mode->hdisplay;
320926deccbSFrançois Tigeot unsigned vblank = native_mode->vtotal - native_mode->vdisplay;
321926deccbSFrançois Tigeot unsigned hover = native_mode->hsync_start - native_mode->hdisplay;
322926deccbSFrançois Tigeot unsigned vover = native_mode->vsync_start - native_mode->vdisplay;
323926deccbSFrançois Tigeot unsigned hsync_width = native_mode->hsync_end - native_mode->hsync_start;
324926deccbSFrançois Tigeot unsigned vsync_width = native_mode->vsync_end - native_mode->vsync_start;
325926deccbSFrançois Tigeot
326926deccbSFrançois Tigeot adjusted_mode->clock = native_mode->clock;
327926deccbSFrançois Tigeot adjusted_mode->flags = native_mode->flags;
328926deccbSFrançois Tigeot
329926deccbSFrançois Tigeot if (ASIC_IS_AVIVO(rdev)) {
330926deccbSFrançois Tigeot adjusted_mode->hdisplay = native_mode->hdisplay;
331926deccbSFrançois Tigeot adjusted_mode->vdisplay = native_mode->vdisplay;
332926deccbSFrançois Tigeot }
333926deccbSFrançois Tigeot
334926deccbSFrançois Tigeot adjusted_mode->htotal = native_mode->hdisplay + hblank;
335926deccbSFrançois Tigeot adjusted_mode->hsync_start = native_mode->hdisplay + hover;
336926deccbSFrançois Tigeot adjusted_mode->hsync_end = adjusted_mode->hsync_start + hsync_width;
337926deccbSFrançois Tigeot
338926deccbSFrançois Tigeot adjusted_mode->vtotal = native_mode->vdisplay + vblank;
339926deccbSFrançois Tigeot adjusted_mode->vsync_start = native_mode->vdisplay + vover;
340926deccbSFrançois Tigeot adjusted_mode->vsync_end = adjusted_mode->vsync_start + vsync_width;
341926deccbSFrançois Tigeot
342926deccbSFrançois Tigeot drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
343926deccbSFrançois Tigeot
344926deccbSFrançois Tigeot if (ASIC_IS_AVIVO(rdev)) {
345926deccbSFrançois Tigeot adjusted_mode->crtc_hdisplay = native_mode->hdisplay;
346926deccbSFrançois Tigeot adjusted_mode->crtc_vdisplay = native_mode->vdisplay;
347926deccbSFrançois Tigeot }
348926deccbSFrançois Tigeot
349926deccbSFrançois Tigeot adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + hblank;
350926deccbSFrançois Tigeot adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + hover;
351926deccbSFrançois Tigeot adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + hsync_width;
352926deccbSFrançois Tigeot
353926deccbSFrançois Tigeot adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + vblank;
354926deccbSFrançois Tigeot adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + vover;
355926deccbSFrançois Tigeot adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + vsync_width;
356926deccbSFrançois Tigeot
357926deccbSFrançois Tigeot }
358926deccbSFrançois Tigeot
radeon_dig_monitor_is_duallink(struct drm_encoder * encoder,u32 pixel_clock)359926deccbSFrançois Tigeot bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
360926deccbSFrançois Tigeot u32 pixel_clock)
361926deccbSFrançois Tigeot {
362926deccbSFrançois Tigeot struct drm_device *dev = encoder->dev;
363926deccbSFrançois Tigeot struct radeon_device *rdev = dev->dev_private;
364926deccbSFrançois Tigeot struct drm_connector *connector;
365926deccbSFrançois Tigeot struct radeon_connector *radeon_connector;
366926deccbSFrançois Tigeot struct radeon_connector_atom_dig *dig_connector;
367926deccbSFrançois Tigeot
368926deccbSFrançois Tigeot connector = radeon_get_connector_for_encoder(encoder);
369926deccbSFrançois Tigeot /* if we don't have an active device yet, just use one of
370926deccbSFrançois Tigeot * the connectors tied to the encoder.
371926deccbSFrançois Tigeot */
372926deccbSFrançois Tigeot if (!connector)
373926deccbSFrançois Tigeot connector = radeon_get_connector_for_encoder_init(encoder);
374926deccbSFrançois Tigeot radeon_connector = to_radeon_connector(connector);
375926deccbSFrançois Tigeot
376926deccbSFrançois Tigeot switch (connector->connector_type) {
377926deccbSFrançois Tigeot case DRM_MODE_CONNECTOR_DVII:
378926deccbSFrançois Tigeot case DRM_MODE_CONNECTOR_HDMIB:
379926deccbSFrançois Tigeot if (radeon_connector->use_digital) {
380926deccbSFrançois Tigeot /* HDMI 1.3 supports up to 340 Mhz over single link */
381c6f73aabSFrançois Tigeot if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
382926deccbSFrançois Tigeot if (pixel_clock > 340000)
383926deccbSFrançois Tigeot return true;
384926deccbSFrançois Tigeot else
385926deccbSFrançois Tigeot return false;
386926deccbSFrançois Tigeot } else {
387926deccbSFrançois Tigeot if (pixel_clock > 165000)
388926deccbSFrançois Tigeot return true;
389926deccbSFrançois Tigeot else
390926deccbSFrançois Tigeot return false;
391926deccbSFrançois Tigeot }
392926deccbSFrançois Tigeot } else
393926deccbSFrançois Tigeot return false;
394926deccbSFrançois Tigeot case DRM_MODE_CONNECTOR_DVID:
395926deccbSFrançois Tigeot case DRM_MODE_CONNECTOR_HDMIA:
396926deccbSFrançois Tigeot case DRM_MODE_CONNECTOR_DisplayPort:
397*c59a5c48SFrançois Tigeot if (radeon_connector->is_mst_connector)
398*c59a5c48SFrançois Tigeot return false;
399*c59a5c48SFrançois Tigeot
400926deccbSFrançois Tigeot dig_connector = radeon_connector->con_priv;
401926deccbSFrançois Tigeot if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
402926deccbSFrançois Tigeot (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
403926deccbSFrançois Tigeot return false;
404926deccbSFrançois Tigeot else {
405926deccbSFrançois Tigeot /* HDMI 1.3 supports up to 340 Mhz over single link */
406c6f73aabSFrançois Tigeot if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
407926deccbSFrançois Tigeot if (pixel_clock > 340000)
408926deccbSFrançois Tigeot return true;
409926deccbSFrançois Tigeot else
410926deccbSFrançois Tigeot return false;
411926deccbSFrançois Tigeot } else {
412926deccbSFrançois Tigeot if (pixel_clock > 165000)
413926deccbSFrançois Tigeot return true;
414926deccbSFrançois Tigeot else
415926deccbSFrançois Tigeot return false;
416926deccbSFrançois Tigeot }
417926deccbSFrançois Tigeot }
418926deccbSFrançois Tigeot default:
419926deccbSFrançois Tigeot return false;
420926deccbSFrançois Tigeot }
421926deccbSFrançois Tigeot }
422926deccbSFrançois Tigeot
radeon_encoder_is_digital(struct drm_encoder * encoder)423591d5043SFrançois Tigeot bool radeon_encoder_is_digital(struct drm_encoder *encoder)
424591d5043SFrançois Tigeot {
425591d5043SFrançois Tigeot struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
426591d5043SFrançois Tigeot switch (radeon_encoder->encoder_id) {
427591d5043SFrançois Tigeot case ENCODER_OBJECT_ID_INTERNAL_LVDS:
428591d5043SFrançois Tigeot case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
429591d5043SFrançois Tigeot case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
430591d5043SFrançois Tigeot case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
431591d5043SFrançois Tigeot case ENCODER_OBJECT_ID_INTERNAL_DVO1:
432591d5043SFrançois Tigeot case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
433591d5043SFrançois Tigeot case ENCODER_OBJECT_ID_INTERNAL_DDI:
434591d5043SFrançois Tigeot case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
435591d5043SFrançois Tigeot case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
436591d5043SFrançois Tigeot case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
437591d5043SFrançois Tigeot case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
438591d5043SFrançois Tigeot case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
439591d5043SFrançois Tigeot return true;
440591d5043SFrançois Tigeot default:
441591d5043SFrançois Tigeot return false;
442591d5043SFrançois Tigeot }
443591d5043SFrançois Tigeot }
444