162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright 2007-8 Advanced Micro Devices, Inc.
362306a36Sopenharmony_ci * Copyright 2008 Red Hat Inc.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
662306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
762306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation
862306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
962306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
1062306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
1362306a36Sopenharmony_ci * all copies or substantial portions of the Software.
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1662306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1762306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1862306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
1962306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2062306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2162306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * Authors: Dave Airlie
2462306a36Sopenharmony_ci *          Alex Deucher
2562306a36Sopenharmony_ci */
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include <linux/pci.h>
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#include <drm/drm_device.h>
3062306a36Sopenharmony_ci#include <drm/radeon_drm.h>
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#include <acpi/video.h>
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#include "radeon.h"
3562306a36Sopenharmony_ci#include "radeon_atombios.h"
3662306a36Sopenharmony_ci#include "radeon_legacy_encoders.h"
3762306a36Sopenharmony_ci#include "atom.h"
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cistatic uint32_t radeon_encoder_clones(struct drm_encoder *encoder)
4062306a36Sopenharmony_ci{
4162306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
4262306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
4362306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
4462306a36Sopenharmony_ci	struct drm_encoder *clone_encoder;
4562306a36Sopenharmony_ci	uint32_t index_mask = 0;
4662306a36Sopenharmony_ci	int count;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	/* DIG routing gets problematic */
4962306a36Sopenharmony_ci	if (rdev->family >= CHIP_R600)
5062306a36Sopenharmony_ci		return index_mask;
5162306a36Sopenharmony_ci	/* LVDS/TV are too wacky */
5262306a36Sopenharmony_ci	if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT)
5362306a36Sopenharmony_ci		return index_mask;
5462306a36Sopenharmony_ci	/* DVO requires 2x ppll clocks depending on tmds chip */
5562306a36Sopenharmony_ci	if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT)
5662306a36Sopenharmony_ci		return index_mask;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	count = -1;
5962306a36Sopenharmony_ci	list_for_each_entry(clone_encoder, &dev->mode_config.encoder_list, head) {
6062306a36Sopenharmony_ci		struct radeon_encoder *radeon_clone = to_radeon_encoder(clone_encoder);
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci		count++;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci		if (clone_encoder == encoder)
6562306a36Sopenharmony_ci			continue;
6662306a36Sopenharmony_ci		if (radeon_clone->devices & (ATOM_DEVICE_LCD_SUPPORT))
6762306a36Sopenharmony_ci			continue;
6862306a36Sopenharmony_ci		if (radeon_clone->devices & ATOM_DEVICE_DFP2_SUPPORT)
6962306a36Sopenharmony_ci			continue;
7062306a36Sopenharmony_ci		else
7162306a36Sopenharmony_ci			index_mask |= (1 << count);
7262306a36Sopenharmony_ci	}
7362306a36Sopenharmony_ci	return index_mask;
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_civoid radeon_setup_encoder_clones(struct drm_device *dev)
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	struct drm_encoder *encoder;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
8162306a36Sopenharmony_ci		encoder->possible_clones = radeon_encoder_clones(encoder);
8262306a36Sopenharmony_ci	}
8362306a36Sopenharmony_ci}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ciuint32_t
8662306a36Sopenharmony_ciradeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, uint8_t dac)
8762306a36Sopenharmony_ci{
8862306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
8962306a36Sopenharmony_ci	uint32_t ret = 0;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	switch (supported_device) {
9262306a36Sopenharmony_ci	case ATOM_DEVICE_CRT1_SUPPORT:
9362306a36Sopenharmony_ci	case ATOM_DEVICE_TV1_SUPPORT:
9462306a36Sopenharmony_ci	case ATOM_DEVICE_TV2_SUPPORT:
9562306a36Sopenharmony_ci	case ATOM_DEVICE_CRT2_SUPPORT:
9662306a36Sopenharmony_ci	case ATOM_DEVICE_CV_SUPPORT:
9762306a36Sopenharmony_ci		switch (dac) {
9862306a36Sopenharmony_ci		case 1: /* dac a */
9962306a36Sopenharmony_ci			if ((rdev->family == CHIP_RS300) ||
10062306a36Sopenharmony_ci			    (rdev->family == CHIP_RS400) ||
10162306a36Sopenharmony_ci			    (rdev->family == CHIP_RS480))
10262306a36Sopenharmony_ci				ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
10362306a36Sopenharmony_ci			else if (ASIC_IS_AVIVO(rdev))
10462306a36Sopenharmony_ci				ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1;
10562306a36Sopenharmony_ci			else
10662306a36Sopenharmony_ci				ret = ENCODER_INTERNAL_DAC1_ENUM_ID1;
10762306a36Sopenharmony_ci			break;
10862306a36Sopenharmony_ci		case 2: /* dac b */
10962306a36Sopenharmony_ci			if (ASIC_IS_AVIVO(rdev))
11062306a36Sopenharmony_ci				ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1;
11162306a36Sopenharmony_ci			else {
11262306a36Sopenharmony_ci				/* if (rdev->family == CHIP_R200)
11362306a36Sopenharmony_ci				 * ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
11462306a36Sopenharmony_ci				 * else
11562306a36Sopenharmony_ci				 */
11662306a36Sopenharmony_ci				ret = ENCODER_INTERNAL_DAC2_ENUM_ID1;
11762306a36Sopenharmony_ci			}
11862306a36Sopenharmony_ci			break;
11962306a36Sopenharmony_ci		case 3: /* external dac */
12062306a36Sopenharmony_ci			if (ASIC_IS_AVIVO(rdev))
12162306a36Sopenharmony_ci				ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
12262306a36Sopenharmony_ci			else
12362306a36Sopenharmony_ci				ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
12462306a36Sopenharmony_ci			break;
12562306a36Sopenharmony_ci		}
12662306a36Sopenharmony_ci		break;
12762306a36Sopenharmony_ci	case ATOM_DEVICE_LCD1_SUPPORT:
12862306a36Sopenharmony_ci		if (ASIC_IS_AVIVO(rdev))
12962306a36Sopenharmony_ci			ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
13062306a36Sopenharmony_ci		else
13162306a36Sopenharmony_ci			ret = ENCODER_INTERNAL_LVDS_ENUM_ID1;
13262306a36Sopenharmony_ci		break;
13362306a36Sopenharmony_ci	case ATOM_DEVICE_DFP1_SUPPORT:
13462306a36Sopenharmony_ci		if ((rdev->family == CHIP_RS300) ||
13562306a36Sopenharmony_ci		    (rdev->family == CHIP_RS400) ||
13662306a36Sopenharmony_ci		    (rdev->family == CHIP_RS480))
13762306a36Sopenharmony_ci			ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
13862306a36Sopenharmony_ci		else if (ASIC_IS_AVIVO(rdev))
13962306a36Sopenharmony_ci			ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1;
14062306a36Sopenharmony_ci		else
14162306a36Sopenharmony_ci			ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1;
14262306a36Sopenharmony_ci		break;
14362306a36Sopenharmony_ci	case ATOM_DEVICE_LCD2_SUPPORT:
14462306a36Sopenharmony_ci	case ATOM_DEVICE_DFP2_SUPPORT:
14562306a36Sopenharmony_ci		if ((rdev->family == CHIP_RS600) ||
14662306a36Sopenharmony_ci		    (rdev->family == CHIP_RS690) ||
14762306a36Sopenharmony_ci		    (rdev->family == CHIP_RS740))
14862306a36Sopenharmony_ci			ret = ENCODER_INTERNAL_DDI_ENUM_ID1;
14962306a36Sopenharmony_ci		else if (ASIC_IS_AVIVO(rdev))
15062306a36Sopenharmony_ci			ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1;
15162306a36Sopenharmony_ci		else
15262306a36Sopenharmony_ci			ret = ENCODER_INTERNAL_DVO1_ENUM_ID1;
15362306a36Sopenharmony_ci		break;
15462306a36Sopenharmony_ci	case ATOM_DEVICE_DFP3_SUPPORT:
15562306a36Sopenharmony_ci		ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1;
15662306a36Sopenharmony_ci		break;
15762306a36Sopenharmony_ci	}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	return ret;
16062306a36Sopenharmony_ci}
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_cistatic void radeon_encoder_add_backlight(struct radeon_encoder *radeon_encoder,
16362306a36Sopenharmony_ci					 struct drm_connector *connector)
16462306a36Sopenharmony_ci{
16562306a36Sopenharmony_ci	struct drm_device *dev = radeon_encoder->base.dev;
16662306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
16762306a36Sopenharmony_ci	bool use_bl = false;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	if (!(radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)))
17062306a36Sopenharmony_ci		return;
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	if (radeon_backlight == 0) {
17362306a36Sopenharmony_ci		use_bl = false;
17462306a36Sopenharmony_ci	} else if (radeon_backlight == 1) {
17562306a36Sopenharmony_ci		use_bl = true;
17662306a36Sopenharmony_ci	} else if (radeon_backlight == -1) {
17762306a36Sopenharmony_ci		/* Quirks */
17862306a36Sopenharmony_ci		/* Amilo Xi 2550 only works with acpi bl */
17962306a36Sopenharmony_ci		if ((rdev->pdev->device == 0x9583) &&
18062306a36Sopenharmony_ci		    (rdev->pdev->subsystem_vendor == 0x1734) &&
18162306a36Sopenharmony_ci		    (rdev->pdev->subsystem_device == 0x1107))
18262306a36Sopenharmony_ci			use_bl = false;
18362306a36Sopenharmony_ci/* Older PPC macs use on-GPU backlight controller */
18462306a36Sopenharmony_ci#ifndef CONFIG_PPC_PMAC
18562306a36Sopenharmony_ci		/* disable native backlight control on older asics */
18662306a36Sopenharmony_ci		else if (rdev->family < CHIP_R600)
18762306a36Sopenharmony_ci			use_bl = false;
18862306a36Sopenharmony_ci#endif
18962306a36Sopenharmony_ci		else
19062306a36Sopenharmony_ci			use_bl = true;
19162306a36Sopenharmony_ci	}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	if (use_bl) {
19462306a36Sopenharmony_ci		if (rdev->is_atom_bios)
19562306a36Sopenharmony_ci			radeon_atom_backlight_init(radeon_encoder, connector);
19662306a36Sopenharmony_ci		else
19762306a36Sopenharmony_ci			radeon_legacy_backlight_init(radeon_encoder, connector);
19862306a36Sopenharmony_ci	}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	/*
20162306a36Sopenharmony_ci	 * If there is no native backlight device (which may happen even when
20262306a36Sopenharmony_ci	 * use_bl==true) try registering an ACPI video backlight device instead.
20362306a36Sopenharmony_ci	 */
20462306a36Sopenharmony_ci	if (!rdev->mode_info.bl_encoder)
20562306a36Sopenharmony_ci		acpi_video_register_backlight();
20662306a36Sopenharmony_ci}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_civoid
20962306a36Sopenharmony_ciradeon_link_encoder_connector(struct drm_device *dev)
21062306a36Sopenharmony_ci{
21162306a36Sopenharmony_ci	struct drm_connector *connector;
21262306a36Sopenharmony_ci	struct radeon_connector *radeon_connector;
21362306a36Sopenharmony_ci	struct drm_encoder *encoder;
21462306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder;
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	/* walk the list and link encoders to connectors */
21762306a36Sopenharmony_ci	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
21862306a36Sopenharmony_ci		radeon_connector = to_radeon_connector(connector);
21962306a36Sopenharmony_ci		list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
22062306a36Sopenharmony_ci			radeon_encoder = to_radeon_encoder(encoder);
22162306a36Sopenharmony_ci			if (radeon_encoder->devices & radeon_connector->devices) {
22262306a36Sopenharmony_ci				drm_connector_attach_encoder(connector, encoder);
22362306a36Sopenharmony_ci				if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
22462306a36Sopenharmony_ci					radeon_encoder_add_backlight(radeon_encoder, connector);
22562306a36Sopenharmony_ci			}
22662306a36Sopenharmony_ci		}
22762306a36Sopenharmony_ci	}
22862306a36Sopenharmony_ci}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_civoid radeon_encoder_set_active_device(struct drm_encoder *encoder)
23162306a36Sopenharmony_ci{
23262306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
23362306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
23462306a36Sopenharmony_ci	struct drm_connector *connector;
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
23762306a36Sopenharmony_ci		if (connector->encoder == encoder) {
23862306a36Sopenharmony_ci			struct radeon_connector *radeon_connector = to_radeon_connector(connector);
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci			radeon_encoder->active_device = radeon_encoder->devices & radeon_connector->devices;
24162306a36Sopenharmony_ci			DRM_DEBUG_KMS("setting active device to %08x from %08x %08x for encoder %d\n",
24262306a36Sopenharmony_ci				  radeon_encoder->active_device, radeon_encoder->devices,
24362306a36Sopenharmony_ci				  radeon_connector->devices, encoder->encoder_type);
24462306a36Sopenharmony_ci		}
24562306a36Sopenharmony_ci	}
24662306a36Sopenharmony_ci}
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_cistruct drm_connector *
24962306a36Sopenharmony_ciradeon_get_connector_for_encoder(struct drm_encoder *encoder)
25062306a36Sopenharmony_ci{
25162306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
25262306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
25362306a36Sopenharmony_ci	struct drm_connector *connector;
25462306a36Sopenharmony_ci	struct radeon_connector *radeon_connector;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
25762306a36Sopenharmony_ci		radeon_connector = to_radeon_connector(connector);
25862306a36Sopenharmony_ci		if (radeon_encoder->active_device & radeon_connector->devices)
25962306a36Sopenharmony_ci			return connector;
26062306a36Sopenharmony_ci	}
26162306a36Sopenharmony_ci	return NULL;
26262306a36Sopenharmony_ci}
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cistruct drm_connector *
26562306a36Sopenharmony_ciradeon_get_connector_for_encoder_init(struct drm_encoder *encoder)
26662306a36Sopenharmony_ci{
26762306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
26862306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
26962306a36Sopenharmony_ci	struct drm_connector *connector;
27062306a36Sopenharmony_ci	struct radeon_connector *radeon_connector;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
27362306a36Sopenharmony_ci		radeon_connector = to_radeon_connector(connector);
27462306a36Sopenharmony_ci		if (radeon_encoder->devices & radeon_connector->devices)
27562306a36Sopenharmony_ci			return connector;
27662306a36Sopenharmony_ci	}
27762306a36Sopenharmony_ci	return NULL;
27862306a36Sopenharmony_ci}
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_cistruct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder)
28162306a36Sopenharmony_ci{
28262306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
28362306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
28462306a36Sopenharmony_ci	struct drm_encoder *other_encoder;
28562306a36Sopenharmony_ci	struct radeon_encoder *other_radeon_encoder;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	if (radeon_encoder->is_ext_encoder)
28862306a36Sopenharmony_ci		return NULL;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) {
29162306a36Sopenharmony_ci		if (other_encoder == encoder)
29262306a36Sopenharmony_ci			continue;
29362306a36Sopenharmony_ci		other_radeon_encoder = to_radeon_encoder(other_encoder);
29462306a36Sopenharmony_ci		if (other_radeon_encoder->is_ext_encoder &&
29562306a36Sopenharmony_ci		    (radeon_encoder->devices & other_radeon_encoder->devices))
29662306a36Sopenharmony_ci			return other_encoder;
29762306a36Sopenharmony_ci	}
29862306a36Sopenharmony_ci	return NULL;
29962306a36Sopenharmony_ci}
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ciu16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder)
30262306a36Sopenharmony_ci{
30362306a36Sopenharmony_ci	struct drm_encoder *other_encoder = radeon_get_external_encoder(encoder);
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	if (other_encoder) {
30662306a36Sopenharmony_ci		struct radeon_encoder *radeon_encoder = to_radeon_encoder(other_encoder);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci		switch (radeon_encoder->encoder_id) {
30962306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_TRAVIS:
31062306a36Sopenharmony_ci		case ENCODER_OBJECT_ID_NUTMEG:
31162306a36Sopenharmony_ci			return radeon_encoder->encoder_id;
31262306a36Sopenharmony_ci		default:
31362306a36Sopenharmony_ci			return ENCODER_OBJECT_ID_NONE;
31462306a36Sopenharmony_ci		}
31562306a36Sopenharmony_ci	}
31662306a36Sopenharmony_ci	return ENCODER_OBJECT_ID_NONE;
31762306a36Sopenharmony_ci}
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_civoid radeon_panel_mode_fixup(struct drm_encoder *encoder,
32062306a36Sopenharmony_ci			     struct drm_display_mode *adjusted_mode)
32162306a36Sopenharmony_ci{
32262306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
32362306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
32462306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
32562306a36Sopenharmony_ci	struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
32662306a36Sopenharmony_ci	unsigned int hblank = native_mode->htotal - native_mode->hdisplay;
32762306a36Sopenharmony_ci	unsigned int vblank = native_mode->vtotal - native_mode->vdisplay;
32862306a36Sopenharmony_ci	unsigned int hover = native_mode->hsync_start - native_mode->hdisplay;
32962306a36Sopenharmony_ci	unsigned int vover = native_mode->vsync_start - native_mode->vdisplay;
33062306a36Sopenharmony_ci	unsigned int hsync_width = native_mode->hsync_end - native_mode->hsync_start;
33162306a36Sopenharmony_ci	unsigned int vsync_width = native_mode->vsync_end - native_mode->vsync_start;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	adjusted_mode->clock = native_mode->clock;
33462306a36Sopenharmony_ci	adjusted_mode->flags = native_mode->flags;
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	if (ASIC_IS_AVIVO(rdev)) {
33762306a36Sopenharmony_ci		adjusted_mode->hdisplay = native_mode->hdisplay;
33862306a36Sopenharmony_ci		adjusted_mode->vdisplay = native_mode->vdisplay;
33962306a36Sopenharmony_ci	}
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	adjusted_mode->htotal = native_mode->hdisplay + hblank;
34262306a36Sopenharmony_ci	adjusted_mode->hsync_start = native_mode->hdisplay + hover;
34362306a36Sopenharmony_ci	adjusted_mode->hsync_end = adjusted_mode->hsync_start + hsync_width;
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	adjusted_mode->vtotal = native_mode->vdisplay + vblank;
34662306a36Sopenharmony_ci	adjusted_mode->vsync_start = native_mode->vdisplay + vover;
34762306a36Sopenharmony_ci	adjusted_mode->vsync_end = adjusted_mode->vsync_start + vsync_width;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	if (ASIC_IS_AVIVO(rdev)) {
35262306a36Sopenharmony_ci		adjusted_mode->crtc_hdisplay = native_mode->hdisplay;
35362306a36Sopenharmony_ci		adjusted_mode->crtc_vdisplay = native_mode->vdisplay;
35462306a36Sopenharmony_ci	}
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + hblank;
35762306a36Sopenharmony_ci	adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + hover;
35862306a36Sopenharmony_ci	adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + hsync_width;
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + vblank;
36162306a36Sopenharmony_ci	adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + vover;
36262306a36Sopenharmony_ci	adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + vsync_width;
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci}
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_cibool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
36762306a36Sopenharmony_ci				    u32 pixel_clock)
36862306a36Sopenharmony_ci{
36962306a36Sopenharmony_ci	struct drm_device *dev = encoder->dev;
37062306a36Sopenharmony_ci	struct radeon_device *rdev = dev->dev_private;
37162306a36Sopenharmony_ci	struct drm_connector *connector;
37262306a36Sopenharmony_ci	struct radeon_connector *radeon_connector;
37362306a36Sopenharmony_ci	struct radeon_connector_atom_dig *dig_connector;
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	connector = radeon_get_connector_for_encoder(encoder);
37662306a36Sopenharmony_ci	/* if we don't have an active device yet, just use one of
37762306a36Sopenharmony_ci	 * the connectors tied to the encoder.
37862306a36Sopenharmony_ci	 */
37962306a36Sopenharmony_ci	if (!connector)
38062306a36Sopenharmony_ci		connector = radeon_get_connector_for_encoder_init(encoder);
38162306a36Sopenharmony_ci	radeon_connector = to_radeon_connector(connector);
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	switch (connector->connector_type) {
38462306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_DVII:
38562306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_HDMIB:
38662306a36Sopenharmony_ci		if (radeon_connector->use_digital) {
38762306a36Sopenharmony_ci			/* HDMI 1.3 supports up to 340 Mhz over single link */
38862306a36Sopenharmony_ci			if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
38962306a36Sopenharmony_ci				if (pixel_clock > 340000)
39062306a36Sopenharmony_ci					return true;
39162306a36Sopenharmony_ci				else
39262306a36Sopenharmony_ci					return false;
39362306a36Sopenharmony_ci			} else {
39462306a36Sopenharmony_ci				if (pixel_clock > 165000)
39562306a36Sopenharmony_ci					return true;
39662306a36Sopenharmony_ci				else
39762306a36Sopenharmony_ci					return false;
39862306a36Sopenharmony_ci			}
39962306a36Sopenharmony_ci		} else
40062306a36Sopenharmony_ci			return false;
40162306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_DVID:
40262306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_HDMIA:
40362306a36Sopenharmony_ci	case DRM_MODE_CONNECTOR_DisplayPort:
40462306a36Sopenharmony_ci		dig_connector = radeon_connector->con_priv;
40562306a36Sopenharmony_ci		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
40662306a36Sopenharmony_ci		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
40762306a36Sopenharmony_ci			return false;
40862306a36Sopenharmony_ci		else {
40962306a36Sopenharmony_ci			/* HDMI 1.3 supports up to 340 Mhz over single link */
41062306a36Sopenharmony_ci			if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
41162306a36Sopenharmony_ci				if (pixel_clock > 340000)
41262306a36Sopenharmony_ci					return true;
41362306a36Sopenharmony_ci				else
41462306a36Sopenharmony_ci					return false;
41562306a36Sopenharmony_ci			} else {
41662306a36Sopenharmony_ci				if (pixel_clock > 165000)
41762306a36Sopenharmony_ci					return true;
41862306a36Sopenharmony_ci				else
41962306a36Sopenharmony_ci					return false;
42062306a36Sopenharmony_ci			}
42162306a36Sopenharmony_ci		}
42262306a36Sopenharmony_ci	default:
42362306a36Sopenharmony_ci		return false;
42462306a36Sopenharmony_ci	}
42562306a36Sopenharmony_ci}
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_cibool radeon_encoder_is_digital(struct drm_encoder *encoder)
42862306a36Sopenharmony_ci{
42962306a36Sopenharmony_ci	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	switch (radeon_encoder->encoder_id) {
43262306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
43362306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
43462306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
43562306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
43662306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
43762306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
43862306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_DDI:
43962306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
44062306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
44162306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
44262306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
44362306a36Sopenharmony_ci	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
44462306a36Sopenharmony_ci		return true;
44562306a36Sopenharmony_ci	default:
44662306a36Sopenharmony_ci		return false;
44762306a36Sopenharmony_ci	}
44862306a36Sopenharmony_ci}
449