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